forked from mirrors/jj
commands: move untrack code to untrack.rs
This commit is contained in:
parent
9d72fa2a51
commit
04eddc666c
2 changed files with 112 additions and 88 deletions
|
@ -50,6 +50,7 @@ mod split;
|
||||||
mod squash;
|
mod squash;
|
||||||
mod status;
|
mod status;
|
||||||
mod unsquash;
|
mod unsquash;
|
||||||
|
mod untrack;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
@ -62,19 +63,17 @@ use jj_lib::backend::ObjectId;
|
||||||
use jj_lib::commit::Commit;
|
use jj_lib::commit::Commit;
|
||||||
use jj_lib::file_util;
|
use jj_lib::file_util;
|
||||||
use jj_lib::matchers::EverythingMatcher;
|
use jj_lib::matchers::EverythingMatcher;
|
||||||
use jj_lib::merge::Merge;
|
use jj_lib::merged_tree::MergedTree;
|
||||||
use jj_lib::merged_tree::{MergedTree, MergedTreeBuilder};
|
|
||||||
use jj_lib::op_store::WorkspaceId;
|
use jj_lib::op_store::WorkspaceId;
|
||||||
use jj_lib::repo::{ReadonlyRepo, Repo};
|
use jj_lib::repo::{ReadonlyRepo, Repo};
|
||||||
use jj_lib::rewrite::merge_commit_trees;
|
use jj_lib::rewrite::merge_commit_trees;
|
||||||
use jj_lib::settings::UserSettings;
|
use jj_lib::settings::UserSettings;
|
||||||
use jj_lib::working_copy::SnapshotOptions;
|
|
||||||
use jj_lib::workspace::{default_working_copy_initializer, Workspace};
|
use jj_lib::workspace::{default_working_copy_initializer, Workspace};
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
use crate::cli_util::{
|
use crate::cli_util::{
|
||||||
check_stale_working_copy, print_checkout_stats, run_ui_editor, user_error,
|
check_stale_working_copy, print_checkout_stats, run_ui_editor, user_error, Args, CommandError,
|
||||||
user_error_with_hint, Args, CommandError, CommandHelper, RevisionArg, WorkspaceCommandHelper,
|
CommandHelper, RevisionArg, WorkspaceCommandHelper,
|
||||||
};
|
};
|
||||||
use crate::diff_util::{self, DiffFormat};
|
use crate::diff_util::{self, DiffFormat};
|
||||||
use crate::formatter::{Formatter, PlainTextFormatter};
|
use crate::formatter::{Formatter, PlainTextFormatter};
|
||||||
|
@ -145,7 +144,7 @@ enum Commands {
|
||||||
/// Undo an operation (shortcut for `jj op undo`)
|
/// Undo an operation (shortcut for `jj op undo`)
|
||||||
Undo(operation::OperationUndoArgs),
|
Undo(operation::OperationUndoArgs),
|
||||||
Unsquash(unsquash::UnsquashArgs),
|
Unsquash(unsquash::UnsquashArgs),
|
||||||
Untrack(UntrackArgs),
|
Untrack(untrack::UntrackArgs),
|
||||||
Version(VersionArgs),
|
Version(VersionArgs),
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
Workspace(WorkspaceCommands),
|
Workspace(WorkspaceCommands),
|
||||||
|
@ -155,14 +154,6 @@ enum Commands {
|
||||||
#[derive(clap::Args, Clone, Debug)]
|
#[derive(clap::Args, Clone, Debug)]
|
||||||
struct VersionArgs {}
|
struct VersionArgs {}
|
||||||
|
|
||||||
/// Stop tracking specified paths in the working copy
|
|
||||||
#[derive(clap::Args, Clone, Debug)]
|
|
||||||
struct UntrackArgs {
|
|
||||||
/// Paths to untrack
|
|
||||||
#[arg(required = true, value_hint = clap::ValueHint::AnyPath)]
|
|
||||||
paths: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Commands for working with workspaces
|
/// Commands for working with workspaces
|
||||||
///
|
///
|
||||||
/// Workspaces let you add additional working copies attached to the same repo.
|
/// Workspaces let you add additional working copies attached to the same repo.
|
||||||
|
@ -234,79 +225,6 @@ fn cmd_version(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip_all)]
|
|
||||||
fn cmd_untrack(
|
|
||||||
ui: &mut Ui,
|
|
||||||
command: &CommandHelper,
|
|
||||||
args: &UntrackArgs,
|
|
||||||
) -> Result<(), CommandError> {
|
|
||||||
let mut workspace_command = command.workspace_helper(ui)?;
|
|
||||||
let store = workspace_command.repo().store().clone();
|
|
||||||
let matcher = workspace_command.matcher_from_values(&args.paths)?;
|
|
||||||
|
|
||||||
let mut tx = workspace_command
|
|
||||||
.start_transaction("untrack paths")
|
|
||||||
.into_inner();
|
|
||||||
let base_ignores = workspace_command.base_ignores();
|
|
||||||
let (mut locked_ws, wc_commit) = workspace_command.start_working_copy_mutation()?;
|
|
||||||
// Create a new tree without the unwanted files
|
|
||||||
let mut tree_builder = MergedTreeBuilder::new(wc_commit.tree_id().clone());
|
|
||||||
let wc_tree = wc_commit.tree()?;
|
|
||||||
for (path, _value) in wc_tree.entries_matching(matcher.as_ref()) {
|
|
||||||
tree_builder.set_or_remove(path, Merge::absent());
|
|
||||||
}
|
|
||||||
let new_tree_id = tree_builder.write_tree(&store)?;
|
|
||||||
let new_tree = store.get_root_tree(&new_tree_id)?;
|
|
||||||
// Reset the working copy to the new tree
|
|
||||||
locked_ws.locked_wc().reset(&new_tree)?;
|
|
||||||
// Commit the working copy again so we can inform the user if paths couldn't be
|
|
||||||
// untracked because they're not ignored.
|
|
||||||
let wc_tree_id = locked_ws.locked_wc().snapshot(SnapshotOptions {
|
|
||||||
base_ignores,
|
|
||||||
fsmonitor_kind: command.settings().fsmonitor_kind()?,
|
|
||||||
progress: None,
|
|
||||||
max_new_file_size: command.settings().max_new_file_size()?,
|
|
||||||
})?;
|
|
||||||
if wc_tree_id != new_tree_id {
|
|
||||||
let wc_tree = store.get_root_tree(&wc_tree_id)?;
|
|
||||||
let added_back = wc_tree.entries_matching(matcher.as_ref()).collect_vec();
|
|
||||||
if !added_back.is_empty() {
|
|
||||||
drop(locked_ws);
|
|
||||||
let path = &added_back[0].0;
|
|
||||||
let ui_path = workspace_command.format_file_path(path);
|
|
||||||
let message = if added_back.len() > 1 {
|
|
||||||
format!(
|
|
||||||
"'{}' and {} other files are not ignored.",
|
|
||||||
ui_path,
|
|
||||||
added_back.len() - 1
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
format!("'{ui_path}' is not ignored.")
|
|
||||||
};
|
|
||||||
return Err(user_error_with_hint(
|
|
||||||
message,
|
|
||||||
"Files that are not ignored will be added back by the next command.
|
|
||||||
Make sure they're ignored, then try again.",
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
// This means there were some concurrent changes made in the working copy. We
|
|
||||||
// don't want to mix those in, so reset the working copy again.
|
|
||||||
locked_ws.locked_wc().reset(&new_tree)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tx.mut_repo()
|
|
||||||
.rewrite_commit(command.settings(), &wc_commit)
|
|
||||||
.set_tree_id(new_tree_id)
|
|
||||||
.write()?;
|
|
||||||
let num_rebased = tx.mut_repo().rebase_descendants(command.settings())?;
|
|
||||||
if num_rebased > 0 {
|
|
||||||
writeln!(ui.stderr(), "Rebased {num_rebased} descendant commits")?;
|
|
||||||
}
|
|
||||||
let repo = tx.commit();
|
|
||||||
locked_ws.finish(repo.op_id().clone())?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn show_predecessor_patch(
|
fn show_predecessor_patch(
|
||||||
ui: &Ui,
|
ui: &Ui,
|
||||||
formatter: &mut dyn Formatter,
|
formatter: &mut dyn Formatter,
|
||||||
|
@ -715,7 +633,7 @@ pub fn run_command(ui: &mut Ui, command_helper: &CommandHelper) -> Result<(), Co
|
||||||
Commands::Init(sub_args) => init::cmd_init(ui, command_helper, sub_args),
|
Commands::Init(sub_args) => init::cmd_init(ui, command_helper, sub_args),
|
||||||
Commands::Config(sub_args) => config::cmd_config(ui, command_helper, sub_args),
|
Commands::Config(sub_args) => config::cmd_config(ui, command_helper, sub_args),
|
||||||
Commands::Checkout(sub_args) => checkout::cmd_checkout(ui, command_helper, sub_args),
|
Commands::Checkout(sub_args) => checkout::cmd_checkout(ui, command_helper, sub_args),
|
||||||
Commands::Untrack(sub_args) => cmd_untrack(ui, command_helper, sub_args),
|
Commands::Untrack(sub_args) => untrack::cmd_untrack(ui, command_helper, sub_args),
|
||||||
Commands::Files(sub_args) => files::cmd_files(ui, command_helper, sub_args),
|
Commands::Files(sub_args) => files::cmd_files(ui, command_helper, sub_args),
|
||||||
Commands::Cat(sub_args) => cat::cmd_cat(ui, command_helper, sub_args),
|
Commands::Cat(sub_args) => cat::cmd_cat(ui, command_helper, sub_args),
|
||||||
Commands::Diff(sub_args) => diff::cmd_diff(ui, command_helper, sub_args),
|
Commands::Diff(sub_args) => diff::cmd_diff(ui, command_helper, sub_args),
|
||||||
|
|
106
cli/src/commands/untrack.rs
Normal file
106
cli/src/commands/untrack.rs
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
// Copyright 2020 The Jujutsu Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
use itertools::Itertools;
|
||||||
|
use jj_lib::merge::Merge;
|
||||||
|
use jj_lib::merged_tree::MergedTreeBuilder;
|
||||||
|
use jj_lib::repo::Repo;
|
||||||
|
use jj_lib::working_copy::SnapshotOptions;
|
||||||
|
use tracing::instrument;
|
||||||
|
|
||||||
|
use crate::cli_util::{user_error_with_hint, CommandError, CommandHelper};
|
||||||
|
use crate::ui::Ui;
|
||||||
|
|
||||||
|
/// Stop tracking specified paths in the working copy
|
||||||
|
#[derive(clap::Args, Clone, Debug)]
|
||||||
|
pub(crate) struct UntrackArgs {
|
||||||
|
/// Paths to untrack
|
||||||
|
#[arg(required = true, value_hint = clap::ValueHint::AnyPath)]
|
||||||
|
paths: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(skip_all)]
|
||||||
|
pub(crate) fn cmd_untrack(
|
||||||
|
ui: &mut Ui,
|
||||||
|
command: &CommandHelper,
|
||||||
|
args: &UntrackArgs,
|
||||||
|
) -> Result<(), CommandError> {
|
||||||
|
let mut workspace_command = command.workspace_helper(ui)?;
|
||||||
|
let store = workspace_command.repo().store().clone();
|
||||||
|
let matcher = workspace_command.matcher_from_values(&args.paths)?;
|
||||||
|
|
||||||
|
let mut tx = workspace_command
|
||||||
|
.start_transaction("untrack paths")
|
||||||
|
.into_inner();
|
||||||
|
let base_ignores = workspace_command.base_ignores();
|
||||||
|
let (mut locked_ws, wc_commit) = workspace_command.start_working_copy_mutation()?;
|
||||||
|
// Create a new tree without the unwanted files
|
||||||
|
let mut tree_builder = MergedTreeBuilder::new(wc_commit.tree_id().clone());
|
||||||
|
let wc_tree = wc_commit.tree()?;
|
||||||
|
for (path, _value) in wc_tree.entries_matching(matcher.as_ref()) {
|
||||||
|
tree_builder.set_or_remove(path, Merge::absent());
|
||||||
|
}
|
||||||
|
let new_tree_id = tree_builder.write_tree(&store)?;
|
||||||
|
let new_tree = store.get_root_tree(&new_tree_id)?;
|
||||||
|
// Reset the working copy to the new tree
|
||||||
|
locked_ws.locked_wc().reset(&new_tree)?;
|
||||||
|
// Commit the working copy again so we can inform the user if paths couldn't be
|
||||||
|
// untracked because they're not ignored.
|
||||||
|
let wc_tree_id = locked_ws.locked_wc().snapshot(SnapshotOptions {
|
||||||
|
base_ignores,
|
||||||
|
fsmonitor_kind: command.settings().fsmonitor_kind()?,
|
||||||
|
progress: None,
|
||||||
|
max_new_file_size: command.settings().max_new_file_size()?,
|
||||||
|
})?;
|
||||||
|
if wc_tree_id != new_tree_id {
|
||||||
|
let wc_tree = store.get_root_tree(&wc_tree_id)?;
|
||||||
|
let added_back = wc_tree.entries_matching(matcher.as_ref()).collect_vec();
|
||||||
|
if !added_back.is_empty() {
|
||||||
|
drop(locked_ws);
|
||||||
|
let path = &added_back[0].0;
|
||||||
|
let ui_path = workspace_command.format_file_path(path);
|
||||||
|
let message = if added_back.len() > 1 {
|
||||||
|
format!(
|
||||||
|
"'{}' and {} other files are not ignored.",
|
||||||
|
ui_path,
|
||||||
|
added_back.len() - 1
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
format!("'{ui_path}' is not ignored.")
|
||||||
|
};
|
||||||
|
return Err(user_error_with_hint(
|
||||||
|
message,
|
||||||
|
"Files that are not ignored will be added back by the next command.
|
||||||
|
Make sure they're ignored, then try again.",
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
// This means there were some concurrent changes made in the working copy. We
|
||||||
|
// don't want to mix those in, so reset the working copy again.
|
||||||
|
locked_ws.locked_wc().reset(&new_tree)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tx.mut_repo()
|
||||||
|
.rewrite_commit(command.settings(), &wc_commit)
|
||||||
|
.set_tree_id(new_tree_id)
|
||||||
|
.write()?;
|
||||||
|
let num_rebased = tx.mut_repo().rebase_descendants(command.settings())?;
|
||||||
|
if num_rebased > 0 {
|
||||||
|
writeln!(ui.stderr(), "Rebased {num_rebased} descendant commits")?;
|
||||||
|
}
|
||||||
|
let repo = tx.commit();
|
||||||
|
locked_ws.finish(repo.op_id().clone())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Reference in a new issue