Working 'init' command for places

This commit is contained in:
Lucien Greathouse
2019-01-09 21:16:08 -08:00
parent 6ced8f32b1
commit 98f8c5c0f2
3 changed files with 84 additions and 26 deletions

View File

@@ -60,7 +60,7 @@ fn main() {
match matches.subcommand() { match matches.subcommand() {
("init", Some(sub_matches)) => { ("init", Some(sub_matches)) => {
let fuzzy_project_path = make_path_absolute(Path::new(sub_matches.value_of("PATH").unwrap_or("."))); let fuzzy_project_path = make_path_absolute(Path::new(sub_matches.value_of("PATH").unwrap_or("")));
let kind = sub_matches.value_of("kind"); let kind = sub_matches.value_of("kind");
let options = commands::InitOptions { let options = commands::InitOptions {

View File

@@ -40,7 +40,7 @@ pub fn init(options: &InitOptions) -> Result<(), InitError> {
Some(invalid) => return Err(InitError::InvalidKind(invalid.to_string())), Some(invalid) => return Err(InitError::InvalidKind(invalid.to_string())),
}; };
println!("Created new {} project at {}", project_kind, project_path.display()); println!("Created new {} project file at {}", project_kind, project_path.display());
Ok(()) Ok(())
} }

View File

@@ -16,6 +16,10 @@ const fn yeah() -> bool {
true true
} }
const fn is_true(value: &bool) -> bool {
*value
}
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)] #[serde(untagged)]
enum SourceProjectNode { enum SourceProjectNode {
@@ -23,10 +27,10 @@ enum SourceProjectNode {
#[serde(rename = "$className")] #[serde(rename = "$className")]
class_name: String, class_name: String,
#[serde(rename = "$properties", default = "HashMap::new")] #[serde(rename = "$properties", default = "HashMap::new", skip_serializing_if = "HashMap::is_empty")]
properties: HashMap<String, RbxValue>, properties: HashMap<String, RbxValue>,
#[serde(rename = "$ignoreUnknownInstances", default = "yeah")] #[serde(rename = "$ignoreUnknownInstances", default = "yeah", skip_serializing_if = "is_true")]
ignore_unknown_instances: bool, ignore_unknown_instances: bool,
#[serde(flatten)] #[serde(flatten)]
@@ -78,9 +82,10 @@ impl SourceProjectNode {
struct SourceProject { struct SourceProject {
name: String, name: String,
tree: SourceProjectNode, tree: SourceProjectNode,
#[serde(skip_serializing_if = "Option::is_none")]
serve_port: Option<u16>, serve_port: Option<u16>,
#[serde(skip_serializing_if = "Option::is_none")]
serve_place_ids: Option<HashSet<u64>>, serve_place_ids: Option<HashSet<u64>>,
serve_place_id: Option<u64>,
} }
impl SourceProject { impl SourceProject {
@@ -174,6 +179,39 @@ pub enum ProjectNode {
SyncPoint(SyncPointProjectNode), SyncPoint(SyncPointProjectNode),
} }
impl ProjectNode {
fn to_source_node(&self, project_file_location: &Path) -> SourceProjectNode {
match self {
ProjectNode::Instance(node) => {
let mut children = HashMap::new();
for (key, child) in &node.children {
children.insert(key.clone(), child.to_source_node(project_file_location));
}
SourceProjectNode::Instance {
class_name: node.class_name.clone(),
children,
properties: node.properties.clone(),
ignore_unknown_instances: node.metadata.ignore_unknown_instances,
}
},
ProjectNode::SyncPoint(sync_node) => {
let project_folder_location = project_file_location.parent().unwrap();
let friendly_path = match sync_node.path.strip_prefix(project_folder_location) {
Ok(stripped) => stripped.to_str().unwrap().replace("\\", "/"),
Err(_) => format!("{}", sync_node.path.display()),
};
SourceProjectNode::SyncPoint {
path: friendly_path,
}
},
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct InstanceProjectNode { pub struct InstanceProjectNode {
@@ -199,18 +237,30 @@ pub struct Project {
} }
impl Project { impl Project {
pub fn init_place(project_fuzzy_location: &Path) -> Result<PathBuf, ProjectInitError> { pub fn init_place(project_fuzzy_path: &Path) -> Result<PathBuf, ProjectInitError> {
let is_exact = project_fuzzy_location.extension().is_some(); let is_exact = project_fuzzy_path.extension().is_some();
let project_name = if is_exact { let project_name = if is_exact {
project_fuzzy_location.parent().unwrap().file_name().unwrap().to_str().unwrap() project_fuzzy_path.parent().unwrap().file_name().unwrap().to_str().unwrap()
} else { } else {
project_fuzzy_location.file_name().unwrap().to_str().unwrap() project_fuzzy_path.file_name().unwrap().to_str().unwrap()
}; };
// TODO: Add children for src folder, potentially client, server, and // TODO: Add children for src folder, potentially client, server, and
// common? // common?
let mut http_service_properties = HashMap::new();
http_service_properties.insert("HttpEnabled".to_string(), RbxValue::Bool {
value: true,
});
let http_service = ProjectNode::Instance(InstanceProjectNode {
class_name: "HttpService".to_string(),
children: HashMap::new(),
properties: http_service_properties,
metadata: Default::default(),
});
let replicated_storage_children = HashMap::new(); let replicated_storage_children = HashMap::new();
let replicated_storage = ProjectNode::Instance(InstanceProjectNode { let replicated_storage = ProjectNode::Instance(InstanceProjectNode {
@@ -222,6 +272,7 @@ impl Project {
let mut root_children = HashMap::new(); let mut root_children = HashMap::new();
root_children.insert("ReplicatedStorage".to_string(), replicated_storage); root_children.insert("ReplicatedStorage".to_string(), replicated_storage);
root_children.insert("HttpService".to_string(), http_service);
let tree = ProjectNode::Instance(InstanceProjectNode { let tree = ProjectNode::Instance(InstanceProjectNode {
class_name: "DataModel".to_string(), class_name: "DataModel".to_string(),
@@ -230,42 +281,44 @@ impl Project {
metadata: Default::default(), metadata: Default::default(),
}); });
let project_path = Project::init_pick_path(project_fuzzy_path)?;
let project = Project { let project = Project {
name: project_name.to_string(), name: project_name.to_string(),
tree, tree,
serve_port: None, serve_port: None,
serve_place_ids: None, serve_place_ids: None,
file_location: project_fuzzy_location.to_path_buf(), file_location: project_path.clone(),
}; };
Project::init_internal(project_fuzzy_location, &project) project.save()
.map_err(ProjectInitError::SaveError)?;
Ok(project_path)
} }
pub fn init_model(_project_fuzzy_location: &Path) -> Result<PathBuf, ProjectInitError> { pub fn init_model(_project_fuzzy_path: &Path) -> Result<PathBuf, ProjectInitError> {
unimplemented!(); unimplemented!();
} }
fn init_internal(project_fuzzy_location: &Path, project: &Project) -> Result<PathBuf, ProjectInitError> { fn init_pick_path(project_fuzzy_path: &Path) -> Result<PathBuf, ProjectInitError> {
let is_exact = project_fuzzy_location.extension().is_some(); let is_exact = project_fuzzy_path.extension().is_some();
let project_location = if is_exact { let project_path = if is_exact {
project_fuzzy_location.to_path_buf() project_fuzzy_path.to_path_buf()
} else { } else {
project_fuzzy_location.join(PROJECT_FILENAME) project_fuzzy_path.join(PROJECT_FILENAME)
}; };
match fs::metadata(&project_location) { match fs::metadata(&project_path) {
Err(error) => match error.kind() { Err(error) => match error.kind() {
io::ErrorKind::NotFound => {}, io::ErrorKind::NotFound => {},
_ => return Err(ProjectInitError::IoError(error)), _ => return Err(ProjectInitError::IoError(error)),
}, },
Ok(_) => return Err(ProjectInitError::AlreadyExists(project_location)), Ok(_) => return Err(ProjectInitError::AlreadyExists(project_path)),
} }
project.save(&project_location) Ok(project_path)
.map_err(ProjectInitError::SaveError)?;
Ok(project_location)
} }
pub fn locate(start_location: &Path) -> Option<PathBuf> { pub fn locate(start_location: &Path) -> Option<PathBuf> {
@@ -310,9 +363,9 @@ impl Project {
Ok(parsed.into_project(project_file_location)) Ok(parsed.into_project(project_file_location))
} }
pub fn save(&self, path: &Path) -> Result<(), ProjectSaveError> { pub fn save(&self) -> Result<(), ProjectSaveError> {
let source_project = self.to_source_project(); let source_project = self.to_source_project();
let mut file = File::create(path) let mut file = File::create(&self.file_location)
.map_err(ProjectSaveError::IoError)?; .map_err(ProjectSaveError::IoError)?;
serde_json::to_writer_pretty(&mut file, &source_project) serde_json::to_writer_pretty(&mut file, &source_project)
@@ -322,6 +375,11 @@ impl Project {
} }
fn to_source_project(&self) -> SourceProject { fn to_source_project(&self) -> SourceProject {
unimplemented!(); SourceProject {
name: self.name.clone(),
tree: self.tree.to_source_node(&self.file_location),
serve_port: self.serve_port,
serve_place_ids: self.serve_place_ids.clone(),
}
} }
} }