mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-04-22 13:45:16 +00:00
Unlike most of the other backports, this code couldn't be directly translated so it had to be re-implemented. Luckily, it is very simple. This implementation is a bit messy and heavy handed with potential panics, but I think it's probably fine since file names that aren't UTF-8 aren't really supported anyway. The original implementation is a lot cleaner though. The test snapshots are (almost) all identical between the 7.5 implementation and this one. The sole exception is with the path in the `snapshot_middleware::project` test, since I didn't feel like adding a `name` parameter to `snapshot_project` in this implementation.
This commit is contained in:
@@ -39,7 +39,7 @@ enum Error {
|
||||
#[serde(deny_unknown_fields, rename_all = "camelCase")]
|
||||
pub struct Project {
|
||||
/// The name of the top-level instance described by the project.
|
||||
pub name: String,
|
||||
pub name: Option<String>,
|
||||
|
||||
/// The tree of instances described by this project. Projects always
|
||||
/// describe at least one instance.
|
||||
|
||||
@@ -110,7 +110,7 @@ impl ServeSession {
|
||||
|
||||
log::debug!("Loading project file from {}", project_path.display());
|
||||
|
||||
let root_project = match vfs.read(&project_path).with_not_found()? {
|
||||
let mut root_project = match vfs.read(&project_path).with_not_found()? {
|
||||
Some(contents) => Project::load_from_slice(&contents, &project_path)?,
|
||||
None => {
|
||||
return Err(ServeSessionError::NoProjectFound {
|
||||
@@ -118,6 +118,35 @@ impl ServeSession {
|
||||
});
|
||||
}
|
||||
};
|
||||
if root_project.name.is_none() {
|
||||
if let Some(file_name) = project_path.file_name().and_then(|s| s.to_str()) {
|
||||
if file_name == "default.project.json" {
|
||||
let folder_name = project_path
|
||||
.parent()
|
||||
.and_then(Path::file_name)
|
||||
.and_then(|s| s.to_str());
|
||||
if let Some(folder_name) = folder_name {
|
||||
root_project.name = Some(folder_name.to_string());
|
||||
} else {
|
||||
return Err(ServeSessionError::FolderNameInvalid {
|
||||
path: project_path.to_path_buf(),
|
||||
});
|
||||
}
|
||||
} else if let Some(trimmed) = file_name.strip_suffix(".project.json") {
|
||||
root_project.name = Some(trimmed.to_string());
|
||||
} else {
|
||||
return Err(ServeSessionError::ProjectNameInvalid {
|
||||
path: project_path.to_path_buf(),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return Err(ServeSessionError::ProjectNameInvalid {
|
||||
path: project_path.to_path_buf(),
|
||||
});
|
||||
}
|
||||
}
|
||||
// Rebind it to make it no longer mutable
|
||||
let root_project = root_project;
|
||||
|
||||
let mut tree = RojoTree::new(InstanceSnapshot::new());
|
||||
|
||||
@@ -190,7 +219,10 @@ impl ServeSession {
|
||||
}
|
||||
|
||||
pub fn project_name(&self) -> &str {
|
||||
&self.root_project.name
|
||||
self.root_project
|
||||
.name
|
||||
.as_ref()
|
||||
.expect("all top-level projects must have their name set")
|
||||
}
|
||||
|
||||
pub fn project_port(&self) -> Option<u16> {
|
||||
@@ -231,6 +263,14 @@ pub enum ServeSessionError {
|
||||
)]
|
||||
NoProjectFound { path: PathBuf },
|
||||
|
||||
#[error("The folder for the provided project cannot be used as a project name: {}\n\
|
||||
Consider setting the `name` field on this project.", .path.display())]
|
||||
FolderNameInvalid { path: PathBuf },
|
||||
|
||||
#[error("The file name of the provided project cannot be used as a project name: {}.\n\
|
||||
Consider setting the `name` field on this project.", .path.display())]
|
||||
ProjectNameInvalid { path: PathBuf },
|
||||
|
||||
#[error(transparent)]
|
||||
Io {
|
||||
#[from]
|
||||
|
||||
@@ -22,6 +22,25 @@ pub fn snapshot_project(
|
||||
let project = Project::load_from_slice(&vfs.read(path)?, path)
|
||||
.with_context(|| format!("File was not a valid Rojo project: {}", path.display()))?;
|
||||
|
||||
// This is not how I would normally do this, but this is a temporary
|
||||
// implementation. The one in 7.5+ is better.
|
||||
let project_name = project.name.as_deref().unwrap_or_else(|| {
|
||||
let file_name = path
|
||||
.file_name()
|
||||
.and_then(|s| s.to_str())
|
||||
.expect("project file names should be valid UTF-8");
|
||||
if file_name == "default.project.json" {
|
||||
path.parent()
|
||||
.and_then(Path::file_name)
|
||||
.and_then(|s| s.to_str())
|
||||
.expect("default.project.json should be inside a folder with a valid UTF-8 name")
|
||||
} else {
|
||||
file_name
|
||||
.strip_suffix(".project.json")
|
||||
.expect("project file names should end with .project.json")
|
||||
}
|
||||
});
|
||||
|
||||
let mut context = context.clone();
|
||||
|
||||
let rules = project.glob_ignore_paths.iter().map(|glob| PathIgnoreRule {
|
||||
@@ -37,7 +56,7 @@ pub fn snapshot_project(
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
match snapshot_project_node(&context, path, &project.name, &project.tree, vfs, None)? {
|
||||
match snapshot_project_node(&context, path, project_name, &project.tree, vfs, None)? {
|
||||
Some(found_snapshot) => {
|
||||
let mut snapshot = found_snapshot;
|
||||
// Setting the instigating source to the project file path is a little
|
||||
@@ -669,4 +688,36 @@ mod test {
|
||||
|
||||
insta::assert_yaml_snapshot!(instance_snapshot);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_name_project() {
|
||||
let _ = env_logger::try_init();
|
||||
|
||||
let mut imfs = InMemoryFs::new();
|
||||
imfs.load_snapshot(
|
||||
"/no_name_project",
|
||||
VfsSnapshot::dir(hashmap! {
|
||||
"default.project.json" => VfsSnapshot::file(r#"
|
||||
{
|
||||
"tree": {
|
||||
"$className": "Model"
|
||||
}
|
||||
}
|
||||
"#),
|
||||
}),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let vfs = Vfs::new(imfs);
|
||||
|
||||
let instance_snapshot = snapshot_project(
|
||||
&InstanceContext::default(),
|
||||
&vfs,
|
||||
Path::new("/no_name_project/default.project.json"),
|
||||
)
|
||||
.expect("snapshot error")
|
||||
.expect("snapshot returned no instances");
|
||||
|
||||
insta::assert_yaml_snapshot!(instance_snapshot);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
source: src/snapshot_middleware/project.rs
|
||||
expression: instance_snapshot
|
||||
---
|
||||
snapshot_id: "00000000000000000000000000000000"
|
||||
metadata:
|
||||
ignore_unknown_instances: true
|
||||
instigating_source:
|
||||
Path: /no_name_project/default.project.json
|
||||
relevant_paths:
|
||||
- /no_name_project/default.project.json
|
||||
context:
|
||||
emit_legacy_scripts: true
|
||||
name: no_name_project
|
||||
class_name: Model
|
||||
properties: {}
|
||||
children: []
|
||||
|
||||
Reference in New Issue
Block a user