Skip to content

Commit 74816c2

Browse files
committed
Added baseline utility
1 parent c6cbad3 commit 74816c2

File tree

4 files changed

+139
-0
lines changed

4 files changed

+139
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212
- Pre-release support for IPM v0.9.0+
1313
- Items mapped from database other than namespace's default routine database are now ignored by default when exporting or adding files
1414
- New setting to configure whether mapped items should be should be treated as read-only
15+
- Command-line utility to do a baseline export of items in a namespace
1516

1617
## [2.3.1] - 2024-04-30
1718

cls/SourceControl/Git/API.cls

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,12 @@ ClassMethod Unlock()
5656
quit ##class(SourceControl.Git.Utils).Locked(0)
5757
}
5858

59+
/// Run in terminal to baseline a namespace by adding all items to source control.
60+
/// - pCommitMessage: if defined, all changes in namespace context will be committed.
61+
/// - pPushToRemote: if defined, will run a git push to the specified remote
62+
ClassMethod BaselineExport(pCommitMessage = "", pPushToRemote = "") As %Status
63+
{
64+
quit ##class(SourceControl.Git.Utils).BaselineExport(pCommitMessage, pPushToRemote)
5965
}
6066

67+
}

cls/SourceControl/Git/Utils.cls

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,7 @@ ClassMethod AddToServerSideSourceControl(InternalName As %String) As %Status
513513

514514
ClassMethod AddToSourceControl(InternalName As %String) As %Status
515515
{
516+
do ##class(SourceControl.Git.PackageManagerContext).ForInternalName(InternalName)
516517
set settings = ##class(SourceControl.Git.Settings).%New()
517518
#dim i as %Integer
518519
#dim ec as %Status = $$$OK
@@ -2062,5 +2063,74 @@ ClassMethod ResetSourceControlClass()
20622063
do ##class(%Studio.SourceControl.Interface).SourceControlClassSet("")
20632064
}
20642065

