Skip to content
Merged

Cache #155

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
1 change: 1 addition & 0 deletions plugins/csharp/src/cs_test_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use tmc_langs_framework::TestResult;
/// Test result from the C# test runner.
#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
#[allow(clippy::upper_case_acronyms)]
pub struct CSTestResult {
pub name: String,
pub passed: bool,
Expand Down
6 changes: 3 additions & 3 deletions plugins/csharp/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ impl From<CSharpError> for TmcError {
}

// conversion from plugin error to a tmc result
impl<T> Into<Result<T, TmcError>> for CSharpError {
fn into(self) -> Result<T, TmcError> {
Err(TmcError::Plugin(Box::new(self)))
impl<T> From<CSharpError> for Result<T, TmcError> {
fn from(from: CSharpError) -> Self {
Err(TmcError::Plugin(Box::new(from)))
}
}
83 changes: 13 additions & 70 deletions plugins/csharp/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use walkdir::WalkDir;
use zip::ZipArchive;

const TMC_CSHARP_RUNNER: &[u8] = include_bytes!("../deps/tmc-csharp-runner-1.1.1.zip");
const TMC_CSHARP_RUNNER_VERSION: &str = "1.1.1";

#[derive(Default)]
pub struct CSharpPlugin {}
Expand All @@ -27,40 +28,6 @@ impl CSharpPlugin {
Self {}
}

/// Verifies that the runner directory matches the contents of the zip.
/// Note: does not check for extra files not in the zip.
fn runner_needs_to_be_extracted(target: &Path) -> Result<bool, CSharpError> {
log::debug!("verifying C# runner integrity at {}", target.display());

// no need to check the zip contents if the directory doesn't even exist
if !target.exists() {
return Ok(true);
}

let mut zip = ZipArchive::new(Cursor::new(TMC_CSHARP_RUNNER))?;
for i in 0..zip.len() {
let file = zip.by_index(i)?;
if file.is_file() {
let target_file_path = target.join(Path::new(file.name()));
if !target_file_path.exists() {
return Ok(true); // new file in zip, need to extract
}

let target_bytes = file_util::read_file(target_file_path)?;
let zip_file_path = PathBuf::from(file.name());
let zip_bytes: Vec<u8> = file
.bytes()
.collect::<Result<Vec<_>, _>>()
.map_err(|e| FileError::FileRead(zip_file_path, e))?;

if target_bytes != zip_bytes {
return Ok(true); // bytes changed, need to extract
}
}
}
Ok(false)
}

/// Extracts the bundled tmc-csharp-runner to the given path.
fn extract_runner_to_dir(target: &Path) -> Result<(), CSharpError> {
log::debug!("extracting C# runner to {}", target.display());
Expand Down Expand Up @@ -94,12 +61,23 @@ impl CSharpPlugin {
match dirs::cache_dir() {
Some(cache_dir) => {
let runner_dir = cache_dir.join("tmc").join("tmc-csharp-runner");
if Self::runner_needs_to_be_extracted(&runner_dir)? {
let version_path = runner_dir.join("VERSION");

let needs_update = if version_path.exists() {
let version = file_util::read_file_to_string(&version_path)?;
version != TMC_CSHARP_RUNNER_VERSION
} else {
true
};

if needs_update {
log::debug!("updating the cached C# runner");
if runner_dir.exists() {
// clear the directory if it exists
file_util::remove_dir_all(&runner_dir)?;
}
Self::extract_runner_to_dir(&runner_dir)?;
file_util::write_to_file(TMC_CSHARP_RUNNER_VERSION.as_bytes(), version_path)?;
}
Ok(runner_dir)
}
Expand Down Expand Up @@ -444,41 +422,6 @@ mod test {
temp
}

#[test]
fn runner_needs_to_be_extracted() {
init();

// replace a file's content with garbage
let temp = tempfile::TempDir::new().unwrap();
CSharpPlugin::extract_runner_to_dir(temp.path()).unwrap();
std::fs::write(
temp.path().join("TestMyCode.CSharp.Bootstrap.exe"),
b"garbage",
)
.unwrap();
assert!(CSharpPlugin::runner_needs_to_be_extracted(&temp.path()).unwrap());

// remove a file
let temp = tempfile::TempDir::new().unwrap();
CSharpPlugin::extract_runner_to_dir(temp.path()).unwrap();
std::fs::remove_file(temp.path().join("TestMyCode.CSharp.Bootstrap.exe")).unwrap();
assert!(CSharpPlugin::runner_needs_to_be_extracted(&temp.path()).unwrap());
}

#[test]
fn runner_does_not_need_to_be_extracted() {
init();

// no changes
let temp = tempfile::TempDir::new().unwrap();
CSharpPlugin::extract_runner_to_dir(temp.path()).unwrap();
assert!(!CSharpPlugin::runner_needs_to_be_extracted(&temp.path()).unwrap());

// new file added
file_to(&temp, "new_file", "stuff");
assert!(!CSharpPlugin::runner_needs_to_be_extracted(&temp.path()).unwrap());
}

#[test]
fn extracts_runner_to_dir() {
init();
Expand Down
Binary file not shown.
6 changes: 3 additions & 3 deletions plugins/java/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ impl From<JavaError> for TmcError {
}

// conversion from plugin error to a tmc result
impl<T> Into<Result<T, TmcError>> for JavaError {
fn into(self) -> Result<T, TmcError> {
Err(TmcError::Plugin(Box::new(self)))
impl<T> From<JavaError> for Result<T, TmcError> {
fn from(from: JavaError) -> Self {
Err(TmcError::Plugin(Box::new(from)))
}
}
2 changes: 1 addition & 1 deletion plugins/java/src/java_plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub(crate) trait JavaPlugin: LanguagePlugin {
self.create_run_result_file(project_root_path, timeout, compile_result)?;
let result = self.parse_test_result(&test_result);
file_util::remove_file(&test_result.test_results)?;
Ok(result?)
result
}

/// Parses test results.
Expand Down
41 changes: 33 additions & 8 deletions plugins/java/src/maven_plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ use tmc_langs_framework::{
};
use tmc_langs_util::file_util;

const MVN_ARCHIVE: &[u8] = include_bytes!("../deps/apache-maven-3.6.3-bin.tar.gz");
const MVN_ARCHIVE: &[u8] = include_bytes!("../deps/apache-maven-3.8.1-bin.tar.gz");
const MVN_PATH_IN_ARCHIVE: &str = "apache-maven-3.8.1"; // the name of the base directory in the maven archive
const MVN_VERSION: &str = "3.8.1";

pub struct MavenPlugin {
jvm: Jvm,
Expand Down Expand Up @@ -52,17 +54,40 @@ impl MavenPlugin {
#[cfg(not(windows))]
let mvn_exec = "mvn";

let mvn_exec_path = tmc_path
.join("apache-maven-3.6.3")
.join("bin")
.join(mvn_exec);
if !mvn_exec_path.exists() {
let mvn_path = tmc_path.join("apache-maven");
let mvn_version_path = mvn_path.join("VERSION");

let needs_update = if mvn_version_path.exists() {
let version_contents = file_util::read_file_to_string(&mvn_version_path)?;
MVN_VERSION != version_contents
} else {
true
};

if needs_update {
if mvn_path.exists() {
file_util::remove_dir_all(&mvn_path)?;
}
// TODO: remove this bit eventually, this is just to clean up the old maven cachce that had the version in the name
let old_path = tmc_path.join("apache-maven-3.6.3");
if old_path.exists() {
file_util::remove_dir_all(old_path)?;
}

log::debug!("extracting bundled tar");
let tar = GzDecoder::new(Cursor::new(MVN_ARCHIVE));
let mut tar = Archive::new(tar);
tar.unpack(&tmc_path)
.map_err(|e| JavaError::JarWrite(tmc_path, e))?;
.map_err(|e| JavaError::JarWrite(tmc_path.clone(), e))?;

log::debug!("renaming extracted archive to apache-maven");
file_util::rename(tmc_path.join(MVN_PATH_IN_ARCHIVE), &mvn_path)?;

log::debug!("writing bundle version data");
file_util::write_to_file(MVN_VERSION.as_bytes(), &mvn_version_path)?;
}

let mvn_exec_path = mvn_path.join("bin").join(mvn_exec);
Ok(mvn_exec_path.as_os_str().to_os_string())
}
}
Expand Down Expand Up @@ -324,7 +349,7 @@ mod test {
std::env::set_var("PATH", "");
let cmd = MavenPlugin::get_mvn_command().unwrap();
let expected = format!(
"tmc{0}apache-maven-3.6.3{0}bin{0}mvn",
"tmc{0}apache-maven-3.8.1{0}bin{0}mvn",
std::path::MAIN_SEPARATOR
);
assert!(cmd.to_string_lossy().ends_with(&expected))
Expand Down
6 changes: 3 additions & 3 deletions plugins/make/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ impl From<MakeError> for TmcError {
}

// conversion from plugin error to a tmc result
impl<T> Into<Result<T, TmcError>> for MakeError {
fn into(self) -> Result<T, TmcError> {
Err(TmcError::Plugin(Box::new(self)))
impl<T> From<MakeError> for Result<T, TmcError> {
fn from(from: MakeError) -> Self {
Err(TmcError::Plugin(Box::new(from)))
}
}
6 changes: 3 additions & 3 deletions plugins/python3/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ impl From<PythonError> for TmcError {
}

// conversion from plugin error to a tmc result
impl<T> Into<Result<T, TmcError>> for PythonError {
fn into(self) -> Result<T, TmcError> {
Err(TmcError::Plugin(Box::new(self)))
impl<T> From<PythonError> for Result<T, TmcError> {
fn from(from: PythonError) -> Self {
Err(TmcError::Plugin(Box::new(from)))
}
}
6 changes: 3 additions & 3 deletions plugins/r/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ impl From<RError> for TmcError {
}

// conversion from plugin error to a tmc result
impl<T> Into<Result<T, TmcError>> for RError {
fn into(self) -> Result<T, TmcError> {
Err(TmcError::Plugin(Box::new(self)))
impl<T> From<RError> for Result<T, TmcError> {
fn from(from: RError) -> Self {
Err(TmcError::Plugin(Box::new(from)))
}
}
2 changes: 1 addition & 1 deletion tmc-langs-util/src/file_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ pub fn write_to_writer<S: AsRef<[u8]>, W: Write>(
) -> Result<(), FileError> {
target
.write_all(source.as_ref())
.map_err(|e| FileError::WriteError(e))?;
.map_err(FileError::WriteError)?;
Ok(())
}

Expand Down
2 changes: 1 addition & 1 deletion tmc-langs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ toml = "0.5"
url = "2"
walkdir = "2"
zip = "0.5"
zstd = "0.6"
zstd = "0.7"

[target.'cfg(unix)'.dependencies]
nix = "0.20"
Expand Down