mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-10-23 05:51:39 +00:00
Add git metadata handling and integration tests for sync direction defaults
- Introduced new tests for git-based sync direction defaults, verifying the presence of git metadata and correct mappings of changed files to instance references. - Enhanced the `compute_git_metadata` function to include canonical paths for repository roots. - Added multiple test cases to ensure accurate behavior of `changedIds` and `scriptCommittedHashes` based on git status. - Created a new project structure for testing, including various script and model files to facilitate comprehensive testing of git integration. These changes improve the robustness of the git synchronization features and ensure reliable behavior in various scenarios.
This commit is contained in:
parent
7ba04f7f6a
commit
6c0098d839
12 changed files with 1707 additions and 1 deletions
|
|
@ -256,6 +256,440 @@ return function()
|
|||
end)
|
||||
end)
|
||||
|
||||
describe("gitMetadata default selections", function()
|
||||
local SHA1 = require(script.Parent.SHA1)
|
||||
|
||||
local function computeBlobSha1(content)
|
||||
local gitBlob = "blob " .. tostring(#content) .. "\0" .. content
|
||||
return SHA1(buffer.fromstring(gitBlob))
|
||||
end
|
||||
|
||||
it("should default to pull for unchanged files (not in changedIds)", function()
|
||||
local patch = PatchSet.newEmpty()
|
||||
local instanceMap = InstanceMap.new()
|
||||
|
||||
local workspace = game:GetService("Workspace")
|
||||
local folder = Instance.new("Folder")
|
||||
folder.Name = "UnchangedFolder"
|
||||
folder.Parent = workspace
|
||||
|
||||
local id = HttpService:GenerateGUID(false)
|
||||
instanceMap:insert(id, folder)
|
||||
|
||||
table.insert(patch.updated, {
|
||||
id = id,
|
||||
changedName = "Renamed",
|
||||
changedProperties = {},
|
||||
})
|
||||
|
||||
local gitMetadata = {
|
||||
changedIds = {}, -- empty = no files changed in git
|
||||
scriptCommittedHashes = {},
|
||||
}
|
||||
|
||||
local tree = PatchTree.build(patch, instanceMap, { "Property", "Current", "Incoming" }, gitMetadata)
|
||||
local selections = PatchTree.buildInitialSelections(tree)
|
||||
|
||||
expect(selections[id]).to.equal("pull")
|
||||
|
||||
folder:Destroy()
|
||||
instanceMap:stop()
|
||||
end)
|
||||
|
||||
it("should default to nil when no gitMetadata provided", function()
|
||||
local patch = PatchSet.newEmpty()
|
||||
local instanceMap = InstanceMap.new()
|
||||
|
||||
local workspace = game:GetService("Workspace")
|
||||
local folder = Instance.new("Folder")
|
||||
folder.Name = "NoGitFolder"
|
||||
folder.Parent = workspace
|
||||
|
||||
local id = HttpService:GenerateGUID(false)
|
||||
instanceMap:insert(id, folder)
|
||||
|
||||
table.insert(patch.updated, {
|
||||
id = id,
|
||||
changedName = "Renamed",
|
||||
changedProperties = {},
|
||||
})
|
||||
|
||||
local tree = PatchTree.build(patch, instanceMap, { "Property", "Current", "Incoming" }, nil)
|
||||
local selections = PatchTree.buildInitialSelections(tree)
|
||||
|
||||
expect(selections[id]).to.equal(nil)
|
||||
|
||||
folder:Destroy()
|
||||
instanceMap:stop()
|
||||
end)
|
||||
|
||||
it("should default to nil for non-script changed files", function()
|
||||
local patch = PatchSet.newEmpty()
|
||||
local instanceMap = InstanceMap.new()
|
||||
|
||||
local workspace = game:GetService("Workspace")
|
||||
local folder = Instance.new("Folder")
|
||||
folder.Name = "ChangedFolder"
|
||||
folder.Parent = workspace
|
||||
|
||||
local id = HttpService:GenerateGUID(false)
|
||||
instanceMap:insert(id, folder)
|
||||
|
||||
table.insert(patch.updated, {
|
||||
id = id,
|
||||
changedName = "Renamed",
|
||||
changedProperties = {},
|
||||
})
|
||||
|
||||
local gitMetadata = {
|
||||
changedIds = { id },
|
||||
scriptCommittedHashes = {},
|
||||
}
|
||||
|
||||
local tree = PatchTree.build(patch, instanceMap, { "Property", "Current", "Incoming" }, gitMetadata)
|
||||
local selections = PatchTree.buildInitialSelections(tree)
|
||||
|
||||
expect(selections[id]).to.equal(nil)
|
||||
|
||||
folder:Destroy()
|
||||
instanceMap:stop()
|
||||
end)
|
||||
|
||||
it("should default to push when script Source matches committed hash", function()
|
||||
local patch = PatchSet.newEmpty()
|
||||
local instanceMap = InstanceMap.new()
|
||||
|
||||
local workspace = game:GetService("Workspace")
|
||||
local script = Instance.new("ModuleScript")
|
||||
script.Name = "MatchingScript"
|
||||
script.Source = "local x = 1\nreturn x"
|
||||
script.Parent = workspace
|
||||
|
||||
local id = HttpService:GenerateGUID(false)
|
||||
instanceMap:insert(id, script)
|
||||
|
||||
table.insert(patch.updated, {
|
||||
id = id,
|
||||
changedProperties = { Source = { String = "-- different from server" } },
|
||||
})
|
||||
|
||||
local committedHash = computeBlobSha1(script.Source)
|
||||
local gitMetadata = {
|
||||
changedIds = { id },
|
||||
scriptCommittedHashes = {
|
||||
[id] = { committedHash },
|
||||
},
|
||||
}
|
||||
|
||||
local tree = PatchTree.build(patch, instanceMap, { "Property", "Current", "Incoming" }, gitMetadata)
|
||||
local selections = PatchTree.buildInitialSelections(tree)
|
||||
|
||||
expect(selections[id]).to.equal("push")
|
||||
|
||||
script:Destroy()
|
||||
instanceMap:stop()
|
||||
end)
|
||||
|
||||
it("should default to nil when script Source does not match any committed hash", function()
|
||||
local patch = PatchSet.newEmpty()
|
||||
local instanceMap = InstanceMap.new()
|
||||
|
||||
local workspace = game:GetService("Workspace")
|
||||
local script = Instance.new("ModuleScript")
|
||||
script.Name = "MismatchScript"
|
||||
script.Source = "-- studio has different content"
|
||||
script.Parent = workspace
|
||||
|
||||
local id = HttpService:GenerateGUID(false)
|
||||
instanceMap:insert(id, script)
|
||||
|
||||
table.insert(patch.updated, {
|
||||
id = id,
|
||||
changedProperties = { Source = { String = "-- server version" } },
|
||||
})
|
||||
|
||||
local gitMetadata = {
|
||||
changedIds = { id },
|
||||
scriptCommittedHashes = {
|
||||
[id] = { computeBlobSha1("-- committed version, different from studio") },
|
||||
},
|
||||
}
|
||||
|
||||
local tree = PatchTree.build(patch, instanceMap, { "Property", "Current", "Incoming" }, gitMetadata)
|
||||
local selections = PatchTree.buildInitialSelections(tree)
|
||||
|
||||
expect(selections[id]).to.equal(nil)
|
||||
|
||||
script:Destroy()
|
||||
instanceMap:stop()
|
||||
end)
|
||||
|
||||
it("should match against staged hash when HEAD hash doesn't match", function()
|
||||
local patch = PatchSet.newEmpty()
|
||||
local instanceMap = InstanceMap.new()
|
||||
|
||||
local workspace = game:GetService("Workspace")
|
||||
local script = Instance.new("ModuleScript")
|
||||
script.Name = "StagedMatchScript"
|
||||
script.Source = "-- staged version content"
|
||||
script.Parent = workspace
|
||||
|
||||
local id = HttpService:GenerateGUID(false)
|
||||
instanceMap:insert(id, script)
|
||||
|
||||
table.insert(patch.updated, {
|
||||
id = id,
|
||||
changedProperties = { Source = { String = "-- server" } },
|
||||
})
|
||||
|
||||
local headHash = computeBlobSha1("-- old committed version")
|
||||
local stagedHash = computeBlobSha1(script.Source)
|
||||
local gitMetadata = {
|
||||
changedIds = { id },
|
||||
scriptCommittedHashes = {
|
||||
[id] = { headHash, stagedHash },
|
||||
},
|
||||
}
|
||||
|
||||
local tree = PatchTree.build(patch, instanceMap, { "Property", "Current", "Incoming" }, gitMetadata)
|
||||
local selections = PatchTree.buildInitialSelections(tree)
|
||||
|
||||
expect(selections[id]).to.equal("push")
|
||||
|
||||
script:Destroy()
|
||||
instanceMap:stop()
|
||||
end)
|
||||
|
||||
it("should not auto-select Added items regardless of git status", function()
|
||||
local patch = PatchSet.newEmpty()
|
||||
local instanceMap = InstanceMap.new()
|
||||
|
||||
local parentId = HttpService:GenerateGUID(false)
|
||||
local workspace = game:GetService("Workspace")
|
||||
instanceMap:insert(parentId, workspace)
|
||||
|
||||
local addId = HttpService:GenerateGUID(false)
|
||||
patch.added[addId] = {
|
||||
Id = addId,
|
||||
Parent = parentId,
|
||||
ClassName = "ModuleScript",
|
||||
Name = "AddedScript",
|
||||
Properties = {},
|
||||
}
|
||||
|
||||
local gitMetadata = {
|
||||
changedIds = { addId },
|
||||
scriptCommittedHashes = {},
|
||||
}
|
||||
|
||||
local tree = PatchTree.build(patch, instanceMap, { "Property", "Current", "Incoming" }, gitMetadata)
|
||||
local selections = PatchTree.buildInitialSelections(tree)
|
||||
|
||||
expect(selections[addId]).to.equal(nil)
|
||||
|
||||
instanceMap:stop()
|
||||
end)
|
||||
|
||||
it("should not auto-select Removed items regardless of git status", function()
|
||||
local patch = PatchSet.newEmpty()
|
||||
local instanceMap = InstanceMap.new()
|
||||
|
||||
local workspace = game:GetService("Workspace")
|
||||
local folder = Instance.new("Folder")
|
||||
folder.Name = "ToRemove"
|
||||
folder.Parent = workspace
|
||||
|
||||
local id = HttpService:GenerateGUID(false)
|
||||
instanceMap:insert(id, folder)
|
||||
table.insert(patch.removed, id)
|
||||
|
||||
local gitMetadata = {
|
||||
changedIds = {},
|
||||
scriptCommittedHashes = {},
|
||||
}
|
||||
|
||||
local tree = PatchTree.build(patch, instanceMap, { "Property", "Current", "Incoming" }, gitMetadata)
|
||||
local selections = PatchTree.buildInitialSelections(tree)
|
||||
|
||||
expect(selections[id]).to.equal(nil)
|
||||
|
||||
folder:Destroy()
|
||||
instanceMap:stop()
|
||||
end)
|
||||
|
||||
it("should handle Script and LocalScript as LuaSourceContainer", function()
|
||||
local patch = PatchSet.newEmpty()
|
||||
local instanceMap = InstanceMap.new()
|
||||
|
||||
local workspace = game:GetService("Workspace")
|
||||
local serverScript = Instance.new("Script")
|
||||
serverScript.Name = "ServerTest"
|
||||
serverScript.Source = "print('server')"
|
||||
serverScript.Parent = workspace
|
||||
|
||||
local localScript = Instance.new("LocalScript")
|
||||
localScript.Name = "ClientTest"
|
||||
localScript.Source = "print('client')"
|
||||
localScript.Parent = workspace
|
||||
|
||||
local serverId = HttpService:GenerateGUID(false)
|
||||
local localId = HttpService:GenerateGUID(false)
|
||||
instanceMap:insert(serverId, serverScript)
|
||||
instanceMap:insert(localId, localScript)
|
||||
|
||||
table.insert(patch.updated, {
|
||||
id = serverId,
|
||||
changedProperties = { Source = { String = "-- new" } },
|
||||
})
|
||||
table.insert(patch.updated, {
|
||||
id = localId,
|
||||
changedProperties = { Source = { String = "-- new" } },
|
||||
})
|
||||
|
||||
local gitMetadata = {
|
||||
changedIds = { serverId, localId },
|
||||
scriptCommittedHashes = {
|
||||
[serverId] = { computeBlobSha1(serverScript.Source) },
|
||||
[localId] = { computeBlobSha1(localScript.Source) },
|
||||
},
|
||||
}
|
||||
|
||||
local tree = PatchTree.build(patch, instanceMap, { "Property", "Current", "Incoming" }, gitMetadata)
|
||||
local selections = PatchTree.buildInitialSelections(tree)
|
||||
|
||||
expect(selections[serverId]).to.equal("push")
|
||||
expect(selections[localId]).to.equal("push")
|
||||
|
||||
serverScript:Destroy()
|
||||
localScript:Destroy()
|
||||
instanceMap:stop()
|
||||
end)
|
||||
|
||||
it("should handle mixed changed and unchanged files", function()
|
||||
local patch = PatchSet.newEmpty()
|
||||
local instanceMap = InstanceMap.new()
|
||||
|
||||
local workspace = game:GetService("Workspace")
|
||||
local changedScript = Instance.new("ModuleScript")
|
||||
changedScript.Name = "Changed"
|
||||
changedScript.Source = "-- matches committed"
|
||||
changedScript.Parent = workspace
|
||||
|
||||
local unchangedFolder = Instance.new("Folder")
|
||||
unchangedFolder.Name = "Unchanged"
|
||||
unchangedFolder.Parent = workspace
|
||||
|
||||
local changedId = HttpService:GenerateGUID(false)
|
||||
local unchangedId = HttpService:GenerateGUID(false)
|
||||
instanceMap:insert(changedId, changedScript)
|
||||
instanceMap:insert(unchangedId, unchangedFolder)
|
||||
|
||||
table.insert(patch.updated, {
|
||||
id = changedId,
|
||||
changedProperties = { Source = { String = "-- server" } },
|
||||
})
|
||||
table.insert(patch.updated, {
|
||||
id = unchangedId,
|
||||
changedName = "StudioRenamed",
|
||||
changedProperties = {},
|
||||
})
|
||||
|
||||
local gitMetadata = {
|
||||
changedIds = { changedId }, -- only the script is git-changed
|
||||
scriptCommittedHashes = {
|
||||
[changedId] = { computeBlobSha1(changedScript.Source) },
|
||||
},
|
||||
}
|
||||
|
||||
local tree = PatchTree.build(patch, instanceMap, { "Property", "Current", "Incoming" }, gitMetadata)
|
||||
local selections = PatchTree.buildInitialSelections(tree)
|
||||
|
||||
expect(selections[changedId]).to.equal("push")
|
||||
expect(selections[unchangedId]).to.equal("pull")
|
||||
|
||||
changedScript:Destroy()
|
||||
unchangedFolder:Destroy()
|
||||
instanceMap:stop()
|
||||
end)
|
||||
|
||||
it("should handle changed script with no committed hash (new file)", function()
|
||||
local patch = PatchSet.newEmpty()
|
||||
local instanceMap = InstanceMap.new()
|
||||
|
||||
local workspace = game:GetService("Workspace")
|
||||
local script = Instance.new("ModuleScript")
|
||||
script.Name = "NewScript"
|
||||
script.Source = "return 'new'"
|
||||
script.Parent = workspace
|
||||
|
||||
local id = HttpService:GenerateGUID(false)
|
||||
instanceMap:insert(id, script)
|
||||
|
||||
table.insert(patch.updated, {
|
||||
id = id,
|
||||
changedProperties = { Source = { String = "-- different" } },
|
||||
})
|
||||
|
||||
local gitMetadata = {
|
||||
changedIds = { id },
|
||||
scriptCommittedHashes = {}, -- no hash for this script (new file)
|
||||
}
|
||||
|
||||
local tree = PatchTree.build(patch, instanceMap, { "Property", "Current", "Incoming" }, gitMetadata)
|
||||
local selections = PatchTree.buildInitialSelections(tree)
|
||||
|
||||
expect(selections[id]).to.equal(nil)
|
||||
|
||||
script:Destroy()
|
||||
instanceMap:stop()
|
||||
end)
|
||||
|
||||
it("should handle empty changedIds with gitMetadata present", function()
|
||||
local patch = PatchSet.newEmpty()
|
||||
local instanceMap = InstanceMap.new()
|
||||
|
||||
local workspace = game:GetService("Workspace")
|
||||
local folder = Instance.new("Folder")
|
||||
folder.Name = "AllUnchanged"
|
||||
folder.Parent = workspace
|
||||
|
||||
local script = Instance.new("ModuleScript")
|
||||
script.Name = "AlsoUnchanged"
|
||||
script.Source = "return true"
|
||||
script.Parent = workspace
|
||||
|
||||
local folderId = HttpService:GenerateGUID(false)
|
||||
local scriptId = HttpService:GenerateGUID(false)
|
||||
instanceMap:insert(folderId, folder)
|
||||
instanceMap:insert(scriptId, script)
|
||||
|
||||
table.insert(patch.updated, {
|
||||
id = folderId,
|
||||
changedName = "StudioRenamed",
|
||||
changedProperties = {},
|
||||
})
|
||||
table.insert(patch.updated, {
|
||||
id = scriptId,
|
||||
changedProperties = { Source = { String = "-- studio version" } },
|
||||
})
|
||||
|
||||
local gitMetadata = {
|
||||
changedIds = {}, -- nothing changed in git
|
||||
scriptCommittedHashes = {},
|
||||
}
|
||||
|
||||
local tree = PatchTree.build(patch, instanceMap, { "Property", "Current", "Incoming" }, gitMetadata)
|
||||
local selections = PatchTree.buildInitialSelections(tree)
|
||||
|
||||
expect(selections[folderId]).to.equal("pull")
|
||||
expect(selections[scriptId]).to.equal("pull")
|
||||
|
||||
folder:Destroy()
|
||||
script:Destroy()
|
||||
instanceMap:stop()
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("getSelectableNodeIds", function()
|
||||
it("should return empty array for empty tree", function()
|
||||
local patch = PatchSet.newEmpty()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue