# # patch "ChangeLog" # from [3a0e32ed3a064d26c81d2d1affc2335b4e668277] # to [729a2feb8126ceb535788322375a2187edcf1b77] # # patch "file_io.cc" # from [68a03f78673d99799fbe6bb6aed82506f197453b] # to [bf552b49ffcb68e946a2ca83d5441a7477b1ff3a] # # patch "file_io.hh" # from [8187a0cdf077dcc00e0929ed7e4c7b264acce4b4] # to [ca3c031befba5c81ab31262211c7268ac1b78039] # # patch "platform.hh" # from [89dbdd8d45cc395f744340d13a1497c21446ee26] # to [b2b68efdf344078c3a266da9baa911c9e512a6c3] # # patch "unix/fs.cc" # from [c197a57ee859a1240973b0f2b47f433706d36178] # to [d3e7a538118693060b9b031fcb717f32cd5b7bc2] # # patch "win32/fs.cc" # from [36d73e1ea0457bac949e35945c0e51bb72971e4c] # to [509e2c22115d934a7ab7bf128b742a92f0e4df94] # ======================================================================== --- ChangeLog 3a0e32ed3a064d26c81d2d1affc2335b4e668277 +++ ChangeLog 729a2feb8126ceb535788322375a2187edcf1b77 @@ -1,5 +1,10 @@ 2005-08-25 Nathaniel Smith - + + * platform.hh (tilde_expand): New function. + * win32/fs.cc, unix/fs.cc: Implement it. + +2005-08-25 Nathaniel Smith + * paths.cc: Many more fixes. Now compiles with and without unit tests. ======================================================================== --- file_io.cc 68a03f78673d99799fbe6bb6aed82506f197453b +++ file_io.cc bf552b49ffcb68e946a2ca83d5441a7477b1ff3a @@ -24,13 +24,6 @@ string const book_keeping_dir("MT"); -#include -#include -#ifndef WIN32 - #include -#endif -#include - string get_homedir() { @@ -90,26 +83,6 @@ } string -absolutify(string const & path) -{ - fs::path tmp = mkpath(path); - if (! tmp.has_root_path()) - tmp = fs::current_path() / tmp; - I(tmp.has_root_path()); - tmp = tmp.normalize(); - return tmp.string(); -} - -string -absolutify_for_command_line(string const & path) -{ - if (path == "-") - return path; - else - return absolutify(path); -} - -string tilde_expand(string const & path) { fs::path tmp = mkpath(path); ======================================================================== --- file_io.hh 8187a0cdf077dcc00e0929ed7e4c7b264acce4b4 +++ file_io.hh ca3c031befba5c81ab31262211c7268ac1b78039 @@ -40,8 +40,6 @@ struct lua_hooks; -system_path get_homedir(); - // use I() void assert_path_is_nonexistent(any_path const & path); void assert_path_is_file(any_path const & path); @@ -112,9 +110,6 @@ virtual ~tree_walker(); }; -// from cwd (nb: we can't describe cwd as a file_path) -void walk_tree(tree_walker & walker); - // from some safe sub-dir of cwd void walk_tree(file_path const & path, tree_walker & walker, ======================================================================== --- platform.hh 89dbdd8d45cc395f744340d13a1497c21446ee26 +++ platform.hh b2b68efdf344078c3a266da9baa911c9e512a6c3 @@ -52,5 +52,5 @@ std::string get_current_working_dir(); // calls N() if fails void change_current_working_dir(any_path const & to); - +utf8 tilde_expand(utf8 const & path); #endif // __PLATFORM_HH__ ======================================================================== --- unix/fs.cc c197a57ee859a1240973b0f2b47f433706d36178 +++ unix/fs.cc d3e7a538118693060b9b031fcb717f32cd5b7bc2 @@ -5,7 +5,13 @@ #include #include +#include +#include +#include +#include +#include + #include "sanity.hh" #include "platform.hh" @@ -22,3 +28,50 @@ E(!chdir(to.as_external().c_str()), F("cannot change to directory %s: %s") % to % strerror(errno)); } + +// FIXME: BUG: this probably mangles character sets +// (as in, we're treating system-provided data as utf8, but it's probably in +// the filesystem charset) +static utf8 +get_homedir() +{ + char * home = getenv("HOME"); + if (home != NULL) + return string(home); + + struct passwd * pw = getpwuid(getuid()); + N(pw != NULL, F("could not find home directory for uid %d") % getuid()); + return string(pw->pw_dir); +} + +utf8 tilde_expand(utf8 const & in) +{ + fs::path tmp(in(), fs::native); + fs::path::iterator i = tmp.begin(); + if (i != tmp.end()) + { + fs::path res; + if (*i == "~") + { + res /= mkpath(get_homedir()); + ++i; + } + else if (i->size() > 1 && i->at(0) == '~') + { + struct passwd * pw; + // FIXME: BUG: this probably mangles character sets (as in, we're + // treating system-provided data as utf8, but it's probably in the + // filesystem charset) + pw = getpwnam(i->substr(1).c_str()); + N(pw != NULL, + F("could not find home directory for user %s") % i->substr(1)); + res /= string(pw->pw_dir); + ++i; + } + while (i != tmp.end()) + res /= *i++; + return res.string(); + } + + return tmp; +} ======================================================================== --- win32/fs.cc 36d73e1ea0457bac949e35945c0e51bb72971e4c +++ win32/fs.cc 509e2c22115d934a7ab7bf128b742a92f0e4df94 @@ -6,6 +6,10 @@ #include #include +#include +#include +#include + #include "sanity.hh" #include "platform.hh" @@ -22,3 +26,75 @@ E(!chdir(to.as_external().c_str()), F("cannot change to directory %s: %s") % to % strerror(errno)); } + +// FIXME: BUG: this probably mangles character sets +// (as in, we're treating system-provided data as utf8, but it's probably in +// the filesystem charset) +static utf8 +get_homedir() +{ + // Windows is fun! + // See thread on monotone-devel: + // Message-Id: + // URL: http://lists.gnu.org/archive/html/monotone-devel/2005-02/msg00241.html + char * home; + L(F("Searching for home directory\n")); + // First try MONOTONE_HOME, to give people a way out in case the cruft below + // doesn't work for them. + home = getenv("MONOTONE_HOME"); + if (home != NULL) + { + L(F("Home directory from MONOTONE_HOME\n")); + return std::string(home); + } + // If running under cygwin or mingw, try HOME next: + home = getenv("HOME"); + char * ostype = getenv("OSTYPE"); + if (home != NULL + && ostype != NULL + && (std::string(ostype) == "cygwin" || std::string(ostype) == "msys")) + { + L(F("Home directory from HOME\n")); + return std::string(home); + } + // Otherwise, try USERPROFILE: + home = getenv("USERPROFILE"); + if (home != NULL) + { + L(F("Home directory from USERPROFILE\n")); + return std::string(home); + } + // Finally, if even that doesn't work (old version of Windows, I think?), + // try the HOMEDRIVE/HOMEPATH combo: + char * homedrive = getenv("HOMEDRIVE"); + char * homepath = getenv("HOMEPATH"); + if (homedrive != NULL && homepath != NULL) + { + L(F("Home directory from HOMEDRIVE+HOMEPATH\n")); + return std::string(homedrive) + std::string(homepath); + } + // And if things _still_ didn't work, give up. + N(false, F("could not find home directory (tried MONOTONE_HOME, HOME (if " + "cygwin/mingw), USERPROFILE, HOMEDRIVE/HOMEPATH")); +} + +utf8 +tilde_expand(utf8 const & path) +{ + fs::path tmp(path, fs::native); + fs::path::iterator i = tmp.begin(); + if (i != tmp.end()) + { + fs::path res; + if (*i == "~" || i->size() > 1 && i->at(0) == '~') + { + res /= mkpath(get_homedir()); + ++i; + } + while (i != tmp.end()) + res /= mkpath(*i++); + return res.string(); + } + + return tmp.string(); +}