-
Notifications
You must be signed in to change notification settings - Fork 966
Expand file tree
/
Copy pathforget.rs
More file actions
127 lines (120 loc) · 4.67 KB
/
forget.rs
File metadata and controls
127 lines (120 loc) · 4.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// Copyright 2020-2023 The Jujutsu Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use clap_complete::ArgValueCandidates;
use itertools::Itertools as _;
use jj_lib::op_store::LocalRemoteRefTarget;
use jj_lib::op_store::RefTarget;
use jj_lib::op_store::RemoteRef;
use jj_lib::ref_name::RefName;
use jj_lib::repo::Repo as _;
use jj_lib::view::View;
use super::warn_unmatched_local_or_remote_bookmarks;
use crate::cli_util::CommandHelper;
use crate::cli_util::default_ignored_remote_name;
use crate::command_error::CommandError;
use crate::complete;
use crate::revset_util::parse_union_name_patterns;
use crate::ui::Ui;
/// Forget a bookmark without marking it as a deletion to be pushed
///
/// If a local bookmark is forgotten, any corresponding remote bookmarks will
/// become untracked to ensure that the forgotten bookmark will not impact
/// remotes on future pushes.
#[derive(clap::Args, Clone, Debug)]
pub struct BookmarkForgetArgs {
/// When forgetting a local bookmark, also forget any corresponding remote
/// bookmarks
///
/// A forgotten remote bookmark will not impact remotes on future pushes. It
/// will be recreated on future fetches if it still exists on the remote. If
/// there is a corresponding Git-tracking remote bookmark, it will also be
/// forgotten.
#[arg(long)]
include_remotes: bool,
/// The bookmarks to forget
///
/// By default, the specified pattern matches bookmark names with glob
/// syntax. You can also use other [string pattern syntax].
///
/// [string pattern syntax]:
/// https://docs.jj-vcs.dev/latest/revsets/#string-patterns
#[arg(required = true)]
#[arg(add = ArgValueCandidates::new(complete::bookmarks))]
names: Vec<String>,
}
pub async fn cmd_bookmark_forget(
ui: &mut Ui,
command: &CommandHelper,
args: &BookmarkForgetArgs,
) -> Result<(), CommandError> {
let mut workspace_command = command.workspace_helper(ui)?;
let repo = workspace_command.repo().clone();
let ignored_remote = default_ignored_remote_name(repo.store());
let matched_bookmarks = find_forgettable_bookmarks(ui, repo.view(), &args.names)?;
if matched_bookmarks.is_empty() {
writeln!(ui.status(), "No bookmarks to forget.")?;
return Ok(());
}
let mut tx = workspace_command.start_transaction();
let mut forgotten_remote: usize = 0;
for (name, bookmark_target) in &matched_bookmarks {
tx.repo_mut()
.set_local_bookmark_target(name, RefTarget::absent());
for (remote, _) in &bookmark_target.remote_refs {
let symbol = name.to_remote_symbol(remote);
// If `--include-remotes` is specified, we forget the corresponding remote
// bookmarks instead of untracking them
if args.include_remotes {
tx.repo_mut()
.set_remote_bookmark(symbol, RemoteRef::absent());
forgotten_remote += 1;
continue;
}
// Git-tracking remote bookmarks cannot be untracked currently, so skip them
if ignored_remote.is_some_and(|ignored| symbol.remote == ignored) {
continue;
}
tx.repo_mut().untrack_remote_bookmark(symbol);
}
}
writeln!(
ui.status(),
"Forgot {} local bookmarks.",
matched_bookmarks.len()
)?;
if forgotten_remote != 0 {
writeln!(ui.status(), "Forgot {forgotten_remote} remote bookmarks.")?;
}
let forgotten_bookmarks = matched_bookmarks
.iter()
.map(|(name, _)| name.as_symbol())
.join(", ");
tx.finish(ui, format!("forget bookmark {forgotten_bookmarks}"))
.await?;
Ok(())
}
fn find_forgettable_bookmarks<'a>(
ui: &Ui,
view: &'a View,
name_patterns: &[String],
) -> Result<Vec<(&'a RefName, LocalRemoteRefTarget<'a>)>, CommandError> {
let name_expr = parse_union_name_patterns(ui, name_patterns)?;
let name_matcher = name_expr.to_matcher();
let matched_bookmarks = view
.bookmarks()
.filter(|(name, _)| name_matcher.is_match(name.as_str()))
.collect();
warn_unmatched_local_or_remote_bookmarks(ui, view, &name_expr)?;
Ok(matched_bookmarks)
}