Skip to content

Commit b22e84b

Browse files
committed
Merge branch 'main' into production-change-control
2 parents 83ffd8e + 90c0853 commit b22e84b

32 files changed

+1351
-316
lines changed

CHANGELOG.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,45 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Added
1111
- Added 'git push --force' in expert mode (#527)
1212
- Add remote repository to settings page (#448)
13+
- Added change context option to pull page (#468)
14+
- Added favorite namespaces setting for a user (#468, #510)
1315
- Added environment awareness in configuration, and showing of environment name in UI (#124)
16+
- Warning on sync page if other users have unstaged changes (#493)
17+
- Added "Export System Default Settings" menu item (#544)
18+
- IRIS Business Intelligence items are mapped to the /dfi subdirectory by default (#428)
19+
- Intelligent merge conflict auto-resolution works for the common Business Rule case as well (#391)
20+
- All git commands run on the server, their output, and any associated sync output, are logged to a table for diagnostic purposes (#454)
21+
- Added API method to automatically add proper %ALL mappings for git-source-control (#214)
1422
- Production Decomposition mode allows controlling interoperability productions as individual files for each host (#469)
1523

1624
### Fixed
1725
- Fixed display of other users' username in workspace view on Unix (#530)
26+
- Fix left-sidebar spacing (#525)
1827
- Fixed slowness loading some CSP pages with multiple instances sharing a webserver (#540)
28+
- Prevent direct commits to default merge branch in basic mode (#484)
29+
- Fixed GetContexts utils function to exclude implied namespaces from the list of namespaces (#468)
30+
- Fixed git path configuration (#463)
31+
- Added feedback to settings page (#550)
32+
- Fix "Home" navigation to point to current namespace (#548)
33+
- Fixed issues when user checks out nonexistent branch (#549)
34+
- Fixed checking out branch with uncommitted work (#539)
35+
- Make sure more fetch calls prune the remote branches (#471)
36+
- Force export of item if it has been modified (#354)
37+
- Production configuration page no longer closes Sync/WebUI when operations there change the production (#542)
38+
- Remove leading/trailing spaces from input to Configure() (#356)
39+
- Fix branches with special characters not showing in GitUI (#523)
40+
- Fix filenames with spaces not showing correctly in workspace view (#551)
41+
- Removed inaccurate placeholder text for commit message in UI (#406)
42+
- Fixed regression that broke production conflict auto-resolve (#526)
43+
- Initialize repo in settings page now uses entered repo (#486)
44+
- Report error more clearly if you try to create a branch with an invalid name (#534)
45+
- Don't default to WINDOWS style paths (#357)
46+
- Fix errors when deleting non-existent files on import (#524)
47+
- Fix errors on commit when a file was added, never committed, then deleted from the repository (#481)
48+
- Fixed issue with saving multiple new no-folder mapping settings at the same time (#533)
49+
- Fixed sending OS error when git pull encounters error (#545)
50+
- Fixed suppressing editing of locked classes (#301)
51+
- Fixed importing CSP files (#251)
1952

2053
## [2.6.0] - 2024-10-07
2154

CONTRIBUTING.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# How to contribute
2+
3+
Thank you for your interest in contributing! While this project originated at InterSystems, it is our hope that the community will continue to extend and enhance it.
4+
5+
## Submitting changes
6+
7+
If you have made a change that you would like to contribute back to the community, please send a [GitHub Pull Request](/pull/new/main) explaining it. If your change fixes an issue that you or another user reported, please mention it in the pull request. You can find out more about pull requests [here](http://help.github.com/pull-requests/).
8+
9+
Every pull request should include at least one entry in CHANGELOG.md - see [keepachangelog.com](https://keepachangelog.com/) for guidelines.
10+
11+
We encourage use of [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).
12+
13+
## Coding conventions
14+
15+
Generally speaking, just try to match the conventions you see in the code you are reading. For this project, these include:
16+
17+
* Do not use shortened command and function names - e.g., `s` instead of `set`, `$p` instead of `$piece`
18+
* One command per line
19+
* Do not use dot syntax
20+
* Indentation with tabs
21+
* Pascal case class and method names
22+
* Avoid using postconditionals
23+
* Local variables start with `t`; formal parameter names start with `p`
24+
* Always check %Status return values
25+
26+
When making changes that involve JavaScript, ensure that your changes still work from Studio (which uses an old version of IE under the hood and therefore doesn't support various things you might take for granted).
27+
28+
Thank you!

README.md

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# git-source-control
2-
Server-side source control extension for Git on InterSystems' platforms
2+
Embedded Git support for InterSystems platforms, supporting unified source control for changes made via IDEs (e.g., VSCode over isfs) and the Management Portal (Interoperability and Business Intelligence).
33

44
## Prerequisites/Dependencies
55

@@ -32,23 +32,43 @@
3232
}
3333
```
3434
35+
### Making available instance-wide via %ALL namespace
36+
37+
To make git-source-control available to all namespaces on an instance without manually installing it in each, you can run:
38+
39+
`do ##class(SourceControl.Git.API).MapEverywhere()`
40+
41+
This will create the appropriate mappings to have all namespaces on the system use the version in the current namespace. Note, namespaces still must be configured independently. To undo this, you can delete the mappings from the %ALL namespace.
42+
3543
## Basic Use
3644
45+
The point of Embedded Git is to intercept events made through all editors - both IDEs and the management portal - so that changes are reflected in the filesystem, in a git repo, and able to be shared with others. There are also source-control specific menus to help you do key tasks.
46+
3747
### Source Control
3848
3949
For those with less experience using source control, we recommend this [page](/docs/scintro.md) for a quick introduction to source control / change control basics.
4050
4151
### Health Connect Cloud
42-
git-source control is the recommended source control for Health Connect Cloud. [This page](/docs/hcc.md) covers HCC specific usage of git-source-control, including the recommended development workflow, initial setup, and CICD pipelining.
52+
53+
git-source control is the recommended source control for Health Connect Cloud. [This page](/docs/hcc.md) covers HCC specific usage of git-source-control, including the recommended development workflow, initial setup, and CI/CD pipelining.
54+
55+
### VSCode
56+
57+
Source control menus will appear under "Server Source Control..." when right-clicking in a file (in the editor) or on a file when exploring an isfs folder. The top level "source control" menu is accessible through the command palette or the source control icon in the top right of the editor.
58+
59+
For full details on all of the menu items, see [this reference page](/docs/menu-items.md).
60+
61+
### Management Portal Editors
62+
63+
In relevant editors in the management portal, there are two icons that allow access to the same source control functionality as in IDEs. Click the source control icon to see the menu, and the clipboard to see output from previously run commands in your browser session.
64+
65+
*Important*: if using source control for interoperability, check the "Permit Enabling Automatic Refresh of Management Portal Pages" box in the management portal, at the page: Interoperability > Manage > Configuration > Interoperability Settings. This mitigates a potential for lost work.
4366
4467
### Studio
45-
Add a file for tracking by right-clicking on it in the workspace/project view and choosing Git > Add.
46-
This same menu also has options to remove (stop tracking the file), discard changes (revert to the index), or commit changes.
4768
48-
You can browse file history and commit changes through a user interface launched from the top level Git > "Launch Git UI" menu item. There is also a page for configuring settings.
69+
Note: Studio has been deprecated. VSCode is the IDE recommended by InterSystems.
4970
50-
### VSCode
51-
The same right click menus as in Studio live under "Server Source Control..." when right-clicking in a file (in the editor) or on a file when exploring an isfs folder. The top level "source control" menu is accessible through the command palette or the source control icon in the top right of the editor.
71+
That said, the same menu items and editor behavior will also work in Studio. There is a top-level "Git" menu with access to various operations and pages dependent on the current editor context.
5272
5373
## Notes
5474
@@ -67,10 +87,22 @@ This might look like:
6787
6888
### Pull Event Handlers
6989
70-
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.
90+
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.
7191
7292
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.
7393
94+
### Use in Deployment
95+
96+
To manually pull the latest code from the current configured branch into an IRIS instance, use the "Git Pull" favorite link that is added to the management portal automatically on installation or via the Settings page "Favorite Namespaces" option.
97+
98+
To use git-source-control as part of automated deployment to a test/production environment with a running IRIS instance, the best approach is to call into the appropriate IRIS namespace to run:
99+
100+
`do ##class(SourceControl.Git.API).Pull(1)`
101+
102+
This is convenient for scripting because it will terminate with an OS-level error if anything goes wrong. Further automation and customization can live in your pull event handler, described above.
103+
104+
[This Developer Community answer](https://community.intersystems.com/post/cache-unit-test-jenkins#comment-115146) has some helpful guidance on how to call in to IRIS from the OS level for CI/CD; there are other helpful resources on the Developer Community as well.
105+
74106
### Security
75107
76108
#### Unsecured (http) connections
@@ -113,8 +145,14 @@ Assuming you have the local and remote repositories created,
113145
`git config core.sshCommand 'ssh -i ~/.ssh/<private key name>'`
114146
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.
115147
148+
## Support
149+
150+
If you find a bug or would like to request an enhancement, [report an issue](https://github.com/intersystems/git-source-control/issues/new). If you have a question, post it on the [InterSystems Developer Community](https://community.intersystems.com/) - consider using the "Git" and "Source Control" tags as appropriate.
151+
152+
## Contributing
116153
154+
Please read [contributing](CONTRIBUTING.md) for details on the process for submitting pull requests to us.
117155
118-
## During Development
156+
### During Development
119157
120158
: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: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,14 @@ ClassMethod Configure()
4444
}
4545

4646
/// API for git pull - just wraps Utils
47-
ClassMethod Pull()
47+
/// - pTerminateOnError: if set to 1, this will terminate on error if there are any errors in the pull, otherwise will return status
48+
ClassMethod Pull(pTerminateOnError As %Boolean = 0)
4849
{
49-
quit ##class(SourceControl.Git.Utils).Pull()
50+
set st = ##class(SourceControl.Git.Utils).Pull(,pTerminateOnError)
51+
if pTerminateOnError && $$$ISERR(st) {
52+
Do $System.Process.Terminate($Job,1)
53+
}
54+
quit st
5055
}
5156

5257
/// Locks the environment to prevent changes to code other than through git pull.
@@ -71,6 +76,11 @@ ClassMethod BaselineExport(pCommitMessage = "", pPushToRemote = "") As %Status
7176
quit ##class(SourceControl.Git.Utils).BaselineExport(pCommitMessage, pPushToRemote)
7277
}
7378

79+
ClassMethod MapEverywhere()
80+
{
81+
Quit ##class(SourceControl.Git.Installer).MapEverywhere()
82+
}
83+
7484
/// Run to baseline all interoperability productions in the namespace to source control.
7585
/// This should be done after changing the value of the "decompose productions" setting.
7686
ClassMethod BaselineProductions()

cls/SourceControl/Git/Change.cls

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,20 @@ ClassMethod RefreshUncommitted(Display = 0, IncludeRevert = 0, Output gitFiles,
177177
if $$$ISERR(sc) continue
178178
}
179179
}
180+
181+
// If a file was added to the index and then deleted, git status will show it as a delete but committing will fail.
182+
// The solution is to git add each deleted file that has never been committed so it will be removed from the index.
183+
set key = $order(gitFiles(""))
184+
while (key '= "") {
185+
if $listget(gitFiles(key),1) = "D" {
186+
set filename = $listget(gitFiles(key),2)
187+
do ##class(SourceControl.Git.Utils).RunGitCommandWithInput("log",,.errStream,.outStream,"--first-parent", "--", filename)
188+
if (outStream.Size = 0) {
189+
do ##class(SourceControl.Git.Utils).RunGitCommandWithInput("add",,errStream,outStream,filename)
190+
}
191+
}
192+
set key = $order(gitFiles(key))
193+
}
180194
set ^IRIS.Temp.gitsourcecontrol("Refresh") = $zdatetime($ztimestamp,-2)
181195
merge ^IRIS.Temp.gitsourcecontrol("LastUncommitted") = gitFiles
182196
quit sc

cls/SourceControl/Git/Extension.cls

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ XData Menu
2929
<MenuItem Name="NewBranch" />
3030
<MenuItem Name="SwitchBranch" />
3131
<MenuItem Separator="true"/>
32+
<MenuItem Name="ExportSystemDefaults" />
3233
<MenuItem Name="Export" />
3334
<MenuItem Name="ExportForce" />
3435
<MenuItem Name="Import" />
@@ -58,13 +59,18 @@ Method UserAction(Type As %Integer, Name As %String, InternalName As %String, Se
5859
// if item is being edited in a different namespace, opening it will display an alert. Editing in this namespace will remove the alert.
5960
set filename = ##class(SourceControl.Git.Utils).FullExternalName(.InternalName)
6061
do ##class(SourceControl.Git.Change).GetUncommitted(filename,.tAction)
62+
do ..GetStatus(.InternalName, .isInSourceControl, .isEditable,.isCheckedOut,.userCheckedOut)
6163
if '$data(tAction) {
6264
set user = "", inNamespace = ""
63-
if ##class(SourceControl.Git.Utils).InstanceWideUncommittedCheck(InternalName, .user, .inNamespace) {
65+
if 'isEditable || ##class(SourceControl.Git.Utils).Locked() {
66+
set Target = "Warning: Attempting to edit read-only file"
67+
write !, Target
68+
set Action = 6
69+
} elseif ##class(SourceControl.Git.Utils).InstanceWideUncommittedCheck(InternalName, .user, .inNamespace) {
6470
set Target = "Warning: Item " _ InternalName _ " is currently being modified by " _ user _ " in namespace " _ inNamespace _ "."
6571
write !, Target
6672
set Action = 6
67-
}
73+
}
6874
}
6975
}
7076
}
@@ -81,6 +87,15 @@ Method UserAction(Type As %Integer, Name As %String, InternalName As %String, Se
8187
quit $$$OK
8288
}
8389

90+
if (menuItemName = "Commit") {
91+
set defaultBasic = ##class(SourceControl.Git.Utils).InDefaultBranchBasicMode()
92+
if (defaultBasic) {
93+
Set Target = "WARNING: Please create a new branch before committing."
94+
set Action = 6
95+
quit $$$OK
96+
}
97+
}
98+
8499
if (menuItemName = "Commit") || (menuItemName = "Sync") {
85100
if ..CheckCommitterIdentity(settings, .Action, .Target) {
86101
quit $$$OK
@@ -116,6 +131,7 @@ Method LocalizeName(name As %String) As %String
116131
"Settings":$$$Text("@Settings@Settings"),
117132
"Init":$$$Text("@Init@Initialize"),
118133
"GitWebUI":$$$Text("@GitWebUI@Launch Git UI"),
134+
"ExportSystemDefaults":$$$Text("@ExportSystemDefaults@Export System Default Settings"),
119135
"Export":$$$Text("@Export@Export All"),
120136
"ExportForce":$$$Text("@ExportForce@Export All (Force)"),
121137
"Import":$$$Text("@Import@Import All"),
@@ -151,6 +167,11 @@ Method OnSourceMenuItem(name As %String, ByRef Enabled As %String, ByRef Display
151167
quit ..OnSourceMenuContextItem(InternalName,name,.Enabled,.DisplayName)
152168
}
153169

170+
if name = "ExportSystemDefaults" {
171+
set Enabled = ##class(%Library.EnsembleMgr).IsEnsembleNamespace()
172+
quit $$$OK
173+
}
174+
154175
if ##class(SourceControl.Git.Utils).BasicMode() {
155176
set Enabled = $CASE(name,
156177
"Status": 1,
@@ -162,7 +183,6 @@ Method OnSourceMenuItem(name As %String, ByRef Enabled As %String, ByRef Display
162183
"Sync": 1,
163184
"": 1,
164185
:-1
165-
166186
)
167187
} else {
168188
set Enabled = $CASE(name,
@@ -340,7 +360,8 @@ Method OnAfterSave(InternalName As %String, Object As %RegisteredObject = {$$$NU
340360
} else {
341361
set filename = ##class(SourceControl.Git.Utils).FullExternalName(InternalName)
342362
$$$ThrowOnError(##class(SourceControl.Git.Utils).RemoveRoutineTSH(InternalName))
343-
$$$ThrowOnError(##class(SourceControl.Git.Utils).ExportItem(InternalName))
363+
set forceExport = (InternalName'= "") && ($data(..Modified(InternalName)))
364+
$$$ThrowOnError(##class(SourceControl.Git.Utils).ExportItem(InternalName,,forceExport))
344365
if '##class(SourceControl.Git.Change).IsUncommitted(filename) {
345366
$$$ThrowOnError(##class(SourceControl.Git.Change).SetUncommitted(filename, "edit", InternalName, $username, "", 1, "", "", 0))
346367
}

cls/SourceControl/Git/Installer.cls

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/// Mostly used from SourceControl.Git.API:MapEverywhere
2+
Class SourceControl.Git.Installer
3+
{
4+
5+
ClassMethod MapEverywhere()
6+
{
7+
set sc = $$$OK
8+
try {
9+
set ns = $namespace
10+
set locDBDir = ##class(%SYS.Namespace).GetGlobalDest(ns,$Name(^IRIS.Msg("Studio")))
11+
set vars("LocalizationDB") = ..DatabaseDirToName(locDBDir)
12+
set codeDBDir = ##class(%SYS.Namespace).GetPackageDest(ns,"SourceControl.Git")
13+
set vars("RoutineDB") = ..DatabaseDirToName(codeDBDir)
14+
$$$ThrowOnError(..RunMapEverywhere(.vars))
15+
} catch e {
16+
set sc = e.AsStatus()
17+
if '$quit {
18+
write !,$System.Status.GetErrorText(sc)
19+
}
20+
}
21+
quit sc
22+
}
23+
24+
ClassMethod DatabaseDirToName(dbDir As %String) As %String [ Private ]
25+
{
26+
New $Namespace
27+
Set $Namespace = "%SYS"
28+
Set tSC = ##class(Config.Databases).DatabasesByDirectory($Piece(dbDir,"^"),$Piece(dbDir,"^",2),.tDBList)
29+
$$$ThrowOnError(tSC)
30+
If ($ListLength(tDBList) '= 1) {
31+
// This is highly unexpected, but worth checking for anyway.
32+
$$$ThrowStatus($$$ERROR($$$GeneralError,$$$FormatText("Could not find database name for '%1'",tDBDir)))
33+
}
34+
$$$ThrowOnError(tSC)
35+
Quit $ListGet(tDBList)
36+
}
37+
38+
/// This is a method generator whose code is generated by XGL.
39+
ClassMethod RunMapEverywhere(ByRef pVars, pLogLevel As %Integer = 3, pInstaller As %Installer.Installer, pLogger As %Installer.AbstractLogger) As %Status [ CodeMode = objectgenerator, Internal, Private ]
40+
{
41+
quit ##class(%Installer.Manifest).%Generate(%compiledclass, %code, "MapEverywhere")
42+
}
43+
44+
XData MapEverywhere [ XMLNamespace = INSTALLER ]
45+
{
46+
<Manifest>
47+
<Namespace Name="%ALL" Create="yes" Ensemble="no" Code="%DEFAULTDB" Data="%DEFAULTDB">
48+
<Configuration>
49+
<GlobalMapping Global="IRIS.Msg" From="%DEFAULTDB" />
50+
<GlobalMapping Global="IRIS.Msg(&quot;Studio&quot;)" From="${LocalizationDB}" />
51+
<ClassMapping Package="SourceControl.Git" From="${RoutineDB}" />
52+
</Configuration>
53+
</Namespace>
54+
</Manifest>
55+
}
56+
57+
}

0 commit comments

Comments
 (0)