Add the history import command (#13450)

# Description

Adds a simple command for importing history between different file
formats. It essentially opens the history of the format opposite of the
one currently selected, and writes new items to the current history. It
also supports piping, because why not.

As more history backends are added, this may need to be extended -
either make the source explicit, or autodetect based on existing files.
For now it should be good though.

This should replace some of the work-arounds mentioned in
https://github.com/nushell/nushell/issues/9403.

I suspect it will have at least one problem:
https://github.com/nushell/nushell/issues/9403 mentions the history file
might be locked on Windows. That being said, I was able to successfully
import plaintext history into sqlite on Linux, so the command should be
functional at least in that environment.

The locking issue could be solved later by plumbing reedline history to
the command (so that it doesn't have to reopen it). But first, I want to
get some general input on the approach.

# User-Facing Changes
New command: `history import`

# Tests + Formatting
There's a unit test, but didn't add a proper integration test yet. Not
entirely sure how - I see there's the `nu!` macro for that, but not sure
how feasible it's to inspect history generated by commands ran that way.
Could use a hint.2
This commit is contained in:
Piotr Kufel
2024-10-12 14:42:27 -07:00
committed by GitHub
parent d83781ddec
commit 1f47d72e86
9 changed files with 564 additions and 18 deletions

View File

@ -234,7 +234,7 @@ macro_rules! nu_with_plugins {
}
use crate::{Outcome, NATIVE_PATH_ENV_VAR};
use nu_path::{AbsolutePath, AbsolutePathBuf, Path};
use nu_path::{AbsolutePath, AbsolutePathBuf, Path, PathBuf};
use std::{
ffi::OsStr,
process::{Command, Stdio},
@ -248,6 +248,10 @@ pub struct NuOpts {
pub envs: Option<Vec<(String, String)>>,
pub collapse_output: Option<bool>,
pub use_ir: Option<bool>,
// Note: At the time this was added, passing in a file path was more convenient. However,
// passing in file contents seems like a better API - consider this when adding new uses of
// this field.
pub env_config: Option<PathBuf>,
}
pub fn nu_run_test(opts: NuOpts, commands: impl AsRef<str>, with_std: bool) -> Outcome {
@ -278,8 +282,14 @@ pub fn nu_run_test(opts: NuOpts, commands: impl AsRef<str>, with_std: bool) -> O
command.envs(envs);
}
// Ensure that the user's config doesn't interfere with the tests
command.arg("--no-config-file");
match opts.env_config {
Some(path) => command.arg("--env-config").arg(path),
// TODO: This seems unnecessary: the code that runs for integration tests
// (run_commands) loads startup configs only if they are specified via flags explicitly or
// the shell is started as logging shell (which it is not in this case).
None => command.arg("--no-config-file"),
};
if !with_std {
command.arg("--no-std-lib");
}