Skip to content

Commit caaad30

Browse files
committed
Merge branch 'main' into issue-545
2 parents 45875dc + f7666d8 commit caaad30

File tree

17 files changed

+452
-213
lines changed

17 files changed

+452
-213
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1515
- Added environment awareness in configuration, and showing of environment name in UI (#124)
1616
- Warning on sync page if other users have unstaged changes (#493)
1717
- 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)
1820

1921
### Fixed
2022
- Fixed display of other users' username in workspace view on Unix (#530)
@@ -30,6 +32,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3032
- Make sure more fetch calls prune the remote branches (#471)
3133
- Force export of item if it has been modified (#354)
3234
- Production configuration page no longer closes Sync/WebUI when operations there change the production (#542)
35+
- Remove leading/trailing spaces from input to Configure() (#356)
36+
- Fix branches with special characters not showing in GitUI (#523)
37+
- Fix filenames with spaces not showing correctly in workspace view (#551)
38+
- Removed inaccurate placeholder text for commit message in UI (#406)
39+
- Fixed regression that broke production conflict auto-resolve (#526)
40+
- Initialize repo in settings page now uses entered repo (#486)
41+
- Report error more clearly if you try to create a branch with an invalid name (#534)
42+
- Don't default to WINDOWS style paths (#357)
43+
- Fix errors when deleting non-existent files on import (#524)
44+
- Fix errors on commit when a file was added, never committed, then deleted from the repository (#481)
45+
- Fixed issue with saving multiple new no-folder mapping settings at the same time (#533)
3346
- Fixed sending OS error when git pull encounters error (#545)
3447

3548
## [2.6.0] - 2024-10-07

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ The same right click menus as in Studio live under "Server Source Control..." wh
4848
4949
Note: Studio has been deprecated. VSCode is the IDE recommended by InterSystems.
5050
51-
Add a file for tracking by right-clicking on it in the workspace/project view and choosing Git > Add.
51+
Add an existing file for tracking by right-clicking on it in the workspace/project view and choosing Git > Add.
5252
This same menu also has options to remove (stop tracking the file), discard changes (revert to the index), or commit changes.
5353
5454
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.

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/PullEventHandler/IncrementalLoad.cls

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -44,32 +44,45 @@ Method OnPull() As %Status
4444
}
4545

4646
Method DeleteFile(item As %String) As %Status
47-
{
48-
set sc = $$$OK
49-
set type = ##class(SourceControl.Git.Utils).Type(item)
50-
set name = ##class(SourceControl.Git.Utils).NameWithoutExtension(item)
51-
set deleted = 1
52-
if type = "prj" {
53-
set sc = $system.OBJ.DeleteProject(name)
54-
}elseif type = "cls" {
55-
set sc = $system.OBJ.Delete(item)
56-
}elseif $listfind($listbuild("mac","int","inc","bas","mvb","mvi"), type) > 0 {
57-
set sc = ##class(%Routine).Delete(item)
58-
}elseif type = "csp" {
59-
set sc = $System.CSP.DeletePage(item)
60-
}elseif ##class(SourceControl.Git.Utils).UserTypeCached(item) {
61-
set sc = ##class(%Library.RoutineMgr).Delete(item)
62-
} else {
63-
set deleted = 0
64-
}
65-
66-
if deleted && $$$ISOK(sc) {
67-
do ##class(SourceControl.Git.Utils).RemoveRoutineTSH(item)
68-
kill $$$TrackedItems(##class(SourceControl.Git.Utils).NormalizeExtension(item))
69-
} else {
70-
if +$system.Status.GetErrorCodes(sc) = $$$ClassDoesNotExist {
71-
// if something we wanted to delete is already deleted -- good!
47+
{
48+
try {
49+
set sc = $$$OK
50+
set type = ##class(SourceControl.Git.Utils).Type(item)
51+
set name = ##class(SourceControl.Git.Utils).NameWithoutExtension(item)
52+
set deleted = 1
53+
if type = "prj" {
54+
set sc = $system.OBJ.DeleteProject(name)
55+
}elseif type = "cls" {
56+
set sc = $system.OBJ.Delete(item)
57+
}elseif $listfind($listbuild("mac","int","inc","bas","mvb","mvi"), type) > 0 {
58+
set sc = ##class(%Routine).Delete(item)
59+
}elseif type = "csp" {
60+
set sc = $System.CSP.DeletePage(item)
61+
}elseif ##class(SourceControl.Git.Utils).UserTypeCached(item) {
62+
set sc = ##class(%Library.RoutineMgr).Delete(item)
63+
} else {
64+
set deleted = 0
65+
}
66+
67+
if deleted && $$$ISOK(sc) {
68+
do ##class(SourceControl.Git.Utils).RemoveRoutineTSH(item)
69+
kill $$$TrackedItems(##class(SourceControl.Git.Utils).NormalizeExtension(item))
70+
} else {
71+
if +$system.Status.GetErrorCodes(sc) = $$$ClassDoesNotExist {
72+
// if something we wanted to delete is already deleted -- good!
73+
set sc = $$$OK
74+
}
75+
}
76+
} catch e {
77+
set filename = ##class(SourceControl.Git.Utils).FullExternalName(item)
78+
if '##class(%File).Exists(filename) {
79+
do ##class(SourceControl.Git.Utils).RemoveRoutineTSH(item)
80+
// file doesn't exist anymore despite error -- should be ok
7281
set sc = $$$OK
82+
} else {
83+
// Item still exists and was not deleted -- bad
84+
set sc = e.AsStatus()
85+
do e.Log()
7386
}
7487
}
7588
return sc

cls/SourceControl/Git/Settings.cls

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ ClassMethod Configure() As %Boolean [ CodeMode = objectgenerator ]
180180
do %code.WriteLine(" set valid = 0")
181181
do %code.WriteLine(" while ('valid) {")
182182
do %code.WriteLine(" set response = ##class(%Library.Prompt).GetString("_promptQuoted_",.value,,,,"_defaultPromptFlag_")")
183+
do %code.WriteLine(" set value = $zstrip(value,""<>W"")")
183184
do %code.WriteLine(" set status = inst.ConfigureBinPath(.value)")
184185
do %code.WriteLine(" if (status) { set valid = 1 }")
185186
do %code.WriteLine(" }")
@@ -206,6 +207,7 @@ ClassMethod Configure() As %Boolean [ CodeMode = objectgenerator ]
206207
do %code.WriteLine(" set response = ##class(%Library.Prompt).GetString("_promptQuoted_",.value,,,,"_defaultPromptFlag_")")
207208
}
208209
do %code.WriteLine(" if response '= $$$SuccessResponse { quit 0 }")
210+
do %code.WriteLine(" set value = $zstrip(value,""<>W"")")
209211
do %code.WriteLine(" set inst."_property_" = value")
210212

211213
}
Lines changed: 3 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -1,156 +1,11 @@
11
Include (%occInclude, %occErrors, %occKeyword, %occReference, %occSAX)
22

3-
Class SourceControl.Git.Util.ProductionConflictResolver Extends %RegisteredObject
3+
Class SourceControl.Git.Util.ProductionConflictResolver Extends SourceControl.Git.Util.XMLConflictResolver
44
{
55

6-
Property logStream As %Stream.Object [ Private ];
6+
Parameter ExpectedConflictTag = "</Item>";
77

8-
Property productionFile As %String [ Private ];
8+
Parameter OutputIndent = " ";
99

10-
Property productionClassname As %Dictionary.CacheClassname [ Private ];
11-
12-
Property errorStatus As %Status [ InitialExpression = 1, Private ];
13-
14-
/// API property: whether or not the conflict was resolved
15-
Property resolved As %Boolean [ InitialExpression = 0 ];
16-
17-
/// API property: error message if resolved is false
18-
Property errorMessage As %String [ Calculated ];
19-
20-
Method errorMessageGet() As %String
21-
{
22-
If $$$ISERR(..errorStatus) {
23-
Do $System.Status.DecomposeStatus(..errorStatus,.components)
24-
If $Get(components(1,"code")) = $$$GeneralError {
25-
Quit $Get(components(1,"param",1))
26-
} Else {
27-
Set ex = ##class(%Exception.StatusException).CreateFromStatus(..errorStatus)
28-
Do ex.Log()
29-
Quit "an internal error occurred and has been logged."
30-
}
31-
} Else {
32-
Quit ""
33-
}
34-
}
35-
36-
ClassMethod FromLog(pOutStream As %Stream.Object) As SourceControl.Git.Util.ProductionConflictResolver
37-
{
38-
Set inst = ..%New()
39-
Try {
40-
Set inst.logStream = pOutStream
41-
Do inst.ConsumeStream()
42-
Do inst.Resolve()
43-
} Catch e {
44-
Set inst.resolved = 0
45-
Set inst.errorStatus = e.AsStatus()
46-
}
47-
Do inst.logStream.Rewind() // Finally
48-
Quit inst
49-
}
50-
51-
Method ConsumeStream() [ Private ]
52-
{
53-
Do ..logStream.Rewind()
54-
Do ..logStream.ReadLine()
55-
Set productionLine = ..logStream.ReadLine()
56-
Set ..productionFile = $Piece(productionLine,"Merge conflict in ",2)
57-
If ..productionFile = "" {
58-
$$$ThrowStatus($$$ERROR($$$GeneralError,"Message did not reflect merge conflict on a single file."))
59-
}
60-
If '..logStream.AtEnd {
61-
$$$ThrowStatus($$$ERROR($$$GeneralError,"Multiple files had merge conflicts; cannot resolve intelligently."))
62-
}
63-
Set internalName = ##class(SourceControl.Git.Utils).NameToInternalName(..productionFile)
64-
If ($Piece(internalName,".",*) '= "CLS") {
65-
$$$ThrowStatus($$$ERROR($$$GeneralError,"File with conflict is not a class."))
66-
}
67-
Set ..productionClassname = $Piece(internalName,".",1,*-1)
68-
If '($$$comClassDefined(..productionClassname) && $ClassMethod(..productionClassname,"%Extends","Ens.Production")) {
69-
$$$ThrowStatus($$$ERROR($$$GeneralError,"File with conflict is not an interoperability production."))
70-
}
71-
}
72-
73-
Method Resolve() [ Private ]
74-
{
75-
Set filePath = ##class(SourceControl.Git.Utils).TempFolder()_..productionFile
76-
Set file = ##class(%Stream.FileCharacter).%OpenId(filePath,,.sc)
77-
$$$ThrowOnError(sc)
78-
79-
Do ..ResolveStream(file) // Throws exception on failure
80-
81-
$$$ThrowOnError(##class(SourceControl.Git.Utils).ImportItem(..productionClassname_".CLS",1))
82-
$$$ThrowOnError($System.OBJ.Compile(..productionClassname,"ck"))
83-
84-
// TODO: if we add multiple resolvers, move this to the end.
85-
set code = ##class(SourceControl.Git.Utils).RunGitWithArgs(.errStream, .outStream, "add", ..productionFile)
86-
if (code '= 0) {
87-
$$$ThrowStatus($$$ERROR($$$GeneralError,"git add reported failure"))
88-
}
89-
set code = ##class(SourceControl.Git.Utils).RunGitWithArgs(.errStream, .outStream, "commit", "--no-edit")
90-
if (code '= 0) {
91-
$$$ThrowStatus($$$ERROR($$$GeneralError,"git commit reported failure"))
92-
}
93-
94-
set code = ##class(SourceControl.Git.Utils).RunGitWithArgs(.errStream, .outStream, "rebase", "--continue")
95-
if (code '= 0) {
96-
$$$ThrowStatus($$$ERROR($$$GeneralError,"git rebase --continue reported failure"))
97-
}
98-
99-
set ..resolved = 1
100-
}
101-
102-
/// Non-private to support unit testing
103-
ClassMethod ResolveStream(stream As %Stream.Object)
104-
{
105-
// File may have:
106-
/*
107-
<<<<<<< HEAD
108-
<Item Name="Demo7" Category="" ClassName="EnsLib.CloudStorage.BusinessOperation" PoolSize="1" Enabled="false" Foreground="false" Comment="" LogTraceEvents="false" Schedule="">
109-
=======
110-
<Item Name="Demo5" Category="" ClassName="EnsLib.AmazonCloudWatch.MetricAlarmOperation" PoolSize="1" Enabled="false" Foreground="false" Comment="" LogTraceEvents="false" Schedule="">
111-
>>>>>>> 607d1f6 (modified src/HCC/Connect/Production.cls add Demo5)
112-
</Item>
113-
*/
114-
115-
// If:
116-
// * We have one such marker (<<<<<<< / ======= / >>>>>>>)
117-
// * The line after >>>>>> is "</Item>"
118-
// Then:
119-
// * We can replace ======= with "</Item>"
120-
121-
Set copy = ##class(%Stream.TmpCharacter).%New()
122-
Set markerCount = 0
123-
Set postCloseMarker = 0
124-
While 'stream.AtEnd {
125-
Set line = stream.ReadLine()
126-
Set start = $Extract(line,1,7)
127-
If start = "<<<<<<<" {
128-
Set markerCount = markerCount + 1
129-
Continue
130-
} ElseIf (start = ">>>>>>>") {
131-
Set postCloseMarker = 1
132-
Continue
133-
} ElseIf (start = "=======") {
134-
Do copy.WriteLine(" </Item>")
135-
Continue
136-
} ElseIf postCloseMarker {
137-
If $ZStrip(line,"<>W") '= "</Item>" {
138-
$$$ThrowStatus($$$ERROR($$$GeneralError,"The type of conflict encountered is not handled; user must resolve manually."))
139-
}
140-
Set postCloseMarker = 0
141-
}
142-
Do copy.WriteLine(line)
143-
}
144-
145-
If markerCount > 1 {
146-
$$$ThrowStatus($$$ERROR($$$GeneralError,"Multiple conflicts found, cannot resolve automatically."))
147-
} ElseIf markerCount = 0 {
148-
$$$ThrowStatus($$$ERROR($$$GeneralError,"No conflict markers found in file"))
149-
}
150-
151-
$$$ThrowOnError(stream.CopyFromAndSave(copy))
152-
153-
Quit 1
15410
}
15511

156-
}

0 commit comments

Comments
 (0)