Interface for Source Control
From CacheWiki
Contents |
[edit]
Interface for Source Control
[edit]
Introduction
Because our team is not skilled in subversion yet I have choosed not to integrate subversion into Studio at the moment
For beginners could be more easy to use TortoiseSvn as a user friendly GUI for subversion communication.
So, all I need is to force Studio to behave as a normal source editor, I mean store or classes and routines
to local filesystem (and treat this local repository as a PRIMARY source, NOT DB) and then use third party user friedly software for revision controlling.
For that purpose I created Interface, which serves for adding/deleting CLS and MAC files to/from Project.
Thx a lot to Daniel Kutac from Intersystems CZ for help and hints :)
[edit]
Include file
<?xml version="1.0" encoding="CP1250"?>
<Export generator="Cache" version="21" zv="Cache for Windows (x86-32) 2007.1.4 (Build 707U)" ts="2008-08-30 13:34:32">
<Routine name="RevisionControl" type="INC" timestamp="61238,47749"><![CDATA[
#IfNDef RevisionControl
/*
Include file
*/
#Include %sySite
#Define RevisionControl
#define PATHSEPARATOR $s($$$ISWINDOWS:"\",1:"/1")
#Define ERREXIT goto exit:($$$ISERR(sc))
#Define DBERRCHECK if ( (SQLCODE '= 0) && (SQLCODE '= 100) ) { set sc = $$$ERROR($$$GeneralError, $SYSTEM.SQL.SQLCODE(SQLCODE)) goto exit }
#Define DBERRCHECK0 if ( (SQLCODE '= 0)) { set sc = $$$ERROR($$$GeneralError, $SYSTEM.SQL.SQLCODE(SQLCODE)) goto exit }
#Define COMMIT if $TLEVEL TCOMMIT
#Define ROLLBACK if $TLEVEL TROLLBACK 1
#Define ROLLBACKALL if $TLEVEL TROLLBACK
#Define FILENAMEFROMPATH(%a) $List($Listfromstring(%a, $$$PATHSEPARATOR), -1)
#Define CATCH(%a) set sc = %a.AsStatus() s:($ze="") $ze="<ZOBJ>"_e.Code d BACK^%ETN $$$ERREXIT
#Define EXCEP(%a) d:($$$ISERR(%a)) ##class(%Exception.StatusException).CreateFromStatus(%a)
//ERRCODES
#Define ERRBASE 100000
#Define DIRECTORYNOTCREATED ($$$ERRBASE + 1)
#Define BADARGUMENT ($$$ERRBASE + 2)
#EndIf
]]></Routine>
</Export>
[edit]
Interface, class file
<?xml version="1.0" encoding="UTF-8"?>
<Export generator="Cache" version="21" zv="Cache for Windows (x86-32) 2007.1.4 (Build 707U)" ts="2008-08-30 14:39:14">
<Class name="RevisionControl.IProjectManipulation">
<Description><![CDATA[
This is a very simple interface for item project manipulation <br>
(MAC and CSP) files. You can export them, import them. <br>
Please <b>see the first section</b> of class variables. Probably you <br>
would to change them. <br>
<b><i>Warning: This class should not be a member of your project!</b></i> <br>
<b><i>created by: jan.vlasak@aposteriori.cz for public use</b></i> <br>
-------------------------------------------------------------------------------- <br>
change log: <br>
-> version: 0.1, basic features, export/import of project items]]></Description>
<IncludeCode>RevisionControl</IncludeCode>
<Super>%RegisteredObject</Super>
<TimeCreated>61215,32643.41447</TimeCreated>
<Property name="version">
<Description>
Version of class</Description>
<Type>%String</Type>
<InitialExpression>"0.1"</InitialExpression>
<Private>1</Private>
</Property>
<UDLText name="T">
<Content><![CDATA[
//-----------------------------------------------------------------------------
]]></Content>
</UDLText>
<Property name="pathSeparator">
<Description>
Path separator</Description>
<Type>%String</Type>
<InitialExpression>$$$PATHSEPARATOR</InitialExpression>
<Private>1</Private>
</Property>
<Property name="repoLocalPath">
<Description>
Default path to repository on filesystem (root, without name of namespace)</Description>
<Type>%String</Type>
<InitialExpression>"d:\@Repo"</InitialExpression>
<Private>1</Private>
</Property>
<Property name="charset">
<Description>
Charset used for export</Description>
<Type>%String</Type>
<InitialExpression>"CP1250"</InitialExpression>
<Private>1</Private>
</Property>
<Property name="projectName">
<Description>
Name of watched project</Description>
<InitialExpression>"Project"</InitialExpression>
<Private>1</Private>
</Property>
<UDLText name="T">
<Content><![CDATA[
//-----------------------------------------------------------------------------
]]></Content>
</UDLText>
<Property name="repoLocalDir">
<Description>
Directory where items are exported (is setted in %OnNew())</Description>
<Type>%String</Type>
<Private>1</Private>
</Property>
<Property name="currNamespace">
<Description>
Name of current nameSpace</Description>
<Type>%String</Type>
<Private>1</Private>
</Property>
<Method name="GetVersion">
<Description>
Get version of class</Description>
<ReturnType>%String</ReturnType>
<Implementation><![CDATA[ q ..version
]]></Implementation>
</Method>
<Method name="%OnNew">
<Description>
Constructor. Local repository is created here (even if exist)</Description>
<FormalSpec>initvalue:%CacheString</FormalSpec>
<Private>1</Private>
<ProcedureBlock>1</ProcedureBlock>
<ReturnType>%Status</ReturnType>
<ServerOnly>1</ServerOnly>
<Implementation><![CDATA[
try
{
set sc = $$$OK
//get current namespace
set ..currNamespace = $zutil(5)
//create directory for export/import items--------------------
set ..repoLocalDir = ..repoLocalPath _ ..pathSeparator _ ..currNamespace _ ..pathSeparator _ ..projectName
set created = ##class(%File).CreateDirectoryChain(..repoLocalDir)
if ( created = 0 )
{
set sc = $$$ERROR($$$DIRECTORYNOTCREATED, "Dir: " _ ..repoLocalDir)
$$$EXCEP(sc)
}
//---------------------------------------------------------
}
catch e
{
$$$CATCH(e)
}
exit
q sc
]]></Implementation>
</Method>
<Method name="ExportOne">
<Description>
Export obj (class, macro, etc.) to filesystem as one XML file</Description>
<FormalSpec>itemName:%String</FormalSpec>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
try
{
set sc = $$$OK
set exportFilePath = ..ExternalName(itemName)
set sc = ##class(%SYSTEM.OBJ).Export(itemName, exportFilePath, "", "", ..charset)
$$$EXCEP(sc)
}
catch e
{
$$$CATCH(e)
}
exit
q sc
]]></Implementation>
</Method>
<Method name="ExportAll">
<Description>
Export all items in project to dir individually</Description>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
set sc = $$$OK
try
{
set sc = ..GetItemsInProject(.names, .types, .exportName)
$$$EXCEP(sc)
for i = 1: 1: exportName.Count()
{
set sc = ..ExportOne( exportName.GetAt(i) )
$$$EXCEP(sc)
}
}
catch e
{
$$$CATCH(e)
}
exit
q sc
]]></Implementation>
</Method>
<Method name="GetItemsInProject">
<Description>
Get array of items in project (just CLS/MAC items)</Description>
<FormalSpec>*itemName:%ArrayOfDataTypes,*itemType:%ArrayOfDataTypes,*exportName:%ArrayOfDataTypes</FormalSpec>
<Private>1</Private>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
try
{
set sc = $$$OK
set itemName = ##class(%ArrayOfDataTypes).%New()
set itemType = ##class(%ArrayOfDataTypes).%New()
set exportName = ##class(%ArrayOfDataTypes).%New()
set r = ##class(%Library.ResultSet).%New("%Studio.Project:ProjectItemsList")
set sc = r.Execute(..projectName)
$$$EXCEP(sc)
set i = 0
while ( r.Next(.sc))
{
$$$EXCEP(sc)
set id = r.Data("ID")
set name = r.Data("Name")
set type = r.Data("Type")
set inSourceControl = r.Data("InSourceControl") //not used yet
if (type = "CLS") || (type = "MAC")
{
set i = i + 1
set sc = itemName.SetAt(name, i)
$$$EXCEP(sc)
set sc = itemType.SetAt(type, i)
$$$EXCEP(sc)
if ( type = "MAC" )
{
set sc = exportName.SetAt( name, i )
$$$EXCEP(sc)
}
else
{
set sc = exportName.SetAt( name _ "." _ type, i )
$$$EXCEP(sc)
}
} //end of if (type = "CLS") || (type = "MAC")
} //end of while
}
catch e
{
$$$CATCH(e)
}
exit
q sc
]]></Implementation>
</Method>
<Method name="ImportOne">
<Description><![CDATA[
Import one XML into namespace/project <br>
It takes few seconds to reload the project]]></Description>
<FormalSpec>itemName:%String,importToProject:%Boolean=1</FormalSpec>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
try
{
set sc = $System.OBJ.Load(..ExternalName(itemName), "-ck") //c = compile, k = dont delete int files
$$$EXCEP(sc)
if ( importToProject )
{
set project = ##class(%Studio.Project).%OpenId(..projectName, 1, .sc)
$$$EXCEP(sc)
set sc = project.AddItem(itemName)
$$$EXCEP(sc)
set sc = project.%Save()
$$$EXCEP(sc)
}
}
catch e
{
$$$CATCH(e)
}
exit
q sc
]]></Implementation>
</Method>
<Method name="ImportAll">
<Description><![CDATA[
Import all XML files from local repository <br>
<b> dont call this method twice </b> Firt kill this instance and then
you can call it again.]]></Description>
<FormalSpec>*files:%ArrayOfDataTypes,importToProject:%Boolean=1,withDeleteAll:%Boolean=1</FormalSpec>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
set sc = $$$OK
try
{
TSTART
if ( withDeleteAll )
{
set sc = ..DeleteAll()
$$$EXCEP(sc)
}
set files = ##class(%ArrayOfDataTypes).%New()
/// first, we must make an array of filenames located there
set r = ##class(%Library.ResultSet).%New("%Library.File:FileSet")
set sc = r.Execute(..repoLocalDir, "*.xml", "name")
$$$EXCEP(sc)
set i = 0
while (r.Next(.sc))
{
$$$EXCEP(sc)
set i = i + 1
set sc = files.SetAt(r.Data("Name"), i)
}
//-------------------------------------------------------------
for i = 1: 1: files.Count()
{
set filePath = files.GetAt(i)
set fileName = $$$FILENAMEFROMPATH(filePath)
//I want do delete .xml file extension
set count = ##class(%Utility).Replace(fileName, ".xml", "", 0, .internalName)
/// no replace :(
if ( count = 0 )
{
set sc = $$$ERROR($$$GeneralError, "No replace for filename: " _ fileName)
$$$EXCEP(sc)
}
set sc = ..ImportOne(internalName, importToProject)
$$$EXCEP(sc)
}
}
catch e
{
$$$CATCH(e)
}
exit
if $$$ISERR(sc)
{
$$$ROLLBACKALL
}
else
{
$$$COMMIT
}
q sc
]]></Implementation>
</Method>
<Method name="DeleteOne">
<Description><![CDATA[
Delete one item in project/namespace<br>
We can manage only MAC/CLS items, others you have to manage <br>
manually]]></Description>
<FormalSpec>itemName:%String,itemType:%String,removeFromProject:%Boolean=1</FormalSpec>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
try
{
set sc = $$$OK
if ( itemType = "CLS" )
{
d:(removeFromProject) ##class(%Studio.Project).DeleteItem(itemName)
set sc = ##class(%SYSTEM.OBJ).Delete(itemName, "", "")
$$$EXCEP(sc)
}
elseif ( itemType = "MAC" )
{
d:(removeFromProject) ##class(%Studio.Project).DeleteItem(itemName)
set sc = ##class(%Library.Routine).Delete(itemName)
$$$EXCEP(sc)
}
else
{
set sc = $$$ERROR($$$BADARGUMENT, "type: " _ itemName)
$$$EXCEP(sc)
}
}
catch e
{
$$$CATCH(e)
}
exit
q sc
]]></Implementation>
</Method>
<Method name="DeleteAll">
<Description><![CDATA[
Delete all items in project (not project itself) <br>
We can manage only MAC/CLS items, others you have to manage <br>
manually]]></Description>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
set sc = $$$OK
try
{
TSTART
set sc = ..GetItemsInProject(.names, .types, .internalNames)
$$$EXCEP(sc)
for i = 1: 1: internalNames.Count()
{
set item = internalNames.GetAt(i)
set type = types.GetAt(i)
set sc = ..DeleteOne(item, type)
$$$EXCEP(sc)
}
}
catch e
{
$$$CATCH(e)
}
exit
if $$$ISERR(sc)
{
$$$ROLLBACKALL
}
else
{
$$$COMMIT
}
q sc
]]></Implementation>
</Method>
<Method name="ExternalName">
<Description>
Convert the internal name, e.g. TEST.MAC to an external name that is used to export
the routine/class/csp item. This is often a filename to write the file out to.</Description>
<FormalSpec>internalName:%String,fullPath:%Boolean=1</FormalSpec>
<Private>1</Private>
<ReturnType>%String</ReturnType>
<Implementation><![CDATA[
// replace slashes in (csp,..) internalname by underscores
set internalName = $tr(internalName,"/\","__")
set len = $l(internalName, ".")
set type = $zcvt($p(internalName, ".", len),"L")
set external = $p(internalName,".", 1, len - 1) _ "." _ type _ ".xml"
set:(fullPath) external = ..repoLocalDir _ ..pathSeparator _ external
q external
]]></Implementation>
</Method>
</Class>
</Export>

