view: port bookmark/tag name types to RefName/RemoteName

I tried to minimize this patch, but it seemed rather complicated than porting
most callers all at once. Remote management functions in git.rs are unchanged.
They'll be ported separately.

With this change, many non-template bookmark/remote name outputs should be
rendered in revset syntax.
This commit is contained in:
Yuya Nishihara
2025-03-24 21:37:33 +09:00
parent 05e10920e6
commit 02722eae54
35 changed files with 629 additions and 404 deletions

View File

@@ -82,6 +82,8 @@ use jj_lib::op_store::WorkspaceId;
use jj_lib::op_walk;
use jj_lib::op_walk::OpsetEvaluationError;
use jj_lib::operation::Operation;
use jj_lib::ref_name::RefName;
use jj_lib::ref_name::RefNameBuf;
use jj_lib::repo::merge_factories_map;
use jj_lib::repo::CheckOutCommitError;
use jj_lib::repo::EditCommitError;
@@ -710,7 +712,7 @@ impl ReadonlyUserRepo {
/// identify eligible bookmarks without actually moving them and
/// return config errors to the user early.
pub struct AdvanceableBookmark {
name: String,
name: RefNameBuf,
old_commit_id: CommitId,
}
@@ -752,17 +754,17 @@ impl AdvanceBookmarksSettings {
/// Returns true if the advance-bookmarks feature is enabled for
/// `bookmark_name`.
fn bookmark_is_eligible(&self, bookmark_name: &str) -> bool {
fn bookmark_is_eligible(&self, bookmark_name: &RefName) -> bool {
if self
.disabled_bookmarks
.iter()
.any(|d| d.matches(bookmark_name))
.any(|d| d.matches(bookmark_name.as_str()))
{
return false;
}
self.enabled_bookmarks
.iter()
.any(|e| e.matches(bookmark_name))
.any(|e| e.matches(bookmark_name.as_str()))
}
/// Returns true if the config includes at least one "enabled-branches"

View File

@@ -133,7 +133,7 @@ pub(crate) fn cmd_abandon(
writeln!(
formatter,
"Deleted bookmarks: {}",
deleted_bookmarks.iter().join(", ")
deleted_bookmarks.iter().map(|n| n.as_symbol()).join(", ")
)?;
}
if num_rebased > 0 {

View File

@@ -13,8 +13,10 @@
// limitations under the License.
use clap_complete::ArgValueCandidates;
use itertools::Itertools as _;
use jj_lib::object_id::ObjectId as _;
use jj_lib::op_store::RefTarget;
use jj_lib::ref_name::RefNameBuf;
use super::has_tracked_remote_bookmarks;
use crate::cli_util::CommandHelper;
@@ -45,7 +47,7 @@ pub struct BookmarkCreateArgs {
/// The bookmarks to create
#[arg(required = true, value_parser = revset_util::parse_bookmark_name)]
names: Vec<String>,
names: Vec<RefNameBuf>,
}
pub fn cmd_bookmark_create(
@@ -68,27 +70,29 @@ pub fn cmd_bookmark_create(
for name in bookmark_names {
if view.get_local_bookmark(name).is_present() {
return Err(user_error_with_hint(
format!("Bookmark already exists: {name}"),
format!("Bookmark already exists: {name}", name = name.as_symbol()),
"Use `jj bookmark set` to update it.",
));
}
if has_tracked_remote_bookmarks(view, name) {
return Err(user_error_with_hint(
format!("Tracked remote bookmarks exist for deleted bookmark: {name}"),
format!(
"Tracked remote bookmarks exist for deleted bookmark: {name}",
name = name.as_symbol()
),
format!(
"Use `jj bookmark set` to recreate the local bookmark. Run `jj bookmark \
untrack 'glob:{name}@*'` to disassociate them."
untrack 'glob:{name}@*'` to disassociate them.",
name = name.as_symbol()
),
));
}
}
let mut tx = workspace_command.start_transaction();
for bookmark_name in bookmark_names {
tx.repo_mut().set_local_bookmark_target(
bookmark_name,
RefTarget::normal(target_commit.id().clone()),
);
for name in bookmark_names {
tx.repo_mut()
.set_local_bookmark_target(name, RefTarget::normal(target_commit.id().clone()));
}
if let Some(mut formatter) = ui.status_formatter() {
@@ -104,7 +108,7 @@ pub fn cmd_bookmark_create(
ui,
format!(
"create bookmark {names} pointing to commit {id}",
names = bookmark_names.join(", "),
names = bookmark_names.iter().map(|n| n.as_symbol()).join(", "),
id = target_commit.id().hex()
),
)?;

View File

@@ -72,7 +72,10 @@ pub fn cmd_bookmark_delete(
ui,
format!(
"delete bookmark {}",
matched_bookmarks.iter().map(|(name, _)| name).join(", ")
matched_bookmarks
.iter()
.map(|(name, _)| name.as_symbol())
.join(", ")
),
)?;
Ok(())

View File

@@ -17,6 +17,7 @@ use itertools::Itertools as _;
use jj_lib::op_store::BookmarkTarget;
use jj_lib::op_store::RefTarget;
use jj_lib::op_store::RemoteRef;
use jj_lib::ref_name::RefName;
use jj_lib::ref_name::RemoteRefSymbol;
use jj_lib::str_util::StringPattern;
use jj_lib::view::View;
@@ -96,7 +97,10 @@ pub fn cmd_bookmark_forget(
if forgotten_remote != 0 {
writeln!(ui.status(), "Forgot {forgotten_remote} remote bookmarks.")?;
}
let forgotten_bookmarks = matched_bookmarks.iter().map(|(name, _)| name).join(", ");
let forgotten_bookmarks = matched_bookmarks
.iter()
.map(|(name, _)| name.as_symbol())
.join(", ");
tx.finish(ui, format!("forget bookmark {forgotten_bookmarks}"))?;
Ok(())
}
@@ -104,10 +108,10 @@ pub fn cmd_bookmark_forget(
fn find_forgettable_bookmarks<'a>(
view: &'a View,
name_patterns: &[StringPattern],
) -> Result<Vec<(&'a str, BookmarkTarget<'a>)>, CommandError> {
) -> Result<Vec<(&'a RefName, BookmarkTarget<'a>)>, CommandError> {
find_bookmarks_with(name_patterns, |pattern| {
view.bookmarks()
.filter(|(name, _)| pattern.matches(name))
.filter(|(name, _)| pattern.matches(name.as_str()))
.map(Ok)
})
}

View File

@@ -17,6 +17,7 @@ use std::rc::Rc;
use clap_complete::ArgValueCandidates;
use itertools::Itertools as _;
use jj_lib::ref_name::RefName;
use jj_lib::repo::Repo as _;
use jj_lib::revset::RevsetExpression;
use jj_lib::str_util::StringPattern;
@@ -120,11 +121,15 @@ pub fn cmd_bookmark_list(
// Like cmd_git_push(), names and revisions are OR-ed.
let bookmark_names_to_list = if args.names.is_some() || args.revisions.is_some() {
let mut bookmark_names: HashSet<&str> = HashSet::new();
let mut bookmark_names: HashSet<&RefName> = HashSet::new();
if let Some(patterns) = &args.names {
bookmark_names.extend(
view.bookmarks()
.filter(|&(name, _)| patterns.iter().any(|pattern| pattern.matches(name)))
.filter(|(name, _)| {
patterns
.iter()
.any(|pattern| pattern.matches(name.as_str()))
})
.map(|(name, _)| name),
);
}
@@ -180,9 +185,11 @@ pub fn cmd_bookmark_list(
let (mut tracking_remote_refs, untracked_remote_refs) = remote_refs
.iter()
.copied()
.filter(|&(remote_name, _)| {
.filter(|(remote_name, _)| {
args.remotes.as_ref().is_none_or(|patterns| {
patterns.iter().any(|pattern| pattern.matches(remote_name))
patterns
.iter()
.any(|pattern| pattern.matches(remote_name.as_str()))
})
})
.partition::<Vec<_>, _>(|&(_, remote_ref)| remote_ref.is_tracking());
@@ -237,7 +244,7 @@ pub fn cmd_bookmark_list(
.map(|item| {
item.tracked.iter().any(|r| {
let remote = r.remote_name().expect("tracked ref should be remote");
!jj_lib::git::is_special_git_remote(remote)
!jj_lib::git::is_special_git_remote(remote.as_ref())
})
})
.max();

View File

@@ -26,6 +26,7 @@ use itertools::Itertools as _;
use jj_lib::backend::CommitId;
use jj_lib::op_store::RefTarget;
use jj_lib::op_store::RemoteRef;
use jj_lib::ref_name::RefName;
use jj_lib::ref_name::RemoteRefSymbol;
use jj_lib::repo::Repo;
use jj_lib::str_util::StringPattern;
@@ -106,7 +107,7 @@ pub fn cmd_bookmark(
fn find_local_bookmarks<'a>(
view: &'a View,
name_patterns: &[StringPattern],
) -> Result<Vec<(&'a str, &'a RefTarget)>, CommandError> {
) -> Result<Vec<(&'a RefName, &'a RefTarget)>, CommandError> {
find_bookmarks_with(name_patterns, |pattern| {
view.local_bookmarks_matching(pattern).map(Ok)
})
@@ -115,11 +116,11 @@ fn find_local_bookmarks<'a>(
fn find_bookmarks_with<'a, 'b, V, I>(
name_patterns: &'b [StringPattern],
mut find_matches: impl FnMut(&'b StringPattern) -> I,
) -> Result<Vec<(&'a str, V)>, CommandError>
) -> Result<Vec<(&'a RefName, V)>, CommandError>
where
I: Iterator<Item = Result<(&'a str, V), CommandError>>,
I: Iterator<Item = Result<(&'a RefName, V), CommandError>>,
{
let mut matching_bookmarks: Vec<(&'a str, V)> = vec![];
let mut matching_bookmarks: Vec<(&'a RefName, V)> = vec![];
let mut unmatched_patterns = vec![];
for pattern in name_patterns {
let mut matches = find_matches(pattern).peekable();
@@ -175,7 +176,7 @@ fn find_remote_bookmarks<'a>(
/// 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 {
fn has_tracked_remote_bookmarks(view: &View, bookmark: &RefName) -> bool {
view.remote_bookmarks_matching(
&StringPattern::exact(bookmark),
&StringPattern::everything(),

View File

@@ -150,7 +150,10 @@ pub fn cmd_bookmark_move(
.find(|(_, old_target)| !is_fast_forward(repo.as_ref(), old_target, target_commit.id()))
{
return Err(user_error_with_hint(
format!("Refusing to move bookmark backwards or sideways: {name}"),
format!(
"Refusing to move bookmark backwards or sideways: {name}",
name = name.as_symbol()
),
"Use --allow-backwards to allow it.",
));
}
@@ -178,7 +181,10 @@ pub fn cmd_bookmark_move(
ui,
format!(
"point bookmark {names} to commit {id}",
names = matched_bookmarks.iter().map(|(name, _)| name).join(", "),
names = matched_bookmarks
.iter()
.map(|(name, _)| name.as_symbol())
.join(", "),
id = target_commit.id().hex()
),
)?;

View File

@@ -14,6 +14,7 @@
use clap_complete::ArgValueCandidates;
use jj_lib::op_store::RefTarget;
use jj_lib::ref_name::RefNameBuf;
use super::has_tracked_remote_bookmarks;
use crate::cli_util::CommandHelper;
@@ -33,11 +34,11 @@ pub struct BookmarkRenameArgs {
value_parser = revset_util::parse_bookmark_name,
add = ArgValueCandidates::new(complete::local_bookmarks),
)]
old: String,
old: RefNameBuf,
/// The new name of the bookmark
#[arg(value_parser = revset_util::parse_bookmark_name)]
new: String,
new: RefNameBuf,
}
pub fn cmd_bookmark_rename(
@@ -50,13 +51,17 @@ pub fn cmd_bookmark_rename(
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}")));
return Err(user_error(format!(
"No such bookmark: {old_bookmark}",
old_bookmark = old_bookmark.as_symbol()
)));
}
let new_bookmark = &args.new;
if view.get_local_bookmark(new_bookmark).is_present() {
return Err(user_error(format!(
"Bookmark already exists: {new_bookmark}"
"Bookmark already exists: {new_bookmark}",
new_bookmark = new_bookmark.as_symbol()
)));
}
@@ -67,7 +72,11 @@ pub fn cmd_bookmark_rename(
.set_local_bookmark_target(old_bookmark, RefTarget::absent());
tx.finish(
ui,
format!("rename bookmark {old_bookmark} to {new_bookmark}"),
format!(
"rename bookmark {old_bookmark} to {new_bookmark}",
old_bookmark = old_bookmark.as_symbol(),
new_bookmark = new_bookmark.as_symbol()
),
)?;
let view = workspace_command.repo().view();
@@ -75,12 +84,15 @@ pub fn cmd_bookmark_rename(
writeln!(
ui.warning_default(),
"Tracked remote bookmarks for bookmark {old_bookmark} were not renamed.",
old_bookmark = old_bookmark.as_symbol(),
)?;
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."
{new_bookmark}`. `jj git push --all` would also be sufficient.",
old_bookmark = old_bookmark.as_symbol(),
new_bookmark = new_bookmark.as_symbol()
)?;
}
if has_tracked_remote_bookmarks(view, new_bookmark) {
@@ -89,11 +101,14 @@ pub fn cmd_bookmark_rename(
// allowed even if the original old bookmark had tracked remotes.
writeln!(
ui.warning_default(),
"Tracked remote bookmarks for bookmark {new_bookmark} exist."
"Tracked remote bookmarks for bookmark {new_bookmark} exist.",
new_bookmark = new_bookmark.as_symbol()
)?;
writeln!(
ui.hint_default(),
"Run `jj bookmark untrack 'glob:{new_bookmark}@*'` to disassociate them."
"Run `jj bookmark untrack 'glob:{new_bookmark}@*'` to disassociate them.",
// TODO: use .as_symbol() if pattern parser is ported to revset
new_bookmark = new_bookmark.as_str()
)?;
}

View File

@@ -13,8 +13,10 @@
// limitations under the License.
use clap_complete::ArgValueCandidates;
use itertools::Itertools as _;
use jj_lib::object_id::ObjectId as _;
use jj_lib::op_store::RefTarget;
use jj_lib::ref_name::RefNameBuf;
use super::has_tracked_remote_bookmarks;
use super::is_fast_forward;
@@ -52,7 +54,7 @@ pub struct BookmarkSetArgs {
value_parser = revset_util::parse_bookmark_name,
add = ArgValueCandidates::new(complete::local_bookmarks),
)]
names: Vec<String>,
names: Vec<RefNameBuf>,
}
pub fn cmd_bookmark_set(
@@ -85,7 +87,10 @@ pub fn cmd_bookmark_set(
}
if !args.allow_backwards && !is_fast_forward(repo, old_target, target_commit.id()) {
return Err(user_error_with_hint(
format!("Refusing to move bookmark backwards or sideways: {name}"),
format!(
"Refusing to move bookmark backwards or sideways: {name}",
name = name.as_symbol()
),
"Use --allow-backwards to allow it.",
));
}
@@ -122,7 +127,7 @@ pub fn cmd_bookmark_set(
ui,
format!(
"point bookmark {names} to commit {id}",
names = bookmark_names.join(", "),
names = bookmark_names.iter().map(|n| n.as_symbol()).join(", "),
id = target_commit.id().hex()
),
)?;

View File

@@ -102,7 +102,7 @@ pub fn cmd_bookmark_track(
.labeled("bookmark_list")
};
let mut remote_per_bookmark: HashMap<&str, Vec<&str>> = HashMap::new();
let mut remote_per_bookmark: HashMap<_, Vec<_>> = HashMap::new();
for symbol in &symbols {
remote_per_bookmark
.entry(symbol.name)

View File

@@ -20,6 +20,8 @@ use std::path::Path;
use jj_lib::git;
use jj_lib::git::GitFetch;
use jj_lib::ref_name::RefNameBuf;
use jj_lib::ref_name::RemoteName;
use jj_lib::ref_name::RemoteRefSymbol;
use jj_lib::repo::Repo as _;
use jj_lib::str_util::StringPattern;
@@ -56,7 +58,7 @@ pub struct GitCloneArgs {
destination: Option<String>,
/// Name of the newly created remote
#[arg(long = "remote", default_value = "origin")]
remote_name: String,
remote_name: String, // TODO: RemoteNameBuf
/// Whether or not to colocate the Jujutsu repo with the git repo
#[arg(long)]
colocate: bool,
@@ -145,10 +147,8 @@ pub fn cmd_git_clone(
let (mut workspace_command, default_branch) = clone_result?;
if let Some(name) = &default_branch {
let default_symbol = RemoteRefSymbol {
name,
remote: remote_name,
};
let remote = RemoteName::new(remote_name); // TODO: use newtype globally
let default_symbol = RemoteRefSymbol { name, remote };
write_repository_level_trunk_alias(ui, workspace_command.repo_path(), default_symbol)?;
let default_branch_remote_ref = workspace_command
@@ -211,7 +211,7 @@ fn fetch_new_remote(
workspace_command: &mut WorkspaceCommandHelper,
remote_name: &str,
depth: Option<NonZeroU32>,
) -> Result<Option<String>, CommandError> {
) -> Result<Option<RefNameBuf>, CommandError> {
writeln!(
ui.status(),
r#"Fetching into new repo in "{}""#,
@@ -228,5 +228,5 @@ fn fetch_new_remote(
let import_stats = git_fetch.import_refs()?;
print_git_import_stats(ui, fetch_tx.repo(), &import_stats, true)?;
fetch_tx.finish(ui, "fetch from git remote into empty repo")?;
Ok(default_branch)
Ok(default_branch.map(Into::into))
}

View File

@@ -248,7 +248,7 @@ pub fn maybe_set_repository_level_trunk_alias(
// TODO: Can we assume the symbolic target points to the same remote?
let symbol = RemoteRefSymbol {
name: symbol.name,
remote: "origin",
remote: "origin".as_ref(),
};
write_repository_level_trunk_alias(ui, workspace_command.repo_path(), symbol)?;
}

View File

@@ -31,6 +31,10 @@ use jj_lib::git::GitBranchPushTargets;
use jj_lib::git::GitPushStats;
use jj_lib::object_id::ObjectId as _;
use jj_lib::op_store::RefTarget;
use jj_lib::ref_name::RefName;
use jj_lib::ref_name::RefNameBuf;
use jj_lib::ref_name::RemoteName;
use jj_lib::ref_name::RemoteNameBuf;
use jj_lib::ref_name::RemoteRefSymbol;
use jj_lib::refs::classify_bookmark_push_action;
use jj_lib::refs::BookmarkPushAction;
@@ -88,7 +92,7 @@ pub struct GitPushArgs {
/// This defaults to the `git.push` setting. If that is not configured, and
/// if there are multiple remotes, the remote named "origin" will be used.
#[arg(long, add = ArgValueCandidates::new(complete::git_remotes))]
remote: Option<String>,
remote: Option<RemoteNameBuf>,
/// Push only this bookmark, or bookmarks matching a pattern (can be
/// repeated)
///
@@ -181,7 +185,7 @@ fn make_bookmark_term(bookmark_names: &[impl fmt::Display]) -> String {
}
}
const DEFAULT_REMOTE: &str = "origin";
const DEFAULT_REMOTE: &RemoteName = RemoteName::new("origin");
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum BookmarkMoveDirection {
@@ -218,7 +222,10 @@ pub fn cmd_git_push(
Err(reason) => reason.print(ui)?,
}
}
tx_description = format!("push all bookmarks to git remote {remote}");
tx_description = format!(
"push all bookmarks to git remote {remote}",
remote = remote.as_symbol()
);
} else if args.tracked {
for (name, targets) in view.local_remote_bookmarks(remote) {
if !targets.remote_ref.is_tracking() {
@@ -231,7 +238,10 @@ pub fn cmd_git_push(
Err(reason) => reason.print(ui)?,
}
}
tx_description = format!("push all tracked bookmarks to git remote {remote}");
tx_description = format!(
"push all tracked bookmarks to git remote {remote}",
remote = remote.as_symbol()
);
} else if args.deleted {
for (name, targets) in view.local_remote_bookmarks(remote) {
if targets.local_target.is_present() {
@@ -244,9 +254,12 @@ pub fn cmd_git_push(
Err(reason) => reason.print(ui)?,
}
}
tx_description = format!("push all deleted bookmarks to git remote {remote}");
tx_description = format!(
"push all deleted bookmarks to git remote {remote}",
remote = remote.as_symbol()
);
} else {
let mut seen_bookmarks: HashSet<&str> = HashSet::new();
let mut seen_bookmarks: HashSet<&RefName> = HashSet::new();
// Process --change bookmarks first because matching bookmarks can be moved.
let bookmark_prefix = tx.settings().get_string("git.push-bookmark-prefix")?;
@@ -272,6 +285,7 @@ pub fn cmd_git_push(
Ok(None) => writeln!(
ui.status(),
"Bookmark {remote_symbol} already matches {name}",
name = name.as_symbol()
)?,
Err(reason) => return Err(reason.into()),
}
@@ -289,6 +303,7 @@ pub fn cmd_git_push(
Ok(None) => writeln!(
ui.status(),
"Bookmark {remote_symbol} already matches {name}",
name = name.as_symbol()
)?,
Err(reason) => return Err(reason.into()),
}
@@ -315,14 +330,14 @@ pub fn cmd_git_push(
}
tx_description = format!(
"push {} to git remote {}",
make_bookmark_term(
"push {names} to git remote {remote}",
names = make_bookmark_term(
&bookmark_updates
.iter()
.map(|(bookmark, _)| bookmark.as_str())
.map(|(name, _)| name.as_symbol())
.collect_vec()
),
&remote
remote = remote.as_symbol()
);
}
if bookmark_updates.is_empty() {
@@ -363,7 +378,11 @@ pub fn cmd_git_push(
}
if let Some(mut formatter) = ui.status_formatter() {
writeln!(formatter, "Changes to push to {remote}:")?;
writeln!(
formatter,
"Changes to push to {remote}:",
remote = remote.as_symbol()
)?;
print_commits_ready_to_push(formatter.as_mut(), tx.repo(), &bookmark_updates)?;
}
@@ -435,8 +454,8 @@ fn process_push_stats(push_stats: &GitPushStats) -> Result<(), CommandError> {
/// Returns the list of commits which need to be signed.
fn validate_commits_ready_to_push(
ui: &Ui,
bookmark_updates: &[(String, BookmarkPushUpdate)],
remote: &str,
bookmark_updates: &[(RefNameBuf, BookmarkPushUpdate)],
remote: &RemoteName,
tx: &WorkspaceCommandTransaction,
args: &GitPushArgs,
sign_behavior: Option<SignBehavior>,
@@ -534,8 +553,8 @@ fn sign_commits_before_push(
tx: &mut WorkspaceCommandTransaction,
commits_to_sign: Vec<Commit>,
sign_behavior: SignBehavior,
bookmark_updates: Vec<(String, BookmarkPushUpdate)>,
) -> Result<(usize, Vec<(String, BookmarkPushUpdate)>), CommandError> {
bookmark_updates: Vec<(RefNameBuf, BookmarkPushUpdate)>,
) -> Result<(usize, Vec<(RefNameBuf, BookmarkPushUpdate)>), CommandError> {
let commit_ids: IndexSet<CommitId> = commits_to_sign.iter().ids().cloned().collect();
let mut old_to_new_commits_map: HashMap<CommitId, CommitId> = HashMap::new();
let mut num_rebased_descendants = 0;
@@ -577,7 +596,7 @@ fn sign_commits_before_push(
fn print_commits_ready_to_push(
formatter: &mut dyn Formatter,
repo: &dyn Repo,
bookmark_updates: &[(String, BookmarkPushUpdate)],
bookmark_updates: &[(RefNameBuf, BookmarkPushUpdate)],
) -> io::Result<()> {
let to_direction = |old_target: &CommitId, new_target: &CommitId| {
assert_ne!(old_target, new_target);
@@ -593,6 +612,7 @@ fn print_commits_ready_to_push(
for (bookmark_name, update) in bookmark_updates {
match (&update.old_target, &update.new_target) {
(Some(old_target), Some(new_target)) => {
let bookmark_name = bookmark_name.as_symbol();
let old = short_commit_hash(old_target);
let new = short_commit_hash(new_target);
// TODO(ilyagr): Add color. Once there is color, "Move bookmark ... sideways"
@@ -617,19 +637,21 @@ fn print_commits_ready_to_push(
(Some(old_target), None) => {
writeln!(
formatter,
" Delete bookmark {bookmark_name} from {}",
short_commit_hash(old_target)
" Delete bookmark {bookmark_name} from {old}",
bookmark_name = bookmark_name.as_symbol(),
old = short_commit_hash(old_target)
)?;
}
(None, Some(new_target)) => {
writeln!(
formatter,
" Add bookmark {bookmark_name} to {}",
short_commit_hash(new_target)
" Add bookmark {bookmark_name} to {new}",
bookmark_name = bookmark_name.as_symbol(),
new = short_commit_hash(new_target)
)?;
}
(None, None) => {
panic!("Not pushing any change to bookmark {bookmark_name}");
panic!("Not pushing any change to bookmark {bookmark_name:?}");
}
}
}
@@ -639,16 +661,18 @@ fn print_commits_ready_to_push(
fn get_default_push_remote(
ui: &Ui,
workspace_command: &WorkspaceCommandHelper,
) -> Result<String, CommandError> {
) -> Result<RemoteNameBuf, CommandError> {
let settings = workspace_command.settings();
if let Some(remote) = settings.get_string("git.push").optional()? {
Ok(remote)
Ok(remote.into())
} else if let Some(remote) = get_single_remote(workspace_command.repo().store())? {
let remote: RemoteNameBuf = remote.into();
// similar to get_default_fetch_remotes
if remote != DEFAULT_REMOTE {
writeln!(
ui.hint_default(),
"Pushing to the only existing remote: {remote}"
"Pushing to the only existing remote: {remote}",
remote = remote.as_symbol()
)?;
}
Ok(remote)
@@ -691,7 +715,10 @@ fn classify_bookmark_update(
match push_action {
BookmarkPushAction::AlreadyMatches => Ok(None),
BookmarkPushAction::LocalConflicted => Err(RejectedBookmarkUpdateReason {
message: format!("Bookmark {name} is conflicted", name = remote_symbol.name),
message: format!(
"Bookmark {name} is conflicted",
name = remote_symbol.name.as_symbol()
),
hint: Some(
"Run `jj bookmark list` to inspect, and use `jj bookmark set` to fix it up."
.to_owned(),
@@ -727,7 +754,7 @@ fn update_change_bookmarks(
tx: &mut WorkspaceCommandTransaction,
changes: &[RevisionArg],
bookmark_prefix: &str,
) -> Result<Vec<String>, CommandError> {
) -> Result<Vec<RefNameBuf>, CommandError> {
if changes.is_empty() {
// NOTE: we don't want resolve_some_revsets_default_single to fail if the
// changes argument wasn't provided, so handle that
@@ -745,7 +772,8 @@ fn update_change_bookmarks(
for commit in all_commits {
let workspace_command = tx.base_workspace_helper();
let short_change_id = short_change_hash(commit.change_id());
let mut bookmark_name = format!("{bookmark_prefix}{}", commit.change_id().hex());
let mut bookmark_name: RefNameBuf =
format!("{bookmark_prefix}{}", commit.change_id().hex()).into();
let view = tx.base_repo().view();
if view.get_local_bookmark(&bookmark_name).is_absent() {
// A local bookmark with the full change ID doesn't exist already, so use the
@@ -755,13 +783,14 @@ fn update_change_bookmarks(
.is_ok()
{
// Short change ID is not ambiguous, so update the bookmark name to use it.
bookmark_name = format!("{bookmark_prefix}{short_change_id}");
bookmark_name = format!("{bookmark_prefix}{short_change_id}").into();
};
}
if view.get_local_bookmark(&bookmark_name).is_absent() {
writeln!(
ui.status(),
"Creating bookmark {bookmark_name} for revision {short_change_id}",
bookmark_name = bookmark_name.as_symbol()
)?;
}
tx.repo_mut()
@@ -774,8 +803,8 @@ fn update_change_bookmarks(
fn find_bookmarks_to_push<'a>(
view: &'a View,
bookmark_patterns: &[StringPattern],
remote: &str,
) -> Result<Vec<(&'a str, LocalAndRemoteRef<'a>)>, CommandError> {
remote: &RemoteName,
) -> Result<Vec<(&'a RefName, LocalAndRemoteRef<'a>)>, CommandError> {
let mut matching_bookmarks = vec![];
let mut unmatched_patterns = vec![];
for pattern in bookmark_patterns {
@@ -805,10 +834,10 @@ fn find_bookmarks_to_push<'a>(
fn find_bookmarks_targeted_by_revisions<'a>(
ui: &Ui,
workspace_command: &'a WorkspaceCommandHelper,
remote: &str,
remote: &RemoteName,
revisions: &[RevisionArg],
use_default_revset: bool,
) -> Result<Vec<(&'a str, LocalAndRemoteRef<'a>)>, CommandError> {
) -> Result<Vec<(&'a RefName, LocalAndRemoteRef<'a>)>, CommandError> {
let mut revision_commit_ids = HashSet::new();
if use_default_revset {
// remote_bookmarks(remote=<remote>)..@
@@ -828,7 +857,8 @@ fn find_bookmarks_targeted_by_revisions<'a>(
writeln!(
ui.warning_default(),
"No bookmarks found in the default push revset: \
remote_bookmarks(remote={remote})..@"
remote_bookmarks(remote={remote})..@",
remote = remote.as_symbol()
)?;
}
for commit_id in commit_ids {

View File

@@ -324,7 +324,7 @@ pub fn show_op_diff(
})?;
for (name, (from_target, to_target)) in changed_local_bookmarks {
with_content_format.write(formatter, |formatter| {
writeln!(formatter, "{name}:")?;
writeln!(formatter, "{name}:", name = name.as_symbol())?;
write_ref_target_summary(
formatter,
current_repo,
@@ -352,7 +352,7 @@ pub fn show_op_diff(
with_content_format.write(formatter, |formatter| writeln!(formatter, "Changed tags:"))?;
for (name, (from_target, to_target)) in changed_tags {
with_content_format.write(formatter, |formatter| {
writeln!(formatter, "{name}:")?;
writeln!(formatter, "{name}:", name = name.as_symbol())?;
write_ref_target_summary(
formatter,
current_repo,

View File

@@ -181,9 +181,9 @@ pub(crate) fn cmd_status(
formatter.labeled("warning").with_heading("Warning: "),
"These bookmarks have conflicts:"
)?;
for bookmark_name in conflicted_local_bookmarks {
for name in conflicted_local_bookmarks {
write!(formatter, " ")?;
write!(formatter.labeled("bookmark"), "{bookmark_name}")?;
write!(formatter.labeled("bookmark"), "{}", name.as_symbol())?;
writeln!(formatter)?;
}
writeln!(

View File

@@ -95,7 +95,12 @@ fn cmd_tag_list(
let mut formatter = ui.stdout_formatter();
for (name, target) in view.tags() {
if !args.names.is_empty() && !args.names.iter().any(|pattern| pattern.matches(name)) {
if !args.names.is_empty()
&& !args
.names
.iter()
.any(|pattern| pattern.matches(name.as_str()))
{
continue;
}
let commit_ref = CommitRef::local_only(name, target.clone());

View File

@@ -1497,8 +1497,8 @@ fn build_bookmarks_index(repo: &dyn Repo) -> CommitRefsIndex {
index
}
fn build_commit_refs_index<'a>(
ref_pairs: impl IntoIterator<Item = (&'a String, &'a RefTarget)>,
fn build_commit_refs_index<'a, K: Into<String>>(
ref_pairs: impl IntoIterator<Item = (K, &'a RefTarget)>,
) -> CommitRefsIndex {
let mut index = CommitRefsIndex::default();
for (name, target) in ref_pairs {

View File

@@ -342,7 +342,7 @@ pub fn print_git_import_stats(
Git remote named '{name}' is reserved for local Git repository.
Use `jj git remote rename` to give a different name.
",
name = git::REMOTE_NAME_FOR_LOCAL_GIT_REPO,
name = git::REMOTE_NAME_FOR_LOCAL_GIT_REPO.as_symbol(),
)?;
}

View File

@@ -26,6 +26,7 @@ use jj_lib::config::ConfigNamePathBuf;
use jj_lib::config::ConfigSource;
use jj_lib::config::StackedConfig;
use jj_lib::id_prefix::IdPrefixContext;
use jj_lib::ref_name::RefNameBuf;
use jj_lib::repo::Repo;
use jj_lib::revset;
use jj_lib::revset::DefaultSymbolResolver;
@@ -361,9 +362,11 @@ pub struct BookmarkNameParseError {
}
/// Parses bookmark name specified in revset syntax.
pub fn parse_bookmark_name(text: &str) -> Result<String, BookmarkNameParseError> {
revset::parse_symbol(text).map_err(|source| BookmarkNameParseError {
input: text.to_owned(),
source,
})
pub fn parse_bookmark_name(text: &str) -> Result<RefNameBuf, BookmarkNameParseError> {
revset::parse_symbol(text)
.map(Into::into)
.map_err(|source| BookmarkNameParseError {
input: text.to_owned(),
source,
})
}

View File

@@ -52,6 +52,9 @@ use crate::op_store::RefTarget;
use crate::op_store::RefTargetOptionExt as _;
use crate::op_store::RemoteRef;
use crate::op_store::RemoteRefState;
use crate::ref_name::RefName;
use crate::ref_name::RefNameBuf;
use crate::ref_name::RemoteName;
use crate::ref_name::RemoteRefSymbol;
use crate::ref_name::RemoteRefSymbolBuf;
#[cfg(feature = "git2")]
@@ -67,7 +70,7 @@ use crate::str_util::StringPattern;
use crate::view::View;
/// Reserved remote name for the backing Git repo.
pub const REMOTE_NAME_FOR_LOCAL_GIT_REPO: &str = "git";
pub const REMOTE_NAME_FOR_LOCAL_GIT_REPO: &RemoteName = RemoteName::new("git");
/// Git ref prefix that would conflict with the reserved "git" remote.
pub const RESERVED_REMOTE_REF_NAMESPACE: &str = "refs/remotes/git/";
/// Ref name used as a placeholder to unset HEAD without a commit.
@@ -80,7 +83,7 @@ const INDEX_DUMMY_CONFLICT_FILE: &str = ".jj-do-not-resolve-this-conflict";
pub enum GitRemoteNameError {
#[error(
"Git remote named '{name}' is reserved for local Git repository",
name = REMOTE_NAME_FOR_LOCAL_GIT_REPO
name = REMOTE_NAME_FOR_LOCAL_GIT_REPO.as_symbol()
)]
ReservedForLocalGitRepo,
#[error("Git remotes with slashes are incompatible with jj: {0}")]
@@ -225,6 +228,7 @@ pub fn parse_git_ref(full_name: &str) -> Option<(GitRefKind, RemoteRefSymbol<'_>
if name == "HEAD" {
return None;
}
let name = RefName::new(name);
let remote = REMOTE_NAME_FOR_LOCAL_GIT_REPO;
Some((GitRefKind::Bookmark, RemoteRefSymbol { name, remote }))
} else if let Some(remote_and_name) = full_name.strip_prefix("refs/remotes/") {
@@ -233,8 +237,11 @@ pub fn parse_git_ref(full_name: &str) -> Option<(GitRefKind, RemoteRefSymbol<'_>
if remote == REMOTE_NAME_FOR_LOCAL_GIT_REPO || name == "HEAD" {
return None;
}
let name = RefName::new(name);
let remote = RemoteName::new(remote);
Some((GitRefKind::Bookmark, RemoteRefSymbol { name, remote }))
} else if let Some(name) = full_name.strip_prefix("refs/tags/") {
let name = RefName::new(name);
let remote = REMOTE_NAME_FOR_LOCAL_GIT_REPO;
Some((GitRefKind::Tag, RemoteRefSymbol { name, remote }))
} else {
@@ -244,6 +251,8 @@ pub fn parse_git_ref(full_name: &str) -> Option<(GitRefKind, RemoteRefSymbol<'_>
fn to_git_ref_name(kind: GitRefKind, symbol: RemoteRefSymbol<'_>) -> Option<String> {
let RemoteRefSymbol { name, remote } = symbol;
let name = name.as_str();
let remote = remote.as_str();
if name.is_empty() || remote.is_empty() {
return None;
}
@@ -985,8 +994,8 @@ pub fn export_some_refs(
fn copy_exportable_local_bookmarks_to_remote_view(
mut_repo: &mut MutableRepo,
remote: &str,
name_filter: impl Fn(&str) -> bool,
remote: &RemoteName,
name_filter: impl Fn(&RefName) -> bool,
) {
let new_local_bookmarks = mut_repo
.view()
@@ -1580,7 +1589,7 @@ fn is_remote_not_found_err(err: &git2::Error) -> bool {
/// remote that is used in the Git backend.
///
/// This function always returns false if the "git" feature is not enabled.
pub fn is_special_git_remote(remote: &str) -> bool {
pub fn is_special_git_remote(remote: &RemoteName) -> bool {
remote == REMOTE_NAME_FOR_LOCAL_GIT_REPO
}
@@ -1736,12 +1745,12 @@ pub fn get_all_remote_names(store: &Store) -> Result<Vec<String>, UnexpectedGitB
// ignore non-UTF-8 remote names which we don't support
.filter_map(|name| String::from_utf8(name.into_owned().into()).ok())
.collect();
Ok(names)
Ok(names) // TODO: RemoteNameBuf
}
pub fn add_remote(
store: &Store,
remote_name: &str,
remote_name: &str, // TODO: &RemoteName
url: &str,
) -> Result<(), GitRemoteManagementError> {
let git_repo = get_git_repo(store)?;
@@ -1774,7 +1783,7 @@ pub fn add_remote(
pub fn remove_remote(
mut_repo: &mut MutableRepo,
remote_name: &str,
remote_name: &str, // TODO: &RemoteName
) -> Result<(), GitRemoteManagementError> {
let mut git_repo = get_git_repo(mut_repo.store())?;
@@ -1813,7 +1822,7 @@ fn remove_remote_git_refs(
}
fn remove_remote_refs(mut_repo: &mut MutableRepo, remote_name: &str) {
mut_repo.remove_remote(remote_name);
mut_repo.remove_remote(remote_name.as_ref());
let prefix = format!("refs/remotes/{remote_name}/");
let git_refs_to_delete = mut_repo
.view()
@@ -1829,8 +1838,8 @@ fn remove_remote_refs(mut_repo: &mut MutableRepo, remote_name: &str) {
pub fn rename_remote(
mut_repo: &mut MutableRepo,
old_remote_name: &str,
new_remote_name: &str,
old_remote_name: &str, // TODO: &RemoteName
new_remote_name: &str, // TODO: &RemoteName
) -> Result<(), GitRemoteManagementError> {
let mut git_repo = get_git_repo(mut_repo.store())?;
@@ -1961,7 +1970,7 @@ where
pub fn set_remote_url(
store: &Store,
remote_name: &str,
remote_name: &str, // TODO: &RemoteName
new_remote_url: &str,
) -> Result<(), GitRemoteManagementError> {
let git_repo = get_git_repo(store)?;
@@ -1994,7 +2003,7 @@ pub fn set_remote_url(
}
fn rename_remote_refs(mut_repo: &mut MutableRepo, old_remote_name: &str, new_remote_name: &str) {
mut_repo.rename_remote(old_remote_name, new_remote_name);
mut_repo.rename_remote(old_remote_name.as_ref(), new_remote_name.as_ref());
let prefix = format!("refs/remotes/{old_remote_name}/");
let git_refs = mut_repo
.view()
@@ -2107,7 +2116,7 @@ impl<'a> GitFetch<'a> {
#[tracing::instrument(skip(self, callbacks))]
pub fn fetch(
&mut self,
remote_name: &str,
remote_name: &str, // TODO: &RemoteName
branch_names: &[StringPattern],
callbacks: RemoteCallbacks<'_>,
depth: Option<NonZeroU32>,
@@ -2126,9 +2135,10 @@ impl<'a> GitFetch<'a> {
#[tracing::instrument(skip(self, callbacks))]
pub fn get_default_branch(
&self,
remote_name: &str,
remote_name: &str, // TODO: &RemoteName
callbacks: RemoteCallbacks<'_>,
) -> Result<Option<String>, GitFetchError> {
// TODO: return Option<RefNameBuf>
self.fetch_impl.get_default_branch(remote_name, callbacks)
}
@@ -2155,7 +2165,7 @@ impl<'a> GitFetch<'a> {
fetched
.branches
.iter()
.any(|pattern| pattern.matches(symbol.name))
.any(|pattern| pattern.matches(symbol.name.as_str()))
}),
GitRefKind::Tag => true,
},
@@ -2417,7 +2427,7 @@ pub enum GitPushError {
#[derive(Clone, Debug)]
pub struct GitBranchPushTargets {
pub branch_updates: Vec<(String, BookmarkPushUpdate)>,
pub branch_updates: Vec<(RefNameBuf, BookmarkPushUpdate)>,
}
pub struct GitRefUpdate {
@@ -2434,17 +2444,17 @@ pub struct GitRefUpdate {
pub fn push_branches(
mut_repo: &mut MutableRepo,
git_settings: &GitSettings,
remote: &str,
remote: &RemoteName,
targets: &GitBranchPushTargets,
callbacks: RemoteCallbacks<'_>,
) -> Result<GitPushStats, GitPushError> {
validate_remote_name(remote)?;
validate_remote_name(remote.as_str())?;
let ref_updates = targets
.branch_updates
.iter()
.map(|(name, update)| GitRefUpdate {
qualified_name: format!("refs/heads/{name}"),
qualified_name: format!("refs/heads/{name}", name = name.as_str()),
expected_current_target: update.old_target.clone(),
new_target: update.new_target.clone(),
})
@@ -2459,7 +2469,11 @@ pub fn push_branches(
if push_stats.all_ok() {
for (name, update) in &targets.branch_updates {
let remote_symbol = RemoteRefSymbol { name, remote };
let git_ref_name = format!("refs/remotes/{remote}/{name}");
let git_ref_name = format!(
"refs/remotes/{remote}/{name}",
remote = remote.as_str(),
name = name.as_str()
);
let new_remote_ref = RemoteRef {
target: RefTarget::resolved(update.new_target.clone()),
state: RemoteRefState::Tracking,
@@ -2476,7 +2490,7 @@ pub fn push_branches(
pub fn push_updates(
repo: &dyn Repo,
git_settings: &GitSettings,
remote_name: &str,
remote_name: &RemoteName,
updates: &[GitRefUpdate],
callbacks: RemoteCallbacks<'_>,
) -> Result<GitPushStats, GitPushError> {
@@ -2510,7 +2524,7 @@ pub fn push_updates(
return git2_push_refs(
repo,
&git_repo,
remote_name,
remote_name.as_str(),
&qualified_remote_refs_expected_locations,
&refspecs,
callbacks,
@@ -2522,7 +2536,7 @@ pub fn push_updates(
subprocess_push_refs(
&git_repo,
&git_ctx,
remote_name,
remote_name.as_str(),
&qualified_remote_refs_expected_locations,
&refspecs,
callbacks,
@@ -2533,7 +2547,7 @@ pub fn push_updates(
fn git2_push_refs(
repo: &dyn Repo,
git_repo: &git2::Repository,
remote_name: &str,
remote_name: &str, // TODO: &RemoteName
qualified_remote_refs_expected_locations: &HashMap<&str, Option<&CommitId>>,
refspecs: &[String],
callbacks: RemoteCallbacks<'_>,
@@ -2675,7 +2689,7 @@ fn git2_push_refs(
fn subprocess_push_refs(
git_repo: &gix::Repository,
git_ctx: &GitSubprocessContext,
remote_name: &str,
remote_name: &str, // TODO: &RemoteName
qualified_remote_refs_expected_locations: &HashMap<&str, Option<&CommitId>>,
refspecs: &[RefSpec],
mut callbacks: RemoteCallbacks<'_>,

View File

@@ -56,11 +56,12 @@ pub mod git;
/// A stub module that provides a no-op implementation of some of the functions
/// in the `git` module.
pub mod git {
use crate::ref_name::RemoteName;
/// Determine, by its name, if a remote refers to the special local-only
/// "git" remote that is used in the Git backend.
///
/// This function always returns false if the "git" feature is not enabled.
pub fn is_special_git_remote(_remote: &str) -> bool {
pub fn is_special_git_remote(_remote: &RemoteName) -> bool {
false
}
}

View File

@@ -37,6 +37,10 @@ use crate::object_id::id_type;
use crate::object_id::HexPrefix;
use crate::object_id::ObjectId as _;
use crate::object_id::PrefixResolution;
use crate::ref_name::RefName;
use crate::ref_name::RefNameBuf;
use crate::ref_name::RemoteName;
use crate::ref_name::RemoteNameBuf;
use crate::ref_name::RemoteRefSymbol;
#[derive(ContentHash, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
@@ -260,7 +264,7 @@ pub struct BookmarkTarget<'a> {
/// 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)>,
pub remote_refs: Vec<(&'a RemoteName, &'a RemoteRef)>,
}
/// Represents the way the repo looks at a given time, just like how a Tree
@@ -269,9 +273,9 @@ pub struct BookmarkTarget<'a> {
pub struct View {
/// All head commits
pub head_ids: HashSet<CommitId>,
pub local_bookmarks: BTreeMap<String, RefTarget>,
pub tags: BTreeMap<String, RefTarget>,
pub remote_views: BTreeMap<String, RemoteView>,
pub local_bookmarks: BTreeMap<RefNameBuf, RefTarget>,
pub tags: BTreeMap<RefNameBuf, RefTarget>,
pub remote_views: BTreeMap<RemoteNameBuf, RemoteView>,
pub git_refs: BTreeMap<String, RefTarget>,
/// The commit the Git HEAD points to.
// TODO: Support multiple Git worktrees?
@@ -321,18 +325,18 @@ pub struct RemoteView {
// has been deleted locally and you pull from a remote, maybe it should make a difference
// 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>,
pub bookmarks: BTreeMap<RefNameBuf, RemoteRef>,
// TODO: pub tags: BTreeMap<RefNameBuf, RemoteRef>,
}
/// 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, BookmarkTarget<'a>)> {
local_bookmarks: &'a BTreeMap<RefNameBuf, RefTarget>,
remote_views: &'a BTreeMap<RemoteNameBuf, RemoteView>,
) -> impl Iterator<Item = (&'a RefName, BookmarkTarget<'a>)> {
let mut local_bookmarks_iter = local_bookmarks
.iter()
.map(|(bookmark_name, target)| (bookmark_name.as_str(), target))
.map(|(bookmark_name, target)| (&**bookmark_name, target))
.peekable();
let mut remote_bookmarks_iter = flatten_remote_bookmarks(remote_views).peekable();
@@ -360,7 +364,7 @@ pub(crate) fn merge_join_bookmark_views<'a>(
/// Iterates bookmark `(symbol, remote_ref)`s in lexicographical order.
pub(crate) fn flatten_remote_bookmarks(
remote_views: &BTreeMap<String, RemoteView>,
remote_views: &BTreeMap<RemoteNameBuf, RemoteView>,
) -> impl Iterator<Item = (RemoteRefSymbol<'_>, &RemoteRef)> {
remote_views
.iter()
@@ -514,24 +518,24 @@ mod tests {
remote_ref(&RefTarget::normal(CommitId::from_hex("666666")));
let local_bookmarks = btreemap! {
"bookmark1".to_owned() => local_bookmark1_target.clone(),
"bookmark2".to_owned() => local_bookmark2_target.clone(),
"bookmark1".into() => local_bookmark1_target.clone(),
"bookmark2".into() => local_bookmark2_target.clone(),
};
let remote_views = btreemap! {
"git".to_owned() => RemoteView {
"git".into() => RemoteView {
bookmarks: btreemap! {
"bookmark1".to_owned() => git_bookmark1_remote_ref.clone(),
"bookmark2".to_owned() => git_bookmark2_remote_ref.clone(),
"bookmark1".into() => git_bookmark1_remote_ref.clone(),
"bookmark2".into() => git_bookmark2_remote_ref.clone(),
},
},
"remote1".to_owned() => RemoteView {
"remote1".into() => RemoteView {
bookmarks: btreemap! {
"bookmark1".to_owned() => remote1_bookmark1_remote_ref.clone(),
"bookmark1".into() => remote1_bookmark1_remote_ref.clone(),
},
},
"remote2".to_owned() => RemoteView {
"remote2".into() => RemoteView {
bookmarks: btreemap! {
"bookmark2".to_owned() => remote2_bookmark2_remote_ref.clone(),
"bookmark2".into() => remote2_bookmark2_remote_ref.clone(),
},
},
};
@@ -539,22 +543,22 @@ mod tests {
merge_join_bookmark_views(&local_bookmarks, &remote_views).collect_vec(),
vec![
(
"bookmark1",
"bookmark1".as_ref(),
BookmarkTarget {
local_target: &local_bookmark1_target,
remote_refs: vec![
("git", &git_bookmark1_remote_ref),
("remote1", &remote1_bookmark1_remote_ref),
("git".as_ref(), &git_bookmark1_remote_ref),
("remote1".as_ref(), &remote1_bookmark1_remote_ref),
],
},
),
(
"bookmark2",
"bookmark2".as_ref(),
BookmarkTarget {
local_target: &local_bookmark2_target.clone(),
remote_refs: vec![
("git", &git_bookmark2_remote_ref),
("remote2", &remote2_bookmark2_remote_ref),
("git".as_ref(), &git_bookmark2_remote_ref),
("remote2".as_ref(), &remote2_bookmark2_remote_ref),
],
},
),
@@ -563,13 +567,13 @@ mod tests {
// Local only
let local_bookmarks = btreemap! {
"bookmark1".to_owned() => local_bookmark1_target.clone(),
"bookmark1".into() => local_bookmark1_target.clone(),
};
let remote_views = btreemap! {};
assert_eq!(
merge_join_bookmark_views(&local_bookmarks, &remote_views).collect_vec(),
vec![(
"bookmark1",
"bookmark1".as_ref(),
BookmarkTarget {
local_target: &local_bookmark1_target,
remote_refs: vec![],
@@ -580,19 +584,19 @@ mod tests {
// Remote only
let local_bookmarks = btreemap! {};
let remote_views = btreemap! {
"remote1".to_owned() => RemoteView {
"remote1".into() => RemoteView {
bookmarks: btreemap! {
"bookmark1".to_owned() => remote1_bookmark1_remote_ref.clone(),
"bookmark1".into() => remote1_bookmark1_remote_ref.clone(),
},
},
};
assert_eq!(
merge_join_bookmark_views(&local_bookmarks, &remote_views).collect_vec(),
vec![(
"bookmark1",
"bookmark1".as_ref(),
BookmarkTarget {
local_target: RefTarget::absent_ref(),
remote_refs: vec![("remote1", &remote1_bookmark1_remote_ref)],
remote_refs: vec![("remote1".as_ref(), &remote1_bookmark1_remote_ref)],
},
)],
);

View File

@@ -294,9 +294,9 @@ impl Display for RefSymbol {
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct RemoteRefSymbolBuf {
/// Local name.
pub name: String,
pub name: RefNameBuf,
/// Remote name.
pub remote: String,
pub remote: RemoteNameBuf,
}
impl RemoteRefSymbolBuf {
@@ -316,9 +316,9 @@ impl RemoteRefSymbolBuf {
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct RemoteRefSymbol<'a> {
/// Local name.
pub name: &'a str,
pub name: &'a RefName,
/// Remote name.
pub remote: &'a str,
pub remote: &'a RemoteName,
}
impl RemoteRefSymbol<'_> {
@@ -370,6 +370,6 @@ impl Display for RemoteRefSymbolBuf {
impl Display for RemoteRefSymbol<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let RemoteRefSymbol { name, remote } = self;
f.pad(&revset::format_remote_symbol(name, remote))
f.pad(&revset::format_remote_symbol(&name.0, &remote.0))
}
}

View File

@@ -73,6 +73,8 @@ use crate::op_store::RemoteRefState;
use crate::op_store::RootOperationData;
use crate::op_store::WorkspaceId;
use crate::operation::Operation;
use crate::ref_name::RefName;
use crate::ref_name::RemoteName;
use crate::ref_name::RemoteRefSymbol;
use crate::refs::diff_named_ref_targets;
use crate::refs::diff_named_remote_refs;
@@ -1524,11 +1526,11 @@ impl MutableRepo {
self.view.mark_dirty();
}
pub fn get_local_bookmark(&self, name: &str) -> RefTarget {
pub fn get_local_bookmark(&self, name: &RefName) -> RefTarget {
self.view.with_ref(|v| v.get_local_bookmark(name).clone())
}
pub fn set_local_bookmark_target(&mut self, name: &str, target: RefTarget) {
pub fn set_local_bookmark_target(&mut self, name: &RefName, target: RefTarget) {
let view = self.view_mut();
for id in target.added_ids() {
view.add_head(id);
@@ -1538,7 +1540,7 @@ impl MutableRepo {
pub fn merge_local_bookmark(
&mut self,
name: &str,
name: &RefName,
base_target: &RefTarget,
other_target: &RefTarget,
) {
@@ -1588,23 +1590,23 @@ impl MutableRepo {
self.set_remote_bookmark(symbol, remote_ref);
}
pub fn remove_remote(&mut self, remote_name: &str) {
pub fn remove_remote(&mut self, remote_name: &RemoteName) {
self.view_mut().remove_remote(remote_name);
}
pub fn rename_remote(&mut self, old: &str, new: &str) {
pub fn rename_remote(&mut self, old: &RemoteName, new: &RemoteName) {
self.view_mut().rename_remote(old, new);
}
pub fn get_tag(&self, name: &str) -> RefTarget {
pub fn get_tag(&self, name: &RefName) -> RefTarget {
self.view.with_ref(|v| v.get_tag(name).clone())
}
pub fn set_tag_target(&mut self, name: &str, target: RefTarget) {
pub fn set_tag_target(&mut self, name: &RefName, target: RefTarget) {
self.view_mut().set_tag_target(name, target);
}
pub fn merge_tag(&mut self, name: &str, base_target: &RefTarget, other_target: &RefTarget) {
pub fn merge_tag(&mut self, name: &RefName, base_target: &RefTarget, other_target: &RefTarget) {
let view = self.view.get_mut();
let index = self.index.as_index();
let self_target = view.get_tag(name);

View File

@@ -1822,7 +1822,9 @@ fn all_formatted_bookmark_symbols(
let view = repo.view();
view.bookmarks().flat_map(move |(name, bookmark_target)| {
let local_target = bookmark_target.local_target;
let local_symbol = local_target.is_present().then(|| format_symbol(name));
let local_symbol = local_target
.is_present()
.then(|| format_symbol(name.as_str()));
let remote_symbols = bookmark_target
.remote_refs
.into_iter()
@@ -1831,7 +1833,7 @@ fn all_formatted_bookmark_symbols(
|| !remote_ref.is_tracking()
|| remote_ref.target != *local_target
})
.map(move |(remote_name, _)| format_remote_symbol(name, remote_name));
.map(move |(remote, _)| format_remote_symbol(name.as_str(), remote.as_str()));
local_symbol.into_iter().chain(remote_symbols)
})
}
@@ -1890,7 +1892,7 @@ impl PartialSymbolResolver for TagResolver {
repo: &dyn Repo,
symbol: &str,
) -> Result<Option<Vec<CommitId>>, RevsetResolutionError> {
let target = repo.view().get_tag(symbol);
let target = repo.view().get_tag(symbol.as_ref());
Ok(target
.is_present()
.then(|| target.added_ids().cloned().collect()))
@@ -1905,7 +1907,7 @@ impl PartialSymbolResolver for BookmarkResolver {
repo: &dyn Repo,
symbol: &str,
) -> Result<Option<Vec<CommitId>>, RevsetResolutionError> {
let target = repo.view().get_local_bookmark(symbol);
let target = repo.view().get_local_bookmark(symbol.as_ref());
Ok(target
.is_present()
.then(|| target.added_ids().cloned().collect()))

View File

@@ -45,6 +45,8 @@ use crate::dsl_util::FoldableExpression;
use crate::dsl_util::FunctionCallParser;
use crate::dsl_util::InvalidArguments;
use crate::dsl_util::StringLiteralParser;
use crate::ref_name::RefNameBuf;
use crate::ref_name::RemoteNameBuf;
use crate::ref_name::RemoteRefSymbolBuf;
#[derive(Parser)]
@@ -651,7 +653,8 @@ fn parse_primary_node(pair: Pair<Rule>) -> Result<ExpressionNode, RevsetParseErr
None => ExpressionKind::AtWorkspace(name),
// infix "<name>@<remote>"
Some(second) => {
let remote = parse_as_string_literal(second);
let name: RefNameBuf = name.into();
let remote: RemoteNameBuf = parse_as_string_literal(second).into();
ExpressionKind::RemoteSymbol(RemoteRefSymbolBuf { name, remote })
}
}
@@ -1337,8 +1340,8 @@ mod tests {
assert_eq!(
parse_into_kind("main@origin"),
Ok(ExpressionKind::RemoteSymbol(RemoteRefSymbolBuf {
name: "main".to_owned(),
remote: "origin".to_owned()
name: "main".into(),
remote: "origin".into()
}))
);
@@ -1350,22 +1353,22 @@ mod tests {
assert_eq!(
parse_into_kind(r#""foo bar"@origin"#),
Ok(ExpressionKind::RemoteSymbol(RemoteRefSymbolBuf {
name: "foo bar".to_owned(),
remote: "origin".to_owned()
name: "foo bar".into(),
remote: "origin".into()
}))
);
assert_eq!(
parse_into_kind(r#"main@"foo bar""#),
Ok(ExpressionKind::RemoteSymbol(RemoteRefSymbolBuf {
name: "main".to_owned(),
remote: "foo bar".to_owned()
name: "main".into(),
remote: "foo bar".into()
}))
);
assert_eq!(
parse_into_kind(r#"'foo bar'@'bar baz'"#),
Ok(ExpressionKind::RemoteSymbol(RemoteRefSymbolBuf {
name: "foo bar".to_owned(),
remote: "bar baz".to_owned()
name: "foo bar".into(),
remote: "bar baz".into()
}))
);
@@ -1391,8 +1394,8 @@ mod tests {
assert_eq!(
parse_into_kind("@"),
Ok(ExpressionKind::RemoteSymbol(RemoteRefSymbolBuf {
name: "".to_owned(),
remote: "".to_owned()
name: "".into(),
remote: "".into()
}))
);
}

View File

@@ -60,6 +60,8 @@ use crate::op_store::RootOperationData;
use crate::op_store::View;
use crate::op_store::ViewId;
use crate::op_store::WorkspaceId;
use crate::ref_name::RefNameBuf;
use crate::ref_name::RemoteNameBuf;
// BLAKE2b-512 hash length in bytes
const OPERATION_ID_LENGTH: usize = 64;
@@ -489,7 +491,7 @@ fn view_to_proto(view: &View) -> crate::protos::op_store::View {
for (name, target) in &view.tags {
proto.tags.push(crate::protos::op_store::Tag {
name: name.clone(),
name: name.into(),
target: ref_target_to_proto(target),
});
}
@@ -530,8 +532,9 @@ fn view_from_proto(proto: crate::protos::op_store::View) -> View {
view.remote_views = remote_views;
for tag_proto in proto.tags {
let name: RefNameBuf = tag_proto.name.into();
view.tags
.insert(tag_proto.name, ref_target_from_proto(tag_proto.target));
.insert(name, ref_target_from_proto(tag_proto.target));
}
for git_ref in proto.git_refs {
@@ -555,8 +558,8 @@ fn view_from_proto(proto: crate::protos::op_store::View) -> View {
}
fn bookmark_views_to_proto_legacy(
local_bookmarks: &BTreeMap<String, RefTarget>,
remote_views: &BTreeMap<String, RemoteView>,
local_bookmarks: &BTreeMap<RefNameBuf, RefTarget>,
remote_views: &BTreeMap<RemoteNameBuf, RemoteView>,
) -> Vec<crate::protos::op_store::Bookmark> {
op_store::merge_join_bookmark_views(local_bookmarks, remote_views)
.map(|(name, bookmark_target)| {
@@ -566,14 +569,14 @@ fn bookmark_views_to_proto_legacy(
.iter()
.map(
|&(remote_name, remote_ref)| crate::protos::op_store::RemoteBookmark {
remote_name: remote_name.to_owned(),
remote_name: remote_name.into(),
target: ref_target_to_proto(&remote_ref.target),
state: remote_ref_state_to_proto(remote_ref.state),
},
)
.collect();
crate::protos::op_store::Bookmark {
name: name.to_owned(),
name: name.into(),
local_target,
remote_bookmarks,
}
@@ -583,12 +586,17 @@ fn bookmark_views_to_proto_legacy(
fn bookmark_views_from_proto_legacy(
bookmarks_legacy: Vec<crate::protos::op_store::Bookmark>,
) -> (BTreeMap<String, RefTarget>, BTreeMap<String, RemoteView>) {
let mut local_bookmarks: BTreeMap<String, RefTarget> = BTreeMap::new();
let mut remote_views: BTreeMap<String, RemoteView> = BTreeMap::new();
) -> (
BTreeMap<RefNameBuf, RefTarget>,
BTreeMap<RemoteNameBuf, RemoteView>,
) {
let mut local_bookmarks: BTreeMap<RefNameBuf, RefTarget> = BTreeMap::new();
let mut remote_views: BTreeMap<RemoteNameBuf, RemoteView> = BTreeMap::new();
for bookmark_proto in bookmarks_legacy {
let bookmark_name: RefNameBuf = bookmark_proto.name.into();
let local_target = ref_target_from_proto(bookmark_proto.local_target);
for remote_bookmark in bookmark_proto.remote_bookmarks {
let remote_name: RemoteNameBuf = remote_bookmark.remote_name.into();
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
@@ -596,32 +604,31 @@ fn bookmark_views_from_proto_legacy(
// 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.
let is_git_tracking =
crate::git::is_special_git_remote(&remote_bookmark.remote_name);
let is_git_tracking = crate::git::is_special_git_remote(&remote_name);
let default_state = if is_git_tracking || local_target.is_present() {
RemoteRefState::Tracking
} else {
RemoteRefState::New
};
tracing::trace!(
?bookmark_proto.name,
?remote_bookmark.remote_name,
?bookmark_name,
?remote_name,
?default_state,
"generated tracking state",
);
default_state
});
let remote_view = remote_views.entry(remote_bookmark.remote_name).or_default();
let remote_view = remote_views.entry(remote_name).or_default();
let remote_ref = RemoteRef {
target: ref_target_from_proto(remote_bookmark.target),
state,
};
remote_view
.bookmarks
.insert(bookmark_proto.name.clone(), remote_ref);
.insert(bookmark_name.clone(), remote_ref);
}
if local_target.is_present() {
local_bookmarks.insert(bookmark_proto.name, local_target);
local_bookmarks.insert(bookmark_name, local_target);
}
}
(local_bookmarks, remote_views)
@@ -753,16 +760,16 @@ mod tests {
View {
head_ids: hashset! {head_id1, head_id2},
local_bookmarks: btreemap! {
"main".to_string() => bookmark_main_local_target,
"main".into() => bookmark_main_local_target,
},
tags: btreemap! {
"v1.0".to_string() => tag_v1_target,
"v1.0".into() => tag_v1_target,
},
remote_views: btreemap! {
"origin".to_string() => RemoteView {
"origin".into() => RemoteView {
bookmarks: btreemap! {
"main".to_string() => tracking_remote_ref(&bookmark_main_origin_target),
"deleted".to_string() => new_remote_ref(&bookmark_deleted_origin_target),
"main".into() => tracking_remote_ref(&bookmark_main_origin_target),
"deleted".into() => new_remote_ref(&bookmark_deleted_origin_target),
},
},
},
@@ -872,25 +879,25 @@ mod tests {
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(),
"bookmark1".into() => local_bookmark1_target.clone(),
"bookmark3".into() => local_bookmark3_target.clone(),
};
let remote_views = btreemap! {
"git".to_owned() => RemoteView {
"git".into() => RemoteView {
bookmarks: btreemap! {
"bookmark1".to_owned() => tracking_remote_ref(&git_bookmark1_target),
"bookmark1".into() => tracking_remote_ref(&git_bookmark1_target),
},
},
"remote1".to_owned() => RemoteView {
"remote1".into() => RemoteView {
bookmarks: btreemap! {
"bookmark1".to_owned() => tracking_remote_ref(&remote1_bookmark1_target),
"bookmark1".into() => tracking_remote_ref(&remote1_bookmark1_target),
},
},
"remote2".to_owned() => RemoteView {
"remote2".into() => RemoteView {
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),
"bookmark2".into() => new_remote_ref(&remote2_bookmark2_target),
"bookmark4".into() => tracking_remote_ref(&remote2_bookmark4_target),
},
},
};

View File

@@ -27,6 +27,9 @@ use crate::op_store::RefTarget;
use crate::op_store::RefTargetOptionExt as _;
use crate::op_store::RemoteRef;
use crate::op_store::WorkspaceId;
use crate::ref_name::RefName;
use crate::ref_name::RefNameBuf;
use crate::ref_name::RemoteName;
use crate::ref_name::RemoteRefSymbol;
use crate::refs;
use crate::refs::LocalAndRemoteRef;
@@ -72,11 +75,11 @@ impl View {
}
/// Iterates pair of local and remote bookmarks by bookmark name.
pub fn bookmarks(&self) -> impl Iterator<Item = (&str, BookmarkTarget<'_>)> {
pub fn bookmarks(&self) -> impl Iterator<Item = (&RefName, BookmarkTarget<'_>)> {
op_store::merge_join_bookmark_views(&self.data.local_bookmarks, &self.data.remote_views)
}
pub fn tags(&self) -> &BTreeMap<String, RefTarget> {
pub fn tags(&self) -> &BTreeMap<RefNameBuf, RefTarget> {
&self.data.tags
}
@@ -128,7 +131,7 @@ impl View {
}
/// Iterates local bookmark `(name, target)`s in lexicographical order.
pub fn local_bookmarks(&self) -> impl Iterator<Item = (&str, &RefTarget)> {
pub fn local_bookmarks(&self) -> impl Iterator<Item = (&RefName, &RefTarget)> {
self.data
.local_bookmarks
.iter()
@@ -140,7 +143,7 @@ impl View {
pub fn local_bookmarks_for_commit<'a, 'b>(
&'a self,
commit_id: &'b CommitId,
) -> impl Iterator<Item = (&'a str, &'a RefTarget)> + use<'a, 'b> {
) -> impl Iterator<Item = (&'a RefName, &'a RefTarget)> + use<'a, 'b> {
self.local_bookmarks()
.filter(|(_, target)| target.added_ids().contains(commit_id))
}
@@ -150,20 +153,20 @@ impl View {
pub fn local_bookmarks_matching<'a, 'b>(
&'a self,
pattern: &'b StringPattern,
) -> impl Iterator<Item = (&'a str, &'a RefTarget)> + use<'a, 'b> {
) -> impl Iterator<Item = (&'a RefName, &'a RefTarget)> + use<'a, 'b> {
pattern
.filter_btree_map(&self.data.local_bookmarks)
.filter_btree_map_as_deref(&self.data.local_bookmarks)
.map(|(name, target)| (name.as_ref(), target))
}
pub fn get_local_bookmark(&self, name: &str) -> &RefTarget {
pub fn get_local_bookmark(&self, name: &RefName) -> &RefTarget {
self.data.local_bookmarks.get(name).flatten()
}
/// 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) {
pub fn set_local_bookmark_target(&mut self, name: &RefName, target: RefTarget) {
if target.is_present() {
self.data.local_bookmarks.insert(name.to_owned(), target);
} else {
@@ -181,8 +184,8 @@ impl View {
/// specified remote in lexicographical order.
pub fn remote_bookmarks(
&self,
remote_name: &str,
) -> impl Iterator<Item = (&str, &RemoteRef)> + use<'_> {
remote_name: &RemoteName,
) -> impl Iterator<Item = (&RefName, &RemoteRef)> + use<'_> {
let maybe_remote_view = self.data.remote_views.get(remote_name);
maybe_remote_view
.map(|remote_view| {
@@ -206,10 +209,10 @@ impl View {
) -> impl Iterator<Item = (RemoteRefSymbol<'a>, &'a RemoteRef)> + use<'a, 'b> {
// Use kmerge instead of flat_map for consistency with all_remote_bookmarks().
remote_pattern
.filter_btree_map(&self.data.remote_views)
.filter_btree_map_as_deref(&self.data.remote_views)
.map(|(remote, remote_view)| {
bookmark_pattern
.filter_btree_map(&remote_view.bookmarks)
.filter_btree_map_as_deref(&remote_view.bookmarks)
.map(|(name, remote_ref)| {
let symbol = RemoteRefSymbol { name, remote };
(symbol, remote_ref)
@@ -252,8 +255,8 @@ impl View {
/// RefTarget::absent_ref() or RemoteRef::absent_ref().
pub fn local_remote_bookmarks(
&self,
remote_name: &str,
) -> impl Iterator<Item = (&str, LocalAndRemoteRef<'_>)> + use<'_> {
remote_name: &RemoteName,
) -> impl Iterator<Item = (&RefName, LocalAndRemoteRef<'_>)> + use<'_> {
refs::iter_named_local_remote_refs(
self.local_bookmarks(),
self.remote_bookmarks(remote_name),
@@ -279,15 +282,17 @@ impl View {
pub fn local_remote_bookmarks_matching<'a, 'b>(
&'a self,
bookmark_pattern: &'b StringPattern,
remote_name: &str,
) -> impl Iterator<Item = (&'a str, LocalAndRemoteRef<'a>)> + use<'a, 'b> {
remote_name: &RemoteName,
) -> impl Iterator<Item = (&'a RefName, LocalAndRemoteRef<'a>)> + use<'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(
bookmark_pattern.filter_btree_map(&self.data.local_bookmarks),
bookmark_pattern.filter_btree_map_as_deref(&self.data.local_bookmarks),
maybe_remote_view
.map(|remote_view| bookmark_pattern.filter_btree_map(&remote_view.bookmarks))
.map(|remote_view| {
bookmark_pattern.filter_btree_map_as_deref(&remote_view.bookmarks)
})
.into_iter()
.flatten(),
)
@@ -300,17 +305,17 @@ impl View {
})
}
pub fn remove_remote(&mut self, remote_name: &str) {
pub fn remove_remote(&mut self, remote_name: &RemoteName) {
self.data.remote_views.remove(remote_name);
}
pub fn rename_remote(&mut self, old: &str, new: &str) {
pub fn rename_remote(&mut self, old: &RemoteName, new: &RemoteName) {
if let Some(remote_view) = self.data.remote_views.remove(old) {
self.data.remote_views.insert(new.to_owned(), remote_view);
}
}
pub fn get_tag(&self, name: &str) -> &RefTarget {
pub fn get_tag(&self, name: &RefName) -> &RefTarget {
self.data.tags.get(name).flatten()
}
@@ -319,15 +324,15 @@ impl View {
pub fn tags_matching<'a, 'b>(
&'a self,
pattern: &'b StringPattern,
) -> impl Iterator<Item = (&'a str, &'a RefTarget)> + use<'a, 'b> {
) -> impl Iterator<Item = (&'a RefName, &'a RefTarget)> + use<'a, 'b> {
pattern
.filter_btree_map(&self.data.tags)
.filter_btree_map_as_deref(&self.data.tags)
.map(|(name, target)| (name.as_ref(), target))
}
/// Sets tag to point to the given target. If the target is absent, the tag
/// will be removed.
pub fn set_tag_target(&mut self, name: &str, target: RefTarget) {
pub fn set_tag_target(&mut self, name: &RefName, target: RefTarget) {
if target.is_present() {
self.data.tags.insert(name.to_owned(), target);
} else {

View File

@@ -53,6 +53,8 @@ use jj_lib::op_store::BookmarkTarget;
use jj_lib::op_store::RefTarget;
use jj_lib::op_store::RemoteRef;
use jj_lib::op_store::RemoteRefState;
use jj_lib::ref_name::RefName;
use jj_lib::ref_name::RemoteName;
use jj_lib::ref_name::RemoteRefSymbol;
use jj_lib::refs::BookmarkPushUpdate;
use jj_lib::repo::MutableRepo;
@@ -109,8 +111,15 @@ fn git_id(commit: &Commit) -> gix::ObjectId {
gix::ObjectId::from_bytes_or_panic(commit.id().as_bytes())
}
fn remote_symbol<'a>(name: &'a str, remote: &'a str) -> RemoteRefSymbol<'a> {
RemoteRefSymbol { name, remote }
fn remote_symbol<'a, N, M>(name: &'a N, remote: &'a M) -> RemoteRefSymbol<'a>
where
N: AsRef<RefName> + ?Sized,
M: AsRef<RemoteName> + ?Sized,
{
RemoteRefSymbol {
name: name.as_ref(),
remote: remote.as_ref(),
}
}
fn get_git_backend(repo: &Arc<ReadonlyRepo>) -> &GitBackend {
@@ -209,7 +218,7 @@ fn test_import_refs() {
assert_eq!(view.bookmarks().count(), 4);
assert_eq!(
view.get_local_bookmark("main"),
view.get_local_bookmark("main".as_ref()),
&RefTarget::normal(jj_id(commit2))
);
assert_eq!(
@@ -227,7 +236,7 @@ fn test_import_refs() {
},
);
assert_eq!(
view.get_local_bookmark("feature1"),
view.get_local_bookmark("feature1".as_ref()),
&RefTarget::normal(jj_id(commit3))
);
assert_eq!(
@@ -241,7 +250,7 @@ fn test_import_refs() {
.get_remote_bookmark(remote_symbol("feature1", "origin"))
.is_absent());
assert_eq!(
view.get_local_bookmark("feature2"),
view.get_local_bookmark("feature2".as_ref()),
&RefTarget::normal(jj_id(commit4))
);
assert_eq!(
@@ -255,7 +264,7 @@ fn test_import_refs() {
.get_remote_bookmark(remote_symbol("feature2", "origin"))
.is_absent());
assert_eq!(
view.get_local_bookmark("feature3"),
view.get_local_bookmark("feature3".as_ref()),
&RefTarget::normal(jj_id(commit6))
);
assert!(view
@@ -269,7 +278,10 @@ fn test_import_refs() {
},
);
assert_eq!(view.get_tag("v1.0"), &RefTarget::normal(jj_id(commit5)));
assert_eq!(
view.get_tag("v1.0".as_ref()),
&RefTarget::normal(jj_id(commit5))
);
assert_eq!(view.git_refs().len(), 6);
assert_eq!(
@@ -349,7 +361,7 @@ fn test_import_refs_reimport() {
.write()
.unwrap();
tx.repo_mut()
.set_local_bookmark_target("feature2", RefTarget::normal(commit6.id().clone()));
.set_local_bookmark_target("feature2".as_ref(), RefTarget::normal(commit6.id().clone()));
let repo = tx.commit("test").unwrap();
let mut tx = repo.start_transaction();
@@ -376,7 +388,7 @@ fn test_import_refs_reimport() {
let commit1_target = RefTarget::normal(jj_id(commit1));
let commit2_target = RefTarget::normal(jj_id(commit2));
assert_eq!(
view.get_local_bookmark("main"),
view.get_local_bookmark("main".as_ref()),
&RefTarget::normal(jj_id(commit2))
);
assert_eq!(
@@ -394,7 +406,7 @@ fn test_import_refs_reimport() {
},
);
assert_eq!(
view.get_local_bookmark("feature2"),
view.get_local_bookmark("feature2".as_ref()),
&RefTarget::from_legacy_form([jj_id(commit4)], [commit6.id().clone(), jj_id(commit5)])
);
assert_eq!(
@@ -607,7 +619,7 @@ fn test_import_refs_reimport_with_deleted_remote_ref() {
// `feature-remote-only`, jj creates one. This follows the model explained
// in docs/bookmarks.md.
assert_eq!(
view.get_local_bookmark("feature-remote-only"),
view.get_local_bookmark("feature-remote-only".as_ref()),
&RefTarget::normal(jj_id(commit_remote_only))
);
assert!(view
@@ -621,7 +633,7 @@ fn test_import_refs_reimport_with_deleted_remote_ref() {
},
);
assert_eq!(
view.get_local_bookmark("feature-remote-and-local"),
view.get_local_bookmark("feature-remote-and-local".as_ref()),
&RefTarget::normal(jj_id(commit_remote_and_local))
);
assert_eq!(
@@ -638,7 +650,7 @@ fn test_import_refs_reimport_with_deleted_remote_ref() {
state: RemoteRefState::Tracking,
},
);
assert!(view.get_local_bookmark("main").is_present()); // bookmark #3 of 3
assert!(view.get_local_bookmark("main".as_ref()).is_present()); // bookmark #3 of 3
// Simulate fetching from a remote where feature-remote-only and
// feature-remote-and-local bookmarks were deleted. This leads to the
@@ -654,13 +666,15 @@ fn test_import_refs_reimport_with_deleted_remote_ref() {
let view = repo.view();
// The local bookmarks were indeed deleted
assert_eq!(view.bookmarks().count(), 2);
assert!(view.get_local_bookmark("main").is_present());
assert!(view.get_local_bookmark("feature-remote-only").is_absent());
assert!(view.get_local_bookmark("main".as_ref()).is_present());
assert!(view
.get_local_bookmark("feature-remote-only".as_ref())
.is_absent());
assert!(view
.get_remote_bookmark(remote_symbol("feature-remote-only", "origin"))
.is_absent());
assert!(view
.get_local_bookmark("feature-remote-and-local")
.get_local_bookmark("feature-remote-and-local".as_ref())
.is_absent());
assert_eq!(
view.get_remote_bookmark(remote_symbol("feature-remote-and-local", "git")),
@@ -728,7 +742,7 @@ fn test_import_refs_reimport_with_moved_remote_ref() {
// `feature-remote-only`, jj creates one. This follows the model explained
// in docs/bookmarks.md.
assert_eq!(
view.get_local_bookmark("feature-remote-only"),
view.get_local_bookmark("feature-remote-only".as_ref()),
&RefTarget::normal(jj_id(commit_remote_only))
);
assert!(view
@@ -742,7 +756,7 @@ fn test_import_refs_reimport_with_moved_remote_ref() {
},
);
assert_eq!(
view.get_local_bookmark("feature-remote-and-local"),
view.get_local_bookmark("feature-remote-and-local".as_ref()),
&RefTarget::normal(jj_id(commit_remote_and_local))
);
assert_eq!(
@@ -759,7 +773,7 @@ fn test_import_refs_reimport_with_moved_remote_ref() {
state: RemoteRefState::Tracking,
},
);
assert!(view.get_local_bookmark("main").is_present()); // bookmark #3 of 3
assert!(view.get_local_bookmark("main".as_ref()).is_present()); // bookmark #3 of 3
// Simulate fetching from a remote where feature-remote-only and
// feature-remote-and-local bookmarks were moved. This leads to the
@@ -786,7 +800,7 @@ fn test_import_refs_reimport_with_moved_remote_ref() {
assert_eq!(view.bookmarks().count(), 3);
// The local bookmarks are moved
assert_eq!(
view.get_local_bookmark("feature-remote-only"),
view.get_local_bookmark("feature-remote-only".as_ref()),
&RefTarget::normal(jj_id(new_commit_remote_only))
);
assert!(view
@@ -800,7 +814,7 @@ fn test_import_refs_reimport_with_moved_remote_ref() {
},
);
assert_eq!(
view.get_local_bookmark("feature-remote-and-local"),
view.get_local_bookmark("feature-remote-and-local".as_ref()),
&RefTarget::normal(jj_id(new_commit_remote_and_local))
);
assert_eq!(
@@ -817,7 +831,7 @@ fn test_import_refs_reimport_with_moved_remote_ref() {
state: RemoteRefState::Tracking,
},
);
assert!(view.get_local_bookmark("main").is_present()); // bookmark #3 of 3
assert!(view.get_local_bookmark("main".as_ref()).is_present()); // bookmark #3 of 3
let expected_heads = hashset! {
jj_id(commit_main),
jj_id(new_commit_remote_and_local),
@@ -1228,7 +1242,7 @@ fn test_import_some_refs() {
git::import_some_refs(tx.repo_mut(), &git_settings, |kind, symbol| {
kind == GitRefKind::Bookmark
&& symbol.remote == "origin"
&& symbol.name.starts_with("feature")
&& symbol.name.as_str().starts_with("feature")
})
.unwrap();
tx.repo_mut().rebase_descendants().unwrap();
@@ -1262,7 +1276,7 @@ fn test_import_some_refs() {
state: RemoteRefState::Tracking,
};
assert_eq!(
view.get_local_bookmark("feature1"),
view.get_local_bookmark("feature1".as_ref()),
&RefTarget::normal(jj_id(commit_feat1))
);
assert_eq!(
@@ -1270,7 +1284,7 @@ fn test_import_some_refs() {
&commit_feat1_remote_ref
);
assert_eq!(
view.get_local_bookmark("feature2"),
view.get_local_bookmark("feature2".as_ref()),
&RefTarget::normal(jj_id(commit_feat2))
);
assert_eq!(
@@ -1278,7 +1292,7 @@ fn test_import_some_refs() {
&commit_feat2_remote_ref
);
assert_eq!(
view.get_local_bookmark("feature3"),
view.get_local_bookmark("feature3".as_ref()),
&RefTarget::normal(jj_id(commit_feat3))
);
assert_eq!(
@@ -1286,14 +1300,14 @@ fn test_import_some_refs() {
&commit_feat3_remote_ref
);
assert_eq!(
view.get_local_bookmark("feature4"),
view.get_local_bookmark("feature4".as_ref()),
&RefTarget::normal(jj_id(commit_feat4))
);
assert_eq!(
view.get_remote_bookmark(remote_symbol("feature4", "origin")),
&commit_feat4_remote_ref
);
assert!(view.get_local_bookmark("main").is_absent());
assert!(view.get_local_bookmark("main".as_ref()).is_absent());
assert!(view
.get_remote_bookmark(remote_symbol("main", "git"))
.is_absent());
@@ -1301,7 +1315,7 @@ fn test_import_some_refs() {
.get_remote_bookmark(remote_symbol("main", "origin"))
.is_absent());
assert!(!view.heads().contains(&jj_id(commit_main)));
assert!(view.get_local_bookmark("ignored").is_absent());
assert!(view.get_local_bookmark("ignored".as_ref()).is_absent());
assert!(view
.get_remote_bookmark(remote_symbol("ignored", "git"))
.is_absent());
@@ -1622,7 +1636,7 @@ fn test_export_refs_bookmark_changed() {
.set_parents(vec![jj_id(commit)])
.write()
.unwrap();
mut_repo.set_local_bookmark_target("main", RefTarget::normal(new_commit.id().clone()));
mut_repo.set_local_bookmark_target("main".as_ref(), RefTarget::normal(new_commit.id().clone()));
let stats = git::export_refs(mut_repo).unwrap();
assert!(stats.failed_bookmarks.is_empty());
assert_eq!(
@@ -1666,7 +1680,7 @@ fn test_export_refs_current_bookmark_changed() {
.set_parents(vec![jj_id(commit1)])
.write()
.unwrap();
mut_repo.set_local_bookmark_target("main", RefTarget::normal(new_commit.id().clone()));
mut_repo.set_local_bookmark_target("main".as_ref(), RefTarget::normal(new_commit.id().clone()));
let stats = git::export_refs(mut_repo).unwrap();
assert!(stats.failed_bookmarks.is_empty());
assert_eq!(
@@ -1704,7 +1718,7 @@ fn test_export_refs_unborn_git_bookmark(move_placeholder_ref: bool) {
assert!(git_repo.head().unwrap().is_unborn(), "HEAD is unborn");
let new_commit = write_random_commit(mut_repo);
mut_repo.set_local_bookmark_target("main", RefTarget::normal(new_commit.id().clone()));
mut_repo.set_local_bookmark_target("main".as_ref(), RefTarget::normal(new_commit.id().clone()));
if move_placeholder_ref {
git_repo
.reference(
@@ -1766,7 +1780,7 @@ fn test_export_import_sequence() {
);
// Modify the bookmark in jj to point to B
mut_repo.set_local_bookmark_target("main", RefTarget::normal(commit_b.id().clone()));
mut_repo.set_local_bookmark_target("main".as_ref(), RefTarget::normal(commit_b.id().clone()));
// Export the bookmark to git
let stats = git::export_refs(mut_repo).unwrap();
@@ -1793,7 +1807,7 @@ fn test_export_import_sequence() {
RefTarget::normal(commit_c.id().clone())
);
assert_eq!(
mut_repo.view().get_local_bookmark("main"),
mut_repo.view().get_local_bookmark("main".as_ref()),
&RefTarget::normal(commit_c.id().clone())
);
}
@@ -1815,7 +1829,10 @@ fn test_import_export_non_tracking_bookmark() {
git::import_refs(mut_repo, &git_settings).unwrap();
assert!(mut_repo.view().get_local_bookmark("main").is_absent());
assert!(mut_repo
.view()
.get_local_bookmark("main".as_ref())
.is_absent());
assert_eq!(
mut_repo
.view()
@@ -1841,9 +1858,12 @@ fn test_import_export_non_tracking_bookmark() {
let commit_feat_t1 = empty_git_commit(&git_repo, "refs/remotes/origin/feat", &[]);
git_settings.auto_local_bookmark = true;
git::import_refs(mut_repo, &git_settings).unwrap();
assert!(mut_repo.view().get_local_bookmark("main").is_absent());
assert!(mut_repo
.view()
.get_local_bookmark("main".as_ref())
.is_absent());
assert_eq!(
mut_repo.view().get_local_bookmark("feat"),
mut_repo.view().get_local_bookmark("feat".as_ref()),
&RefTarget::normal(jj_id(commit_feat_t1))
);
assert_eq!(
@@ -1870,9 +1890,12 @@ fn test_import_export_non_tracking_bookmark() {
let commit_feat_t2 = empty_git_commit(&git_repo, "refs/remotes/origin/feat", &[commit_feat_t1]);
git_settings.auto_local_bookmark = false;
git::import_refs(mut_repo, &git_settings).unwrap();
assert!(mut_repo.view().get_local_bookmark("main").is_absent());
assert!(mut_repo
.view()
.get_local_bookmark("main".as_ref())
.is_absent());
assert_eq!(
mut_repo.view().get_local_bookmark("feat"),
mut_repo.view().get_local_bookmark("feat".as_ref()),
&RefTarget::normal(jj_id(commit_feat_t2))
);
assert_eq!(
@@ -1905,16 +1928,17 @@ fn test_export_conflicts() {
let commit_a = write_random_commit(mut_repo);
let commit_b = write_random_commit(mut_repo);
let commit_c = write_random_commit(mut_repo);
mut_repo.set_local_bookmark_target("main", RefTarget::normal(commit_a.id().clone()));
mut_repo.set_local_bookmark_target("feature", RefTarget::normal(commit_a.id().clone()));
mut_repo.set_local_bookmark_target("main".as_ref(), RefTarget::normal(commit_a.id().clone()));
mut_repo
.set_local_bookmark_target("feature".as_ref(), RefTarget::normal(commit_a.id().clone()));
let stats = git::export_refs(mut_repo).unwrap();
assert!(stats.failed_bookmarks.is_empty());
// Create a conflict and export. It should not be exported, but other changes
// should be.
mut_repo.set_local_bookmark_target("main", RefTarget::normal(commit_b.id().clone()));
mut_repo.set_local_bookmark_target("main".as_ref(), RefTarget::normal(commit_b.id().clone()));
mut_repo.set_local_bookmark_target(
"feature",
"feature".as_ref(),
RefTarget::from_legacy_form(
[commit_a.id().clone()],
[commit_b.id().clone(), commit_c.id().clone()],
@@ -1963,7 +1987,7 @@ fn test_export_bookmark_on_root_commit() {
let mut tx = test_data.repo.start_transaction();
let mut_repo = tx.repo_mut();
mut_repo.set_local_bookmark_target(
"on_root",
"on_root".as_ref(),
RefTarget::normal(mut_repo.store().root_commit_id().clone()),
);
let stats = git::export_refs(mut_repo).unwrap();
@@ -1988,13 +2012,13 @@ fn test_export_partial_failure() {
let commit_a = write_random_commit(mut_repo);
let target = RefTarget::normal(commit_a.id().clone());
// Empty string is disallowed by Git
mut_repo.set_local_bookmark_target("", target.clone());
mut_repo.set_local_bookmark_target("".as_ref(), target.clone());
// Branch named HEAD is disallowed by Git CLI
mut_repo.set_local_bookmark_target("HEAD", target.clone());
mut_repo.set_local_bookmark_target("main", target.clone());
mut_repo.set_local_bookmark_target("HEAD".as_ref(), target.clone());
mut_repo.set_local_bookmark_target("main".as_ref(), target.clone());
// `main/sub` will conflict with `main` in Git, at least when using loose ref
// storage
mut_repo.set_local_bookmark_target("main/sub", target.clone());
mut_repo.set_local_bookmark_target("main/sub".as_ref(), target.clone());
let stats = git::export_refs(mut_repo).unwrap();
assert_eq!(stats.failed_bookmarks.len(), 3);
assert_eq!(
@@ -2055,7 +2079,7 @@ fn test_export_partial_failure() {
// Now remove the `main` bookmark and make sure that the `main/sub` gets
// exported even though it didn't change
mut_repo.set_local_bookmark_target("main", RefTarget::absent());
mut_repo.set_local_bookmark_target("main".as_ref(), RefTarget::absent());
let stats = git::export_refs(mut_repo).unwrap();
assert_eq!(stats.failed_bookmarks.len(), 2);
assert_eq!(
@@ -2139,20 +2163,23 @@ fn test_export_reexport_transitions() {
for bookmark in [
"AAB", "AAX", "ABA", "ABB", "ABC", "ABX", "AXA", "AXB", "AXX",
] {
mut_repo.set_local_bookmark_target(bookmark, RefTarget::normal(commit_a.id().clone()));
mut_repo
.set_local_bookmark_target(bookmark.as_ref(), RefTarget::normal(commit_a.id().clone()));
}
let stats = git::export_refs(mut_repo).unwrap();
assert!(stats.failed_bookmarks.is_empty());
// Make changes on the jj side
for bookmark in ["AXA", "AXB", "AXX"] {
mut_repo.set_local_bookmark_target(bookmark, RefTarget::absent());
mut_repo.set_local_bookmark_target(bookmark.as_ref(), RefTarget::absent());
}
for bookmark in ["XAA", "XAB", "XAX"] {
mut_repo.set_local_bookmark_target(bookmark, RefTarget::normal(commit_a.id().clone()));
mut_repo
.set_local_bookmark_target(bookmark.as_ref(), RefTarget::normal(commit_a.id().clone()));
}
for bookmark in ["ABA", "ABB", "ABC", "ABX"] {
mut_repo.set_local_bookmark_target(bookmark, RefTarget::normal(commit_b.id().clone()));
mut_repo
.set_local_bookmark_target(bookmark.as_ref(), RefTarget::normal(commit_b.id().clone()));
}
// Make changes on the git side
@@ -2274,7 +2301,7 @@ fn test_export_undo_reexport() {
// Initial export
let commit_a = write_random_commit(mut_repo);
let target_a = RefTarget::normal(commit_a.id().clone());
mut_repo.set_local_bookmark_target("main", target_a.clone());
mut_repo.set_local_bookmark_target("main".as_ref(), target_a.clone());
let stats = git::export_refs(mut_repo).unwrap();
assert!(stats.failed_bookmarks.is_empty());
assert_eq!(
@@ -2868,10 +2895,10 @@ fn test_fetch_initial_commit_head_is_not_set(subprocess: bool) {
assert_eq!(
view.bookmarks().collect::<BTreeMap<_, _>>(),
btreemap! {
"main" => BookmarkTarget {
"main".as_ref() => BookmarkTarget {
local_target: &initial_commit_target,
remote_refs: vec![
("origin", &initial_commit_remote_ref),
("origin".as_ref(), &initial_commit_remote_ref),
],
},
}
@@ -2982,10 +3009,10 @@ fn test_fetch_success(subprocess: bool) {
assert_eq!(
view.bookmarks().collect::<BTreeMap<_, _>>(),
btreemap! {
"main" => BookmarkTarget {
"main".as_ref() => BookmarkTarget {
local_target: &new_commit_target,
remote_refs: vec![
("origin", &new_commit_remote_ref),
("origin".as_ref(), &new_commit_remote_ref),
],
},
}
@@ -2993,7 +3020,7 @@ fn test_fetch_success(subprocess: bool) {
assert_eq!(
*view.tags(),
btreemap! {
"v1.0".to_string() => new_commit_target.clone(),
"v1.0".into() => new_commit_target.clone(),
}
);
}
@@ -3017,7 +3044,7 @@ fn test_fetch_prune_deleted_ref(subprocess: bool) {
)
.unwrap();
// Test the setup
assert!(tx.repo().get_local_bookmark("main").is_present());
assert!(tx.repo().get_local_bookmark("main".as_ref()).is_present());
assert!(tx
.repo()
.get_remote_bookmark(remote_symbol("main", "origin"))
@@ -3038,7 +3065,7 @@ fn test_fetch_prune_deleted_ref(subprocess: bool) {
)
.unwrap();
assert_eq!(stats.import_stats.abandoned_commits, vec![jj_id(commit)]);
assert!(tx.repo().get_local_bookmark("main").is_absent());
assert!(tx.repo().get_local_bookmark("main".as_ref()).is_absent());
assert!(tx
.repo_mut()
.get_remote_bookmark(remote_symbol("main", "origin"))
@@ -3259,7 +3286,7 @@ fn test_push_bookmarks_success(subprocess: bool) {
let targets = GitBranchPushTargets {
branch_updates: vec![(
"main".to_owned(),
"main".into(),
BookmarkPushUpdate {
old_target: Some(setup.main_commit.id().clone()),
new_target: Some(setup.child_of_main_commit.id().clone()),
@@ -3269,7 +3296,7 @@ fn test_push_bookmarks_success(subprocess: bool) {
let result = git::push_branches(
tx.repo_mut(),
&git_settings,
"origin",
"origin".as_ref(),
&targets,
git::RemoteCallbacks::default(),
);
@@ -3332,7 +3359,7 @@ fn test_push_bookmarks_deletion(subprocess: bool) {
let targets = GitBranchPushTargets {
branch_updates: vec![(
"main".to_owned(),
"main".into(),
BookmarkPushUpdate {
old_target: Some(setup.main_commit.id().clone()),
new_target: None,
@@ -3342,7 +3369,7 @@ fn test_push_bookmarks_deletion(subprocess: bool) {
let result = git::push_branches(
tx.repo_mut(),
&git_settings,
"origin",
"origin".as_ref(),
&targets,
git::RemoteCallbacks::default(),
);
@@ -3390,14 +3417,14 @@ fn test_push_bookmarks_mixed_deletion_and_addition(subprocess: bool) {
let targets = GitBranchPushTargets {
branch_updates: vec![
(
"main".to_owned(),
"main".into(),
BookmarkPushUpdate {
old_target: Some(setup.main_commit.id().clone()),
new_target: None,
},
),
(
"topic".to_owned(),
"topic".into(),
BookmarkPushUpdate {
old_target: None,
new_target: Some(setup.child_of_main_commit.id().clone()),
@@ -3408,7 +3435,7 @@ fn test_push_bookmarks_mixed_deletion_and_addition(subprocess: bool) {
let result = git::push_branches(
tx.repo_mut(),
&git_settings,
"origin",
"origin".as_ref(),
&targets,
git::RemoteCallbacks::default(),
);
@@ -3467,7 +3494,7 @@ fn test_push_bookmarks_not_fast_forward(subprocess: bool) {
let targets = GitBranchPushTargets {
branch_updates: vec![(
"main".to_owned(),
"main".into(),
BookmarkPushUpdate {
old_target: Some(setup.main_commit.id().clone()),
new_target: Some(setup.sideways_commit.id().clone()),
@@ -3477,7 +3504,7 @@ fn test_push_bookmarks_not_fast_forward(subprocess: bool) {
let result = git::push_branches(
tx.repo_mut(),
&git_settings,
"origin",
"origin".as_ref(),
&targets,
git::RemoteCallbacks::default(),
);
@@ -3527,7 +3554,7 @@ fn test_push_updates_unexpectedly_moved_sideways_on_remote(subprocess: bool) {
git::push_updates(
setup.jj_repo.as_ref(),
&git_settings,
"origin",
"origin".as_ref(),
&targets,
git::RemoteCallbacks::default(),
)
@@ -3606,7 +3633,7 @@ fn test_push_updates_unexpectedly_moved_forward_on_remote(subprocess: bool) {
git::push_updates(
setup.jj_repo.as_ref(),
&git_settings,
"origin",
"origin".as_ref(),
&targets,
git::RemoteCallbacks::default(),
)
@@ -3684,7 +3711,7 @@ fn test_push_updates_unexpectedly_exists_on_remote(subprocess: bool) {
git::push_updates(
setup.jj_repo.as_ref(),
&git_settings,
"origin",
"origin".as_ref(),
&targets,
git::RemoteCallbacks::default(),
)
@@ -3730,7 +3757,7 @@ fn test_push_updates_success(subprocess: bool) {
let result = git::push_updates(
setup.jj_repo.as_ref(),
&git_settings,
"origin",
"origin".as_ref(),
&[GitRefUpdate {
qualified_name: "refs/heads/main".to_string(),
expected_current_target: Some(setup.main_commit.id().clone()),
@@ -3771,7 +3798,7 @@ fn test_push_updates_no_such_remote(subprocess: bool) {
let result = git::push_updates(
setup.jj_repo.as_ref(),
&git_settings,
"invalid-remote",
"invalid-remote".as_ref(),
&[GitRefUpdate {
qualified_name: "refs/heads/main".to_string(),
expected_current_target: Some(setup.main_commit.id().clone()),
@@ -3792,7 +3819,7 @@ fn test_push_updates_invalid_remote(subprocess: bool) {
let result = git::push_updates(
setup.jj_repo.as_ref(),
&git_settings,
"http://invalid-remote",
"http://invalid-remote".as_ref(),
&[GitRefUpdate {
qualified_name: "refs/heads/main".to_string(),
expected_current_target: Some(setup.main_commit.id().clone()),

View File

@@ -33,6 +33,8 @@ use jj_lib::object_id::ObjectId as _;
use jj_lib::object_id::PrefixResolution;
use jj_lib::op_store::RefTarget;
use jj_lib::op_store::RemoteRef;
use jj_lib::ref_name::RefName;
use jj_lib::ref_name::RemoteName;
use jj_lib::ref_name::RemoteRefSymbol;
use jj_lib::repo::MutableRepo;
use jj_lib::repo::ReadonlyRepo;
@@ -56,8 +58,15 @@ fn generation_number(index: &CompositeIndex, commit_id: &CommitId) -> u32 {
index.entry_by_id(commit_id).unwrap().generation_number()
}
fn remote_symbol<'a>(name: &'a str, remote: &'a str) -> RemoteRefSymbol<'a> {
RemoteRefSymbol { name, remote }
fn remote_symbol<'a, N, M>(name: &'a N, remote: &'a M) -> RemoteRefSymbol<'a>
where
N: AsRef<RefName> + ?Sized,
M: AsRef<RemoteName> + ?Sized,
{
RemoteRefSymbol {
name: name.as_ref(),
remote: remote.as_ref(),
}
}
#[test]

View File

@@ -17,6 +17,8 @@ use jj_lib::op_store::RefTarget;
use jj_lib::op_store::RemoteRef;
use jj_lib::op_store::RemoteRefState;
use jj_lib::op_store::WorkspaceId;
use jj_lib::ref_name::RefName;
use jj_lib::ref_name::RemoteName;
use jj_lib::ref_name::RemoteRefSymbol;
use jj_lib::repo::Repo as _;
use jj_lib::rewrite::RebaseOptions;
@@ -29,8 +31,15 @@ use testutils::write_random_commit;
use testutils::CommitGraphBuilder;
use testutils::TestRepo;
fn remote_symbol<'a>(name: &'a str, remote: &'a str) -> RemoteRefSymbol<'a> {
RemoteRefSymbol { name, remote }
fn remote_symbol<'a, N, M>(name: &'a N, remote: &'a M) -> RemoteRefSymbol<'a>
where
N: AsRef<RefName> + ?Sized,
M: AsRef<RemoteName> + ?Sized,
{
RemoteRefSymbol {
name: name.as_ref(),
remote: remote.as_ref(),
}
}
#[test]
@@ -205,7 +214,7 @@ fn test_edit_previous_empty_with_local_bookmark() {
)
.write()
.unwrap();
mut_repo.set_local_bookmark_target("b", RefTarget::normal(old_wc_commit.id().clone()));
mut_repo.set_local_bookmark_target("b".as_ref(), 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").unwrap();
@@ -471,7 +480,7 @@ fn test_has_changed() {
mut_repo
.set_wc_commit(ws_id.clone(), commit1.id().clone())
.unwrap();
mut_repo.set_local_bookmark_target("main", RefTarget::normal(commit1.id().clone()));
mut_repo.set_local_bookmark_target("main".as_ref(), RefTarget::normal(commit1.id().clone()));
mut_repo.set_remote_bookmark(
remote_symbol("main", "origin"),
normal_remote_ref(commit1.id()),
@@ -487,7 +496,7 @@ fn test_has_changed() {
mut_repo
.set_wc_commit(ws_id.clone(), commit1.id().clone())
.unwrap();
mut_repo.set_local_bookmark_target("main", RefTarget::normal(commit1.id().clone()));
mut_repo.set_local_bookmark_target("main".as_ref(), RefTarget::normal(commit1.id().clone()));
mut_repo.set_remote_bookmark(
remote_symbol("main", "origin"),
normal_remote_ref(commit1.id()),
@@ -495,7 +504,7 @@ fn test_has_changed() {
assert!(!mut_repo.has_changes());
mut_repo.remove_head(commit2.id());
mut_repo.set_local_bookmark_target("stable", RefTarget::absent());
mut_repo.set_local_bookmark_target("stable".as_ref(), RefTarget::absent());
mut_repo.set_remote_bookmark(remote_symbol("stable", "origin"), RemoteRef::absent());
assert!(!mut_repo.has_changes());
@@ -511,9 +520,9 @@ fn test_has_changed() {
mut_repo.set_wc_commit(ws_id, commit1.id().clone()).unwrap();
assert!(!mut_repo.has_changes());
mut_repo.set_local_bookmark_target("main", RefTarget::normal(commit2.id().clone()));
mut_repo.set_local_bookmark_target("main".as_ref(), RefTarget::normal(commit2.id().clone()));
assert!(mut_repo.has_changes());
mut_repo.set_local_bookmark_target("main", RefTarget::normal(commit1.id().clone()));
mut_repo.set_local_bookmark_target("main".as_ref(), RefTarget::normal(commit1.id().clone()));
mut_repo.remove_head(commit2.id());
assert!(!mut_repo.has_changes());
@@ -607,7 +616,7 @@ fn test_rename_remote() {
state: RemoteRefState::Tracking, // doesn't matter
};
mut_repo.set_remote_bookmark(remote_symbol("main", "origin"), remote_ref.clone());
mut_repo.rename_remote("origin", "upstream");
mut_repo.rename_remote("origin".as_ref(), "upstream".as_ref());
assert_eq!(
mut_repo.get_remote_bookmark(remote_symbol("main", "upstream")),
remote_ref
@@ -689,7 +698,8 @@ fn test_reparent_descendants() {
("child_a", &commit_child_a),
("child_b", &commit_child_b),
] {
mut_repo.set_local_bookmark_target(bookmark, RefTarget::normal(commit.id().clone()));
mut_repo
.set_local_bookmark_target(bookmark.as_ref(), RefTarget::normal(commit.id().clone()));
}
let repo = tx.commit("test").unwrap();
@@ -716,7 +726,7 @@ fn test_reparent_descendants() {
] {
let rewritten_id = repo
.view()
.get_local_bookmark(bookmark)
.get_local_bookmark(bookmark.as_ref())
.as_normal()
.unwrap()
.clone();
@@ -753,7 +763,7 @@ fn test_bookmark_hidden_commit() {
let mut tx = repo.start_transaction();
tx.repo_mut()
.set_local_bookmark_target("b", RefTarget::normal(wc_commit.id().clone()));
.set_local_bookmark_target("b".as_ref(), RefTarget::normal(wc_commit.id().clone()));
let repo = tx.commit("test").unwrap();
assert_eq!(
*repo.view().heads(),

View File

@@ -34,6 +34,8 @@ use jj_lib::op_store::RefTarget;
use jj_lib::op_store::RemoteRef;
use jj_lib::op_store::RemoteRefState;
use jj_lib::op_store::WorkspaceId;
use jj_lib::ref_name::RefName;
use jj_lib::ref_name::RemoteName;
use jj_lib::ref_name::RemoteRefSymbol;
use jj_lib::repo::Repo;
use jj_lib::repo_path::RepoPath;
@@ -62,8 +64,15 @@ use testutils::TestRepo;
use testutils::TestRepoBackend;
use testutils::TestWorkspace;
fn remote_symbol<'a>(name: &'a str, remote: &'a str) -> RemoteRefSymbol<'a> {
RemoteRefSymbol { name, remote }
fn remote_symbol<'a, N, M>(name: &'a N, remote: &'a M) -> RemoteRefSymbol<'a>
where
N: AsRef<RefName> + ?Sized,
M: AsRef<RemoteName> + ?Sized,
{
RemoteRefSymbol {
name: name.as_ref(),
remote: remote.as_ref(),
}
}
fn resolve_symbol_with_extensions(
@@ -526,35 +535,38 @@ fn test_resolve_symbol_bookmarks() {
let commit4 = write_random_commit(mut_repo);
let commit5 = write_random_commit(mut_repo);
mut_repo.set_local_bookmark_target("local", RefTarget::normal(commit1.id().clone()));
mut_repo.set_local_bookmark_target("local".as_ref(), RefTarget::normal(commit1.id().clone()));
mut_repo.set_remote_bookmark(
remote_symbol("remote", "origin"),
normal_tracking_remote_ref(commit2.id()),
);
mut_repo.set_local_bookmark_target("local-remote", RefTarget::normal(commit3.id().clone()));
mut_repo.set_local_bookmark_target(
"local-remote".as_ref(),
RefTarget::normal(commit3.id().clone()),
);
mut_repo.set_remote_bookmark(
remote_symbol("local-remote", "origin"),
normal_tracking_remote_ref(commit4.id()),
);
mut_repo.set_local_bookmark_target(
"local-remote@origin", // not a remote bookmark
"local-remote@origin".as_ref(), // not a remote bookmark
RefTarget::normal(commit5.id().clone()),
);
mut_repo.set_remote_bookmark(
remote_symbol("local-remote", "mirror"),
tracking_remote_ref(mut_repo.get_local_bookmark("local-remote")),
tracking_remote_ref(mut_repo.get_local_bookmark("local-remote".as_ref())),
);
mut_repo.set_remote_bookmark(
remote_symbol("local-remote", "untracked"),
new_remote_ref(mut_repo.get_local_bookmark("local-remote")),
new_remote_ref(mut_repo.get_local_bookmark("local-remote".as_ref())),
);
mut_repo.set_remote_bookmark(
remote_symbol("local-remote", git::REMOTE_NAME_FOR_LOCAL_GIT_REPO),
tracking_remote_ref(mut_repo.get_local_bookmark("local-remote")),
tracking_remote_ref(mut_repo.get_local_bookmark("local-remote".as_ref())),
);
mut_repo.set_local_bookmark_target(
"local-conflicted",
"local-conflicted".as_ref(),
RefTarget::from_legacy_form(
[commit1.id().clone()],
[commit3.id().clone(), commit2.id().clone()],
@@ -750,8 +762,14 @@ fn test_resolve_symbol_tags() {
let commit2 = write_random_commit(mut_repo);
let commit3 = write_random_commit(mut_repo);
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_tag_target(
"tag-bookmark".as_ref(),
RefTarget::normal(commit1.id().clone()),
);
mut_repo.set_local_bookmark_target(
"tag-bookmark".as_ref(),
RefTarget::normal(commit2.id().clone()),
);
mut_repo.set_git_ref_target(
"refs/tags/unimported",
RefTarget::normal(commit3.id().clone()),
@@ -773,8 +791,8 @@ fn test_resolve_symbol_tags() {
mut_repo
.set_wc_commit(ws_id.clone(), commit1.id().clone())
.unwrap();
mut_repo.set_tag_target("@", RefTarget::normal(commit2.id().clone()));
mut_repo.set_tag_target("root", RefTarget::normal(commit3.id().clone()));
mut_repo.set_tag_target("@".as_ref(), RefTarget::normal(commit2.id().clone()));
mut_repo.set_tag_target("root".as_ref(), RefTarget::normal(commit3.id().clone()));
assert_eq!(
resolve_symbol(mut_repo, r#""@""#).unwrap(),
vec![commit2.id().clone()]
@@ -2006,8 +2024,14 @@ fn test_evaluate_expression_bookmarks() {
// 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()));
mut_repo.set_local_bookmark_target(
"bookmark1".as_ref(),
RefTarget::normal(commit1.id().clone()),
);
mut_repo.set_local_bookmark_target(
"bookmark2".as_ref(),
RefTarget::normal(commit2.id().clone()),
);
assert_eq!(
resolve_commit_ids(mut_repo, "bookmarks()"),
vec![commit2.id().clone(), commit1.id().clone()]
@@ -2049,27 +2073,30 @@ fn test_evaluate_expression_bookmarks() {
);
// Two bookmarks pointing to the same commit does not result in a duplicate in
// the revset
mut_repo.set_local_bookmark_target("bookmark3", RefTarget::normal(commit2.id().clone()));
mut_repo.set_local_bookmark_target(
"bookmark3".as_ref(),
RefTarget::normal(commit2.id().clone()),
);
assert_eq!(
resolve_commit_ids(mut_repo, "bookmarks()"),
vec![commit2.id().clone(), commit1.id().clone()]
);
// Can get bookmarks when there are conflicted refs
mut_repo.set_local_bookmark_target(
"bookmark1",
"bookmark1".as_ref(),
RefTarget::from_legacy_form(
[commit1.id().clone()],
[commit2.id().clone(), commit3.id().clone()],
),
);
mut_repo.set_local_bookmark_target(
"bookmark2",
"bookmark2".as_ref(),
RefTarget::from_legacy_form(
[commit2.id().clone()],
[commit3.id().clone(), commit4.id().clone()],
),
);
mut_repo.set_local_bookmark_target("bookmark3", RefTarget::absent());
mut_repo.set_local_bookmark_target("bookmark3".as_ref(), RefTarget::absent());
assert_eq!(
resolve_commit_ids(mut_repo, "bookmarks()"),
vec![
@@ -2271,8 +2298,8 @@ fn test_evaluate_expression_tags() {
// Can get tags when there are none
assert_eq!(resolve_commit_ids(mut_repo, "tags()"), vec![]);
// Can get a few tags
mut_repo.set_tag_target("tag1", RefTarget::normal(commit1.id().clone()));
mut_repo.set_tag_target("tag2", RefTarget::normal(commit2.id().clone()));
mut_repo.set_tag_target("tag1".as_ref(), RefTarget::normal(commit1.id().clone()));
mut_repo.set_tag_target("tag2".as_ref(), RefTarget::normal(commit2.id().clone()));
assert_eq!(
resolve_commit_ids(mut_repo, "tags()"),
vec![commit2.id().clone(), commit1.id().clone()]
@@ -2308,27 +2335,27 @@ fn test_evaluate_expression_tags() {
assert_eq!(resolve_commit_ids(mut_repo, "tags(exact:ag1)"), vec![]);
// Two tags pointing to the same commit does not result in a duplicate in
// the revset
mut_repo.set_tag_target("tag3", RefTarget::normal(commit2.id().clone()));
mut_repo.set_tag_target("tag3".as_ref(), RefTarget::normal(commit2.id().clone()));
assert_eq!(
resolve_commit_ids(mut_repo, "tags()"),
vec![commit2.id().clone(), commit1.id().clone()]
);
// Can get tags when there are conflicted refs
mut_repo.set_tag_target(
"tag1",
"tag1".as_ref(),
RefTarget::from_legacy_form(
[commit1.id().clone()],
[commit2.id().clone(), commit3.id().clone()],
),
);
mut_repo.set_tag_target(
"tag2",
"tag2".as_ref(),
RefTarget::from_legacy_form(
[commit2.id().clone()],
[commit3.id().clone(), commit4.id().clone()],
),
);
mut_repo.set_tag_target("tag3", RefTarget::absent());
mut_repo.set_tag_target("tag3".as_ref(), RefTarget::absent());
assert_eq!(
resolve_commit_ids(mut_repo, "tags()"),
vec![
@@ -3113,8 +3140,10 @@ fn test_evaluate_expression_at_operation() {
.set_description("commit2@op1")
.write()
.unwrap();
tx.repo_mut()
.set_local_bookmark_target("commit1_ref", RefTarget::normal(commit1_op1.id().clone()));
tx.repo_mut().set_local_bookmark_target(
"commit1_ref".as_ref(),
RefTarget::normal(commit1_op1.id().clone()),
);
let repo1 = tx.commit("test").unwrap();
let mut tx = repo1.start_transaction();
@@ -3242,8 +3271,8 @@ fn test_evaluate_expression_coalesce() {
let mut graph_builder = CommitGraphBuilder::new(mut_repo);
let commit1 = graph_builder.initial_commit();
let commit2 = graph_builder.commit_with_parents(&[&commit1]);
mut_repo.set_local_bookmark_target("commit1", RefTarget::normal(commit1.id().clone()));
mut_repo.set_local_bookmark_target("commit2", RefTarget::normal(commit2.id().clone()));
mut_repo.set_local_bookmark_target("commit1".as_ref(), RefTarget::normal(commit1.id().clone()));
mut_repo.set_local_bookmark_target("commit2".as_ref(), RefTarget::normal(commit2.id().clone()));
assert_eq!(resolve_commit_ids(mut_repo, "coalesce()"), vec![]);
assert_eq!(resolve_commit_ids(mut_repo, "coalesce(none())"), vec![]);
@@ -3993,7 +4022,10 @@ fn test_no_such_revision_suggestion() {
let commit = write_random_commit(mut_repo);
for bookmark_name in ["foo", "bar", "baz"] {
mut_repo.set_local_bookmark_target(bookmark_name, RefTarget::normal(commit.id().clone()));
mut_repo.set_local_bookmark_target(
bookmark_name.as_ref(),
RefTarget::normal(commit.id().clone()),
);
}
assert_matches!(resolve_symbol(mut_repo, "bar"), Ok(_));

View File

@@ -22,6 +22,8 @@ use jj_lib::op_store::RefTarget;
use jj_lib::op_store::RemoteRef;
use jj_lib::op_store::RemoteRefState;
use jj_lib::op_store::WorkspaceId;
use jj_lib::ref_name::RefName;
use jj_lib::ref_name::RemoteName;
use jj_lib::ref_name::RemoteRefSymbol;
use jj_lib::repo::Repo as _;
use jj_lib::repo_path::RepoPath;
@@ -44,8 +46,15 @@ use testutils::write_random_commit;
use testutils::CommitGraphBuilder;
use testutils::TestRepo;
fn remote_symbol<'a>(name: &'a str, remote: &'a str) -> RemoteRefSymbol<'a> {
RemoteRefSymbol { name, remote }
fn remote_symbol<'a, N, M>(name: &'a N, remote: &'a M) -> RemoteRefSymbol<'a>
where
N: AsRef<RefName> + ?Sized,
M: AsRef<RemoteName> + ?Sized,
{
RemoteRefSymbol {
name: name.as_ref(),
remote: remote.as_ref(),
}
}
#[test]
@@ -931,14 +940,14 @@ fn test_rebase_descendants_basic_bookmark_update() {
let commit_a = graph_builder.initial_commit();
let commit_b = graph_builder.commit_with_parents(&[&commit_a]);
tx.repo_mut()
.set_local_bookmark_target("main", RefTarget::normal(commit_b.id().clone()));
.set_local_bookmark_target("main".as_ref(), RefTarget::normal(commit_b.id().clone()));
let repo = tx.commit("test").unwrap();
let mut tx = repo.start_transaction();
let commit_b2 = tx.repo_mut().rewrite_commit(&commit_b).write().unwrap();
tx.repo_mut().rebase_descendants().unwrap();
assert_eq!(
tx.repo().get_local_bookmark("main"),
tx.repo().get_local_bookmark("main".as_ref()),
RefTarget::normal(commit_b2.id().clone())
);
@@ -966,7 +975,7 @@ fn test_rebase_descendants_bookmark_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_bookmark_target("main", RefTarget::normal(commit_c.id().clone()));
.set_local_bookmark_target("main".as_ref(), RefTarget::normal(commit_c.id().clone()));
let repo = tx.commit("test").unwrap();
let mut tx = repo.start_transaction();
@@ -990,7 +999,7 @@ fn test_rebase_descendants_bookmark_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().get_local_bookmark("main"),
tx.repo().get_local_bookmark("main".as_ref()),
RefTarget::normal(commit_c3.id().clone())
);
}
@@ -1017,18 +1026,18 @@ fn test_rebase_descendants_basic_bookmark_update_with_non_local_bookmark() {
state: RemoteRefState::Tracking,
};
tx.repo_mut()
.set_local_bookmark_target("main", RefTarget::normal(commit_b.id().clone()));
.set_local_bookmark_target("main".as_ref(), RefTarget::normal(commit_b.id().clone()));
tx.repo_mut()
.set_remote_bookmark(remote_symbol("main", "origin"), commit_b_remote_ref.clone());
tx.repo_mut()
.set_tag_target("v1", RefTarget::normal(commit_b.id().clone()));
.set_tag_target("v1".as_ref(), RefTarget::normal(commit_b.id().clone()));
let repo = tx.commit("test").unwrap();
let mut tx = repo.start_transaction();
let commit_b2 = tx.repo_mut().rewrite_commit(&commit_b).write().unwrap();
tx.repo_mut().rebase_descendants().unwrap();
assert_eq!(
tx.repo().get_local_bookmark("main"),
tx.repo().get_local_bookmark("main".as_ref()),
RefTarget::normal(commit_b2.id().clone())
);
// The remote bookmark and tag should not get updated
@@ -1038,7 +1047,7 @@ fn test_rebase_descendants_basic_bookmark_update_with_non_local_bookmark() {
commit_b_remote_ref
);
assert_eq!(
tx.repo().get_tag("v1"),
tx.repo().get_tag("v1".as_ref()),
RefTarget::normal(commit_b.id().clone())
);
@@ -1071,11 +1080,11 @@ fn test_rebase_descendants_update_bookmark_after_abandon(delete_abandoned_bookma
state: RemoteRefState::Tracking,
};
tx.repo_mut()
.set_local_bookmark_target("main", RefTarget::normal(commit_b.id().clone()));
.set_local_bookmark_target("main".as_ref(), RefTarget::normal(commit_b.id().clone()));
tx.repo_mut()
.set_remote_bookmark(remote_symbol("main", "origin"), commit_b_remote_ref.clone());
tx.repo_mut()
.set_local_bookmark_target("other", RefTarget::normal(commit_c.id().clone()));
.set_local_bookmark_target("other".as_ref(), RefTarget::normal(commit_c.id().clone()));
let repo = tx.commit("test").unwrap();
let mut tx = repo.start_transaction();
@@ -1088,7 +1097,7 @@ fn test_rebase_descendants_update_bookmark_after_abandon(delete_abandoned_bookma
};
let rebase_map = rebase_descendants_with_options_return_map(tx.repo_mut(), &options);
assert_eq!(
tx.repo().get_local_bookmark("main"),
tx.repo().get_local_bookmark("main".as_ref()),
if delete_abandoned_bookmarks {
RefTarget::absent()
} else {
@@ -1102,7 +1111,7 @@ fn test_rebase_descendants_update_bookmark_after_abandon(delete_abandoned_bookma
RefTarget::normal(commit_b.id().clone())
);
assert_eq!(
tx.repo().get_local_bookmark("other"),
tx.repo().get_local_bookmark("other".as_ref()),
RefTarget::normal(rebase_map[commit_c.id()].clone())
);
@@ -1134,9 +1143,9 @@ fn test_rebase_descendants_update_bookmarks_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_bookmark_target("main", RefTarget::normal(commit_b.id().clone()));
.set_local_bookmark_target("main".as_ref(), RefTarget::normal(commit_b.id().clone()));
tx.repo_mut()
.set_local_bookmark_target("other", RefTarget::normal(commit_c.id().clone()));
.set_local_bookmark_target("other".as_ref(), RefTarget::normal(commit_c.id().clone()));
let repo = tx.commit("test").unwrap();
let mut tx = repo.start_transaction();
@@ -1176,7 +1185,7 @@ fn test_rebase_descendants_update_bookmarks_after_divergent_rewrite() {
);
tx.repo_mut().rebase_descendants().unwrap();
let main_target = tx.repo().get_local_bookmark("main");
let main_target = tx.repo().get_local_bookmark("main".as_ref());
assert!(main_target.has_conflict());
// If the bookmark were moved at each rewrite point, there would be separate
// negative terms: { commit_b => 2, commit_b4 => 1 }. Since we flatten
@@ -1195,7 +1204,7 @@ fn test_rebase_descendants_update_bookmarks_after_divergent_rewrite() {
},
);
let other_target = tx.repo().get_local_bookmark("other");
let other_target = tx.repo().get_local_bookmark("other".as_ref());
assert_eq!(other_target.as_normal(), Some(commit_c.id()));
assert_eq!(
@@ -1224,7 +1233,7 @@ fn test_rebase_descendants_rewrite_updates_bookmark_conflict() {
let commit_b = graph_builder.initial_commit();
let commit_c = graph_builder.initial_commit();
tx.repo_mut().set_local_bookmark_target(
"main",
"main".as_ref(),
RefTarget::from_legacy_form(
[commit_a.id().clone()],
[commit_b.id().clone(), commit_c.id().clone()],
@@ -1259,7 +1268,7 @@ fn test_rebase_descendants_rewrite_updates_bookmark_conflict() {
);
tx.repo_mut().rebase_descendants().unwrap();
let target = tx.repo().get_local_bookmark("main");
let target = tx.repo().get_local_bookmark("main".as_ref());
assert!(target.has_conflict());
assert_eq!(
target.removed_ids().counts(),
@@ -1304,7 +1313,7 @@ fn test_rebase_descendants_rewrite_resolves_bookmark_conflict() {
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_bookmark_target(
"main",
"main".as_ref(),
RefTarget::from_legacy_form(
[commit_a.id().clone()],
[commit_b.id().clone(), commit_c.id().clone()],
@@ -1321,7 +1330,7 @@ fn test_rebase_descendants_rewrite_resolves_bookmark_conflict() {
.unwrap();
tx.repo_mut().rebase_descendants().unwrap();
assert_eq!(
tx.repo().get_local_bookmark("main"),
tx.repo().get_local_bookmark("main".as_ref()),
RefTarget::normal(commit_b2.id().clone())
);
@@ -1352,7 +1361,7 @@ fn test_rebase_descendants_bookmark_delete_modify_abandon(delete_abandoned_bookm
let commit_a = graph_builder.initial_commit();
let commit_b = graph_builder.commit_with_parents(&[&commit_a]);
tx.repo_mut().set_local_bookmark_target(
"main",
"main".as_ref(),
RefTarget::from_legacy_form([commit_a.id().clone()], [commit_b.id().clone()]),
);
let repo = tx.commit("test").unwrap();
@@ -1366,7 +1375,10 @@ fn test_rebase_descendants_bookmark_delete_modify_abandon(delete_abandoned_bookm
..Default::default()
};
let _rebase_map = rebase_descendants_with_options_return_map(tx.repo_mut(), &options);
assert_eq!(tx.repo().get_local_bookmark("main"), RefTarget::absent());
assert_eq!(
tx.repo().get_local_bookmark("main".as_ref()),
RefTarget::absent()
);
}
#[test_case(false; "slide down abandoned")]
@@ -1389,7 +1401,7 @@ fn test_rebase_descendants_bookmark_move_forward_abandon(delete_abandoned_bookma
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_bookmark_target(
"main",
"main".as_ref(),
RefTarget::from_merge(Merge::from_vec(vec![
Some(commit_b.id().clone()),
Some(commit_a.id().clone()),
@@ -1408,7 +1420,7 @@ fn test_rebase_descendants_bookmark_move_forward_abandon(delete_abandoned_bookma
};
let _rebase_map = rebase_descendants_with_options_return_map(tx.repo_mut(), &options);
assert_eq!(
tx.repo().get_local_bookmark("main"),
tx.repo().get_local_bookmark("main".as_ref()),
if delete_abandoned_bookmarks {
RefTarget::from_merge(Merge::from_vec(vec![
None,
@@ -1441,7 +1453,7 @@ fn test_rebase_descendants_bookmark_move_sideways_abandon(delete_abandoned_bookm
let commit_b = graph_builder.initial_commit();
let commit_c = graph_builder.initial_commit();
tx.repo_mut().set_local_bookmark_target(
"main",
"main".as_ref(),
RefTarget::from_merge(Merge::from_vec(vec![
Some(commit_b.id().clone()),
Some(commit_a.id().clone()),
@@ -1460,7 +1472,7 @@ fn test_rebase_descendants_bookmark_move_sideways_abandon(delete_abandoned_bookm
};
let _rebase_map = rebase_descendants_with_options_return_map(tx.repo_mut(), &options);
assert_eq!(
tx.repo().get_local_bookmark("main"),
tx.repo().get_local_bookmark("main".as_ref()),
if delete_abandoned_bookmarks {
RefTarget::from_merge(Merge::from_vec(vec![
None,

View File

@@ -19,6 +19,8 @@ use jj_lib::op_store::RefTarget;
use jj_lib::op_store::RemoteRef;
use jj_lib::op_store::RemoteRefState;
use jj_lib::op_store::WorkspaceId;
use jj_lib::ref_name::RefName;
use jj_lib::ref_name::RemoteName;
use jj_lib::ref_name::RemoteRefSymbol;
use jj_lib::repo::Repo as _;
use maplit::btreemap;
@@ -30,8 +32,15 @@ use testutils::write_random_commit;
use testutils::CommitGraphBuilder;
use testutils::TestRepo;
fn remote_symbol<'a>(name: &'a str, remote: &'a str) -> RemoteRefSymbol<'a> {
RemoteRefSymbol { name, remote }
fn remote_symbol<'a, N, M>(name: &'a N, remote: &'a M) -> RemoteRefSymbol<'a>
where
N: AsRef<RefName> + ?Sized,
M: AsRef<RemoteName> + ?Sized,
{
RemoteRefSymbol {
name: name.as_ref(),
remote: remote.as_ref(),
}
}
#[test]
@@ -223,7 +232,7 @@ fn test_merge_views_bookmarks() {
state: RemoteRefState::Tracking,
};
mut_repo.set_local_bookmark_target(
"main",
"main".as_ref(),
RefTarget::normal(main_bookmark_local_tx0.id().clone()),
);
mut_repo.set_remote_bookmark(
@@ -236,7 +245,7 @@ fn test_merge_views_bookmarks() {
);
let feature_bookmark_local_tx0 = write_random_commit(mut_repo);
mut_repo.set_local_bookmark_target(
"feature",
"feature".as_ref(),
RefTarget::normal(feature_bookmark_local_tx0.id().clone()),
);
let repo = tx.commit("test").unwrap();
@@ -244,12 +253,12 @@ fn test_merge_views_bookmarks() {
let mut tx1 = repo.start_transaction();
let main_bookmark_local_tx1 = write_random_commit(tx1.repo_mut());
tx1.repo_mut().set_local_bookmark_target(
"main",
"main".as_ref(),
RefTarget::normal(main_bookmark_local_tx1.id().clone()),
);
let feature_bookmark_tx1 = write_random_commit(tx1.repo_mut());
tx1.repo_mut().set_local_bookmark_target(
"feature",
"feature".as_ref(),
RefTarget::normal(feature_bookmark_tx1.id().clone()),
);
@@ -261,7 +270,7 @@ fn test_merge_views_bookmarks() {
state: RemoteRefState::Tracking,
};
tx2.repo_mut().set_local_bookmark_target(
"main",
"main".as_ref(),
RefTarget::normal(main_bookmark_local_tx2.id().clone()),
);
tx2.repo_mut().set_remote_bookmark(
@@ -279,9 +288,12 @@ fn test_merge_views_bookmarks() {
],
),
remote_refs: vec![
("alternate", &main_bookmark_alternate_tx0_remote_ref),
(
"alternate".as_ref(),
&main_bookmark_alternate_tx0_remote_ref,
),
// tx1: unchanged, tx2: new -> tracking
("origin", &main_bookmark_origin_tx2_remote_ref),
("origin".as_ref(), &main_bookmark_origin_tx2_remote_ref),
],
};
let expected_feature_bookmark = BookmarkTarget {
@@ -291,8 +303,8 @@ fn test_merge_views_bookmarks() {
assert_eq!(
repo.view().bookmarks().collect::<BTreeMap<_, _>>(),
btreemap! {
"main" => expected_main_bookmark,
"feature" => expected_feature_bookmark,
"main".as_ref() => expected_main_bookmark,
"feature".as_ref() => expected_feature_bookmark,
}
);
}
@@ -307,23 +319,23 @@ fn test_merge_views_tags() {
let mut tx = repo.start_transaction();
let mut_repo = tx.repo_mut();
let v1_tx0 = write_random_commit(mut_repo);
mut_repo.set_tag_target("v1.0", RefTarget::normal(v1_tx0.id().clone()));
mut_repo.set_tag_target("v1.0".as_ref(), RefTarget::normal(v1_tx0.id().clone()));
let v2_tx0 = write_random_commit(mut_repo);
mut_repo.set_tag_target("v2.0", RefTarget::normal(v2_tx0.id().clone()));
mut_repo.set_tag_target("v2.0".as_ref(), RefTarget::normal(v2_tx0.id().clone()));
let repo = tx.commit("test").unwrap();
let mut tx1 = repo.start_transaction();
let v1_tx1 = write_random_commit(tx1.repo_mut());
tx1.repo_mut()
.set_tag_target("v1.0", RefTarget::normal(v1_tx1.id().clone()));
.set_tag_target("v1.0".as_ref(), RefTarget::normal(v1_tx1.id().clone()));
let v2_tx1 = write_random_commit(tx1.repo_mut());
tx1.repo_mut()
.set_tag_target("v2.0", RefTarget::normal(v2_tx1.id().clone()));
.set_tag_target("v2.0".as_ref(), RefTarget::normal(v2_tx1.id().clone()));
let mut tx2 = repo.start_transaction();
let v1_tx2 = write_random_commit(tx2.repo_mut());
tx2.repo_mut()
.set_tag_target("v1.0", RefTarget::normal(v1_tx2.id().clone()));
.set_tag_target("v1.0".as_ref(), RefTarget::normal(v1_tx2.id().clone()));
let repo = commit_transactions(vec![tx1, tx2]);
let expected_v1 = RefTarget::from_legacy_form(
@@ -334,8 +346,8 @@ fn test_merge_views_tags() {
assert_eq!(
repo.view().tags(),
&btreemap! {
"v1.0".to_string() => expected_v1,
"v2.0".to_string() => expected_v2,
"v1.0".into() => expected_v1,
"v2.0".into() => expected_v2,
}
);
}