mirror of
https://github.com/modrinth/code.git
synced 2026-07-31 21:26:40 +00:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
304ded1984 | ||
|
|
51ad88c9d1 | ||
|
|
19caa610b1 | ||
|
|
702429c950 |
+1
@@ -97,6 +97,7 @@ type ReleaseChannel = 'release' | 'beta' | 'alpha'
|
||||
export type InstanceLoader = 'vanilla' | 'forge' | 'fabric' | 'quilt' | 'neoforge'
|
||||
|
||||
type ContentFile = {
|
||||
enabled: boolean
|
||||
metadata?: {
|
||||
project_id: string
|
||||
version_id: string
|
||||
|
||||
Generated
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "\n\t\tUPDATE instance_files\n\t\tSET\n\t\t\trelative_path = ?,\n\t\t\tfile_name = ?,\n\t\t\tenabled = ?,\n\t\t\tmissing = 0,\n\t\t\tmodified_at = ?\n\t\tWHERE instance_id = ? AND relative_path = ?\n\t\t",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 6
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "c5f78eaae528b6f930bcc9ade15384564c86cd98a1e407515ea718127a3b1777"
|
||||
}
|
||||
Generated
-12
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "\n\t\tUPDATE instance_files\n\t\tSET\n\t\t\trelative_path = ?,\n\t\t\tfile_name = ?,\n\t\t\tenabled = ?,\n\t\t\tmodified_at = ?\n\t\tWHERE instance_id = ? AND relative_path = ?\n\t\t",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 6
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "f93f5fca4f004dc70cab05f879993eb92fa6199c7356bbc2c5ca36468f916380"
|
||||
}
|
||||
@@ -117,6 +117,7 @@ impl ModLoader {
|
||||
pub struct ContentFile {
|
||||
pub hash: String,
|
||||
pub file_name: String,
|
||||
pub enabled: bool,
|
||||
pub size: u64,
|
||||
pub metadata: Option<FileMetadata>,
|
||||
pub update_version_id: Option<String>,
|
||||
|
||||
@@ -627,6 +627,7 @@ pub(crate) async fn rename_instance_file(
|
||||
relative_path = ?,
|
||||
file_name = ?,
|
||||
enabled = ?,
|
||||
missing = 0,
|
||||
modified_at = ?
|
||||
WHERE instance_id = ? AND relative_path = ?
|
||||
",
|
||||
@@ -856,11 +857,11 @@ pub(crate) async fn set_content_entry_enabled_for_file(
|
||||
file_id: &str,
|
||||
enabled: bool,
|
||||
pool: &SqlitePool,
|
||||
) -> crate::Result<()> {
|
||||
) -> crate::Result<bool> {
|
||||
let enabled = i64::from(enabled);
|
||||
let modified_at = Utc::now().timestamp();
|
||||
|
||||
sqlx::query!(
|
||||
let result = sqlx::query!(
|
||||
"
|
||||
UPDATE instance_content_entries
|
||||
SET enabled = ?, modified_at = ?
|
||||
@@ -874,7 +875,7 @@ pub(crate) async fn set_content_entry_enabled_for_file(
|
||||
.execute(pool)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
Ok(result.rows_affected() > 0)
|
||||
}
|
||||
|
||||
pub(crate) async fn remove_content_entries_for_file(
|
||||
|
||||
@@ -661,13 +661,31 @@ pub(crate) async fn toggle_disable_project(
|
||||
}
|
||||
None => index_existing_file(&scope, &new_path, state).await?,
|
||||
};
|
||||
content_rows::set_content_entry_enabled_for_file(
|
||||
let updated_entry = content_rows::set_content_entry_enabled_for_file(
|
||||
&scope.content_set_id,
|
||||
&file.id,
|
||||
enabled,
|
||||
&state.pool,
|
||||
)
|
||||
.await?;
|
||||
if !updated_entry {
|
||||
let project_type = ProjectType::get_from_parent_folder(&new_path)
|
||||
.ok_or_else(|| {
|
||||
crate::ErrorKind::InputError(format!(
|
||||
"Unable to infer project type from {new_path}"
|
||||
))
|
||||
})?;
|
||||
upsert_entry_for_file(
|
||||
&scope,
|
||||
&file,
|
||||
project_type,
|
||||
None,
|
||||
None,
|
||||
ContentSourceKind::Local,
|
||||
&state.pool,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(new_path)
|
||||
}
|
||||
|
||||
@@ -281,12 +281,31 @@ async fn plan_bulk_update(
|
||||
instance_id: &str,
|
||||
state: &State,
|
||||
) -> crate::Result<BulkUpdatePlan> {
|
||||
let updateable_paths =
|
||||
bulk_updateable_project_paths(instance_id, state).await?;
|
||||
if updateable_paths.is_empty() {
|
||||
return Ok(BulkUpdatePlan {
|
||||
project_updates: Vec::new(),
|
||||
dependency_additions: Vec::new(),
|
||||
});
|
||||
}
|
||||
|
||||
let updates = check_content_updates(
|
||||
instance_id,
|
||||
Some(CacheBehaviour::MustRevalidate),
|
||||
state,
|
||||
)
|
||||
.await?;
|
||||
.await?
|
||||
.into_iter()
|
||||
.filter(|update| updateable_paths.contains(&update.relative_path))
|
||||
.collect::<Vec<_>>();
|
||||
if updates.is_empty() {
|
||||
return Ok(BulkUpdatePlan {
|
||||
project_updates: Vec::new(),
|
||||
dependency_additions: Vec::new(),
|
||||
});
|
||||
}
|
||||
|
||||
let content_set =
|
||||
content_rows::get_applied_content_set(instance_id, &state.pool)
|
||||
.await?
|
||||
@@ -320,6 +339,7 @@ async fn plan_bulk_update(
|
||||
.collect::<HashMap<_, _>>();
|
||||
let version_ids = installed
|
||||
.iter()
|
||||
.filter(|project| updateable_paths.contains(&project.relative_path))
|
||||
.filter_map(|project| project.version_id.clone())
|
||||
.chain(
|
||||
updates
|
||||
@@ -343,6 +363,7 @@ async fn plan_bulk_update(
|
||||
let planned_versions = installed
|
||||
.iter()
|
||||
.filter(|project| project.enabled)
|
||||
.filter(|project| updateable_paths.contains(&project.relative_path))
|
||||
.filter_map(|project| {
|
||||
let target_version_id = updates_by_path
|
||||
.get(&project.relative_path)
|
||||
@@ -379,6 +400,21 @@ async fn plan_bulk_update(
|
||||
})
|
||||
}
|
||||
|
||||
async fn bulk_updateable_project_paths(
|
||||
instance_id: &str,
|
||||
state: &State,
|
||||
) -> crate::Result<HashSet<String>> {
|
||||
let items = super::list_content::list_content(
|
||||
instance_id,
|
||||
None,
|
||||
Some(CacheBehaviour::MustRevalidate),
|
||||
state,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(items.into_iter().map(|item| item.file_path).collect())
|
||||
}
|
||||
|
||||
async fn installed_projects(
|
||||
instance_id: &str,
|
||||
content_set: &ContentSet,
|
||||
|
||||
@@ -208,6 +208,8 @@ pub(crate) async fn list_content(
|
||||
)
|
||||
.await?;
|
||||
let imported_modpack_scope = is_imported_modpack_scope(&resolved, &link);
|
||||
let linked_modpack_source_kind = linked_modpack_source_kind(&link);
|
||||
let mut failed_modpack_identifier_lookup = false;
|
||||
let modpack_ids = if imported_modpack_scope {
|
||||
None
|
||||
} else {
|
||||
@@ -226,6 +228,7 @@ pub(crate) async fn list_content(
|
||||
"Failed to fetch modpack identifiers: {}",
|
||||
err
|
||||
);
|
||||
failed_modpack_identifier_lookup = true;
|
||||
None
|
||||
}
|
||||
},
|
||||
@@ -240,6 +243,12 @@ pub(crate) async fn list_content(
|
||||
}
|
||||
} else if let Some(ids) = modpack_ids.as_ref() {
|
||||
ContentFilter::ExcludeModpack(ids)
|
||||
} else if failed_modpack_identifier_lookup {
|
||||
ContentFilter::ExcludeSourceKind {
|
||||
source_kind: linked_modpack_source_kind
|
||||
.unwrap_or(ContentSourceKind::ModrinthModpack),
|
||||
exclude_untracked: true,
|
||||
}
|
||||
} else {
|
||||
ContentFilter::All
|
||||
};
|
||||
@@ -735,6 +744,9 @@ async fn content_projects_for_scope(
|
||||
update_version_id,
|
||||
hash: file.sha1,
|
||||
file_name: file.file_name,
|
||||
enabled: entry.map_or(file.enabled, |entry| {
|
||||
entry.enabled && file.enabled
|
||||
}),
|
||||
size: file.size,
|
||||
metadata: file_metadata_from_entry_or_cache(entry, metadata),
|
||||
project_type,
|
||||
@@ -882,7 +894,7 @@ async fn content_files_to_content_items(
|
||||
file_path: path.clone(),
|
||||
id: file.hash.clone(),
|
||||
size: file.size,
|
||||
enabled: !file.file_name.ends_with(".disabled"),
|
||||
enabled: file.enabled,
|
||||
project_type: file.project_type,
|
||||
project: project.map(|project| ContentItemProject {
|
||||
id: project.id.clone(),
|
||||
@@ -1097,6 +1109,20 @@ fn linked_modpack_ids(link: &InstanceLink) -> Option<(String, String)> {
|
||||
}
|
||||
}
|
||||
|
||||
fn linked_modpack_source_kind(
|
||||
link: &InstanceLink,
|
||||
) -> Option<ContentSourceKind> {
|
||||
match link {
|
||||
InstanceLink::ModrinthModpack { .. } => {
|
||||
Some(ContentSourceKind::ModrinthModpack)
|
||||
}
|
||||
InstanceLink::ServerProjectModpack { .. } => {
|
||||
Some(ContentSourceKind::ServerProject)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn check_modpack_update(
|
||||
installed_version_id: &str,
|
||||
installed_version: &Version,
|
||||
|
||||
@@ -39,9 +39,18 @@ pub(crate) async fn sync_instance_content_files(
|
||||
&state.api_semaphore,
|
||||
)
|
||||
.await?;
|
||||
let hashes_by_path = hashes
|
||||
let hashes_by_key = hashes
|
||||
.into_iter()
|
||||
.map(|hash| (hash.path.clone(), hash))
|
||||
.map(|hash| {
|
||||
(
|
||||
format!(
|
||||
"{}-{}",
|
||||
hash.size,
|
||||
hash.path.trim_end_matches(".disabled")
|
||||
),
|
||||
hash,
|
||||
)
|
||||
})
|
||||
.collect::<HashMap<_, _>>();
|
||||
let existing_files =
|
||||
sqlite::content_rows::get_instance_files(&instance.id, &state.pool)
|
||||
@@ -55,8 +64,8 @@ pub(crate) async fn sync_instance_content_files(
|
||||
let mut files = Vec::new();
|
||||
|
||||
for file in scanned {
|
||||
let cache_path = format!("{}/{}", instance.path, file.relative_path);
|
||||
let Some(hash) = hashes_by_path.get(&cache_path) else {
|
||||
let hash_key = file.hash_cache_key.trim_end_matches(".disabled");
|
||||
let Some(hash) = hashes_by_key.get(hash_key) else {
|
||||
continue;
|
||||
};
|
||||
let existing_file = existing_files_by_path.get(&file.relative_path);
|
||||
|
||||
Reference in New Issue
Block a user