Skip to content
This repository was archived by the owner on Oct 23, 2022. It is now read-only.

feat: ipfs-unixfs get or "walk over anything" #189

Merged
merged 76 commits into from
Jun 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
823f207
feat: add prorotype of walking over all unixfs
Jun 11, 2020
5ac211f
feat: filevisit vec caching
Jun 12, 2020
d62da31
add: unixfs/examples/get.rs
Jun 12, 2020
7590da6
feat: make different file segments easier to distinguish
Jun 12, 2020
1c2981b
feat: print sha256 in examples/get.rs
Jun 12, 2020
d74a9be
refactor: dry unixfs/examples/get
Jun 13, 2020
1367e50
refactor: FileSegment to struct
Jun 13, 2020
c5e3949
refactor: path name recycling
Jun 13, 2020
9800710
wip: update skipping story
Jun 13, 2020
27df611
refactor: simplify copypasted parts
Jun 13, 2020
3a4e2fc
feat: walk empty root directories
Jun 13, 2020
306b10e
refactor: simplify dir walk start
Jun 13, 2020
72f6887
fix: bad FileSegment::is_last, reorg, comments
Jun 15, 2020
eec4598
doc: apply suggestions from code review
koivunej Jun 16, 2020
b7b3d12
add tar dependency
Jun 15, 2020
281f63f
doc: Entry::path
Jun 15, 2020
d2dc475
add FileSegment::total_file_size
Jun 15, 2020
1d572be
add Entry::metadata
Jun 15, 2020
c1a0943
wip: sneak in most of the private parts of tar-rs
Jun 15, 2020
795a34f
doc: add note regarding utf8
Jun 15, 2020
02b5a47
add: metadata to filetime conversion
Jun 15, 2020
769ae5b
feat: keep track of file size
Jun 15, 2020
dafbf49
wip: add symlinks and hamt sharded dirs
Jun 15, 2020
6671e74
feat: /get http endpoint
Jun 16, 2020
c61d55d
fix: start now returns ContinuedWalk, root name
Jun 16, 2020
6255f3c
fix: root paths for dirs and sharded
Jun 16, 2020
5e36924
refactor: prettify tests
Jun 16, 2020
585b521
refactor: split two scenario tests
Jun 16, 2020
182da8d
add root level test cases
Jun 16, 2020
08fa4c7
add: top level file support
Jun 16, 2020
81233dd
add: top level symlink support
Jun 16, 2020
8ada837
fix: get walking interop tests to complete
Jun 16, 2020
cbd2d4a
feat: add follow_dagpb_data option to ipfspath
Jun 16, 2020
07ae552
doc: add comments to tar export
Jun 16, 2020
1e0dd4e
add(unixfs): sharded to non-sharded resolving test
Jun 16, 2020
3da2bc7
fix: last cat conformance test failure
Jun 16, 2020
7feeded
fix: refs must use new ipfspath.follow_dagpb_data
Jun 16, 2020
f37974a
doc: document Walker and friends
Jun 16, 2020
9163518
refactor: remove home-grown Either
Jun 16, 2020
fcdf59a
doc: document public members
Jun 16, 2020
d16a264
fix: errors during walking
Jun 16, 2020
d61b042
fix: use errors instead of unwraps in /get as well
Jun 16, 2020
9b18427
refactor: move ipfs_unixfs::dir::walk to top level
Jun 16, 2020
948eeff
refactor: rename FileMetadata to ipfs_unixfs::Metadata
Jun 16, 2020
f71c212
chore: fmt and clippy warnings
Jun 16, 2020
e25a233
refactor: split tar helper to own module
Jun 16, 2020
6a96593
refactor: make Walker easier to use
Jun 16, 2020
062468c
add: test case for checking filesegments
Jun 16, 2020
7983fcf
chore: cargo fmt
Jun 16, 2020
f3f9f26
refactor: remove unused code
Jun 16, 2020
92cc2ab
fix panicing with long link names
Jun 16, 2020
350bb9c
fix: hopefully get windows compiling
Jun 16, 2020
9151834
chore: cleanup warnings, fmt
Jun 16, 2020
6eb276e
add: test /get for long and file names
Jun 16, 2020
9b75c16
fix(unixfs/ex): simplify get back to listing
Jun 17, 2020
bd6a974
refactor: simplify to simple buffer in TarHelper
Jun 17, 2020
7e0fcd0
refactor(http): more /get test support
Jun 17, 2020
f5ada87
add(http): multiblock file /get test
Jun 17, 2020
d589e90
refactor(unix): split test_support with FakeBlockstore
Jun 17, 2020
1d50a51
fix: check dirs and hamtshards supported
Jun 17, 2020
6be2556
chore: cargo fmt
Jun 17, 2020
bfd8722
refactor: rename dir submodule to directory
Jun 17, 2020
ed8a2c3
doc: update unixfs/README.md and docs
Jun 17, 2020
c874e11
fix: windows build
Jun 17, 2020
0d2dd47
doc: refresh and check out cargo docs
Jun 17, 2020
24e4c4d
chore: cargo fmt
Jun 17, 2020
9aa9322
refactor: remove unused warnings on windows
Jun 17, 2020
d56058a
fix: use patched conformance tests
Jun 17, 2020
3bfa506
refactor: suggestions from code review
koivunej Jun 17, 2020
7b7ddbb
fix: add back self.depth assertions in set_path
Jun 17, 2020
ee8cab7
fix: remove dead code on bucket -> bucket transitions
Jun 17, 2020
629e338
refactor: unify InnerKind, switch todos to unreachable
Jun 17, 2020
b43ec1e
refactor: solidify link conversion
Jun 17, 2020
c70320d
refactor: suggestions from code review
koivunej Jun 17, 2020
a6167fc
chore: cargo fmt
Jun 17, 2020
0c5ad59
doc: add missing "for"
koivunej Jun 17, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/conformance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ jobs:
if: matrix.platform.cross == false
run: cargo build --workspace

