-
Notifications
You must be signed in to change notification settings - Fork 11
Indexes 5: Adds spk repo index subcommand for index generation and updates
#1340
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
base: index-4-indexed-repository-and-fbindex
Are you sure you want to change the base?
Changes from 17 commits
8d68d35
4df7970
34c2a47
60bb597
399f0d6
9044083
289b83c
bb66e4f
3e592be
4f30958
45e4956
051989b
073a4c0
51bb6ac
d8b735a
3b026bb
7556016
ebf1744
f4f648e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| // Copyright (c) Contributors to the SPK project. | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
| // https://github.com/spkenv/spk | ||
|
|
||
| use std::path::PathBuf; | ||
|
|
||
| use crate::Result; | ||
|
|
||
| /// The index location path of a repository. | ||
| #[async_trait::async_trait] | ||
| pub trait IndexPath { | ||
| /// Get the index location path of this repository, will create it | ||
| /// if it does not exist. | ||
| async fn index_path(&self) -> Result<PathBuf>; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,10 +2,15 @@ | |
| // SPDX-License-Identifier: Apache-2.0 | ||
| // https://github.com/spkenv/spk | ||
|
|
||
| use std::str::FromStr; | ||
| use std::time::Instant; | ||
|
|
||
| use clap::{Args, Subcommand}; | ||
| use itertools::Itertools; | ||
| use miette::{Context, Result}; | ||
| use spk_cli_common::{CommandArgs, Run}; | ||
| use spk_storage as storage; | ||
| use spk_cli_common::{CommandArgs, Run, flags}; | ||
| use spk_schema::ident::OptVersionIdent; | ||
| use spk_storage::{self as storage, FlatBufferRepoIndex, RepositoryHandle, RepositoryIndexMut}; | ||
| use storage::Repository; | ||
|
|
||
| /// Perform repository-level actions and maintenance | ||
|
|
@@ -45,19 +50,128 @@ pub enum RepoCommand { | |
| #[clap(name = "REPO")] | ||
| repo: String, | ||
| }, | ||
| /// Generate an index for a repository | ||
| Index { | ||
| /// Repository to generate or update an index from. | ||
| #[clap(long, short = 'r')] | ||
| repo: String, | ||
|
|
||
| /// Package or package/version of a published package to | ||
| /// update in an existing index. | ||
| /// | ||
| /// Can be specified multiple times. Other packages in the | ||
| /// index will not be updated. Without this the full index | ||
| /// will be constructed from scratch. If the repo does not | ||
| /// have an index, a full index will be constructed from | ||
| /// scratch if the repository supports an index. | ||
| /// | ||
| /// This option is only supported for flatbuffer indexes. | ||
| #[clap(long, name = "PACKAGE/VERSION")] | ||
| update: Vec<String>, | ||
| }, | ||
| } | ||
|
|
||
| impl RepoCommand { | ||
| pub async fn run(&mut self) -> Result<i32> { | ||
| let repo = match &self { | ||
| Self::Upgrade { repo } => repo, | ||
| }; | ||
| let repo = match repo.as_str() { | ||
| "local" => storage::local_repository().await?, | ||
| _ => storage::remote_repository(repo).await?, | ||
| }; | ||
| let status = repo.upgrade().await.wrap_err("Upgrade failed")?; | ||
| tracing::info!("{}", status); | ||
| Ok(1) | ||
| match &self { | ||
| // spk repo upgrade ... | ||
| Self::Upgrade { repo: repo_name } => { | ||
| let repo = match repo_name.as_str() { | ||
| "local" => storage::local_repository().await?, | ||
| _ => storage::remote_repository(repo_name).await?, | ||
| }; | ||
|
|
||
| let status = repo.upgrade().await.wrap_err("Upgrade failed")?; | ||
| tracing::info!("{}", status); | ||
| Ok(1) | ||
| } | ||
|
|
||
| // spk repo index ... | ||
| Self::Index { repo, update } => { | ||
| // Generate or update an index a repo. The repo must | ||
| // be the underlying repo and not an indexed repo. So as | ||
| // a safety measure, this disables index use for this | ||
| // command regardless of config or command line flags. | ||
| flags::disable_index_use(); | ||
|
|
||
| // Construct the repo handle to operate on, and repo | ||
| // list that contains it. | ||
| let repo_to_index: RepositoryHandle = match repo.as_str() { | ||
| "local" => storage::local_repository().await?.into(), | ||
| name => storage::remote_repository(name).await?.into(), | ||
| }; | ||
| let repos = vec![(repo_to_index.name().to_string(), repo_to_index.clone())]; | ||
|
|
||
| if !update.is_empty() { | ||
| // Update the existing index for the given package/version | ||
| let start = Instant::now(); | ||
| let idents: Vec<OptVersionIdent> = update | ||
| .iter() | ||
| .filter_map(|pv| match OptVersionIdent::from_str(pv) { | ||
| Ok(i) => Some(i), | ||
| Err(err) => { | ||
| tracing::warn!( | ||
| "Skipping '{pv}': Unable to parse it as a package/version: {err}" | ||
| ); | ||
| None | ||
| } | ||
| }) | ||
| .collect(); | ||
|
|
||
| tracing::debug!( | ||
| "Command line update option: [{}]", | ||
| update.iter().map(ToString::to_string).join(", ") | ||
| ); | ||
| tracing::info!( | ||
| "Package/versions to update: [{}]", | ||
| idents.iter().map(ToString::to_string).join(", ") | ||
| ); | ||
| if idents.is_empty() { | ||
| tracing::error!( | ||
| "No valid package/versions given, nothing to update. Stopping." | ||
| ); | ||
| return Ok(2); | ||
| } | ||
|
|
||
| // Load the current index for this repo now | ||
| let mut was_full_index = String::from(""); | ||
| match FlatBufferRepoIndex::from_repo_file(&repo_to_index).await { | ||
| Ok(current_index) => { | ||
| current_index | ||
| .update_packages(&repo_to_index, &idents) | ||
| .await? | ||
| } | ||
| Err(err) => { | ||
| // There isn't an existing index, so generate one from scratch that | ||
| // will also include the update package version. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you match on a more specific error before assuming the problem is that the index doesn't exist?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've changed this to match the appropriate spk storage error. |
||
| tracing::warn!("Failed to load flatbuffer index: {err}"); | ||
| tracing::warn!("No current index to update. Creating a full index ..."); | ||
| FlatBufferRepoIndex::index_repo(&repos).await?; | ||
| was_full_index = | ||
| " [no previous index, so a full index was created]".to_string() | ||
| } | ||
| }; | ||
|
|
||
| tracing::info!( | ||
| "Index update for '{}' in '{}' repo completed in: {} secs{was_full_index}", | ||
| idents.iter().map(ToString::to_string).join(", "), | ||
| repo_to_index.name(), | ||
| start.elapsed().as_secs_f64() | ||
| ); | ||
| } else { | ||
| // Generate a full index from scratch | ||
| let start = Instant::now(); | ||
| FlatBufferRepoIndex::index_repo(&repos).await?; | ||
|
|
||
| tracing::info!( | ||
| "Index generation for '{}' repo completed in: {} secs", | ||
| repo_to_index.name(), | ||
| start.elapsed().as_secs_f64() | ||
| ); | ||
| } | ||
|
|
||
| Ok(0) | ||
| } | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've updated this.