-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
3: Split the `retrieve testcases` command r=qryxip a=qryxip Co-authored-by: Ryo Yamashita <qryxip@gmail.com>
- Loading branch information
Showing
14 changed files
with
835 additions
and
596 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,209 @@ | ||
use crate::{ | ||
project::{MetadataExt as _, WorkspaceMetadataCargoCompetePlatform}, | ||
shell::ColorChoice, | ||
}; | ||
use anyhow::Context as _; | ||
use snowchains_core::web::{ | ||
RetrieveTestCasesOutcome, RetrieveTestCasesOutcomeContest, RetrieveTestCasesOutcomeProblem, | ||
}; | ||
use std::path::PathBuf; | ||
use structopt::StructOpt; | ||
use strum::VariantNames as _; | ||
use url::Url; | ||
|
||
#[derive(StructOpt, Debug)] | ||
pub struct OptCompeteNew { | ||
/// Retrieve system test cases | ||
#[structopt(long)] | ||
pub full: bool, | ||
|
||
/// Open URLs and files | ||
#[structopt(long)] | ||
pub open: bool, | ||
|
||
/// Retrieve only the problems | ||
#[structopt(long, value_name("INDEX"))] | ||
pub problems: Option<Vec<String>>, | ||
|
||
/// Path to Cargo.toml | ||
#[structopt(long, value_name("PATH"))] | ||
pub manifest_path: Option<PathBuf>, | ||
|
||
/// Coloring | ||
#[structopt( | ||
long, | ||
value_name("WHEN"), | ||
possible_values(ColorChoice::VARIANTS), | ||
default_value("auto") | ||
)] | ||
pub color: ColorChoice, | ||
|
||
/// Contest ID. Required for some platforms | ||
pub contest: Option<String>, | ||
} | ||
|
||
pub fn run(opt: OptCompeteNew, ctx: crate::Context<'_>) -> anyhow::Result<()> { | ||
let OptCompeteNew { | ||
full, | ||
open, | ||
problems, | ||
manifest_path, | ||
color, | ||
contest, | ||
} = opt; | ||
|
||
let crate::Context { cwd, shell } = ctx; | ||
|
||
shell.set_color_choice(color); | ||
|
||
let manifest_path = manifest_path | ||
.map(Ok) | ||
.unwrap_or_else(|| crate::project::locate_project(&cwd))?; | ||
let metadata = crate::project::cargo_metadata(&manifest_path)?; | ||
let workspace_metadata = metadata.read_workspace_metadata()?; | ||
|
||
match workspace_metadata.platform { | ||
WorkspaceMetadataCargoCompetePlatform::Atcoder { .. } => { | ||
let contest = contest.with_context(|| "`contest` is required for AtCoder")?; | ||
let problems = problems.map(|ps| ps.into_iter().collect()); | ||
|
||
let outcome = | ||
crate::web::retrieve_testcases::dl_from_atcoder(&contest, problems, full, shell)?; | ||
|
||
let package_name = outcome | ||
.contest | ||
.as_ref() | ||
.map(|RetrieveTestCasesOutcomeContest { id, .. }| id) | ||
.unwrap_or(&contest); | ||
|
||
let problems = outcome | ||
.problems | ||
.iter() | ||
.map(|RetrieveTestCasesOutcomeProblem { index, url, .. }| (&**index, url)) | ||
.collect(); | ||
|
||
let workspace_root = metadata.workspace_root.clone(); | ||
let pkg_manifest_dir = metadata.workspace_root.join(package_name); | ||
let urls = urls(&outcome); | ||
|
||
let file_paths = itertools::zip_eq( | ||
metadata.add_member(package_name, &problems, false, shell)?, | ||
crate::web::retrieve_testcases::save_test_cases( | ||
&workspace_root, | ||
&workspace_metadata.test_suite, | ||
outcome, | ||
shell, | ||
)?, | ||
) | ||
.collect::<Vec<_>>(); | ||
|
||
if open { | ||
crate::open::open( | ||
&urls, | ||
workspace_metadata.open, | ||
&file_paths, | ||
&pkg_manifest_dir, | ||
&cwd, | ||
shell, | ||
)?; | ||
} | ||
} | ||
WorkspaceMetadataCargoCompetePlatform::Codeforces => { | ||
let contest = contest.with_context(|| "`contest` is required for Codeforces")?; | ||
let problems = problems.map(|ps| ps.into_iter().collect()); | ||
|
||
let outcome = | ||
crate::web::retrieve_testcases::dl_from_codeforces(&contest, problems, shell)?; | ||
|
||
let package_name = outcome | ||
.contest | ||
.as_ref() | ||
.map(|RetrieveTestCasesOutcomeContest { id, .. }| id) | ||
.unwrap_or(&contest); | ||
|
||
let problems = outcome | ||
.problems | ||
.iter() | ||
.map(|RetrieveTestCasesOutcomeProblem { index, url, .. }| (&**index, url)) | ||
.collect(); | ||
|
||
let workspace_root = metadata.workspace_root.clone(); | ||
let pkg_manifest_dir = metadata.workspace_root.join(package_name); | ||
let urls = urls(&outcome); | ||
|
||
let file_paths = itertools::zip_eq( | ||
metadata.add_member(package_name, &problems, false, shell)?, | ||
crate::web::retrieve_testcases::save_test_cases( | ||
&workspace_root, | ||
&workspace_metadata.test_suite, | ||
outcome, | ||
shell, | ||
)?, | ||
) | ||
.collect::<Vec<_>>(); | ||
|
||
if open { | ||
crate::open::open( | ||
&urls, | ||
workspace_metadata.open, | ||
&file_paths, | ||
&pkg_manifest_dir, | ||
&cwd, | ||
shell, | ||
)?; | ||
} | ||
} | ||
WorkspaceMetadataCargoCompetePlatform::Yukicoder => { | ||
let contest = contest.as_deref(); | ||
let problems = problems.map(|ps| ps.into_iter().collect()); | ||
|
||
let outcome = | ||
crate::web::retrieve_testcases::dl_from_yukicoder(contest, problems, full, shell)?; | ||
|
||
let package_name = outcome | ||
.contest | ||
.as_ref() | ||
.map(|RetrieveTestCasesOutcomeContest { id, .. }| &**id) | ||
.or(contest); | ||
let is_no = package_name.is_none(); | ||
let package_name = package_name.unwrap_or("problems"); | ||
|
||
let problems = outcome | ||
.problems | ||
.iter() | ||
.map(|RetrieveTestCasesOutcomeProblem { index, url, .. }| (&**index, url)) | ||
.collect(); | ||
|
||
let workspace_root = metadata.workspace_root.clone(); | ||
let pkg_manifest_dir = metadata.workspace_root.join(package_name); | ||
let urls = urls(&outcome); | ||
|
||
let file_paths = itertools::zip_eq( | ||
metadata.add_member(package_name, &problems, is_no, shell)?, | ||
crate::web::retrieve_testcases::save_test_cases( | ||
&workspace_root, | ||
&workspace_metadata.test_suite, | ||
outcome, | ||
shell, | ||
)?, | ||
) | ||
.collect::<Vec<_>>(); | ||
|
||
if open { | ||
crate::open::open( | ||
&urls, | ||
workspace_metadata.open, | ||
&file_paths, | ||
&pkg_manifest_dir, | ||
&cwd, | ||
shell, | ||
)?; | ||
} | ||
} | ||
} | ||
Ok(()) | ||
} | ||
|
||
fn urls(outcome: &RetrieveTestCasesOutcome) -> Vec<Url> { | ||
outcome.problems.iter().map(|p| p.url.clone()).collect() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
use crate::{ | ||
project::{MetadataExt as _, PackageExt as _, PackageMetadataCargoCompeteBin}, | ||
shell::ColorChoice, | ||
}; | ||
use maplit::hashset; | ||
use std::{collections::HashSet, path::PathBuf}; | ||
use structopt::StructOpt; | ||
use strum::VariantNames as _; | ||
|
||
#[derive(StructOpt, Debug)] | ||
pub struct OptCompeteOpen { | ||
/// Retrieves system test cases | ||
#[structopt(long)] | ||
pub full: bool, | ||
|
||
/// Problem indexes | ||
#[structopt(long)] | ||
pub problems: Option<Vec<String>>, | ||
|
||
/// Package (see `cargo help pkgid`) | ||
#[structopt(short, long, value_name("SPEC"))] | ||
pub package: Option<String>, | ||
|
||
/// Path to Cargo.toml | ||
#[structopt(long, value_name("PATH"))] | ||
pub manifest_path: Option<PathBuf>, | ||
|
||
/// Coloring | ||
#[structopt( | ||
long, | ||
value_name("WHEN"), | ||
possible_values(ColorChoice::VARIANTS), | ||
default_value("auto") | ||
)] | ||
pub color: ColorChoice, | ||
} | ||
|
||
pub(crate) fn run(opt: OptCompeteOpen, ctx: crate::Context<'_>) -> anyhow::Result<()> { | ||
let OptCompeteOpen { | ||
full, | ||
problems, | ||
package, | ||
manifest_path, | ||
color, | ||
} = opt; | ||
|
||
let crate::Context { cwd, shell } = ctx; | ||
|
||
shell.set_color_choice(color); | ||
|
||
let problems = problems.map(|ps| ps.into_iter().collect::<HashSet<_>>()); | ||
|
||
let manifest_path = manifest_path | ||
.map(Ok) | ||
.unwrap_or_else(|| crate::project::locate_project(&cwd))?; | ||
let metadata = crate::project::cargo_metadata(&manifest_path)?; | ||
let workspace_metadata = metadata.read_workspace_metadata()?; | ||
|
||
let member = metadata.query_for_member(package)?; | ||
|
||
let package_metadata_bin = member.read_package_metadata()?.bin; | ||
|
||
let mut urls = vec![]; | ||
let mut file_paths = vec![]; | ||
let mut missing = hashset!(); | ||
|
||
for (index, PackageMetadataCargoCompeteBin { name, problem, .. }) in &package_metadata_bin { | ||
if problems.as_ref().map_or(true, |ps| ps.contains(index)) { | ||
urls.extend(problem.url()); | ||
|
||
let test_suite_path = crate::testing::test_suite_path( | ||
&metadata.workspace_root, | ||
&workspace_metadata.test_suite, | ||
&problem, | ||
)?; | ||
|
||
if !test_suite_path.exists() { | ||
missing.insert(index.clone()); | ||
} | ||
|
||
file_paths.push((&member.bin_target(&name)?.src_path, test_suite_path)); | ||
} | ||
} | ||
|
||
if !missing.is_empty() { | ||
shell.status("Retrieving", "missing test cases")?; | ||
|
||
crate::web::retrieve_testcases::dl_for_existing_package( | ||
&package_metadata_bin, | ||
Some(&missing), | ||
full, | ||
&metadata.workspace_root, | ||
&workspace_metadata.test_suite, | ||
shell, | ||
)?; | ||
} | ||
|
||
crate::open::open( | ||
&urls, | ||
workspace_metadata.open, | ||
&file_paths, | ||
member.manifest_path.parent().unwrap(), | ||
&cwd, | ||
shell, | ||
) | ||
} |
Oops, something went wrong.