diff -x '*.info*' -uNr monotone-0.25/file_io.cc monotone-0.25-ignore-symlink/file_io.cc --- monotone-0.25/file_io.cc 2005-12-30 18:10:34.000000000 +0100 +++ monotone-0.25-ignore-symlink/file_io.cc 2006-01-05 23:19:01.000000000 +0100 @@ -43,6 +43,13 @@ } void +assert_path_is_symlink(any_path const & path) +{ + I(get_path_status(path) == path::symlink); +} + + +void require_path_is_nonexistent(any_path const & path, boost::format const & message) { @@ -52,7 +59,7 @@ void require_path_is_file(any_path const & path, boost::format const & message_if_nonexistent, - boost::format const & message_if_directory) + boost::format const & message_unless_file) { switch (get_path_status(path)) { @@ -61,8 +68,8 @@ break; case path::file: return; - case path::directory: - N(false, message_if_directory); + default: + N(false, message_unless_file); break; } } @@ -70,21 +77,40 @@ void require_path_is_directory(any_path const & path, boost::format const & message_if_nonexistent, - boost::format const & message_if_file) + boost::format const & message_unless_directory) { switch (get_path_status(path)) { case path::nonexistent: N(false, message_if_nonexistent); break; - case path::file: - N(false, message_if_file); case path::directory: return; + default: + N(false, message_unless_directory); + break; + } +} + +void +require_path_is_symlink(any_path const & path, + boost::format const & message_if_nonexistent, + boost::format const & message_unless_symlink) +{ + switch (get_path_status(path)) + { + case path::nonexistent: + N(false, message_if_nonexistent); + break; + case path::symlink: + return; + default: + N(false, message_unless_symlink); break; } } + bool path_exists(any_path const & p) { @@ -103,6 +129,13 @@ return get_path_status(p) == path::file; } +bool +symlink_exists(any_path const & p) +{ + return get_path_status(p) == path::symlink; +} + + bool ident_existing_file(file_path const & p, file_id & ident, lua_hooks & lua) { @@ -115,6 +148,9 @@ case path::directory: W(F("expected file '%s', but it is a directory.") % p); return false; + case path::symlink: + W(F("expected file '%s', but it is a symlink.") % p); + return false; } hexenc id; @@ -184,13 +220,15 @@ // print "could not create directory: Success". Which is unhelpful. E(get_path_status(p) != path::file, F("could not create directory '%s'\nit is a file") % p); + E(get_path_status(p) != path::symlink, + F("could not create directory '%s'\nit is a symlink") % p); E(false, F("could not create directory '%s'\n%s") % err.path1().native_directory_string() % strerror(err.native_error())); } require_path_is_directory(p, F("could not create directory '%s'") % p, - F("could not create directory '%s'\nit is a file") % p); + F("could not create directory '%s'\nit exists but is not a directory?!") % p); } void @@ -211,7 +249,7 @@ { require_path_is_file(p, F("file to delete '%s' does not exist") % p, - F("file to delete, '%s', is not a file but a directory") % p); + F("file to delete, '%s', is not a regular file?") % p); fs::remove(mkdir(p)); } @@ -220,7 +258,7 @@ { require_path_is_directory(p, F("directory to delete, '%s', does not exist") % p, - F("directory to delete, '%s', is a file") % p); + F("directory to delete, '%s', is not a directory") % p); fs::remove_all(mkdir(p)); } @@ -230,7 +268,7 @@ { require_path_is_file(old_path, F("rename source file '%s' does not exist") % old_path, - F("rename source file '%s' is a directory " + F("rename source file '%s' is not a regular file " "-- bug in monotone?") % old_path); require_path_is_nonexistent(new_path, F("rename target '%s' already exists") % new_path); @@ -243,7 +281,7 @@ { require_path_is_directory(old_path, F("rename source dir '%s' does not exist") % old_path, - F("rename source dir '%s' is a file " + F("rename source dir '%s' is not a directory " "-- bug in monotone?") % old_path); require_path_is_nonexistent(new_path, F("rename target '%s' already exists") % new_path); @@ -259,6 +297,9 @@ case path::nonexistent: N(false, F("rename source path '%s' does not exist") % old_path); break; + case path::symlink: + N(false, F("rename source path '%s' is a symlink") % old_path); + break; case path::file: move_file(old_path, new_path); break; @@ -273,7 +314,7 @@ { require_path_is_file(p, F("file %s does not exist") % p, - F("file %s cannot be read as data; it is a directory") % p); + F("file %s cannot be read as data; it is not a regular file") % p); ifstream file(p.as_external().c_str(), ios_base::in | ios_base::binary); @@ -477,27 +518,34 @@ L(F("ignoring book keeping entry %s\n") % rel_entry.string()); continue; } + + file_path p; + try + { + // FIXME: BUG: this screws up charsets + p = file_path_internal(rel_entry.normalize().string()); + } + catch (std::runtime_error const & c) + { + W(F("caught runtime error %s constructing file path for %s\n") + % c.what() % rel_entry.string()); + continue; + } if (!fs::exists(entry) || di->string() == "." || di->string() == "..") + { ; // ignore + } + else if (symlink_exists(p)) + { + P( F("ignoring symlink '%s'\n") %entry.string()); // ignore verbose + } else if (fs::is_directory(entry)) walk_tree_recursive(entry, rel_entry, walker); else { - file_path p; - try - { - // FIXME: BUG: this screws up charsets - p = file_path_internal(rel_entry.normalize().string()); - } - catch (std::runtime_error const & c) - { - W(F("caught runtime error %s constructing file path for %s\n") - % c.what() % rel_entry.string()); - continue; - } walker.visit_file(p); } } @@ -521,6 +569,9 @@ N(!require_existing_path, F("no such file or directory: '%s'") % path); walker.visit_file(path); break; + case path::symlink: + N(false, F("ignoring symlink: '%s'") % path); + break; case path::file: walker.visit_file(path); break; diff -x '*.info*' -uNr monotone-0.25/platform.hh monotone-0.25-ignore-symlink/platform.hh --- monotone-0.25/platform.hh 2005-12-30 18:10:35.000000000 +0100 +++ monotone-0.25-ignore-symlink/platform.hh 2006-01-05 20:31:27.000000000 +0100 @@ -53,7 +53,7 @@ utf8 get_homedir(); namespace path { - typedef enum { nonexistent, directory, file } status; + typedef enum { nonexistent, directory, file, symlink } status; }; path::status get_path_status(any_path const & path); diff -x '*.info*' -uNr monotone-0.25/unix/fs.cc monotone-0.25-ignore-symlink/unix/fs.cc --- monotone-0.25/unix/fs.cc 2005-12-30 18:10:42.000000000 +0100 +++ monotone-0.25-ignore-symlink/unix/fs.cc 2006-01-05 23:14:01.000000000 +0100 @@ -95,7 +95,7 @@ { struct stat buf; int res; - res = stat(path.as_external().c_str(), &buf); + res = lstat(path.as_external().c_str(), &buf); if (res < 0) { if (errno == ENOENT) @@ -103,10 +103,18 @@ else E(false, F("error accessing file %s: %s") % path % std::strerror(errno)); } - if (S_ISREG(buf.st_mode)) - return path::file; + if (S_ISLNK(buf.st_mode)) + { + return path::symlink; + } + else if (S_ISREG(buf.st_mode)) + { + return path::file; + } else if (S_ISDIR(buf.st_mode)) - return path::directory; + { + return path::directory; + } else { // fifo or device or who knows what...