jj_cli/commands/bookmark/
untrack.rs

1// Copyright 2020-2023 The Jujutsu Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use clap_complete::ArgValueCandidates;
16use itertools::Itertools as _;
17use jj_lib::repo::Repo as _;
18
19use super::find_trackable_remote_bookmarks;
20use crate::cli_util::CommandHelper;
21use crate::cli_util::RemoteBookmarkNamePattern;
22use crate::cli_util::default_ignored_remote_name;
23use crate::command_error::CommandError;
24use crate::complete;
25use crate::ui::Ui;
26
27/// Stop tracking given remote bookmarks
28///
29/// A non-tracking remote bookmark is just a pointer to the last-fetched remote
30/// bookmark. It won't be imported as a local bookmark on future pulls.
31///
32/// If you want to forget a local bookmark while also untracking the
33/// corresponding remote bookmarks, use `jj bookmark forget` instead.
34#[derive(clap::Args, Clone, Debug)]
35pub struct BookmarkUntrackArgs {
36    /// Remote bookmarks to untrack
37    ///
38    /// By default, the specified name matches exactly. Use `glob:` prefix to
39    /// select bookmarks by [wildcard pattern].
40    ///
41    /// Examples: bookmark@remote, glob:main@*, glob:jjfan-*@upstream
42    ///
43    /// [wildcard pattern]:
44    ///     https://jj-vcs.github.io/jj/latest/revsets/#string-patterns
45    #[arg(
46        required = true,
47        value_name = "BOOKMARK@REMOTE",
48        add = ArgValueCandidates::new(complete::tracked_bookmarks)
49    )]
50    names: Vec<RemoteBookmarkNamePattern>,
51}
52
53pub fn cmd_bookmark_untrack(
54    ui: &mut Ui,
55    command: &CommandHelper,
56    args: &BookmarkUntrackArgs,
57) -> Result<(), CommandError> {
58    let mut workspace_command = command.workspace_helper(ui)?;
59    let repo = workspace_command.repo().clone();
60    let ignored_remote = default_ignored_remote_name(repo.store());
61    let mut symbols = Vec::new();
62    for (symbol, remote_ref) in find_trackable_remote_bookmarks(repo.view(), &args.names)? {
63        if ignored_remote.is_some_and(|ignored| symbol.remote == ignored) {
64            // This restriction can be lifted if we want to support untracked @git
65            // bookmarks.
66            writeln!(
67                ui.warning_default(),
68                "Git-tracking bookmark cannot be untracked: {symbol}"
69            )?;
70        } else if !remote_ref.is_tracked() {
71            writeln!(
72                ui.warning_default(),
73                "Remote bookmark not tracked yet: {symbol}"
74            )?;
75        } else {
76            symbols.push(symbol);
77        }
78    }
79    let mut tx = workspace_command.start_transaction();
80    for &symbol in &symbols {
81        tx.repo_mut().untrack_remote_bookmark(symbol);
82    }
83    if !symbols.is_empty() {
84        writeln!(
85            ui.status(),
86            "Stopped tracking {} remote bookmarks.",
87            symbols.len()
88        )?;
89    }
90    tx.finish(
91        ui,
92        format!("untrack remote bookmark {}", symbols.iter().join(", ")),
93    )?;
94    Ok(())
95}