Skip to content

GtFileBrowserFolderTool class>>#forFolder: fails for FileLocator>>#temp #4870

@iriyak

Description

@iriyak

Summary

When inspecting the FileReference in Gt for FileLocator>>#temp we get an error as indicating the path cannot be read.

Image

Description

When a Windows user account has a long username (e.g. Marcus R. Greek), the TEMP and TMP environment variables contain the 8.3 shortened form (MARCUS~1.GRE) instead of the full username. WindowsResolver>>#temp returns the same shortened path via WinPlatform>>#getTempPath, which calls the Windows API GetTempPathW.

GtFileBrowserFolderTool class>>#forFolder: reported the FileReference returned by WindowsResolver>>#temp whose pathString was C:\Users\MARCUS~1.GRE\AppData\Local\Temp as "Not able to read the path to the given folder". This occurs because Gt's folder matching logic expects long-form paths and doesn't recognize the shortened path as matching any existing folder model.

Proposed Solution

A proposed solution has been posted to pharo-project/pharo#18961 to normalize paths to long-form format regardless of where they came from. This would resolve the issue at the WinPlatform level.

Alternative approach (not recommended)

GtFileBrowserFoldersModel>>#findFileBrowserFolderModel:ifFound:ifNone: could be modified to handle this edge case by comparing both long and shortened path forms. However, this approach degrades performance because it checks every path even though most paths are in long-form format.

Implementation details:
FileReference>>#shortenedName

shortenedName
	"Return the shortened full path name of the receiver."

	| platform buffer r |
	platform := OSPlatform current.
	buffer := Win32WideString new: platform defaultMaximumPathLength.
	r := platform
			getShortPathName: self pathString asWin32WideString
			buffer: buffer
			size: platform defaultMaximumPathLength.
	r = 0
		ifTrue: [ self error: 'Error while calling getShortPathName() for ' , self pathString ].
	^ buffer asString

WinPlatform>>#getShortPathName:buffer:size:

getShortPathName: lpszLongPath buffer: lpszShortPath size: cchBuffer
	self
		ffiCall: #(long GetShortPathNameW #(Win32WideString lpszLongPath , void * lpszShortPath , ulong cchBuffer))

GtFileBrowserFoldersModel>>#findFileBrowserFolderModel:ifFound:ifNone:

findFileBrowserFolderModel: aFolder ifFound: aFoundBlock ifNone: aNoneBlock
	"Find a child object based on the child model and evaluate aFoundBlock if such child was found,
	aNoneBlock otherwise."

	<return: #Object>
	<generatedFrom: #'TGtRobocoderMetamodelChildrenForManyWithModelTemplate>>#findObjectIfFoundIfNoneTemplate'>
	^ self fileBrowserFolderModels
		detect: [ :eachFileBrowserFolderModel | 
			aFolder fileSystem isCaseSensitive
				ifTrue: [ eachFileBrowserFolderModel fileReference = aFolder ]
				ifFalse: [ OSPlatform current isWindows
						ifTrue: [ (eachFileBrowserFolderModel fileReference pathString
								sameAs: aFolder pathString)
								or: [ eachFileBrowserFolderModel fileReference shortenedName
										sameAs: aFolder shortenedName ] ]
						ifFalse: [ eachFileBrowserFolderModel fileReference pathString
								sameAs: aFolder pathString ] ] ]
		ifFound: aFoundBlock
		ifNone: aNoneBlock

History

Originally reported at https://discord.com/channels/729445214812504107/736333725788274819/1377959221395718185.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions