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

Support both gel.toml and edgedb.toml #355

Merged
merged 2 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 50 additions & 25 deletions edgedb-tokio/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::credentials::{Credentials, TlsSecurity};
use crate::errors::{ClientError, Error, ErrorKind, ResultExt};
use crate::errors::{ClientNoCredentialsError, NoCloudConfigFound};
use crate::errors::{InterfaceError, InvalidArgumentError};
use crate::tls;
use crate::{tls, PROJECT_FILES};

pub const DEFAULT_CONNECT_TIMEOUT: Duration = Duration::from_secs(10);
pub const DEFAULT_WAIT: Duration = Duration::from_secs(30);
Expand Down Expand Up @@ -220,20 +220,6 @@ fn has_port_env() -> bool {
}
}

pub async fn search_dir(base: &Path) -> Result<Option<&Path>, Error> {
let mut path = base;
if fs::metadata(path.join("edgedb.toml")).await.is_ok() {
return Ok(Some(path));
}
while let Some(parent) = path.parent() {
if fs::metadata(parent.join("edgedb.toml")).await.is_ok() {
return Ok(Some(parent));
}
path = parent;
}
Ok(None)
}

#[cfg(unix)]
fn path_bytes(path: &Path) -> &'_ [u8] {
use std::os::unix::ffi::OsStrExt;
Expand Down Expand Up @@ -2381,7 +2367,8 @@ fn test_instance_name() {
}
}

/// Searches for project dir either from current dir or from specified
/// Searches for a project directory either from the current director or from a
/// specified directory, optionally searching parent directories.
pub async fn get_project_dir(
override_dir: Option<&Path>,
search_parents: bool,
Expand All @@ -2394,16 +2381,54 @@ pub async fn get_project_dir(
})?),
};

if search_parents {
if let Some(ancestor) = search_dir(&dir).await? {
Ok(Some(ancestor.to_path_buf()))
} else {
Ok(None)
search_dir(&dir, search_parents).await
}

async fn search_dir(base: &Path, search_parents: bool) -> Result<Option<PathBuf>, Error> {
let mut path = base;
loop {
let mut found = vec![];
for name in PROJECT_FILES {
let file = path.join(name);
match fs::metadata(file).await {
Ok(_) => found.push(path.to_path_buf()),
Err(e) if e.kind() == io::ErrorKind::NotFound => {}
Err(e) => return Err(ClientError::with_source(e)),
}
}
} else {
if fs::metadata(dir.join("edgedb.toml")).await.is_err() {
return Ok(None);

// Future note: we allow multiple configuration files to be found in one
// folder but you must ensure that they contain the same contents
// (either via copy or symlink).
if found.len() > 1 {
let (a, b) = found.split_at(1);
let a = &a[0];
let s = fs::read_to_string(a)
.await
.map_err(|e| ClientError::with_source(e).context("failed to read file"))?;
for file in b {
if fs::read_to_string(file)
.await
.map_err(|e| ClientError::with_source(e).context("failed to read file"))?
!= s
{
return Err(ClientError::with_message(format!(
"{:?} and {:?} found in {base:?} but the contents are different",
a.file_name(),
file.file_name()
)));
}
}
}

if !search_parents {
break;
}
if let Some(parent) = path.parent() {
path = parent;
} else {
break;
}
Ok(Some(dir.to_path_buf()))
}
Ok(None)
}
15 changes: 9 additions & 6 deletions edgedb-tokio/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,20 +150,23 @@ pub use query_executor::{QueryExecutor, ResultVerbose};
pub use state::{ConfigDelta, GlobalsDelta};
pub use transaction::Transaction;

/// The ordered list of project filenames supported.
pub const PROJECT_FILES: &[&str] = &["gel.toml", "edgedb.toml"];

#[cfg(feature = "unstable")]
pub use builder::get_project_dir;

/// Create a connection to the database with default parameters
///
/// It's expected that connection parameters are set up using environment
/// (either environment variables or project configuration in `edgedb.toml`)
/// so no configuration is specified here.
/// (either environment variables or project configuration in a file named by
/// [`PROJECT_FILES`]) so no configuration is specified here.
///
/// This method tries to esablish single connection immediately to
/// ensure that configuration is valid and will error out otherwise.
/// This method tries to esablish single connection immediately to ensure that
/// configuration is valid and will error out otherwise.
///
/// For more fine-grained setup see [`Client`] and [`Builder`] documentation
/// and the source of this function.
/// For more fine-grained setup see [`Client`] and [`Builder`] documentation and
/// the source of this function.
#[cfg(feature = "env")]
pub async fn create_client() -> Result<Client, Error> {
let pool = Client::new(&Builder::new().build_env().await?);
Expand Down
Loading