|
My justification for modifying #/ to accept a path:
Pharo's FileSystem behaviour is currently somewhat inconsistent in its treatment of path strings.
To be able to demonstrate the limitations and fixes, I'm assuming that the following files and directories have been created (/dev/shm is a memory based file system in Ubuntu):
cd /dev/shm mkdir -p d1/d2/d3/d4 touch d1/t1.txt d1/d2/t2.txt d1/d2/d3/t3.txt d1/d2/d3/d4/t4.txt pushd d1 && ln -s d2/d3 ./s3 && popd
1. Path's are canonicalised during initial creation, but are not when extending the path, i.e. sending #/
E.g.
'/dev/shm/d1/d2/../t1.txt' asFileReference " File @ /dev/shm/d1/t1.txt"
'/dev/shm/d1/' asFileReference / 'd2/../t1.txt' " File @ /dev/shm/d1/d2/../t1.txt"
Automatic canonicalisation is problematic as the code doesn't handle symbolic links in the path name:
('/dev/shm/d1/' asFileReference / 's3/../t2.txt') exists " true (correct answer)"
'/dev/shm/d1/s3/../t2.txt' asFileReference exists " false (wrong answer)"
(Note: I'm not expecting that the code is written like this, it is more likely that the FileReference is created early in the code and the argument to #/ is external input at a later stage).
2. In an attempt to be completely general, the argument to #/ is assumed to be a single directory / file. This is incorrect as the path delimiter is not allowed to be part of the file name. The result is that path comparisons and operations such as #parent give unexpected results.
E.g.
('/dev/shm/d1/' asFileReference / 'd2/d3/t3.txt') exists " true"
('/dev/shm/d1/' asFileReference / 'd2/d3/t3.txt') parent " File @ /dev/shm/d1"
The PR modifies FileSystem so that the argument to #/ can be either a single file / directory name or a path.
('/dev/shm/d1/' asFileReference / 'd2/d3/t3.txt') parent " File @ /dev/shm/d1/d2/d3"
Note that the argument to #/ is interpreted using the platforms delimiter, so on Windows the parameter would be 'd2\d3\t3.txt'.
The argument has also been put forward that limiting the parameter to #/ to a single file / directory is a more general abstraction than allowing a path in the parameter. However I believe the programmers rule of being strict in what you write and forgiving in what you read is more useful here.
Ensuring that the parameter to #/ is always a single file / directory, i.e. raising an exception if it is a path, would also have the side effect of meaning that #resolve(String): is almost always used, #/ effectively redundant, and the code more verbose.
The changes here mean that the result is always canonicalized, i.e. '..' is interpreted as the parent, and the path adjusted accordingly. As mentioned above, this means that symbolic links may not be handled correctly. A separate patch will be submitted to make canonicalization something that must be requested explicitly.
Two unit tests have been added to test the new behaviour:
PathTest>>testExtendingPath PathTest>>testRedundantSeparators
Pull request to follow.
|
|
|
Priority: 5 – Fix If Time
|
|
Status: Work Needed
|
|
Assigned to: Everyone
|
|
Milestone: Later
|
Go to Case
|
|