ok/jj
1
0
Fork 0
forked from mirrors/jj

commands: move untrack code to untrack.rs

This commit is contained in:
Antoine Cezar 2023-11-02 21:10:38 +01:00 committed by Antoine Cezar
parent 9d72fa2a51
commit 04eddc666c
2 changed files with 112 additions and 88 deletions

View file

@ -50,6 +50,7 @@ mod split;
mod squash;
mod status;
mod unsquash;
mod untrack;
mod util;
use std::fmt::Debug;
@ -62,19 +63,17 @@ use jj_lib::backend::ObjectId;
use jj_lib::commit::Commit;
use jj_lib::file_util;
use jj_lib::matchers::EverythingMatcher;
use jj_lib::merge::Merge;
use jj_lib::merged_tree::{MergedTree, MergedTreeBuilder};
use jj_lib::merged_tree::MergedTree;
use jj_lib::op_store::WorkspaceId;
use jj_lib::repo::{ReadonlyRepo, Repo};
use jj_lib::rewrite::merge_commit_trees;
use jj_lib::settings::UserSettings;
use jj_lib::working_copy::SnapshotOptions;
use jj_lib::workspace::{default_working_copy_initializer, Workspace};
use tracing::instrument;
use crate::cli_util::{
check_stale_working_copy, print_checkout_stats, run_ui_editor, user_error,
user_error_with_hint, Args, CommandError, CommandHelper, RevisionArg, WorkspaceCommandHelper,
check_stale_working_copy, print_checkout_stats, run_ui_editor, user_error, Args, CommandError,
CommandHelper, RevisionArg, WorkspaceCommandHelper,
};
use crate::diff_util::{self, DiffFormat};
use crate::formatter::{Formatter, PlainTextFormatter};
@ -145,7 +144,7 @@ enum Commands {
/// Undo an operation (shortcut for `jj op undo`)
Undo(operation::OperationUndoArgs),
Unsquash(unsquash::UnsquashArgs),
Untrack(UntrackArgs),
Untrack(untrack::UntrackArgs),
Version(VersionArgs),
#[command(subcommand)]
Workspace(WorkspaceCommands),
@ -155,14 +154,6 @@ enum Commands {
#[derive(clap::Args, Clone, Debug)]
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
///
/// Workspaces let you add additional working copies attached to the same repo.
@ -234,79 +225,6 @@ fn cmd_version(
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(
ui: &Ui,
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::Config(sub_args) => config::cmd_config(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::Cat(sub_args) => cat::cmd_cat(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
View 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(())
}