Skip to content

Commit

Permalink
Merge branch 'master' into new-plugin-template
Browse files Browse the repository at this point in the history
  • Loading branch information
nezuo authored Jul 18, 2023
2 parents a9bbef7 + dc17a18 commit 9f65e16
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 56 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* Better settings controls ([#725])
* Rework patch visualizer with many fixes and improvements ([#726])
* Added support for syncing in `.toml` files ([#633])
* Add `plugin` flag to the `build` command that outputs to the local plugins folder ([#735])
* Add new plugin template to the `init` command ([#738])

[#668]: https://github.com/rojo-rbx/rojo/pull/668
Expand All @@ -35,6 +36,7 @@
[#725]: https://github.com/rojo-rbx/rojo/pull/725
[#726]: https://github.com/rojo-rbx/rojo/pull/726
[#633]: https://github.com/rojo-rbx/rojo/pull/633
[#735]: https://github.com/rojo-rbx/rojo/pull/735
[#738]: https://github.com/rojo-rbx/rojo/pull/738

## [7.3.0] - April 22, 2023
Expand Down
3 changes: 2 additions & 1 deletion benches/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,12 @@ fn bench_build_place(c: &mut Criterion, name: &str, path: &str) {
fn place_setup<P: AsRef<Path>>(input_path: P) -> (TempDir, BuildCommand) {
let dir = tempdir().unwrap();
let input = input_path.as_ref().to_path_buf();
let output = dir.path().join("output.rbxlx");
let output = Some(dir.path().join("output.rbxlx"));

let options = BuildCommand {
project: input,
watch: false,
plugin: None,
output,
};

Expand Down
15 changes: 2 additions & 13 deletions plugin/src/ApiContext.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,6 @@ local validateApiInfo = Types.ifEnabled(Types.ApiInfoResponse)
local validateApiRead = Types.ifEnabled(Types.ApiReadResponse)
local validateApiSubscribe = Types.ifEnabled(Types.ApiSubscribeResponse)

--[[
Returns a promise that will never resolve nor reject.
]]
local function hangingPromise()
return Promise.new(function() end)
end

local function rejectFailedRequests(response)
if response.code >= 400 then
local message = string.format("HTTP %s:\n%s", tostring(response.code), response.body)
Expand Down Expand Up @@ -212,12 +205,8 @@ function ApiContext:retrieveMessages()
local function sendRequest()
local request = Http.get(url)
:catch(function(err)
if err.type == Http.Error.Kind.Timeout then
if self.__connected then
return sendRequest()
else
return hangingPromise()
end
if err.type == Http.Error.Kind.Timeout and self.__connected then
return sendRequest()
end

return Promise.reject(err)
Expand Down
2 changes: 1 addition & 1 deletion plugin/src/App/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ function App:startSession()
end)
end)

serveSession:onPatchApplied(function(patch, unapplied)
serveSession:hookPostcommit(function(patch, _instanceMap, unapplied)
local now = os.time()
local old = self.state.patchData

Expand Down
63 changes: 38 additions & 25 deletions plugin/src/ServeSession.lua
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ function ServeSession.new(options)
__instanceMap = instanceMap,
__changeBatcher = changeBatcher,
__statusChangedCallback = nil,
__patchAppliedCallback = nil,
__connections = connections,
}

Expand Down Expand Up @@ -129,8 +128,12 @@ function ServeSession:setConfirmCallback(callback)
self.__userConfirmCallback = callback
end

function ServeSession:onPatchApplied(callback)
self.__patchAppliedCallback = callback
function ServeSession:hookPrecommit(callback)
return self.__reconciler:hookPrecommit(callback)
end

function ServeSession:hookPostcommit(callback)
return self.__reconciler:hookPostcommit(callback)
end

function ServeSession:start()
Expand Down Expand Up @@ -291,35 +294,45 @@ function ServeSession:__initialSync(serverInfo)
Log.warn("Could not apply all changes requested by the Rojo server:\n{}",
PatchSet.humanSummary(self.__instanceMap, unappliedPatch))
end
if self.__patchAppliedCallback then
pcall(self.__patchAppliedCallback, catchUpPatch, unappliedPatch)
end
end
end)
end

function ServeSession:__mainSyncLoop()
return self.__apiContext:retrieveMessages()
:andThen(function(messages)
Log.trace("Serve session {} retrieved {} messages", tostring(self), #messages)

for _, message in ipairs(messages) do
local unappliedPatch = self.__reconciler:applyPatch(message)

if not PatchSet.isEmpty(unappliedPatch) then
Log.warn("Could not apply all changes requested by the Rojo server:\n{}",
PatchSet.humanSummary(self.__instanceMap, unappliedPatch))
end

if self.__patchAppliedCallback then
pcall(self.__patchAppliedCallback, message, unappliedPatch)
end
return Promise.new(function(resolve, reject)
while self.__status == Status.Connected do
local success, result = self.__apiContext:retrieveMessages()
:andThen(function(messages)
if self.__status == Status.Disconnected then
-- In the time it took to retrieve messages, we disconnected
-- so we just resolve immediately without patching anything
return
end

Log.trace("Serve session {} retrieved {} messages", tostring(self), #messages)

for _, message in messages do
local unappliedPatch = self.__reconciler:applyPatch(message)

if not PatchSet.isEmpty(unappliedPatch) then
Log.warn("Could not apply all changes requested by the Rojo server:\n{}",
PatchSet.humanSummary(self.__instanceMap, unappliedPatch))
end
end
end):await()

if self.__status == Status.Disconnected then
-- If we are no longer connected after applying, we stop silently
-- without checking for errors as they are no longer relevant
break
elseif success == false then
reject(result)
end
end

if self.__status ~= Status.Disconnected then
return self:__mainSyncLoop()
end
end)
-- We are no longer connected, so we resolve the promise
resolve()
end)
end

function ServeSession:__stopInternal(err)
Expand Down
87 changes: 71 additions & 16 deletions src/cli/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ use std::{
path::{Path, PathBuf},
};

use anyhow::Context;
use clap::Parser;
use anyhow::{bail, Context};
use clap::{CommandFactory, Parser};
use fs_err::File;
use memofs::Vfs;
use roblox_install::RobloxStudio;
use tokio::runtime::Runtime;

use crate::serve_session::ServeSession;
Expand All @@ -16,6 +17,8 @@ use super::resolve_path;

const UNKNOWN_OUTPUT_KIND_ERR: &str = "Could not detect what kind of file to build. \
Expected output file to end in .rbxl, .rbxlx, .rbxm, or .rbxmx.";
const UNKNOWN_PLUGIN_KIND_ERR: &str = "Could not detect what kind of file to build. \
Expected plugin file to end in .rbxm or .rbxmx.";

/// Generates a model or place file from the Rojo project.
#[derive(Debug, Parser)]
Expand All @@ -28,7 +31,13 @@ pub struct BuildCommand {
///
/// Should end in .rbxm, .rbxl, .rbxmx, or .rbxlx.
#[clap(long, short)]
pub output: PathBuf,
pub output: Option<PathBuf>,

/// Alternative to the output flag that outputs the result in the local plugins folder.
///
/// Should end in .rbxm or .rbxl.
#[clap(long, short)]
pub plugin: Option<PathBuf>,

/// Whether to automatically rebuild when any input files change.
#[clap(long)]
Expand All @@ -37,18 +46,52 @@ pub struct BuildCommand {

impl BuildCommand {
pub fn run(self) -> anyhow::Result<()> {
let project_path = resolve_path(&self.project);
let (output_path, output_kind) = match (self.output, self.plugin) {
(Some(_), Some(_)) => {
BuildCommand::command()
.error(
clap::ErrorKind::ArgumentConflict,
"the argument '--output <OUTPUT>' cannot be used with '--plugin <PLUGIN>'",
)
.exit();
}
(None, None) => {
BuildCommand::command()
.error(
clap::ErrorKind::MissingRequiredArgument,
"one of the following arguments must be provided: \n --output <OUTPUT>\n --plugin <PLUGIN>",
)
.exit();
}
(Some(output), None) => {
let output_kind =
OutputKind::from_output_path(&output).context(UNKNOWN_OUTPUT_KIND_ERR)?;

(output, output_kind)
}
(None, Some(plugin)) => {
if plugin.is_absolute() {
bail!("plugin flag path cannot be absolute.")
}

let output_kind = detect_output_kind(&self.output).context(UNKNOWN_OUTPUT_KIND_ERR)?;
let output_kind =
OutputKind::from_plugin_path(&plugin).context(UNKNOWN_PLUGIN_KIND_ERR)?;
let studio = RobloxStudio::locate()?;

(studio.plugins_path().join(&plugin), output_kind)
}
};

let project_path = resolve_path(&self.project);

log::trace!("Constructing in-memory filesystem");
let vfs = Vfs::new_default();
vfs.set_watch_enabled(self.watch);

let session = ServeSession::new(vfs, &project_path)?;
let session = ServeSession::new(vfs, project_path)?;
let mut cursor = session.message_queue().cursor();

write_model(&session, &self.output, output_kind)?;
write_model(&session, &output_path, output_kind)?;

if self.watch {
let rt = Runtime::new().unwrap();
Expand All @@ -58,7 +101,7 @@ impl BuildCommand {
let (new_cursor, _patch_set) = rt.block_on(receiver).unwrap();
cursor = new_cursor;

write_model(&session, &self.output, output_kind)?;
write_model(&session, &output_path, output_kind)?;
}
}

Expand Down Expand Up @@ -86,15 +129,27 @@ enum OutputKind {
Rbxl,
}

fn detect_output_kind(output: &Path) -> Option<OutputKind> {
let extension = output.extension()?.to_str()?;
impl OutputKind {
fn from_output_path(output: &Path) -> Option<OutputKind> {
let extension = output.extension()?.to_str()?;

match extension {
"rbxlx" => Some(OutputKind::Rbxlx),
"rbxmx" => Some(OutputKind::Rbxmx),
"rbxl" => Some(OutputKind::Rbxl),
"rbxm" => Some(OutputKind::Rbxm),
_ => None,
}
}

match extension {
"rbxlx" => Some(OutputKind::Rbxlx),
"rbxmx" => Some(OutputKind::Rbxmx),
"rbxl" => Some(OutputKind::Rbxl),
"rbxm" => Some(OutputKind::Rbxm),
_ => None,
fn from_plugin_path(output: &Path) -> Option<OutputKind> {
let extension = output.extension()?.to_str()?;

match extension {
"rbxmx" => Some(OutputKind::Rbxmx),
"rbxm" => Some(OutputKind::Rbxm),
_ => None,
}
}
}

Expand Down

0 comments on commit 9f65e16

Please sign in to comment.