How to retrieve the absolute path represented by a `Dir` object in Ruby? - ruby

I want to write a method that takes a Dir-object as argument and does something with it, and for that I need to know the absolute path represented by this object. How do I retrieve this information?
The solution I came with is something like File.absolute_path(dir.path) (dir is the Dir-object in question), which doesn't work if dir was instantiated with a relative path and the current working directory is different from the working directory at the time of the instantiation.

Related

Get FinalPath for any given UNC folder path (including NAS) and any per-user redirects

I need to figure out if a given (UNC) path actually points/ends/is the given path (directory).
Example: "\?\UNC\machine1\shared1". GetFinalPathNameByHandle will result in "\?\UNC\machine1\shared1".
However, if there's a symlink "sym" inside shared1 and the given path is "\?\UNC\machine1\shared1\sym", having "sym" be created with mklink and pointing to "\machine2\shared2", the result given by GetFinalPathNameByHandle is "\?\UNC\machine2\shared2".
Now, we have a QNAP NAS, with "home" folders enabled - meaning that each domain user, when navigating to "\nas\home", will end up in its own directory.
GetFinalPathNameByHandle for "\?\UNC\nas\home" results in "\?\UNC\nas\home", while I would need to get my hands on the actual directory name, like "\?\UNC\nas\homes\user_name". I do not need to read/write - I just need to know that "\?\UNC\nas\home" is really not "\?\UNC\nas\home".
This idea then propagates to any similar scenarios when "\machine\folder" ends up somewhere else (per user). Say I do not even need to know where does it really end, just that there's some kind of reparsing happening...
Any ideas?

How to check if two paths point to the same folder location Ruby?

I have the two folder paths as string. How to check if two paths point to same folder location. I do not want to compare the string as it will not be the proper way. I tried with File.identical? but it returns false as it seems to expect two file paths not folder paths as agruments. For your information, I want to use this code in Ruby filter plugin in Logstash
I don't see anything improper in comparing strings if they provide precise and correct location. If File.identical? doesn't work and Dir does't provide similar method, I would just convert the paths with File.realdirpath() and compare them.
File.realdirpath("first/path/") == File.realdirpath("second/path/")
It follows symlinks.
https://ruby-doc.org/core-2.5.0/File.html#method-c-realdirpath
If you are on a Unix-like system and really distrust string comparisons, you can compare inode numbers.
File.stat(File.realdirpath("first/path/")).ino == File.stat(File.realdirpath("second/path/")).ino
EDITED
Didn't notice your comment about being on Windows. I don't know how File::Stat exactly works there, but it should be available and using info it provides might be better than string comparison.
File.realpath(folder_path) == File.realpath(other_folder_path)
This method returns string with absolute pathname in the actual filesystem not containing symlinks or dots.
Unlike File.realdirpath, all components of the pathname must exist when this method is called.

For what paths is resolvingSymlinksInPath() wrong?

On macOS, /tmp is a symlink to /private/tmp, yet when I do this:
URL(fileURLWithPath: "/tmp").resolvingSymlinksInPath().path
it returns "/tmp".
(I've reported this to Apple, and they closed it as a duplicate, so they know about it already.)
Is it publicly known what paths have incorrect values returned by this method? If it's just a couple paths which are hardcoded internally, then it'd be easier to check for them, than to rewrite a working resolvingSymlinksInPath() from scratch.
See the documentation for resolvingSymlinksInPath:
If the name of the receiving path begins with /private, this property strips off the /private designator, provided the result is the name of an existing file.
So if the result is, say, /private/var and there is /var then that is what is returned.
This appears to be based on a convention only, there is no check that the resultant path references the same filesystem item. E.g. create /a, /private/a and sym link /test to /private/a then resolve symlinks for /test and the result is /a despite that not being the same as /private/a

how to reference a relative file from code and tests

I need to reference patients.json from patients.go, here's the folder structure:
If I do:
filepath.Abs("../../conf/patients.json")
it works for go test ./... but fails for revel run
If I do:
filepath.Abs("conf/patients.json")
the exact opposite happens (revel is fine but tests fail).
Is there a way to correctly reference the file so that it works both for tests and normal program run?
Relative paths are always interpreted / resolved to a base path: the current or working directory - therefore it will always have its limitations.
If you can live with always taking care of the proper working directory, you may keep using relative paths.
What I would suggest is to not rely on the working directory, but an explicitly specified base path. This may have a default value hard-coded in your application (which may be the working directory as well), and you should provide several ways to override its value.
Recommended ways to override the base path to which your "relative" paths are resolved against:
Command line flag (see flag package)
Environment variable (see os.Getenv())
(Fix named) Config file in user's home directory (see os/user/User and os/user/Current())
Once you have the base path, you can get the full path by joining the base path and the relative path. You may use path.Join() or filepath.Join(), e.g.:
// Get base path, from any or from the combination of the above mentioned solutions
base := "/var/myapp"
// Relative path, resource to read/write from:
relf := "conf/patients.json"
// Full path that identifies the resource:
full := filepath.Join(base, relf) // full will be "/var/myapp/conf/patients.json"
I've never used Revel myself but the following looks helpful to me:
http://revel.github.io/docs/godoc/revel.html
revel.BasePath
revel.AppPath
This is not the problem with path, but the problem with your design.
You should design your code more careful.
As far as I can tell, you share same path in your test file and reveal run. I guess that maybe you hard code your json path in your model package which is not suggested.
Better way is
model package get json path from global config, or init model with json path like model := NewModel(config_path). so reveal run can init model with any json you want.
hard code "../../conf/patients.json" in your xxxx_testing.go

Given two directory names, how can I get relative name of one as if another is working dir in Ruby?

In my Rails application, I need to create a symlink between two files inside RAILS_ROOT. The names of target and symlink are given as absolute paths. However, I want to create a symlink that uses relative paths, so the application folder could easily be moved.
In other words, from RAILS_ROOT/path/foo/bar and RAILS_ROOT/path/baz I want to get ../../baz as an answer.
Is there a library function (or a simple one-liner) to do that?
Try the relative_path_from method of a Pathname.

Resources