# # patch "commands.cc" # from [af9078ec98297982cd41e7a8b0cea758e9a9df6c] # to [7a5a8d34d167ffb077abf385ff687b3018327543] # # patch "cset.hh" # from [37e25c0a3768be89b4a6208db27ebdfc5cf1968f] # to [1d39340bb52aef571e199835e698586da071aa66] # # patch "roster.hh" # from [fbb120910384d9f860cb39b2f576e470c9187c46] # to [36aa7d8540e15710ea9fb44023c7e0419fdf4c1b] # # patch "work.cc" # from [0dcca2bd49850d419b5904775a74313235fcba2a] # to [5157509316effe608f2939ffda66714edb6b2a71] # # patch "work.hh" # from [3fe7ca77fa62c1c922143e00f3a708b62627d891] # to [5690b5fbbff1b09efb707af80ba8b4f84c0288cf] # ======================================================================== --- commands.cc af9078ec98297982cd41e7a8b0cea758e9a9df6c +++ commands.cc 7a5a8d34d167ffb077abf385ff687b3018327543 @@ -2611,7 +2611,7 @@ } } - /* + /* FIXME_ROSTERS CMD(diff, N_("informative"), N_("[PATH]..."), N_("show current diffs on stdout.\n" ======================================================================== --- cset.hh 37e25c0a3768be89b4a6208db27ebdfc5cf1968f +++ cset.hh 1d39340bb52aef571e199835e698586da071aa66 @@ -31,12 +31,12 @@ { // Detaching existing nodes (for renaming or deleting) virtual node_id detach_node(split_path const & src) = 0; - virtual void drop_detached_node(node_id n) = 0; + virtual void drop_detached_node(node_id nid) = 0; // Attaching new nodes (via creation or as the tail end of renaming) virtual node_id create_dir_node() = 0; virtual node_id create_file_node(file_id const & content) = 0; - virtual void attach_node(node_id n, split_path const & dst) = 0; + virtual void attach_node(node_id nid, split_path const & dst) = 0; // Modifying elements in-place virtual void apply_delta(split_path const & pth, ======================================================================== --- roster.hh fbb120910384d9f860cb39b2f576e470c9187c46 +++ roster.hh 36aa7d8540e15710ea9fb44023c7e0419fdf4c1b @@ -166,15 +166,15 @@ roster_t & operator=(roster_t const & other); bool has_root() const; bool has_node(split_path const & sp) const; - bool has_node(node_id n) const; + bool has_node(node_id nid) const; node_t get_node(split_path const & sp) const; - node_t get_node(node_id n) const; - void get_name(node_id n, split_path & sp) const; + node_t get_node(node_id nid) const; + void get_name(node_id nid, split_path & sp) const; void replace_node_id(node_id from, node_id to); // editable_tree operations node_id detach_node(split_path const & src); - void drop_detached_node(node_id n); + void drop_detached_node(node_id nid); node_id create_dir_node(node_id_source & nis); void create_dir_node(node_id nid); node_id create_file_node(file_id const & content, @@ -182,8 +182,8 @@ void create_file_node(file_id const & content, node_id nid); void insert_node(node_t n); - void attach_node(node_id n, split_path const & dst); - void attach_node(node_id n, node_id parent, path_component name); + void attach_node(node_id nid, split_path const & dst); + void attach_node(node_id nid, node_id parent, path_component name); void apply_delta(split_path const & pth, file_id const & old_id, file_id const & new_new); @@ -278,10 +278,10 @@ void select_nodes_modified_by_cset(cset const & cs, - roster_t const & old_roster, - roster_t const & new_roster, - std::set & nodes_changed, - std::set & nodes_born); + roster_t const & old_roster, + roster_t const & new_roster, + std::set & nodes_changed, + std::set & nodes_born); void update_restricted_roster_from_filesystem(roster_t & ros, ======================================================================== --- work.cc 0dcca2bd49850d419b5904775a74313235fcba2a +++ work.cc 5157509316effe608f2939ffda66714edb6b2a71 @@ -781,3 +781,108 @@ apply_attributes(app, attr); */ } + +editable_working_tree::editable_working_tree(app_state & app, + file_content_source const & source) + : app(app), source(source), next_nid(1) +{ +} + +static inline bookkeeping_path +path_for_nid(node_id nid) +{ + return bookkeeping_root / "tmp" / boost::lexical_cast(nid); +} + +node_id +editable_working_tree::detach_node(split_path const & src) +{ + node_id nid = next_nid++; + file_path src_pth(src); + bookkeeping_path dst_pth = path_for_nid(nid); + make_dir_for(dst_pth); + move_path(src_pth, dst_pth); + return nid; +} + +void +editable_working_tree::drop_detached_node(node_id nid) +{ + bookkeeping_path pth = path_for_nid(nid); + delete_file_or_dir_shallow(pth); +} + +node_id +editable_working_tree::create_dir_node() +{ + node_id nid = next_nid++; + bookkeeping_path pth = path_for_nid(nid); + require_path_is_nonexistent(pth, + F("path %s already exists")); + mkdir_p(pth); + return nid; +} + +node_id +editable_working_tree::create_file_node(file_id const & content) +{ + node_id nid = next_nid++; + bookkeeping_path pth = path_for_nid(nid); + require_path_is_nonexistent(pth, + F("path %s already exists")); + file_data dat; + source.get_file_content(content, dat); + // FIXME_ROSTERS: what about charset conversion etc.? + write_data(pth, dat.inner()); + return nid; +} + +void +editable_working_tree::attach_node(node_id nid, split_path const & dst) +{ + bookkeeping_path src_pth = path_for_nid(nid); + file_path dst_pth(dst); + move_path(src_pth, dst_pth); +} + +void +editable_working_tree::apply_delta(split_path const & pth, + file_id const & old_id, + file_id const & new_id) +{ + file_path pth_unsplit(pth); + require_path_is_file(pth_unsplit, + F("file '%s' does not exist") % pth_unsplit, + F("file '%s' is a directory") % pth_unsplit); + hexenc curr_id_raw; + calculate_ident(pth_unsplit, curr_id_raw, app.lua); + file_id curr_id(curr_id_raw); + E(curr_id == old_id, + F("content of file '%s' has changed, not overwriting")); + P(F("updating %s to %s") % pth_unsplit % new_id); + + file_data dat; + source.get_file_content(new_id, dat); + // FIXME_ROSTERS: inconsistent with file addition code above, and + // write_localized_data is poorly designed anyway... + write_localized_data(pth_unsplit, dat.inner(), app.lua); +} + +void +editable_working_tree::clear_attr(split_path const & pth, + attr_key const & name) +{ + // FIXME_ROSTERS: call a lua hook +} + +void +editable_working_tree::set_attr(split_path const & pth, + attr_key const & name, + attr_value const & val) +{ + // FIXME_ROSTERS: call a lua hook +} + +editable_working_tree::~editable_working_tree() +{ +} ======================================================================== --- work.hh 3fe7ca77fa62c1c922143e00f3a708b62627d891 +++ work.hh 5690b5fbbff1b09efb707af80ba8b4f84c0288cf @@ -207,4 +207,38 @@ extern std::string const binary_encoding; extern std::string const default_encoding; +struct file_content_source +{ + virtual void get_file_content(file_id const & fid, + file_data const & dat) const = 0; + virtual ~file_content_source() {}; +}; + +struct editable_working_tree : public editable_tree +{ + editable_working_tree(app_state & app, file_content_source const & source); + + virtual node_id detach_node(split_path const & src); + virtual void drop_detached_node(node_id nid); + + virtual node_id create_dir_node(); + virtual node_id create_file_node(file_id const & content); + virtual void attach_node(node_id nid, split_path const & dst); + + virtual void apply_delta(split_path const & pth, + file_id const & old_id, + file_id const & new_id); + virtual void clear_attr(split_path const & pth, + attr_key const & name); + virtual void set_attr(split_path const & pth, + attr_key const & name, + attr_value const & val); + + virtual ~editable_working_tree(); +private: + app_state & app; + file_content_source const & source; + node_id next_nid; +}; + #endif // __WORK_HH__