Here’s a module that will allow you to save a project milestone for any project on the current Iguana instance.
Note: This module will not work if the target project exists on a different Iguana instance.
local translator = {}
function node.getChannel(Config, Name)
for i=1,#Config.iguana_config.channel_config do
local Channel = Config.iguana_config.channel_config[i]
if Channel.name:nodeValue() == Name then
return Channel
end
end
return nil
end
function node.S(ANode)
return tostring(ANode)
end
function Split(s, d)
local t = {}
local i = 0
local f
local match = '(.-)' .. d .. '()'
if string.find(s, d) == nil then
return {s}
end
for sub, j in string.gfind(s, match) do
i = i + 1
t[i] = sub
f = j
end
if i~= 0 then
t[i+1]=string.sub(s,f)
end
return t
end
local function GetSandbox(Root, WorkingDirectory)
os.execute('mkdir "'..Root..'"')
os.execute('cd "'..Root..'" & "'..WorkingDirectory..'fossil" open "'..WorkingDirectory..'vcs_repo.sqlite"')
end
local function CheckGuidArguments(T)
if not T.channel then
error('Parameter 'channel' is required.', 3)
elseif not T.component_type then
error('Parameter 'component_type' is required.', 3)
end
end
local function CheckSaveMilestoneArguments(T)
if not T.text then
error('Parameter 'text' is required.', 3)
elseif not T.guid then
error('Parameter 'guid' is required.', 3)
elseif not T.url then
error('Parameter 'url' is required.', 3)
elseif not T.user then
error('Parameter 'user' is required.', 3)
elseif not T.password then
error('Parameter 'password' is required.', 3)
end
end
local function ScriptGuid(ScriptType, ChannelName, Config)
local Channel = Config:getChannel(ChannelName)
if not Channel then
error('Channel '..ChannelName..' does not exist', 3)
end
if ScriptType == translator.TO then
local Component = Channel.to_mapper
if not Component then
error('There is no "To Translator" component for this channel', 3)
end
return Component.guid:nodeValue()
end
if ScriptType == translator.FROM then
local Component = Channel.from_mapper
if not Component then
error('There is no "From Translator" component for this channel', 3)
end
return Component.guid:nodeValue()
end
if ScriptType == translator.FILTER then
local Component= Channel.message_filter
if not Component then
error('There is no "Translator Filter" component for this channel', 3)
end
return Component.translator_guid:nodeValue()
end
if ScriptType == translator.ACK then
local Component = Channel.from_llp_listener
if not Component or not Component.ack_script then
error('There is no "Custom ACK Translator" component for this channel', 3)
end
return Component.ack_script:nodeValue()
end
if ScriptType == translator.HTTPS then
local Component = Channel.from_http
if not Component or not Component.from_http_guid then
error('There is no "From HTTPS translator" component for this channel', 3)
end
return Channel.from_http.guid:nodeValue()
end
end
--[[
Function takes user credentials and returns a valid session id upon a
successful login.
]]
local function GetLoginKey(Url, User, Password)
local Success, Result, _, Headers = pcall(
net.http.get,
{
url=Url..'login.html',
parameters={
username=User,
password=Password
},
live=true
}
)
if not Success then
return nil, Result
end
-- That gives us our session cookie which we use for our
-- login credentials. The login interface was not quite
-- meant for an API - but the problem is solvable.
local SessionId = Headers["Set-Cookie"]
if not SessionId then
error('Username and/or password wrong',3)
end
return Split(SessionId,' ')[1]
end
--[[
Function returns the dependency list of the Translator project identified by
the inputted GUID.
]]
local function GetDependencies(Guid, User, WorkingDirectory)
local PathSeparator = WorkingDirectory:sub(#WorkingDirectory)
local Sandbox = 'edit'..PathSeparator..User..PathSeparator
local Project = Sandbox..Guid..PathSeparator..'project.prj'
local ProjectFile = io.open(Project, 'r')
-- The user's sandbox may not yet exist. If not, let's create it.
if not ProjectFile then
GetSandbox(Sandbox, WorkingDirectory)
ProjectFile = io.open(Project, 'r')
end
local ProjectInfo = json.parse{data=ProjectFile:read('*a')}
local Dependencies = ProjectInfo.LuaDependencies
local Size = #Dependencies
for k,v in pairs(ProjectInfo.OtherDependencies) do Dependencies[Size + k] = v end
io.close(ProjectFile)
return Dependencies
end
--[[
Translator interface
]]
translator.FROM = 'from'
translator.TO = 'to'
translator.FILTER = 'filter'
translator.ACK = 'ack'
translator.HTTPS = 'https'
--[[
Function returns the GUID associated the Translator project
identified by the inputted channel name and component type.
]]
function translator.guid(T)
CheckGuidArguments(T)
local ChannelName = T.channel
local ComponentType = T.component_type
-- Read the config file.
local ConfigFile = io.open('IguanaConfiguration.xml', 'r')
Config = xml.parse{data=ConfigFile:read('*a')}
io.close(ConfigFile)
return ScriptGuid(ComponentType, ChannelName, Config)
end
local GuidHelpData = {
Title='translator.guid',
Usage=[[translator.guid{channel=<value>, component_type=<value>}]],
Desc=[[Returns the GUID associated with the Translator project identified by the
inputted channel name and component type.]],
Returns='The GUID of interest.',
ParameterTable=true,
Parameters={
{channel={Desc='The channel name containing the Translator project.'}},
{component_type={Desc='The component type in which the Translator project is defined.'}}
},
Examples={
[[translator.guid{channel='Example', component_type=translator.FROM}]]
},
SeeAlso=nil
}
help.set{input_function=translator.guid, help_data=GuidHelpData}
--[[
Function commits the project identified by the inputted GUID under the given milestone name.
]]
function translator.saveMilestone(T)
CheckSaveMilestoneArguments(T)
local Text = T.text
local Guid = T.guid
local Url = T.url
local User = T.user
local Password = T.password
local Live = T.live or not iguana.isTest()
local LoginKey, LoginResult = GetLoginKey(Url, User, Password)
if not LoginKey then
error(LoginResult, 2)
end
local WorkingDirectory = iguana.workingDir()
local Dependencies = GetDependencies(Guid, User, WorkingDirectory)
local DependencyString = 'mainnproject settingsn'..table.concat(Dependencies, 'n')
if not Live then
return 'Set live=true to really run the code'
end
local Success, Result = pcall(
net.http.post,
{
url=Url..'source_control',
parameters={
RequestType='save_milestone',
FileLabels=DependencyString,
MilestoneName=Text,
ChannelGuid=Guid
},
headers={Cookie=LoginKey},
live=Live
}
)
if not Success then
error(Result, 2)
end
Success, Result = pcall(json.parse,{data=Result})
if not Success then
error(Result, 2)
elseif Result.ErrorMessage then
error(Result.ErrorMessage, 2)
elseif Result.PermissionIssue then
error(Result.PermissionIssue, 2)
end
return "Saved milestone "..T.text
end
local SaveHelpData = {
Title='translator.saveMilestone',
Usage=[[translator.saveMilestone{text=<value>, guid=<value>, url=<value>,
user=<value>, password=<value>, live=<value>}]],
Desc=[[Commits the Translator project associated with the inputted GUID.<br><br>Important Note: This API
can only save milestones of projects that exist on the same instance of Iguana that uses this API.]],
Returns=nil,
ParameterTable=true,
Parameters={
{text={Desc='The milestone name to use for the commit.'}},
{guid={Desc='The GUID associated with the project being committed.'}},
{url={Desc=[[The URL of the Iguana server running the project that uses this API.]]}},
{user={Desc='User name to login with.'}},
{password={Desc='Password to login with.'}},
{live={Desc='Flag that determines if the code will be run.'}}
},
Examples={
[[translator.saveMilestone{
text='Milestone 1',
guid='123456',
url='http://localhost:6543/',
user='admin',
password='password',
live=true
}]]
},
SeeAlso=nil
}
help.set{input_function=translator.saveMilestone, help_data=SaveHelpData}
return translator
Here’s a main module that uses the module above.
translator = require 'translator'
function main()
translator.saveMilestone{
text='New milestone at '..os.date('%Y%m%d %H:%M:%S'),
guid=translator.guid{
channel='XDS.b RET',
component_type=translator.FROM
},
url='http://10.211.55.8:6543/',
user='admin',
password='password',
live=true
}
end