# # patch "ChangeLog" # from [155dafa653a18847a962af21b5406b5881f0881c] # to [a5dafa1ffb333c3848b1bccb92f51ce60673ddb0] # # patch "file_io.hh" # from [83ef00a480c3187cb1ee240278659773fa130b39] # to [f104a889390ecd8eb031a56a81862cfef3aec01a] # # patch "paths.hh" # from [16661900264cb8d876b8a98b0adde390bda5d88c] # to [0c935d21c18770ef295b3580e53b9171e124c80a] # ======================================================================== --- ChangeLog 155dafa653a18847a962af21b5406b5881f0881c +++ ChangeLog a5dafa1ffb333c3848b1bccb92f51ce60673ddb0 @@ -1,5 +1,10 @@ 2005-08-26 Nathaniel Smith + * file_io.hh: Remove comment describing old path types. + * paths.hh: Add comment describing new path types. + +2005-08-26 Nathaniel Smith + * app_state.cc (create_working_copy): Remove fs::filesystem_exception catching. * file_io.hh (mkdir_p): Remove comment noting app_state.cc's ======================================================================== --- file_io.hh 83ef00a480c3187cb1ee240278659773fa130b39 +++ file_io.hh f104a889390ecd8eb031a56a81862cfef3aec01a @@ -13,31 +13,11 @@ // this layer deals with talking to the filesystem, loading and saving // files, walking trees, etc. -// -// we have *three* types of file path we're willing to deal with. -// -// - a boost::filesystem::path (fs::path) -// [ defined in boost/filesystem/path.hpp ] -// this is a generally portable path to anywhere in the fs -// -// - a local_path -// [ defined in vocab.{hh,cc} ] -// this is a path to a file in-or-under the current directory; it doesn't -// escape cwd, and it's name restrictions are tighter than an fs::path, -// as far as illegal characters and junk -// -// - a file_path -// [ defined in vocab.{hh,cc} ] -// this is a local_path which is *not* in the MT/ book-keeping -// directory. in other words, it's a local_path which may permissibly be -// part of a manifest. -// -// several functions in *this* file are defined on more than one of these -// sorts of paths. the reason for the multiple path types is to avoid ever -// constructing (and "forgetting to check the validity" of) an illegal -// value in *other* parts of the code. this file contains stuff which is so -// low level we can't mostly know whether what's being asked for is legal. +// this code mostly deals in any_path's, because these operations are too low +// level for us to say whether applying them in any given case is valid or +// not. + struct lua_hooks; // use I() @@ -64,11 +44,10 @@ bool ident_existing_file(file_path const & p, file_id & ident, lua_hooks & lua); -// returns true if the string content is binary according to monotone euristic +// returns true if the string content is binary according to monotone heuristic bool guess_binary(std::string const & s); void mkdir_p(any_path const & path); - void make_dir_for(any_path const & p); void delete_file(any_path const & path); ======================================================================== --- paths.hh 16661900264cb8d876b8a98b0adde390bda5d88c +++ paths.hh 0c935d21c18770ef295b3580e53b9171e124c80a @@ -6,8 +6,98 @@ // licensed to the public under the terms of the GNU GPL (>= 2) // see the file COPYING for details -// safe, portable, fast, simple file handling -- in that order +// safe, portable, fast, simple path handling -- in that order. +// but they all count. +// +// this file defines the vocabulary we speak in when dealing with the +// filesystem. this is an extremely complex problem by the time one worries +// about normalization, security issues, character sets, and so on; +// furthermore, path manipulation has historically been a performance +// bottleneck in monotone. so the goal here is the efficient implementation +// of a design that makes it hard or impossible to introduce as many classes +// of bugs as possible. +// +// Our approach is to have three different types of paths: +// -- system_path +// this is a path to anywhere in the fs. it is in native format. it is +// always absolute. when constructed from a string, it interprets the +// string as being relative to the directory that monotone was run in. +// (note that this may be different from monotone's current directory, as +// when run in working copy monotone chdir's to the project root.) +// +// one can also construct a system_path from one of the below two types +// of paths. this is intelligent, in that it knows that these sorts of +// paths are considered to be relative to the project root. thus +// system_path(file_path_internal("foo")) +// is not, in general, the same as +// system_path("foo") +// +// -- file_path +// this is a path representing a versioned file. it is always +// a fully normalized relative path, that does not escape the project +// root. it is always relative to the project root. +// you cannot construct a file_path directly from a string; you must pick +// a constructor: +// file_path_internal: use this for strings that come from +// "monotone-internal" places, e.g. parsing revisions. this turns on +// stricter checking -- the string must already be normalized -- and +// is extremely fast. such strings are interpreted as being relative +// to the project root. +// file_path_external: use this for strings that come from the user. +// these strings are normalized before being checked, and if there is +// a problem trigger N() invariants rather than I() invariants. such +// strings are interpreted as being _relative to the user's original +// directory_. this function can only be called from within a +// working copy. +// file_path_internal_from_user: use this for strings that come from +// the user, _but_ are not referring to paths in the working copy, +// but rather in some database object directly. for instance, 'cat +// file REV PATH' uses this function. this function is exactly like +// file_path_internal, except that it raises N() errors rather than +// I() errors. +// file_path's also provide optimized splitting and joining +// functionality. +// +// -- bookkeeping_path +// this is a path representing something in the MT/ directory of a +// working copy. it has the same format restrictions as a file_path, +// except instead of being forbidden to point into the MT directory, it +// is _required_ to point into the MT directory. the one constructor is +// strict, and analogous to file_path_internal. however, the normal way +// to construct bookkeeping_path's is to use the global constant +// 'bookkeeping_root', which points to the MT directory. Thus to +// construct a path pointing to MT/options, use: +// bookkeeping_root / "options" +// +// All path types should always be constructed from utf8-encoded strings. +// +// All path types provide an "operator /" which allows one to construct new +// paths pointing to things underneath a given path. E.g., +// file_path_internal("foo") / "bar" == file_path_internal("foo/bar") +// +// All path types subclass 'any_path', which provides: +// -- emptyness checking with .empty() +// -- a method .as_internal(), which returns the utf8-encoded string +// representing this path for internal use. for instance, this is the +// string that should be embedded into the text of revisions. +// -- a method .as_external(), which returns a std::string suitable for +// passing to filesystem interface functions. in practice, this means +// that it is recoded into an appropriate character set, etc. +// -- a operator<< for ostreams. this should always be used when writing +// out paths for display to the user. at the moment it just calls one +// of the above functions, but this is _not_ correct. there are +// actually 3 different logical character sets -- internal (utf8), +// user (locale-specific), and filesystem (locale-specific, except +// when it's not, i.e., on OS X). so we need three distinct operations, +// and you should use the correct one. +// +// all this means that when you want to print out a path, you usually +// want to just say: +// F("my path is %s") % my_path +// i.e., nothing fancy necessary, for purposes of F() just treat it like +// it were a string + #include #include #include