Skip to content

Commit

Permalink
cli: make paths to auto-track configurable, add jj track
Browse files Browse the repository at this point in the history
  • Loading branch information
martinvonz committed Aug 25, 2024
1 parent b78c83e commit ef7c4a8
Show file tree
Hide file tree
Showing 10 changed files with 139 additions and 1 deletion.
15 changes: 15 additions & 0 deletions cli/src/cli_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ use jj_lib::gitignore::GitIgnoreError;
use jj_lib::gitignore::GitIgnoreFile;
use jj_lib::hex_util::to_reverse_hex;
use jj_lib::id_prefix::IdPrefixContext;
use jj_lib::matchers::EverythingMatcher;
use jj_lib::matchers::Matcher;
use jj_lib::merge::MergedTreeValue;
use jj_lib::merged_tree::MergedTree;
Expand Down Expand Up @@ -856,6 +857,18 @@ impl WorkspaceCommandHelper {
Ok(FilesetExpression::union_all(expressions))
}

pub fn auto_tracking_matcher(&self) -> Result<Box<dyn Matcher>, CommandError> {
let pattern = self.settings.config().get_string("snapshot.auto-track")?;
// This special case is to support users who have disabled filesets
// TODO: once we delete allow-filesets, we can default to "all()" in misc.toml
// and drop this special case
if pattern.is_empty() {
return Ok(Box::new(EverythingMatcher));
}
let expression = self.parse_file_patterns(&[pattern])?;
Ok(expression.to_matcher())
}

pub(crate) fn path_converter(&self) -> &RepoPathUiConverter {
&self.path_converter
}
Expand Down Expand Up @@ -1289,6 +1302,7 @@ impl WorkspaceCommandHelper {
return Ok(());
};
let base_ignores = self.base_ignores()?;
let auto_tracking_matcher = self.auto_tracking_matcher()?;

