Skip to content

Commit c0750cb

Browse files
authored
Merge branch 'main' into add-branch-name-to-pull-event-handler
2 parents 9f9964e + 83d71e8 commit c0750cb

File tree

5 files changed

+121
-1
lines changed

5 files changed

+121
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ 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-
- Added a new "Branch" parameter to `##class(SourceControl.Git.PullEventHandler)` (#351)
15+
- Added a new "Branch" parameter to `##class(SourceControl.Git.PullEventHandler)` (#35
16+
- Command-line utility to do a baseline export of items in a namespace
1617

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

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ This might look like:
5858
5959
![Example of mapping configuration](docs/images/settings.PNG "Example of mapping configuration")
6060
61+
### Pull Event Handlers
62+
63+
The ##class(SourceControl.Git.PullEventHandler) is a base class that can be extended in order to develop functionality that should be run when the repository pulls from remote. The code placed inside the subclass' OnPull() method will be executed any time a pull occurs.
64+
65+
A recommended way to implement CI/CD would be to use one of the pre-defined subclasses of PullEventHandler that are placed inside the PullEventHandler package. Additionally, custom load logic can be placed in that package following the model of the existing subclasses.
66+
6167
### Security
6268
6369
#### Unsecured (http) connections
@@ -99,6 +105,8 @@ Assuming you have the local and remote repositories created,
99105
`git config core.sshCommand 'ssh -i ~/.ssh/<private key name>'`
100106
8. Test the refresh button for the remote branches on the WebUI, fetch from the source control menu in Studio or VS Code, and `git fetch` in Git Bash. All 3 should work without any issues.
101107
108+
109+
102110
## During Development
103111
104112
:warning: Whenever any code in this project is updated outside the server (e.g. after every `git pull`), you _have_ to run `zpm "load <absolute path to git-source-control>"`. Otherwise, the changes won't be reflected on the server. However, if you load git-source-control via the InterSystems package manager and run `git pull` via the extension itself with the default pull event handler configured, it'll just work.

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: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,7 @@ ClassMethod AddToServerSideSourceControl(InternalName As %String) As %Status
519519

520520
ClassMethod AddToSourceControl(InternalName As %String) As %Status
521521
{
522+
do ##class(SourceControl.Git.PackageManagerContext).ForInternalName(InternalName)
522523
set settings = ##class(SourceControl.Git.Settings).%New()
523524
#dim i as %Integer
524525
#dim ec as %Status = $$$OK
@@ -2068,5 +2069,47 @@ ClassMethod ResetSourceControlClass()
20682069
do ##class(%Studio.SourceControl.Interface).SourceControlClassSet("")
20692070
}
20702071

2072+
ClassMethod BaselineExport(pCommitMessage = "", pPushToRemote = "") As %Status
2073+
{
2074+
set sc = $$$OK
2075+
try {
2076+
write !, "Exporting items..."
2077+
set rs = ##class(%Library.RoutineMgr).StudioOpenDialogFunc(
2078+
"*.mac,*.int,*.inc,*.cls,*.csp" // Spec
2079+
, , ,0 // SystemFiles
2080+
,1 // Flat
2081+
,0 // NotStudio
2082+
,0 // ShowGenerated
2083+
, , ,0 // Mapped
2084+
)
2085+
throw:rs.%SQLCODE<0 ##class(%Exception.SQL).CreateFromSQLCODE(rs.%SQLCODE,rs.%Message)
2086+
while rs.%Next(.sc) {
2087+
$$$ThrowOnError(sc)
2088+
set internalName = rs.Name
2089+
// exclude items in a non-default IPM package
2090+
set context = ##class(SourceControl.Git.PackageManagerContext).ForInternalName(internalName)
2091+
continue:($isobject(context.Package) && 'context.IsInDefaultPackage)
2092+
$$$ThrowOnError(..AddToSourceControl(internalName))
2093+
}
2094+
if pCommitMessage '= "" {
2095+
// switch to default context
2096+
do ##class(SourceControl.Git.PackageManagerContext).ForInternalName("")
2097+
do ..RunGitWithArgs(.errStream, .outStream, "add", "--all")
2098+
do ..PrintStreams(errStream, outStream)
2099+
set username = ..GitUserName()
2100+
set email = ..GitUserEmail()
2101+
set author = username_" <"_email_">"
2102+
do ..RunGitWithArgs(.errStream, .outStream, "commit", "--author", author, "-m", pCommitMessage)
2103+
do ..PrintStreams(errStream, outStream)
2104+
$$$ThrowOnError(##class(SourceControl.Git.Change).RefreshUncommitted(,,,1))
2105+
if (pPushToRemote '= "") {
2106+
$$$ThrowOnError(..Push(pPushToRemote))
2107+
}
2108+
}
2109+
} catch err {
2110+
set sc = err.AsStatus()
2111+
}
2112+
return sc
20712113
}
20722114

2115+
}
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)