Implement DataModel name change removal in PatchSet and adjust session handling in App

- Added a new function to PatchSet to remove the DataModel name change from updates, preventing unwanted synchronization of the project name.
- Updated the App:startSession method to conditionally skip session lock acquisition and release based on one-shot mode settings.
- Enhanced the confirmation callback to utilize the new PatchSet function for filtering DataModel name changes from patches.
This commit is contained in:
Joe 2026-01-30 11:26:40 -06:00
parent 240c225be0
commit 77088eccd8
3 changed files with 62 additions and 42 deletions

View file

@ -153,15 +153,15 @@ function ConfirmingPage:render()
onClick = self.props.onAbort, onClick = self.props.onAbort,
}), }),
PullAll = e(TextButton, { PullAll = e(TextButton, {
text = "Pull All", text = "Pull All",
style = "Danger", style = "Danger",
transparency = self.props.transparency, transparency = self.props.transparency,
layoutOrder = 2, layoutOrder = 2,
onClick = function() onClick = function()
self.setAllSelections("pull") self.setAllSelections("pull")
end, end,
}), }),
SkipAll = e(TextButton, { SkipAll = e(TextButton, {
text = "Skip All", text = "Skip All",

View file

@ -571,22 +571,25 @@ function App:useRunningConnectionInfo()
end end
function App:startSession() function App:startSession()
local claimedLock, priorOwner = self:claimSyncLock() -- Skip session lock in one-shot mode since it's a quick sync-and-disconnect
if not claimedLock then if not Settings:get("oneShotSync") then
local msg = string.format("Could not sync because user '%s' is already syncing", tostring(priorOwner)) local claimedLock, priorOwner = self:claimSyncLock()
if not claimedLock then
local msg = string.format("Could not sync because user '%s' is already syncing", tostring(priorOwner))
Log.warn(msg) Log.warn(msg)
self:addNotification({ self:addNotification({
text = msg, text = msg,
timeout = 10, timeout = 10,
}) })
self:setState({ self:setState({
appStatus = AppStatus.Error, appStatus = AppStatus.Error,
errorMessage = msg, errorMessage = msg,
toolbarIcon = Assets.Images.PluginButtonWarning, toolbarIcon = Assets.Images.PluginButtonWarning,
}) })
return return
end
end end
local host, port = self:getHostAndPort() local host, port = self:getHostAndPort()
@ -671,7 +674,10 @@ function App:startSession()
}) })
elseif status == ServeSession.Status.Disconnected then elseif status == ServeSession.Status.Disconnected then
self.serveSession = nil self.serveSession = nil
self:releaseSyncLock() -- Only release lock if we claimed it (not in one-shot mode)
if not Settings:get("oneShotSync") then
self:releaseSyncLock()
end
self:clearRunningConnectionInfo() self:clearRunningConnectionInfo()
self:setState({ self:setState({
patchData = { patchData = {
@ -709,6 +715,10 @@ function App:startSession()
end) end)
serveSession:setConfirmCallback(function(instanceMap, patch, serverInfo) serveSession:setConfirmCallback(function(instanceMap, patch, serverInfo)
-- Filter out the DataModel name change from the patch
-- The project name (DataModel.Name) is managed by Studio independently
PatchSet.removeDataModelName(patch, instanceMap)
local isOneShotMode = Settings:get("oneShotSync") local isOneShotMode = Settings:get("oneShotSync")
-- ONE-SHOT MODE: Never auto-accept, always require explicit confirmation -- ONE-SHOT MODE: Never auto-accept, always require explicit confirmation
@ -759,24 +769,6 @@ function App:startSession()
return "Accept" return "Accept"
end end
end end
-- The datamodel name gets overwritten by Studio, making confirmation of it intrusive
-- and unnecessary. This special case allows it to be accepted without confirmation.
if
PatchSet.hasAdditions(patch) == false
and PatchSet.hasRemoves(patch) == false
and PatchSet.containsOnlyInstance(patch, instanceMap, game)
then
local datamodelUpdates = PatchSet.getUpdateForInstance(patch, instanceMap, game)
if
datamodelUpdates ~= nil
and next(datamodelUpdates.changedProperties) == nil
and datamodelUpdates.changedClassName == nil
then
Log.trace("Accepting patch without confirmation because it only contains a datamodel name change")
return "Accept"
end
end
else else
Log.info("One-shot mode: skipping all auto-accept paths, requiring explicit confirmation") Log.info("One-shot mode: skipping all auto-accept paths, requiring explicit confirmation")
end end

View file

@ -394,6 +394,34 @@ function PatchSet.updatedIdList(patchSet): { string }
return table.freeze(idList) return table.freeze(idList)
end end
--[[
Remove the Name property change from the DataModel update in the patch.
This prevents the project name from being synced, which is usually
unwanted as Studio manages the DataModel name independently.
Mutates the patch in place for efficiency.
]]
function PatchSet.removeDataModelName(patchSet, instanceMap)
local dataModelId = instanceMap.fromInstances[game]
if dataModelId == nil then
return
end
for i, update in ipairs(patchSet.updated) do
if update.id == dataModelId and update.changedName ~= nil then
update.changedName = nil
-- Remove update entirely if no other changes remain
if
update.changedClassName == nil
and update.changedMetadata == nil
and next(update.changedProperties) == nil
then
table.remove(patchSet.updated, i)
end
return
end
end
end
--[[ --[[
Create a list of human-readable statements summarizing the contents of this Create a list of human-readable statements summarizing the contents of this
patch, intended to be displayed to users. patch, intended to be displayed to users.