# # # patch "automate.cc" # from [e045fd011c06f5c5ef4812e8c5ef82635182b8df] # to [a4b981cd5ddf67cc5bb95c3314b911b28978c3b1] # # patch "basic_io.hh" # from [df6d95570895d30d6143bbce4d31dd93687b0fd1] # to [64cbd940961328cf9c6a868e015424e35efad4cf] # # patch "cmd_merging.cc" # from [b21c375b373335346034d880ef5dca15cf0a025c] # to [602d5834212b47cdb5cc9151fe8eaa77d325f571] # # patch "database.cc" # from [f52aceca72edd2079f6203ae0ad016d5cf5891fb] # to [94a4e84298bb6f80aedf7fbb45fe3bb87e35c6b3] # # patch "database.hh" # from [47695146fe0bf270c37e3e4646efd6d6b78abef0] # to [59dbc78eee566565e591994556a7c9446f2a8865] # # patch "roster.cc" # from [9587de0d8b3a9387d29aa8d773d0789cda48e72c] # to [b4cec49faa1928388c7ab0ae1e2f389b202270b0] # # patch "roster.hh" # from [7d804006ba9ae9662c967f905d722ddf891030af] # to [2b498673424f4d69f74cdb1486b9f8b051766e34] # ============================================================ --- database.cc f52aceca72edd2079f6203ae0ad016d5cf5891fb +++ database.cc 94a4e84298bb6f80aedf7fbb45fe3bb87e35c6b3 @@ -350,10 +350,6 @@ private: string const & data_table, string const & delta_table); - void get_version_size(id const & ident, - file_size & size, - string const & size_table); - void drop(id const & base, string const & table); @@ -2097,18 +2093,6 @@ database_impl::get_version(id const & id vcache.insert_clean(ident, dat); } -void -database_impl::get_version_size(id const & ident, - file_size & size, - std::string const & size_table) -{ - results res; - query q("SELECT size FROM " + size_table + " WHERE id = ?"); - fetch(res, one_col, one_row, q % blob(ident())); - I(!res.empty()); - size = lexical_cast(res[0][0]); -} - struct roster_reconstruction_graph : public reconstruction_graph { database_impl & imp; @@ -2404,13 +2388,40 @@ void } void -database::get_file_size(file_id const & id, +database::get_file_size(file_id const & ident, file_size & size) { - imp->get_version_size(id.inner(), size, "file_sizes"); + results res; + query q("SELECT size FROM file_sizes WHERE id = ?"); + imp->fetch(res, one_col, one_row, q % blob(ident.inner()())); + I(!res.empty()); + size = lexical_cast(res[0][0]); } void +database::get_file_sizes(roster_t const & roster, + map & sizes) +{ + sizes.clear(); + + node_map const & nodes = roster.all_nodes(); + for (node_map::const_iterator i = nodes.begin(); i != nodes.end(); ++i) + { + node_id nid = i->first; + if (!is_file_t(i->second)) + continue; + + file_t file = downcast_to_file_t(i->second); + if (sizes.find(file->content) != sizes.end()) + continue; + + file_size size; + get_file_size(file->content, size); + sizes.insert(make_pair(file->content, size)); + } +} + +void database::get_manifest_version(manifest_id const & id, manifest_data & dat) { ============================================================ --- database.hh 47695146fe0bf270c37e3e4646efd6d6b78abef0 +++ database.hh 59dbc78eee566565e591994556a7c9446f2a8865 @@ -133,6 +133,10 @@ public: void get_file_size(file_id const & ident, file_size & size); + // gets a map of all file sizes of this particular roster + void get_file_sizes(roster_t const & roster, + std::map & file_sizes); + // put file w/o predecessor into db void put_file(file_id const & new_id, file_data const & dat); ============================================================ --- basic_io.hh df6d95570895d30d6143bbce4d31dd93687b0fd1 +++ basic_io.hh 64cbd940961328cf9c6a868e015424e35efad4cf @@ -38,6 +38,7 @@ namespace basic_io symbol const dir("dir"); symbol const file("file"); symbol const content("content"); + symbol const size("size"); symbol const attr("attr"); symbol const content_mark("content_mark"); ============================================================ --- automate.cc e045fd011c06f5c5ef4812e8c5ef82635182b8df +++ automate.cc a4b981cd5ddf67cc5bb95c3314b911b28978c3b1 @@ -1445,7 +1445,133 @@ CMD_AUTOMATE(get_manifest_of, N_("[REVID output << dat; } +namespace +{ + namespace syms + { + symbol const dormant_attr("dormant_attr"); + symbol const path_mark("path_mark"); + symbol const content_mark("content_mark"); + symbol const attr_mark("attr_mark"); + } +}; +static void +print_extended_manifest(roster_t const & roster, marking_map const & mm, + map const & file_sizes, data & dat) +{ + basic_io::printer pr; + + for (dfs_iter i(roster.root(), true); !i.finished(); ++i) + { + const_node_t curr = *i; + basic_io::stanza st; + + if (is_dir_t(curr)) + { + st.push_str_pair(basic_io::syms::dir, i.path()); + } + else + { + const_file_t ftmp = downcast_to_file_t(curr); + st.push_str_pair(basic_io::syms::file, i.path()); + st.push_binary_pair(basic_io::syms::content, ftmp->content.inner()); + + map::const_iterator s = file_sizes.find(ftmp->content); + I(s != file_sizes.end()); + st.push_str_pair(basic_io::syms::size, + boost::lexical_cast(s->second)); + } + + // Push the non-dormant part of the attr map + for (attr_map_t::const_iterator j = curr->attrs.begin(); + j != curr->attrs.end(); ++j) + { + if (!j->second.first) + continue; + st.push_str_triple(basic_io::syms::attr, j->first(), j->second.second()); + } + + // Push the dormant part of the attr map + for (attr_map_t::const_iterator j = curr->attrs.begin(); + j != curr->attrs.end(); ++j) + { + if (j->second.first) + continue; + + I(j->second.second().empty()); + st.push_str_pair(syms::dormant_attr, j->first()); + } + + const_marking_t mark = mm.get_marking(curr->self); + I(!null_id(mark->birth_revision)); + + st.push_binary_pair(syms::birth, mark->birth_revision.inner()); + + for (set::const_iterator j = mark->parent_name.begin(); + j != mark->parent_name.end(); ++j) + { + st.push_binary_pair(syms::path_mark, (*j).inner()); + } + + if (is_file_t(curr)) + { + for (set::const_iterator j = mark->file_content.begin(); + j != mark->file_content.end(); ++j) + { + st.push_binary_pair(syms::content_mark, (*j).inner()); + } + } + else + I(mark->file_content.empty()); + + for (map >::const_iterator j = mark->attrs.begin(); + j != mark->attrs.end(); ++j) + { + for (set::const_iterator k = j->second.begin(); + k != j->second.end(); ++k) + { + st.push_binary_triple(syms::attr_mark, j->first(), (*k).inner()); + } + } + + pr.print_stanza(st); + } + + dat = data(pr.buf.data(), origin::database); +} + +// Name: get_extended_manifest_of +// Arguments: none +// Added in: 13.0 +// Purpose: Prints the extended manifest for the given identifier +// Output format: basicio +// Error conditions: if the revision does not exist, prints an error and exits +CMD_AUTOMATE(get_extended_manifest_of, "REVISION", + N_("Prints the extended manifest for the given identifier"), + "", + options::opts::none) +{ + E(args.size() == 1, origin::user, + F("wrong argument count")); + + database db(app); + roster_t roster; + marking_map mm; + + revision_id rid = decode_hexenc_as(idx(args, 0)(), origin::user); + E(db.revision_exists(rid), origin::user, + F("no revision %s found in database") % rid); + db.get_roster(rid, roster, mm); + + map file_sizes; + db.get_file_sizes(roster, file_sizes); + + data dat; + print_extended_manifest(roster, mm, file_sizes, dat); + output << dat; +} + // Name: packet_for_rdata // Arguments: // 1: a revision id ============================================================ --- roster.cc 9587de0d8b3a9387d29aa8d773d0789cda48e72c +++ roster.cc b4cec49faa1928388c7ab0ae1e2f389b202270b0 @@ -10,7 +10,6 @@ #include "base.hh" #include -#include #include #include "vector.hh" #include @@ -432,128 +431,116 @@ roster_t::operator=(roster_t const & oth } -struct -dfs_iter +dfs_iter::dfs_iter(const_dir_t r, bool t = false) + : root(r), return_root(root), track_path(t) { - const_dir_t root; - string curr_path; - bool return_root; - bool track_path; - stack< pair > stk; + if (root && !root->children.empty()) + stk.push(make_pair(root, root->children.begin())); +} +bool +dfs_iter::finished() const +{ + return (!return_root) && stk.empty(); +} - dfs_iter(const_dir_t r, bool t = false) - : root(r), return_root(root), track_path(t) - { - if (root && !root->children.empty()) - stk.push(make_pair(root, root->children.begin())); - } +string const & +dfs_iter::path() const +{ + I(track_path); + return curr_path; +} +const_node_t +dfs_iter::operator*() const +{ + I(!finished()); + if (return_root) + return root; + else + { + I(!stk.empty()); + return stk.top().second->second; + } +} - bool finished() const - { - return (!return_root) && stk.empty(); - } +void +dfs_iter::advance_top() +{ + int prevsize = 0; + int nextsize = 0; + pair & stack_top(stk.top()); + if (track_path) + { + prevsize = stack_top.second->first().size(); + } + ++stack_top.second; - string const & path() const - { - I(track_path); - return curr_path; - } + if (track_path) + { + if (stack_top.second != stack_top.first->children.end()) + nextsize = stack_top.second->first().size(); + int tmpsize = curr_path.size()-prevsize; + I(tmpsize >= 0); + curr_path.resize(tmpsize); + if (nextsize != 0) + curr_path.insert(curr_path.end(), + stack_top.second->first().begin(), + stack_top.second->first().end()); + } +} - const_node_t operator*() const - { - I(!finished()); - if (return_root) - return root; - else - { - I(!stk.empty()); - return stk.top().second->second; - } - } +void +dfs_iter::operator++() +{ + I(!finished()); -private: - void advance_top() - { - int prevsize = 0; - int nextsize = 0; - pair & stack_top(stk.top()); - if (track_path) - { - prevsize = stack_top.second->first().size(); - } + if (return_root) + { + return_root = false; + if (!stk.empty()) + curr_path = stk.top().second->first(); + return; + } - ++stack_top.second; + // we're not finished, so we need to set up so operator* will return the + // right thing. + node_t ntmp = stk.top().second->second; + if (is_dir_t(ntmp)) + { + dir_t dtmp = downcast_to_dir_t(ntmp); + stk.push(make_pair(dtmp, dtmp->children.begin())); - if (track_path) - { - if (stack_top.second != stack_top.first->children.end()) - nextsize = stack_top.second->first().size(); + if (track_path) + { + if (!curr_path.empty()) + curr_path += "/"; + if (!dtmp->children.empty()) + curr_path += dtmp->children.begin()->first(); + } + } + else + { + advance_top(); + } - int tmpsize = curr_path.size()-prevsize; - I(tmpsize >= 0); - curr_path.resize(tmpsize); - if (nextsize != 0) - curr_path.insert(curr_path.end(), - stack_top.second->first().begin(), - stack_top.second->first().end()); - } - } -public: + while (!stk.empty() + && stk.top().second == stk.top().first->children.end()) + { + stk.pop(); + if (!stk.empty()) + { + if (track_path) + { + curr_path.resize(curr_path.size()-1); + } + advance_top(); + } + } +} - void operator++() - { - I(!finished()); - - if (return_root) - { - return_root = false; - if (!stk.empty()) - curr_path = stk.top().second->first(); - return; - } - - // we're not finished, so we need to set up so operator* will return the - // right thing. - node_t ntmp = stk.top().second->second; - if (is_dir_t(ntmp)) - { - dir_t dtmp = downcast_to_dir_t(ntmp); - stk.push(make_pair(dtmp, dtmp->children.begin())); - - if (track_path) - { - if (!curr_path.empty()) - curr_path += "/"; - if (!dtmp->children.empty()) - curr_path += dtmp->children.begin()->first(); - } - } - else - { - advance_top(); - } - - while (!stk.empty() - && stk.top().second == stk.top().first->children.end()) - { - stk.pop(); - if (!stk.empty()) - { - if (track_path) - { - curr_path.resize(curr_path.size()-1); - } - advance_top(); - } - } - } -}; - - bool roster_t::has_root() const { @@ -1850,7 +1837,7 @@ namespace if (mm.size() > ros.all_nodes().size()) { std::set to_drop; - + marking_map::const_iterator mi = mm.begin(), me = mm.end(); node_map::const_iterator ri = ros.all_nodes().begin(), re = ros.all_nodes().end(); ============================================================ --- roster.hh 7d804006ba9ae9662c967f905d722ddf891030af +++ roster.hh 2b498673424f4d69f74cdb1486b9f8b051766e34 @@ -16,6 +16,8 @@ #include "rev_types.hh" #include "cset.hh" // need full definition of editable_tree +#include + struct node_id_source { virtual node_id next() = 0; @@ -36,6 +38,24 @@ enum roster_node_type { node_type_none, enum roster_node_type { node_type_none, node_type_file, node_type_dir }; +struct dfs_iter +{ + const_dir_t root; + std::string curr_path; + bool return_root; + bool track_path; + std::stack< std::pair > stk; + + dfs_iter(const_dir_t r, bool t); + bool finished() const; + std::string const & path() const; + const_node_t operator*() const; + void operator++(); + +private: + void advance_top(); +}; + struct node { node(); ============================================================ --- cmd_merging.cc b21c375b373335346034d880ef5dca15cf0a025c +++ cmd_merging.cc 602d5834212b47cdb5cc9151fe8eaa77d325f571 @@ -1462,87 +1462,6 @@ CMD(heads, "heads", "", CMD_REF(tree), " cout << describe_revision(app.opts, app.lua, project, *i) << '\n'; } -// Name: get_roster -// Arguments: none -// Added in: 13.0 -// Purpose: Prints the internal roster for the given revision -// Output format: basicio -// Error conditions: if the revision does not exist, prints an error and exits -CMD_AUTOMATE(get_roster, "[REVISION]", - N_("Prints the roster associated with a given identifier"), - N_("If no REVISION is given, the workspace is used."), - options::opts::none) -{ - E(args.size() < 2, origin::user, - F("wrong argument count")); - - database db(app); - roster_t roster; - marking_map mm; - - if (args.empty()) - { - parent_map parents; - temp_node_id_source nis; - revision_id rid(fake_id()); - - workspace work(app); - work.get_parent_rosters(db, parents); - work.get_current_roster_shape(db, nis, roster); - work.update_current_roster_from_filesystem(roster); - - if (parents.empty()) - { - mark_roster_with_no_parents(rid, roster, mm); - } - else if (parents.size() == 1) - { - roster_t parent = parent_roster(parents.begin()); - marking_map parent_mm = parent_marking(parents.begin()); - mark_roster_with_one_parent(parent, parent_mm, rid, roster, mm); - } - else - { - parent_map::const_iterator i = parents.begin(); - revision_id left_id = parent_id(i); - roster_t const & left_roster = parent_roster(i); - marking_map const & left_markings = parent_marking(i); - - i++; - revision_id right_id = parent_id(i); - roster_t const & right_roster = parent_roster(i); - marking_map const & right_markings = parent_marking(i); - - i++; I(i == parents.end()); - - set left_uncommon_ancestors, right_uncommon_ancestors; - db.get_uncommon_ancestors(left_id, right_id, - left_uncommon_ancestors, - right_uncommon_ancestors); - - mark_merge_roster(left_roster, left_markings, - left_uncommon_ancestors, - right_roster, right_markings, - right_uncommon_ancestors, - rid, roster, mm); - } - } - else if (args.size() == 1) - { - project_t project(db); - revision_id rid; - complete(app.opts, app.lua, project, idx(args, 0)(), rid); - I(!null_id(rid)); - db.get_roster(rid, roster, mm); - } - else - I(false); - - roster_data dat; - write_roster_and_marking(roster, mm, dat); - output << dat; -} - // Local Variables: // mode: C++ // fill-column: 76