// Compare working-copy tree and operation with repo's, and reload as needed.
let mut locked_ws = self.workspace.start_working_copy_mutation()?;
Expand Down Expand Up @@ -1341,6 +1355,7 @@ See https://github.com/martinvonz/jj/blob/main/docs/working-copy.md#stale-workin
base_ignores,
fsmonitor_settings: self.settings.fsmonitor_settings()?,
progress: progress.as_ref().map(|x| x as _),
start_tracking_matcher: &auto_tracking_matcher,
max_new_file_size: self.settings.max_new_file_size()?,
})?;
drop(progress);
Expand Down
3 changes: 3 additions & 0 deletions cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ mod split;
mod squash;
mod status;
mod tag;
mod track;
mod unsquash;
mod untrack;
mod util;
Expand Down Expand Up @@ -147,6 +148,7 @@ enum Command {
Status(status::StatusArgs),
#[command(subcommand)]
Tag(tag::TagCommand),
Track(track::TrackArgs),
#[command(subcommand)]
Util(util::UtilCommand),
/// Undo an operation (shortcut for `jj op undo`)
Expand Down Expand Up @@ -216,6 +218,7 @@ pub fn run_command(ui: &mut Ui, command_helper: &CommandHelper) -> Result<(), Co
Command::Squash(args) => squash::cmd_squash(ui, command_helper, args),
Command::Status(args) => status::cmd_status(ui, command_helper, args),
Command::Tag(args) => tag::cmd_tag(ui, command_helper, args),
Command::Track(args) => track::cmd_track(ui, command_helper, args),
Command::Undo(args) => operation::undo::cmd_op_undo(ui, command_helper, args),
Command::Unsquash(args) => unsquash::cmd_unsquash(ui, command_helper, args),
Command::Untrack(args) => untrack::cmd_untrack(ui, command_helper, args),
Expand Down
65 changes: 65 additions & 0 deletions cli/src/commands/track.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// 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 jj_lib::working_copy::SnapshotOptions;
use tracing::instrument;

use crate::cli_util::CommandHelper;
use crate::command_error::CommandError;
use crate::ui::Ui;

/// Start tracking specified paths in the working copy
///
/// By default, all paths are automatically tracked. This command is not useful
/// then. You can configure which paths to automatically track by setting e.g.
/// `snapshot.auto-track = 'none()'`. You will then need to run this command to
/// start tracking new files.
#[derive(clap::Args, Clone, Debug)]
pub(crate) struct TrackArgs {
/// Paths to track.
#[arg(required = true, value_hint = clap::ValueHint::AnyPath)]
paths: Vec<String>,
}

#[instrument(skip_all)]
pub(crate) fn cmd_track(
ui: &mut Ui,
command: &CommandHelper,
args: &TrackArgs,
) -> Result<(), CommandError> {
let mut workspace_command = command.workspace_helper(ui)?;
let matcher = workspace_command
.parse_file_patterns(&args.paths)?
.to_matcher();

let mut tx = workspace_command.start_transaction().into_inner();
let base_ignores = workspace_command.base_ignores()?;
let (mut locked_ws, _wc_commit) = workspace_command.start_working_copy_mutation()?;
locked_ws.locked_wc().snapshot(SnapshotOptions {
base_ignores,
fsmonitor_settings: command.settings().fsmonitor_settings()?,
progress: None,
start_tracking_matcher: &matcher,
max_new_file_size: command.settings().max_new_file_size()?,
})?;
let num_rebased = tx.mut_repo().rebase_descendants(command.settings())?;
if num_rebased > 0 {
writeln!(ui.status(), "Rebased {num_rebased} descendant commits")?;
}
let repo = tx.commit("track paths");
locked_ws.finish(repo.op_id().clone())?;
Ok(())
}
2 changes: 2 additions & 0 deletions cli/src/commands/untrack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ pub(crate) fn cmd_untrack(

let mut tx = workspace_command.start_transaction().into_inner();
let base_ignores = workspace_command.base_ignores()?;
let auto_tracking_matcher = workspace_command.auto_tracking_matcher()?;
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());
Expand All @@ -72,6 +73,7 @@ pub(crate) fn cmd_untrack(
base_ignores,
fsmonitor_settings: command.settings().fsmonitor_settings()?,
progress: None,
start_tracking_matcher: &auto_tracking_matcher,
max_new_file_size: command.settings().max_new_file_size()?,
})?;
if wc_tree_id != *new_commit.tree_id() {
Expand Down
2 changes: 2 additions & 0 deletions cli/src/config/misc.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,5 @@ edit = false

[snapshot]
max-new-file-size = "1MiB"
# TODO: once we delete allow-filesets, this can default to the clearer "all()"
auto-track = ""
2 changes: 2 additions & 0 deletions cli/src/merge_tools/diff_working_copies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use jj_lib::fsmonitor::FsmonitorSettings;
use jj_lib::gitignore::GitIgnoreFile;
use jj_lib::local_working_copy::TreeState;
use jj_lib::local_working_copy::TreeStateError;
use jj_lib::matchers::EverythingMatcher;
use jj_lib::matchers::Matcher;
use jj_lib::merged_tree::MergedTree;
use jj_lib::merged_tree::TreeDiffEntry;
Expand Down Expand Up @@ -286,6 +287,7 @@ diff editing in mind and be a little inaccurate.
base_ignores,
fsmonitor_settings: FsmonitorSettings::None,
progress: None,
start_tracking_matcher: &EverythingMatcher,
max_new_file_size: u64::MAX,
})?;
Ok(output_tree_state.current_tree_id().clone())
Expand Down
1 change: 1 addition & 0 deletions cli/tests/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ mod test_squash_command;
mod test_status_command;
mod test_tag_command;
mod test_templater;
mod test_track_command;
mod test_undo;
mod test_unsquash_command;
mod test_untrack_command;
Expand Down
35 changes: 35 additions & 0 deletions cli/tests/test_track_command.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2024 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 crate::common::TestEnvironment;

