Opened 14 years ago

Closed 7 years ago

#1976 closed Feature Requests (fixed)

Inverse function for complete

Reported by: me22.ca+boost@… Owned by: Beman Dawes
Milestone: Boost 1.60.0 Component: filesystem
Version: Boost 1.35.0 Severity: Problem
Keywords: Cc: taylor@…, boost@…

Description

As mentioned in the '[boost] [filesystem] "leaf"' thread, complete is the only path composition function without a corresponding decomposition function.

The idea: uncomplete(/foo/new, /foo/bar) => ../new

The use case for this is any time you get a full path (from an open dialog, perhaps) and want to store a relative path so that the group of files can be moved to a different directory without breaking the paths. An IDE would be a simple example, so that the project file could be safely checked out of subversion.

I'd like to call it relative, but that conceptually conflicts with the relative_path member decomposition function. Perhaps the member function could be changed to local_path(), or something.

A discussion will need to be held to determine expected behaviour in the presence of symlinks, since root/foo/bar/.. is not always root/foo.

Change History (16)

comment:1 by me22.ca+boost@…, 14 years ago

An additional use case for this came up on the users list: http://lists.boost.org/boost-users/2008/08/39597.php

The use case here is creating complete output paths for "copy-pasting a sub-tree from input_base_path to output_base_path" (ofcourse with some transformations along the way).

For now, I am using

  fs::wpath output_path=output_base_path;
  int k=0; for(fs::wpath::iterator
i=input_path.begin();i!=input_path.end();i++,k++) if(k>=7)
output_path/=(*i);

Again, 7 is the number of elements in input_base_path. advance() would make it atleast slightly cleaner (remove k, and the if on k), uncomplete would be ideal.

comment:2 by anonymous, 14 years ago

Here's a naive implementation (that doesn't handle symlinks and isn't well tested):

#include <boost/filesystem.hpp>

boost::filesystem::path
naive_uncomplete(boost::filesystem::path const path, boost::filesystem::path const base) {
    if (path.has_root_path()){
        if (path.root_path() != base.root_path()) {
            return path;
        } else {
            return naive_uncomplete(path.relative_path(), base.relative_path());
        }
    } else {
        if (base.has_root_path()) {
            throw "cannot uncomplete a path relative path from a rooted base";
        } else {
            typedef boost::filesystem::path::const_iterator path_iterator;
            path_iterator path_it = path.begin();
            path_iterator base_it = base.begin();
            while ( path_it != path.end() && base_it != base.end() ) {
                if (*path_it != *base_it) break;
                ++path_it; ++base_it;
            }
            boost::filesystem::path result;
            for (; base_it != base.end(); ++base_it) {
                result /= "..";
            }
            for (; path_it != path.end(); ++path_it) {
                result /= *path_it;
            }
            return result;
        }
    }
}

in reply to:  description comment:3 by anonymous, 14 years ago

I would like this functionality to be added as well. My use case is similar to the first one mentioned (wanting to persist relative paths).

comment:4 by anonymous, 14 years ago

Getting paths relative to an arbitrary directory is a very useful feature. My use case is the same at the first one (it is an IDE which needs to store paths relative to project file).

comment:5 by tom@…, 13 years ago

I would like this for a media application which should save lines in an M3U playlist as filepaths relative to the playlist path.

comment:6 by anonymous, 12 years ago

This would be useful for me as well.

comment:7 by anonymous, 12 years ago

This feature would be very useful for us, too. In a use case similar to the first one.

comment:8 by sorokin@…, 11 years ago

Is there any plans to include this function is boost? Maybe under name relativize?

comment:9 by Taylor Braun-Jones <taylor@…>, 11 years ago

Cc: taylor@… added

comment:10 by anonymous, 10 years ago

I'm interested in this feature too.

comment:11 by Chris Pick <boost@…>, 10 years ago

Cc: boost@… added

comment:12 by anonymous, 9 years ago

There a quite a few links on the internet linking here. This would be a great feature. I'd wonder how to make this portable though with drive letters on windows, reparse points, symlinks on *nix...

comment:13 by anonymous, 9 years ago

There's an example at https://svn.boost.org/trac/boost/ticket/6249 , it relies only on lexicographic compare so doesn't handle links etc, but on the other hand I think the expected behavior of such a function is that it's entirely lexicographic on the path.

comment:14 by slowriot <riot@…>, 8 years ago

+1 for this as well

comment:15 by anonymous, 7 years ago

I also need this!

comment:16 by Beman Dawes, 7 years ago

Milestone: Boost 1.36.0Boost 1.60.0
Resolution: fixed
Status: newclosed

Boost 1.60.0 will add functions lexically_normal, lexically_relative, relative, and weakly_canonical. These are designed to provide the functionality requested by this ticket.

See http://boostorg.github.io/filesystem/relative_proposal.html for more information. It proposes additional lexical and operational proximate functions, but I have chosen not to include those now. They will be reconsidered once users get some field experience with the core functionality for computing relative paths.

These function are available now on the https://github.com/boostorg/filesystem develop branch, and will be merged to master as soon as sufficient regression tests have cycled. They will also be proposed for inclusion in the next version of the C++ committee's TS 18822, File System Technical Specification.

Many thanks to Jamie Allsop for his help and perseverance, and to everyone else who made suggestions and comments. Jamie's paper is available at https://github.com/ja11sop/std-filesystem-relative

Thanks,

--Beman

Note: See TracTickets for help on using tickets.