Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: replace manifest.json with {.dfx/}canister_ids.json #815

Merged
merged 10 commits into from
Jul 15, 2020

Conversation

ericswanson-dfinity
Copy link
Member

Implements #780

Removed the canister manifest (which had one canister ID per canister, as well as paths to outputs) and replaced it with two files:

  • .dfx/canister_ids.json: stores ephemeral canister ids for (typically) local "networks"
  • canister_ids.json: stores persistent canister ids for (typically) remote networks.

The dfx create command populates these files, while other commands use the values.

Added a NetworkDescriptor field to Environment (though really only AgentEnvironment), in order to tell which canister_ids.json file to use.

Added to dfx.json networks a type field ("persistent" or "ephemeral")

@ericswanson-dfinity ericswanson-dfinity requested a review from a team as a code owner July 14, 2020 23:42
@p-shahi
Copy link
Contributor

p-shahi commented Jul 15, 2020

@ericswanson-dfinity I believe src/dfx/assets/new_project_files/dfx.json should be updated with the new json fields...although, the e2e tests seem to indicate that is not necessary!

use std::path::PathBuf;

pub fn canister_did_location(canister_name: &str) -> PathBuf {
PathBuf::from(format!("canisters/{}/{}.did", canister_name, canister_name))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to double check: is the did file always under canisters/ or the build output directory specified in dfx.json?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we were going to remove that output directory (and have everything go under .dfx/somewhere), but until that is done, this should probably point to wherever dfx.json says.

Copy link
Contributor

@hansl hansl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some changes, but nothing major.

@@ -173,6 +185,25 @@ impl Display for DfxError {
DfxError::NoLocalNetworkProviderFound => {
f.write_str("Expected there to be a local network with a bind address")?;
}
DfxError::CouldNotFindCanisterIdForNetwork(canister, network) => {
f.write_fmt(format_args!(
"Cannot find canister id. Please issue 'dfx canister --network {} create {}'.",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we special case network == "local" if that's the default?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hah, I did first try to only make it include the --network {} part if network != "local", but ran into trouble. I'll try again.

canister_id: RefCell::new(None),

manifest_path,
canister_id: RefCell::new(canister_id),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems to me we don't need a RefCell anymore (since we panic if it's not set), correct? If so I'd like to get rid of it. They're usually an anti-pattern. Simply Option should do the trick.

let identity = get_profile_path().expect("Failed to access profile");
let agent_url = network_descriptor.providers.first().unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably be random in this case. Actually, could you add an issue to have ic-agent support having multiple providers in round robin? This would probably be the better place to make this change. If you do that then this code is okay for now.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let canister_type = canister_config
.r#type
.as_ref()
.cloned()
.unwrap_or_else(|| "motoko".to_owned());

let canister_id = canister_id_store
.map(|store| store.get_canister_id(name))
.transpose()?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh that's neat.


let maybe_canister_id = canister_id_store.find_canister_id(&info.get_name());
if let Some(canister_id) = maybe_canister_id {
info.set_canister_id(canister_id)?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be why it's still a RefCell, but it seems we could pass that to the constructor... or not sure actually.

pub ids: CanisterIds,
}

impl CanisterIdStore {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since many functions here has canister_id, what do you think of simplifying their names as it's redundant and the types already give you that information. So add_canister_id => add, find_canister_id => find. Also, remove canister where it feels redundant; get_canister_name => get_name.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, sounds good

@@ -258,15 +214,6 @@ impl CanisterPool {
for canister in &self.canisters {
if build_config.build_mode_check {
canister.generate_and_set_canister_id()?;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hansl When trying to remove the RefCell, I run into this here:

error[E0596]: cannot borrow data in an `Arc` as mutable
   --> src/dfx/src/lib/models/canister.rs:218:17
    |
218 |                 canister.generate_and_set_canister_id()?;
    |                 ^^^^^^^^ cannot borrow as mutable
    |
    = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::sync::Arc<lib::models::canister::Canister>`

Copy link
Contributor

@hansl hansl Jul 15, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it makes canister info immutable. If that's too much trouble we can defer to another PR.

pub struct CanisterManifest {
pub canisters: Map<String, serde_json::value::Value>,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct CanManMetadata {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this struct should be deleted

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@mergify mergify bot merged commit 88e2e41 into master Jul 15, 2020
@p-shahi p-shahi deleted the ericswanson-780-canister-ids-json branch July 15, 2020 20:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants