Skip to content

Commit e20a504

Browse files
Merge pull request #15 from thunderstore-io/fix-invalid-index-state
Fix panic when index is in an invalid state (missing files or just completely gone)
2 parents 5e8497d + d2ddd6f commit e20a504

File tree

1 file changed

+21
-6
lines changed

1 file changed

+21
-6
lines changed

src/package/index.rs

+21-6
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@ struct IndexHeader {
3535
pub struct PackageIndex {
3636
lookup: Vec<LookupTableEntry>,
3737

38-
// Yes, we're continuing this naming scheme. Why? I can't come up with anything better.
39-
tight_lookup: HashMap<String, usize>,
38+
strict_lookup: HashMap<String, usize>,
4039
loose_lookup: HashMap<String, Vec<usize>>,
4140

4241
index_file: File,
@@ -147,6 +146,11 @@ impl PackageIndex {
147146

148147
/// Open and serialize the on-disk index, retrieving a fresh copy if it doesn't already exist.
149148
pub async fn open(tcli_home: &Path) -> Result<&PackageIndex, Error> {
149+
// Sync the index before we open it if it's in an invalid state.
150+
if !is_index_valid(tcli_home) {
151+
PackageIndex::sync(tcli_home).await?;
152+
}
153+
150154
// Maintain a cached version of the index so subsequent calls don't trigger a complete reload.
151155
static CACHE: OnceCell<PackageIndex> = OnceCell::new();
152156
if let Some(index) = CACHE.get() {
@@ -160,14 +164,14 @@ impl PackageIndex {
160164
};
161165

162166
let mut entries = vec![];
163-
let mut tight = HashMap::new();
167+
let mut strict = HashMap::new();
164168
let mut loose: HashMap<String, Vec<usize>> = HashMap::new();
165169

166170
// There's likely a more "rusty" way to do this, but this is simple and it works.
167171
// Note that the ordering will not be consistent across reruns.
168172
for (index, (pkg_ref, entry)) in lookup.into_iter().enumerate() {
169173
entries.push(entry);
170-
tight.insert(pkg_ref.to_string(), index);
174+
strict.insert(pkg_ref.to_string(), index);
171175

172176
let l_ident = pkg_ref.to_loose_ident_string();
173177
let l_entries = loose.entry(l_ident).or_default();
@@ -179,7 +183,7 @@ impl PackageIndex {
179183
let index = PackageIndex {
180184
lookup: entries,
181185
loose_lookup: loose,
182-
tight_lookup: tight,
186+
strict_lookup: strict,
183187
index_file,
184188
};
185189
CACHE.set(index).unwrap();
@@ -189,7 +193,7 @@ impl PackageIndex {
189193

190194
/// Get a package which matches the given package reference.
191195
pub fn get_package(&self, reference: impl Borrow<PackageReference>) -> Option<PackageIndexEntry> {
192-
let entry_idx = self.tight_lookup.get(&reference.borrow().to_string())?;
196+
let entry_idx = self.strict_lookup.get(&reference.borrow().to_string())?;
193197
let entry = self.lookup.get(*entry_idx)?;
194198

195199
let index_str = self.read_index_string(entry).ok()?;
@@ -223,3 +227,14 @@ impl PackageIndex {
223227
Ok(String::from_utf8(buffer).unwrap())
224228
}
225229
}
230+
231+
/// Determine if the index is in a valid state or not.
232+
pub fn is_index_valid(tcli_home: &Path) -> bool {
233+
let index_dir = tcli_home.join("index");
234+
235+
let lookup = index_dir.join("lookup.json");
236+
let index = index_dir.join("index.json");
237+
let header = index_dir.join("header.json");
238+
239+
index_dir.exists() && lookup.exists() && index.exists() && header.exists()
240+
}

0 commit comments

Comments
 (0)