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

cli: extract function that prints multiple file contents

Prepares for migrating to the matcher API. "Path exists but is not a file"
error is turned into a warning because the loop shouldn't terminate there.

"No such path" error message is also updated for consistency.
This commit is contained in:
Yuya Nishihara 2024-04-09 23:00:24 +09:00
parent 7bed5dd222
commit ac794e560f
2 changed files with 43 additions and 24 deletions

View file

@ -12,14 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use std::io::Write;
use std::io::{self, Write};
use jj_lib::conflicts::{materialize_tree_value, MaterializedTreeValue};
use jj_lib::merge::MergedTreeValue;
use jj_lib::repo::Repo;
use jj_lib::repo_path::RepoPath;
use pollster::FutureExt;
use tracing::instrument;
use crate::cli_util::{CommandHelper, RevisionArg};
use crate::cli_util::{CommandHelper, RevisionArg, WorkspaceCommandHelper};
use crate::command_error::{user_error, CommandError};
use crate::ui::Ui;
@ -45,25 +47,41 @@ pub(crate) fn cmd_cat(
let tree = commit.tree()?;
// TODO: migrate to .parse_file_patterns()?.to_matcher()?
let path = workspace_command.parse_file_path(&args.path)?;
let repo = workspace_command.repo();
let value = tree.path_value(&path);
let materialized = materialize_tree_value(repo.store(), &path, value).block_on()?;
match materialized {
MaterializedTreeValue::Absent => {
return Err(user_error("No such path"));
}
MaterializedTreeValue::File { mut reader, .. } => {
ui.request_pager();
std::io::copy(&mut reader, &mut ui.stdout_formatter().as_mut())?;
}
MaterializedTreeValue::Conflict { contents, .. } => {
ui.request_pager();
ui.stdout_formatter().write_all(&contents)?;
}
MaterializedTreeValue::Symlink { .. }
| MaterializedTreeValue::Tree(_)
| MaterializedTreeValue::GitSubmodule(_) => {
return Err(user_error("Path exists but is not a file"));
if value.is_absent() {
let ui_path = workspace_command.format_file_path(&path);
return Err(user_error(format!("No such path: {ui_path}")));
}
ui.request_pager();
write_tree_entries(ui, &workspace_command, [(&path, value)])?;
Ok(())
}
fn write_tree_entries<P: AsRef<RepoPath>>(
ui: &Ui,
workspace_command: &WorkspaceCommandHelper,
entries: impl IntoIterator<Item = (P, MergedTreeValue)>,
) -> Result<(), CommandError> {
let repo = workspace_command.repo();
for (path, value) in entries {
let materialized = materialize_tree_value(repo.store(), path.as_ref(), value).block_on()?;
match materialized {
MaterializedTreeValue::Absent => panic!("absent values should be excluded"),
MaterializedTreeValue::File { mut reader, .. } => {
io::copy(&mut reader, &mut ui.stdout_formatter().as_mut())?;
}
MaterializedTreeValue::Conflict { contents, .. } => {
ui.stdout_formatter().write_all(&contents)?;
}
MaterializedTreeValue::Symlink { .. }
| MaterializedTreeValue::Tree(_)
| MaterializedTreeValue::GitSubmodule(_) => {
let ui_path = workspace_command.format_file_path(path.as_ref());
writeln!(
ui.warning_default(),
"Path exists but is not a file: {ui_path}"
)?;
}
}
}
Ok(())

View file

@ -58,13 +58,14 @@ fn test_cat() {
// Error if the path doesn't exist
let stderr = test_env.jj_cmd_failure(&repo_path, &["cat", "nonexistent"]);
insta::assert_snapshot!(stderr, @r###"
Error: No such path
Error: No such path: nonexistent
"###);
// Error if the path is not a file
let stderr = test_env.jj_cmd_failure(&repo_path, &["cat", "dir"]);
// TODO: files under the directory will be printed
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["cat", "dir"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @r###"
Error: Path exists but is not a file
Warning: Path exists but is not a file: dir
"###);
// Can print a conflict