Using GtSubprocess instead of OSSubprocess. Will backporting this to "plain" Pharo be a future issue?

This commit is contained in:
Offray Vladimir Luna Cárdenas 2024-05-19 11:47:59 -05:00
parent c01d31a2a9
commit 5de6a81029
14 changed files with 626 additions and 630 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,42 +1,42 @@
Class { Class {
#name : #ExoPackage, #name : #ExoPackage,
#superclass : #Object, #superclass : #Object,
#instVars : [ #instVars : [
'repository' 'repository'
], ],
#category : #'ExoRepo-External' #category : #'ExoRepo-External'
} }
{ #category : #accessing } { #category : #accessing }
ExoPackage class >> githubAPIEndPoint [ ExoPackage class >> githubAPIEndPoint [
^ 'https://api.github.com/' asUrl ^ 'https://api.github.com/' asUrl
] ]
{ #category : #accessing } { #category : #accessing }
ExoPackage >> assets [ ExoPackage >> assets [
^ (self lastReleaseData at: 'assets') collect: [:each | ^ (self lastReleaseData at: 'assets') collect: [:each |
GitHubAsset fromDictionary: each GitHubAsset fromDictionary: each
] ]
] ]
{ #category : #accessing } { #category : #accessing }
ExoPackage >> lastReleaseData [ ExoPackage >> lastReleaseData [
| releasesLink | | releasesLink |
releasesLink := self class githubAPIEndPoint addPathSegment: 'repos'. releasesLink := self class githubAPIEndPoint addPathSegment: 'repos'.
self repository asUrl segments do: [:segment | self repository asUrl segments do: [:segment |
releasesLink addPathSegment: segment releasesLink addPathSegment: segment
]. ].
releasesLink addPathSegment: 'releases'. releasesLink addPathSegment: 'releases'.
^ (STONJSON ^ (STONJSON
fromString: releasesLink retrieveContents) first fromString: releasesLink retrieveContents) first
] ]
{ #category : #accessing } { #category : #accessing }
ExoPackage >> repository [ ExoPackage >> repository [
^ repository ^ repository
] ]
{ #category : #accessing } { #category : #accessing }
ExoPackage >> repository: anUrl [ ExoPackage >> repository: anUrl [
repository := anUrl repository := anUrl
] ]

View File

@ -1,123 +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 class >> userDataFolder [ ExoRepo class >> userDataFolder [
Smalltalk os isWindows Smalltalk os isWindows
ifTrue: [ ^ FileLocator home / 'AppData' / 'Local' ] ifTrue: [ ^ FileLocator home / 'AppData' / 'Local' ]
ifFalse: [ ^ FileLocator userData ]. ifFalse: [ ^ FileLocator userData ].
] ]
{ #category : #accessing } { #category : #accessing }
ExoRepo >> load [ ExoRepo >> load [
"I load the configuration of this package using a external Gitea repository." "I load the configuration of this package using a external Gitea repository."
"While more Git independient providers are implemented in Monticello, I will "While more Git independient providers are implemented in Monticello, I will
use Iceberg to download the repository and load it from a local directory" use Iceberg to download the repository and load it from a local directory"
| localRepo repoName count | | localRepo repoName count |
repoName := self repositoryName. repoName := self repositoryName.
self local exists self local exists
ifFalse: [ (IceRepositoryCreator new ifFalse: [ (IceRepositoryCreator new
location: self local; location: self local;
remote: (IceGitRemote url: self repository greaseString ", '.git'"); remote: (IceGitRemote url: self repository greaseString ", '.git'");
createRepository) register ]. createRepository) register ].
localRepo := 'gitlocal://' , self local fullName. localRepo := 'gitlocal://' , self local fullName.
count := 1. count := 1.
[ true ] [ true ]
whileTrue: [ [ ^ Metacello new whileTrue: [ [ ^ Metacello new
repository: localRepo; repository: localRepo;
baseline: repoName; baseline: repoName;
onConflictUseLoaded; onConflictUseLoaded;
onWarningLog; onWarningLog;
load ] load ]
on: IceGenericError on: IceGenericError
do: [ :ex | do: [ :ex |
Notification Notification
signal: (String with: Character cr) , ex description , (String with: Character cr) signal: (String with: Character cr) , ex description , (String with: Character cr)
, 'RETRYING ' , count greaseString. , 'RETRYING ' , count greaseString.
(Delay forSeconds: 2) wait. (Delay forSeconds: 2) wait.
ex retry ]. ex retry ].
count := count + 1 ] count := count + 1 ]
] ]
{ #category : #accessing } { #category : #accessing }
ExoRepo >> local [ ExoRepo >> local [
^ FileLocator localDirectory / 'iceberg' / (self provider) / self repositoryName ^ FileLocator localDirectory / 'iceberg' / (self provider) / self repositoryName
] ]
{ #category : #accessing } { #category : #accessing }
ExoRepo >> printOn: aStream [ ExoRepo >> printOn: aStream [
super initialize. super initialize.
self repository ifNotNil: [ self repository ifNotNil: [
aStream nextPutAll: self repositoryName, ' | ', self repository asString] aStream nextPutAll: self repositoryName, ' | ', self repository asString]
ifNil: [ aStream nextPutAll: 'ExoRepo without repository' ]. ifNil: [ aStream nextPutAll: 'ExoRepo without repository' ].
] ]
{ #category : #accessing } { #category : #accessing }
ExoRepo >> provider [ ExoRepo >> provider [
self repository ifNil: [ ^ nil ]. self repository ifNil: [ ^ nil ].
^ self repository segments first ^ self repository segments first
] ]
{ #category : #accessing } { #category : #accessing }
ExoRepo >> repository [ ExoRepo >> repository [
^ repository. ^ repository.
] ]
{ #category : #accessing } { #category : #accessing }
ExoRepo >> repository: aString [ ExoRepo >> repository: aString [
repository := aString asZnUrl repository := aString asZnUrl
] ]
{ #category : #accessing } { #category : #accessing }
ExoRepo >> repositoryName [ ExoRepo >> repositoryName [
self repository ifNil: [ ^ self ]. self repository ifNil: [ ^ self ].
^ self repository segments second ^ self repository segments second
] ]
{ #category : #accessing } { #category : #accessing }
ExoRepo >> wiki [ ExoRepo >> wiki [
^ (self local / 'wiki') ensureCreateDirectory. ^ (self local / 'wiki') ensureCreateDirectory.
] ]

View File

@ -1,56 +1,56 @@
Class { Class {
#name : #GitHubAsset, #name : #GitHubAsset,
#superclass : #Object, #superclass : #Object,
#instVars : [ #instVars : [
'name', 'name',
'created', 'created',
'updated', 'updated',
'size', 'size',
'downloadLink' 'downloadLink'
], ],
#category : #'ExoRepo-External' #category : #'ExoRepo-External'
} }
{ #category : #accessing } { #category : #accessing }
GitHubAsset class >> fromDictionary: aGitHubAssetDictionary [ GitHubAsset class >> fromDictionary: aGitHubAssetDictionary [
| response | | response |
response := self new response := self new
name: (aGitHubAssetDictionary at: 'name'); name: (aGitHubAssetDictionary at: 'name');
size: (aGitHubAssetDictionary at: 'size'); size: (aGitHubAssetDictionary at: 'size');
created: (aGitHubAssetDictionary at: 'created_at'); created: (aGitHubAssetDictionary at: 'created_at');
updated: (aGitHubAssetDictionary at: 'updated_at'); updated: (aGitHubAssetDictionary at: 'updated_at');
downloadLink: (aGitHubAssetDictionary at: 'browser_download_url'). downloadLink: (aGitHubAssetDictionary at: 'browser_download_url').
^ response ^ response
] ]
{ #category : #accessing } { #category : #accessing }
GitHubAsset >> created: anObject [ GitHubAsset >> created: anObject [
created := anObject created := anObject
] ]
{ #category : #accessing } { #category : #accessing }
GitHubAsset >> downloadLink: anUrl [ GitHubAsset >> downloadLink: anUrl [
downloadLink := anUrl downloadLink := anUrl
] ]
{ #category : #accessing } { #category : #accessing }
GitHubAsset >> name: anObject [ GitHubAsset >> name: anObject [
name := anObject name := anObject
] ]
{ #category : #accessing } { #category : #accessing }
GitHubAsset >> printOn: aStream [ GitHubAsset >> printOn: aStream [
super initialize. super initialize.
aStream aStream
nextPutAll: '(', name, ')' nextPutAll: '(', name, ')'
] ]
{ #category : #accessing } { #category : #accessing }
GitHubAsset >> size: anObject [ GitHubAsset >> size: anObject [
size := anObject size := anObject
] ]
{ #category : #accessing } { #category : #accessing }
GitHubAsset >> updated: anObject [ GitHubAsset >> updated: anObject [
updated := anObject updated := anObject
] ]

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,66 +1,66 @@
" "
I'm run an implementation of the [Nano ID](https://github.com/ai/nanoid) tiny, secure URL-friendly unique string ID generator via its [Nim implementation](https://github.com/icyphox/nanoid.nim). I'm run an implementation of the [Nano ID](https://github.com/ai/nanoid) tiny, secure URL-friendly unique string ID generator via its [Nim implementation](https://github.com/icyphox/nanoid.nim).
The Nim script has hard coded: The Nim script has hard coded:
* a [base 58 encoding](https://medium.com/concerning-pharo/understanding-base58-encoding-23e673e37ff6) alphabet to avoid similar looking letter and the use of non-alphanumeric characters. * a [base 58 encoding](https://medium.com/concerning-pharo/understanding-base58-encoding-23e673e37ff6) alphabet to avoid similar looking letter and the use of non-alphanumeric characters.
* a 12 characters length output, which gives [a pretty low probability collision](https://zelark.github.io/nano-id-cc/) for the previous alphabet: * a 12 characters length output, which gives [a pretty low probability collision](https://zelark.github.io/nano-id-cc/) for the previous alphabet:
~616 years needed, in order to have a 1% probability of at least one collision at a speed of 1000 IDs per hour. ~616 years needed, in order to have a 1% probability of at least one collision at a speed of 1000 IDs per hour.
This is more than enough for our unique IDs applications, mostly in the documentation context, This is more than enough for our unique IDs applications, mostly in the documentation context,
which consists of hand crafted and/or programmatically produced notes , which consists of hand crafted and/or programmatically produced notes ,
for example in data narratives, book(lets) and TiddlyWiki tiddlers of tens or hundreds of notes at most, for example in data narratives, book(lets) and TiddlyWiki tiddlers of tens or hundreds of notes at most,
unevenly produced between hours, days and/or weeks.. unevenly produced between hours, days and/or weeks..
The `External` tag is related on its dependency on other programming languages and frameworks, The `External` tag is related on its dependency on other programming languages and frameworks,
though the dependency should be loaded by just loading a small binary with no dependencies. though the dependency should be loaded by just loading a small binary with no dependencies.
" "
Class { Class {
#name : #NanoID, #name : #NanoID,
#superclass : #Object, #superclass : #Object,
#category : #'ExoRepo-External' #category : #'ExoRepo-External'
} }
{ #category : #accessing } { #category : #accessing }
NanoID class >> binaryFile [ NanoID class >> binaryFile [
Smalltalk os isWindows Smalltalk os isWindows
ifFalse: [ ^ MiniDocs appFolder / self scriptSourceCode basenameWithoutExtension ] ifFalse: [ ^ MiniDocs appFolder / self scriptSourceCode basenameWithoutExtension ]
ifTrue: [ ^ ExoRepo userDataFolder / 'NanoId' / 'nanoid' ] ifTrue: [ ^ ExoRepo userDataFolder / 'NanoId' / 'nanoid' ]
] ]
{ #category : #accessing } { #category : #accessing }
NanoID class >> generate [ NanoID class >> generate [
self binaryFile exists ifFalse: [ NanoID install]. self binaryFile exists ifFalse: [ NanoID install].
Smalltalk os isWindows Smalltalk os isWindows
ifTrue: [ ^ (LibC resultOfCommand:self binaryFile fullName) copyWithoutAll: (Character lf asString) ]. ifTrue: [ ^ (LibC resultOfCommand:self binaryFile fullName) copyWithoutAll: (Character lf asString) ].
OSSUnixSubprocess new OSSUnixSubprocess new
command: self binaryFile fullName; command: self binaryFile fullName;
redirectStdout; redirectStdout;
redirectStdout; redirectStdout;
runAndWaitOnExitDo: [ :process :outString | ^ outString copyWithoutAll: (Character lf asString) ] runAndWaitOnExitDo: [ :process :outString | ^ outString copyWithoutAll: (Character lf asString) ]
] ]
{ #category : #accessing } { #category : #accessing }
NanoID class >> install [ NanoID class >> install [
"For the moment, only Gnu/Linux and Mac are supported. "For the moment, only Gnu/Linux and Mac are supported.
IMPORTANT: Nimble, Nim's package manager should be installed, as this process doesn't verify its proper installation." IMPORTANT: Nimble, Nim's package manager should be installed, as this process doesn't verify its proper installation."
self binaryFile exists ifTrue: [ ^ MiniDocs appFolder ]. self binaryFile exists ifTrue: [ ^ MiniDocs appFolder ].
Nimble install: 'nanoid'. Nimble install: 'nanoid'.
Smalltalk os isWindows Smalltalk os isWindows
ifTrue: [ ^ LibC resultOfCommand: 'nanoid c ',self scriptSourceCode fullName ]. ifTrue: [ ^ LibC resultOfCommand: 'nanoid c ',self scriptSourceCode fullName ].
OSSUnixSubprocess new OSSUnixSubprocess new
command: 'nim'; command: 'nim';
arguments: {'c'. self scriptSourceCode fullName}; arguments: {'c'. self scriptSourceCode fullName};
runAndWaitOnExitDo: [ :process :outString | runAndWaitOnExitDo: [ :process :outString |
(self scriptSourceCode parent / (self scriptSourceCode) basenameWithoutExtension) moveToPageTitled: MiniDocs appFolder asFileReference. (self scriptSourceCode parent / (self scriptSourceCode) basenameWithoutExtension) moveToPageTitled: MiniDocs appFolder asFileReference.
^ MiniDocs appFolder ] ^ MiniDocs appFolder ]
] ]
{ #category : #accessing } { #category : #accessing }
NanoID class >> isInstalled [ NanoID class >> isInstalled [
^ self binaryFile exists ^ self binaryFile exists
] ]
{ #category : #accessing } { #category : #accessing }
NanoID class >> scriptSourceCode [ NanoID class >> scriptSourceCode [
^ FileLocator image parent / 'pharo-local/iceberg/Offray/MiniDocs/src/nanoIdGen.nim' ^ FileLocator image parent / 'pharo-local/iceberg/Offray/MiniDocs/src/nanoIdGen.nim'
] ]

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,60 +1,56 @@
" "
The `External` tag is related on its dependency on other programming languages and frameworks, The `External` tag is related on its dependency on other programming languages and frameworks,
though the dependency should be loaded by just loading a small binary with no dependencies. though the dependency should be loaded by just loading a small binary with no dependencies.
" "
Class { Class {
#name : #YQ, #name : #YQ,
#superclass : #Object, #superclass : #Object,
#category : #'ExoRepo-External' #category : #'ExoRepo-External'
} }
{ #category : #accessing } { #category : #accessing }
YQ class >> binaryDownloadLinkFor: operativeSystem on: processor [ YQ class >> binaryDownloadLinkFor: operativeSystem on: processor [
| binaryName binaryDownloadData | | binaryName binaryDownloadData |
binaryName := 'yq_', operativeSystem , '_', processor. binaryName := 'yq_', operativeSystem , '_', processor.
binaryDownloadData := ((self lastReleaseData at: 'assets') binaryDownloadData := ((self lastReleaseData at: 'assets')
select: [:each | (each at: 'name') beginsWith: binaryName ]) first. select: [:each | (each at: 'name') beginsWith: binaryName ]) first.
^ binaryDownloadData at: 'browser_download_url' ^ binaryDownloadData at: 'browser_download_url'
] ]
{ #category : #accessing } { #category : #accessing }
YQ class >> binaryFile [ YQ class >> binaryFile [
"Starting with location on Arch Linux and its derivates. Multidistro and multiOS support should be added." "Starting with location on Arch Linux and its derivates. Multidistro and multiOS support should be added."
Smalltalk os isWindows ifFalse: [^ FileLocator root / 'usr/bin/yq']. Smalltalk os isWindows ifFalse: [^ FileLocator root / 'usr/bin/yq'].
^ FileLocator home / 'scoop/shims/yq.exe' ^ FileLocator home / 'scoop/shims/yq.exe'
] ]
{ #category : #accessing } { #category : #accessing }
YQ class >> exoPackage [ YQ class >> exoPackage [
^ ExoPackage new ^ ExoPackage new
repository: self repository repository: self repository
] ]
{ #category : #accessing } { #category : #accessing }
YQ class >> install [ YQ class >> install [
^ ExoPackage new ^ ExoPackage new
repository: self repository; repository: self repository;
lastReleaseData lastReleaseData
] ]
{ #category : #accessing } { #category : #accessing }
YQ class >> jsonToYaml: aDictionary [ YQ class >> jsonToYaml: aDictionary [
| jsonFile | | jsonFile |
self binaryFile exists ifFalse: [ YQ install]. self binaryFile exists ifFalse: [ YQ install].
jsonFile := MarkupFile exportAsFileOn: FileLocator temp / 'data.json' containing: aDictionary. jsonFile := MarkupFile exportAsFileOn: FileLocator temp / 'data.json' containing: aDictionary.
(Smalltalk os isUnix or: [ Smalltalk os isMacOS ]) Smalltalk os isWindows
ifTrue: [ ifTrue: [ ^ LibC resultOfCommand: 'yq -p=json ', jsonFile fullName ].
OSSUnixSubprocess new ^ GtSubprocessWithInMemoryOutput new
shellCommand: 'cat ', jsonFile fullName,' | yq -y'; shellCommand: 'cat ', jsonFile fullName,' | yq -y';
redirectStdout; runAndWait;
runAndWaitOnExitDo: [ :command :outString | stdout
^ outString ]
]].
Smalltalk os isWindows { #category : #accessing }
ifTrue: [ ^ LibC resultOfCommand: 'yq -p=json ', jsonFile fullName ]. YQ class >> repository [
] ^ 'https://github.com/mikefarah/yq'
]
{ #category : #accessing }
YQ class >> repository [
^ 'https://github.com/mikefarah/yq'
]

View File

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