From 998a54ec5bd36aed1cae7a0b322b1c0da9f6a1f9 Mon Sep 17 00:00:00 2001
From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com>
Date: Wed, 28 Aug 2024 16:14:35 -0400
Subject: [PATCH 01/12] feat: allow editing of files via web application
First pass - probably needs a bit more work around the use case where a CSP file changes. (Theory: call OnBeforeTimestamp / OnBeforeLoad at end of AfterUserAction if the name is mapped?)
---
cls/SourceControl/Git/Settings.cls | 74 ++++++++++++++++++++++++++++++
cls/SourceControl/Git/Utils.cls | 7 +++
2 files changed, 81 insertions(+)
diff --git a/cls/SourceControl/Git/Settings.cls b/cls/SourceControl/Git/Settings.cls
index 6a4ce435..da9fdddf 100644
--- a/cls/SourceControl/Git/Settings.cls
+++ b/cls/SourceControl/Git/Settings.cls
@@ -47,6 +47,9 @@ Property defaultMergeBranch As %String [ InitialExpression = {##class(SourceCont
/// Compile using the configured pull event handler when "Import All" is run
Property compileOnImport As %Boolean [ InitialExpression = {##class(SourceControl.Git.Utils).CompileOnImport()} ];
+/// Define a namespace-level web application allowing access to multiple git repos across separate namespaces
+Property namespaceLevelGitWebApp As %Boolean [ InitialExpression = {##class(SourceControl.Git.Settings).HasNamespaceWebApp()} ];
+
Property Mappings [ MultiDimensional ];
Method %OnNew() As %Status
@@ -160,6 +163,75 @@ ClassMethod Configure() As %Boolean [ CodeMode = objectgenerator ]
do %code.WriteLine(" quit 1")
}
+Method ConfigureNamespaceWebApplication()
+{
+ Set root = ##class(%Library.File).NormalizeDirectory(##class(SourceControl.Git.Utils).TempFolder())
+ Set deleteWebApp = ..HasNamespaceWebApp(.appDirectory) && '..namespaceLevelGitWebApp
+ Set createWebApp = ..namespaceLevelGitWebApp && '..HasNamespaceWebApp()
+ Do ..WebAppOperation("/git/"_$Namespace_"/", createWebApp, deleteWebApp, root)
+}
+
+Method WebAppOperation(name, create As %Boolean, delete As %Boolean, root As %String) [ Private ]
+{
+ Set namespace = $Namespace
+ New $Namespace
+ Set $Namespace = "%SYS"
+ If $Extract(name) = "/" {
+ Set name = $Extract(name,1,*-1)
+ }
+ If delete {
+ If ##class(Security.Applications).Exists(name) {
+ $$$ThrowOnError(##class(Security.Applications).Delete(name))
+ Write !,"Removed web application "_name
+ }
+ Quit
+ }
+
+ // These are the only things we want to coerce.
+ Set props("AutheEnabled")=0 // No auth methods enabled = impossible to use
+ Set props("InbndWebServicesEnabled")=0
+ Set props("ServeFiles")=0
+ Set props("Enabled")=1
+ Set props("Name")=name
+ Set props("NameSpace")=namespace
+ Set props("Path")=root
+ Set props("Type")=2
+ Set props("Recurse")=1
+ If create {
+ Write !,"Creating web application: "_name_"... "
+ $$$ThrowOnError(##class(Security.Applications).Create(name,.props))
+ Write "done."
+ } ElseIf ##class(Security.Applications).Exists(name) {
+ Write !,"Web application '"_name_"' already exists."
+ $$$ThrowOnError(##class(Security.Applications).Get(name,.existingProps))
+ Set changes = 0
+ Set key = ""
+ For {
+ Set key = $Order(props(key),1,value)
+ Quit:key=""
+ If (value '= $Get(existingProps(key))) {
+ Write !,"Changing "_key_": "_$Get(existingProps(key))_" -> "_value
+ Set changes = 1
+ }
+ }
+ If changes {
+ $$$ThrowOnError(##class(Security.Applications).Modify(name,.props))
+ Write !,"Web application '"_name_"' updated."
+ } Else {
+ Write !,"No changes made to web application."
+ }
+ }
+}
+
+ClassMethod HasNamespaceWebApp(Output webAppDirectory) As %Boolean
+{
+ Set webAppDirectory = $System.CSP.GetFileName("/git/"_$Namespace_"/")
+ If (webAppDirectory '= "") {
+ Set webAppDirectory = ##class(%Library.File).NormalizeDirectory(webAppDirectory)
+ }
+ Quit (webAppDirectory '= "")
+}
+
Method OnAfterConfigure() As %Boolean
{
set defaultPromptFlag = $$$DisableBackupCharMask + $$$TrapCtrlCMask + $$$EnableQuitCharMask + $$$DisableHelpCharMask + $$$DisableHelpContextCharMask + $$$TrapErrorMask
@@ -186,6 +258,8 @@ Method OnAfterConfigure() As %Boolean
}
}
+ do ..ConfigureNamespaceWebApplication()
+
set gitDir = ##class(%File).NormalizeDirectory(..namespaceTemp)_".git"
if '##class(%File).DirectoryExists(gitDir) {
set list(1) = "Initialize empty repo"
diff --git a/cls/SourceControl/Git/Utils.cls b/cls/SourceControl/Git/Utils.cls
index 9b6405c7..9f9e159a 100644
--- a/cls/SourceControl/Git/Utils.cls
+++ b/cls/SourceControl/Git/Utils.cls
@@ -1132,6 +1132,13 @@ ClassMethod NormalizeInternalName(ByRef name As %String) As %String
if ($extract(name) '= "/") && (type'="csp") {
quit $piece(name,".",1,*-1)_"."_$zconvert($piece(name,".",*),"U")
}
+
+ if (name [ "/") && (type = "csp") {
+ set cspFilename = $System.CSP.GetFileName(name)
+ if (cspFilename '= "") && (cspFilename [ ..TempFolder()) {
+ set name = ..NameToInternalName(cspFilename)
+ }
+ }
if (type = "inc") || (type = "mac") || (type = "int") {
set name = $extract($translate(name, "/", "."), 2, *)
From 13905752812ca19c9a7976d7709d49d35d8c710f Mon Sep 17 00:00:00 2001
From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com>
Date: Thu, 29 Aug 2024 09:24:57 -0400
Subject: [PATCH 02/12] feat: add VSCode workspace download link
Also tweaks some styling and fixes behavior for interop-enabled namespaces with a URLPrefix.
---
cls/SourceControl/Git/StreamServer.cls | 3 +-
cls/SourceControl/Git/Utils.cls | 5 +-
cls/SourceControl/Git/WebUIDriver.cls | 61 +++++++++++++++++++
.../share/git-webui/webui/css/git-webui.css | 18 +++++-
.../share/git-webui/webui/img/context.svg | 2 +-
.../share/git-webui/webui/js/git-webui.js | 3 +
.../share/git-webui/webui/css/git-webui.less | 23 ++++++-
.../src/share/git-webui/webui/img/context.svg | 2 +-
.../src/share/git-webui/webui/js/git-webui.js | 3 +
9 files changed, 108 insertions(+), 12 deletions(-)
diff --git a/cls/SourceControl/Git/StreamServer.cls b/cls/SourceControl/Git/StreamServer.cls
index daf75a8d..42b2330e 100644
--- a/cls/SourceControl/Git/StreamServer.cls
+++ b/cls/SourceControl/Git/StreamServer.cls
@@ -7,7 +7,7 @@ Class SourceControl.Git.StreamServer Extends %CSP.StreamServer
ClassMethod OnPage() As %Status
{
if (%stream '= $$$NULLOREF) && $data(%base)#2 {
- set sourceControlInclude = ##class(SourceControl.Git.Utils).GetSourceControlInclude()
+ set sourceControlInclude = ##class(SourceControl.Git.Utils).GetSourceControlInclude(%request.URLPrefix)
while '%stream.AtEnd {
set text = %stream.Read()
set text = $replace(text,"{{baseHref}}",..EscapeHTML(%base))
@@ -19,4 +19,3 @@ ClassMethod OnPage() As %Status
}
}
-
diff --git a/cls/SourceControl/Git/Utils.cls b/cls/SourceControl/Git/Utils.cls
index 9f9e159a..1efca933 100644
--- a/cls/SourceControl/Git/Utils.cls
+++ b/cls/SourceControl/Git/Utils.cls
@@ -2403,10 +2403,10 @@ ClassMethod GetPackageVersion() As %String [ CodeMode = objectgenerator ]
quit $$$OK
}
-ClassMethod GetSourceControlInclude() As %String
+ClassMethod GetSourceControlInclude(prefix As %String = "") As %String
{
quit $select(##class(%Library.EnsembleMgr).IsEnsembleInstalled():
- "",
+ "",
1: "")
}
@@ -2622,4 +2622,3 @@ ClassMethod BaselineExport(pCommitMessage = "", pPushToRemote = "") As %Status
}
}
-
diff --git a/cls/SourceControl/Git/WebUIDriver.cls b/cls/SourceControl/Git/WebUIDriver.cls
index 5d8a2b17..1699453c 100644
--- a/cls/SourceControl/Git/WebUIDriver.cls
+++ b/cls/SourceControl/Git/WebUIDriver.cls
@@ -27,6 +27,67 @@ ClassMethod HandleRequest(pagePath As %String, InternalName As %String = "", Out
if $isobject($get(responseJSON)) {
do responseJSON.%ToJSON(%data)
}
+ } elseif pathStart = "vscode-workspace" {
+ set handled = 1
+ set namespace = $Namespace
+ set instanceName = $ZConvert(##class(%SYS.System).InstanceGUID(),"L")
+ set hasCSP = 0
+ if (InternalName = "") || context.IsInDefaultPackage {
+ set hasCSP = ##class(SourceControl.Git.Settings).HasNamespaceWebApp()
+ set workspaceFilename = namespace_"-"_instanceName_"-.code-workspace"
+ set filter = "?mapped=0"
+ } elseif context.IsInGitEnabledPackage {
+ set workspaceFilename = context.Package.Name_"-"_instanceName_".code-workspace"
+ // Loading an IPM package in dev mode automatically creates a project for it, so filter to that.
+ set filter = "?project="_context.Package.Name
+ } else {
+ // TODO: Error? But really shouldn't happen.
+ quit
+ }
+ set server = {
+ "webServer": {
+ "host": (%request.CgiEnvs("SERVER_NAME")),
+ "port": (%request.CgiEnvs("SERVER_PORT")),
+ "scheme": ($Select(%request.Secure:"https",1:"http"))
+ },
+ "username": ($Username)
+ }
+ if (%request.URLPrefix '= "") {
+ set server.webServer.pathPrefix = %request.URLPrefix
+ }
+ set workspaceDef = {
+ "folders": [
+ {
+ "name": ($Namespace),
+ "uri": ("isfs://"_instanceName_":"_$Namespace_"/"_filter)
+ }
+ ],
+ "settings": {
+ "intersystems.servers": {
+ "/default": (instanceName)
+ },
+ "objectscript.conn": {
+ "active": false
+ }
+ }
+ }
+ if hasCSP {
+ do workspaceDef.folders.%Push({
+ "name": ($Namespace_" (Filesystem)"),
+ "uri": ("isfs://"_instanceName_":"_$Namespace_"/git/"_$Namespace_"?csp")
+ })
+ }
+ set $Property(workspaceDef.settings."intersystems.servers",instanceName) = server
+ set stream = ##class(%CSP.CharacterStream).%New()
+ do stream.SetAttribute("ContentDisposition","attachment; filename="_workspaceFilename)
+ set formatter = ##class(%JSON.Formatter).%New()
+ do formatter.FormatToStream(workspaceDef,stream)
+ $$$ThrowOnError(stream.%Save())
+ do %request.Set("STREAMOID",##class(%CSP.Page).Encrypt(stream.%Oid()))
+ set %request.Data("EXPIRES",1,"encrypt") = 1
+ do %request.Set("EXPIRES",0)
+ do ##class(%CSP.StreamServer).OnPreHTTP() // Need to call this to set headers properly
+ set %stream = 1 // Leak this to webuidriver.csp
} elseif $match(pathStart,"git-command|git|dirname|hostname|viewonly|contexts") {
if (%request.Method = "GET") {
set %data = ##class(%Stream.TmpCharacter).%New()
diff --git a/git-webui/release/share/git-webui/webui/css/git-webui.css b/git-webui/release/share/git-webui/webui/css/git-webui.css
index 0a0043b7..2eebf585 100644
--- a/git-webui/release/share/git-webui/webui/css/git-webui.css
+++ b/git-webui/release/share/git-webui/webui/css/git-webui.css
@@ -183,7 +183,7 @@ body {
padding-bottom: 100px;
}
#sidebar #sidebar-content > :first-child,
-#sidebar #sidebar-content > :nth-last-child(2) {
+#sidebar #sidebar-content > :nth-last-child(3) {
border-top: 1px solid #5e5e5e;
}
#sidebar #sidebar-content h4:before {
@@ -216,12 +216,26 @@ body {
#sidebar #sidebar-content #sidebar-tags h4:before {
content: url(../img/tag.svg);
}
+#sidebar #sidebar-content #sidebar-vscode a {
+ color: white;
+}
+#sidebar #sidebar-content #sidebar-vscode h4:before {
+ content: url(../img/file.svg);
+}
+#sidebar #sidebar-content #sidebar-vscode {
+ position: absolute;
+ bottom: 80px;
+ width: 16.7em;
+ padding-bottom: 0.3rem;
+ margin-bottom: 0;
+ background-color: #333333;
+}
#sidebar #sidebar-content #sidebar-context h4:before {
content: url(../img/context.svg);
}
#sidebar #sidebar-content #sidebar-context {
position: absolute;
- bottom: 50px;
+ bottom: 40px;
width: 16.7em;
padding-bottom: 0.3rem;
margin-bottom: 0;
diff --git a/git-webui/release/share/git-webui/webui/img/context.svg b/git-webui/release/share/git-webui/webui/img/context.svg
index e3732172..f5ef6c98 100644
--- a/git-webui/release/share/git-webui/webui/img/context.svg
+++ b/git-webui/release/share/git-webui/webui/img/context.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/git-webui/release/share/git-webui/webui/js/git-webui.js b/git-webui/release/share/git-webui/webui/js/git-webui.js
index 9625c506..7161e0d8 100644
--- a/git-webui/release/share/git-webui/webui/js/git-webui.js
+++ b/git-webui/release/share/git-webui/webui/js/git-webui.js
@@ -973,6 +973,9 @@ webui.SideBarView = function(mainView, noEventHandlers) {
'' +
+ '' +
'' +
diff --git a/git-webui/src/share/git-webui/webui/css/git-webui.less b/git-webui/src/share/git-webui/webui/css/git-webui.less
index 652d5bdb..41b16101 100644
--- a/git-webui/src/share/git-webui/webui/css/git-webui.less
+++ b/git-webui/src/share/git-webui/webui/css/git-webui.less
@@ -257,7 +257,7 @@ body {
color: @gray-lighter;
padding-bottom: 100px;
- > :first-child, >:nth-last-child(2) {
+ > :first-child, >:nth-last-child(3) {
border-top: 1px solid darken(@separator-line, 50%);
}
@@ -301,13 +301,30 @@ body {
content: url(../img/tag.svg);
}
+ #sidebar-vscode a {
+ color: white;
+ }
+
+ #sidebar-vscode h4:before {
+ content: url(../img/file.svg);
+ }
+
+ #sidebar-vscode {
+ position: absolute;
+ bottom: 80px;
+ width: 16.7em;
+ padding-bottom: 0.3rem;
+ margin-bottom: 0;
+ background-color: rgba(51, 51, 51, 1);
+ }
+
#sidebar-context h4:before {
- content: url(../img/context.svg)
+ content: url(../img/context.svg);
}
#sidebar-context {
position: absolute;
- bottom: 50px;
+ bottom: 40px;
width: 16.7em;
padding-bottom: 0.3rem;
margin-bottom: 0;
diff --git a/git-webui/src/share/git-webui/webui/img/context.svg b/git-webui/src/share/git-webui/webui/img/context.svg
index e3732172..f5ef6c98 100644
--- a/git-webui/src/share/git-webui/webui/img/context.svg
+++ b/git-webui/src/share/git-webui/webui/img/context.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/git-webui/src/share/git-webui/webui/js/git-webui.js b/git-webui/src/share/git-webui/webui/js/git-webui.js
index 9625c506..7161e0d8 100644
--- a/git-webui/src/share/git-webui/webui/js/git-webui.js
+++ b/git-webui/src/share/git-webui/webui/js/git-webui.js
@@ -973,6 +973,9 @@ webui.SideBarView = function(mainView, noEventHandlers) {
'' +
+ '' +
'' +
From 4ba8b80063f57a2f0cc616ee6e875b59a31537d5 Mon Sep 17 00:00:00 2001
From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com>
Date: Thu, 29 Aug 2024 09:55:03 -0400
Subject: [PATCH 03/12] feat: compile files modified via web application
---
CHANGELOG.md | 3 +++
cls/SourceControl/Git/Extension.cls | 29 ++++++++++++++++++++---------
cls/SourceControl/Git/Utils.cls | 9 ++++++---
3 files changed, 29 insertions(+), 12 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5e6a615a..5ee1b6f6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,10 +10,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- New UI for the basic mode Sync (#415)
- Allow changing namespaces and IPM package context from web UI (#280)
+- Support for editing repo from filesystem perspective via web application (#464)
+- Support for downloading a VSCode workspace file from web UI
### Fixed
- Instance wide settings are placed in proper global (#444)
- Added support to switch branch in basic mode from menu (#451)
+- Avoid delay/errors in loading interop JS when there is a URL prefix (e.g., instance name in multi-instance webserver configuration)
## [2.4.1] - 2024-08-02
diff --git a/cls/SourceControl/Git/Extension.cls b/cls/SourceControl/Git/Extension.cls
index dacf2816..f4eab0b3 100644
--- a/cls/SourceControl/Git/Extension.cls
+++ b/cls/SourceControl/Git/Extension.cls
@@ -74,9 +74,13 @@ Method AfterUserAction(Type As %Integer, Name As %String, InternalName As %Strin
if menu '= "%SourceMenu", menu'="%SourceContext" {
quit $$$OK
}
- set InternalName = ##class(SourceControl.Git.Utils).NormalizeInternalName(InternalName)
+ set InternalName = ##class(SourceControl.Git.Utils).NormalizeInternalName(InternalName, .fromWebApp)
set context = ##class(SourceControl.Git.PackageManagerContext).ForInternalName(InternalName)
set ec = ##class(SourceControl.Git.Utils).AfterUserAction(Type, Name, InternalName, .Answer, .Msg, .Reload)
+ if fromWebApp {
+ // Force reload and compile of actual item if underlying file has changed
+ do ..OnBeforeLoad(InternalName,1,1)
+ }
quit ec
}
@@ -235,12 +239,12 @@ Method OnMenuItem(MenuName As %String, InternalName As %String, SelectedText As
/// This is called before the actual load of data to give the chance
/// to load the item from an external format.
-Method OnBeforeLoad(InternalName As %String, verbose As %Boolean) As %Status
+Method OnBeforeLoad(InternalName As %String, verbose As %Boolean, compile As %Boolean = 0) As %Status
{
set context = ##class(SourceControl.Git.PackageManagerContext).ForInternalName(InternalName)
set InternalName = ##class(SourceControl.Git.Utils).NormalizeInternalName(InternalName)
if ##class(SourceControl.Git.Utils).IsInSourceControl(InternalName) {
- quit ##class(SourceControl.Git.Utils).ImportItem(InternalName,,0)
+ quit ##class(SourceControl.Git.Utils).ImportItem(InternalName,,0,compile)
}
quit $$$OK
}
@@ -274,14 +278,21 @@ Method OnAfterSave(InternalName As %String, Object As %RegisteredObject = {$$$NU
{
set sc = $$$OK
try {
- set InternalName = ##class(SourceControl.Git.Utils).NormalizeInternalName(.InternalName)
+ set InternalName = ##class(SourceControl.Git.Utils).NormalizeInternalName(.InternalName,.fromWebApp,.fullExternalName)
set context = ##class(SourceControl.Git.PackageManagerContext).ForInternalName(InternalName)
if ##class(SourceControl.Git.Utils).IsNamespaceInGit() && ..IsInSourceControl(InternalName) {
- set filename = ##class(SourceControl.Git.Utils).FullExternalName(InternalName)
- $$$ThrowOnError(##class(SourceControl.Git.Utils).RemoveRoutineTSH(InternalName))
- $$$ThrowOnError(##class(SourceControl.Git.Utils).ExportItem(InternalName))
- if '##class(SourceControl.Git.Change).IsUncommitted(filename) {
- $$$ThrowOnError(##class(SourceControl.Git.Change).SetUncommitted(filename, "edit", InternalName, $username, "", 1, "", "", 0))
+ if fromWebApp {
+ if fullExternalName = ##class(SourceControl.Git.Utils).FullExternalName(InternalName) {
+ // Reimport item into database
+ $$$ThrowOnError(##class(SourceControl.Git.Utils).ImportItem(InternalName,,1,1))
+ }
+ } else {
+ set filename = ##class(SourceControl.Git.Utils).FullExternalName(InternalName)
+ $$$ThrowOnError(##class(SourceControl.Git.Utils).RemoveRoutineTSH(InternalName))
+ $$$ThrowOnError(##class(SourceControl.Git.Utils).ExportItem(InternalName))
+ if '##class(SourceControl.Git.Change).IsUncommitted(filename) {
+ $$$ThrowOnError(##class(SourceControl.Git.Change).SetUncommitted(filename, "edit", InternalName, $username, "", 1, "", "", 0))
+ }
}
}
} catch e {
diff --git a/cls/SourceControl/Git/Utils.cls b/cls/SourceControl/Git/Utils.cls
index 1efca933..94290b60 100644
--- a/cls/SourceControl/Git/Utils.cls
+++ b/cls/SourceControl/Git/Utils.cls
@@ -1116,7 +1116,7 @@ ClassMethod FullExternalName(ByRef InternalName As %String, ByRef MappingExists
..TempFolder()_..ExternalName(.InternalName, .MappingExists)
}
-ClassMethod NormalizeInternalName(ByRef name As %String) As %String
+ClassMethod NormalizeInternalName(ByRef name As %String, Output fromWebApp As %Boolean = 0, Output cspFilename) As %String
{
//Studio passes name of routine with dots as it is in folders
//e.g. Package.SubPackage.Routine.mac has InternalName = /Package/SubPackage/Routine.mac
@@ -1137,6 +1137,9 @@ ClassMethod NormalizeInternalName(ByRef name As %String) As %String
set cspFilename = $System.CSP.GetFileName(name)
if (cspFilename '= "") && (cspFilename [ ..TempFolder()) {
set name = ..NameToInternalName(cspFilename)
+ set fromWebApp = 1
+ } else {
+ kill cspFilename
}
}
@@ -1253,7 +1256,7 @@ ClassMethod FixProjectCspReferences(projectName As %String) As %Status
/// imports file if version in system is newer then version on disk.
/// if force = 1 then imports in any case.
-ClassMethod ImportItem(InternalName As %String, force As %Boolean = 0, verbose As %Boolean = 1) As %Status
+ClassMethod ImportItem(InternalName As %String, force As %Boolean = 0, verbose As %Boolean = 1, compile As %Boolean = 0) As %Status
{
#dim filename as %String = ..FullExternalName(.InternalName)
#dim fileTSH = ##class(%File).GetFileDateModified(filename)
@@ -1272,7 +1275,7 @@ ClassMethod ImportItem(InternalName As %String, force As %Boolean = 0, verbose A
if ($extract(InternalName, 1) = "/"){
set sc = ..ImportCSPFile(InternalName)
} else{
- set sc = $system.OBJ.Load(filename,"-l-d")
+ set sc = $system.OBJ.Load(filename,$Select(compile:"ck-l",1:"-l-d"))
}
}
if sc {
From b4905e867754fa5857ae25efbd69605dbb923702 Mon Sep 17 00:00:00 2001
From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com>
Date: Thu, 29 Aug 2024 11:08:38 -0400
Subject: [PATCH 04/12] fix: tweak InternalName logic
---
cls/SourceControl/Git/WebUIDriver.cls | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/cls/SourceControl/Git/WebUIDriver.cls b/cls/SourceControl/Git/WebUIDriver.cls
index 1699453c..a8331485 100644
--- a/cls/SourceControl/Git/WebUIDriver.cls
+++ b/cls/SourceControl/Git/WebUIDriver.cls
@@ -32,17 +32,14 @@ ClassMethod HandleRequest(pagePath As %String, InternalName As %String = "", Out
set namespace = $Namespace
set instanceName = $ZConvert(##class(%SYS.System).InstanceGUID(),"L")
set hasCSP = 0
- if (InternalName = "") || context.IsInDefaultPackage {
- set hasCSP = ##class(SourceControl.Git.Settings).HasNamespaceWebApp()
- set workspaceFilename = namespace_"-"_instanceName_"-.code-workspace"
- set filter = "?mapped=0"
- } elseif context.IsInGitEnabledPackage {
+ if context.IsInGitEnabledPackage && 'context.IsInDefaultPackage {
set workspaceFilename = context.Package.Name_"-"_instanceName_".code-workspace"
// Loading an IPM package in dev mode automatically creates a project for it, so filter to that.
set filter = "?project="_context.Package.Name
} else {
- // TODO: Error? But really shouldn't happen.
- quit
+ set hasCSP = ##class(SourceControl.Git.Settings).HasNamespaceWebApp()
+ set workspaceFilename = namespace_"-"_instanceName_"-.code-workspace"
+ set filter = "?mapped=0"
}
set server = {
"webServer": {
From 58b5e7f00bea3d7e0ba3a79624e9a3ef5e3c7d45 Mon Sep 17 00:00:00 2001
From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com>
Date: Thu, 29 Aug 2024 11:24:44 -0400
Subject: [PATCH 05/12] fix: remove stray dash
---
cls/SourceControl/Git/WebUIDriver.cls | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cls/SourceControl/Git/WebUIDriver.cls b/cls/SourceControl/Git/WebUIDriver.cls
index a8331485..5787162b 100644
--- a/cls/SourceControl/Git/WebUIDriver.cls
+++ b/cls/SourceControl/Git/WebUIDriver.cls
@@ -38,7 +38,7 @@ ClassMethod HandleRequest(pagePath As %String, InternalName As %String = "", Out
set filter = "?project="_context.Package.Name
} else {
set hasCSP = ##class(SourceControl.Git.Settings).HasNamespaceWebApp()
- set workspaceFilename = namespace_"-"_instanceName_"-.code-workspace"
+ set workspaceFilename = namespace_"-"_instanceName_".code-workspace"
set filter = "?mapped=0"
}
set server = {
From 23c2dc981d22beb863e7e5fa02dec95f73ebf67a Mon Sep 17 00:00:00 2001
From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com>
Date: Fri, 30 Aug 2024 09:33:45 -0400
Subject: [PATCH 06/12] fix: always just include one folder
---
cls/SourceControl/Git/WebUIDriver.cls | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/cls/SourceControl/Git/WebUIDriver.cls b/cls/SourceControl/Git/WebUIDriver.cls
index 5787162b..a2888688 100644
--- a/cls/SourceControl/Git/WebUIDriver.cls
+++ b/cls/SourceControl/Git/WebUIDriver.cls
@@ -54,10 +54,6 @@ ClassMethod HandleRequest(pagePath As %String, InternalName As %String = "", Out
}
set workspaceDef = {
"folders": [
- {
- "name": ($Namespace),
- "uri": ("isfs://"_instanceName_":"_$Namespace_"/"_filter)
- }
],
"settings": {
"intersystems.servers": {
@@ -73,6 +69,11 @@ ClassMethod HandleRequest(pagePath As %String, InternalName As %String = "", Out
"name": ($Namespace_" (Filesystem)"),
"uri": ("isfs://"_instanceName_":"_$Namespace_"/git/"_$Namespace_"?csp")
})
+ } else {
+ do workspaceDef.folders.%Push({
+ "name": ($Namespace),
+ "uri": ("isfs://"_instanceName_":"_$Namespace_"/"_filter)
+ })
}
set $Property(workspaceDef.settings."intersystems.servers",instanceName) = server
set stream = ##class(%CSP.CharacterStream).%New()
From 0bd96de98fa010f8ae6382f5a5bbb39752f06dd4 Mon Sep 17 00:00:00 2001
From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com>
Date: Fri, 30 Aug 2024 15:12:34 -0400
Subject: [PATCH 07/12] fix: add JS escaping in sync output
---
CHANGELOG.md | 1 +
csp/sync.csp | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5ee1b6f6..0c6c52c3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Instance wide settings are placed in proper global (#444)
- Added support to switch branch in basic mode from menu (#451)
- Avoid delay/errors in loading interop JS when there is a URL prefix (e.g., instance name in multi-instance webserver configuration)
+- Added proper JS escaping in sync output
## [2.4.1] - 2024-08-02
diff --git a/csp/sync.csp b/csp/sync.csp
index 78be9c2c..03404f08 100644
--- a/csp/sync.csp
+++ b/csp/sync.csp
@@ -146,7 +146,7 @@
&js<
var outputContainer = document.getElementById('outputBox');
- var lineText = "#(escapedLine)#";
+ var lineText = "#(..QuoteJS(escapedLine))#";
var lineTextNode = document.createTextNode(lineText);
outputContainer.innerHTML += lineText + "
";
>
From e649df77bc6f3302dc94b19062c1f5f24407c7dc Mon Sep 17 00:00:00 2001
From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com>
Date: Fri, 30 Aug 2024 15:13:47 -0400
Subject: [PATCH 08/12] fix: don't double-quote
---
csp/sync.csp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/csp/sync.csp b/csp/sync.csp
index 03404f08..bab0d58d 100644
--- a/csp/sync.csp
+++ b/csp/sync.csp
@@ -146,7 +146,7 @@
&js<
var outputContainer = document.getElementById('outputBox');
- var lineText = "#(..QuoteJS(escapedLine))#";
+ var lineText = #(..QuoteJS(escapedLine))#;
var lineTextNode = document.createTextNode(lineText);
outputContainer.innerHTML += lineText + "
";
>
From a52a079dca6ba26817572796b5e8b8565881af87 Mon Sep 17 00:00:00 2001
From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com>
Date: Fri, 30 Aug 2024 15:16:49 -0400
Subject: [PATCH 09/12] fix: tweaks to workspace setup
---
cls/SourceControl/Git/WebUIDriver.cls | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/cls/SourceControl/Git/WebUIDriver.cls b/cls/SourceControl/Git/WebUIDriver.cls
index a2888688..d5580448 100644
--- a/cls/SourceControl/Git/WebUIDriver.cls
+++ b/cls/SourceControl/Git/WebUIDriver.cls
@@ -44,7 +44,7 @@ ClassMethod HandleRequest(pagePath As %String, InternalName As %String = "", Out
set server = {
"webServer": {
"host": (%request.CgiEnvs("SERVER_NAME")),
- "port": (%request.CgiEnvs("SERVER_PORT")),
+ "port": (+%request.CgiEnvs("SERVER_PORT")),
"scheme": ($Select(%request.Secure:"https",1:"http"))
},
"username": ($Username)
@@ -66,7 +66,7 @@ ClassMethod HandleRequest(pagePath As %String, InternalName As %String = "", Out
}
if hasCSP {
do workspaceDef.folders.%Push({
- "name": ($Namespace_" (Filesystem)"),
+ "name": ($Namespace),
"uri": ("isfs://"_instanceName_":"_$Namespace_"/git/"_$Namespace_"?csp")
})
} else {
From de9eb688459d3d9af7b2ee54f897fa26d8f1fa1b Mon Sep 17 00:00:00 2001
From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com>
Date: Thu, 12 Sep 2024 15:09:17 -0400
Subject: [PATCH 10/12] fix: tweak IE box model
Also fixed an issue with regex matching where I couldn't view my local git-source-control repo
---
.../share/git-webui/webui/css/git-webui.css | 15 +++++++++------
.../share/git-webui/webui/js/git-webui.js | 3 +++
.../share/git-webui/webui/css/git-webui.less | 18 ++++++++++++------
.../src/share/git-webui/webui/js/git-webui.js | 3 +++
4 files changed, 27 insertions(+), 12 deletions(-)
diff --git a/git-webui/release/share/git-webui/webui/css/git-webui.css b/git-webui/release/share/git-webui/webui/css/git-webui.css
index 2eebf585..0c75c1f4 100644
--- a/git-webui/release/share/git-webui/webui/css/git-webui.css
+++ b/git-webui/release/share/git-webui/webui/css/git-webui.css
@@ -219,6 +219,9 @@ body {
#sidebar #sidebar-content #sidebar-vscode a {
color: white;
}
+#sidebar #sidebar-content #sidebar-vscode h4 {
+ padding: 0px;
+}
#sidebar #sidebar-content #sidebar-vscode h4:before {
content: url(../img/file.svg);
}
@@ -226,10 +229,11 @@ body {
position: absolute;
bottom: 80px;
width: 16.7em;
- padding-bottom: 0.3rem;
- margin-bottom: 0;
background-color: #333333;
}
+#sidebar #sidebar-content #sidebar-context h4 {
+ padding: 0px;
+}
#sidebar #sidebar-content #sidebar-context h4:before {
content: url(../img/context.svg);
}
@@ -237,10 +241,11 @@ body {
position: absolute;
bottom: 40px;
width: 16.7em;
- padding-bottom: 0.3rem;
- margin-bottom: 0;
background-color: #333333;
}
+#sidebar #sidebar-content #sidebar-settings h4 {
+ padding: 0px;
+}
#sidebar #sidebar-content #sidebar-settings h4:before {
content: url(../img/gear-fill.svg);
}
@@ -248,8 +253,6 @@ body {
position: absolute;
bottom: 0px;
width: 16.7em;
- padding-bottom: 0.3rem;
- margin-bottom: 0px;
background-color: #333333;
}
#sidebar #sidebar-content ul {
diff --git a/git-webui/release/share/git-webui/webui/js/git-webui.js b/git-webui/release/share/git-webui/webui/js/git-webui.js
index 7161e0d8..632c10f1 100644
--- a/git-webui/release/share/git-webui/webui/js/git-webui.js
+++ b/git-webui/release/share/git-webui/webui/js/git-webui.js
@@ -421,6 +421,9 @@ webui.SideBarView = function(mainView, noEventHandlers) {
if (id.indexOf("local-branches") > -1) {
// parses the output of git branch --verbose --verbose
var matches = /^\*?\s*([\w-\/]+)\s+([^\s]+)\s+(\[.*\])?.*/.exec(ref);
+ if (!matches) {
+ continue;
+ }
var branchInfo = {
"branch_name": matches[1],
"hash": matches[2],
diff --git a/git-webui/src/share/git-webui/webui/css/git-webui.less b/git-webui/src/share/git-webui/webui/css/git-webui.less
index 41b16101..8fb86733 100644
--- a/git-webui/src/share/git-webui/webui/css/git-webui.less
+++ b/git-webui/src/share/git-webui/webui/css/git-webui.less
@@ -305,6 +305,10 @@ body {
color: white;
}
+ #sidebar-vscode h4 {
+ padding: 0px;
+ }
+
#sidebar-vscode h4:before {
content: url(../img/file.svg);
}
@@ -313,11 +317,13 @@ body {
position: absolute;
bottom: 80px;
width: 16.7em;
- padding-bottom: 0.3rem;
- margin-bottom: 0;
background-color: rgba(51, 51, 51, 1);
}
+ #sidebar-context h4 {
+ padding: 0px;
+ }
+
#sidebar-context h4:before {
content: url(../img/context.svg);
}
@@ -326,11 +332,13 @@ body {
position: absolute;
bottom: 40px;
width: 16.7em;
- padding-bottom: 0.3rem;
- margin-bottom: 0;
background-color: rgba(51, 51, 51, 1);
}
+ #sidebar-settings h4 {
+ padding: 0px;
+ }
+
#sidebar-settings h4:before {
content: url(../img/gear-fill.svg);
}
@@ -339,8 +347,6 @@ body {
position: absolute;
bottom: 0px;
width: 16.7em;
- padding-bottom: 0.3rem;
- margin-bottom:0px;
background-color: rgba(51, 51, 51, 1);
}
diff --git a/git-webui/src/share/git-webui/webui/js/git-webui.js b/git-webui/src/share/git-webui/webui/js/git-webui.js
index 7161e0d8..632c10f1 100644
--- a/git-webui/src/share/git-webui/webui/js/git-webui.js
+++ b/git-webui/src/share/git-webui/webui/js/git-webui.js
@@ -421,6 +421,9 @@ webui.SideBarView = function(mainView, noEventHandlers) {
if (id.indexOf("local-branches") > -1) {
// parses the output of git branch --verbose --verbose
var matches = /^\*?\s*([\w-\/]+)\s+([^\s]+)\s+(\[.*\])?.*/.exec(ref);
+ if (!matches) {
+ continue;
+ }
var branchInfo = {
"branch_name": matches[1],
"hash": matches[2],
From c8fffb9e0f7cb130b339185b779cb7bb71b965c5 Mon Sep 17 00:00:00 2001
From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com>
Date: Thu, 12 Sep 2024 13:53:46 -0400
Subject: [PATCH 11/12] fix: various pull event handler issues
---
CHANGELOG.md | 5 ++
.../Git/PullEventHandler/IncrementalLoad.cls | 18 +++--
cls/SourceControl/Git/Utils.cls | 62 +++++++++++++---
cls/_zpkg/isc/sc/git/Socket.cls | 74 ++++++++++---------
4 files changed, 109 insertions(+), 50 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0c6c52c3..29824901 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,12 +12,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Allow changing namespaces and IPM package context from web UI (#280)
- Support for editing repo from filesystem perspective via web application (#464)
- Support for downloading a VSCode workspace file from web UI
+- IncrementalLoad pull event handler will update the running production, if any (#473)
### Fixed
- Instance wide settings are placed in proper global (#444)
- Added support to switch branch in basic mode from menu (#451)
- Avoid delay/errors in loading interop JS when there is a URL prefix (e.g., instance name in multi-instance webserver configuration)
- Added proper JS escaping in sync output
+- Pull event handler will not fail when change set includes unmapped files (#453)
+- Pull event handler will attempt compile even if there are failures to load (#457)
+- Improved logging in preview and when errors occur via WebSocket commands (#467)
+- Fixed pull event handler handling of extremely long class names from diff (#467)
## [2.4.1] - 2024-08-02
diff --git a/cls/SourceControl/Git/PullEventHandler/IncrementalLoad.cls b/cls/SourceControl/Git/PullEventHandler/IncrementalLoad.cls
index 8dd64d3b..ae13af6f 100644
--- a/cls/SourceControl/Git/PullEventHandler/IncrementalLoad.cls
+++ b/cls/SourceControl/Git/PullEventHandler/IncrementalLoad.cls
@@ -9,7 +9,7 @@ Parameter DESCRIPTION = "Performs an incremental load and compile of all changes
Method OnPull() As %Status
{
- set loadSC = $$$OK
+ set sc = $$$OK
set nFiles = 0
for i=1:1:$get(..ModifiedFiles){
@@ -17,8 +17,8 @@ Method OnPull() As %Status
if ((internalName = "") && (..ModifiedFiles(i).changeType '= "D")) {
write !, ..ModifiedFiles(i).externalName, " was not imported into the database and will not be compiled. "
} elseif (..ModifiedFiles(i).changeType = "D") {
- set sc = ..DeleteFile(internalName)
- if sc {
+ set delSC = ..DeleteFile(internalName)
+ if delSC {
write !, ..ModifiedFiles(i).externalName, " was deleted."
} else {
write !, "WARNING: Deletion of ", ..ModifiedFiles(i).externalName, " failed."
@@ -26,8 +26,7 @@ Method OnPull() As %Status
} else {
set compilelist(internalName) = ""
set nFiles = nFiles + 1
- set loadSC = $$$ADDSC(loadSC,##class(SourceControl.Git.Utils).ImportItem(internalName, 1))
- $$$ThrowOnError(loadSC)
+ set sc = $$$ADDSC(sc,##class(SourceControl.Git.Utils).ImportItem(internalName, 1))
}
}
@@ -35,7 +34,13 @@ Method OnPull() As %Status
write !, "Nothing to compile."
quit $$$OK
}
- quit $system.OBJ.CompileList(.compilelist, "ck")
+ set sc = $$$ADDSC(sc,$system.OBJ.CompileList(.compilelist, "ck"))
+ if $$$comClassDefined("Ens.Director") && ##class(Ens.Director).IsProductionRunning() {
+ write !,"Updating production... "
+ set sc = $$$ADDSC(sc,##class(Ens.Director).UpdateProduction())
+ write "done."
+ }
+ quit sc
}
Method DeleteFile(item As %String) As %Status
@@ -71,4 +76,3 @@ Method DeleteFile(item As %String) As %Status
}
}
-
diff --git a/cls/SourceControl/Git/Utils.cls b/cls/SourceControl/Git/Utils.cls
index 94290b60..bd96f37e 100644
--- a/cls/SourceControl/Git/Utils.cls
+++ b/cls/SourceControl/Git/Utils.cls
@@ -546,14 +546,19 @@ ClassMethod GetCurrentBranch() As %String
ClassMethod Pull(remote As %String = "origin") As %Status
{
+ New %gitSCOutputFlag
+ Set %gitSCOutputFlag = 1
#define Force 1
do ##class(SourceControl.Git.Utils).RunGitCommandWithInput("branch",,.errStream,.outStream,"--show-current")
set branchName = outStream.ReadLine(outStream.Size)
write !, "Pulling from branch: ", branchName
kill errStream, outStream
set returnCode = ..RunGitWithArgs(.errStream, .outStream, "pull", remote, branchName)
-
- w !, "Pull ran with return code: " _ returnCode
+ write !
+ do outStream.OutputToDevice()
+ write !
+ do errStream.OutputToDevice()
+ write !, "Pull ran with return code: " _ returnCode
quit $$$OK
}
@@ -626,10 +631,13 @@ ClassMethod ExternalName(InternalName As %String, ByRef MappingExists As %Boolea
ClassMethod AddToServerSideSourceControl(InternalName As %String) As %Status
{
- #dim i as %Integer
+ #dim i as %Integer
#dim ec as %Status = $$$OK
for i = 1:1:$length(InternalName, ",") {
#dim item as %String = ..NormalizeExtension($piece(InternalName, ",", i))
+ if (item = "") {
+ continue
+ }
set @..#Storage@("items", item) = ""
#dim sc as %Status = ..ImportItem(item, 1)
if 'sc {
@@ -1791,12 +1799,16 @@ ClassMethod RunGitCommandWithInput(command As %String, inFile As %String = "", O
}
}
} elseif syncIrisWithCommand {
- do ..PrintStreams(errStream, outStream)
+ if '$data(%gitSCOutputFlag)#2 {
+ do ..PrintStreams(errStream, outStream)
+ }
set buffer = ##class(SourceControl.Git.Util.Buffer).%New()
do buffer.BeginCaptureOutput()
set st = ..SyncIrisWithRepoThroughCommand(.outStream)
set out = ##class(%Stream.GlobalCharacter).%New()
do buffer.EndCaptureOutput(.out)
+ do outStream.MoveToEnd()
+ do errStream.MoveToEnd()
if $$$ISOK(st) {
while 'out.AtEnd {
do outStream.WriteLine(out.ReadLine())
@@ -1836,11 +1848,31 @@ ClassMethod SyncIrisWithRepoThroughCommand(ByRef outStream) As %Status
}
} elseif (line [ "|") {
set externalName = $zstrip($piece(line,"|",1),"<>W")
- set modification = ##class(SourceControl.Git.Modification).%New()
- set modification.changeType = "C"
- set modification.internalName = ##class(SourceControl.Git.Utils).NameToInternalName(externalName,,0)
- set modification.externalName = externalName
- set files($i(files)) = modification
+ if $Extract(externalName,1,3) = "..." {
+ // For extremely long file names, git may truncate the path.
+ // Simplifying assumption: this is a class, because nothing else would have that long a name.
+ // In other cases, we'll just end up logging the invalid externalName.
+ if $Piece(externalName,".",*) = "cls" {
+ set possibleClasses = ..ExpandClasses(externalName)
+ set pointer = 0
+ while $ListNext(possibleClasses,pointer,class) {
+ set modification = ##class(SourceControl.Git.Modification).%New()
+ set modification.changeType = "C"
+ set modification.internalName = class_".CLS"
+ set modification.externalName = ..ExternalName(modification.internalName)
+ set files($i(files)) = modification
+ }
+ } else {
+ write !,"WARNING: unable to translate external name ",externalName
+ continue
+ }
+ } else {
+ set modification = ##class(SourceControl.Git.Modification).%New()
+ set modification.changeType = "C"
+ set modification.internalName = ##class(SourceControl.Git.Utils).NameToInternalName(externalName,,0)
+ set modification.externalName = externalName
+ set files($i(files)) = modification
+ }
}
}
@@ -1858,6 +1890,18 @@ ClassMethod SyncIrisWithRepoThroughCommand(ByRef outStream) As %Status
quit ##class(SourceControl.Git.PullEventHandler).ForModifications(.files)
}
+ClassMethod ExpandClasses(externalName As %String) As %List
+{
+ set internalName = $Piece(externalName,".",1,*-1)
+ set internalName = $Extract(internalName,4,*)
+ set internalName = $Translate(internalName,"/\%",".."_..PercentClassReplace())
+ &sql(select %DLIST(Name) into :classes from %Dictionary.ClassDefinition where Name like '%'||:internalName)
+ if (SQLCODE < 0) {
+ Throw ##class(%Exception.SQL).CreateFromSQLCODE(SQLCODE,%msg)
+ }
+ quit classes
+}
+
ClassMethod ParseDiffStream(stream As %Stream.Object, verbose As %Boolean = 1, Output files)
{
kill files
diff --git a/cls/_zpkg/isc/sc/git/Socket.cls b/cls/_zpkg/isc/sc/git/Socket.cls
index 0bc691f8..48c5e4ed 100644
--- a/cls/_zpkg/isc/sc/git/Socket.cls
+++ b/cls/_zpkg/isc/sc/git/Socket.cls
@@ -11,36 +11,40 @@ Property OriginalDevice;
ClassMethod Run()
{
- If %request.Get("method") = "preview" {
- set branchName = ##class(SourceControl.Git.Utils).GetCurrentBranch()
- do ##class(SourceControl.Git.Utils).RunGitWithArgs(.errStream, .outStream, "fetch")
- kill errStream, outStream
- do ##class(SourceControl.Git.Utils).RunGitWithArgs(.errStream, .outStream, "log", "HEAD..origin", "--name-status")
- do ##class(SourceControl.Git.Utils).PrintStreams(errStream, outStream)
- } ElseIf %request.Get("method") = "pull" {
- Do ##class(SourceControl.Git.API).Pull()
- } ElseIf %request.Get("method") = "init" {
- Do ##class(SourceControl.Git.Utils).Init()
+ If %request.Get("method") = "preview" {
+ Set branchName = ##class(SourceControl.Git.Utils).GetCurrentBranch()
+ Write !,"Current branch: ",branchName
+ Do ##class(SourceControl.Git.Utils).RunGitWithArgs(.errStream, .outStream, "fetch")
+ Kill errStream, outStream
+ Do ##class(SourceControl.Git.Utils).RunGitWithArgs(.errStream, .outStream, "log", "HEAD..origin", "--name-status")
+ Do ##class(SourceControl.Git.Utils).PrintStreams(errStream, outStream)
+ If (outStream.Size = 0) && (errStream.Size = 0) {
+ Write !,"Already up to date."
+ }
+ } ElseIf %request.Get("method") = "pull" {
+ Do ##class(SourceControl.Git.API).Pull()
+ } ElseIf %request.Get("method") = "init" {
+ Do ##class(SourceControl.Git.Utils).Init()
Write !,"Done."
- } ElseIf %request.Get("method") = "clone" {
- Set remote = %request.Get("remote")
- Do ##class(SourceControl.Git.Utils).Clone(remote)
+ } ElseIf %request.Get("method") = "clone" {
+ Set remote = %request.Get("remote")
+ Do ##class(SourceControl.Git.Utils).Clone(remote)
Write !,"Done."
- } ElseIf %request.Get("method") = "sshkeygen" {
- Do ##class(SourceControl.Git.Utils).GenerateSSHKeyPair()
+ } ElseIf %request.Get("method") = "sshkeygen" {
+ Do ##class(SourceControl.Git.Utils).GenerateSSHKeyPair()
Write !,"Done."
- } Else {
- Write !!,"Invalid method selected.",!!
- }
+ } Else {
+ Write !!,"Invalid method selected.",!!
+ }
}
Method OnPreServer() As %Status
{
- If '$System.Security.Check("%Development","USE") {
- Quit $$$ERROR($$$AccessDenied)
- }
+ If '$SYSTEM.Security.Check("%Development","USE") {
+ Quit $$$ERROR($$$AccessDenied)
+ }
If (%request.Get("$NAMESPACE") '= "") {
- Set $Namespace = %request.Get("$NAMESPACE")
+ Set $NAMESPACE = %request.Get("$NAMESPACE")
}
Quit $$$OK
}
@@ -56,9 +60,11 @@ Method Server() As %Status
// In subclasses: Do Something that produces output to the current device.
// It will be sent back to the client, Base64-encoded, over the web socket connection.
- Do ..Run()
+ Do ..Run()
} Catch e {
Do e.Log()
+ Write !,"An error occurred. More details can be found in the Application error log."
+ Write !,$SYSTEM.Status.GetErrorText(e.AsStatus())
Set tSC = e.AsStatus()
}
@@ -77,7 +83,7 @@ Method StartOutputCapture() [ ProcedureBlock = 0 ]
#dim tSC As %Status = $$$OK
#dim tRedirected As %Boolean = 0
Try {
- Set %server = $this
+ Set %server = $THIS
Set ..OriginallyRedirected = 0
Set ..OriginalMnemonic = ""
Set ..OriginalDevice = $IO
@@ -107,27 +113,27 @@ Method StartOutputCapture() [ ProcedureBlock = 0 ]
#; Public entry points for I/O redirection
wstr(s) Do write(s)
Quit
-wchr(a) Do write($char(a))
+wchr(a) Do write($CHAR(a))
Quit
wnl Do write($$$EOL)
Set $X = 0
Quit
wff Do wnl Quit
wtab(n) New tTab
- Set tTab = $J("",$S(n>$X:n-$X,1:0))
+ Set tTab = $JUSTIFY("",$SELECT(n>$X:n-$X,1:0))
Do write(tTab)
Quit
write(str)
// If there was an argumentless NEW, cache the output and leave it at that.
// This will be output next time there's a write with %server in scope.
- If '$IsObject($Get(%server)) {
- Set ^||OutputCapture.Cache($i(^||OutputCapture.Cache)) = str
+ If '$ISOBJECT($GET(%server)) {
+ Set ^||OutputCapture.Cache($INCREMENT(^||OutputCapture.Cache)) = str
Quit
}
// Restore previous I/O redirection settings.
New tOriginalDevice,i
- Set tOriginalDevice = $io
+ Set tOriginalDevice = $IO
If ##class(%Library.Device).ReDirectIO(0) {
Use tOriginalDevice
}
@@ -138,8 +144,8 @@ write(str)
Do ##class(%Library.Device).ReDirectIO(1)
}
- If $Data(^||OutputCapture.Cache) {
- For i=1:1:$Get(^||OutputCapture.Cache) {
+ If $DATA(^||OutputCapture.Cache) {
+ For i=1:1:$GET(^||OutputCapture.Cache) {
Do reallywrite(^||OutputCapture.Cache(i))
}
Kill ^||OutputCapture.Cache
@@ -155,7 +161,7 @@ write(str)
reallywrite(pString)
New tMsg
Set tMsg = {"content":(pString)} // This is handy because it handles escaping of newlines, etc.
- Do %server.Write($System.Encryption.Base64Encode(tMsg.%ToJSON()))
+ Do %server.Write($SYSTEM.Encryption.Base64Encode(tMsg.%ToJSON()))
Quit
rstr(len, time) Quit ""
rchr(time) Quit ""
@@ -179,7 +185,7 @@ Method EndOutputCapture()
Method SendJSON(pObject As %DynamicAbstractObject)
{
- Set tOriginalDevice = $io
+ Set tOriginalDevice = $IO
If ##class(%Library.Device).ReDirectIO(0) {
Use tOriginalDevice
}
@@ -189,7 +195,7 @@ Method SendJSON(pObject As %DynamicAbstractObject)
If ..OriginallyRedirected {
Do ##class(%Library.Device).ReDirectIO(1)
}
- Do ..Write($System.Encryption.Base64Encode(pObject.%ToJSON()))
+ Do ..Write($SYSTEM.Encryption.Base64Encode(pObject.%ToJSON()))
Do ##class(%Library.Device).ReDirectIO(1)
Use tOriginalDevice::("^"_$ZNAME)
}
From e1ca8533f3649c96d6a2addf72f9dee42b9cc7e7 Mon Sep 17 00:00:00 2001
From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com>
Date: Thu, 12 Sep 2024 16:55:50 -0400
Subject: [PATCH 12/12] Update CHANGELOG.md
Remote duplicated content
---
CHANGELOG.md | 2 --
1 file changed, 2 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f5cbc2a0..2e14cc25 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,8 +19,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Avoid delay/errors in loading interop JS when there is a URL prefix (e.g., instance name in multi-instance webserver configuration)
- Added proper JS escaping in sync output
- Added support to switch branch in basic mode from menu (#451)
-- Avoid delay/errors in loading interop JS when there is a URL prefix (e.g., instance name in multi-instance webserver configuration)
-- Added proper JS escaping in sync output
- Pull event handler will not fail when change set includes unmapped files (#453)
- Pull event handler will attempt compile even if there are failures to load (#457)
- Improved logging in preview and when errors occur via WebSocket commands (#467)