mirror of
https://github.com/jj-vcs/jj.git
synced 2025-12-23 06:01:01 +00:00
everything: Rename branches to bookmarks
Jujutsu's branches do not behave like Git branches, which is a major hurdle for people adopting it from Git. They rather behave like Mercurial's (hg) bookmarks. We've had multiple discussions about it in the last ~1.5 years about this rename in the Discord, where multiple people agreed that this _false_ familiarity does not help anyone. Initially we were reluctant to do it but overtime, more and more users agreed that `bookmark` was a better for name the current mechanism. This may be hard break for current `jj branch` users, but it will immensly help Jujutsu's future, by defining it as our first own term. The `[experimental-moving-branches]` config option is currently left alone, to force not another large config update for users, since the last time this happened was when `jj log -T show` was removed, which immediately resulted in breaking users and introduced soft deprecations. This name change will also make it easier to introduce Topics (#3402) as _topological branches_ with a easier model. This was mostly done via LSP, ripgrep and sed and a whole bunch of manual changes either from me being lazy or thankfully pointed out by reviewers.
This commit is contained in:
parent
831404628f
commit
d9c68e08b1
96 changed files with 4574 additions and 4273 deletions
11
CHANGELOG.md
11
CHANGELOG.md
|
|
@ -13,11 +13,22 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|||
|
||||
* Invalid `ui.graph.style` configuration is now an error.
|
||||
|
||||
* The builtin template `branch_list` has been renamed to `bookmark_list` in
|
||||
lieu of the `jj branch` deprecation.
|
||||
|
||||
### Deprecations
|
||||
|
||||
* `jj obslog` is now called `jj evolution-log`/`jj evolog`. `jj obslog` remains
|
||||
as an alias.
|
||||
|
||||
* `jj branch` has been deprecated in favor of `jj bookmark`.
|
||||
|
||||
**Rationale:** Jujutsu's branches don't behave like Git branches, which a
|
||||
confused many newcomers, as they expected a similar behavior given the name.
|
||||
We've renamed them to "bookmarks" to match the actual behavior, as we think
|
||||
that describes them better, and they also behave similar to Mercurial's
|
||||
bookmarks.
|
||||
|
||||
### New features
|
||||
|
||||
* The new config option `snapshot.auto-track` lets you automatically track only
|
||||
|
|
|
|||
|
|
@ -512,33 +512,33 @@ impl ReadonlyUserRepo {
|
|||
}
|
||||
}
|
||||
|
||||
/// A branch that should be advanced to satisfy the "advance-branches" feature.
|
||||
/// This is a helper for `WorkspaceCommandTransaction`. It provides a type-safe
|
||||
/// way to separate the work of checking whether a branch can be advanced and
|
||||
/// actually advancing it. Advancing the branch never fails, but can't be done
|
||||
/// until the new `CommitId` is available. Splitting the work in this way also
|
||||
/// allows us to identify eligible branches without actually moving them and
|
||||
/// return config errors to the user early.
|
||||
pub struct AdvanceableBranch {
|
||||
/// A bookmark that should be advanced to satisfy the "advance-bookmarks"
|
||||
/// feature. This is a helper for `WorkspaceCommandTransaction`. It provides a
|
||||
/// type-safe way to separate the work of checking whether a bookmark can be
|
||||
/// advanced and actually advancing it. Advancing the bookmark never fails, but
|
||||
/// can't be done until the new `CommitId` is available. Splitting the work in
|
||||
/// this way also allows us to identify eligible bookmarks without actually
|
||||
/// moving them and return config errors to the user early.
|
||||
pub struct AdvanceableBookmark {
|
||||
name: String,
|
||||
old_commit_id: CommitId,
|
||||
}
|
||||
|
||||
/// Helper for parsing and evaluating settings for the advance-branches feature.
|
||||
/// Settings are configured in the jj config.toml as lists of [`StringPattern`]s
|
||||
/// for enabled and disabled branches. Example:
|
||||
/// Helper for parsing and evaluating settings for the advance-bookmarks
|
||||
/// feature. Settings are configured in the jj config.toml as lists of
|
||||
/// [`StringPattern`]s for enabled and disabled bookmarks. Example:
|
||||
/// ```toml
|
||||
/// [experimental-advance-branches]
|
||||
/// # Enable the feature for all branches except "main".
|
||||
/// enabled-branches = ["glob:*"]
|
||||
/// disabled-branches = ["main"]
|
||||
/// ```
|
||||
struct AdvanceBranchesSettings {
|
||||
enabled_branches: Vec<StringPattern>,
|
||||
disabled_branches: Vec<StringPattern>,
|
||||
struct AdvanceBookmarksSettings {
|
||||
enabled_bookmarks: Vec<StringPattern>,
|
||||
disabled_bookmarks: Vec<StringPattern>,
|
||||
}
|
||||
|
||||
impl AdvanceBranchesSettings {
|
||||
impl AdvanceBookmarksSettings {
|
||||
fn from_config(config: &config::Config) -> Result<Self, CommandError> {
|
||||
let get_setting = |setting_key| {
|
||||
let setting = format!("experimental-advance-branches.{setting_key}");
|
||||
|
|
@ -558,28 +558,30 @@ impl AdvanceBranchesSettings {
|
|||
}
|
||||
};
|
||||
Ok(Self {
|
||||
enabled_branches: get_setting("enabled-branches")?,
|
||||
disabled_branches: get_setting("disabled-branches")?,
|
||||
enabled_bookmarks: get_setting("enabled-branches")?,
|
||||
disabled_bookmarks: get_setting("disabled-branches")?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns true if the advance-branches feature is enabled for
|
||||
/// `branch_name`.
|
||||
fn branch_is_eligible(&self, branch_name: &str) -> bool {
|
||||
/// Returns true if the advance-bookmarks feature is enabled for
|
||||
/// `bookmark_name`.
|
||||
fn bookmark_is_eligible(&self, bookmark_name: &str) -> bool {
|
||||
if self
|
||||
.disabled_branches
|
||||
.disabled_bookmarks
|
||||
.iter()
|
||||
.any(|d| d.matches(branch_name))
|
||||
.any(|d| d.matches(bookmark_name))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
self.enabled_branches.iter().any(|e| e.matches(branch_name))
|
||||
self.enabled_bookmarks
|
||||
.iter()
|
||||
.any(|e| e.matches(bookmark_name))
|
||||
}
|
||||
|
||||
/// Returns true if the config includes at least one "enabled-branches"
|
||||
/// pattern.
|
||||
fn feature_enabled(&self) -> bool {
|
||||
!self.enabled_branches.is_empty()
|
||||
!self.enabled_bookmarks.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -855,10 +857,10 @@ impl WorkspaceCommandHelper {
|
|||
}
|
||||
|
||||
/// Imports branches and tags from the underlying Git repo, abandons old
|
||||
/// branches.
|
||||
/// bookmarks.
|
||||
///
|
||||
/// If the working-copy branch is rebased, and if update is allowed, the new
|
||||
/// working-copy commit will be checked out.
|
||||
/// If the working-copy branch is rebased, and if update is allowed, the
|
||||
/// new working-copy commit will be checked out.
|
||||
///
|
||||
/// This function does not import the Git HEAD, but the HEAD may be reset to
|
||||
/// the working copy parent if the repository is colocated.
|
||||
|
|
@ -1479,8 +1481,8 @@ See https://martinvonz.github.io/jj/latest/working-copy/#stale-working-copy \
|
|||
}
|
||||
|
||||
if self.working_copy_shared_with_git {
|
||||
let failed_branches = git::export_refs(mut_repo)?;
|
||||
print_failed_git_export(ui, &failed_branches)?;
|
||||
let refs = git::export_refs(mut_repo)?;
|
||||
print_failed_git_export(ui, &refs)?;
|
||||
}
|
||||
|
||||
self.user_repo = ReadonlyUserRepo::new(tx.commit("snapshot working copy"));
|
||||
|
|
@ -1596,8 +1598,8 @@ See https://martinvonz.github.io/jj/latest/working-copy/#stale-working-copy \
|
|||
if let Some(wc_commit) = &maybe_new_wc_commit {
|
||||
git::reset_head(tx.repo_mut(), &git_repo, wc_commit)?;
|
||||
}
|
||||
let failed_branches = git::export_refs(tx.repo_mut())?;
|
||||
print_failed_git_export(ui, &failed_branches)?;
|
||||
let refs = git::export_refs(tx.repo_mut())?;
|
||||
print_failed_git_export(ui, &refs)?;
|
||||
}
|
||||
|
||||
self.user_repo = ReadonlyUserRepo::new(tx.commit(description));
|
||||
|
|
@ -1781,34 +1783,35 @@ Then run `jj squash` to move the resolution into the conflicted commit."#,
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Identifies branches which are eligible to be moved automatically during
|
||||
/// `jj commit` and `jj new`. Whether a branch is eligible is determined by
|
||||
/// its target and the user and repo config for "advance-branches".
|
||||
/// Identifies bookmarks which are eligible to be moved automatically
|
||||
/// during `jj commit` and `jj new`. Whether a bookmark is eligible is
|
||||
/// determined by its target and the user and repo config for
|
||||
/// "advance-bookmarks".
|
||||
///
|
||||
/// Returns a Vec of branches in `repo` that point to any of the `from`
|
||||
/// Returns a Vec of bookmarks in `repo` that point to any of the `from`
|
||||
/// commits and that are eligible to advance. The `from` commits are
|
||||
/// typically the parents of the target commit of `jj commit` or `jj new`.
|
||||
///
|
||||
/// Branches are not moved until
|
||||
/// `WorkspaceCommandTransaction::advance_branches()` is called with the
|
||||
/// `AdvanceableBranch`s returned by this function.
|
||||
/// `WorkspaceCommandTransaction::advance_bookmarks()` is called with the
|
||||
/// `AdvanceableBookmark`s returned by this function.
|
||||
///
|
||||
/// Returns an empty `std::Vec` if no branches are eligible to advance.
|
||||
pub fn get_advanceable_branches<'a>(
|
||||
/// Returns an empty `std::Vec` if no bookmarks are eligible to advance.
|
||||
pub fn get_advanceable_bookmarks<'a>(
|
||||
&self,
|
||||
from: impl IntoIterator<Item = &'a CommitId>,
|
||||
) -> Result<Vec<AdvanceableBranch>, CommandError> {
|
||||
let ab_settings = AdvanceBranchesSettings::from_config(self.settings().config())?;
|
||||
) -> Result<Vec<AdvanceableBookmark>, CommandError> {
|
||||
let ab_settings = AdvanceBookmarksSettings::from_config(self.settings().config())?;
|
||||
if !ab_settings.feature_enabled() {
|
||||
// Return early if we know that there's no work to do.
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
|
||||
let mut advanceable_branches = Vec::new();
|
||||
let mut advanceable_bookmarks = Vec::new();
|
||||
for from_commit in from {
|
||||
for (name, _) in self.repo().view().local_branches_for_commit(from_commit) {
|
||||
if ab_settings.branch_is_eligible(name) {
|
||||
advanceable_branches.push(AdvanceableBranch {
|
||||
for (name, _) in self.repo().view().local_bookmarks_for_commit(from_commit) {
|
||||
if ab_settings.bookmark_is_eligible(name) {
|
||||
advanceable_bookmarks.push(AdvanceableBookmark {
|
||||
name: name.to_owned(),
|
||||
old_commit_id: from_commit.clone(),
|
||||
});
|
||||
|
|
@ -1816,7 +1819,7 @@ Then run `jj squash` to move the resolution into the conflicted commit."#,
|
|||
}
|
||||
}
|
||||
|
||||
Ok(advanceable_branches)
|
||||
Ok(advanceable_bookmarks)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1928,18 +1931,18 @@ impl WorkspaceCommandTransaction<'_> {
|
|||
self.tx
|
||||
}
|
||||
|
||||
/// Moves each branch in `branches` from an old commit it's associated with
|
||||
/// (configured by `get_advanceable_branches`) to the `move_to` commit. If
|
||||
/// the branch is conflicted before the update, it will remain conflicted
|
||||
/// after the update, but the conflict will involve the `move_to` commit
|
||||
/// instead of the old commit.
|
||||
pub fn advance_branches(&mut self, branches: Vec<AdvanceableBranch>, move_to: &CommitId) {
|
||||
for branch in branches {
|
||||
// This removes the old commit ID from the branch's RefTarget and
|
||||
/// Moves each bookmark in `bookmarks` from an old commit it's associated
|
||||
/// with (configured by `get_advanceable_bookmarks`) to the `move_to`
|
||||
/// commit. If the bookmark is conflicted before the update, it will
|
||||
/// remain conflicted after the update, but the conflict will involve
|
||||
/// the `move_to` commit instead of the old commit.
|
||||
pub fn advance_bookmarks(&mut self, bookmarks: Vec<AdvanceableBookmark>, move_to: &CommitId) {
|
||||
for bookmark in bookmarks {
|
||||
// This removes the old commit ID from the bookmark's RefTarget and
|
||||
// replaces it with the `move_to` ID.
|
||||
self.repo_mut().merge_local_branch(
|
||||
&branch.name,
|
||||
&RefTarget::normal(branch.old_commit_id),
|
||||
self.repo_mut().merge_local_bookmark(
|
||||
&bookmark.name,
|
||||
&RefTarget::normal(bookmark.old_commit_id),
|
||||
&RefTarget::normal(move_to.clone()),
|
||||
);
|
||||
}
|
||||
|
|
@ -2233,35 +2236,35 @@ pub fn print_unmatched_explicit_paths<'a>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn print_trackable_remote_branches(ui: &Ui, view: &View) -> io::Result<()> {
|
||||
let remote_branch_names = view
|
||||
.branches()
|
||||
.filter(|(_, branch_target)| branch_target.local_target.is_present())
|
||||
.flat_map(|(name, branch_target)| {
|
||||
branch_target
|
||||
pub fn print_trackable_remote_bookmarks(ui: &Ui, view: &View) -> io::Result<()> {
|
||||
let remote_bookmark_names = view
|
||||
.bookmarks()
|
||||
.filter(|(_, bookmark_target)| bookmark_target.local_target.is_present())
|
||||
.flat_map(|(name, bookmark_target)| {
|
||||
bookmark_target
|
||||
.remote_refs
|
||||
.into_iter()
|
||||
.filter(|&(_, remote_ref)| !remote_ref.is_tracking())
|
||||
.map(move |(remote, _)| format!("{name}@{remote}"))
|
||||
})
|
||||
.collect_vec();
|
||||
if remote_branch_names.is_empty() {
|
||||
if remote_bookmark_names.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Some(mut formatter) = ui.status_formatter() {
|
||||
writeln!(
|
||||
formatter.labeled("hint").with_heading("Hint: "),
|
||||
"The following remote branches aren't associated with the existing local branches:"
|
||||
"The following remote bookmarks aren't associated with the existing local bookmarks:"
|
||||
)?;
|
||||
for full_name in &remote_branch_names {
|
||||
for full_name in &remote_bookmark_names {
|
||||
write!(formatter, " ")?;
|
||||
writeln!(formatter.labeled("branch"), "{full_name}")?;
|
||||
writeln!(formatter.labeled("bookmark"), "{full_name}")?;
|
||||
}
|
||||
writeln!(
|
||||
formatter.labeled("hint").with_heading("Hint: "),
|
||||
"Run `jj branch track {names}` to keep local branches updated on future pulls.",
|
||||
names = remote_branch_names.join(" "),
|
||||
"Run `jj bookmark track {names}` to keep local bookmarks updated on future pulls.",
|
||||
names = remote_bookmark_names.join(" "),
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
|
|
@ -2509,30 +2512,30 @@ impl DiffSelector {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
pub struct RemoteBranchName {
|
||||
pub branch: String,
|
||||
pub struct RemoteBookmarkName {
|
||||
pub bookmark: String,
|
||||
pub remote: String,
|
||||
}
|
||||
|
||||
impl fmt::Display for RemoteBranchName {
|
||||
impl fmt::Display for RemoteBookmarkName {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let RemoteBranchName { branch, remote } = self;
|
||||
write!(f, "{branch}@{remote}")
|
||||
let RemoteBookmarkName { bookmark, remote } = self;
|
||||
write!(f, "{bookmark}@{remote}")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct RemoteBranchNamePattern {
|
||||
pub branch: StringPattern,
|
||||
pub struct RemoteBookmarkNamePattern {
|
||||
pub bookmark: StringPattern,
|
||||
pub remote: StringPattern,
|
||||
}
|
||||
|
||||
impl FromStr for RemoteBranchNamePattern {
|
||||
impl FromStr for RemoteBookmarkNamePattern {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(src: &str) -> Result<Self, Self::Err> {
|
||||
// The kind prefix applies to both branch and remote fragments. It's
|
||||
// weird that unanchored patterns like substring:branch@remote is split
|
||||
// The kind prefix applies to both bookmark and remote fragments. It's
|
||||
// weird that unanchored patterns like substring:bookmark@remote is split
|
||||
// into two, but I can't think of a better syntax.
|
||||
// TODO: should we disable substring pattern? what if we added regex?
|
||||
let (maybe_kind, pat) = src
|
||||
|
|
@ -2545,27 +2548,27 @@ impl FromStr for RemoteBranchNamePattern {
|
|||
Ok(StringPattern::exact(pat))
|
||||
}
|
||||
};
|
||||
// TODO: maybe reuse revset parser to handle branch/remote name containing @
|
||||
let (branch, remote) = pat
|
||||
.rsplit_once('@')
|
||||
.ok_or_else(|| "remote branch must be specified in branch@remote form".to_owned())?;
|
||||
Ok(RemoteBranchNamePattern {
|
||||
branch: to_pattern(branch)?,
|
||||
// TODO: maybe reuse revset parser to handle bookmark/remote name containing @
|
||||
let (bookmark, remote) = pat.rsplit_once('@').ok_or_else(|| {
|
||||
"remote bookmark must be specified in bookmark@remote form".to_owned()
|
||||
})?;
|
||||
Ok(RemoteBookmarkNamePattern {
|
||||
bookmark: to_pattern(bookmark)?,
|
||||
remote: to_pattern(remote)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl RemoteBranchNamePattern {
|
||||
impl RemoteBookmarkNamePattern {
|
||||
pub fn is_exact(&self) -> bool {
|
||||
self.branch.is_exact() && self.remote.is_exact()
|
||||
self.bookmark.is_exact() && self.remote.is_exact()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for RemoteBranchNamePattern {
|
||||
impl fmt::Display for RemoteBookmarkNamePattern {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let RemoteBranchNamePattern { branch, remote } = self;
|
||||
write!(f, "{branch}@{remote}")
|
||||
let RemoteBookmarkNamePattern { bookmark, remote } = self;
|
||||
write!(f, "{bookmark}@{remote}")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,80 +16,82 @@ use clap::builder::NonEmptyStringValueParser;
|
|||
use jj_lib::object_id::ObjectId as _;
|
||||
use jj_lib::op_store::RefTarget;
|
||||
|
||||
use super::has_tracked_remote_branches;
|
||||
use super::has_tracked_remote_bookmarks;
|
||||
use crate::cli_util::CommandHelper;
|
||||
use crate::cli_util::RevisionArg;
|
||||
use crate::command_error::user_error_with_hint;
|
||||
use crate::command_error::CommandError;
|
||||
use crate::ui::Ui;
|
||||
|
||||
/// Create a new branch
|
||||
/// Create a new bookmark
|
||||
#[derive(clap::Args, Clone, Debug)]
|
||||
pub struct BranchCreateArgs {
|
||||
/// The branch's target revision
|
||||
pub struct BookmarkCreateArgs {
|
||||
/// The bookmark's target revision
|
||||
//
|
||||
// The `--to` alias exists for making it easier for the user to switch
|
||||
// between `branch create`, `branch move`, and `branch set`.
|
||||
// between `bookmark create`, `bookmark move`, and `bookmark set`.
|
||||
#[arg(long, short, visible_alias = "to")]
|
||||
revision: Option<RevisionArg>,
|
||||
|
||||
/// The branches to create
|
||||
/// The bookmarks to create
|
||||
#[arg(required = true, value_parser = NonEmptyStringValueParser::new())]
|
||||
names: Vec<String>,
|
||||
}
|
||||
|
||||
pub fn cmd_branch_create(
|
||||
pub fn cmd_bookmark_create(
|
||||
ui: &mut Ui,
|
||||
command: &CommandHelper,
|
||||
args: &BranchCreateArgs,
|
||||
args: &BookmarkCreateArgs,
|
||||
) -> Result<(), CommandError> {
|
||||
let mut workspace_command = command.workspace_helper(ui)?;
|
||||
let target_commit =
|
||||
workspace_command.resolve_single_rev(args.revision.as_ref().unwrap_or(&RevisionArg::AT))?;
|
||||
let view = workspace_command.repo().view();
|
||||
let branch_names = &args.names;
|
||||
for name in branch_names {
|
||||
if view.get_local_branch(name).is_present() {
|
||||
let bookmark_names = &args.names;
|
||||
for name in bookmark_names {
|
||||
if view.get_local_bookmark(name).is_present() {
|
||||
return Err(user_error_with_hint(
|
||||
format!("Branch already exists: {name}"),
|
||||
"Use `jj branch set` to update it.",
|
||||
format!("Bookmark already exists: {name}"),
|
||||
"Use `jj bookmark set` to update it.",
|
||||
));
|
||||
}
|
||||
if has_tracked_remote_branches(view, name) {
|
||||
if has_tracked_remote_bookmarks(view, name) {
|
||||
return Err(user_error_with_hint(
|
||||
format!("Tracked remote branches exist for deleted branch: {name}"),
|
||||
format!("Tracked remote bookmarks exist for deleted bookmark: {name}"),
|
||||
format!(
|
||||
"Use `jj branch set` to recreate the local branch. Run `jj branch untrack \
|
||||
'glob:{name}@*'` to disassociate them."
|
||||
"Use `jj bookmark set` to recreate the local bookmark. Run `jj bookmark \
|
||||
untrack 'glob:{name}@*'` to disassociate them."
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
let mut tx = workspace_command.start_transaction();
|
||||
for branch_name in branch_names {
|
||||
tx.repo_mut()
|
||||
.set_local_branch_target(branch_name, RefTarget::normal(target_commit.id().clone()));
|
||||
for bookmark_name in bookmark_names {
|
||||
tx.repo_mut().set_local_bookmark_target(
|
||||
bookmark_name,
|
||||
RefTarget::normal(target_commit.id().clone()),
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(mut formatter) = ui.status_formatter() {
|
||||
write!(
|
||||
formatter,
|
||||
"Created {} branches pointing to ",
|
||||
branch_names.len()
|
||||
"Created {} bookmarks pointing to ",
|
||||
bookmark_names.len()
|
||||
)?;
|
||||
tx.write_commit_summary(formatter.as_mut(), &target_commit)?;
|
||||
writeln!(formatter)?;
|
||||
}
|
||||
if branch_names.len() > 1 && args.revision.is_none() {
|
||||
if bookmark_names.len() > 1 && args.revision.is_none() {
|
||||
writeln!(ui.hint_default(), "Use -r to specify the target revision.")?;
|
||||
}
|
||||
|
||||
tx.finish(
|
||||
ui,
|
||||
format!(
|
||||
"create branch {names} pointing to commit {id}",
|
||||
names = branch_names.join(", "),
|
||||
"create bookmark {names} pointing to commit {id}",
|
||||
names = bookmark_names.join(", "),
|
||||
id = target_commit.id().hex()
|
||||
),
|
||||
)?;
|
||||
|
|
@ -16,43 +16,47 @@ use itertools::Itertools as _;
|
|||
use jj_lib::op_store::RefTarget;
|
||||
use jj_lib::str_util::StringPattern;
|
||||
|
||||
use super::find_local_branches;
|
||||
use super::find_local_bookmarks;
|
||||
use crate::cli_util::CommandHelper;
|
||||
use crate::command_error::CommandError;
|
||||
use crate::ui::Ui;
|
||||
|
||||
/// Delete an existing branch and propagate the deletion to remotes on the
|
||||
/// Delete an existing bookmark and propagate the deletion to remotes on the
|
||||
/// next push
|
||||
#[derive(clap::Args, Clone, Debug)]
|
||||
pub struct BranchDeleteArgs {
|
||||
/// The branches to delete
|
||||
pub struct BookmarkDeleteArgs {
|
||||
/// The bookmarks to delete
|
||||
///
|
||||
/// By default, the specified name matches exactly. Use `glob:` prefix to
|
||||
/// select branches by wildcard pattern. For details, see
|
||||
/// https://martinvonz.github.io/jj/latest/revsets/#string-patterns.
|
||||
/// select bookmarks by wildcard pattern. For details, see
|
||||
/// https://martinvonz.github.io/jj/latest/revsets/#string-patterns.
|
||||
#[arg(required = true, value_parser = StringPattern::parse)]
|
||||
names: Vec<StringPattern>,
|
||||
}
|
||||
|
||||
pub fn cmd_branch_delete(
|
||||
pub fn cmd_bookmark_delete(
|
||||
ui: &mut Ui,
|
||||
command: &CommandHelper,
|
||||
args: &BranchDeleteArgs,
|
||||
args: &BookmarkDeleteArgs,
|
||||
) -> Result<(), CommandError> {
|
||||
let mut workspace_command = command.workspace_helper(ui)?;
|
||||
let repo = workspace_command.repo().clone();
|
||||
let matched_branches = find_local_branches(repo.view(), &args.names)?;
|
||||
let matched_bookmarks = find_local_bookmarks(repo.view(), &args.names)?;
|
||||
let mut tx = workspace_command.start_transaction();
|
||||
for (name, _) in &matched_branches {
|
||||
for (name, _) in &matched_bookmarks {
|
||||
tx.repo_mut()
|
||||
.set_local_branch_target(name, RefTarget::absent());
|
||||
.set_local_bookmark_target(name, RefTarget::absent());
|
||||
}
|
||||
writeln!(ui.status(), "Deleted {} branches.", matched_branches.len())?;
|
||||
writeln!(
|
||||
ui.status(),
|
||||
"Deleted {} bookmarks.",
|
||||
matched_bookmarks.len()
|
||||
)?;
|
||||
tx.finish(
|
||||
ui,
|
||||
format!(
|
||||
"delete branch {}",
|
||||
matched_branches.iter().map(|(name, _)| name).join(", ")
|
||||
"delete bookmark {}",
|
||||
matched_bookmarks.iter().map(|(name, _)| name).join(", ")
|
||||
),
|
||||
)?;
|
||||
Ok(())
|
||||
|
|
@ -19,60 +19,60 @@ use jj_lib::op_store::RemoteRef;
|
|||
use jj_lib::str_util::StringPattern;
|
||||
use jj_lib::view::View;
|
||||
|
||||
use super::find_branches_with;
|
||||
use super::find_bookmarks_with;
|
||||
use crate::cli_util::CommandHelper;
|
||||
use crate::command_error::CommandError;
|
||||
use crate::ui::Ui;
|
||||
|
||||
/// Forget everything about a branch, including its local and remote
|
||||
/// Forget everything about a bookmark, including its local and remote
|
||||
/// targets
|
||||
///
|
||||
/// A forgotten branch will not impact remotes on future pushes. It will be
|
||||
/// A forgotten bookmark will not impact remotes on future pushes. It will be
|
||||
/// recreated on future pulls if it still exists in the remote.
|
||||
#[derive(clap::Args, Clone, Debug)]
|
||||
pub struct BranchForgetArgs {
|
||||
/// The branches to forget
|
||||
pub struct BookmarkForgetArgs {
|
||||
/// The bookmarks to forget
|
||||
///
|
||||
/// By default, the specified name matches exactly. Use `glob:` prefix to
|
||||
/// select branches by wildcard pattern. For details, see
|
||||
/// https://martinvonz.github.io/jj/latest/revsets/#string-patterns.
|
||||
/// select bookmarks by wildcard pattern. For details, see
|
||||
/// https://martinvonz.github.io/jj/latest/revsets/#string-patterns.
|
||||
#[arg(required = true, value_parser = StringPattern::parse)]
|
||||
names: Vec<StringPattern>,
|
||||
}
|
||||
|
||||
pub fn cmd_branch_forget(
|
||||
pub fn cmd_bookmark_forget(
|
||||
ui: &mut Ui,
|
||||
command: &CommandHelper,
|
||||
args: &BranchForgetArgs,
|
||||
args: &BookmarkForgetArgs,
|
||||
) -> Result<(), CommandError> {
|
||||
let mut workspace_command = command.workspace_helper(ui)?;
|
||||
let repo = workspace_command.repo().clone();
|
||||
let matched_branches = find_forgettable_branches(repo.view(), &args.names)?;
|
||||
let matched_bookmarks = find_forgettable_bookmarks(repo.view(), &args.names)?;
|
||||
let mut tx = workspace_command.start_transaction();
|
||||
for (name, branch_target) in &matched_branches {
|
||||
for (name, bookmark_target) in &matched_bookmarks {
|
||||
tx.repo_mut()
|
||||
.set_local_branch_target(name, RefTarget::absent());
|
||||
for (remote_name, _) in &branch_target.remote_refs {
|
||||
.set_local_bookmark_target(name, RefTarget::absent());
|
||||
for (remote_name, _) in &bookmark_target.remote_refs {
|
||||
tx.repo_mut()
|
||||
.set_remote_branch(name, remote_name, RemoteRef::absent());
|
||||
.set_remote_bookmark(name, remote_name, RemoteRef::absent());
|
||||
}
|
||||
}
|
||||
writeln!(ui.status(), "Forgot {} branches.", matched_branches.len())?;
|
||||
writeln!(ui.status(), "Forgot {} bookmarks.", matched_bookmarks.len())?;
|
||||
tx.finish(
|
||||
ui,
|
||||
format!(
|
||||
"forget branch {}",
|
||||
matched_branches.iter().map(|(name, _)| name).join(", ")
|
||||
"forget bookmark {}",
|
||||
matched_bookmarks.iter().map(|(name, _)| name).join(", ")
|
||||
),
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn find_forgettable_branches<'a>(
|
||||
fn find_forgettable_bookmarks<'a>(
|
||||
view: &'a View,
|
||||
name_patterns: &[StringPattern],
|
||||
) -> Result<Vec<(&'a str, BranchTarget<'a>)>, CommandError> {
|
||||
find_branches_with(name_patterns, |pattern| {
|
||||
view.branches().filter(|(name, _)| pattern.matches(name))
|
||||
find_bookmarks_with(name_patterns, |pattern| {
|
||||
view.bookmarks().filter(|(name, _)| pattern.matches(name))
|
||||
})
|
||||
}
|
||||
|
|
@ -25,71 +25,71 @@ use crate::commit_templater::CommitTemplateLanguage;
|
|||
use crate::commit_templater::RefName;
|
||||
use crate::ui::Ui;
|
||||
|
||||
/// List branches and their targets
|
||||
/// List bookmarks and their targets
|
||||
///
|
||||
/// By default, a tracking remote branch will be included only if its target is
|
||||
/// different from the local target. A non-tracking remote branch won't be
|
||||
/// listed. For a conflicted branch (both local and remote), old target
|
||||
/// By default, a tracking remote bookmark will be included only if its target
|
||||
/// is different from the local target. A non-tracking remote bookmark won't be
|
||||
/// listed. For a conflicted bookmark (both local and remote), old target
|
||||
/// revisions are preceded by a "-" and new target revisions are preceded by a
|
||||
/// "+".
|
||||
///
|
||||
/// For information about branches, see
|
||||
/// https://martinvonz.github.io/jj/latest/branches/.
|
||||
/// For information about bookmarks, see
|
||||
/// https://martinvonz.github.io/jj/docs/bookmarks.md.
|
||||
#[derive(clap::Args, Clone, Debug)]
|
||||
pub struct BranchListArgs {
|
||||
/// Show all tracking and non-tracking remote branches including the ones
|
||||
/// whose targets are synchronized with the local branches
|
||||
pub struct BookmarkListArgs {
|
||||
/// Show all tracking and non-tracking remote bookmarks including the ones
|
||||
/// whose targets are synchronized with the local bookmarks
|
||||
#[arg(long, short, alias = "all")]
|
||||
all_remotes: bool,
|
||||
|
||||
/// Show remote tracked branches only. Omits local Git-tracking branches by
|
||||
/// default
|
||||
/// Show remote tracked bookmarks only. Omits local Git-tracking bookmarks
|
||||
/// by default
|
||||
#[arg(long, short, conflicts_with_all = ["all_remotes"])]
|
||||
tracked: bool,
|
||||
|
||||
/// Show conflicted branches only
|
||||
/// Show conflicted bookmarks only
|
||||
#[arg(long, short, conflicts_with_all = ["all_remotes"])]
|
||||
conflicted: bool,
|
||||
|
||||
/// Show branches whose local name matches
|
||||
/// Show bookmarks whose local name matches
|
||||
///
|
||||
/// By default, the specified name matches exactly. Use `glob:` prefix to
|
||||
/// select branches by wildcard pattern. For details, see
|
||||
/// https://martinvonz.github.io/jj/latest/revsets/#string-patterns.
|
||||
/// select bookmarks by wildcard pattern. For details, see
|
||||
/// https://martinvonz.github.io/jj/docs/revsets.md#string-patterns.
|
||||
#[arg(value_parser = StringPattern::parse)]
|
||||
names: Vec<StringPattern>,
|
||||
|
||||
/// Show branches whose local targets are in the given revisions
|
||||
/// Show bookmarks whose local targets are in the given revisions
|
||||
///
|
||||
/// Note that `-r deleted_branch` will not work since `deleted_branch`
|
||||
/// Note that `-r deleted_bookmark` will not work since `deleted_bookmark`
|
||||
/// wouldn't have a local target.
|
||||
#[arg(long, short)]
|
||||
revisions: Vec<RevisionArg>,
|
||||
|
||||
/// Render each branch using the given template
|
||||
/// Render each bookmark using the given template
|
||||
///
|
||||
/// All 0-argument methods of the `RefName` type are available as keywords.
|
||||
///
|
||||
/// For the syntax, see https://martinvonz.github.io/jj/latest/templates/
|
||||
/// For the syntax, see https://martinvonz.github.io/jj/latest/docs/templates.md
|
||||
#[arg(long, short = 'T')]
|
||||
template: Option<String>,
|
||||
}
|
||||
|
||||
pub fn cmd_branch_list(
|
||||
pub fn cmd_bookmark_list(
|
||||
ui: &mut Ui,
|
||||
command: &CommandHelper,
|
||||
args: &BranchListArgs,
|
||||
args: &BookmarkListArgs,
|
||||
) -> Result<(), CommandError> {
|
||||
let workspace_command = command.workspace_helper(ui)?;
|
||||
let repo = workspace_command.repo();
|
||||
let view = repo.view();
|
||||
|
||||
// Like cmd_git_push(), names and revisions are OR-ed.
|
||||
let branch_names_to_list = if !args.names.is_empty() || !args.revisions.is_empty() {
|
||||
let mut branch_names: HashSet<&str> = HashSet::new();
|
||||
let bookmark_names_to_list = if !args.names.is_empty() || !args.revisions.is_empty() {
|
||||
let mut bookmark_names: HashSet<&str> = HashSet::new();
|
||||
if !args.names.is_empty() {
|
||||
branch_names.extend(
|
||||
view.branches()
|
||||
bookmark_names.extend(
|
||||
view.bookmarks()
|
||||
.filter(|&(name, _)| args.names.iter().any(|pattern| pattern.matches(name)))
|
||||
.map(|(name, _)| name),
|
||||
);
|
||||
|
|
@ -97,18 +97,19 @@ pub fn cmd_branch_list(
|
|||
if !args.revisions.is_empty() {
|
||||
// Match against local targets only, which is consistent with "jj git push".
|
||||
let mut expression = workspace_command.parse_union_revsets(&args.revisions)?;
|
||||
// Intersects with the set of local branch targets to minimize the lookup space.
|
||||
expression.intersect_with(&RevsetExpression::branches(StringPattern::everything()));
|
||||
// Intersects with the set of local bookmark targets to minimize the lookup
|
||||
// space.
|
||||
expression.intersect_with(&RevsetExpression::bookmarks(StringPattern::everything()));
|
||||
let filtered_targets: HashSet<_> = expression.evaluate_to_commit_ids()?.collect();
|
||||
branch_names.extend(
|
||||
view.local_branches()
|
||||
bookmark_names.extend(
|
||||
view.local_bookmarks()
|
||||
.filter(|(_, target)| {
|
||||
target.added_ids().any(|id| filtered_targets.contains(id))
|
||||
})
|
||||
.map(|(name, _)| name),
|
||||
);
|
||||
}
|
||||
Some(branch_names)
|
||||
Some(bookmark_names)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
|
@ -117,27 +118,27 @@ pub fn cmd_branch_list(
|
|||
let language = workspace_command.commit_template_language();
|
||||
let text = match &args.template {
|
||||
Some(value) => value.to_owned(),
|
||||
None => command.settings().config().get("templates.branch_list")?,
|
||||
None => command.settings().config().get("templates.bookmark_list")?,
|
||||
};
|
||||
workspace_command
|
||||
.parse_template(&language, &text, CommitTemplateLanguage::wrap_ref_name)?
|
||||
.labeled("branch_list")
|
||||
.labeled("bookmark_list")
|
||||
};
|
||||
|
||||
ui.request_pager();
|
||||
let mut formatter = ui.stdout_formatter();
|
||||
|
||||
let mut found_deleted_local_branch = false;
|
||||
let mut found_deleted_tracking_local_branch = false;
|
||||
let branches_to_list = view.branches().filter(|(name, target)| {
|
||||
branch_names_to_list
|
||||
let mut found_deleted_local_bookmark = false;
|
||||
let mut found_deleted_tracking_local_bookmark = false;
|
||||
let bookmarks_to_list = view.bookmarks().filter(|(name, target)| {
|
||||
bookmark_names_to_list
|
||||
.as_ref()
|
||||
.map_or(true, |branch_names| branch_names.contains(name))
|
||||
.map_or(true, |bookmark_names| bookmark_names.contains(name))
|
||||
&& (!args.conflicted || target.local_target.has_conflict())
|
||||
});
|
||||
for (name, branch_target) in branches_to_list {
|
||||
let local_target = branch_target.local_target;
|
||||
let remote_refs = branch_target.remote_refs;
|
||||
for (name, bookmark_target) in bookmarks_to_list {
|
||||
let local_target = bookmark_target.local_target;
|
||||
let remote_refs = bookmark_target.remote_refs;
|
||||
let (mut tracking_remote_refs, untracked_remote_refs) = remote_refs
|
||||
.iter()
|
||||
.copied()
|
||||
|
|
@ -165,8 +166,8 @@ pub fn cmd_branch_list(
|
|||
}
|
||||
|
||||
if local_target.is_absent() && !tracking_remote_refs.is_empty() {
|
||||
found_deleted_local_branch = true;
|
||||
found_deleted_tracking_local_branch |= tracking_remote_refs
|
||||
found_deleted_local_bookmark = true;
|
||||
found_deleted_tracking_local_bookmark |= tracking_remote_refs
|
||||
.iter()
|
||||
.any(|&(remote, _)| remote != git::REMOTE_NAME_FOR_LOCAL_GIT_REPO);
|
||||
}
|
||||
|
|
@ -182,18 +183,18 @@ pub fn cmd_branch_list(
|
|||
drop(formatter);
|
||||
|
||||
// Print only one of these hints. It's not important to mention unexported
|
||||
// branches, but user might wonder why deleted branches are still listed.
|
||||
if found_deleted_tracking_local_branch {
|
||||
// bookmarks, but user might wonder why deleted bookmarks are still listed.
|
||||
if found_deleted_tracking_local_bookmark {
|
||||
writeln!(
|
||||
ui.hint_default(),
|
||||
"Branches marked as deleted will be *deleted permanently* on the remote on the next \
|
||||
`jj git push`. Use `jj branch forget` to prevent this."
|
||||
"Bookmarkes marked as deleted will be *deleted permanently* on the remote on the next \
|
||||
`jj git push`. Use `jj bookmark forget` to prevent this."
|
||||
)?;
|
||||
} else if found_deleted_local_branch {
|
||||
} else if found_deleted_local_bookmark {
|
||||
writeln!(
|
||||
ui.hint_default(),
|
||||
"Branches marked as deleted will be deleted from the underlying Git repo on the next \
|
||||
`jj git export`."
|
||||
"Bookmarkes marked as deleted will be deleted from the underlying Git repo on the \
|
||||
next `jj git export`."
|
||||
)?;
|
||||
}
|
||||
|
||||
198
cli/src/commands/bookmark/mod.rs
Normal file
198
cli/src/commands/bookmark/mod.rs
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
// Copyright 2020-2023 The Jujutsu Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
mod create;
|
||||
mod delete;
|
||||
mod forget;
|
||||
mod list;
|
||||
mod r#move;
|
||||
mod rename;
|
||||
mod set;
|
||||
mod track;
|
||||
mod untrack;
|
||||
|
||||
use itertools::Itertools as _;
|
||||
use jj_lib::backend::CommitId;
|
||||
use jj_lib::git;
|
||||
use jj_lib::op_store::RefTarget;
|
||||
use jj_lib::op_store::RemoteRef;
|
||||
use jj_lib::repo::Repo;
|
||||
use jj_lib::str_util::StringPattern;
|
||||
use jj_lib::view::View;
|
||||
|
||||
use self::create::cmd_bookmark_create;
|
||||
use self::create::BookmarkCreateArgs;
|
||||
use self::delete::cmd_bookmark_delete;
|
||||
use self::delete::BookmarkDeleteArgs;
|
||||
use self::forget::cmd_bookmark_forget;
|
||||
use self::forget::BookmarkForgetArgs;
|
||||
use self::list::cmd_bookmark_list;
|
||||
use self::list::BookmarkListArgs;
|
||||
use self::r#move::cmd_bookmark_move;
|
||||
use self::r#move::BookmarkMoveArgs;
|
||||
use self::rename::cmd_bookmark_rename;
|
||||
use self::rename::BookmarkRenameArgs;
|
||||
use self::set::cmd_bookmark_set;
|
||||
use self::set::BookmarkSetArgs;
|
||||
use self::track::cmd_bookmark_track;
|
||||
use self::track::BookmarkTrackArgs;
|
||||
use self::untrack::cmd_bookmark_untrack;
|
||||
use self::untrack::BookmarkUntrackArgs;
|
||||
use crate::cli_util::CommandHelper;
|
||||
use crate::cli_util::RemoteBookmarkName;
|
||||
use crate::cli_util::RemoteBookmarkNamePattern;
|
||||
use crate::command_error::user_error;
|
||||
use crate::command_error::CommandError;
|
||||
use crate::ui::Ui;
|
||||
|
||||
/// Manage bookmarks
|
||||
///
|
||||
/// For information about bookmarks, see
|
||||
/// https://martinvonz.github.io/jj/latest/docs/bookmarks.md.
|
||||
#[derive(clap::Subcommand, Clone, Debug)]
|
||||
pub enum BookmarkCommand {
|
||||
#[command(visible_alias("c"))]
|
||||
Create(BookmarkCreateArgs),
|
||||
#[command(visible_alias("d"))]
|
||||
Delete(BookmarkDeleteArgs),
|
||||
#[command(visible_alias("f"))]
|
||||
Forget(BookmarkForgetArgs),
|
||||
#[command(visible_alias("l"))]
|
||||
List(BookmarkListArgs),
|
||||
#[command(visible_alias("m"))]
|
||||
Move(BookmarkMoveArgs),
|
||||
#[command(visible_alias("r"))]
|
||||
Rename(BookmarkRenameArgs),
|
||||
#[command(visible_alias("s"))]
|
||||
Set(BookmarkSetArgs),
|
||||
#[command(visible_alias("t"))]
|
||||
Track(BookmarkTrackArgs),
|
||||
Untrack(BookmarkUntrackArgs),
|
||||
}
|
||||
|
||||
pub fn cmd_bookmark(
|
||||
ui: &mut Ui,
|
||||
command: &CommandHelper,
|
||||
subcommand: &BookmarkCommand,
|
||||
) -> Result<(), CommandError> {
|
||||
match subcommand {
|
||||
BookmarkCommand::Create(args) => cmd_bookmark_create(ui, command, args),
|
||||
BookmarkCommand::Delete(args) => cmd_bookmark_delete(ui, command, args),
|
||||
BookmarkCommand::Forget(args) => cmd_bookmark_forget(ui, command, args),
|
||||
BookmarkCommand::List(args) => cmd_bookmark_list(ui, command, args),
|
||||
BookmarkCommand::Move(args) => cmd_bookmark_move(ui, command, args),
|
||||
BookmarkCommand::Rename(args) => cmd_bookmark_rename(ui, command, args),
|
||||
BookmarkCommand::Set(args) => cmd_bookmark_set(ui, command, args),
|
||||
BookmarkCommand::Track(args) => cmd_bookmark_track(ui, command, args),
|
||||
BookmarkCommand::Untrack(args) => cmd_bookmark_untrack(ui, command, args),
|
||||
}
|
||||
}
|
||||
|
||||
fn find_local_bookmarks<'a>(
|
||||
view: &'a View,
|
||||
name_patterns: &[StringPattern],
|
||||
) -> Result<Vec<(&'a str, &'a RefTarget)>, CommandError> {
|
||||
find_bookmarks_with(name_patterns, |pattern| {
|
||||
view.local_bookmarks_matching(pattern)
|
||||
})
|
||||
}
|
||||
|
||||
fn find_bookmarks_with<'a, 'b, V, I: Iterator<Item = (&'a str, V)>>(
|
||||
name_patterns: &'b [StringPattern],
|
||||
mut find_matches: impl FnMut(&'b StringPattern) -> I,
|
||||
) -> Result<Vec<I::Item>, CommandError> {
|
||||
let mut matching_bookmarks: Vec<I::Item> = vec![];
|
||||
let mut unmatched_patterns = vec![];
|
||||
for pattern in name_patterns {
|
||||
let mut matches = find_matches(pattern).peekable();
|
||||
if matches.peek().is_none() {
|
||||
unmatched_patterns.push(pattern);
|
||||
}
|
||||
matching_bookmarks.extend(matches);
|
||||
}
|
||||
match &unmatched_patterns[..] {
|
||||
[] => {
|
||||
matching_bookmarks.sort_unstable_by_key(|(name, _)| *name);
|
||||
matching_bookmarks.dedup_by_key(|(name, _)| *name);
|
||||
Ok(matching_bookmarks)
|
||||
}
|
||||
[pattern] if pattern.is_exact() => Err(user_error(format!("No such bookmark: {pattern}"))),
|
||||
patterns => Err(user_error(format!(
|
||||
"No matching bookmarks for patterns: {}",
|
||||
patterns.iter().join(", ")
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
fn find_remote_bookmarks<'a>(
|
||||
view: &'a View,
|
||||
name_patterns: &[RemoteBookmarkNamePattern],
|
||||
) -> Result<Vec<(RemoteBookmarkName, &'a RemoteRef)>, CommandError> {
|
||||
let mut matching_bookmarks = vec![];
|
||||
let mut unmatched_patterns = vec![];
|
||||
for pattern in name_patterns {
|
||||
let mut matches = view
|
||||
.remote_bookmarks_matching(&pattern.bookmark, &pattern.remote)
|
||||
.map(|((bookmark, remote), remote_ref)| {
|
||||
let name = RemoteBookmarkName {
|
||||
bookmark: bookmark.to_owned(),
|
||||
remote: remote.to_owned(),
|
||||
};
|
||||
(name, remote_ref)
|
||||
})
|
||||
.peekable();
|
||||
if matches.peek().is_none() {
|
||||
unmatched_patterns.push(pattern);
|
||||
}
|
||||
matching_bookmarks.extend(matches);
|
||||
}
|
||||
match &unmatched_patterns[..] {
|
||||
[] => {
|
||||
matching_bookmarks.sort_unstable_by(|(name1, _), (name2, _)| name1.cmp(name2));
|
||||
matching_bookmarks.dedup_by(|(name1, _), (name2, _)| name1 == name2);
|
||||
Ok(matching_bookmarks)
|
||||
}
|
||||
[pattern] if pattern.is_exact() => {
|
||||
Err(user_error(format!("No such remote bookmark: {pattern}")))
|
||||
}
|
||||
patterns => Err(user_error(format!(
|
||||
"No matching remote bookmarks for patterns: {}",
|
||||
patterns.iter().join(", ")
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether or not the `bookmark` has any tracked remotes (i.e. is a tracking
|
||||
/// local bookmark.)
|
||||
fn has_tracked_remote_bookmarks(view: &View, bookmark: &str) -> bool {
|
||||
view.remote_bookmarks_matching(
|
||||
&StringPattern::exact(bookmark),
|
||||
&StringPattern::everything(),
|
||||
)
|
||||
.filter(|&((_, remote_name), _)| remote_name != git::REMOTE_NAME_FOR_LOCAL_GIT_REPO)
|
||||
.any(|(_, remote_ref)| remote_ref.is_tracking())
|
||||
}
|
||||
|
||||
fn is_fast_forward(repo: &dyn Repo, old_target: &RefTarget, new_target_id: &CommitId) -> bool {
|
||||
if old_target.is_present() {
|
||||
// Strictly speaking, "all" old targets should be ancestors, but we allow
|
||||
// conflict resolution by setting bookmark to "any" of the old target
|
||||
// descendants.
|
||||
old_target
|
||||
.added_ids()
|
||||
.any(|old| repo.index().is_ancestor(old, new_target_id))
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
@ -18,7 +18,7 @@ use jj_lib::object_id::ObjectId as _;
|
|||
use jj_lib::op_store::RefTarget;
|
||||
use jj_lib::str_util::StringPattern;
|
||||
|
||||
use super::find_branches_with;
|
||||
use super::find_bookmarks_with;
|
||||
use super::is_fast_forward;
|
||||
use crate::cli_util::CommandHelper;
|
||||
use crate::cli_util::RevisionArg;
|
||||
|
|
@ -26,51 +26,52 @@ use crate::command_error::user_error_with_hint;
|
|||
use crate::command_error::CommandError;
|
||||
use crate::ui::Ui;
|
||||
|
||||
/// Move existing branches to target revision
|
||||
/// Move existing bookmarks to target revision
|
||||
///
|
||||
/// If branch names are given, the specified branches will be updated to point
|
||||
/// to the target revision.
|
||||
/// If bookmark names are given, the specified bookmarks will be updated to
|
||||
/// point to the target revision.
|
||||
///
|
||||
/// If `--from` options are given, branches currently pointing to the specified
|
||||
/// revisions will be updated. The branches can also be filtered by names.
|
||||
/// If `--from` options are given, bookmarks currently pointing to the
|
||||
/// specified revisions will be updated. The bookmarks can also be filtered by
|
||||
/// names.
|
||||
///
|
||||
/// Example: pull up the nearest branches to the working-copy parent
|
||||
/// Example: pull up the nearest bookmarks to the working-copy parent
|
||||
///
|
||||
/// $ jj branch move --from 'heads(::@- & branches())' --to @-
|
||||
/// $ jj bookmark move --from 'heads(::@- & bookmarks())' --to @-
|
||||
#[derive(clap::Args, Clone, Debug)]
|
||||
#[command(group(clap::ArgGroup::new("source").multiple(true).required(true)))]
|
||||
pub struct BranchMoveArgs {
|
||||
/// Move branches from the given revisions
|
||||
pub struct BookmarkMoveArgs {
|
||||
/// Move bookmarks from the given revisions
|
||||
#[arg(long, group = "source", value_name = "REVISIONS")]
|
||||
from: Vec<RevisionArg>,
|
||||
|
||||
/// Move branches to this revision
|
||||
/// Move bookmarks to this revision
|
||||
#[arg(long, default_value = "@", value_name = "REVISION")]
|
||||
to: RevisionArg,
|
||||
|
||||
/// Allow moving branches backwards or sideways
|
||||
/// Allow moving bookmarks backwards or sideways
|
||||
#[arg(long, short = 'B')]
|
||||
allow_backwards: bool,
|
||||
|
||||
/// Move branches matching the given name patterns
|
||||
/// Move bookmarks matching the given name patterns
|
||||
///
|
||||
/// By default, the specified name matches exactly. Use `glob:` prefix to
|
||||
/// select branches by wildcard pattern. For details, see
|
||||
/// select bookmarks by wildcard pattern. For details, see
|
||||
/// https://martinvonz.github.io/jj/latest/revsets/#string-patterns.
|
||||
#[arg(group = "source", value_parser = StringPattern::parse)]
|
||||
names: Vec<StringPattern>,
|
||||
}
|
||||
|
||||
pub fn cmd_branch_move(
|
||||
pub fn cmd_bookmark_move(
|
||||
ui: &mut Ui,
|
||||
command: &CommandHelper,
|
||||
args: &BranchMoveArgs,
|
||||
args: &BookmarkMoveArgs,
|
||||
) -> Result<(), CommandError> {
|
||||
let mut workspace_command = command.workspace_helper(ui)?;
|
||||
let repo = workspace_command.repo().clone();
|
||||
|
||||
let target_commit = workspace_command.resolve_single_rev(&args.to)?;
|
||||
let matched_branches = {
|
||||
let matched_bookmarks = {
|
||||
let is_source_commit = if !args.from.is_empty() {
|
||||
workspace_command
|
||||
.parse_union_revsets(&args.from)?
|
||||
|
|
@ -79,63 +80,63 @@ pub fn cmd_branch_move(
|
|||
} else {
|
||||
Box::new(|_: &CommitId| true)
|
||||
};
|
||||
let mut branches = if !args.names.is_empty() {
|
||||
find_branches_with(&args.names, |pattern| {
|
||||
let mut bookmarks = if !args.names.is_empty() {
|
||||
find_bookmarks_with(&args.names, |pattern| {
|
||||
repo.view()
|
||||
.local_branches_matching(pattern)
|
||||
.local_bookmarks_matching(pattern)
|
||||
.filter(|(_, target)| target.added_ids().any(&is_source_commit))
|
||||
})?
|
||||
} else {
|
||||
repo.view()
|
||||
.local_branches()
|
||||
.local_bookmarks()
|
||||
.filter(|(_, target)| target.added_ids().any(&is_source_commit))
|
||||
.collect()
|
||||
};
|
||||
// Noop matches aren't error, but should be excluded from stats.
|
||||
branches.retain(|(_, old_target)| old_target.as_normal() != Some(target_commit.id()));
|
||||
branches
|
||||
bookmarks.retain(|(_, old_target)| old_target.as_normal() != Some(target_commit.id()));
|
||||
bookmarks
|
||||
};
|
||||
|
||||
if matched_branches.is_empty() {
|
||||
writeln!(ui.status(), "No branches to update.")?;
|
||||
if matched_bookmarks.is_empty() {
|
||||
writeln!(ui.status(), "No bookmarks to update.")?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if !args.allow_backwards {
|
||||
if let Some((name, _)) = matched_branches
|
||||
if let Some((name, _)) = matched_bookmarks
|
||||
.iter()
|
||||
.find(|(_, old_target)| !is_fast_forward(repo.as_ref(), old_target, target_commit.id()))
|
||||
{
|
||||
return Err(user_error_with_hint(
|
||||
format!("Refusing to move branch backwards or sideways: {name}"),
|
||||
format!("Refusing to move bookmark backwards or sideways: {name}"),
|
||||
"Use --allow-backwards to allow it.",
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
let mut tx = workspace_command.start_transaction();
|
||||
for (name, _) in &matched_branches {
|
||||
for (name, _) in &matched_bookmarks {
|
||||
tx.repo_mut()
|
||||
.set_local_branch_target(name, RefTarget::normal(target_commit.id().clone()));
|
||||
.set_local_bookmark_target(name, RefTarget::normal(target_commit.id().clone()));
|
||||
}
|
||||
|
||||
if let Some(mut formatter) = ui.status_formatter() {
|
||||
write!(formatter, "Moved {} branches to ", matched_branches.len())?;
|
||||
write!(formatter, "Moved {} bookmarks to ", matched_bookmarks.len())?;
|
||||
tx.write_commit_summary(formatter.as_mut(), &target_commit)?;
|
||||
writeln!(formatter)?;
|
||||
}
|
||||
if matched_branches.len() > 1 && args.names.is_empty() {
|
||||
if matched_bookmarks.len() > 1 && args.names.is_empty() {
|
||||
writeln!(
|
||||
ui.hint_default(),
|
||||
"Specify branch by name to update just one of the branches."
|
||||
"Specify bookmark by name to update just one of the bookmarks."
|
||||
)?;
|
||||
}
|
||||
|
||||
tx.finish(
|
||||
ui,
|
||||
format!(
|
||||
"point branch {names} to commit {id}",
|
||||
names = matched_branches.iter().map(|(name, _)| name).join(", "),
|
||||
"point bookmark {names} to commit {id}",
|
||||
names = matched_bookmarks.iter().map(|(name, _)| name).join(", "),
|
||||
id = target_commit.id().hex()
|
||||
),
|
||||
)?;
|
||||
93
cli/src/commands/bookmark/rename.rs
Normal file
93
cli/src/commands/bookmark/rename.rs
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
// Copyright 2020-2023 The Jujutsu Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use jj_lib::op_store::RefTarget;
|
||||
|
||||
use super::has_tracked_remote_bookmarks;
|
||||
use crate::cli_util::CommandHelper;
|
||||
use crate::command_error::user_error;
|
||||
use crate::command_error::CommandError;
|
||||
use crate::ui::Ui;
|
||||
|
||||
/// Rename `old` bookmark name to `new` bookmark name
|
||||
///
|
||||
/// The new bookmark name points at the same commit as the old bookmark name.
|
||||
#[derive(clap::Args, Clone, Debug)]
|
||||
pub struct BookmarkRenameArgs {
|
||||
/// The old name of the bookmark
|
||||
old: String,
|
||||
|
||||
/// The new name of the bookmark
|
||||
new: String,
|
||||
}
|
||||
|
||||
pub fn cmd_bookmark_rename(
|
||||
ui: &mut Ui,
|
||||
command: &CommandHelper,
|
||||
args: &BookmarkRenameArgs,
|
||||
) -> Result<(), CommandError> {
|
||||
let mut workspace_command = command.workspace_helper(ui)?;
|
||||
let view = workspace_command.repo().view();
|
||||
let old_bookmark = &args.old;
|
||||
let ref_target = view.get_local_bookmark(old_bookmark).clone();
|
||||
if ref_target.is_absent() {
|
||||
return Err(user_error(format!("No such bookmark: {old_bookmark}")));
|
||||
}
|
||||
|
||||
let new_bookmark = &args.new;
|
||||
if view.get_local_bookmark(new_bookmark).is_present() {
|
||||
return Err(user_error(format!(
|
||||
"Bookmark already exists: {new_bookmark}"
|
||||
)));
|
||||
}
|
||||
|
||||
let mut tx = workspace_command.start_transaction();
|
||||
tx.repo_mut()
|
||||
.set_local_bookmark_target(new_bookmark, ref_target);
|
||||
tx.repo_mut()
|
||||
.set_local_bookmark_target(old_bookmark, RefTarget::absent());
|
||||
tx.finish(
|
||||
ui,
|
||||
format!("rename bookmark {old_bookmark} to {new_bookmark}"),
|
||||
)?;
|
||||
|
||||
let view = workspace_command.repo().view();
|
||||
if has_tracked_remote_bookmarks(view, old_bookmark) {
|
||||
writeln!(
|
||||
ui.warning_default(),
|
||||
"Tracked remote bookmarks for bookmark {old_bookmark} were not renamed.",
|
||||
)?;
|
||||
writeln!(
|
||||
ui.hint_default(),
|
||||
"To rename the bookmark on the remote, you can `jj git push --bookmark \
|
||||
{old_bookmark}` first (to delete it on the remote), and then `jj git push --bookmark \
|
||||
{new_bookmark}`. `jj git push --all` would also be sufficient."
|
||||
)?;
|
||||
}
|
||||
if has_tracked_remote_bookmarks(view, new_bookmark) {
|
||||
// This isn't an error because bookmark renaming can't be propagated to
|
||||
// the remote immediately. "rename old new && rename new old" should be
|
||||
// allowed even if the original old bookmark had tracked remotes.
|
||||
writeln!(
|
||||
ui.warning_default(),
|
||||
"Tracked remote bookmarks for bookmark {new_bookmark} exist."
|
||||
)?;
|
||||
writeln!(
|
||||
ui.hint_default(),
|
||||
"Run `jj bookmark untrack 'glob:{new_bookmark}@*'` to disassociate them."
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ use clap::builder::NonEmptyStringValueParser;
|
|||
use jj_lib::object_id::ObjectId as _;
|
||||
use jj_lib::op_store::RefTarget;
|
||||
|
||||
use super::has_tracked_remote_branches;
|
||||
use super::has_tracked_remote_bookmarks;
|
||||
use super::is_fast_forward;
|
||||
use crate::cli_util::CommandHelper;
|
||||
use crate::cli_util::RevisionArg;
|
||||
|
|
@ -24,88 +24,90 @@ use crate::command_error::user_error_with_hint;
|
|||
use crate::command_error::CommandError;
|
||||
use crate::ui::Ui;
|
||||
|
||||
/// Create or update a branch to point to a certain commit
|
||||
/// Create or update a bookmark to point to a certain commit
|
||||
#[derive(clap::Args, Clone, Debug)]
|
||||
pub struct BranchSetArgs {
|
||||
/// The branch's target revision
|
||||
pub struct BookmarkSetArgs {
|
||||
/// The bookmark's target revision
|
||||
#[arg(long, short, visible_alias = "to")]
|
||||
revision: Option<RevisionArg>,
|
||||
|
||||
/// Allow moving the branch backwards or sideways
|
||||
/// Allow moving the bookmark backwards or sideways
|
||||
#[arg(long, short = 'B')]
|
||||
allow_backwards: bool,
|
||||
|
||||
/// The branches to update
|
||||
/// The bookmarks to update
|
||||
#[arg(required = true, value_parser = NonEmptyStringValueParser::new())]
|
||||
names: Vec<String>,
|
||||
}
|
||||
|
||||
pub fn cmd_branch_set(
|
||||
pub fn cmd_bookmark_set(
|
||||
ui: &mut Ui,
|
||||
command: &CommandHelper,
|
||||
args: &BranchSetArgs,
|
||||
args: &BookmarkSetArgs,
|
||||
) -> Result<(), CommandError> {
|
||||
let mut workspace_command = command.workspace_helper(ui)?;
|
||||
let target_commit =
|
||||
workspace_command.resolve_single_rev(args.revision.as_ref().unwrap_or(&RevisionArg::AT))?;
|
||||
let repo = workspace_command.repo().as_ref();
|
||||
let branch_names = &args.names;
|
||||
let mut new_branch_count = 0;
|
||||
let mut moved_branch_count = 0;
|
||||
for name in branch_names {
|
||||
let old_target = repo.view().get_local_branch(name);
|
||||
// If a branch is absent locally but is still tracking remote branches,
|
||||
// we are resurrecting the local branch, not "creating" a new branch.
|
||||
if old_target.is_absent() && !has_tracked_remote_branches(repo.view(), name) {
|
||||
new_branch_count += 1;
|
||||
let bookmark_names = &args.names;
|
||||
let mut new_bookmark_count = 0;
|
||||
let mut moved_bookmark_count = 0;
|
||||
for name in bookmark_names {
|
||||
let old_target = repo.view().get_local_bookmark(name);
|
||||
// If a bookmark is absent locally but is still tracking remote bookmarks,
|
||||
// we are resurrecting the local bookmark, not "creating" a new bookmark.
|
||||
if old_target.is_absent() && !has_tracked_remote_bookmarks(repo.view(), name) {
|
||||
new_bookmark_count += 1;
|
||||
} else if old_target.as_normal() != Some(target_commit.id()) {
|
||||
moved_branch_count += 1;
|
||||
moved_bookmark_count += 1;
|
||||
}
|
||||
if !args.allow_backwards && !is_fast_forward(repo, old_target, target_commit.id()) {
|
||||
return Err(user_error_with_hint(
|
||||
format!("Refusing to move branch backwards or sideways: {name}"),
|
||||
format!("Refusing to move bookmark backwards or sideways: {name}"),
|
||||
"Use --allow-backwards to allow it.",
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
let mut tx = workspace_command.start_transaction();
|
||||
for branch_name in branch_names {
|
||||
tx.repo_mut()
|
||||
.set_local_branch_target(branch_name, RefTarget::normal(target_commit.id().clone()));
|
||||
for bookmark_name in bookmark_names {
|
||||
tx.repo_mut().set_local_bookmark_target(
|
||||
bookmark_name,
|
||||
RefTarget::normal(target_commit.id().clone()),
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(mut formatter) = ui.status_formatter() {
|
||||
if new_branch_count > 0 {
|
||||
if new_bookmark_count > 0 {
|
||||
write!(
|
||||
formatter,
|
||||
"Created {new_branch_count} branches pointing to "
|
||||
"Created {new_bookmark_count} bookmarks pointing to "
|
||||
)?;
|
||||
tx.write_commit_summary(formatter.as_mut(), &target_commit)?;
|
||||
writeln!(formatter)?;
|
||||
}
|
||||
if moved_branch_count > 0 {
|
||||
write!(formatter, "Moved {moved_branch_count} branches to ")?;
|
||||
if moved_bookmark_count > 0 {
|
||||
write!(formatter, "Moved {moved_bookmark_count} bookmarks to ")?;
|
||||
tx.write_commit_summary(formatter.as_mut(), &target_commit)?;
|
||||
writeln!(formatter)?;
|
||||
}
|
||||
}
|
||||
if branch_names.len() > 1 && args.revision.is_none() {
|
||||
if bookmark_names.len() > 1 && args.revision.is_none() {
|
||||
writeln!(ui.hint_default(), "Use -r to specify the target revision.")?;
|
||||
}
|
||||
if new_branch_count > 0 {
|
||||
if new_bookmark_count > 0 {
|
||||
// TODO: delete this hint in jj 0.25+
|
||||
writeln!(
|
||||
ui.hint_default(),
|
||||
"Consider using `jj branch move` if your intention was to move existing branches."
|
||||
"Consider using `jj bookmark move` if your intention was to move existing bookmarks."
|
||||
)?;
|
||||
}
|
||||
|
||||
tx.finish(
|
||||
ui,
|
||||
format!(
|
||||
"point branch {names} to commit {id}",
|
||||
names = branch_names.join(", "),
|
||||
"point bookmark {names} to commit {id}",
|
||||
names = bookmark_names.join(", "),
|
||||
id = target_commit.id().hex()
|
||||
),
|
||||
)?;
|
||||
|
|
@ -16,45 +16,45 @@ use std::collections::HashMap;
|
|||
|
||||
use itertools::Itertools as _;
|
||||
|
||||
use super::find_remote_branches;
|
||||
use super::find_remote_bookmarks;
|
||||
use crate::cli_util::CommandHelper;
|
||||
use crate::cli_util::RemoteBranchNamePattern;
|
||||
use crate::cli_util::RemoteBookmarkNamePattern;
|
||||
use crate::command_error::CommandError;
|
||||
use crate::commit_templater::CommitTemplateLanguage;
|
||||
use crate::commit_templater::RefName;
|
||||
use crate::ui::Ui;
|
||||
|
||||
/// Start tracking given remote branches
|
||||
/// Start tracking given remote bookmarks
|
||||
///
|
||||
/// A tracking remote branch will be imported as a local branch of the same
|
||||
/// name. Changes to it will propagate to the existing local branch on future
|
||||
/// A tracking remote bookmark will be imported as a local bookmark of the same
|
||||
/// name. Changes to it will propagate to the existing local bookmark on future
|
||||
/// pulls.
|
||||
#[derive(clap::Args, Clone, Debug)]
|
||||
pub struct BranchTrackArgs {
|
||||
/// Remote branches to track
|
||||
pub struct BookmarkTrackArgs {
|
||||
/// Remote bookmarks to track
|
||||
///
|
||||
/// By default, the specified name matches exactly. Use `glob:` prefix to
|
||||
/// select branches by wildcard pattern. For details, see
|
||||
/// select bookmarks by wildcard pattern. For details, see
|
||||
/// https://martinvonz.github.io/jj/latest/revsets/#string-patterns.
|
||||
///
|
||||
/// Examples: branch@remote, glob:main@*, glob:jjfan-*@upstream
|
||||
/// Examples: bookmark@remote, glob:main@*, glob:jjfan-*@upstream
|
||||
#[arg(required = true, value_name = "BRANCH@REMOTE")]
|
||||
names: Vec<RemoteBranchNamePattern>,
|
||||
names: Vec<RemoteBookmarkNamePattern>,
|
||||
}
|
||||
|
||||
pub fn cmd_branch_track(
|
||||
pub fn cmd_bookmark_track(
|
||||
ui: &mut Ui,
|
||||
command: &CommandHelper,
|
||||
args: &BranchTrackArgs,
|
||||
args: &BookmarkTrackArgs,
|
||||
) -> Result<(), CommandError> {
|
||||
let mut workspace_command = command.workspace_helper(ui)?;
|
||||
let view = workspace_command.repo().view();
|
||||
let mut names = Vec::new();
|
||||
for (name, remote_ref) in find_remote_branches(view, &args.names)? {
|
||||
for (name, remote_ref) in find_remote_bookmarks(view, &args.names)? {
|
||||
if remote_ref.is_tracking() {
|
||||
writeln!(
|
||||
ui.warning_default(),
|
||||
"Remote branch already tracked: {name}"
|
||||
"Remote bookmark already tracked: {name}"
|
||||
)?;
|
||||
} else {
|
||||
names.push(name);
|
||||
|
|
@ -63,21 +63,21 @@ pub fn cmd_branch_track(
|
|||
let mut tx = workspace_command.start_transaction();
|
||||
for name in &names {
|
||||
tx.repo_mut()
|
||||
.track_remote_branch(&name.branch, &name.remote);
|
||||
.track_remote_bookmark(&name.bookmark, &name.remote);
|
||||
}
|
||||
if !names.is_empty() {
|
||||
writeln!(
|
||||
ui.status(),
|
||||
"Started tracking {} remote branches.",
|
||||
"Started tracking {} remote bookmarks.",
|
||||
names.len()
|
||||
)?;
|
||||
}
|
||||
tx.finish(
|
||||
ui,
|
||||
format!("track remote branch {}", names.iter().join(", ")),
|
||||
format!("track remote bookmark {}", names.iter().join(", ")),
|
||||
)?;
|
||||
|
||||
//show conflicted branches if there are some
|
||||
//show conflicted bookmarks if there are some
|
||||
|
||||
if let Some(mut formatter) = ui.status_formatter() {
|
||||
let template = {
|
||||
|
|
@ -85,39 +85,39 @@ pub fn cmd_branch_track(
|
|||
let text = command
|
||||
.settings()
|
||||
.config()
|
||||
.get::<String>("templates.branch_list")?;
|
||||
.get::<String>("templates.bookmark_list")?;
|
||||
workspace_command
|
||||
.parse_template(&language, &text, CommitTemplateLanguage::wrap_ref_name)?
|
||||
.labeled("branch_list")
|
||||
.labeled("bookmark_list")
|
||||
};
|
||||
|
||||
let mut remote_per_branch: HashMap<&str, Vec<&str>> = HashMap::new();
|
||||
let mut remote_per_bookmark: HashMap<&str, Vec<&str>> = HashMap::new();
|
||||
for n in names.iter() {
|
||||
remote_per_branch
|
||||
.entry(&n.branch)
|
||||
remote_per_bookmark
|
||||
.entry(&n.bookmark)
|
||||
.or_default()
|
||||
.push(&n.remote);
|
||||
}
|
||||
let branches_to_list =
|
||||
let bookmarks_to_list =
|
||||
workspace_command
|
||||
.repo()
|
||||
.view()
|
||||
.branches()
|
||||
.bookmarks()
|
||||
.filter(|(name, target)| {
|
||||
remote_per_branch.contains_key(name) && target.local_target.has_conflict()
|
||||
remote_per_bookmark.contains_key(name) && target.local_target.has_conflict()
|
||||
});
|
||||
|
||||
for (name, branch_target) in branches_to_list {
|
||||
let local_target = branch_target.local_target;
|
||||
for (name, bookmark_target) in bookmarks_to_list {
|
||||
let local_target = bookmark_target.local_target;
|
||||
let ref_name = RefName::local(
|
||||
name,
|
||||
local_target.clone(),
|
||||
branch_target.remote_refs.iter().map(|x| x.1),
|
||||
bookmark_target.remote_refs.iter().map(|x| x.1),
|
||||
);
|
||||
template.format(&ref_name, formatter.as_mut())?;
|
||||
|
||||
for (remote_name, remote_ref) in branch_target.remote_refs {
|
||||
if remote_per_branch[name].contains(&remote_name) {
|
||||
for (remote_name, remote_ref) in bookmark_target.remote_refs {
|
||||
if remote_per_bookmark[name].contains(&remote_name) {
|
||||
let ref_name =
|
||||
RefName::remote(name, remote_name, remote_ref.clone(), local_target);
|
||||
template.format(&ref_name, formatter.as_mut())?;
|
||||
|
|
@ -15,48 +15,49 @@
|
|||
use itertools::Itertools as _;
|
||||
use jj_lib::git;
|
||||
|
||||
use super::find_remote_branches;
|
||||
use super::find_remote_bookmarks;
|
||||
use crate::cli_util::CommandHelper;
|
||||
use crate::cli_util::RemoteBranchNamePattern;
|
||||
use crate::cli_util::RemoteBookmarkNamePattern;
|
||||
use crate::command_error::CommandError;
|
||||
use crate::ui::Ui;
|
||||
|
||||
/// Stop tracking given remote branches
|
||||
/// Stop tracking given remote bookmarks
|
||||
///
|
||||
/// A non-tracking remote branch is just a pointer to the last-fetched remote
|
||||
/// branch. It won't be imported as a local branch on future pulls.
|
||||
/// A non-tracking remote bookmark is just a pointer to the last-fetched remote
|
||||
/// bookmark. It won't be imported as a local bookmark on future pulls.
|
||||
#[derive(clap::Args, Clone, Debug)]
|
||||
pub struct BranchUntrackArgs {
|
||||
/// Remote branches to untrack
|
||||
pub struct BookmarkUntrackArgs {
|
||||
/// Remote bookmarks to untrack
|
||||
///
|
||||
/// By default, the specified name matches exactly. Use `glob:` prefix to
|
||||
/// select branches by wildcard pattern. For details, see
|
||||
/// select bookmarks by wildcard pattern. For details, see
|
||||
/// https://martinvonz.github.io/jj/latest/revsets/#string-patterns.
|
||||
///
|
||||
/// Examples: branch@remote, glob:main@*, glob:jjfan-*@upstream
|
||||
/// Examples: bookmark@remote, glob:main@*, glob:jjfan-*@upstream
|
||||
#[arg(required = true, value_name = "BRANCH@REMOTE")]
|
||||
names: Vec<RemoteBranchNamePattern>,
|
||||
names: Vec<RemoteBookmarkNamePattern>,
|
||||
}
|
||||
|
||||
pub fn cmd_branch_untrack(
|
||||
pub fn cmd_bookmark_untrack(
|
||||
ui: &mut Ui,
|
||||
command: &CommandHelper,
|
||||
args: &BranchUntrackArgs,
|
||||
args: &BookmarkUntrackArgs,
|
||||
) -> Result<(), CommandError> {
|
||||
let mut workspace_command = command.workspace_helper(ui)?;
|
||||
let view = workspace_command.repo().view();
|
||||
let mut names = Vec::new();
|
||||
for (name, remote_ref) in find_remote_branches(view, &args.names)? {
|
||||
for (name, remote_ref) in find_remote_bookmarks(view, &args.names)? {
|
||||
if name.remote == git::REMOTE_NAME_FOR_LOCAL_GIT_REPO {
|
||||
// This restriction can be lifted if we want to support untracked @git branches.
|
||||
// This restriction can be lifted if we want to support untracked @git
|
||||
// bookmarks.
|
||||
writeln!(
|
||||
ui.warning_default(),
|
||||
"Git-tracking branch cannot be untracked: {name}"
|
||||
"Git-tracking bookmark cannot be untracked: {name}"
|
||||
)?;
|
||||
} else if !remote_ref.is_tracking() {
|
||||
writeln!(
|
||||
ui.warning_default(),
|
||||
"Remote branch not tracked yet: {name}"
|
||||
"Remote bookmark not tracked yet: {name}"
|
||||
)?;
|
||||
} else {
|
||||
names.push(name);
|
||||
|
|
@ -65,18 +66,18 @@ pub fn cmd_branch_untrack(
|
|||
let mut tx = workspace_command.start_transaction();
|
||||
for name in &names {
|
||||
tx.repo_mut()
|
||||
.untrack_remote_branch(&name.branch, &name.remote);
|
||||
.untrack_remote_bookmark(&name.bookmark, &name.remote);
|
||||
}
|
||||
if !names.is_empty() {
|
||||
writeln!(
|
||||
ui.status(),
|
||||
"Stopped tracking {} remote branches.",
|
||||
"Stopped tracking {} remote bookmarks.",
|
||||
names.len()
|
||||
)?;
|
||||
}
|
||||
tx.finish(
|
||||
ui,
|
||||
format!("untrack remote branch {}", names.iter().join(", ")),
|
||||
format!("untrack remote bookmark {}", names.iter().join(", ")),
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -1,194 +0,0 @@
|
|||
// Copyright 2020-2023 The Jujutsu Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
mod create;
|
||||
mod delete;
|
||||
mod forget;
|
||||
mod list;
|
||||
mod r#move;
|
||||
mod rename;
|
||||
mod set;
|
||||
mod track;
|
||||
mod untrack;
|
||||
|
||||
use itertools::Itertools as _;
|
||||
use jj_lib::backend::CommitId;
|
||||
use jj_lib::git;
|
||||
use jj_lib::op_store::RefTarget;
|
||||
use jj_lib::op_store::RemoteRef;
|
||||
use jj_lib::repo::Repo;
|
||||
use jj_lib::str_util::StringPattern;
|
||||
use jj_lib::view::View;
|
||||
|
||||
use self::create::cmd_branch_create;
|
||||
use self::create::BranchCreateArgs;
|
||||
use self::delete::cmd_branch_delete;
|
||||
use self::delete::BranchDeleteArgs;
|
||||
use self::forget::cmd_branch_forget;
|
||||
use self::forget::BranchForgetArgs;
|
||||
use self::list::cmd_branch_list;
|
||||
use self::list::BranchListArgs;
|
||||
use self::r#move::cmd_branch_move;
|
||||
use self::r#move::BranchMoveArgs;
|
||||
use self::rename::cmd_branch_rename;
|
||||
use self::rename::BranchRenameArgs;
|
||||
use self::set::cmd_branch_set;
|
||||
use self::set::BranchSetArgs;
|
||||
use self::track::cmd_branch_track;
|
||||
use self::track::BranchTrackArgs;
|
||||
use self::untrack::cmd_branch_untrack;
|
||||
use self::untrack::BranchUntrackArgs;
|
||||
use crate::cli_util::CommandHelper;
|
||||
use crate::cli_util::RemoteBranchName;
|
||||
use crate::cli_util::RemoteBranchNamePattern;
|
||||
use crate::command_error::user_error;
|
||||
use crate::command_error::CommandError;
|
||||
use crate::ui::Ui;
|
||||
|
||||
/// Manage branches
|
||||
///
|
||||
/// For information about branches, see
|
||||
/// https://martinvonz.github.io/jj/latest/branches/.
|
||||
#[derive(clap::Subcommand, Clone, Debug)]
|
||||
pub enum BranchCommand {
|
||||
#[command(visible_alias("c"))]
|
||||
Create(BranchCreateArgs),
|
||||
#[command(visible_alias("d"))]
|
||||
Delete(BranchDeleteArgs),
|
||||
#[command(visible_alias("f"))]
|
||||
Forget(BranchForgetArgs),
|
||||
#[command(visible_alias("l"))]
|
||||
List(BranchListArgs),
|
||||
#[command(visible_alias("m"))]
|
||||
Move(BranchMoveArgs),
|
||||
#[command(visible_alias("r"))]
|
||||
Rename(BranchRenameArgs),
|
||||
#[command(visible_alias("s"))]
|
||||
Set(BranchSetArgs),
|
||||
#[command(visible_alias("t"))]
|
||||
Track(BranchTrackArgs),
|
||||
Untrack(BranchUntrackArgs),
|
||||
}
|
||||
|
||||
pub fn cmd_branch(
|
||||
ui: &mut Ui,
|
||||
command: &CommandHelper,
|
||||
subcommand: &BranchCommand,
|
||||
) -> Result<(), CommandError> {
|
||||
match subcommand {
|
||||
BranchCommand::Create(args) => cmd_branch_create(ui, command, args),
|
||||
BranchCommand::Delete(args) => cmd_branch_delete(ui, command, args),
|
||||
BranchCommand::Forget(args) => cmd_branch_forget(ui, command, args),
|
||||
BranchCommand::List(args) => cmd_branch_list(ui, command, args),
|
||||
BranchCommand::Move(args) => cmd_branch_move(ui, command, args),
|
||||
BranchCommand::Rename(args) => cmd_branch_rename(ui, command, args),
|
||||
BranchCommand::Set(args) => cmd_branch_set(ui, command, args),
|
||||
BranchCommand::Track(args) => cmd_branch_track(ui, command, args),
|
||||
BranchCommand::Untrack(args) => cmd_branch_untrack(ui, command, args),
|
||||
}
|
||||
}
|
||||
|
||||
fn find_local_branches<'a>(
|
||||
view: &'a View,
|
||||
name_patterns: &[StringPattern],
|
||||
) -> Result<Vec<(&'a str, &'a RefTarget)>, CommandError> {
|
||||
find_branches_with(name_patterns, |pattern| {
|
||||
view.local_branches_matching(pattern)
|
||||
})
|
||||
}
|
||||
|
||||
fn find_branches_with<'a, 'b, V, I: Iterator<Item = (&'a str, V)>>(
|
||||
name_patterns: &'b [StringPattern],
|
||||
mut find_matches: impl FnMut(&'b StringPattern) -> I,
|
||||
) -> Result<Vec<I::Item>, CommandError> {
|
||||
let mut matching_branches: Vec<I::Item> = vec![];
|
||||
let mut unmatched_patterns = vec![];
|
||||
for pattern in name_patterns {
|
||||
let mut matches = find_matches(pattern).peekable();
|
||||
if matches.peek().is_none() {
|
||||
unmatched_patterns.push(pattern);
|
||||
}
|
||||
matching_branches.extend(matches);
|
||||
}
|
||||
match &unmatched_patterns[..] {
|
||||
[] => {
|
||||
matching_branches.sort_unstable_by_key(|(name, _)| *name);
|
||||
matching_branches.dedup_by_key(|(name, _)| *name);
|
||||
Ok(matching_branches)
|
||||
}
|
||||
[pattern] if pattern.is_exact() => Err(user_error(format!("No such branch: {pattern}"))),
|
||||
patterns => Err(user_error(format!(
|
||||
"No matching branches for patterns: {}",
|
||||
patterns.iter().join(", ")
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
fn find_remote_branches<'a>(
|
||||
view: &'a View,
|
||||
name_patterns: &[RemoteBranchNamePattern],
|
||||
) -> Result<Vec<(RemoteBranchName, &'a RemoteRef)>, CommandError> {
|
||||
let mut matching_branches = vec![];
|
||||
let mut unmatched_patterns = vec![];
|
||||
for pattern in name_patterns {
|
||||
let mut matches = view
|
||||
.remote_branches_matching(&pattern.branch, &pattern.remote)
|
||||
.map(|((branch, remote), remote_ref)| {
|
||||
let name = RemoteBranchName {
|
||||
branch: branch.to_owned(),
|
||||
remote: remote.to_owned(),
|
||||
};
|
||||
(name, remote_ref)
|
||||
})
|
||||
.peekable();
|
||||
if matches.peek().is_none() {
|
||||
unmatched_patterns.push(pattern);
|
||||
}
|
||||
matching_branches.extend(matches);
|
||||
}
|
||||
match &unmatched_patterns[..] {
|
||||
[] => {
|
||||
matching_branches.sort_unstable_by(|(name1, _), (name2, _)| name1.cmp(name2));
|
||||
matching_branches.dedup_by(|(name1, _), (name2, _)| name1 == name2);
|
||||
Ok(matching_branches)
|
||||
}
|
||||
[pattern] if pattern.is_exact() => {
|
||||
Err(user_error(format!("No such remote branch: {pattern}")))
|
||||
}
|
||||
patterns => Err(user_error(format!(
|
||||
"No matching remote branches for patterns: {}",
|
||||
patterns.iter().join(", ")
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether or not the `branch` has any tracked remotes (i.e. is a tracking
|
||||
/// local branch.)
|
||||
fn has_tracked_remote_branches(view: &View, branch: &str) -> bool {
|
||||
view.remote_branches_matching(&StringPattern::exact(branch), &StringPattern::everything())
|
||||
.filter(|&((_, remote_name), _)| remote_name != git::REMOTE_NAME_FOR_LOCAL_GIT_REPO)
|
||||
.any(|(_, remote_ref)| remote_ref.is_tracking())
|
||||
}
|
||||
|
||||
fn is_fast_forward(repo: &dyn Repo, old_target: &RefTarget, new_target_id: &CommitId) -> bool {
|
||||
if old_target.is_present() {
|
||||
// Strictly speaking, "all" old targets should be ancestors, but we allow
|
||||
// conflict resolution by setting branch to "any" of the old target descendants.
|
||||
old_target
|
||||
.added_ids()
|
||||
.any(|old| repo.index().is_ancestor(old, new_target_id))
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
// Copyright 2020-2023 The Jujutsu Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use jj_lib::op_store::RefTarget;
|
||||
|
||||
use super::has_tracked_remote_branches;
|
||||
use crate::cli_util::CommandHelper;
|
||||
use crate::command_error::user_error;
|
||||
use crate::command_error::CommandError;
|
||||
use crate::ui::Ui;
|
||||
|
||||
/// Rename `old` branch name to `new` branch name
|
||||
///
|
||||
/// The new branch name points at the same commit as the old branch name.
|
||||
#[derive(clap::Args, Clone, Debug)]
|
||||
pub struct BranchRenameArgs {
|
||||
/// The old name of the branch
|
||||
old: String,
|
||||
|
||||
/// The new name of the branch
|
||||
new: String,
|
||||
}
|
||||
|
||||
pub fn cmd_branch_rename(
|
||||
ui: &mut Ui,
|
||||
command: &CommandHelper,
|
||||
args: &BranchRenameArgs,
|
||||
) -> Result<(), CommandError> {
|
||||
let mut workspace_command = command.workspace_helper(ui)?;
|
||||
let view = workspace_command.repo().view();
|
||||
let old_branch = &args.old;
|
||||
let ref_target = view.get_local_branch(old_branch).clone();
|
||||
if ref_target.is_absent() {
|
||||
return Err(user_error(format!("No such branch: {old_branch}")));
|
||||
}
|
||||
|
||||
let new_branch = &args.new;
|
||||
if view.get_local_branch(new_branch).is_present() {
|
||||
return Err(user_error(format!("Branch already exists: {new_branch}")));
|
||||
}
|
||||
|
||||
let mut tx = workspace_command.start_transaction();
|
||||
tx.repo_mut()
|
||||
.set_local_branch_target(new_branch, ref_target);
|
||||
tx.repo_mut()
|
||||
.set_local_branch_target(old_branch, RefTarget::absent());
|
||||
tx.finish(ui, format!("rename branch {old_branch} to {new_branch}"))?;
|
||||
|
||||
let view = workspace_command.repo().view();
|
||||
if has_tracked_remote_branches(view, old_branch) {
|
||||
writeln!(
|
||||
ui.warning_default(),
|
||||
"Tracked remote branches for branch {old_branch} were not renamed.",
|
||||
)?;
|
||||
writeln!(
|
||||
ui.hint_default(),
|
||||
"To rename the branch on the remote, you can `jj git push --branch {old_branch}` \
|
||||
first (to delete it on the remote), and then `jj git push --branch {new_branch}`. \
|
||||
`jj git push --all` would also be sufficient."
|
||||
)?;
|
||||
}
|
||||
if has_tracked_remote_branches(view, new_branch) {
|
||||
// This isn't an error because branch renaming can't be propagated to
|
||||
// the remote immediately. "rename old new && rename new old" should be
|
||||
// allowed even if the original old branch had tracked remotes.
|
||||
writeln!(
|
||||
ui.warning_default(),
|
||||
"Tracked remote branches for branch {new_branch} exist."
|
||||
)?;
|
||||
writeln!(
|
||||
ui.hint_default(),
|
||||
"Run `jj branch untrack 'glob:{new_branch}@*'` to disassociate them."
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -67,7 +67,7 @@ pub(crate) fn cmd_commit(
|
|||
let matcher = workspace_command
|
||||
.parse_file_patterns(&args.paths)?
|
||||
.to_matcher();
|
||||
let advanceable_branches = workspace_command.get_advanceable_branches(commit.parent_ids())?;
|
||||
let advanceable_branches = workspace_command.get_advanceable_bookmarks(commit.parent_ids())?;
|
||||
let diff_selector =
|
||||
workspace_command.diff_selector(ui, args.tool.as_deref(), args.interactive)?;
|
||||
let mut tx = workspace_command.start_transaction();
|
||||
|
|
@ -132,7 +132,7 @@ new working-copy commit.
|
|||
.write()?;
|
||||
|
||||
// Does nothing if there's no branches to advance.
|
||||
tx.advance_branches(advanceable_branches, new_commit.id());
|
||||
tx.advance_bookmarks(advanceable_branches, new_commit.id());
|
||||
|
||||
for workspace_id in workspace_ids {
|
||||
tx.repo_mut().edit(workspace_id, &new_wc_commit).unwrap();
|
||||
|
|
|
|||
|
|
@ -172,13 +172,13 @@ pub fn cmd_git_clone(
|
|||
let default_branch_remote_ref = workspace_command
|
||||
.repo()
|
||||
.view()
|
||||
.get_remote_branch(default_branch, remote_name);
|
||||
.get_remote_bookmark(default_branch, remote_name);
|
||||
if let Some(commit_id) = default_branch_remote_ref.target.as_normal().cloned() {
|
||||
let mut checkout_tx = workspace_command.start_transaction();
|
||||
// For convenience, create local branch as Git would do.
|
||||
checkout_tx
|
||||
.repo_mut()
|
||||
.track_remote_branch(default_branch, remote_name);
|
||||
.track_remote_bookmark(default_branch, remote_name);
|
||||
if let Ok(commit) = checkout_tx.repo().store().get_commit(&commit_id) {
|
||||
checkout_tx.check_out(&commit)?;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ use jj_lib::repo::ReadonlyRepo;
|
|||
use jj_lib::repo::Repo;
|
||||
use jj_lib::workspace::Workspace;
|
||||
|
||||
use crate::cli_util::print_trackable_remote_branches;
|
||||
use crate::cli_util::print_trackable_remote_bookmarks;
|
||||
use crate::cli_util::start_repo_transaction;
|
||||
use crate::cli_util::CommandHelper;
|
||||
use crate::cli_util::WorkspaceCommandHelper;
|
||||
|
|
@ -184,7 +184,7 @@ pub fn do_init(
|
|||
tx.finish(ui, "import git head")?;
|
||||
}
|
||||
}
|
||||
print_trackable_remote_branches(ui, workspace_command.repo().view())?;
|
||||
print_trackable_remote_bookmarks(ui, workspace_command.repo().view())?;
|
||||
}
|
||||
GitInitMode::Internal => {
|
||||
Workspace::init_internal_git(command.settings(), workspace_root)?;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ use jj_lib::git::GitBranchPushTargets;
|
|||
use jj_lib::git::GitPushError;
|
||||
use jj_lib::object_id::ObjectId;
|
||||
use jj_lib::op_store::RefTarget;
|
||||
use jj_lib::refs::classify_branch_push_action;
|
||||
use jj_lib::refs::classify_bookmark_push_action;
|
||||
use jj_lib::refs::BranchPushAction;
|
||||
use jj_lib::refs::BranchPushUpdate;
|
||||
use jj_lib::refs::LocalAndRemoteRef;
|
||||
|
|
@ -56,51 +56,52 @@ use crate::ui::Ui;
|
|||
|
||||
/// Push to a Git remote
|
||||
///
|
||||
/// By default, pushes any branches pointing to
|
||||
/// `remote_branches(remote=<remote>)..@`. Use `--branch` to push specific
|
||||
/// branches. Use `--all` to push all branches. Use `--change` to generate
|
||||
/// branch names based on the change IDs of specific commits.
|
||||
/// By default, pushes any bookmarks pointing to
|
||||
/// `remote_bookmarks(remote=<remote>)..@`. Use `--bookmark` to push specific
|
||||
/// bookmarks. Use `--all` to push all bookmarks. Use `--change` to generate
|
||||
/// bookmark names based on the change IDs of specific commits.
|
||||
///
|
||||
/// Before the command actually moves, creates, or deletes a remote branch, it
|
||||
/// Before the command actually moves, creates, or deletes a remote bookmark, it
|
||||
/// makes several [safety checks]. If there is a problem, you may need to run
|
||||
/// `jj git fetch --remote <remote name>` and/or resolve some [branch
|
||||
/// `jj git fetch --remote <remote name>` and/or resolve some [bookmark
|
||||
/// conflicts].
|
||||
///
|
||||
/// [safety checks]:
|
||||
/// https://martinvonz.github.io/jj/latest/branches/#pushing-branches-safety-checks
|
||||
/// https://martinvonz.github.io/jj/latest/bookmarks/#pushing-bookmarks-safety-checks
|
||||
///
|
||||
/// [branch conflicts]:
|
||||
/// https://martinvonz.github.io/jj/latest/branches/#conflicts
|
||||
/// [bookmark conflicts]:
|
||||
/// https://martinvonz.github.io/jj/latest/bookmarks/#conflicts
|
||||
|
||||
#[derive(clap::Args, Clone, Debug)]
|
||||
#[command(group(ArgGroup::new("specific").args(&["branch", "change", "revisions"]).multiple(true)))]
|
||||
#[command(group(ArgGroup::new("specific").args(&["bookmark", "change", "revisions"]).multiple(true)))]
|
||||
#[command(group(ArgGroup::new("what").args(&["all", "deleted", "tracked"]).conflicts_with("specific")))]
|
||||
pub struct GitPushArgs {
|
||||
/// The remote to push to (only named remotes are supported)
|
||||
#[arg(long)]
|
||||
remote: Option<String>,
|
||||
/// Push only this branch, or branches matching a pattern (can be repeated)
|
||||
/// Push only this bookmark, or bookmarks matching a pattern (can be
|
||||
/// repeated)
|
||||
///
|
||||
/// By default, the specified name matches exactly. Use `glob:` prefix to
|
||||
/// select branches by wildcard pattern. For details, see
|
||||
/// select bookmarks by wildcard pattern. For details, see
|
||||
/// https://martinvonz.github.io/jj/latest/revsets#string-patterns.
|
||||
#[arg(long, short, value_parser = StringPattern::parse)]
|
||||
branch: Vec<StringPattern>,
|
||||
/// Push all branches (including deleted branches)
|
||||
bookmark: Vec<StringPattern>,
|
||||
/// Push all bookmarks (including deleted bookmarks)
|
||||
#[arg(long)]
|
||||
all: bool,
|
||||
/// Push all tracked branches (including deleted branches)
|
||||
/// Push all tracked bookmarks (including deleted bookmarks)
|
||||
///
|
||||
/// This usually means that the branch was already pushed to or fetched from
|
||||
/// the relevant remote. For details, see
|
||||
/// https://martinvonz.github.io/jj/latest/branches#remotes-and-tracked-branches
|
||||
/// This usually means that the bookmark was already pushed to or fetched
|
||||
/// from the relevant remote. For details, see
|
||||
/// https://martinvonz.github.io/jj/latest/bookmarks#remotes-and-tracked-bookmarks
|
||||
#[arg(long)]
|
||||
tracked: bool,
|
||||
/// Push all deleted branches
|
||||
/// Push all deleted bookmarks
|
||||
///
|
||||
/// Only tracked branches can be successfully deleted on the remote. A
|
||||
/// warning will be printed if any untracked branches on the remote
|
||||
/// correspond to missing local branches.
|
||||
/// Only tracked bookmarks can be successfully deleted on the remote. A
|
||||
/// warning will be printed if any untracked bookmarks on the remote
|
||||
/// correspond to missing local bookmarks.
|
||||
#[arg(long)]
|
||||
deleted: bool,
|
||||
/// Allow pushing commits with empty descriptions
|
||||
|
|
@ -109,10 +110,10 @@ pub struct GitPushArgs {
|
|||
/// Allow pushing commits that are private
|
||||
#[arg(long)]
|
||||
allow_private: bool,
|
||||
/// Push branches pointing to these commits (can be repeated)
|
||||
/// Push bookmarks pointing to these commits (can be repeated)
|
||||
#[arg(long, short)]
|
||||
revisions: Vec<RevisionArg>,
|
||||
/// Push this commit by creating a branch based on its change ID (can be
|
||||
/// Push this commit by creating a bookmark based on its change ID (can be
|
||||
/// repeated)
|
||||
#[arg(long, short)]
|
||||
change: Vec<RevisionArg>,
|
||||
|
|
@ -121,10 +122,10 @@ pub struct GitPushArgs {
|
|||
dry_run: bool,
|
||||
}
|
||||
|
||||
fn make_branch_term(branch_names: &[impl fmt::Display]) -> String {
|
||||
match branch_names {
|
||||
[branch_name] => format!("branch {}", branch_name),
|
||||
branch_names => format!("branches {}", branch_names.iter().join(", ")),
|
||||
fn make_bookmark_term(bookmark_names: &[impl fmt::Display]) -> String {
|
||||
match bookmark_names {
|
||||
[bookmark_name] => format!("bookmark {}", bookmark_name),
|
||||
bookmark_names => format!("bookmarks {}", bookmark_names.iter().join(", ")),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -156,85 +157,85 @@ pub fn cmd_git_push(
|
|||
let tx_description;
|
||||
let mut branch_updates = vec![];
|
||||
if args.all {
|
||||
for (branch_name, targets) in repo.view().local_remote_branches(&remote) {
|
||||
match classify_branch_update(branch_name, &remote, targets) {
|
||||
Ok(Some(update)) => branch_updates.push((branch_name.to_owned(), update)),
|
||||
for (bookmark_name, targets) in repo.view().local_remote_bookmarks(&remote) {
|
||||
match classify_bookmark_update(bookmark_name, &remote, targets) {
|
||||
Ok(Some(update)) => branch_updates.push((bookmark_name.to_owned(), update)),
|
||||
Ok(None) => {}
|
||||
Err(reason) => reason.print(ui)?,
|
||||
}
|
||||
}
|
||||
tx_description = format!("push all branches to git remote {remote}");
|
||||
tx_description = format!("push all bookmarks to git remote {remote}");
|
||||
} else if args.tracked {
|
||||
for (branch_name, targets) in repo.view().local_remote_branches(&remote) {
|
||||
for (bookmark_name, targets) in repo.view().local_remote_bookmarks(&remote) {
|
||||
if !targets.remote_ref.is_tracking() {
|
||||
continue;
|
||||
}
|
||||
match classify_branch_update(branch_name, &remote, targets) {
|
||||
Ok(Some(update)) => branch_updates.push((branch_name.to_owned(), update)),
|
||||
match classify_bookmark_update(bookmark_name, &remote, targets) {
|
||||
Ok(Some(update)) => branch_updates.push((bookmark_name.to_owned(), update)),
|
||||
Ok(None) => {}
|
||||
Err(reason) => reason.print(ui)?,
|
||||
}
|
||||
}
|
||||
tx_description = format!("push all tracked branches to git remote {remote}");
|
||||
tx_description = format!("push all tracked bookmarks to git remote {remote}");
|
||||
} else if args.deleted {
|
||||
for (branch_name, targets) in repo.view().local_remote_branches(&remote) {
|
||||
for (bookmark_name, targets) in repo.view().local_remote_bookmarks(&remote) {
|
||||
if targets.local_target.is_present() {
|
||||
continue;
|
||||
}
|
||||
match classify_branch_update(branch_name, &remote, targets) {
|
||||
Ok(Some(update)) => branch_updates.push((branch_name.to_owned(), update)),
|
||||
match classify_bookmark_update(bookmark_name, &remote, targets) {
|
||||
Ok(Some(update)) => branch_updates.push((bookmark_name.to_owned(), update)),
|
||||
Ok(None) => {}
|
||||
Err(reason) => reason.print(ui)?,
|
||||
}
|
||||
}
|
||||
tx_description = format!("push all deleted branches to git remote {remote}");
|
||||
tx_description = format!("push all deleted bookmarks to git remote {remote}");
|
||||
} else {
|
||||
let mut seen_branches: HashSet<&str> = HashSet::new();
|
||||
let mut seen_bookmarks: HashSet<&str> = HashSet::new();
|
||||
|
||||
// Process --change branches first because matching branches can be moved.
|
||||
let change_branch_names = update_change_branches(
|
||||
// Process --change bookmarks first because matching bookmarks can be moved.
|
||||
let change_bookmark_names = update_change_bookmarks(
|
||||
ui,
|
||||
&mut tx,
|
||||
&args.change,
|
||||
&command.settings().push_branch_prefix(),
|
||||
&command.settings().push_bookmark_prefix(),
|
||||
)?;
|
||||
let change_branches = change_branch_names.iter().map(|branch_name| {
|
||||
let change_bookmarks = change_bookmark_names.iter().map(|bookmark_name| {
|
||||
let targets = LocalAndRemoteRef {
|
||||
local_target: tx.repo().view().get_local_branch(branch_name),
|
||||
remote_ref: tx.repo().view().get_remote_branch(branch_name, &remote),
|
||||
local_target: tx.repo().view().get_local_bookmark(bookmark_name),
|
||||
remote_ref: tx.repo().view().get_remote_bookmark(bookmark_name, &remote),
|
||||
};
|
||||
(branch_name.as_ref(), targets)
|
||||
(bookmark_name.as_ref(), targets)
|
||||
});
|
||||
let branches_by_name = find_branches_to_push(repo.view(), &args.branch, &remote)?;
|
||||
for (branch_name, targets) in change_branches.chain(branches_by_name.iter().copied()) {
|
||||
if !seen_branches.insert(branch_name) {
|
||||
let bookmarks_by_name = find_bookmarks_to_push(repo.view(), &args.bookmark, &remote)?;
|
||||
for (bookmark_name, targets) in change_bookmarks.chain(bookmarks_by_name.iter().copied()) {
|
||||
if !seen_bookmarks.insert(bookmark_name) {
|
||||
continue;
|
||||
}
|
||||
match classify_branch_update(branch_name, &remote, targets) {
|
||||
Ok(Some(update)) => branch_updates.push((branch_name.to_owned(), update)),
|
||||
match classify_bookmark_update(bookmark_name, &remote, targets) {
|
||||
Ok(Some(update)) => branch_updates.push((bookmark_name.to_owned(), update)),
|
||||
Ok(None) => writeln!(
|
||||
ui.status(),
|
||||
"Branch {branch_name}@{remote} already matches {branch_name}",
|
||||
"Branch {bookmark_name}@{remote} already matches {bookmark_name}",
|
||||
)?,
|
||||
Err(reason) => return Err(reason.into()),
|
||||
}
|
||||
}
|
||||
|
||||
let use_default_revset =
|
||||
args.branch.is_empty() && args.change.is_empty() && args.revisions.is_empty();
|
||||
let branches_targeted = find_branches_targeted_by_revisions(
|
||||
args.bookmark.is_empty() && args.change.is_empty() && args.revisions.is_empty();
|
||||
let bookmarks_targeted = find_bookmarks_targeted_by_revisions(
|
||||
ui,
|
||||
tx.base_workspace_helper(),
|
||||
&remote,
|
||||
&args.revisions,
|
||||
use_default_revset,
|
||||
)?;
|
||||
for &(branch_name, targets) in &branches_targeted {
|
||||
if !seen_branches.insert(branch_name) {
|
||||
for &(bookmark_name, targets) in &bookmarks_targeted {
|
||||
if !seen_bookmarks.insert(bookmark_name) {
|
||||
continue;
|
||||
}
|
||||
match classify_branch_update(branch_name, &remote, targets) {
|
||||
Ok(Some(update)) => branch_updates.push((branch_name.to_owned(), update)),
|
||||
match classify_bookmark_update(bookmark_name, &remote, targets) {
|
||||
Ok(Some(update)) => branch_updates.push((bookmark_name.to_owned(), update)),
|
||||
Ok(None) => {}
|
||||
Err(reason) => reason.print(ui)?,
|
||||
}
|
||||
|
|
@ -242,10 +243,10 @@ pub fn cmd_git_push(
|
|||
|
||||
tx_description = format!(
|
||||
"push {} to git remote {}",
|
||||
make_branch_term(
|
||||
make_bookmark_term(
|
||||
&branch_updates
|
||||
.iter()
|
||||
.map(|(branch, _)| branch.as_str())
|
||||
.map(|(bookmark, _)| bookmark.as_str())
|
||||
.collect_vec()
|
||||
),
|
||||
&remote
|
||||
|
|
@ -256,8 +257,8 @@ pub fn cmd_git_push(
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
let mut branch_push_direction = HashMap::new();
|
||||
for (branch_name, update) in &branch_updates {
|
||||
let mut bookmark_push_direction = HashMap::new();
|
||||
for (bookmark_name, update) in &branch_updates {
|
||||
let BranchPushUpdate {
|
||||
old_target: Some(old_target),
|
||||
new_target: Some(new_target),
|
||||
|
|
@ -266,8 +267,8 @@ pub fn cmd_git_push(
|
|||
continue;
|
||||
};
|
||||
assert_ne!(old_target, new_target);
|
||||
branch_push_direction.insert(
|
||||
branch_name.to_string(),
|
||||
bookmark_push_direction.insert(
|
||||
bookmark_name.to_string(),
|
||||
if repo.index().is_ancestor(old_target, new_target) {
|
||||
BranchMoveDirection::Forward
|
||||
} else if repo.index().is_ancestor(new_target, old_target) {
|
||||
|
|
@ -281,25 +282,26 @@ pub fn cmd_git_push(
|
|||
validate_commits_ready_to_push(&branch_updates, &remote, &tx, command, args)?;
|
||||
|
||||
writeln!(ui.status(), "Branch changes to push to {}:", &remote)?;
|
||||
for (branch_name, update) in &branch_updates {
|
||||
for (bookmark_name, update) in &branch_updates {
|
||||
match (&update.old_target, &update.new_target) {
|
||||
(Some(old_target), Some(new_target)) => {
|
||||
let old = short_commit_hash(old_target);
|
||||
let new = short_commit_hash(new_target);
|
||||
// TODO(ilyagr): Add color. Once there is color, "Move branch ... sideways" may
|
||||
// read more naturally than "Move sideways branch ...". Without color, it's hard
|
||||
// to see at a glance if one branch among many was moved sideways (say).
|
||||
// TODO: People on Discord suggest "Move branch ... forward by n commits",
|
||||
// possibly "Move branch ... sideways (X forward, Y back)".
|
||||
let msg = match branch_push_direction.get(branch_name).unwrap() {
|
||||
// TODO(ilyagr): Add color. Once there is color, "Move bookmark ... sideways"
|
||||
// may read more naturally than "Move sideways bookmark ...".
|
||||
// Without color, it's hard to see at a glance if one bookmark
|
||||
// among many was moved sideways (say). TODO: People on Discord
|
||||
// suggest "Move bookmark ... forward by n commits",
|
||||
// possibly "Move bookmark ... sideways (X forward, Y back)".
|
||||
let msg = match bookmark_push_direction.get(bookmark_name).unwrap() {
|
||||
BranchMoveDirection::Forward => {
|
||||
format!("Move forward branch {branch_name} from {old} to {new}")
|
||||
format!("Move forward bookmark {bookmark_name} from {old} to {new}")
|
||||
}
|
||||
BranchMoveDirection::Backward => {
|
||||
format!("Move backward branch {branch_name} from {old} to {new}")
|
||||
format!("Move backward bookmark {bookmark_name} from {old} to {new}")
|
||||
}
|
||||
BranchMoveDirection::Sideways => {
|
||||
format!("Move sideways branch {branch_name} from {old} to {new}")
|
||||
format!("Move sideways bookmark {bookmark_name} from {old} to {new}")
|
||||
}
|
||||
};
|
||||
writeln!(ui.status(), " {msg}")?;
|
||||
|
|
@ -307,19 +309,19 @@ pub fn cmd_git_push(
|
|||
(Some(old_target), None) => {
|
||||
writeln!(
|
||||
ui.status(),
|
||||
" Delete branch {branch_name} from {}",
|
||||
" Delete bookmark {bookmark_name} from {}",
|
||||
short_commit_hash(old_target)
|
||||
)?;
|
||||
}
|
||||
(None, Some(new_target)) => {
|
||||
writeln!(
|
||||
ui.status(),
|
||||
" Add branch {branch_name} to {}",
|
||||
" Add bookmark {bookmark_name} to {}",
|
||||
short_commit_hash(new_target)
|
||||
)?;
|
||||
}
|
||||
(None, None) => {
|
||||
panic!("Not pushing any change to branch {branch_name}");
|
||||
panic!("Not pushing any change to bookmark {bookmark_name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -341,12 +343,12 @@ pub fn cmd_git_push(
|
|||
GitPushError::InternalGitError(err) => map_git_error(err),
|
||||
GitPushError::RefInUnexpectedLocation(refs) => user_error_with_hint(
|
||||
format!(
|
||||
"Refusing to push a branch that unexpectedly moved on the remote. Affected refs: \
|
||||
{}",
|
||||
"Refusing to push a bookmark that unexpectedly moved on the remote. Affected \
|
||||
refs: {}",
|
||||
refs.join(", ")
|
||||
),
|
||||
"Try fetching from the remote, then make the branch point to where you want it to be, \
|
||||
and push again.",
|
||||
"Try fetching from the remote, then make the bookmark point to where you want it to \
|
||||
be, and push again.",
|
||||
),
|
||||
_ => user_error(err),
|
||||
})?;
|
||||
|
|
@ -358,7 +360,7 @@ pub fn cmd_git_push(
|
|||
/// Validates that the commits that will be pushed are ready (have authorship
|
||||
/// information, are not conflicted, etc.)
|
||||
fn validate_commits_ready_to_push(
|
||||
branch_updates: &[(String, BranchPushUpdate)],
|
||||
bookmark_updates: &[(String, BranchPushUpdate)],
|
||||
remote: &str,
|
||||
tx: &WorkspaceCommandTransaction,
|
||||
command: &CommandHelper,
|
||||
|
|
@ -367,13 +369,13 @@ fn validate_commits_ready_to_push(
|
|||
let workspace_helper = tx.base_workspace_helper();
|
||||
let repo = workspace_helper.repo();
|
||||
|
||||
let new_heads = branch_updates
|
||||
let new_heads = bookmark_updates
|
||||
.iter()
|
||||
.filter_map(|(_, update)| update.new_target.clone())
|
||||
.collect_vec();
|
||||
let old_heads = repo
|
||||
.view()
|
||||
.remote_branches(remote)
|
||||
.remote_bookmarks(remote)
|
||||
.flat_map(|(_, old_head)| old_head.target.added_ids())
|
||||
.cloned()
|
||||
.collect_vec();
|
||||
|
|
@ -476,40 +478,42 @@ impl From<RejectedBranchUpdateReason> for CommandError {
|
|||
}
|
||||
}
|
||||
|
||||
fn classify_branch_update(
|
||||
branch_name: &str,
|
||||
fn classify_bookmark_update(
|
||||
bookmark_name: &str,
|
||||
remote_name: &str,
|
||||
targets: LocalAndRemoteRef,
|
||||
) -> Result<Option<BranchPushUpdate>, RejectedBranchUpdateReason> {
|
||||
let push_action = classify_branch_push_action(targets);
|
||||
let push_action = classify_bookmark_push_action(targets);
|
||||
match push_action {
|
||||
BranchPushAction::AlreadyMatches => Ok(None),
|
||||
BranchPushAction::LocalConflicted => Err(RejectedBranchUpdateReason {
|
||||
message: format!("Branch {branch_name} is conflicted"),
|
||||
message: format!("Branch {bookmark_name} is conflicted"),
|
||||
hint: Some(
|
||||
"Run `jj branch list` to inspect, and use `jj branch set` to fix it up.".to_owned(),
|
||||
"Run `jj bookmark list` to inspect, and use `jj bookmark set` to fix it up."
|
||||
.to_owned(),
|
||||
),
|
||||
}),
|
||||
BranchPushAction::RemoteConflicted => Err(RejectedBranchUpdateReason {
|
||||
message: format!("Branch {branch_name}@{remote_name} is conflicted"),
|
||||
hint: Some("Run `jj git fetch` to update the conflicted remote branch.".to_owned()),
|
||||
message: format!("Branch {bookmark_name}@{remote_name} is conflicted"),
|
||||
hint: Some("Run `jj git fetch` to update the conflicted remote bookmark.".to_owned()),
|
||||
}),
|
||||
BranchPushAction::RemoteUntracked => Err(RejectedBranchUpdateReason {
|
||||
message: format!("Non-tracking remote branch {branch_name}@{remote_name} exists"),
|
||||
message: format!("Non-tracking remote bookmark {bookmark_name}@{remote_name} exists"),
|
||||
hint: Some(format!(
|
||||
"Run `jj branch track {branch_name}@{remote_name}` to import the remote branch."
|
||||
"Run `jj bookmark track {bookmark_name}@{remote_name}` to import the remote \
|
||||
bookmark."
|
||||
)),
|
||||
}),
|
||||
BranchPushAction::Update(update) => Ok(Some(update)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates or moves branches based on the change IDs.
|
||||
fn update_change_branches(
|
||||
/// Creates or moves bookmarks based on the change IDs.
|
||||
fn update_change_bookmarks(
|
||||
ui: &Ui,
|
||||
tx: &mut WorkspaceCommandTransaction,
|
||||
changes: &[RevisionArg],
|
||||
branch_prefix: &str,
|
||||
bookmark_prefix: &str,
|
||||
) -> Result<Vec<String>, CommandError> {
|
||||
if changes.is_empty() {
|
||||
// NOTE: we don't want resolve_some_revsets_default_single to fail if the
|
||||
|
|
@ -517,71 +521,71 @@ fn update_change_branches(
|
|||
return Ok(vec![]);
|
||||
}
|
||||
|
||||
let mut branch_names = Vec::new();
|
||||
let mut bookmark_names = Vec::new();
|
||||
let workspace_command = tx.base_workspace_helper();
|
||||
let all_commits = workspace_command.resolve_some_revsets_default_single(changes)?;
|
||||
|
||||
for commit in all_commits {
|
||||
let workspace_command = tx.base_workspace_helper();
|
||||
let short_change_id = short_change_hash(commit.change_id());
|
||||
let mut branch_name = format!("{branch_prefix}{}", commit.change_id().hex());
|
||||
let mut bookmark_name = format!("{bookmark_prefix}{}", commit.change_id().hex());
|
||||
let view = tx.base_repo().view();
|
||||
if view.get_local_branch(&branch_name).is_absent() {
|
||||
// A local branch with the full change ID doesn't exist already, so use the
|
||||
if view.get_local_bookmark(&bookmark_name).is_absent() {
|
||||
// A local bookmark with the full change ID doesn't exist already, so use the
|
||||
// short ID if it's not ambiguous (which it shouldn't be most of the time).
|
||||
if workspace_command
|
||||
.resolve_single_rev(&RevisionArg::from(short_change_id.clone()))
|
||||
.is_ok()
|
||||
{
|
||||
// Short change ID is not ambiguous, so update the branch name to use it.
|
||||
branch_name = format!("{branch_prefix}{short_change_id}");
|
||||
// Short change ID is not ambiguous, so update the bookmark name to use it.
|
||||
bookmark_name = format!("{bookmark_prefix}{short_change_id}");
|
||||
};
|
||||
}
|
||||
if view.get_local_branch(&branch_name).is_absent() {
|
||||
if view.get_local_bookmark(&bookmark_name).is_absent() {
|
||||
writeln!(
|
||||
ui.status(),
|
||||
"Creating branch {branch_name} for revision {short_change_id}",
|
||||
"Creating bookmark {bookmark_name} for revision {short_change_id}",
|
||||
)?;
|
||||
}
|
||||
tx.repo_mut()
|
||||
.set_local_branch_target(&branch_name, RefTarget::normal(commit.id().clone()));
|
||||
branch_names.push(branch_name);
|
||||
.set_local_bookmark_target(&bookmark_name, RefTarget::normal(commit.id().clone()));
|
||||
bookmark_names.push(bookmark_name);
|
||||
}
|
||||
Ok(branch_names)
|
||||
Ok(bookmark_names)
|
||||
}
|
||||
|
||||
fn find_branches_to_push<'a>(
|
||||
fn find_bookmarks_to_push<'a>(
|
||||
view: &'a View,
|
||||
branch_patterns: &[StringPattern],
|
||||
bookmark_patterns: &[StringPattern],
|
||||
remote_name: &str,
|
||||
) -> Result<Vec<(&'a str, LocalAndRemoteRef<'a>)>, CommandError> {
|
||||
let mut matching_branches = vec![];
|
||||
let mut matching_bookmarks = vec![];
|
||||
let mut unmatched_patterns = vec![];
|
||||
for pattern in branch_patterns {
|
||||
for pattern in bookmark_patterns {
|
||||
let mut matches = view
|
||||
.local_remote_branches_matching(pattern, remote_name)
|
||||
.local_remote_bookmarks_matching(pattern, remote_name)
|
||||
.filter(|(_, targets)| {
|
||||
// If the remote exists but is not tracking, the absent local shouldn't
|
||||
// be considered a deleted branch.
|
||||
// be considered a deleted bookmark.
|
||||
targets.local_target.is_present() || targets.remote_ref.is_tracking()
|
||||
})
|
||||
.peekable();
|
||||
if matches.peek().is_none() {
|
||||
unmatched_patterns.push(pattern);
|
||||
}
|
||||
matching_branches.extend(matches);
|
||||
matching_bookmarks.extend(matches);
|
||||
}
|
||||
match &unmatched_patterns[..] {
|
||||
[] => Ok(matching_branches),
|
||||
[pattern] if pattern.is_exact() => Err(user_error(format!("No such branch: {pattern}"))),
|
||||
[] => Ok(matching_bookmarks),
|
||||
[pattern] if pattern.is_exact() => Err(user_error(format!("No such bookmark: {pattern}"))),
|
||||
patterns => Err(user_error(format!(
|
||||
"No matching branches for patterns: {}",
|
||||
"No matching bookmarks for patterns: {}",
|
||||
patterns.iter().join(", ")
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
fn find_branches_targeted_by_revisions<'a>(
|
||||
fn find_bookmarks_targeted_by_revisions<'a>(
|
||||
ui: &Ui,
|
||||
workspace_command: &'a WorkspaceCommandHelper,
|
||||
remote_name: &str,
|
||||
|
|
@ -593,44 +597,44 @@ fn find_branches_targeted_by_revisions<'a>(
|
|||
let Some(wc_commit_id) = workspace_command.get_wc_commit_id().cloned() else {
|
||||
return Err(user_error("Nothing checked out in this workspace"));
|
||||
};
|
||||
let current_branches_expression = RevsetExpression::remote_branches(
|
||||
let current_bookmarks_expression = RevsetExpression::remote_bookmarks(
|
||||
StringPattern::everything(),
|
||||
StringPattern::exact(remote_name),
|
||||
None,
|
||||
)
|
||||
.range(&RevsetExpression::commit(wc_commit_id))
|
||||
.intersection(&RevsetExpression::branches(StringPattern::everything()));
|
||||
let current_branches_revset =
|
||||
current_branches_expression.evaluate_programmatic(workspace_command.repo().as_ref())?;
|
||||
revision_commit_ids.extend(current_branches_revset.iter());
|
||||
.intersection(&RevsetExpression::bookmarks(StringPattern::everything()));
|
||||
let current_bookmarks_revset = current_bookmarks_expression
|
||||
.evaluate_programmatic(workspace_command.repo().as_ref())?;
|
||||
revision_commit_ids.extend(current_bookmarks_revset.iter());
|
||||
if revision_commit_ids.is_empty() {
|
||||
writeln!(
|
||||
ui.warning_default(),
|
||||
"No branches found in the default push revset: \
|
||||
remote_branches(remote={remote_name})..@"
|
||||
"No bookmarks found in the default push revset: \
|
||||
remote_bookmarks(remote={remote_name})..@"
|
||||
)?;
|
||||
}
|
||||
}
|
||||
for rev_arg in revisions {
|
||||
let mut expression = workspace_command.parse_revset(rev_arg)?;
|
||||
expression.intersect_with(&RevsetExpression::branches(StringPattern::everything()));
|
||||
expression.intersect_with(&RevsetExpression::bookmarks(StringPattern::everything()));
|
||||
let mut commit_ids = expression.evaluate_to_commit_ids()?.peekable();
|
||||
if commit_ids.peek().is_none() {
|
||||
writeln!(
|
||||
ui.warning_default(),
|
||||
"No branches point to the specified revisions: {rev_arg}"
|
||||
"No bookmarks point to the specified revisions: {rev_arg}"
|
||||
)?;
|
||||
}
|
||||
revision_commit_ids.extend(commit_ids);
|
||||
}
|
||||
let branches_targeted = workspace_command
|
||||
let bookmarks_targeted = workspace_command
|
||||
.repo()
|
||||
.view()
|
||||
.local_remote_branches(remote_name)
|
||||
.local_remote_bookmarks(remote_name)
|
||||
.filter(|(_, targets)| {
|
||||
let mut local_ids = targets.local_target.added_ids();
|
||||
local_ids.any(|id| revision_commit_ids.contains(id))
|
||||
})
|
||||
.collect_vec();
|
||||
Ok(branches_targeted)
|
||||
Ok(bookmarks_targeted)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ mod abandon;
|
|||
mod backout;
|
||||
#[cfg(feature = "bench")]
|
||||
mod bench;
|
||||
mod branch;
|
||||
mod bookmark;
|
||||
mod checkout;
|
||||
mod commit;
|
||||
mod config;
|
||||
|
|
@ -77,8 +77,10 @@ enum Command {
|
|||
#[command(subcommand)]
|
||||
Bench(bench::BenchCommand),
|
||||
#[command(subcommand)]
|
||||
Branch(branch::BranchCommand),
|
||||
// TODO: Delete `cat` in jj 0.25+
|
||||
Bookmark(bookmark::BookmarkCommand),
|
||||
// TODO: Remove in jj 0.28+
|
||||
#[command(subcommand, hide = true)]
|
||||
Branch(bookmark::BookmarkCommand),
|
||||
#[command(alias = "print", hide = true)]
|
||||
Cat(file::show::FileShowArgs),
|
||||
#[command(hide = true)]
|
||||
|
|
@ -110,7 +112,7 @@ enum Command {
|
|||
Init(init::InitArgs),
|
||||
Interdiff(interdiff::InterdiffArgs),
|
||||
Log(log::LogArgs),
|
||||
/// Merge work from multiple branches (DEPRECATED, use `jj new`)
|
||||
/// Merge work from multiple bookmarks (DEPRECATED, use `jj new`)
|
||||
///
|
||||
/// Unlike most other VCSs, `jj merge` does not implicitly include the
|
||||
/// working copy revision's parent as one of the parents of the merge;
|
||||
|
|
@ -182,7 +184,11 @@ pub fn run_command(ui: &mut Ui, command_helper: &CommandHelper) -> Result<(), Co
|
|||
Command::Backout(args) => backout::cmd_backout(ui, command_helper, args),
|
||||
#[cfg(feature = "bench")]
|
||||
Command::Bench(args) => bench::cmd_bench(ui, command_helper, args),
|
||||
Command::Branch(args) => branch::cmd_branch(ui, command_helper, args),
|
||||
Command::Bookmark(args) => bookmark::cmd_bookmark(ui, command_helper, args),
|
||||
Command::Branch(args) => {
|
||||
let cmd = renamed_cmd("branch", "bookmark", bookmark::cmd_bookmark);
|
||||
cmd(ui, command_helper, args)
|
||||
}
|
||||
Command::Cat(args) => {
|
||||
let cmd = renamed_cmd("cat", "file show", file::show::cmd_file_show);
|
||||
cmd(ui, command_helper, args)
|
||||
|
|
@ -243,7 +249,7 @@ pub fn run_command(ui: &mut Ui, command_helper: &CommandHelper) -> Result<(), Co
|
|||
}
|
||||
|
||||
/// Wraps deprecated command of `old_name` which has been renamed to `new_name`.
|
||||
fn renamed_cmd<Args>(
|
||||
pub(crate) fn renamed_cmd<Args>(
|
||||
old_name: &'static str,
|
||||
new_name: &'static str,
|
||||
cmd: impl Fn(&mut Ui, &CommandHelper, &Args) -> Result<(), CommandError>,
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ pub(crate) fn cmd_new(
|
|||
if should_advance_branches {
|
||||
advance_branches_target = Some(parent_commit_ids[0].clone());
|
||||
advanceable_branches =
|
||||
workspace_command.get_advanceable_branches(parent_commits[0].parent_ids())?;
|
||||
workspace_command.get_advanceable_bookmarks(parent_commits[0].parent_ids())?;
|
||||
}
|
||||
};
|
||||
workspace_command.check_rewritable(children_commits.iter().ids())?;
|
||||
|
|
@ -222,7 +222,7 @@ pub(crate) fn cmd_new(
|
|||
|
||||
// Does nothing if there's no branches to advance.
|
||||
if let Some(target) = advance_branches_target {
|
||||
tx.advance_branches(advanceable_branches, &target);
|
||||
tx.advance_bookmarks(advanceable_branches, &target);
|
||||
}
|
||||
|
||||
tx.finish(ui, "new empty commit")?;
|
||||
|
|
|
|||
|
|
@ -300,15 +300,15 @@ pub fn show_op_diff(
|
|||
}
|
||||
}
|
||||
|
||||
let changed_local_branches = diff_named_ref_targets(
|
||||
from_repo.view().local_branches(),
|
||||
to_repo.view().local_branches(),
|
||||
let changed_local_bookmarks = diff_named_ref_targets(
|
||||
from_repo.view().local_bookmarks(),
|
||||
to_repo.view().local_bookmarks(),
|
||||
)
|
||||
.collect_vec();
|
||||
if !changed_local_branches.is_empty() {
|
||||
if !changed_local_bookmarks.is_empty() {
|
||||
writeln!(formatter)?;
|
||||
writeln!(formatter, "Changed local branches:")?;
|
||||
for (name, (from_target, to_target)) in changed_local_branches {
|
||||
for (name, (from_target, to_target)) in changed_local_bookmarks {
|
||||
writeln!(formatter, "{}:", name)?;
|
||||
write_ref_target_summary(
|
||||
formatter,
|
||||
|
|
@ -357,8 +357,8 @@ pub fn show_op_diff(
|
|||
}
|
||||
|
||||
let changed_remote_branches = diff_named_remote_refs(
|
||||
from_repo.view().all_remote_branches(),
|
||||
to_repo.view().all_remote_branches(),
|
||||
from_repo.view().all_remote_bookmarks(),
|
||||
to_repo.view().all_remote_bookmarks(),
|
||||
)
|
||||
// Skip updates to the local git repo, since they should typically be covered in
|
||||
// local branches.
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ fn view_with_desired_portions_restored(
|
|||
};
|
||||
jj_lib::op_store::View {
|
||||
head_ids: repo_source.head_ids.clone(),
|
||||
local_branches: repo_source.local_branches.clone(),
|
||||
local_bookmarks: repo_source.local_bookmarks.clone(),
|
||||
tags: repo_source.tags.clone(),
|
||||
remote_views: remote_source.remote_views.clone(),
|
||||
git_refs: current_view.git_refs.clone(),
|
||||
|
|
|
|||
|
|
@ -33,8 +33,7 @@ use crate::ui::Ui;
|
|||
///
|
||||
/// * The working copy commit and its (first) parent, and a summary of the
|
||||
/// changes between them
|
||||
///
|
||||
/// * Conflicted branches (see https://martinvonz.github.io/jj/latest/branches/)
|
||||
/// * Conflicted bookmarks (see https://martinvonz.github.io/jj/latest/bookmarks/)
|
||||
#[derive(clap::Args, Clone, Debug)]
|
||||
#[command(visible_alias = "st")]
|
||||
pub(crate) struct StatusArgs {
|
||||
|
|
@ -143,47 +142,50 @@ pub(crate) fn cmd_status(
|
|||
writeln!(formatter, "No working copy")?;
|
||||
}
|
||||
|
||||
let conflicted_local_branches = repo
|
||||
let conflicted_local_bookmarks = repo
|
||||
.view()
|
||||
.local_branches()
|
||||
.local_bookmarks()
|
||||
.filter(|(_, target)| target.has_conflict())
|
||||
.map(|(branch_name, _)| branch_name)
|
||||
.map(|(bookmark_name, _)| bookmark_name)
|
||||
.collect_vec();
|
||||
let conflicted_remote_branches = repo
|
||||
let conflicted_remote_bookmarks = repo
|
||||
.view()
|
||||
.all_remote_branches()
|
||||
.all_remote_bookmarks()
|
||||
.filter(|(_, remote_ref)| remote_ref.target.has_conflict())
|
||||
.map(|(full_name, _)| full_name)
|
||||
.collect_vec();
|
||||
if !conflicted_local_branches.is_empty() {
|
||||
if !conflicted_local_bookmarks.is_empty() {
|
||||
writeln!(
|
||||
formatter.labeled("conflict"),
|
||||
"These branches have conflicts:"
|
||||
"These bookmarks have conflicts:"
|
||||
)?;
|
||||
for branch_name in conflicted_local_branches {
|
||||
for bookmark_name in conflicted_local_bookmarks {
|
||||
write!(formatter, " ")?;
|
||||
write!(formatter.labeled("branch"), "{branch_name}")?;
|
||||
write!(formatter.labeled("bookmark"), "{bookmark_name}")?;
|
||||
writeln!(formatter)?;
|
||||
}
|
||||
writeln!(
|
||||
formatter,
|
||||
" Use `jj branch list` to see details. Use `jj branch set <name> -r <rev>` to \
|
||||
" Use `jj bookmark list` to see details. Use `jj bookmark set <name> -r <rev>` to \
|
||||
resolve."
|
||||
)?;
|
||||
}
|
||||
if !conflicted_remote_branches.is_empty() {
|
||||
if !conflicted_remote_bookmarks.is_empty() {
|
||||
writeln!(
|
||||
formatter.labeled("conflict"),
|
||||
"These remote branches have conflicts:"
|
||||
"These remote bookmarks have conflicts:"
|
||||
)?;
|
||||
for (branch_name, remote_name) in conflicted_remote_branches {
|
||||
for (bookmark_name, remote_name) in conflicted_remote_bookmarks {
|
||||
write!(formatter, " ")?;
|
||||
write!(formatter.labeled("branch"), "{branch_name}@{remote_name}")?;
|
||||
write!(
|
||||
formatter.labeled("bookmark"),
|
||||
"{bookmark_name}@{remote_name}"
|
||||
)?;
|
||||
writeln!(formatter)?;
|
||||
}
|
||||
writeln!(
|
||||
formatter,
|
||||
" Use `jj branch list` to see details. Use `jj git fetch` to resolve."
|
||||
" Use `jj bookmark list` to see details. Use `jj git fetch` to resolve."
|
||||
)?;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -450,16 +450,16 @@ impl<'repo> CommitTemplateBuildFnTable<'repo> {
|
|||
#[derive(Default)]
|
||||
pub struct CommitKeywordCache<'repo> {
|
||||
// Build index lazily, and Rc to get away from &self lifetime.
|
||||
branches_index: OnceCell<Rc<RefNamesIndex>>,
|
||||
bookmarks_index: OnceCell<Rc<RefNamesIndex>>,
|
||||
tags_index: OnceCell<Rc<RefNamesIndex>>,
|
||||
git_refs_index: OnceCell<Rc<RefNamesIndex>>,
|
||||
is_immutable_fn: OnceCell<Rc<RevsetContainingFn<'repo>>>,
|
||||
}
|
||||
|
||||
impl<'repo> CommitKeywordCache<'repo> {
|
||||
pub fn branches_index(&self, repo: &dyn Repo) -> &Rc<RefNamesIndex> {
|
||||
self.branches_index
|
||||
.get_or_init(|| Rc::new(build_branches_index(repo)))
|
||||
pub fn bookmarks_index(&self, repo: &dyn Repo) -> &Rc<RefNamesIndex> {
|
||||
self.bookmarks_index
|
||||
.get_or_init(|| Rc::new(build_bookmarks_index(repo)))
|
||||
}
|
||||
|
||||
pub fn tags_index(&self, repo: &dyn Repo) -> &Rc<RefNamesIndex> {
|
||||
|
|
@ -569,10 +569,13 @@ fn builtin_commit_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Comm
|
|||
},
|
||||
);
|
||||
map.insert(
|
||||
"branches",
|
||||
"bookmarks",
|
||||
|language, _build_ctx, self_property, function| {
|
||||
function.expect_no_arguments()?;
|
||||
let index = language.keyword_cache.branches_index(language.repo).clone();
|
||||
let index = language
|
||||
.keyword_cache
|
||||
.bookmarks_index(language.repo)
|
||||
.clone();
|
||||
let out_property = self_property.map(move |commit| {
|
||||
index
|
||||
.get(commit.id())
|
||||
|
|
@ -585,10 +588,13 @@ fn builtin_commit_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Comm
|
|||
},
|
||||
);
|
||||
map.insert(
|
||||
"local_branches",
|
||||
"local_bookmarks",
|
||||
|language, _build_ctx, self_property, function| {
|
||||
function.expect_no_arguments()?;
|
||||
let index = language.keyword_cache.branches_index(language.repo).clone();
|
||||
let index = language
|
||||
.keyword_cache
|
||||
.bookmarks_index(language.repo)
|
||||
.clone();
|
||||
let out_property = self_property.map(move |commit| {
|
||||
index
|
||||
.get(commit.id())
|
||||
|
|
@ -601,10 +607,13 @@ fn builtin_commit_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Comm
|
|||
},
|
||||
);
|
||||
map.insert(
|
||||
"remote_branches",
|
||||
"remote_bookmarks",
|
||||
|language, _build_ctx, self_property, function| {
|
||||
function.expect_no_arguments()?;
|
||||
let index = language.keyword_cache.branches_index(language.repo).clone();
|
||||
let index = language
|
||||
.keyword_cache
|
||||
.bookmarks_index(language.repo)
|
||||
.clone();
|
||||
let out_property = self_property.map(move |commit| {
|
||||
index
|
||||
.get(commit.id())
|
||||
|
|
@ -616,6 +625,11 @@ fn builtin_commit_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Comm
|
|||
Ok(L::wrap_ref_name_list(out_property))
|
||||
},
|
||||
);
|
||||
// TODO: Remove the following block after jj 0.28+
|
||||
map.insert("branches", map["bookmarks"]);
|
||||
map.insert("local_branches", map["local_bookmarks"]);
|
||||
map.insert("remote_branches", map["remote_bookmarks"]);
|
||||
|
||||
map.insert("tags", |language, _build_ctx, self_property, function| {
|
||||
function.expect_no_arguments()?;
|
||||
let index = language.keyword_cache.tags_index(language.repo).clone();
|
||||
|
|
@ -1115,14 +1129,14 @@ impl RefNamesIndex {
|
|||
}
|
||||
}
|
||||
|
||||
fn build_branches_index(repo: &dyn Repo) -> RefNamesIndex {
|
||||
fn build_bookmarks_index(repo: &dyn Repo) -> RefNamesIndex {
|
||||
let mut index = RefNamesIndex::default();
|
||||
for (branch_name, branch_target) in repo.view().branches() {
|
||||
let local_target = branch_target.local_target;
|
||||
let remote_refs = branch_target.remote_refs;
|
||||
for (bookmark_name, bookmark_target) in repo.view().bookmarks() {
|
||||
let local_target = bookmark_target.local_target;
|
||||
let remote_refs = bookmark_target.remote_refs;
|
||||
if local_target.is_present() {
|
||||
let ref_name = RefName::local(
|
||||
branch_name,
|
||||
bookmark_name,
|
||||
local_target.clone(),
|
||||
remote_refs.iter().map(|&(_, remote_ref)| remote_ref),
|
||||
);
|
||||
|
|
@ -1130,7 +1144,7 @@ fn build_branches_index(repo: &dyn Repo) -> RefNamesIndex {
|
|||
}
|
||||
for &(remote_name, remote_ref) in &remote_refs {
|
||||
let ref_name =
|
||||
RefName::remote(branch_name, remote_name, remote_ref.clone(), local_target);
|
||||
RefName::remote(bookmark_name, remote_name, remote_ref.clone(), local_target);
|
||||
index.insert(remote_ref.target.added_ids(), ref_name);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,11 @@
|
|||
"username" = "yellow"
|
||||
"timestamp" = "cyan"
|
||||
"working_copies" = "green"
|
||||
"bookmark" = "magenta"
|
||||
"bookmarks" = "magenta"
|
||||
"local_bookmarks" = "magenta"
|
||||
"remote_bookmarks" = "magenta"
|
||||
# TODO: Remove in jj 0.28+
|
||||
"branch" = "magenta"
|
||||
"branches" = "magenta"
|
||||
"local_branches" = "magenta"
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
[templates]
|
||||
branch_list = '''
|
||||
bookmark_list = '''
|
||||
if(remote,
|
||||
if(tracked,
|
||||
" " ++ separate(" ",
|
||||
label("branch", "@" ++ remote),
|
||||
label("bookmark", "@" ++ remote),
|
||||
format_tracked_remote_ref_distances(self),
|
||||
) ++ format_ref_targets(self),
|
||||
label("branch", name ++ "@" ++ remote) ++ format_ref_targets(self),
|
||||
label("bookmark", name ++ "@" ++ remote) ++ format_ref_targets(self),
|
||||
),
|
||||
label("branch", name) ++ if(present, format_ref_targets(self), " (deleted)"),
|
||||
label("bookmark", name) ++ if(present, format_ref_targets(self), " (deleted)"),
|
||||
) ++ "\n"
|
||||
'''
|
||||
|
||||
commit_summary = 'format_commit_summary_with_refs(self, branches)'
|
||||
commit_summary = 'format_commit_summary_with_refs(self, bookmarks)'
|
||||
|
||||
config_list = '''
|
||||
if(overridden,
|
||||
|
|
@ -51,7 +51,7 @@ if(root,
|
|||
format_short_change_id_with_hidden_and_divergent_info(self),
|
||||
if(author.email(), author.username(), email_placeholder),
|
||||
format_timestamp(committer.timestamp()),
|
||||
branches,
|
||||
bookmarks,
|
||||
tags,
|
||||
working_copies,
|
||||
git_head,
|
||||
|
|
@ -76,7 +76,7 @@ if(root,
|
|||
format_short_change_id_with_hidden_and_divergent_info(self),
|
||||
format_short_signature(author),
|
||||
format_timestamp(committer.timestamp()),
|
||||
branches,
|
||||
bookmarks,
|
||||
tags,
|
||||
working_copies,
|
||||
git_head,
|
||||
|
|
@ -99,7 +99,7 @@ builtin_log_detailed = '''
|
|||
concat(
|
||||
"Commit ID: " ++ commit_id ++ "\n",
|
||||
"Change ID: " ++ change_id ++ "\n",
|
||||
surround("Branches: ", "\n", separate(" ", local_branches, remote_branches)),
|
||||
surround("Bookmarks: ", "\n", separate(" ", local_bookmarks, remote_bookmarks)),
|
||||
surround("Tags: ", "\n", tags),
|
||||
"Author: " ++ format_detailed_signature(author) ++ "\n",
|
||||
"Committer: " ++ format_detailed_signature(committer) ++ "\n",
|
||||
|
|
@ -163,7 +163,7 @@ separate(" ",
|
|||
format_short_change_id(root.change_id()),
|
||||
label("root", "root()"),
|
||||
format_short_commit_id(root.commit_id()),
|
||||
root.branches()
|
||||
root.bookmarks()
|
||||
) ++ "\n"
|
||||
'''
|
||||
|
||||
|
|
|
|||
|
|
@ -322,7 +322,11 @@ impl RefStatus {
|
|||
RefName::RemoteBranch { branch, remote } => (
|
||||
format!("{branch}@{remote}"),
|
||||
RefKind::Branch,
|
||||
if repo.view().get_remote_branch(branch, remote).is_tracking() {
|
||||
if repo
|
||||
.view()
|
||||
.get_remote_bookmark(branch, remote)
|
||||
.is_tracking()
|
||||
{
|
||||
TrackingStatus::Tracked
|
||||
} else {
|
||||
TrackingStatus::Untracked
|
||||
|
|
|
|||
|
|
@ -13,16 +13,16 @@ This document contains the help content for the `jj` command-line program.
|
|||
* [`jj`↴](#jj)
|
||||
* [`jj abandon`↴](#jj-abandon)
|
||||
* [`jj backout`↴](#jj-backout)
|
||||
* [`jj branch`↴](#jj-branch)
|
||||
* [`jj branch create`↴](#jj-branch-create)
|
||||
* [`jj branch delete`↴](#jj-branch-delete)
|
||||
* [`jj branch forget`↴](#jj-branch-forget)
|
||||
* [`jj branch list`↴](#jj-branch-list)
|
||||
* [`jj branch move`↴](#jj-branch-move)
|
||||
* [`jj branch rename`↴](#jj-branch-rename)
|
||||
* [`jj branch set`↴](#jj-branch-set)
|
||||
* [`jj branch track`↴](#jj-branch-track)
|
||||
* [`jj branch untrack`↴](#jj-branch-untrack)
|
||||
* [`jj bookmark`↴](#jj-bookmark)
|
||||
* [`jj bookmark create`↴](#jj-bookmark-create)
|
||||
* [`jj bookmark delete`↴](#jj-bookmark-delete)
|
||||
* [`jj bookmark forget`↴](#jj-bookmark-forget)
|
||||
* [`jj bookmark list`↴](#jj-bookmark-list)
|
||||
* [`jj bookmark move`↴](#jj-bookmark-move)
|
||||
* [`jj bookmark rename`↴](#jj-bookmark-rename)
|
||||
* [`jj bookmark set`↴](#jj-bookmark-set)
|
||||
* [`jj bookmark track`↴](#jj-bookmark-track)
|
||||
* [`jj bookmark untrack`↴](#jj-bookmark-untrack)
|
||||
* [`jj commit`↴](#jj-commit)
|
||||
* [`jj config`↴](#jj-config)
|
||||
* [`jj config edit`↴](#jj-config-edit)
|
||||
|
|
@ -113,7 +113,7 @@ To get started, see the tutorial at https://martinvonz.github.io/jj/latest/tutor
|
|||
|
||||
* `abandon` — Abandon a revision
|
||||
* `backout` — Apply the reverse of a revision on top of another revision
|
||||
* `branch` — Manage branches
|
||||
* `bookmark` — Manage bookmarks
|
||||
* `commit` — Update the description and create a new change on top
|
||||
* `config` — Manage config options
|
||||
* `describe` — Update the change description or other metadata
|
||||
|
|
@ -226,201 +226,201 @@ Apply the reverse of a revision on top of another revision
|
|||
|
||||
|
||||
|
||||
## `jj branch`
|
||||
## `jj bookmark`
|
||||
|
||||
Manage branches
|
||||
Manage bookmarks
|
||||
|
||||
For information about branches, see https://martinvonz.github.io/jj/latest/branches/.
|
||||
For information about bookmarks, see https://martinvonz.github.io/jj/latest/docs/bookmarks.md.
|
||||
|
||||
**Usage:** `jj branch <COMMAND>`
|
||||
**Usage:** `jj bookmark <COMMAND>`
|
||||
|
||||
###### **Subcommands:**
|
||||
|
||||
* `create` — Create a new branch
|
||||
* `delete` — Delete an existing branch and propagate the deletion to remotes on the next push
|
||||
* `forget` — Forget everything about a branch, including its local and remote targets
|
||||
* `list` — List branches and their targets
|
||||
* `move` — Move existing branches to target revision
|
||||
* `rename` — Rename `old` branch name to `new` branch name
|
||||
* `set` — Create or update a branch to point to a certain commit
|
||||
* `track` — Start tracking given remote branches
|
||||
* `untrack` — Stop tracking given remote branches
|
||||
* `create` — Create a new bookmark
|
||||
* `delete` — Delete an existing bookmark and propagate the deletion to remotes on the next push
|
||||
* `forget` — Forget everything about a bookmark, including its local and remote targets
|
||||
* `list` — List bookmarks and their targets
|
||||
* `move` — Move existing bookmarks to target revision
|
||||
* `rename` — Rename `old` bookmark name to `new` bookmark name
|
||||
* `set` — Create or update a bookmark to point to a certain commit
|
||||
* `track` — Start tracking given remote bookmarks
|
||||
* `untrack` — Stop tracking given remote bookmarks
|
||||
|
||||
|
||||
|
||||
## `jj branch create`
|
||||
## `jj bookmark create`
|
||||
|
||||
Create a new branch
|
||||
Create a new bookmark
|
||||
|
||||
**Usage:** `jj branch create [OPTIONS] <NAMES>...`
|
||||
**Usage:** `jj bookmark create [OPTIONS] <NAMES>...`
|
||||
|
||||
###### **Arguments:**
|
||||
|
||||
* `<NAMES>` — The branches to create
|
||||
* `<NAMES>` — The bookmarks to create
|
||||
|
||||
###### **Options:**
|
||||
|
||||
* `-r`, `--revision <REVISION>` — The branch's target revision
|
||||
* `-r`, `--revision <REVISION>` — The bookmark's target revision
|
||||
|
||||
|
||||
|
||||
## `jj branch delete`
|
||||
## `jj bookmark delete`
|
||||
|
||||
Delete an existing branch and propagate the deletion to remotes on the next push
|
||||
Delete an existing bookmark and propagate the deletion to remotes on the next push
|
||||
|
||||
**Usage:** `jj branch delete <NAMES>...`
|
||||
**Usage:** `jj bookmark delete <NAMES>...`
|
||||
|
||||
###### **Arguments:**
|
||||
|
||||
* `<NAMES>` — The branches to delete
|
||||
* `<NAMES>` — The bookmarks to delete
|
||||
|
||||
By default, the specified name matches exactly. Use `glob:` prefix to select branches by wildcard pattern. For details, see https://martinvonz.github.io/jj/latest/revsets/#string-patterns.
|
||||
By default, the specified name matches exactly. Use `glob:` prefix to select bookmarks by wildcard pattern. For details, see https://martinvonz.github.io/jj/latest/revsets/#string-patterns.
|
||||
|
||||
|
||||
|
||||
## `jj branch forget`
|
||||
## `jj bookmark forget`
|
||||
|
||||
Forget everything about a branch, including its local and remote targets
|
||||
Forget everything about a bookmark, including its local and remote targets
|
||||
|
||||
A forgotten branch will not impact remotes on future pushes. It will be recreated on future pulls if it still exists in the remote.
|
||||
A forgotten bookmark will not impact remotes on future pushes. It will be recreated on future pulls if it still exists in the remote.
|
||||
|
||||
**Usage:** `jj branch forget <NAMES>...`
|
||||
**Usage:** `jj bookmark forget <NAMES>...`
|
||||
|
||||
###### **Arguments:**
|
||||
|
||||
* `<NAMES>` — The branches to forget
|
||||
* `<NAMES>` — The bookmarks to forget
|
||||
|
||||
By default, the specified name matches exactly. Use `glob:` prefix to select branches by wildcard pattern. For details, see https://martinvonz.github.io/jj/latest/revsets/#string-patterns.
|
||||
By default, the specified name matches exactly. Use `glob:` prefix to select bookmarks by wildcard pattern. For details, see https://martinvonz.github.io/jj/latest/revsets/#string-patterns.
|
||||
|
||||
|
||||
|
||||
## `jj branch list`
|
||||
## `jj bookmark list`
|
||||
|
||||
List branches and their targets
|
||||
List bookmarks and their targets
|
||||
|
||||
By default, a tracking remote branch will be included only if its target is different from the local target. A non-tracking remote branch won't be listed. For a conflicted branch (both local and remote), old target revisions are preceded by a "-" and new target revisions are preceded by a "+".
|
||||
By default, a tracking remote bookmark will be included only if its target is different from the local target. A non-tracking remote bookmark won't be listed. For a conflicted bookmark (both local and remote), old target revisions are preceded by a "-" and new target revisions are preceded by a "+".
|
||||
|
||||
For information about branches, see https://martinvonz.github.io/jj/latest/branches/.
|
||||
For information about bookmarks, see https://martinvonz.github.io/jj/docs/bookmarks.md.
|
||||
|
||||
**Usage:** `jj branch list [OPTIONS] [NAMES]...`
|
||||
**Usage:** `jj bookmark list [OPTIONS] [NAMES]...`
|
||||
|
||||
###### **Arguments:**
|
||||
|
||||
* `<NAMES>` — Show branches whose local name matches
|
||||
* `<NAMES>` — Show bookmarks whose local name matches
|
||||
|
||||
By default, the specified name matches exactly. Use `glob:` prefix to select branches by wildcard pattern. For details, see https://martinvonz.github.io/jj/latest/revsets/#string-patterns.
|
||||
By default, the specified name matches exactly. Use `glob:` prefix to select bookmarks by wildcard pattern. For details, see https://martinvonz.github.io/jj/docs/revsets.md#string-patterns.
|
||||
|
||||
###### **Options:**
|
||||
|
||||
* `-a`, `--all-remotes` — Show all tracking and non-tracking remote branches including the ones whose targets are synchronized with the local branches
|
||||
* `-t`, `--tracked` — Show remote tracked branches only. Omits local Git-tracking branches by default
|
||||
* `-c`, `--conflicted` — Show conflicted branches only
|
||||
* `-r`, `--revisions <REVISIONS>` — Show branches whose local targets are in the given revisions
|
||||
* `-a`, `--all-remotes` — Show all tracking and non-tracking remote bookmarks including the ones whose targets are synchronized with the local bookmarks
|
||||
* `-t`, `--tracked` — Show remote tracked bookmarks only. Omits local Git-tracking bookmarks by default
|
||||
* `-c`, `--conflicted` — Show conflicted bookmarks only
|
||||
* `-r`, `--revisions <REVISIONS>` — Show bookmarks whose local targets are in the given revisions
|
||||
|
||||
Note that `-r deleted_branch` will not work since `deleted_branch` wouldn't have a local target.
|
||||
* `-T`, `--template <TEMPLATE>` — Render each branch using the given template
|
||||
Note that `-r deleted_bookmark` will not work since `deleted_bookmark` wouldn't have a local target.
|
||||
* `-T`, `--template <TEMPLATE>` — Render each bookmark using the given template
|
||||
|
||||
All 0-argument methods of the `RefName` type are available as keywords.
|
||||
|
||||
For the syntax, see https://martinvonz.github.io/jj/latest/templates/
|
||||
For the syntax, see https://martinvonz.github.io/jj/latest/docs/templates.md
|
||||
|
||||
|
||||
|
||||
## `jj branch move`
|
||||
## `jj bookmark move`
|
||||
|
||||
Move existing branches to target revision
|
||||
Move existing bookmarks to target revision
|
||||
|
||||
If branch names are given, the specified branches will be updated to point to the target revision.
|
||||
If bookmark names are given, the specified bookmarks will be updated to point to the target revision.
|
||||
|
||||
If `--from` options are given, branches currently pointing to the specified revisions will be updated. The branches can also be filtered by names.
|
||||
If `--from` options are given, bookmarks currently pointing to the specified revisions will be updated. The bookmarks can also be filtered by names.
|
||||
|
||||
Example: pull up the nearest branches to the working-copy parent
|
||||
Example: pull up the nearest bookmarks to the working-copy parent
|
||||
|
||||
$ jj branch move --from 'heads(::@- & branches())' --to @-
|
||||
$ jj bookmark move --from 'heads(::@- & bookmarks())' --to @-
|
||||
|
||||
**Usage:** `jj branch move [OPTIONS] <--from <REVISIONS>|NAMES>`
|
||||
**Usage:** `jj bookmark move [OPTIONS] <--from <REVISIONS>|NAMES>`
|
||||
|
||||
###### **Arguments:**
|
||||
|
||||
* `<NAMES>` — Move branches matching the given name patterns
|
||||
* `<NAMES>` — Move bookmarks matching the given name patterns
|
||||
|
||||
By default, the specified name matches exactly. Use `glob:` prefix to select branches by wildcard pattern. For details, see https://martinvonz.github.io/jj/latest/revsets/#string-patterns.
|
||||
By default, the specified name matches exactly. Use `glob:` prefix to select bookmarks by wildcard pattern. For details, see https://martinvonz.github.io/jj/latest/revsets/#string-patterns.
|
||||
|
||||
###### **Options:**
|
||||
|
||||
* `--from <REVISIONS>` — Move branches from the given revisions
|
||||
* `--to <REVISION>` — Move branches to this revision
|
||||
* `--from <REVISIONS>` — Move bookmarks from the given revisions
|
||||
* `--to <REVISION>` — Move bookmarks to this revision
|
||||
|
||||
Default value: `@`
|
||||
* `-B`, `--allow-backwards` — Allow moving branches backwards or sideways
|
||||
* `-B`, `--allow-backwards` — Allow moving bookmarks backwards or sideways
|
||||
|
||||
|
||||
|
||||
## `jj branch rename`
|
||||
## `jj bookmark rename`
|
||||
|
||||
Rename `old` branch name to `new` branch name
|
||||
Rename `old` bookmark name to `new` bookmark name
|
||||
|
||||
The new branch name points at the same commit as the old branch name.
|
||||
The new bookmark name points at the same commit as the old bookmark name.
|
||||
|
||||
**Usage:** `jj branch rename <OLD> <NEW>`
|
||||
**Usage:** `jj bookmark rename <OLD> <NEW>`
|
||||
|
||||
###### **Arguments:**
|
||||
|
||||
* `<OLD>` — The old name of the branch
|
||||
* `<NEW>` — The new name of the branch
|
||||
* `<OLD>` — The old name of the bookmark
|
||||
* `<NEW>` — The new name of the bookmark
|
||||
|
||||
|
||||
|
||||
## `jj branch set`
|
||||
## `jj bookmark set`
|
||||
|
||||
Create or update a branch to point to a certain commit
|
||||
Create or update a bookmark to point to a certain commit
|
||||
|
||||
**Usage:** `jj branch set [OPTIONS] <NAMES>...`
|
||||
**Usage:** `jj bookmark set [OPTIONS] <NAMES>...`
|
||||
|
||||
###### **Arguments:**
|
||||
|
||||
* `<NAMES>` — The branches to update
|
||||
* `<NAMES>` — The bookmarks to update
|
||||
|
||||
###### **Options:**
|
||||
|
||||
* `-r`, `--revision <REVISION>` — The branch's target revision
|
||||
* `-B`, `--allow-backwards` — Allow moving the branch backwards or sideways
|
||||
* `-r`, `--revision <REVISION>` — The bookmark's target revision
|
||||
* `-B`, `--allow-backwards` — Allow moving the bookmark backwards or sideways
|
||||
|
||||
|
||||
|
||||
## `jj branch track`
|
||||
## `jj bookmark track`
|
||||
|
||||
Start tracking given remote branches
|
||||
Start tracking given remote bookmarks
|
||||
|
||||
A tracking remote branch will be imported as a local branch of the same name. Changes to it will propagate to the existing local branch on future pulls.
|
||||
A tracking remote bookmark will be imported as a local bookmark of the same name. Changes to it will propagate to the existing local bookmark on future pulls.
|
||||
|
||||
**Usage:** `jj branch track <BRANCH@REMOTE>...`
|
||||
**Usage:** `jj bookmark track <BRANCH@REMOTE>...`
|
||||
|
||||
###### **Arguments:**
|
||||
|
||||
* `<BRANCH@REMOTE>` — Remote branches to track
|
||||
* `<BRANCH@REMOTE>` — Remote bookmarks to track
|
||||
|
||||
By default, the specified name matches exactly. Use `glob:` prefix to select branches by wildcard pattern. For details, see https://martinvonz.github.io/jj/latest/revsets/#string-patterns.
|
||||
By default, the specified name matches exactly. Use `glob:` prefix to select bookmarks by wildcard pattern. For details, see https://martinvonz.github.io/jj/latest/revsets/#string-patterns.
|
||||
|
||||
Examples: branch@remote, glob:main@*, glob:jjfan-*@upstream
|
||||
Examples: bookmark@remote, glob:main@*, glob:jjfan-*@upstream
|
||||
|
||||
|
||||
|
||||
## `jj branch untrack`
|
||||
## `jj bookmark untrack`
|
||||
|
||||
Stop tracking given remote branches
|
||||
Stop tracking given remote bookmarks
|
||||
|
||||
A non-tracking remote branch is just a pointer to the last-fetched remote branch. It won't be imported as a local branch on future pulls.
|
||||
A non-tracking remote bookmark is just a pointer to the last-fetched remote bookmark. It won't be imported as a local bookmark on future pulls.
|
||||
|
||||
**Usage:** `jj branch untrack <BRANCH@REMOTE>...`
|
||||
**Usage:** `jj bookmark untrack <BRANCH@REMOTE>...`
|
||||
|
||||
###### **Arguments:**
|
||||
|
||||
* `<BRANCH@REMOTE>` — Remote branches to untrack
|
||||
* `<BRANCH@REMOTE>` — Remote bookmarks to untrack
|
||||
|
||||
By default, the specified name matches exactly. Use `glob:` prefix to select branches by wildcard pattern. For details, see https://martinvonz.github.io/jj/latest/revsets/#string-patterns.
|
||||
By default, the specified name matches exactly. Use `glob:` prefix to select bookmarks by wildcard pattern. For details, see https://martinvonz.github.io/jj/latest/revsets/#string-patterns.
|
||||
|
||||
Examples: branch@remote, glob:main@*, glob:jjfan-*@upstream
|
||||
Examples: bookmark@remote, glob:main@*, glob:jjfan-*@upstream
|
||||
|
||||
|
||||
|
||||
|
|
@ -1032,33 +1032,33 @@ Create a new Git backed repo
|
|||
|
||||
Push to a Git remote
|
||||
|
||||
By default, pushes any branches pointing to `remote_branches(remote=<remote>)..@`. Use `--branch` to push specific branches. Use `--all` to push all branches. Use `--change` to generate branch names based on the change IDs of specific commits.
|
||||
By default, pushes any bookmarks pointing to `remote_bookmarks(remote=<remote>)..@`. Use `--bookmark` to push specific bookmarks. Use `--all` to push all bookmarks. Use `--change` to generate bookmark names based on the change IDs of specific commits.
|
||||
|
||||
Before the command actually moves, creates, or deletes a remote branch, it makes several [safety checks]. If there is a problem, you may need to run `jj git fetch --remote <remote name>` and/or resolve some [branch conflicts].
|
||||
Before the command actually moves, creates, or deletes a remote bookmark, it makes several [safety checks]. If there is a problem, you may need to run `jj git fetch --remote <remote name>` and/or resolve some [bookmark conflicts].
|
||||
|
||||
[safety checks]: https://martinvonz.github.io/jj/latest/branches/#pushing-branches-safety-checks
|
||||
[safety checks]: https://martinvonz.github.io/jj/latest/bookmarks/#pushing-bookmarks-safety-checks
|
||||
|
||||
[branch conflicts]: https://martinvonz.github.io/jj/latest/branches/#conflicts
|
||||
[bookmark conflicts]: https://martinvonz.github.io/jj/latest/bookmarks/#conflicts
|
||||
|
||||
**Usage:** `jj git push [OPTIONS]`
|
||||
|
||||
###### **Options:**
|
||||
|
||||
* `--remote <REMOTE>` — The remote to push to (only named remotes are supported)
|
||||
* `-b`, `--branch <BRANCH>` — Push only this branch, or branches matching a pattern (can be repeated)
|
||||
* `-b`, `--bookmark <BOOKMARK>` — Push only this bookmark, or bookmarks matching a pattern (can be repeated)
|
||||
|
||||
By default, the specified name matches exactly. Use `glob:` prefix to select branches by wildcard pattern. For details, see https://martinvonz.github.io/jj/latest/revsets#string-patterns.
|
||||
* `--all` — Push all branches (including deleted branches)
|
||||
* `--tracked` — Push all tracked branches (including deleted branches)
|
||||
By default, the specified name matches exactly. Use `glob:` prefix to select bookmarks by wildcard pattern. For details, see https://martinvonz.github.io/jj/latest/revsets#string-patterns.
|
||||
* `--all` — Push all bookmarks (including deleted bookmarks)
|
||||
* `--tracked` — Push all tracked bookmarks (including deleted bookmarks)
|
||||
|
||||
This usually means that the branch was already pushed to or fetched from the relevant remote. For details, see https://martinvonz.github.io/jj/latest/branches#remotes-and-tracked-branches
|
||||
* `--deleted` — Push all deleted branches
|
||||
This usually means that the bookmark was already pushed to or fetched from the relevant remote. For details, see https://martinvonz.github.io/jj/latest/bookmarks#remotes-and-tracked-bookmarks
|
||||
* `--deleted` — Push all deleted bookmarks
|
||||
|
||||
Only tracked branches can be successfully deleted on the remote. A warning will be printed if any untracked branches on the remote correspond to missing local branches.
|
||||
Only tracked bookmarks can be successfully deleted on the remote. A warning will be printed if any untracked bookmarks on the remote correspond to missing local bookmarks.
|
||||
* `--allow-empty-description` — Allow pushing commits with empty descriptions
|
||||
* `--allow-private` — Allow pushing commits that are private
|
||||
* `-r`, `--revisions <REVISIONS>` — Push branches pointing to these commits (can be repeated)
|
||||
* `-c`, `--change <CHANGE>` — Push this commit by creating a branch based on its change ID (can be repeated)
|
||||
* `-r`, `--revisions <REVISIONS>` — Push bookmarks pointing to these commits (can be repeated)
|
||||
* `-c`, `--change <CHANGE>` — Push this commit by creating a bookmark based on its change ID (can be repeated)
|
||||
* `--dry-run` — Only display what will change on the remote
|
||||
|
||||
|
||||
|
|
@ -1916,9 +1916,7 @@ Show high-level repo status
|
|||
|
||||
This includes:
|
||||
|
||||
* The working copy commit and its (first) parent, and a summary of the changes between them
|
||||
|
||||
* Conflicted branches (see https://martinvonz.github.io/jj/latest/branches/)
|
||||
* The working copy commit and its (first) parent, and a summary of the changes between them * Conflicted bookmarks (see https://martinvonz.github.io/jj/latest/bookmarks/)
|
||||
|
||||
**Usage:** `jj status [PATHS]...`
|
||||
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ fn test_no_forgotten_test_files() {
|
|||
|
||||
mod test_abandon_command;
|
||||
mod test_acls;
|
||||
mod test_advance_branches;
|
||||
mod test_advance_bookmarks;
|
||||
mod test_alias;
|
||||
mod test_backout_command;
|
||||
mod test_branch_command;
|
||||
mod test_bookmark_command;
|
||||
mod test_builtin_aliases;
|
||||
mod test_checkout;
|
||||
mod test_commit_command;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ fn create_commit(test_env: &TestEnvironment, repo_path: &Path, name: &str, paren
|
|||
test_env.jj_cmd_ok(repo_path, &args);
|
||||
}
|
||||
std::fs::write(repo_path.join(name), format!("{name}\n")).unwrap();
|
||||
test_env.jj_cmd_ok(repo_path, &["branch", "create", name]);
|
||||
test_env.jj_cmd_ok(repo_path, &["bookmark", "create", name]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -291,7 +291,7 @@ fn test_bug_2600() {
|
|||
○ [rlv] nottherootcommit
|
||||
◆ [zzz]
|
||||
"###);
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["branch", "list", "b"]);
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "list", "b"]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
b: zsuskuln 73c929fc base
|
||||
"###);
|
||||
|
|
@ -370,7 +370,7 @@ fn get_log_output(test_env: &TestEnvironment, repo_path: &Path) -> String {
|
|||
&[
|
||||
"log",
|
||||
"-T",
|
||||
r#"separate(" ", "[" ++ change_id.short(3) ++ "]", branches)"#,
|
||||
r#"separate(" ", "[" ++ change_id.short(3) ++ "]", bookmarks)"#,
|
||||
],
|
||||
)
|
||||
}
|
||||
|
|
|
|||
455
cli/tests/test_advance_bookmarks.rs
Normal file
455
cli/tests/test_advance_bookmarks.rs
Normal file
|
|
@ -0,0 +1,455 @@
|
|||
// Copyright 2024 The Jujutsu Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use test_case::test_case;
|
||||
|
||||
use crate::common::TestEnvironment;
|
||||
|
||||
fn get_log_output_with_bookmarks(test_env: &TestEnvironment, cwd: &Path) -> String {
|
||||
// Don't include commit IDs since they will be different depending on
|
||||
// whether the test runs with `jj commit` or `jj describe` + `jj new`.
|
||||
let template = r#""bookmarks{" ++ local_bookmarks ++ "} desc: " ++ description"#;
|
||||
test_env.jj_cmd_success(cwd, &["log", "-T", template])
|
||||
}
|
||||
|
||||
fn set_advance_bookmarks(test_env: &TestEnvironment, enabled: bool) {
|
||||
if enabled {
|
||||
test_env.add_config(
|
||||
r#"[experimental-advance-branches]
|
||||
enabled-branches = ["glob:*"]
|
||||
"#,
|
||||
);
|
||||
} else {
|
||||
test_env.add_config(
|
||||
r#"[experimental-advance-branches]
|
||||
enabled-branches = []
|
||||
"#,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Runs a command in the specified test environment and workspace path that
|
||||
// describes the current commit with `commit_message` and creates a new commit
|
||||
// on top of it.
|
||||
type CommitFn = fn(env: &TestEnvironment, workspace_path: &Path, commit_message: &str);
|
||||
|
||||
// Implements CommitFn using the `jj commit` command.
|
||||
fn commit_cmd(env: &TestEnvironment, workspace_path: &Path, commit_message: &str) {
|
||||
env.jj_cmd_ok(workspace_path, &["commit", "-m", commit_message]);
|
||||
}
|
||||
|
||||
// Implements CommitFn using the `jj describe` and `jj new`.
|
||||
fn describe_new_cmd(env: &TestEnvironment, workspace_path: &Path, commit_message: &str) {
|
||||
env.jj_cmd_ok(workspace_path, &["describe", "-m", commit_message]);
|
||||
env.jj_cmd_ok(workspace_path, &["new"]);
|
||||
}
|
||||
|
||||
// Check that enabling and disabling advance-bookmarks works as expected.
|
||||
#[test_case(commit_cmd ; "commit")]
|
||||
#[test_case(describe_new_cmd; "new")]
|
||||
fn test_advance_bookmarks_enabled(make_commit: CommitFn) {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let workspace_path = test_env.env_root().join("repo");
|
||||
|
||||
// First, test with advance-bookmarks enabled. Start by creating a bookmark on
|
||||
// the root commit.
|
||||
set_advance_bookmarks(&test_env, true);
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_path,
|
||||
&["bookmark", "create", "-r", "@-", "test_bookmark"],
|
||||
);
|
||||
|
||||
// Check the initial state of the repo.
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_bookmarks(&test_env, &workspace_path), @r###"
|
||||
@ bookmarks{} desc:
|
||||
◆ bookmarks{test_bookmark} desc:
|
||||
"###);
|
||||
}
|
||||
|
||||
// Run jj commit, which will advance the bookmark pointing to @-.
|
||||
make_commit(&test_env, &workspace_path, "first");
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_bookmarks(&test_env, &workspace_path), @r###"
|
||||
@ bookmarks{} desc:
|
||||
○ bookmarks{test_bookmark} desc: first
|
||||
◆ bookmarks{} desc:
|
||||
"###);
|
||||
}
|
||||
|
||||
// Now disable advance bookmarks and commit again. The bookmark shouldn't move.
|
||||
set_advance_bookmarks(&test_env, false);
|
||||
make_commit(&test_env, &workspace_path, "second");
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_bookmarks(&test_env, &workspace_path), @r###"
|
||||
@ bookmarks{} desc:
|
||||
○ bookmarks{} desc: second
|
||||
○ bookmarks{test_bookmark} desc: first
|
||||
◆ bookmarks{} desc:
|
||||
"###);
|
||||
}
|
||||
}
|
||||
|
||||
// Check that only a bookmark pointing to @- advances. Branches pointing to @
|
||||
// are not advanced.
|
||||
#[test_case(commit_cmd ; "commit")]
|
||||
#[test_case(describe_new_cmd; "new")]
|
||||
fn test_advance_bookmarks_at_minus(make_commit: CommitFn) {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let workspace_path = test_env.env_root().join("repo");
|
||||
|
||||
set_advance_bookmarks(&test_env, true);
|
||||
test_env.jj_cmd_ok(&workspace_path, &["bookmark", "create", "test_bookmark"]);
|
||||
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_bookmarks(&test_env, &workspace_path), @r###"
|
||||
@ bookmarks{test_bookmark} desc:
|
||||
◆ bookmarks{} desc:
|
||||
"###);
|
||||
}
|
||||
|
||||
make_commit(&test_env, &workspace_path, "first");
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_bookmarks(&test_env, &workspace_path), @r###"
|
||||
@ bookmarks{} desc:
|
||||
○ bookmarks{test_bookmark} desc: first
|
||||
◆ bookmarks{} desc:
|
||||
"###);
|
||||
}
|
||||
|
||||
// Create a second bookmark pointing to @. On the next commit, only the first
|
||||
// bookmark, which points to @-, will advance.
|
||||
test_env.jj_cmd_ok(&workspace_path, &["bookmark", "create", "test_bookmark2"]);
|
||||
make_commit(&test_env, &workspace_path, "second");
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_bookmarks(&test_env, &workspace_path), @r###"
|
||||
@ bookmarks{} desc:
|
||||
○ bookmarks{test_bookmark test_bookmark2} desc: second
|
||||
○ bookmarks{} desc: first
|
||||
◆ bookmarks{} desc:
|
||||
"###);
|
||||
}
|
||||
}
|
||||
|
||||
// Test that per-bookmark overrides invert the behavior of
|
||||
// experimental-advance-bookmarks.enabled.
|
||||
#[test_case(commit_cmd ; "commit")]
|
||||
#[test_case(describe_new_cmd; "new")]
|
||||
fn test_advance_bookmarks_overrides(make_commit: CommitFn) {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let workspace_path = test_env.env_root().join("repo");
|
||||
|
||||
// advance-bookmarks is disabled by default.
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_path,
|
||||
&["bookmark", "create", "-r", "@-", "test_bookmark"],
|
||||
);
|
||||
|
||||
// Check the initial state of the repo.
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_bookmarks(&test_env, &workspace_path), @r###"
|
||||
@ bookmarks{} desc:
|
||||
◆ bookmarks{test_bookmark} desc:
|
||||
"###);
|
||||
}
|
||||
|
||||
// Commit will not advance the bookmark since advance-bookmarks is disabled.
|
||||
make_commit(&test_env, &workspace_path, "first");
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_bookmarks(&test_env, &workspace_path), @r###"
|
||||
@ bookmarks{} desc:
|
||||
○ bookmarks{} desc: first
|
||||
◆ bookmarks{test_bookmark} desc:
|
||||
"###);
|
||||
}
|
||||
|
||||
// Now enable advance bookmarks for "test_bookmark", move the bookmark, and
|
||||
// commit again.
|
||||
test_env.add_config(
|
||||
r#"[experimental-advance-bookmarks]
|
||||
enabled-bookmarks = ["test_bookmark"]
|
||||
"#,
|
||||
);
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_path,
|
||||
&["bookmark", "set", "test_bookmark", "-r", "@-"],
|
||||
);
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_bookmarks(&test_env, &workspace_path), @r###"
|
||||
@ bookmarks{} desc:
|
||||
○ bookmarks{test_bookmark} desc: first
|
||||
◆ bookmarks{} desc:
|
||||
"###);
|
||||
}
|
||||
make_commit(&test_env, &workspace_path, "second");
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_bookmarks(&test_env, &workspace_path), @r###"
|
||||
@ bookmarks{} desc:
|
||||
○ bookmarks{} desc: second
|
||||
○ bookmarks{test_bookmark} desc: first
|
||||
◆ bookmarks{} desc:
|
||||
"###);
|
||||
}
|
||||
|
||||
// Now disable advance bookmarks for "test_bookmark" and "second_bookmark",
|
||||
// which we will use later. Disabling always takes precedence over enabling.
|
||||
test_env.add_config(
|
||||
r#"[experimental-advance-bookmarks]
|
||||
enabled-bookmarks = ["test_bookmark", "second_bookmark"]
|
||||
disabled-bookmarks = ["test_bookmark"]
|
||||
"#,
|
||||
);
|
||||
make_commit(&test_env, &workspace_path, "third");
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_bookmarks(&test_env, &workspace_path), @r###"
|
||||
@ bookmarks{} desc:
|
||||
○ bookmarks{} desc: third
|
||||
○ bookmarks{} desc: second
|
||||
○ bookmarks{test_bookmark} desc: first
|
||||
◆ bookmarks{} desc:
|
||||
"###);
|
||||
}
|
||||
|
||||
// If we create a new bookmark at @- and move test_bookmark there as well. When
|
||||
// we commit, only "second_bookmark" will advance since "test_bookmark" is
|
||||
// disabled.
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_path,
|
||||
&["bookmark", "create", "second_bookmark", "-r", "@-"],
|
||||
);
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_path,
|
||||
&["bookmark", "set", "test_bookmark", "-r", "@-"],
|
||||
);
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_bookmarks(&test_env, &workspace_path), @r###"
|
||||
@ bookmarks{} desc:
|
||||
○ bookmarks{second_bookmark test_bookmark} desc: third
|
||||
○ bookmarks{} desc: second
|
||||
○ bookmarks{} desc: first
|
||||
◆ bookmarks{} desc:
|
||||
"###);
|
||||
}
|
||||
make_commit(&test_env, &workspace_path, "fourth");
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_bookmarks(&test_env, &workspace_path), @r###"
|
||||
@ bookmarks{} desc:
|
||||
○ bookmarks{} desc: fourth
|
||||
○ bookmarks{second_bookmark test_bookmark} desc: third
|
||||
○ bookmarks{} desc: second
|
||||
○ bookmarks{} desc: first
|
||||
◆ bookmarks{} desc:
|
||||
"###);
|
||||
}
|
||||
}
|
||||
|
||||
// If multiple eligible bookmarks point to @-, all of them will be advanced.
|
||||
#[test_case(commit_cmd ; "commit")]
|
||||
#[test_case(describe_new_cmd; "new")]
|
||||
fn test_advance_bookmarks_multiple_bookmarks(make_commit: CommitFn) {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let workspace_path = test_env.env_root().join("repo");
|
||||
|
||||
set_advance_bookmarks(&test_env, true);
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_path,
|
||||
&["bookmark", "create", "-r", "@-", "first_bookmark"],
|
||||
);
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_path,
|
||||
&["bookmark", "create", "-r", "@-", "second_bookmark"],
|
||||
);
|
||||
|
||||
insta::allow_duplicates! {
|
||||
// Check the initial state of the repo.
|
||||
insta::assert_snapshot!(get_log_output_with_bookmarks(&test_env, &workspace_path), @r###"
|
||||
@ bookmarks{} desc:
|
||||
◆ bookmarks{first_bookmark second_bookmark} desc:
|
||||
"###);
|
||||
}
|
||||
|
||||
// Both bookmarks are eligible and both will advance.
|
||||
make_commit(&test_env, &workspace_path, "first");
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_bookmarks(&test_env, &workspace_path), @r###"
|
||||
@ bookmarks{} desc:
|
||||
○ bookmarks{first_bookmark second_bookmark} desc: first
|
||||
◆ bookmarks{} desc:
|
||||
"###);
|
||||
}
|
||||
}
|
||||
|
||||
// Call `jj new` on an interior commit and see that the bookmark pointing to its
|
||||
// parent's parent is advanced.
|
||||
#[test]
|
||||
fn test_new_advance_bookmarks_interior() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let workspace_path = test_env.env_root().join("repo");
|
||||
|
||||
set_advance_bookmarks(&test_env, true);
|
||||
|
||||
// Check the initial state of the repo.
|
||||
insta::assert_snapshot!(get_log_output_with_bookmarks(&test_env, &workspace_path), @r###"
|
||||
@ bookmarks{} desc:
|
||||
◆ bookmarks{} desc:
|
||||
"###);
|
||||
|
||||
// Create a gap in the commits for us to insert our new commit with --before.
|
||||
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m", "first"]);
|
||||
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m", "second"]);
|
||||
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m", "third"]);
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_path,
|
||||
&["bookmark", "create", "-r", "@---", "test_bookmark"],
|
||||
);
|
||||
insta::assert_snapshot!(get_log_output_with_bookmarks(&test_env, &workspace_path), @r###"
|
||||
@ bookmarks{} desc:
|
||||
○ bookmarks{} desc: third
|
||||
○ bookmarks{} desc: second
|
||||
○ bookmarks{test_bookmark} desc: first
|
||||
◆ bookmarks{} desc:
|
||||
"###);
|
||||
|
||||
test_env.jj_cmd_ok(&workspace_path, &["new", "-r", "@--"]);
|
||||
insta::assert_snapshot!(get_log_output_with_bookmarks(&test_env, &workspace_path), @r###"
|
||||
@ bookmarks{} desc:
|
||||
│ ○ bookmarks{} desc: third
|
||||
├─╯
|
||||
○ bookmarks{test_bookmark} desc: second
|
||||
○ bookmarks{} desc: first
|
||||
◆ bookmarks{} desc:
|
||||
"###);
|
||||
}
|
||||
|
||||
// If the `--before` flag is passed to `jj new`, bookmarks are not advanced.
|
||||
#[test]
|
||||
fn test_new_advance_bookmarks_before() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let workspace_path = test_env.env_root().join("repo");
|
||||
|
||||
set_advance_bookmarks(&test_env, true);
|
||||
|
||||
// Check the initial state of the repo.
|
||||
insta::assert_snapshot!(get_log_output_with_bookmarks(&test_env, &workspace_path), @r###"
|
||||
@ bookmarks{} desc:
|
||||
◆ bookmarks{} desc:
|
||||
"###);
|
||||
|
||||
// Create a gap in the commits for us to insert our new commit with --before.
|
||||
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m", "first"]);
|
||||
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m", "second"]);
|
||||
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m", "third"]);
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_path,
|
||||
&["bookmark", "create", "-r", "@---", "test_bookmark"],
|
||||
);
|
||||
insta::assert_snapshot!(get_log_output_with_bookmarks(&test_env, &workspace_path), @r###"
|
||||
@ bookmarks{} desc:
|
||||
○ bookmarks{} desc: third
|
||||
○ bookmarks{} desc: second
|
||||
○ bookmarks{test_bookmark} desc: first
|
||||
◆ bookmarks{} desc:
|
||||
"###);
|
||||
|
||||
test_env.jj_cmd_ok(&workspace_path, &["new", "--before", "@-"]);
|
||||
insta::assert_snapshot!(get_log_output_with_bookmarks(&test_env, &workspace_path), @r###"
|
||||
○ bookmarks{} desc: third
|
||||
@ bookmarks{} desc:
|
||||
○ bookmarks{} desc: second
|
||||
○ bookmarks{test_bookmark} desc: first
|
||||
◆ bookmarks{} desc:
|
||||
"###);
|
||||
}
|
||||
|
||||
// If the `--after` flag is passed to `jj new`, bookmarks are not advanced.
|
||||
#[test]
|
||||
fn test_new_advance_bookmarks_after() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let workspace_path = test_env.env_root().join("repo");
|
||||
|
||||
set_advance_bookmarks(&test_env, true);
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_path,
|
||||
&["bookmark", "create", "-r", "@-", "test_bookmark"],
|
||||
);
|
||||
|
||||
// Check the initial state of the repo.
|
||||
insta::assert_snapshot!(get_log_output_with_bookmarks(&test_env, &workspace_path), @r###"
|
||||
@ bookmarks{} desc:
|
||||
◆ bookmarks{test_bookmark} desc:
|
||||
"###);
|
||||
|
||||
test_env.jj_cmd_ok(&workspace_path, &["describe", "-m", "first"]);
|
||||
test_env.jj_cmd_ok(&workspace_path, &["new", "--after", "@"]);
|
||||
insta::assert_snapshot!(get_log_output_with_bookmarks(&test_env, &workspace_path), @r###"
|
||||
@ bookmarks{} desc:
|
||||
○ bookmarks{} desc: first
|
||||
◆ bookmarks{test_bookmark} desc:
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_new_advance_bookmarks_merge_children() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let workspace_path = test_env.env_root().join("repo");
|
||||
|
||||
set_advance_bookmarks(&test_env, true);
|
||||
test_env.jj_cmd_ok(&workspace_path, &["desc", "-m", "0"]);
|
||||
test_env.jj_cmd_ok(&workspace_path, &["new", "-m", "1"]);
|
||||
test_env.jj_cmd_ok(&workspace_path, &["new", "description(0)", "-m", "2"]);
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_path,
|
||||
&[
|
||||
"bookmark",
|
||||
"create",
|
||||
"test_bookmark",
|
||||
"-r",
|
||||
"description(0)",
|
||||
],
|
||||
);
|
||||
|
||||
// Check the initial state of the repo.
|
||||
insta::assert_snapshot!(get_log_output_with_bookmarks(&test_env, &workspace_path), @r###"
|
||||
@ bookmarks{} desc: 2
|
||||
│ ○ bookmarks{} desc: 1
|
||||
├─╯
|
||||
○ bookmarks{test_bookmark} desc: 0
|
||||
◆ bookmarks{} desc:
|
||||
"###);
|
||||
|
||||
// The bookmark won't advance because `jj new` had multiple targets.
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_path,
|
||||
&["new", "description(1)", "description(2)"],
|
||||
);
|
||||
insta::assert_snapshot!(get_log_output_with_bookmarks(&test_env, &workspace_path), @r###"
|
||||
@ bookmarks{} desc:
|
||||
├─╮
|
||||
│ ○ bookmarks{} desc: 2
|
||||
○ │ bookmarks{} desc: 1
|
||||
├─╯
|
||||
○ bookmarks{test_bookmark} desc: 0
|
||||
◆ bookmarks{} desc:
|
||||
"###);
|
||||
}
|
||||
|
|
@ -1,448 +0,0 @@
|
|||
// Copyright 2024 The Jujutsu Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use test_case::test_case;
|
||||
|
||||
use crate::common::TestEnvironment;
|
||||
|
||||
fn get_log_output_with_branches(test_env: &TestEnvironment, cwd: &Path) -> String {
|
||||
// Don't include commit IDs since they will be different depending on
|
||||
// whether the test runs with `jj commit` or `jj describe` + `jj new`.
|
||||
let template = r#""branches{" ++ local_branches ++ "} desc: " ++ description"#;
|
||||
test_env.jj_cmd_success(cwd, &["log", "-T", template])
|
||||
}
|
||||
|
||||
fn set_advance_branches(test_env: &TestEnvironment, enabled: bool) {
|
||||
if enabled {
|
||||
test_env.add_config(
|
||||
r#"[experimental-advance-branches]
|
||||
enabled-branches = ["glob:*"]
|
||||
"#,
|
||||
);
|
||||
} else {
|
||||
test_env.add_config(
|
||||
r#"[experimental-advance-branches]
|
||||
enabled-branches = []
|
||||
"#,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Runs a command in the specified test environment and workspace path that
|
||||
// describes the current commit with `commit_message` and creates a new commit
|
||||
// on top of it.
|
||||
type CommitFn = fn(env: &TestEnvironment, workspace_path: &Path, commit_message: &str);
|
||||
|
||||
// Implements CommitFn using the `jj commit` command.
|
||||
fn commit_cmd(env: &TestEnvironment, workspace_path: &Path, commit_message: &str) {
|
||||
env.jj_cmd_ok(workspace_path, &["commit", "-m", commit_message]);
|
||||
}
|
||||
|
||||
// Implements CommitFn using the `jj describe` and `jj new`.
|
||||
fn describe_new_cmd(env: &TestEnvironment, workspace_path: &Path, commit_message: &str) {
|
||||
env.jj_cmd_ok(workspace_path, &["describe", "-m", commit_message]);
|
||||
env.jj_cmd_ok(workspace_path, &["new"]);
|
||||
}
|
||||
|
||||
// Check that enabling and disabling advance-branches works as expected.
|
||||
#[test_case(commit_cmd ; "commit")]
|
||||
#[test_case(describe_new_cmd; "new")]
|
||||
fn test_advance_branches_enabled(make_commit: CommitFn) {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let workspace_path = test_env.env_root().join("repo");
|
||||
|
||||
// First, test with advance-branches enabled. Start by creating a branch on the
|
||||
// root commit.
|
||||
set_advance_branches(&test_env, true);
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_path,
|
||||
&["branch", "create", "-r", "@-", "test_branch"],
|
||||
);
|
||||
|
||||
// Check the initial state of the repo.
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
◆ branches{test_branch} desc:
|
||||
"###);
|
||||
}
|
||||
|
||||
// Run jj commit, which will advance the branch pointing to @-.
|
||||
make_commit(&test_env, &workspace_path, "first");
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
○ branches{test_branch} desc: first
|
||||
◆ branches{} desc:
|
||||
"###);
|
||||
}
|
||||
|
||||
// Now disable advance branches and commit again. The branch shouldn't move.
|
||||
set_advance_branches(&test_env, false);
|
||||
make_commit(&test_env, &workspace_path, "second");
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
○ branches{} desc: second
|
||||
○ branches{test_branch} desc: first
|
||||
◆ branches{} desc:
|
||||
"###);
|
||||
}
|
||||
}
|
||||
|
||||
// Check that only a branch pointing to @- advances. Branches pointing to @ are
|
||||
// not advanced.
|
||||
#[test_case(commit_cmd ; "commit")]
|
||||
#[test_case(describe_new_cmd; "new")]
|
||||
fn test_advance_branches_at_minus(make_commit: CommitFn) {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let workspace_path = test_env.env_root().join("repo");
|
||||
|
||||
set_advance_branches(&test_env, true);
|
||||
test_env.jj_cmd_ok(&workspace_path, &["branch", "create", "test_branch"]);
|
||||
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{test_branch} desc:
|
||||
◆ branches{} desc:
|
||||
"###);
|
||||
}
|
||||
|
||||
make_commit(&test_env, &workspace_path, "first");
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
○ branches{test_branch} desc: first
|
||||
◆ branches{} desc:
|
||||
"###);
|
||||
}
|
||||
|
||||
// Create a second branch pointing to @. On the next commit, only the first
|
||||
// branch, which points to @-, will advance.
|
||||
test_env.jj_cmd_ok(&workspace_path, &["branch", "create", "test_branch2"]);
|
||||
make_commit(&test_env, &workspace_path, "second");
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
○ branches{test_branch test_branch2} desc: second
|
||||
○ branches{} desc: first
|
||||
◆ branches{} desc:
|
||||
"###);
|
||||
}
|
||||
}
|
||||
|
||||
// Test that per-branch overrides invert the behavior of
|
||||
// experimental-advance-branches.enabled.
|
||||
#[test_case(commit_cmd ; "commit")]
|
||||
#[test_case(describe_new_cmd; "new")]
|
||||
fn test_advance_branches_overrides(make_commit: CommitFn) {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let workspace_path = test_env.env_root().join("repo");
|
||||
|
||||
// advance-branches is disabled by default.
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_path,
|
||||
&["branch", "create", "-r", "@-", "test_branch"],
|
||||
);
|
||||
|
||||
// Check the initial state of the repo.
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
◆ branches{test_branch} desc:
|
||||
"###);
|
||||
}
|
||||
|
||||
// Commit will not advance the branch since advance-branches is disabled.
|
||||
make_commit(&test_env, &workspace_path, "first");
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
○ branches{} desc: first
|
||||
◆ branches{test_branch} desc:
|
||||
"###);
|
||||
}
|
||||
|
||||
// Now enable advance branches for "test_branch", move the branch, and commit
|
||||
// again.
|
||||
test_env.add_config(
|
||||
r#"[experimental-advance-branches]
|
||||
enabled-branches = ["test_branch"]
|
||||
"#,
|
||||
);
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_path,
|
||||
&["branch", "set", "test_branch", "-r", "@-"],
|
||||
);
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
○ branches{test_branch} desc: first
|
||||
◆ branches{} desc:
|
||||
"###);
|
||||
}
|
||||
make_commit(&test_env, &workspace_path, "second");
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
○ branches{test_branch} desc: second
|
||||
○ branches{} desc: first
|
||||
◆ branches{} desc:
|
||||
"###);
|
||||
}
|
||||
|
||||
// Now disable advance branches for "test_branch" and "second_branch", which
|
||||
// we will use later. Disabling always takes precedence over enabling.
|
||||
test_env.add_config(
|
||||
r#"[experimental-advance-branches]
|
||||
enabled-branches = ["test_branch", "second_branch"]
|
||||
disabled-branches = ["test_branch"]
|
||||
"#,
|
||||
);
|
||||
make_commit(&test_env, &workspace_path, "third");
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
○ branches{} desc: third
|
||||
○ branches{test_branch} desc: second
|
||||
○ branches{} desc: first
|
||||
◆ branches{} desc:
|
||||
"###);
|
||||
}
|
||||
|
||||
// If we create a new branch at @- and move test_branch there as well. When
|
||||
// we commit, only "second_branch" will advance since "test_branch" is disabled.
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_path,
|
||||
&["branch", "create", "second_branch", "-r", "@-"],
|
||||
);
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_path,
|
||||
&["branch", "set", "test_branch", "-r", "@-"],
|
||||
);
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
○ branches{second_branch test_branch} desc: third
|
||||
○ branches{} desc: second
|
||||
○ branches{} desc: first
|
||||
◆ branches{} desc:
|
||||
"###);
|
||||
}
|
||||
make_commit(&test_env, &workspace_path, "fourth");
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
○ branches{second_branch} desc: fourth
|
||||
○ branches{test_branch} desc: third
|
||||
○ branches{} desc: second
|
||||
○ branches{} desc: first
|
||||
◆ branches{} desc:
|
||||
"###);
|
||||
}
|
||||
}
|
||||
|
||||
// If multiple eligible branches point to @-, all of them will be advanced.
|
||||
#[test_case(commit_cmd ; "commit")]
|
||||
#[test_case(describe_new_cmd; "new")]
|
||||
fn test_advance_branches_multiple_branches(make_commit: CommitFn) {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let workspace_path = test_env.env_root().join("repo");
|
||||
|
||||
set_advance_branches(&test_env, true);
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_path,
|
||||
&["branch", "create", "-r", "@-", "first_branch"],
|
||||
);
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_path,
|
||||
&["branch", "create", "-r", "@-", "second_branch"],
|
||||
);
|
||||
|
||||
insta::allow_duplicates! {
|
||||
// Check the initial state of the repo.
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
◆ branches{first_branch second_branch} desc:
|
||||
"###);
|
||||
}
|
||||
|
||||
// Both branches are eligible and both will advance.
|
||||
make_commit(&test_env, &workspace_path, "first");
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
○ branches{first_branch second_branch} desc: first
|
||||
◆ branches{} desc:
|
||||
"###);
|
||||
}
|
||||
}
|
||||
|
||||
// Call `jj new` on an interior commit and see that the branch pointing to its
|
||||
// parent's parent is advanced.
|
||||
#[test]
|
||||
fn test_new_advance_branches_interior() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let workspace_path = test_env.env_root().join("repo");
|
||||
|
||||
set_advance_branches(&test_env, true);
|
||||
|
||||
// Check the initial state of the repo.
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
◆ branches{} desc:
|
||||
"###);
|
||||
|
||||
// Create a gap in the commits for us to insert our new commit with --before.
|
||||
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m", "first"]);
|
||||
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m", "second"]);
|
||||
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m", "third"]);
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_path,
|
||||
&["branch", "create", "-r", "@---", "test_branch"],
|
||||
);
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
○ branches{} desc: third
|
||||
○ branches{} desc: second
|
||||
○ branches{test_branch} desc: first
|
||||
◆ branches{} desc:
|
||||
"###);
|
||||
|
||||
test_env.jj_cmd_ok(&workspace_path, &["new", "-r", "@--"]);
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
│ ○ branches{} desc: third
|
||||
├─╯
|
||||
○ branches{test_branch} desc: second
|
||||
○ branches{} desc: first
|
||||
◆ branches{} desc:
|
||||
"###);
|
||||
}
|
||||
|
||||
// If the `--before` flag is passed to `jj new`, branches are not advanced.
|
||||
#[test]
|
||||
fn test_new_advance_branches_before() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let workspace_path = test_env.env_root().join("repo");
|
||||
|
||||
set_advance_branches(&test_env, true);
|
||||
|
||||
// Check the initial state of the repo.
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
◆ branches{} desc:
|
||||
"###);
|
||||
|
||||
// Create a gap in the commits for us to insert our new commit with --before.
|
||||
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m", "first"]);
|
||||
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m", "second"]);
|
||||
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m", "third"]);
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_path,
|
||||
&["branch", "create", "-r", "@---", "test_branch"],
|
||||
);
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
○ branches{} desc: third
|
||||
○ branches{} desc: second
|
||||
○ branches{test_branch} desc: first
|
||||
◆ branches{} desc:
|
||||
"###);
|
||||
|
||||
test_env.jj_cmd_ok(&workspace_path, &["new", "--before", "@-"]);
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
○ branches{} desc: third
|
||||
@ branches{} desc:
|
||||
○ branches{} desc: second
|
||||
○ branches{test_branch} desc: first
|
||||
◆ branches{} desc:
|
||||
"###);
|
||||
}
|
||||
|
||||
// If the `--after` flag is passed to `jj new`, branches are not advanced.
|
||||
#[test]
|
||||
fn test_new_advance_branches_after() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let workspace_path = test_env.env_root().join("repo");
|
||||
|
||||
set_advance_branches(&test_env, true);
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_path,
|
||||
&["branch", "create", "-r", "@-", "test_branch"],
|
||||
);
|
||||
|
||||
// Check the initial state of the repo.
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
◆ branches{test_branch} desc:
|
||||
"###);
|
||||
|
||||
test_env.jj_cmd_ok(&workspace_path, &["describe", "-m", "first"]);
|
||||
test_env.jj_cmd_ok(&workspace_path, &["new", "--after", "@"]);
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
○ branches{} desc: first
|
||||
◆ branches{test_branch} desc:
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_new_advance_branches_merge_children() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let workspace_path = test_env.env_root().join("repo");
|
||||
|
||||
set_advance_branches(&test_env, true);
|
||||
test_env.jj_cmd_ok(&workspace_path, &["desc", "-m", "0"]);
|
||||
test_env.jj_cmd_ok(&workspace_path, &["new", "-m", "1"]);
|
||||
test_env.jj_cmd_ok(&workspace_path, &["new", "description(0)", "-m", "2"]);
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_path,
|
||||
&["branch", "create", "test_branch", "-r", "description(0)"],
|
||||
);
|
||||
|
||||
// Check the initial state of the repo.
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc: 2
|
||||
│ ○ branches{} desc: 1
|
||||
├─╯
|
||||
○ branches{test_branch} desc: 0
|
||||
◆ branches{} desc:
|
||||
"###);
|
||||
|
||||
// The branch won't advance because `jj new` had multiple targets.
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_path,
|
||||
&["new", "description(1)", "description(2)"],
|
||||
);
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
├─╮
|
||||
│ ○ branches{} desc: 2
|
||||
○ │ branches{} desc: 1
|
||||
├─╯
|
||||
○ branches{test_branch} desc: 0
|
||||
◆ branches{} desc:
|
||||
"###);
|
||||
}
|
||||
|
|
@ -24,11 +24,11 @@ fn test_alias_basic() {
|
|||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let repo_path = test_env.env_root().join("repo");
|
||||
|
||||
test_env.add_config(r#"aliases.b = ["log", "-r", "@", "-T", "branches"]"#);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "my-branch"]);
|
||||
test_env.add_config(r#"aliases.b = ["log", "-r", "@", "-T", "bookmarks"]"#);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "my-bookmark"]);
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["b"]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
@ my-branch
|
||||
@ my-bookmark
|
||||
│
|
||||
~
|
||||
"###);
|
||||
|
|
@ -41,17 +41,17 @@ fn test_alias_legacy_section() {
|
|||
let repo_path = test_env.env_root().join("repo");
|
||||
|
||||
// Can define aliases in [alias] section
|
||||
test_env.add_config(r#"alias.b = ["log", "-r", "@", "-T", "branches"]"#);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "my-branch"]);
|
||||
test_env.add_config(r#"alias.b = ["log", "-r", "@", "-T", "bookmarks"]"#);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "my-bookmark"]);
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["b"]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
@ my-branch
|
||||
@ my-bookmark
|
||||
│
|
||||
~
|
||||
"###);
|
||||
|
||||
// The same alias (name) in both [alias] and [aliases] sections is an error
|
||||
test_env.add_config(r#"aliases.b = ["branch", "list"]"#);
|
||||
test_env.add_config(r#"aliases.b = ["bookmark", "list"]"#);
|
||||
let stderr = test_env.jj_cmd_failure(&repo_path, &["b"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Error: Alias "b" is defined in both [aliases] and [alias]
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ fn create_commit(
|
|||
for (name, contents) in files {
|
||||
std::fs::write(repo_path.join(name), contents).unwrap();
|
||||
}
|
||||
test_env.jj_cmd_ok(repo_path, &["branch", "create", name]);
|
||||
test_env.jj_cmd_ok(repo_path, &["bookmark", "create", name]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -27,9 +27,9 @@ fn set_up(trunk_name: &str) -> (TestEnvironment, PathBuf) {
|
|||
.join("git");
|
||||
|
||||
test_env.jj_cmd_ok(&origin_path, &["describe", "-m=description 1"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["branch", "create", trunk_name]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["bookmark", "create", trunk_name]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["new", "root()", "-m=description 2"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["branch", "create", "unrelated_branch"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["bookmark", "create", "unrelated_bookmark"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["git", "export"]);
|
||||
|
||||
test_env.jj_cmd_ok(
|
||||
|
|
@ -87,7 +87,7 @@ fn test_builtin_alias_trunk_matches_exactly_one_commit() {
|
|||
let (test_env, workspace_root) = set_up("main");
|
||||
let origin_path = test_env.env_root().join("origin");
|
||||
test_env.jj_cmd_ok(&origin_path, &["new", "root()", "-m=description 3"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["branch", "create", "master"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["bookmark", "create", "master"]);
|
||||
|
||||
let stdout = test_env.jj_cmd_success(&workspace_root, &["log", "-r", "trunk()"]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
|
|
@ -102,7 +102,7 @@ fn test_builtin_alias_trunk_override_alias() {
|
|||
let (test_env, workspace_root) = set_up("override-trunk");
|
||||
|
||||
test_env.add_config(
|
||||
r#"revset-aliases.'trunk()' = 'latest(remote_branches(exact:"override-trunk", exact:"origin"))'"#,
|
||||
r#"revset-aliases.'trunk()' = 'latest(remote_bookmarks(exact:"override-trunk", exact:"origin"))'"#,
|
||||
);
|
||||
|
||||
let stdout = test_env.jj_cmd_success(&workspace_root, &["log", "-r", "trunk()"]);
|
||||
|
|
|
|||
|
|
@ -184,12 +184,12 @@ fn test_log_default() {
|
|||
std::fs::write(repo_path.join("file1"), "foo\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "add a file"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-m", "description 1"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "my-branch"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "my-bookmark"]);
|
||||
|
||||
// Test default log output format
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["log"]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
@ kkmpptxz test.user@example.com 2001-02-03 08:05:09 my-branch bac9ff9e
|
||||
@ kkmpptxz test.user@example.com 2001-02-03 08:05:09 my-bookmark bac9ff9e
|
||||
│ (empty) description 1
|
||||
○ qpvuntsm test.user@example.com 2001-02-03 08:05:08 aa2015d7
|
||||
│ add a file
|
||||
|
|
@ -199,7 +199,7 @@ fn test_log_default() {
|
|||
// Color
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["log", "--color=always"]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
[1m[38;5;2m@[0m [1m[38;5;13mk[38;5;8mkmpptxz[39m [38;5;3mtest.user@example.com[39m [38;5;14m2001-02-03 08:05:09[39m [38;5;13mmy-branch[39m [38;5;12mb[38;5;8mac9ff9e[39m[0m
|
||||
[1m[38;5;2m@[0m [1m[38;5;13mk[38;5;8mkmpptxz[39m [38;5;3mtest.user@example.com[39m [38;5;14m2001-02-03 08:05:09[39m [38;5;5mmy-bookmark[39m [38;5;12mb[38;5;8mac9ff9e[39m[0m
|
||||
│ [1m[38;5;10m(empty)[39m description 1[0m
|
||||
○ [1m[38;5;5mq[0m[38;5;8mpvuntsm[39m [38;5;3mtest.user@example.com[39m [38;5;6m2001-02-03 08:05:08[39m [1m[38;5;4ma[0m[38;5;8ma2015d7[39m
|
||||
│ add a file
|
||||
|
|
@ -209,7 +209,7 @@ fn test_log_default() {
|
|||
// Color without graph
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["log", "--color=always", "--no-graph"]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
[1m[38;5;13mk[38;5;8mkmpptxz[39m [38;5;3mtest.user@example.com[39m [38;5;14m2001-02-03 08:05:09[39m [38;5;13mmy-branch[39m [38;5;12mb[38;5;8mac9ff9e[39m[0m
|
||||
[1m[38;5;13mk[38;5;8mkmpptxz[39m [38;5;3mtest.user@example.com[39m [38;5;14m2001-02-03 08:05:09[39m [38;5;5mmy-bookmark[39m [38;5;12mb[38;5;8mac9ff9e[39m[0m
|
||||
[1m[38;5;10m(empty)[39m description 1[0m
|
||||
[1m[38;5;5mq[0m[38;5;8mpvuntsm[39m [38;5;3mtest.user@example.com[39m [38;5;6m2001-02-03 08:05:08[39m [1m[38;5;4ma[0m[38;5;8ma2015d7[39m
|
||||
add a file
|
||||
|
|
@ -235,17 +235,17 @@ fn test_log_builtin_templates() {
|
|||
"new",
|
||||
],
|
||||
);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "my-branch"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "my-bookmark"]);
|
||||
|
||||
insta::assert_snapshot!(render(r#"builtin_log_oneline"#), @r###"
|
||||
rlvkpnrz (no email set) 2001-02-03 08:05:08 my-branch dc315397 (empty) (no description set)
|
||||
rlvkpnrz (no email set) 2001-02-03 08:05:08 my-bookmark dc315397 (empty) (no description set)
|
||||
qpvuntsm test.user 2001-02-03 08:05:07 230dd059 (empty) (no description set)
|
||||
zzzzzzzz root() 00000000
|
||||
[EOF]
|
||||
"###);
|
||||
|
||||
insta::assert_snapshot!(render(r#"builtin_log_compact"#), @r###"
|
||||
rlvkpnrz (no email set) 2001-02-03 08:05:08 my-branch dc315397
|
||||
rlvkpnrz (no email set) 2001-02-03 08:05:08 my-bookmark dc315397
|
||||
(empty) (no description set)
|
||||
qpvuntsm test.user@example.com 2001-02-03 08:05:07 230dd059
|
||||
(empty) (no description set)
|
||||
|
|
@ -254,7 +254,7 @@ fn test_log_builtin_templates() {
|
|||
"###);
|
||||
|
||||
insta::assert_snapshot!(render(r#"builtin_log_comfortable"#), @r###"
|
||||
rlvkpnrz (no email set) 2001-02-03 08:05:08 my-branch dc315397
|
||||
rlvkpnrz (no email set) 2001-02-03 08:05:08 my-bookmark dc315397
|
||||
(empty) (no description set)
|
||||
|
||||
qpvuntsm test.user@example.com 2001-02-03 08:05:07 230dd059
|
||||
|
|
@ -268,7 +268,7 @@ fn test_log_builtin_templates() {
|
|||
insta::assert_snapshot!(render(r#"builtin_log_detailed"#), @r###"
|
||||
Commit ID: dc31539712c7294d1d712cec63cef4504b94ca74
|
||||
Change ID: rlvkpnrzqnoowoytxnquwvuryrwnrmlp
|
||||
Branches: my-branch
|
||||
Bookmarks: my-bookmark
|
||||
Author: (no name set) <(no email set)> (2001-02-03 08:05:08)
|
||||
Committer: (no name set) <(no email set)> (2001-02-03 08:05:08)
|
||||
|
||||
|
|
@ -308,16 +308,16 @@ fn test_log_builtin_templates_colored() {
|
|||
"new",
|
||||
],
|
||||
);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "my-branch"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "my-bookmark"]);
|
||||
|
||||
insta::assert_snapshot!(render(r#"builtin_log_oneline"#), @r###"
|
||||
[1m[38;5;2m@[0m [1m[38;5;13mr[38;5;8mlvkpnrz[39m [38;5;9m(no email set)[39m [38;5;14m2001-02-03 08:05:08[39m [38;5;13mmy-branch[39m [38;5;12md[38;5;8mc315397[39m [38;5;10m(empty)[39m [38;5;10m(no description set)[39m[0m
|
||||
[1m[38;5;2m@[0m [1m[38;5;13mr[38;5;8mlvkpnrz[39m [38;5;9m(no email set)[39m [38;5;14m2001-02-03 08:05:08[39m [38;5;5mmy-bookmark[39m [38;5;12md[38;5;8mc315397[39m [38;5;10m(empty)[39m [38;5;10m(no description set)[39m[0m
|
||||
○ [1m[38;5;5mq[0m[38;5;8mpvuntsm[39m [38;5;3mtest.user[39m [38;5;6m2001-02-03 08:05:07[39m [1m[38;5;4m2[0m[38;5;8m30dd059[39m [38;5;2m(empty)[39m [38;5;2m(no description set)[39m
|
||||
[1m[38;5;14m◆[0m [1m[38;5;5mz[0m[38;5;8mzzzzzzz[39m [38;5;2mroot()[39m [1m[38;5;4m0[0m[38;5;8m0000000[39m
|
||||
"###);
|
||||
|
||||
insta::assert_snapshot!(render(r#"builtin_log_compact"#), @r###"
|
||||
[1m[38;5;2m@[0m [1m[38;5;13mr[38;5;8mlvkpnrz[39m [38;5;9m(no email set)[39m [38;5;14m2001-02-03 08:05:08[39m [38;5;13mmy-branch[39m [38;5;12md[38;5;8mc315397[39m[0m
|
||||
[1m[38;5;2m@[0m [1m[38;5;13mr[38;5;8mlvkpnrz[39m [38;5;9m(no email set)[39m [38;5;14m2001-02-03 08:05:08[39m [38;5;5mmy-bookmark[39m [38;5;12md[38;5;8mc315397[39m[0m
|
||||
│ [1m[38;5;10m(empty)[39m [38;5;10m(no description set)[39m[0m
|
||||
○ [1m[38;5;5mq[0m[38;5;8mpvuntsm[39m [38;5;3mtest.user@example.com[39m [38;5;6m2001-02-03 08:05:07[39m [1m[38;5;4m2[0m[38;5;8m30dd059[39m
|
||||
│ [38;5;2m(empty)[39m [38;5;2m(no description set)[39m
|
||||
|
|
@ -325,7 +325,7 @@ fn test_log_builtin_templates_colored() {
|
|||
"###);
|
||||
|
||||
insta::assert_snapshot!(render(r#"builtin_log_comfortable"#), @r###"
|
||||
[1m[38;5;2m@[0m [1m[38;5;13mr[38;5;8mlvkpnrz[39m [38;5;9m(no email set)[39m [38;5;14m2001-02-03 08:05:08[39m [38;5;13mmy-branch[39m [38;5;12md[38;5;8mc315397[39m[0m
|
||||
[1m[38;5;2m@[0m [1m[38;5;13mr[38;5;8mlvkpnrz[39m [38;5;9m(no email set)[39m [38;5;14m2001-02-03 08:05:08[39m [38;5;5mmy-bookmark[39m [38;5;12md[38;5;8mc315397[39m[0m
|
||||
│ [1m[38;5;10m(empty)[39m [38;5;10m(no description set)[39m[0m
|
||||
│
|
||||
○ [1m[38;5;5mq[0m[38;5;8mpvuntsm[39m [38;5;3mtest.user@example.com[39m [38;5;6m2001-02-03 08:05:07[39m [1m[38;5;4m2[0m[38;5;8m30dd059[39m
|
||||
|
|
@ -338,7 +338,7 @@ fn test_log_builtin_templates_colored() {
|
|||
insta::assert_snapshot!(render(r#"builtin_log_detailed"#), @r###"
|
||||
[1m[38;5;2m@[0m Commit ID: [38;5;4mdc31539712c7294d1d712cec63cef4504b94ca74[39m
|
||||
│ Change ID: [38;5;5mrlvkpnrzqnoowoytxnquwvuryrwnrmlp[39m
|
||||
│ Branches: [38;5;5mmy-branch[39m
|
||||
│ Bookmarks: [38;5;5mmy-bookmark[39m
|
||||
│ Author: [38;5;1m(no name set)[39m <[38;5;1m(no email set)[39m> ([38;5;6m2001-02-03 08:05:08[39m)
|
||||
│ Committer: [38;5;1m(no name set)[39m <[38;5;1m(no email set)[39m> ([38;5;6m2001-02-03 08:05:08[39m)
|
||||
│
|
||||
|
|
@ -377,16 +377,16 @@ fn test_log_builtin_templates_colored_debug() {
|
|||
"new",
|
||||
],
|
||||
);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "my-branch"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "my-bookmark"]);
|
||||
|
||||
insta::assert_snapshot!(render(r#"builtin_log_oneline"#), @r###"
|
||||
[1m[38;5;2m<<node working_copy::@>>[0m [1m[38;5;13m<<log working_copy change_id shortest prefix::r>>[38;5;8m<<log working_copy change_id shortest rest::lvkpnrz>>[39m<<log working_copy:: >>[38;5;9m<<log working_copy email placeholder::(no email set)>>[39m<<log working_copy:: >>[38;5;14m<<log working_copy committer timestamp local format::2001-02-03 08:05:08>>[39m<<log working_copy:: >>[38;5;13m<<log working_copy branches name::my-branch>>[39m<<log working_copy:: >>[38;5;12m<<log working_copy commit_id shortest prefix::d>>[38;5;8m<<log working_copy commit_id shortest rest::c315397>>[39m<<log working_copy:: >>[38;5;10m<<log working_copy empty::(empty)>>[39m<<log working_copy:: >>[38;5;10m<<log working_copy empty description placeholder::(no description set)>>[39m<<log working_copy::>>[0m
|
||||
[1m[38;5;2m<<node working_copy::@>>[0m [1m[38;5;13m<<log working_copy change_id shortest prefix::r>>[38;5;8m<<log working_copy change_id shortest rest::lvkpnrz>>[39m<<log working_copy:: >>[38;5;9m<<log working_copy email placeholder::(no email set)>>[39m<<log working_copy:: >>[38;5;14m<<log working_copy committer timestamp local format::2001-02-03 08:05:08>>[39m<<log working_copy:: >>[38;5;5m<<log working_copy bookmarks name::my-bookmark>>[39m<<log working_copy:: >>[38;5;12m<<log working_copy commit_id shortest prefix::d>>[38;5;8m<<log working_copy commit_id shortest rest::c315397>>[39m<<log working_copy:: >>[38;5;10m<<log working_copy empty::(empty)>>[39m<<log working_copy:: >>[38;5;10m<<log working_copy empty description placeholder::(no description set)>>[39m<<log working_copy::>>[0m
|
||||
<<node::○>> [1m[38;5;5m<<log change_id shortest prefix::q>>[0m[38;5;8m<<log change_id shortest rest::pvuntsm>>[39m<<log:: >>[38;5;3m<<log author username::test.user>>[39m<<log:: >>[38;5;6m<<log committer timestamp local format::2001-02-03 08:05:07>>[39m<<log:: >>[1m[38;5;4m<<log commit_id shortest prefix::2>>[0m[38;5;8m<<log commit_id shortest rest::30dd059>>[39m<<log:: >>[38;5;2m<<log empty::(empty)>>[39m<<log:: >>[38;5;2m<<log empty description placeholder::(no description set)>>[39m<<log::>>
|
||||
[1m[38;5;14m<<node immutable::◆>>[0m [1m[38;5;5m<<log change_id shortest prefix::z>>[0m[38;5;8m<<log change_id shortest rest::zzzzzzz>>[39m<<log:: >>[38;5;2m<<log root::root()>>[39m<<log:: >>[1m[38;5;4m<<log commit_id shortest prefix::0>>[0m[38;5;8m<<log commit_id shortest rest::0000000>>[39m<<log::>>
|
||||
"###);
|
||||
|
||||
insta::assert_snapshot!(render(r#"builtin_log_compact"#), @r###"
|
||||
[1m[38;5;2m<<node working_copy::@>>[0m [1m[38;5;13m<<log working_copy change_id shortest prefix::r>>[38;5;8m<<log working_copy change_id shortest rest::lvkpnrz>>[39m<<log working_copy:: >>[38;5;9m<<log working_copy email placeholder::(no email set)>>[39m<<log working_copy:: >>[38;5;14m<<log working_copy committer timestamp local format::2001-02-03 08:05:08>>[39m<<log working_copy:: >>[38;5;13m<<log working_copy branches name::my-branch>>[39m<<log working_copy:: >>[38;5;12m<<log working_copy commit_id shortest prefix::d>>[38;5;8m<<log working_copy commit_id shortest rest::c315397>>[39m<<log working_copy::>>[0m
|
||||
[1m[38;5;2m<<node working_copy::@>>[0m [1m[38;5;13m<<log working_copy change_id shortest prefix::r>>[38;5;8m<<log working_copy change_id shortest rest::lvkpnrz>>[39m<<log working_copy:: >>[38;5;9m<<log working_copy email placeholder::(no email set)>>[39m<<log working_copy:: >>[38;5;14m<<log working_copy committer timestamp local format::2001-02-03 08:05:08>>[39m<<log working_copy:: >>[38;5;5m<<log working_copy bookmarks name::my-bookmark>>[39m<<log working_copy:: >>[38;5;12m<<log working_copy commit_id shortest prefix::d>>[38;5;8m<<log working_copy commit_id shortest rest::c315397>>[39m<<log working_copy::>>[0m
|
||||
│ [1m[38;5;10m<<log working_copy empty::(empty)>>[39m<<log working_copy:: >>[38;5;10m<<log working_copy empty description placeholder::(no description set)>>[39m<<log working_copy::>>[0m
|
||||
<<node::○>> [1m[38;5;5m<<log change_id shortest prefix::q>>[0m[38;5;8m<<log change_id shortest rest::pvuntsm>>[39m<<log:: >>[38;5;3m<<log author email::test.user@example.com>>[39m<<log:: >>[38;5;6m<<log committer timestamp local format::2001-02-03 08:05:07>>[39m<<log:: >>[1m[38;5;4m<<log commit_id shortest prefix::2>>[0m[38;5;8m<<log commit_id shortest rest::30dd059>>[39m<<log::>>
|
||||
│ [38;5;2m<<log empty::(empty)>>[39m<<log:: >>[38;5;2m<<log empty description placeholder::(no description set)>>[39m<<log::>>
|
||||
|
|
@ -394,7 +394,7 @@ fn test_log_builtin_templates_colored_debug() {
|
|||
"###);
|
||||
|
||||
insta::assert_snapshot!(render(r#"builtin_log_comfortable"#), @r###"
|
||||
[1m[38;5;2m<<node working_copy::@>>[0m [1m[38;5;13m<<log working_copy change_id shortest prefix::r>>[38;5;8m<<log working_copy change_id shortest rest::lvkpnrz>>[39m<<log working_copy:: >>[38;5;9m<<log working_copy email placeholder::(no email set)>>[39m<<log working_copy:: >>[38;5;14m<<log working_copy committer timestamp local format::2001-02-03 08:05:08>>[39m<<log working_copy:: >>[38;5;13m<<log working_copy branches name::my-branch>>[39m<<log working_copy:: >>[38;5;12m<<log working_copy commit_id shortest prefix::d>>[38;5;8m<<log working_copy commit_id shortest rest::c315397>>[39m<<log working_copy::>>[0m
|
||||
[1m[38;5;2m<<node working_copy::@>>[0m [1m[38;5;13m<<log working_copy change_id shortest prefix::r>>[38;5;8m<<log working_copy change_id shortest rest::lvkpnrz>>[39m<<log working_copy:: >>[38;5;9m<<log working_copy email placeholder::(no email set)>>[39m<<log working_copy:: >>[38;5;14m<<log working_copy committer timestamp local format::2001-02-03 08:05:08>>[39m<<log working_copy:: >>[38;5;5m<<log working_copy bookmarks name::my-bookmark>>[39m<<log working_copy:: >>[38;5;12m<<log working_copy commit_id shortest prefix::d>>[38;5;8m<<log working_copy commit_id shortest rest::c315397>>[39m<<log working_copy::>>[0m
|
||||
│ [1m[38;5;10m<<log working_copy empty::(empty)>>[39m<<log working_copy:: >>[38;5;10m<<log working_copy empty description placeholder::(no description set)>>[39m<<log working_copy::>>[0m
|
||||
│ <<log::>>
|
||||
<<node::○>> [1m[38;5;5m<<log change_id shortest prefix::q>>[0m[38;5;8m<<log change_id shortest rest::pvuntsm>>[39m<<log:: >>[38;5;3m<<log author email::test.user@example.com>>[39m<<log:: >>[38;5;6m<<log committer timestamp local format::2001-02-03 08:05:07>>[39m<<log:: >>[1m[38;5;4m<<log commit_id shortest prefix::2>>[0m[38;5;8m<<log commit_id shortest rest::30dd059>>[39m<<log::>>
|
||||
|
|
@ -407,7 +407,7 @@ fn test_log_builtin_templates_colored_debug() {
|
|||
insta::assert_snapshot!(render(r#"builtin_log_detailed"#), @r###"
|
||||
[1m[38;5;2m<<node working_copy::@>>[0m <<log::Commit ID: >>[38;5;4m<<log commit_id::dc31539712c7294d1d712cec63cef4504b94ca74>>[39m<<log::>>
|
||||
│ <<log::Change ID: >>[38;5;5m<<log change_id::rlvkpnrzqnoowoytxnquwvuryrwnrmlp>>[39m<<log::>>
|
||||
│ <<log::Branches: >>[38;5;5m<<log local_branches name::my-branch>>[39m<<log::>>
|
||||
│ <<log::Bookmarks: >>[38;5;5m<<log local_bookmarks name::my-bookmark>>[39m<<log::>>
|
||||
│ <<log::Author: >>[38;5;1m<<log name placeholder::(no name set)>>[39m<<log:: <>>[38;5;1m<<log email placeholder::(no email set)>>[39m<<log::> (>>[38;5;6m<<log author timestamp local format::2001-02-03 08:05:08>>[39m<<log::)>>
|
||||
│ <<log::Committer: >>[38;5;1m<<log name placeholder::(no name set)>>[39m<<log:: <>>[38;5;1m<<log email placeholder::(no email set)>>[39m<<log::> (>>[38;5;6m<<log committer timestamp local format::2001-02-03 08:05:08>>[39m<<log::)>>
|
||||
│ <<log::>>
|
||||
|
|
@ -497,7 +497,7 @@ fn test_log_evolog_divergence() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_log_branches() {
|
||||
fn test_log_bookmarks() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.add_config("git.auto-local-branch = true");
|
||||
test_env.add_config(r#"revset-aliases."immutable_heads()" = "none()""#);
|
||||
|
|
@ -510,13 +510,16 @@ fn test_log_branches() {
|
|||
.join("store")
|
||||
.join("git");
|
||||
|
||||
// Created some branches on the remote
|
||||
// Created some bookmarks on the remote
|
||||
test_env.jj_cmd_ok(&origin_path, &["describe", "-m=description 1"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["branch", "create", "branch1"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["bookmark", "create", "bookmark1"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["new", "root()", "-m=description 2"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["branch", "create", "branch2", "unchanged"]);
|
||||
test_env.jj_cmd_ok(
|
||||
&origin_path,
|
||||
&["bookmark", "create", "bookmark2", "unchanged"],
|
||||
);
|
||||
test_env.jj_cmd_ok(&origin_path, &["new", "root()", "-m=description 3"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["branch", "create", "branch3"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["bookmark", "create", "bookmark3"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["git", "export"]);
|
||||
test_env.jj_cmd_ok(
|
||||
test_env.env_root(),
|
||||
|
|
@ -529,64 +532,64 @@ fn test_log_branches() {
|
|||
);
|
||||
let workspace_root = test_env.env_root().join("local");
|
||||
|
||||
// Rewrite branch1, move branch2 forward, create conflict in branch3, add
|
||||
// new-branch
|
||||
// Rewrite bookmark1, move bookmark2 forward, create conflict in bookmark3, add
|
||||
// new-bookmark
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_root,
|
||||
&["describe", "branch1", "-m", "modified branch1 commit"],
|
||||
&["describe", "bookmark1", "-m", "modified bookmark1 commit"],
|
||||
);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["new", "branch2"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["branch", "set", "branch2"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["branch", "create", "new-branch"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["describe", "branch3", "-m=local"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["describe", "branch3", "-m=origin"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["new", "bookmark2"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["bookmark", "set", "bookmark2"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["bookmark", "create", "new-bookmark"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["describe", "bookmark3", "-m=local"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["describe", "bookmark3", "-m=origin"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["git", "export"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["git", "fetch"]);
|
||||
|
||||
let template = r#"commit_id.short() ++ " " ++ if(branches, branches, "(no branches)")"#;
|
||||
let template = r#"commit_id.short() ++ " " ++ if(bookmarks, bookmarks, "(no bookmarks)")"#;
|
||||
let output = test_env.jj_cmd_success(&workspace_root, &["log", "-T", template]);
|
||||
insta::assert_snapshot!(output, @r###"
|
||||
○ fed794e2ba44 branch3?? branch3@origin
|
||||
│ ○ b1bb3766d584 branch3??
|
||||
○ fed794e2ba44 bookmark3?? bookmark3@origin
|
||||
│ ○ b1bb3766d584 bookmark3??
|
||||
├─╯
|
||||
│ ○ 28ff13ce7195 branch1*
|
||||
│ ○ 4a7e4246fc4d bookmark1*
|
||||
├─╯
|
||||
│ @ a5b4d15489cc branch2* new-branch
|
||||
│ ○ 8476341eb395 branch2@origin unchanged
|
||||
│ @ a5b4d15489cc bookmark2* new-bookmark
|
||||
│ ○ 8476341eb395 bookmark2@origin unchanged
|
||||
├─╯
|
||||
◆ 000000000000 (no branches)
|
||||
◆ 000000000000 (no bookmarks)
|
||||
"###);
|
||||
|
||||
let template = r#"branches.map(|b| separate("/", b.remote(), b.name())).join(", ")"#;
|
||||
let template = r#"bookmarks.map(|b| separate("/", b.remote(), b.name())).join(", ")"#;
|
||||
let output = test_env.jj_cmd_success(&workspace_root, &["log", "-T", template]);
|
||||
insta::assert_snapshot!(output, @r###"
|
||||
○ branch3, origin/branch3
|
||||
│ ○ branch3
|
||||
○ bookmark3, origin/bookmark3
|
||||
│ ○ bookmark3
|
||||
├─╯
|
||||
│ ○ branch1
|
||||
│ ○ bookmark1
|
||||
├─╯
|
||||
│ @ branch2, new-branch
|
||||
│ ○ origin/branch2, unchanged
|
||||
│ @ bookmark2, new-bookmark
|
||||
│ ○ origin/bookmark2, unchanged
|
||||
├─╯
|
||||
◆
|
||||
"###);
|
||||
|
||||
let template = r#"separate(" ", "L:", local_branches, "R:", remote_branches)"#;
|
||||
let template = r#"separate(" ", "L:", local_bookmarks, "R:", remote_bookmarks)"#;
|
||||
let output = test_env.jj_cmd_success(&workspace_root, &["log", "-T", template]);
|
||||
insta::assert_snapshot!(output, @r###"
|
||||
○ L: branch3?? R: branch3@origin
|
||||
│ ○ L: branch3?? R:
|
||||
○ L: bookmark3?? R: bookmark3@origin
|
||||
│ ○ L: bookmark3?? R:
|
||||
├─╯
|
||||
│ ○ L: branch1* R:
|
||||
│ ○ L: bookmark1* R:
|
||||
├─╯
|
||||
│ @ L: branch2* new-branch R:
|
||||
│ ○ L: unchanged R: branch2@origin unchanged@origin
|
||||
│ @ L: bookmark2* new-bookmark R:
|
||||
│ ○ L: unchanged R: bookmark2@origin unchanged@origin
|
||||
├─╯
|
||||
◆ L: R:
|
||||
"###);
|
||||
|
||||
let template = r#"
|
||||
remote_branches.map(|ref| concat(
|
||||
remote_bookmarks.map(|ref| concat(
|
||||
ref,
|
||||
if(ref.tracked(),
|
||||
"(+" ++ ref.tracking_ahead_count().lower()
|
||||
|
|
@ -595,13 +598,13 @@ fn test_log_branches() {
|
|||
"#;
|
||||
let output = test_env.jj_cmd_success(
|
||||
&workspace_root,
|
||||
&["log", "-r::remote_branches()", "-T", template],
|
||||
&["log", "-r::remote_bookmarks()", "-T", template],
|
||||
);
|
||||
insta::assert_snapshot!(output, @r###"
|
||||
○ branch3@origin(+0/-1)
|
||||
│ ○ branch2@origin(+0/-1) unchanged@origin(+0/-0)
|
||||
○ bookmark3@origin(+0/-1)
|
||||
│ ○ bookmark2@origin(+0/-1) unchanged@origin(+0/-0)
|
||||
├─╯
|
||||
│ ○ branch1@origin(+1/-1)
|
||||
│ ○ bookmark1@origin(+1/-1)
|
||||
├─╯
|
||||
◆
|
||||
"###);
|
||||
|
|
@ -690,14 +693,14 @@ fn test_log_immutable() {
|
|||
let repo_path = test_env.env_root().join("repo");
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-mA", "root()"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-mB"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "main"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "main"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-mC"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-mD", "root()"]);
|
||||
|
||||
let template = r#"
|
||||
separate(" ",
|
||||
description.first_line(),
|
||||
branches,
|
||||
bookmarks,
|
||||
if(immutable, "[immutable]"),
|
||||
) ++ "\n"
|
||||
"#;
|
||||
|
|
@ -757,7 +760,7 @@ fn test_log_contained_in() {
|
|||
let repo_path = test_env.env_root().join("repo");
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-mA", "root()"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-mB"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "main"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "main"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-mC"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-mD", "root()"]);
|
||||
|
||||
|
|
@ -766,7 +769,7 @@ fn test_log_contained_in() {
|
|||
r#"
|
||||
separate(" ",
|
||||
description.first_line(),
|
||||
branches,
|
||||
bookmarks,
|
||||
if(self.contained_in("{revset}"), "[contained_in]"),
|
||||
) ++ "\n"
|
||||
"#
|
||||
|
|
|
|||
|
|
@ -365,7 +365,7 @@ fn test_diffedit_merge() {
|
|||
std::fs::write(repo_path.join("file1"), "a\n").unwrap();
|
||||
std::fs::write(repo_path.join("file2"), "a\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "b"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "b"]);
|
||||
std::fs::write(repo_path.join("file1"), "b\n").unwrap();
|
||||
std::fs::write(repo_path.join("file2"), "b\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "@-"]);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ fn create_commit(test_env: &TestEnvironment, repo_path: &Path, name: &str, paren
|
|||
test_env.jj_cmd_ok(repo_path, &args);
|
||||
}
|
||||
std::fs::write(repo_path.join(name), format!("{name}\n")).unwrap();
|
||||
test_env.jj_cmd_ok(repo_path, &["branch", "create", name]);
|
||||
test_env.jj_cmd_ok(repo_path, &["bookmark", "create", name]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -33,11 +33,11 @@ fn create_commit(
|
|||
for (name, content) in files {
|
||||
std::fs::write(repo_path.join(name), content).unwrap();
|
||||
}
|
||||
test_env.jj_cmd_ok(repo_path, &["branch", "create", name]);
|
||||
test_env.jj_cmd_ok(repo_path, &["bookmark", "create", name]);
|
||||
}
|
||||
|
||||
fn get_log_output(test_env: &TestEnvironment, repo_path: &Path) -> String {
|
||||
test_env.jj_cmd_success(repo_path, &["log", "-T", "branches"])
|
||||
test_env.jj_cmd_success(repo_path, &["log", "-T", "bookmarks"])
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -468,13 +468,13 @@ fn test_fix_parent_commit() {
|
|||
let (test_env, repo_path, redact) = init_with_fake_formatter(&["--uppercase"]);
|
||||
// Using one file name for all commits adds coverage of some possible bugs.
|
||||
std::fs::write(repo_path.join("file"), "parent").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "parent"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "parent"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
std::fs::write(repo_path.join("file"), "child1").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "child1"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "child1"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-r", "parent"]);
|
||||
std::fs::write(repo_path.join("file"), "child2").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "child2"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "child2"]);
|
||||
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "parent"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
|
|
@ -502,13 +502,13 @@ fn test_fix_parent_commit() {
|
|||
fn test_fix_sibling_commit() {
|
||||
let (test_env, repo_path, redact) = init_with_fake_formatter(&["--uppercase"]);
|
||||
std::fs::write(repo_path.join("file"), "parent").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "parent"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "parent"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
std::fs::write(repo_path.join("file"), "child1").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "child1"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "child1"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-r", "parent"]);
|
||||
std::fs::write(repo_path.join("file"), "child2").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "child2"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "child2"]);
|
||||
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "child1"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
|
|
@ -533,22 +533,22 @@ fn test_fix_sibling_commit() {
|
|||
fn test_default_revset() {
|
||||
let (test_env, repo_path, redact) = init_with_fake_formatter(&["--uppercase"]);
|
||||
std::fs::write(repo_path.join("file"), "trunk1").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "trunk1"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "trunk1"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
std::fs::write(repo_path.join("file"), "trunk2").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "trunk2"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "trunk2"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "trunk1"]);
|
||||
std::fs::write(repo_path.join("file"), "foo").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "foo"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "foo"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "trunk1"]);
|
||||
std::fs::write(repo_path.join("file"), "bar1").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "bar1"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "bar1"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
std::fs::write(repo_path.join("file"), "bar2").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "bar2"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "bar2"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
std::fs::write(repo_path.join("file"), "bar3").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "bar3"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "bar3"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["edit", "bar2"]);
|
||||
|
||||
// With no args and no revset configuration, we fix `reachable(@, mutable())`,
|
||||
|
|
@ -588,10 +588,10 @@ fn test_custom_default_revset() {
|
|||
let (test_env, repo_path, redact) = init_with_fake_formatter(&["--uppercase"]);
|
||||
|
||||
std::fs::write(repo_path.join("file"), "foo").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "foo"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "foo"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
std::fs::write(repo_path.join("file"), "bar").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "bar"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "bar"]);
|
||||
|
||||
// Check out a different commit so that the schema default `reachable(@,
|
||||
// mutable())` would behave differently from our customized default.
|
||||
|
|
@ -619,10 +619,10 @@ fn test_custom_default_revset() {
|
|||
fn test_fix_immutable_commit() {
|
||||
let (test_env, repo_path, redact) = init_with_fake_formatter(&["--uppercase"]);
|
||||
std::fs::write(repo_path.join("file"), "immutable").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "immutable"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "immutable"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
std::fs::write(repo_path.join("file"), "mutable").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "mutable"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "mutable"]);
|
||||
test_env.add_config(r#"revset-aliases."immutable_heads()" = "immutable""#);
|
||||
|
||||
let stderr = test_env.jj_cmd_failure(&repo_path, &["fix", "-s", "immutable"]);
|
||||
|
|
@ -742,16 +742,16 @@ fn test_deduplication() {
|
|||
// There are at least two interesting cases: the content is repeated immediately
|
||||
// in the child commit, or later in another descendant.
|
||||
std::fs::write(repo_path.join("file"), "foo\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "a"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "a"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
std::fs::write(repo_path.join("file"), "bar\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "b"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "b"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
std::fs::write(repo_path.join("file"), "bar\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "c"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "c"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
std::fs::write(repo_path.join("file"), "foo\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "d"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "d"]);
|
||||
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "a"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
|
|
@ -971,11 +971,11 @@ fn test_fix_trivial_merge_commit() {
|
|||
let (test_env, repo_path, redact) = init_with_fake_formatter(&["--uppercase"]);
|
||||
std::fs::write(repo_path.join("file_a"), "content a").unwrap();
|
||||
std::fs::write(repo_path.join("file_c"), "content c").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "a"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "a"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "@-"]);
|
||||
std::fs::write(repo_path.join("file_b"), "content b").unwrap();
|
||||
std::fs::write(repo_path.join("file_c"), "content c").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "b"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "b"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "a", "b"]);
|
||||
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "@"]);
|
||||
|
|
@ -1005,11 +1005,11 @@ fn test_fix_adding_merge_commit() {
|
|||
let (test_env, repo_path, redact) = init_with_fake_formatter(&["--uppercase"]);
|
||||
std::fs::write(repo_path.join("file_a"), "content a").unwrap();
|
||||
std::fs::write(repo_path.join("file_c"), "content c").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "a"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "a"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "@-"]);
|
||||
std::fs::write(repo_path.join("file_b"), "content b").unwrap();
|
||||
std::fs::write(repo_path.join("file_c"), "content c").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "b"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "b"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "a", "b"]);
|
||||
std::fs::write(repo_path.join("file_a"), "change a").unwrap();
|
||||
std::fs::write(repo_path.join("file_b"), "change b").unwrap();
|
||||
|
|
@ -1045,10 +1045,10 @@ fn test_fix_adding_merge_commit() {
|
|||
fn test_fix_both_sides_of_conflict() {
|
||||
let (test_env, repo_path, redact) = init_with_fake_formatter(&["--uppercase"]);
|
||||
std::fs::write(repo_path.join("file"), "content a\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "a"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "a"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "@-"]);
|
||||
std::fs::write(repo_path.join("file"), "content b\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "b"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "b"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "a", "b"]);
|
||||
|
||||
// The conflicts are not different from the merged parent, so they would not be
|
||||
|
|
@ -1095,10 +1095,10 @@ fn test_fix_resolve_conflict() {
|
|||
// will be resolved.
|
||||
let (test_env, repo_path, redact) = init_with_fake_formatter(&["--uppercase"]);
|
||||
std::fs::write(repo_path.join("file"), "Content\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "a"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "a"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "@-"]);
|
||||
std::fs::write(repo_path.join("file"), "cOnTeNt\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "b"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "b"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "a", "b"]);
|
||||
|
||||
// The conflicts are not different from the merged parent, so they would not be
|
||||
|
|
|
|||
|
|
@ -234,9 +234,9 @@ fn test_git_clone_colocate() {
|
|||
Status(IGNORED) .jj/working_copy/
|
||||
"###);
|
||||
|
||||
// The old default branch "master" shouldn't exist.
|
||||
// The old default bookmark "master" shouldn't exist.
|
||||
insta::assert_snapshot!(
|
||||
get_branch_output(&test_env, &test_env.env_root().join("clone")), @r###"
|
||||
get_bookmark_output(&test_env, &test_env.env_root().join("clone")), @r###"
|
||||
main: mzyxwzks 9f01a0e0 message
|
||||
@git: mzyxwzks 9f01a0e0 message
|
||||
@origin: mzyxwzks 9f01a0e0 message
|
||||
|
|
@ -351,12 +351,12 @@ fn test_git_clone_colocate() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_git_clone_remote_default_branch() {
|
||||
fn test_git_clone_remote_default_bookmark() {
|
||||
let test_env = TestEnvironment::default();
|
||||
let git_repo_path = test_env.env_root().join("source");
|
||||
let git_repo = git2::Repository::init(git_repo_path).unwrap();
|
||||
set_up_non_empty_git_repo(&git_repo);
|
||||
// Create non-default branch in remote
|
||||
// Create non-default bookmark in remote
|
||||
let oid = git_repo
|
||||
.find_reference("refs/heads/main")
|
||||
.unwrap()
|
||||
|
|
@ -366,7 +366,7 @@ fn test_git_clone_remote_default_branch() {
|
|||
.reference("refs/heads/feature1", oid, false, "")
|
||||
.unwrap();
|
||||
|
||||
// All fetched branches will be imported if auto-local-branch is on
|
||||
// All fetched bookmarks will be imported if auto-local-branch is on
|
||||
test_env.add_config("git.auto-local-branch = true");
|
||||
let (_stdout, stderr) =
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "clone", "source", "clone1"]);
|
||||
|
|
@ -380,14 +380,14 @@ fn test_git_clone_remote_default_branch() {
|
|||
Added 1 files, modified 0 files, removed 0 files
|
||||
"###);
|
||||
insta::assert_snapshot!(
|
||||
get_branch_output(&test_env, &test_env.env_root().join("clone1")), @r###"
|
||||
get_bookmark_output(&test_env, &test_env.env_root().join("clone1")), @r###"
|
||||
feature1: mzyxwzks 9f01a0e0 message
|
||||
@origin: mzyxwzks 9f01a0e0 message
|
||||
main: mzyxwzks 9f01a0e0 message
|
||||
@origin: mzyxwzks 9f01a0e0 message
|
||||
"###);
|
||||
|
||||
// "trunk()" alias should be set to default branch "main"
|
||||
// "trunk()" alias should be set to default bookmark "main"
|
||||
let stdout = test_env.jj_cmd_success(
|
||||
&test_env.env_root().join("clone1"),
|
||||
&["config", "list", "--repo", "revset-aliases.'trunk()'"],
|
||||
|
|
@ -396,7 +396,7 @@ fn test_git_clone_remote_default_branch() {
|
|||
revset-aliases.'trunk()' = "main@origin"
|
||||
"###);
|
||||
|
||||
// Only the default branch will be imported if auto-local-branch is off
|
||||
// Only the default bookmark will be imported if auto-local-branch is off
|
||||
test_env.add_config("git.auto-local-branch = false");
|
||||
let (_stdout, stderr) =
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "clone", "source", "clone2"]);
|
||||
|
|
@ -410,13 +410,13 @@ fn test_git_clone_remote_default_branch() {
|
|||
Added 1 files, modified 0 files, removed 0 files
|
||||
"###);
|
||||
insta::assert_snapshot!(
|
||||
get_branch_output(&test_env, &test_env.env_root().join("clone2")), @r###"
|
||||
get_bookmark_output(&test_env, &test_env.env_root().join("clone2")), @r###"
|
||||
feature1@origin: mzyxwzks 9f01a0e0 message
|
||||
main: mzyxwzks 9f01a0e0 message
|
||||
@origin: mzyxwzks 9f01a0e0 message
|
||||
"###);
|
||||
|
||||
// Change the default branch in remote
|
||||
// Change the default bookmark in remote
|
||||
git_repo.set_head("refs/heads/feature1").unwrap();
|
||||
let (_stdout, stderr) =
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "clone", "source", "clone3"]);
|
||||
|
|
@ -430,13 +430,13 @@ fn test_git_clone_remote_default_branch() {
|
|||
Added 1 files, modified 0 files, removed 0 files
|
||||
"###);
|
||||
insta::assert_snapshot!(
|
||||
get_branch_output(&test_env, &test_env.env_root().join("clone2")), @r###"
|
||||
get_bookmark_output(&test_env, &test_env.env_root().join("clone2")), @r###"
|
||||
feature1@origin: mzyxwzks 9f01a0e0 message
|
||||
main: mzyxwzks 9f01a0e0 message
|
||||
@origin: mzyxwzks 9f01a0e0 message
|
||||
"###);
|
||||
|
||||
// "trunk()" alias should be set to new default branch "feature1"
|
||||
// "trunk()" alias should be set to new default bookmark "feature1"
|
||||
let stdout = test_env.jj_cmd_success(
|
||||
&test_env.env_root().join("clone3"),
|
||||
&["config", "list", "--repo", "revset-aliases.'trunk()'"],
|
||||
|
|
@ -498,6 +498,6 @@ fn test_git_clone_at_operation() {
|
|||
"###);
|
||||
}
|
||||
|
||||
fn get_branch_output(test_env: &TestEnvironment, repo_path: &Path) -> String {
|
||||
test_env.jj_cmd_success(repo_path, &["branch", "list", "--all-remotes"])
|
||||
fn get_bookmark_output(test_env: &TestEnvironment, repo_path: &Path) -> String {
|
||||
test_env.jj_cmd_success(repo_path, &["bookmark", "list", "--all-remotes"])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ fn test_git_colocated() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_git_colocated_unborn_branch() {
|
||||
fn test_git_colocated_unborn_bookmark() {
|
||||
let test_env = TestEnvironment::default();
|
||||
let workspace_root = test_env.env_root().join("repo");
|
||||
let git_repo = git2::Repository::init(&workspace_root).unwrap();
|
||||
|
|
@ -152,7 +152,7 @@ fn test_git_colocated_unborn_branch() {
|
|||
"###);
|
||||
|
||||
// Stage some change, and create new HEAD. This shouldn't move the default
|
||||
// branch.
|
||||
// bookmark.
|
||||
add_file_to_index("file1", "");
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&workspace_root, &["new"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
|
|
@ -180,8 +180,8 @@ fn test_git_colocated_unborn_branch() {
|
|||
Parent commit: kkmpptxz e3e01407 (no description set)
|
||||
"###);
|
||||
|
||||
// Assign the default branch. The branch is no longer "unborn".
|
||||
test_env.jj_cmd_ok(&workspace_root, &["branch", "create", "-r@-", "master"]);
|
||||
// Assign the default bookmark. The bookmark is no longer "unborn".
|
||||
test_env.jj_cmd_ok(&workspace_root, &["bookmark", "create", "-r@-", "master"]);
|
||||
|
||||
// Stage some change, and check out root again. This should unset the HEAD.
|
||||
// https://github.com/martinvonz/jj/issues/1495
|
||||
|
|
@ -232,8 +232,8 @@ fn test_git_colocated_unborn_branch() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_git_colocated_export_branches_on_snapshot() {
|
||||
// Checks that we export branches that were changed only because the working
|
||||
fn test_git_colocated_export_bookmarks_on_snapshot() {
|
||||
// Checks that we export bookmarks that were changed only because the working
|
||||
// copy was snapshotted
|
||||
|
||||
let test_env = TestEnvironment::default();
|
||||
|
|
@ -241,15 +241,15 @@ fn test_git_colocated_export_branches_on_snapshot() {
|
|||
let git_repo = git2::Repository::init(&workspace_root).unwrap();
|
||||
test_env.jj_cmd_ok(&workspace_root, &["git", "init", "--git-repo", "."]);
|
||||
|
||||
// Create branch pointing to the initial commit
|
||||
// Create bookmark pointing to the initial commit
|
||||
std::fs::write(workspace_root.join("file"), "initial").unwrap();
|
||||
test_env.jj_cmd_ok(&workspace_root, &["branch", "create", "foo"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["bookmark", "create", "foo"]);
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &workspace_root), @r###"
|
||||
@ b15ef4cdd277d2c63cce6d67c1916f53a36141f7 foo
|
||||
◆ 0000000000000000000000000000000000000000
|
||||
"###);
|
||||
|
||||
// The branch gets updated when we modify the working copy, and it should get
|
||||
// The bookmark gets updated when we modify the working copy, and it should get
|
||||
// exported to Git without requiring any other changes
|
||||
std::fs::write(workspace_root.join("file"), "modified").unwrap();
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &workspace_root), @r###"
|
||||
|
|
@ -275,7 +275,7 @@ fn test_git_colocated_rebase_on_import() {
|
|||
std::fs::write(workspace_root.join("file"), "contents").unwrap();
|
||||
test_env.jj_cmd_ok(&workspace_root, &["commit", "-m", "add a file"]);
|
||||
std::fs::write(workspace_root.join("file"), "modified").unwrap();
|
||||
test_env.jj_cmd_ok(&workspace_root, &["branch", "create", "master"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["bookmark", "create", "master"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["commit", "-m", "modify a file"]);
|
||||
// TODO: We shouldn't need this command here to trigger an import of the
|
||||
// refs/heads/master we just exported
|
||||
|
|
@ -309,7 +309,7 @@ fn test_git_colocated_rebase_on_import() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_git_colocated_branches() {
|
||||
fn test_git_colocated_bookmarks() {
|
||||
let test_env = TestEnvironment::default();
|
||||
let workspace_root = test_env.env_root().join("repo");
|
||||
let git_repo = git2::Repository::init(&workspace_root).unwrap();
|
||||
|
|
@ -324,9 +324,9 @@ fn test_git_colocated_branches() {
|
|||
◆ 0000000000000000000000000000000000000000
|
||||
"###);
|
||||
|
||||
// Create a branch in jj. It should be exported to Git even though it points to
|
||||
// the working- copy commit.
|
||||
test_env.jj_cmd_ok(&workspace_root, &["branch", "create", "master"]);
|
||||
// Create a bookmark in jj. It should be exported to Git even though it points
|
||||
// to the working- copy commit.
|
||||
test_env.jj_cmd_ok(&workspace_root, &["bookmark", "create", "master"]);
|
||||
insta::assert_snapshot!(
|
||||
git_repo.find_reference("refs/heads/master").unwrap().target().unwrap().to_string(),
|
||||
@"3560559274ab431feea00b7b7e0b9250ecce951f"
|
||||
|
|
@ -336,7 +336,7 @@ fn test_git_colocated_branches() {
|
|||
@"230dd059e1b059aefc0da06a2e5a7dbf22362f22"
|
||||
);
|
||||
|
||||
// Update the branch in Git
|
||||
// Update the bookmark in Git
|
||||
let target_id = test_env.jj_cmd_success(
|
||||
&workspace_root,
|
||||
&["log", "--no-graph", "-T=commit_id", "-r=description(foo)"],
|
||||
|
|
@ -366,58 +366,65 @@ fn test_git_colocated_branches() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_git_colocated_branch_forget() {
|
||||
fn test_git_colocated_bookmark_forget() {
|
||||
let test_env = TestEnvironment::default();
|
||||
let workspace_root = test_env.env_root().join("repo");
|
||||
let _git_repo = git2::Repository::init(&workspace_root).unwrap();
|
||||
test_env.jj_cmd_ok(&workspace_root, &["git", "init", "--git-repo", "."]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["new"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["branch", "create", "foo"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["bookmark", "create", "foo"]);
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &workspace_root), @r###"
|
||||
@ 65b6b74e08973b88d38404430f119c8c79465250 foo
|
||||
○ 230dd059e1b059aefc0da06a2e5a7dbf22362f22 HEAD@git
|
||||
◆ 0000000000000000000000000000000000000000
|
||||
"###);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &workspace_root), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &workspace_root), @r###"
|
||||
foo: rlvkpnrz 65b6b74e (empty) (no description set)
|
||||
@git: rlvkpnrz 65b6b74e (empty) (no description set)
|
||||
"###);
|
||||
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&workspace_root, &["branch", "forget", "foo"]);
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&workspace_root, &["bookmark", "forget", "foo"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Forgot 1 branches.
|
||||
Forgot 1 bookmarks.
|
||||
"###);
|
||||
// A forgotten branch is deleted in the git repo. For a detailed demo explaining
|
||||
// this, see `test_branch_forget_export` in `test_branch_command.rs`.
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &workspace_root), @"");
|
||||
// A forgotten bookmark is deleted in the git repo. For a detailed demo
|
||||
// explaining this, see `test_bookmark_forget_export` in
|
||||
// `test_bookmark_command.rs`.
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &workspace_root), @"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_git_colocated_branch_at_root() {
|
||||
fn test_git_colocated_bookmark_at_root() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "--colocate", "repo"]);
|
||||
let repo_path = test_env.env_root().join("repo");
|
||||
|
||||
let (_stdout, stderr) =
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "foo", "-r=root()"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "foo", "-r=root()"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Created 1 branches pointing to zzzzzzzz 00000000 foo | (empty) (no description set)
|
||||
Created 1 bookmarks pointing to zzzzzzzz 00000000 foo | (empty) (no description set)
|
||||
Warning: Failed to export some branches:
|
||||
foo: Ref cannot point to the root commit in Git
|
||||
"###);
|
||||
|
||||
let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["branch", "move", "foo"]);
|
||||
let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "move", "foo"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Moved 1 branches to qpvuntsm 230dd059 foo | (empty) (no description set)
|
||||
Moved 1 bookmarks to qpvuntsm 230dd059 foo | (empty) (no description set)
|
||||
"###);
|
||||
|
||||
let (_stdout, stderr) = test_env.jj_cmd_ok(
|
||||
&repo_path,
|
||||
&["branch", "move", "foo", "--allow-backwards", "--to=root()"],
|
||||
&[
|
||||
"bookmark",
|
||||
"move",
|
||||
"foo",
|
||||
"--allow-backwards",
|
||||
"--to=root()",
|
||||
],
|
||||
);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Moved 1 branches to zzzzzzzz 00000000 foo* | (empty) (no description set)
|
||||
Moved 1 bookmarks to zzzzzzzz 00000000 foo* | (empty) (no description set)
|
||||
Warning: Failed to export some branches:
|
||||
foo: Ref cannot point to the root commit in Git
|
||||
"###);
|
||||
|
|
@ -429,12 +436,12 @@ fn test_git_colocated_conflicting_git_refs() {
|
|||
let workspace_root = test_env.env_root().join("repo");
|
||||
git2::Repository::init(&workspace_root).unwrap();
|
||||
test_env.jj_cmd_ok(&workspace_root, &["git", "init", "--git-repo", "."]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["branch", "create", "main"]);
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&workspace_root, &["branch", "create", "main/sub"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["bookmark", "create", "main"]);
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&workspace_root, &["bookmark", "create", "main/sub"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
insta::with_settings!({filters => vec![("Failed to set: .*", "Failed to set: ...")]}, {
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Created 1 branches pointing to qpvuntsm 230dd059 main main/sub | (empty) (no description set)
|
||||
Created 1 bookmarks pointing to qpvuntsm 230dd059 main main/sub | (empty) (no description set)
|
||||
Warning: Failed to export some branches:
|
||||
main/sub: Failed to set: ...
|
||||
Hint: Git doesn't allow a branch name that looks like a parent directory of
|
||||
|
|
@ -507,18 +514,18 @@ fn test_git_colocated_checkout_non_empty_working_copy() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_git_colocated_fetch_deleted_or_moved_branch() {
|
||||
fn test_git_colocated_fetch_deleted_or_moved_bookmark() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.add_config("git.auto-local-branch = true");
|
||||
let origin_path = test_env.env_root().join("origin");
|
||||
git2::Repository::init(&origin_path).unwrap();
|
||||
test_env.jj_cmd_ok(&origin_path, &["git", "init", "--git-repo=."]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["describe", "-m=A"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["branch", "create", "A"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["bookmark", "create", "A"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["new", "-m=B_to_delete"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["branch", "create", "B_to_delete"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["bookmark", "create", "B_to_delete"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["new", "-m=original C", "@-"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["branch", "create", "C_to_move"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["bookmark", "create", "C_to_move"]);
|
||||
|
||||
let clone_path = test_env.env_root().join("clone");
|
||||
git2::Repository::clone(origin_path.to_str().unwrap(), &clone_path).unwrap();
|
||||
|
|
@ -534,8 +541,8 @@ fn test_git_colocated_fetch_deleted_or_moved_branch() {
|
|||
◆ 0000000000000000000000000000000000000000
|
||||
"###);
|
||||
|
||||
test_env.jj_cmd_ok(&origin_path, &["branch", "delete", "B_to_delete"]);
|
||||
// Move branch C sideways
|
||||
test_env.jj_cmd_ok(&origin_path, &["bookmark", "delete", "B_to_delete"]);
|
||||
// Move bookmark C sideways
|
||||
test_env.jj_cmd_ok(&origin_path, &["describe", "C_to_move", "-m", "moved C"]);
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&clone_path, &["git", "fetch"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
|
|
@ -544,7 +551,7 @@ fn test_git_colocated_fetch_deleted_or_moved_branch() {
|
|||
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
|
||||
// "original C" and "B_to_delete" are abandoned, as the corresponding bookmarks
|
||||
// were deleted or moved on the remote (#864)
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &clone_path), @r###"
|
||||
○ 4f3d13296f978cbc351c46a43b4619c91b888475 C_to_move moved C
|
||||
|
|
@ -565,9 +572,9 @@ fn test_git_colocated_rebase_dirty_working_copy() {
|
|||
std::fs::write(repo_path.join("file"), "base").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
std::fs::write(repo_path.join("file"), "old").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "feature"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "feature"]);
|
||||
|
||||
// Make the working-copy dirty, delete the checked out branch.
|
||||
// Make the working-copy dirty, delete the checked out bookmark.
|
||||
std::fs::write(repo_path.join("file"), "new").unwrap();
|
||||
git_repo
|
||||
.find_reference("refs/heads/feature")
|
||||
|
|
@ -576,16 +583,16 @@ fn test_git_colocated_rebase_dirty_working_copy() {
|
|||
.unwrap();
|
||||
|
||||
// Because the working copy is dirty, the new working-copy commit will be
|
||||
// diverged. Therefore, the feature branch has change-delete conflict.
|
||||
// diverged. Therefore, the feature bookmark has change-delete conflict.
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["status"]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
Working copy changes:
|
||||
M file
|
||||
Working copy : rlvkpnrz 6bad94b1 feature?? | (no description set)
|
||||
Parent commit: qpvuntsm 3230d522 (no description set)
|
||||
These branches have conflicts:
|
||||
These bookmarks have conflicts:
|
||||
feature
|
||||
Use `jj branch list` to see details. Use `jj branch set <name> -r <rev>` to resolve.
|
||||
Use `jj bookmark list` to see details. Use `jj bookmark set <name> -r <rev>` to resolve.
|
||||
"###);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Warning: Failed to export some branches:
|
||||
|
|
@ -616,11 +623,11 @@ fn test_git_colocated_external_checkout() {
|
|||
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "init", "--git-repo=."]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["ci", "-m=A"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "-r@-", "master"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "-r@-", "master"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-m=B", "root()"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
|
||||
// Checked out anonymous branch
|
||||
// Checked out anonymous bookmark
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
|
||||
@ f8a23336e41840ed1757ef323402a770427dc89a
|
||||
○ eccedddfa5152d99fc8ddd1081b375387a8a382a HEAD@git B
|
||||
|
|
@ -629,10 +636,10 @@ fn test_git_colocated_external_checkout() {
|
|||
◆ 0000000000000000000000000000000000000000
|
||||
"###);
|
||||
|
||||
// Check out another branch by external command
|
||||
// Check out another bookmark by external command
|
||||
git_check_out_ref("refs/heads/master");
|
||||
|
||||
// The old working-copy commit gets abandoned, but the whole branch should not
|
||||
// The old working-copy commit gets abandoned, but the whole bookmark should not
|
||||
// be abandoned. (#1042)
|
||||
let (stdout, stderr) = get_log_output_with_stderr(&test_env, &repo_path);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
|
|
@ -658,7 +665,7 @@ fn test_git_colocated_external_checkout() {
|
|||
◆ 0000000000000000000000000000000000000000
|
||||
"###);
|
||||
|
||||
// Check out another branch by external command
|
||||
// Check out another bookmark by external command
|
||||
git_check_out_ref("refs/heads/master");
|
||||
|
||||
// The old working-copy commit shouldn't be abandoned. (#3747)
|
||||
|
|
@ -769,7 +776,7 @@ fn get_log_output_divergence(test_env: &TestEnvironment, repo_path: &Path) -> St
|
|||
change_id.short(),
|
||||
commit_id.short(),
|
||||
description.first_line(),
|
||||
branches,
|
||||
bookmarks,
|
||||
git_head,
|
||||
if(divergent, "!divergence!"),
|
||||
)
|
||||
|
|
@ -778,7 +785,7 @@ fn get_log_output_divergence(test_env: &TestEnvironment, repo_path: &Path) -> St
|
|||
}
|
||||
|
||||
fn get_log_output(test_env: &TestEnvironment, workspace_root: &Path) -> String {
|
||||
let template = r#"separate(" ", commit_id, branches, git_head, description)"#;
|
||||
let template = r#"separate(" ", commit_id, bookmarks, git_head, description)"#;
|
||||
test_env.jj_cmd_success(workspace_root, &["log", "-T", template, "-r=all()"])
|
||||
}
|
||||
|
||||
|
|
@ -786,7 +793,7 @@ fn get_log_output_with_stderr(
|
|||
test_env: &TestEnvironment,
|
||||
workspace_root: &Path,
|
||||
) -> (String, String) {
|
||||
let template = r#"separate(" ", commit_id, branches, git_head, description)"#;
|
||||
let template = r#"separate(" ", commit_id, bookmarks, git_head, description)"#;
|
||||
test_env.jj_cmd_ok(workspace_root, &["log", "-T", template, "-r=all()"])
|
||||
}
|
||||
|
||||
|
|
@ -862,7 +869,7 @@ fn test_git_colocated_unreachable_commits() {
|
|||
"###);
|
||||
}
|
||||
|
||||
fn get_branch_output(test_env: &TestEnvironment, repo_path: &Path) -> String {
|
||||
// --quiet to suppress deleted branches hint
|
||||
test_env.jj_cmd_success(repo_path, &["branch", "list", "--all-remotes", "--quiet"])
|
||||
fn get_bookmark_output(test_env: &TestEnvironment, repo_path: &Path) -> String {
|
||||
// --quiet to suppress deleted bookmarks hint
|
||||
test_env.jj_cmd_success(repo_path, &["bookmark", "list", "--all-remotes", "--quiet"])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ use std::path::Path;
|
|||
|
||||
use crate::common::TestEnvironment;
|
||||
|
||||
/// Creates a remote Git repo containing a branch with the same name
|
||||
/// Creates a remote Git repo containing a bookmark with the same name
|
||||
fn init_git_remote(test_env: &TestEnvironment, remote: &str) {
|
||||
let git_repo_path = test_env.env_root().join(remote);
|
||||
let git_repo = git2::Repository::init(git_repo_path).unwrap();
|
||||
|
|
@ -40,7 +40,7 @@ fn init_git_remote(test_env: &TestEnvironment, remote: &str) {
|
|||
.unwrap();
|
||||
}
|
||||
|
||||
/// Add a remote containing a branch with the same name
|
||||
/// Add a remote containing a bookmark with the same name
|
||||
fn add_git_remote(test_env: &TestEnvironment, repo_path: &Path, remote: &str) {
|
||||
init_git_remote(test_env, remote);
|
||||
test_env.jj_cmd_ok(
|
||||
|
|
@ -49,9 +49,9 @@ fn add_git_remote(test_env: &TestEnvironment, repo_path: &Path, remote: &str) {
|
|||
);
|
||||
}
|
||||
|
||||
fn get_branch_output(test_env: &TestEnvironment, repo_path: &Path) -> String {
|
||||
// --quiet to suppress deleted branches hint
|
||||
test_env.jj_cmd_success(repo_path, &["branch", "list", "--all-remotes", "--quiet"])
|
||||
fn get_bookmark_output(test_env: &TestEnvironment, repo_path: &Path) -> String {
|
||||
// --quiet to suppress deleted bookmarks hint
|
||||
test_env.jj_cmd_success(repo_path, &["bookmark", "list", "--all-remotes", "--quiet"])
|
||||
}
|
||||
|
||||
fn create_commit(test_env: &TestEnvironment, repo_path: &Path, name: &str, parents: &[&str]) {
|
||||
|
|
@ -64,11 +64,11 @@ fn create_commit(test_env: &TestEnvironment, repo_path: &Path, name: &str, paren
|
|||
test_env.jj_cmd_ok(repo_path, &args);
|
||||
}
|
||||
std::fs::write(repo_path.join(name), format!("{name}\n")).unwrap();
|
||||
test_env.jj_cmd_ok(repo_path, &["branch", "create", name]);
|
||||
test_env.jj_cmd_ok(repo_path, &["bookmark", "create", name]);
|
||||
}
|
||||
|
||||
fn get_log_output(test_env: &TestEnvironment, workspace_root: &Path) -> String {
|
||||
let template = r#"commit_id.short() ++ " " ++ description.first_line() ++ " " ++ branches"#;
|
||||
let template = r#"commit_id.short() ++ " " ++ description.first_line() ++ " " ++ bookmarks"#;
|
||||
test_env.jj_cmd_success(workspace_root, &["log", "-T", template, "-r", "all()"])
|
||||
}
|
||||
|
||||
|
|
@ -80,7 +80,7 @@ fn test_git_fetch_with_default_config() {
|
|||
add_git_remote(&test_env, &repo_path, "origin");
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "fetch"]);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
origin@origin: oputwtnw ffecd2d6 message
|
||||
"###);
|
||||
}
|
||||
|
|
@ -94,7 +94,7 @@ fn test_git_fetch_default_remote() {
|
|||
add_git_remote(&test_env, &repo_path, "origin");
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "fetch"]);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
origin: oputwtnw ffecd2d6 message
|
||||
@origin: oputwtnw ffecd2d6 message
|
||||
"###);
|
||||
|
|
@ -113,7 +113,7 @@ fn test_git_fetch_single_remote() {
|
|||
Hint: Fetching from the only existing remote: rem1
|
||||
branch: rem1@rem1 [new] tracked
|
||||
"###);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
rem1: qxosxrvv 6a211027 message
|
||||
@rem1: qxosxrvv 6a211027 message
|
||||
"###);
|
||||
|
|
@ -131,7 +131,7 @@ fn test_git_fetch_single_remote_all_remotes_flag() {
|
|||
.jj_cmd(&repo_path, &["git", "fetch", "--all-remotes"])
|
||||
.assert()
|
||||
.success();
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
rem1: qxosxrvv 6a211027 message
|
||||
@rem1: qxosxrvv 6a211027 message
|
||||
"###);
|
||||
|
|
@ -146,7 +146,7 @@ fn test_git_fetch_single_remote_from_arg() {
|
|||
add_git_remote(&test_env, &repo_path, "rem1");
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "fetch", "--remote", "rem1"]);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
rem1: qxosxrvv 6a211027 message
|
||||
@rem1: qxosxrvv 6a211027 message
|
||||
"###);
|
||||
|
|
@ -162,7 +162,7 @@ fn test_git_fetch_single_remote_from_config() {
|
|||
test_env.add_config(r#"git.fetch = "rem1""#);
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "fetch"]);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
rem1: qxosxrvv 6a211027 message
|
||||
@rem1: qxosxrvv 6a211027 message
|
||||
"###);
|
||||
|
|
@ -181,7 +181,7 @@ fn test_git_fetch_multiple_remotes() {
|
|||
&repo_path,
|
||||
&["git", "fetch", "--remote", "rem1", "--remote", "rem2"],
|
||||
);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
rem1: qxosxrvv 6a211027 message
|
||||
@rem1: qxosxrvv 6a211027 message
|
||||
rem2: yszkquru 2497a8a0 message
|
||||
|
|
@ -199,7 +199,7 @@ fn test_git_fetch_all_remotes() {
|
|||
add_git_remote(&test_env, &repo_path, "rem2");
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "fetch", "--all-remotes"]);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
rem1: qxosxrvv 6a211027 message
|
||||
@rem1: qxosxrvv 6a211027 message
|
||||
rem2: yszkquru 2497a8a0 message
|
||||
|
|
@ -218,7 +218,7 @@ fn test_git_fetch_multiple_remotes_from_config() {
|
|||
test_env.add_config(r#"git.fetch = ["rem1", "rem2"]"#);
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "fetch"]);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
rem1: qxosxrvv 6a211027 message
|
||||
@rem1: qxosxrvv 6a211027 message
|
||||
rem2: yszkquru 2497a8a0 message
|
||||
|
|
@ -242,7 +242,7 @@ fn test_git_fetch_nonexistent_remote() {
|
|||
Error: No git remote named 'rem2'
|
||||
"###);
|
||||
// No remote should have been fetched as part of the failing transaction
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @"");
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -259,7 +259,7 @@ fn test_git_fetch_nonexistent_remote_from_config() {
|
|||
Error: No git remote named 'rem2'
|
||||
"###);
|
||||
// No remote should have been fetched as part of the failing transaction
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @"");
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -283,7 +283,7 @@ fn test_git_fetch_from_remote_named_git() {
|
|||
"###);
|
||||
|
||||
// Implicit import shouldn't fail because of the remote ref.
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["branch", "list", "--all-remotes"]);
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "list", "--all-remotes"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
insta::assert_snapshot!(stderr, @"");
|
||||
|
||||
|
|
@ -297,7 +297,7 @@ fn test_git_fetch_from_remote_named_git() {
|
|||
|
||||
// The remote can be renamed, and the ref can be imported.
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "remote", "rename", "git", "bar"]);
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["branch", "list", "--all-remotes"]);
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "list", "--all-remotes"]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
git: mrylzrtu 76fc7466 message
|
||||
@bar: mrylzrtu 76fc7466 message
|
||||
|
|
@ -316,12 +316,12 @@ fn test_git_fetch_prune_before_updating_tips() {
|
|||
let repo_path = test_env.env_root().join("repo");
|
||||
add_git_remote(&test_env, &repo_path, "origin");
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "fetch"]);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
origin: oputwtnw ffecd2d6 message
|
||||
@origin: oputwtnw ffecd2d6 message
|
||||
"###);
|
||||
|
||||
// Remove origin branch in git repo and create origin/subname
|
||||
// Remove origin bookmark in git repo and create origin/subname
|
||||
let git_repo = git2::Repository::open(test_env.env_root().join("origin")).unwrap();
|
||||
git_repo
|
||||
.find_branch("origin", git2::BranchType::Local)
|
||||
|
|
@ -330,24 +330,24 @@ fn test_git_fetch_prune_before_updating_tips() {
|
|||
.unwrap();
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "fetch"]);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
origin/subname: oputwtnw ffecd2d6 message
|
||||
@origin: oputwtnw ffecd2d6 message
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_git_fetch_conflicting_branches() {
|
||||
fn test_git_fetch_conflicting_bookmarks() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.add_config("git.auto-local-branch = true");
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let repo_path = test_env.env_root().join("repo");
|
||||
add_git_remote(&test_env, &repo_path, "rem1");
|
||||
|
||||
// Create a rem1 branch locally
|
||||
// Create a rem1 bookmark locally
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "root()"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "rem1"]);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "rem1"]);
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
rem1: kkmpptxz fcdbbd73 (empty) (no description set)
|
||||
"###);
|
||||
|
||||
|
|
@ -355,8 +355,8 @@ fn test_git_fetch_conflicting_branches() {
|
|||
&repo_path,
|
||||
&["git", "fetch", "--remote", "rem1", "--branch", "glob:*"],
|
||||
);
|
||||
// This should result in a CONFLICTED branch
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
// This should result in a CONFLICTED bookmark
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
rem1 (conflicted):
|
||||
+ kkmpptxz fcdbbd73 (empty) (no description set)
|
||||
+ qxosxrvv 6a211027 message
|
||||
|
|
@ -365,20 +365,20 @@ fn test_git_fetch_conflicting_branches() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_git_fetch_conflicting_branches_colocated() {
|
||||
fn test_git_fetch_conflicting_bookmarks_colocated() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.add_config("git.auto-local-branch = true");
|
||||
let repo_path = test_env.env_root().join("repo");
|
||||
let _git_repo = git2::Repository::init(&repo_path).unwrap();
|
||||
// create_colocated_repo_and_branches_from_trunk1(&test_env, &repo_path);
|
||||
// create_colocated_repo_and_bookmarks_from_trunk1(&test_env, &repo_path);
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "init", "--git-repo", "."]);
|
||||
add_git_remote(&test_env, &repo_path, "rem1");
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @"");
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @"");
|
||||
|
||||
// Create a rem1 branch locally
|
||||
// Create a rem1 bookmark locally
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "root()"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "rem1"]);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "rem1"]);
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
rem1: zsuskuln f652c321 (empty) (no description set)
|
||||
@git: zsuskuln f652c321 (empty) (no description set)
|
||||
"###);
|
||||
|
|
@ -387,9 +387,9 @@ fn test_git_fetch_conflicting_branches_colocated() {
|
|||
&repo_path,
|
||||
&["git", "fetch", "--remote", "rem1", "--branch", "rem1"],
|
||||
);
|
||||
// This should result in a CONFLICTED branch
|
||||
// This should result in a CONFLICTED bookmark
|
||||
// See https://github.com/martinvonz/jj/pull/1146#discussion_r1112372340 for the bug this tests for.
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
rem1 (conflicted):
|
||||
+ zsuskuln f652c321 (empty) (no description set)
|
||||
+ qxosxrvv 6a211027 message
|
||||
|
|
@ -398,9 +398,9 @@ fn test_git_fetch_conflicting_branches_colocated() {
|
|||
"###);
|
||||
}
|
||||
|
||||
// Helper functions to test obtaining multiple branches at once and changed
|
||||
// branches
|
||||
fn create_colocated_repo_and_branches_from_trunk1(
|
||||
// Helper functions to test obtaining multiple bookmarks at once and changed
|
||||
// bookmarks
|
||||
fn create_colocated_repo_and_bookmarks_from_trunk1(
|
||||
test_env: &TestEnvironment,
|
||||
repo_path: &Path,
|
||||
) -> String {
|
||||
|
|
@ -416,7 +416,7 @@ fn create_colocated_repo_and_branches_from_trunk1(
|
|||
)
|
||||
}
|
||||
|
||||
fn create_trunk2_and_rebase_branches(test_env: &TestEnvironment, repo_path: &Path) -> String {
|
||||
fn create_trunk2_and_rebase_bookmarks(test_env: &TestEnvironment, repo_path: &Path) -> String {
|
||||
create_commit(test_env, repo_path, "trunk2", &["trunk1"]);
|
||||
for br in ["a1", "a2", "b"] {
|
||||
test_env.jj_cmd_ok(repo_path, &["rebase", "-b", br, "-d", "trunk2"]);
|
||||
|
|
@ -446,7 +446,7 @@ fn test_git_fetch_all() {
|
|||
let target_jj_repo_path = test_env.env_root().join("target");
|
||||
|
||||
let source_log =
|
||||
create_colocated_repo_and_branches_from_trunk1(&test_env, &source_git_repo_path);
|
||||
create_colocated_repo_and_bookmarks_from_trunk1(&test_env, &source_git_repo_path);
|
||||
insta::assert_snapshot!(source_log, @r###"
|
||||
===== Source git repo contents =====
|
||||
@ c7d4bdcbc215 descr_for_b b
|
||||
|
|
@ -463,7 +463,7 @@ fn test_git_fetch_all() {
|
|||
@ 230dd059e1b0
|
||||
◆ 000000000000
|
||||
"###);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &target_jj_repo_path), @"");
|
||||
insta::assert_snapshot!(get_bookmark_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, @r###"
|
||||
|
|
@ -472,7 +472,7 @@ fn test_git_fetch_all() {
|
|||
branch: b@origin [new] tracked
|
||||
branch: trunk1@origin [new] tracked
|
||||
"###);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &target_jj_repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &target_jj_repo_path), @r###"
|
||||
a1: nknoxmzm 359a9a02 descr_for_a1
|
||||
@origin: nknoxmzm 359a9a02 descr_for_a1
|
||||
a2: qkvnknrk decaa396 descr_for_a2
|
||||
|
|
@ -496,7 +496,7 @@ fn test_git_fetch_all() {
|
|||
|
||||
// ==== Change both repos ====
|
||||
// First, change the target repo:
|
||||
let source_log = create_trunk2_and_rebase_branches(&test_env, &source_git_repo_path);
|
||||
let source_log = create_trunk2_and_rebase_bookmarks(&test_env, &source_git_repo_path);
|
||||
insta::assert_snapshot!(source_log, @r###"
|
||||
===== Source git repo contents =====
|
||||
○ babc49226c14 descr_for_b b
|
||||
|
|
@ -508,7 +508,7 @@ fn test_git_fetch_all() {
|
|||
○ ff36dc55760e descr_for_trunk1 trunk1
|
||||
◆ 000000000000
|
||||
"###);
|
||||
// Change a branch in the source repo as well, so that it becomes conflicted.
|
||||
// Change a bookmark in the source repo as well, so that it becomes conflicted.
|
||||
test_env.jj_cmd_ok(
|
||||
&target_jj_repo_path,
|
||||
&["describe", "b", "-m=new_descr_for_b_to_create_conflict"],
|
||||
|
|
@ -526,7 +526,7 @@ fn test_git_fetch_all() {
|
|||
├─╯
|
||||
◆ 000000000000
|
||||
"###);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &target_jj_repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &target_jj_repo_path), @r###"
|
||||
a1: nknoxmzm 359a9a02 descr_for_a1
|
||||
@origin: nknoxmzm 359a9a02 descr_for_a1
|
||||
a2: qkvnknrk decaa396 descr_for_a2
|
||||
|
|
@ -545,7 +545,7 @@ fn test_git_fetch_all() {
|
|||
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###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &target_jj_repo_path), @r###"
|
||||
a1: quxllqov 0424f6df descr_for_a1
|
||||
@origin: quxllqov 0424f6df descr_for_a1
|
||||
a2: osusxwst 91e46b4b descr_for_a2
|
||||
|
|
@ -577,7 +577,7 @@ fn test_git_fetch_all() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_git_fetch_some_of_many_branches() {
|
||||
fn test_git_fetch_some_of_many_bookmarks() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.add_config("git.auto-local-branch = true");
|
||||
test_env.add_config(r#"revset-aliases."immutable_heads()" = "none()""#);
|
||||
|
|
@ -595,7 +595,7 @@ fn test_git_fetch_some_of_many_branches() {
|
|||
let target_jj_repo_path = test_env.env_root().join("target");
|
||||
|
||||
let source_log =
|
||||
create_colocated_repo_and_branches_from_trunk1(&test_env, &source_git_repo_path);
|
||||
create_colocated_repo_and_bookmarks_from_trunk1(&test_env, &source_git_repo_path);
|
||||
insta::assert_snapshot!(source_log, @r###"
|
||||
===== Source git repo contents =====
|
||||
@ c7d4bdcbc215 descr_for_b b
|
||||
|
|
@ -626,7 +626,7 @@ fn test_git_fetch_some_of_many_branches() {
|
|||
@ 230dd059e1b0
|
||||
◆ 000000000000
|
||||
"###);
|
||||
// Fetch one branch...
|
||||
// Fetch one bookmark...
|
||||
let (stdout, stderr) =
|
||||
test_env.jj_cmd_ok(&target_jj_repo_path, &["git", "fetch", "--branch", "b"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
|
|
@ -641,7 +641,7 @@ fn test_git_fetch_some_of_many_branches() {
|
|||
◆ 000000000000
|
||||
"###);
|
||||
// ...check what the intermediate state looks like...
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &target_jj_repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &target_jj_repo_path), @r###"
|
||||
b: vpupmnsl c7d4bdcb descr_for_b
|
||||
@origin: vpupmnsl c7d4bdcb descr_for_b
|
||||
"###);
|
||||
|
|
@ -666,7 +666,7 @@ fn test_git_fetch_some_of_many_branches() {
|
|||
├─╯
|
||||
◆ 000000000000
|
||||
"###);
|
||||
// Fetching the same branch again
|
||||
// Fetching the same bookmark again
|
||||
let (stdout, stderr) =
|
||||
test_env.jj_cmd_ok(&target_jj_repo_path, &["git", "fetch", "--branch", "a1"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
|
|
@ -687,7 +687,7 @@ fn test_git_fetch_some_of_many_branches() {
|
|||
|
||||
// ==== Change both repos ====
|
||||
// First, change the target repo:
|
||||
let source_log = create_trunk2_and_rebase_branches(&test_env, &source_git_repo_path);
|
||||
let source_log = create_trunk2_and_rebase_bookmarks(&test_env, &source_git_repo_path);
|
||||
insta::assert_snapshot!(source_log, @r###"
|
||||
===== Source git repo contents =====
|
||||
○ 01d115196c39 descr_for_b b
|
||||
|
|
@ -699,13 +699,13 @@ fn test_git_fetch_some_of_many_branches() {
|
|||
○ ff36dc55760e descr_for_trunk1 trunk1
|
||||
◆ 000000000000
|
||||
"###);
|
||||
// Change a branch in the source repo as well, so that it becomes conflicted.
|
||||
// Change a bookmark in the source repo as well, so that it becomes conflicted.
|
||||
test_env.jj_cmd_ok(
|
||||
&target_jj_repo_path,
|
||||
&["describe", "b", "-m=new_descr_for_b_to_create_conflict"],
|
||||
);
|
||||
|
||||
// Our repo before and after fetch of two branches
|
||||
// Our repo before and after fetch of two bookmarks
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &target_jj_repo_path), @r###"
|
||||
○ 6ebd41dc4f13 new_descr_for_b_to_create_conflict b*
|
||||
│ ○ decaa3966c83 descr_for_a2 a2
|
||||
|
|
@ -742,8 +742,8 @@ fn test_git_fetch_some_of_many_branches() {
|
|||
◆ 000000000000
|
||||
"###);
|
||||
|
||||
// We left a2 where it was before, let's see how `jj branch list` sees this.
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &target_jj_repo_path), @r###"
|
||||
// We left a2 where it was before, let's see how `jj bookmark list` sees this.
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &target_jj_repo_path), @r###"
|
||||
a1: ypowunwp 6df2d34c descr_for_a1
|
||||
@origin: ypowunwp 6df2d34c descr_for_a1
|
||||
a2: qkvnknrk decaa396 descr_for_a2
|
||||
|
|
@ -779,7 +779,7 @@ fn test_git_fetch_some_of_many_branches() {
|
|||
├─╯
|
||||
◆ 000000000000
|
||||
"###);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &target_jj_repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &target_jj_repo_path), @r###"
|
||||
a1: ypowunwp 6df2d34c descr_for_a1
|
||||
@origin: ypowunwp 6df2d34c descr_for_a1
|
||||
a2: qrmzolkr 31c7d94b descr_for_a2
|
||||
|
|
@ -793,7 +793,7 @@ fn test_git_fetch_some_of_many_branches() {
|
|||
}
|
||||
|
||||
// See `test_undo_restore_commands.rs` for fetch-undo-push and fetch-undo-fetch
|
||||
// of the same branches for various kinds of undo.
|
||||
// of the same bookmarks for various kinds of undo.
|
||||
#[test]
|
||||
fn test_git_fetch_undo() {
|
||||
let test_env = TestEnvironment::default();
|
||||
|
|
@ -812,7 +812,7 @@ fn test_git_fetch_undo() {
|
|||
let target_jj_repo_path = test_env.env_root().join("target");
|
||||
|
||||
let source_log =
|
||||
create_colocated_repo_and_branches_from_trunk1(&test_env, &source_git_repo_path);
|
||||
create_colocated_repo_and_bookmarks_from_trunk1(&test_env, &source_git_repo_path);
|
||||
insta::assert_snapshot!(source_log, @r###"
|
||||
===== Source git repo contents =====
|
||||
@ c7d4bdcbc215 descr_for_b b
|
||||
|
|
@ -824,7 +824,7 @@ fn test_git_fetch_undo() {
|
|||
◆ 000000000000
|
||||
"###);
|
||||
|
||||
// Fetch 2 branches
|
||||
// Fetch 2 bookmarks
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(
|
||||
&target_jj_repo_path,
|
||||
&["git", "fetch", "--branch", "b", "--branch", "a1"],
|
||||
|
|
@ -851,7 +851,7 @@ fn test_git_fetch_undo() {
|
|||
@ 230dd059e1b0
|
||||
◆ 000000000000
|
||||
"###);
|
||||
// Now try to fetch just one branch
|
||||
// Now try to fetch just one bookmark
|
||||
let (stdout, stderr) =
|
||||
test_env.jj_cmd_ok(&target_jj_repo_path, &["git", "fetch", "--branch", "b"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
|
|
@ -887,7 +887,7 @@ fn test_fetch_undo_what() {
|
|||
let repo_path = test_env.env_root().join("target");
|
||||
|
||||
let source_log =
|
||||
create_colocated_repo_and_branches_from_trunk1(&test_env, &source_git_repo_path);
|
||||
create_colocated_repo_and_bookmarks_from_trunk1(&test_env, &source_git_repo_path);
|
||||
insta::assert_snapshot!(source_log, @r###"
|
||||
===== Source git repo contents =====
|
||||
@ c7d4bdcbc215 descr_for_b b
|
||||
|
|
@ -900,11 +900,11 @@ fn test_fetch_undo_what() {
|
|||
"###);
|
||||
|
||||
// Initial state we will try to return to after `op restore`. There are no
|
||||
// branches.
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @"");
|
||||
// bookmarks.
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @"");
|
||||
let base_operation_id = test_env.current_operation_id(&repo_path);
|
||||
|
||||
// Fetch a branch
|
||||
// Fetch a bookmark
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "fetch", "--branch", "b"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
|
|
@ -917,32 +917,33 @@ fn test_fetch_undo_what() {
|
|||
├─╯
|
||||
◆ 000000000000
|
||||
"###);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
b: vpupmnsl c7d4bdcb descr_for_b
|
||||
@origin: vpupmnsl c7d4bdcb descr_for_b
|
||||
"###);
|
||||
|
||||
// We can undo the change in the repo without moving the remote-tracking branch
|
||||
// We can undo the change in the repo without moving the remote-tracking
|
||||
// bookmark
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(
|
||||
&repo_path,
|
||||
&["op", "restore", "--what", "repo", &base_operation_id],
|
||||
);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
insta::assert_snapshot!(stderr, @"");
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
b (deleted)
|
||||
@origin: vpupmnsl hidden c7d4bdcb descr_for_b
|
||||
"###);
|
||||
|
||||
// Now, let's demo restoring just the remote-tracking branch. First, let's
|
||||
// Now, let's demo restoring just the remote-tracking bookmark. First, let's
|
||||
// change our local repo state...
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "c", "newbranch"]);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "c", "newbookmark"]);
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
b (deleted)
|
||||
@origin: vpupmnsl hidden c7d4bdcb descr_for_b
|
||||
newbranch: qpvuntsm 230dd059 (empty) (no description set)
|
||||
newbookmark: qpvuntsm 230dd059 (empty) (no description set)
|
||||
"###);
|
||||
// Restoring just the remote-tracking state will not affect `newbranch`, but
|
||||
// Restoring just the remote-tracking state will not affect `newbookmark`, but
|
||||
// will eliminate `b@origin`.
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(
|
||||
&repo_path,
|
||||
|
|
@ -956,8 +957,8 @@ fn test_fetch_undo_what() {
|
|||
);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
insta::assert_snapshot!(stderr, @"");
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
newbranch: qpvuntsm 230dd059 (empty) (no description set)
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
newbookmark: qpvuntsm 230dd059 (empty) (no description set)
|
||||
"###);
|
||||
}
|
||||
|
||||
|
|
@ -969,13 +970,13 @@ fn test_git_fetch_remove_fetch() {
|
|||
let repo_path = test_env.env_root().join("repo");
|
||||
add_git_remote(&test_env, &repo_path, "origin");
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "origin"]);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "origin"]);
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
origin: qpvuntsm 230dd059 (empty) (no description set)
|
||||
"###);
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "fetch"]);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
origin (conflicted):
|
||||
+ qpvuntsm 230dd059 (empty) (no description set)
|
||||
+ oputwtnw ffecd2d6 message
|
||||
|
|
@ -983,7 +984,7 @@ fn test_git_fetch_remove_fetch() {
|
|||
"###);
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "remote", "remove", "origin"]);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
origin (conflicted):
|
||||
+ qpvuntsm 230dd059 (empty) (no description set)
|
||||
+ oputwtnw ffecd2d6 message
|
||||
|
|
@ -997,7 +998,7 @@ fn test_git_fetch_remove_fetch() {
|
|||
insta::assert_snapshot!(stderr, @r###"
|
||||
branch: origin@origin [new] tracked
|
||||
"###);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
origin (conflicted):
|
||||
+ qpvuntsm 230dd059 (empty) (no description set)
|
||||
+ oputwtnw ffecd2d6 message
|
||||
|
|
@ -1013,13 +1014,13 @@ fn test_git_fetch_rename_fetch() {
|
|||
let repo_path = test_env.env_root().join("repo");
|
||||
add_git_remote(&test_env, &repo_path, "origin");
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "origin"]);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "origin"]);
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
origin: qpvuntsm 230dd059 (empty) (no description set)
|
||||
"###);
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "fetch"]);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
origin (conflicted):
|
||||
+ qpvuntsm 230dd059 (empty) (no description set)
|
||||
+ oputwtnw ffecd2d6 message
|
||||
|
|
@ -1030,7 +1031,7 @@ fn test_git_fetch_rename_fetch() {
|
|||
&repo_path,
|
||||
&["git", "remote", "rename", "origin", "upstream"],
|
||||
);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
origin (conflicted):
|
||||
+ qpvuntsm 230dd059 (empty) (no description set)
|
||||
+ oputwtnw ffecd2d6 message
|
||||
|
|
@ -1047,7 +1048,7 @@ fn test_git_fetch_rename_fetch() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_git_fetch_removed_branch() {
|
||||
fn test_git_fetch_removed_bookmark() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.add_config("git.auto-local-branch = true");
|
||||
let source_git_repo_path = test_env.env_root().join("source");
|
||||
|
|
@ -1064,7 +1065,7 @@ fn test_git_fetch_removed_branch() {
|
|||
let target_jj_repo_path = test_env.env_root().join("target");
|
||||
|
||||
let source_log =
|
||||
create_colocated_repo_and_branches_from_trunk1(&test_env, &source_git_repo_path);
|
||||
create_colocated_repo_and_bookmarks_from_trunk1(&test_env, &source_git_repo_path);
|
||||
insta::assert_snapshot!(source_log, @r###"
|
||||
===== Source git repo contents =====
|
||||
@ c7d4bdcbc215 descr_for_b b
|
||||
|
|
@ -1076,7 +1077,7 @@ fn test_git_fetch_removed_branch() {
|
|||
◆ 000000000000
|
||||
"###);
|
||||
|
||||
// Fetch all branches
|
||||
// Fetch all bookmarks
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&target_jj_repo_path, &["git", "fetch"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
|
|
@ -1097,10 +1098,10 @@ fn test_git_fetch_removed_branch() {
|
|||
◆ 000000000000
|
||||
"###);
|
||||
|
||||
// Remove a2 branch in origin
|
||||
test_env.jj_cmd_ok(&source_git_repo_path, &["branch", "forget", "a2"]);
|
||||
// Remove a2 bookmark in origin
|
||||
test_env.jj_cmd_ok(&source_git_repo_path, &["bookmark", "forget", "a2"]);
|
||||
|
||||
// Fetch branch a1 from origin and check that a2 is still there
|
||||
// Fetch bookmark a1 from origin and check that a2 is still there
|
||||
let (stdout, stderr) =
|
||||
test_env.jj_cmd_ok(&target_jj_repo_path, &["git", "fetch", "--branch", "a1"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
|
|
@ -1119,7 +1120,7 @@ fn test_git_fetch_removed_branch() {
|
|||
◆ 000000000000
|
||||
"###);
|
||||
|
||||
// Fetch branches a2 from origin, and check that it has been removed locally
|
||||
// Fetch bookmarks a2 from origin, and check that it has been removed locally
|
||||
let (stdout, stderr) =
|
||||
test_env.jj_cmd_ok(&target_jj_repo_path, &["git", "fetch", "--branch", "a2"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
|
|
@ -1139,7 +1140,7 @@ fn test_git_fetch_removed_branch() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_git_fetch_removed_parent_branch() {
|
||||
fn test_git_fetch_removed_parent_bookmark() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.add_config("git.auto-local-branch = true");
|
||||
let source_git_repo_path = test_env.env_root().join("source");
|
||||
|
|
@ -1156,7 +1157,7 @@ fn test_git_fetch_removed_parent_branch() {
|
|||
let target_jj_repo_path = test_env.env_root().join("target");
|
||||
|
||||
let source_log =
|
||||
create_colocated_repo_and_branches_from_trunk1(&test_env, &source_git_repo_path);
|
||||
create_colocated_repo_and_bookmarks_from_trunk1(&test_env, &source_git_repo_path);
|
||||
insta::assert_snapshot!(source_log, @r###"
|
||||
===== Source git repo contents =====
|
||||
@ c7d4bdcbc215 descr_for_b b
|
||||
|
|
@ -1168,7 +1169,7 @@ fn test_git_fetch_removed_parent_branch() {
|
|||
◆ 000000000000
|
||||
"###);
|
||||
|
||||
// Fetch all branches
|
||||
// Fetch all bookmarks
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&target_jj_repo_path, &["git", "fetch"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
|
|
@ -1189,11 +1190,11 @@ fn test_git_fetch_removed_parent_branch() {
|
|||
◆ 000000000000
|
||||
"###);
|
||||
|
||||
// Remove all branches in origin.
|
||||
test_env.jj_cmd_ok(&source_git_repo_path, &["branch", "forget", "glob:*"]);
|
||||
// Remove all bookmarks in origin.
|
||||
test_env.jj_cmd_ok(&source_git_repo_path, &["bookmark", "forget", "glob:*"]);
|
||||
|
||||
// Fetch branches master, trunk1 and a1 from origin and check that only those
|
||||
// branches have been removed and that others were not rebased because of
|
||||
// Fetch bookmarks master, trunk1 and a1 from origin and check that only those
|
||||
// bookmarks have been removed and that others were not rebased because of
|
||||
// abandoned commits.
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(
|
||||
&target_jj_repo_path,
|
||||
|
|
@ -1219,7 +1220,7 @@ fn test_git_fetch_removed_parent_branch() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_git_fetch_remote_only_branch() {
|
||||
fn test_git_fetch_remote_only_bookmark() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let repo_path = test_env.env_root().join("repo");
|
||||
|
|
@ -1240,7 +1241,7 @@ fn test_git_fetch_remote_only_branch() {
|
|||
&repo_path,
|
||||
&["git", "remote", "add", "origin", "../git-repo"],
|
||||
);
|
||||
// Create a commit and a branch in the git repo
|
||||
// Create a commit and a bookmark in the git repo
|
||||
git_repo
|
||||
.commit(
|
||||
Some("refs/heads/feature1"),
|
||||
|
|
@ -1252,10 +1253,10 @@ fn test_git_fetch_remote_only_branch() {
|
|||
)
|
||||
.unwrap();
|
||||
|
||||
// Fetch using git.auto_local_branch = true
|
||||
// Fetch using git.auto_local_bookmark = true
|
||||
test_env.add_config("git.auto-local-branch = true");
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "fetch", "--remote=origin"]);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
feature1: mzyxwzks 9f01a0e0 message
|
||||
@origin: mzyxwzks 9f01a0e0 message
|
||||
"###);
|
||||
|
|
@ -1271,7 +1272,7 @@ fn test_git_fetch_remote_only_branch() {
|
|||
)
|
||||
.unwrap();
|
||||
|
||||
// Fetch using git.auto_local_branch = false
|
||||
// Fetch using git.auto_local_bookmark = false
|
||||
test_env.add_config("git.auto-local-branch = false");
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "fetch", "--remote=origin"]);
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
|
||||
|
|
@ -1280,7 +1281,7 @@ fn test_git_fetch_remote_only_branch() {
|
|||
├─╯
|
||||
◆ 000000000000
|
||||
"###);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
feature1: mzyxwzks 9f01a0e0 message
|
||||
@origin: mzyxwzks 9f01a0e0 message
|
||||
feature2@origin: mzyxwzks 9f01a0e0 message
|
||||
|
|
|
|||
|
|
@ -19,20 +19,20 @@ use jj_lib::backend::CommitId;
|
|||
use crate::common::TestEnvironment;
|
||||
|
||||
#[test]
|
||||
fn test_resolution_of_git_tracking_branches() {
|
||||
fn test_resolution_of_git_tracking_bookmarks() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let repo_path = test_env.env_root().join("repo");
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "main"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "main"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["describe", "-r", "main", "-m", "old_message"]);
|
||||
|
||||
// Create local-git tracking branch
|
||||
// Create local-git tracking bookmark
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "export"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
insta::assert_snapshot!(stderr, @"");
|
||||
// Move the local branch somewhere else
|
||||
// Move the local bookmark somewhere else
|
||||
test_env.jj_cmd_ok(&repo_path, &["describe", "-r", "main", "-m", "new_message"]);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
main: qpvuntsm b61d21b6 (empty) new_message
|
||||
@git (ahead by 1 commits, behind by 1 commits): qpvuntsm hidden 03757d22 (empty) old_message
|
||||
"###);
|
||||
|
|
@ -51,8 +51,8 @@ fn test_resolution_of_git_tracking_branches() {
|
|||
insta::assert_snapshot!(query("main@git"), @r###"
|
||||
03757d2212d89990ec158e97795b612a38446652 old_message
|
||||
"###);
|
||||
// Can't be selected by remote_branches()
|
||||
insta::assert_snapshot!(query(r#"remote_branches(exact:"main", exact:"git")"#), @"");
|
||||
// Can't be selected by remote_bookmarks()
|
||||
insta::assert_snapshot!(query(r#"remote_bookmarks(exact:"main", exact:"git")"#), @"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -61,8 +61,8 @@ fn test_git_export_conflicting_git_refs() {
|
|||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let repo_path = test_env.env_root().join("repo");
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "main"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "main/sub"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "main"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "main/sub"]);
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "export"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
insta::with_settings!({filters => vec![("Failed to set: .*", "Failed to set: ...")]}, {
|
||||
|
|
@ -83,8 +83,8 @@ fn test_git_export_undo() {
|
|||
let repo_path = test_env.env_root().join("repo");
|
||||
let git_repo = git2::Repository::open(repo_path.join(".jj/repo/store/git")).unwrap();
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "a"]);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "a"]);
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
a: qpvuntsm 230dd059 (empty) (no description set)
|
||||
"###);
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "export"]);
|
||||
|
|
@ -97,7 +97,7 @@ fn test_git_export_undo() {
|
|||
"###);
|
||||
|
||||
// Exported refs won't be removed by undoing the export, but the git-tracking
|
||||
// branch is. This is the same as remote-tracking branches.
|
||||
// bookmark is. This is the same as remote-tracking bookmarks.
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["op", "undo"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
insta::assert_snapshot!(stderr, @"");
|
||||
|
|
@ -116,7 +116,7 @@ fn test_git_export_undo() {
|
|||
Hint: Did you mean "a"?
|
||||
"###);
|
||||
|
||||
// This would re-export branch "a" and create git-tracking branch.
|
||||
// This would re-export bookmark "a" and create git-tracking bookmark.
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "export"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
insta::assert_snapshot!(stderr, @"");
|
||||
|
|
@ -134,7 +134,7 @@ fn test_git_import_undo() {
|
|||
let repo_path = test_env.env_root().join("repo");
|
||||
let git_repo = git2::Repository::open(repo_path.join(".jj/repo/store/git")).unwrap();
|
||||
|
||||
// Create branch "a" in git repo
|
||||
// Create bookmark "a" in git repo
|
||||
let commit_id =
|
||||
test_env.jj_cmd_success(&repo_path, &["log", "-Tcommit_id", "--no-graph", "-r@"]);
|
||||
let commit = git_repo
|
||||
|
|
@ -142,8 +142,8 @@ fn test_git_import_undo() {
|
|||
.unwrap();
|
||||
git_repo.branch("a", &commit, true).unwrap();
|
||||
|
||||
// Initial state we will return to after `undo`. There are no branches.
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @"");
|
||||
// Initial state we will return to after `undo`. There are no bookmarks.
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @"");
|
||||
let base_operation_id = test_env.current_operation_id(&repo_path);
|
||||
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "import"]);
|
||||
|
|
@ -151,7 +151,7 @@ fn test_git_import_undo() {
|
|||
insta::assert_snapshot!(stderr, @r###"
|
||||
branch: a [new] tracked
|
||||
"###);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
a: qpvuntsm 230dd059 (empty) (no description set)
|
||||
@git: qpvuntsm 230dd059 (empty) (no description set)
|
||||
"###);
|
||||
|
|
@ -160,14 +160,14 @@ fn test_git_import_undo() {
|
|||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["op", "restore", &base_operation_id]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
insta::assert_snapshot!(stderr, @"");
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @"");
|
||||
// Try "git import" again, which should re-import the branch "a".
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @"");
|
||||
// Try "git import" again, which should re-import the bookmark "a".
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "import"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
branch: a [new] tracked
|
||||
"###);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
a: qpvuntsm 230dd059 (empty) (no description set)
|
||||
@git: qpvuntsm 230dd059 (empty) (no description set)
|
||||
"###);
|
||||
|
|
@ -180,7 +180,7 @@ fn test_git_import_move_export_with_default_undo() {
|
|||
let repo_path = test_env.env_root().join("repo");
|
||||
let git_repo = git2::Repository::open(repo_path.join(".jj/repo/store/git")).unwrap();
|
||||
|
||||
// Create branch "a" in git repo
|
||||
// Create bookmark "a" in git repo
|
||||
let commit_id =
|
||||
test_env.jj_cmd_success(&repo_path, &["log", "-Tcommit_id", "--no-graph", "-r@"]);
|
||||
let commit = git_repo
|
||||
|
|
@ -189,8 +189,8 @@ fn test_git_import_move_export_with_default_undo() {
|
|||
git_repo.branch("a", &commit, true).unwrap();
|
||||
|
||||
// Initial state we will try to return to after `op restore`. There are no
|
||||
// branches.
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @"");
|
||||
// bookmarks.
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @"");
|
||||
let base_operation_id = test_env.current_operation_id(&repo_path);
|
||||
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "import"]);
|
||||
|
|
@ -198,28 +198,28 @@ fn test_git_import_move_export_with_default_undo() {
|
|||
insta::assert_snapshot!(stderr, @r###"
|
||||
branch: a [new] tracked
|
||||
"###);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
a: qpvuntsm 230dd059 (empty) (no description set)
|
||||
@git: qpvuntsm 230dd059 (empty) (no description set)
|
||||
"###);
|
||||
|
||||
// Move branch "a" and export to git repo
|
||||
// Move bookmark "a" and export to git repo
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "set", "a"]);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "set", "a"]);
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
a: yqosqzyt 096dc80d (empty) (no description set)
|
||||
@git (behind by 1 commits): qpvuntsm 230dd059 (empty) (no description set)
|
||||
"###);
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "export"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
insta::assert_snapshot!(stderr, @"");
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
a: yqosqzyt 096dc80d (empty) (no description set)
|
||||
@git: yqosqzyt 096dc80d (empty) (no description set)
|
||||
"###);
|
||||
|
||||
// "git import" can be undone with the default `restore` behavior, as shown in
|
||||
// the previous test. However, "git export" can't: the branches in the git
|
||||
// the previous test. However, "git export" can't: the bookmarks in the git
|
||||
// repo stay where they were.
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["op", "restore", &base_operation_id]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
|
|
@ -227,7 +227,7 @@ fn test_git_import_move_export_with_default_undo() {
|
|||
Working copy now at: qpvuntsm 230dd059 (empty) (no description set)
|
||||
Parent commit : zzzzzzzz 00000000 (empty) (no description set)
|
||||
"###);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @"");
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @"");
|
||||
insta::assert_debug_snapshot!(get_git_repo_refs(&git_repo), @r###"
|
||||
[
|
||||
(
|
||||
|
|
@ -239,21 +239,21 @@ fn test_git_import_move_export_with_default_undo() {
|
|||
]
|
||||
"###);
|
||||
|
||||
// The last branch "a" state is imported from git. No idea what's the most
|
||||
// The last bookmark "a" state is imported from git. No idea what's the most
|
||||
// intuitive result here.
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "import"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
branch: a [new] tracked
|
||||
"###);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
a: yqosqzyt 096dc80d (empty) (no description set)
|
||||
@git: yqosqzyt 096dc80d (empty) (no description set)
|
||||
"###);
|
||||
}
|
||||
|
||||
fn get_branch_output(test_env: &TestEnvironment, repo_path: &Path) -> String {
|
||||
test_env.jj_cmd_success(repo_path, &["branch", "list", "--all-remotes"])
|
||||
fn get_bookmark_output(test_env: &TestEnvironment, repo_path: &Path) -> String {
|
||||
test_env.jj_cmd_success(repo_path, &["bookmark", "list", "--all-remotes"])
|
||||
}
|
||||
|
||||
fn get_git_repo_refs(git_repo: &git2::Repository) -> Vec<(String, CommitId)> {
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ fn init_git_repo_with_opts(
|
|||
.unwrap();
|
||||
git_repo
|
||||
.commit(
|
||||
Some("refs/heads/my-branch"),
|
||||
Some("refs/heads/my-bookmark"),
|
||||
&git_signature,
|
||||
&git_signature,
|
||||
"My commit message",
|
||||
|
|
@ -55,16 +55,16 @@ fn init_git_repo_with_opts(
|
|||
)
|
||||
.unwrap();
|
||||
drop(git_tree);
|
||||
git_repo.set_head("refs/heads/my-branch").unwrap();
|
||||
git_repo.set_head("refs/heads/my-bookmark").unwrap();
|
||||
git_repo
|
||||
}
|
||||
|
||||
fn get_branch_output(test_env: &TestEnvironment, repo_path: &Path) -> String {
|
||||
test_env.jj_cmd_success(repo_path, &["branch", "list", "--all-remotes"])
|
||||
fn get_bookmark_output(test_env: &TestEnvironment, repo_path: &Path) -> String {
|
||||
test_env.jj_cmd_success(repo_path, &["bookmark", "list", "--all-remotes"])
|
||||
}
|
||||
|
||||
fn get_log_output(test_env: &TestEnvironment, workspace_root: &Path) -> String {
|
||||
let template = r#"separate(" ", commit_id.short(), branches, git_head, description)"#;
|
||||
let template = r#"separate(" ", commit_id.short(), bookmarks, git_head, description)"#;
|
||||
test_env.jj_cmd_success(workspace_root, &["log", "-T", template, "-r=all()"])
|
||||
}
|
||||
|
||||
|
|
@ -144,7 +144,7 @@ fn test_git_init_external(bare: bool) {
|
|||
insta::assert_snapshot!(stderr, @r###"
|
||||
Done importing changes from the underlying Git repo.
|
||||
Working copy now at: sqpuoqvx f6950fc1 (empty) (no description set)
|
||||
Parent commit : mwrttmos 8d698d4a my-branch | My commit message
|
||||
Parent commit : mwrttmos 8d698d4a my-bookmark | My commit message
|
||||
Added 1 files, modified 0 files, removed 0 files
|
||||
Initialized repo in "repo"
|
||||
"###);
|
||||
|
|
@ -170,7 +170,7 @@ fn test_git_init_external(bare: bool) {
|
|||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
|
||||
@ f6950fc115ae
|
||||
○ 8d698d4a8ee1 my-branch HEAD@git My commit message
|
||||
○ 8d698d4a8ee1 my-bookmark HEAD@git My commit message
|
||||
◆ 000000000000
|
||||
"###);
|
||||
}
|
||||
|
|
@ -183,9 +183,9 @@ fn test_git_init_external_import_trunk(bare: bool) {
|
|||
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"
|
||||
// Add remote bookmark "trunk" for remote "origin", and set it as "origin/HEAD"
|
||||
let oid = git_repo
|
||||
.find_reference("refs/heads/my-branch")
|
||||
.find_reference("refs/heads/my-bookmark")
|
||||
.unwrap()
|
||||
.target()
|
||||
.unwrap();
|
||||
|
|
@ -217,13 +217,13 @@ fn test_git_init_external_import_trunk(bare: bool) {
|
|||
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
|
||||
Parent commit : mwrttmos 8d698d4a my-bookmark 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"
|
||||
// "trunk()" alias should be set to remote "origin"'s default bookmark "trunk"
|
||||
let stdout = test_env.jj_cmd_success(
|
||||
&test_env.env_root().join("repo"),
|
||||
&["config", "list", "--repo", "revset-aliases.\"trunk()\""],
|
||||
|
|
@ -344,7 +344,7 @@ fn test_git_init_colocated_via_git_repo_path() {
|
|||
// Check that the Git repo's HEAD got checked out
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
|
||||
@ f61b77cd4bb5
|
||||
○ 8d698d4a8ee1 my-branch HEAD@git My commit message
|
||||
○ 8d698d4a8ee1 my-bookmark HEAD@git My commit message
|
||||
◆ 000000000000
|
||||
"###);
|
||||
|
||||
|
|
@ -353,7 +353,7 @@ fn test_git_init_colocated_via_git_repo_path() {
|
|||
insta::assert_snapshot!(get_log_output(&test_env, &workspace_root), @r###"
|
||||
@ f1c7aa7c62d8
|
||||
○ f61b77cd4bb5 HEAD@git
|
||||
○ 8d698d4a8ee1 my-branch My commit message
|
||||
○ 8d698d4a8ee1 my-bookmark My commit message
|
||||
◆ 000000000000
|
||||
"###);
|
||||
}
|
||||
|
|
@ -380,7 +380,7 @@ fn test_git_init_colocated_via_git_repo_path_gitlink() {
|
|||
// Check that the Git repo's HEAD got checked out
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &workspace_root), @r###"
|
||||
@ f61b77cd4bb5
|
||||
○ 8d698d4a8ee1 my-branch HEAD@git My commit message
|
||||
○ 8d698d4a8ee1 my-bookmark HEAD@git My commit message
|
||||
◆ 000000000000
|
||||
"###);
|
||||
|
||||
|
|
@ -389,7 +389,7 @@ fn test_git_init_colocated_via_git_repo_path_gitlink() {
|
|||
insta::assert_snapshot!(get_log_output(&test_env, &workspace_root), @r###"
|
||||
@ f1c7aa7c62d8
|
||||
○ f61b77cd4bb5 HEAD@git
|
||||
○ 8d698d4a8ee1 my-branch My commit message
|
||||
○ 8d698d4a8ee1 my-bookmark My commit message
|
||||
◆ 000000000000
|
||||
"###);
|
||||
}
|
||||
|
|
@ -415,7 +415,7 @@ fn test_git_init_colocated_via_git_repo_path_symlink_directory() {
|
|||
// Check that the Git repo's HEAD got checked out
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &workspace_root), @r###"
|
||||
@ f61b77cd4bb5
|
||||
○ 8d698d4a8ee1 my-branch HEAD@git My commit message
|
||||
○ 8d698d4a8ee1 my-bookmark HEAD@git My commit message
|
||||
◆ 000000000000
|
||||
"###);
|
||||
|
||||
|
|
@ -424,7 +424,7 @@ fn test_git_init_colocated_via_git_repo_path_symlink_directory() {
|
|||
insta::assert_snapshot!(get_log_output(&test_env, &workspace_root), @r###"
|
||||
@ f1c7aa7c62d8
|
||||
○ f61b77cd4bb5 HEAD@git
|
||||
○ 8d698d4a8ee1 my-branch My commit message
|
||||
○ 8d698d4a8ee1 my-bookmark My commit message
|
||||
◆ 000000000000
|
||||
"###);
|
||||
}
|
||||
|
|
@ -453,7 +453,7 @@ fn test_git_init_colocated_via_git_repo_path_symlink_directory_without_bare_conf
|
|||
// Check that the Git repo's HEAD got checked out
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &workspace_root), @r###"
|
||||
@ f61b77cd4bb5
|
||||
○ 8d698d4a8ee1 my-branch HEAD@git My commit message
|
||||
○ 8d698d4a8ee1 my-bookmark HEAD@git My commit message
|
||||
◆ 000000000000
|
||||
"###);
|
||||
|
||||
|
|
@ -462,7 +462,7 @@ fn test_git_init_colocated_via_git_repo_path_symlink_directory_without_bare_conf
|
|||
insta::assert_snapshot!(get_log_output(&test_env, &workspace_root), @r###"
|
||||
@ f1c7aa7c62d8
|
||||
○ f61b77cd4bb5 HEAD@git
|
||||
○ 8d698d4a8ee1 my-branch My commit message
|
||||
○ 8d698d4a8ee1 my-bookmark My commit message
|
||||
◆ 000000000000
|
||||
"###);
|
||||
}
|
||||
|
|
@ -493,7 +493,7 @@ fn test_git_init_colocated_via_git_repo_path_symlink_gitlink() {
|
|||
// Check that the Git repo's HEAD got checked out
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &workspace_root), @r###"
|
||||
@ f61b77cd4bb5
|
||||
○ 8d698d4a8ee1 my-branch HEAD@git My commit message
|
||||
○ 8d698d4a8ee1 my-bookmark HEAD@git My commit message
|
||||
◆ 000000000000
|
||||
"###);
|
||||
|
||||
|
|
@ -502,7 +502,7 @@ fn test_git_init_colocated_via_git_repo_path_symlink_gitlink() {
|
|||
insta::assert_snapshot!(get_log_output(&test_env, &workspace_root), @r###"
|
||||
@ f1c7aa7c62d8
|
||||
○ f61b77cd4bb5 HEAD@git
|
||||
○ 8d698d4a8ee1 my-branch My commit message
|
||||
○ 8d698d4a8ee1 my-bookmark My commit message
|
||||
◆ 000000000000
|
||||
"###);
|
||||
}
|
||||
|
|
@ -517,7 +517,7 @@ fn test_git_init_colocated_via_git_repo_path_imported_refs() {
|
|||
let remote_path = test_env.env_root().join("remote");
|
||||
test_env.jj_cmd_ok(
|
||||
&remote_path,
|
||||
&["branch", "create", "local-remote", "remote-only"],
|
||||
&["bookmark", "create", "local-remote", "remote-only"],
|
||||
);
|
||||
test_env.jj_cmd_ok(&remote_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&remote_path, &["git", "export"]);
|
||||
|
|
@ -547,7 +547,7 @@ fn test_git_init_colocated_via_git_repo_path_imported_refs() {
|
|||
Done importing changes from the underlying Git repo.
|
||||
Initialized repo in "."
|
||||
"###);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &local_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &local_path), @r###"
|
||||
local-remote: vvkvtnvv 230dd059 (empty) (no description set)
|
||||
@git: vvkvtnvv 230dd059 (empty) (no description set)
|
||||
@origin: vvkvtnvv 230dd059 (empty) (no description set)
|
||||
|
|
@ -563,12 +563,12 @@ fn test_git_init_colocated_via_git_repo_path_imported_refs() {
|
|||
let (_stdout, stderr) = test_env.jj_cmd_ok(&local_path, &["git", "init", "--git-repo=."]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Done importing changes from the underlying Git repo.
|
||||
Hint: The following remote branches aren't associated with the existing local branches:
|
||||
Hint: The following remote bookmarks aren't associated with the existing local bookmarks:
|
||||
local-remote@origin
|
||||
Hint: Run `jj branch track local-remote@origin` to keep local branches updated on future pulls.
|
||||
Hint: Run `jj bookmark track local-remote@origin` to keep local bookmarks updated on future pulls.
|
||||
Initialized repo in "."
|
||||
"###);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &local_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &local_path), @r###"
|
||||
local-remote: vvkvtnvv 230dd059 (empty) (no description set)
|
||||
@git: vvkvtnvv 230dd059 (empty) (no description set)
|
||||
local-remote@origin: vvkvtnvv 230dd059 (empty) (no description set)
|
||||
|
|
@ -620,7 +620,7 @@ fn test_git_init_colocated_dirty_working_copy() {
|
|||
│ C {some-file => new-staged-file}
|
||||
│ M some-file
|
||||
│ C {some-file => unstaged-file}
|
||||
○ mwrttmos git.user@example.com 1970-01-01 11:02:03 my-branch HEAD@git 8d698d4a
|
||||
○ mwrttmos git.user@example.com 1970-01-01 11:02:03 my-bookmark HEAD@git 8d698d4a
|
||||
│ My commit message
|
||||
│ A some-file
|
||||
◆ zzzzzzzz root() 00000000
|
||||
|
|
@ -719,7 +719,7 @@ fn test_git_init_colocated_via_flag_git_dir_exists() {
|
|||
// Check that the Git repo's HEAD got checked out
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &workspace_root), @r###"
|
||||
@ f61b77cd4bb5
|
||||
○ 8d698d4a8ee1 my-branch HEAD@git My commit message
|
||||
○ 8d698d4a8ee1 my-bookmark HEAD@git My commit message
|
||||
◆ 000000000000
|
||||
"###);
|
||||
|
||||
|
|
@ -728,7 +728,7 @@ fn test_git_init_colocated_via_flag_git_dir_exists() {
|
|||
insta::assert_snapshot!(get_log_output(&test_env, &workspace_root), @r###"
|
||||
@ f1c7aa7c62d8
|
||||
○ f61b77cd4bb5 HEAD@git
|
||||
○ 8d698d4a8ee1 my-branch My commit message
|
||||
○ 8d698d4a8ee1 my-bookmark My commit message
|
||||
◆ 000000000000
|
||||
"###);
|
||||
}
|
||||
|
|
@ -749,10 +749,10 @@ fn test_git_init_colocated_via_flag_git_dir_not_exists() {
|
|||
◆ 000000000000
|
||||
"###);
|
||||
|
||||
// Create the default branch (create both in case we change the default)
|
||||
test_env.jj_cmd_ok(&workspace_root, &["branch", "create", "main", "master"]);
|
||||
// Create the default bookmark (create both in case we change the default)
|
||||
test_env.jj_cmd_ok(&workspace_root, &["bookmark", "create", "main", "master"]);
|
||||
|
||||
// If .git/HEAD pointed to the default branch, new working-copy commit would
|
||||
// If .git/HEAD pointed to the default bookmark, new working-copy commit would
|
||||
// be created on top.
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &workspace_root), @r###"
|
||||
@ 230dd059e1b0 main master
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ fn set_up() -> (TestEnvironment, PathBuf) {
|
|||
|
||||
test_env.jj_cmd_ok(&origin_path, &["describe", "-m=public 1"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["new", "-m=public 2"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["branch", "create", "main"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["bookmark", "create", "main"]);
|
||||
test_env.jj_cmd_ok(&origin_path, &["git", "export"]);
|
||||
|
||||
test_env.jj_cmd_ok(
|
||||
|
|
@ -76,7 +76,7 @@ fn test_git_private_commits_block_pushing() {
|
|||
let (test_env, workspace_root) = set_up();
|
||||
|
||||
test_env.jj_cmd_ok(&workspace_root, &["new", "main", "-m=private 1"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["branch", "set", "main"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["bookmark", "set", "main"]);
|
||||
|
||||
// Will not push when a pushed commit is contained in git.private-commits
|
||||
test_env.add_config(r#"git.private-commits = "description(glob:'private*')""#);
|
||||
|
|
@ -90,7 +90,7 @@ fn test_git_private_commits_block_pushing() {
|
|||
let (_, stderr) = test_env.jj_cmd_ok(&workspace_root, &["git", "push", "--all"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Branch changes to push to origin:
|
||||
Move forward branch main from 7eb97bf230ad to aa3058ff8663
|
||||
Move forward bookmark main from 7eb97bf230ad to aa3058ff8663
|
||||
Warning: The working-copy commit in workspace 'default' became immutable, so a new commit has been created on top of it.
|
||||
Working copy now at: znkkpsqq 2e1adf47 (empty) (no description set)
|
||||
Parent commit : yqosqzyt aa3058ff main | (empty) private 1
|
||||
|
|
@ -102,7 +102,7 @@ fn test_git_private_commits_can_be_overridden() {
|
|||
let (test_env, workspace_root) = set_up();
|
||||
|
||||
test_env.jj_cmd_ok(&workspace_root, &["new", "main", "-m=private 1"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["branch", "set", "main"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["bookmark", "set", "main"]);
|
||||
|
||||
// Will not push when a pushed commit is contained in git.private-commits
|
||||
test_env.add_config(r#"git.private-commits = "description(glob:'private*')""#);
|
||||
|
|
@ -118,7 +118,7 @@ fn test_git_private_commits_can_be_overridden() {
|
|||
);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Branch changes to push to origin:
|
||||
Move forward branch main from 7eb97bf230ad to aa3058ff8663
|
||||
Move forward bookmark main from 7eb97bf230ad to aa3058ff8663
|
||||
Warning: The working-copy commit in workspace 'default' became immutable, so a new commit has been created on top of it.
|
||||
Working copy now at: znkkpsqq 2e1adf47 (empty) (no description set)
|
||||
Parent commit : yqosqzyt aa3058ff main | (empty) private 1
|
||||
|
|
@ -130,14 +130,14 @@ fn test_git_private_commits_are_not_checked_if_immutable() {
|
|||
let (test_env, workspace_root) = set_up();
|
||||
|
||||
test_env.jj_cmd_ok(&workspace_root, &["new", "main", "-m=private 1"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["branch", "set", "main"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["bookmark", "set", "main"]);
|
||||
|
||||
test_env.add_config(r#"git.private-commits = "description(glob:'private*')""#);
|
||||
test_env.add_config(r#"revset-aliases."immutable_heads()" = "all()""#);
|
||||
let (_, stderr) = test_env.jj_cmd_ok(&workspace_root, &["git", "push", "--all"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Branch changes to push to origin:
|
||||
Move forward branch main from 7eb97bf230ad to aa3058ff8663
|
||||
Move forward bookmark main from 7eb97bf230ad to aa3058ff8663
|
||||
Warning: The working-copy commit in workspace 'default' became immutable, so a new commit has been created on top of it.
|
||||
Working copy now at: yostqsxw dce4a15c (empty) (no description set)
|
||||
Parent commit : yqosqzyt aa3058ff main | (empty) private 1
|
||||
|
|
@ -152,10 +152,10 @@ fn test_git_private_commits_not_directly_in_line_block_pushing() {
|
|||
test_env.jj_cmd_ok(&workspace_root, &["new", "root()", "-m=private 1"]);
|
||||
|
||||
test_env.jj_cmd_ok(&workspace_root, &["new", "main", "@", "-m=public 3"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["branch", "create", "branch1"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["bookmark", "create", "bookmark1"]);
|
||||
|
||||
test_env.add_config(r#"git.private-commits = "description(glob:'private*')""#);
|
||||
let stderr = test_env.jj_cmd_failure(&workspace_root, &["git", "push", "-b=branch1"]);
|
||||
let stderr = test_env.jj_cmd_failure(&workspace_root, &["git", "push", "-b=bookmark1"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Error: Won't push commit f1253a9b1ea9 since it is private
|
||||
"###);
|
||||
|
|
@ -166,14 +166,14 @@ fn test_git_private_commits_descending_from_commits_pushed_do_not_block_pushing(
|
|||
let (test_env, workspace_root) = set_up();
|
||||
|
||||
test_env.jj_cmd_ok(&workspace_root, &["new", "main", "-m=public 3"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["branch", "move", "main"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["bookmark", "move", "main"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["new", "-m=private 1"]);
|
||||
|
||||
test_env.add_config(r#"git.private-commits = "description(glob:'private*')""#);
|
||||
let (_, stderr) = test_env.jj_cmd_ok(&workspace_root, &["git", "push", "-b=main"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Branch changes to push to origin:
|
||||
Move forward branch main from 7eb97bf230ad to 05ef53bc99ec
|
||||
Move forward bookmark main from 7eb97bf230ad to 05ef53bc99ec
|
||||
"###);
|
||||
}
|
||||
|
||||
|
|
@ -181,20 +181,23 @@ fn test_git_private_commits_descending_from_commits_pushed_do_not_block_pushing(
|
|||
fn test_git_private_commits_already_on_the_remote_do_not_block_push() {
|
||||
let (test_env, workspace_root) = set_up();
|
||||
|
||||
// Start a branch before a "private" commit lands in main
|
||||
test_env.jj_cmd_ok(&workspace_root, &["branch", "create", "branch1", "-r=main"]);
|
||||
// Start a bookmark before a "private" commit lands in main
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_root,
|
||||
&["bookmark", "create", "bookmark1", "-r=main"],
|
||||
);
|
||||
|
||||
// Push a commit that would become a private_root if it weren't already on
|
||||
// the remote
|
||||
test_env.jj_cmd_ok(&workspace_root, &["new", "main", "-m=private 1"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["new", "-m=public 3"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["branch", "set", "main"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["bookmark", "set", "main"]);
|
||||
let (_, stderr) =
|
||||
test_env.jj_cmd_ok(&workspace_root, &["git", "push", "-b=main", "-b=branch1"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["git", "push", "-b=main", "-b=bookmark1"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Branch changes to push to origin:
|
||||
Move forward branch main from 7eb97bf230ad to fbb352762352
|
||||
Add branch branch1 to 7eb97bf230ad
|
||||
Move forward bookmark main from 7eb97bf230ad to fbb352762352
|
||||
Add bookmark bookmark1 to 7eb97bf230ad
|
||||
Warning: The working-copy commit in workspace 'default' became immutable, so a new commit has been created on top of it.
|
||||
Working copy now at: kpqxywon a7b08364 (empty) (no description set)
|
||||
Parent commit : yostqsxw fbb35276 main | (empty) public 3
|
||||
|
|
@ -203,24 +206,27 @@ fn test_git_private_commits_already_on_the_remote_do_not_block_push() {
|
|||
test_env.add_config(r#"git.private-commits = "description(glob:'private*')""#);
|
||||
|
||||
// Since "private 1" is already on the remote, pushing it should be allowed
|
||||
test_env.jj_cmd_ok(&workspace_root, &["branch", "set", "branch1", "-r=main"]);
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_root,
|
||||
&["bookmark", "set", "bookmark1", "-r=main"],
|
||||
);
|
||||
let (_, stderr) = test_env.jj_cmd_ok(&workspace_root, &["git", "push", "--all"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Branch changes to push to origin:
|
||||
Move forward branch branch1 from 7eb97bf230ad to fbb352762352
|
||||
Move forward bookmark bookmark1 from 7eb97bf230ad to fbb352762352
|
||||
"###);
|
||||
|
||||
// Ensure that the already-pushed commit doesn't block a new branch from
|
||||
// Ensure that the already-pushed commit doesn't block a new bookmark from
|
||||
// being pushed
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_root,
|
||||
&["new", "description('private 1')", "-m=public 4"],
|
||||
);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["branch", "create", "branch2"]);
|
||||
let (_, stderr) = test_env.jj_cmd_ok(&workspace_root, &["git", "push", "-b=branch2"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["bookmark", "create", "bookmark2"]);
|
||||
let (_, stderr) = test_env.jj_cmd_ok(&workspace_root, &["git", "push", "-b=bookmark2"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Branch changes to push to origin:
|
||||
Add branch branch2 to ee5b808b0b95
|
||||
Add bookmark bookmark2 to ee5b808b0b95
|
||||
"###);
|
||||
}
|
||||
|
||||
|
|
@ -234,11 +240,11 @@ fn test_git_private_commits_are_evaluated_separately_for_each_remote() {
|
|||
// the remote
|
||||
test_env.jj_cmd_ok(&workspace_root, &["new", "main", "-m=private 1"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["new", "-m=public 3"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["branch", "set", "main"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["bookmark", "set", "main"]);
|
||||
let (_, stderr) = test_env.jj_cmd_ok(&workspace_root, &["git", "push", "-b=main"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Branch changes to push to origin:
|
||||
Move forward branch main from 7eb97bf230ad to d8632ce893ab
|
||||
Move forward bookmark main from 7eb97bf230ad to d8632ce893ab
|
||||
"###);
|
||||
|
||||
test_env.add_config(r#"git.private-commits = "description(glob:'private*')""#);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -192,7 +192,7 @@ fn test_git_remote_named_git() {
|
|||
.remote("git", "http://example.com/repo/repo")
|
||||
.unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "init", "--git-repo=."]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "main"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "main"]);
|
||||
|
||||
// The remote can be renamed.
|
||||
let (stdout, stderr) =
|
||||
|
|
@ -203,8 +203,8 @@ fn test_git_remote_named_git() {
|
|||
insta::assert_snapshot!(stdout, @r###"
|
||||
bar http://example.com/repo/repo
|
||||
"###);
|
||||
// @git branch shouldn't be renamed.
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["log", "-rmain@git", "-Tbranches"]);
|
||||
// @git bookmark shouldn't be renamed.
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["log", "-rmain@git", "-Tbookmarks"]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
@ main
|
||||
│
|
||||
|
|
@ -229,8 +229,8 @@ fn test_git_remote_named_git() {
|
|||
let stdout = test_env.jj_cmd_success(&repo_path, &["git", "remote", "list"]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
"###);
|
||||
// @git branch shouldn't be removed.
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["log", "-rmain@git", "-Tbranches"]);
|
||||
// @git bookmark shouldn't be removed.
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["log", "-rmain@git", "-Tbookmarks"]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
○ main
|
||||
│
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ fn test_gitignores_ignored_file_in_target_commit() {
|
|||
|
||||
// Create a commit with file "ignored" in it
|
||||
std::fs::write(workspace_root.join("ignored"), "committed contents\n").unwrap();
|
||||
test_env.jj_cmd_ok(&workspace_root, &["branch", "create", "with-file"]);
|
||||
test_env.jj_cmd_ok(&workspace_root, &["bookmark", "create", "with-file"]);
|
||||
let target_commit_id = test_env.jj_cmd_success(
|
||||
&workspace_root,
|
||||
&["log", "--no-graph", "-T=commit_id", "-r=@"],
|
||||
|
|
|
|||
|
|
@ -89,9 +89,9 @@ fn test_no_subcommand() {
|
|||
assert_eq!(stdout, test_env.jj_cmd_success(&repo_path, &["log"]));
|
||||
|
||||
// Command argument that looks like a command name.
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "help"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "log"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "show"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "help"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "log"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "show"]);
|
||||
// TODO: test_env.jj_cmd_ok(&repo_path, &["-r", "help"])
|
||||
insta::assert_snapshot!(test_env.jj_cmd_success(&repo_path, &["-r", "log"]), @r###"
|
||||
@ qpvuntsm test.user@example.com 2001-02-03 08:05:07 help log show 230dd059
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ fn test_rewrite_immutable_generic() {
|
|||
test_env.jj_cmd_ok(&repo_path, &["describe", "-m=a"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-m=b"]);
|
||||
std::fs::write(repo_path.join("file"), "b").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "main"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "main"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "main-", "-m=c"]);
|
||||
std::fs::write(repo_path.join("file"), "c").unwrap();
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["log"]);
|
||||
|
|
@ -59,11 +59,11 @@ fn test_rewrite_immutable_generic() {
|
|||
|
||||
// Error mutating the repo if immutable_heads() uses a ref that can't be
|
||||
// resolved
|
||||
test_env.add_config(r#"revset-aliases."immutable_heads()" = "branch_that_does_not_exist""#);
|
||||
test_env.add_config(r#"revset-aliases."immutable_heads()" = "bookmark_that_does_not_exist""#);
|
||||
let stderr = test_env.jj_cmd_failure(&repo_path, &["new", "main"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Config error: Invalid `revset-aliases.immutable_heads()`
|
||||
Caused by: Revision "branch_that_does_not_exist" doesn't exist
|
||||
Caused by: Revision "bookmark_that_does_not_exist" doesn't exist
|
||||
For help, see https://martinvonz.github.io/jj/latest/config/.
|
||||
"###);
|
||||
|
||||
|
|
@ -85,7 +85,7 @@ fn test_rewrite_immutable_generic() {
|
|||
|
||||
// Mutating the repo works if ref is wrapped in present()
|
||||
test_env.add_config(
|
||||
r#"revset-aliases."immutable_heads()" = "present(branch_that_does_not_exist)""#,
|
||||
r#"revset-aliases."immutable_heads()" = "present(bookmark_that_does_not_exist)""#,
|
||||
);
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["new", "main"]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
|
|
@ -107,12 +107,12 @@ fn test_rewrite_immutable_generic() {
|
|||
fn test_new_wc_commit_when_wc_immutable() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init"]);
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["branch", "create", "main"]);
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["bookmark", "create", "main"]);
|
||||
test_env.add_config(r#"revset-aliases."immutable_heads()" = "main""#);
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["new", "-m=a"]);
|
||||
let (_, stderr) = test_env.jj_cmd_ok(test_env.env_root(), &["branch", "set", "main"]);
|
||||
let (_, stderr) = test_env.jj_cmd_ok(test_env.env_root(), &["bookmark", "set", "main"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Moved 1 branches to kkmpptxz a164195b main | (empty) a
|
||||
Moved 1 bookmarks to kkmpptxz a164195b main | (empty) a
|
||||
Warning: The working-copy commit in workspace 'default' became immutable, so a new commit has been created on top of it.
|
||||
Working copy now at: zsuskuln ef5fa85b (empty) (no description set)
|
||||
Parent commit : kkmpptxz a164195b main | (empty) a
|
||||
|
|
@ -123,7 +123,7 @@ fn test_new_wc_commit_when_wc_immutable() {
|
|||
fn test_immutable_heads_set_to_working_copy() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init"]);
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["branch", "create", "main"]);
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["bookmark", "create", "main"]);
|
||||
test_env.add_config(r#"revset-aliases."immutable_heads()" = "@""#);
|
||||
let (_, stderr) = test_env.jj_cmd_ok(test_env.env_root(), &["new", "-m=a"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
|
|
@ -138,15 +138,15 @@ fn test_new_wc_commit_when_wc_immutable_multi_workspace() {
|
|||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let repo_path = test_env.env_root().join("repo");
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "main"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "main"]);
|
||||
test_env.add_config(r#"revset-aliases."immutable_heads()" = "main""#);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-m=a"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["workspace", "add", "../workspace1"]);
|
||||
let workspace1_envroot = test_env.env_root().join("workspace1");
|
||||
test_env.jj_cmd_ok(&workspace1_envroot, &["edit", "default@"]);
|
||||
let (_, stderr) = test_env.jj_cmd_ok(&repo_path, &["branch", "set", "main"]);
|
||||
let (_, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "set", "main"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Moved 1 branches to kkmpptxz 7796c4df main | (empty) a
|
||||
Moved 1 bookmarks to kkmpptxz 7796c4df main | (empty) a
|
||||
Warning: The working-copy commit in workspace 'default' became immutable, so a new commit has been created on top of it.
|
||||
Warning: The working-copy commit in workspace 'workspace1' became immutable, so a new commit has been created on top of it.
|
||||
Working copy now at: royxmykx 896465c4 (empty) (no description set)
|
||||
|
|
@ -180,7 +180,7 @@ fn test_rewrite_immutable_commands() {
|
|||
// Create another file to make sure the merge commit isn't empty (to satisfy `jj
|
||||
// split`) and still has a conflict (to satisfy `jj resolve`).
|
||||
std::fs::write(repo_path.join("file2"), "merged").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "main"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "main"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "description(b)"]);
|
||||
test_env.add_config(r#"revset-aliases."immutable_heads()" = "main""#);
|
||||
test_env.add_config(r#"revset-aliases."trunk()" = "main""#);
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ fn init_git_repo_with_opts(
|
|||
.unwrap();
|
||||
git_repo
|
||||
.commit(
|
||||
Some("refs/heads/my-branch"),
|
||||
Some("refs/heads/my-bookmark"),
|
||||
&git_signature,
|
||||
&git_signature,
|
||||
"My commit message",
|
||||
|
|
@ -54,12 +54,12 @@ fn init_git_repo_with_opts(
|
|||
)
|
||||
.unwrap();
|
||||
drop(git_tree);
|
||||
git_repo.set_head("refs/heads/my-branch").unwrap();
|
||||
git_repo.set_head("refs/heads/my-bookmark").unwrap();
|
||||
git_repo
|
||||
}
|
||||
|
||||
fn get_branch_output(test_env: &TestEnvironment, repo_path: &Path) -> String {
|
||||
test_env.jj_cmd_success(repo_path, &["branch", "list", "--all-remotes"])
|
||||
fn get_bookmark_output(test_env: &TestEnvironment, repo_path: &Path) -> String {
|
||||
test_env.jj_cmd_success(repo_path, &["bookmark", "list", "--all-remotes"])
|
||||
}
|
||||
|
||||
fn read_git_target(workspace_root: &Path) -> String {
|
||||
|
|
@ -113,7 +113,7 @@ fn test_init_git_external(bare: bool) {
|
|||
insta::assert_snapshot!(stderr, @r###"
|
||||
Done importing changes from the underlying Git repo.
|
||||
Working copy now at: sqpuoqvx f6950fc1 (empty) (no description set)
|
||||
Parent commit : mwrttmos 8d698d4a my-branch | My commit message
|
||||
Parent commit : mwrttmos 8d698d4a my-bookmark | My commit message
|
||||
Added 1 files, modified 0 files, removed 0 files
|
||||
Warning: `--git` and `--git-repo` are deprecated.
|
||||
Use `jj git init` instead
|
||||
|
|
@ -141,7 +141,7 @@ fn test_init_git_external(bare: bool) {
|
|||
let stdout = test_env.jj_cmd_success(&repo_path, &["log", "-r", "@-"]);
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
○ mwrttmos git.user@example.com 1970-01-01 11:02:03 my-branch HEAD@git 8d698d4a
|
||||
○ mwrttmos git.user@example.com 1970-01-01 11:02:03 my-bookmark HEAD@git 8d698d4a
|
||||
│ My commit message
|
||||
~
|
||||
"###);
|
||||
|
|
@ -209,7 +209,7 @@ fn test_init_git_colocated() {
|
|||
// Check that the Git repo's HEAD got checked out
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["log", "-r", "@-"]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
○ mwrttmos git.user@example.com 1970-01-01 11:02:03 my-branch HEAD@git 8d698d4a
|
||||
○ mwrttmos git.user@example.com 1970-01-01 11:02:03 my-bookmark HEAD@git 8d698d4a
|
||||
│ My commit message
|
||||
~
|
||||
"###);
|
||||
|
|
@ -248,7 +248,7 @@ fn test_init_git_colocated_gitlink() {
|
|||
// Check that the Git repo's HEAD got checked out
|
||||
let stdout = test_env.jj_cmd_success(&workspace_root, &["log", "-r", "@-"]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
○ mwrttmos git.user@example.com 1970-01-01 11:02:03 my-branch HEAD@git 8d698d4a
|
||||
○ mwrttmos git.user@example.com 1970-01-01 11:02:03 my-bookmark HEAD@git 8d698d4a
|
||||
│ My commit message
|
||||
~
|
||||
"###);
|
||||
|
|
@ -286,7 +286,7 @@ fn test_init_git_colocated_symlink_directory() {
|
|||
// Check that the Git repo's HEAD got checked out
|
||||
let stdout = test_env.jj_cmd_success(&workspace_root, &["log", "-r", "@-"]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
○ mwrttmos git.user@example.com 1970-01-01 11:02:03 my-branch HEAD@git 8d698d4a
|
||||
○ mwrttmos git.user@example.com 1970-01-01 11:02:03 my-bookmark HEAD@git 8d698d4a
|
||||
│ My commit message
|
||||
~
|
||||
"###);
|
||||
|
|
@ -327,7 +327,7 @@ fn test_init_git_colocated_symlink_directory_without_bare_config() {
|
|||
// Check that the Git repo's HEAD got checked out
|
||||
let stdout = test_env.jj_cmd_success(&workspace_root, &["log", "-r", "@-"]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
○ mwrttmos git.user@example.com 1970-01-01 11:02:03 my-branch HEAD@git 8d698d4a
|
||||
○ mwrttmos git.user@example.com 1970-01-01 11:02:03 my-bookmark HEAD@git 8d698d4a
|
||||
│ My commit message
|
||||
~
|
||||
"###);
|
||||
|
|
@ -370,7 +370,7 @@ fn test_init_git_colocated_symlink_gitlink() {
|
|||
// Check that the Git repo's HEAD got checked out
|
||||
let stdout = test_env.jj_cmd_success(&workspace_root, &["log", "-r", "@-"]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
○ mwrttmos git.user@example.com 1970-01-01 11:02:03 my-branch HEAD@git 8d698d4a
|
||||
○ mwrttmos git.user@example.com 1970-01-01 11:02:03 my-bookmark HEAD@git 8d698d4a
|
||||
│ My commit message
|
||||
~
|
||||
"###);
|
||||
|
|
@ -395,7 +395,7 @@ fn test_init_git_colocated_imported_refs() {
|
|||
let remote_path = test_env.env_root().join("remote");
|
||||
test_env.jj_cmd_ok(
|
||||
&remote_path,
|
||||
&["branch", "create", "local-remote", "remote-only"],
|
||||
&["bookmark", "create", "local-remote", "remote-only"],
|
||||
);
|
||||
test_env.jj_cmd_ok(&remote_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&remote_path, &["git", "export"]);
|
||||
|
|
@ -427,7 +427,7 @@ fn test_init_git_colocated_imported_refs() {
|
|||
Use `jj git init` instead
|
||||
Initialized repo in "."
|
||||
"###);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &local_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &local_path), @r###"
|
||||
local-remote: vvkvtnvv 230dd059 (empty) (no description set)
|
||||
@git: vvkvtnvv 230dd059 (empty) (no description set)
|
||||
@origin: vvkvtnvv 230dd059 (empty) (no description set)
|
||||
|
|
@ -443,14 +443,14 @@ fn test_init_git_colocated_imported_refs() {
|
|||
let (_stdout, stderr) = test_env.jj_cmd_ok(&local_path, &["init", "--git-repo=."]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Done importing changes from the underlying Git repo.
|
||||
Hint: The following remote branches aren't associated with the existing local branches:
|
||||
Hint: The following remote bookmarks aren't associated with the existing local bookmarks:
|
||||
local-remote@origin
|
||||
Hint: Run `jj branch track local-remote@origin` to keep local branches updated on future pulls.
|
||||
Hint: Run `jj bookmark track local-remote@origin` to keep local bookmarks updated on future pulls.
|
||||
Warning: `--git` and `--git-repo` are deprecated.
|
||||
Use `jj git init` instead
|
||||
Initialized repo in "."
|
||||
"###);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &local_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &local_path), @r###"
|
||||
local-remote: vvkvtnvv 230dd059 (empty) (no description set)
|
||||
@git: vvkvtnvv 230dd059 (empty) (no description set)
|
||||
local-remote@origin: vvkvtnvv 230dd059 (empty) (no description set)
|
||||
|
|
|
|||
|
|
@ -23,13 +23,13 @@ fn test_interdiff_basic() {
|
|||
std::fs::write(repo_path.join("file1"), "foo\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
std::fs::write(repo_path.join("file2"), "foo\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "left"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "left"]);
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["checkout", "root()"]);
|
||||
std::fs::write(repo_path.join("file3"), "foo\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
std::fs::write(repo_path.join("file2"), "foo\nbar\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "right"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "right"]);
|
||||
|
||||
// implicit --to
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["interdiff", "--from", "left"]);
|
||||
|
|
@ -87,7 +87,7 @@ fn test_interdiff_paths() {
|
|||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
std::fs::write(repo_path.join("file1"), "bar\n").unwrap();
|
||||
std::fs::write(repo_path.join("file2"), "bar\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "left"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "left"]);
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["checkout", "root()"]);
|
||||
std::fs::write(repo_path.join("file1"), "foo\n").unwrap();
|
||||
|
|
@ -95,7 +95,7 @@ fn test_interdiff_paths() {
|
|||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
std::fs::write(repo_path.join("file1"), "baz\n").unwrap();
|
||||
std::fs::write(repo_path.join("file2"), "baz\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "right"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "right"]);
|
||||
|
||||
let stdout = test_env.jj_cmd_success(
|
||||
&repo_path,
|
||||
|
|
@ -135,13 +135,13 @@ fn test_interdiff_conflicting() {
|
|||
std::fs::write(repo_path.join("file"), "foo\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
std::fs::write(repo_path.join("file"), "bar\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "left"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "left"]);
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["checkout", "root()"]);
|
||||
std::fs::write(repo_path.join("file"), "abc\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
std::fs::write(repo_path.join("file"), "def\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "right"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "right"]);
|
||||
|
||||
let stdout = test_env.jj_cmd_success(
|
||||
&repo_path,
|
||||
|
|
|
|||
|
|
@ -351,7 +351,7 @@ fn test_log_shortest_accessors() {
|
|||
|
||||
std::fs::write(repo_path.join("file"), "original file\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "initial"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "c", "original"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "c", "original"]);
|
||||
insta::assert_snapshot!(
|
||||
render("original", r#"format_id(change_id) ++ " " ++ format_id(commit_id)"#),
|
||||
@"q[pvuntsmwlqt] e[0e22b9fae75]");
|
||||
|
|
@ -474,7 +474,7 @@ fn test_log_prefix_highlight_styled() {
|
|||
change_id.shortest({0}),
|
||||
description.first_line(),
|
||||
commit_id.shortest({0}),
|
||||
branches,
|
||||
bookmarks,
|
||||
)
|
||||
"###,
|
||||
len.map(|l| l.to_string()).unwrap_or_default()
|
||||
|
|
@ -483,7 +483,7 @@ fn test_log_prefix_highlight_styled() {
|
|||
|
||||
std::fs::write(repo_path.join("file"), "original file\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "initial"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "c", "original"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "c", "original"]);
|
||||
insta::assert_snapshot!(
|
||||
test_env.jj_cmd_success(&repo_path, &["log", "-r", "original", "-T", &prefix_format(Some(12))]),
|
||||
@r###"
|
||||
|
|
@ -611,13 +611,13 @@ fn test_log_prefix_highlight_counts_hidden_commits() {
|
|||
format_id(change_id),
|
||||
description.first_line(),
|
||||
format_id(commit_id),
|
||||
branches,
|
||||
bookmarks,
|
||||
)
|
||||
"#;
|
||||
|
||||
std::fs::write(repo_path.join("file"), "original file\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "initial"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "c", "original"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "c", "original"]);
|
||||
insta::assert_snapshot!(
|
||||
test_env.jj_cmd_success(&repo_path, &["log", "-r", "all()", "-T", prefix_format]),
|
||||
@r###"
|
||||
|
|
@ -1097,21 +1097,21 @@ fn test_multiple_revsets() {
|
|||
let repo_path = test_env.env_root().join("repo");
|
||||
for name in ["foo", "bar", "baz"] {
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-m", name]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", name]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", name]);
|
||||
}
|
||||
|
||||
// Default revset should be overridden if one or more -r options are specified.
|
||||
test_env.add_config(r#"revsets.log = "root()""#);
|
||||
|
||||
insta::assert_snapshot!(
|
||||
test_env.jj_cmd_success(&repo_path, &["log", "-T", "branches", "-rfoo"]),
|
||||
test_env.jj_cmd_success(&repo_path, &["log", "-T", "bookmarks", "-rfoo"]),
|
||||
@r###"
|
||||
○ foo
|
||||
│
|
||||
~
|
||||
"###);
|
||||
insta::assert_snapshot!(
|
||||
test_env.jj_cmd_success(&repo_path, &["log", "-T", "branches", "-rfoo", "-rbar", "-rbaz"]),
|
||||
test_env.jj_cmd_success(&repo_path, &["log", "-T", "bookmarks", "-rfoo", "-rbar", "-rbaz"]),
|
||||
@r###"
|
||||
@ baz
|
||||
○ bar
|
||||
|
|
@ -1120,7 +1120,7 @@ fn test_multiple_revsets() {
|
|||
~
|
||||
"###);
|
||||
insta::assert_snapshot!(
|
||||
test_env.jj_cmd_success(&repo_path, &["log", "-T", "branches", "-rfoo", "-rfoo"]),
|
||||
test_env.jj_cmd_success(&repo_path, &["log", "-T", "bookmarks", "-rfoo", "-rfoo"]),
|
||||
@r###"
|
||||
○ foo
|
||||
│
|
||||
|
|
@ -1184,15 +1184,21 @@ fn test_graph_styles() {
|
|||
let repo_path = test_env.env_root().join("repo");
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["commit", "-m", "initial"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["commit", "-m", "main branch 1"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "main branch 2"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["commit", "-m", "main bookmark 1"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "main bookmark 2"]);
|
||||
test_env.jj_cmd_ok(
|
||||
&repo_path,
|
||||
&["new", "-m", "side branch\nwith\nlong\ndescription"],
|
||||
&["new", "-m", "side bookmark\nwith\nlong\ndescription"],
|
||||
);
|
||||
test_env.jj_cmd_ok(
|
||||
&repo_path,
|
||||
&["new", "-m", "merge", r#"description("main branch 1")"#, "@"],
|
||||
&[
|
||||
"new",
|
||||
"-m",
|
||||
"merge",
|
||||
r#"description("main bookmark 1")"#,
|
||||
"@",
|
||||
],
|
||||
);
|
||||
|
||||
// Default (curved) style
|
||||
|
|
@ -1200,13 +1206,13 @@ fn test_graph_styles() {
|
|||
insta::assert_snapshot!(stdout, @r###"
|
||||
@ merge
|
||||
├─╮
|
||||
│ ○ side branch
|
||||
│ ○ side bookmark
|
||||
│ │ with
|
||||
│ │ long
|
||||
│ │ description
|
||||
│ ○ main branch 2
|
||||
│ ○ main bookmark 2
|
||||
├─╯
|
||||
○ main branch 1
|
||||
○ main bookmark 1
|
||||
○ initial
|
||||
◆
|
||||
"###);
|
||||
|
|
@ -1217,13 +1223,13 @@ fn test_graph_styles() {
|
|||
insta::assert_snapshot!(stdout, @r###"
|
||||
@ merge
|
||||
|\
|
||||
| o side branch
|
||||
| o side bookmark
|
||||
| | with
|
||||
| | long
|
||||
| | description
|
||||
| o main branch 2
|
||||
| o main bookmark 2
|
||||
|/
|
||||
o main branch 1
|
||||
o main bookmark 1
|
||||
o initial
|
||||
+
|
||||
"###);
|
||||
|
|
@ -1235,14 +1241,14 @@ fn test_graph_styles() {
|
|||
@ merge
|
||||
|\
|
||||
| \
|
||||
| o side branch
|
||||
| o side bookmark
|
||||
| | with
|
||||
| | long
|
||||
| | description
|
||||
| o main branch 2
|
||||
| o main bookmark 2
|
||||
| /
|
||||
|/
|
||||
o main branch 1
|
||||
o main bookmark 1
|
||||
o initial
|
||||
+
|
||||
"###);
|
||||
|
|
@ -1253,13 +1259,13 @@ fn test_graph_styles() {
|
|||
insta::assert_snapshot!(stdout, @r###"
|
||||
@ merge
|
||||
├─╮
|
||||
│ ○ side branch
|
||||
│ ○ side bookmark
|
||||
│ │ with
|
||||
│ │ long
|
||||
│ │ description
|
||||
│ ○ main branch 2
|
||||
│ ○ main bookmark 2
|
||||
├─╯
|
||||
○ main branch 1
|
||||
○ main bookmark 1
|
||||
○ initial
|
||||
◆
|
||||
"###);
|
||||
|
|
@ -1270,13 +1276,13 @@ fn test_graph_styles() {
|
|||
insta::assert_snapshot!(stdout, @r###"
|
||||
@ merge
|
||||
├─┐
|
||||
│ ○ side branch
|
||||
│ ○ side bookmark
|
||||
│ │ with
|
||||
│ │ long
|
||||
│ │ description
|
||||
│ ○ main branch 2
|
||||
│ ○ main bookmark 2
|
||||
├─┘
|
||||
○ main branch 1
|
||||
○ main bookmark 1
|
||||
○ initial
|
||||
◆
|
||||
"###);
|
||||
|
|
@ -1311,36 +1317,36 @@ fn test_log_word_wrap() {
|
|||
get_stdout_string(&assert)
|
||||
};
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["commit", "-m", "main branch 1"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "main branch 2"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["commit", "-m", "main bookmark 1"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "main bookmark 2"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-m", "side"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-m", "merge", "@--", "@"]);
|
||||
|
||||
// ui.log-word-wrap option applies to both graph/no-graph outputs
|
||||
insta::assert_snapshot!(render(&["log", "-r@"], 40, false), @r###"
|
||||
@ mzvwutvl test.user@example.com 2001-02-03 08:05:11 044c0400
|
||||
@ mzvwutvl test.user@example.com 2001-02-03 08:05:11 f3efbd00
|
||||
│ (empty) merge
|
||||
~
|
||||
"###);
|
||||
insta::assert_snapshot!(render(&["log", "-r@"], 40, true), @r###"
|
||||
@ mzvwutvl test.user@example.com
|
||||
│ 2001-02-03 08:05:11 044c0400
|
||||
│ 2001-02-03 08:05:11 f3efbd00
|
||||
~ (empty) merge
|
||||
"###);
|
||||
insta::assert_snapshot!(render(&["log", "--no-graph", "-r@"], 40, false), @r###"
|
||||
mzvwutvl test.user@example.com 2001-02-03 08:05:11 044c0400
|
||||
mzvwutvl test.user@example.com 2001-02-03 08:05:11 f3efbd00
|
||||
(empty) merge
|
||||
"###);
|
||||
insta::assert_snapshot!(render(&["log", "--no-graph", "-r@"], 40, true), @r###"
|
||||
mzvwutvl test.user@example.com
|
||||
2001-02-03 08:05:11 044c0400
|
||||
2001-02-03 08:05:11 f3efbd00
|
||||
(empty) merge
|
||||
"###);
|
||||
|
||||
// Color labels should be preserved
|
||||
insta::assert_snapshot!(render(&["log", "-r@", "--color=always"], 40, true), @r###"
|
||||
[1m[38;5;2m@[0m [1m[38;5;13mm[38;5;8mzvwutvl[39m [38;5;3mtest.user@example.com[39m[0m
|
||||
│ [1m[38;5;14m2001-02-03 08:05:11[39m [38;5;12m04[38;5;8m4c0400[39m[0m
|
||||
│ [1m[38;5;14m2001-02-03 08:05:11[39m [38;5;12mf[38;5;8m3efbd00[39m[0m
|
||||
~ [1m[38;5;10m(empty)[39m merge[0m
|
||||
"###);
|
||||
|
||||
|
|
@ -1373,7 +1379,7 @@ fn test_log_word_wrap() {
|
|||
│ test.user@example.com
|
||||
~ 2001-02-03
|
||||
08:05:11
|
||||
044c0400
|
||||
f3efbd00
|
||||
(empty)
|
||||
merge
|
||||
"###);
|
||||
|
|
@ -1382,7 +1388,7 @@ fn test_log_word_wrap() {
|
|||
│ test.user@example.com
|
||||
~ 2001-02-03
|
||||
08:05:11
|
||||
044c0400
|
||||
f3efbd00
|
||||
(empty)
|
||||
merge
|
||||
"###);
|
||||
|
|
@ -1443,13 +1449,19 @@ fn test_elided() {
|
|||
let repo_path = test_env.env_root().join("repo");
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "initial"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-m", "main branch 1"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-m", "main branch 2"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "@--", "-m", "side branch 1"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-m", "side branch 2"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-m", "main bookmark 1"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-m", "main bookmark 2"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "@--", "-m", "side bookmark 1"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-m", "side bookmark 2"]);
|
||||
test_env.jj_cmd_ok(
|
||||
&repo_path,
|
||||
&["new", "-m", "merge", r#"description("main branch 2")"#, "@"],
|
||||
&[
|
||||
"new",
|
||||
"-m",
|
||||
"merge",
|
||||
r#"description("main bookmark 2")"#,
|
||||
"@",
|
||||
],
|
||||
);
|
||||
|
||||
let get_log = |revs: &str| -> String {
|
||||
|
|
@ -1463,13 +1475,13 @@ fn test_elided() {
|
|||
insta::assert_snapshot!(get_log("::"), @r###"
|
||||
@ merge
|
||||
├─╮
|
||||
│ ○ side branch 2
|
||||
│ ○ side bookmark 2
|
||||
│ │
|
||||
│ ○ side branch 1
|
||||
│ ○ side bookmark 1
|
||||
│ │
|
||||
○ │ main branch 2
|
||||
○ │ main bookmark 2
|
||||
│ │
|
||||
○ │ main branch 1
|
||||
○ │ main bookmark 1
|
||||
├─╯
|
||||
○ initial
|
||||
│
|
||||
|
|
@ -1482,9 +1494,9 @@ fn test_elided() {
|
|||
insta::assert_snapshot!(get_log("@ | @- | description(initial)"), @r###"
|
||||
@ merge
|
||||
├─╮
|
||||
│ ○ side branch 2
|
||||
│ ○ side bookmark 2
|
||||
│ ╷
|
||||
○ ╷ main branch 2
|
||||
○ ╷ main bookmark 2
|
||||
├─╯
|
||||
○ initial
|
||||
│
|
||||
|
|
@ -1494,9 +1506,9 @@ fn test_elided() {
|
|||
// Elide shared commits. It's unclear that a revision was skipped on the right
|
||||
// side (#1252).
|
||||
insta::assert_snapshot!(get_log("@-- | root()"), @r###"
|
||||
○ side branch 1
|
||||
○ side bookmark 1
|
||||
╷
|
||||
╷ ○ main branch 1
|
||||
╷ ○ main bookmark 1
|
||||
╭─╯
|
||||
◆
|
||||
"###);
|
||||
|
|
@ -1508,10 +1520,10 @@ fn test_elided() {
|
|||
insta::assert_snapshot!(get_log("@ | @- | description(initial)"), @r###"
|
||||
@ merge
|
||||
├─╮
|
||||
│ ○ side branch 2
|
||||
│ ○ side bookmark 2
|
||||
│ │
|
||||
│ ~ (elided revisions)
|
||||
○ │ main branch 2
|
||||
○ │ main bookmark 2
|
||||
│ │
|
||||
~ │ (elided revisions)
|
||||
├─╯
|
||||
|
|
@ -1523,10 +1535,10 @@ fn test_elided() {
|
|||
// Elide shared commits. To keep the implementation simple, it still gets
|
||||
// rendered as two synthetic nodes.
|
||||
insta::assert_snapshot!(get_log("@-- | root()"), @r###"
|
||||
○ side branch 1
|
||||
○ side bookmark 1
|
||||
│
|
||||
~ (elided revisions)
|
||||
│ ○ main branch 1
|
||||
│ ○ main bookmark 1
|
||||
│ │
|
||||
│ ~ (elided revisions)
|
||||
├─╯
|
||||
|
|
@ -1542,13 +1554,19 @@ fn test_log_with_custom_symbols() {
|
|||
let repo_path = test_env.env_root().join("repo");
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "initial"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-m", "main branch 1"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-m", "main branch 2"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "@--", "-m", "side branch 1"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-m", "side branch 2"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-m", "main bookmark 1"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-m", "main bookmark 2"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "@--", "-m", "side bookmark 1"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-m", "side bookmark 2"]);
|
||||
test_env.jj_cmd_ok(
|
||||
&repo_path,
|
||||
&["new", "-m", "merge", r#"description("main branch 2")"#, "@"],
|
||||
&[
|
||||
"new",
|
||||
"-m",
|
||||
"merge",
|
||||
r#"description("main bookmark 2")"#,
|
||||
"@",
|
||||
],
|
||||
);
|
||||
|
||||
let get_log = |revs: &str| -> String {
|
||||
|
|
@ -1568,10 +1586,10 @@ fn test_log_with_custom_symbols() {
|
|||
insta::assert_snapshot!(get_log("@ | @- | description(initial) | root()"), @r###"
|
||||
$ merge
|
||||
├─╮
|
||||
│ ┝ side branch 2
|
||||
│ ┝ side bookmark 2
|
||||
│ │
|
||||
│ 🮀 (elided revisions)
|
||||
┝ │ main branch 2
|
||||
┝ │ main bookmark 2
|
||||
│ │
|
||||
🮀 │ (elided revisions)
|
||||
├─╯
|
||||
|
|
@ -1591,10 +1609,10 @@ fn test_log_with_custom_symbols() {
|
|||
insta::assert_snapshot!(get_log("@ | @- | description(initial) | root()"), @r###"
|
||||
$ merge
|
||||
|\
|
||||
| * side branch 2
|
||||
| * side bookmark 2
|
||||
| |
|
||||
| : (elided revisions)
|
||||
* | main branch 2
|
||||
* | main bookmark 2
|
||||
| |
|
||||
: | (elided revisions)
|
||||
|/
|
||||
|
|
|
|||
|
|
@ -34,25 +34,25 @@ fn test_move() {
|
|||
//
|
||||
// When moving changes between e.g. C and F, we should not get unrelated changes
|
||||
// from B and D.
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "a"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "a"]);
|
||||
std::fs::write(repo_path.join("file1"), "a\n").unwrap();
|
||||
std::fs::write(repo_path.join("file2"), "a\n").unwrap();
|
||||
std::fs::write(repo_path.join("file3"), "a\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "b"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "b"]);
|
||||
std::fs::write(repo_path.join("file3"), "b\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "c"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "c"]);
|
||||
std::fs::write(repo_path.join("file1"), "c\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["edit", "a"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "d"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "d"]);
|
||||
std::fs::write(repo_path.join("file3"), "d\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "e"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "e"]);
|
||||
std::fs::write(repo_path.join("file2"), "e\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "f"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "f"]);
|
||||
std::fs::write(repo_path.join("file2"), "f\n").unwrap();
|
||||
// Test the setup
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
|
||||
|
|
@ -183,20 +183,20 @@ fn test_move_partial() {
|
|||
// D B
|
||||
// |/
|
||||
// A
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "a"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "a"]);
|
||||
std::fs::write(repo_path.join("file1"), "a\n").unwrap();
|
||||
std::fs::write(repo_path.join("file2"), "a\n").unwrap();
|
||||
std::fs::write(repo_path.join("file3"), "a\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "b"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "b"]);
|
||||
std::fs::write(repo_path.join("file3"), "b\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "c"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "c"]);
|
||||
std::fs::write(repo_path.join("file1"), "c\n").unwrap();
|
||||
std::fs::write(repo_path.join("file2"), "c\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["edit", "a"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "d"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "d"]);
|
||||
std::fs::write(repo_path.join("file3"), "d\n").unwrap();
|
||||
// Test the setup
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
|
||||
|
|
@ -358,7 +358,7 @@ fn test_move_partial() {
|
|||
}
|
||||
|
||||
fn get_log_output(test_env: &TestEnvironment, cwd: &Path) -> String {
|
||||
let template = r#"commit_id.short() ++ " " ++ branches"#;
|
||||
let template = r#"commit_id.short() ++ " " ++ bookmarks"#;
|
||||
test_env.jj_cmd_success(cwd, &["log", "-T", template])
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ fn test_new_merge() {
|
|||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let repo_path = test_env.env_root().join("repo");
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "main"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "main"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "add file1"]);
|
||||
std::fs::write(repo_path.join("file1"), "a").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "root()", "-m", "add file2"]);
|
||||
|
|
@ -617,19 +617,19 @@ fn test_new_insert_after_before_no_loop() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_new_conflicting_branches() {
|
||||
fn test_new_conflicting_bookmarks() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let repo_path = test_env.env_root().join("repo");
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "one"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-m", "two", "@-"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "foo"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "foo"]);
|
||||
test_env.jj_cmd_ok(
|
||||
&repo_path,
|
||||
&[
|
||||
"--at-op=@-",
|
||||
"branch",
|
||||
"bookmark",
|
||||
"create",
|
||||
"foo",
|
||||
"-r",
|
||||
|
|
@ -689,19 +689,19 @@ fn test_new_error_revision_does_not_exist() {
|
|||
}
|
||||
|
||||
fn setup_before_insertion(test_env: &TestEnvironment, repo_path: &Path) {
|
||||
test_env.jj_cmd_ok(repo_path, &["branch", "create", "A"]);
|
||||
test_env.jj_cmd_ok(repo_path, &["bookmark", "create", "A"]);
|
||||
test_env.jj_cmd_ok(repo_path, &["commit", "-m", "A"]);
|
||||
test_env.jj_cmd_ok(repo_path, &["branch", "create", "B"]);
|
||||
test_env.jj_cmd_ok(repo_path, &["bookmark", "create", "B"]);
|
||||
test_env.jj_cmd_ok(repo_path, &["commit", "-m", "B"]);
|
||||
test_env.jj_cmd_ok(repo_path, &["branch", "create", "C"]);
|
||||
test_env.jj_cmd_ok(repo_path, &["bookmark", "create", "C"]);
|
||||
test_env.jj_cmd_ok(repo_path, &["describe", "-m", "C"]);
|
||||
test_env.jj_cmd_ok(repo_path, &["new", "-m", "D", "root()"]);
|
||||
test_env.jj_cmd_ok(repo_path, &["branch", "create", "D"]);
|
||||
test_env.jj_cmd_ok(repo_path, &["bookmark", "create", "D"]);
|
||||
test_env.jj_cmd_ok(repo_path, &["new", "-m", "E", "root()"]);
|
||||
test_env.jj_cmd_ok(repo_path, &["branch", "create", "E"]);
|
||||
test_env.jj_cmd_ok(repo_path, &["bookmark", "create", "E"]);
|
||||
// Any number of -r's is ignored
|
||||
test_env.jj_cmd_ok(repo_path, &["new", "-m", "F", "-r", "D", "-r", "E"]);
|
||||
test_env.jj_cmd_ok(repo_path, &["branch", "create", "F"]);
|
||||
test_env.jj_cmd_ok(repo_path, &["bookmark", "create", "F"]);
|
||||
}
|
||||
|
||||
fn get_log_output(test_env: &TestEnvironment, repo_path: &Path) -> String {
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ fn test_next_exceeding_history() {
|
|||
}
|
||||
|
||||
// The working copy commit is a child of a "fork" with two children on each
|
||||
// branch.
|
||||
// bookmark.
|
||||
#[test]
|
||||
fn test_next_parent_has_multiple_descendants() {
|
||||
let test_env = TestEnvironment::default();
|
||||
|
|
@ -332,7 +332,7 @@ fn test_next_on_merge_commit() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_next_fails_on_branching_children_no_stdin() {
|
||||
fn test_next_fails_on_bookmarking_children_no_stdin() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let repo_path = test_env.env_root().join("repo");
|
||||
|
|
@ -361,7 +361,7 @@ fn test_next_fails_on_branching_children_no_stdin() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_next_fails_on_branching_children_quit_prompt() {
|
||||
fn test_next_fails_on_bookmarking_children_quit_prompt() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let repo_path = test_env.env_root().join("repo");
|
||||
|
|
@ -401,7 +401,7 @@ fn test_next_fails_on_branching_children_quit_prompt() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_next_choose_branching_child() {
|
||||
fn test_next_choose_bookmarking_child() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let repo_path = test_env.env_root().join("repo");
|
||||
|
|
@ -434,9 +434,9 @@ fn test_prev_on_merge_commit() {
|
|||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let repo_path = test_env.env_root().join("repo");
|
||||
test_env.jj_cmd_ok(&repo_path, &["desc", "-m", "first"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "c", "left"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "c", "left"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "root()", "-m", "second"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "c", "right"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "c", "right"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "left", "right"]);
|
||||
|
||||
// Check that the graph looks the way we expect.
|
||||
|
|
@ -1113,6 +1113,6 @@ fn test_movement_edit_mode_false() {
|
|||
}
|
||||
|
||||
fn get_log_output(test_env: &TestEnvironment, cwd: &Path) -> String {
|
||||
let template = r#"separate(" ", change_id.short(), local_branches, if(conflict, "conflict"), description)"#;
|
||||
let template = r#"separate(" ", change_id.short(), local_bookmarks, if(conflict, "conflict"), description)"#;
|
||||
test_env.jj_cmd_success(cwd, &["log", "-T", template])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -702,10 +702,10 @@ fn test_op_diff() {
|
|||
// Overview of op log.
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "log"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
@ 984d5ceb039f test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
|
||||
@ ea112f6a02be test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
|
||||
│ check out git remote's default branch
|
||||
│ args: jj git clone git-repo repo
|
||||
○ 817baaeefcbb test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
|
||||
○ cba9d7096849 test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
|
||||
│ fetch from git remote into empty repo
|
||||
│ args: jj git clone git-repo repo
|
||||
○ b51416386f26 test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
|
||||
|
|
@ -727,8 +727,8 @@ fn test_op_diff() {
|
|||
"###);
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "diff", "--from", "@", "--to", "@"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
From operation 984d5ceb039f: check out git remote's default branch
|
||||
To operation 984d5ceb039f: check out git remote's default branch
|
||||
From operation ea112f6a02be: check out git remote's default branch
|
||||
To operation ea112f6a02be: check out git remote's default branch
|
||||
"###);
|
||||
|
||||
// Diff from parent operation to latest operation.
|
||||
|
|
@ -736,8 +736,8 @@ fn test_op_diff() {
|
|||
// @- --to @` (if `@` is not a merge commit).
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "diff", "--from", "@-", "--to", "@"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
From operation 817baaeefcbb: fetch from git remote into empty repo
|
||||
To operation 984d5ceb039f: check out git remote's default branch
|
||||
From operation cba9d7096849: fetch from git remote into empty repo
|
||||
To operation ea112f6a02be: check out git remote's default branch
|
||||
|
||||
Changed commits:
|
||||
○ Change sqpuoqvxutmz
|
||||
|
|
@ -746,14 +746,14 @@ fn test_op_diff() {
|
|||
- qpvuntsm hidden 230dd059 (empty) (no description set)
|
||||
|
||||
Changed local branches:
|
||||
branch-1:
|
||||
+ ulyvmwyz 1d843d1f branch-1 | Commit 1
|
||||
bookmark-1:
|
||||
+ ulyvmwyz 1d843d1f bookmark-1 | Commit 1
|
||||
- (absent)
|
||||
|
||||
Changed remote branches:
|
||||
branch-1@origin:
|
||||
+ tracked ulyvmwyz 1d843d1f branch-1 | Commit 1
|
||||
- untracked ulyvmwyz 1d843d1f branch-1 | Commit 1
|
||||
bookmark-1@origin:
|
||||
+ tracked ulyvmwyz 1d843d1f bookmark-1 | Commit 1
|
||||
- untracked ulyvmwyz 1d843d1f bookmark-1 | Commit 1
|
||||
"###);
|
||||
let stdout_without_from_to = test_env.jj_cmd_success(&repo_path, &["op", "diff"]);
|
||||
assert_eq!(stdout, stdout_without_from_to);
|
||||
|
|
@ -762,41 +762,41 @@ fn test_op_diff() {
|
|||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "diff", "--from", "0000000"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
From operation 000000000000: root()
|
||||
To operation 984d5ceb039f: check out git remote's default branch
|
||||
To operation ea112f6a02be: check out git remote's default branch
|
||||
|
||||
Changed commits:
|
||||
○ Change sqpuoqvxutmz
|
||||
│ + sqpuoqvx 9708515f (empty) (no description set)
|
||||
○ Change ulyvmwyzwuwt
|
||||
│ + ulyvmwyz 1d843d1f branch-1 | Commit 1
|
||||
│ + ulyvmwyz 1d843d1f bookmark-1 | Commit 1
|
||||
│ ○ Change tqyxmsztkvot
|
||||
├─╯ + tqyxmszt 3e785984 branch-3@origin | Commit 3
|
||||
├─╯ + tqyxmszt 3e785984 bookmark-3@origin | Commit 3
|
||||
│ ○ Change yuvsmzqkmpws
|
||||
├─╯ + yuvsmzqk 3d9189bc branch-2@origin | Commit 2
|
||||
├─╯ + yuvsmzqk 3d9189bc bookmark-2@origin | Commit 2
|
||||
○ Change zzzzzzzzzzzz
|
||||
+ zzzzzzzz 00000000 (empty) (no description set)
|
||||
|
||||
Changed local branches:
|
||||
branch-1:
|
||||
+ ulyvmwyz 1d843d1f branch-1 | Commit 1
|
||||
bookmark-1:
|
||||
+ ulyvmwyz 1d843d1f bookmark-1 | Commit 1
|
||||
- (absent)
|
||||
|
||||
Changed remote branches:
|
||||
branch-1@origin:
|
||||
+ tracked ulyvmwyz 1d843d1f branch-1 | Commit 1
|
||||
bookmark-1@origin:
|
||||
+ tracked ulyvmwyz 1d843d1f bookmark-1 | Commit 1
|
||||
- untracked (absent)
|
||||
branch-2@origin:
|
||||
+ untracked yuvsmzqk 3d9189bc branch-2@origin | Commit 2
|
||||
bookmark-2@origin:
|
||||
+ untracked yuvsmzqk 3d9189bc bookmark-2@origin | Commit 2
|
||||
- untracked (absent)
|
||||
branch-3@origin:
|
||||
+ untracked tqyxmszt 3e785984 branch-3@origin | Commit 3
|
||||
bookmark-3@origin:
|
||||
+ untracked tqyxmszt 3e785984 bookmark-3@origin | Commit 3
|
||||
- untracked (absent)
|
||||
"###);
|
||||
|
||||
// Diff from latest operation to root operation
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "diff", "--to", "0000000"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
From operation 984d5ceb039f: check out git remote's default branch
|
||||
From operation ea112f6a02be: check out git remote's default branch
|
||||
To operation 000000000000: root()
|
||||
|
||||
Changed commits:
|
||||
|
|
@ -812,31 +812,31 @@ fn test_op_diff() {
|
|||
- zzzzzzzz hidden 00000000 (empty) (no description set)
|
||||
|
||||
Changed local branches:
|
||||
branch-1:
|
||||
bookmark-1:
|
||||
+ (absent)
|
||||
- ulyvmwyz hidden 1d843d1f Commit 1
|
||||
|
||||
Changed remote branches:
|
||||
branch-1@origin:
|
||||
bookmark-1@origin:
|
||||
+ untracked (absent)
|
||||
- tracked ulyvmwyz hidden 1d843d1f Commit 1
|
||||
branch-2@origin:
|
||||
bookmark-2@origin:
|
||||
+ untracked (absent)
|
||||
- untracked yuvsmzqk hidden 3d9189bc Commit 2
|
||||
branch-3@origin:
|
||||
bookmark-3@origin:
|
||||
+ untracked (absent)
|
||||
- untracked tqyxmszt hidden 3e785984 Commit 3
|
||||
"###);
|
||||
|
||||
// Create a conflicted branch using a concurrent operation.
|
||||
// Create a conflicted bookmark using a concurrent operation.
|
||||
test_env.jj_cmd_ok(
|
||||
&repo_path,
|
||||
&[
|
||||
"branch",
|
||||
"bookmark",
|
||||
"set",
|
||||
"branch-1",
|
||||
"bookmark-1",
|
||||
"-r",
|
||||
"branch-2@origin",
|
||||
"bookmark-2@origin",
|
||||
"--at-op",
|
||||
"@-",
|
||||
],
|
||||
|
|
@ -847,16 +847,16 @@ fn test_op_diff() {
|
|||
"###);
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "log"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
@ afab0949fddc test-username@host.example.com 2001-02-03 04:05:16.000 +07:00 - 2001-02-03 04:05:16.000 +07:00
|
||||
@ f534dfc3151b test-username@host.example.com 2001-02-03 04:05:16.000 +07:00 - 2001-02-03 04:05:16.000 +07:00
|
||||
├─╮ reconcile divergent operations
|
||||
│ │ args: jj log
|
||||
○ │ 984d5ceb039f test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
|
||||
○ │ ea112f6a02be test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
|
||||
│ │ check out git remote's default branch
|
||||
│ │ args: jj git clone git-repo repo
|
||||
│ ○ 5ed581429582 test-username@host.example.com 2001-02-03 04:05:15.000 +07:00 - 2001-02-03 04:05:15.000 +07:00
|
||||
├─╯ point branch branch-1 to commit 3d9189bc56a1972729350456eb95ec5bf90be2a8
|
||||
│ args: jj branch set branch-1 -r branch-2@origin --at-op @-
|
||||
○ 817baaeefcbb test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
|
||||
│ ○ 9ded7e2755e1 test-username@host.example.com 2001-02-03 04:05:15.000 +07:00 - 2001-02-03 04:05:15.000 +07:00
|
||||
├─╯ point bookmark bookmark-1 to commit 3d9189bc56a1972729350456eb95ec5bf90be2a8
|
||||
│ args: jj bookmark set bookmark-1 -r bookmark-2@origin --at-op @-
|
||||
○ cba9d7096849 test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
|
||||
│ fetch from git remote into empty repo
|
||||
│ args: jj git clone git-repo repo
|
||||
○ b51416386f26 test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
|
||||
|
|
@ -876,14 +876,14 @@ fn test_op_diff() {
|
|||
&["op", "diff", "--from", first_parent_id, "--to", op_id],
|
||||
);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
From operation 984d5ceb039f: check out git remote's default branch
|
||||
To operation afab0949fddc: reconcile divergent operations
|
||||
From operation ea112f6a02be: check out git remote's default branch
|
||||
To operation f534dfc3151b: reconcile divergent operations
|
||||
|
||||
Changed local branches:
|
||||
branch-1:
|
||||
+ (added) ulyvmwyz 1d843d1f branch-1?? branch-1@origin | Commit 1
|
||||
+ (added) yuvsmzqk 3d9189bc branch-1?? branch-2@origin | Commit 2
|
||||
- ulyvmwyz 1d843d1f branch-1?? branch-1@origin | Commit 1
|
||||
bookmark-1:
|
||||
+ (added) ulyvmwyz 1d843d1f bookmark-1?? bookmark-1@origin | Commit 1
|
||||
+ (added) yuvsmzqk 3d9189bc bookmark-1?? bookmark-2@origin | Commit 2
|
||||
- ulyvmwyz 1d843d1f bookmark-1?? bookmark-1@origin | Commit 1
|
||||
"###);
|
||||
|
||||
// Diff between the second parent of the merge operation and the merge
|
||||
|
|
@ -893,8 +893,8 @@ fn test_op_diff() {
|
|||
&["op", "diff", "--from", second_parent_id, "--to", op_id],
|
||||
);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
From operation 5ed581429582: point branch branch-1 to commit 3d9189bc56a1972729350456eb95ec5bf90be2a8
|
||||
To operation afab0949fddc: reconcile divergent operations
|
||||
From operation 9ded7e2755e1: point bookmark bookmark-1 to commit 3d9189bc56a1972729350456eb95ec5bf90be2a8
|
||||
To operation f534dfc3151b: reconcile divergent operations
|
||||
|
||||
Changed commits:
|
||||
○ Change sqpuoqvxutmz
|
||||
|
|
@ -903,15 +903,15 @@ fn test_op_diff() {
|
|||
- qpvuntsm hidden 230dd059 (empty) (no description set)
|
||||
|
||||
Changed local branches:
|
||||
branch-1:
|
||||
+ (added) ulyvmwyz 1d843d1f branch-1?? branch-1@origin | Commit 1
|
||||
+ (added) yuvsmzqk 3d9189bc branch-1?? branch-2@origin | Commit 2
|
||||
- yuvsmzqk 3d9189bc branch-1?? branch-2@origin | Commit 2
|
||||
bookmark-1:
|
||||
+ (added) ulyvmwyz 1d843d1f bookmark-1?? bookmark-1@origin | Commit 1
|
||||
+ (added) yuvsmzqk 3d9189bc bookmark-1?? bookmark-2@origin | Commit 2
|
||||
- yuvsmzqk 3d9189bc bookmark-1?? bookmark-2@origin | Commit 2
|
||||
|
||||
Changed remote branches:
|
||||
branch-1@origin:
|
||||
+ tracked ulyvmwyz 1d843d1f branch-1?? branch-1@origin | Commit 1
|
||||
- untracked ulyvmwyz 1d843d1f branch-1?? branch-1@origin | Commit 1
|
||||
bookmark-1@origin:
|
||||
+ tracked ulyvmwyz 1d843d1f bookmark-1?? bookmark-1@origin | Commit 1
|
||||
- untracked ulyvmwyz 1d843d1f bookmark-1?? bookmark-1@origin | Commit 1
|
||||
"###);
|
||||
|
||||
// Test fetching from git remote.
|
||||
|
|
@ -920,140 +920,170 @@ fn test_op_diff() {
|
|||
insta::assert_snapshot!(&stdout, @r###"
|
||||
"###);
|
||||
insta::assert_snapshot!(&stderr, @r###"
|
||||
branch: branch-1@origin [updated] tracked
|
||||
branch: branch-2@origin [updated] untracked
|
||||
branch: branch-3@origin [deleted] untracked
|
||||
branch: bookmark-1@origin [updated] tracked
|
||||
branch: bookmark-2@origin [updated] untracked
|
||||
branch: bookmark-3@origin [deleted] untracked
|
||||
Abandoned 1 commits that are no longer reachable.
|
||||
"###);
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "diff"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
From operation afab0949fddc: reconcile divergent operations
|
||||
To operation aa3c1cbed385: fetch from git remote(s) origin
|
||||
From operation f534dfc3151b: reconcile divergent operations
|
||||
To operation 8a21e297a587: fetch from git remote(s) origin
|
||||
|
||||
Changed commits:
|
||||
○ Change qzxslznxxpoz
|
||||
+ qzxslznx d487febd branch-2@origin | Commit 5
|
||||
+ qzxslznx d487febd bookmark-2@origin | Commit 5
|
||||
○ Change slvtnnzxztqy
|
||||
+ slvtnnzx 4f856199 branch-1?? branch-1@origin | Commit 4
|
||||
+ slvtnnzx 4f856199 bookmark-1?? bookmark-1@origin | Commit 4
|
||||
○ Change tqyxmsztkvot
|
||||
- tqyxmszt hidden 3e785984 Commit 3
|
||||
|
||||
Changed local branches:
|
||||
branch-1:
|
||||
+ (added) slvtnnzx 4f856199 branch-1?? branch-1@origin | Commit 4
|
||||
+ (added) yuvsmzqk 3d9189bc branch-1?? | Commit 2
|
||||
bookmark-1:
|
||||
+ (added) slvtnnzx 4f856199 bookmark-1?? bookmark-1@origin | Commit 4
|
||||
+ (added) yuvsmzqk 3d9189bc bookmark-1?? | Commit 2
|
||||
- (added) ulyvmwyz 1d843d1f Commit 1
|
||||
- (added) yuvsmzqk 3d9189bc branch-1?? | Commit 2
|
||||
- (added) yuvsmzqk 3d9189bc bookmark-1?? | Commit 2
|
||||
|
||||
Changed remote branches:
|
||||
branch-1@origin:
|
||||
+ tracked slvtnnzx 4f856199 branch-1?? branch-1@origin | Commit 4
|
||||
bookmark-1@origin:
|
||||
+ tracked slvtnnzx 4f856199 bookmark-1?? bookmark-1@origin | Commit 4
|
||||
- tracked ulyvmwyz 1d843d1f Commit 1
|
||||
branch-2@origin:
|
||||
+ untracked qzxslznx d487febd branch-2@origin | Commit 5
|
||||
- untracked yuvsmzqk 3d9189bc branch-1?? | Commit 2
|
||||
branch-3@origin:
|
||||
bookmark-2@origin:
|
||||
+ untracked qzxslznx d487febd bookmark-2@origin | Commit 5
|
||||
- untracked yuvsmzqk 3d9189bc bookmark-1?? | Commit 2
|
||||
bookmark-3@origin:
|
||||
+ untracked (absent)
|
||||
- untracked tqyxmszt hidden 3e785984 Commit 3
|
||||
"###);
|
||||
|
||||
// Test creation of branch.
|
||||
// Test creation of bookmark.
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(
|
||||
&repo_path,
|
||||
&["branch", "create", "branch-2", "-r", "branch-2@origin"],
|
||||
&[
|
||||
"bookmark",
|
||||
"create",
|
||||
"bookmark-2",
|
||||
"-r",
|
||||
"bookmark-2@origin",
|
||||
],
|
||||
);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
"###);
|
||||
insta::assert_snapshot!(&stderr, @r###"
|
||||
Created 1 branches pointing to qzxslznx d487febd branch-2 branch-2@origin | Commit 5
|
||||
Created 1 bookmarks pointing to qzxslznx d487febd bookmark-2 bookmark-2@origin | Commit 5
|
||||
"###);
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "diff"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
From operation aa3c1cbed385: fetch from git remote(s) origin
|
||||
To operation be49cc959876: create branch branch-2 pointing to commit d487febd08e690ee775a4e0387e30d544307e409
|
||||
From operation 8a21e297a587: fetch from git remote(s) origin
|
||||
To operation ef314062f7f5: create bookmark bookmark-2 pointing to commit d487febd08e690ee775a4e0387e30d544307e409
|
||||
|
||||
Changed local branches:
|
||||
branch-2:
|
||||
+ qzxslznx d487febd branch-2 branch-2@origin | Commit 5
|
||||
bookmark-2:
|
||||
+ qzxslznx d487febd bookmark-2 bookmark-2@origin | Commit 5
|
||||
- (absent)
|
||||
"###);
|
||||
|
||||
// Test tracking of branch.
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["branch", "track", "branch-2@origin"]);
|
||||
// Test tracking of bookmark.
|
||||
let (stdout, stderr) =
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "track", "bookmark-2@origin"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
"###);
|
||||
"###);
|
||||
insta::assert_snapshot!(&stderr, @r###"
|
||||
Started tracking 1 remote branches.
|
||||
Started tracking 1 remote bookmarks.
|
||||
"###);
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "diff"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
From operation be49cc959876: create branch branch-2 pointing to commit d487febd08e690ee775a4e0387e30d544307e409
|
||||
To operation c6bace1690a5: track remote branch branch-2@origin
|
||||
From operation ef314062f7f5: create bookmark bookmark-2 pointing to commit d487febd08e690ee775a4e0387e30d544307e409
|
||||
To operation bc306c9bb67f: track remote bookmark bookmark-2@origin
|
||||
|
||||
Changed remote branches:
|
||||
branch-2@origin:
|
||||
+ tracked qzxslznx d487febd branch-2 | Commit 5
|
||||
- untracked qzxslznx d487febd branch-2 | Commit 5
|
||||
bookmark-2@origin:
|
||||
+ tracked qzxslznx d487febd bookmark-2 | Commit 5
|
||||
- untracked qzxslznx d487febd bookmark-2 | Commit 5
|
||||
"###);
|
||||
|
||||
// Test creation of new commit.
|
||||
// Test tracking of bookmark.
|
||||
let (stdout, stderr) =
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "branch-1@origin", "-m", "new commit"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "track", "bookmark-2@origin"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
"###);
|
||||
insta::assert_snapshot!(&stderr, @r###"
|
||||
Working copy now at: nmzmmopx bed2698f (empty) new commit
|
||||
Parent commit : slvtnnzx 4f856199 branch-1?? branch-1@origin | Commit 4
|
||||
Warning: Remote bookmark already tracked: bookmark-2@origin
|
||||
Nothing changed.
|
||||
"###);
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "diff"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
From operation ef314062f7f5: create bookmark bookmark-2 pointing to commit d487febd08e690ee775a4e0387e30d544307e409
|
||||
To operation bc306c9bb67f: track remote bookmark bookmark-2@origin
|
||||
|
||||
Changed remote branches:
|
||||
bookmark-2@origin:
|
||||
+ tracked qzxslznx d487febd bookmark-2 | Commit 5
|
||||
- untracked qzxslznx d487febd bookmark-2 | Commit 5
|
||||
"###);
|
||||
|
||||
// Test creation of new commit.
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(
|
||||
&repo_path,
|
||||
&["new", "bookmark-1@origin", "-m", "new commit"],
|
||||
);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
"###);
|
||||
insta::assert_snapshot!(&stderr, @r###"
|
||||
Working copy now at: wvuyspvk 358b82d6 (empty) new commit
|
||||
Parent commit : slvtnnzx 4f856199 bookmark-1?? bookmark-1@origin | Commit 4
|
||||
Added 1 files, modified 0 files, removed 1 files
|
||||
"###);
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "diff"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
From operation c6bace1690a5: track remote branch branch-2@origin
|
||||
To operation 06ad17cad045: new empty commit
|
||||
From operation bc306c9bb67f: track remote bookmark bookmark-2@origin
|
||||
To operation 1ae777a7acc8: new empty commit
|
||||
|
||||
Changed commits:
|
||||
○ Change nmzmmopxokps
|
||||
+ nmzmmopx bed2698f (empty) new commit
|
||||
○ Change wvuyspvkupzz
|
||||
+ wvuyspvk 358b82d6 (empty) new commit
|
||||
○ Change sqpuoqvxutmz
|
||||
- sqpuoqvx hidden 9708515f (empty) (no description set)
|
||||
"###);
|
||||
|
||||
// Test updating of local branch.
|
||||
// Test updating of local bookmark.
|
||||
let (stdout, stderr) =
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "set", "branch-1", "-r", "@"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "set", "bookmark-1", "-r", "@"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
"###);
|
||||
insta::assert_snapshot!(&stderr, @r###"
|
||||
Moved 1 branches to nmzmmopx bed2698f branch-1* | (empty) new commit
|
||||
Moved 1 bookmarks to wvuyspvk 358b82d6 bookmark-1* | (empty) new commit
|
||||
"###);
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "diff"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
From operation 06ad17cad045: new empty commit
|
||||
To operation f98d2aca274d: point branch branch-1 to commit bed2698f6baf06f7eea56c616bc3fe36d9065651
|
||||
From operation 1ae777a7acc8: new empty commit
|
||||
To operation 5728693d7de3: point bookmark bookmark-1 to commit 358b82d6be53fa9b062325abb8bc820a8b34c68d
|
||||
|
||||
Changed local branches:
|
||||
branch-1:
|
||||
+ nmzmmopx bed2698f branch-1* | (empty) new commit
|
||||
- (added) slvtnnzx 4f856199 branch-1@origin | Commit 4
|
||||
bookmark-1:
|
||||
+ wvuyspvk 358b82d6 bookmark-1* | (empty) new commit
|
||||
- (added) slvtnnzx 4f856199 bookmark-1@origin | Commit 4
|
||||
- (added) yuvsmzqk 3d9189bc Commit 2
|
||||
"###);
|
||||
|
||||
// Test deletion of local branch.
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["branch", "delete", "branch-2"]);
|
||||
// Test deletion of local bookmark.
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "delete", "bookmark-2"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
"###);
|
||||
insta::assert_snapshot!(&stderr, @r###"
|
||||
Deleted 1 branches.
|
||||
Deleted 1 bookmarks.
|
||||
"###);
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "diff"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
From operation f98d2aca274d: point branch branch-1 to commit bed2698f6baf06f7eea56c616bc3fe36d9065651
|
||||
To operation 238af436e327: delete branch branch-2
|
||||
From operation 5728693d7de3: point bookmark bookmark-1 to commit 358b82d6be53fa9b062325abb8bc820a8b34c68d
|
||||
To operation 0f77d601f1cd: delete bookmark bookmark-2
|
||||
|
||||
Changed local branches:
|
||||
branch-2:
|
||||
bookmark-2:
|
||||
+ (absent)
|
||||
- qzxslznx d487febd branch-2@origin | Commit 5
|
||||
- qzxslznx d487febd bookmark-2@origin | Commit 5
|
||||
"###);
|
||||
|
||||
// Test pushing to Git remote.
|
||||
|
|
@ -1062,26 +1092,26 @@ fn test_op_diff() {
|
|||
"###);
|
||||
insta::assert_snapshot!(&stderr, @r###"
|
||||
Branch changes to push to origin:
|
||||
Move forward branch branch-1 from 4f856199edbf to bed2698f6baf
|
||||
Delete branch branch-2 from d487febd08e6
|
||||
Move forward bookmark bookmark-1 from 4f856199edbf to 358b82d6be53
|
||||
Delete bookmark bookmark-2 from d487febd08e6
|
||||
Warning: The working-copy commit in workspace 'default' became immutable, so a new commit has been created on top of it.
|
||||
Working copy now at: uuuvxpvw 2c8e84a8 (empty) (no description set)
|
||||
Parent commit : nmzmmopx bed2698f branch-1 | (empty) new commit
|
||||
Working copy now at: oupztwtk 2f0718a0 (empty) (no description set)
|
||||
Parent commit : wvuyspvk 358b82d6 bookmark-1 | (empty) new commit
|
||||
"###);
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "diff"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
From operation 238af436e327: delete branch branch-2
|
||||
To operation c5aa1d1304a6: push all tracked branches to git remote origin
|
||||
From operation 0f77d601f1cd: delete bookmark bookmark-2
|
||||
To operation 65409e59d36a: push all tracked bookmarks to git remote origin
|
||||
|
||||
Changed commits:
|
||||
○ Change uuuvxpvwspwr
|
||||
+ uuuvxpvw 2c8e84a8 (empty) (no description set)
|
||||
○ Change oupztwtkortx
|
||||
+ oupztwtk 2f0718a0 (empty) (no description set)
|
||||
|
||||
Changed remote branches:
|
||||
branch-1@origin:
|
||||
+ tracked nmzmmopx bed2698f branch-1 | (empty) new commit
|
||||
bookmark-1@origin:
|
||||
+ tracked wvuyspvk 358b82d6 bookmark-1 | (empty) new commit
|
||||
- tracked slvtnnzx 4f856199 Commit 4
|
||||
branch-2@origin:
|
||||
bookmark-2@origin:
|
||||
+ untracked (absent)
|
||||
- tracked qzxslznx d487febd Commit 5
|
||||
"###);
|
||||
|
|
@ -1326,10 +1356,10 @@ fn test_op_show() {
|
|||
// Overview of op log.
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "log"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
@ 984d5ceb039f test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
|
||||
@ ea112f6a02be test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
|
||||
│ check out git remote's default branch
|
||||
│ args: jj git clone git-repo repo
|
||||
○ 817baaeefcbb test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
|
||||
○ cba9d7096849 test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
|
||||
│ fetch from git remote into empty repo
|
||||
│ args: jj git clone git-repo repo
|
||||
○ b51416386f26 test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
|
||||
|
|
@ -1348,7 +1378,7 @@ fn test_op_show() {
|
|||
// Showing the latest operation.
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "show", "@"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
984d5ceb039f test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
|
||||
ea112f6a02be test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
|
||||
check out git remote's default branch
|
||||
args: jj git clone git-repo repo
|
||||
|
||||
|
|
@ -1359,14 +1389,14 @@ fn test_op_show() {
|
|||
- qpvuntsm hidden 230dd059 (empty) (no description set)
|
||||
|
||||
Changed local branches:
|
||||
branch-1:
|
||||
+ ulyvmwyz 1d843d1f branch-1 | Commit 1
|
||||
bookmark-1:
|
||||
+ ulyvmwyz 1d843d1f bookmark-1 | Commit 1
|
||||
- (absent)
|
||||
|
||||
Changed remote branches:
|
||||
branch-1@origin:
|
||||
+ tracked ulyvmwyz 1d843d1f branch-1 | Commit 1
|
||||
- untracked ulyvmwyz 1d843d1f branch-1 | Commit 1
|
||||
bookmark-1@origin:
|
||||
+ tracked ulyvmwyz 1d843d1f bookmark-1 | Commit 1
|
||||
- untracked ulyvmwyz 1d843d1f bookmark-1 | Commit 1
|
||||
"###);
|
||||
// `jj op show @` should behave identically to `jj op show`.
|
||||
let stdout_without_op_id = test_env.jj_cmd_success(&repo_path, &["op", "show"]);
|
||||
|
|
@ -1375,39 +1405,39 @@ fn test_op_show() {
|
|||
// Showing a given operation.
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "show", "@-"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
817baaeefcbb test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
|
||||
cba9d7096849 test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
|
||||
fetch from git remote into empty repo
|
||||
args: jj git clone git-repo repo
|
||||
|
||||
Changed commits:
|
||||
○ Change tqyxmsztkvot
|
||||
+ tqyxmszt 3e785984 branch-3@origin | Commit 3
|
||||
+ tqyxmszt 3e785984 bookmark-3@origin | Commit 3
|
||||
○ Change yuvsmzqkmpws
|
||||
+ yuvsmzqk 3d9189bc branch-2@origin | Commit 2
|
||||
+ yuvsmzqk 3d9189bc bookmark-2@origin | Commit 2
|
||||
○ Change ulyvmwyzwuwt
|
||||
+ ulyvmwyz 1d843d1f branch-1@origin | Commit 1
|
||||
+ ulyvmwyz 1d843d1f bookmark-1@origin | Commit 1
|
||||
|
||||
Changed remote branches:
|
||||
branch-1@origin:
|
||||
+ untracked ulyvmwyz 1d843d1f branch-1@origin | Commit 1
|
||||
bookmark-1@origin:
|
||||
+ untracked ulyvmwyz 1d843d1f bookmark-1@origin | Commit 1
|
||||
- untracked (absent)
|
||||
branch-2@origin:
|
||||
+ untracked yuvsmzqk 3d9189bc branch-2@origin | Commit 2
|
||||
bookmark-2@origin:
|
||||
+ untracked yuvsmzqk 3d9189bc bookmark-2@origin | Commit 2
|
||||
- untracked (absent)
|
||||
branch-3@origin:
|
||||
+ untracked tqyxmszt 3e785984 branch-3@origin | Commit 3
|
||||
bookmark-3@origin:
|
||||
+ untracked tqyxmszt 3e785984 bookmark-3@origin | Commit 3
|
||||
- untracked (absent)
|
||||
"###);
|
||||
|
||||
// Create a conflicted branch using a concurrent operation.
|
||||
// Create a conflicted bookmark using a concurrent operation.
|
||||
test_env.jj_cmd_ok(
|
||||
&repo_path,
|
||||
&[
|
||||
"branch",
|
||||
"bookmark",
|
||||
"set",
|
||||
"branch-1",
|
||||
"bookmark-1",
|
||||
"-r",
|
||||
"branch-2@origin",
|
||||
"bookmark-2@origin",
|
||||
"--at-op",
|
||||
"@-",
|
||||
],
|
||||
|
|
@ -1419,7 +1449,7 @@ fn test_op_show() {
|
|||
// Showing a merge operation is empty.
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "show"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
40495fbd29b6 test-username@host.example.com 2001-02-03 04:05:14.000 +07:00 - 2001-02-03 04:05:14.000 +07:00
|
||||
5d52ce7672bb test-username@host.example.com 2001-02-03 04:05:14.000 +07:00 - 2001-02-03 04:05:14.000 +07:00
|
||||
reconcile divergent operations
|
||||
args: jj log
|
||||
"###);
|
||||
|
|
@ -1430,146 +1460,176 @@ fn test_op_show() {
|
|||
insta::assert_snapshot!(&stdout, @r###"
|
||||
"###);
|
||||
insta::assert_snapshot!(&stderr, @r###"
|
||||
branch: branch-1@origin [updated] tracked
|
||||
branch: branch-2@origin [updated] untracked
|
||||
branch: branch-3@origin [deleted] untracked
|
||||
branch: bookmark-1@origin [updated] tracked
|
||||
branch: bookmark-2@origin [updated] untracked
|
||||
branch: bookmark-3@origin [deleted] untracked
|
||||
Abandoned 1 commits that are no longer reachable.
|
||||
"###);
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "show"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
1ed37acf8335 test-username@host.example.com 2001-02-03 04:05:16.000 +07:00 - 2001-02-03 04:05:16.000 +07:00
|
||||
5eed0f5f5fbc test-username@host.example.com 2001-02-03 04:05:16.000 +07:00 - 2001-02-03 04:05:16.000 +07:00
|
||||
fetch from git remote(s) origin
|
||||
args: jj git fetch
|
||||
|
||||
Changed commits:
|
||||
○ Change qzxslznxxpoz
|
||||
+ qzxslznx d487febd branch-2@origin | Commit 5
|
||||
+ qzxslznx d487febd bookmark-2@origin | Commit 5
|
||||
○ Change slvtnnzxztqy
|
||||
+ slvtnnzx 4f856199 branch-1?? branch-1@origin | Commit 4
|
||||
+ slvtnnzx 4f856199 bookmark-1?? bookmark-1@origin | Commit 4
|
||||
○ Change tqyxmsztkvot
|
||||
- tqyxmszt hidden 3e785984 Commit 3
|
||||
|
||||
Changed local branches:
|
||||
branch-1:
|
||||
+ (added) slvtnnzx 4f856199 branch-1?? branch-1@origin | Commit 4
|
||||
+ (added) yuvsmzqk 3d9189bc branch-1?? | Commit 2
|
||||
bookmark-1:
|
||||
+ (added) slvtnnzx 4f856199 bookmark-1?? bookmark-1@origin | Commit 4
|
||||
+ (added) yuvsmzqk 3d9189bc bookmark-1?? | Commit 2
|
||||
- (added) ulyvmwyz 1d843d1f Commit 1
|
||||
- (added) yuvsmzqk 3d9189bc branch-1?? | Commit 2
|
||||
- (added) yuvsmzqk 3d9189bc bookmark-1?? | Commit 2
|
||||
|
||||
Changed remote branches:
|
||||
branch-1@origin:
|
||||
+ tracked slvtnnzx 4f856199 branch-1?? branch-1@origin | Commit 4
|
||||
bookmark-1@origin:
|
||||
+ tracked slvtnnzx 4f856199 bookmark-1?? bookmark-1@origin | Commit 4
|
||||
- tracked ulyvmwyz 1d843d1f Commit 1
|
||||
branch-2@origin:
|
||||
+ untracked qzxslznx d487febd branch-2@origin | Commit 5
|
||||
- untracked yuvsmzqk 3d9189bc branch-1?? | Commit 2
|
||||
branch-3@origin:
|
||||
bookmark-2@origin:
|
||||
+ untracked qzxslznx d487febd bookmark-2@origin | Commit 5
|
||||
- untracked yuvsmzqk 3d9189bc bookmark-1?? | Commit 2
|
||||
bookmark-3@origin:
|
||||
+ untracked (absent)
|
||||
- untracked tqyxmszt hidden 3e785984 Commit 3
|
||||
"###);
|
||||
|
||||
// Test creation of branch.
|
||||
// Test creation of bookmark.
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(
|
||||
&repo_path,
|
||||
&["branch", "create", "branch-2", "-r", "branch-2@origin"],
|
||||
&[
|
||||
"bookmark",
|
||||
"create",
|
||||
"bookmark-2",
|
||||
"-r",
|
||||
"bookmark-2@origin",
|
||||
],
|
||||
);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
"###);
|
||||
insta::assert_snapshot!(&stderr, @r###"
|
||||
Created 1 branches pointing to qzxslznx d487febd branch-2 branch-2@origin | Commit 5
|
||||
Created 1 bookmarks pointing to qzxslznx d487febd bookmark-2 bookmark-2@origin | Commit 5
|
||||
"###);
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "show"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
61235941fe15 test-username@host.example.com 2001-02-03 04:05:18.000 +07:00 - 2001-02-03 04:05:18.000 +07:00
|
||||
create branch branch-2 pointing to commit d487febd08e690ee775a4e0387e30d544307e409
|
||||
args: jj branch create branch-2 -r branch-2@origin
|
||||
25b687bb01b6 test-username@host.example.com 2001-02-03 04:05:18.000 +07:00 - 2001-02-03 04:05:18.000 +07:00
|
||||
create bookmark bookmark-2 pointing to commit d487febd08e690ee775a4e0387e30d544307e409
|
||||
args: jj bookmark create bookmark-2 -r bookmark-2@origin
|
||||
|
||||
Changed local branches:
|
||||
branch-2:
|
||||
+ qzxslznx d487febd branch-2 branch-2@origin | Commit 5
|
||||
bookmark-2:
|
||||
+ qzxslznx d487febd bookmark-2 bookmark-2@origin | Commit 5
|
||||
- (absent)
|
||||
"###);
|
||||
|
||||
// Test tracking of branch.
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["branch", "track", "branch-2@origin"]);
|
||||
// Test tracking of a bookmark.
|
||||
let (stdout, stderr) =
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "track", "bookmark-2@origin"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
"###);
|
||||
"###);
|
||||
insta::assert_snapshot!(&stderr, @r###"
|
||||
Started tracking 1 remote branches.
|
||||
Started tracking 1 remote bookmarks.
|
||||
"###);
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "show"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
18035ff599c1 test-username@host.example.com 2001-02-03 04:05:20.000 +07:00 - 2001-02-03 04:05:20.000 +07:00
|
||||
track remote branch branch-2@origin
|
||||
args: jj branch track branch-2@origin
|
||||
48cf434c463d test-username@host.example.com 2001-02-03 04:05:20.000 +07:00 - 2001-02-03 04:05:20.000 +07:00
|
||||
track remote bookmark bookmark-2@origin
|
||||
args: jj bookmark track bookmark-2@origin
|
||||
|
||||
Changed remote branches:
|
||||
branch-2@origin:
|
||||
+ tracked qzxslznx d487febd branch-2 | Commit 5
|
||||
- untracked qzxslznx d487febd branch-2 | Commit 5
|
||||
bookmark-2@origin:
|
||||
+ tracked qzxslznx d487febd bookmark-2 | Commit 5
|
||||
- untracked qzxslznx d487febd bookmark-2 | Commit 5
|
||||
"###);
|
||||
|
||||
// Test creation of new commit.
|
||||
let (stdout, stderr) =
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "branch-1@origin", "-m", "new commit"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "track", "bookmark-2@origin"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
"###);
|
||||
insta::assert_snapshot!(&stderr, @r###"
|
||||
Working copy now at: nkmrtpmo 71fe694d (empty) new commit
|
||||
Parent commit : slvtnnzx 4f856199 branch-1?? branch-1@origin | Commit 4
|
||||
Warning: Remote bookmark already tracked: bookmark-2@origin
|
||||
Nothing changed.
|
||||
"###);
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "show"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
48cf434c463d test-username@host.example.com 2001-02-03 04:05:20.000 +07:00 - 2001-02-03 04:05:20.000 +07:00
|
||||
track remote bookmark bookmark-2@origin
|
||||
args: jj bookmark track bookmark-2@origin
|
||||
|
||||
Changed remote branches:
|
||||
bookmark-2@origin:
|
||||
+ tracked qzxslznx d487febd bookmark-2 | Commit 5
|
||||
- untracked qzxslznx d487febd bookmark-2 | Commit 5
|
||||
"###);
|
||||
|
||||
// Test creation of new commit.
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(
|
||||
&repo_path,
|
||||
&["new", "bookmark-1@origin", "-m", "new commit"],
|
||||
);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
"###);
|
||||
insta::assert_snapshot!(&stderr, @r###"
|
||||
Working copy now at: xznxytkn eb6c2b21 (empty) new commit
|
||||
Parent commit : slvtnnzx 4f856199 bookmark-1?? bookmark-1@origin | Commit 4
|
||||
Added 1 files, modified 0 files, removed 1 files
|
||||
"###);
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "show"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
6ae7eab9f2c5 test-username@host.example.com 2001-02-03 04:05:22.000 +07:00 - 2001-02-03 04:05:22.000 +07:00
|
||||
89aa6cca51fc test-username@host.example.com 2001-02-03 04:05:24.000 +07:00 - 2001-02-03 04:05:24.000 +07:00
|
||||
new empty commit
|
||||
args: jj new branch-1@origin -m 'new commit'
|
||||
args: jj new bookmark-1@origin -m 'new commit'
|
||||
|
||||
Changed commits:
|
||||
○ Change nkmrtpmomlro
|
||||
+ nkmrtpmo 71fe694d (empty) new commit
|
||||
○ Change xznxytknoqwo
|
||||
+ xznxytkn eb6c2b21 (empty) new commit
|
||||
○ Change sqpuoqvxutmz
|
||||
- sqpuoqvx hidden 9708515f (empty) (no description set)
|
||||
"###);
|
||||
|
||||
// Test updating of local branch.
|
||||
// Test updating of local bookmark.
|
||||
let (stdout, stderr) =
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "set", "branch-1", "-r", "@"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "set", "bookmark-1", "-r", "@"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
"###);
|
||||
insta::assert_snapshot!(&stderr, @r###"
|
||||
Moved 1 branches to nkmrtpmo 71fe694d branch-1* | (empty) new commit
|
||||
Moved 1 bookmarks to xznxytkn eb6c2b21 bookmark-1* | (empty) new commit
|
||||
"###);
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "show"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
044836a4ea77 test-username@host.example.com 2001-02-03 04:05:24.000 +07:00 - 2001-02-03 04:05:24.000 +07:00
|
||||
point branch branch-1 to commit 71fe694da7811a184f404fffe35cd62b0adb3d89
|
||||
args: jj branch set branch-1 -r @
|
||||
6d6bf9b35d8a test-username@host.example.com 2001-02-03 04:05:26.000 +07:00 - 2001-02-03 04:05:26.000 +07:00
|
||||
point bookmark bookmark-1 to commit eb6c2b21ec20a33ab6a1c44bc86c59d84ffd93ac
|
||||
args: jj bookmark set bookmark-1 -r @
|
||||
|
||||
Changed local branches:
|
||||
branch-1:
|
||||
+ nkmrtpmo 71fe694d branch-1* | (empty) new commit
|
||||
- (added) slvtnnzx 4f856199 branch-1@origin | Commit 4
|
||||
bookmark-1:
|
||||
+ xznxytkn eb6c2b21 bookmark-1* | (empty) new commit
|
||||
- (added) slvtnnzx 4f856199 bookmark-1@origin | Commit 4
|
||||
- (added) yuvsmzqk 3d9189bc Commit 2
|
||||
"###);
|
||||
|
||||
// Test deletion of local branch.
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["branch", "delete", "branch-2"]);
|
||||
// Test deletion of local bookmark.
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "delete", "bookmark-2"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
"###);
|
||||
insta::assert_snapshot!(&stderr, @r###"
|
||||
Deleted 1 branches.
|
||||
Deleted 1 bookmarks.
|
||||
"###);
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "show"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
6595a222e6f1 test-username@host.example.com 2001-02-03 04:05:26.000 +07:00 - 2001-02-03 04:05:26.000 +07:00
|
||||
delete branch branch-2
|
||||
args: jj branch delete branch-2
|
||||
a50c95a6b180 test-username@host.example.com 2001-02-03 04:05:28.000 +07:00 - 2001-02-03 04:05:28.000 +07:00
|
||||
delete bookmark bookmark-2
|
||||
args: jj bookmark delete bookmark-2
|
||||
|
||||
Changed local branches:
|
||||
branch-2:
|
||||
bookmark-2:
|
||||
+ (absent)
|
||||
- qzxslznx d487febd branch-2@origin | Commit 5
|
||||
- qzxslznx d487febd bookmark-2@origin | Commit 5
|
||||
"###);
|
||||
|
||||
// Test pushing to Git remote.
|
||||
|
|
@ -1578,27 +1638,27 @@ fn test_op_show() {
|
|||
"###);
|
||||
insta::assert_snapshot!(&stderr, @r###"
|
||||
Branch changes to push to origin:
|
||||
Move forward branch branch-1 from 4f856199edbf to 71fe694da781
|
||||
Delete branch branch-2 from d487febd08e6
|
||||
Move forward bookmark bookmark-1 from 4f856199edbf to eb6c2b21ec20
|
||||
Delete bookmark bookmark-2 from d487febd08e6
|
||||
Warning: The working-copy commit in workspace 'default' became immutable, so a new commit has been created on top of it.
|
||||
Working copy now at: wvuyspvk 6136f89a (empty) (no description set)
|
||||
Parent commit : nkmrtpmo 71fe694d branch-1 | (empty) new commit
|
||||
Working copy now at: pzsxstzt 7ab2d837 (empty) (no description set)
|
||||
Parent commit : xznxytkn eb6c2b21 bookmark-1 | (empty) new commit
|
||||
"###);
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "show"]);
|
||||
insta::assert_snapshot!(&stdout, @r###"
|
||||
c69699290f76 test-username@host.example.com 2001-02-03 04:05:28.000 +07:00 - 2001-02-03 04:05:28.000 +07:00
|
||||
push all tracked branches to git remote origin
|
||||
5d994bb7d230 test-username@host.example.com 2001-02-03 04:05:30.000 +07:00 - 2001-02-03 04:05:30.000 +07:00
|
||||
push all tracked bookmarks to git remote origin
|
||||
args: jj git push --tracked
|
||||
|
||||
Changed commits:
|
||||
○ Change wvuyspvkupzz
|
||||
+ wvuyspvk 6136f89a (empty) (no description set)
|
||||
○ Change pzsxstztnpkv
|
||||
+ pzsxstzt 7ab2d837 (empty) (no description set)
|
||||
|
||||
Changed remote branches:
|
||||
branch-1@origin:
|
||||
+ tracked nkmrtpmo 71fe694d branch-1 | (empty) new commit
|
||||
bookmark-1@origin:
|
||||
+ tracked xznxytkn eb6c2b21 bookmark-1 | (empty) new commit
|
||||
- tracked slvtnnzx 4f856199 Commit 4
|
||||
branch-2@origin:
|
||||
bookmark-2@origin:
|
||||
+ untracked (absent)
|
||||
- tracked qzxslznx d487febd Commit 5
|
||||
"###);
|
||||
|
|
@ -1725,7 +1785,7 @@ fn init_bare_git_repo(git_repo_path: &Path) -> git2::Repository {
|
|||
.unwrap();
|
||||
git_repo
|
||||
.commit(
|
||||
Some("refs/heads/branch-1"),
|
||||
Some("refs/heads/bookmark-1"),
|
||||
&git_signature,
|
||||
&git_signature,
|
||||
"Commit 1",
|
||||
|
|
@ -1735,7 +1795,7 @@ fn init_bare_git_repo(git_repo_path: &Path) -> git2::Repository {
|
|||
.unwrap();
|
||||
git_repo
|
||||
.commit(
|
||||
Some("refs/heads/branch-2"),
|
||||
Some("refs/heads/bookmark-2"),
|
||||
&git_signature,
|
||||
&git_signature,
|
||||
"Commit 2",
|
||||
|
|
@ -1745,7 +1805,7 @@ fn init_bare_git_repo(git_repo_path: &Path) -> git2::Repository {
|
|||
.unwrap();
|
||||
git_repo
|
||||
.commit(
|
||||
Some("refs/heads/branch-3"),
|
||||
Some("refs/heads/bookmark-3"),
|
||||
&git_signature,
|
||||
&git_signature,
|
||||
"Commit 3",
|
||||
|
|
@ -1754,7 +1814,7 @@ fn init_bare_git_repo(git_repo_path: &Path) -> git2::Repository {
|
|||
)
|
||||
.unwrap();
|
||||
drop(git_tree);
|
||||
git_repo.set_head("refs/heads/branch-1").unwrap();
|
||||
git_repo.set_head("refs/heads/bookmark-1").unwrap();
|
||||
git_repo
|
||||
}
|
||||
|
||||
|
|
@ -1773,44 +1833,44 @@ fn modify_git_repo(git_repo: git2::Repository) -> git2::Repository {
|
|||
&git2::Time::new(123, 60),
|
||||
)
|
||||
.unwrap();
|
||||
let branch1_commit = git_repo
|
||||
.find_reference("refs/heads/branch-1")
|
||||
let bookmark1_commit = git_repo
|
||||
.find_reference("refs/heads/bookmark-1")
|
||||
.unwrap()
|
||||
.peel_to_commit()
|
||||
.unwrap();
|
||||
let branch2_commit = git_repo
|
||||
.find_reference("refs/heads/branch-2")
|
||||
let bookmark2_commit = git_repo
|
||||
.find_reference("refs/heads/bookmark-2")
|
||||
.unwrap()
|
||||
.peel_to_commit()
|
||||
.unwrap();
|
||||
git_repo
|
||||
.commit(
|
||||
Some("refs/heads/branch-1"),
|
||||
Some("refs/heads/bookmark-1"),
|
||||
&git_signature,
|
||||
&git_signature,
|
||||
"Commit 4",
|
||||
&git_tree,
|
||||
&[&branch1_commit],
|
||||
&[&bookmark1_commit],
|
||||
)
|
||||
.unwrap();
|
||||
git_repo
|
||||
.commit(
|
||||
Some("refs/heads/branch-2"),
|
||||
Some("refs/heads/bookmark-2"),
|
||||
&git_signature,
|
||||
&git_signature,
|
||||
"Commit 5",
|
||||
&git_tree,
|
||||
&[&branch2_commit],
|
||||
&[&bookmark2_commit],
|
||||
)
|
||||
.unwrap();
|
||||
git_repo
|
||||
.find_reference("refs/heads/branch-3")
|
||||
.find_reference("refs/heads/bookmark-3")
|
||||
.unwrap()
|
||||
.delete()
|
||||
.unwrap();
|
||||
drop(git_tree);
|
||||
drop(branch1_commit);
|
||||
drop(branch2_commit);
|
||||
drop(bookmark1_commit);
|
||||
drop(bookmark2_commit);
|
||||
git_repo
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ fn create_commit(test_env: &TestEnvironment, repo_path: &Path, name: &str, paren
|
|||
test_env.jj_cmd_ok(repo_path, &args);
|
||||
}
|
||||
std::fs::write(repo_path.join(name), format!("{name}\n")).unwrap();
|
||||
test_env.jj_cmd_ok(repo_path, &["branch", "create", name]);
|
||||
test_env.jj_cmd_ok(repo_path, &["bookmark", "create", name]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -169,7 +169,7 @@ fn test_rebase_invalid() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_rebase_branch() {
|
||||
fn test_rebase_bookmark() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let repo_path = test_env.env_root().join("repo");
|
||||
|
|
@ -206,7 +206,7 @@ fn test_rebase_branch() {
|
|||
◆
|
||||
"###);
|
||||
|
||||
// Test rebasing multiple branches at once
|
||||
// Test rebasing multiple bookmarks at once
|
||||
test_env.jj_cmd_ok(&repo_path, &["undo"]);
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["rebase", "-b=e", "-b=d", "-d=b"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
|
|
@ -260,7 +260,7 @@ fn test_rebase_branch() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_rebase_branch_with_merge() {
|
||||
fn test_rebase_bookmark_with_merge() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let repo_path = test_env.env_root().join("repo");
|
||||
|
|
@ -939,7 +939,7 @@ fn test_rebase_error_revision_does_not_exist() {
|
|||
let repo_path = test_env.env_root().join("repo");
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "one"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "b-one"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "b-one"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-r", "@-", "-m", "two"]);
|
||||
|
||||
let stderr = test_env.jj_cmd_failure(&repo_path, &["rebase", "-b", "b-one", "-d", "this"]);
|
||||
|
|
@ -1432,7 +1432,7 @@ fn test_rebase_revisions_after() {
|
|||
"###);
|
||||
test_env.jj_cmd_ok(&repo_path, &["op", "restore", &setup_opid]);
|
||||
|
||||
// Rebase a commit after a commit in a branch of a merge commit.
|
||||
// Rebase a commit after a commit in a bookmark of a merge commit.
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["rebase", "-r", "f", "--after", "b1"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
|
|
@ -1459,7 +1459,7 @@ fn test_rebase_revisions_after() {
|
|||
"###);
|
||||
test_env.jj_cmd_ok(&repo_path, &["op", "restore", &setup_opid]);
|
||||
|
||||
// Rebase a commit after the last commit in a branch of a merge commit.
|
||||
// Rebase a commit after the last commit in a bookmark of a merge commit.
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["rebase", "-r", "f", "--after", "b2"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
|
|
@ -1850,7 +1850,7 @@ fn test_rebase_revisions_before() {
|
|||
"###);
|
||||
test_env.jj_cmd_ok(&repo_path, &["op", "restore", &setup_opid]);
|
||||
|
||||
// Rebase a commit before a commit in a branch of a merge commit.
|
||||
// Rebase a commit before a commit in a bookmark of a merge commit.
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["rebase", "-r", "f", "--before", "b2"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
|
|
@ -1877,7 +1877,7 @@ fn test_rebase_revisions_before() {
|
|||
"###);
|
||||
test_env.jj_cmd_ok(&repo_path, &["op", "restore", &setup_opid]);
|
||||
|
||||
// Rebase a commit before the first commit in a branch of a merge commit.
|
||||
// Rebase a commit before the first commit in a bookmark of a merge commit.
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["rebase", "-r", "f", "--before", "b1"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
|
|
@ -1963,7 +1963,7 @@ fn test_rebase_revisions_before() {
|
|||
"###);
|
||||
test_env.jj_cmd_ok(&repo_path, &["op", "restore", &setup_opid]);
|
||||
|
||||
// Rebase a commit before two commits in separate branches to create a merge
|
||||
// Rebase a commit before two commits in separate bookmarks to create a merge
|
||||
// commit.
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(
|
||||
&repo_path,
|
||||
|
|
@ -2455,12 +2455,12 @@ fn test_rebase_skip_if_on_destination() {
|
|||
}
|
||||
|
||||
fn get_log_output(test_env: &TestEnvironment, repo_path: &Path) -> String {
|
||||
let template = "branches ++ surround(': ', '', parents.map(|c| c.branches()))";
|
||||
let template = "bookmarks ++ surround(': ', '', parents.map(|c| c.bookmarks()))";
|
||||
test_env.jj_cmd_success(repo_path, &["log", "-T", template])
|
||||
}
|
||||
|
||||
fn get_long_log_output(test_env: &TestEnvironment, repo_path: &Path) -> String {
|
||||
let template = "branches ++ ' ' ++ change_id.shortest(8) ++ ' ' ++ commit_id.shortest(8) ++ \
|
||||
surround(': ', '', parents.map(|c| c.branches()))";
|
||||
let template = "bookmarks ++ ' ' ++ change_id.shortest(8) ++ ' ' ++ commit_id.shortest(8) \
|
||||
++ surround(': ', '', parents.map(|c| c.bookmarks()))";
|
||||
test_env.jj_cmd_success(repo_path, &["log", "-T", template])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,11 +35,11 @@ fn create_commit(
|
|||
for (name, content) in files {
|
||||
std::fs::write(repo_path.join(name), content).unwrap();
|
||||
}
|
||||
test_env.jj_cmd_ok(repo_path, &["branch", "create", name]);
|
||||
test_env.jj_cmd_ok(repo_path, &["bookmark", "create", name]);
|
||||
}
|
||||
|
||||
fn get_log_output(test_env: &TestEnvironment, repo_path: &Path) -> String {
|
||||
test_env.jj_cmd_success(repo_path, &["log", "-T", "branches"])
|
||||
test_env.jj_cmd_success(repo_path, &["log", "-T", "bookmarks"])
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -278,9 +278,9 @@ fn create_commit(
|
|||
for (name, content) in files {
|
||||
std::fs::write(repo_path.join(name), content).unwrap();
|
||||
}
|
||||
test_env.jj_cmd_ok(repo_path, &["branch", "create", name]);
|
||||
test_env.jj_cmd_ok(repo_path, &["bookmark", "create", name]);
|
||||
}
|
||||
|
||||
fn get_log_output(test_env: &TestEnvironment, repo_path: &Path) -> String {
|
||||
test_env.jj_cmd_success(repo_path, &["log", "-T", "branches"])
|
||||
test_env.jj_cmd_success(repo_path, &["log", "-T", "bookmarks"])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -197,28 +197,28 @@ fn test_bad_function_call() {
|
|||
4: Invalid component ".." in repo-relative path "../out"
|
||||
"###);
|
||||
|
||||
let stderr = test_env.jj_cmd_failure(&repo_path, &["log", "-r", "branches(bad:pattern)"]);
|
||||
let stderr = test_env.jj_cmd_failure(&repo_path, &["log", "-r", "bookmarks(bad:pattern)"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Error: Failed to parse revset: Invalid string pattern
|
||||
Caused by:
|
||||
1: --> 1:10
|
||||
1: --> 1:11
|
||||
|
|
||||
1 | branches(bad:pattern)
|
||||
| ^---------^
|
||||
1 | bookmarks(bad:pattern)
|
||||
| ^---------^
|
||||
|
|
||||
= Invalid string pattern
|
||||
2: Invalid string pattern kind "bad:"
|
||||
Hint: Try prefixing with one of `exact:`, `glob:`, `regex:`, or `substring:`
|
||||
"###);
|
||||
|
||||
let stderr = test_env.jj_cmd_failure(&repo_path, &["log", "-r", "branches(regex:'(')"]);
|
||||
let stderr = test_env.jj_cmd_failure(&repo_path, &["log", "-r", "bookmarks(regex:'(')"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Error: Failed to parse revset: Invalid string pattern
|
||||
Caused by:
|
||||
1: --> 1:10
|
||||
1: --> 1:11
|
||||
|
|
||||
1 | branches(regex:'(')
|
||||
| ^-------^
|
||||
1 | bookmarks(regex:'(')
|
||||
| ^-------^
|
||||
|
|
||||
= Invalid string pattern
|
||||
2: regex parse error:
|
||||
|
|
@ -240,48 +240,48 @@ fn test_bad_function_call() {
|
|||
|
||||
let stderr = test_env.jj_cmd_failure(
|
||||
&repo_path,
|
||||
&["log", "-r", "remote_branches(a, b, remote=c)"],
|
||||
&["log", "-r", "remote_bookmarks(a, b, remote=c)"],
|
||||
);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Error: Failed to parse revset: Function "remote_branches": Got multiple values for keyword "remote"
|
||||
Caused by: --> 1:23
|
||||
Error: Failed to parse revset: Function "remote_bookmarks": Got multiple values for keyword "remote"
|
||||
Caused by: --> 1:24
|
||||
|
|
||||
1 | remote_branches(a, b, remote=c)
|
||||
| ^------^
|
||||
1 | remote_bookmarks(a, b, remote=c)
|
||||
| ^------^
|
||||
|
|
||||
= Function "remote_branches": Got multiple values for keyword "remote"
|
||||
= Function "remote_bookmarks": Got multiple values for keyword "remote"
|
||||
"###);
|
||||
|
||||
let stderr =
|
||||
test_env.jj_cmd_failure(&repo_path, &["log", "-r", "remote_branches(remote=a, b)"]);
|
||||
test_env.jj_cmd_failure(&repo_path, &["log", "-r", "remote_bookmarks(remote=a, b)"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Error: Failed to parse revset: Function "remote_branches": Positional argument follows keyword argument
|
||||
Caused by: --> 1:27
|
||||
Error: Failed to parse revset: Function "remote_bookmarks": Positional argument follows keyword argument
|
||||
Caused by: --> 1:28
|
||||
|
|
||||
1 | remote_branches(remote=a, b)
|
||||
| ^
|
||||
1 | remote_bookmarks(remote=a, b)
|
||||
| ^
|
||||
|
|
||||
= Function "remote_branches": Positional argument follows keyword argument
|
||||
= Function "remote_bookmarks": Positional argument follows keyword argument
|
||||
"###);
|
||||
|
||||
let stderr = test_env.jj_cmd_failure(&repo_path, &["log", "-r", "remote_branches(=foo)"]);
|
||||
let stderr = test_env.jj_cmd_failure(&repo_path, &["log", "-r", "remote_bookmarks(=foo)"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Error: Failed to parse revset: Syntax error
|
||||
Caused by: --> 1:17
|
||||
Caused by: --> 1:18
|
||||
|
|
||||
1 | remote_branches(=foo)
|
||||
| ^---
|
||||
1 | remote_bookmarks(=foo)
|
||||
| ^---
|
||||
|
|
||||
= expected <identifier> or <expression>
|
||||
"###);
|
||||
|
||||
let stderr = test_env.jj_cmd_failure(&repo_path, &["log", "-r", "remote_branches(remote=)"]);
|
||||
let stderr = test_env.jj_cmd_failure(&repo_path, &["log", "-r", "remote_bookmarks(remote=)"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Error: Failed to parse revset: Syntax error
|
||||
Caused by: --> 1:24
|
||||
Caused by: --> 1:25
|
||||
|
|
||||
1 | remote_branches(remote=)
|
||||
| ^---
|
||||
1 | remote_bookmarks(remote=)
|
||||
| ^---
|
||||
|
|
||||
= expected <expression>
|
||||
"###);
|
||||
|
|
@ -297,23 +297,23 @@ fn test_function_name_hint() {
|
|||
test_env.add_config(
|
||||
r###"
|
||||
[revset-aliases]
|
||||
'branches(x)' = 'x' # override builtin function
|
||||
'bookmarks(x)' = 'x' # override builtin function
|
||||
'my_author(x)' = 'author(x)' # similar name to builtin function
|
||||
'author_sym' = 'x' # not a function alias
|
||||
'my_branches' = 'branch()' # typo in alias
|
||||
'my_bookmarks' = 'bookmark()' # typo in alias
|
||||
"###,
|
||||
);
|
||||
|
||||
// The suggestion "branches" shouldn't be duplicated
|
||||
insta::assert_snapshot!(evaluate_err("branch()"), @r###"
|
||||
Error: Failed to parse revset: Function "branch" doesn't exist
|
||||
// The suggestion "bookmarks" shouldn't be duplicated
|
||||
insta::assert_snapshot!(evaluate_err("bookmark()"), @r###"
|
||||
Error: Failed to parse revset: Function "bookmark" doesn't exist
|
||||
Caused by: --> 1:1
|
||||
|
|
||||
1 | branch()
|
||||
| ^----^
|
||||
1 | bookmark()
|
||||
| ^------^
|
||||
|
|
||||
= Function "branch" doesn't exist
|
||||
Hint: Did you mean "branches", "reachable"?
|
||||
= Function "bookmark" doesn't exist
|
||||
Hint: Did you mean "bookmarks", "remote_bookmarks"?
|
||||
"###);
|
||||
|
||||
// Both builtin function and function alias should be suggested
|
||||
|
|
@ -328,22 +328,22 @@ fn test_function_name_hint() {
|
|||
Hint: Did you mean "author", "author_date", "my_author"?
|
||||
"###);
|
||||
|
||||
insta::assert_snapshot!(evaluate_err("my_branches"), @r###"
|
||||
Error: Failed to parse revset: Alias "my_branches" cannot be expanded
|
||||
insta::assert_snapshot!(evaluate_err("my_bookmarks"), @r###"
|
||||
Error: Failed to parse revset: Alias "my_bookmarks" cannot be expanded
|
||||
Caused by:
|
||||
1: --> 1:1
|
||||
|
|
||||
1 | my_branches
|
||||
| ^---------^
|
||||
1 | my_bookmarks
|
||||
| ^----------^
|
||||
|
|
||||
= Alias "my_branches" cannot be expanded
|
||||
= Alias "my_bookmarks" cannot be expanded
|
||||
2: --> 1:1
|
||||
|
|
||||
1 | branch()
|
||||
| ^----^
|
||||
1 | bookmark()
|
||||
| ^------^
|
||||
|
|
||||
= Function "branch" doesn't exist
|
||||
Hint: Did you mean "branches", "reachable"?
|
||||
= Function "bookmark" doesn't exist
|
||||
Hint: Did you mean "bookmarks", "remote_bookmarks"?
|
||||
"###);
|
||||
}
|
||||
|
||||
|
|
@ -555,11 +555,11 @@ fn test_all_modifier() {
|
|||
"###);
|
||||
|
||||
// Command that accepts only single revision
|
||||
let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["branch", "create", "-rall:@", "x"]);
|
||||
let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "-rall:@", "x"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Created 1 branches pointing to qpvuntsm 230dd059 x | (empty) (no description set)
|
||||
Created 1 bookmarks pointing to qpvuntsm 230dd059 x | (empty) (no description set)
|
||||
"###);
|
||||
let stderr = test_env.jj_cmd_failure(&repo_path, &["branch", "set", "-rall:all()", "x"]);
|
||||
let stderr = test_env.jj_cmd_failure(&repo_path, &["bookmark", "set", "-rall:all()", "x"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Error: Revset "all:all()" resolved to more than one revision
|
||||
Hint: The revset "all:all()" resolved to these revisions:
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ use std::path::PathBuf;
|
|||
use crate::common::TestEnvironment;
|
||||
|
||||
fn get_log_output(test_env: &TestEnvironment, cwd: &Path) -> String {
|
||||
let template = r#"separate(" ", change_id.short(), empty, description, local_branches)"#;
|
||||
let template = r#"separate(" ", change_id.short(), empty, description, local_bookmarks)"#;
|
||||
test_env.jj_cmd_success(cwd, &["log", "-T", template])
|
||||
}
|
||||
|
||||
|
|
@ -220,9 +220,9 @@ fn test_split_with_default_description() {
|
|||
std::fs::write(workspace_path.join("file1"), "foo\n").unwrap();
|
||||
std::fs::write(workspace_path.join("file2"), "bar\n").unwrap();
|
||||
|
||||
// Create a branch pointing to the commit. It will be moved to the second
|
||||
// Create a bookmark pointing to the commit. It will be moved to the second
|
||||
// commit after the split.
|
||||
test_env.jj_cmd_ok(&workspace_path, &["branch", "create", "test_branch"]);
|
||||
test_env.jj_cmd_ok(&workspace_path, &["bookmark", "create", "test_bookmark"]);
|
||||
|
||||
let edit_script = test_env.set_up_fake_editor();
|
||||
std::fs::write(
|
||||
|
|
@ -234,8 +234,8 @@ fn test_split_with_default_description() {
|
|||
insta::assert_snapshot!(stdout, @"");
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
First part: qpvuntsm 48018df6 TESTED=TODO
|
||||
Second part: kkmpptxz 350b4c13 test_branch | (no description set)
|
||||
Working copy now at: kkmpptxz 350b4c13 test_branch | (no description set)
|
||||
Second part: kkmpptxz 350b4c13 test_bookmark | (no description set)
|
||||
Working copy now at: kkmpptxz 350b4c13 test_bookmark | (no description set)
|
||||
Parent commit : qpvuntsm 48018df6 TESTED=TODO
|
||||
"###);
|
||||
|
||||
|
|
@ -257,7 +257,7 @@ fn test_split_with_default_description() {
|
|||
"###);
|
||||
assert!(!test_env.env_root().join("editor2").exists());
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &workspace_path), @r###"
|
||||
@ kkmpptxzrspx false test_branch
|
||||
@ kkmpptxzrspx false test_bookmark
|
||||
○ qpvuntsmwlqt false TESTED=TODO
|
||||
◆ zzzzzzzzzzzz true
|
||||
"###);
|
||||
|
|
@ -328,11 +328,11 @@ fn test_split_siblings_no_descendants() {
|
|||
std::fs::write(workspace_path.join("file1"), "foo\n").unwrap();
|
||||
std::fs::write(workspace_path.join("file2"), "bar\n").unwrap();
|
||||
|
||||
// Create a branch pointing to the commit. It will be moved to the second
|
||||
// Create a bookmark pointing to the commit. It will be moved to the second
|
||||
// commit after the split.
|
||||
test_env.jj_cmd_ok(&workspace_path, &["branch", "create", "test_branch"]);
|
||||
test_env.jj_cmd_ok(&workspace_path, &["bookmark", "create", "test_bookmark"]);
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &workspace_path), @r###"
|
||||
@ qpvuntsmwlqt false test_branch
|
||||
@ qpvuntsmwlqt false test_bookmark
|
||||
◆ zzzzzzzzzzzz true
|
||||
"###);
|
||||
|
||||
|
|
@ -346,13 +346,13 @@ fn test_split_siblings_no_descendants() {
|
|||
insta::assert_snapshot!(stdout, @"");
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
First part: qpvuntsm 0dced07a TESTED=TODO
|
||||
Second part: zsuskuln 0473f014 test_branch | (no description set)
|
||||
Working copy now at: zsuskuln 0473f014 test_branch | (no description set)
|
||||
Second part: zsuskuln 0473f014 test_bookmark | (no description set)
|
||||
Working copy now at: zsuskuln 0473f014 test_bookmark | (no description set)
|
||||
Parent commit : zzzzzzzz 00000000 (empty) (no description set)
|
||||
Added 0 files, modified 0 files, removed 1 files
|
||||
"###);
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &workspace_path), @r###"
|
||||
@ zsuskulnrvyr false test_branch
|
||||
@ zsuskulnrvyr false test_bookmark
|
||||
│ ○ qpvuntsmwlqt false TESTED=TODO
|
||||
├─╯
|
||||
◆ zzzzzzzzzzzz true
|
||||
|
|
|
|||
|
|
@ -23,13 +23,13 @@ fn test_squash() {
|
|||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let repo_path = test_env.env_root().join("repo");
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "a"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "a"]);
|
||||
std::fs::write(repo_path.join("file1"), "a\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "b"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "b"]);
|
||||
std::fs::write(repo_path.join("file1"), "b\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "c"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "c"]);
|
||||
std::fs::write(repo_path.join("file1"), "c\n").unwrap();
|
||||
// Test the setup
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
|
||||
|
|
@ -85,10 +85,10 @@ fn test_squash() {
|
|||
test_env.jj_cmd_ok(&repo_path, &["undo"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["edit", "b"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "d"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "d"]);
|
||||
std::fs::write(repo_path.join("file2"), "d\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "c", "d"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "e"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "e"]);
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
|
||||
@ 41219719ab5f e (empty)
|
||||
├─╮
|
||||
|
|
@ -137,15 +137,15 @@ fn test_squash_partial() {
|
|||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let repo_path = test_env.env_root().join("repo");
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "a"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "a"]);
|
||||
std::fs::write(repo_path.join("file1"), "a\n").unwrap();
|
||||
std::fs::write(repo_path.join("file2"), "a\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "b"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "b"]);
|
||||
std::fs::write(repo_path.join("file1"), "b\n").unwrap();
|
||||
std::fs::write(repo_path.join("file2"), "b\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "c"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "c"]);
|
||||
std::fs::write(repo_path.join("file1"), "c\n").unwrap();
|
||||
std::fs::write(repo_path.join("file2"), "c\n").unwrap();
|
||||
// Test the setup
|
||||
|
|
@ -283,13 +283,13 @@ fn test_squash_keep_emptied() {
|
|||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let repo_path = test_env.env_root().join("repo");
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "a"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "a"]);
|
||||
std::fs::write(repo_path.join("file1"), "a\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "b"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "b"]);
|
||||
std::fs::write(repo_path.join("file1"), "b\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "c"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "c"]);
|
||||
std::fs::write(repo_path.join("file1"), "c\n").unwrap();
|
||||
// Test the setup
|
||||
|
||||
|
|
@ -337,25 +337,25 @@ fn test_squash_from_to() {
|
|||
//
|
||||
// When moving changes between e.g. C and F, we should not get unrelated changes
|
||||
// from B and D.
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "a"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "a"]);
|
||||
std::fs::write(repo_path.join("file1"), "a\n").unwrap();
|
||||
std::fs::write(repo_path.join("file2"), "a\n").unwrap();
|
||||
std::fs::write(repo_path.join("file3"), "a\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "b"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "b"]);
|
||||
std::fs::write(repo_path.join("file3"), "b\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "c"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "c"]);
|
||||
std::fs::write(repo_path.join("file1"), "c\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["edit", "a"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "d"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "d"]);
|
||||
std::fs::write(repo_path.join("file3"), "d\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "e"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "e"]);
|
||||
std::fs::write(repo_path.join("file2"), "e\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "f"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "f"]);
|
||||
std::fs::write(repo_path.join("file2"), "f\n").unwrap();
|
||||
// Test the setup
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
|
||||
|
|
@ -469,20 +469,20 @@ fn test_squash_from_to_partial() {
|
|||
// D B
|
||||
// |/
|
||||
// A
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "a"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "a"]);
|
||||
std::fs::write(repo_path.join("file1"), "a\n").unwrap();
|
||||
std::fs::write(repo_path.join("file2"), "a\n").unwrap();
|
||||
std::fs::write(repo_path.join("file3"), "a\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "b"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "b"]);
|
||||
std::fs::write(repo_path.join("file3"), "b\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "c"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "c"]);
|
||||
std::fs::write(repo_path.join("file1"), "c\n").unwrap();
|
||||
std::fs::write(repo_path.join("file2"), "c\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["edit", "a"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "d"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "d"]);
|
||||
std::fs::write(repo_path.join("file3"), "d\n").unwrap();
|
||||
// Test the setup
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
|
||||
|
|
@ -651,22 +651,22 @@ fn test_squash_from_multiple() {
|
|||
// \|/
|
||||
// A
|
||||
let file = repo_path.join("file");
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "a"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "a"]);
|
||||
std::fs::write(&file, "a\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "b"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "b"]);
|
||||
std::fs::write(&file, "b\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "@-"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "c"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "c"]);
|
||||
std::fs::write(&file, "c\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "@-"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "d"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "d"]);
|
||||
std::fs::write(&file, "d\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "all:visible_heads()"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "e"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "e"]);
|
||||
std::fs::write(&file, "e\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "f"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "f"]);
|
||||
std::fs::write(&file, "f\n").unwrap();
|
||||
// Test the setup
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
|
||||
|
|
@ -770,27 +770,27 @@ fn test_squash_from_multiple_partial() {
|
|||
// A
|
||||
let file1 = repo_path.join("file1");
|
||||
let file2 = repo_path.join("file2");
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "a"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "a"]);
|
||||
std::fs::write(&file1, "a\n").unwrap();
|
||||
std::fs::write(&file2, "a\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "b"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "b"]);
|
||||
std::fs::write(&file1, "b\n").unwrap();
|
||||
std::fs::write(&file2, "b\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "@-"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "c"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "c"]);
|
||||
std::fs::write(&file1, "c\n").unwrap();
|
||||
std::fs::write(&file2, "c\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "@-"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "d"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "d"]);
|
||||
std::fs::write(&file1, "d\n").unwrap();
|
||||
std::fs::write(&file2, "d\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "all:visible_heads()"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "e"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "e"]);
|
||||
std::fs::write(&file1, "e\n").unwrap();
|
||||
std::fs::write(&file2, "e\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "f"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "f"]);
|
||||
std::fs::write(&file1, "f\n").unwrap();
|
||||
std::fs::write(&file2, "f\n").unwrap();
|
||||
// Test the setup
|
||||
|
|
@ -1005,7 +1005,7 @@ fn get_log_output(test_env: &TestEnvironment, repo_path: &Path) -> String {
|
|||
let template = r#"separate(
|
||||
" ",
|
||||
commit_id.short(),
|
||||
branches,
|
||||
bookmarks,
|
||||
description,
|
||||
if(empty, "(empty)")
|
||||
)"#;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ fn create_commit(
|
|||
for (name, content) in files {
|
||||
std::fs::write(repo_path.join(name), content).unwrap();
|
||||
}
|
||||
test_env.jj_cmd_ok(repo_path, &["branch", "create", name]);
|
||||
test_env.jj_cmd_ok(repo_path, &["bookmark", "create", name]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -77,7 +77,7 @@ fn test_status_merge() {
|
|||
|
||||
std::fs::write(repo_path.join("file"), "base").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-m=left"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "left"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "left"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "@-", "-m=right"]);
|
||||
std::fs::write(repo_path.join("file"), "right").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "left", "@"]);
|
||||
|
|
|
|||
|
|
@ -32,20 +32,20 @@ fn test_tag_list() {
|
|||
};
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "root()", "-mcommit1"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "branch1"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "bookmark1"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "root()", "-mcommit2"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "branch2"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "bookmark2"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "root()", "-mcommit3"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "branch3"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "bookmark3"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "export"]);
|
||||
|
||||
copy_ref("refs/heads/branch1", "refs/tags/test_tag");
|
||||
copy_ref("refs/heads/branch2", "refs/tags/test_tag2");
|
||||
copy_ref("refs/heads/branch1", "refs/tags/conflicted_tag");
|
||||
copy_ref("refs/heads/bookmark1", "refs/tags/test_tag");
|
||||
copy_ref("refs/heads/bookmark2", "refs/tags/test_tag2");
|
||||
copy_ref("refs/heads/bookmark1", "refs/tags/conflicted_tag");
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "import"]);
|
||||
copy_ref("refs/heads/branch2", "refs/tags/conflicted_tag");
|
||||
copy_ref("refs/heads/bookmark2", "refs/tags/conflicted_tag");
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "import"]);
|
||||
copy_ref("refs/heads/branch3", "refs/tags/conflicted_tag");
|
||||
copy_ref("refs/heads/bookmark3", "refs/tags/conflicted_tag");
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "import", "--at-op=@-"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["status"]); // resolve concurrent ops
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ fn test_git_push_undo() {
|
|||
let repo_path = test_env.env_root().join("repo");
|
||||
|
||||
test_env.advance_test_rng_seed_to_multiple_of(100_000);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "main"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "main"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "AA"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "push"]);
|
||||
test_env.advance_test_rng_seed_to_multiple_of(100_000);
|
||||
|
|
@ -68,7 +68,7 @@ fn test_git_push_undo() {
|
|||
// ------------------------------------------
|
||||
// local `main` | BB | -- | --
|
||||
// remote-tracking | AA | AA | AA
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
main: qpvuntsm 75e78001 (empty) BB
|
||||
@origin (ahead by 1 commits, behind by 1 commits): qpvuntsm hidden 2080bdb8 (empty) AA
|
||||
"###);
|
||||
|
|
@ -80,7 +80,7 @@ fn test_git_push_undo() {
|
|||
// ------------------------------------------
|
||||
// local `main` | BB | -- | --
|
||||
// remote-tracking | BB | BB | BB
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
main: qpvuntsm 75e78001 (empty) BB
|
||||
@origin: qpvuntsm 75e78001 (empty) BB
|
||||
"###);
|
||||
|
|
@ -93,7 +93,7 @@ fn test_git_push_undo() {
|
|||
// ------------------------------------------
|
||||
// local `main` | BB | -- | --
|
||||
// remote-tracking | AA | AA | BB
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
main: qpvuntsm 75e78001 (empty) BB
|
||||
@origin (ahead by 1 commits, behind by 1 commits): qpvuntsm hidden 2080bdb8 (empty) AA
|
||||
"###);
|
||||
|
|
@ -106,9 +106,9 @@ fn test_git_push_undo() {
|
|||
// have been).
|
||||
//
|
||||
// One option to solve this would be to have undo not restore remote-tracking
|
||||
// branches, but that also has undersired consequences: the second fetch in `jj
|
||||
// git fetch && jj undo && jj git fetch` would become a no-op.
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
// bookmarks, but that also has undersired consequences: the second fetch in
|
||||
// `jj git fetch && jj undo && jj git fetch` would become a no-op.
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
main (conflicted):
|
||||
- qpvuntsm hidden 2080bdb8 (empty) AA
|
||||
+ qpvuntsm?? 20b2cc4b (empty) CC
|
||||
|
|
@ -129,7 +129,7 @@ fn test_git_push_undo_with_import() {
|
|||
let repo_path = test_env.env_root().join("repo");
|
||||
|
||||
test_env.advance_test_rng_seed_to_multiple_of(100_000);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "main"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "main"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "AA"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "push"]);
|
||||
test_env.advance_test_rng_seed_to_multiple_of(100_000);
|
||||
|
|
@ -141,7 +141,7 @@ fn test_git_push_undo_with_import() {
|
|||
// ------------------------------------------
|
||||
// local `main` | BB | -- | --
|
||||
// remote-tracking | AA | AA | AA
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
main: qpvuntsm 75e78001 (empty) BB
|
||||
@origin (ahead by 1 commits, behind by 1 commits): qpvuntsm hidden 2080bdb8 (empty) AA
|
||||
"###);
|
||||
|
|
@ -153,7 +153,7 @@ fn test_git_push_undo_with_import() {
|
|||
// ------------------------------------------
|
||||
// local `main` | BB | -- | --
|
||||
// remote-tracking | BB | BB | BB
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
main: qpvuntsm 75e78001 (empty) BB
|
||||
@origin: qpvuntsm 75e78001 (empty) BB
|
||||
"###);
|
||||
|
|
@ -166,14 +166,14 @@ fn test_git_push_undo_with_import() {
|
|||
// ------------------------------------------
|
||||
// local `main` | BB | -- | --
|
||||
// remote-tracking | AA | AA | BB
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
main: qpvuntsm 75e78001 (empty) BB
|
||||
@origin (ahead by 1 commits, behind by 1 commits): qpvuntsm hidden 2080bdb8 (empty) AA
|
||||
"###);
|
||||
|
||||
// PROBLEM: inserting this import changes the outcome compared to previous test
|
||||
// TODO: decide if this is the better behavior, and whether import of
|
||||
// remote-tracking branches should happen on every operation.
|
||||
// remote-tracking bookmarks should happen on every operation.
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "import"]);
|
||||
// | jj refs | jj's | git
|
||||
// | | git | repo
|
||||
|
|
@ -181,7 +181,7 @@ fn test_git_push_undo_with_import() {
|
|||
// ------------------------------------------
|
||||
// local `main` | BB | -- | --
|
||||
// remote-tracking | BB | BB | BB
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
main: qpvuntsm 75e78001 (empty) BB
|
||||
@origin: qpvuntsm 75e78001 (empty) BB
|
||||
"###);
|
||||
|
|
@ -190,7 +190,7 @@ fn test_git_push_undo_with_import() {
|
|||
test_env.jj_cmd_ok(&repo_path, &["git", "fetch"]);
|
||||
// There is not a conflict. This seems like a good outcome; undoing `git push`
|
||||
// was essentially a no-op.
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
main: qpvuntsm 20b2cc4b (empty) CC
|
||||
@origin (ahead by 1 commits, behind by 1 commits): qpvuntsm hidden 75e78001 (empty) BB
|
||||
"###);
|
||||
|
|
@ -209,7 +209,7 @@ fn test_git_push_undo_colocated() {
|
|||
test_env.jj_cmd_ok(&repo_path, &["git", "init", "--git-repo=."]);
|
||||
|
||||
test_env.advance_test_rng_seed_to_multiple_of(100_000);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "main"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "main"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "AA"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "push"]);
|
||||
test_env.advance_test_rng_seed_to_multiple_of(100_000);
|
||||
|
|
@ -221,7 +221,7 @@ fn test_git_push_undo_colocated() {
|
|||
// ------------------------------------------
|
||||
// local `main` | BB | BB | BB
|
||||
// remote-tracking | AA | AA | AA
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
main: qpvuntsm 75e78001 (empty) BB
|
||||
@git: qpvuntsm 75e78001 (empty) BB
|
||||
@origin (ahead by 1 commits, behind by 1 commits): qpvuntsm hidden 2080bdb8 (empty) AA
|
||||
|
|
@ -234,7 +234,7 @@ fn test_git_push_undo_colocated() {
|
|||
// ------------------------------------------
|
||||
// local `main` | BB | BB | BB
|
||||
// remote-tracking | BB | BB | BB
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
main: qpvuntsm 75e78001 (empty) BB
|
||||
@git: qpvuntsm 75e78001 (empty) BB
|
||||
@origin: qpvuntsm 75e78001 (empty) BB
|
||||
|
|
@ -256,7 +256,7 @@ fn test_git_push_undo_colocated() {
|
|||
// ------------------------------------------
|
||||
// local `main` | BB | BB | BB
|
||||
// remote-tracking | AA | AA | AA
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
main: qpvuntsm 75e78001 (empty) BB
|
||||
@git: qpvuntsm 75e78001 (empty) BB
|
||||
@origin (ahead by 1 commits, behind by 1 commits): qpvuntsm hidden 2080bdb8 (empty) AA
|
||||
|
|
@ -266,7 +266,7 @@ fn test_git_push_undo_colocated() {
|
|||
test_env.jj_cmd_ok(&repo_path, &["git", "fetch"]);
|
||||
// We have the same conflict as `test_git_push_undo`. TODO: why did we get the
|
||||
// same result in a seemingly different way?
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
main (conflicted):
|
||||
- qpvuntsm hidden 2080bdb8 (empty) AA
|
||||
+ qpvuntsm?? 20b2cc4b (empty) CC
|
||||
|
|
@ -277,7 +277,7 @@ fn test_git_push_undo_colocated() {
|
|||
}
|
||||
|
||||
// This test is currently *identical* to `test_git_push_undo` except
|
||||
// both the git_refs and the remote-tracking branches are preserved by undo.
|
||||
// both the git_refs and the remote-tracking bookmarks are preserved by undo.
|
||||
// TODO: Investigate the different outcome
|
||||
#[test]
|
||||
fn test_git_push_undo_repo_only() {
|
||||
|
|
@ -289,28 +289,28 @@ fn test_git_push_undo_repo_only() {
|
|||
let repo_path = test_env.env_root().join("repo");
|
||||
|
||||
test_env.advance_test_rng_seed_to_multiple_of(100_000);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "main"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "main"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "AA"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "push"]);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
main: qpvuntsm 2080bdb8 (empty) AA
|
||||
@origin: qpvuntsm 2080bdb8 (empty) AA
|
||||
"###);
|
||||
test_env.advance_test_rng_seed_to_multiple_of(100_000);
|
||||
test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "BB"]);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
main: qpvuntsm 75e78001 (empty) BB
|
||||
@origin (ahead by 1 commits, behind by 1 commits): qpvuntsm hidden 2080bdb8 (empty) AA
|
||||
"###);
|
||||
let pre_push_opid = test_env.current_operation_id(&repo_path);
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "push"]);
|
||||
|
||||
// Undo the push, but keep both the git_refs and the remote-tracking branches
|
||||
// Undo the push, but keep both the git_refs and the remote-tracking bookmarks
|
||||
test_env.jj_cmd_ok(
|
||||
&repo_path,
|
||||
&["op", "restore", "--what=repo", &pre_push_opid],
|
||||
);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
main: qpvuntsm 75e78001 (empty) BB
|
||||
@origin: qpvuntsm 75e78001 (empty) BB
|
||||
"###);
|
||||
|
|
@ -318,14 +318,14 @@ fn test_git_push_undo_repo_only() {
|
|||
test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "CC"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "fetch"]);
|
||||
// This currently gives an identical result to `test_git_push_undo_import`.
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
main: qpvuntsm 20b2cc4b (empty) CC
|
||||
@origin (ahead by 1 commits, behind by 1 commits): qpvuntsm hidden 75e78001 (empty) BB
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_branch_track_untrack_undo() {
|
||||
fn test_bookmark_track_untrack_undo() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.add_config(r#"revset-aliases."immutable_heads()" = "none()""#);
|
||||
let git_repo_path = test_env.env_root().join("git-repo");
|
||||
|
|
@ -334,10 +334,10 @@ fn test_branch_track_untrack_undo() {
|
|||
let repo_path = test_env.env_root().join("repo");
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["describe", "-mcommit"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "feature1", "feature2"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "feature1", "feature2"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["git", "push"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "delete", "feature2"]);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "delete", "feature2"]);
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
feature1: qpvuntsm 8da1cfc8 (empty) commit
|
||||
@origin: qpvuntsm 8da1cfc8 (empty) commit
|
||||
feature2 (deleted)
|
||||
|
|
@ -347,16 +347,16 @@ fn test_branch_track_untrack_undo() {
|
|||
// Track/untrack can be undone so long as states can be trivially merged.
|
||||
test_env.jj_cmd_ok(
|
||||
&repo_path,
|
||||
&["branch", "untrack", "feature1@origin", "feature2@origin"],
|
||||
&["bookmark", "untrack", "feature1@origin", "feature2@origin"],
|
||||
);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
feature1: qpvuntsm 8da1cfc8 (empty) commit
|
||||
feature1@origin: qpvuntsm 8da1cfc8 (empty) commit
|
||||
feature2@origin: qpvuntsm 8da1cfc8 (empty) commit
|
||||
"###);
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["undo"]);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
feature1: qpvuntsm 8da1cfc8 (empty) commit
|
||||
@origin: qpvuntsm 8da1cfc8 (empty) commit
|
||||
feature2 (deleted)
|
||||
|
|
@ -364,28 +364,28 @@ fn test_branch_track_untrack_undo() {
|
|||
"###);
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["undo"]);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
feature1: qpvuntsm 8da1cfc8 (empty) commit
|
||||
feature1@origin: qpvuntsm 8da1cfc8 (empty) commit
|
||||
feature2@origin: qpvuntsm 8da1cfc8 (empty) commit
|
||||
"###);
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "track", "feature1@origin"]);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "track", "feature1@origin"]);
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
feature1: qpvuntsm 8da1cfc8 (empty) commit
|
||||
@origin: qpvuntsm 8da1cfc8 (empty) commit
|
||||
feature2@origin: qpvuntsm 8da1cfc8 (empty) commit
|
||||
"###);
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["undo"]);
|
||||
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
||||
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
|
||||
feature1: qpvuntsm 8da1cfc8 (empty) commit
|
||||
feature1@origin: qpvuntsm 8da1cfc8 (empty) commit
|
||||
feature2@origin: qpvuntsm 8da1cfc8 (empty) commit
|
||||
"###);
|
||||
}
|
||||
|
||||
fn get_branch_output(test_env: &TestEnvironment, repo_path: &Path) -> String {
|
||||
// --quiet to suppress deleted branches hint
|
||||
test_env.jj_cmd_success(repo_path, &["branch", "list", "--all-remotes", "--quiet"])
|
||||
fn get_bookmark_output(test_env: &TestEnvironment, repo_path: &Path) -> String {
|
||||
// --quiet to suppress deleted bookmarks hint
|
||||
test_env.jj_cmd_success(repo_path, &["bookmark", "list", "--all-remotes", "--quiet"])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,13 +23,13 @@ fn test_unsquash() {
|
|||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let repo_path = test_env.env_root().join("repo");
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "a"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "a"]);
|
||||
std::fs::write(repo_path.join("file1"), "a\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "b"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "b"]);
|
||||
std::fs::write(repo_path.join("file1"), "b\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "c"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "c"]);
|
||||
std::fs::write(repo_path.join("file1"), "c\n").unwrap();
|
||||
// Test the setup
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
|
||||
|
|
@ -84,10 +84,10 @@ fn test_unsquash() {
|
|||
test_env.jj_cmd_ok(&repo_path, &["undo"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["edit", "b"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "d"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "d"]);
|
||||
std::fs::write(repo_path.join("file2"), "d\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new", "-m", "merge", "c", "d"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "e"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "e"]);
|
||||
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
|
||||
@ b780e7469252 e
|
||||
├─╮
|
||||
|
|
@ -135,15 +135,15 @@ fn test_unsquash_partial() {
|
|||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let repo_path = test_env.env_root().join("repo");
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "a"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "a"]);
|
||||
std::fs::write(repo_path.join("file1"), "a\n").unwrap();
|
||||
std::fs::write(repo_path.join("file2"), "a\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "b"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "b"]);
|
||||
std::fs::write(repo_path.join("file1"), "b\n").unwrap();
|
||||
std::fs::write(repo_path.join("file2"), "b\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "c"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "c"]);
|
||||
std::fs::write(repo_path.join("file1"), "c\n").unwrap();
|
||||
std::fs::write(repo_path.join("file2"), "c\n").unwrap();
|
||||
// Test the setup
|
||||
|
|
@ -256,7 +256,7 @@ fn test_unsquash_partial() {
|
|||
}
|
||||
|
||||
fn get_log_output(test_env: &TestEnvironment, repo_path: &Path) -> String {
|
||||
let template = r#"commit_id.short() ++ " " ++ branches"#;
|
||||
let template = r#"commit_id.short() ++ " " ++ bookmarks"#;
|
||||
test_env.jj_cmd_success(repo_path, &["log", "-T", template])
|
||||
}
|
||||
|
||||
|
|
|
|||
32
docs/FAQ.md
32
docs/FAQ.md
|
|
@ -1,19 +1,19 @@
|
|||
# Frequently asked questions
|
||||
|
||||
### Why does my branch not move to the new commit after `jj new/commit`?
|
||||
### Why does my bookmark not move to the new commit after `jj new/commit`?
|
||||
|
||||
If you're familiar with Git, you might expect the current branch to move forward
|
||||
when you commit. However, Jujutsu does not have a concept of a "current branch".
|
||||
If you're familiar with Git, you might expect the current bookmark to move forward
|
||||
when you commit. However, Jujutsu does not have a concept of a "current bookmark".
|
||||
|
||||
To move branches, use `jj branch set`.
|
||||
To move bookmarks, use `jj bookmark set`.
|
||||
|
||||
### I made a commit and `jj git push --all` says "Nothing changed" instead of pushing it. What do I do?
|
||||
|
||||
`jj git push --all` pushes all _branches_, not all revisions. You have two
|
||||
`jj git push --all` pushes all _bookmarks_, not all revisions. You have two
|
||||
options:
|
||||
|
||||
* Using `jj git push --change` will automatically create a branch and push it.
|
||||
* Using `jj branch` commands to create or move a branch to either the commit
|
||||
* Using `jj git push --change` will automatically create a bookmark and push it.
|
||||
* Using `jj bookmark` commands to create or move a bookmark to either the commit
|
||||
you want to push or a descendant on it. Unlike Git, Jujutsu doesn't do this
|
||||
automatically (see previous question).
|
||||
|
||||
|
|
@ -262,15 +262,15 @@ this is to abandon the unneeded commits (using `jj abandon <commit ID>`). If you
|
|||
would like to keep both commits with this change ID, you can `jj duplicate` one
|
||||
of them before abandoning it.
|
||||
|
||||
### How do I deal with conflicted branches ('??' after branch name)?
|
||||
### How do I deal with conflicted bookmarks ('??' after bookmark name)?
|
||||
|
||||
A [conflicted branch][branches_conflicts] is a branch that refers to multiple
|
||||
A [conflicted bookmark][bookmarks_conflicts] is a bookmark that refers to multiple
|
||||
different commits because jj couldn't fully resolve its desired position.
|
||||
Resolving conflicted branches is usually done by setting the branch to the
|
||||
correct commit using `jj branch set <commit ID>`.
|
||||
Resolving conflicted bookmarks is usually done by setting the bookmark to the
|
||||
correct commit using `jj bookmark set <commit ID>`.
|
||||
|
||||
Usually, the different commits associated with the conflicted branch should all
|
||||
appear in the log, but if they don't you can use `jj branch list`to show all the
|
||||
Usually, the different commits associated with the conflicted bookmark should all
|
||||
appear in the log, but if they don't you can use `jj bookmark list`to show all the
|
||||
commits associated with it.
|
||||
|
||||
### How do I integrate Jujutsu with Gerrit?
|
||||
|
|
@ -282,15 +282,15 @@ contributor (look for the `jj signoff` alias).
|
|||
|
||||
After you have attached the `Change-Id:` footer to the commit series, you'll
|
||||
have to manually invoke `git push` of `HEAD` on the underlying git repository
|
||||
into the remote Gerrit branch `refs/for/$BRANCH`, where `$BRANCH` is the base
|
||||
branch you want your changes to go to (e.g., `git push origin
|
||||
into the remote Gerrit bookmark `refs/for/$BRANCH`, where `$BRANCH` is the base
|
||||
bookmark you want your changes to go to (e.g., `git push origin
|
||||
HEAD:refs/for/main`). Using a [co-located][co-located] repo
|
||||
will make the underlying git repo directly accessible from the working
|
||||
directory.
|
||||
|
||||
We hope to integrate with Gerrit natively in the future.
|
||||
|
||||
[branches_conflicts]: branches.md#conflicts
|
||||
[bookmarks_conflicts]: bookmarks.md#conflicts
|
||||
|
||||
[change ID]: glossary.md#change-id
|
||||
[co-located]: glossary.md#co-located-repos
|
||||
|
|
|
|||
221
docs/bookmarks.md
Normal file
221
docs/bookmarks.md
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
# Bookmarks
|
||||
|
||||
|
||||
## Introduction
|
||||
|
||||
Bookmarks are named pointers to revisions (just like branches are in Git). You
|
||||
can move them without affecting the target revision's identity. Bookmarks
|
||||
automatically move when revisions are rewritten (e.g. by `jj rebase`). You can
|
||||
pass a bookmark's name to commands that want a revision as argument. For example,
|
||||
`jj new main` will create a new revision on top of the "main" bookmark. Use
|
||||
`jj bookmark list` to list bookmarks and `jj bookmark` to create, move, or delete
|
||||
bookmarks. There is currently no concept of an active/current/checked-out bookmark.
|
||||
|
||||
Currently Jujutsu maps its Bookmarks to Git Branches and stores them as that
|
||||
in the Git backend. This means that all Bookmarks will be reflected as
|
||||
Git Branches, this may change in the future.
|
||||
|
||||
## Remotes and tracked bookmarks
|
||||
|
||||
Jujutsu records the last seen position of a bookmark on each remote (just like
|
||||
Git's remote-tracking branches). This record is updated on every `jj git fetch`
|
||||
and `jj git push` of the bookmark. You can refer to the remembered remote bookmark
|
||||
positions with `<bookmark name>@<remote name>`, such as `jj new main@origin`. `jj`
|
||||
does not provide a way to manually edit these recorded positions.
|
||||
|
||||
A remote bookmark can be associated with a local bookmark of the same name. This is
|
||||
called a **tracked remote bookmark**, which currently maps to a Git remote
|
||||
branch. When you pull a tracked bookmark from a remote, any changes compared to
|
||||
the current record of the remote's state will be propagated to the corresponding
|
||||
local bookmark, which will be created if it doesn't exist already.
|
||||
|
||||
!!! note "Details: how `fetch` pulls bookmarks"
|
||||
|
||||
Let's say you run `jj git fetch --remote origin` and, during the fetch, `jj`
|
||||
determines that the remote's "main" bookmark has been moved so that its target is
|
||||
now ahead of the local record in `main@origin`.
|
||||
|
||||
`jj` will then update `main@origin` to the new target. If `main@origin` is
|
||||
**tracked**, `jj` will also apply the change to the local bookmark `main`. If the
|
||||
local target has also been moved compared to `main@origin` (probably because you
|
||||
ran `jj bookmark set main`), then the two updates will be merged. If one is ahead
|
||||
of the other, then that target will become the new target. Otherwise, the local
|
||||
bookmark will become conflicted (see the ["Conflicts" section](#conflicts) below
|
||||
for details).
|
||||
|
||||
Most commands don't show the tracked remote bookmark if it has the same target as
|
||||
the local bookmark. The local bookmark (without `@<remote name>`) is considered the
|
||||
bookmark's desired target. Consequently, if you want to update a bookmark on a
|
||||
remote, you first update the bookmark locally and then push the update to the
|
||||
remote. If a local bookmark also exists on some remote but points to a different
|
||||
target there, `jj log` will show the bookmark name with an asterisk suffix (e.g.
|
||||
`main*`). That is meant to remind you that you may want to push the bookmark to
|
||||
some remote.
|
||||
|
||||
If you want to know the internals of bookmark tracking, consult the
|
||||
[Design Doc][design].
|
||||
|
||||
### Terminology summary
|
||||
|
||||
- A **remote bookmark** is a bookmark ref on the remote. `jj` can find out its
|
||||
actual state only when it's actively communicating with the remote. However,
|
||||
`jj` does store the last-seen position of the remote bookmark; this is the
|
||||
commit `jj show <bookmark name>@<remote name>` would show. This notion is
|
||||
completely analogous to Git's "remote-tracking bookmarks".
|
||||
- A **tracked (remote) bookmark** is defined above. You can make a remote bookmark
|
||||
tracked with the [`jj bookmark track` command](#manually-tracking-a-bookmark), for
|
||||
example.
|
||||
- A **tracking (local) bookmark** is the local bookmark that `jj` tries to keep in
|
||||
sync with the tracked remote bookmark. For example, after `jj bookmark track
|
||||
mybookmark@origin`, there will be a local bookmark `mybookmark` that's tracking the
|
||||
remote `mybookmark@origin` bookmark. A local bookmark can track a bookmark of the same
|
||||
name on 0 or more remotes.
|
||||
|
||||
The notion of tracked bookmarks serves a similar function to the Git notion of an
|
||||
"upstream branch". Unlike Git, a single local bookmark can be tracking remote
|
||||
bookmarks on multiple remotes, and the names of the local and remote bookmarks
|
||||
must match.
|
||||
|
||||
### Manually tracking a bookmark
|
||||
|
||||
To track a bookmark permanently use `jj bookmark track <bookmark name>@<remote name>`.
|
||||
It will now be imported as a local bookmark until you untrack it or it is deleted
|
||||
on the remote.
|
||||
|
||||
Example:
|
||||
|
||||
```sh
|
||||
$ # List all available bookmarks, as we want our colleague's bookmark.
|
||||
$ jj bookmark list --all
|
||||
$ # Find the bookmark.
|
||||
$ # [...]
|
||||
$ # Actually track the bookmark.
|
||||
$ jj bookmark track <bookmark name>@<remote name> # Example: jj bookmark track my-feature@origin
|
||||
$ # From this point on, <bookmark name> will be imported when fetching from <remote name>.
|
||||
$ jj git fetch --remote <remote name>
|
||||
$ # A local bookmark <bookmark name> should have been created or updated while fetching.
|
||||
$ jj new <bookmark name> # Do some local testing, etc.
|
||||
```
|
||||
|
||||
### Untracking a bookmark
|
||||
|
||||
To stop following a remote bookmark, you can `jj bookmark untrack` it. After that,
|
||||
subsequent fetches of that remote will no longer move the local bookmark to match
|
||||
the position of the remote bookmark.
|
||||
|
||||
Example:
|
||||
|
||||
```sh
|
||||
$ # List all local and remote bookmarks.
|
||||
$ jj bookmark list --all
|
||||
$ # Find the bookmark we no longer want to track.
|
||||
$ # [...]
|
||||
# # Actually untrack it.
|
||||
$ jj bookmark untrack <bookmark name>@<remote name> # Example: jj bookmark untrack stuff@origin
|
||||
$ # From this point on, this remote bookmark won't be imported anymore.
|
||||
$ # The local bookmark (e.g. stuff) is unaffected. It may or may not still
|
||||
$ # be tracking bookmarks on other remotes (e.g. stuff@upstream).
|
||||
```
|
||||
|
||||
### Listing tracked bookmarks
|
||||
|
||||
To list tracked bookmarks, you can `jj bookmark list --tracked` or `jj bookmark list -t`.
|
||||
This command omits local Git-tracking bookmarks by default.
|
||||
|
||||
You can see if a specific bookmark is tracked with `jj bookmark list --tracked <bookmark name>`.
|
||||
|
||||
|
||||
### Automatic tracking of bookmarks & `git.auto-local-bookmark` option
|
||||
|
||||
There are two situations where `jj` tracks bookmarks automatically. `jj git
|
||||
clone` automatically sets up the default remote bookmark (e.g. `main@origin`) as
|
||||
tracked. When you push a local bookmark, the newly created bookmark on the remote is
|
||||
marked as tracked.
|
||||
|
||||
By default, every other remote bookmark is marked as "not tracked" when it's
|
||||
fetched. If desired, you need to manually `jj bookmark track` them. This works
|
||||
well for repositories where multiple people work on a large number of bookmarks.
|
||||
|
||||
The default can be changed by setting the config `git.auto-local-bookmark = true`.
|
||||
Then, `jj git fetch` tracks every *newly fetched* bookmark with a local bookmark.
|
||||
Branches that already existed before the `jj git fetch` are not affected. This
|
||||
is similar to Mercurial, which fetches all its bookmarks (equivalent to Git
|
||||
bookmarks) by default.
|
||||
|
||||
## Bookmark movement
|
||||
|
||||
Currently Jujutsu automatically moves local bookmarks when these conditions are
|
||||
met:
|
||||
|
||||
* When a commit has been rewritten (e.g, when you rebase) bookmarks and the
|
||||
working-copy will move along with it.
|
||||
* When a commit has been abandoned, all associated bookmarks will be moved
|
||||
to its parent(s). If a working copy was pointing to the abandoned commit,
|
||||
then a new working-copy commit will be created on top of the parent(s).
|
||||
|
||||
You could describe the movement as following along the change-id of the
|
||||
current bookmark commit, even if it isn't entirely accurate.
|
||||
|
||||
## Pushing bookmarks: Safety checks
|
||||
|
||||
Before `jj git push` actually moves, creates, or deletes a remote bookmark, it
|
||||
makes several safety checks.
|
||||
|
||||
1. `jj` will contact the remote and check that the actual state of the remote
|
||||
bookmark matches `jj`'s record of its last known position. If there is a
|
||||
conflict, `jj` will refuse to push the bookmark. In this case, you need to run
|
||||
`jj git fetch --remote <remote name>` and resolve the resulting bookmark
|
||||
conflict. Then, you can try `jj git push` again.
|
||||
|
||||
If you are familiar with Git, this makes `jj git push` similar to `git
|
||||
push --force-with-lease`.
|
||||
|
||||
There are a few cases where `jj git push` will succeed even though the remote
|
||||
bookmark is in an unexpected location. These are the cases where `jj git fetch`
|
||||
would not create a bookmark conflict and would not move the local bookmark, e.g.
|
||||
if the unexpected location is identical to the local position of the bookmark.
|
||||
|
||||
2. The local bookmark must not be [conflicted](#conflicts). If it is, you would
|
||||
need to use `jj bookmark set`, for example, to resolve the conflict.
|
||||
|
||||
This makes `jj git push` safe even if `jj git fetch` is performed on a timer
|
||||
in the background (this situation is a known issue[^known-issue] with some
|
||||
forms of `git push --force-with-lease`). If the bookmark moves on a remote in a
|
||||
problematic way, `jj git fetch` will create a conflict. This should ensure
|
||||
that the user becomes aware of the conflict before they can `jj git push` and
|
||||
override the bookmark on the remote.
|
||||
|
||||
3. If the remote bookmark already exists on the remote, it must be
|
||||
[tracked](#remotes-and-tracked-bookmarks). If the bookmark does not already
|
||||
exist on the remote, there is no problem; `jj git push` will create the
|
||||
remote bookmark and mark it as tracked.
|
||||
|
||||
[^known-issue]: See "A general note on safety" in
|
||||
<https://git-scm.com/docs/git-push#Documentation/git-push.txt---no-force-with-lease>
|
||||
|
||||
|
||||
## Conflicts
|
||||
|
||||
Bookmarks can end up in a conflicted state. When that happens, `jj status` will
|
||||
include information about the conflicted bookmarks (and instructions for how to
|
||||
mitigate it). `jj bookmark list` will have details. `jj log` will show the bookmark
|
||||
name with a double question mark suffix (e.g. `main??`) on each of the
|
||||
conflicted bookmark's potential target revisions. Using the bookmark name to look up
|
||||
a revision will resolve to all potential targets. That means that `jj new main`
|
||||
will error out, complaining that the revset resolved to multiple revisions.
|
||||
|
||||
Both local bookmarks (e.g. `main`) and the remote bookmark (e.g. `main@origin`) can
|
||||
have conflicts. Both can end up in that state if concurrent operations were run
|
||||
in the repo. The local bookmark more typically becomes conflicted because it was
|
||||
updated both locally and on a remote.
|
||||
|
||||
To resolve a conflicted state in a local bookmark (e.g. `main`), you can move the
|
||||
bookmark to the desired target with `jj bookmark move`. You may want to first either
|
||||
merge the conflicted targets with `jj new` (e.g. `jj new 'all:main'`), or you may
|
||||
want to rebase one side on top of the other with `jj rebase`.
|
||||
|
||||
To resolve a conflicted state in a remote bookmark (e.g. `main@origin`), simply
|
||||
pull from the remote (e.g. `jj git fetch`). The conflict resolution will also
|
||||
propagate to the local bookmark (which was presumably also conflicted).
|
||||
|
||||
[design]: design/tracking-branches.md
|
||||
217
docs/branches.md
217
docs/branches.md
|
|
@ -1,217 +0,0 @@
|
|||
# Branches
|
||||
|
||||
|
||||
## Introduction
|
||||
|
||||
Branches are named pointers to revisions (just like they are in Git). You can
|
||||
move them without affecting the target revision's identity. Branches
|
||||
automatically move when revisions are rewritten (e.g. by `jj rebase`). You can
|
||||
pass a branch's name to commands that want a revision as argument. For example,
|
||||
`jj new main` will create a new revision on top of the "main" branch. Use
|
||||
`jj branch list` to list branches and `jj branch` to create, move, or delete
|
||||
branches. There is currently no concept of an active/current/checked-out branch.
|
||||
|
||||
## Remotes and tracked branches
|
||||
|
||||
Jujutsu records the last seen position of a branch on each remote (just like
|
||||
Git's remote-tracking branches). This record is updated on every `jj git fetch`
|
||||
and `jj git push` of the branch. You can refer to the remembered remote branch
|
||||
positions with `<branch name>@<remote name>`, such as `jj new main@origin`. `jj`
|
||||
does not provide a way to manually edit these recorded positions.
|
||||
|
||||
A remote branch can be associated with a local branch of the same name. This is
|
||||
called a **tracked remote branch**. When you pull a tracked branch from a
|
||||
remote, any changes compared to the current record of the remote's state will be
|
||||
propagated to the corresponding local branch, which will be created if it
|
||||
doesn't exist already.
|
||||
|
||||
!!! note "Details: how `fetch` pulls branches"
|
||||
|
||||
Let's say you run `jj git fetch --remote origin` and, during the fetch, `jj`
|
||||
determines that the remote's "main" branch has been moved so that its target is
|
||||
now ahead of the local record in `main@origin`.
|
||||
|
||||
`jj` will then update `main@origin` to the new target. If `main@origin` is
|
||||
**tracked**, `jj` will also apply the change to the local branch `main`. If the
|
||||
local target has also been moved compared to `main@origin` (probably because you
|
||||
ran `jj branch set main`), then the two updates will be merged. If one is ahead
|
||||
of the other, then that target will become the new target. Otherwise, the local
|
||||
branch will become conflicted (see the ["Conflicts" section](#conflicts) below
|
||||
for details).
|
||||
|
||||
Most commands don't show the tracked remote branch if it has the same target as
|
||||
the local branch. The local branch (without `@<remote name>`) is considered the
|
||||
branch's desired target. Consequently, if you want to update a branch on a
|
||||
remote, you first update the branch locally and then push the update to the
|
||||
remote. If a local branch also exists on some remote but points to a different
|
||||
target there, `jj log` will show the branch name with an asterisk suffix (e.g.
|
||||
`main*`). That is meant to remind you that you may want to push the branch to
|
||||
some remote.
|
||||
|
||||
If you want to know the internals of branch tracking, consult the
|
||||
[Design Doc][design].
|
||||
|
||||
### Terminology summary
|
||||
|
||||
- A **remote branch** is a branch ref on the remote. `jj` can find out its
|
||||
actual state only when it's actively communicating with the remote. However,
|
||||
`jj` does store the last-seen position of the remote branch; this is the
|
||||
commit `jj show <branch name>@<remote name>` would show. This notion is
|
||||
completely analogous to Git's "remote-tracking branches".
|
||||
- A **tracked (remote) branch** is defined above. You can make a remote branch
|
||||
tracked with the [`jj branch track` command](#manually-tracking-a-branch), for
|
||||
example.
|
||||
- A **tracking (local) branch** is the local branch that `jj` tries to keep in
|
||||
sync with the tracked remote branch. For example, after `jj branch track
|
||||
mybranch@origin`, there will be a local branch `mybranch` that's tracking the
|
||||
remote `mybranch@origin` branch. A local branch can track a branch of the same
|
||||
name on 0 or more remotes.
|
||||
|
||||
The notion of tracked branches serves a similar function to the Git notion of an
|
||||
"upstream branch". Unlike Git, a single local branch can be tracking remote
|
||||
branches on multiple remotes, and the names of the local and remote branches
|
||||
must match.
|
||||
|
||||
### Manually tracking a branch
|
||||
|
||||
To track a branch permanently use `jj branch track <branch name>@<remote name>`.
|
||||
It will now be imported as a local branch until you untrack it or it is deleted
|
||||
on the remote.
|
||||
|
||||
Example:
|
||||
|
||||
```sh
|
||||
$ # List all available branches, as we want our colleague's branch.
|
||||
$ jj branch list --all
|
||||
$ # Find the branch.
|
||||
$ # [...]
|
||||
$ # Actually track the branch.
|
||||
$ jj branch track <branch name>@<remote name> # Example: jj branch track my-feature@origin
|
||||
$ # From this point on, <branch name> will be imported when fetching from <remote name>.
|
||||
$ jj git fetch --remote <remote name>
|
||||
$ # A local branch <branch name> should have been created or updated while fetching.
|
||||
$ jj new <branch name> # Do some local testing, etc.
|
||||
```
|
||||
|
||||
### Untracking a branch
|
||||
|
||||
To stop following a remote branch, you can `jj branch untrack` it. After that,
|
||||
subsequent fetches of that remote will no longer move the local branch to match
|
||||
the position of the remote branch.
|
||||
|
||||
Example:
|
||||
|
||||
```sh
|
||||
$ # List all local and remote branches.
|
||||
$ jj branch list --all
|
||||
$ # Find the branch we no longer want to track.
|
||||
$ # [...]
|
||||
# # Actually untrack it.
|
||||
$ jj branch untrack <branch name>@<remote name> # Example: jj branch untrack stuff@origin
|
||||
$ # From this point on, this remote branch won't be imported anymore.
|
||||
$ # The local branch (e.g. stuff) is unaffected. It may or may not still
|
||||
$ # be tracking branches on other remotes (e.g. stuff@upstream).
|
||||
```
|
||||
|
||||
### Listing tracked branches
|
||||
|
||||
To list tracked branches, you can `jj branch list --tracked` or `jj branch list -t`.
|
||||
This command omits local Git-tracking branches by default.
|
||||
|
||||
You can see if a specific branch is tracked with `jj branch list --tracked <branch name>`.
|
||||
|
||||
|
||||
### Automatic tracking of branches & `git.auto-local-branch` option
|
||||
|
||||
There are two situations where `jj` tracks branches automatically. `jj git
|
||||
clone` automatically sets up the default remote branch (e.g. `main@origin`) as
|
||||
tracked. When you push a local branch, the newly created branch on the remote is
|
||||
marked as tracked.
|
||||
|
||||
By default, every other remote branch is marked as "not tracked" when it's
|
||||
fetched. If desired, you need to manually `jj branch track` them. This works
|
||||
well for repositories where multiple people work on a large number of branches.
|
||||
|
||||
The default can be changed by setting the config `git.auto-local-branch = true`.
|
||||
Then, `jj git fetch` tracks every *newly fetched* branch with a local branch.
|
||||
Branches that already existed before the `jj git fetch` are not affected. This
|
||||
is similar to Mercurial, which fetches all its bookmarks (equivalent to Git
|
||||
branches) by default.
|
||||
|
||||
## Branch movement
|
||||
|
||||
Currently Jujutsu automatically moves local branches when these conditions are
|
||||
met:
|
||||
|
||||
* When a commit has been rewritten (e.g, when you rebase) branches and the
|
||||
working-copy will move along with it.
|
||||
* When a commit has been abandoned, all associated branches will be moved
|
||||
to its parent(s). If a working copy was pointing to the abandoned commit,
|
||||
then a new working-copy commit will be created on top of the parent(s).
|
||||
|
||||
You could describe the movement as following along the change-id of the
|
||||
current branch commit, even if it isn't entirely accurate.
|
||||
|
||||
## Pushing branches: Safety checks
|
||||
|
||||
Before `jj git push` actually moves, creates, or deletes a remote branch, it
|
||||
makes several safety checks.
|
||||
|
||||
1. `jj` will contact the remote and check that the actual state of the remote
|
||||
branch matches `jj`'s record of its last known position. If there is a
|
||||
conflict, `jj` will refuse to push the branch. In this case, you need to run
|
||||
`jj git fetch --remote <remote name>` and resolve the resulting branch
|
||||
conflict. Then, you can try `jj git push` again.
|
||||
|
||||
If you are familiar with Git, this makes `jj git push` similar to `git
|
||||
push --force-with-lease`.
|
||||
|
||||
There are a few cases where `jj git push` will succeed even though the remote
|
||||
branch is in an unexpected location. These are the cases where `jj git fetch`
|
||||
would not create a branch conflict and would not move the local branch, e.g.
|
||||
if the unexpected location is identical to the local position of the branch.
|
||||
|
||||
2. The local branch must not be [conflicted](#conflicts). If it is, you would
|
||||
need to use `jj branch set`, for example, to resolve the conflict.
|
||||
|
||||
This makes `jj git push` safe even if `jj git fetch` is performed on a timer
|
||||
in the background (this situation is a known issue[^known-issue] with some
|
||||
forms of `git push --force-with-lease`). If the branch moves on a remote in a
|
||||
problematic way, `jj git fetch` will create a conflict. This should ensure
|
||||
that the user becomes aware of the conflict before they can `jj git push` and
|
||||
override the branch on the remote.
|
||||
|
||||
3. If the remote branch already exists on the remote, it must be
|
||||
[tracked](#remotes-and-tracked-branches). If the branch does not already
|
||||
exist on the remote, there is no problem; `jj git push` will create the
|
||||
remote branch and mark it as tracked.
|
||||
|
||||
[^known-issue]: See "A general note on safety" in
|
||||
<https://git-scm.com/docs/git-push#Documentation/git-push.txt---no-force-with-lease>
|
||||
|
||||
|
||||
## Conflicts
|
||||
|
||||
Branches can end up in a conflicted state. When that happens, `jj status` will
|
||||
include information about the conflicted branches (and instructions for how to
|
||||
mitigate it). `jj branch list` will have details. `jj log` will show the branch
|
||||
name with a double question mark suffix (e.g. `main??`) on each of the
|
||||
conflicted branch's potential target revisions. Using the branch name to look up
|
||||
a revision will resolve to all potential targets. That means that `jj new main`
|
||||
will error out, complaining that the revset resolved to multiple revisions.
|
||||
|
||||
Both local branches (e.g. `main`) and the remote branch (e.g. `main@origin`) can
|
||||
have conflicts. Both can end up in that state if divergent operations were run
|
||||
in the repo. The local branch more typically becomes conflicted because it was
|
||||
updated both locally and on a remote.
|
||||
|
||||
To resolve a conflicted state in a local branch (e.g. `main`), you can move the
|
||||
branch to the desired target with `jj branch move`. You may want to first either
|
||||
merge the conflicted targets with `jj new` (e.g. `jj new 'all:main'`), or you may
|
||||
want to rebase one side on top of the other with `jj rebase`.
|
||||
|
||||
To resolve a conflicted state in a remote branch (e.g. `main@origin`), simply
|
||||
pull from the remote (e.g. `jj git fetch`). The conflict resolution will also
|
||||
propagate to the local branch (which was presumably also conflicted).
|
||||
|
||||
[design]: design/tracking-branches.md
|
||||
|
|
@ -266,7 +266,7 @@ diff-invocation-mode = "file-by-file"
|
|||
|
||||
You can configure the set of immutable commits via
|
||||
`revset-aliases."immutable_heads()"`. The default set of immutable heads is
|
||||
`trunk() | tags() | untracked_remote_branches()`. For example, to prevent
|
||||
`trunk() | tags() | untracked_remote_bookmarks()`. For example, to prevent
|
||||
rewriting commits on `main@origin` and commits authored by other users:
|
||||
|
||||
```toml
|
||||
|
|
@ -357,7 +357,7 @@ To customize these separately, use the `format_short_commit_id()` and
|
|||
To get shorter prefixes for certain revisions, set `revsets.short-prefixes`:
|
||||
|
||||
```toml
|
||||
# Prioritize the current branch
|
||||
# Prioritize the current bookmark
|
||||
revsets.short-prefixes = "(main..@)::"
|
||||
```
|
||||
|
||||
|
|
@ -475,8 +475,8 @@ format = "git"
|
|||
You can define aliases for commands, including their arguments. For example:
|
||||
|
||||
```toml
|
||||
# `jj l` shows commits on the working-copy commit's (anonymous) branch
|
||||
# compared to the `main` branch
|
||||
# `jj l` shows commits on the working-copy commit's (anonymous) bookmark
|
||||
# compared to the `main` bookmark
|
||||
aliases.l = ["log", "-r", "(main..@):: | (main..@)-"]
|
||||
```
|
||||
|
||||
|
|
@ -861,32 +861,32 @@ Note that unlike `git.fetch`, `git.push` can currently only be a single remote.
|
|||
This is not a hard limitation, and could be changed in the future if there is
|
||||
demand.
|
||||
|
||||
### Automatic local branch creation
|
||||
### Automatic local bookmark creation
|
||||
|
||||
When `jj` imports a new remote-tracking branch from Git, it can also create a
|
||||
local branch with the same name. This feature is disabled by default because it
|
||||
When `jj` imports a new remote-tracking bookmark from Git, it can also create a
|
||||
local bookmark with the same name. This feature is disabled by default because it
|
||||
may be undesirable in some repositories, e.g.:
|
||||
|
||||
- There is a remote with a lot of historical branches that you don't
|
||||
- There is a remote with a lot of historical bookmarks that you don't
|
||||
want to be exported to the co-located Git repo.
|
||||
- There are multiple remotes with conflicting views of that branch,
|
||||
- There are multiple remotes with conflicting views of that bookmark,
|
||||
resulting in an unhelpful conflicted state.
|
||||
|
||||
You can enable this behavior by setting `git.auto-local-branch` like so,
|
||||
You can enable this behavior by setting `git.auto-local-bookmark` like so,
|
||||
|
||||
```toml
|
||||
git.auto-local-branch = true
|
||||
git.auto-local-bookmark = true
|
||||
```
|
||||
|
||||
This setting is applied only to new remote branches. Existing remote branches
|
||||
can be tracked individually by using `jj branch track`/`untrack` commands.
|
||||
This setting is applied only to new remote bookmarks. Existing remote bookmarks
|
||||
can be tracked individually by using `jj bookmark track`/`untrack` commands.
|
||||
|
||||
```shell
|
||||
# import feature1 branch and start tracking it
|
||||
jj branch track feature1@origin
|
||||
# delete local gh-pages branch and stop tracking it
|
||||
jj branch delete gh-pages
|
||||
jj branch untrack gh-pages@upstream
|
||||
# import feature1 bookmark and start tracking it
|
||||
jj bookmark track feature1@origin
|
||||
# delete local gh-pages bookmark and stop tracking it
|
||||
jj bookmark delete gh-pages
|
||||
jj bookmark untrack gh-pages@upstream
|
||||
```
|
||||
|
||||
### Abandon commits that became unreachable in Git
|
||||
|
|
@ -903,13 +903,13 @@ git.abandon-unreachable-commits = false
|
|||
|
||||
[reachable]: https://git-scm.com/docs/gitglossary/#Documentation/gitglossary.txt-aiddefreachableareachable
|
||||
|
||||
### Prefix for generated branches on push
|
||||
### Prefix for generated bookmarks on push
|
||||
|
||||
`jj git push --change` generates branch names with a prefix of "push-" by
|
||||
default. You can pick a different prefix by setting `git.push-branch-prefix`. For
|
||||
`jj git push --change` generates bookmark names with a prefix of "push-" by
|
||||
default. You can pick a different prefix by setting `git.push-bookmark-prefix`. For
|
||||
example:
|
||||
|
||||
git.push-branch-prefix = "martinvonz/push-"
|
||||
git.push-bookmark-prefix = "martinvonz/push-"
|
||||
|
||||
### Set of private commits
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ is typical on GitHub). Instead, please make the changes in the appropriate
|
|||
commit. You can do that by creating a new commit on top of the initial commit
|
||||
(`jj new <commit>`) and then squash in the changes when you're done (`jj squash`).
|
||||
`jj git push`
|
||||
will automatically force-push the branch.
|
||||
will automatically force-push the bookmark.
|
||||
|
||||
When your first PR has been approved, we typically give you contributor access,
|
||||
so you can address any remaining minor comments and then merge the PR yourself
|
||||
|
|
@ -284,11 +284,11 @@ Windows, you'll need to understand and adapt the shell script):
|
|||
cloned from your fork of `jj` (e.g. `jjfan.github.com/jj`). You can also use a
|
||||
pure Git repo if you prefer.
|
||||
|
||||
2. Make sure `jjfan.github.com/jj` includes the `gh-pages` branch of the jj repo
|
||||
2. Make sure `jjfan.github.com/jj` includes the `gh-pages` bookmark of the jj repo
|
||||
and run `git fetch origin gh-pages`.
|
||||
|
||||
3. Go to the GitHub repository settings, enable GitHub Pages, and configure them
|
||||
to use the `gh-pages` branch (this is usually the default).
|
||||
to use the `gh-pages` bookmark (this is usually the default).
|
||||
|
||||
4. Run the same `sh` script that is used in GitHub CI (details below):
|
||||
|
||||
|
|
@ -298,8 +298,8 @@ to use the `gh-pages` branch (this is usually the default).
|
|||
```
|
||||
|
||||
This should build the version of the docs from the current commit,
|
||||
deploy it as a new commit to the `gh-pages` branch,
|
||||
and push the `gh-pages` branch to the origin.
|
||||
deploy it as a new commit to the `gh-pages` bookmark,
|
||||
and push the `gh-pages` bookmark to the origin.
|
||||
|
||||
5. Now, you should be able to see the full website, including your latest changes
|
||||
to the `prerelease` version, at `https://jjfan.github.io/jj/prerelease/`.
|
||||
|
|
@ -315,18 +315,18 @@ back and forth, you can also rebuild the docs for the latest release as follows.
|
|||
v1.33.1 latest --push
|
||||
```
|
||||
|
||||
7. (Optional) When you are done, you may want to reset the `gh-branches` to the
|
||||
7. (Optional) When you are done, you may want to reset the `gh-bookmarks` to the
|
||||
same spot as it is in the upstream. If you configured the `upstream` remote,
|
||||
this can be done with:
|
||||
|
||||
```shell
|
||||
# This will LOSE any changes you made to `gh-pages`
|
||||
jj git fetch --remote upstream
|
||||
jj branch set gh-pages -r gh-pages@upstream
|
||||
jj git push --remote origin --branch gh-pages
|
||||
jj bookmark set gh-pages -r gh-pages@upstream
|
||||
jj git push --remote origin --bookmark gh-pages
|
||||
```
|
||||
|
||||
If you want to preserve some of the changes you made, you can do `jj branch
|
||||
If you want to preserve some of the changes you made, you can do `jj bookmark
|
||||
set my-changes -r gh-pages` BEFORE running the above commands.
|
||||
|
||||
#### Explanation of the `docs-build-deploy` script
|
||||
|
|
@ -341,10 +341,10 @@ deploy`, which does the rest of the job. Run `poetry run -- mike help deploy` to
|
|||
find out what the arguments do.
|
||||
|
||||
If you need to do something more complicated, you can use `poetry run -- mike
|
||||
...` commands. You can also edit the `gh-pages` branch directly, but take care
|
||||
...` commands. You can also edit the `gh-pages` bookmark directly, but take care
|
||||
to avoid files that will be overwritten by future invocations of `mike`. Then,
|
||||
you can submit a PR based on the `gh-pages` branch of
|
||||
<https://martinvonz.github.com/jj> (instead of the usual `main` branch).
|
||||
you can submit a PR based on the `gh-pages` bookmark of
|
||||
<https://martinvonz.github.com/jj> (instead of the usual `main` bookmark).
|
||||
|
||||
|
||||
## Modifying protobuffers (this is not common)
|
||||
|
|
|
|||
|
|
@ -22,19 +22,19 @@ various use cases.
|
|||
to an intermediate commit between `HEAD` and the working copy, so workflows
|
||||
that depend on it can be modeled using proper commits instead. Jujutsu has
|
||||
excellent support for moving changes between commits. [Details](#the-index).
|
||||
* **No need for branch names (but they are supported).** Git lets you check out
|
||||
a commit without attaching a branch. It calls this state "detached HEAD". This
|
||||
* **No need for bookmark names (but they are supported).** Git lets you check out
|
||||
a commit without attaching a bookmark. It calls this state "detached HEAD". This
|
||||
is the normal state in Jujutsu (there's actually no way -- yet, at least -- to
|
||||
have an active branch). However, Jujutsu keeps track of all visible heads
|
||||
have an active bookmark). However, Jujutsu keeps track of all visible heads
|
||||
(leaves) of the commit graph, so the commits won't get lost or
|
||||
garbage-collected.
|
||||
* **No current branch.** Git lets you check out a branch, making it the 'current
|
||||
branch', and new commits will automatically update the branch. This is
|
||||
* **No current bookmark.** Git lets you check out a bookmark, making it the 'current
|
||||
bookmark', and new commits will automatically update the bookmark. This is
|
||||
necessary in Git because Git might otherwise lose track of the new commits.
|
||||
Jujutsu does not have a 'current branch'; instead, you update branches
|
||||
manually. For example, if you start work on top of a commit with a branch,
|
||||
new commits are created on top of the branch, then you issue a later command
|
||||
to update the branch.
|
||||
Jujutsu does not have a 'current bookmark'; instead, you update bookmarks
|
||||
manually. For example, if you start work on top of a commit with a bookmark,
|
||||
new commits are created on top of the bookmark, then you issue a later command
|
||||
to update the bookmark.
|
||||
* **Conflicts can be committed.** No commands fail because of merge conflicts.
|
||||
The conflicts are instead recorded in commits and you can resolve them later.
|
||||
[Details](conflicts.md).
|
||||
|
|
@ -44,10 +44,10 @@ various use cases.
|
|||
updated, and so will the working copy if it points to any of the rebased
|
||||
commits.
|
||||
* **Branches are identified by their names (across remotes).** For example, if
|
||||
you pull from a remote that has a `main` branch, you'll get a branch by that
|
||||
you pull from a remote that has a `main` bookmark, you'll get a bookmark by that
|
||||
name in your local repo as well. If you then move it and push back to the
|
||||
remote, the `main` branch on the remote will be updated.
|
||||
[Details](branches.md).
|
||||
remote, the `main` bookmark on the remote will be updated.
|
||||
[Details](bookmarks.md).
|
||||
* **The operation log replaces reflogs.** The operation log is similar to
|
||||
reflogs, but is much more powerful. It keeps track of atomic updates to all
|
||||
refs at once (Jujutsu thus improves on Git's per-ref history much in the same
|
||||
|
|
@ -56,7 +56,7 @@ various use cases.
|
|||
* **There's a single, virtual root commit.** Like Mercurial, Jujutsu has a
|
||||
virtual commit (with a hash consisting of only zeros) called the "root commit"
|
||||
(called the "null revision" in Mercurial). This commit is a common ancestor of
|
||||
all commits. That removes the awkward state Git calls the "unborn branch"
|
||||
all commits. That removes the awkward state Git calls the "unborn bookmark"
|
||||
state (which is the state a newly initialized Git repo is in), and related
|
||||
command-line flags (e.g. `git rebase --root`, `git checkout --orphan`).
|
||||
|
||||
|
|
@ -110,23 +110,23 @@ parent.
|
|||
<td><code>git clone <source> <destination></code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Update the local repo with all branches from a remote</td>
|
||||
<td>Update the local repo with all bookmarks from a remote</td>
|
||||
<td><code>jj git fetch [--remote <remote>]</code> (there is no
|
||||
support for fetching into non-Git repos yet)</td>
|
||||
<td><code>git fetch [<remote>]</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Update a remote repo with all branches from the local repo</td>
|
||||
<td>Update a remote repo with all bookmarks from the local repo</td>
|
||||
<td><code>jj git push --all [--remote <remote>]</code> (there is no
|
||||
support for pushing from non-Git repos yet)</td>
|
||||
<td><code>git push --all [<remote>]</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Update a remote repo with a single branch from the local repo</td>
|
||||
<td><code>jj git push --branch <branch name>
|
||||
<td>Update a remote repo with a single bookmark from the local repo</td>
|
||||
<td><code>jj git push --bookmark <bookmark name>
|
||||
[--remote <remote>]</code> (there is no support for
|
||||
pushing from non-Git repos yet)</td>
|
||||
<td><code>git push <remote> <branch name></code></td>
|
||||
<td><code>git push <remote> <bookmark name></code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Show summary of current work and repo status</td>
|
||||
|
|
@ -187,10 +187,10 @@ parent.
|
|||
<tr>
|
||||
<td>See log of all reachable commits</td>
|
||||
<td><code>jj log -r 'all()'</code> or <code>jj log -r ::</code></td>
|
||||
<td><code>git log --oneline --graph --decorate --branches</code></td>
|
||||
<td><code>git log --oneline --graph --decorate --bookmarks</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Show log of commits not on the main branch</td>
|
||||
<td>Show log of commits not on the main bookmark</td>
|
||||
<td><code>jj log</code></td>
|
||||
<td>(TODO)</td>
|
||||
</tr>
|
||||
|
|
@ -243,23 +243,23 @@ parent.
|
|||
<td><code>git stash</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Start working on a new change based on the <main> branch</td>
|
||||
<td>Start working on a new change based on the <main> bookmark</td>
|
||||
<td><code>jj new main</code></td>
|
||||
<td><code>git switch -c topic main</code> or
|
||||
<code>git checkout -b topic main</code> (may need to stash or commit
|
||||
first)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Move branch A onto branch B</td>
|
||||
<td>Move bookmark A onto bookmark B</td>
|
||||
<td><code>jj rebase -b A -d B</code></td>
|
||||
<td><code>git rebase B A</code>
|
||||
(may need to rebase other descendant branches separately)</td>
|
||||
(may need to rebase other descendant bookmarks separately)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Move change A and its descendants onto change B</td>
|
||||
<td><code>jj rebase -s A -d B</code></td>
|
||||
<td><code>git rebase --onto B A^ <some descendant branch></code>
|
||||
(may need to rebase other descendant branches separately)</td>
|
||||
<td><code>git rebase --onto B A^ <some descendant bookmark></code>
|
||||
(may need to rebase other descendant bookmarks separately)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Reorder changes from A-B-C-D to A-C-B-D</td>
|
||||
|
|
@ -324,29 +324,29 @@ parent.
|
|||
<td><code>git rev-parse --show-toplevel</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>List branches</td>
|
||||
<td><code>jj branch list</code></td>
|
||||
<td><code>git branch</code></td>
|
||||
<td>List bookmarks</td>
|
||||
<td><code>jj bookmark list</code></td>
|
||||
<td><code>git bookmark</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Create a branch</td>
|
||||
<td><code>jj branch create <name> -r <revision></code></td>
|
||||
<td><code>git branch <name> <revision></code></td>
|
||||
<td>Create a bookmark</td>
|
||||
<td><code>jj bookmark create <name> -r <revision></code></td>
|
||||
<td><code>git bookmark <name> <revision></code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Move a branch forward</td>
|
||||
<td><code>jj branch set <name> -r <revision></code></td>
|
||||
<td><code>git branch -f <name> <revision></code></td>
|
||||
<td>Move a bookmark forward</td>
|
||||
<td><code>jj bookmark set <name> -r <revision></code></td>
|
||||
<td><code>git bookmark -f <name> <revision></code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Move a branch backward or sideways</td>
|
||||
<td><code>jj branch set <name> -r <revision> --allow-backwards</code></td>
|
||||
<td><code>git branch -f <name> <revision></code></td>
|
||||
<td>Move a bookmark backward or sideways</td>
|
||||
<td><code>jj bookmark set <name> -r <revision> --allow-backwards</code></td>
|
||||
<td><code>git bookmark -f <name> <revision></code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Delete a branch</td>
|
||||
<td><code>jj branch delete <name> </code></td>
|
||||
<td><code>git branch --delete <name></code></td>
|
||||
<td>Delete a bookmark</td>
|
||||
<td><code>jj bookmark delete <name> </code></td>
|
||||
<td><code>git bookmark --delete <name></code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>See log of operations performed on the repo</td>
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ a comparison with Git, including how workflows are different, see the
|
|||
only `~/.ssh/id_rsa`, `~/.ssh/id_ed25519` or `~/.ssh/id_ed25519_sk`), or
|
||||
a `credential.helper`.
|
||||
* **Branches: Yes.** You can read more about
|
||||
[how branches work in Jujutsu](branches.md)
|
||||
[how branches work in Jujutsu](bookmarks.md)
|
||||
and [how they interoperate with Git](#branches).
|
||||
* **Tags: Partial.** You can check out tagged commits by name (pointed to be
|
||||
either annotated or lightweight tags), but you cannot create new tags.
|
||||
|
|
|
|||
|
|
@ -12,54 +12,54 @@ authenticated HTTP.
|
|||
## Basic workflow
|
||||
|
||||
The simplest way to start with Jujutsu is to create a stack of commits first.
|
||||
You will only need to create a branch when you need to push the stack to a
|
||||
remote. There are two primary workflows: using a generated branch name or
|
||||
naming a branch.
|
||||
You will only need to create a bookmark when you need to push the stack to a
|
||||
remote. There are two primary workflows: using a generated bookmark name or
|
||||
naming a bookmark.
|
||||
|
||||
### Using a generated branch name
|
||||
### Using a generated bookmark name
|
||||
|
||||
In this example we're letting Jujutsu auto-create a branch.
|
||||
In this example we're letting Jujutsu auto-create a bookmark.
|
||||
|
||||
```shell
|
||||
# Start a new commit off of the default branch.
|
||||
# Start a new commit off of the default bookmark.
|
||||
$ jj new main
|
||||
# Refactor some files, then add a description and start a new commit
|
||||
$ jj commit -m 'refactor(foo): restructure foo()'
|
||||
# Add a feature, then add a description and start a new commit
|
||||
$ jj commit -m 'feat(bar): add support for bar'
|
||||
# Let Jujutsu generate a branch name and push that to GitHub. Note that we
|
||||
# Let Jujutsu generate a bookmark name and push that to GitHub. Note that we
|
||||
# push the working-copy commit's *parent* because the working-copy commit
|
||||
# itself is empty.
|
||||
$ jj git push -c @-
|
||||
```
|
||||
|
||||
### Using a named branch
|
||||
### Using a named bookmark
|
||||
|
||||
In this example, we create a branch named `bar` and then push it to the remote.
|
||||
In this example, we create a bookmark named `bar` and then push it to the remote.
|
||||
|
||||
```shell
|
||||
# Start a new commit off of the default branch.
|
||||
# Start a new commit off of the default bookmark.
|
||||
$ jj new main
|
||||
# Refactor some files, then add a description and start a new commit
|
||||
$ jj commit -m 'refactor(foo): restructure foo()'
|
||||
# Add a feature, then add a description and start a new commit
|
||||
$ jj commit -m 'feat(bar): add support for bar'
|
||||
# Create a branch so we can push it to GitHub. Note that we created the branch
|
||||
# Create a bookmark so we can push it to GitHub. Note that we created the bookmark
|
||||
# on the working-copy commit's *parent* because the working copy itself is empty.
|
||||
$ jj branch create bar -r @- # `bar` now contains the previous two commits.
|
||||
# Push the branch to GitHub (pushes only `bar`)
|
||||
$ jj bookmark create bar -r @- # `bar` now contains the previous two commits.
|
||||
# Push the bookmark to GitHub (pushes only `bar`)
|
||||
$ jj git push
|
||||
```
|
||||
|
||||
While it's possible to create a branch in advance and commit on top of it in a
|
||||
Git-like manner, you will then need to move the branch manually when you create
|
||||
While it's possible to create a bookmark in advance and commit on top of it in a
|
||||
Git-like manner, you will then need to move the bookmark manually when you create
|
||||
a new commits. Unlike Git, Jujutsu will not do it automatically.
|
||||
|
||||
## Updating the repository
|
||||
|
||||
As of October 2023, Jujutsu has no equivalent to a `git pull` command (see
|
||||
[issue #1039][sync-issue]). Until such a command is added, you need to use
|
||||
`jj git fetch` followed by a `jj rebase -d $main_branch` to update your
|
||||
`jj git fetch` followed by a `jj rebase -d $main_bookmark` to update your
|
||||
changes.
|
||||
|
||||
[sync-issue]: https://github.com/martinvonz/jj/issues/1039
|
||||
|
|
@ -67,7 +67,7 @@ changes.
|
|||
## Working in a Git co-located repository
|
||||
|
||||
After doing `jj git init --colocate`, Git will be in a [detached HEAD
|
||||
state][detached], which is unusual, as Git mainly works with branches. In a
|
||||
state][detached], which is unusual, as Git mainly works with bookmarks. In a
|
||||
co-located repository, every `jj` command will automatically synchronize
|
||||
Jujutsu's view of the repo with Git's view. For example, `jj commit` updates the
|
||||
HEAD of the Git repository, enabling an incremental migration.
|
||||
|
|
@ -76,21 +76,21 @@ HEAD of the Git repository, enabling an incremental migration.
|
|||
$ nvim docs/tutorial.md
|
||||
$ # Do some more work.
|
||||
$ jj commit -m "Update tutorial"
|
||||
# Create a branch on the working-copy commit's parent
|
||||
$ jj branch create doc-update -r @-
|
||||
# Create a bookmark on the working-copy commit's parent
|
||||
$ jj bookmark create doc-update -r @-
|
||||
$ jj git push
|
||||
```
|
||||
|
||||
## Working in a Jujutsu repository
|
||||
|
||||
In a Jujutsu repository, the workflow is simplified. If there's no need for
|
||||
explicitly named branches, you can just generate one for a change. As Jujutsu is
|
||||
able to create a branch for a revision.
|
||||
explicitly named bookmarks, you can just generate one for a change. As Jujutsu is
|
||||
able to create a bookmark for a revision.
|
||||
|
||||
```shell
|
||||
$ # Do your work
|
||||
$ jj commit
|
||||
$ # Push change "mw", letting Jujutsu automatically create a branch called
|
||||
$ # Push change "mw", letting Jujutsu automatically create a bookmark called
|
||||
$ # "push-mwmpwkwknuz"
|
||||
$ jj git push --change mw
|
||||
```
|
||||
|
|
@ -99,7 +99,7 @@ $ jj git push --change mw
|
|||
|
||||
There are two workflows for addressing review comments, depending on your
|
||||
project's preference. Many projects prefer that you address comments by adding
|
||||
commits to your branch[^1]. Some projects (such as Jujutsu and LLVM) instead
|
||||
commits to your bookmark[^1]. Some projects (such as Jujutsu and LLVM) instead
|
||||
prefer that you keep your commits clean by rewriting them and then
|
||||
force-pushing[^2].
|
||||
|
||||
|
|
@ -109,14 +109,14 @@ If your project prefers that you address review comments by adding commits on
|
|||
top, you can do that by doing something like this:
|
||||
|
||||
```shell
|
||||
$ # Create a new commit on top of the `your-feature` branch from above.
|
||||
$ # Create a new commit on top of the `your-feature` bookmark from above.
|
||||
$ jj new your-feature
|
||||
$ # Address the comments by updating the code. Then review the changes.
|
||||
$ jj diff
|
||||
$ # Give the fix a description and create a new working-copy on top.
|
||||
$ jj commit -m 'address pr comments'
|
||||
$ # Update the branch to point to the new commit.
|
||||
$ jj branch set your-feature -r @-
|
||||
$ # Update the bookmark to point to the new commit.
|
||||
$ jj bookmark set your-feature -r @-
|
||||
$ # Push it to your remote
|
||||
$ jj git push
|
||||
```
|
||||
|
|
@ -129,14 +129,14 @@ achieved without creating a new commit.
|
|||
> still get amended to the previous commit.
|
||||
|
||||
```shell
|
||||
$ # Create a new commit on top of the `your-feature` branch from above.
|
||||
$ # Create a new commit on top of the `your-feature` bookmark from above.
|
||||
$ jj new your-feature
|
||||
$ # Address the comments by updating the code. Then review the changes.
|
||||
$ jj diff
|
||||
$ # Give the fix a description.
|
||||
$ jj describe -m 'address pr comments'
|
||||
$ # Update the branch to point to the current commit.
|
||||
$ jj branch set your-feature -r @
|
||||
$ # Update the bookmark to point to the current commit.
|
||||
$ jj bookmark set your-feature -r @
|
||||
$ # Push it to your remote
|
||||
$ jj git push
|
||||
```
|
||||
|
|
@ -154,26 +154,26 @@ $ # Address the comments by updating the code. Then review the changes.
|
|||
$ jj diff
|
||||
$ # Squash the changes into the parent commit
|
||||
$ jj squash
|
||||
$ # Push the updated branch to the remote. Jujutsu automatically makes it a
|
||||
$ # Push the updated bookmark to the remote. Jujutsu automatically makes it a
|
||||
$ # force push
|
||||
$ jj git push --branch your-feature
|
||||
$ jj git push --bookmark your-feature
|
||||
```
|
||||
|
||||
The hyphen after `your-feature` comes from the
|
||||
[revset](https://github.com/martinvonz/jj/blob/main/docs/revsets.md) syntax.
|
||||
|
||||
## Working with other people's branches
|
||||
## Working with other people's bookmarks
|
||||
|
||||
By default, `jj git clone` imports the default remote branch (which is usually
|
||||
`main` or `master`), but `jj git fetch` doesn't import new remote branches to
|
||||
local branches. This means that if you want to iterate or test another
|
||||
contributor's branch, you'll need to do `jj new <branch>@<remote>` onto it.
|
||||
By default, `jj git clone` imports the default remote bookmark (which is usually
|
||||
`main` or `master`), but `jj git fetch` doesn't import new remote bookmarks to
|
||||
local bookmarks. This means that if you want to iterate or test another
|
||||
contributor's bookmark, you'll need to do `jj new <bookmark>@<remote>` onto it.
|
||||
|
||||
If you want to import all remote branches including inactive ones, set
|
||||
`git.auto-local-branch = true` in the config file. Then you can specify a
|
||||
contributor's branch as `jj new <branch>` instead of `jj new <branch>@<remote>`.
|
||||
If you want to import all remote bookmarks including inactive ones, set
|
||||
`git.auto-local-bookmark = true` in the config file. Then you can specify a
|
||||
contributor's bookmark as `jj new <bookmark>` instead of `jj new <bookmark>@<remote>`.
|
||||
|
||||
You can find more information on that setting [here][auto-branch].
|
||||
You can find more information on that setting [here][auto-bookmark].
|
||||
|
||||
## Using GitHub CLI
|
||||
|
||||
|
|
@ -202,30 +202,30 @@ commands like `gh issue list` normally.
|
|||
|
||||
## Useful Revsets
|
||||
|
||||
Log all revisions across all local branches that aren't on the main branch nor
|
||||
Log all revisions across all local bookmarks that aren't on the main bookmark nor
|
||||
on any remote:
|
||||
|
||||
```shell
|
||||
$ jj log -r 'branches() & ~(main | remote_branches())'
|
||||
$ jj log -r 'bookmarks() & ~(main | remote_bookmarks())'
|
||||
```
|
||||
|
||||
Log all revisions that you authored, across all branches that aren't on any
|
||||
Log all revisions that you authored, across all bookmarks that aren't on any
|
||||
remote:
|
||||
|
||||
```shell
|
||||
$ jj log -r 'mine() & branches() & ~remote_branches()'
|
||||
$ jj log -r 'mine() & bookmarks() & ~remote_bookmarks()'
|
||||
```
|
||||
|
||||
Log all remote branches that you authored or committed to:
|
||||
Log all remote bookmarks that you authored or committed to:
|
||||
|
||||
```shell
|
||||
$ jj log -r 'remote_branches() & (mine() | committer(your@email.com))'
|
||||
$ jj log -r 'remote_bookmarks() & (mine() | committer(your@email.com))'
|
||||
```
|
||||
|
||||
Log all descendants of the current working copy that aren't on any remote:
|
||||
|
||||
```shell
|
||||
$ jj log -r '::@ & ~remote_branches()'
|
||||
$ jj log -r '::@ & ~remote_bookmarks()'
|
||||
```
|
||||
|
||||
## Merge conflicts
|
||||
|
|
@ -235,13 +235,13 @@ the [tutorial][tut].
|
|||
|
||||
[^1]:
|
||||
This is a GitHub-style review, as GitHub currently only is able to compare
|
||||
branches.
|
||||
bookmarks.
|
||||
|
||||
[^2]:
|
||||
If you're wondering why we prefer clean commits in this project, see
|
||||
e.g. [this blog post][stacked]
|
||||
|
||||
[auto-branch]: config.md#automatic-local-branch-creation
|
||||
[auto-bookmark]: config.md#automatic-local-bookmark-creation
|
||||
[detached]: https://git-scm.com/docs/git-checkout#_detached_head
|
||||
[gh]: https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent
|
||||
[http-auth]: https://github.com/martinvonz/jj/issues/469
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
# Glossary
|
||||
|
||||
## Anonymous branch
|
||||
## Anonymous bookmark
|
||||
|
||||
An anonymous branch is a chain of commits that doesn't have any
|
||||
[named branches](#branch) pointing to it or to any of its descendants. Unlike
|
||||
Git, Jujutsu keeps commits on anonymous branches around until they are
|
||||
explicitly abandoned. Visible anonymous branches are tracked by the
|
||||
[view](#view), which stores a list of [heads](#head) of such branches.
|
||||
An anonymous bookmark is a chain of commits that doesn't have any
|
||||
[named bookmarks](#bookmark) pointing to it or to any of its descendants. Unlike
|
||||
Git, Jujutsu keeps commits on anonymous bookmarks around until they are
|
||||
explicitly abandoned. Visible anonymous bookmarks are tracked by the
|
||||
[view](#view), which stores a list of [heads](#head) of such bookmarks.
|
||||
|
||||
## Backend
|
||||
|
||||
|
|
@ -20,15 +20,15 @@ There are also pluggable backends for storing other information than commits,
|
|||
such as the "operation store backend" for storing
|
||||
[the operation log](#operation-log).
|
||||
|
||||
## Branch
|
||||
## Bookmark
|
||||
|
||||
A branch is a named pointer to a [commit](#commit). They automatically follow
|
||||
A bookmark is a named pointer to a [commit](#commit). They automatically follow
|
||||
the commit if it gets [rewritten](#rewrite). Branches are sometimes called
|
||||
"named branches" to distinguish them from
|
||||
[anonymous branches](#anonymous-branch), but note that they are more similar
|
||||
to Git's branches than to
|
||||
[Mercurial's named branches](https://www.mercurial-scm.org/wiki/Branch#Named_branches).
|
||||
See [here](branches.md) for details.
|
||||
"named bookmarks" to distinguish them from
|
||||
[anonymous bookmarks](#anonymous-bookmark), but note that they are more similar
|
||||
to Git's bookmarks than to
|
||||
[Mercurial's named bookmarks](https://www.mercurial-scm.org/wiki/Branch#Named_bookmarks).
|
||||
See [here](bookmarks.md) for details.
|
||||
|
||||
## Change
|
||||
|
||||
|
|
@ -85,12 +85,12 @@ Those are the conflicts that users coming from other VCSs are usually familiar
|
|||
with. You can see them in `jj status` and in `jj log` (the red "conflict"
|
||||
label at the end of the line). See [here](conflicts.md) for details.
|
||||
|
||||
Conflicts can also occur in [branches](#branch). For example, if you moved a
|
||||
branch locally, and it was also moved on the remote, then the branch will be
|
||||
Conflicts can also occur in [bookmarks](#bookmark). For example, if you moved a
|
||||
bookmark locally, and it was also moved on the remote, then the bookmark will be
|
||||
in a conflicted state after you pull from the remote.
|
||||
See [here](branches.md#conflicts) for details.
|
||||
See [here](bookmarks.md#conflicts) for details.
|
||||
|
||||
Similar to a branch conflict, when a [change](#change) is rewritten locally
|
||||
Similar to a bookmark conflict, when a [change](#change) is rewritten locally
|
||||
and remotely, for example, then the change will be in a conflicted state. We
|
||||
call that a [divergent change](#divergent-change).
|
||||
|
||||
|
|
@ -105,7 +105,7 @@ A head is a commit with no descendants. The context in which it has no
|
|||
descendants varies. For example, the `heads(X)`
|
||||
[revset function](revsets.md#functions) returns commits that have no descendants
|
||||
within the set `X` itself. The [view](#view) records which
|
||||
anonymous heads (heads without a branch pointing to them) are visible at a
|
||||
anonymous heads (heads without a bookmark pointing to them) are visible at a
|
||||
given [operation](#operation). Note that this is quite different from Git's
|
||||
[HEAD](https://git-scm.com/book/en/v2/Git-Internals-Git-References#ref_the_ref).
|
||||
|
||||
|
|
@ -115,7 +115,7 @@ See [visible commits](#visible-commits).
|
|||
|
||||
## Operation
|
||||
|
||||
A snapshot of the [visible commits](#visible-commits) and [branches](#branch)
|
||||
A snapshot of the [visible commits](#visible-commits) and [bookmarks](#bookmark)
|
||||
at a given point in time (technically a [view object](#view)), together with
|
||||
some metadata. The metadata includes the username, hostname, timestamps, and
|
||||
pointers to the operation's parents.
|
||||
|
|
@ -173,12 +173,12 @@ A tree object represents a snapshot of a directory in the repository. Tree
|
|||
objects are defined recursively; each tree object only has the files and
|
||||
directories contained directly in the directory it represents.
|
||||
|
||||
## Tracked branches and tracking branches
|
||||
## Tracked bookmarks and tracking bookmarks
|
||||
|
||||
A remote branch can be made "tracked" with the `jj branch track` command. This
|
||||
results in a "tracking" local branch that tracks the remote branch.
|
||||
A remote bookmark can be made "tracked" with the `jj bookmark track` command. This
|
||||
results in a "tracking" local bookmark that tracks the remote bookmark.
|
||||
|
||||
See [the branches documentation](branches.md#terminology-summary) for a more
|
||||
See [the bookmarks documentation](bookmarks.md#terminology-summary) for a more
|
||||
detailed definition of these terms.
|
||||
|
||||
## Visible commits
|
||||
|
|
@ -195,7 +195,7 @@ accessible by their [commit id](#commit-id).
|
|||
|
||||
## View
|
||||
|
||||
A view is a snapshot of branches and their targets, anonymous heads,
|
||||
A view is a snapshot of bookmarks and their targets, anonymous heads,
|
||||
and working-copy commits. The anonymous heads define which commits
|
||||
are [visible](#visible-commits).
|
||||
|
||||
|
|
|
|||
|
|
@ -80,11 +80,11 @@ This type cannot be printed. The following methods are defined.
|
|||
working-copy commit as `<workspace name>@`.
|
||||
* `current_working_copy() -> Boolean`: True for the working-copy commit of the
|
||||
current workspace.
|
||||
* `branches() -> List<RefName>`: Local and remote branches pointing to the commit.
|
||||
A tracking remote branch will be included only if its target is different
|
||||
from the local one.
|
||||
* `local_branches() -> List<RefName>`: All local branches pointing to the commit.
|
||||
* `remote_branches() -> List<RefName>`: All remote branches pointing to the commit.
|
||||
* `bookmarks() -> List<RefName>`: Local and remote bookmarks pointing to the
|
||||
commit. A tracking remote branch will be included only if its target is
|
||||
different from the local one.
|
||||
* `local_bookmarks() -> List<RefName>`: All local bookmarks pointing to the commit.
|
||||
* `remote_bookmarks() -> List<RefName>`: All remote bookmarks pointing to the commit.
|
||||
* `tags() -> List<RefName>`
|
||||
* `git_refs() -> List<RefName>`
|
||||
* `git_head() -> Option<RefName>`
|
||||
|
|
@ -162,7 +162,7 @@ The following methods are defined.
|
|||
* `.remote() -> String`: Remote name or empty if this is a local ref.
|
||||
* `.present() -> Boolean`: True if the ref points to any commit.
|
||||
* `.conflict() -> Boolean`: True if [the branch or tag is
|
||||
conflicted](branches.md#conflicts).
|
||||
conflicted](bookmarks.md#conflicts).
|
||||
* `.normal_target() -> Option<Commit>`: Target commit if the ref is not
|
||||
conflicted and points to a commit.
|
||||
* `.removed_targets() -> List<Commit>`: Old target commits if conflicted.
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ where
|
|||
/// For example, topological order of chronological data should respect
|
||||
/// timestamp (except a few outliers caused by clock skew.)
|
||||
///
|
||||
/// Use `topo_order_reverse()` if the DAG is heavily branched. This can
|
||||
/// Use `topo_order_reverse()` if the DAG is heavily bookmarked. This can
|
||||
/// only process linear part lazily.
|
||||
pub fn topo_order_reverse_lazy<T, ID, II, NI>(
|
||||
start: II,
|
||||
|
|
@ -277,7 +277,7 @@ impl<T: Ord, ID: Hash + Eq + Clone, E> TopoOrderReverseLazyInner<T, ID, E> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Splits DAG at single fork point, and extracts branchy part as sub graph.
|
||||
/// Splits DAG at single fork point, and extracts bookmarky part as sub graph.
|
||||
///
|
||||
/// ```text
|
||||
/// o | C
|
||||
|
|
@ -286,9 +286,9 @@ impl<T: Ord, ID: Hash + Eq + Clone, E> TopoOrderReverseLazyInner<T, ID, E> {
|
|||
/// o A
|
||||
/// ```
|
||||
///
|
||||
/// If a branch reached to root (empty neighbors), the graph can't be split
|
||||
/// anymore because the other branch may be connected to a descendant of
|
||||
/// the rooted branch.
|
||||
/// If a bookmark reached to root (empty neighbors), the graph can't be split
|
||||
/// anymore because the other bookmark may be connected to a descendant of
|
||||
/// the rooted bookmark.
|
||||
///
|
||||
/// ```text
|
||||
/// o | C
|
||||
|
|
@ -809,7 +809,7 @@ mod tests {
|
|||
assert_eq!(common, vec!['E', 'D', 'C', 'B', 'a']);
|
||||
|
||||
// The root node 'a' is visited before 'C'. If the graph were split there,
|
||||
// the branch 'C->B->a' would be orphaned.
|
||||
// the bookmark 'C->B->a' would be orphaned.
|
||||
let common = topo_order_reverse_lazy(vec!['E'], id_fn, neighbors_fn).collect_vec();
|
||||
assert_eq!(common, vec!['E', 'D', 'C', 'B', 'a']);
|
||||
|
||||
|
|
@ -1067,7 +1067,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_topo_order_reverse_cycle_to_branchy_sub_graph() {
|
||||
fn test_topo_order_reverse_cycle_to_bookmarky_sub_graph() {
|
||||
// This graph:
|
||||
// o D
|
||||
// |\
|
||||
|
|
|
|||
|
|
@ -312,18 +312,22 @@ pub fn import_some_refs(
|
|||
match ref_name {
|
||||
RefName::LocalBranch(branch) => {
|
||||
if new_remote_ref.is_tracking() {
|
||||
mut_repo.merge_local_branch(branch, base_target, &new_remote_ref.target);
|
||||
mut_repo.merge_local_bookmark(branch, base_target, &new_remote_ref.target);
|
||||
}
|
||||
// Update Git-tracking branch like the other remote branches.
|
||||
mut_repo.set_remote_branch(branch, REMOTE_NAME_FOR_LOCAL_GIT_REPO, new_remote_ref);
|
||||
mut_repo.set_remote_bookmark(
|
||||
branch,
|
||||
REMOTE_NAME_FOR_LOCAL_GIT_REPO,
|
||||
new_remote_ref,
|
||||
);
|
||||
}
|
||||
RefName::RemoteBranch { branch, remote } => {
|
||||
if new_remote_ref.is_tracking() {
|
||||
mut_repo.merge_local_branch(branch, base_target, &new_remote_ref.target);
|
||||
mut_repo.merge_local_bookmark(branch, base_target, &new_remote_ref.target);
|
||||
}
|
||||
// Remote-tracking branch is the last known state of the branch in the remote.
|
||||
// It shouldn't diverge even if we had inconsistent view.
|
||||
mut_repo.set_remote_branch(branch, remote, new_remote_ref);
|
||||
mut_repo.set_remote_bookmark(branch, remote, new_remote_ref);
|
||||
}
|
||||
RefName::Tag(name) => {
|
||||
if new_remote_ref.is_tracking() {
|
||||
|
|
@ -400,7 +404,7 @@ fn diff_refs_to_import(
|
|||
.collect();
|
||||
// TODO: migrate tags to the remote view, and don't destructure &RemoteRef
|
||||
let mut known_remote_refs: HashMap<RefName, (&RefTarget, RemoteRefState)> = itertools::chain(
|
||||
view.all_remote_branches()
|
||||
view.all_remote_bookmarks()
|
||||
.map(|((branch, remote), remote_ref)| {
|
||||
// TODO: want to abstract local ref as "git" tracking remote, but
|
||||
// we'll probably need to refactor the git_ref_filter API first.
|
||||
|
|
@ -496,7 +500,7 @@ fn default_remote_ref_state_for(ref_name: &RefName, git_settings: &GitSettings)
|
|||
// LocalBranch means Git-tracking branch
|
||||
RefName::LocalBranch(_) | RefName::Tag(_) => RemoteRefState::Tracking,
|
||||
RefName::RemoteBranch { .. } => {
|
||||
if git_settings.auto_local_branch {
|
||||
if git_settings.auto_local_bookmark {
|
||||
RemoteRefState::Tracking
|
||||
} else {
|
||||
RemoteRefState::New
|
||||
|
|
@ -512,7 +516,7 @@ fn default_remote_ref_state_for(ref_name: &RefName, git_settings: &GitSettings)
|
|||
/// tracking remotes, and such mutation isn't applied to `view.git_refs()` yet.
|
||||
fn pinned_commit_ids(view: &View) -> Vec<CommitId> {
|
||||
itertools::chain(
|
||||
view.local_branches().map(|(_, target)| target),
|
||||
view.local_bookmarks().map(|(_, target)| target),
|
||||
view.tags().values(),
|
||||
)
|
||||
.flat_map(|target| target.added_ids())
|
||||
|
|
@ -527,7 +531,7 @@ fn pinned_commit_ids(view: &View) -> Vec<CommitId> {
|
|||
/// propagate to the other remotes on later push. OTOH, untracked remote
|
||||
/// branches are considered independent refs.
|
||||
fn remotely_pinned_commit_ids(view: &View) -> Vec<CommitId> {
|
||||
view.all_remote_branches()
|
||||
view.all_remote_bookmarks()
|
||||
.filter(|(_, remote_ref)| !remote_ref.is_tracking())
|
||||
.map(|(_, remote_ref)| &remote_ref.target)
|
||||
.flat_map(|target| target.added_ids())
|
||||
|
|
@ -747,7 +751,7 @@ fn copy_exportable_local_branches_to_remote_view(
|
|||
) {
|
||||
let new_local_branches = mut_repo
|
||||
.view()
|
||||
.local_remote_branches(remote_name)
|
||||
.local_remote_bookmarks(remote_name)
|
||||
.filter_map(|(branch, targets)| {
|
||||
// TODO: filter out untracked branches (if we add support for untracked @git
|
||||
// branches)
|
||||
|
|
@ -763,7 +767,7 @@ fn copy_exportable_local_branches_to_remote_view(
|
|||
target: new_target,
|
||||
state: RemoteRefState::Tracking,
|
||||
};
|
||||
mut_repo.set_remote_branch(&branch, remote_name, new_remote_ref);
|
||||
mut_repo.set_remote_bookmark(&branch, remote_name, new_remote_ref);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -776,9 +780,9 @@ fn diff_refs_to_export(
|
|||
// Local targets will be copied to the "git" remote if successfully exported. So
|
||||
// the local branches are considered to be the new "git" remote branches.
|
||||
let mut all_branch_targets: HashMap<RefName, (&RefTarget, &RefTarget)> = itertools::chain(
|
||||
view.local_branches()
|
||||
view.local_bookmarks()
|
||||
.map(|(branch, target)| (RefName::LocalBranch(branch.to_owned()), target)),
|
||||
view.all_remote_branches()
|
||||
view.all_remote_bookmarks()
|
||||
.filter(|&((_, remote), _)| remote != REMOTE_NAME_FOR_LOCAL_GIT_REPO)
|
||||
.map(|((branch, remote), remote_ref)| {
|
||||
let ref_name = RefName::RemoteBranch {
|
||||
|
|
@ -1379,7 +1383,7 @@ pub fn push_branches(
|
|||
state: RemoteRefState::Tracking,
|
||||
};
|
||||
mut_repo.set_git_ref_target(&git_ref_name, new_remote_ref.target.clone());
|
||||
mut_repo.set_remote_branch(branch_name, remote_name, new_remote_ref);
|
||||
mut_repo.set_remote_bookmark(branch_name, remote_name, new_remote_ref);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ impl RefTarget {
|
|||
}
|
||||
}
|
||||
|
||||
/// Remote branch or tag.
|
||||
/// Remote bookmark or tag.
|
||||
#[derive(ContentHash, Clone, Debug, Eq, Hash, PartialEq)]
|
||||
pub struct RemoteRef {
|
||||
pub target: RefTarget,
|
||||
|
|
@ -253,10 +253,10 @@ impl<'a> RefTargetOptionExt for Option<&'a RemoteRef> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Local and remote branches of the same branch name.
|
||||
/// Local and remote bookmarks of the same bookmark name.
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
pub struct BranchTarget<'a> {
|
||||
/// The commit the branch points to locally.
|
||||
/// The commit the bookmark points to locally.
|
||||
pub local_target: &'a RefTarget,
|
||||
/// `(remote_name, remote_ref)` pairs in lexicographical order.
|
||||
pub remote_refs: Vec<(&'a str, &'a RemoteRef)>,
|
||||
|
|
@ -268,13 +268,13 @@ pub struct BranchTarget<'a> {
|
|||
pub struct View {
|
||||
/// All head commits
|
||||
pub head_ids: HashSet<CommitId>,
|
||||
pub local_branches: BTreeMap<String, RefTarget>,
|
||||
pub local_bookmarks: BTreeMap<String, RefTarget>,
|
||||
pub tags: BTreeMap<String, RefTarget>,
|
||||
pub remote_views: BTreeMap<String, RemoteView>,
|
||||
pub git_refs: BTreeMap<String, RefTarget>,
|
||||
/// The commit the Git HEAD points to.
|
||||
// TODO: Support multiple Git worktrees?
|
||||
// TODO: Do we want to store the current branch name too?
|
||||
// TODO: Do we want to store the current bookmark name too?
|
||||
pub git_head: RefTarget,
|
||||
// The commit that *should be* checked out in the workspace. Note that the working copy
|
||||
// (.jj/working_copy/) has the source of truth about which commit *is* checked out (to be
|
||||
|
|
@ -285,60 +285,63 @@ pub struct View {
|
|||
/// Represents the state of the remote repo.
|
||||
#[derive(ContentHash, Clone, Debug, Default, Eq, PartialEq)]
|
||||
pub struct RemoteView {
|
||||
// TODO: Do we need to support tombstones for remote branches? For example, if the branch
|
||||
// TODO: Do we need to support tombstones for remote bookmarks? For example, if the bookmark
|
||||
// has been deleted locally and you pull from a remote, maybe it should make a difference
|
||||
// whether the branch is known to have existed on the remote. We may not want to resurrect
|
||||
// the branch if the branch's state on the remote was just not known.
|
||||
pub branches: BTreeMap<String, RemoteRef>,
|
||||
// whether the bookmark is known to have existed on the remote. We may not want to resurrect
|
||||
// the bookmark if the bookmark's state on the remote was just not known.
|
||||
pub bookmarks: BTreeMap<String, RemoteRef>,
|
||||
// TODO: pub tags: BTreeMap<String, RemoteRef>,
|
||||
}
|
||||
|
||||
/// Iterates pair of local and remote branches by branch name.
|
||||
pub(crate) fn merge_join_branch_views<'a>(
|
||||
local_branches: &'a BTreeMap<String, RefTarget>,
|
||||
/// Iterates pair of local and remote bookmarks by bookmark name.
|
||||
pub(crate) fn merge_join_bookmark_views<'a>(
|
||||
local_bookmarks: &'a BTreeMap<String, RefTarget>,
|
||||
remote_views: &'a BTreeMap<String, RemoteView>,
|
||||
) -> impl Iterator<Item = (&'a str, BranchTarget<'a>)> {
|
||||
let mut local_branches_iter = local_branches
|
||||
let mut local_bookmarks_iter = local_bookmarks
|
||||
.iter()
|
||||
.map(|(branch_name, target)| (branch_name.as_str(), target))
|
||||
.map(|(bookmark_name, target)| (bookmark_name.as_str(), target))
|
||||
.peekable();
|
||||
let mut remote_branches_iter = flatten_remote_branches(remote_views).peekable();
|
||||
let mut remote_bookmarks_iter = flatten_remote_bookmarks(remote_views).peekable();
|
||||
|
||||
iter::from_fn(move || {
|
||||
// Pick earlier branch name
|
||||
let (branch_name, local_target) =
|
||||
if let Some(&((remote_branch_name, _), _)) = remote_branches_iter.peek() {
|
||||
local_branches_iter
|
||||
.next_if(|&(local_branch_name, _)| local_branch_name <= remote_branch_name)
|
||||
.unwrap_or((remote_branch_name, RefTarget::absent_ref()))
|
||||
} else {
|
||||
local_branches_iter.next()?
|
||||
};
|
||||
let remote_refs = remote_branches_iter
|
||||
.peeking_take_while(|&((remote_branch_name, _), _)| remote_branch_name == branch_name)
|
||||
// Pick earlier bookmark name
|
||||
let (bookmark_name, local_target) = if let Some(&((remote_bookmark_name, _), _)) =
|
||||
remote_bookmarks_iter.peek()
|
||||
{
|
||||
local_bookmarks_iter
|
||||
.next_if(|&(local_bookmark_name, _)| local_bookmark_name <= remote_bookmark_name)
|
||||
.unwrap_or((remote_bookmark_name, RefTarget::absent_ref()))
|
||||
} else {
|
||||
local_bookmarks_iter.next()?
|
||||
};
|
||||
let remote_refs = remote_bookmarks_iter
|
||||
.peeking_take_while(|&((remote_bookmark_name, _), _)| {
|
||||
remote_bookmark_name == bookmark_name
|
||||
})
|
||||
.map(|((_, remote_name), remote_ref)| (remote_name, remote_ref))
|
||||
.collect();
|
||||
let branch_target = BranchTarget {
|
||||
let bookmark_target = BranchTarget {
|
||||
local_target,
|
||||
remote_refs,
|
||||
};
|
||||
Some((branch_name, branch_target))
|
||||
Some((bookmark_name, bookmark_target))
|
||||
})
|
||||
}
|
||||
|
||||
/// Iterates branch `((name, remote_name), remote_ref)`s in lexicographical
|
||||
/// Iterates bookmark `((name, remote_name), remote_ref)`s in lexicographical
|
||||
/// order.
|
||||
pub(crate) fn flatten_remote_branches(
|
||||
pub(crate) fn flatten_remote_bookmarks(
|
||||
remote_views: &BTreeMap<String, RemoteView>,
|
||||
) -> impl Iterator<Item = ((&str, &str), &RemoteRef)> {
|
||||
remote_views
|
||||
.iter()
|
||||
.map(|(remote_name, remote_view)| {
|
||||
remote_view
|
||||
.branches
|
||||
.bookmarks
|
||||
.iter()
|
||||
.map(move |(branch_name, remote_ref)| {
|
||||
let full_name = (branch_name.as_str(), remote_name.as_str());
|
||||
.map(move |(bookmark_name, remote_ref)| {
|
||||
let full_name = (bookmark_name.as_str(), remote_name.as_str());
|
||||
(full_name, remote_ref)
|
||||
})
|
||||
})
|
||||
|
|
@ -464,62 +467,62 @@ mod tests {
|
|||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_merge_join_branch_views() {
|
||||
fn test_merge_join_bookmark_views() {
|
||||
let remote_ref = |target: &RefTarget| RemoteRef {
|
||||
target: target.clone(),
|
||||
state: RemoteRefState::Tracking, // doesn't matter
|
||||
};
|
||||
let local_branch1_target = RefTarget::normal(CommitId::from_hex("111111"));
|
||||
let local_branch2_target = RefTarget::normal(CommitId::from_hex("222222"));
|
||||
let git_branch1_remote_ref = remote_ref(&RefTarget::normal(CommitId::from_hex("333333")));
|
||||
let git_branch2_remote_ref = remote_ref(&RefTarget::normal(CommitId::from_hex("444444")));
|
||||
let remote1_branch1_remote_ref =
|
||||
let local_bookmark1_target = RefTarget::normal(CommitId::from_hex("111111"));
|
||||
let local_bookmark2_target = RefTarget::normal(CommitId::from_hex("222222"));
|
||||
let git_bookmark1_remote_ref = remote_ref(&RefTarget::normal(CommitId::from_hex("333333")));
|
||||
let git_bookmark2_remote_ref = remote_ref(&RefTarget::normal(CommitId::from_hex("444444")));
|
||||
let remote1_bookmark1_remote_ref =
|
||||
remote_ref(&RefTarget::normal(CommitId::from_hex("555555")));
|
||||
let remote2_branch2_remote_ref =
|
||||
let remote2_bookmark2_remote_ref =
|
||||
remote_ref(&RefTarget::normal(CommitId::from_hex("666666")));
|
||||
|
||||
let local_branches = btreemap! {
|
||||
"branch1".to_owned() => local_branch1_target.clone(),
|
||||
"branch2".to_owned() => local_branch2_target.clone(),
|
||||
let local_bookmarks = btreemap! {
|
||||
"bookmark1".to_owned() => local_bookmark1_target.clone(),
|
||||
"bookmark2".to_owned() => local_bookmark2_target.clone(),
|
||||
};
|
||||
let remote_views = btreemap! {
|
||||
"git".to_owned() => RemoteView {
|
||||
branches: btreemap! {
|
||||
"branch1".to_owned() => git_branch1_remote_ref.clone(),
|
||||
"branch2".to_owned() => git_branch2_remote_ref.clone(),
|
||||
bookmarks: btreemap! {
|
||||
"bookmark1".to_owned() => git_bookmark1_remote_ref.clone(),
|
||||
"bookmark2".to_owned() => git_bookmark2_remote_ref.clone(),
|
||||
},
|
||||
},
|
||||
"remote1".to_owned() => RemoteView {
|
||||
branches: btreemap! {
|
||||
"branch1".to_owned() => remote1_branch1_remote_ref.clone(),
|
||||
bookmarks: btreemap! {
|
||||
"bookmark1".to_owned() => remote1_bookmark1_remote_ref.clone(),
|
||||
},
|
||||
},
|
||||
"remote2".to_owned() => RemoteView {
|
||||
branches: btreemap! {
|
||||
"branch2".to_owned() => remote2_branch2_remote_ref.clone(),
|
||||
bookmarks: btreemap! {
|
||||
"bookmark2".to_owned() => remote2_bookmark2_remote_ref.clone(),
|
||||
},
|
||||
},
|
||||
};
|
||||
assert_eq!(
|
||||
merge_join_branch_views(&local_branches, &remote_views).collect_vec(),
|
||||
merge_join_bookmark_views(&local_bookmarks, &remote_views).collect_vec(),
|
||||
vec![
|
||||
(
|
||||
"branch1",
|
||||
"bookmark1",
|
||||
BranchTarget {
|
||||
local_target: &local_branch1_target,
|
||||
local_target: &local_bookmark1_target,
|
||||
remote_refs: vec![
|
||||
("git", &git_branch1_remote_ref),
|
||||
("remote1", &remote1_branch1_remote_ref),
|
||||
("git", &git_bookmark1_remote_ref),
|
||||
("remote1", &remote1_bookmark1_remote_ref),
|
||||
],
|
||||
},
|
||||
),
|
||||
(
|
||||
"branch2",
|
||||
"bookmark2",
|
||||
BranchTarget {
|
||||
local_target: &local_branch2_target.clone(),
|
||||
local_target: &local_bookmark2_target.clone(),
|
||||
remote_refs: vec![
|
||||
("git", &git_branch2_remote_ref),
|
||||
("remote2", &remote2_branch2_remote_ref),
|
||||
("git", &git_bookmark2_remote_ref),
|
||||
("remote2", &remote2_bookmark2_remote_ref),
|
||||
],
|
||||
},
|
||||
),
|
||||
|
|
@ -527,37 +530,37 @@ mod tests {
|
|||
);
|
||||
|
||||
// Local only
|
||||
let local_branches = btreemap! {
|
||||
"branch1".to_owned() => local_branch1_target.clone(),
|
||||
let local_bookmarks = btreemap! {
|
||||
"bookmark1".to_owned() => local_bookmark1_target.clone(),
|
||||
};
|
||||
let remote_views = btreemap! {};
|
||||
assert_eq!(
|
||||
merge_join_branch_views(&local_branches, &remote_views).collect_vec(),
|
||||
merge_join_bookmark_views(&local_bookmarks, &remote_views).collect_vec(),
|
||||
vec![(
|
||||
"branch1",
|
||||
"bookmark1",
|
||||
BranchTarget {
|
||||
local_target: &local_branch1_target,
|
||||
local_target: &local_bookmark1_target,
|
||||
remote_refs: vec![],
|
||||
},
|
||||
)],
|
||||
);
|
||||
|
||||
// Remote only
|
||||
let local_branches = btreemap! {};
|
||||
let local_bookmarks = btreemap! {};
|
||||
let remote_views = btreemap! {
|
||||
"remote1".to_owned() => RemoteView {
|
||||
branches: btreemap! {
|
||||
"branch1".to_owned() => remote1_branch1_remote_ref.clone(),
|
||||
bookmarks: btreemap! {
|
||||
"bookmark1".to_owned() => remote1_bookmark1_remote_ref.clone(),
|
||||
},
|
||||
},
|
||||
};
|
||||
assert_eq!(
|
||||
merge_join_branch_views(&local_branches, &remote_views).collect_vec(),
|
||||
merge_join_bookmark_views(&local_bookmarks, &remote_views).collect_vec(),
|
||||
vec![(
|
||||
"branch1",
|
||||
"bookmark1",
|
||||
BranchTarget {
|
||||
local_target: RefTarget::absent_ref(),
|
||||
remote_refs: vec![("remote1", &remote1_branch1_remote_ref)],
|
||||
remote_refs: vec![("remote1", &remote1_bookmark1_remote_ref)],
|
||||
},
|
||||
)],
|
||||
);
|
||||
|
|
|
|||
|
|
@ -190,8 +190,8 @@ pub enum BranchPushAction {
|
|||
}
|
||||
|
||||
/// Figure out what changes (if any) need to be made to the remote when pushing
|
||||
/// this branch.
|
||||
pub fn classify_branch_push_action(targets: LocalAndRemoteRef) -> BranchPushAction {
|
||||
/// this bookmark.
|
||||
pub fn classify_bookmark_push_action(targets: LocalAndRemoteRef) -> BranchPushAction {
|
||||
let local_target = targets.local_target;
|
||||
let remote_target = targets.remote_ref.tracking_target();
|
||||
if local_target == remote_target {
|
||||
|
|
@ -230,27 +230,27 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_classify_branch_push_action_unchanged() {
|
||||
fn test_classify_bookmark_push_action_unchanged() {
|
||||
let commit_id1 = CommitId::from_hex("11");
|
||||
let targets = LocalAndRemoteRef {
|
||||
local_target: &RefTarget::normal(commit_id1.clone()),
|
||||
remote_ref: &tracking_remote_ref(RefTarget::normal(commit_id1)),
|
||||
};
|
||||
assert_eq!(
|
||||
classify_branch_push_action(targets),
|
||||
classify_bookmark_push_action(targets),
|
||||
BranchPushAction::AlreadyMatches
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_classify_branch_push_action_added() {
|
||||
fn test_classify_bookmark_push_action_added() {
|
||||
let commit_id1 = CommitId::from_hex("11");
|
||||
let targets = LocalAndRemoteRef {
|
||||
local_target: &RefTarget::normal(commit_id1.clone()),
|
||||
remote_ref: RemoteRef::absent_ref(),
|
||||
};
|
||||
assert_eq!(
|
||||
classify_branch_push_action(targets),
|
||||
classify_bookmark_push_action(targets),
|
||||
BranchPushAction::Update(BranchPushUpdate {
|
||||
old_target: None,
|
||||
new_target: Some(commit_id1),
|
||||
|
|
@ -259,14 +259,14 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_classify_branch_push_action_removed() {
|
||||
fn test_classify_bookmark_push_action_removed() {
|
||||
let commit_id1 = CommitId::from_hex("11");
|
||||
let targets = LocalAndRemoteRef {
|
||||
local_target: RefTarget::absent_ref(),
|
||||
remote_ref: &tracking_remote_ref(RefTarget::normal(commit_id1.clone())),
|
||||
};
|
||||
assert_eq!(
|
||||
classify_branch_push_action(targets),
|
||||
classify_bookmark_push_action(targets),
|
||||
BranchPushAction::Update(BranchPushUpdate {
|
||||
old_target: Some(commit_id1),
|
||||
new_target: None,
|
||||
|
|
@ -275,7 +275,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_classify_branch_push_action_updated() {
|
||||
fn test_classify_bookmark_push_action_updated() {
|
||||
let commit_id1 = CommitId::from_hex("11");
|
||||
let commit_id2 = CommitId::from_hex("22");
|
||||
let targets = LocalAndRemoteRef {
|
||||
|
|
@ -283,7 +283,7 @@ mod tests {
|
|||
remote_ref: &tracking_remote_ref(RefTarget::normal(commit_id1.clone())),
|
||||
};
|
||||
assert_eq!(
|
||||
classify_branch_push_action(targets),
|
||||
classify_bookmark_push_action(targets),
|
||||
BranchPushAction::Update(BranchPushUpdate {
|
||||
old_target: Some(commit_id1),
|
||||
new_target: Some(commit_id2),
|
||||
|
|
@ -292,22 +292,22 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_classify_branch_push_action_removed_untracked() {
|
||||
// This is not RemoteUntracked error since non-tracking remote branches
|
||||
// have no relation to local branches, and there's nothing to push.
|
||||
fn test_classify_bookmark_push_action_removed_untracked() {
|
||||
// This is not RemoteUntracked error since non-tracking remote bookmarks
|
||||
// have no relation to local bookmarks, and there's nothing to push.
|
||||
let commit_id1 = CommitId::from_hex("11");
|
||||
let targets = LocalAndRemoteRef {
|
||||
local_target: RefTarget::absent_ref(),
|
||||
remote_ref: &new_remote_ref(RefTarget::normal(commit_id1.clone())),
|
||||
};
|
||||
assert_eq!(
|
||||
classify_branch_push_action(targets),
|
||||
classify_bookmark_push_action(targets),
|
||||
BranchPushAction::AlreadyMatches
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_classify_branch_push_action_updated_untracked() {
|
||||
fn test_classify_bookmark_push_action_updated_untracked() {
|
||||
let commit_id1 = CommitId::from_hex("11");
|
||||
let commit_id2 = CommitId::from_hex("22");
|
||||
let targets = LocalAndRemoteRef {
|
||||
|
|
@ -315,13 +315,13 @@ mod tests {
|
|||
remote_ref: &new_remote_ref(RefTarget::normal(commit_id1.clone())),
|
||||
};
|
||||
assert_eq!(
|
||||
classify_branch_push_action(targets),
|
||||
classify_bookmark_push_action(targets),
|
||||
BranchPushAction::RemoteUntracked
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_classify_branch_push_action_local_conflicted() {
|
||||
fn test_classify_bookmark_push_action_local_conflicted() {
|
||||
let commit_id1 = CommitId::from_hex("11");
|
||||
let commit_id2 = CommitId::from_hex("22");
|
||||
let targets = LocalAndRemoteRef {
|
||||
|
|
@ -329,13 +329,13 @@ mod tests {
|
|||
remote_ref: &tracking_remote_ref(RefTarget::normal(commit_id1)),
|
||||
};
|
||||
assert_eq!(
|
||||
classify_branch_push_action(targets),
|
||||
classify_bookmark_push_action(targets),
|
||||
BranchPushAction::LocalConflicted
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_classify_branch_push_action_remote_conflicted() {
|
||||
fn test_classify_bookmark_push_action_remote_conflicted() {
|
||||
let commit_id1 = CommitId::from_hex("11");
|
||||
let commit_id2 = CommitId::from_hex("22");
|
||||
let targets = LocalAndRemoteRef {
|
||||
|
|
@ -346,7 +346,7 @@ mod tests {
|
|||
)),
|
||||
};
|
||||
assert_eq!(
|
||||
classify_branch_push_action(targets),
|
||||
classify_bookmark_push_action(targets),
|
||||
BranchPushAction::RemoteConflicted
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -919,7 +919,7 @@ impl MutableRepo {
|
|||
/// Record a commit as being rewritten into multiple other commits in this
|
||||
/// transaction.
|
||||
///
|
||||
/// A later call to `rebase_descendants()` will update branches pointing to
|
||||
/// A later call to `rebase_descendants()` will update bookmarks pointing to
|
||||
/// `old_id` be conflicted and pointing to all pf `new_ids`. Working copies
|
||||
/// pointing to `old_id` will be updated to point to the first commit in
|
||||
/// `new_ids``. Descendants of `old_id` will be left alone.
|
||||
|
|
@ -939,10 +939,10 @@ impl MutableRepo {
|
|||
///
|
||||
/// This record is used by `rebase_descendants` to know which commits have
|
||||
/// children that need to be rebased, and where to rebase the children (as
|
||||
/// well as branches) to.
|
||||
/// well as bookmarks) to.
|
||||
///
|
||||
/// The `rebase_descendants` logic will rebase the descendants of `old_id`
|
||||
/// to become the descendants of parent(s) of `old_id`. Any branches at
|
||||
/// to become the descendants of parent(s) of `old_id`. Any bookmarks at
|
||||
/// `old_id` would be moved to the parent(s) of `old_id` as well.
|
||||
// TODO: Propagate errors from commit lookup or take a Commit as argument.
|
||||
pub fn record_abandoned_commit(&mut self, old_id: CommitId) {
|
||||
|
|
@ -1056,7 +1056,7 @@ impl MutableRepo {
|
|||
new_mapping
|
||||
}
|
||||
|
||||
/// Updates branches, working copies, and anonymous heads after rewriting
|
||||
/// Updates bookmarks, working copies, and anonymous heads after rewriting
|
||||
/// and/or abandoning commits.
|
||||
pub fn update_rewritten_references(&mut self, settings: &UserSettings) -> BackendResult<()> {
|
||||
self.update_all_references(settings)?;
|
||||
|
|
@ -1074,7 +1074,7 @@ impl MutableRepo {
|
|||
fn update_local_branches(&mut self, rewrite_mapping: &HashMap<CommitId, Vec<CommitId>>) {
|
||||
let changed_branches = self
|
||||
.view()
|
||||
.local_branches()
|
||||
.local_bookmarks()
|
||||
.flat_map(|(name, target)| {
|
||||
target.added_ids().filter_map(|id| {
|
||||
let change = rewrite_mapping.get_key_value(id)?;
|
||||
|
|
@ -1082,7 +1082,7 @@ impl MutableRepo {
|
|||
})
|
||||
})
|
||||
.collect_vec();
|
||||
for (branch_name, (old_commit_id, new_commit_ids)) in changed_branches {
|
||||
for (bookmark_name, (old_commit_id, new_commit_ids)) in changed_branches {
|
||||
let old_target = RefTarget::normal(old_commit_id.clone());
|
||||
let new_target = RefTarget::from_merge(
|
||||
MergeBuilder::from_iter(
|
||||
|
|
@ -1091,7 +1091,8 @@ impl MutableRepo {
|
|||
)
|
||||
.build(),
|
||||
);
|
||||
self.merge_local_branch(&branch_name, &old_target, &new_target);
|
||||
|
||||
self.merge_local_bookmark(&bookmark_name, &old_target, &new_target);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1268,7 +1269,7 @@ impl MutableRepo {
|
|||
Ok(Some(rebaser))
|
||||
}
|
||||
|
||||
// TODO(ilyagr): Either document that this also moves branches (rename the
|
||||
// TODO(ilyagr): Either document that this also moves bookmarks (rename the
|
||||
// function and the related functions?) or change things so that this only
|
||||
// rebases descendants.
|
||||
pub fn rebase_descendants_with_options(
|
||||
|
|
@ -1295,7 +1296,7 @@ impl MutableRepo {
|
|||
/// key-value pair where the key is the abandoned commit and the value is
|
||||
/// **its parent**. One can tell this case apart since the change ids of the
|
||||
/// key and the value will not match. The parent will inherit the
|
||||
/// descendants and the branches of the abandoned commit.
|
||||
/// descendants and the bookmarks of the abandoned commit.
|
||||
// TODO: Rewrite this using `transform_descendants()`
|
||||
pub fn rebase_descendants_with_options_return_map(
|
||||
&mut self,
|
||||
|
|
@ -1390,7 +1391,7 @@ impl MutableRepo {
|
|||
.filter(|&(ws_id, _)| ws_id != workspace_id)
|
||||
.map(|(_, wc_id)| wc_id)
|
||||
.chain(
|
||||
view.local_branches()
|
||||
view.local_bookmarks()
|
||||
.flat_map(|(_, target)| target.added_ids()),
|
||||
)
|
||||
.any(|id| id == commit_id)
|
||||
|
|
@ -1411,7 +1412,7 @@ impl MutableRepo {
|
|||
&& self.view().heads().contains(wc_commit.id())
|
||||
{
|
||||
// Abandon the working-copy commit we're leaving if it's
|
||||
// discardable, not pointed by local branch or other working
|
||||
// discardable, not pointed by local bookmark or other working
|
||||
// copies, and a head commit.
|
||||
self.record_abandoned_commit(wc_commit_id);
|
||||
}
|
||||
|
|
@ -1504,15 +1505,15 @@ impl MutableRepo {
|
|||
self.view.mark_dirty();
|
||||
}
|
||||
|
||||
pub fn get_local_branch(&self, name: &str) -> RefTarget {
|
||||
self.view.with_ref(|v| v.get_local_branch(name).clone())
|
||||
pub fn get_local_bookmark(&self, name: &str) -> RefTarget {
|
||||
self.view.with_ref(|v| v.get_local_bookmark(name).clone())
|
||||
}
|
||||
|
||||
pub fn set_local_branch_target(&mut self, name: &str, target: RefTarget) {
|
||||
self.view_mut().set_local_branch_target(name, target);
|
||||
pub fn set_local_bookmark_target(&mut self, name: &str, target: RefTarget) {
|
||||
self.view_mut().set_local_bookmark_target(name, target);
|
||||
}
|
||||
|
||||
pub fn merge_local_branch(
|
||||
pub fn merge_local_bookmark(
|
||||
&mut self,
|
||||
name: &str,
|
||||
base_target: &RefTarget,
|
||||
|
|
@ -1520,22 +1521,22 @@ impl MutableRepo {
|
|||
) {
|
||||
let view = self.view.get_mut();
|
||||
let index = self.index.as_index();
|
||||
let self_target = view.get_local_branch(name);
|
||||
let self_target = view.get_local_bookmark(name);
|
||||
let new_target = merge_ref_targets(index, self_target, base_target, other_target);
|
||||
view.set_local_branch_target(name, new_target);
|
||||
view.set_local_bookmark_target(name, new_target);
|
||||
}
|
||||
|
||||
pub fn get_remote_branch(&self, name: &str, remote_name: &str) -> RemoteRef {
|
||||
pub fn get_remote_bookmark(&self, name: &str, remote_name: &str) -> RemoteRef {
|
||||
self.view
|
||||
.with_ref(|v| v.get_remote_branch(name, remote_name).clone())
|
||||
.with_ref(|v| v.get_remote_bookmark(name, remote_name).clone())
|
||||
}
|
||||
|
||||
pub fn set_remote_branch(&mut self, name: &str, remote_name: &str, remote_ref: RemoteRef) {
|
||||
pub fn set_remote_bookmark(&mut self, name: &str, remote_name: &str, remote_ref: RemoteRef) {
|
||||
self.view_mut()
|
||||
.set_remote_branch(name, remote_name, remote_ref);
|
||||
.set_remote_bookmark(name, remote_name, remote_ref);
|
||||
}
|
||||
|
||||
fn merge_remote_branch(
|
||||
fn merge_remote_bookmark(
|
||||
&mut self,
|
||||
name: &str,
|
||||
remote_name: &str,
|
||||
|
|
@ -1544,26 +1545,26 @@ impl MutableRepo {
|
|||
) {
|
||||
let view = self.view.get_mut();
|
||||
let index = self.index.as_index();
|
||||
let self_ref = view.get_remote_branch(name, remote_name);
|
||||
let self_ref = view.get_remote_bookmark(name, remote_name);
|
||||
let new_ref = merge_remote_refs(index, self_ref, base_ref, other_ref);
|
||||
view.set_remote_branch(name, remote_name, new_ref);
|
||||
view.set_remote_bookmark(name, remote_name, new_ref);
|
||||
}
|
||||
|
||||
/// Merges the specified remote branch in to local branch, and starts
|
||||
/// Merges the specified remote bookmark in to local bookmark, and starts
|
||||
/// tracking it.
|
||||
pub fn track_remote_branch(&mut self, name: &str, remote_name: &str) {
|
||||
let mut remote_ref = self.get_remote_branch(name, remote_name);
|
||||
pub fn track_remote_bookmark(&mut self, name: &str, remote_name: &str) {
|
||||
let mut remote_ref = self.get_remote_bookmark(name, remote_name);
|
||||
let base_target = remote_ref.tracking_target();
|
||||
self.merge_local_branch(name, base_target, &remote_ref.target);
|
||||
self.merge_local_bookmark(name, base_target, &remote_ref.target);
|
||||
remote_ref.state = RemoteRefState::Tracking;
|
||||
self.set_remote_branch(name, remote_name, remote_ref);
|
||||
self.set_remote_bookmark(name, remote_name, remote_ref);
|
||||
}
|
||||
|
||||
/// Stops tracking the specified remote branch.
|
||||
pub fn untrack_remote_branch(&mut self, name: &str, remote_name: &str) {
|
||||
let mut remote_ref = self.get_remote_branch(name, remote_name);
|
||||
/// Stops tracking the specified remote bookmark.
|
||||
pub fn untrack_remote_bookmark(&mut self, name: &str, remote_name: &str) {
|
||||
let mut remote_ref = self.get_remote_bookmark(name, remote_name);
|
||||
remote_ref.state = RemoteRefState::New;
|
||||
self.set_remote_branch(name, remote_name, remote_ref);
|
||||
self.set_remote_bookmark(name, remote_name, remote_ref);
|
||||
}
|
||||
|
||||
pub fn remove_remote(&mut self, remote_name: &str) {
|
||||
|
|
@ -1688,10 +1689,10 @@ impl MutableRepo {
|
|||
self.view_mut().add_head(added_head);
|
||||
}
|
||||
|
||||
let changed_local_branches =
|
||||
diff_named_ref_targets(base.local_branches(), other.local_branches());
|
||||
for (name, (base_target, other_target)) in changed_local_branches {
|
||||
self.merge_local_branch(name, base_target, other_target);
|
||||
let changed_local_bookmarks =
|
||||
diff_named_ref_targets(base.local_bookmarks(), other.local_bookmarks());
|
||||
for (name, (base_target, other_target)) in changed_local_bookmarks {
|
||||
self.merge_local_bookmark(name, base_target, other_target);
|
||||
}
|
||||
|
||||
let changed_tags = diff_named_ref_targets(base.tags(), other.tags());
|
||||
|
|
@ -1704,10 +1705,10 @@ impl MutableRepo {
|
|||
self.merge_git_ref(name, base_target, other_target);
|
||||
}
|
||||
|
||||
let changed_remote_branches =
|
||||
diff_named_remote_refs(base.all_remote_branches(), other.all_remote_branches());
|
||||
for ((name, remote_name), (base_ref, other_ref)) in changed_remote_branches {
|
||||
self.merge_remote_branch(name, remote_name, base_ref, other_ref);
|
||||
let changed_remote_bookmarks =
|
||||
diff_named_remote_refs(base.all_remote_bookmarks(), other.all_remote_bookmarks());
|
||||
for ((name, remote_name), (base_ref, other_ref)) in changed_remote_bookmarks {
|
||||
self.merge_remote_bookmark(name, remote_name, base_ref, other_ref);
|
||||
}
|
||||
|
||||
let new_git_head_target = merge_ref_targets(
|
||||
|
|
|
|||
|
|
@ -119,9 +119,9 @@ pub enum RevsetCommitRef {
|
|||
},
|
||||
VisibleHeads,
|
||||
Root,
|
||||
Branches(StringPattern),
|
||||
RemoteBranches {
|
||||
branch_pattern: StringPattern,
|
||||
Bookmarks(StringPattern),
|
||||
RemoteBookmarks {
|
||||
bookmark_pattern: StringPattern,
|
||||
remote_pattern: StringPattern,
|
||||
remote_ref_state: Option<RemoteRefState>,
|
||||
},
|
||||
|
|
@ -256,20 +256,20 @@ impl RevsetExpression {
|
|||
Rc::new(RevsetExpression::CommitRef(RevsetCommitRef::Root))
|
||||
}
|
||||
|
||||
pub fn branches(pattern: StringPattern) -> Rc<RevsetExpression> {
|
||||
Rc::new(RevsetExpression::CommitRef(RevsetCommitRef::Branches(
|
||||
pub fn bookmarks(pattern: StringPattern) -> Rc<RevsetExpression> {
|
||||
Rc::new(RevsetExpression::CommitRef(RevsetCommitRef::Bookmarks(
|
||||
pattern,
|
||||
)))
|
||||
}
|
||||
|
||||
pub fn remote_branches(
|
||||
branch_pattern: StringPattern,
|
||||
pub fn remote_bookmarks(
|
||||
bookmark_pattern: StringPattern,
|
||||
remote_pattern: StringPattern,
|
||||
remote_ref_state: Option<RemoteRefState>,
|
||||
) -> Rc<RevsetExpression> {
|
||||
Rc::new(RevsetExpression::CommitRef(
|
||||
RevsetCommitRef::RemoteBranches {
|
||||
branch_pattern,
|
||||
RevsetCommitRef::RemoteBookmarks {
|
||||
bookmark_pattern,
|
||||
remote_pattern,
|
||||
remote_ref_state,
|
||||
},
|
||||
|
|
@ -460,7 +460,7 @@ impl RevsetExpression {
|
|||
}
|
||||
|
||||
/// Resolve a programmatically created revset expression. In particular, the
|
||||
/// expression must not contain any symbols (branches, tags, change/commit
|
||||
/// expression must not contain any symbols (bookmarks, tags, change/commit
|
||||
/// prefixes). Callers must not include `RevsetExpression::symbol()` in
|
||||
/// the expression, and should instead resolve symbols to `CommitId`s and
|
||||
/// pass them into `RevsetExpression::commits()`. Similarly, the expression
|
||||
|
|
@ -644,24 +644,34 @@ static BUILTIN_FUNCTION_MAP: Lazy<HashMap<&'static str, RevsetFunction>> = Lazy:
|
|||
function.expect_no_arguments()?;
|
||||
Ok(RevsetExpression::root())
|
||||
});
|
||||
map.insert("branches", |function, _context| {
|
||||
map.insert("bookmarks", |function, _context| {
|
||||
let ([], [opt_arg]) = function.expect_arguments()?;
|
||||
let pattern = if let Some(arg) = opt_arg {
|
||||
expect_string_pattern(arg)?
|
||||
} else {
|
||||
StringPattern::everything()
|
||||
};
|
||||
Ok(RevsetExpression::branches(pattern))
|
||||
Ok(RevsetExpression::bookmarks(pattern))
|
||||
});
|
||||
map.insert("remote_branches", |function, _context| {
|
||||
parse_remote_branches_arguments(function, None)
|
||||
map.insert("remote_bookmarks", |function, _context| {
|
||||
parse_remote_bookmarks_arguments(function, None)
|
||||
});
|
||||
map.insert("tracked_remote_branches", |function, _context| {
|
||||
parse_remote_branches_arguments(function, Some(RemoteRefState::Tracking))
|
||||
map.insert("tracked_remote_bookmarks", |function, _context| {
|
||||
parse_remote_bookmarks_arguments(function, Some(RemoteRefState::Tracking))
|
||||
});
|
||||
map.insert("untracked_remote_branches", |function, _context| {
|
||||
parse_remote_branches_arguments(function, Some(RemoteRefState::New))
|
||||
map.insert("untracked_remote_bookmarks", |function, _context| {
|
||||
parse_remote_bookmarks_arguments(function, Some(RemoteRefState::New))
|
||||
});
|
||||
|
||||
// TODO: Remove in jj 0.28+
|
||||
map.insert("branches", map["bookmarks"]);
|
||||
map.insert("remote_branches", map["remote_bookmarks"]);
|
||||
map.insert("tracked_remote_branches", map["tracked_remote_bookmarks"]);
|
||||
map.insert(
|
||||
"untracked_remote_branches",
|
||||
map["untracked_remote_bookmarks"],
|
||||
);
|
||||
|
||||
map.insert("tags", |function, _context| {
|
||||
function.expect_no_arguments()?;
|
||||
Ok(RevsetExpression::tags())
|
||||
|
|
@ -822,14 +832,14 @@ pub fn expect_date_pattern(
|
|||
revset_parser::expect_pattern_with("date pattern", node, parse_pattern)
|
||||
}
|
||||
|
||||
fn parse_remote_branches_arguments(
|
||||
fn parse_remote_bookmarks_arguments(
|
||||
function: &FunctionCallNode,
|
||||
remote_ref_state: Option<RemoteRefState>,
|
||||
) -> Result<Rc<RevsetExpression>, RevsetParseError> {
|
||||
let ([], [branch_opt_arg, remote_opt_arg]) =
|
||||
let ([], [bookmark_opt_arg, remote_opt_arg]) =
|
||||
function.expect_named_arguments(&["", "remote"])?;
|
||||
let branch_pattern = if let Some(branch_arg) = branch_opt_arg {
|
||||
expect_string_pattern(branch_arg)?
|
||||
let bookmark_pattern = if let Some(bookmark_arg) = bookmark_opt_arg {
|
||||
expect_string_pattern(bookmark_arg)?
|
||||
} else {
|
||||
StringPattern::everything()
|
||||
};
|
||||
|
|
@ -838,8 +848,8 @@ fn parse_remote_branches_arguments(
|
|||
} else {
|
||||
StringPattern::everything()
|
||||
};
|
||||
Ok(RevsetExpression::remote_branches(
|
||||
branch_pattern,
|
||||
Ok(RevsetExpression::remote_bookmarks(
|
||||
bookmark_pattern,
|
||||
remote_pattern,
|
||||
remote_ref_state,
|
||||
))
|
||||
|
|
@ -1411,29 +1421,29 @@ pub fn walk_revs<'index>(
|
|||
.evaluate_programmatic(repo)
|
||||
}
|
||||
|
||||
fn resolve_remote_branch(repo: &dyn Repo, name: &str, remote: &str) -> Option<Vec<CommitId>> {
|
||||
fn resolve_remote_bookmark(repo: &dyn Repo, name: &str, remote: &str) -> Option<Vec<CommitId>> {
|
||||
let view = repo.view();
|
||||
let target = match (name, remote) {
|
||||
#[cfg(feature = "git")]
|
||||
("HEAD", crate::git::REMOTE_NAME_FOR_LOCAL_GIT_REPO) => view.git_head(),
|
||||
(name, remote) => &view.get_remote_branch(name, remote).target,
|
||||
(name, remote) => &view.get_remote_bookmark(name, remote).target,
|
||||
};
|
||||
target
|
||||
.is_present()
|
||||
.then(|| target.added_ids().cloned().collect())
|
||||
}
|
||||
|
||||
fn all_branch_symbols(
|
||||
fn all_bookmark_symbols(
|
||||
repo: &dyn Repo,
|
||||
include_synced_remotes: bool,
|
||||
) -> impl Iterator<Item = String> + '_ {
|
||||
let view = repo.view();
|
||||
view.branches()
|
||||
.flat_map(move |(name, branch_target)| {
|
||||
// Remote branch "x"@"y" may conflict with local "x@y" in unquoted form.
|
||||
let local_target = branch_target.local_target;
|
||||
view.bookmarks()
|
||||
.flat_map(move |(name, bookmark_target)| {
|
||||
// Remote bookmark "x"@"y" may conflict with local "x@y" in unquoted form.
|
||||
let local_target = bookmark_target.local_target;
|
||||
let local_symbol = local_target.is_present().then(|| name.to_owned());
|
||||
let remote_symbols = branch_target
|
||||
let remote_symbols = bookmark_target
|
||||
.remote_refs
|
||||
.into_iter()
|
||||
.filter(move |&(_, remote_ref)| {
|
||||
|
|
@ -1450,8 +1460,8 @@ fn all_branch_symbols(
|
|||
fn make_no_such_symbol_error(repo: &dyn Repo, name: impl Into<String>) -> RevsetResolutionError {
|
||||
let name = name.into();
|
||||
// TODO: include tags?
|
||||
let branch_names = all_branch_symbols(repo, name.contains('@'));
|
||||
let candidates = collect_similar(&name, branch_names);
|
||||
let bookmark_names = all_bookmark_symbols(repo, name.contains('@'));
|
||||
let candidates = collect_similar(&name, bookmark_names);
|
||||
RevsetResolutionError::NoSuchRevision { name, candidates }
|
||||
}
|
||||
|
||||
|
|
@ -1508,7 +1518,7 @@ impl PartialSymbolResolver for BranchResolver {
|
|||
repo: &dyn Repo,
|
||||
symbol: &str,
|
||||
) -> Result<Option<Vec<CommitId>>, RevsetResolutionError> {
|
||||
let target = repo.view().get_local_branch(symbol);
|
||||
let target = repo.view().get_local_bookmark(symbol);
|
||||
Ok(target
|
||||
.is_present()
|
||||
.then(|| target.added_ids().cloned().collect()))
|
||||
|
|
@ -1603,7 +1613,7 @@ impl PartialSymbolResolver for ChangePrefixResolver<'_> {
|
|||
/// Each PartialSymbolResolver will be invoked in order, its result used if one
|
||||
/// is provided. Native resolvers are always invoked first. In the future, we
|
||||
/// may provide a way for extensions to override native resolvers like tags and
|
||||
/// branches.
|
||||
/// bookmarks.
|
||||
pub trait SymbolResolverExtension {
|
||||
/// PartialSymbolResolvers can capture `repo` for caching purposes if
|
||||
/// desired, but they do not have to since `repo` is passed into
|
||||
|
|
@ -1611,8 +1621,8 @@ pub trait SymbolResolverExtension {
|
|||
fn new_resolvers<'a>(&self, repo: &'a dyn Repo) -> Vec<Box<dyn PartialSymbolResolver + 'a>>;
|
||||
}
|
||||
|
||||
/// Resolves branches, remote branches, tags, git refs, and full and abbreviated
|
||||
/// commit and change ids.
|
||||
/// Resolves bookmarks, remote bookmarks, tags, git refs, and full and
|
||||
/// abbreviated commit and change ids.
|
||||
pub struct DefaultSymbolResolver<'a> {
|
||||
repo: &'a dyn Repo,
|
||||
commit_id_resolver: CommitPrefixResolver<'a>,
|
||||
|
|
@ -1673,8 +1683,10 @@ fn resolve_commit_ref(
|
|||
) -> Result<Vec<CommitId>, RevsetResolutionError> {
|
||||
match commit_ref {
|
||||
RevsetCommitRef::Symbol(symbol) => symbol_resolver.resolve_symbol(symbol),
|
||||
RevsetCommitRef::RemoteSymbol { name, remote } => resolve_remote_branch(repo, name, remote)
|
||||
.ok_or_else(|| make_no_such_symbol_error(repo, format!("{name}@{remote}"))),
|
||||
RevsetCommitRef::RemoteSymbol { name, remote } => {
|
||||
resolve_remote_bookmark(repo, name, remote)
|
||||
.ok_or_else(|| make_no_such_symbol_error(repo, format!("{name}@{remote}")))
|
||||
}
|
||||
RevsetCommitRef::WorkingCopy(workspace_id) => {
|
||||
if let Some(commit_id) = repo.view().get_wc_commit_id(workspace_id) {
|
||||
Ok(vec![commit_id.clone()])
|
||||
|
|
@ -1690,24 +1702,24 @@ fn resolve_commit_ref(
|
|||
}
|
||||
RevsetCommitRef::VisibleHeads => Ok(repo.view().heads().iter().cloned().collect_vec()),
|
||||
RevsetCommitRef::Root => Ok(vec![repo.store().root_commit_id().clone()]),
|
||||
RevsetCommitRef::Branches(pattern) => {
|
||||
RevsetCommitRef::Bookmarks(pattern) => {
|
||||
let commit_ids = repo
|
||||
.view()
|
||||
.local_branches_matching(pattern)
|
||||
.local_bookmarks_matching(pattern)
|
||||
.flat_map(|(_, target)| target.added_ids())
|
||||
.cloned()
|
||||
.collect();
|
||||
Ok(commit_ids)
|
||||
}
|
||||
RevsetCommitRef::RemoteBranches {
|
||||
branch_pattern,
|
||||
RevsetCommitRef::RemoteBookmarks {
|
||||
bookmark_pattern,
|
||||
remote_pattern,
|
||||
remote_ref_state,
|
||||
} => {
|
||||
// TODO: should we allow to select @git branches explicitly?
|
||||
// TODO: should we allow to select @git bookmarks explicitly?
|
||||
let commit_ids = repo
|
||||
.view()
|
||||
.remote_branches_matching(branch_pattern, remote_pattern)
|
||||
.remote_bookmarks_matching(bookmark_pattern, remote_pattern)
|
||||
.filter(|(_, remote_ref)| {
|
||||
remote_ref_state.map_or(true, |state| remote_ref.state == state)
|
||||
})
|
||||
|
|
@ -1903,7 +1915,7 @@ impl VisibilityResolutionContext<'_> {
|
|||
// transformation rules may subtly change the evaluated set. For example,
|
||||
// `all() & x` is not `x` if `x` is hidden. This wouldn't matter in practice,
|
||||
// but if it does, the heads set could be extended to include the commits
|
||||
// (and `remote_branches()`) specified in the revset expression. Alternatively,
|
||||
// (and `remote_bookmarks()`) specified in the revset expression. Alternatively,
|
||||
// some optimization rules could be removed, but that means `author(_) & x`
|
||||
// would have to test `::visible_heads() & x`.
|
||||
ResolvedExpression::Ancestors {
|
||||
|
|
@ -2411,32 +2423,32 @@ mod tests {
|
|||
insta::assert_debug_snapshot!(
|
||||
parse("foo").unwrap(),
|
||||
@r###"CommitRef(Symbol("foo"))"###);
|
||||
// Default arguments for *branches() are all ""
|
||||
// Default arguments for *bookmarks() are all ""
|
||||
insta::assert_debug_snapshot!(
|
||||
parse("branches()").unwrap(),
|
||||
@r###"CommitRef(Branches(Substring("")))"###);
|
||||
insta::assert_debug_snapshot!(parse("remote_branches()").unwrap(), @r###"
|
||||
parse("bookmarks()").unwrap(),
|
||||
@r###"CommitRef(Bookmarks(Substring("")))"###);
|
||||
insta::assert_debug_snapshot!(parse("remote_bookmarks()").unwrap(), @r###"
|
||||
CommitRef(
|
||||
RemoteBranches {
|
||||
branch_pattern: Substring(""),
|
||||
RemoteBookmarks {
|
||||
bookmark_pattern: Substring(""),
|
||||
remote_pattern: Substring(""),
|
||||
remote_ref_state: None,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
insta::assert_debug_snapshot!(parse("tracked_remote_branches()").unwrap(), @r###"
|
||||
insta::assert_debug_snapshot!(parse("tracked_remote_bookmarks()").unwrap(), @r###"
|
||||
CommitRef(
|
||||
RemoteBranches {
|
||||
branch_pattern: Substring(""),
|
||||
RemoteBookmarks {
|
||||
bookmark_pattern: Substring(""),
|
||||
remote_pattern: Substring(""),
|
||||
remote_ref_state: Some(Tracking),
|
||||
},
|
||||
)
|
||||
"###);
|
||||
insta::assert_debug_snapshot!(parse("untracked_remote_branches()").unwrap(), @r###"
|
||||
insta::assert_debug_snapshot!(parse("untracked_remote_bookmarks()").unwrap(), @r###"
|
||||
CommitRef(
|
||||
RemoteBranches {
|
||||
branch_pattern: Substring(""),
|
||||
RemoteBookmarks {
|
||||
bookmark_pattern: Substring(""),
|
||||
remote_pattern: Substring(""),
|
||||
remote_ref_state: Some(New),
|
||||
},
|
||||
|
|
@ -2565,22 +2577,22 @@ mod tests {
|
|||
let _guard = settings.bind_to_scope();
|
||||
|
||||
insta::assert_debug_snapshot!(
|
||||
parse(r#"branches("foo")"#).unwrap(),
|
||||
@r###"CommitRef(Branches(Substring("foo")))"###);
|
||||
parse(r#"bookmarks("foo")"#).unwrap(),
|
||||
@r###"CommitRef(Bookmarks(Substring("foo")))"###);
|
||||
insta::assert_debug_snapshot!(
|
||||
parse(r#"branches(exact:"foo")"#).unwrap(),
|
||||
@r###"CommitRef(Branches(Exact("foo")))"###);
|
||||
parse(r#"bookmarks(exact:"foo")"#).unwrap(),
|
||||
@r###"CommitRef(Bookmarks(Exact("foo")))"###);
|
||||
insta::assert_debug_snapshot!(
|
||||
parse(r#"branches(substring:"foo")"#).unwrap(),
|
||||
@r###"CommitRef(Branches(Substring("foo")))"###);
|
||||
parse(r#"bookmarks(substring:"foo")"#).unwrap(),
|
||||
@r###"CommitRef(Bookmarks(Substring("foo")))"###);
|
||||
insta::assert_debug_snapshot!(
|
||||
parse(r#"branches(bad:"foo")"#).unwrap_err().kind(),
|
||||
parse(r#"bookmarks(bad:"foo")"#).unwrap_err().kind(),
|
||||
@r###"Expression("Invalid string pattern")"###);
|
||||
insta::assert_debug_snapshot!(
|
||||
parse(r#"branches(exact::"foo")"#).unwrap_err().kind(),
|
||||
parse(r#"bookmarks(exact::"foo")"#).unwrap_err().kind(),
|
||||
@r###"Expression("Expected expression of string pattern")"###);
|
||||
insta::assert_debug_snapshot!(
|
||||
parse(r#"branches(exact:"foo"+)"#).unwrap_err().kind(),
|
||||
parse(r#"bookmarks(exact:"foo"+)"#).unwrap_err().kind(),
|
||||
@r###"Expression("Expected expression of string pattern")"###);
|
||||
|
||||
// String pattern isn't allowed at top level.
|
||||
|
|
@ -2698,74 +2710,74 @@ mod tests {
|
|||
let _guard = settings.bind_to_scope();
|
||||
|
||||
insta::assert_debug_snapshot!(
|
||||
parse("remote_branches(remote=foo)").unwrap(), @r###"
|
||||
parse("remote_bookmarks(remote=foo)").unwrap(), @r###"
|
||||
CommitRef(
|
||||
RemoteBranches {
|
||||
branch_pattern: Substring(""),
|
||||
RemoteBookmarks {
|
||||
bookmark_pattern: Substring(""),
|
||||
remote_pattern: Substring("foo"),
|
||||
remote_ref_state: None,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
insta::assert_debug_snapshot!(
|
||||
parse("remote_branches(foo, remote=bar)").unwrap(), @r###"
|
||||
parse("remote_bookmarks(foo, remote=bar)").unwrap(), @r###"
|
||||
CommitRef(
|
||||
RemoteBranches {
|
||||
branch_pattern: Substring("foo"),
|
||||
RemoteBookmarks {
|
||||
bookmark_pattern: Substring("foo"),
|
||||
remote_pattern: Substring("bar"),
|
||||
remote_ref_state: None,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
insta::assert_debug_snapshot!(
|
||||
parse("tracked_remote_branches(foo, remote=bar)").unwrap(), @r###"
|
||||
parse("tracked_remote_bookmarks(foo, remote=bar)").unwrap(), @r###"
|
||||
CommitRef(
|
||||
RemoteBranches {
|
||||
branch_pattern: Substring("foo"),
|
||||
RemoteBookmarks {
|
||||
bookmark_pattern: Substring("foo"),
|
||||
remote_pattern: Substring("bar"),
|
||||
remote_ref_state: Some(Tracking),
|
||||
},
|
||||
)
|
||||
"###);
|
||||
insta::assert_debug_snapshot!(
|
||||
parse("untracked_remote_branches(foo, remote=bar)").unwrap(), @r###"
|
||||
parse("untracked_remote_bookmarks(foo, remote=bar)").unwrap(), @r###"
|
||||
CommitRef(
|
||||
RemoteBranches {
|
||||
branch_pattern: Substring("foo"),
|
||||
RemoteBookmarks {
|
||||
bookmark_pattern: Substring("foo"),
|
||||
remote_pattern: Substring("bar"),
|
||||
remote_ref_state: Some(New),
|
||||
},
|
||||
)
|
||||
"###);
|
||||
insta::assert_debug_snapshot!(
|
||||
parse(r#"remote_branches(remote=foo, bar)"#).unwrap_err().kind(),
|
||||
parse(r#"remote_bookmarks(remote=foo, bar)"#).unwrap_err().kind(),
|
||||
@r###"
|
||||
InvalidFunctionArguments {
|
||||
name: "remote_branches",
|
||||
name: "remote_bookmarks",
|
||||
message: "Positional argument follows keyword argument",
|
||||
}
|
||||
"###);
|
||||
insta::assert_debug_snapshot!(
|
||||
parse(r#"remote_branches("", foo, remote=bar)"#).unwrap_err().kind(),
|
||||
parse(r#"remote_bookmarks("", foo, remote=bar)"#).unwrap_err().kind(),
|
||||
@r###"
|
||||
InvalidFunctionArguments {
|
||||
name: "remote_branches",
|
||||
name: "remote_bookmarks",
|
||||
message: "Got multiple values for keyword \"remote\"",
|
||||
}
|
||||
"###);
|
||||
insta::assert_debug_snapshot!(
|
||||
parse(r#"remote_branches(remote=bar, remote=bar)"#).unwrap_err().kind(),
|
||||
parse(r#"remote_bookmarks(remote=bar, remote=bar)"#).unwrap_err().kind(),
|
||||
@r###"
|
||||
InvalidFunctionArguments {
|
||||
name: "remote_branches",
|
||||
name: "remote_bookmarks",
|
||||
message: "Got multiple values for keyword \"remote\"",
|
||||
}
|
||||
"###);
|
||||
insta::assert_debug_snapshot!(
|
||||
parse(r#"remote_branches(unknown=bar)"#).unwrap_err().kind(),
|
||||
parse(r#"remote_bookmarks(unknown=bar)"#).unwrap_err().kind(),
|
||||
@r###"
|
||||
InvalidFunctionArguments {
|
||||
name: "remote_branches",
|
||||
name: "remote_bookmarks",
|
||||
message: "Unexpected keyword argument \"unknown\"",
|
||||
}
|
||||
"###);
|
||||
|
|
@ -2833,61 +2845,61 @@ mod tests {
|
|||
// (e.g. Range -> DagRange) nor reorders arguments unintentionally.
|
||||
|
||||
insta::assert_debug_snapshot!(
|
||||
optimize(parse("parents(branches() & all())").unwrap()), @r###"
|
||||
optimize(parse("parents(bookmarks() & all())").unwrap()), @r###"
|
||||
Ancestors {
|
||||
heads: CommitRef(Branches(Substring(""))),
|
||||
heads: CommitRef(Bookmarks(Substring(""))),
|
||||
generation: 1..2,
|
||||
}
|
||||
"###);
|
||||
insta::assert_debug_snapshot!(
|
||||
optimize(parse("children(branches() & all())").unwrap()), @r###"
|
||||
optimize(parse("children(bookmarks() & all())").unwrap()), @r###"
|
||||
Descendants {
|
||||
roots: CommitRef(Branches(Substring(""))),
|
||||
roots: CommitRef(Bookmarks(Substring(""))),
|
||||
generation: 1..2,
|
||||
}
|
||||
"###);
|
||||
insta::assert_debug_snapshot!(
|
||||
optimize(parse("ancestors(branches() & all())").unwrap()), @r###"
|
||||
optimize(parse("ancestors(bookmarks() & all())").unwrap()), @r###"
|
||||
Ancestors {
|
||||
heads: CommitRef(Branches(Substring(""))),
|
||||
heads: CommitRef(Bookmarks(Substring(""))),
|
||||
generation: 0..18446744073709551615,
|
||||
}
|
||||
"###);
|
||||
insta::assert_debug_snapshot!(
|
||||
optimize(parse("descendants(branches() & all())").unwrap()), @r###"
|
||||
optimize(parse("descendants(bookmarks() & all())").unwrap()), @r###"
|
||||
Descendants {
|
||||
roots: CommitRef(Branches(Substring(""))),
|
||||
roots: CommitRef(Bookmarks(Substring(""))),
|
||||
generation: 0..18446744073709551615,
|
||||
}
|
||||
"###);
|
||||
|
||||
insta::assert_debug_snapshot!(
|
||||
optimize(parse("(branches() & all())..(all() & tags())").unwrap()), @r###"
|
||||
optimize(parse("(bookmarks() & all())..(all() & tags())").unwrap()), @r###"
|
||||
Range {
|
||||
roots: CommitRef(Branches(Substring(""))),
|
||||
roots: CommitRef(Bookmarks(Substring(""))),
|
||||
heads: CommitRef(Tags),
|
||||
generation: 0..18446744073709551615,
|
||||
}
|
||||
"###);
|
||||
insta::assert_debug_snapshot!(
|
||||
optimize(parse("(branches() & all())::(all() & tags())").unwrap()), @r###"
|
||||
optimize(parse("(bookmarks() & all())::(all() & tags())").unwrap()), @r###"
|
||||
DagRange {
|
||||
roots: CommitRef(Branches(Substring(""))),
|
||||
roots: CommitRef(Bookmarks(Substring(""))),
|
||||
heads: CommitRef(Tags),
|
||||
}
|
||||
"###);
|
||||
|
||||
insta::assert_debug_snapshot!(
|
||||
optimize(parse("heads(branches() & all())").unwrap()),
|
||||
@r###"Heads(CommitRef(Branches(Substring(""))))"###);
|
||||
optimize(parse("heads(bookmarks() & all())").unwrap()),
|
||||
@r###"Heads(CommitRef(Bookmarks(Substring(""))))"###);
|
||||
insta::assert_debug_snapshot!(
|
||||
optimize(parse("roots(branches() & all())").unwrap()),
|
||||
@r###"Roots(CommitRef(Branches(Substring(""))))"###);
|
||||
optimize(parse("roots(bookmarks() & all())").unwrap()),
|
||||
@r###"Roots(CommitRef(Bookmarks(Substring(""))))"###);
|
||||
|
||||
insta::assert_debug_snapshot!(
|
||||
optimize(parse("latest(branches() & all(), 2)").unwrap()), @r###"
|
||||
optimize(parse("latest(bookmarks() & all(), 2)").unwrap()), @r###"
|
||||
Latest {
|
||||
candidates: CommitRef(Branches(Substring(""))),
|
||||
candidates: CommitRef(Bookmarks(Substring(""))),
|
||||
count: 2,
|
||||
}
|
||||
"###);
|
||||
|
|
@ -2902,30 +2914,30 @@ mod tests {
|
|||
)
|
||||
"###);
|
||||
insta::assert_debug_snapshot!(
|
||||
optimize(parse("present(branches() & all())").unwrap()),
|
||||
@r###"Present(CommitRef(Branches(Substring(""))))"###);
|
||||
optimize(parse("present(bookmarks() & all())").unwrap()),
|
||||
@r###"Present(CommitRef(Bookmarks(Substring(""))))"###);
|
||||
|
||||
insta::assert_debug_snapshot!(
|
||||
optimize(parse("~branches() & all()").unwrap()),
|
||||
@r###"NotIn(CommitRef(Branches(Substring(""))))"###);
|
||||
optimize(parse("~bookmarks() & all()").unwrap()),
|
||||
@r###"NotIn(CommitRef(Bookmarks(Substring(""))))"###);
|
||||
insta::assert_debug_snapshot!(
|
||||
optimize(parse("(branches() & all()) | (all() & tags())").unwrap()), @r###"
|
||||
optimize(parse("(bookmarks() & all()) | (all() & tags())").unwrap()), @r###"
|
||||
Union(
|
||||
CommitRef(Branches(Substring(""))),
|
||||
CommitRef(Bookmarks(Substring(""))),
|
||||
CommitRef(Tags),
|
||||
)
|
||||
"###);
|
||||
insta::assert_debug_snapshot!(
|
||||
optimize(parse("(branches() & all()) & (all() & tags())").unwrap()), @r###"
|
||||
optimize(parse("(bookmarks() & all()) & (all() & tags())").unwrap()), @r###"
|
||||
Intersection(
|
||||
CommitRef(Branches(Substring(""))),
|
||||
CommitRef(Bookmarks(Substring(""))),
|
||||
CommitRef(Tags),
|
||||
)
|
||||
"###);
|
||||
insta::assert_debug_snapshot!(
|
||||
optimize(parse("(branches() & all()) ~ (all() & tags())").unwrap()), @r###"
|
||||
optimize(parse("(bookmarks() & all()) ~ (all() & tags())").unwrap()), @r###"
|
||||
Difference(
|
||||
CommitRef(Branches(Substring(""))),
|
||||
CommitRef(Bookmarks(Substring(""))),
|
||||
CommitRef(Tags),
|
||||
)
|
||||
"###);
|
||||
|
|
@ -2947,20 +2959,20 @@ mod tests {
|
|||
let optimized = optimize(parsed.clone());
|
||||
assert!(Rc::ptr_eq(&parsed, &optimized));
|
||||
|
||||
let parsed = parse("branches() | tags()").unwrap();
|
||||
let parsed = parse("bookmarks() | tags()").unwrap();
|
||||
let optimized = optimize(parsed.clone());
|
||||
assert!(Rc::ptr_eq(&parsed, &optimized));
|
||||
|
||||
let parsed = parse("branches() & tags()").unwrap();
|
||||
let parsed = parse("bookmarks() & tags()").unwrap();
|
||||
let optimized = optimize(parsed.clone());
|
||||
assert!(Rc::ptr_eq(&parsed, &optimized));
|
||||
|
||||
// Only left subtree should be rewritten.
|
||||
let parsed = parse("(branches() & all()) | tags()").unwrap();
|
||||
let parsed = parse("(bookmarks() & all()) | tags()").unwrap();
|
||||
let optimized = optimize(parsed.clone());
|
||||
assert_matches!(
|
||||
unwrap_union(&optimized).0.as_ref(),
|
||||
RevsetExpression::CommitRef(RevsetCommitRef::Branches(_))
|
||||
RevsetExpression::CommitRef(RevsetCommitRef::Bookmarks(_))
|
||||
);
|
||||
assert!(Rc::ptr_eq(
|
||||
unwrap_union(&parsed).1,
|
||||
|
|
@ -2968,7 +2980,7 @@ mod tests {
|
|||
));
|
||||
|
||||
// Only right subtree should be rewritten.
|
||||
let parsed = parse("branches() | (all() & tags())").unwrap();
|
||||
let parsed = parse("bookmarks() | (all() & tags())").unwrap();
|
||||
let optimized = optimize(parsed.clone());
|
||||
assert!(Rc::ptr_eq(
|
||||
unwrap_union(&parsed).0,
|
||||
|
|
|
|||
|
|
@ -44,14 +44,14 @@ pub struct RepoSettings {
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct GitSettings {
|
||||
pub auto_local_branch: bool,
|
||||
pub auto_local_bookmark: bool,
|
||||
pub abandon_unreachable_commits: bool,
|
||||
}
|
||||
|
||||
impl GitSettings {
|
||||
pub fn from_config(config: &config::Config) -> Self {
|
||||
GitSettings {
|
||||
auto_local_branch: config.get_bool("git.auto-local-branch").unwrap_or(false),
|
||||
auto_local_bookmark: config.get_bool("git.auto-local-branch").unwrap_or(false),
|
||||
abandon_unreachable_commits: config
|
||||
.get_bool("git.abandon-unreachable-commits")
|
||||
.unwrap_or(true),
|
||||
|
|
@ -62,7 +62,7 @@ impl GitSettings {
|
|||
impl Default for GitSettings {
|
||||
fn default() -> Self {
|
||||
GitSettings {
|
||||
auto_local_branch: false,
|
||||
auto_local_bookmark: false,
|
||||
abandon_unreachable_commits: true,
|
||||
}
|
||||
}
|
||||
|
|
@ -190,9 +190,9 @@ impl UserSettings {
|
|||
.unwrap_or_else(|_| whoami::username())
|
||||
}
|
||||
|
||||
pub fn push_branch_prefix(&self) -> String {
|
||||
pub fn push_bookmark_prefix(&self) -> String {
|
||||
self.config
|
||||
.get_string("git.push-branch-prefix")
|
||||
.get_string("git.push-bookmark-prefix")
|
||||
.unwrap_or_else(|_| "push-".to_string())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -436,7 +436,7 @@ fn view_to_proto(view: &View) -> crate::protos::op_store::View {
|
|||
proto.head_ids.push(head_id.to_bytes());
|
||||
}
|
||||
|
||||
proto.branches = branch_views_to_proto_legacy(&view.local_branches, &view.remote_views);
|
||||
proto.branches = bookmark_views_to_proto_legacy(&view.local_bookmarks, &view.remote_views);
|
||||
|
||||
for (name, target) in &view.tags {
|
||||
proto.tags.push(crate::protos::op_store::Tag {
|
||||
|
|
@ -475,8 +475,8 @@ fn view_from_proto(proto: crate::protos::op_store::View) -> View {
|
|||
view.head_ids.insert(CommitId::new(head_id_bytes));
|
||||
}
|
||||
|
||||
let (local_branches, remote_views) = branch_views_from_proto_legacy(proto.branches);
|
||||
view.local_branches = local_branches;
|
||||
let (local_bookmarks, remote_views) = bookmark_views_from_proto_legacy(proto.branches);
|
||||
view.local_bookmarks = local_bookmarks;
|
||||
view.remote_views = remote_views;
|
||||
|
||||
for tag_proto in proto.tags {
|
||||
|
|
@ -508,14 +508,14 @@ fn view_from_proto(proto: crate::protos::op_store::View) -> View {
|
|||
view
|
||||
}
|
||||
|
||||
fn branch_views_to_proto_legacy(
|
||||
local_branches: &BTreeMap<String, RefTarget>,
|
||||
fn bookmark_views_to_proto_legacy(
|
||||
local_bookmarks: &BTreeMap<String, RefTarget>,
|
||||
remote_views: &BTreeMap<String, RemoteView>,
|
||||
) -> Vec<crate::protos::op_store::Branch> {
|
||||
op_store::merge_join_branch_views(local_branches, remote_views)
|
||||
.map(|(name, branch_target)| {
|
||||
let local_target = ref_target_to_proto(branch_target.local_target);
|
||||
let remote_branches = branch_target
|
||||
op_store::merge_join_bookmark_views(local_bookmarks, remote_views)
|
||||
.map(|(name, bookmark_target)| {
|
||||
let local_target = ref_target_to_proto(bookmark_target.local_target);
|
||||
let remote_bookmarks = bookmark_target
|
||||
.remote_refs
|
||||
.iter()
|
||||
.map(
|
||||
|
|
@ -529,29 +529,30 @@ fn branch_views_to_proto_legacy(
|
|||
crate::protos::op_store::Branch {
|
||||
name: name.to_owned(),
|
||||
local_target,
|
||||
remote_branches,
|
||||
remote_branches: remote_bookmarks,
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn branch_views_from_proto_legacy(
|
||||
branches_legacy: Vec<crate::protos::op_store::Branch>,
|
||||
fn bookmark_views_from_proto_legacy(
|
||||
bookmarks_legacy: Vec<crate::protos::op_store::Branch>,
|
||||
) -> (BTreeMap<String, RefTarget>, BTreeMap<String, RemoteView>) {
|
||||
let mut local_branches: BTreeMap<String, RefTarget> = BTreeMap::new();
|
||||
let mut local_bookmarks: BTreeMap<String, RefTarget> = BTreeMap::new();
|
||||
let mut remote_views: BTreeMap<String, RemoteView> = BTreeMap::new();
|
||||
for branch_proto in branches_legacy {
|
||||
let local_target = ref_target_from_proto(branch_proto.local_target);
|
||||
for remote_branch in branch_proto.remote_branches {
|
||||
let state = remote_ref_state_from_proto(remote_branch.state).unwrap_or_else(|| {
|
||||
// If local branch doesn't exist, we assume that the remote branch hasn't been
|
||||
// merged because git.auto-local-branch was off. That's probably more common
|
||||
// than deleted but yet-to-be-pushed local branch. Alternatively, we could read
|
||||
// git.auto-local-branch setting here, but that wouldn't always work since the
|
||||
// setting could be toggled after the branch got merged.
|
||||
for bookmark_proto in bookmarks_legacy {
|
||||
let local_target = ref_target_from_proto(bookmark_proto.local_target);
|
||||
for remote_bookmark in bookmark_proto.remote_branches {
|
||||
let state = remote_ref_state_from_proto(remote_bookmark.state).unwrap_or_else(|| {
|
||||
// If local bookmark doesn't exist, we assume that the remote bookmark hasn't
|
||||
// been merged because git.auto-local-bookmark was off. That's
|
||||
// probably more common than deleted but yet-to-be-pushed local
|
||||
// bookmark. Alternatively, we could read
|
||||
// git.auto-local-bookmark setting here, but that wouldn't always work since the
|
||||
// setting could be toggled after the bookmark got merged.
|
||||
#[cfg(feature = "git")]
|
||||
let is_git_tracking =
|
||||
remote_branch.remote_name == crate::git::REMOTE_NAME_FOR_LOCAL_GIT_REPO;
|
||||
remote_bookmark.remote_name == crate::git::REMOTE_NAME_FOR_LOCAL_GIT_REPO;
|
||||
#[cfg(not(feature = "git"))]
|
||||
let is_git_tracking = false;
|
||||
let default_state = if is_git_tracking || local_target.is_present() {
|
||||
|
|
@ -560,27 +561,27 @@ fn branch_views_from_proto_legacy(
|
|||
RemoteRefState::New
|
||||
};
|
||||
tracing::trace!(
|
||||
?branch_proto.name,
|
||||
?remote_branch.remote_name,
|
||||
?bookmark_proto.name,
|
||||
?remote_bookmark.remote_name,
|
||||
?default_state,
|
||||
"generated tracking state",
|
||||
);
|
||||
default_state
|
||||
});
|
||||
let remote_view = remote_views.entry(remote_branch.remote_name).or_default();
|
||||
let remote_view = remote_views.entry(remote_bookmark.remote_name).or_default();
|
||||
let remote_ref = RemoteRef {
|
||||
target: ref_target_from_proto(remote_branch.target),
|
||||
target: ref_target_from_proto(remote_bookmark.target),
|
||||
state,
|
||||
};
|
||||
remote_view
|
||||
.branches
|
||||
.insert(branch_proto.name.clone(), remote_ref);
|
||||
.bookmarks
|
||||
.insert(bookmark_proto.name.clone(), remote_ref);
|
||||
}
|
||||
if local_target.is_present() {
|
||||
local_branches.insert(branch_proto.name, local_target);
|
||||
local_bookmarks.insert(bookmark_proto.name, local_target);
|
||||
}
|
||||
}
|
||||
(local_branches, remote_views)
|
||||
(local_bookmarks, remote_views)
|
||||
}
|
||||
|
||||
fn migrate_git_refs_to_remote(view: &mut View) {
|
||||
|
|
@ -589,17 +590,17 @@ fn migrate_git_refs_to_remote(view: &mut View) {
|
|||
return;
|
||||
}
|
||||
|
||||
tracing::info!("migrating Git-tracking branches");
|
||||
tracing::info!("migrating Git-tracking bookmarks");
|
||||
let mut git_view = RemoteView::default();
|
||||
for (full_name, target) in &view.git_refs {
|
||||
if let Some(name) = full_name.strip_prefix("refs/heads/") {
|
||||
assert!(!name.is_empty());
|
||||
let remote_ref = RemoteRef {
|
||||
target: target.clone(),
|
||||
// Git-tracking branches should never be untracked.
|
||||
// Git-tracking bookmarks should never be untracked.
|
||||
state: RemoteRefState::Tracking,
|
||||
};
|
||||
git_view.branches.insert(name.to_owned(), remote_ref);
|
||||
git_view.bookmarks.insert(name.to_owned(), remote_ref);
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "git")]
|
||||
|
|
@ -731,9 +732,9 @@ mod tests {
|
|||
};
|
||||
let head_id1 = CommitId::from_hex("aaa111");
|
||||
let head_id2 = CommitId::from_hex("aaa222");
|
||||
let branch_main_local_target = RefTarget::normal(CommitId::from_hex("ccc111"));
|
||||
let branch_main_origin_target = RefTarget::normal(CommitId::from_hex("ccc222"));
|
||||
let branch_deleted_origin_target = RefTarget::normal(CommitId::from_hex("ccc333"));
|
||||
let bookmark_main_local_target = RefTarget::normal(CommitId::from_hex("ccc111"));
|
||||
let bookmark_main_origin_target = RefTarget::normal(CommitId::from_hex("ccc222"));
|
||||
let bookmark_deleted_origin_target = RefTarget::normal(CommitId::from_hex("ccc333"));
|
||||
let tag_v1_target = RefTarget::normal(CommitId::from_hex("ddd111"));
|
||||
let git_refs_main_target = RefTarget::normal(CommitId::from_hex("fff111"));
|
||||
let git_refs_feature_target = RefTarget::from_legacy_form(
|
||||
|
|
@ -744,17 +745,17 @@ mod tests {
|
|||
let test_wc_commit_id = CommitId::from_hex("abc222");
|
||||
View {
|
||||
head_ids: hashset! {head_id1, head_id2},
|
||||
local_branches: btreemap! {
|
||||
"main".to_string() => branch_main_local_target,
|
||||
local_bookmarks: btreemap! {
|
||||
"main".to_string() => bookmark_main_local_target,
|
||||
},
|
||||
tags: btreemap! {
|
||||
"v1.0".to_string() => tag_v1_target,
|
||||
},
|
||||
remote_views: btreemap! {
|
||||
"origin".to_string() => RemoteView {
|
||||
branches: btreemap! {
|
||||
"main".to_string() => tracking_remote_ref(&branch_main_origin_target),
|
||||
"deleted".to_string() => new_remote_ref(&branch_deleted_origin_target),
|
||||
bookmarks: btreemap! {
|
||||
"main".to_string() => tracking_remote_ref(&bookmark_main_origin_target),
|
||||
"deleted".to_string() => new_remote_ref(&bookmark_deleted_origin_target),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -837,7 +838,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_branch_views_legacy_roundtrip() {
|
||||
fn test_bookmark_views_legacy_roundtrip() {
|
||||
let new_remote_ref = |target: &RefTarget| RemoteRef {
|
||||
target: target.clone(),
|
||||
state: RemoteRefState::New,
|
||||
|
|
@ -846,49 +847,49 @@ mod tests {
|
|||
target: target.clone(),
|
||||
state: RemoteRefState::Tracking,
|
||||
};
|
||||
let local_branch1_target = RefTarget::normal(CommitId::from_hex("111111"));
|
||||
let local_branch3_target = RefTarget::normal(CommitId::from_hex("222222"));
|
||||
let git_branch1_target = RefTarget::normal(CommitId::from_hex("333333"));
|
||||
let remote1_branch1_target = RefTarget::normal(CommitId::from_hex("444444"));
|
||||
let remote2_branch2_target = RefTarget::normal(CommitId::from_hex("555555"));
|
||||
let remote2_branch4_target = RefTarget::normal(CommitId::from_hex("666666"));
|
||||
let local_branches = btreemap! {
|
||||
"branch1".to_owned() => local_branch1_target.clone(),
|
||||
"branch3".to_owned() => local_branch3_target.clone(),
|
||||
let local_bookmark1_target = RefTarget::normal(CommitId::from_hex("111111"));
|
||||
let local_bookmark3_target = RefTarget::normal(CommitId::from_hex("222222"));
|
||||
let git_bookmark1_target = RefTarget::normal(CommitId::from_hex("333333"));
|
||||
let remote1_bookmark1_target = RefTarget::normal(CommitId::from_hex("444444"));
|
||||
let remote2_bookmark2_target = RefTarget::normal(CommitId::from_hex("555555"));
|
||||
let remote2_bookmark4_target = RefTarget::normal(CommitId::from_hex("666666"));
|
||||
let local_bookmarks = btreemap! {
|
||||
"bookmark1".to_owned() => local_bookmark1_target.clone(),
|
||||
"bookmark3".to_owned() => local_bookmark3_target.clone(),
|
||||
};
|
||||
let remote_views = btreemap! {
|
||||
"git".to_owned() => RemoteView {
|
||||
branches: btreemap! {
|
||||
"branch1".to_owned() => tracking_remote_ref(&git_branch1_target),
|
||||
bookmarks: btreemap! {
|
||||
"bookmark1".to_owned() => tracking_remote_ref(&git_bookmark1_target),
|
||||
},
|
||||
},
|
||||
"remote1".to_owned() => RemoteView {
|
||||
branches: btreemap! {
|
||||
"branch1".to_owned() => tracking_remote_ref(&remote1_branch1_target),
|
||||
bookmarks: btreemap! {
|
||||
"bookmark1".to_owned() => tracking_remote_ref(&remote1_bookmark1_target),
|
||||
},
|
||||
},
|
||||
"remote2".to_owned() => RemoteView {
|
||||
branches: btreemap! {
|
||||
// "branch2" is non-tracking. "branch4" is tracking, but locally deleted.
|
||||
"branch2".to_owned() => new_remote_ref(&remote2_branch2_target),
|
||||
"branch4".to_owned() => tracking_remote_ref(&remote2_branch4_target),
|
||||
bookmarks: btreemap! {
|
||||
// "bookmark2" is non-tracking. "bookmark4" is tracking, but locally deleted.
|
||||
"bookmark2".to_owned() => new_remote_ref(&remote2_bookmark2_target),
|
||||
"bookmark4".to_owned() => tracking_remote_ref(&remote2_bookmark4_target),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
let branches_legacy = branch_views_to_proto_legacy(&local_branches, &remote_views);
|
||||
let bookmarks_legacy = bookmark_views_to_proto_legacy(&local_bookmarks, &remote_views);
|
||||
assert_eq!(
|
||||
branches_legacy
|
||||
bookmarks_legacy
|
||||
.iter()
|
||||
.map(|proto| &proto.name)
|
||||
.sorted()
|
||||
.collect_vec(),
|
||||
vec!["branch1", "branch2", "branch3", "branch4"],
|
||||
vec!["bookmark1", "bookmark2", "bookmark3", "bookmark4"],
|
||||
);
|
||||
|
||||
let (local_branches_reconstructed, remote_views_reconstructed) =
|
||||
branch_views_from_proto_legacy(branches_legacy);
|
||||
assert_eq!(local_branches_reconstructed, local_branches);
|
||||
let (local_bookmarks_reconstructed, remote_views_reconstructed) =
|
||||
bookmark_views_from_proto_legacy(bookmarks_legacy);
|
||||
assert_eq!(local_bookmarks_reconstructed, local_bookmarks);
|
||||
assert_eq!(remote_views_reconstructed, remote_views);
|
||||
}
|
||||
|
||||
|
|
@ -903,17 +904,17 @@ mod tests {
|
|||
target: normal_ref_target(id_hex),
|
||||
state: RemoteRefState::Tracking,
|
||||
};
|
||||
let branch_to_proto =
|
||||
let bookmark_to_proto =
|
||||
|name: &str, local_ref_target, remote_branches| crate::protos::op_store::Branch {
|
||||
name: name.to_owned(),
|
||||
local_target: ref_target_to_proto(local_ref_target),
|
||||
remote_branches,
|
||||
};
|
||||
let remote_branch_to_proto =
|
||||
let remote_bookmark_to_proto =
|
||||
|remote_name: &str, ref_target| crate::protos::op_store::RemoteBranch {
|
||||
remote_name: remote_name.to_owned(),
|
||||
target: ref_target_to_proto(ref_target),
|
||||
state: None, // to be generated based on local branch existence
|
||||
state: None, // to be generated based on local bookmark existence
|
||||
};
|
||||
let git_ref_to_proto = |name: &str, ref_target| crate::protos::op_store::GitRef {
|
||||
name: name.to_owned(),
|
||||
|
|
@ -923,18 +924,21 @@ mod tests {
|
|||
|
||||
let proto = crate::protos::op_store::View {
|
||||
branches: vec![
|
||||
branch_to_proto(
|
||||
bookmark_to_proto(
|
||||
"main",
|
||||
&normal_ref_target("111111"),
|
||||
vec![
|
||||
remote_branch_to_proto("git", &normal_ref_target("222222")),
|
||||
remote_branch_to_proto("gita", &normal_ref_target("333333")),
|
||||
remote_bookmark_to_proto("git", &normal_ref_target("222222")),
|
||||
remote_bookmark_to_proto("gita", &normal_ref_target("333333")),
|
||||
],
|
||||
),
|
||||
branch_to_proto(
|
||||
bookmark_to_proto(
|
||||
"untracked",
|
||||
RefTarget::absent_ref(),
|
||||
vec![remote_branch_to_proto("gita", &normal_ref_target("777777"))],
|
||||
vec![remote_bookmark_to_proto(
|
||||
"gita",
|
||||
&normal_ref_target("777777"),
|
||||
)],
|
||||
),
|
||||
],
|
||||
git_refs: vec![
|
||||
|
|
@ -949,7 +953,7 @@ mod tests {
|
|||
|
||||
let view = view_from_proto(proto);
|
||||
assert_eq!(
|
||||
view.local_branches,
|
||||
view.local_bookmarks,
|
||||
btreemap! {
|
||||
"main".to_owned() => normal_ref_target("111111"),
|
||||
},
|
||||
|
|
@ -958,12 +962,12 @@ mod tests {
|
|||
view.remote_views,
|
||||
btreemap! {
|
||||
"git".to_owned() => RemoteView {
|
||||
branches: btreemap! {
|
||||
bookmarks: btreemap! {
|
||||
"main".to_owned() => normal_tracking_remote_ref("444444"), // refs/heads/main
|
||||
},
|
||||
},
|
||||
"gita".to_owned() => RemoteView {
|
||||
branches: btreemap! {
|
||||
bookmarks: btreemap! {
|
||||
"main".to_owned() => normal_tracking_remote_ref("333333"),
|
||||
"untracked".to_owned() => normal_new_remote_ref("777777"),
|
||||
},
|
||||
|
|
@ -979,7 +983,7 @@ mod tests {
|
|||
},
|
||||
);
|
||||
|
||||
// Once migrated, "git" remote branches shouldn't be populated again.
|
||||
// Once migrated, "git" remote bookmarks shouldn't be populated again.
|
||||
let mut proto = view_to_proto(&view);
|
||||
assert!(proto.has_git_refs_migrated_to_remote);
|
||||
proto.branches.clear();
|
||||
|
|
|
|||
140
lib/src/view.rs
140
lib/src/view.rs
|
|
@ -70,9 +70,9 @@ impl View {
|
|||
&self.data.head_ids
|
||||
}
|
||||
|
||||
/// Iterates pair of local and remote branches by branch name.
|
||||
pub fn branches(&self) -> impl Iterator<Item = (&str, BranchTarget<'_>)> {
|
||||
op_store::merge_join_branch_views(&self.data.local_branches, &self.data.remote_views)
|
||||
/// Iterates pair of local and remote bookmarks by bookmark name.
|
||||
pub fn bookmarks(&self) -> impl Iterator<Item = (&str, BranchTarget<'_>)> {
|
||||
op_store::merge_join_bookmark_views(&self.data.local_bookmarks, &self.data.remote_views)
|
||||
}
|
||||
|
||||
pub fn tags(&self) -> &BTreeMap<String, RefTarget> {
|
||||
|
|
@ -103,63 +103,64 @@ impl View {
|
|||
self.data.head_ids.remove(head_id);
|
||||
}
|
||||
|
||||
/// Iterates local branch `(name, target)`s in lexicographical order.
|
||||
pub fn local_branches(&self) -> impl Iterator<Item = (&str, &RefTarget)> {
|
||||
/// Iterates local bookmark `(name, target)`s in lexicographical order.
|
||||
pub fn local_bookmarks(&self) -> impl Iterator<Item = (&str, &RefTarget)> {
|
||||
self.data
|
||||
.local_branches
|
||||
.local_bookmarks
|
||||
.iter()
|
||||
.map(|(name, target)| (name.as_ref(), target))
|
||||
}
|
||||
|
||||
/// Iterates local branches `(name, target)` in lexicographical order where
|
||||
/// Iterates local bookmarks `(name, target)` in lexicographical order where
|
||||
/// the target adds `commit_id`.
|
||||
pub fn local_branches_for_commit<'a: 'b, 'b>(
|
||||
pub fn local_bookmarks_for_commit<'a: 'b, 'b>(
|
||||
&'a self,
|
||||
commit_id: &'b CommitId,
|
||||
) -> impl Iterator<Item = (&'a str, &'a RefTarget)> + 'b {
|
||||
self.local_branches()
|
||||
self.local_bookmarks()
|
||||
.filter(|(_, target)| target.added_ids().contains(commit_id))
|
||||
}
|
||||
|
||||
/// Iterates local branch `(name, target)`s matching the given pattern.
|
||||
/// Iterates local bookmark `(name, target)`s matching the given pattern.
|
||||
/// Entries are sorted by `name`.
|
||||
pub fn local_branches_matching<'a: 'b, 'b>(
|
||||
pub fn local_bookmarks_matching<'a: 'b, 'b>(
|
||||
&'a self,
|
||||
pattern: &'b StringPattern,
|
||||
) -> impl Iterator<Item = (&'a str, &'a RefTarget)> + 'b {
|
||||
pattern
|
||||
.filter_btree_map(&self.data.local_branches)
|
||||
.filter_btree_map(&self.data.local_bookmarks)
|
||||
.map(|(name, target)| (name.as_ref(), target))
|
||||
}
|
||||
|
||||
pub fn get_local_branch(&self, name: &str) -> &RefTarget {
|
||||
self.data.local_branches.get(name).flatten()
|
||||
pub fn get_local_bookmark(&self, name: &str) -> &RefTarget {
|
||||
self.data.local_bookmarks.get(name).flatten()
|
||||
}
|
||||
|
||||
/// Sets local branch to point to the given target. If the target is absent,
|
||||
/// and if no associated remote branches exist, the branch will be removed.
|
||||
pub fn set_local_branch_target(&mut self, name: &str, target: RefTarget) {
|
||||
/// Sets local bookmark to point to the given target. If the target is
|
||||
/// absent, and if no associated remote bookmarks exist, the bookmark
|
||||
/// will be removed.
|
||||
pub fn set_local_bookmark_target(&mut self, name: &str, target: RefTarget) {
|
||||
if target.is_present() {
|
||||
self.data.local_branches.insert(name.to_owned(), target);
|
||||
self.data.local_bookmarks.insert(name.to_owned(), target);
|
||||
} else {
|
||||
self.data.local_branches.remove(name);
|
||||
self.data.local_bookmarks.remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterates over `((name, remote_name), remote_ref)` for all remote
|
||||
/// branches in lexicographical order.
|
||||
pub fn all_remote_branches(&self) -> impl Iterator<Item = ((&str, &str), &RemoteRef)> {
|
||||
op_store::flatten_remote_branches(&self.data.remote_views)
|
||||
/// bookmarks in lexicographical order.
|
||||
pub fn all_remote_bookmarks(&self) -> impl Iterator<Item = ((&str, &str), &RemoteRef)> {
|
||||
op_store::flatten_remote_bookmarks(&self.data.remote_views)
|
||||
}
|
||||
|
||||
/// Iterates over `(name, remote_ref)`s for all remote branches of the
|
||||
/// Iterates over `(name, remote_ref)`s for all remote bookmarks of the
|
||||
/// specified remote in lexicographical order.
|
||||
pub fn remote_branches(&self, remote_name: &str) -> impl Iterator<Item = (&str, &RemoteRef)> {
|
||||
pub fn remote_bookmarks(&self, remote_name: &str) -> impl Iterator<Item = (&str, &RemoteRef)> {
|
||||
let maybe_remote_view = self.data.remote_views.get(remote_name);
|
||||
maybe_remote_view
|
||||
.map(|remote_view| {
|
||||
remote_view
|
||||
.branches
|
||||
.bookmarks
|
||||
.iter()
|
||||
.map(|(name, remote_ref)| (name.as_ref(), remote_ref))
|
||||
})
|
||||
|
|
@ -167,94 +168,97 @@ impl View {
|
|||
.flatten()
|
||||
}
|
||||
|
||||
/// Iterates over `(name, remote_ref)`s for all remote branches of the
|
||||
/// Iterates over `(name, remote_ref)`s for all remote bookmarks of the
|
||||
/// specified remote that match the given pattern.
|
||||
///
|
||||
/// Entries are sorted by `(name, remote_name)`.
|
||||
pub fn remote_branches_matching<'a: 'b, 'b>(
|
||||
pub fn remote_bookmarks_matching<'a: 'b, 'b>(
|
||||
&'a self,
|
||||
branch_pattern: &'b StringPattern,
|
||||
bookmark_pattern: &'b StringPattern,
|
||||
remote_pattern: &'b StringPattern,
|
||||
) -> impl Iterator<Item = ((&'a str, &'a str), &'a RemoteRef)> + 'b {
|
||||
// Use kmerge instead of flat_map for consistency with all_remote_branches().
|
||||
// Use kmerge instead of flat_map for consistency with all_remote_bookmarks().
|
||||
remote_pattern
|
||||
.filter_btree_map(&self.data.remote_views)
|
||||
.map(|(remote_name, remote_view)| {
|
||||
branch_pattern.filter_btree_map(&remote_view.branches).map(
|
||||
|(branch_name, remote_ref)| {
|
||||
let full_name = (branch_name.as_ref(), remote_name.as_ref());
|
||||
bookmark_pattern
|
||||
.filter_btree_map(&remote_view.bookmarks)
|
||||
.map(|(bookmark_name, remote_ref)| {
|
||||
let full_name = (bookmark_name.as_ref(), remote_name.as_ref());
|
||||
(full_name, remote_ref)
|
||||
},
|
||||
)
|
||||
})
|
||||
})
|
||||
.kmerge_by(|(full_name1, _), (full_name2, _)| full_name1 < full_name2)
|
||||
}
|
||||
|
||||
pub fn get_remote_branch(&self, name: &str, remote_name: &str) -> &RemoteRef {
|
||||
pub fn get_remote_bookmark(&self, name: &str, remote_name: &str) -> &RemoteRef {
|
||||
if let Some(remote_view) = self.data.remote_views.get(remote_name) {
|
||||
remote_view.branches.get(name).flatten()
|
||||
remote_view.bookmarks.get(name).flatten()
|
||||
} else {
|
||||
RemoteRef::absent_ref()
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets remote-tracking branch to the given target and state. If the target
|
||||
/// is absent, the branch will be removed.
|
||||
pub fn set_remote_branch(&mut self, name: &str, remote_name: &str, remote_ref: RemoteRef) {
|
||||
/// Sets remote-tracking bookmark to the given target and state. If the
|
||||
/// target is absent, the bookmark will be removed.
|
||||
pub fn set_remote_bookmark(&mut self, name: &str, remote_name: &str, remote_ref: RemoteRef) {
|
||||
if remote_ref.is_present() {
|
||||
let remote_view = self
|
||||
.data
|
||||
.remote_views
|
||||
.entry(remote_name.to_owned())
|
||||
.or_default();
|
||||
remote_view.branches.insert(name.to_owned(), remote_ref);
|
||||
remote_view.bookmarks.insert(name.to_owned(), remote_ref);
|
||||
} else if let Some(remote_view) = self.data.remote_views.get_mut(remote_name) {
|
||||
remote_view.branches.remove(name);
|
||||
remote_view.bookmarks.remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterates over `(name, {local_ref, remote_ref})`s for every branch
|
||||
/// Iterates over `(name, {local_ref, remote_ref})`s for every bookmark
|
||||
/// present locally and/or on the specified remote, in lexicographical
|
||||
/// order.
|
||||
///
|
||||
/// Note that this does *not* take into account whether the local branch
|
||||
/// tracks the remote branch or not. Missing values are represented as
|
||||
/// Note that this does *not* take into account whether the local bookmark
|
||||
/// tracks the remote bookmark or not. Missing values are represented as
|
||||
/// RefTarget::absent_ref() or RemoteRef::absent_ref().
|
||||
pub fn local_remote_branches<'a>(
|
||||
pub fn local_remote_bookmarks<'a>(
|
||||
&'a self,
|
||||
remote_name: &str,
|
||||
) -> impl Iterator<Item = (&'a str, LocalAndRemoteRef<'a>)> + 'a {
|
||||
refs::iter_named_local_remote_refs(self.local_branches(), self.remote_branches(remote_name))
|
||||
.map(|(name, (local_target, remote_ref))| {
|
||||
let targets = LocalAndRemoteRef {
|
||||
local_target,
|
||||
remote_ref,
|
||||
};
|
||||
(name, targets)
|
||||
})
|
||||
refs::iter_named_local_remote_refs(
|
||||
self.local_bookmarks(),
|
||||
self.remote_bookmarks(remote_name),
|
||||
)
|
||||
.map(|(name, (local_target, remote_ref))| {
|
||||
let targets = LocalAndRemoteRef {
|
||||
local_target,
|
||||
remote_ref,
|
||||
};
|
||||
(name, targets)
|
||||
})
|
||||
}
|
||||
|
||||
/// Iterates over `(name, TrackingRefPair {local_ref, remote_ref})`s for
|
||||
/// every branch with a name that matches the given pattern, and that is
|
||||
/// every bookmark with a name that matches the given pattern, and that is
|
||||
/// present locally and/or on the specified remote.
|
||||
///
|
||||
/// Entries are sorted by `name`.
|
||||
///
|
||||
/// Note that this does *not* take into account whether the local branch
|
||||
/// tracks the remote branch or not. Missing values are represented as
|
||||
/// Note that this does *not* take into account whether the local bookmark
|
||||
/// tracks the remote bookmark or not. Missing values are represented as
|
||||
/// RefTarget::absent_ref() or RemoteRef::absent_ref().
|
||||
pub fn local_remote_branches_matching<'a: 'b, 'b>(
|
||||
pub fn local_remote_bookmarks_matching<'a: 'b, 'b>(
|
||||
&'a self,
|
||||
branch_pattern: &'b StringPattern,
|
||||
bookmark_pattern: &'b StringPattern,
|
||||
remote_name: &str,
|
||||
) -> impl Iterator<Item = (&'a str, LocalAndRemoteRef<'a>)> + 'b {
|
||||
// Change remote_name to StringPattern if needed, but merge-join adapter won't
|
||||
// be usable.
|
||||
let maybe_remote_view = self.data.remote_views.get(remote_name);
|
||||
refs::iter_named_local_remote_refs(
|
||||
branch_pattern.filter_btree_map(&self.data.local_branches),
|
||||
bookmark_pattern.filter_btree_map(&self.data.local_bookmarks),
|
||||
maybe_remote_view
|
||||
.map(|remote_view| branch_pattern.filter_btree_map(&remote_view.branches))
|
||||
.map(|remote_view| bookmark_pattern.filter_btree_map(&remote_view.bookmarks))
|
||||
.into_iter()
|
||||
.flatten(),
|
||||
)
|
||||
|
|
@ -313,10 +317,10 @@ impl View {
|
|||
|
||||
/// Iterates all commit ids referenced by this view.
|
||||
///
|
||||
/// This can include hidden commits referenced by remote branches, previous
|
||||
/// positions of conflicted branches, etc. The ancestors and predecessors of
|
||||
/// the returned commits should be considered reachable from the view. Use
|
||||
/// this to build commit index from scratch.
|
||||
/// This can include hidden commits referenced by remote bookmarks, previous
|
||||
/// positions of conflicted bookmarks, etc. The ancestors and predecessors
|
||||
/// of the returned commits should be considered reachable from the
|
||||
/// view. Use this to build commit index from scratch.
|
||||
///
|
||||
/// The iteration order is unspecified, and may include duplicated entries.
|
||||
pub fn all_referenced_commit_ids(&self) -> impl Iterator<Item = &CommitId> {
|
||||
|
|
@ -330,7 +334,7 @@ impl View {
|
|||
// not be smart here. Callers will build a larger set of commits anyway.
|
||||
let op_store::View {
|
||||
head_ids,
|
||||
local_branches,
|
||||
local_bookmarks,
|
||||
tags,
|
||||
remote_views,
|
||||
git_refs,
|
||||
|
|
@ -339,11 +343,11 @@ impl View {
|
|||
} = &self.data;
|
||||
itertools::chain!(
|
||||
head_ids,
|
||||
local_branches.values().flat_map(ref_target_ids),
|
||||
local_bookmarks.values().flat_map(ref_target_ids),
|
||||
tags.values().flat_map(ref_target_ids),
|
||||
remote_views.values().flat_map(|remote_view| {
|
||||
let op_store::RemoteView { branches } = remote_view;
|
||||
branches
|
||||
let op_store::RemoteView { bookmarks } = remote_view;
|
||||
bookmarks
|
||||
.values()
|
||||
.flat_map(|remote_ref| ref_target_ids(&remote_ref.target))
|
||||
}),
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -355,7 +355,7 @@ fn test_index_commits_hidden_but_referenced() {
|
|||
tx.repo_mut().remove_head(commit_a.id());
|
||||
tx.repo_mut().remove_head(commit_b.id());
|
||||
tx.repo_mut().remove_head(commit_c.id());
|
||||
tx.repo_mut().set_remote_branch(
|
||||
tx.repo_mut().set_remote_bookmark(
|
||||
"branch",
|
||||
"origin",
|
||||
RemoteRef {
|
||||
|
|
|
|||
|
|
@ -191,9 +191,9 @@ fn test_edit_previous_empty_with_description() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_edit_previous_empty_with_local_branch() {
|
||||
fn test_edit_previous_empty_with_local_bookmark() {
|
||||
// Test that MutableRepo::edit() does not abandon the previous commit if it
|
||||
// is pointed by local branch.
|
||||
// is pointed by local bookmark.
|
||||
let settings = testutils::user_settings();
|
||||
let test_repo = TestRepo::init();
|
||||
let repo = &test_repo.repo;
|
||||
|
|
@ -208,7 +208,7 @@ fn test_edit_previous_empty_with_local_branch() {
|
|||
)
|
||||
.write()
|
||||
.unwrap();
|
||||
mut_repo.set_local_branch_target("b", RefTarget::normal(old_wc_commit.id().clone()));
|
||||
mut_repo.set_local_bookmark_target("b", RefTarget::normal(old_wc_commit.id().clone()));
|
||||
let ws_id = WorkspaceId::default();
|
||||
mut_repo.edit(ws_id.clone(), &old_wc_commit).unwrap();
|
||||
let repo = tx.commit("test");
|
||||
|
|
@ -467,7 +467,7 @@ fn test_remove_head() {
|
|||
#[test]
|
||||
fn test_has_changed() {
|
||||
// Test that MutableRepo::has_changed() reports changes iff the view has changed
|
||||
// (e.g. not after setting a branch to point to where it was already
|
||||
// (e.g. not after setting a bookmark to point to where it was already
|
||||
// pointing).
|
||||
let settings = testutils::user_settings();
|
||||
let test_repo = TestRepo::init();
|
||||
|
|
@ -486,8 +486,8 @@ fn test_has_changed() {
|
|||
mut_repo
|
||||
.set_wc_commit(ws_id.clone(), commit1.id().clone())
|
||||
.unwrap();
|
||||
mut_repo.set_local_branch_target("main", RefTarget::normal(commit1.id().clone()));
|
||||
mut_repo.set_remote_branch("main", "origin", normal_remote_ref(commit1.id()));
|
||||
mut_repo.set_local_bookmark_target("main", RefTarget::normal(commit1.id().clone()));
|
||||
mut_repo.set_remote_bookmark("main", "origin", normal_remote_ref(commit1.id()));
|
||||
let repo = tx.commit("test");
|
||||
// Test the setup
|
||||
assert_eq!(repo.view().heads(), &hashset! {commit1.id().clone()});
|
||||
|
|
@ -499,13 +499,13 @@ fn test_has_changed() {
|
|||
mut_repo
|
||||
.set_wc_commit(ws_id.clone(), commit1.id().clone())
|
||||
.unwrap();
|
||||
mut_repo.set_local_branch_target("main", RefTarget::normal(commit1.id().clone()));
|
||||
mut_repo.set_remote_branch("main", "origin", normal_remote_ref(commit1.id()));
|
||||
mut_repo.set_local_bookmark_target("main", RefTarget::normal(commit1.id().clone()));
|
||||
mut_repo.set_remote_bookmark("main", "origin", normal_remote_ref(commit1.id()));
|
||||
assert!(!mut_repo.has_changes());
|
||||
|
||||
mut_repo.remove_head(commit2.id());
|
||||
mut_repo.set_local_branch_target("stable", RefTarget::absent());
|
||||
mut_repo.set_remote_branch("stable", "origin", RemoteRef::absent());
|
||||
mut_repo.set_local_bookmark_target("stable", RefTarget::absent());
|
||||
mut_repo.set_remote_bookmark("stable", "origin", RemoteRef::absent());
|
||||
assert!(!mut_repo.has_changes());
|
||||
|
||||
mut_repo.add_head(&commit2).unwrap();
|
||||
|
|
@ -520,14 +520,14 @@ fn test_has_changed() {
|
|||
mut_repo.set_wc_commit(ws_id, commit1.id().clone()).unwrap();
|
||||
assert!(!mut_repo.has_changes());
|
||||
|
||||
mut_repo.set_local_branch_target("main", RefTarget::normal(commit2.id().clone()));
|
||||
mut_repo.set_local_bookmark_target("main", RefTarget::normal(commit2.id().clone()));
|
||||
assert!(mut_repo.has_changes());
|
||||
mut_repo.set_local_branch_target("main", RefTarget::normal(commit1.id().clone()));
|
||||
mut_repo.set_local_bookmark_target("main", RefTarget::normal(commit1.id().clone()));
|
||||
assert!(!mut_repo.has_changes());
|
||||
|
||||
mut_repo.set_remote_branch("main", "origin", normal_remote_ref(commit2.id()));
|
||||
mut_repo.set_remote_bookmark("main", "origin", normal_remote_ref(commit2.id()));
|
||||
assert!(mut_repo.has_changes());
|
||||
mut_repo.set_remote_branch("main", "origin", normal_remote_ref(commit1.id()));
|
||||
mut_repo.set_remote_bookmark("main", "origin", normal_remote_ref(commit1.id()));
|
||||
assert!(!mut_repo.has_changes());
|
||||
}
|
||||
|
||||
|
|
@ -617,11 +617,11 @@ fn test_rename_remote() {
|
|||
target: RefTarget::normal(commit.id().clone()),
|
||||
state: RemoteRefState::Tracking, // doesn't matter
|
||||
};
|
||||
mut_repo.set_remote_branch("main", "origin", remote_ref.clone());
|
||||
mut_repo.set_remote_bookmark("main", "origin", remote_ref.clone());
|
||||
mut_repo.rename_remote("origin", "upstream");
|
||||
assert_eq!(mut_repo.get_remote_branch("main", "upstream"), remote_ref);
|
||||
assert_eq!(mut_repo.get_remote_bookmark("main", "upstream"), remote_ref);
|
||||
assert_eq!(
|
||||
mut_repo.get_remote_branch("main", "origin"),
|
||||
mut_repo.get_remote_bookmark("main", "origin"),
|
||||
RemoteRef::absent()
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -263,7 +263,7 @@ fn test_reparent_range_linear() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_reparent_range_branchy() {
|
||||
fn test_reparent_range_bookmarky() {
|
||||
let settings = testutils::user_settings();
|
||||
let test_repo = TestRepo::init();
|
||||
let repo_0 = test_repo.repo;
|
||||
|
|
@ -279,7 +279,7 @@ fn test_reparent_range_branchy() {
|
|||
parents.try_into().unwrap()
|
||||
}
|
||||
|
||||
// Set up branchy operation graph:
|
||||
// Set up bookmarky operation graph:
|
||||
// G
|
||||
// |\
|
||||
// | F
|
||||
|
|
|
|||
|
|
@ -255,7 +255,7 @@ fn test_resolve_symbol_change_id(readonly: bool) {
|
|||
for i in &[133, 664, 840, 5085] {
|
||||
let git_commit_id = git_repo
|
||||
.commit(
|
||||
Some(&format!("refs/heads/branch{i}")),
|
||||
Some(&format!("refs/heads/bookmark{i}")),
|
||||
&git_author,
|
||||
&git_committer,
|
||||
&format!("test {i}"),
|
||||
|
|
@ -445,7 +445,7 @@ fn test_resolve_working_copies() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_resolve_symbol_branches() {
|
||||
fn test_resolve_symbol_bookmarks() {
|
||||
let settings = testutils::user_settings();
|
||||
let test_repo = TestRepo::init();
|
||||
let repo = &test_repo.repo;
|
||||
|
|
@ -469,42 +469,42 @@ fn test_resolve_symbol_branches() {
|
|||
let commit4 = write_random_commit(mut_repo, &settings);
|
||||
let commit5 = write_random_commit(mut_repo, &settings);
|
||||
|
||||
mut_repo.set_local_branch_target("local", RefTarget::normal(commit1.id().clone()));
|
||||
mut_repo.set_remote_branch("remote", "origin", normal_tracking_remote_ref(commit2.id()));
|
||||
mut_repo.set_local_branch_target("local-remote", RefTarget::normal(commit3.id().clone()));
|
||||
mut_repo.set_remote_branch(
|
||||
mut_repo.set_local_bookmark_target("local", RefTarget::normal(commit1.id().clone()));
|
||||
mut_repo.set_remote_bookmark("remote", "origin", normal_tracking_remote_ref(commit2.id()));
|
||||
mut_repo.set_local_bookmark_target("local-remote", RefTarget::normal(commit3.id().clone()));
|
||||
mut_repo.set_remote_bookmark(
|
||||
"local-remote",
|
||||
"origin",
|
||||
normal_tracking_remote_ref(commit4.id()),
|
||||
);
|
||||
mut_repo.set_local_branch_target(
|
||||
"local-remote@origin", // not a remote branch
|
||||
mut_repo.set_local_bookmark_target(
|
||||
"local-remote@origin", // not a remote bookmark
|
||||
RefTarget::normal(commit5.id().clone()),
|
||||
);
|
||||
mut_repo.set_remote_branch(
|
||||
mut_repo.set_remote_bookmark(
|
||||
"local-remote",
|
||||
"mirror",
|
||||
tracking_remote_ref(mut_repo.get_local_branch("local-remote")),
|
||||
tracking_remote_ref(mut_repo.get_local_bookmark("local-remote")),
|
||||
);
|
||||
mut_repo.set_remote_branch(
|
||||
mut_repo.set_remote_bookmark(
|
||||
"local-remote",
|
||||
"untracked",
|
||||
new_remote_ref(mut_repo.get_local_branch("local-remote")),
|
||||
new_remote_ref(mut_repo.get_local_bookmark("local-remote")),
|
||||
);
|
||||
mut_repo.set_remote_branch(
|
||||
mut_repo.set_remote_bookmark(
|
||||
"local-remote",
|
||||
git::REMOTE_NAME_FOR_LOCAL_GIT_REPO,
|
||||
tracking_remote_ref(mut_repo.get_local_branch("local-remote")),
|
||||
tracking_remote_ref(mut_repo.get_local_bookmark("local-remote")),
|
||||
);
|
||||
|
||||
mut_repo.set_local_branch_target(
|
||||
mut_repo.set_local_bookmark_target(
|
||||
"local-conflicted",
|
||||
RefTarget::from_legacy_form(
|
||||
[commit1.id().clone()],
|
||||
[commit3.id().clone(), commit2.id().clone()],
|
||||
),
|
||||
);
|
||||
mut_repo.set_remote_branch(
|
||||
mut_repo.set_remote_bookmark(
|
||||
"remote-conflicted",
|
||||
"origin",
|
||||
tracking_remote_ref(RefTarget::from_legacy_form(
|
||||
|
|
@ -580,11 +580,11 @@ fn test_resolve_symbol_branches() {
|
|||
vec![commit5.id().clone(), commit4.id().clone()],
|
||||
);
|
||||
|
||||
// Typo of local/remote branch name:
|
||||
// Typo of local/remote bookmark name:
|
||||
// For "local-emote" (without @remote part), "local-remote@mirror"/"@git" aren't
|
||||
// suggested since they point to the same target as "local-remote". OTOH,
|
||||
// "local-remote@untracked" is suggested because non-tracking branch is
|
||||
// unrelated to the local branch of the same name.
|
||||
// "local-remote@untracked" is suggested because non-tracking bookmark is
|
||||
// unrelated to the local bookmark of the same name.
|
||||
insta::assert_debug_snapshot!(
|
||||
resolve_symbol(mut_repo, "local-emote").unwrap_err(), @r###"
|
||||
NoSuchRevision {
|
||||
|
|
@ -643,7 +643,7 @@ fn test_resolve_symbol_branches() {
|
|||
}
|
||||
"###);
|
||||
|
||||
// Typo of remote-only branch name
|
||||
// Typo of remote-only bookmark name
|
||||
insta::assert_debug_snapshot!(
|
||||
resolve_symbol(mut_repo, "emote").unwrap_err(), @r###"
|
||||
NoSuchRevision {
|
||||
|
|
@ -690,16 +690,16 @@ fn test_resolve_symbol_tags() {
|
|||
let commit2 = write_random_commit(mut_repo, &settings);
|
||||
let commit3 = write_random_commit(mut_repo, &settings);
|
||||
|
||||
mut_repo.set_tag_target("tag-branch", RefTarget::normal(commit1.id().clone()));
|
||||
mut_repo.set_local_branch_target("tag-branch", RefTarget::normal(commit2.id().clone()));
|
||||
mut_repo.set_tag_target("tag-bookmark", RefTarget::normal(commit1.id().clone()));
|
||||
mut_repo.set_local_bookmark_target("tag-bookmark", RefTarget::normal(commit2.id().clone()));
|
||||
mut_repo.set_git_ref_target(
|
||||
"refs/tags/unimported",
|
||||
RefTarget::normal(commit3.id().clone()),
|
||||
);
|
||||
|
||||
// Tag precedes branch
|
||||
// Tag precedes bookmark
|
||||
assert_eq!(
|
||||
resolve_symbol(mut_repo, "tag-branch").unwrap(),
|
||||
resolve_symbol(mut_repo, "tag-bookmark").unwrap(),
|
||||
vec![commit1.id().clone()],
|
||||
);
|
||||
|
||||
|
|
@ -785,11 +785,11 @@ fn test_resolve_symbol_git_refs() {
|
|||
let commit4 = write_random_commit(mut_repo, &settings);
|
||||
let commit5 = write_random_commit(mut_repo, &settings);
|
||||
mut_repo.set_git_ref_target(
|
||||
"refs/heads/branch1",
|
||||
"refs/heads/bookmark1",
|
||||
RefTarget::normal(commit1.id().clone()),
|
||||
);
|
||||
mut_repo.set_git_ref_target(
|
||||
"refs/heads/branch2",
|
||||
"refs/heads/bookmark2",
|
||||
RefTarget::normal(commit2.id().clone()),
|
||||
);
|
||||
mut_repo.set_git_ref_target(
|
||||
|
|
@ -801,7 +801,7 @@ fn test_resolve_symbol_git_refs() {
|
|||
);
|
||||
mut_repo.set_git_ref_target("refs/tags/tag1", RefTarget::normal(commit2.id().clone()));
|
||||
mut_repo.set_git_ref_target(
|
||||
"refs/tags/remotes/origin/branch1",
|
||||
"refs/tags/remotes/origin/bookmark1",
|
||||
RefTarget::normal(commit3.id().clone()),
|
||||
);
|
||||
|
||||
|
|
@ -813,26 +813,35 @@ fn test_resolve_symbol_git_refs() {
|
|||
);
|
||||
|
||||
// Full ref
|
||||
mut_repo.set_git_ref_target("refs/heads/branch", RefTarget::normal(commit4.id().clone()));
|
||||
mut_repo.set_git_ref_target(
|
||||
"refs/heads/bookmark",
|
||||
RefTarget::normal(commit4.id().clone()),
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_symbol(mut_repo, "refs/heads/branch").unwrap(),
|
||||
resolve_symbol(mut_repo, "refs/heads/bookmark").unwrap(),
|
||||
vec![commit4.id().clone()]
|
||||
);
|
||||
|
||||
// Qualified with only heads/
|
||||
mut_repo.set_git_ref_target("refs/heads/branch", RefTarget::normal(commit5.id().clone()));
|
||||
mut_repo.set_git_ref_target("refs/tags/branch", RefTarget::normal(commit4.id().clone()));
|
||||
// branch alone is not recognized
|
||||
mut_repo.set_git_ref_target(
|
||||
"refs/heads/bookmark",
|
||||
RefTarget::normal(commit5.id().clone()),
|
||||
);
|
||||
mut_repo.set_git_ref_target(
|
||||
"refs/tags/bookmark",
|
||||
RefTarget::normal(commit4.id().clone()),
|
||||
);
|
||||
// bookmark alone is not recognized
|
||||
insta::assert_debug_snapshot!(
|
||||
resolve_symbol(mut_repo, "branch").unwrap_err(), @r###"
|
||||
resolve_symbol(mut_repo, "bookmark").unwrap_err(), @r###"
|
||||
NoSuchRevision {
|
||||
name: "branch",
|
||||
name: "bookmark",
|
||||
candidates: [],
|
||||
}
|
||||
"###);
|
||||
// heads/branch does get resolved to the git ref refs/heads/branch
|
||||
// heads/bookmark does get resolved to the git ref refs/heads/bookmark
|
||||
assert_eq!(
|
||||
resolve_symbol(mut_repo, "heads/branch").unwrap(),
|
||||
resolve_symbol(mut_repo, "heads/bookmark").unwrap(),
|
||||
vec![commit5.id().clone()]
|
||||
);
|
||||
|
||||
|
|
@ -843,13 +852,13 @@ fn test_resolve_symbol_git_refs() {
|
|||
Err(RevsetResolutionError::NoSuchRevision { .. })
|
||||
);
|
||||
|
||||
// Unqualified remote-tracking branch name
|
||||
// Unqualified remote-tracking bookmark name
|
||||
mut_repo.set_git_ref_target(
|
||||
"refs/remotes/origin/remote-branch",
|
||||
"refs/remotes/origin/remote-bookmark",
|
||||
RefTarget::normal(commit2.id().clone()),
|
||||
);
|
||||
assert_matches!(
|
||||
resolve_symbol(mut_repo, "origin/remote-branch"),
|
||||
resolve_symbol(mut_repo, "origin/remote-bookmark"),
|
||||
Err(RevsetResolutionError::NoSuchRevision { .. })
|
||||
);
|
||||
|
||||
|
|
@ -1941,7 +1950,7 @@ fn test_evaluate_expression_git_refs() {
|
|||
assert_eq!(resolve_commit_ids(mut_repo, "git_refs()"), vec![]);
|
||||
// Can get a mix of git refs
|
||||
mut_repo.set_git_ref_target(
|
||||
"refs/heads/branch1",
|
||||
"refs/heads/bookmark1",
|
||||
RefTarget::normal(commit1.id().clone()),
|
||||
);
|
||||
mut_repo.set_git_ref_target("refs/tags/tag1", RefTarget::normal(commit2.id().clone()));
|
||||
|
|
@ -1958,7 +1967,7 @@ fn test_evaluate_expression_git_refs() {
|
|||
);
|
||||
// Can get git refs when there are conflicted refs
|
||||
mut_repo.set_git_ref_target(
|
||||
"refs/heads/branch1",
|
||||
"refs/heads/bookmark1",
|
||||
RefTarget::from_legacy_form(
|
||||
[commit1.id().clone()],
|
||||
[commit2.id().clone(), commit3.id().clone()],
|
||||
|
|
@ -2003,7 +2012,7 @@ fn test_evaluate_expression_git_head() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_evaluate_expression_branches() {
|
||||
fn test_evaluate_expression_bookmarks() {
|
||||
let settings = testutils::user_settings();
|
||||
let test_repo = TestRepo::init();
|
||||
let repo = &test_repo.repo;
|
||||
|
|
@ -2016,75 +2025,75 @@ fn test_evaluate_expression_branches() {
|
|||
let commit3 = write_random_commit(mut_repo, &settings);
|
||||
let commit4 = write_random_commit(mut_repo, &settings);
|
||||
|
||||
// Can get branches when there are none
|
||||
assert_eq!(resolve_commit_ids(mut_repo, "branches()"), vec![]);
|
||||
// Can get a few branches
|
||||
mut_repo.set_local_branch_target("branch1", RefTarget::normal(commit1.id().clone()));
|
||||
mut_repo.set_local_branch_target("branch2", RefTarget::normal(commit2.id().clone()));
|
||||
// Can get bookmarks when there are none
|
||||
assert_eq!(resolve_commit_ids(mut_repo, "bookmarks()"), vec![]);
|
||||
// Can get a few bookmarks
|
||||
mut_repo.set_local_bookmark_target("bookmark1", RefTarget::normal(commit1.id().clone()));
|
||||
mut_repo.set_local_bookmark_target("bookmark2", RefTarget::normal(commit2.id().clone()));
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, "branches()"),
|
||||
resolve_commit_ids(mut_repo, "bookmarks()"),
|
||||
vec![commit2.id().clone(), commit1.id().clone()]
|
||||
);
|
||||
// Can get branches with matching names
|
||||
// Can get bookmarks with matching names
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, "branches(branch1)"),
|
||||
resolve_commit_ids(mut_repo, "bookmarks(bookmark1)"),
|
||||
vec![commit1.id().clone()]
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, "branches(branch)"),
|
||||
resolve_commit_ids(mut_repo, "bookmarks(bookmark)"),
|
||||
vec![commit2.id().clone(), commit1.id().clone()]
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, "branches(exact:branch1)"),
|
||||
resolve_commit_ids(mut_repo, "bookmarks(exact:bookmark1)"),
|
||||
vec![commit1.id().clone()]
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, r#"branches(glob:"Branch?")"#),
|
||||
resolve_commit_ids(mut_repo, r#"bookmarks(glob:"Bookmark?")"#),
|
||||
vec![]
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, r#"branches(glob-i:"Branch?")"#),
|
||||
resolve_commit_ids(mut_repo, r#"bookmarks(glob-i:"Bookmark?")"#),
|
||||
vec![commit2.id().clone(), commit1.id().clone()]
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, "branches(regex:'ranch')"),
|
||||
resolve_commit_ids(mut_repo, "bookmarks(regex:'ookmark')"),
|
||||
vec![commit2.id().clone(), commit1.id().clone()]
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, "branches(regex:'^[Bb]ranch1$')"),
|
||||
resolve_commit_ids(mut_repo, "bookmarks(regex:'^[Bb]ookmark1$')"),
|
||||
vec![commit1.id().clone()]
|
||||
);
|
||||
// Can silently resolve to an empty set if there's no matches
|
||||
assert_eq!(resolve_commit_ids(mut_repo, "branches(branch3)"), vec![]);
|
||||
assert_eq!(resolve_commit_ids(mut_repo, "bookmarks(bookmark3)"), vec![]);
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, "branches(exact:ranch1)"),
|
||||
resolve_commit_ids(mut_repo, "bookmarks(exact:ookmark1)"),
|
||||
vec![]
|
||||
);
|
||||
// Two branches pointing to the same commit does not result in a duplicate in
|
||||
// Two bookmarks pointing to the same commit does not result in a duplicate in
|
||||
// the revset
|
||||
mut_repo.set_local_branch_target("branch3", RefTarget::normal(commit2.id().clone()));
|
||||
mut_repo.set_local_bookmark_target("bookmark3", RefTarget::normal(commit2.id().clone()));
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, "branches()"),
|
||||
resolve_commit_ids(mut_repo, "bookmarks()"),
|
||||
vec![commit2.id().clone(), commit1.id().clone()]
|
||||
);
|
||||
// Can get branches when there are conflicted refs
|
||||
mut_repo.set_local_branch_target(
|
||||
"branch1",
|
||||
// Can get bookmarks when there are conflicted refs
|
||||
mut_repo.set_local_bookmark_target(
|
||||
"bookmark1",
|
||||
RefTarget::from_legacy_form(
|
||||
[commit1.id().clone()],
|
||||
[commit2.id().clone(), commit3.id().clone()],
|
||||
),
|
||||
);
|
||||
mut_repo.set_local_branch_target(
|
||||
"branch2",
|
||||
mut_repo.set_local_bookmark_target(
|
||||
"bookmark2",
|
||||
RefTarget::from_legacy_form(
|
||||
[commit2.id().clone()],
|
||||
[commit3.id().clone(), commit4.id().clone()],
|
||||
),
|
||||
);
|
||||
mut_repo.set_local_branch_target("branch3", RefTarget::absent());
|
||||
mut_repo.set_local_bookmark_target("bookmark3", RefTarget::absent());
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, "branches()"),
|
||||
resolve_commit_ids(mut_repo, "bookmarks()"),
|
||||
vec![
|
||||
commit4.id().clone(),
|
||||
commit3.id().clone(),
|
||||
|
|
@ -2094,7 +2103,7 @@ fn test_evaluate_expression_branches() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_evaluate_expression_remote_branches() {
|
||||
fn test_evaluate_expression_remote_bookmarks() {
|
||||
let settings = testutils::user_settings();
|
||||
let test_repo = TestRepo::init();
|
||||
let repo = &test_repo.repo;
|
||||
|
|
@ -2114,11 +2123,11 @@ fn test_evaluate_expression_remote_branches() {
|
|||
let commit4 = write_random_commit(mut_repo, &settings);
|
||||
let commit_git_remote = write_random_commit(mut_repo, &settings);
|
||||
|
||||
// Can get branches when there are none
|
||||
assert_eq!(resolve_commit_ids(mut_repo, "remote_branches()"), vec![]);
|
||||
// Can get bookmarks when there are none
|
||||
assert_eq!(resolve_commit_ids(mut_repo, "remote_bookmarks()"), vec![]);
|
||||
// Branch 1 is untracked on remote origin
|
||||
mut_repo.set_remote_branch(
|
||||
"branch1",
|
||||
mut_repo.set_remote_bookmark(
|
||||
"bookmark1",
|
||||
"origin",
|
||||
RemoteRef {
|
||||
target: RefTarget::normal(commit1.id().clone()),
|
||||
|
|
@ -2126,144 +2135,147 @@ fn test_evaluate_expression_remote_branches() {
|
|||
},
|
||||
);
|
||||
// Branch 2 is tracked on remote private
|
||||
mut_repo.set_remote_branch(
|
||||
"branch2",
|
||||
mut_repo.set_remote_bookmark(
|
||||
"bookmark2",
|
||||
"private",
|
||||
normal_tracking_remote_ref(commit2.id()),
|
||||
);
|
||||
// Git-tracking branches aren't included
|
||||
mut_repo.set_remote_branch(
|
||||
"branch",
|
||||
// Git-tracking bookmarks aren't included
|
||||
mut_repo.set_remote_bookmark(
|
||||
"bookmark",
|
||||
git::REMOTE_NAME_FOR_LOCAL_GIT_REPO,
|
||||
normal_tracking_remote_ref(commit_git_remote.id()),
|
||||
);
|
||||
// Can get a few branches
|
||||
// Can get a few bookmarks
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, "remote_branches()"),
|
||||
resolve_commit_ids(mut_repo, "remote_bookmarks()"),
|
||||
vec![commit2.id().clone(), commit1.id().clone()]
|
||||
);
|
||||
// Can get branches with matching names
|
||||
// Can get bookmarks with matching names
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, "remote_branches(branch1)"),
|
||||
resolve_commit_ids(mut_repo, "remote_bookmarks(bookmark1)"),
|
||||
vec![commit1.id().clone()]
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, "remote_branches(branch)"),
|
||||
resolve_commit_ids(mut_repo, "remote_bookmarks(bookmark)"),
|
||||
vec![commit2.id().clone(), commit1.id().clone()]
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, "remote_branches(exact:branch1)"),
|
||||
resolve_commit_ids(mut_repo, "remote_bookmarks(exact:bookmark1)"),
|
||||
vec![commit1.id().clone()]
|
||||
);
|
||||
// Can get branches from matching remotes
|
||||
// Can get bookmarks from matching remotes
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, r#"remote_branches("", origin)"#),
|
||||
resolve_commit_ids(mut_repo, r#"remote_bookmarks("", origin)"#),
|
||||
vec![commit1.id().clone()]
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, r#"remote_branches("", ri)"#),
|
||||
resolve_commit_ids(mut_repo, r#"remote_bookmarks("", ri)"#),
|
||||
vec![commit2.id().clone(), commit1.id().clone()]
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, r#"remote_branches("", exact:origin)"#),
|
||||
resolve_commit_ids(mut_repo, r#"remote_bookmarks("", exact:origin)"#),
|
||||
vec![commit1.id().clone()]
|
||||
);
|
||||
// Can get branches with matching names from matching remotes
|
||||
// Can get bookmarks with matching names from matching remotes
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, "remote_branches(branch1, ri)"),
|
||||
resolve_commit_ids(mut_repo, "remote_bookmarks(bookmark1, ri)"),
|
||||
vec![commit1.id().clone()]
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, r#"remote_branches(branch, private)"#),
|
||||
resolve_commit_ids(mut_repo, r#"remote_bookmarks(bookmark, private)"#),
|
||||
vec![commit2.id().clone()]
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, r#"remote_branches(exact:branch1, exact:origin)"#),
|
||||
resolve_commit_ids(
|
||||
mut_repo,
|
||||
r#"remote_bookmarks(exact:bookmark1, exact:origin)"#
|
||||
),
|
||||
vec![commit1.id().clone()]
|
||||
);
|
||||
// Can filter branches by tracked and untracked
|
||||
// Can filter bookmarks by tracked and untracked
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, "tracked_remote_branches()"),
|
||||
resolve_commit_ids(mut_repo, "tracked_remote_bookmarks()"),
|
||||
vec![commit2.id().clone()]
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, "untracked_remote_branches()"),
|
||||
resolve_commit_ids(mut_repo, "untracked_remote_bookmarks()"),
|
||||
vec![commit1.id().clone()]
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, "untracked_remote_branches(branch1, origin)"),
|
||||
resolve_commit_ids(mut_repo, "untracked_remote_bookmarks(bookmark1, origin)"),
|
||||
vec![commit1.id().clone()]
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, "tracked_remote_branches(branch2, private)"),
|
||||
resolve_commit_ids(mut_repo, "tracked_remote_bookmarks(bookmark2, private)"),
|
||||
vec![commit2.id().clone()]
|
||||
);
|
||||
// Can silently resolve to an empty set if there's no matches
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, "remote_branches(branch3)"),
|
||||
resolve_commit_ids(mut_repo, "remote_bookmarks(bookmark3)"),
|
||||
vec![]
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, r#"remote_branches("", upstream)"#),
|
||||
resolve_commit_ids(mut_repo, r#"remote_bookmarks("", upstream)"#),
|
||||
vec![]
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, r#"remote_branches(branch1, private)"#),
|
||||
resolve_commit_ids(mut_repo, r#"remote_bookmarks(bookmark1, private)"#),
|
||||
vec![]
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, r#"remote_branches(exact:ranch1, exact:origin)"#),
|
||||
resolve_commit_ids(mut_repo, r#"remote_bookmarks(exact:ranch1, exact:origin)"#),
|
||||
vec![]
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, r#"remote_branches(exact:branch1, exact:orig)"#),
|
||||
resolve_commit_ids(mut_repo, r#"remote_bookmarks(exact:bookmark1, exact:orig)"#),
|
||||
vec![]
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, "tracked_remote_branches(branch1)"),
|
||||
resolve_commit_ids(mut_repo, "tracked_remote_bookmarks(bookmark1)"),
|
||||
vec![]
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, "untracked_remote_branches(branch2)"),
|
||||
resolve_commit_ids(mut_repo, "untracked_remote_bookmarks(bookmark2)"),
|
||||
vec![]
|
||||
);
|
||||
// Two branches pointing to the same commit does not result in a duplicate in
|
||||
// Two bookmarks pointing to the same commit does not result in a duplicate in
|
||||
// the revset
|
||||
mut_repo.set_remote_branch(
|
||||
"branch3",
|
||||
mut_repo.set_remote_bookmark(
|
||||
"bookmark3",
|
||||
"origin",
|
||||
normal_tracking_remote_ref(commit2.id()),
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, "remote_branches()"),
|
||||
resolve_commit_ids(mut_repo, "remote_bookmarks()"),
|
||||
vec![commit2.id().clone(), commit1.id().clone()]
|
||||
);
|
||||
// The commits don't have to be in the current set of heads to be included.
|
||||
mut_repo.remove_head(commit2.id());
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, "remote_branches()"),
|
||||
resolve_commit_ids(mut_repo, "remote_bookmarks()"),
|
||||
vec![commit2.id().clone(), commit1.id().clone()]
|
||||
);
|
||||
// Can get branches when there are conflicted refs
|
||||
mut_repo.set_remote_branch(
|
||||
"branch1",
|
||||
// Can get bookmarks when there are conflicted refs
|
||||
mut_repo.set_remote_bookmark(
|
||||
"bookmark1",
|
||||
"origin",
|
||||
tracking_remote_ref(RefTarget::from_legacy_form(
|
||||
[commit1.id().clone()],
|
||||
[commit2.id().clone(), commit3.id().clone()],
|
||||
)),
|
||||
);
|
||||
mut_repo.set_remote_branch(
|
||||
"branch2",
|
||||
mut_repo.set_remote_bookmark(
|
||||
"bookmark2",
|
||||
"private",
|
||||
tracking_remote_ref(RefTarget::from_legacy_form(
|
||||
[commit2.id().clone()],
|
||||
[commit3.id().clone(), commit4.id().clone()],
|
||||
)),
|
||||
);
|
||||
mut_repo.set_remote_branch("branch3", "origin", RemoteRef::absent());
|
||||
mut_repo.set_remote_bookmark("bookmark3", "origin", RemoteRef::absent());
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo, "remote_branches()"),
|
||||
resolve_commit_ids(mut_repo, "remote_bookmarks()"),
|
||||
vec![
|
||||
commit4.id().clone(),
|
||||
commit3.id().clone(),
|
||||
|
|
@ -3513,8 +3525,8 @@ fn test_no_such_revision_suggestion() {
|
|||
let mut_repo = tx.repo_mut();
|
||||
let commit = write_random_commit(mut_repo, &settings);
|
||||
|
||||
for branch_name in ["foo", "bar", "baz"] {
|
||||
mut_repo.set_local_branch_target(branch_name, RefTarget::normal(commit.id().clone()));
|
||||
for bookmark_name in ["foo", "bar", "baz"] {
|
||||
mut_repo.set_local_bookmark_target(bookmark_name, RefTarget::normal(commit.id().clone()));
|
||||
}
|
||||
|
||||
assert_matches!(resolve_symbol(mut_repo, "bar"), Ok(_));
|
||||
|
|
|
|||
|
|
@ -264,7 +264,7 @@ fn test_rebase_descendants_backward() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_rebase_descendants_chain_becomes_branchy() {
|
||||
fn test_rebase_descendants_chain_becomes_bookmarky() {
|
||||
let settings = testutils::user_settings();
|
||||
let test_repo = TestRepo::init();
|
||||
let repo = &test_repo.repo;
|
||||
|
|
@ -972,7 +972,7 @@ fn test_rebase_descendants_contents() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_rebase_descendants_basic_branch_update() {
|
||||
fn test_rebase_descendants_basic_bookmark_update() {
|
||||
let settings = testutils::user_settings();
|
||||
let test_repo = TestRepo::init();
|
||||
let repo = &test_repo.repo;
|
||||
|
|
@ -988,7 +988,7 @@ fn test_rebase_descendants_basic_branch_update() {
|
|||
let commit_a = graph_builder.initial_commit();
|
||||
let commit_b = graph_builder.commit_with_parents(&[&commit_a]);
|
||||
tx.repo_mut()
|
||||
.set_local_branch_target("main", RefTarget::normal(commit_b.id().clone()));
|
||||
.set_local_bookmark_target("main", RefTarget::normal(commit_b.id().clone()));
|
||||
let repo = tx.commit("test");
|
||||
|
||||
let mut tx = repo.start_transaction(&settings);
|
||||
|
|
@ -999,7 +999,7 @@ fn test_rebase_descendants_basic_branch_update() {
|
|||
.unwrap();
|
||||
tx.repo_mut().rebase_descendants(&settings).unwrap();
|
||||
assert_eq!(
|
||||
tx.repo_mut().get_local_branch("main"),
|
||||
tx.repo_mut().get_local_bookmark("main"),
|
||||
RefTarget::normal(commit_b2.id().clone())
|
||||
);
|
||||
|
||||
|
|
@ -1010,14 +1010,14 @@ fn test_rebase_descendants_basic_branch_update() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_rebase_descendants_branch_move_two_steps() {
|
||||
fn test_rebase_descendants_bookmark_move_two_steps() {
|
||||
let settings = testutils::user_settings();
|
||||
let test_repo = TestRepo::init();
|
||||
let repo = &test_repo.repo;
|
||||
|
||||
// Branch "main" points to branch C. C gets rewritten as C2 and B gets rewritten
|
||||
// as B2. C2 should be rebased onto B2, creating C3, and main should be
|
||||
// updated to point to C3.
|
||||
// Branch "main" points to bookmark C. C gets rewritten as C2 and B gets
|
||||
// rewritten as B2. C2 should be rebased onto B2, creating C3, and main
|
||||
// should be updated to point to C3.
|
||||
//
|
||||
// C2 C main C3 main
|
||||
// | / |
|
||||
|
|
@ -1031,7 +1031,7 @@ fn test_rebase_descendants_branch_move_two_steps() {
|
|||
let commit_b = graph_builder.commit_with_parents(&[&commit_a]);
|
||||
let commit_c = graph_builder.commit_with_parents(&[&commit_b]);
|
||||
tx.repo_mut()
|
||||
.set_local_branch_target("main", RefTarget::normal(commit_c.id().clone()));
|
||||
.set_local_bookmark_target("main", RefTarget::normal(commit_c.id().clone()));
|
||||
let repo = tx.commit("test");
|
||||
|
||||
let mut tx = repo.start_transaction(&settings);
|
||||
|
|
@ -1055,19 +1055,19 @@ fn test_rebase_descendants_branch_move_two_steps() {
|
|||
assert_ne!(commit_c3.id(), commit_c2.id());
|
||||
assert_eq!(commit_c3.parent_ids(), vec![commit_b2.id().clone()]);
|
||||
assert_eq!(
|
||||
tx.repo_mut().get_local_branch("main"),
|
||||
tx.repo_mut().get_local_bookmark("main"),
|
||||
RefTarget::normal(commit_c3.id().clone())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rebase_descendants_basic_branch_update_with_non_local_branch() {
|
||||
fn test_rebase_descendants_basic_bookmark_update_with_non_local_bookmark() {
|
||||
let settings = testutils::user_settings();
|
||||
let test_repo = TestRepo::init();
|
||||
let repo = &test_repo.repo;
|
||||
|
||||
// Branch "main" points to commit B. B gets rewritten as B2. Branch main should
|
||||
// be updated to point to B2. Remote branch main@origin and tag v1 should not
|
||||
// be updated to point to B2. Remote bookmark main@origin and tag v1 should not
|
||||
// get updated.
|
||||
//
|
||||
// B2 main
|
||||
|
|
@ -1083,9 +1083,9 @@ fn test_rebase_descendants_basic_branch_update_with_non_local_branch() {
|
|||
state: RemoteRefState::Tracking,
|
||||
};
|
||||
tx.repo_mut()
|
||||
.set_local_branch_target("main", RefTarget::normal(commit_b.id().clone()));
|
||||
.set_local_bookmark_target("main", RefTarget::normal(commit_b.id().clone()));
|
||||
tx.repo_mut()
|
||||
.set_remote_branch("main", "origin", commit_b_remote_ref.clone());
|
||||
.set_remote_bookmark("main", "origin", commit_b_remote_ref.clone());
|
||||
tx.repo_mut()
|
||||
.set_tag_target("v1", RefTarget::normal(commit_b.id().clone()));
|
||||
let repo = tx.commit("test");
|
||||
|
|
@ -1098,12 +1098,12 @@ fn test_rebase_descendants_basic_branch_update_with_non_local_branch() {
|
|||
.unwrap();
|
||||
tx.repo_mut().rebase_descendants(&settings).unwrap();
|
||||
assert_eq!(
|
||||
tx.repo_mut().get_local_branch("main"),
|
||||
tx.repo_mut().get_local_bookmark("main"),
|
||||
RefTarget::normal(commit_b2.id().clone())
|
||||
);
|
||||
// The remote branch and tag should not get updated
|
||||
// The remote bookmark and tag should not get updated
|
||||
assert_eq!(
|
||||
tx.repo_mut().get_remote_branch("main", "origin"),
|
||||
tx.repo_mut().get_remote_bookmark("main", "origin"),
|
||||
commit_b_remote_ref,
|
||||
);
|
||||
assert_eq!(
|
||||
|
|
@ -1111,8 +1111,8 @@ fn test_rebase_descendants_basic_branch_update_with_non_local_branch() {
|
|||
RefTarget::normal(commit_b.id().clone())
|
||||
);
|
||||
|
||||
// Commit B is no longer visible even though the remote branch points to it.
|
||||
// (The user can still see it using e.g. the `remote_branches()` revset.)
|
||||
// Commit B is no longer visible even though the remote bookmark points to it.
|
||||
// (The user can still see it using e.g. the `remote_bookmarks()` revset.)
|
||||
assert_eq!(
|
||||
*tx.repo_mut().view().heads(),
|
||||
hashset! {commit_b2.id().clone()}
|
||||
|
|
@ -1120,7 +1120,7 @@ fn test_rebase_descendants_basic_branch_update_with_non_local_branch() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_rebase_descendants_update_branch_after_abandon() {
|
||||
fn test_rebase_descendants_update_bookmark_after_abandon() {
|
||||
let settings = testutils::user_settings();
|
||||
let test_repo = TestRepo::init();
|
||||
let repo = &test_repo.repo;
|
||||
|
|
@ -1136,14 +1136,14 @@ fn test_rebase_descendants_update_branch_after_abandon() {
|
|||
let commit_a = graph_builder.initial_commit();
|
||||
let commit_b = graph_builder.commit_with_parents(&[&commit_a]);
|
||||
tx.repo_mut()
|
||||
.set_local_branch_target("main", RefTarget::normal(commit_b.id().clone()));
|
||||
.set_local_bookmark_target("main", RefTarget::normal(commit_b.id().clone()));
|
||||
let repo = tx.commit("test");
|
||||
|
||||
let mut tx = repo.start_transaction(&settings);
|
||||
tx.repo_mut().record_abandoned_commit(commit_b.id().clone());
|
||||
tx.repo_mut().rebase_descendants(&settings).unwrap();
|
||||
assert_eq!(
|
||||
tx.repo_mut().get_local_branch("main"),
|
||||
tx.repo_mut().get_local_bookmark("main"),
|
||||
RefTarget::normal(commit_a.id().clone())
|
||||
);
|
||||
|
||||
|
|
@ -1154,7 +1154,7 @@ fn test_rebase_descendants_update_branch_after_abandon() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_rebase_descendants_update_branches_after_divergent_rewrite() {
|
||||
fn test_rebase_descendants_update_bookmarks_after_divergent_rewrite() {
|
||||
let settings = testutils::user_settings();
|
||||
let test_repo = TestRepo::init();
|
||||
let repo = &test_repo.repo;
|
||||
|
|
@ -1176,9 +1176,9 @@ fn test_rebase_descendants_update_branches_after_divergent_rewrite() {
|
|||
let commit_b = graph_builder.commit_with_parents(&[&commit_a]);
|
||||
let commit_c = graph_builder.commit_with_parents(&[&commit_b]);
|
||||
tx.repo_mut()
|
||||
.set_local_branch_target("main", RefTarget::normal(commit_b.id().clone()));
|
||||
.set_local_bookmark_target("main", RefTarget::normal(commit_b.id().clone()));
|
||||
tx.repo_mut()
|
||||
.set_local_branch_target("other", RefTarget::normal(commit_c.id().clone()));
|
||||
.set_local_bookmark_target("other", RefTarget::normal(commit_c.id().clone()));
|
||||
let repo = tx.commit("test");
|
||||
|
||||
let mut tx = repo.start_transaction(&settings);
|
||||
|
|
@ -1226,7 +1226,7 @@ fn test_rebase_descendants_update_branches_after_divergent_rewrite() {
|
|||
);
|
||||
tx.repo_mut().rebase_descendants(&settings).unwrap();
|
||||
|
||||
let main_target = tx.repo_mut().get_local_branch("main");
|
||||
let main_target = tx.repo_mut().get_local_bookmark("main");
|
||||
assert!(main_target.has_conflict());
|
||||
// If the branch were moved at each rewrite point, there would be separate
|
||||
// negative terms: { commit_b => 2, commit_b4 => 1 }. Since we flatten
|
||||
|
|
@ -1245,7 +1245,7 @@ fn test_rebase_descendants_update_branches_after_divergent_rewrite() {
|
|||
},
|
||||
);
|
||||
|
||||
let other_target = tx.repo_mut().get_local_branch("other");
|
||||
let other_target = tx.repo_mut().get_local_bookmark("other");
|
||||
assert_eq!(other_target.as_normal(), Some(commit_c.id()));
|
||||
|
||||
assert_eq!(
|
||||
|
|
@ -1261,20 +1261,20 @@ fn test_rebase_descendants_update_branches_after_divergent_rewrite() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_rebase_descendants_rewrite_updates_branch_conflict() {
|
||||
fn test_rebase_descendants_rewrite_updates_bookmark_conflict() {
|
||||
let settings = testutils::user_settings();
|
||||
let test_repo = TestRepo::init();
|
||||
let repo = &test_repo.repo;
|
||||
|
||||
// Branch "main" is a conflict removing commit A and adding commits B and C.
|
||||
// A gets rewritten as A2 and A3. B gets rewritten as B2 and B2. The branch
|
||||
// A gets rewritten as A2 and A3. B gets rewritten as B2 and B2. The bookmark
|
||||
// should become a conflict removing A and B, and adding B2, B3, C.
|
||||
let mut tx = repo.start_transaction(&settings);
|
||||
let mut graph_builder = CommitGraphBuilder::new(&settings, tx.repo_mut());
|
||||
let commit_a = graph_builder.initial_commit();
|
||||
let commit_b = graph_builder.initial_commit();
|
||||
let commit_c = graph_builder.initial_commit();
|
||||
tx.repo_mut().set_local_branch_target(
|
||||
tx.repo_mut().set_local_bookmark_target(
|
||||
"main",
|
||||
RefTarget::from_legacy_form(
|
||||
[commit_a.id().clone()],
|
||||
|
|
@ -1318,7 +1318,7 @@ fn test_rebase_descendants_rewrite_updates_branch_conflict() {
|
|||
);
|
||||
tx.repo_mut().rebase_descendants(&settings).unwrap();
|
||||
|
||||
let target = tx.repo_mut().get_local_branch("main");
|
||||
let target = tx.repo_mut().get_local_bookmark("main");
|
||||
assert!(target.has_conflict());
|
||||
assert_eq!(
|
||||
target.removed_ids().counts(),
|
||||
|
|
@ -1346,7 +1346,7 @@ fn test_rebase_descendants_rewrite_updates_branch_conflict() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_rebase_descendants_rewrite_resolves_branch_conflict() {
|
||||
fn test_rebase_descendants_rewrite_resolves_bookmark_conflict() {
|
||||
let settings = testutils::user_settings();
|
||||
let test_repo = TestRepo::init();
|
||||
let repo = &test_repo.repo;
|
||||
|
|
@ -1363,7 +1363,7 @@ fn test_rebase_descendants_rewrite_resolves_branch_conflict() {
|
|||
let commit_a = graph_builder.initial_commit();
|
||||
let commit_b = graph_builder.commit_with_parents(&[&commit_a]);
|
||||
let commit_c = graph_builder.commit_with_parents(&[&commit_a]);
|
||||
tx.repo_mut().set_local_branch_target(
|
||||
tx.repo_mut().set_local_bookmark_target(
|
||||
"main",
|
||||
RefTarget::from_legacy_form(
|
||||
[commit_a.id().clone()],
|
||||
|
|
@ -1381,7 +1381,7 @@ fn test_rebase_descendants_rewrite_resolves_branch_conflict() {
|
|||
.unwrap();
|
||||
tx.repo_mut().rebase_descendants(&settings).unwrap();
|
||||
assert_eq!(
|
||||
tx.repo_mut().get_local_branch("main"),
|
||||
tx.repo_mut().get_local_bookmark("main"),
|
||||
RefTarget::normal(commit_b2.id().clone())
|
||||
);
|
||||
|
||||
|
|
@ -1392,21 +1392,21 @@ fn test_rebase_descendants_rewrite_resolves_branch_conflict() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_rebase_descendants_branch_delete_modify_abandon() {
|
||||
fn test_rebase_descendants_bookmark_delete_modify_abandon() {
|
||||
let settings = testutils::user_settings();
|
||||
let test_repo = TestRepo::init();
|
||||
let repo = &test_repo.repo;
|
||||
|
||||
// Branch "main" initially points to commit A. One operation rewrites it to
|
||||
// point to B (child of A). A concurrent operation deletes the branch. That
|
||||
// leaves the branch pointing to "-A+B". We now abandon B. That should
|
||||
// result in the branch pointing to "-A+A=0", so the branch should
|
||||
// point to B (child of A). A concurrent operation deletes the bookmark. That
|
||||
// leaves the bookmark pointing to "-A+B". We now abandon B. That should
|
||||
// result in the bookmark pointing to "-A+A=0", so the bookmark should
|
||||
// be deleted.
|
||||
let mut tx = repo.start_transaction(&settings);
|
||||
let mut graph_builder = CommitGraphBuilder::new(&settings, tx.repo_mut());
|
||||
let commit_a = graph_builder.initial_commit();
|
||||
let commit_b = graph_builder.commit_with_parents(&[&commit_a]);
|
||||
tx.repo_mut().set_local_branch_target(
|
||||
tx.repo_mut().set_local_bookmark_target(
|
||||
"main",
|
||||
RefTarget::from_legacy_form([commit_a.id().clone()], [commit_b.id().clone()]),
|
||||
);
|
||||
|
|
@ -1415,7 +1415,14 @@ fn test_rebase_descendants_branch_delete_modify_abandon() {
|
|||
let mut tx = repo.start_transaction(&settings);
|
||||
tx.repo_mut().record_abandoned_commit(commit_b.id().clone());
|
||||
tx.repo_mut().rebase_descendants(&settings).unwrap();
|
||||
assert_eq!(tx.repo_mut().get_local_branch("main"), RefTarget::absent());
|
||||
assert_eq!(
|
||||
tx.repo_mut().get_local_bookmark("main"),
|
||||
RefTarget::absent()
|
||||
);
|
||||
assert_eq!(
|
||||
tx.repo_mut().get_local_bookmark("main"),
|
||||
RefTarget::absent()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -202,8 +202,8 @@ fn test_merge_views_checkout() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_merge_views_branches() {
|
||||
// Tests merging of branches (by performing divergent operations). See
|
||||
fn test_merge_views_bookmarks() {
|
||||
// Tests merging of bookmarks (by performing concurrent operations). See
|
||||
// test_refs.rs for tests of merging of individual ref targets.
|
||||
let settings = testutils::user_settings();
|
||||
let test_repo = TestRepo::init();
|
||||
|
|
@ -211,84 +211,87 @@ fn test_merge_views_branches() {
|
|||
|
||||
let mut tx = repo.start_transaction(&settings);
|
||||
let mut_repo = tx.repo_mut();
|
||||
let main_branch_local_tx0 = write_random_commit(mut_repo, &settings);
|
||||
let main_branch_origin_tx0 = write_random_commit(mut_repo, &settings);
|
||||
let main_branch_alternate_tx0 = write_random_commit(mut_repo, &settings);
|
||||
let main_branch_origin_tx0_remote_ref = RemoteRef {
|
||||
target: RefTarget::normal(main_branch_origin_tx0.id().clone()),
|
||||
let main_bookmark_local_tx0 = write_random_commit(mut_repo, &settings);
|
||||
let main_bookmark_origin_tx0 = write_random_commit(mut_repo, &settings);
|
||||
let main_bookmark_alternate_tx0 = write_random_commit(mut_repo, &settings);
|
||||
let main_bookmark_origin_tx0_remote_ref = RemoteRef {
|
||||
target: RefTarget::normal(main_bookmark_origin_tx0.id().clone()),
|
||||
state: RemoteRefState::New,
|
||||
};
|
||||
let main_branch_alternate_tx0_remote_ref = RemoteRef {
|
||||
target: RefTarget::normal(main_branch_alternate_tx0.id().clone()),
|
||||
let main_bookmark_alternate_tx0_remote_ref = RemoteRef {
|
||||
target: RefTarget::normal(main_bookmark_alternate_tx0.id().clone()),
|
||||
state: RemoteRefState::Tracking,
|
||||
};
|
||||
mut_repo.set_local_branch_target(
|
||||
mut_repo.set_local_bookmark_target(
|
||||
"main",
|
||||
RefTarget::normal(main_branch_local_tx0.id().clone()),
|
||||
RefTarget::normal(main_bookmark_local_tx0.id().clone()),
|
||||
);
|
||||
mut_repo.set_remote_branch("main", "origin", main_branch_origin_tx0_remote_ref);
|
||||
mut_repo.set_remote_branch(
|
||||
mut_repo.set_remote_bookmark("main", "origin", main_bookmark_origin_tx0_remote_ref);
|
||||
mut_repo.set_remote_bookmark(
|
||||
"main",
|
||||
"alternate",
|
||||
main_branch_alternate_tx0_remote_ref.clone(),
|
||||
main_bookmark_alternate_tx0_remote_ref.clone(),
|
||||
);
|
||||
let feature_branch_local_tx0 = write_random_commit(mut_repo, &settings);
|
||||
mut_repo.set_local_branch_target(
|
||||
let feature_bookmark_local_tx0 = write_random_commit(mut_repo, &settings);
|
||||
mut_repo.set_local_bookmark_target(
|
||||
"feature",
|
||||
RefTarget::normal(feature_branch_local_tx0.id().clone()),
|
||||
RefTarget::normal(feature_bookmark_local_tx0.id().clone()),
|
||||
);
|
||||
let repo = tx.commit("test");
|
||||
|
||||
let mut tx1 = repo.start_transaction(&settings);
|
||||
let main_branch_local_tx1 = write_random_commit(tx1.repo_mut(), &settings);
|
||||
tx1.repo_mut().set_local_branch_target(
|
||||
let main_bookmark_local_tx1 = write_random_commit(tx1.repo_mut(), &settings);
|
||||
tx1.repo_mut().set_local_bookmark_target(
|
||||
"main",
|
||||
RefTarget::normal(main_branch_local_tx1.id().clone()),
|
||||
RefTarget::normal(main_bookmark_local_tx1.id().clone()),
|
||||
);
|
||||
let feature_branch_tx1 = write_random_commit(tx1.repo_mut(), &settings);
|
||||
tx1.repo_mut().set_local_branch_target(
|
||||
let feature_bookmark_tx1 = write_random_commit(tx1.repo_mut(), &settings);
|
||||
tx1.repo_mut().set_local_bookmark_target(
|
||||
"feature",
|
||||
RefTarget::normal(feature_branch_tx1.id().clone()),
|
||||
RefTarget::normal(feature_bookmark_tx1.id().clone()),
|
||||
);
|
||||
|
||||
let mut tx2 = repo.start_transaction(&settings);
|
||||
let main_branch_local_tx2 = write_random_commit(tx2.repo_mut(), &settings);
|
||||
let main_branch_origin_tx2 = write_random_commit(tx2.repo_mut(), &settings);
|
||||
let main_branch_origin_tx2_remote_ref = RemoteRef {
|
||||
target: RefTarget::normal(main_branch_origin_tx2.id().clone()),
|
||||
let main_bookmark_local_tx2 = write_random_commit(tx2.repo_mut(), &settings);
|
||||
let main_bookmark_origin_tx2 = write_random_commit(tx2.repo_mut(), &settings);
|
||||
let main_bookmark_origin_tx2_remote_ref = RemoteRef {
|
||||
target: RefTarget::normal(main_bookmark_origin_tx2.id().clone()),
|
||||
state: RemoteRefState::Tracking,
|
||||
};
|
||||
tx2.repo_mut().set_local_branch_target(
|
||||
tx2.repo_mut().set_local_bookmark_target(
|
||||
"main",
|
||||
RefTarget::normal(main_branch_local_tx2.id().clone()),
|
||||
RefTarget::normal(main_bookmark_local_tx2.id().clone()),
|
||||
);
|
||||
tx2.repo_mut().set_remote_bookmark(
|
||||
"main",
|
||||
"origin",
|
||||
main_bookmark_origin_tx2_remote_ref.clone(),
|
||||
);
|
||||
tx2.repo_mut()
|
||||
.set_remote_branch("main", "origin", main_branch_origin_tx2_remote_ref.clone());
|
||||
|
||||
let repo = commit_transactions(&settings, vec![tx1, tx2]);
|
||||
let expected_main_branch = BranchTarget {
|
||||
let expected_main_bookmark = BranchTarget {
|
||||
local_target: &RefTarget::from_legacy_form(
|
||||
[main_branch_local_tx0.id().clone()],
|
||||
[main_bookmark_local_tx0.id().clone()],
|
||||
[
|
||||
main_branch_local_tx1.id().clone(),
|
||||
main_branch_local_tx2.id().clone(),
|
||||
main_bookmark_local_tx1.id().clone(),
|
||||
main_bookmark_local_tx2.id().clone(),
|
||||
],
|
||||
),
|
||||
remote_refs: vec![
|
||||
("alternate", &main_branch_alternate_tx0_remote_ref),
|
||||
("alternate", &main_bookmark_alternate_tx0_remote_ref),
|
||||
// tx1: unchanged, tx2: new -> tracking
|
||||
("origin", &main_branch_origin_tx2_remote_ref),
|
||||
("origin", &main_bookmark_origin_tx2_remote_ref),
|
||||
],
|
||||
};
|
||||
let expected_feature_branch = BranchTarget {
|
||||
local_target: &RefTarget::normal(feature_branch_tx1.id().clone()),
|
||||
let expected_feature_bookmark = BranchTarget {
|
||||
local_target: &RefTarget::normal(feature_bookmark_tx1.id().clone()),
|
||||
remote_refs: vec![],
|
||||
};
|
||||
assert_eq!(
|
||||
repo.view().branches().collect::<BTreeMap<_, _>>(),
|
||||
repo.view().bookmarks().collect::<BTreeMap<_, _>>(),
|
||||
btreemap! {
|
||||
"main" => expected_main_branch,
|
||||
"feature" => expected_feature_branch,
|
||||
"main" => expected_main_bookmark,
|
||||
"feature" => expected_feature_bookmark,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
@ -347,48 +350,51 @@ fn test_merge_views_git_refs() {
|
|||
|
||||
let mut tx = repo.start_transaction(&settings);
|
||||
let mut_repo = tx.repo_mut();
|
||||
let main_branch_tx0 = write_random_commit(mut_repo, &settings);
|
||||
let main_bookmark_tx0 = write_random_commit(mut_repo, &settings);
|
||||
mut_repo.set_git_ref_target(
|
||||
"refs/heads/main",
|
||||
RefTarget::normal(main_branch_tx0.id().clone()),
|
||||
RefTarget::normal(main_bookmark_tx0.id().clone()),
|
||||
);
|
||||
let feature_branch_tx0 = write_random_commit(mut_repo, &settings);
|
||||
let feature_bookmark_tx0 = write_random_commit(mut_repo, &settings);
|
||||
mut_repo.set_git_ref_target(
|
||||
"refs/heads/feature",
|
||||
RefTarget::normal(feature_branch_tx0.id().clone()),
|
||||
RefTarget::normal(feature_bookmark_tx0.id().clone()),
|
||||
);
|
||||
let repo = tx.commit("test");
|
||||
|
||||
let mut tx1 = repo.start_transaction(&settings);
|
||||
let main_branch_tx1 = write_random_commit(tx1.repo_mut(), &settings);
|
||||
let main_bookmark_tx1 = write_random_commit(tx1.repo_mut(), &settings);
|
||||
tx1.repo_mut().set_git_ref_target(
|
||||
"refs/heads/main",
|
||||
RefTarget::normal(main_branch_tx1.id().clone()),
|
||||
RefTarget::normal(main_bookmark_tx1.id().clone()),
|
||||
);
|
||||
let feature_branch_tx1 = write_random_commit(tx1.repo_mut(), &settings);
|
||||
let feature_bookmark_tx1 = write_random_commit(tx1.repo_mut(), &settings);
|
||||
tx1.repo_mut().set_git_ref_target(
|
||||
"refs/heads/feature",
|
||||
RefTarget::normal(feature_branch_tx1.id().clone()),
|
||||
RefTarget::normal(feature_bookmark_tx1.id().clone()),
|
||||
);
|
||||
|
||||
let mut tx2 = repo.start_transaction(&settings);
|
||||
let main_branch_tx2 = write_random_commit(tx2.repo_mut(), &settings);
|
||||
let main_bookmark_tx2 = write_random_commit(tx2.repo_mut(), &settings);
|
||||
tx2.repo_mut().set_git_ref_target(
|
||||
"refs/heads/main",
|
||||
RefTarget::normal(main_branch_tx2.id().clone()),
|
||||
RefTarget::normal(main_bookmark_tx2.id().clone()),
|
||||
);
|
||||
|
||||
let repo = commit_transactions(&settings, vec![tx1, tx2]);
|
||||
let expected_main_branch = RefTarget::from_legacy_form(
|
||||
[main_branch_tx0.id().clone()],
|
||||
[main_branch_tx1.id().clone(), main_branch_tx2.id().clone()],
|
||||
let expected_main_bookmark = RefTarget::from_legacy_form(
|
||||
[main_bookmark_tx0.id().clone()],
|
||||
[
|
||||
main_bookmark_tx1.id().clone(),
|
||||
main_bookmark_tx2.id().clone(),
|
||||
],
|
||||
);
|
||||
let expected_feature_branch = RefTarget::normal(feature_branch_tx1.id().clone());
|
||||
let expected_feature_bookmark = RefTarget::normal(feature_bookmark_tx1.id().clone());
|
||||
assert_eq!(
|
||||
repo.view().git_refs(),
|
||||
&btreemap! {
|
||||
"refs/heads/main".to_string() => expected_main_branch,
|
||||
"refs/heads/feature".to_string() => expected_feature_branch,
|
||||
"refs/heads/main".to_string() => expected_main_bookmark,
|
||||
"refs/heads/feature".to_string() => expected_feature_bookmark,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ nav:
|
|||
|
||||
- Concepts:
|
||||
- 'Working Copy': 'working-copy.md'
|
||||
- 'Branches': 'branches.md'
|
||||
- 'Bookmarks': 'bookmarks.md'
|
||||
- 'Conflicts': 'conflicts.md'
|
||||
- 'Operation Log': 'operation-log.md'
|
||||
- 'Glossary': 'glossary.md'
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue