just playing with tangled
1// Copyright 2020 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 std::fmt::Write as _;
16use std::path::Path;
17
18use itertools::Itertools as _;
19use jj_lib::repo_path::RepoPathBuf;
20use tracing::instrument;
21
22use super::update_sparse_patterns_with;
23use crate::cli_util::CommandHelper;
24use crate::command_error::internal_error;
25use crate::command_error::user_error_with_message;
26use crate::command_error::CommandError;
27use crate::description_util::TextEditor;
28use crate::ui::Ui;
29
30/// Start an editor to update the patterns that are present in the working copy
31#[derive(clap::Args, Clone, Debug)]
32pub struct SparseEditArgs {}
33
34#[instrument(skip_all)]
35pub fn cmd_sparse_edit(
36 ui: &mut Ui,
37 command: &CommandHelper,
38 _args: &SparseEditArgs,
39) -> Result<(), CommandError> {
40 let mut workspace_command = command.workspace_helper(ui)?;
41 let editor = workspace_command.text_editor()?;
42 update_sparse_patterns_with(ui, &mut workspace_command, |_ui, old_patterns| {
43 let mut new_patterns = edit_sparse(&editor, old_patterns)?;
44 new_patterns.sort_unstable();
45 new_patterns.dedup();
46 Ok(new_patterns)
47 })
48}
49
50fn edit_sparse(
51 editor: &TextEditor,
52 sparse: &[RepoPathBuf],
53) -> Result<Vec<RepoPathBuf>, CommandError> {
54 let mut content = String::new();
55 for sparse_path in sparse {
56 // Invalid path shouldn't block editing. Edited paths will be validated.
57 let workspace_relative_sparse_path = sparse_path.to_fs_path_unchecked(Path::new(""));
58 let path_string = workspace_relative_sparse_path.to_str().ok_or_else(|| {
59 internal_error(format!(
60 "Stored sparse path is not valid utf-8: {}",
61 workspace_relative_sparse_path.display()
62 ))
63 })?;
64 writeln!(&mut content, "{path_string}").unwrap();
65 }
66
67 let content = editor
68 .edit_str(content, Some(".jjsparse"))
69 .map_err(|err| err.with_name("sparse patterns"))?;
70
71 content
72 .lines()
73 .filter(|line| !line.starts_with("JJ:"))
74 .map(|line| line.trim())
75 .filter(|line| !line.is_empty())
76 .map(|line| {
77 RepoPathBuf::from_relative_path(line).map_err(|err| {
78 user_error_with_message(format!("Failed to parse sparse pattern: {line}"), err)
79 })
80 })
81 .try_collect()
82}