diff options
author | Ferris Tseng <ferristseng@fastmail.fm> | 2017-11-24 23:13:55 -0500 |
---|---|---|
committer | Ferris Tseng <ferristseng@fastmail.fm> | 2017-11-24 23:13:55 -0500 |
commit | feb3931bd8ebc073e254fed0de966e71a668f71b (patch) | |
tree | ccc4b777b4fc2873f3cabc2c5064bc6ff3f80548 | |
parent | dcd6f22f7c21ee8985e5de7f962818ac93bc5b26 (diff) |
refactoring and new calls
-rw-r--r-- | ipfs-api/src/response/block.rs | 2 | ||||
-rw-r--r-- | ipfs-cli/src/command/add.rs | 35 | ||||
-rw-r--r-- | ipfs-cli/src/command/bitswap.rs | 92 | ||||
-rw-r--r-- | ipfs-cli/src/command/block.rs | 81 | ||||
-rw-r--r-- | ipfs-cli/src/command/bootstrap.rs | 79 | ||||
-rw-r--r-- | ipfs-cli/src/command/mod.rs | 31 | ||||
-rw-r--r-- | ipfs-cli/src/command/version.rs | 34 | ||||
-rw-r--r-- | ipfs-cli/src/main.rs | 86 |
8 files changed, 374 insertions, 66 deletions
diff --git a/ipfs-api/src/response/block.rs b/ipfs-api/src/response/block.rs index c909c27..f1a816e 100644 --- a/ipfs-api/src/response/block.rs +++ b/ipfs-api/src/response/block.rs @@ -21,7 +21,7 @@ pub struct BlockPutResponse { #[serde(rename_all = "PascalCase")] pub struct BlockRmResponse { pub hash: String, - pub error: String, + pub error: Option<String>, } diff --git a/ipfs-cli/src/command/add.rs b/ipfs-cli/src/command/add.rs new file mode 100644 index 0000000..cc5c5e6 --- /dev/null +++ b/ipfs-cli/src/command/add.rs @@ -0,0 +1,35 @@ +// Copyright 2017 rust-ipfs-api Developers +// +// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or +// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or +// http://opensource.org/licenses/MIT>, at your option. This file may not be +// copied, modified, or distributed except according to those terms. +// + +use clap::{App, ArgMatches}; +use command::{verify_file, EXPECTED_API}; +use ipfs_api::IpfsClient; +use std::fs::File; +use tokio_core::reactor::Core; + + +pub fn signature<'a, 'b>() -> App<'a, 'b> { + clap_app!( + @subcommand add => + (about: "Add file to ipfs") + (@arg INPUT: +required {verify_file} "File to add") + ) +} + + +pub fn handle(core: &mut Core, client: &IpfsClient, args: &ArgMatches) { + let path = args.value_of("INPUT").unwrap(); + let file = File::open(path).expect("expected to read input file"); + let response = core.run(client.add(file)).expect(EXPECTED_API); + + println!(""); + println!(" name : {}", response.name); + println!(" hash : {}", response.hash); + println!(" size : {}", response.size); + println!(""); +} diff --git a/ipfs-cli/src/command/bitswap.rs b/ipfs-cli/src/command/bitswap.rs new file mode 100644 index 0000000..fe03048 --- /dev/null +++ b/ipfs-cli/src/command/bitswap.rs @@ -0,0 +1,92 @@ +// Copyright 2017 rust-ipfs-api Developers +// +// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or +// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or +// http://opensource.org/licenses/MIT>, at your option. This file may not be +// copied, modified, or distributed except according to those terms. +// + +use clap::{App, ArgMatches}; +use command::EXPECTED_API; +use ipfs_api::IpfsClient; +use tokio_core::reactor::Core; + + +pub fn signature<'a, 'b>() -> App<'a, 'b> { + clap_app!( + @subcommand bitswap => + (@setting SubcommandRequiredElseHelp) + (@subcommand ledger => + (about: "Show the current ledger for a peer") + (@arg PEER: +required "Peer to inspect") + ) + (@subcommand stat => + (about: "Show some diagnostic information on the bitswap agent") + ) + (@subcommand unwant => + (about: "Remove a given block from your wantlist") + (@arg KEY: +required "Key of the block to remove") + ) + (@subcommand wantlist => + (about: "Shows blocks currently on the wantlist") + ) + ) +} + + +pub fn handle(core: &mut Core, client: &IpfsClient, bitswap: &ArgMatches) { + match bitswap.subcommand() { + ("ledger", Some(ref args)) => { + let peer = args.value_of("PEER").unwrap(); + let ledger = core.run(client.bitswap_ledger(&peer)).expect(EXPECTED_API); + + println!(""); + println!(" peer : {}", ledger.peer); + println!(" value : {}", ledger.value); + println!(" sent : {}", ledger.sent); + println!(" recv : {}", ledger.recv); + println!(" exchanged : {}", ledger.exchanged); + println!(""); + } + ("stat", _) => { + let stat = core.run(client.bitswap_stat()).expect(EXPECTED_API); + + println!(""); + println!(" provide_buf_len : {}", stat.provide_buf_len); + println!(" wantlist :"); + for want in stat.wantlist { + println!(" {}", want); + } + println!(" peers :"); + for peer in stat.peers { + println!(" {}", peer); + } + println!(" blocks_received : {}", stat.blocks_received); + println!(" data_received : {}", stat.data_received); + println!(" blocks_sent : {}", stat.blocks_sent); + println!(" data_sent : {}", stat.data_sent); + println!(" dup_blks_received : {}", stat.dup_blks_received); + println!(" dup_data_received : {}", stat.dup_data_received); + println!(""); + } + ("unwant", Some(ref args)) => { + let key = args.value_of("KEY").unwrap(); + + core.run(client.bitswap_unwant(&key)).expect(EXPECTED_API); + + println!("OK"); + } + ("wantlist", Some(ref args)) => { + let peer = args.value_of("PEER"); + let wantlist = core.run(client.bitswap_wantlist(peer)).expect(EXPECTED_API); + + println!(""); + println!(" wantlist :"); + for key in wantlist.keys { + println!(" {}", key); + } + println!(""); + } + _ => unreachable!(), + } +} diff --git a/ipfs-cli/src/command/block.rs b/ipfs-cli/src/command/block.rs new file mode 100644 index 0000000..848b799 --- /dev/null +++ b/ipfs-cli/src/command/block.rs @@ -0,0 +1,81 @@ +// Copyright 2017 rust-ipfs-api Developers +// +// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or +// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or +// http://opensource.org/licenses/MIT>, at your option. This file may not be +// copied, modified, or distributed except according to those terms. +// + +use clap::{App, ArgMatches}; +use command::{verify_file, EXPECTED_API}; +use ipfs_api::IpfsClient; +use std::fs::File; +use tokio_core::reactor::Core; + + +pub fn signature<'a, 'b>() -> App<'a, 'b> { + clap_app!( + @subcommand block => + (@setting SubcommandRequiredElseHelp) + (@subcommand get => + (about: "Get a raw IPFS block") + (@arg KEY: +required "The base58 multihash of an existing block") + ) + (@subcommand put => + (about: "Store a file as an IPFS block") + (@arg INPUT: +required {verify_file} "The file to store as an IPFS block") + ) + (@subcommand rm => + (about: "Removes an IPFS block") + (@arg KEY: +required "The base58 multihash of a block to remove") + ) + (@subcommand stat => + (about: "Get information about a raw IPFS block") + (@arg KEY: +required "The base58 multihash of the block to retrieve") + ) + ) +} + + +pub fn handle(core: &mut Core, client: &IpfsClient, block: &ArgMatches) { + match block.subcommand() { + ("get", Some(args)) => { + let key = args.value_of("KEY").unwrap(); + let block = core.run(client.block_get(key)).expect(EXPECTED_API); + + println!("{}", String::from_utf8_lossy(&block)); + } + ("put", Some(args)) => { + let path = args.value_of("INPUT").unwrap(); + let file = File::open(path).expect("expected to read input file"); + let block = core.run(client.block_put(file)).expect(EXPECTED_API); + + println!(""); + println!(" key : {}", block.key); + println!(" size : {}", block.size); + println!(""); + } + ("rm", Some(args)) => { + let key = args.value_of("KEY").unwrap(); + let rm = core.run(client.block_rm(key)).expect(EXPECTED_API); + + println!(""); + println!(" hash : {}", rm.hash); + if let Some(error) = rm.error { + println!(" error : {}", error); + } + println!(""); + } + ("stat", Some(args)) => { + let key = args.value_of("KEY").unwrap(); + let stat = core.run(client.block_stat(key)).expect(EXPECTED_API); + + println!(""); + println!(" key : {}", stat.key); + println!(" size : {}", stat.size); + println!(""); + } + _ => unreachable!(), + } + +} diff --git a/ipfs-cli/src/command/bootstrap.rs b/ipfs-cli/src/command/bootstrap.rs new file mode 100644 index 0000000..04d3022 --- /dev/null +++ b/ipfs-cli/src/command/bootstrap.rs @@ -0,0 +1,79 @@ +// Copyright 2017 rust-ipfs-api Developers +// +// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or +// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or +// http://opensource.org/licenses/MIT>, at your option. This file may not be +// copied, modified, or distributed except according to those terms. +// + +use clap::{App, ArgMatches}; +use command::EXPECTED_API; +use ipfs_api::IpfsClient; +use tokio_core::reactor::Core; + + +pub fn signature<'a, 'b>() -> App<'a, 'b> { + clap_app!( + @subcommand bootstrap => + (@setting SubcommandRequiredElseHelp) + (@subcommand add => + (@setting SubcommandRequiredElseHelp) + (@subcommand default => + (about: "Add default peers to the bootstrap list") + ) + ) + (@subcommand list => + (about: "Show peers in the bootstrap list") + ) + (@subcommand rm => + (@setting SubcommandRequiredElseHelp) + (@subcommand all => + (about: "Remove all peers from the bootstrap list") + ) + ) + ) +} + + +fn print_peers(peers: &Vec<String>) { + println!(""); + println!(" peers :"); + for peer in peers { + println!(" {}", peer); + } + println!(""); +} + + +pub fn handle(core: &mut Core, client: &IpfsClient, bootstrap: &ArgMatches) { + match bootstrap.subcommand() { + ("add", Some(add)) => { + match add.subcommand() { + ("default", _) => { + let peers = core.run(client.bootstrap_add_default()).expect( + EXPECTED_API, + ); + + print_peers(&peers.peers); + } + _ => unreachable!(), + } + } + ("list", _) => { + let peers = core.run(client.bootstrap_list()).expect(EXPECTED_API); + + print_peers(&peers.peers); + } + ("rm", Some(rm)) => { + match rm.subcommand() { + ("all", _) => { + let peers = core.run(client.bootstrap_rm_all()).expect(EXPECTED_API); + + print_peers(&peers.peers); + } + _ => unreachable!(), + } + } + _ => unreachable!(), + } +} diff --git a/ipfs-cli/src/command/mod.rs b/ipfs-cli/src/command/mod.rs new file mode 100644 index 0000000..498fafb --- /dev/null +++ b/ipfs-cli/src/command/mod.rs @@ -0,0 +1,31 @@ +// Copyright 2017 rust-ipfs-api Developers +// +// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or +// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or +// http://opensource.org/licenses/MIT>, at your option. This file may not be +// copied, modified, or distributed except according to those terms. +// + +use std::error::Error; +use std::fs; + + +pub const EXPECTED_API: &'static str = "expected response from API"; + + +/// Verifies that a path points to a file that exists, and not a directory. +/// +pub fn verify_file(path: String) -> Result<(), String> { + match fs::metadata(path) { + Ok(ref metadata) if metadata.is_file() => Ok(()), + Ok(_) => Err("file must not be a directory".into()), + Err(e) => Err(e.description().into()), + } +} + + +pub mod add; +pub mod bitswap; +pub mod block; +pub mod bootstrap; +pub mod version; diff --git a/ipfs-cli/src/command/version.rs b/ipfs-cli/src/command/version.rs new file mode 100644 index 0000000..380cd8b --- /dev/null +++ b/ipfs-cli/src/command/version.rs @@ -0,0 +1,34 @@ +// Copyright 2017 rust-ipfs-api Developers +// +// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or +// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or +// http://opensource.org/licenses/MIT>, at your option. This file may not be +// copied, modified, or distributed except according to those terms. +// + +use clap::App; +use ipfs_api::IpfsClient; +use tokio_core::reactor::Core; + + +pub fn signature<'a, 'b>() -> App<'a, 'b> { + clap_app!( + @subcommand version => + (about: "Show ipfs version information") + ) +} + + +pub fn handle(core: &mut Core, client: &IpfsClient) { + let version = core.run(client.version()).expect( + "expected response from API", + ); + + println!(""); + println!(" version : {}", version.version); + println!(" commit : {}", version.commit); + println!(" repo : {}", version.repo); + println!(" system : {}", version.system); + println!(" golang : {}", version.golang); + println!(""); +} diff --git a/ipfs-cli/src/main.rs b/ipfs-cli/src/main.rs index 815674b..3849272 100644 --- a/ipfs-cli/src/main.rs +++ b/ipfs-cli/src/main.rs @@ -1,12 +1,21 @@ +// Copyright 2017 rust-ipfs-api Developers +// +// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or +// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or +// http://opensource.org/licenses/MIT>, at your option. This file may not be +// copied, modified, or distributed except according to those terms. +// + #[macro_use] extern crate clap; extern crate ipfs_api; extern crate tokio_core; use ipfs_api::IpfsClient; -use std::fs::File; use tokio_core::reactor::Core; +mod command; + fn main() { let matches = clap_app!( app => @@ -15,77 +24,24 @@ fn main() { (version: crate_version!()) (author: "Ferris T. <ferristseng@fastmail.fm>") (@setting SubcommandRequiredElseHelp) - (@subcommand add => - (about: "Add file to ipfs") - (@arg INPUT: +required "File to add") - ) - (@subcommand bitswap => - (@setting SubcommandRequiredElseHelp) - (@subcommand ledger => - (about: "Show the current ledger for a peer") - (@arg PEER: +required "Peer to inspect") - ) - ) - (@subcommand version => - (about: "Show ipfs version information") - ) + (subcommand: command::add::signature()) + (subcommand: command::bitswap::signature()) + (subcommand: command::block::signature()) + (subcommand: command::bootstrap::signature()) + (subcommand: command::version::signature()) ).get_matches(); let mut core = Core::new().expect("expected event loop"); let client = IpfsClient::default(&core.handle()); match matches.subcommand() { - ("add", Some(args)) => { - let path = args.value_of("INPUT").unwrap(); - let file = File::open(path).expect("expected to read input file"); - let metadata = file.metadata().expect("expected to read file's metadata"); - - if !metadata.is_file() { - panic!("input must be a file not directory"); - } - - let response = core.run(client.add(file)).expect( - "expected response from API", - ); - - println!(""); - println!(" name : {}", response.name); - println!(" hash : {}", response.hash); - println!(" size : {}", response.size); - println!(""); - } - ("bitswap", Some(bitswap)) => { - match bitswap.subcommand() { - ("ledger", Some(ledger)) => { - let peer = ledger.value_of("PEER").unwrap(); - let ledger = core.run(client.bitswap_ledger(&peer)).expect( - "expected response from API", - ); - - println!(""); - println!(" peer : {}", ledger.peer); - println!(" value : {}", ledger.value); - println!(" sent : {}", ledger.sent); - println!(" recv : {}", ledger.recv); - println!(" exchanged : {}", ledger.exchanged); - println!(""); - } - _ => unreachable!(), - } - } - ("version", _) => { - let version = core.run(client.version()).expect( - "expected response from API", - ); - - println!(""); - println!(" version : {}", version.version); - println!(" commit : {}", version.commit); - println!(" repo : {}", version.repo); - println!(" system : {}", version.system); - println!(" golang : {}", version.golang); - println!(""); + ("add", Some(args)) => command::add::handle(&mut core, &client, args), + ("bitswap", Some(bitswap)) => command::bitswap::handle(&mut core, &client, &bitswap), + ("block", Some(block)) => command::block::handle(&mut core, &client, &block), + ("bootstrap", Some(bootstrap)) => { + command::bootstrap::handle(&mut core, &client, &bootstrap) } + ("version", _) => command::version::handle(&mut core, &client), _ => unreachable!(), } } |