Skip to content

Commit 3c99521

Browse files
ElestriasMarkuu-s
authored andcommitted
parent 18e194b
author elestrias <[email protected]> 1644918587 +0300 committer Markuu-s <[email protected]> 1646871341 +0300
1 parent 18e194b commit 3c99521

File tree

15 files changed

+233
-82
lines changed

15 files changed

+233
-82
lines changed

core/api/rpc/info.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,12 @@ namespace fc::api::rpc {
2828
address = info.substr(0, i);
2929
token = info.substr(i + 1);
3030
} else if (!repo.empty()) {
31-
boost::filesystem::load_string_file(repo / "api", address);
32-
boost::filesystem::load_string_file(repo / "token", token);
31+
try {
32+
boost::filesystem::load_string_file(repo / "api", address);
33+
boost::filesystem::load_string_file(repo / "token", token);
34+
} catch (...) {
35+
return {};
36+
}
3337
} else {
3438
return {};
3539
}

core/cli/cli.hpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,30 @@ namespace fc::cli {
4848
// note: Args is defined inside command
4949
using Argv = std::vector<std::string>;
5050

51+
const std::string &cliArgv(const Argv &argv,
52+
size_t i,
53+
const std::string_view &name) {
54+
if (i < argv.size()) {
55+
return argv[i];
56+
}
57+
throw CliError{"positional argument {} is required but missing", name};
58+
}
59+
template <typename T>
60+
T cliArgv(const std::string &arg, const std::string_view &name) {
61+
boost::any out;
62+
try {
63+
po::value<T>()->xparse(out, Argv{arg});
64+
} catch (po::validation_error &e) {
65+
e.set_option_name(std::string{name});
66+
throw;
67+
}
68+
return boost::any_cast<T>(out);
69+
}
70+
template <typename T>
71+
T cliArgv(const Argv &argv, size_t i, const std::string_view &name) {
72+
return cliArgv<T>(cliArgv(argv, i, name), name);
73+
}
74+
5175
struct Empty {
5276
struct Args {
5377
CLI_OPTS() {

core/cli/node/client.hpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ namespace fc::cli::_node {
2020
boost::filesystem::path path;
2121
std::string provider;
2222
bool car{};
23+
std::string root;
2324

2425
CLI_OPTS() {
2526
Opts opts;
@@ -39,12 +40,14 @@ namespace fc::cli::_node {
3940
option("car",
4041
po::bool_switch(&car),
4142
"store result of retrieval deal to car file");
43+
option("root-CID", po::value(&root), "Specifies root CID for retrieval deal");
4244
return opts;
4345
}
4446
};
4547

4648
CLI_RUN() {
4749
Node::Api api{argm};
50+
CLI_TRY_TEXT(root, CID::fromString(args.root), "Invalid root CID: " + args.root);
4851
CLI_TRY_TEXT(cid,
4952
CID::fromString(args.piece_cid),
5053
"Invalid piece CID: " + args.piece_cid)
@@ -118,6 +121,23 @@ namespace fc::cli::_node {
118121
}
119122
};
120123

124+
struct clientFind{
125+
struct Args{
126+
127+
CLI_OPTS(){
128+
Opts opts;
129+
auto option{opts.add_options()};
130+
131+
}
132+
};
133+
134+
};
135+
136+
137+
138+
139+
140+
121141

122142

123143
} // namespace fc::cli::_node

core/cli/node/net.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace fc::cli::_node {
1111
struct Node_net_listen : Empty {
1212
CLI_RUN() {
1313
Node::Api api{argm};
14-
const auto peer{api._->NetAddrsListen().value()};
14+
const auto peer{cliTry(api._->NetAddrsListen())};
1515
for (const auto &addr : peer.addresses) {
1616
fmt::print("{}\n", addr.getStringAddress());
1717
}

core/cli/node/node.hpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#include "api/rpc/client_setup.hpp"
1111
#include "api/rpc/info.hpp"
1212
#include "cli/cli.hpp"
13+
#include "cli/try.hpp"
14+
#include "common/libp2p/multi/multiaddress_fmt.hpp"
1315
#include "node/node_version.hpp"
1416

1517
namespace fc::cli::_node {
@@ -41,12 +43,15 @@ namespace fc::cli::_node {
4143

4244
Api(const ArgsMap &argm) {
4345
const auto &args{argm.of<Node>()};
44-
const auto info{
45-
*api::rpc::loadInfo(args.repo.value_or(""), "FULLNODE_API_INFO")};
46+
const auto info{cliTry(
47+
api::rpc::loadInfo(args.repo.value_or(""), "FULLNODE_API_INFO").o,
48+
"api info is missing")};
4649
_ = std::make_shared<api::FullNodeApi>();
4750
wsc = std::make_shared<api::rpc::Client>(*thread.io);
4851
wsc->setup(*_);
49-
wsc->connect(info.first, "/rpc/v1", info.second).value();
52+
cliTry(wsc->connect(info.first, "/rpc/v1", info.second),
53+
"connecting to {}",
54+
info.first);
5055
}
5156
};
5257
};

core/cli/run.hpp

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@
55

66
#pragma once
77

8-
#include <fmt/format.h>
9-
#include <fmt/ostream.h>
108
#include <boost/program_options/parsers.hpp>
119
#include <boost/program_options/variables_map.hpp>
1210

1311
#include "cli/tree.hpp"
12+
#include "cli/try.hpp"
1413

1514
namespace fc::cli {
1615
inline bool isDash(const std::string &s) {
@@ -20,7 +19,8 @@ namespace fc::cli {
2019
return s.size() == 2 && s[0] == '-' && s[1] == '-';
2120
}
2221
// note: returns first positional arg or end
23-
inline Argv::iterator hackBoost(const Opts &opts,
22+
inline Argv::iterator hackBoost(po::variables_map &vm,
23+
const Opts &opts,
2424
Argv::iterator begin,
2525
Argv::iterator end) {
2626
po::parsed_options parsed{&opts};
@@ -49,9 +49,7 @@ namespace fc::cli {
4949
begin += option.original_tokens.size();
5050
}
5151
}
52-
po::variables_map vm;
5352
po::store(parsed, vm);
54-
po::notify(vm);
5553
return begin;
5654
}
5755

@@ -64,12 +62,18 @@ namespace fc::cli {
6462
while (true) {
6563
auto args{tree->args()};
6664
auto option{args.opts.add_options()};
67-
bool help{};
68-
// note: help doesn't work with required options
69-
option("help,h", po::bool_switch(&help));
70-
argv_it = hackBoost(args.opts, argv_it, argv.end());
71-
argm._.emplace(args._);
65+
option("help,h", "print help");
66+
po::variables_map vm;
67+
try {
68+
argv_it = hackBoost(vm, args.opts, argv_it, argv.end());
69+
} catch (po::error &e) {
70+
fmt::print("{}: {}\n", fmt::join(cmds, " "), e.what());
71+
return;
72+
}
73+
const auto help{vm.count("help") != 0};
7274
if (!help) {
75+
po::notify(vm);
76+
argm._.emplace(args._);
7377
if (argv_it != argv.end()) {
7478
auto sub_it{tree->sub.find(*argv_it)};
7579
if (sub_it != tree->sub.end()) {
@@ -83,6 +87,12 @@ namespace fc::cli {
8387
try {
8488
return tree->run(argm, {argv_it, argv.end()});
8589
} catch (ShowHelp &) {
90+
} catch (po::error &e) {
91+
fmt::print("{}: {}\n", fmt::join(cmds, " "), e.what());
92+
return;
93+
} catch (CliError &e) {
94+
fmt::print("{}: {}\n", fmt::join(cmds, " "), e.what());
95+
return;
8696
}
8797
}
8898
}

core/cli/try.hpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/**
2+
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#pragma once
7+
8+
#include <fmt/format.h>
9+
#include <fmt/ostream.h>
10+
#include <boost/optional.hpp>
11+
12+
#include "common/outcome.hpp"
13+
#include "common/outcome_fmt.hpp"
14+
15+
namespace fc::cli {
16+
struct CliError : std::runtime_error {
17+
template <typename... Args>
18+
CliError(const std::string_view &format, const Args &...args)
19+
: runtime_error{fmt::format(format, args...)} {}
20+
};
21+
22+
template <typename R, typename... Args>
23+
auto cliTry(outcome::result<R> &&o,
24+
const std::string_view &format,
25+
const Args &...args) {
26+
if (o) {
27+
return std::move(o).value();
28+
}
29+
throw CliError{
30+
"{} (error_code: {:#})", fmt::format(format, args...), o.error()};
31+
}
32+
33+
template <typename R>
34+
auto cliTry(outcome::result<R> &&o) {
35+
return cliTry(std::move(o), "outcome::result");
36+
}
37+
38+
template <typename R, typename... Args>
39+
auto cliTry(boost::optional<R> &&o,
40+
const std::string_view &format,
41+
const Args &...args) {
42+
if (o) {
43+
return std::move(o).value();
44+
}
45+
throw CliError{format, args...};
46+
}
47+
48+
template <typename R>
49+
auto cliTry(boost::optional<R> &&o) {
50+
return cliTry(std::move(o), "boost::optional");
51+
}
52+
} // namespace fc::cli

core/cli/validate/address.hpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#pragma once
7+
8+
#include "cli/validate/with.hpp"
9+
#include "primitives/address/address_codec.hpp"
10+
11+
namespace fc::primitives::address {
12+
CLI_VALIDATE(Address) {
13+
return validateWith(out, values, [](const std::string &value) {
14+
return decodeFromString(value).value();
15+
});
16+
}
17+
} // namespace fc::primitives::address

core/cli/validate/cid.hpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#pragma once
7+
8+
#include "cli/validate/with.hpp"
9+
#include "primitives/cid/cid.hpp"
10+
11+
namespace fc {
12+
CLI_VALIDATE(CID) {
13+
return validateWith(out, values, [](const std::string &value) {
14+
return CID::fromString(value).value();
15+
});
16+
}
17+
} // namespace fc

core/cli/validate/with.hpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#pragma once
7+
8+
#include <boost/program_options/value_semantic.hpp>
9+
10+
#define CLI_VALIDATE(TYPE) \
11+
inline void validate( \
12+
boost::any &out, const std::vector<std::string> &values, TYPE *, int)
13+
14+
namespace fc {
15+
template <typename F>
16+
void validateWith(boost::any &out,
17+
const std::vector<std::string> &values,
18+
const F &f) {
19+
namespace po = boost::program_options;
20+
po::check_first_occurrence(out);
21+
const auto &value{po::get_single_string(values)};
22+
try {
23+
out = f(value);
24+
} catch (...) {
25+
boost::throw_exception(po::invalid_option_value{value});
26+
}
27+
}
28+
} // namespace fc

0 commit comments

Comments
 (0)