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

Allow eg. pkgx +rust like pkgx^1 does #1090

Merged
merged 2 commits into from
Jan 24, 2025
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
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,10 @@ jobs:
- run: pkgx /usr/bin/awk --version
- run: pkgx +yarnpkg.com yarn --version
- run: pkgx +yarnpkg.com -- yarn --version
# coverage for conflict error messages
- run: '! pkgx yarn --version'
# coverage for display-name resolution
- run: pkgx +agg

- name: generate coverage
run: |
Expand Down
6 changes: 3 additions & 3 deletions crates/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ async fn main() -> Result<(), Box<dyn Error>> {

let cache_dir = config.pantry_dir.parent().unwrap();
std::fs::create_dir_all(cache_dir)?;
let mut conn = Connection::open(cache_dir.join("pantry.db"))?;
let mut conn = Connection::open(cache_dir.join("pantry.2.db"))?;
Copy link
Contributor

Choose a reason for hiding this comment

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

i sense migrations coming. there's a fair few tools in rust for that. and a few in pkgx, like goose.

Copy link
Member Author

Choose a reason for hiding this comment

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

we would certainly be more proper to be able to update the db incrementally and with migrations. That’s work I am not interested in RN tho for sure.


let spinner = if flags.silent || flags.quiet {
None
Expand All @@ -51,7 +51,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
Some(spinner)
};

let did_sync = if sync::should(&config) {
let did_sync = if sync::should(&config)? {
if let Some(spinner) = &spinner {
spinner.set_message("syncing pkg-db…");
}
Expand Down Expand Up @@ -263,7 +263,7 @@ impl std::fmt::Display for WhichError {
impl std::error::Error for WhichError {}

async fn which(cmd: &String, conn: &Connection, pkgs: &[PackageReq]) -> Result<String, WhichError> {
let candidates = pantry_db::which(cmd, conn).map_err(WhichError::DbError)?;
let candidates = pantry_db::projects_for_symbol(cmd, conn).map_err(WhichError::DbError)?;
if candidates.len() == 1 {
Ok(candidates[0].clone())
} else if candidates.is_empty() {
Expand Down
6 changes: 6 additions & 0 deletions crates/lib/src/pantry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub struct PantryEntry {
pub programs: Vec<String>,
pub companions: Vec<PackageReq>,
pub env: HashMap<String, String>,
pub display_name: Option<String>,
}

impl PantryEntry {
Expand Down Expand Up @@ -73,12 +74,15 @@ impl PantryEntry {
HashMap::new()
};

let display_name = entry.display_name;

Ok(Self {
deps,
project,
env,
companions,
programs,
display_name,
})
}
}
Expand Down Expand Up @@ -131,6 +135,8 @@ struct RawPantryEntry {
provides: Option<Provides>,
companions: Option<Deps>,
runtime: Option<Runtime>,
#[serde(rename = "display-name")]
display_name: Option<String>,
}

#[derive(Debug)]
Expand Down
30 changes: 30 additions & 0 deletions crates/lib/src/pantry_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,15 @@ pub fn cache(config: &Config, conn: &mut Connection) -> Result<(), Box<dyn Error
project TEXT,
envline TEXT
);
CREATE TABLE aliases (
project TEXT,
alias TEXT
);
CREATE INDEX idx_project ON provides(project);
CREATE INDEX idx_program ON provides(program);
CREATE INDEX idx_project_dependencies ON dependencies(project);
CREATE INDEX idx_project_companions ON companions(project);
CREATE INDEX idx_alias_project ON aliases(alias);
",
)?;

Expand All @@ -53,6 +58,13 @@ pub fn cache(config: &Config, conn: &mut Connection) -> Result<(), Box<dyn Error
)?;
}

if let Some(display_name) = pkg.display_name {
tx.execute(
"INSERT INTO aliases (project, alias) VALUES (?1, ?2);",
params![pkg.project, display_name],
)?;
}

for dep in pkg.deps {
tx.execute(
"INSERT INTO dependencies (project, pkgspec) VALUES (?1, ?2);",
Expand Down Expand Up @@ -103,6 +115,24 @@ pub fn which(cmd: &String, conn: &Connection) -> Result<Vec<String>, rusqlite::E
Ok(rv)
}

pub fn projects_for_symbol(
symbol: &String,
conn: &Connection,
) -> Result<Vec<String>, rusqlite::Error> {
let mut stmt = conn.prepare(
"
SELECT project FROM provides WHERE program = ?1
UNION
SELECT project FROM aliases WHERE LOWER(alias) = LOWER(?1);",
)?;
let mut rv = Vec::new();
let mut rows = stmt.query(params![symbol])?;
while let Some(row) = rows.next()? {
rv.push(row.get(0)?);
}
Comment on lines +128 to +132
Copy link
Contributor

Choose a reason for hiding this comment

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

just for style reasons, this is:

Ok(
    stmt
    .query(params![symbol])?
    .map(|row| row.get(0).expect("Query returned malformed data."))
    .collect::<Vec<String>
)

assuming the borrow checker doesn't think you're dropping bits.

Copy link
Member Author

Choose a reason for hiding this comment

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

Doesn't compile and I am not enough of a rust guru yet to fix

Copy link
Contributor

Choose a reason for hiding this comment

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

if you haven't, give pkgx bacon -j clippy a try ;)

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 have not, though I have been there numerous times lately since it is the latest addition to the pantry. I guess I don't see how it would help me here.

Copy link
Contributor

Choose a reason for hiding this comment

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

not here specifically, but the feedback is rapid and, to my mind, better organized than rust-analyzer+vscode (it also works no matter what base directory you're in, which rust-analyzer struggles with).

Ok(rv)
}

pub fn runtime_env_for_project(
project: &String,
conn: &Connection,
Expand Down
17 changes: 6 additions & 11 deletions crates/lib/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,14 @@ use tokio_tar::Archive;
use tokio_util::compat::FuturesAsyncReadCompatExt;

#[allow(clippy::all)]
pub fn should(config: &Config) -> bool {
pub fn should(config: &Config) -> Result<bool, Box<dyn Error>> {
if !config.pantry_dir.join("projects").is_dir() {
true
} else if !config
.pantry_dir
.parent()
.unwrap()
.join("pantry.db")
.is_file()
{
true
Ok(true)
} else {
false
let path = config.pantry_dir.parent().unwrap().join("pantry.2.db");
// the file always exists because we create the connection
// but will be 0 bytes if we need to fill it
Ok(std::fs::metadata(&path)?.len() == 0)
}
}

Expand Down
Loading