From 3bd21aeed457f056e3c129956bbdbcb4b86e41f5 Mon Sep 17 00:00:00 2001 From: Filip Tibell Date: Mon, 15 Jul 2024 19:52:04 +0200 Subject: [PATCH] Fix tool cache loading erroring on first startup --- CHANGELOG.md | 6 ++++++ lib/storage/home.rs | 3 +++ lib/storage/tool_cache.rs | 26 ++++++++++++++++++++++---- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 837537e..da91002 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Fixed + +- Fixed Rokit erroring on first startup due to some directories not yet being created + ## `0.1.7` - July 15th, 2024 ### Fixed diff --git a/lib/storage/home.rs b/lib/storage/home.rs index f3e26ec..7d1a2bd 100644 --- a/lib/storage/home.rs +++ b/lib/storage/home.rs @@ -2,6 +2,8 @@ use std::env::var; use std::path::{Path, PathBuf}; use std::sync::Arc; +use tokio::fs::create_dir_all; + use crate::manifests::AuthManifest; use crate::result::{RokitError, RokitResult}; use crate::sources::ArtifactSource; @@ -60,6 +62,7 @@ impl Home { let path = dirs::home_dir() .ok_or(RokitError::HomeNotFound)? .join(".rokit"); + create_dir_all(&path).await?; Self::load_from_path(path).await } } diff --git a/lib/storage/tool_cache.rs b/lib/storage/tool_cache.rs index 9cbb41c..5e69471 100644 --- a/lib/storage/tool_cache.rs +++ b/lib/storage/tool_cache.rs @@ -13,7 +13,7 @@ use std::{ use dashmap::DashSet; use semver::Version; use serde::Deserialize; -use tokio::{task::spawn_blocking, time::Instant}; +use tokio::{fs::create_dir_all, task::spawn_blocking, time::Instant}; use tracing::{instrument, trace}; use crate::{ @@ -191,19 +191,37 @@ impl ToolCache { } async fn load_impl(path: PathBuf) -> RokitResult { + // Make sure we have created the directory for the cache file, since + // OpenOptions::create will only create the file and not the directory. + let dir = path + .parent() + .expect("should not be given empty or root path"); + create_dir_all(dir).await?; + // NOTE: Using std::fs here and passing a reader to serde_json lets us // deserialize the cache faster and without storing the file in memory. let result = spawn_blocking(move || { use std::{ - fs::File, + fs::OpenOptions, io::{BufReader, Error}, }; - let reader = BufReader::new(File::open(path)?); + + let file = OpenOptions::new() + .read(true) + .write(true) + .create(true) + .truncate(false) + .open(path)?; + let reader = BufReader::new(file); let this: ToolCache = serde_json::from_reader(reader)?; + Ok::<_, Error>(this) }); - Ok(result.await?.unwrap_or_default()) + let read_result = result + .await + .expect("blocking reader task panicked unexpectedly"); + Ok(read_result.unwrap_or_default()) } async fn save_impl(path: PathBuf, cache: &ToolCache) -> RokitResult<()> {