cli: Allow custom cluster config (#2271)

* cli: Allow custom cluster config

* Update changelog

* Downgrade the code

* Fix rust fmt

Co-authored-by: Henry-E <henry.elder@adaptcentre.ie>
This commit is contained in:
Jean Marchand (Exotic Markets) 2022-11-22 17:33:44 +01:00 committed by GitHub
parent 5291a7b6ff
commit b8cda8a717
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 70 additions and 6 deletions

View File

@ -29,7 +29,8 @@ The minor version will be incremented upon a breaking change and the patch versi
- ts: Add ability to resolve missing accounts with a custom resolver ([#2194](https://github.com/coral-xyz/anchor/pull/2194))
- ts: Update the Solana web3 library used by anchor ts to version 1.64.0 ([#2220](https://github.com/coral-xyz/anchor/issues/2220))
- lang: Updates `AccountsClose` to make it safe to call manually ([#2209](https://github.com/coral-xyz/anchor/pull/2209))
- lang: Update rust used in the repo version 1.64 ([#2272](https://github.com/coral-xyz/anchor/pull/2272))
- lang: Update rust used in the repo version 1.62 ([#2272](https://github.com/coral-xyz/anchor/pull/2272))
- cli: Allow custom cluster config ([#2271](https://github.com/coral-xyz/anchor/pull/2271)).
### Fixes

View File

@ -4,19 +4,22 @@ use anchor_syn::idl::Idl;
use anyhow::{anyhow, Context, Error, Result};
use clap::{Parser, ValueEnum};
use heck::ToSnakeCase;
use serde::{Deserialize, Serialize};
use reqwest::Url;
use serde::de::{self, MapAccess, Visitor};
use serde::{Deserialize, Deserializer, Serialize};
use solana_cli_config::{Config as SolanaConfig, CONFIG_FILE};
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::{Keypair, Signer};
use std::collections::{BTreeMap, HashMap};
use std::convert::TryFrom;
use std::fs::{self, File};
use std::io;
use std::io::prelude::*;
use std::marker::PhantomData;
use std::ops::Deref;
use std::path::Path;
use std::path::PathBuf;
use std::str::FromStr;
use std::{fmt, io};
use walkdir::WalkDir;
pub trait Merge: Sized {
@ -420,10 +423,58 @@ struct _Config {
#[derive(Debug, Serialize, Deserialize)]
struct Provider {
cluster: String,
#[serde(deserialize_with = "des_cluster")]
cluster: Cluster,
wallet: String,
}
fn des_cluster<'de, D>(deserializer: D) -> Result<Cluster, D::Error>
where
D: Deserializer<'de>,
{
struct StringOrCustomCluster(PhantomData<fn() -> Cluster>);
impl<'de> Visitor<'de> for StringOrCustomCluster {
type Value = Cluster;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("string or map")
}
fn visit_str<E>(self, value: &str) -> Result<Cluster, E>
where
E: de::Error,
{
value.parse().map_err(de::Error::custom)
}
fn visit_map<M>(self, mut map: M) -> Result<Cluster, M::Error>
where
M: MapAccess<'de>,
{
// Gets keys
if let (Some((http_key, http_value)), Some((ws_key, ws_value))) = (
map.next_entry::<String, String>()?,
map.next_entry::<String, String>()?,
) {
// Checks keys
if http_key != "http" || ws_key != "ws" {
return Err(de::Error::custom("Invalid key"));
}
// Checks urls
Url::parse(&http_value).map_err(de::Error::custom)?;
Url::parse(&ws_value).map_err(de::Error::custom)?;
Ok(Cluster::Custom(http_value, ws_value))
} else {
Err(de::Error::custom("Invalid entry"))
}
}
}
deserializer.deserialize_any(StringOrCustomCluster(PhantomData))
}
impl ToString for Config {
fn to_string(&self) -> String {
let programs = {
@ -440,7 +491,7 @@ impl ToString for Config {
features: Some(self.features.clone()),
registry: Some(self.registry.clone()),
provider: Provider {
cluster: format!("{}", self.provider.cluster),
cluster: self.provider.cluster.clone(),
wallet: self.provider.wallet.to_string(),
},
test: self.test_validator.clone().map(Into::into),
@ -469,7 +520,7 @@ impl FromStr for Config {
features: cfg.features.unwrap_or_default(),
registry: cfg.registry.unwrap_or_default(),
provider: ProviderConfig {
cluster: cfg.provider.cluster.parse()?,
cluster: cfg.provider.cluster,
wallet: shellexpand::tilde(&cfg.provider.wallet).parse()?,
},
scripts: cfg.scripts.unwrap_or_default(),
@ -1139,6 +1190,18 @@ mod tests {
wallet = \"id.json\"
";
const CUSTOM_CONFIG: &str = "
[provider]
cluster = { http = \"http://my-url.com\", ws = \"ws://my-url.com\" }
wallet = \"id.json\"
";
#[test]
fn parse_custom_cluster() {
let config = Config::from_str(CUSTOM_CONFIG).unwrap();
assert!(!config.features.skip_lint);
}
#[test]
fn parse_skip_lint_no_section() {
let config = Config::from_str(BASE_CONFIG).unwrap();