2066+
ClassMethod BaselineExport(pCommitMessage = "", pPushToRemote = "") As %Status
2067+
{
2068+
set sc = $$$OK
2069+
try {
2070+
write !, "Exporting classes..."
2071+
set sql = "SELECT ID FROM %Dictionary.ClassDefinition"
2072+
_ " WHERE GeneratedBy IS Null AND Deployed = 0"
2073+
_ " AND NOT ("
2074+
_ " ID %STARTSWITH 'csr.csp.' OR ID %STARTSWITH '%' OR ID %STARTSWITH 'CSPX.' OR ID %STARTSWITH 'Ens.'"
2075+
_ " OR ID %STARTSWITH 'EnsLib.' OR ID %STARTSWITH 'EnsPortal.'"
2076+
_ ")"
2077+
set rs = ##class(%SQL.Statement).%ExecDirect(,sql)
2078+
throw:rs.%SQLCODE<0 ##class(%Exception.SQL).CreateFromSQLCODE(rs.%SQLCODE,rs.%Message)
2079+
while rs.%Next() {
2080+
set internalName = rs.ID _ ".CLS"
2081+
// exclude items in a non-default IPM package
2082+
set context = ##class(SourceControl.Git.PackageManagerContext).ForInternalName(internalName)
2083+
continue:($isobject(context.Package) && 'context.IsInDefaultPackage)
2084+
$$$ThrowOnError(..AddToSourceControl(internalName))
2085+
}
2086+
write !, "Exporting mac routines..."
2087+
do ..BaselineExportRoutines("*.MAC")
2088+
write !, "Exporting inc routines..."
2089+
do ..BaselineExportRoutines("*.INC")
2090+
/*
2091+
Other items may be supported in the future:
2092+
- DeepSee folder items
2093+
- Ensemble lookup tables
2094+
- Ensemble schema documents
2095+
- CSP applications
2096+
*/
2097+
if pCommitMessage '= "" {
2098+
// switch to default context
2099+
do ##class(SourceControl.Git.PackageManagerContext).ForInternalName("")
2100+
do ..RunGitWithArgs(.errStream, .outStream, "add", "--all")
2101+
do ..PrintStreams(errStream, outStream)
2102+
set username = ..GitUserName()
2103+
set email = ..GitUserEmail()
2104+
set author = username_" <"_email_">"
2105+
do ..RunGitWithArgs(.errStream, .outStream, "commit", "--author", author, "-m", pCommitMessage)
2106+
do ..PrintStreams(errStream, outStream)
2107+
$$$ThrowOnError(##class(SourceControl.Git.Change).RefreshUncommitted(,,,1))
2108+
if (pPushToRemote '= "") {
2109+
$$$ThrowOnError(..Push(pPushToRemote))
2110+
}
2111+
}
2112+
} catch err {
2113+
set sc = err.AsStatus()
2114+
}
2115+
return sc
20652116
}
20662117

2118+
ClassMethod BaselineExportRoutines(pFilter) [ Private ]
2119+
{
2120+
set rs = ##class(%Library.Routine).RoutineListFunc(pFilter)
2121+
throw:rs.%SQLCODE<0 ##class(%Exception.SQL).CreateFromSQLCODE(rs.%SQLCODE,rs.%Message)
2122+
while rs.%Next() {
2123+
continue:rs.Size=0
2124+
set item = rs.Name
2125+
// exclude items in a non-default IPM package
2126+
set context = ##class(SourceControl.Git.PackageManagerContext).ForInternalName(item)
2127+
continue:($isobject(context.Package) && 'context.IsInDefaultPackage)
2128+
// exclude generated routines from classes, SQL, etc.
2129+
continue:##class(%Library.RoutineMgr).IsGenerated(item)
2130+
// exclude Ens* routines
2131+
continue:($extract(item,1,3)="Ens")
2132+
$$$ThrowOnError(..AddToSourceControl(item))
2133+
}
2134+
}
2135+
2136+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
Class UnitTest.SourceControl.Git.BaselineExport Extends %UnitTest.TestCase
2+
{
3+
4+
Method TestBaselineExport()
5+
{
6+
// create a mac routine
7+
if '##class(%Routine).Exists("test.mac") {
8+
set r = ##class(%Routine).%New("test.mac")
9+
do r.WriteLine(" write 22,!")
10+
do r.Save()
11+
do r.Compile()
12+
}
13+
// create an inc routine
14+
if '##class(%Routine).Exists("test.inc") {
15+
set r = ##class(%Routine).%New("test.inc")
16+
do r.WriteLine(" ; test include routine")
17+
do r.Save()
18+
do r.Compile()
19+
}
20+
// create a class
21+
if '##class(%Dictionary.ClassDefinition).%OpenId("TestPkg.Class") {
22+
set class = ##class(%Dictionary.ClassDefinition).%New()
23+
set class.Name = "TestPkg.Class"
24+
$$$ThrowOnError(class.%Save())
25+
do $system.OBJ.Compile("TestPkg.Class")
26+
}
27+
do $$$AssertNotTrue(##class(SourceControl.Git.Utils).IsInSourceControl("test.mac"))
28+
do $$$AssertNotTrue(##class(SourceControl.Git.Utils).IsInSourceControl("test.inc"))
29+
do $$$AssertNotTrue(##class(SourceControl.Git.Utils).IsInSourceControl("TestPkg.Class.cls"))
30+
do $$$AssertStatusOK(##class(SourceControl.Git.API).BaselineExport())
31+
do $$$AssertTrue(##class(SourceControl.Git.Utils).IsInSourceControl("test.mac"))
32+
do $$$AssertTrue(##class(SourceControl.Git.Utils).IsInSourceControl("test.inc"))
33+
do $$$AssertTrue(##class(SourceControl.Git.Utils).IsInSourceControl("TestPkg.Class.cls"))
34+
}
35+
36+
Property InitialExtension As %String [ InitialExpression = {##class(%Studio.SourceControl.Interface).SourceControlClassGet()} ];
37+
38+
Property SourceControlGlobal [ MultiDimensional ];
39+
40+
Method %OnNew(initvalue) As %Status
41+
{
42+
Merge ..SourceControlGlobal = ^SYS("SourceControl")
43+
Kill ^SYS("SourceControl")
44+
Set settings = ##class(SourceControl.Git.Settings).%New()
45+
Set settings.namespaceTemp = ##class(%Library.File).TempFilename()_"dir"
46+
Set settings.Mappings("MAC","*")="rtn/"
47+
Set settings.Mappings("CLS","*")="cls/"
48+
Do settings.%Save()
49+
Do ##class(%Studio.SourceControl.Interface).SourceControlClassSet("SourceControl.Git.Extension")
50+
Quit ##super(initvalue)
51+
}
52+
53+
Method %OnClose() As %Status [ Private, ServerOnly = 1 ]
54+
{
55+
Do ##class(%Studio.SourceControl.Interface).SourceControlClassSet(..InitialExtension)
56+
Kill ^SYS("SourceControl")
57+
Merge ^SYS("SourceControl") = ..SourceControlGlobal
58+
Quit $$$OK
59+
}
60+
61+
}

0 commit comments

Comments
 (0)