Giter VIP home page Giter VIP logo

Comments (3)

aruhier avatar aruhier commented on July 28, 2024

@ajeetdsouza: FYI, I'm working on this feature and will do a PR soon.

I was just a bit disappointed that std::fs doesn't have a function that gives the absolute path of a target without resolving the symlinks, so I had to quickly workaround it.

from zoxide.

ajeetdsouza avatar ajeetdsouza commented on July 28, 2024

@aruhier I've done some work on this too. It turns out that finding normalized paths including symlinks is a non-trivial task - there was even a PR to add it into Rust at one point, but it was closed because it could not pass all the test cases due to Path::components not being 100% accurate.

The most obvious approach would be to manually parse and write your own path normalizer. This is easy on Linux; on Windows, not so much. See this to know how messy it can get. On the bright side, this is slightly simplified by the fact that we don't have to handle UNC paths.

However, there are easier ways of doing this (I think), especially since we do want to interactive with the filesystem to validate the existence of the resultant path.

I came up with the following (admittedly hacky) ways of solving this:

  • On Windows, env::set_current_dir() followed by env::current_dir() seems to return a normalized path without resolving symlinks, and fails if the path isn't valid - perfect for our use case.

  • However, env::current_dir() uses getcwd() under the hood, which on POSIX, is required to resolve symlinks. The upside here is that most shells also set the PWD environment variable, which does not resolve symlinks. So, we can validate PWD as an absolute path and fallback to env::current_dir() if the path is invalid. This is exactly what the pwd utility does.

  • Alternatively, we can solve this problem on POSIX systems by imitating realpath -ms, adding a validation check to see if the resultant path currently exists.

Do let me know your thoughts.

from zoxide.

aruhier avatar aruhier commented on July 28, 2024

I came up with the following (admittedly hacky) ways of solving this:

* On Windows, `env::set_current_dir()` followed by `env::current_dir()` seems to return a normalized path without resolving symlinks, and fails if the path isn't valid - perfect for our use case.

* However, `env::current_dir()` uses `getcwd()` under the hood, which on POSIX, is required to resolve symlinks. The upside here is that most shells also set the `PWD` environment variable, which does not resolve symlinks. So, we can validate `PWD` as an absolute path and fallback to `env::current_dir()` if the path is invalid. This is exactly what the [`pwd`](https://github.com/wertarbyte/coreutils/blob/master/src/pwd.c) utility does.

That's exactly what I wanted to do on my side. Here is what I wrote for the moment to get the absolute_path from a base_dir:

pub fn absolute_path<P: AsRef<Path>>(base_dir: &P, path: &P) -> Result<PathBuf> {
    let path = path.as_ref();
    let mut abs_path : PathBuf;

    // If path is an absolute path, base_dir is not needed.
    // "absolute" does not mean the path is clean (can be "/foo/../bar"), cleaning the path is still needed.
    if path.is_absolute() {
        abs_path = PathBuf::from(Component::RootDir.as_os_str())
    } else {
        abs_path = PathBuf::from(base_dir.as_ref());
    }

    for c in path.components() {
        match c {
            Component::CurDir | Component::RootDir => {},
            Component::ParentDir => {
                if abs_path.parent() != None {
                    abs_path.pop();
                }
            }
            _ => {
                abs_path.push(PathBuf::from(c.as_os_str()));
            }
        }
    }

    Ok(abs_path)
}

I planned to send env::current_dir() for the base_dir, and clean the path for windows with https://docs.rs/dunce/1.0.1/dunce/fn.simplified.html.

Edit: words.

from zoxide.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.