misc: rename to 'pgd'

This commit is contained in:
hdbg
2025-12-04 18:53:39 +01:00
parent 6e2ee650d8
commit 71f363fde9
11 changed files with 55 additions and 52 deletions

View File

@@ -4,27 +4,27 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Project Overview
`pgx` is a CLI tool for managing project-scoped PostgreSQL instances running in Docker containers. Each project gets its own isolated Postgres instance, managed through a `pgx.toml` configuration file.
`pgd` is a CLI tool for managing project-scoped PostgreSQL instances running in Docker containers. Each project gets its own isolated Postgres instance, managed through a `pgd.toml` configuration file.
## Core Architecture
### Project-Oriented Design
- Each project has a `pgx.toml` file at its root that defines the Postgres configuration
- The project name is derived from the directory containing `pgx.toml`
- Each project has a `pgd.toml` file at its root that defines the Postgres configuration
- The project name is derived from the directory containing `pgd.toml`
- Each project gets its own Docker container
- State is tracked separately per instance to detect configuration drift
### Configuration Management
The `pgx.toml` file stores:
The `pgd.toml` file stores:
- `postgres_version`: PostgreSQL version to use
- `database_name`: Name of the database
- `user_name`: Database user
- `password`: Database password
- `port`: Host port to bind (auto-selected from available ports)
Values are auto-populated during `pgx init` with sensible defaults or random values where appropriate.
Values are auto-populated during `pgd init` with sensible defaults or random values where appropriate.
### State Tracking
@@ -36,7 +36,7 @@ The tool maintains separate state for each instance to detect configuration drif
## Key Dependencies
- **clap** (with derive feature): CLI argument parsing and command structure
- **toml**: Parsing and serializing `pgx.toml` configuration files
- **toml**: Parsing and serializing `pgd.toml` configuration files
- **bollard**: Docker daemon interaction for container lifecycle management
- **tokio** (with full feature set): Async runtime for Docker operations
- **tracing** + **tracing-subscriber**: Structured logging throughout the application
@@ -80,15 +80,15 @@ cargo fmt -- --check # Check without modifying
The CLI follows this pattern:
```
pgx <command> [options]
pgd <command> [options]
```
Key commands to implement:
- `pgx init`: Create pgx.toml with auto-populated configuration
- `pgx start`: Start the Postgres container for current project
- `pgx stop`: Stop the running container
- `pgx status`: Show instance status and detect drift
- `pgx destroy`: Remove container and clean up
- `pgd init`: Create pgd.toml with auto-populated configuration
- `pgd start`: Start the Postgres container for current project
- `pgd stop`: Stop the running container
- `pgd status`: Show instance status and detect drift
- `pgd destroy`: Remove container and clean up
## Implementation Notes

2
Cargo.lock generated
View File

