Starting multiOS support for binary files.

This commit is contained in:
Offray 2024-04-29 17:46:22 -05:00
parent 24ed0af7f5
commit 8d9f42d8e1
10 changed files with 406 additions and 399 deletions

View File

@ -1,20 +1,20 @@
Class { Class {
#name : #Brew, #name : #Brew,
#superclass : #Object, #superclass : #Object,
#category : #ExoRepo #category : #ExoRepo
} }
{ #category : #accessing } { #category : #accessing }
Brew class >> install [ Brew class >> install [
"This is a preliminary starting installation script that is not working. "This is a preliminary starting installation script that is not working.
Dependencies and sudo access are not managed here. Dependencies and sudo access are not managed here.
For example, doing 'sudo -S base-devel' on Arch based systems or For example, doing 'sudo -S base-devel' on Arch based systems or
'brew intall gcc' is yet not managed here." 'brew intall gcc' is yet not managed here."
Smalltalk os isWindows ifTrue: [ ^ nil ]. Smalltalk os isWindows ifTrue: [ ^ nil ].
OSSUnixSubprocess new OSSUnixSubprocess new
shellCommand: '/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"'; shellCommand: '/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"';
redirectStdout; redirectStdout;
runAndWaitOnExitDo: [ :command :outString | runAndWaitOnExitDo: [ :command :outString |
^ outString ^ outString
]. ].
] ]

View File

@ -1,116 +1,123 @@
Class { Class {
#name : #ExoRepo, #name : #ExoRepo,
#superclass : #Object, #superclass : #Object,
#instVars : [ #instVars : [
'repository' 'repository'
], ],
#category : #ExoRepo #category : #ExoRepo
} }
{ #category : #accessing } { #category : #accessing }
ExoRepo class >> index [ ExoRepo class >> index [
"I list a set of external recommended repositories from the Grafoscopio community, in installation order." "I list a set of external recommended repositories from the Grafoscopio community, in installation order."
| reposIndex repositoryAddresses users | | reposIndex repositoryAddresses users |
users := #('Offray' 'mutabiT' 'ruidajo' ). users := #('Offray' 'mutabiT' 'ruidajo' ).
reposIndex := OrderedCollection new. reposIndex := OrderedCollection new.
repositoryAddresses := users do: [:user | repositoryAddresses := users do: [:user |
reposIndex add: reposIndex add:
((STONJSON fromString:('https://code.sustrato.red/api/v1/users/', user, '/repos') asZnUrl retrieveContents) collect: [:repo | ((STONJSON fromString:('https://code.sustrato.red/api/v1/users/', user, '/repos') asZnUrl retrieveContents) collect: [:repo |
(repo at: 'name') -> (repo at: 'html_url')])]. (repo at: 'name') -> (repo at: 'html_url')])].
^ (reposIndex flatCollect: [:i | i]) asDictionary ^ (reposIndex flatCollect: [:i | i]) asDictionary
] ]
{ #category : #accessing } { #category : #accessing }
ExoRepo class >> install: shortNameString [ ExoRepo class >> install: shortNameString [
| repo exoRepo | | repo exoRepo |
[repo := self index at: shortNameString] [repo := self index at: shortNameString]
onErrorDo: [:err | UIManager default inform: 'No repository named: ', shortNameString, '. onErrorDo: [:err | UIManager default inform: 'No repository named: ', shortNameString, '.
Please run ExoRepo index Please run ExoRepo index
to list know repositories or load your own repository with: to list know repositories or load your own repository with:
ExoRepo new ExoRepo new
repository: {repositoryAddres}; repository: {repositoryAddres};
load. load.
replacing {repositoryAddres} with a Git public repository'.^ {self new. err}]. replacing {repositoryAddres} with a Git public repository'.^ {self new. err}].
exoRepo := self new repository: repo. exoRepo := self new repository: repo.
(IceRepositoryCreator new (IceRepositoryCreator new
location: exoRepo local; location: exoRepo local;
remote: (IceGitRemote url: repo); remote: (IceGitRemote url: repo);
createRepository) register. createRepository) register.
^ exoRepo load ^ exoRepo load
] ]
{ #category : #accessing } { #category : #accessing }
ExoRepo >> load [ ExoRepo class >> userDataFolder [
"I load the configuration of this package using a external Gitea repository." Smalltalk os isWindows
ifTrue: [ ^ FileLocator home / 'AppData' / 'Local' ]
"While more Git independient providers are implemented in Monticello, I will ifFalse: [ ^ FileLocator userData ].
use Iceberg to download the repository and load it from a local directory" ]
| localRepo repoName count | { #category : #accessing }
repoName := self repositoryName. ExoRepo >> load [
self local exists "I load the configuration of this package using a external Gitea repository."
ifFalse: [ (IceRepositoryCreator new
location: self local; "While more Git independient providers are implemented in Monticello, I will
remote: (IceGitRemote url: self repository greaseString ", '.git'"); use Iceberg to download the repository and load it from a local directory"
createRepository) register ].
localRepo := 'gitlocal://' , self local fullName. | localRepo repoName count |
count := 1. repoName := self repositoryName.
[ true ] self local exists
whileTrue: [ [ ^ Metacello new ifFalse: [ (IceRepositoryCreator new
repository: localRepo; location: self local;
baseline: repoName; remote: (IceGitRemote url: self repository greaseString ", '.git'");
onConflictUseLoaded; createRepository) register ].
onWarningLog; localRepo := 'gitlocal://' , self local fullName.
load ] count := 1.
on: IceGenericError [ true ]
do: [ :ex | whileTrue: [ [ ^ Metacello new
Notification repository: localRepo;
signal: (String with: Character cr) , ex description , (String with: Character cr) baseline: repoName;
, 'RETRYING ' , count greaseString. onConflictUseLoaded;
(Delay forSeconds: 2) wait. onWarningLog;
ex retry ]. load ]
count := count + 1 ] on: IceGenericError
] do: [ :ex |
Notification
{ #category : #accessing } signal: (String with: Character cr) , ex description , (String with: Character cr)
ExoRepo >> local [ , 'RETRYING ' , count greaseString.
^ FileLocator localDirectory / 'iceberg' / (self provider) / self repositoryName (Delay forSeconds: 2) wait.
] ex retry ].
count := count + 1 ]
{ #category : #accessing } ]
ExoRepo >> printOn: aStream [
super initialize. { #category : #accessing }
self repository ifNotNil: [ ExoRepo >> local [
aStream nextPutAll: self repositoryName, ' | ', self repository asString] ^ FileLocator localDirectory / 'iceberg' / (self provider) / self repositoryName
ifNil: [ aStream nextPutAll: 'ExoRepo without repository' ]. ]
]
{ #category : #accessing }
{ #category : #accessing } ExoRepo >> printOn: aStream [
ExoRepo >> provider [ super initialize.
self repository ifNil: [ ^ nil ]. self repository ifNotNil: [
^ self repository segments first aStream nextPutAll: self repositoryName, ' | ', self repository asString]
] ifNil: [ aStream nextPutAll: 'ExoRepo without repository' ].
]
{ #category : #accessing }
ExoRepo >> repository [ { #category : #accessing }
^ repository. ExoRepo >> provider [
] self repository ifNil: [ ^ nil ].
^ self repository segments first
{ #category : #accessing } ]
ExoRepo >> repository: aString [
repository := aString asZnUrl { #category : #accessing }
] ExoRepo >> repository [
^ repository.
{ #category : #accessing } ]
ExoRepo >> repositoryName [
self repository ifNil: [ ^ self ]. { #category : #accessing }
^ self repository segments second ExoRepo >> repository: aString [
] repository := aString asZnUrl
]
{ #category : #accessing }
ExoRepo >> wiki [ { #category : #accessing }
^ (self local / 'wiki') ensureCreateDirectory. ExoRepo >> repositoryName [
self repository ifNil: [ ^ self ].
] ^ self repository segments second
]
{ #category : #accessing }
ExoRepo >> wiki [
^ (self local / 'wiki') ensureCreateDirectory.
]

View File

@ -1,14 +1,14 @@
Extension { #name : #Gofer } Extension { #name : #Gofer }
{ #category : #'*ExoRepo' } { #category : #'*ExoRepo' }
Gofer >> repositories [ Gofer >> repositories [
"Answer the configured monticello repositories." "Answer the configured monticello repositories."
| result | | result |
result := OrderedCollection withAll: repositories. result := OrderedCollection withAll: repositories.
packageCacheRepository ifNotNil: [ result addFirst: packageCacheRepository ]. packageCacheRepository ifNotNil: [ result addFirst: packageCacheRepository ].
^ result asArray collect: [:each | ^ result asArray collect: [:each |
(each class = MCHttpRepository and: [each location beginsWith: 'gitea']) (each class = MCHttpRepository and: [each location beginsWith: 'gitea'])
ifTrue: [ MCRepository fromUrl: each location ] ifFalse: [ each ] ifTrue: [ MCRepository fromUrl: each location ] ifFalse: [ each ]
]. ].
] ]

View File

@ -1,79 +1,79 @@
Class { Class {
#name : #MCGiteabRepository, #name : #MCGiteabRepository,
#superclass : #MCGitBasedNetworkRepository, #superclass : #MCGitBasedNetworkRepository,
#category : #ExoRepo #category : #ExoRepo
} }
{ #category : #accessing } { #category : #accessing }
MCGiteabRepository class >> basicDescription [ MCGiteabRepository class >> basicDescription [
^ 'gitea' ^ 'gitea'
] ]
{ #category : #'as yet unclassified' } { #category : #'as yet unclassified' }
MCGiteabRepository class >> basicFromUrl: aZnUrl [ MCGiteabRepository class >> basicFromUrl: aZnUrl [
^ self location: aZnUrl asString ^ self location: aZnUrl asString
] ]
{ #category : #'*ExoRepo' } { #category : #'*ExoRepo' }
MCGiteabRepository class >> createRepositoryFromSpec: aMetacelloRepositorySpec on: anIceMetacelloPharoPlatform [ MCGiteabRepository class >> createRepositoryFromSpec: aMetacelloRepositorySpec on: anIceMetacelloPharoPlatform [
^ anIceMetacelloPharoPlatform createGiteaRepository: aMetacelloRepositorySpec ^ anIceMetacelloPharoPlatform createGiteaRepository: aMetacelloRepositorySpec
] ]
{ #category : #accessing } { #category : #accessing }
MCGiteabRepository class >> isAvailableFor: type [ MCGiteabRepository class >> isAvailableFor: type [
^ type = 'gitea' ^ type = 'gitea'
] ]
{ #category : #private } { #category : #private }
MCGiteabRepository class >> projectZipUrlFor: projectPath versionString: versionString [ MCGiteabRepository class >> projectZipUrlFor: projectPath versionString: versionString [
^ 'https://' , projectPath , '/archive/' , versionString , '.zip' ^ 'https://' , projectPath , '/archive/' , versionString , '.zip'
] ]
{ #category : #accessing } { #category : #accessing }
MCGiteabRepository class >> urlSchemes [ MCGiteabRepository class >> urlSchemes [
^ #(gitea) ^ #(gitea)
] ]
{ #category : #accessing } { #category : #accessing }
MCGiteabRepository >> branches [ MCGiteabRepository >> branches [
"IMPORTANT! This requires the installation of the external multiplatform binary dependency "IMPORTANT! This requires the installation of the external multiplatform binary dependency
restify at: https://github.com/itzg/restify/. restify at: https://github.com/itzg/restify/.
This should be installed independiently." This should be installed independiently."
| response | | response |
response := OrderedDictionary new. response := OrderedDictionary new.
OSSUnixSubprocess new OSSUnixSubprocess new
shellCommand: 'restify --class="gt-ellipsis" ', 'https://', self projectPath, '/', self repoPath, '/branches'; shellCommand: 'restify --class="gt-ellipsis" ', 'https://', self projectPath, '/', self repoPath, '/branches';
redirectStdout; redirectStdout;
runAndWaitOnExitDo: [ :command :outString | runAndWaitOnExitDo: [ :command :outString |
outString ifEmpty: [^ command ]. outString ifEmpty: [^ command ].
(STON fromString: outString) do: [:each | (STON fromString: outString) do: [:each |
response at: (each at: 'text') put: (each at: 'href') response at: (each at: 'text') put: (each at: 'href')
] ]
]. ].
^ response ^ response
] ]
{ #category : #accessing } { #category : #accessing }
MCGiteabRepository >> calculateRepositoryDirectory [ MCGiteabRepository >> calculateRepositoryDirectory [
| directory | | directory |
directory := self class directory := self class
projectDirectoryFrom: self projectPath, '/', self repoPath projectDirectoryFrom: self projectPath, '/', self repoPath
version: self projectVersion. version: self projectVersion.
self repoPath isEmpty ifFalse: [ self repoPath isEmpty ifFalse: [
directory := directory parent ]. directory := directory parent ].
^ directory ^ directory
] ]
{ #category : #accessing } { #category : #accessing }
MCGiteabRepository >> location: aString [ MCGiteabRepository >> location: aString [
] ]
{ #category : #accessing } { #category : #accessing }
MCGiteabRepository >> projectVersion [ MCGiteabRepository >> projectVersion [
(projectVersion == nil or: [ projectVersion isEmpty ]) (projectVersion == nil or: [ projectVersion isEmpty ])
ifTrue: [ projectVersion := self branches keys first ]. ifTrue: [ projectVersion := self branches keys first ].
^ projectVersion ^ projectVersion
] ]

View File

@ -1,6 +1,6 @@
Extension { #name : #MCGiteabRepository } Extension { #name : #MCGiteabRepository }
{ #category : #'*ExoRepo' } { #category : #'*ExoRepo' }
MCGiteabRepository class >> createRepositoryFromSpec: aMetacelloRepositorySpec on: anIceMetacelloPharoPlatform [ MCGiteabRepository class >> createRepositoryFromSpec: aMetacelloRepositorySpec on: anIceMetacelloPharoPlatform [
^ anIceMetacelloPharoPlatform createGiteaRepository: aMetacelloRepositorySpec ^ anIceMetacelloPharoPlatform createGiteaRepository: aMetacelloRepositorySpec
] ]

View File

@ -1,15 +1,15 @@
Extension { #name : #MetacelloCommonMCSpecLoader } Extension { #name : #MetacelloCommonMCSpecLoader }
{ #category : #'*ExoRepo' } { #category : #'*ExoRepo' }
MetacelloCommonMCSpecLoader >> linearLoadPackageSpecs: packageSpecs repositories: repositories [ MetacelloCommonMCSpecLoader >> linearLoadPackageSpecs: packageSpecs repositories: repositories [
| gofer sanitizedRepos | | gofer sanitizedRepos |
gofer := MetacelloGofer new. gofer := MetacelloGofer new.
sanitizedRepos := OrderedCollection withAll: repositories. sanitizedRepos := OrderedCollection withAll: repositories.
sanitizedRepos := sanitizedRepos collect: [:each | sanitizedRepos := sanitizedRepos collect: [:each |
(each class = MCHttpRepository and: [each location beginsWith: 'gitea']) (each class = MCHttpRepository and: [each location beginsWith: 'gitea'])
ifTrue: [ MCRepository fromUrl: each location ] ifFalse: [ each ] ifTrue: [ MCRepository fromUrl: each location ] ifFalse: [ each ]
]. ].
sanitizedRepos do: [:repo | gofer repository: repo ]. sanitizedRepos do: [:repo | gofer repository: repo ].
packageSpecs do: [:pkg | pkg loadUsing: self gofer: gofer ]. packageSpecs do: [:pkg | pkg loadUsing: self gofer: gofer ].
] ]

View File

@ -1,32 +1,32 @@
Extension { #name : #MetacelloPlatform } Extension { #name : #MetacelloPlatform }
{ #category : #'*ExoRepo' } { #category : #'*ExoRepo' }
MetacelloPlatform >> createGiteaRepository: aRepositorySpec [ MetacelloPlatform >> createGiteaRepository: aRepositorySpec [
| cl | | cl |
cl := MCGiteabRepository. cl := MCGiteabRepository.
^ cl location: aRepositorySpec description ^ cl location: aRepositorySpec description
] ]
{ #category : #'*ExoRepo' } { #category : #'*ExoRepo' }
MetacelloPlatform >> extractTypeFromDescription: description [ MetacelloPlatform >> extractTypeFromDescription: description [
description == nil description == nil
ifTrue: [ ^ nil ]. ifTrue: [ ^ nil ].
((description beginsWith: '/') or: [ description second = $: ]) ((description beginsWith: '/') or: [ description second = $: ])
ifTrue: [ ^ 'directory' ]. ifTrue: [ ^ 'directory' ].
(description beginsWith: 'dictionary://') (description beginsWith: 'dictionary://')
ifTrue: [ ^ 'dictionary' ]. ifTrue: [ ^ 'dictionary' ].
(description beginsWith: 'filetree://') (description beginsWith: 'filetree://')
ifTrue: [ ^ 'filetree' ]. ifTrue: [ ^ 'filetree' ].
(description beginsWith: 'tonel://') (description beginsWith: 'tonel://')
ifTrue: [ ^ 'tonel' ]. ifTrue: [ ^ 'tonel' ].
(description beginsWith: 'github://') (description beginsWith: 'github://')
ifTrue: [ ^ 'github' ]. ifTrue: [ ^ 'github' ].
(description beginsWith: 'gitorious://') (description beginsWith: 'gitorious://')
ifTrue: [ ^ 'gitorious' ]. ifTrue: [ ^ 'gitorious' ].
(description beginsWith: 'gitea://') (description beginsWith: 'gitea://')
ifTrue: [ ^ 'gitea' ]. ifTrue: [ ^ 'gitea' ].
(description beginsWith: 'bitbucket://') (description beginsWith: 'bitbucket://')
ifTrue: [ ^ 'bitbucket' ]. ifTrue: [ ^ 'bitbucket' ].
^ 'http' ^ 'http'
] ]

View File

@ -1,27 +1,27 @@
" "
I'm a a front-end to use multiple package managers like [Scoop](https://scoop.sh/) on Windows and [Brew](https://brew.sh/) on MacOS and Gnu/Linux I'm a a front-end to use multiple package managers like [Scoop](https://scoop.sh/) on Windows and [Brew](https://brew.sh/) on MacOS and Gnu/Linux
" "
Class { Class {
#name : #MultiPack, #name : #MultiPack,
#superclass : #Object, #superclass : #Object,
#instVars : [ #instVars : [
'requirements', 'requirements',
'recommendations', 'recommendations',
'repository' 'repository'
], ],
#category : #ExoRepo #category : #ExoRepo
} }
{ #category : #accessing } { #category : #accessing }
MultiPack >> recommendations: aDictionary [ MultiPack >> recommendations: aDictionary [
recommendations := aDictionary recommendations := aDictionary
] ]
{ #category : #accessing } { #category : #accessing }
MultiPack >> repository: anObject [ MultiPack >> repository: anObject [
] ]
{ #category : #accessing } { #category : #accessing }
MultiPack >> requirements: aDictionary [ MultiPack >> requirements: aDictionary [
requirements := aDictionary requirements := aDictionary
] ]

View File

@ -1,89 +1,89 @@
" "
I'm a helper class modelling the common uses of the Nim's [Nimble package manager](https://github.com/nim-lang/nimble). I'm a helper class modelling the common uses of the Nim's [Nimble package manager](https://github.com/nim-lang/nimble).
This was evolved in the context of the [Grafoscopio](mutabit.com/grafoscopio/en.html) community exploration and prototyping of interactive documentation. This was evolved in the context of the [Grafoscopio](mutabit.com/grafoscopio/en.html) community exploration and prototyping of interactive documentation.
" "
Class { Class {
#name : #Nimble, #name : #Nimble,
#superclass : #Object, #superclass : #Object,
#category : #'ExoRepo-External' #category : #'ExoRepo-External'
} }
{ #category : #accessing } { #category : #accessing }
Nimble class >> detect: packageName [ Nimble class >> detect: packageName [
^ self installed ^ self installed
detect: [ :dependency | dependency beginsWith: packageName ] detect: [ :dependency | dependency beginsWith: packageName ]
ifFound: [ ^ true ] ifFound: [ ^ true ]
ifNone: [ ^ false ] ifNone: [ ^ false ]
] ]
{ #category : #accessing } { #category : #accessing }
Nimble class >> install: packageName [ Nimble class >> install: packageName [
(self detect: packageName) ifTrue: [ ^ self ]. (self detect: packageName) ifTrue: [ ^ self ].
self installPackagesList. self installPackagesList.
Smalltalk os isWindows Smalltalk os isWindows
ifTrue: [ ^ LibC runCommand: 'nimble install ', packageName ]. ifTrue: [ ^ LibC runCommand: 'nimble install ', packageName ].
OSSUnixSubprocess new OSSUnixSubprocess new
command: 'nimble'; command: 'nimble';
arguments: {'install'. arguments: {'install'.
packageName}; packageName};
redirectStdout; redirectStdout;
redirectStderr; redirectStderr;
runAndWaitOnExitDo: [ :process :outString :errString | runAndWaitOnExitDo: [ :process :outString :errString |
process isSuccess process isSuccess
ifTrue: [ Transcript show: 'Command exited correctly with output: ', outString. ] ifTrue: [ Transcript show: 'Command exited correctly with output: ', outString. ]
ifFalse: [ ifFalse: [
^ 'Command exit with error status: ', process exitStatusInterpreter printString, String cr, ^ 'Command exit with error status: ', process exitStatusInterpreter printString, String cr,
'Stderr contents: ', errString. 'Stderr contents: ', errString.
] ]
] ]
] ]
{ #category : #accessing } { #category : #accessing }
Nimble class >> installPackagesList [ Nimble class >> installPackagesList [
(FileLocator home / '.nimble' / 'packages_official.json') exists (FileLocator home / '.nimble' / 'packages_official.json') exists
ifTrue: [ ^ self ]. ifTrue: [ ^ self ].
(Smalltalk os isUnix or: [ Smalltalk os isMacOS ]) (Smalltalk os isUnix or: [ Smalltalk os isMacOS ])
ifTrue: [ ifTrue: [
OSSUnixSubprocess new OSSUnixSubprocess new
command: 'nimble'; command: 'nimble';
arguments: #('refresh'); arguments: #('refresh');
redirectStdout; redirectStdout;
runAndWaitOnExitDo: [ :process :outString | ^ outString ]. runAndWaitOnExitDo: [ :process :outString | ^ outString ].
]. ].
Smalltalk os isWindows Smalltalk os isWindows
ifTrue: [ ^ LibC resultOfCommand: 'nimble refresh' ] ifTrue: [ ^ LibC resultOfCommand: 'nimble refresh' ]
] ]
{ #category : #accessing } { #category : #accessing }
Nimble class >> installed [ Nimble class >> installed [
Smalltalk os isWindows Smalltalk os isWindows
ifTrue: [ | process | ifTrue: [ | process |
process := GtExternalProcessBuilder new process := GtExternalProcessBuilder new
command: 'nimble.exe'; command: 'nimble.exe';
args: #('list' '--installed'); args: #('list' '--installed');
output. output.
^ process stdout lines ]. ^ process stdout lines ].
OSSUnixSubprocess new OSSUnixSubprocess new
command: 'nimble'; command: 'nimble';
arguments: #('list' '--installed'); arguments: #('list' '--installed');
redirectStdout; redirectStdout;
redirectStderr; redirectStderr;
runAndWaitOnExitDo: [ :process :outString :errString | runAndWaitOnExitDo: [ :process :outString :errString |
process isSuccess process isSuccess
ifTrue: [ ^ outString lines ]; ifTrue: [ ^ outString lines ];
ifFalse: [ ^ nil ] ifFalse: [ ^ nil ]
] ]
] ]
{ #category : #accessing } { #category : #accessing }
Nimble class >> version [ Nimble class >> version [
OSSUnixSubprocess new OSSUnixSubprocess new
command: 'nimble'; command: 'nimble';
arguments: #('--version'); arguments: #('--version');
redirectStdout; redirectStdout;
runAndWaitOnExitDo: [ :process :outString | ^ outString ] runAndWaitOnExitDo: [ :process :outString | ^ outString ]
] ]

View File

@ -1 +1 @@
Package { #name : #ExoRepo } Package { #name : #ExoRepo }