- name: npm install
run: npm install
- name: Setup conformance tests
run: ./setup.sh
working-directory: ./conformance

- name: Symlink executable
Expand Down
29 changes: 29 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions http/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ warp = "0.2.2"
async-stream = "0.2.1"
pin-project = "0.4.8"
url = "2.1.1"
tar = { version = "0.4.28", default-features = false }
bytes = "0.5.4"

[dev-dependencies]
hex = "0.4.2"
hex-literal = "0.2.1"
2 changes: 1 addition & 1 deletion http/src/v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ pub fn routes<T: IpfsTypes>(
dag::put(ipfs),
dag::resolve(ipfs),
warp::path!("dht" / ..).and_then(not_implemented),
warp::path!("get").and_then(not_implemented),
root_files::cat(ipfs),
root_files::get(ipfs),
warp::path!("key" / ..).and_then(not_implemented),
warp::path!("name" / ..).and_then(not_implemented),
warp::path!("object" / ..).and_then(not_implemented),
Expand Down
29 changes: 22 additions & 7 deletions http/src/v0/refs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,18 @@ async fn refs_inner<T: IpfsTypes>(
formatter
);

let paths = opts
let mut paths = opts
.arg
.iter()
.map(|s| IpfsPath::try_from(s.as_str()).map_err(StringError::from))
.collect::<Result<Vec<_>, _>>()?;

for path in paths.iter_mut() {
// this is needed because the paths should not error on matching on the final Data segment,
// it just becomes projected as `Loaded::Raw(_)`, however such items can have no links.
path.set_follow_dagpb_data(true);
}

let st = refs_paths(ipfs, paths, max_depth, opts.unique)
.await
.map_err(|e| {
Expand Down Expand Up @@ -241,7 +247,7 @@ pub async fn walk_path<T: IpfsTypes>(
ipfs: &Ipfs<T>,
mut path: IpfsPath,
) -> Result<(Cid, Loaded, Vec<String>), WalkError> {
use ipfs::unixfs::ll::MaybeResolved;
use ipfs::unixfs::ll::{MaybeResolved, ResolveError};

let mut current = path.take_root().unwrap();

Expand Down Expand Up @@ -280,6 +286,13 @@ pub async fn walk_path<T: IpfsTypes>(
Ok(MaybeResolved::NotFound) => {
return handle_dagpb_not_found(current, &data, needle, &path)
}
Err(ResolveError::UnexpectedType(_)) => {
// the conformance tests use a path which would end up going through a file
// and the returned error string is tested against listed alternatives.
// unexpected type is not one of them.
let e = WalkFailed::from(path::WalkFailed::UnmatchedNamedLink(needle));
return Err(WalkError::from((e, current)));
}
Err(e) => return Err(WalkError::from((WalkFailed::from(e), current))),
};

Expand Down Expand Up @@ -360,10 +373,12 @@ fn handle_dagpb_not_found(
needle: String,
path: &IpfsPath,
) -> Result<(Cid, Loaded, Vec<String>), WalkError> {
if needle == "Data" && path.len() == 0 {
// /dag/resolve needs to "resolve through" a dag-pb node down to the "just
// data" even though we do not need to extract it ... however this might be
// good to just filter with refs, as no refs of such path exist
use ipfs::unixfs::ll::dagpb::node_data;

if needle == "Data" && path.len() == 0 && path.follow_dagpb_data() {
// /dag/resolve needs to "resolve through" a dag-pb node down to the "just data" even
// though we do not need to extract it ... however this might be good to just filter with
// refs, as no refs of such path can exist as the links are in the outer structure.
//
// testing with go-ipfs 0.5 reveals that dag resolve only follows links
// which are actually present in the dag-pb, not numeric links like Links/5
Expand All @@ -372,7 +387,7 @@ fn handle_dagpb_not_found(
// comment on this special casing: there cannot be any other such
// special case as the Links do not work like Data so while this is not
// pretty, it's not terrible.
let data = ipfs::unixfs::ll::dagpb::node_data(&data)
let data = node_data(&data)
.expect("already parsed once, second time cannot fail")
.unwrap_or_default();
Ok((at, Loaded::Ipld(Ipld::Bytes(data.to_vec())), vec![needle]))
Expand Down
20 changes: 19 additions & 1 deletion http/src/v0/refs/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ pub struct IpfsPath {
/// Option to support moving the cid
root: Option<Cid>,
path: std::vec::IntoIter<String>,
/// True by default, to allow "finding" `Data` under dag-pb node
/// TODO: document why this matters
follow_dagpb_data: bool,
}

impl From<Cid> for IpfsPath {
Expand All @@ -43,6 +46,7 @@ impl From<Cid> for IpfsPath {
IpfsPath {
root: Some(root),
path: Vec::new().into_iter(),
follow_dagpb_data: true,
}
}
}
Expand Down Expand Up @@ -90,7 +94,13 @@ impl TryFrom<&str> for IpfsPath {

let root = Some(Cid::try_from(root).map_err(PathError::InvalidCid)?);

Ok(IpfsPath { root, path })
let follow_dagpb_data = true;

Ok(IpfsPath {
root,
path,
follow_dagpb_data,
})
}
}

Expand All @@ -99,6 +109,14 @@ impl IpfsPath {
self.root.take()
}

pub fn set_follow_dagpb_data(&mut self, follow: bool) {
self.follow_dagpb_data = follow;
}

pub fn follow_dagpb_data(&self) -> bool {
self.follow_dagpb_data
}

pub fn resolve(&mut self, ipld: Ipld) -> Result<WalkSuccess, WalkFailed> {
let key = match self.next() {
Some(key) => key,
Expand Down
Loading