Store an uploaded mod: the artifact plus a `mod.json` the catalog scan picks up. `modId` is `slug(name)-version`, where `version` defaults to the first 8 hex of the file's SHA-256 (the `name-hash8` convention).
(&self, input: &PublishModInput)
| 180 | prefix: normalize_prefix(config.prefix), |
| 181 | signed_url_ttl: config.signed_url_ttl, |
| 182 | current_lock: Arc::new(tokio::sync::Mutex::new(())), |
| 183 | artifact_placement: ArtifactPlacement::ReservedRename, |
| 184 | }) |
| 185 | } |
| 186 | |
| 187 | async fn place_temp_if_absent( |
| 188 | &self, |
| 189 | temp: &ObjectPath, |
| 190 | destination: &ObjectPath, |
| 191 | ) -> object_store::Result<()> { |
| 192 | match self.artifact_placement { |
| 193 | ArtifactPlacement::ConditionalRename => { |
| 194 | self.store.rename_if_not_exists(temp, destination).await?; |
| 195 | } |
| 196 | ArtifactPlacement::ReservedRename => { |
| 197 | let reservation = ObjectPath::from(format!("{}.reserved", destination.as_ref())); |
| 198 | self.store |
| 199 | .put_opts( |
| 200 | &reservation, |
| 201 | Bytes::from(temp.as_ref().as_bytes().to_vec()).into(), |
| 202 | PutMode::Create.into(), |
| 203 | ) |
| 204 | .await?; |
| 205 | self.store.rename(temp, destination).await?; |
| 206 | } |
| 207 | } |
| 208 | Ok(()) |
| 209 | } |
| 210 | |
| 211 | fn artifact_path(mod_id: &str) -> ObjectPath { |
| 212 | ObjectPath::from(format!("{mod_id}/{mod_id}.{MOD_ARTIFACT_EXT}")) |
| 213 | } |
| 214 | |
| 215 | fn revision_artifact_path(mod_id: &str, revision: u64) -> ObjectPath { |
| 216 | ObjectPath::from(format!( |
| 217 | "{mod_id}/revisions/{revision}/{mod_id}.{MOD_ARTIFACT_EXT}" |
| 218 | )) |
| 219 | } |
| 220 | |
| 221 | fn metadata_path(mod_id: &str) -> ObjectPath { |
| 222 | ObjectPath::from(format!("{mod_id}/{MOD_METADATA_FILE}")) |
| 223 | } |
| 224 | |
| 225 | fn revision_metadata_path(mod_id: &str, revision: u64) -> ObjectPath { |
| 226 | ObjectPath::from(format!("{mod_id}/revisions/{revision}/{MOD_METADATA_FILE}")) |
| 227 | } |
| 228 | |
| 229 | fn current_path(mod_id: &str) -> ObjectPath { |
| 230 | ObjectPath::from(format!("{mod_id}/{CURRENT_FILE}")) |
| 231 | } |
| 232 | |
| 233 | fn store_path(&self, path: ObjectPath) -> ObjectPath { |
| 234 | if let Some(prefix) = &self.prefix { |
| 235 | ObjectPath::from(format!("{}/{}", prefix.as_ref(), path.as_ref())) |
no test coverage detected