First non-trivial change for a while... because this involves reading from the OS, we should cache as much as we can in memory. So, group membership checking is done immediately after reading a group name, as the group structure has already been populated.
Curiously enough, this turned out to be helpful today... Git can't
traverse symlinks, so I had to use hard links instead, and then I had to
work out which files had more than one link at a glance. If I hadn't
already had most of exa written, I'd be stuck using find!
This requires the dir field to store a reference to the path that
created it, so that path can be used to join onto the filename so it can
be properly statted.
There doesn't seem to be an io::FileType entry for character special
devices or sockets, so these fall under the io::UnknownType entry. Which
also gets highlighted in yellow, for precisely that reason.
Dir::readdir and File::from path now both return IoResults, rather than just calling fail! and exiting. This allows the program to continue after an error.
I'd much rather have this separate, as it has the definite potential to
balloon up to a huge size and end up making the other parts of the file
module hard to read. But on the other hand, it meant making a few more
methods public on file... readability over cleanliness, I guess.
This new object is then passed down to the File, so it can see what files are around it. This means it doesn't need to re-query the filesystem several times per file, instead using the in-memory copy.
Also, switch to using the built-in Path#with_extension method.
And an extra level of compiled files that don't get highlighted when their source files aren't present. I don't really like having two functions that do (almost) the same thing, but I have to due to the way colouring is done.
Compiled files with a source present (such as code.o when code.c is present) are now classified as temporary files. If the source isn't present, they're highlighted in a kind of drab colour (using the new 255-colour ability, yay!)
The code does do exists() checks on the filesystem when it could be possible to compare the files to the list of files we got from the call to readdir(), but it doesn't.