#[test]
fn test_track() {
let test_env = TestEnvironment::default();
test_env.add_config(r#"snapshot.auto-track = 'none()'"#);
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
let repo_path = test_env.env_root().join("repo");

std::fs::write(repo_path.join("file1"), "initial").unwrap();
std::fs::write(repo_path.join("file2"), "initial").unwrap();

let stdout = test_env.jj_cmd_success(&repo_path, &["file", "list"]);
insta::assert_snapshot!(stdout, @"");
let stdout = test_env.jj_cmd_success(&repo_path, &["track", "file2"]);
insta::assert_snapshot!(stdout, @"");
let stdout = test_env.jj_cmd_success(&repo_path, &["file", "list"]);
insta::assert_snapshot!(stdout, @r###"
file2
"###);
}
9 changes: 8 additions & 1 deletion lib/src/local_working_copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,7 @@ impl TreeState {
base_ignores,
fsmonitor_settings,
progress,
start_tracking_matcher,
max_new_file_size,
} = options;

Expand Down Expand Up @@ -835,6 +836,7 @@ impl TreeState {
};
self.visit_directory(
&matcher,
start_tracking_matcher,
&current_tree,
tree_entries_tx,
file_states_tx,
Expand Down Expand Up @@ -908,6 +910,7 @@ impl TreeState {
fn visit_directory(
&self,
matcher: &dyn Matcher,
start_tracking_matcher: &dyn Matcher,
current_tree: &MergedTree,
tree_entries_tx: Sender<(RepoPathBuf, MergedTreeValue)>,
file_states_tx: Sender<(RepoPathBuf, FileState)>,
Expand Down Expand Up @@ -1017,6 +1020,7 @@ impl TreeState {
};
self.visit_directory(
matcher,
start_tracking_matcher,
current_tree,
tree_entries_tx.clone(),
file_states_tx.clone(),
Expand Down Expand Up @@ -1049,7 +1053,10 @@ impl TreeState {
max_size: HumanByteSize(max_new_file_size),
});
}
if let Some(new_file_state) = file_state(&metadata) {
if maybe_current_file_state.is_none() && !start_tracking_matcher.matches(&path) {
// Leave untracked
// TODO: Report this path to the caller
} else if let Some(new_file_state) = file_state(&metadata) {
present_files_tx.send(path.clone()).ok();
let update = self.get_updated_tree_value(
&path,
Expand Down
6 changes: 6 additions & 0 deletions lib/src/working_copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ use crate::commit::Commit;
use crate::fsmonitor::FsmonitorSettings;
use crate::gitignore::GitIgnoreError;
use crate::gitignore::GitIgnoreFile;
use crate::matchers::EverythingMatcher;
use crate::matchers::Matcher;
use crate::op_store::OperationId;
use crate::op_store::WorkspaceId;
use crate::repo_path::RepoPath;
Expand Down Expand Up @@ -193,6 +195,9 @@ pub struct SnapshotOptions<'a> {
pub fsmonitor_settings: FsmonitorSettings,
/// A callback for the UI to display progress.
pub progress: Option<&'a SnapshotProgress<'a>>,
/// For new files that are not already tracked, start tracking them if they
/// match this.
pub start_tracking_matcher: &'a dyn Matcher,
/// The size of the largest file that should be allowed to become tracked
/// (already tracked files are always snapshotted). If there are larger
/// files in the working copy, then `LockedWorkingCopy::snapshot()` may
Expand All @@ -208,6 +213,7 @@ impl SnapshotOptions<'_> {
base_ignores: GitIgnoreFile::empty(),
fsmonitor_settings: FsmonitorSettings::None,
progress: None,
start_tracking_matcher: &EverythingMatcher,
max_new_file_size: u64::MAX,
}
}
Expand Down

0 comments on commit ef7c4a8

Please sign in to comment.