mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-10-23 05:51:39 +00:00
Implement Project, which is more direct
This commit is contained in:
parent
6b9367c370
commit
0a05ab4d69
3 changed files with 121 additions and 58 deletions
|
|
@ -1,10 +1,10 @@
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process;
|
use std::process;
|
||||||
|
|
||||||
use project::SourceProject;
|
use project::Project;
|
||||||
|
|
||||||
pub fn init(project_path: &PathBuf) {
|
pub fn init(project_path: &PathBuf) {
|
||||||
match SourceProject::init(project_path) {
|
match Project::init(project_path) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
println!("Created new empty project at {}", project_path.display());
|
println!("Created new empty project at {}", project_path.display());
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,17 @@
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process;
|
use std::process;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
use rand;
|
use rand;
|
||||||
|
|
||||||
use project::SourceProject;
|
use project::Project;
|
||||||
use web;
|
use web;
|
||||||
use session::{Session, SessionConfig};
|
use session::{Session, SessionConfig};
|
||||||
use partition::Partition;
|
|
||||||
|
|
||||||
pub fn serve(project_path: &PathBuf, port: Option<u64>) {
|
pub fn serve(project_path: &PathBuf, port: Option<u64>) {
|
||||||
let server_id = rand::random::<u64>();
|
let server_id = rand::random::<u64>();
|
||||||
|
|
||||||
let project = match SourceProject::load(project_path) {
|
let project = match Project::load(project_path) {
|
||||||
Ok(v) => {
|
Ok(v) => {
|
||||||
println!("Using project from {}", fs::canonicalize(project_path).unwrap().display());
|
println!("Using project from {}", fs::canonicalize(project_path).unwrap().display());
|
||||||
v
|
v
|
||||||
|
|
@ -24,21 +22,8 @@ pub fn serve(project_path: &PathBuf, port: Option<u64>) {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut partitions = HashMap::new();
|
|
||||||
|
|
||||||
for (partition_name, partition) in project.partitions.iter() {
|
|
||||||
let path = fs::canonicalize(project_path.join(&partition.path)).unwrap();
|
|
||||||
let target = partition.target.split(".").map(String::from).collect::<Vec<_>>();
|
|
||||||
|
|
||||||
partitions.insert(partition_name.clone(), Partition {
|
|
||||||
path,
|
|
||||||
target,
|
|
||||||
name: partition_name.clone(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let config = SessionConfig {
|
let config = SessionConfig {
|
||||||
partitions: partitions.clone(),
|
partitions: project.partitions.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
println!("Using session config {:#?}", config);
|
println!("Using session config {:#?}", config);
|
||||||
|
|
@ -51,7 +36,7 @@ pub fn serve(project_path: &PathBuf, port: Option<u64>) {
|
||||||
server_id,
|
server_id,
|
||||||
rbx_session: session.get_rbx_session(),
|
rbx_session: session.get_rbx_session(),
|
||||||
message_session: session.get_message_session(),
|
message_session: session.get_message_session(),
|
||||||
partitions,
|
partitions: project.partitions,
|
||||||
};
|
};
|
||||||
|
|
||||||
println!("Server listening on port {}", web_config.port);
|
println!("Server listening on port {}", web_config.port);
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ use rand::{self, Rng};
|
||||||
|
|
||||||
use serde_json;
|
use serde_json;
|
||||||
|
|
||||||
|
use partition::Partition;
|
||||||
|
|
||||||
pub static PROJECT_FILENAME: &'static str = "rojo.json";
|
pub static PROJECT_FILENAME: &'static str = "rojo.json";
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -61,7 +63,7 @@ impl fmt::Display for ProjectInitError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct SourceProjectPartition {
|
pub struct SourceProjectPartition {
|
||||||
/// A slash-separated path to a file or folder, relative to the project's
|
/// A slash-separated path to a file or folder, relative to the project's
|
||||||
|
|
@ -72,12 +74,14 @@ pub struct SourceProjectPartition {
|
||||||
pub target: String,
|
pub target: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents a project configured by a user for use with Rojo. Holds anything
|
/// Represents a Rojo project in the format that's most convenient for users to
|
||||||
/// that can be configured with `rojo.json`.
|
/// edit. This should generally line up with `Project`, but can diverge when
|
||||||
///
|
/// there's either compatibility shims or when the data structures that Rojo
|
||||||
/// In the future, this object will hold dependency information and other handy
|
/// want are too verbose to write in JSON but easy to convert from something
|
||||||
/// configurables
|
/// else.
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
//
|
||||||
|
/// Holds anything that can be configured with `rojo.json`.
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
#[serde(default, rename_all = "camelCase")]
|
#[serde(default, rename_all = "camelCase")]
|
||||||
pub struct SourceProject {
|
pub struct SourceProject {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
@ -85,17 +89,98 @@ pub struct SourceProject {
|
||||||
pub partitions: HashMap<String, SourceProjectPartition>,
|
pub partitions: HashMap<String, SourceProjectPartition>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SourceProject {
|
impl Default for SourceProject {
|
||||||
|
fn default() -> SourceProject {
|
||||||
|
SourceProject {
|
||||||
|
name: "new-project".to_string(),
|
||||||
|
serve_port: 8000,
|
||||||
|
partitions: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents a Rojo project in the format that's convenient for Rojo to work
|
||||||
|
/// with.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Project {
|
||||||
|
/// The path to the project file that this project is associated with.
|
||||||
|
pub project_path: PathBuf,
|
||||||
|
|
||||||
|
/// The name of this project, used for user-facing labels.
|
||||||
|
pub name: String,
|
||||||
|
|
||||||
|
/// The port that this project will run a web server on.
|
||||||
|
pub serve_port: u64,
|
||||||
|
|
||||||
|
/// All of the project's partitions, laid out in an expanded way.
|
||||||
|
pub partitions: HashMap<String, Partition>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Project {
|
||||||
|
fn from_source_project(source_project: SourceProject, project_path: PathBuf) -> Project {
|
||||||
|
let mut partitions = HashMap::new();
|
||||||
|
|
||||||
|
{
|
||||||
|
let project_directory = project_path.parent().unwrap();
|
||||||
|
|
||||||
|
for (partition_name, partition) in source_project.partitions.into_iter() {
|
||||||
|
let path = project_directory.join(&partition.path);
|
||||||
|
let target = partition.target
|
||||||
|
.split(".")
|
||||||
|
.map(String::from)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
partitions.insert(partition_name.clone(), Partition {
|
||||||
|
path,
|
||||||
|
target,
|
||||||
|
name: partition_name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Project {
|
||||||
|
project_path,
|
||||||
|
name: source_project.name,
|
||||||
|
serve_port: source_project.serve_port,
|
||||||
|
partitions,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_source_project(&self) -> SourceProject {
|
||||||
|
let mut partitions = HashMap::new();
|
||||||
|
|
||||||
|
for partition in self.partitions.values() {
|
||||||
|
let path = partition.path.strip_prefix(&self.project_path)
|
||||||
|
.unwrap_or_else(|_| &partition.path)
|
||||||
|
.to_str()
|
||||||
|
.unwrap()
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
let target = partition.target.join(".");
|
||||||
|
|
||||||
|
partitions.insert(partition.name.clone(), SourceProjectPartition {
|
||||||
|
path,
|
||||||
|
target,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceProject {
|
||||||
|
partitions,
|
||||||
|
name: self.name.clone(),
|
||||||
|
serve_port: self.serve_port,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Initializes a new project inside the given folder path.
|
/// Initializes a new project inside the given folder path.
|
||||||
pub fn init<T: AsRef<Path>>(location: T) -> Result<SourceProject, ProjectInitError> {
|
pub fn init<T: AsRef<Path>>(location: T) -> Result<Project, ProjectInitError> {
|
||||||
let location = location.as_ref();
|
let location = location.as_ref();
|
||||||
let package_path = location.join(PROJECT_FILENAME);
|
let project_path = location.join(PROJECT_FILENAME);
|
||||||
|
|
||||||
// We abort if the project file already exists.
|
// We abort if the project file already exists.
|
||||||
fs::metadata(&package_path)
|
fs::metadata(&project_path)
|
||||||
.map_err(|_| ProjectInitError::AlreadyExists)?;
|
.map_err(|_| ProjectInitError::AlreadyExists)?;
|
||||||
|
|
||||||
let mut file = File::create(&package_path)
|
let mut file = File::create(&project_path)
|
||||||
.map_err(|_| ProjectInitError::FailedToCreate)?;
|
.map_err(|_| ProjectInitError::FailedToCreate)?;
|
||||||
|
|
||||||
// Try to give the project a meaningful name.
|
// Try to give the project a meaningful name.
|
||||||
|
|
@ -109,60 +194,53 @@ impl SourceProject {
|
||||||
let serve_port = rand::thread_rng().gen_range(2000, 49151);
|
let serve_port = rand::thread_rng().gen_range(2000, 49151);
|
||||||
|
|
||||||
// Configure the project with all of the values we know so far.
|
// Configure the project with all of the values we know so far.
|
||||||
let project = SourceProject {
|
let source_project = SourceProject {
|
||||||
name,
|
name,
|
||||||
serve_port,
|
serve_port,
|
||||||
partitions: HashMap::new(),
|
partitions: HashMap::new(),
|
||||||
};
|
};
|
||||||
let serialized = serde_json::to_string_pretty(&project).unwrap();
|
let serialized = serde_json::to_string_pretty(&source_project).unwrap();
|
||||||
|
|
||||||
file.write(serialized.as_bytes())
|
file.write(serialized.as_bytes())
|
||||||
.map_err(|_| ProjectInitError::FailedToWrite)?;
|
.map_err(|_| ProjectInitError::FailedToWrite)?;
|
||||||
|
|
||||||
Ok(project)
|
Ok(Project::from_source_project(source_project, project_path))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to load a project from the file named PROJECT_FILENAME from the
|
/// Attempts to load a project from the file named PROJECT_FILENAME from the
|
||||||
/// given folder.
|
/// given folder.
|
||||||
pub fn load<T: AsRef<Path>>(location: T) -> Result<SourceProject, ProjectLoadError> {
|
pub fn load<T: AsRef<Path>>(location: T) -> Result<Project, ProjectLoadError> {
|
||||||
let package_path = location.as_ref().join(Path::new(PROJECT_FILENAME));
|
let project_path = location.as_ref().join(Path::new(PROJECT_FILENAME));
|
||||||
|
|
||||||
fs::metadata(&package_path)
|
fs::metadata(&project_path)
|
||||||
.map_err(|_| ProjectLoadError::DidNotExist(package_path.clone()))?;
|
.map_err(|_| ProjectLoadError::DidNotExist(project_path.clone()))?;
|
||||||
|
|
||||||
let mut file = File::open(&package_path)
|
let mut file = File::open(&project_path)
|
||||||
.map_err(|_| ProjectLoadError::FailedToOpen(package_path.clone()))?;
|
.map_err(|_| ProjectLoadError::FailedToOpen(project_path.clone()))?;
|
||||||
|
|
||||||
let mut contents = String::new();
|
let mut contents = String::new();
|
||||||
|
|
||||||
file.read_to_string(&mut contents)
|
file.read_to_string(&mut contents)
|
||||||
.map_err(|_| ProjectLoadError::FailedToRead(package_path.clone()))?;
|
.map_err(|_| ProjectLoadError::FailedToRead(project_path.clone()))?;
|
||||||
|
|
||||||
serde_json::from_str(&contents)
|
let source_project = serde_json::from_str(&contents)
|
||||||
.map_err(|e| ProjectLoadError::InvalidJson(package_path.clone(), e))
|
.map_err(|e| ProjectLoadError::InvalidJson(project_path.clone(), e))?;
|
||||||
|
|
||||||
|
Ok(Project::from_source_project(source_project, project_path))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Saves the given project file to the given folder with the appropriate name.
|
/// Saves the given project file to the given folder with the appropriate name.
|
||||||
pub fn save<T: AsRef<Path>>(&self, location: T) -> Result<(), ProjectSaveError> {
|
pub fn save<T: AsRef<Path>>(&self, location: T) -> Result<(), ProjectSaveError> {
|
||||||
let package_path = location.as_ref().join(Path::new(PROJECT_FILENAME));
|
let project_path = location.as_ref().join(Path::new(PROJECT_FILENAME));
|
||||||
|
|
||||||
let mut file = File::create(&package_path)
|
let mut file = File::create(&project_path)
|
||||||
.map_err(|_| ProjectSaveError::FailedToCreate)?;
|
.map_err(|_| ProjectSaveError::FailedToCreate)?;
|
||||||
|
|
||||||
let serialized = serde_json::to_string_pretty(self).unwrap();
|
let source_project = self.as_source_project();
|
||||||
|
let serialized = serde_json::to_string_pretty(&source_project).unwrap();
|
||||||
|
|
||||||
file.write(serialized.as_bytes()).unwrap();
|
file.write(serialized.as_bytes()).unwrap();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for SourceProject {
|
|
||||||
fn default() -> SourceProject {
|
|
||||||
SourceProject {
|
|
||||||
name: "new-project".to_string(),
|
|
||||||
serve_port: 8000,
|
|
||||||
partitions: HashMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue