zinc icon indicating copy to clipboard operation
zinc copied to clipboard

Is asZnUrl implemented correctly for FileReferences?

Open kasperosterbye opened this issue 3 years ago • 9 comments

@Ducasse and I ran into a peculiar error today, not sure if the problem is mine or yours :-)

The situation an absolute path, for example '/Users/kasper/tmp'. Assuming the directory tmp exist, I get '/Users/kasper/tmp' asFileReference isDirectory to be true. However, '/Users/kasper/tmp' asFileReference asZnUrl isDirectoryPath returns false.

The reason for the difference is that the implementation of asZnUrl for file references are based on paths

AbstractFilePath>>asZnUrl
	^ self asAbsolute path asZnUrl

Basing the implementation on the path looses the information that '/Users/kasper/tmp' is a directory.

We have a chokepoint in our code which will allow us to encapsulate this, so we can work around our specific problem. But the question is if the implementation above should really be:

AbstractFilePath>>asZnUrl
	^ self isDirectory 
		ifTrue: [ ('file:',self pathString , '/') asZnUrl ]
		ifFalse: [ self asAbsolute path asZnUrl ]

I am sure you know a better implementation, but this seems to work - that is '/Users/kasper/tmp' asFileReference asZnUrl isDirectoryPath returns true

kasperosterbye avatar Jul 27 '22 16:07 kasperosterbye

This is difficult. I do not think there is a real solution here.

At least on macOS and other Unix based systems, a path to something can be both a file or a directory. Which one depends on the actual thing on the file system. It cannot be determined from the path alone, you have to ask the OS, look at the file system.

This is what FileReference does.

The trailing slash is a way to make clear this difference, just by looking at the path, that is what ZnUrl does. It should be possible to work with a URL without having access to the file system / OS itself.

Now, the suggested change could make sense, I don't know for sure. I need to think about this a bit. Input from others might be useful too.

svenvc avatar Jul 29 '22 10:07 svenvc

The trailing slash is a way to make clear this difference, just by looking at the path, that is what ZnUrl does. It should be possible to work with a URL without having access to the file system / OS itself.

The solution I ended up with in our code is a variant of the above:

	| znUrl |
	znUrl := aFileReference asZnUrl.
	aFileReference isDirectory 
		ifTrue: [ znUrl addPathSegment: $/ "a Character not a string!?" ].

So while one cannot tell a directory from a file in a pure path, here the starting point is a filereference, and thus we just needed a way to keep alive its directoryness.

We have our issue isolated, but thought it might be worth for you to consider.

kasperosterbye avatar Jul 29 '22 14:07 kasperosterbye

I understand. But my point is that doing #isDirectory on a FileReference is accessing OS/filesystem info that is not obvious from the path alone. This means you can only do it on a (local) machine where that directory actually exists (and is accessible). I could want to work with paths that do not (yet/locally) exist.

But I do not known what the best answer is. It probably depends on the use case.

svenvc avatar Jul 29 '22 14:07 svenvc

Indeed only on local machine. The situation is that /User/kasper/tmp asFileReference isDirectory is true, whereas /User/kasper/foo asFileReference isDirectory is not (I do not have a foo directory).

Let the issue rest for a while - soliciting others input is also a good idea as you suggested.

kasperosterbye avatar Jul 29 '22 15:07 kasperosterbye

May be sven the solution is to provide a solution to configure the ZnUrl to be a directory when the use knows it. Because in our case, we know that the basedirectory is a directory so we could set it using a setAsDirectory kind of message and if ZnUrl use this information to resolve correctly then it would be already a step forward.

Ducasse avatar Jul 31 '22 10:07 Ducasse

May be sven the solution is to provide a solution to configure the ZnUrl to be a directory when the use knows it. Because in our case, we know that the basedirectory is a directory so we could set it using a setAsDirectory kind of message and if ZnUrl use this information to resolve correctly then it would be already a step forward.

There is such a method, it is called #closePath this adds a trailing slash to the path if there is not already one present, effectively making sure that #isDirectoryPath returns true.

svenvc avatar Aug 01 '22 09:08 svenvc

Ahhhhh I would have never guess it. So this is good to know.

Ducasse avatar Aug 03 '22 07:08 Ducasse

Yeah, the name is maybe a bit strange, don't forget that URLs are for much more than just file references.

We could add an alias in the future, but maybe that is not really needed.

svenvc avatar Aug 03 '22 11:08 svenvc

Yeah, the name is maybe a bit strange, don't forget that URLs are for much more than just file references.

So true! But it is also for file references - which is while I suggested FileReference>>asZnUrl to localise the file specific behaviour so it will not bleed into ZnUrl as such.

kasperosterbye avatar Aug 03 '22 11:08 kasperosterbye