summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFerris Tseng <ferristseng@fastmail.fm>2017-11-24 23:13:55 -0500
committerFerris Tseng <ferristseng@fastmail.fm>2017-11-24 23:13:55 -0500
commitfeb3931bd8ebc073e254fed0de966e71a668f71b (patch)
treeccc4b777b4fc2873f3cabc2c5064bc6ff3f80548
parentdcd6f22f7c21ee8985e5de7f962818ac93bc5b26 (diff)
refactoring and new calls
-rw-r--r--ipfs-api/src/response/block.rs2
-rw-r--r--ipfs-cli/src/command/add.rs35
-rw-r--r--ipfs-cli/src/command/bitswap.rs92
-rw-r--r--ipfs-cli/src/command/block.rs81
-rw-r--r--ipfs-cli/src/command/bootstrap.rs79
-rw-r--r--ipfs-cli/src/command/mod.rs31
-rw-r--r--ipfs-cli/src/command/version.rs34
-rw-r--r--ipfs-cli/src/main.rs86
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!(),
}
}