# # old_revision [850fc61ed4c0721851f41e91dceb07c23bd01163] # # patch "database.cc" # from [847c12cc2ef53be42177dcc95961db198f44857c] # to [c79ff86003ffe03f8ba07aeae1f7d5294e4356a5] # # patch "file_io.cc" # from [c1938a3a23c60dfeceaafcc39e17bbfd72c9a029] # to [c1ab2b112a17fbb4127e0b1abb5299a4bc4109ce] # # patch "file_io.hh" # from [1a250c948af12df05843eb0e1f4c02106a3c77dd] # to [08447a80b9409ec37658a3f68d52d4d216fe4c7d] # # patch "key_store.cc" # from [c15c1c54b12ba2e79540d132da465c88d48ada34] # to [3ad9e0f9d7428efb8687238062e346ab0465fb7d] # # patch "lua.cc" # from [86dd5f2354857f44b75a7c2c229bad870031b562] # to [998815a5434cfc1115f8d3dd98f38d37b45b98fb] # # patch "paths.cc" # from [8367c798e233a2dd623e832c5e041dc8e896530e] # to [c18fbb624648f808bab7807c160f8c77f5595d3e] # # patch "platform.hh" # from [bd5be744c791a66527b0184fa5dbc5d8ec94e223] # to [da06f1d75986a30cd0ecb5d6f758ed2c82ca23c9] # # patch "rcs_import.cc" # from [7e735462858d40848d763833eccc88f656ebb3ec] # to [17b71642fa722e79f57ab7b841abcb7bbea90db3] # # patch "tester.cc" # from [e41c1170a163dbd12343e68444132e768da083ca] # to [e11cb3f5d62dab81a04a5d70ec6842628869a769] # # patch "unix/fs.cc" # from [fd280df80c6829c787f99fe1bc3748c7530ffacd] # to [d61c20720fdbdb47e3cf0403ba6e63ed04119bf0] # # patch "win32/fs.cc" # from [918ede5caf8f3f46fb54f462d29610713adf2339] # to [ad733f82002e12dca2cad86db53e32d1b50bdd18] # # patch "work.cc" # from [d602424dc046f080220d23b5dc663b93b573284a] # to [d03ac0b0542e4de1d279c73794402473ad4eb382] # ============================================================ --- database.cc 847c12cc2ef53be42177dcc95961db198f44857c +++ database.cc c79ff86003ffe03f8ba07aeae1f7d5294e4356a5 @@ -3406,6 +3406,9 @@ database::check_db_exists() N(false, F("%s is a directory, not a database") % filename); } break; + case path::special: + N(false, F("database %s is not a regular file") % filename); + break; } } ============================================================ --- file_io.cc c1938a3a23c60dfeceaafcc39e17bbfd72c9a029 +++ file_io.cc c1ab2b112a17fbb4127e0b1abb5299a4bc4109ce @@ -59,7 +59,7 @@ require_path_is_file(any_path const & pa void require_path_is_file(any_path const & path, i18n_format const & message_if_nonexistent, - i18n_format const & message_if_directory) + i18n_format const & message_if_not_file) { switch (get_path_status(path)) { @@ -69,7 +69,8 @@ require_path_is_file(any_path const & pa case path::file: return; case path::directory: - N(false, message_if_directory); + case path::special: + N(false, message_if_not_file); break; } } @@ -85,6 +86,7 @@ require_path_is_directory(any_path const N(false, message_if_nonexistent); break; case path::file: + case path::special: N(false, message_if_file); case path::directory: return; @@ -125,7 +127,7 @@ directory_empty(any_path const & path) { directory_empty_helper h; try { - do_read_directory(system_path(path).as_external(), h, h); + do_read_directory(system_path(path).as_external(), h, h, h); } catch (directory_not_empty_exception) { return false; } @@ -182,6 +184,7 @@ mkdir_p(any_path const & p) case path::directory: return; case path::file: + case path::special: E(false, F("could not create directory '%s': it is a file") % p); case path::nonexistent: mkdir_p(p.dirname()); @@ -200,7 +203,7 @@ delete_file(any_path const & p) { 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); do_remove(p.as_external()); } @@ -209,7 +212,7 @@ delete_dir_shallow(any_path const & p) { require_path_is_directory(p, F("directory to delete '%s' does not exist") % p, - F("directory to delete, '%s', is not a directory but a file") % p); + F("directory to delete, '%s', is a file") % p); do_remove(p.as_external()); } @@ -259,7 +262,7 @@ do_remove_recursive(any_path const & p) fill_pc_vec subdir_fill(subdirs); file_deleter delete_files(p); - do_read_directory(p.as_external(), delete_files, subdir_fill); + do_read_directory(p.as_external(), delete_files, subdir_fill, delete_files); for (vector::const_iterator i = subdirs.begin(); i != subdirs.end(); i++) do_remove_recursive(p / *i); @@ -284,7 +287,7 @@ move_file(any_path const & old_path, { 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") @@ -324,7 +327,7 @@ read_data(any_path const & p, data & dat { 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; not a regular file") % p); ifstream file(p.as_external().c_str(), ios_base::in | ios_base::binary); @@ -338,10 +341,11 @@ void read_directory(any_path const & pat void read_directory(any_path const & path, vector & files, - vector & dirs) + vector & dirs, + vector & specials) { - fill_pc_vec ff(files), df(dirs); - do_read_directory(path.as_external(), ff, df); + fill_pc_vec ff(files), df(dirs), sf(specials); + do_read_directory(path.as_external(), ff, df, sf); } // This function can only be called once per run. @@ -429,6 +433,14 @@ tree_walker::visit_dir(file_path const & return true; } +// by default we don't like special files. +// specialisations can handle them as required though. +void +tree_walker::visit_special(file_path const & path) +{ + E(false, F("cannot handle special file '%s'") % path); +} + // subroutine of walk_tree_recursive: if the path composition of PATH and PC // is a valid file_path, write it to ENTRY and return true. otherwise, // generate an appropriate diagnostic and return false. in this context, an @@ -477,8 +489,8 @@ walk_tree_recursive(file_path const & pa // peak memory. By splitting the loop in half, we avoid this problem. // // [1] http://lkml.org/lkml/2006/2/24/215 - vector files, dirs; - read_directory(path, files, dirs); + vector files, dirs, specials; + read_directory(path, files, dirs, specials); for (vector::const_iterator i = files.begin(); i != files.end(); ++i) @@ -488,6 +500,14 @@ walk_tree_recursive(file_path const & pa walker.visit_file(entry); } + for (vector::const_iterator i = specials.begin(); + i != specials.end(); ++i) + { + file_path entry; + if (safe_compose(path, *i, false, entry)) + walker.visit_special(entry); + } + for (vector::const_iterator i = dirs.begin(); i != dirs.end(); ++i) { @@ -516,6 +536,9 @@ walk_tree(file_path const & path, tree_w case path::file: walker.visit_file(path); break; + case path::special: + walker.visit_special(path); + break; case path::directory: if (walker.visit_dir(path)) walk_tree_recursive(path, walker); @@ -538,6 +561,9 @@ ident_existing_file(file_path const & p, return false; case path::file: break; + case path::special: + E(false, F("cannot handle special file '%s'") % p); + return false; case path::directory: W(F("expected file '%s', but it is a directory.") % p); return false; ============================================================ --- file_io.hh 1a250c948af12df05843eb0e1f4c02106a3c77dd +++ file_io.hh 08447a80b9409ec37658a3f68d52d4d216fe4c7d @@ -72,7 +72,8 @@ void read_directory(any_path const & pat void read_directory(any_path const & path, std::vector & files, - std::vector & dirs); + std::vector & dirs, + std::vector & specials); void read_data_stdin(data & dat); @@ -106,6 +107,7 @@ public: public: // returns true if the directory should be descended into virtual bool visit_dir(file_path const & path); + virtual void visit_special(file_path const & path); virtual void visit_file(file_path const & path) = 0; virtual ~tree_walker(); }; ============================================================ --- key_store.cc c15c1c54b12ba2e79540d132da465c88d48ada34 +++ key_store.cc 3ad9e0f9d7428efb8687238062e346ab0465fb7d @@ -74,11 +74,11 @@ key_store::read_key_dir() void key_store::read_key_dir() { - vector key_files, dirs; + vector key_files, dirs, specials; if (directory_exists(key_dir)) { L(FL("reading key dir '%s'") % key_dir); - read_directory(key_dir, key_files, dirs); + read_directory(key_dir, key_files, dirs, specials); } else L(FL("key dir '%s' does not exist") % key_dir); ============================================================ --- lua.cc 86dd5f2354857f44b75a7c2c229bad870031b562 +++ lua.cc 998815a5434cfc1115f8d3dd98f38d37b45b98fb @@ -542,8 +542,6 @@ namespace namespace { - struct ignore_directories : public dirent_consumer - { virtual void consume(const char *) {} }; struct record_if_matches : public dirent_consumer { record_if_matches(string const & b, char const * p, @@ -573,6 +571,7 @@ run_directory(lua_State * st, char const case path::nonexistent: N(false, F("Directory '%s' does not exist") % pathstr); case path::file: + case path::special: N(false, F("'%s' is not a directory") % pathstr); case path::directory: break; @@ -582,9 +581,10 @@ run_directory(lua_State * st, char const // matching the pattern, sorting them and loading in sorted order vector arr; { - ignore_directories id; + ignore_consumer id; + ignore_consumer specials; record_if_matches rim(path, pattern, arr); - do_read_directory(path, rim, id); + do_read_directory(path, rim, id, specials); } sort(arr.begin(), arr.end()); ============================================================ --- paths.cc 8367c798e233a2dd623e832c5e041dc8e896530e +++ paths.cc c18fbb624648f808bab7807c160f8c77f5595d3e @@ -793,6 +793,7 @@ find_bookdir(system_path const & root, p continue; case path::file: + case path::special: L(FL("'%s' is not a directory") % check); return false; @@ -811,6 +812,7 @@ find_bookdir(system_path const & root, p return false; case path::file: + case path::special: L(FL("'%s' is not a directory") % check); return false; ============================================================ --- platform.hh bd5be744c791a66527b0184fa5dbc5d8ec94e223 +++ platform.hh da06f1d75986a30cd0ecb5d6f758ed2c82ca23c9 @@ -114,7 +114,7 @@ namespace path std::string get_homedir(); namespace path { - typedef enum { nonexistent, directory, file } status; + typedef enum { nonexistent, directory, file, special } status; }; path::status get_path_status(std::string const & path); @@ -123,9 +123,14 @@ struct dirent_consumer virtual ~dirent_consumer() {} virtual void consume(const char *) = 0; }; + +struct ignore_consumer : public dirent_consumer +{ virtual void consume(const char *) {} }; + void do_read_directory(std::string const & path, dirent_consumer & files, - dirent_consumer & dirs); + dirent_consumer & dirs, + dirent_consumer & specials); void rename_clobberingly(std::string const & from, std::string const & to); void do_remove(std::string const & path); ============================================================ --- rcs_import.cc 7e735462858d40848d763833eccc88f656ebb3ec +++ rcs_import.cc 17b71642fa722e79f57ab7b841abcb7bbea90db3 @@ -910,6 +910,7 @@ public: else L(FL("skipping non-RCS file %s") % file); } + virtual ~cvs_tree_walker() {} }; ============================================================ --- tester.cc e41c1170a163dbd12343e68444132e768da083ca +++ tester.cc e11cb3f5d62dab81a04a5d70ec6842628869a769 @@ -313,9 +313,9 @@ void do_remove_recursive(string const & make_accessible(p); vector subdirs; struct fill_vec get_subdirs(subdirs); - struct file_deleter del_files(p); + struct file_deleter del_files(p), del_specials(p); - do_read_directory(p, del_files, get_subdirs); + do_read_directory(p, del_files, get_subdirs, del_specials); for(vector::const_iterator i = subdirs.begin(); i != subdirs.end(); i++) do_remove_recursive(p + "/" + *i); @@ -324,6 +324,7 @@ void do_remove_recursive(string const & return; case path::file: + case path::special: make_accessible(p); do_remove(p); return; @@ -343,8 +344,9 @@ void do_make_tree_accessible(string cons vector subdirs; struct fill_vec get_subdirs(subdirs); struct file_accessible_maker access_files(p); + ignore_consumer ign_specials; - do_read_directory(p, access_files, get_subdirs); + do_read_directory(p, access_files, get_subdirs, ign_specials); for(vector::const_iterator i = subdirs.begin(); i != subdirs.end(); i++) do_make_tree_accessible(p + "/" + *i); @@ -354,6 +356,10 @@ void do_make_tree_accessible(string cons case path::file: make_accessible(p); return; + + case path::special: + E(false, F("cannot handle special file '%s'") % p); + return; case path::nonexistent: return; @@ -387,11 +393,13 @@ void do_copy_recursive(string const & fr if (fromstat == path::directory) { - vector subdirs; - struct fill_vec get_subdirs(subdirs); + vector subdirs, specials; + struct fill_vec get_subdirs(subdirs), get_specials(specials); struct file_copier copy_files(from, to); - do_read_directory(from, copy_files, get_subdirs); + do_read_directory(from, copy_files, get_subdirs, get_specials); + E(specials.empty(), F("cannot handle special file '%s/%s'") + % from % specials.front()); for (vector::const_iterator i = subdirs.begin(); i != subdirs.end(); i++) do_copy_recursive(from + "/" + *i, to + "/" + *i); @@ -577,9 +585,14 @@ LUAEXT(exists, ) char const * name = luaL_checkstring(L, -1); switch (get_path_status(name)) { - case path::nonexistent: lua_pushboolean(L, false); break; + case path::nonexistent: + lua_pushboolean(L, false); + break; case path::file: - case path::directory: lua_pushboolean(L, true); break; + case path::special: + case path::directory: + lua_pushboolean(L, true); + break; } } catch(informative_failure & e) @@ -597,8 +610,13 @@ LUAEXT(isdir, ) switch (get_path_status(name)) { case path::nonexistent: - case path::file: lua_pushboolean(L, false); break; - case path::directory: lua_pushboolean(L, true); break; + case path::file: + case path::special: + lua_pushboolean(L, false); + break; + case path::directory: + lua_pushboolean(L, true); + break; } } catch(informative_failure & e) @@ -636,7 +654,8 @@ LUAEXT(read_directory, ) string path(luaL_checkstring(L, -1)); build_table tbl(L); - do_read_directory(path, tbl, tbl); + // XXX - should it ignore specials? probably not. + do_read_directory(path, tbl, tbl, tbl); } catch(informative_failure &) { ============================================================ --- unix/fs.cc fd280df80c6829c787f99fe1bc3748c7530ffacd +++ unix/fs.cc d61c20720fdbdb47e3cf0403ba6e63ed04119bf0 @@ -115,8 +115,7 @@ get_path_status(string const & path) return path::directory; else { - // fifo or device or who knows what... - E(false, F("cannot handle special file %s") % path); + return path::special; } } @@ -145,7 +144,8 @@ do_read_directory(string const & path, void do_read_directory(string const & path, dirent_consumer & files, - dirent_consumer & dirs) + dirent_consumer & dirs, + dirent_consumer & specials) { string p(path); if (p == "") @@ -175,7 +175,8 @@ do_read_directory(string const & path, break; default: - goto bad_special_file; + specials.consume(d->d_name); + continue; } #endif @@ -209,12 +210,8 @@ do_read_directory(string const & path, else if (S_ISDIR(st.st_mode)) dirs.consume(d->d_name); else - goto bad_special_file; + specials.consume(d->d_name); } - return; - - bad_special_file: - E(false, F("cannot handle special file '%s/%s'") % p % d->d_name); } ============================================================ --- win32/fs.cc 918ede5caf8f3f46fb54f462d29610713adf2339 +++ win32/fs.cc ad733f82002e12dca2cad86db53e32d1b50bdd18 @@ -199,7 +199,8 @@ do_read_directory(std::string const & pa void do_read_directory(std::string const & path, dirent_consumer & files, - dirent_consumer & dirs) + dirent_consumer & dirs, + dirent_consumer & specials) { dirhandle dir(path); WIN32_FIND_DATA d; ============================================================ --- work.cc d602424dc046f080220d23b5dc663b93b573284a +++ work.cc d03ac0b0542e4de1d279c73794402473ad4eb382 @@ -484,6 +484,7 @@ struct file_itemizer : public tree_walke : db(db), lua(lua), known(k), unknown(u), ignored(i), mask(r) {} virtual bool visit_dir(file_path const & path); virtual void visit_file(file_path const & path); + virtual void visit_special(file_path const & path); }; @@ -506,6 +507,11 @@ file_itemizer::visit_file(file_path cons } } +void +file_itemizer::visit_special(file_path const & path) +{ + ignored.insert(path); +} struct workspace_itemizer : public tree_walker { @@ -517,6 +523,7 @@ struct workspace_itemizer : public tree_ node_id_source & nis); virtual bool visit_dir(file_path const & path); virtual void visit_file(file_path const & path); + virtual void visit_special(file_path const & path); }; workspace_itemizer::workspace_itemizer(roster_t & roster, @@ -544,7 +551,15 @@ workspace_itemizer::visit_file(file_path roster.attach_node(nid, path); } +void +workspace_itemizer::visit_special(file_path const & path) +{ + // we just treat it the same as a file - other code + // can check it properly later. + visit_file(path); +} + class addition_builder : public tree_walker @@ -562,6 +577,7 @@ public: {} virtual bool visit_dir(file_path const & path); virtual void visit_file(file_path const & path); + virtual void visit_special(file_path const & path); void add_nodes_for(file_path const & path, file_path const & goal); }; @@ -597,6 +613,9 @@ addition_builder::add_nodes_for(file_pat case path::directory: nid = er.create_dir_node(); break; + case path::special: + E(false, F("cannot handle special file '%s'") % path); + return; } I(nid != the_null_node); @@ -638,6 +657,12 @@ addition_builder::visit_file(file_path c add_nodes_for(path, path); } +void +addition_builder::visit_special(file_path const & path) +{ + W(F("skipping special file '%s'") % path); +} + struct editable_working_tree : public editable_tree { editable_working_tree(lua_hooks & lua, content_merge_adaptor const & source, @@ -765,8 +790,10 @@ editable_working_tree::detach_node(file_ { // root dir detach, so we move contents, rather than the dir itself mkdir_p(dst_pth); - vector files, dirs; - read_directory(src_pth, files, dirs); + vector files, dirs, specials; + read_directory(src_pth, files, dirs, specials); + // XXX or should we do something better? + E(specials.empty(), F("cannot handle special file '%s'") % specials.front());; for (vector::const_iterator i = files.begin(); i != files.end(); ++i) move_file(src_pth / *i, dst_pth / *i); @@ -837,8 +864,10 @@ editable_working_tree::attach_node(node_ if (dst_pth == file_path()) { // root dir attach, so we move contents, rather than the dir itself - vector files, dirs; - read_directory(src_pth, files, dirs); + vector files, dirs, specials; + read_directory(src_pth, files, dirs, specials); + // XXX or should we do something better? + E(specials.empty(), F("cannot handle special file '%s'") % specials.front());; for (vector::const_iterator i = files.begin(); i != files.end(); ++i) { @@ -1187,7 +1216,7 @@ workspace::update_current_roster_from_fi } else if (status != path::file) { - W(F("not a file '%s'") % (fp)); + W(F("not a regular file '%s'") % (fp)); missing_items++; } @@ -1295,6 +1324,10 @@ workspace::perform_additions(set