Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

22658-Better-manage-encoding-of-environment-variables #1980

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Athens-Cairo/CairoLibrary.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ CairoLibrary >> unix32ModuleName [
Look in a number of known locations, or LD_LIBRARY_PATH."

(#('/usr/lib/i386-linux-gnu' '/usr/lib32' '/usr/lib'),
(((OSEnvironment current getEnv: 'LD_LIBRARY_PATH') ifNil: [ '' ]) substrings: ':'))
((OSEnvironment current at: 'LD_LIBRARY_PATH' ifAbsent: [ '' ]) substrings: ':'))
do: [ :path |
| libraryPath |
libraryPath := path asFileReference / 'libcairo.so.2'.
Expand All @@ -38,7 +38,7 @@ CairoLibrary >> unix64ModuleName [
Look in a number of known locations, or LD_LIBRARY_PATH."

(#('/lib/x86_64-linux-gnu' '/usr/lib'),
(((OSEnvironment current getEnv: 'LD_LIBRARY_PATH') ifNil: [ '' ]) substrings: ':'))
((OSEnvironment current at: 'LD_LIBRARY_PATH' ifAbsent: [ '' ]) substrings: ':'))
do: [ :path |
| libraryPath |
libraryPath := path asFileReference / 'libcairo.so.2'.
Expand Down
8 changes: 2 additions & 6 deletions src/FileSystem-Core/FileSystemResolver.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,11 @@ FileSystemResolver >> resolve: aSymbol [

{ #category : #resolving }
FileSystemResolver >> resolveString: aString [
| decoded fs |
"The argument string is actually a byte array encoded differently on each platform.
We are transforming it to an image string.
We assume for now that the string is utf8 encoded."
decoded := aString asByteArray utf8Decoded.
| fs |
fs := FileSystem disk.
^ FileReference
fileSystem: fs
path: (fs pathFromString: decoded)
path: (fs pathFromString: aString)
]

{ #category : #resolving }
Expand Down
4 changes: 2 additions & 2 deletions src/FileSystem-Core/SystemResolver.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ SystemResolver >> changes [

{ #category : #origins }
SystemResolver >> image [
^ self resolveString: Smalltalk primImagePath
^ self resolveString: Smalltalk imagePath
]

{ #category : #origins }
Expand All @@ -72,5 +72,5 @@ SystemResolver >> vmBinary [

{ #category : #origins }
SystemResolver >> vmDirectory [
^ self resolveString: Smalltalk vm primVmDirectoryPath
^ self resolveString: Smalltalk vm directory
]
2 changes: 1 addition & 1 deletion src/Ombu/OmSessionStore.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ OmSessionStore >> headReference [
OmSessionStore >> imagePathString [
"Answer the full path name for the current image."

^ SmalltalkImage current primImagePath
^ SmalltalkImage current imagePath
]

{ #category : #initialization }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ PharoBootstrapInitialization class >> initializeCommandLineHandlerAndErrorHandli
UIManager default activate.

Smalltalk sourceFileVersionString: 'PharoV60'.
(Smalltalk class classVariableNamed: 'LastImagePath') value: Smalltalk primImagePath. "set the default value"
(Smalltalk class classVariableNamed: 'LastImagePath') value: Smalltalk imagePath. "set the default value"
SourceFiles := SourceFileArray new.

"Create the ASTCache and add it to the startup list"
Expand Down
102 changes: 70 additions & 32 deletions src/System-OSEnvironments/OSEnvironment.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,22 @@ I represent the user environment variables. See `man environ` for more details.
Get access using:

Smalltalk os environment

Low level API

- getEnv: aVariableName
Gets the value of an environment variable called `aVariableName`
It is the system reponsibility to manage the encoding.
Rationale: A common denominator for all platforms providing an already decoded string, because windows does not (compared to *nix systems) provide a encoded byte representation of the value. Windows has instead its own wide string representation.

- getEnvRaw: anEncodedVariableName
Gets the value of an environment variable called `anEncodedVariableName` already encoded.
It is the user responsibility to encode and decode argument and return values in the encoding of this preference.
Rationale: Some systems may want to have the liberty to use different encodings, or even to put binary data in the variables.

- getEnv: aVariableName encoding: anEncoding
Gets the value of an environment variable called `aVariableName` using `anEncoding` to encode/decode arguments and return values.
Rationale: *xes could use different encodings
"
Class {
#name : #OSEnvironment,
Expand Down Expand Up @@ -94,39 +110,75 @@ OSEnvironment >> associationsDo: aBlock [

{ #category : #accessing }
OSEnvironment >> at: aKey [
"Gets the value of an environment variable called `aKey`.
Throws a KeyNotFound exception if not found.
It is the system reponsibility to manage the encodings of the argument and return values.

This is the common denominator API for all platforms.
Rationale: Windows does not (compared to *nix systems) provide a encoded byte representation of the value. Windows has instead its own wide string representation."

^ self at: aKey ifAbsent: [ KeyNotFound signalFor: aKey ]
]

{ #category : #accessing }
OSEnvironment >> at: aKey ifAbsent: aBlock [
^ (self getEnv: aKey) ifNil: aBlock
"Gets the value of an environment variable called `aKey`.
Execute aBlock if absent.
It is the system reponsibility to manage the encodings of the argument and return values.

This is the common denominator API for all platforms.
Rationale: Windows does not (compared to *nix systems) provide a encoded byte representation of the value. Windows has instead its own wide string representation."

self subclassResponsibility
]

{ #category : #accessing }
OSEnvironment >> at: key ifAbsentPut: aBlock [
"Return the value at the given key.
If key is not included in the receiver store the result
of evaluating aBlock as new value."
OSEnvironment >> at: aKey ifAbsentPut: aBlock [
"Gets the value of an environment variable called `aKey`.
If absent, insert the value given by aBlock.
It is the system reponsibility to manage the encodings of the argument and return values.

This is the common denominator API for all platforms.
Rationale: Windows does not (compared to *nix systems) provide a encoded byte representation of the value. Windows has instead its own wide string representation."

^ self at: key ifAbsent: [ self at: key put: aBlock value ]
^ self at: aKey ifAbsent: [ self at: aKey put: aBlock value ]
]

{ #category : #accessing }
OSEnvironment >> at: aKey ifPresent: aBlock [
"Gets the value of an environment variable called `aKey` and invoke aBlock with it.
Return nil if absent.
It is the system reponsibility to manage the encodings of the argument and return values.

This is the common denominator API for all platforms.
Rationale: Windows does not (compared to *nix systems) provide a encoded byte representation of the value. Windows has instead its own wide string representation."

^ aBlock value: (self at: aKey ifAbsent: [ ^ nil ])
]

{ #category : #accessing }
OSEnvironment >> at: key ifPresent: oneArgBlock ifAbsent: absentBlock [
"Lookup the given key in the receiver. If it is present, answer the value of evaluating the oneArgBlock with the value associated with the key, otherwise answer the value of absentBlock."
OSEnvironment >> at: aKey ifPresent: presentBlock ifAbsent: absentBlock [
"Gets the value of an environment variable called `aKey`.
Call presentBlock with it if present.
Execute absentBlock if absent.
It is the system reponsibility to manage the encodings of the argument and return values.

This is the common denominator API for all platforms.
Rationale: Windows does not (compared to *nix systems) provide a encoded byte representation of the value. Windows has instead its own wide string representation."

self at: key ifPresent: [ :v | ^oneArgBlock cull: v ].
self at: aKey ifPresent: [ :v | ^ presentBlock cull: v ].
^absentBlock value
]

{ #category : #accessing }
OSEnvironment >> at: aKey put: aValue [
^ self setEnv: aKey value: aValue
"Sets the value of an environment variable called `aKey` to `aValue`.
It is the system reponsibility to manage the encodings of both arguments.

This is the common denominator API for all platforms.
Rationale: Windows does not (compared to *nix systems) provide a encoded byte representation of the value. Windows has instead its own wide string representation."

^ self subclassResponsibility
]

{ #category : #enumeration }
Expand All @@ -135,26 +187,6 @@ OSEnvironment >> do: aBlock [
^self valuesDo: aBlock
]

{ #category : #accessing }
OSEnvironment >> getEnv: varName [

"This method calls the Standard C Library getenv() function."
"OSEnvironment current getEnv: 'HOME' "

<primitive: 'primitiveGetenv' module: '' error: ec>
ec ifNil: [ ^self getEnvViaFFI: varName ].
ec == #'bad argument' ifTrue: [
varName isString
ifFalse: [ ^self getEnv: varName asString ] ].
self primitiveFail
]

{ #category : #private }
OSEnvironment >> getEnvViaFFI: arg1 [
"This method calls the Standard C Library getenv() function. The name of the argument (arg1) should fit decompiled version."
^ self ffiCall: #( String getenv (String arg1) ) module: LibC
]

{ #category : #testing }
OSEnvironment >> includes: anObject [

Expand Down Expand Up @@ -207,8 +239,14 @@ OSEnvironment >> platform [
]

{ #category : #accessing }
OSEnvironment >> removeKey: key [
^ self unsetEnv: key
OSEnvironment >> removeKey: aKey [
"Removes the entry `aKey` from the environment variables.
It is the system reponsibility to manage the encoding of the argument.

This is the common denominator API for all platforms.
Rationale: Windows does not (compared to *nix systems) provide a encoded byte representation of the value. Windows has instead its own wide string representation."

^ self subclassResponsibility
]

{ #category : #accessing }
Expand Down
19 changes: 10 additions & 9 deletions src/System-OSEnvironments/PlatformIndependentEnvironment.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,23 @@ PlatformIndependentEnvironment class >> isDefaultFor: aPlatform [
^ false
]

{ #category : #private }
PlatformIndependentEnvironment >> getEnv: aVariableName [
{ #category : #accessing }
PlatformIndependentEnvironment >> at: aKey ifAbsent: aBlock [

^ nil
]

{ #category : #enumeration }
PlatformIndependentEnvironment >> keysAndValuesDo: aBlock [
{ #category : #accessing }
PlatformIndependentEnvironment >> at: aKey put: aValue [
"Do nothing"
]

{ #category : #private }
PlatformIndependentEnvironment >> setEnv: nameString value: valueString [
{ #category : #enumeration }
PlatformIndependentEnvironment >> keysAndValuesDo: aBlock [
"Do nothing"
]

{ #category : #private }
PlatformIndependentEnvironment >> unsetEnv: aString [
^ self setEnv: aString value: nil
{ #category : #accessing }
PlatformIndependentEnvironment >> removeKey: key [
"Do nothing"
]
Loading