-
Notifications
You must be signed in to change notification settings - Fork 15
iroh get command #180
Comments
We want progress bars, but we focus on adding this to the #179 first. |
Looks great to me. I'd like to advocate for one flag that will help users see just how terrible network fetching is:
Often new users to IPFS will be confused by the wild swings in fetching time, and then can't reproduce their problem once they actually manage to resolve the content once (b/c cache is permanent). Adding this flag makes that conversation easier. Also, iroh developer friendliness. |
Full help text, updated on this branch:
|
I had a bunch of test cases I've moved into the main issue text as a task list here. My comment ended with this: Any other tests require a refactoring: the API should not write files but instead deliver a stream of files which can then be mocked, and then the CLI actually writes the files itself. The code that actually writes the files too should also be accessible in the API, because that's a common use case for the API. The code to get the stream and write the files already lives in the API, so it should be possible to rewrite it. Update This refactoring is starting to work now, so I can write |
@b5 regarding |
Absolutely. Feel free to punt on any flags that seem even remotely complex for now. We can break them out into separate issues later, and either they make the release, or they don't. |
It turns out that getting unwrapped files overwriting an existing file without erroring out (like any other scenario) is harder to implement than I anticipating, and it makes me question whether it's worthwhile and whether we shouldn't simply fail in that case too. What do you think @b5? The reason it's harder to implement is because we get a stream and we don't know in advance whether it contains just a single file or a bunch files and directories. Only in the form case when the only element is a file, should we overwrite. But knowing that requires consuming the stream. So it turns out it's easier to either always overwrite or never. I choose never overwrite as always overwrite is more dangerous and there are some tricky issues (do we remove files and directories that don't exist in what we're downloading?). |
Yep, let's totally punt & just error out. |
Clap derive by default produces this help text:
One difference here is that in our spec we have |
This focuses on creating tests for the `iroh get` CLI command. The Iroh API is also improved along the way. This required more work in the underlying API to make it more testable. What's tested here is everything *except* the actual IPFS behavior -- the focus is on the behavior of the CLI and API and its interactions with the filesystem. ## trycmd tests In `iroh/tests/cmd` you can see quite a few `.trycmd` files. These describes the command-line interaction. Stuff behind `$ is a command, there's a special `? failed` indicator if the command is considered to have failed, and the output of the command is shown. New are the `.out` and `.in` directories with the same names as the `.trycmd` files. These describe the filesystem before the command runs (may be missing), and the filesystem after the command has run. This way we can describe the effects of the `iroh get` command - directories and files are supposed to be created. We can also test failure scenarios where we refuse to overwrite a directory that already exists. #269 tracks various test cases. ## `get_stream` The `get` high level CLI method has been removed from the mockable `Api` trait (read on to see where it went). Instead, a more low level but still useful API method `get_stream` has been added to the `Api` trait. This gets a stream of relative paths and `OutType`, describing the directories and files you can create. The big difference with what was there before is that it returns relative paths and doesn't calculate final destination paths -- that's up to the user of the API. ## No `async_trait` macro for `Api` trait The interactions between the `Api` trait, `mockall` macro and `async_trait` were getting so hairy I couldn't figure out how to express things anymore once I wanted to add `get_stream`. For my sanity and also to learn better how this really works underneath, I've rewritten the `Api` trait to describe itself explicitly in terms of `(Local)BoxFuture` and `(Local)_BoxStream`. It's more verbose but functionally equivalent and I could express what I wanted. ## `ApiExt` trait The `ApiExt` trait is a trait that implements the high level `get` command. It puts everything together: it handles various error conditions, accesses the stream and then writes the stream to the filesystem. It's basically `iroh get`. The `ApiExt` trait is solely intended to contain default trait methods, and is automatically available when the `Api` contract is fulfilled (if you `use` it). Factored out `save_get_stream` from `getadd.rs` to be solely concerned with turning a stream into files and directories on the files system. That makes it possible to test its behavior in isolation. ## test fixture The `get` test fixture now mocks `get_stream` and returns a fake stream made from a `Vec`. This defines the actual stuff that the CLI writes to disk. ## relative_path Now depend on the [`relative-path` crate](https://crates.io/crates/relative-path) because what the stream returns are clearly relative paths, and we want to force the user to do something with them before being able to actually write stuff.
Discussion proposal
iroh-ctl get <ipfs-path> [<path>]
ipfs-path
can be a true IPFS path, or a CIDpath
is a filesystem path and is optional. If it’s not supplied, path is set to theCID
.Download file or directory from IPFS into
path
. Ifpath
already exists and is a file then it’s overwritten with the new downloaded file. Ifpath
already exists and is a directory, the command fails with an error. Ifpath
already exists, is a file and the downloaded data is a directory, that’s an errorDifferences with Kubo:
ipfs get
has an--output
flag, instead we have a second optionalpath
argument.ipfs get
downloads into--output
if that output path already exists and is a directory. We consider that an error. The motivation is that it’s while it mirrors the behavior of Unixcp
, we can’t fully mirrorcp
because we don’t always have the source file name or directory, and it risks creating an accidental nested directory structure when you repeatedly download.ipfs get
silently overwrites the directory if no--output
was given. Instead of silently overwriting, we choose to present the user with an error so that the behavior of the omittedpath
is identical to when you supply one.Test cases
iroh get cid/a/b
whereb
is a fileiroh get cid/a/b
whereb
is a directoryiroh get cid/a/b
where b doesn't existQuestions
The text was updated successfully, but these errors were encountered: