nushell/crates/nu-command/src/filesystem/save.rs

421 lines
14 KiB
Rust
Raw Normal View History

use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
Standardise the use of ShellError::UnsupportedInput and ShellError::TypeMismatch and add spans to every instance of the former (#7217) # Description * I was dismayed to discover recently that UnsupportedInput and TypeMismatch are used *extremely* inconsistently across the codebase. UnsupportedInput is sometimes used for input type-checks (as per the name!!), but *also* used for argument type-checks. TypeMismatch is also used for both. I thus devised the following standard: input type-checking *only* uses UnsupportedInput, and argument type-checking *only* uses TypeMismatch. Moreover, to differentiate them, UnsupportedInput now has *two* error arrows (spans), one pointing at the command and the other at the input origin, while TypeMismatch only has the one (because the command should always be nearby) * In order to apply that standard, a very large number of UnsupportedInput uses were changed so that the input's span could be retrieved and delivered to it. * Additionally, I noticed many places where **errors are not propagated correctly**: there are lots of `match` sites which take a Value::Error, then throw it away and replace it with a new Value::Error with less/misleading information (such as reporting the error as an "incorrect type"). I believe that the earliest errors are the most important, and should always be propagated where possible. * Also, to standardise one broad subset of UnsupportedInput error messages, who all used slightly different wordings of "expected `<type>`, got `<type>`", I created OnlySupportsThisInputType as a variant of it. * Finally, a bunch of error sites that had "repeated spans" - i.e. where an error expected two spans, but `call.head` was given for both - were fixed to use different spans. # Example BEFORE ``` 〉20b | str starts-with 'a' Error: nu::shell::unsupported_input (link) × Unsupported input ╭─[entry #31:1:1] 1 │ 20b | str starts-with 'a' · ┬ · ╰── Input's type is filesize. This command only works with strings. ╰──── 〉'a' | math cos Error: nu::shell::unsupported_input (link) × Unsupported input ╭─[entry #33:1:1] 1 │ 'a' | math cos · ─┬─ · ╰── Only numerical values are supported, input type: String ╰──── 〉0x[12] | encode utf8 Error: nu::shell::unsupported_input (link) × Unsupported input ╭─[entry #38:1:1] 1 │ 0x[12] | encode utf8 · ───┬── · ╰── non-string input ╰──── ``` AFTER ``` 〉20b | str starts-with 'a' Error: nu::shell::pipeline_mismatch (link) × Pipeline mismatch. ╭─[entry #1:1:1] 1 │ 20b | str starts-with 'a' · ┬ ───────┬─────── · │ ╰── only string input data is supported · ╰── input type: filesize ╰──── 〉'a' | math cos Error: nu::shell::pipeline_mismatch (link) × Pipeline mismatch. ╭─[entry #2:1:1] 1 │ 'a' | math cos · ─┬─ ────┬─── · │ ╰── only numeric input data is supported · ╰── input type: string ╰──── 〉0x[12] | encode utf8 Error: nu::shell::pipeline_mismatch (link) × Pipeline mismatch. ╭─[entry #3:1:1] 1 │ 0x[12] | encode utf8 · ───┬── ───┬── · │ ╰── only string input data is supported · ╰── input type: binary ╰──── ``` # User-Facing Changes Various error messages suddenly make more sense (i.e. have two arrows instead of one). # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-23 07:48:53 +01:00
Category, Example, PipelineData, RawStream, ShellError, Signature, Span, Spanned, SyntaxShape,
Type, Value,
};
use std::fs::File;
`save` command: Don't use BufWriter to write external strem to a file (#9377) # Description Fixes: #9293 The problem is caused by `save` makes a `BufferWriter` for output file, when external commands redirect it's output to a file, the content is bufferred first... To fix the issue, I'd like to introduce a `--no-buf` flag for `save` command, and it's only used in redirection scenario. Sorry it's hard to test against it in test, because it requires external command to sleep or pause... # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2023-06-10 10:07:26 +02:00
use std::io::Write;
use std::path::Path;
use std::thread;
Progress bar Implementation (#7661) # Description _(Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience.)_ I implemented the status bar we talk about yesterday. The idea was inspired by the progress bar of `wget`. I decided to go for the second suggestion by `@Reilly` > 2. add an Option<usize> or whatever to RawStream (and ListStream?) for situations where you do know the length ahead of time For now only works with the command `save` but after the approve of this PR we can see how we can implement it on commands like `cp` and `mv` When using `fetch` nushell will check if there is any `content-length` attribute in the request header. If so, then `fetch` will send it through the new `Option` variable in the `RawStream` to the `save`. If we know the total size we show the progress bar ![nu_pb01](https://user-images.githubusercontent.com/38369407/210298647-07ee55ea-e751-41b1-a84d-f72ec1f6e9e5.jpg) but if we don't then we just show the stats like: data already saved, bytes per second, and time lapse. ![nu_pb02](https://user-images.githubusercontent.com/38369407/210298698-1ef65f51-40cc-4481-83de-309cbd1049cb.jpg) ![nu_pb03](https://user-images.githubusercontent.com/38369407/210298701-eef2ef13-9206-4a98-8202-e4fe5531d79d.jpg) Please let me know If I need to make any changes and I will be happy to do it. # User-Facing Changes A new flag (`--progress` `-p`) was added to the `save` command Examples: ```nu fetch https://github.com/torvalds/linux/archive/refs/heads/master.zip | save --progress -f main.zip fetch https://releases.ubuntu.com/22.04.1/ubuntu-22.04.1-desktop-amd64.iso | save --progress -f main.zip open main.zip --raw | save --progress main.copy ``` # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - I am getting some errors and its weird because the errors are showing up in files i haven't touch. Is this normal? # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. Co-authored-by: Reilly Wood <reilly.wood@icloud.com>
2023-01-11 02:57:48 +01:00
use crate::progress_bar;
#[derive(Clone)]
pub struct Save;
impl Command for Save {
fn name(&self) -> &str {
"save"
}
fn usage(&self) -> &str {
"Save a file."
}
fn search_terms(&self) -> Vec<&str> {
vec![
"write",
"write_file",
"append",
"redirection",
"file",
"io",
">",
">>",
]
}
fn signature(&self) -> nu_protocol::Signature {
Signature::build("save")
.input_output_types(vec![(Type::Any, Type::Nothing)])
.required("filename", SyntaxShape::Filepath, "the filename to use")
.named(
"stderr",
SyntaxShape::Filepath,
"the filename used to save stderr, only works with `-r` flag",
Some('e'),
)
.switch("raw", "save file as raw binary", Some('r'))
.switch("append", "append input to the end of the file", Some('a'))
.switch("force", "overwrite the destination", Some('f'))
Progress bar Implementation (#7661) # Description _(Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience.)_ I implemented the status bar we talk about yesterday. The idea was inspired by the progress bar of `wget`. I decided to go for the second suggestion by `@Reilly` > 2. add an Option<usize> or whatever to RawStream (and ListStream?) for situations where you do know the length ahead of time For now only works with the command `save` but after the approve of this PR we can see how we can implement it on commands like `cp` and `mv` When using `fetch` nushell will check if there is any `content-length` attribute in the request header. If so, then `fetch` will send it through the new `Option` variable in the `RawStream` to the `save`. If we know the total size we show the progress bar ![nu_pb01](https://user-images.githubusercontent.com/38369407/210298647-07ee55ea-e751-41b1-a84d-f72ec1f6e9e5.jpg) but if we don't then we just show the stats like: data already saved, bytes per second, and time lapse. ![nu_pb02](https://user-images.githubusercontent.com/38369407/210298698-1ef65f51-40cc-4481-83de-309cbd1049cb.jpg) ![nu_pb03](https://user-images.githubusercontent.com/38369407/210298701-eef2ef13-9206-4a98-8202-e4fe5531d79d.jpg) Please let me know If I need to make any changes and I will be happy to do it. # User-Facing Changes A new flag (`--progress` `-p`) was added to the `save` command Examples: ```nu fetch https://github.com/torvalds/linux/archive/refs/heads/master.zip | save --progress -f main.zip fetch https://releases.ubuntu.com/22.04.1/ubuntu-22.04.1-desktop-amd64.iso | save --progress -f main.zip open main.zip --raw | save --progress main.copy ``` # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - I am getting some errors and its weird because the errors are showing up in files i haven't touch. Is this normal? # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. Co-authored-by: Reilly Wood <reilly.wood@icloud.com>
2023-01-11 02:57:48 +01:00
.switch("progress", "enable progress bar", Some('p'))
.category(Category::FileSystem)
}
fn run(
&self,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let raw = call.has_flag("raw");
let append = call.has_flag("append");
let force = call.has_flag("force");
Progress bar Implementation (#7661) # Description _(Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience.)_ I implemented the status bar we talk about yesterday. The idea was inspired by the progress bar of `wget`. I decided to go for the second suggestion by `@Reilly` > 2. add an Option<usize> or whatever to RawStream (and ListStream?) for situations where you do know the length ahead of time For now only works with the command `save` but after the approve of this PR we can see how we can implement it on commands like `cp` and `mv` When using `fetch` nushell will check if there is any `content-length` attribute in the request header. If so, then `fetch` will send it through the new `Option` variable in the `RawStream` to the `save`. If we know the total size we show the progress bar ![nu_pb01](https://user-images.githubusercontent.com/38369407/210298647-07ee55ea-e751-41b1-a84d-f72ec1f6e9e5.jpg) but if we don't then we just show the stats like: data already saved, bytes per second, and time lapse. ![nu_pb02](https://user-images.githubusercontent.com/38369407/210298698-1ef65f51-40cc-4481-83de-309cbd1049cb.jpg) ![nu_pb03](https://user-images.githubusercontent.com/38369407/210298701-eef2ef13-9206-4a98-8202-e4fe5531d79d.jpg) Please let me know If I need to make any changes and I will be happy to do it. # User-Facing Changes A new flag (`--progress` `-p`) was added to the `save` command Examples: ```nu fetch https://github.com/torvalds/linux/archive/refs/heads/master.zip | save --progress -f main.zip fetch https://releases.ubuntu.com/22.04.1/ubuntu-22.04.1-desktop-amd64.iso | save --progress -f main.zip open main.zip --raw | save --progress main.copy ``` # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - I am getting some errors and its weird because the errors are showing up in files i haven't touch. Is this normal? # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. Co-authored-by: Reilly Wood <reilly.wood@icloud.com>
2023-01-11 02:57:48 +01:00
let progress = call.has_flag("progress");
let span = call.head;
let path = call.req::<Spanned<String>>(engine_state, stack, 0)?;
let stderr_path = call.get_flag::<Spanned<String>>(engine_state, stack, "stderr")?;
match input {
PipelineData::ExternalStream { stdout: None, .. } => {
// Open files to possibly truncate them
let _ = get_files(&path, &stderr_path, append, force)?;
Ok(PipelineData::empty())
}
PipelineData::ExternalStream {
stdout: Some(stream),
stderr,
..
} => {
let (file, stderr_file) = get_files(&path, &stderr_path, append, force)?;
// delegate a thread to redirect stderr to result.
let handler = stderr.map(|stderr_stream| match stderr_file {
Some(stderr_file) => thread::Builder::new()
.name("stderr redirector".to_string())
.spawn(move || stream_to_file(stderr_stream, stderr_file, span, progress))
.expect("Failed to create thread"),
None => thread::Builder::new()
.name("stderr redirector".to_string())
.spawn(move || {
let _ = stderr_stream.into_bytes();
Ok(PipelineData::empty())
})
.expect("Failed to create thread"),
});
Progress bar Implementation (#7661) # Description _(Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience.)_ I implemented the status bar we talk about yesterday. The idea was inspired by the progress bar of `wget`. I decided to go for the second suggestion by `@Reilly` > 2. add an Option<usize> or whatever to RawStream (and ListStream?) for situations where you do know the length ahead of time For now only works with the command `save` but after the approve of this PR we can see how we can implement it on commands like `cp` and `mv` When using `fetch` nushell will check if there is any `content-length` attribute in the request header. If so, then `fetch` will send it through the new `Option` variable in the `RawStream` to the `save`. If we know the total size we show the progress bar ![nu_pb01](https://user-images.githubusercontent.com/38369407/210298647-07ee55ea-e751-41b1-a84d-f72ec1f6e9e5.jpg) but if we don't then we just show the stats like: data already saved, bytes per second, and time lapse. ![nu_pb02](https://user-images.githubusercontent.com/38369407/210298698-1ef65f51-40cc-4481-83de-309cbd1049cb.jpg) ![nu_pb03](https://user-images.githubusercontent.com/38369407/210298701-eef2ef13-9206-4a98-8202-e4fe5531d79d.jpg) Please let me know If I need to make any changes and I will be happy to do it. # User-Facing Changes A new flag (`--progress` `-p`) was added to the `save` command Examples: ```nu fetch https://github.com/torvalds/linux/archive/refs/heads/master.zip | save --progress -f main.zip fetch https://releases.ubuntu.com/22.04.1/ubuntu-22.04.1-desktop-amd64.iso | save --progress -f main.zip open main.zip --raw | save --progress main.copy ``` # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - I am getting some errors and its weird because the errors are showing up in files i haven't touch. Is this normal? # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. Co-authored-by: Reilly Wood <reilly.wood@icloud.com>
2023-01-11 02:57:48 +01:00
let res = stream_to_file(stream, file, span, progress);
if let Some(h) = handler {
2023-03-06 18:33:09 +01:00
h.join().map_err(|err| ShellError::ExternalCommand {
label: "Fail to receive external commands stderr message".to_string(),
help: format!("{err:?}"),
span,
})??;
res
} else {
res
}
}
PipelineData::ListStream(ls, _)
if raw || prepare_path(&path, append, force)?.0.extension().is_none() =>
{
let (mut file, _) = get_files(&path, &stderr_path, append, force)?;
for val in ls {
file.write_all(&value_to_bytes(val)?)
.map_err(|err| ShellError::IOError(err.to_string()))?;
file.write_all("\n".as_bytes())
.map_err(|err| ShellError::IOError(err.to_string()))?;
}
file.flush()?;
Ok(PipelineData::empty())
}
input => {
let bytes =
input_to_bytes(input, Path::new(&path.item), raw, engine_state, stack, span)?;
// Only open file after successful conversion
let (mut file, _) = get_files(&path, &stderr_path, append, force)?;
file.write_all(&bytes)
.map_err(|err| ShellError::IOError(err.to_string()))?;
file.flush()?;
Ok(PipelineData::empty())
}
}
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Save a string to foo.txt in the current directory",
2022-10-26 18:36:42 +02:00
example: r#"'save me' | save foo.txt"#,
result: None,
},
Example {
description: "Append a string to the end of foo.txt",
2022-10-26 18:36:42 +02:00
example: r#"'append me' | save --append foo.txt"#,
result: None,
},
Example {
description: "Save a record to foo.json in the current directory",
2022-10-26 18:36:42 +02:00
example: r#"{ a: 1, b: 2 } | save foo.json"#,
result: None,
},
Example {
description: "Save a running program's stderr to foo.txt",
example: r#"do -i {} | save foo.txt --stderr foo.txt"#,
result: None,
},
Example {
description: "Save a running program's stderr to separate file",
example: r#"do -i {} | save foo.txt --stderr bar.txt"#,
result: None,
},
]
}
}
/// Convert [`PipelineData`] bytes to write in file, possibly converting
/// to format of output file
fn input_to_bytes(
input: PipelineData,
path: &Path,
raw: bool,
engine_state: &EngineState,
stack: &mut Stack,
span: Span,
) -> Result<Vec<u8>, ShellError> {
let ext = if raw {
None
// if is extern stream , in other words , not value
} else if let PipelineData::ExternalStream { .. } = input {
None
} else if let PipelineData::Value(Value::String { .. }, ..) = input {
None
} else {
path.extension()
.map(|name| name.to_string_lossy().to_string())
};
if let Some(ext) = ext {
convert_to_extension(engine_state, &ext, stack, input, span)
} else {
let value = input.into_value(span);
value_to_bytes(value)
}
}
/// Convert given data into content of file of specified extension if
/// corresponding `to` command exists. Otherwise attempt to convert
/// data to bytes as is
fn convert_to_extension(
engine_state: &EngineState,
extension: &str,
stack: &mut Stack,
input: PipelineData,
span: Span,
) -> Result<Vec<u8>, ShellError> {
let converter = engine_state.find_decl(format!("to {extension}").as_bytes(), &[]);
let output = match converter {
Some(converter_id) => {
let output = engine_state.get_decl(converter_id).run(
engine_state,
stack,
&Call::new(span),
input,
)?;
output.into_value(span)
}
None => input.into_value(span),
};
value_to_bytes(output)
}
/// Convert [`Value::String`] [`Value::Binary`] or [`Value::List`] into [`Vec`] of bytes
///
/// Propagates [`Value::Error`] and creates error otherwise
fn value_to_bytes(value: Value) -> Result<Vec<u8>, ShellError> {
match value {
Value::String { val, .. } => Ok(val.into_bytes()),
Value::Binary { val, .. } => Ok(val),
Value::List { vals, .. } => {
let val = vals
.into_iter()
.map(|it| it.as_string())
.collect::<Result<Vec<String>, ShellError>>()?
.join("\n")
+ "\n";
Ok(val.into_bytes())
}
// Propagate errors by explicitly matching them before the final case.
Value::Error { error } => Err(*error),
other => Ok(other.as_string()?.into_bytes()),
}
}
/// Convert string path to [`Path`] and [`Span`] and check if this path
/// can be used with given flags
fn prepare_path(
path: &Spanned<String>,
append: bool,
force: bool,
) -> Result<(&Path, Span), ShellError> {
let span = path.span;
let path = Path::new(&path.item);
if !(force || append) && path.exists() {
Err(ShellError::GenericError(
"Destination file already exists".into(),
format!(
"Destination file '{}' already exists",
path.to_string_lossy()
),
Some(span),
Some("you can use -f, --force to force overwriting the destination".into()),
Vec::new(),
))
} else {
Ok((path, span))
}
}
fn open_file(path: &Path, span: Span, append: bool) -> Result<File, ShellError> {
let file = match (append, path.exists()) {
(true, true) => std::fs::OpenOptions::new()
.write(true)
.append(true)
.open(path),
_ => std::fs::File::create(path),
};
file.map_err(|err| {
ShellError::GenericError(
"Permission denied".into(),
err.to_string(),
Some(span),
None,
Vec::new(),
)
})
}
/// Get output file and optional stderr file
fn get_files(
path: &Spanned<String>,
stderr_path: &Option<Spanned<String>>,
append: bool,
force: bool,
) -> Result<(File, Option<File>), ShellError> {
// First check both paths
let (path, path_span) = prepare_path(path, append, force)?;
let stderr_path_and_span = stderr_path
.as_ref()
.map(|stderr_path| prepare_path(stderr_path, append, force))
.transpose()?;
// Only if both files can be used open and possibly truncate them
let file = open_file(path, path_span, append)?;
let stderr_file = stderr_path_and_span
.map(|(stderr_path, stderr_path_span)| {
if path == stderr_path {
don't allow `save` command to save both stdout and stderr to the same file (#9368) # Description It's not a good idea to save `stdout` and `stderr` to the same file from `save` command directly. Because it saves `stdout` and `stderr` in different thread, which leads to in-consistent output. As replace, we can use `o+e` redirection to fix the issue # User-Facing Changes ``` ❯ do -i { "aa" } | save foo.txt -e foo.txt Error: × input and stderr input to same file ╭─[entry #3:1:1] 1 │ do -i { "aa" } | save foo.txt -e foo.txt · ───┬─── · ╰── can't save both input and stderr input to the same file ╰──── help: you should use `o+e> file` instead ``` # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-06-10 10:09:19 +02:00
Err(ShellError::GenericError(
"input and stderr input to same file".to_string(),
"can't save both input and stderr input to the same file".to_string(),
Some(stderr_path_span),
Some("you should use `o+e> file` instead".to_string()),
vec![],
))
} else {
open_file(stderr_path, stderr_path_span, append)
}
})
.transpose()?;
Ok((file, stderr_file))
}
Standardise the use of ShellError::UnsupportedInput and ShellError::TypeMismatch and add spans to every instance of the former (#7217) # Description * I was dismayed to discover recently that UnsupportedInput and TypeMismatch are used *extremely* inconsistently across the codebase. UnsupportedInput is sometimes used for input type-checks (as per the name!!), but *also* used for argument type-checks. TypeMismatch is also used for both. I thus devised the following standard: input type-checking *only* uses UnsupportedInput, and argument type-checking *only* uses TypeMismatch. Moreover, to differentiate them, UnsupportedInput now has *two* error arrows (spans), one pointing at the command and the other at the input origin, while TypeMismatch only has the one (because the command should always be nearby) * In order to apply that standard, a very large number of UnsupportedInput uses were changed so that the input's span could be retrieved and delivered to it. * Additionally, I noticed many places where **errors are not propagated correctly**: there are lots of `match` sites which take a Value::Error, then throw it away and replace it with a new Value::Error with less/misleading information (such as reporting the error as an "incorrect type"). I believe that the earliest errors are the most important, and should always be propagated where possible. * Also, to standardise one broad subset of UnsupportedInput error messages, who all used slightly different wordings of "expected `<type>`, got `<type>`", I created OnlySupportsThisInputType as a variant of it. * Finally, a bunch of error sites that had "repeated spans" - i.e. where an error expected two spans, but `call.head` was given for both - were fixed to use different spans. # Example BEFORE ``` 〉20b | str starts-with 'a' Error: nu::shell::unsupported_input (link) × Unsupported input ╭─[entry #31:1:1] 1 │ 20b | str starts-with 'a' · ┬ · ╰── Input's type is filesize. This command only works with strings. ╰──── 〉'a' | math cos Error: nu::shell::unsupported_input (link) × Unsupported input ╭─[entry #33:1:1] 1 │ 'a' | math cos · ─┬─ · ╰── Only numerical values are supported, input type: String ╰──── 〉0x[12] | encode utf8 Error: nu::shell::unsupported_input (link) × Unsupported input ╭─[entry #38:1:1] 1 │ 0x[12] | encode utf8 · ───┬── · ╰── non-string input ╰──── ``` AFTER ``` 〉20b | str starts-with 'a' Error: nu::shell::pipeline_mismatch (link) × Pipeline mismatch. ╭─[entry #1:1:1] 1 │ 20b | str starts-with 'a' · ┬ ───────┬─────── · │ ╰── only string input data is supported · ╰── input type: filesize ╰──── 〉'a' | math cos Error: nu::shell::pipeline_mismatch (link) × Pipeline mismatch. ╭─[entry #2:1:1] 1 │ 'a' | math cos · ─┬─ ────┬─── · │ ╰── only numeric input data is supported · ╰── input type: string ╰──── 〉0x[12] | encode utf8 Error: nu::shell::pipeline_mismatch (link) × Pipeline mismatch. ╭─[entry #3:1:1] 1 │ 0x[12] | encode utf8 · ───┬── ───┬── · │ ╰── only string input data is supported · ╰── input type: binary ╰──── ``` # User-Facing Changes Various error messages suddenly make more sense (i.e. have two arrows instead of one). # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-23 07:48:53 +01:00
fn stream_to_file(
mut stream: RawStream,
file: File,
span: Span,
Progress bar Implementation (#7661) # Description _(Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience.)_ I implemented the status bar we talk about yesterday. The idea was inspired by the progress bar of `wget`. I decided to go for the second suggestion by `@Reilly` > 2. add an Option<usize> or whatever to RawStream (and ListStream?) for situations where you do know the length ahead of time For now only works with the command `save` but after the approve of this PR we can see how we can implement it on commands like `cp` and `mv` When using `fetch` nushell will check if there is any `content-length` attribute in the request header. If so, then `fetch` will send it through the new `Option` variable in the `RawStream` to the `save`. If we know the total size we show the progress bar ![nu_pb01](https://user-images.githubusercontent.com/38369407/210298647-07ee55ea-e751-41b1-a84d-f72ec1f6e9e5.jpg) but if we don't then we just show the stats like: data already saved, bytes per second, and time lapse. ![nu_pb02](https://user-images.githubusercontent.com/38369407/210298698-1ef65f51-40cc-4481-83de-309cbd1049cb.jpg) ![nu_pb03](https://user-images.githubusercontent.com/38369407/210298701-eef2ef13-9206-4a98-8202-e4fe5531d79d.jpg) Please let me know If I need to make any changes and I will be happy to do it. # User-Facing Changes A new flag (`--progress` `-p`) was added to the `save` command Examples: ```nu fetch https://github.com/torvalds/linux/archive/refs/heads/master.zip | save --progress -f main.zip fetch https://releases.ubuntu.com/22.04.1/ubuntu-22.04.1-desktop-amd64.iso | save --progress -f main.zip open main.zip --raw | save --progress main.copy ``` # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - I am getting some errors and its weird because the errors are showing up in files i haven't touch. Is this normal? # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. Co-authored-by: Reilly Wood <reilly.wood@icloud.com>
2023-01-11 02:57:48 +01:00
progress: bool,
Standardise the use of ShellError::UnsupportedInput and ShellError::TypeMismatch and add spans to every instance of the former (#7217) # Description * I was dismayed to discover recently that UnsupportedInput and TypeMismatch are used *extremely* inconsistently across the codebase. UnsupportedInput is sometimes used for input type-checks (as per the name!!), but *also* used for argument type-checks. TypeMismatch is also used for both. I thus devised the following standard: input type-checking *only* uses UnsupportedInput, and argument type-checking *only* uses TypeMismatch. Moreover, to differentiate them, UnsupportedInput now has *two* error arrows (spans), one pointing at the command and the other at the input origin, while TypeMismatch only has the one (because the command should always be nearby) * In order to apply that standard, a very large number of UnsupportedInput uses were changed so that the input's span could be retrieved and delivered to it. * Additionally, I noticed many places where **errors are not propagated correctly**: there are lots of `match` sites which take a Value::Error, then throw it away and replace it with a new Value::Error with less/misleading information (such as reporting the error as an "incorrect type"). I believe that the earliest errors are the most important, and should always be propagated where possible. * Also, to standardise one broad subset of UnsupportedInput error messages, who all used slightly different wordings of "expected `<type>`, got `<type>`", I created OnlySupportsThisInputType as a variant of it. * Finally, a bunch of error sites that had "repeated spans" - i.e. where an error expected two spans, but `call.head` was given for both - were fixed to use different spans. # Example BEFORE ``` 〉20b | str starts-with 'a' Error: nu::shell::unsupported_input (link) × Unsupported input ╭─[entry #31:1:1] 1 │ 20b | str starts-with 'a' · ┬ · ╰── Input's type is filesize. This command only works with strings. ╰──── 〉'a' | math cos Error: nu::shell::unsupported_input (link) × Unsupported input ╭─[entry #33:1:1] 1 │ 'a' | math cos · ─┬─ · ╰── Only numerical values are supported, input type: String ╰──── 〉0x[12] | encode utf8 Error: nu::shell::unsupported_input (link) × Unsupported input ╭─[entry #38:1:1] 1 │ 0x[12] | encode utf8 · ───┬── · ╰── non-string input ╰──── ``` AFTER ``` 〉20b | str starts-with 'a' Error: nu::shell::pipeline_mismatch (link) × Pipeline mismatch. ╭─[entry #1:1:1] 1 │ 20b | str starts-with 'a' · ┬ ───────┬─────── · │ ╰── only string input data is supported · ╰── input type: filesize ╰──── 〉'a' | math cos Error: nu::shell::pipeline_mismatch (link) × Pipeline mismatch. ╭─[entry #2:1:1] 1 │ 'a' | math cos · ─┬─ ────┬─── · │ ╰── only numeric input data is supported · ╰── input type: string ╰──── 〉0x[12] | encode utf8 Error: nu::shell::pipeline_mismatch (link) × Pipeline mismatch. ╭─[entry #3:1:1] 1 │ 0x[12] | encode utf8 · ───┬── ───┬── · │ ╰── only string input data is supported · ╰── input type: binary ╰──── ``` # User-Facing Changes Various error messages suddenly make more sense (i.e. have two arrows instead of one). # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-23 07:48:53 +01:00
) -> Result<PipelineData, ShellError> {
`save` command: Don't use BufWriter to write external strem to a file (#9377) # Description Fixes: #9293 The problem is caused by `save` makes a `BufferWriter` for output file, when external commands redirect it's output to a file, the content is bufferred first... To fix the issue, I'd like to introduce a `--no-buf` flag for `save` command, and it's only used in redirection scenario. Sorry it's hard to test against it in test, because it requires external command to sleep or pause... # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2023-06-10 10:07:26 +02:00
// https://github.com/nushell/nushell/pull/9377 contains the reason
// for not using BufWriter<File>
let mut writer = file;
Progress bar Implementation (#7661) # Description _(Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience.)_ I implemented the status bar we talk about yesterday. The idea was inspired by the progress bar of `wget`. I decided to go for the second suggestion by `@Reilly` > 2. add an Option<usize> or whatever to RawStream (and ListStream?) for situations where you do know the length ahead of time For now only works with the command `save` but after the approve of this PR we can see how we can implement it on commands like `cp` and `mv` When using `fetch` nushell will check if there is any `content-length` attribute in the request header. If so, then `fetch` will send it through the new `Option` variable in the `RawStream` to the `save`. If we know the total size we show the progress bar ![nu_pb01](https://user-images.githubusercontent.com/38369407/210298647-07ee55ea-e751-41b1-a84d-f72ec1f6e9e5.jpg) but if we don't then we just show the stats like: data already saved, bytes per second, and time lapse. ![nu_pb02](https://user-images.githubusercontent.com/38369407/210298698-1ef65f51-40cc-4481-83de-309cbd1049cb.jpg) ![nu_pb03](https://user-images.githubusercontent.com/38369407/210298701-eef2ef13-9206-4a98-8202-e4fe5531d79d.jpg) Please let me know If I need to make any changes and I will be happy to do it. # User-Facing Changes A new flag (`--progress` `-p`) was added to the `save` command Examples: ```nu fetch https://github.com/torvalds/linux/archive/refs/heads/master.zip | save --progress -f main.zip fetch https://releases.ubuntu.com/22.04.1/ubuntu-22.04.1-desktop-amd64.iso | save --progress -f main.zip open main.zip --raw | save --progress main.copy ``` # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - I am getting some errors and its weird because the errors are showing up in files i haven't touch. Is this normal? # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. Co-authored-by: Reilly Wood <reilly.wood@icloud.com>
2023-01-11 02:57:48 +01:00
let mut bytes_processed: u64 = 0;
let bytes_processed_p = &mut bytes_processed;
let file_total_size = stream.known_size;
let mut process_failed = false;
let process_failed_p = &mut process_failed;
// Create the progress bar
// It looks a bit messy but I am doing it this way to avoid
// creating the bar when is not needed
let (mut bar_opt, bar_opt_clone) = if progress {
let tmp_bar = progress_bar::NuProgressBar::new(file_total_size);
let tmp_bar_clone = tmp_bar.clone();
(Some(tmp_bar), Some(tmp_bar_clone))
} else {
(None, None)
};
let result = stream
.try_for_each(move |result| {
let buf = match result {
Ok(v) => match v {
Value::String { val, .. } => val.into_bytes(),
Value::Binary { val, .. } => val,
Standardise the use of ShellError::UnsupportedInput and ShellError::TypeMismatch and add spans to every instance of the former (#7217) # Description * I was dismayed to discover recently that UnsupportedInput and TypeMismatch are used *extremely* inconsistently across the codebase. UnsupportedInput is sometimes used for input type-checks (as per the name!!), but *also* used for argument type-checks. TypeMismatch is also used for both. I thus devised the following standard: input type-checking *only* uses UnsupportedInput, and argument type-checking *only* uses TypeMismatch. Moreover, to differentiate them, UnsupportedInput now has *two* error arrows (spans), one pointing at the command and the other at the input origin, while TypeMismatch only has the one (because the command should always be nearby) * In order to apply that standard, a very large number of UnsupportedInput uses were changed so that the input's span could be retrieved and delivered to it. * Additionally, I noticed many places where **errors are not propagated correctly**: there are lots of `match` sites which take a Value::Error, then throw it away and replace it with a new Value::Error with less/misleading information (such as reporting the error as an "incorrect type"). I believe that the earliest errors are the most important, and should always be propagated where possible. * Also, to standardise one broad subset of UnsupportedInput error messages, who all used slightly different wordings of "expected `<type>`, got `<type>`", I created OnlySupportsThisInputType as a variant of it. * Finally, a bunch of error sites that had "repeated spans" - i.e. where an error expected two spans, but `call.head` was given for both - were fixed to use different spans. # Example BEFORE ``` 〉20b | str starts-with 'a' Error: nu::shell::unsupported_input (link) × Unsupported input ╭─[entry #31:1:1] 1 │ 20b | str starts-with 'a' · ┬ · ╰── Input's type is filesize. This command only works with strings. ╰──── 〉'a' | math cos Error: nu::shell::unsupported_input (link) × Unsupported input ╭─[entry #33:1:1] 1 │ 'a' | math cos · ─┬─ · ╰── Only numerical values are supported, input type: String ╰──── 〉0x[12] | encode utf8 Error: nu::shell::unsupported_input (link) × Unsupported input ╭─[entry #38:1:1] 1 │ 0x[12] | encode utf8 · ───┬── · ╰── non-string input ╰──── ``` AFTER ``` 〉20b | str starts-with 'a' Error: nu::shell::pipeline_mismatch (link) × Pipeline mismatch. ╭─[entry #1:1:1] 1 │ 20b | str starts-with 'a' · ┬ ───────┬─────── · │ ╰── only string input data is supported · ╰── input type: filesize ╰──── 〉'a' | math cos Error: nu::shell::pipeline_mismatch (link) × Pipeline mismatch. ╭─[entry #2:1:1] 1 │ 'a' | math cos · ─┬─ ────┬─── · │ ╰── only numeric input data is supported · ╰── input type: string ╰──── 〉0x[12] | encode utf8 Error: nu::shell::pipeline_mismatch (link) × Pipeline mismatch. ╭─[entry #3:1:1] 1 │ 0x[12] | encode utf8 · ───┬── ───┬── · │ ╰── only string input data is supported · ╰── input type: binary ╰──── ``` # User-Facing Changes Various error messages suddenly make more sense (i.e. have two arrows instead of one). # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-23 07:48:53 +01:00
// Propagate errors by explicitly matching them before the final case.
Value::Error { error } => return Err(*error),
Standardise the use of ShellError::UnsupportedInput and ShellError::TypeMismatch and add spans to every instance of the former (#7217) # Description * I was dismayed to discover recently that UnsupportedInput and TypeMismatch are used *extremely* inconsistently across the codebase. UnsupportedInput is sometimes used for input type-checks (as per the name!!), but *also* used for argument type-checks. TypeMismatch is also used for both. I thus devised the following standard: input type-checking *only* uses UnsupportedInput, and argument type-checking *only* uses TypeMismatch. Moreover, to differentiate them, UnsupportedInput now has *two* error arrows (spans), one pointing at the command and the other at the input origin, while TypeMismatch only has the one (because the command should always be nearby) * In order to apply that standard, a very large number of UnsupportedInput uses were changed so that the input's span could be retrieved and delivered to it. * Additionally, I noticed many places where **errors are not propagated correctly**: there are lots of `match` sites which take a Value::Error, then throw it away and replace it with a new Value::Error with less/misleading information (such as reporting the error as an "incorrect type"). I believe that the earliest errors are the most important, and should always be propagated where possible. * Also, to standardise one broad subset of UnsupportedInput error messages, who all used slightly different wordings of "expected `<type>`, got `<type>`", I created OnlySupportsThisInputType as a variant of it. * Finally, a bunch of error sites that had "repeated spans" - i.e. where an error expected two spans, but `call.head` was given for both - were fixed to use different spans. # Example BEFORE ``` 〉20b | str starts-with 'a' Error: nu::shell::unsupported_input (link) × Unsupported input ╭─[entry #31:1:1] 1 │ 20b | str starts-with 'a' · ┬ · ╰── Input's type is filesize. This command only works with strings. ╰──── 〉'a' | math cos Error: nu::shell::unsupported_input (link) × Unsupported input ╭─[entry #33:1:1] 1 │ 'a' | math cos · ─┬─ · ╰── Only numerical values are supported, input type: String ╰──── 〉0x[12] | encode utf8 Error: nu::shell::unsupported_input (link) × Unsupported input ╭─[entry #38:1:1] 1 │ 0x[12] | encode utf8 · ───┬── · ╰── non-string input ╰──── ``` AFTER ``` 〉20b | str starts-with 'a' Error: nu::shell::pipeline_mismatch (link) × Pipeline mismatch. ╭─[entry #1:1:1] 1 │ 20b | str starts-with 'a' · ┬ ───────┬─────── · │ ╰── only string input data is supported · ╰── input type: filesize ╰──── 〉'a' | math cos Error: nu::shell::pipeline_mismatch (link) × Pipeline mismatch. ╭─[entry #2:1:1] 1 │ 'a' | math cos · ─┬─ ────┬─── · │ ╰── only numeric input data is supported · ╰── input type: string ╰──── 〉0x[12] | encode utf8 Error: nu::shell::pipeline_mismatch (link) × Pipeline mismatch. ╭─[entry #3:1:1] 1 │ 0x[12] | encode utf8 · ───┬── ───┬── · │ ╰── only string input data is supported · ╰── input type: binary ╰──── ``` # User-Facing Changes Various error messages suddenly make more sense (i.e. have two arrows instead of one). # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-23 07:48:53 +01:00
other => {
return Err(ShellError::OnlySupportsThisInputType {
exp_input_type: "string or binary".into(),
wrong_type: other.get_type().to_string(),
dst_span: span,
src_span: other.expect_span(),
});
}
},
Progress bar Implementation (#7661) # Description _(Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience.)_ I implemented the status bar we talk about yesterday. The idea was inspired by the progress bar of `wget`. I decided to go for the second suggestion by `@Reilly` > 2. add an Option<usize> or whatever to RawStream (and ListStream?) for situations where you do know the length ahead of time For now only works with the command `save` but after the approve of this PR we can see how we can implement it on commands like `cp` and `mv` When using `fetch` nushell will check if there is any `content-length` attribute in the request header. If so, then `fetch` will send it through the new `Option` variable in the `RawStream` to the `save`. If we know the total size we show the progress bar ![nu_pb01](https://user-images.githubusercontent.com/38369407/210298647-07ee55ea-e751-41b1-a84d-f72ec1f6e9e5.jpg) but if we don't then we just show the stats like: data already saved, bytes per second, and time lapse. ![nu_pb02](https://user-images.githubusercontent.com/38369407/210298698-1ef65f51-40cc-4481-83de-309cbd1049cb.jpg) ![nu_pb03](https://user-images.githubusercontent.com/38369407/210298701-eef2ef13-9206-4a98-8202-e4fe5531d79d.jpg) Please let me know If I need to make any changes and I will be happy to do it. # User-Facing Changes A new flag (`--progress` `-p`) was added to the `save` command Examples: ```nu fetch https://github.com/torvalds/linux/archive/refs/heads/master.zip | save --progress -f main.zip fetch https://releases.ubuntu.com/22.04.1/ubuntu-22.04.1-desktop-amd64.iso | save --progress -f main.zip open main.zip --raw | save --progress main.copy ``` # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - I am getting some errors and its weird because the errors are showing up in files i haven't touch. Is this normal? # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. Co-authored-by: Reilly Wood <reilly.wood@icloud.com>
2023-01-11 02:57:48 +01:00
Err(err) => {
*process_failed_p = true;
return Err(err);
}
};
Progress bar Implementation (#7661) # Description _(Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience.)_ I implemented the status bar we talk about yesterday. The idea was inspired by the progress bar of `wget`. I decided to go for the second suggestion by `@Reilly` > 2. add an Option<usize> or whatever to RawStream (and ListStream?) for situations where you do know the length ahead of time For now only works with the command `save` but after the approve of this PR we can see how we can implement it on commands like `cp` and `mv` When using `fetch` nushell will check if there is any `content-length` attribute in the request header. If so, then `fetch` will send it through the new `Option` variable in the `RawStream` to the `save`. If we know the total size we show the progress bar ![nu_pb01](https://user-images.githubusercontent.com/38369407/210298647-07ee55ea-e751-41b1-a84d-f72ec1f6e9e5.jpg) but if we don't then we just show the stats like: data already saved, bytes per second, and time lapse. ![nu_pb02](https://user-images.githubusercontent.com/38369407/210298698-1ef65f51-40cc-4481-83de-309cbd1049cb.jpg) ![nu_pb03](https://user-images.githubusercontent.com/38369407/210298701-eef2ef13-9206-4a98-8202-e4fe5531d79d.jpg) Please let me know If I need to make any changes and I will be happy to do it. # User-Facing Changes A new flag (`--progress` `-p`) was added to the `save` command Examples: ```nu fetch https://github.com/torvalds/linux/archive/refs/heads/master.zip | save --progress -f main.zip fetch https://releases.ubuntu.com/22.04.1/ubuntu-22.04.1-desktop-amd64.iso | save --progress -f main.zip open main.zip --raw | save --progress main.copy ``` # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - I am getting some errors and its weird because the errors are showing up in files i haven't touch. Is this normal? # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. Co-authored-by: Reilly Wood <reilly.wood@icloud.com>
2023-01-11 02:57:48 +01:00
// If the `progress` flag is set then
if progress {
// Update the total amount of bytes that has been saved and then print the progress bar
*bytes_processed_p += buf.len() as u64;
if let Some(bar) = &mut bar_opt {
bar.update_bar(*bytes_processed_p);
}
}
if let Err(err) = writer.write(&buf) {
Progress bar Implementation (#7661) # Description _(Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience.)_ I implemented the status bar we talk about yesterday. The idea was inspired by the progress bar of `wget`. I decided to go for the second suggestion by `@Reilly` > 2. add an Option<usize> or whatever to RawStream (and ListStream?) for situations where you do know the length ahead of time For now only works with the command `save` but after the approve of this PR we can see how we can implement it on commands like `cp` and `mv` When using `fetch` nushell will check if there is any `content-length` attribute in the request header. If so, then `fetch` will send it through the new `Option` variable in the `RawStream` to the `save`. If we know the total size we show the progress bar ![nu_pb01](https://user-images.githubusercontent.com/38369407/210298647-07ee55ea-e751-41b1-a84d-f72ec1f6e9e5.jpg) but if we don't then we just show the stats like: data already saved, bytes per second, and time lapse. ![nu_pb02](https://user-images.githubusercontent.com/38369407/210298698-1ef65f51-40cc-4481-83de-309cbd1049cb.jpg) ![nu_pb03](https://user-images.githubusercontent.com/38369407/210298701-eef2ef13-9206-4a98-8202-e4fe5531d79d.jpg) Please let me know If I need to make any changes and I will be happy to do it. # User-Facing Changes A new flag (`--progress` `-p`) was added to the `save` command Examples: ```nu fetch https://github.com/torvalds/linux/archive/refs/heads/master.zip | save --progress -f main.zip fetch https://releases.ubuntu.com/22.04.1/ubuntu-22.04.1-desktop-amd64.iso | save --progress -f main.zip open main.zip --raw | save --progress main.copy ``` # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - I am getting some errors and its weird because the errors are showing up in files i haven't touch. Is this normal? # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. Co-authored-by: Reilly Wood <reilly.wood@icloud.com>
2023-01-11 02:57:48 +01:00
*process_failed_p = true;
return Err(ShellError::IOError(err.to_string()));
}
Ok(())
})
Progress bar Implementation (#7661) # Description _(Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience.)_ I implemented the status bar we talk about yesterday. The idea was inspired by the progress bar of `wget`. I decided to go for the second suggestion by `@Reilly` > 2. add an Option<usize> or whatever to RawStream (and ListStream?) for situations where you do know the length ahead of time For now only works with the command `save` but after the approve of this PR we can see how we can implement it on commands like `cp` and `mv` When using `fetch` nushell will check if there is any `content-length` attribute in the request header. If so, then `fetch` will send it through the new `Option` variable in the `RawStream` to the `save`. If we know the total size we show the progress bar ![nu_pb01](https://user-images.githubusercontent.com/38369407/210298647-07ee55ea-e751-41b1-a84d-f72ec1f6e9e5.jpg) but if we don't then we just show the stats like: data already saved, bytes per second, and time lapse. ![nu_pb02](https://user-images.githubusercontent.com/38369407/210298698-1ef65f51-40cc-4481-83de-309cbd1049cb.jpg) ![nu_pb03](https://user-images.githubusercontent.com/38369407/210298701-eef2ef13-9206-4a98-8202-e4fe5531d79d.jpg) Please let me know If I need to make any changes and I will be happy to do it. # User-Facing Changes A new flag (`--progress` `-p`) was added to the `save` command Examples: ```nu fetch https://github.com/torvalds/linux/archive/refs/heads/master.zip | save --progress -f main.zip fetch https://releases.ubuntu.com/22.04.1/ubuntu-22.04.1-desktop-amd64.iso | save --progress -f main.zip open main.zip --raw | save --progress main.copy ``` # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - I am getting some errors and its weird because the errors are showing up in files i haven't touch. Is this normal? # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. Co-authored-by: Reilly Wood <reilly.wood@icloud.com>
2023-01-11 02:57:48 +01:00
.map(|_| PipelineData::empty());
// If the `progress` flag is set then
if progress {
// If the process failed, stop the progress bar with an error message.
if process_failed {
if let Some(bar) = bar_opt_clone {
bar.abandoned_msg("# Error while saving #".to_owned());
}
}
}
// And finally return the stream result.
result
}