From ca689d4260ad4adfba5c3c90edc177e8da2363fa Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Sat, 15 Oct 2022 07:59:31 +0200 Subject: [PATCH 1/4] add support for external fetch and push via OSProcess --- .../instance/externalGitDo.showText..st | 12 ++++++++++++ .../instance/externalPush.toRemote..st | 4 ++++ .../instance/fetchAllExternalFrom..st | 6 ++++++ .../instance/fetchFromAll..st | 4 +++- .../instance/push.toRemote..st | 4 +++- .../methodProperties.json | 7 +++++-- .../class/externalFetchAndPush..st | 3 +++ .../class/externalFetchAndPush.st | 5 +++++ .../GitFeatureFlags.class/methodProperties.json | 2 ++ .../GitFeatureFlags.class/properties.json | 1 + 10 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 src/FileSystem-Git.package/FileSystemGitRepository.class/instance/externalGitDo.showText..st create mode 100644 src/FileSystem-Git.package/FileSystemGitRepository.class/instance/externalPush.toRemote..st create mode 100644 src/FileSystem-Git.package/FileSystemGitRepository.class/instance/fetchAllExternalFrom..st create mode 100644 src/FileSystem-Git.package/GitFeatureFlags.class/class/externalFetchAndPush..st create mode 100644 src/FileSystem-Git.package/GitFeatureFlags.class/class/externalFetchAndPush.st diff --git a/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/externalGitDo.showText..st b/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/externalGitDo.showText..st new file mode 100644 index 000000000..b3997d1b9 --- /dev/null +++ b/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/externalGitDo.showText..st @@ -0,0 +1,12 @@ +git porcelain +externalGitDo: aCommandLineSuffix showText: aBoolean + (Smalltalk classNamed: #OSProcess) + ifNotNil: [:osProcess | | pipeline err out | + pipeline := osProcess evaluate: ('git -C {1} {2}' format: {repository workingDir. aCommandLineSuffix}). + out := pipeline upToEndOfFile. + err := pipeline errorUpToEndOfFile. + pipeline waitForAllToComplete. + pipeline last exitCode = 0 + ifFalse: [self notify: out, String cr, err] + ifTrue: [aBoolean ifTrue: [self inform: out, err] ifFalse: [Transcript showln: out, err]]] + ifNil: [self error: 'For external commands, OSProcess must be installed'] \ No newline at end of file diff --git a/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/externalPush.toRemote..st b/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/externalPush.toRemote..st new file mode 100644 index 000000000..09f448145 --- /dev/null +++ b/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/externalPush.toRemote..st @@ -0,0 +1,4 @@ +git porcelain +externalPush: aCollectionOfBranchNamesAndAssociations toRemote: remoteName + aCollectionOfBranchNamesAndAssociations do: [:branch | + self externalGitDo: ('push {1} {2}' format: {remoteName. branch value}) showText: true] \ No newline at end of file diff --git a/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/fetchAllExternalFrom..st b/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/fetchAllExternalFrom..st new file mode 100644 index 000000000..3eb97f833 --- /dev/null +++ b/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/fetchAllExternalFrom..st @@ -0,0 +1,6 @@ +git porcelain +fetchAllExternalFrom: aRemoteName + | remote | + remote := self unitOfWork remoteNamed: aRemoteName. + remote ifNil: [(GitRemoteUndefined remote: remote) signal: 'No URL configured.']. + self externalGitDo: ('pull {1}' format: {aRemoteName}) showText: false \ No newline at end of file diff --git a/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/fetchFromAll..st b/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/fetchFromAll..st index 13b0d50ad..2a58482d1 100644 --- a/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/fetchFromAll..st +++ b/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/fetchFromAll..st @@ -1,3 +1,5 @@ git porcelain fetchFromAll: aCollectionOfRemoteNames - aCollectionOfRemoteNames do: [:each | self fetchFrom: each]. \ No newline at end of file + GitFeatureFlags externalFetchAndPush + ifTrue: [aCollectionOfRemoteNames do: [:each | self fetchAllExternalFrom: each]] + ifFalse: [aCollectionOfRemoteNames do: [:each | self fetchFrom: each]] \ No newline at end of file diff --git a/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/push.toRemote..st b/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/push.toRemote..st index 856033672..22021bfb5 100644 --- a/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/push.toRemote..st +++ b/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/push.toRemote..st @@ -2,4 +2,6 @@ git porcelain push: aCollectionOfBranchNamesAndAssociations toRemote: remoteName "self push: { 'master' } toRemote: 'origin'. self push: { 'branch' -> 'remoteBranchName' } toRemote: 'origin'" - ^ self pushToRemote: remoteName update: aCollectionOfBranchNamesAndAssociations deleteRemoteBranches: Array empty \ No newline at end of file + GitFeatureFlags externalFetchAndPush + ifTrue: [self externalPush: aCollectionOfBranchNamesAndAssociations toRemote: remoteName] + ifFalse: [self pushToRemote: remoteName update: aCollectionOfBranchNamesAndAssociations deleteRemoteBranches: Array empty] \ No newline at end of file diff --git a/src/FileSystem-Git.package/FileSystemGitRepository.class/methodProperties.json b/src/FileSystem-Git.package/FileSystemGitRepository.class/methodProperties.json index 28bee1fae..acea0b78e 100644 --- a/src/FileSystem-Git.package/FileSystemGitRepository.class/methodProperties.json +++ b/src/FileSystem-Git.package/FileSystemGitRepository.class/methodProperties.json @@ -10,8 +10,11 @@ "commitNamed:" : "jr 8/13/2020 23:08", "createBranchNamed:at:" : "jr 3/4/2020 00:47", "expandRemoteRef:" : "pre 6/15/2018 16:04", + "externalGitDo:showText:" : "tobe 10/15/2022 07:49", + "externalPush:toRemote:" : "tobe 10/15/2022 07:45", + "fetchAllExternalFrom:" : "tobe 10/15/2022 07:52", "fetchFrom:" : "jr 5/14/2021 22:08", - "fetchFromAll:" : "jr 4/12/2017 11:26", + "fetchFromAll:" : "tobe 10/15/2022 07:55", "filesystemOn:" : "CamilloBruni 8/30/2012 14:06", "flushCaches" : "jr 7/2/2017 19:12", "gitStoreOn:" : "CamilloBruni 9/2/2012 12:33", @@ -19,7 +22,7 @@ "headReference" : "jr 3/4/2020 00:47", "initializeOn:" : "MaxLeske 7/23/2010 09:59", "orphanedHead" : "jr 1/29/2017 22:52", - "push:toRemote:" : "jr 1/2/2017 10:20", + "push:toRemote:" : "tobe 10/15/2022 07:38", "pushToRemote:deleteRemoteBranches:" : "jr 1/2/2017 10:18", "pushToRemote:update:deleteRemoteBranches:" : "jr 7/23/2020 00:43", "pushToUpstreamBranchOf:ifNone:" : "jr 3/4/2020 00:49", diff --git a/src/FileSystem-Git.package/GitFeatureFlags.class/class/externalFetchAndPush..st b/src/FileSystem-Git.package/GitFeatureFlags.class/class/externalFetchAndPush..st new file mode 100644 index 000000000..05a30839d --- /dev/null +++ b/src/FileSystem-Git.package/GitFeatureFlags.class/class/externalFetchAndPush..st @@ -0,0 +1,3 @@ +accessing +externalFetchAndPush: aBoolean + ExternalFetchAndPush := aBoolean \ No newline at end of file diff --git a/src/FileSystem-Git.package/GitFeatureFlags.class/class/externalFetchAndPush.st b/src/FileSystem-Git.package/GitFeatureFlags.class/class/externalFetchAndPush.st new file mode 100644 index 000000000..b0ac51b66 --- /dev/null +++ b/src/FileSystem-Git.package/GitFeatureFlags.class/class/externalFetchAndPush.st @@ -0,0 +1,5 @@ +accessing +externalFetchAndPush + + + ^ ExternalFetchAndPush ifNil: [false] \ No newline at end of file diff --git a/src/FileSystem-Git.package/GitFeatureFlags.class/methodProperties.json b/src/FileSystem-Git.package/GitFeatureFlags.class/methodProperties.json index 36b0a5742..cd2dfb705 100644 --- a/src/FileSystem-Git.package/GitFeatureFlags.class/methodProperties.json +++ b/src/FileSystem-Git.package/GitFeatureFlags.class/methodProperties.json @@ -3,6 +3,8 @@ "evictFromObjectCache" : "jr 8/10/2020 23:42", "evictFromObjectCache:" : "jr 4/20/2020 21:59", "evictFromObjectCacheForTests:" : "jr 4/20/2020 23:33", + "externalFetchAndPush" : "tobe 10/15/2022 07:17", + "externalFetchAndPush:" : "tobe 10/15/2022 07:17", "warnAboutUseOfDeprecatedMethods" : "jr 9/21/2020 23:10", "warnAboutUseOfDeprecatedMethods:" : "jr 4/17/2020 11:49" }, "instance" : { diff --git a/src/FileSystem-Git.package/GitFeatureFlags.class/properties.json b/src/FileSystem-Git.package/GitFeatureFlags.class/properties.json index 29838e4a4..eca3b5f21 100644 --- a/src/FileSystem-Git.package/GitFeatureFlags.class/properties.json +++ b/src/FileSystem-Git.package/GitFeatureFlags.class/properties.json @@ -4,6 +4,7 @@ ], "classvars" : [ "EvictFromObjectCache", + "ExternalFetchAndPush", "UseUnitOfWorkInterface", "WarnAboutUseOfDeprecatedMethods" ], "commentStamp" : "", From 2529a475190f5dba96bc595e2c85a87522e9dd43 Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Sat, 15 Oct 2022 08:05:06 +0200 Subject: [PATCH 2/4] if we allow external pushes, all remote types are supported --- .../SquitBrowser.class/instance/chooseableRemoteNamesFrom..st | 1 + src/Squit.package/SquitBrowser.class/methodProperties.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Squit.package/SquitBrowser.class/instance/chooseableRemoteNamesFrom..st b/src/Squit.package/SquitBrowser.class/instance/chooseableRemoteNamesFrom..st index 1c507733c..90b8054c5 100644 --- a/src/Squit.package/SquitBrowser.class/instance/chooseableRemoteNamesFrom..st +++ b/src/Squit.package/SquitBrowser.class/instance/chooseableRemoteNamesFrom..st @@ -1,4 +1,5 @@ user requests chooseableRemoteNamesFrom: gitRepository + GitFeatureFlags externalFetchAndPush ifTrue: [^ gitRepository remoteNames]. ^ gitRepository remoteNames select: [:each | (gitRepository remoteUrl: each) beginsWith: 'http'] \ No newline at end of file diff --git a/src/Squit.package/SquitBrowser.class/methodProperties.json b/src/Squit.package/SquitBrowser.class/methodProperties.json index 301065b9f..710143f76 100644 --- a/src/Squit.package/SquitBrowser.class/methodProperties.json +++ b/src/Squit.package/SquitBrowser.class/methodProperties.json @@ -102,7 +102,7 @@ "cherryPick:toWorkingCopy:" : "ct 9/15/2022 19:15", "chooseOneRemoteFrom:" : "jr 7/24/2020 11:33", "chooseRemotesFrom:" : "jr 8/3/2020 01:07", - "chooseableRemoteNamesFrom:" : "jr 4/26/2017 13:38", + "chooseableRemoteNamesFrom:" : "tobe 10/15/2022 08:03", "clone" : "jr 12/23/2021 18:24", "commitList" : "jr 7/2/2022 22:31", "commitListKey:from:" : "fn 4/12/2017 10:52", From ca57611e7328d5c145b7d2f17ba8df8b9a972f9d Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Sat, 15 Oct 2022 03:44:55 -0700 Subject: [PATCH 3/4] fix invoking command on windows --- .../instance/externalCommand..st | 20 +++++++++++++++++++ .../instance/externalGitDo.showText..st | 17 ++++++---------- .../instance/externalPush.toRemote..st | 2 +- .../instance/fetchAllExternalFrom..st | 4 ++-- .../methodProperties.json | 5 +++-- 5 files changed, 32 insertions(+), 16 deletions(-) create mode 100644 src/FileSystem-Git.package/FileSystemGitRepository.class/instance/externalCommand..st diff --git a/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/externalCommand..st b/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/externalCommand..st new file mode 100644 index 000000000..4e252adf1 --- /dev/null +++ b/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/externalCommand..st @@ -0,0 +1,20 @@ +git porcelain - external +externalCommand: aString + ^ (Smalltalk classNamed: #OSProcess) + ifNotNil: [:osProcess | | pipeline err out | + osProcess isWindows + ifTrue: [ | tmpFile output process | + " on windows, the osvm does not support reading stdout/stderr. as a workaround, we put the output into a file that we delete right after reading it. note that we place the file into FileDirectory default because it is likely that we can read that one (is also the place where we are saving the image to) " + tmpFile := (FileDirectory default / (UUID new asString, '.txt')) fullName. + output := [ + process := OSProcess waitForCommand: ('cmd.exe /c "{1} > {2} 2>&1"' format: {aString copyReplaceAll: '"' with: '\"'. tmpFile}). + FileStream readOnlyFileNamed: tmpFile do: [:s | s contents] + ] ensure: [FileDirectory deleteFilePath: tmpFile]. + {process exitStatus = 0. output}] + ifFalse: [ + pipeline := osProcess evaluate: aString. + out := pipeline upToEndOfFile. + err := pipeline errorUpToEndOfFile. + pipeline waitForAllToComplete. + {pipeline last exitCode = 0. out, err}]] + ifNil: [self error: 'For external commands, OSProcess must be installed'] \ No newline at end of file diff --git a/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/externalGitDo.showText..st b/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/externalGitDo.showText..st index b3997d1b9..fd3016495 100644 --- a/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/externalGitDo.showText..st +++ b/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/externalGitDo.showText..st @@ -1,12 +1,7 @@ -git porcelain +git porcelain - external externalGitDo: aCommandLineSuffix showText: aBoolean - (Smalltalk classNamed: #OSProcess) - ifNotNil: [:osProcess | | pipeline err out | - pipeline := osProcess evaluate: ('git -C {1} {2}' format: {repository workingDir. aCommandLineSuffix}). - out := pipeline upToEndOfFile. - err := pipeline errorUpToEndOfFile. - pipeline waitForAllToComplete. - pipeline last exitCode = 0 - ifFalse: [self notify: out, String cr, err] - ifTrue: [aBoolean ifTrue: [self inform: out, err] ifFalse: [Transcript showln: out, err]]] - ifNil: [self error: 'For external commands, OSProcess must be installed'] \ No newline at end of file + | res | + res := self externalCommand: ('git -C {1} {2}' format: {repository workingDir. aCommandLineSuffix}). + res first + ifFalse: [self error: res second] + ifTrue: [aBoolean ifTrue: [self inform: res second] ifFalse: [Transcript showln: res second]] \ No newline at end of file diff --git a/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/externalPush.toRemote..st b/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/externalPush.toRemote..st index 09f448145..a67499b6b 100644 --- a/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/externalPush.toRemote..st +++ b/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/externalPush.toRemote..st @@ -1,4 +1,4 @@ -git porcelain +git porcelain - external externalPush: aCollectionOfBranchNamesAndAssociations toRemote: remoteName aCollectionOfBranchNamesAndAssociations do: [:branch | self externalGitDo: ('push {1} {2}' format: {remoteName. branch value}) showText: true] \ No newline at end of file diff --git a/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/fetchAllExternalFrom..st b/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/fetchAllExternalFrom..st index 3eb97f833..720f56473 100644 --- a/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/fetchAllExternalFrom..st +++ b/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/fetchAllExternalFrom..st @@ -1,6 +1,6 @@ -git porcelain +git porcelain - external fetchAllExternalFrom: aRemoteName | remote | remote := self unitOfWork remoteNamed: aRemoteName. remote ifNil: [(GitRemoteUndefined remote: remote) signal: 'No URL configured.']. - self externalGitDo: ('pull {1}' format: {aRemoteName}) showText: false \ No newline at end of file + self externalGitDo: ('fetch {1}' format: {aRemoteName}) showText: false \ No newline at end of file diff --git a/src/FileSystem-Git.package/FileSystemGitRepository.class/methodProperties.json b/src/FileSystem-Git.package/FileSystemGitRepository.class/methodProperties.json index acea0b78e..60bb649b6 100644 --- a/src/FileSystem-Git.package/FileSystemGitRepository.class/methodProperties.json +++ b/src/FileSystem-Git.package/FileSystemGitRepository.class/methodProperties.json @@ -10,9 +10,10 @@ "commitNamed:" : "jr 8/13/2020 23:08", "createBranchNamed:at:" : "jr 3/4/2020 00:47", "expandRemoteRef:" : "pre 6/15/2018 16:04", - "externalGitDo:showText:" : "tobe 10/15/2022 07:49", + "externalCommand:" : "tobe 10/15/2022 03:44", + "externalGitDo:showText:" : "tobe 10/15/2022 03:15", "externalPush:toRemote:" : "tobe 10/15/2022 07:45", - "fetchAllExternalFrom:" : "tobe 10/15/2022 07:52", + "fetchAllExternalFrom:" : "tobe 10/15/2022 03:42", "fetchFrom:" : "jr 5/14/2021 22:08", "fetchFromAll:" : "tobe 10/15/2022 07:55", "filesystemOn:" : "CamilloBruni 8/30/2012 14:06", From f9c2cbfb1e4155bee485a41d0ec28053a1b40b0e Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Sat, 15 Oct 2022 14:35:41 +0200 Subject: [PATCH 4/4] escape spaces in path to working dir (thanks @LinqLover) --- .../instance/externalGitDo.showText..st | 2 +- .../FileSystemGitRepository.class/methodProperties.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/externalGitDo.showText..st b/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/externalGitDo.showText..st index fd3016495..710b3b068 100644 --- a/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/externalGitDo.showText..st +++ b/src/FileSystem-Git.package/FileSystemGitRepository.class/instance/externalGitDo.showText..st @@ -1,7 +1,7 @@ git porcelain - external externalGitDo: aCommandLineSuffix showText: aBoolean | res | - res := self externalCommand: ('git -C {1} {2}' format: {repository workingDir. aCommandLineSuffix}). + res := self externalCommand: ('git -C {1} {2}' format: {repository workingDir pathName copyReplaceAll: ' ' with: '\ '. aCommandLineSuffix}). res first ifFalse: [self error: res second] ifTrue: [aBoolean ifTrue: [self inform: res second] ifFalse: [Transcript showln: res second]] \ No newline at end of file diff --git a/src/FileSystem-Git.package/FileSystemGitRepository.class/methodProperties.json b/src/FileSystem-Git.package/FileSystemGitRepository.class/methodProperties.json index 60bb649b6..b1c2bbdee 100644 --- a/src/FileSystem-Git.package/FileSystemGitRepository.class/methodProperties.json +++ b/src/FileSystem-Git.package/FileSystemGitRepository.class/methodProperties.json @@ -11,7 +11,7 @@ "createBranchNamed:at:" : "jr 3/4/2020 00:47", "expandRemoteRef:" : "pre 6/15/2018 16:04", "externalCommand:" : "tobe 10/15/2022 03:44", - "externalGitDo:showText:" : "tobe 10/15/2022 03:15", + "externalGitDo:showText:" : "tobe 10/15/2022 14:35", "externalPush:toRemote:" : "tobe 10/15/2022 07:45", "fetchAllExternalFrom:" : "tobe 10/15/2022 03:42", "fetchFrom:" : "jr 5/14/2021 22:08",