@@ -1001,7 +1001,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
[[package]]
name = "pgx"
name = "pgd"
version = "0.1.0"
dependencies = [
"bollard",

View File

@@ -1,5 +1,5 @@
[package]
name = "pgx"
name = "pgd"
version = "0.1.0"
edition = "2024"

3
pgd.toml Normal file
View File

@@ -0,0 +1,3 @@
version = "18.1"
password = "GypnQVF1uV23DWvp"
port = 5433

View File

@@ -1,7 +1,7 @@
_______ _______ __ __
| || || |_| |
| _ || ___|| |
| |_| || | __ | |
| ___|| || | | |
| | | |_| || _ |
|___| |_______||__| |__|
▄▄▄▄ ▐▌
█ █ ▐▌
█▄▄▄▀ ▗▞▀▜▌
▗▄▖▝▚▄▟▌
▐▌ ▐▌
▝▀▜▌
▐▙▄▞▘

View File

@@ -7,7 +7,7 @@ const STYLES: styling::Styles = styling::Styles::styled()
.placeholder(styling::AnsiColor::Cyan.on_default());
#[derive(Parser)]
#[command(name = "pgx")]
#[command(name = "pgd")]
#[command(about = "Project-scoped PostgreSQL instance manager", long_about = None)]
#[command(version)]
#[command(styles = STYLES)]

View File

@@ -35,12 +35,12 @@ impl Display for PostgresVersion {
}
}
const PROJECT_FILENAME: &str = "pgx.toml";
const PROJECT_FILENAME: &str = "pgd.toml";
/// Configuration stored in pgx.toml
/// Configuration stored in pgd.toml
#[serde_as]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PgxConfig {
pub struct PGDConfig {
/// PostgreSQL version to use
#[serde_as(as = "DisplayFromStr")]
pub version: PostgresVersion,
@@ -52,16 +52,16 @@ pub struct PgxConfig {
pub port: u16,
}
impl PgxConfig {
impl PGDConfig {
pub fn load(path: impl AsRef<Path>) -> Result<Self> {
let path = path.as_ref();
let content = std::fs::read_to_string(path)
.into_diagnostic()
.wrap_err_with(|| format!("Failed to read config file: {}", path.display()))?;
let config: PgxConfig = toml::from_str(&content)
let config: PGDConfig = toml::from_str(&content)
.into_diagnostic()
.wrap_err("Failed to parse pgx.toml")?;
.wrap_err("Failed to parse pgd.toml")?;
Ok(config)
}
@@ -85,16 +85,16 @@ pub struct Project {
/// Project name (derived from directory name)
pub name: String,
/// Path to the project directory containing pgx.toml
/// Path to the project directory containing pgd.toml
pub path: PathBuf,
pub config: PgxConfig,
pub config: PGDConfig,
}
impl Project {
pub fn container_name(&self) -> String {
let container_name = format!(
"pgx-{}-{}",
"pgd-{}-{}",
self.name,
self.config.version.to_string().replace('.', "_")
);
@@ -110,7 +110,7 @@ impl Project {
return Ok(None);
}
let config = PgxConfig::load(&config_path)?;
let config = PGDConfig::load(&config_path)?;
let name = Self::extract_project_name(&project_path)?;
Ok(Some(Project {
@@ -120,7 +120,7 @@ impl Project {
}))
}
pub fn new(config: PgxConfig) -> Result<Self> {
pub fn new(config: PGDConfig) -> Result<Self> {
let project_path = get_project_path()?;
let name = Self::extract_project_name(&project_path)?;
@@ -143,9 +143,9 @@ impl Project {
.ok_or_else(|| miette::miette!("Failed to extract project name from path"))
}
/// Get the path to the pgx.toml file
/// Get the path to the pgd.toml file
pub fn config_path(&self) -> PathBuf {
self.path.join("pgx.toml")
self.path.join("pgd.toml")
}
/// Save the current configuration

View File

@@ -3,7 +3,7 @@ use miette::{bail, miette};
use miette::Result;
use crate::{
config::{PgxConfig, PostgresVersion, Project},
config::{PGDConfig, PostgresVersion, Project},
controller::docker::DockerController,
state::{InstanceState, StateManager},
};
@@ -34,7 +34,7 @@ impl Controller {
return self.reconcile(project).await;
}
println!("Initializing new pgx project...");
println!("Initializing new pgd project...");
let mut versions = self.docker.available_versions().await?;
versions.sort();
@@ -42,14 +42,14 @@ impl Controller {
.last()
.ok_or(miette!("expected to have at least one version"))?;
let config = PgxConfig {
let config = PGDConfig {
version: *latest_version,
password: utils::generate_password(),
port: utils::find_available_port()?,
};
let project = Project::new(config)?;
println!("Created pgx.toml in {}", project.path.display());
println!("Created pgd.toml in {}", project.path.display());
println!(" Project: {}", project.name);
println!(" PostgreSQL version: {}", project.config.version);
println!(" Port: {}", project.config.port);

View File

@@ -34,7 +34,7 @@ impl DockerController {
let docker = Docker::connect_with_local_defaults()
.into_diagnostic()
.wrap_err(
"Failed to connect to Docker! pgx required Docker installed. Make sure it's running.",
"Failed to connect to Docker! pgd required Docker installed. Make sure it's running.",
)?;
info!("docker.created");
@@ -156,7 +156,7 @@ impl DockerController {
};
let mut labels = HashMap::new();
labels.insert("pgx.postgres.version".to_string(), version.to_string());
labels.insert("pgd.postgres.version".to_string(), version.to_string());
let config = ContainerCreateBody {
image: Some(image),
@@ -255,8 +255,8 @@ impl DockerController {
.ok_or_else(|| miette!("Container has no labels"))?;
let version_str = labels
.get("pgx.postgres.version")
.ok_or_else(|| miette!("Container missing pgx.postgres.version label"))?;
.get("pgd.postgres.version")
.ok_or_else(|| miette!("Container missing pgd.postgres.version label"))?;
PostgresVersion::from_str(version_str)
.map_err(|_| miette!("Invalid version in label: {}", version_str))

View File

@@ -23,7 +23,7 @@ async fn main() -> Result<()> {
let cli = Cli::parse();
init_tracing(cli.verbose);
info!("pgx.start");
info!("pgd.start");
let controller = Controller::new().await?;
match cli.command {

View File

@@ -21,7 +21,7 @@ pub struct InstanceState {
pub created_at: u64,
}
/// Manages the global state file at ~/.pgx/state.json
/// Manages the global state file at ~/.pgd/state.json
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StateManager {
/// Map of project name to instance state
@@ -29,23 +29,23 @@ pub struct StateManager {
instances: HashMap<String, InstanceState>,
}
/// Get the path to the state file (~/.pgx/state.json)
/// Get the path to the state file (~/.pgd/state.json)
fn state_file_path() -> Result<PathBuf> {
let home = std::env::var("HOME")
.into_diagnostic()
.wrap_err("Failed to get HOME environment variable")?;
Ok(PathBuf::from(home).join(".pgx").join("state.json"))
Ok(PathBuf::from(home).join(".pgd").join("state.json"))
}
/// Get the path to the .pgx directory
pub fn pgx_dir() -> Result<PathBuf> {
/// Get the path to the .pgd directory
pub fn pgd_dir() -> Result<PathBuf> {
let home = std::env::var("HOME")
.into_diagnostic()
.wrap_err("Failed to get HOME environment variable")?;
Ok(PathBuf::from(home).join(".pgx"))
Ok(PathBuf::from(home).join(".pgd"))
}
impl StateManager {
@@ -58,7 +58,7 @@ impl StateManager {
if let Some(parent) = state_path.parent() {
std::fs::create_dir_all(parent)
.into_diagnostic()
.wrap_err("Failed to create .pgx directory")?;
.wrap_err("Failed to create .pgd directory")?;
}
// Return empty state
@@ -86,7 +86,7 @@ impl StateManager {
if let Some(parent) = state_path.parent() {
std::fs::create_dir_all(parent)
.into_diagnostic()
.wrap_err("Failed to create .pgx directory")?;
.wrap_err("Failed to create .pgd directory")?;
}
let content = serde_json::to_string_pretty(self)