# # # patch "asciik.cc" # from [ffa47c5ecf5fcf0d3f43ff3bd15e20dbf1dc990e] # to [6aae7dc89b1e940cf260a226ad541696439e2428] # # patch "asciik.hh" # from [83815e833d8e513dcba3607a9257feb101399562] # to [f7324eb4f3e0de0099fefb77f77196ef60847fb9] # # patch "cmd_diff_log.cc" # from [ab4bb66739586bf28c0aa5d378131a893916458a] # to [c9321adf9b7ceb162c37ecc2311f9e6fc8c40d48] # # patch "options_list.hh" # from [bdf99561b7ca94bcf196ca26b8d192d8d74f1492] # to [32e67fa380672bec58a2a66f520044c5b8983242] # ============================================================ --- asciik.cc ffa47c5ecf5fcf0d3f43ff3bd15e20dbf1dc990e +++ asciik.cc 6aae7dc89b1e940cf260a226ad541696439e2428 @@ -135,7 +135,6 @@ Loop: #include "asciik.hh" #include "cmd.hh" -using std::cout; using std::insert_iterator; using std::max; using std::min; @@ -148,8 +147,9 @@ static revision_id ghost; // valid but e static revision_id ghost; // valid but empty revision_id to be used as ghost value -asciik::asciik(ostream & os) +asciik::asciik(size_t min_width, ostream & os) { + width = min_width; output = &os; } @@ -173,7 +173,7 @@ asciik::draw(const size_t curr_items, co const size_t curr_loc, const set > & links, const set & curr_ghosts, const string & annotation) const { - size_t line_len = max(curr_items, next_items) * 2; + size_t line_len = max(width, max(curr_items, next_items) * 2); string line(line_len, ' '); // actual len: curr_items * 2 - 1 string interline(line_len, ' '); // actual len: max(curr_items, next_items) * 2 - 1 string interline2(line_len, ' '); @@ -248,10 +248,10 @@ asciik::draw(const size_t curr_items, co lines.push_back(string("")); // prints it out - *output << F("%-8s %s") % line % lines[0] << '\n'; - *output << F("%-8s %s") % interline % lines[1] << '\n'; + *output << line << " " << lines[0] << '\n'; + *output << interline << " " << lines[1] << '\n'; for (int i = 2; i < num_lines; ++i) - *output << F("%-8s %s") % interline2 % lines[i] << '\n'; + *output << interline2 << " " << lines[i] << '\n'; } bool @@ -288,6 +288,7 @@ asciik::try_draw(const vector > parent_links; for (set::const_iterator p = parents.begin(); p != parents.end(); ++p) + if (*p != ghost) { size_t i = curr_loc; size_t j = distance(next_row.begin(), @@ -375,7 +376,7 @@ CMD(asciik, N_("tree"), N_("SELECTOR"), selectors::selector_type ty = selectors::sel_ident; selectors::complete_selector("", sels, ty, completions, app); - asciik graph(cout); + asciik graph(10); set revs; for (set::const_iterator i = completions.begin(); i != completions.end(); ++i) ============================================================ --- asciik.hh 83815e833d8e513dcba3607a9257feb101399562 +++ asciik.hh f7324eb4f3e0de0099fefb77f77196ef60847fb9 @@ -9,7 +9,7 @@ public: class asciik { public: - asciik(std::ostream & os); + asciik(size_t min_width = 0, std::ostream & os = std::cout); // Prints an ASCII-k chunk using the given revisions. void print(const revision_id & rev, const std::set & parents, const string & annotation); //TODO: cambiare set-parents to vector-next @@ -18,6 +18,7 @@ private: void draw(const size_t curr_items, const size_t next_items, const size_t curr_loc, const std::set > & links, const std::set & curr_ghosts, const string & annotation) const; bool try_draw(const std::vector & next_row, const size_t curr_loc, const std::set & parents, const string & annotation) const; // internal state + size_t width; std::ostream * output; std::vector curr_row; }; ============================================================ --- cmd_diff_log.cc ab4bb66739586bf28c0aa5d378131a893916458a +++ cmd_diff_log.cc c9321adf9b7ceb162c37ecc2311f9e6fc8c40d48 @@ -13,6 +13,7 @@ #include #include +#include "asciik.hh" #include "cmd.hh" #include "diff_patch.hh" #include "file_io.hh" @@ -124,14 +125,14 @@ changes_summary::print(ostream & os, siz for (map::const_iterator i = cs.nodes_renamed.begin(); i != cs.nodes_renamed.end(); i++) - os << " " << file_path(i->first) + os << " " << file_path(i->first) << " to " << file_path(i->second) << "\n"; } if (! cs.files_added.empty()) { path_set tmp; - for (map::const_iterator + for (map::const_iterator i = cs.files_added.begin(); i != cs.files_added.end(); ++i) tmp.insert(i->first); @@ -148,7 +149,7 @@ changes_summary::print(ostream & os, siz if (! cs.deltas_applied.empty()) { path_set tmp; - for (map >::const_iterator + for (map >::const_iterator i = cs.deltas_applied.begin(); i != cs.deltas_applied.end(); ++i) tmp.insert(i->first); @@ -159,12 +160,12 @@ changes_summary::print(ostream & os, siz if (! cs.attrs_set.empty() || ! cs.attrs_cleared.empty()) { path_set tmp; - for (set >::const_iterator + for (set >::const_iterator i = cs.attrs_cleared.begin(); i != cs.attrs_cleared.end(); ++i) tmp.insert(i->first); - for (map, attr_value>::const_iterator + for (map, attr_value>::const_iterator i = cs.attrs_set.begin(); i != cs.attrs_set.end(); ++i) tmp.insert(i->first.first); @@ -331,9 +332,9 @@ dump_diffs(cset const & cs, // common functionality for diff and automate content_diff to determine // revisions and rosters which should be diffed -static void +static void prepare_diff(cset & included, - app_state & app, + app_state & app, std::vector args, bool & new_is_archived, std::string & revheader) @@ -351,7 +352,7 @@ prepare_diff(cset & included, N(app.opts.revision_selectors.size() <= 2, F("more than two revisions given")); - + if (app.opts.revision_selectors.size() == 0) { roster_t new_roster, old_roster; @@ -366,7 +367,7 @@ prepare_diff(cset & included, old_roster, new_roster, app); app.work.update_current_roster_from_filesystem(new_roster, mask); - make_restricted_csets(old_roster, new_roster, + make_restricted_csets(old_roster, new_roster, included, excluded, mask); check_restricted_cset(old_roster, included); @@ -390,12 +391,12 @@ prepare_diff(cset & included, // N(r_new.edges.size() == 1, F("current revision has no ancestor")); node_restriction mask(args_to_paths(args), - args_to_paths(app.opts.exclude_patterns), + args_to_paths(app.opts.exclude_patterns), app.opts.depth, old_roster, new_roster, app); app.work.update_current_roster_from_filesystem(new_roster, mask); - make_restricted_csets(old_roster, new_roster, + make_restricted_csets(old_roster, new_roster, included, excluded, mask); check_restricted_cset(old_roster, included); @@ -445,7 +446,7 @@ prepare_diff(cset & included, // (which fails for paths with @'s in them) or possibly //rev/file // since versioned paths are required to be relative. - make_restricted_csets(old_roster, new_roster, + make_restricted_csets(old_roster, new_roster, included, excluded, mask); check_restricted_cset(old_roster, included); @@ -475,9 +476,9 @@ CMD(diff, N_("informative"), N_("[PATH]. cset included; std::string revs; bool new_is_archived; - + prepare_diff(included, app, args, new_is_archived, revs); - + data summary; write_cset(included, summary); @@ -487,7 +488,7 @@ CMD(diff, N_("informative"), N_("[PATH]. if (summary().size() > 0) { cout << revs << "# " << "\n"; - for (vector::iterator i = lines.begin(); + for (vector::iterator i = lines.begin(); i != lines.end(); ++i) cout << "# " << *i << "\n"; } @@ -520,9 +521,9 @@ AUTOMATE(content_diff, N_("[FILE [...]]" cset included; std::string dummy_header; bool new_is_archived; - + prepare_diff(included, app, args, new_is_archived, dummy_header); - + dump_diffs(included, app, new_is_archived, output); } @@ -568,7 +569,7 @@ static void } static void -log_certs(ostream & os, app_state & app, revision_id id, cert_name name, +log_certs(ostream & os, app_state & app, revision_id id, cert_name name, string label, bool multiline) { log_certs(os, app, id, name, label, label, multiline, true); @@ -601,8 +602,9 @@ CMD(log, N_("informative"), N_("[FILE] . "revisions are given, use them as a starting point."), options::opts::last | options::opts::next | options::opts::from | options::opts::to - | options::opts::brief | options::opts::diffs - | options::opts::no_merges | options::opts::no_files) + | options::opts::brief | options::opts::diffs + | options::opts::no_merges | options::opts::no_files + | options::opts::no_graph) { if (app.opts.from.size() == 0) app.require_workspace("try passing a --from revision to start at"); @@ -615,7 +617,7 @@ CMD(log, N_("informative"), N_("[FILE] . frontier_t frontier(rev_cmp(!(next>0))); revision_id first_rid; // for mapping paths to node ids when restricted - + if (app.opts.from.size() == 0) { app.work.get_revision_id(first_rid); @@ -661,7 +663,7 @@ CMD(log, N_("informative"), N_("[FILE] . // FIXME_RESTRICTIONS: should this add paths from the rosters of // all selected revs? mask = node_restriction(args_to_paths(args), - args_to_paths(app.opts.exclude_patterns), + args_to_paths(app.opts.exclude_patterns), app.opts.depth, old_roster, new_roster, app); } @@ -734,11 +736,14 @@ CMD(log, N_("informative"), N_("[FILE] . set seen; revision_t rev; - while(! frontier.empty() && (last == -1 || last > 0) + asciik * graph = NULL; + if (!app.opts.no_graph) + graph = new asciik(); + while(! frontier.empty() && (last == -1 || last > 0) && (next == -1 || next > 0)) { revision_id const & rid = frontier.top().second; - + bool print_this = mask.empty(); set diff_paths; @@ -765,7 +770,7 @@ CMD(log, N_("informative"), N_("[FILE] . { node_id node = m->first; marking_t marking = m->second; - + if (mask.includes(roster, node)) { marked_revs.insert(marking.file_content.begin(), marking.file_content.end()); @@ -784,12 +789,12 @@ CMD(log, N_("informative"), N_("[FILE] . select_nodes_modified_by_rev(rev, roster, nodes_modified, app); - + for (set::const_iterator n = nodes_modified.begin(); n != nodes_modified.end(); ++n) { // a deleted node will be "modified" but won't - // exist in the result. + // exist in the result. // we don't want to print them. if (roster.has_node(*n) && mask.includes(roster, *n)) { @@ -807,52 +812,57 @@ CMD(log, N_("informative"), N_("[FILE] . if (app.opts.no_merges && rev.is_merge_node()) print_this = false; - + if (print_this) { + ostream * out; + if (graph) + out = new ostringstream; + else + out = &cout; if (app.opts.brief) { - cout << rid; - log_certs(cout, app, rid, author_name); - log_certs(cout, app, rid, date_name); - log_certs(cout, app, rid, branch_name); - cout << "\n"; + *out << rid; + log_certs(*out, app, rid, author_name); + log_certs(*out, app, rid, date_name); + log_certs(*out, app, rid, branch_name); + *out << "\n"; } else { - cout << string(65, '-') << "\n"; - cout << "Revision: " << rid << "\n"; - + *out << string(65, '-') << "\n"; + *out << "Revision: " << rid << "\n"; + changes_summary csum; - + set ancestors; - + for (edge_map::const_iterator e = rev.edges.begin(); e != rev.edges.end(); ++e) { ancestors.insert(edge_old_revision(e)); csum.add_change_set(edge_changes(e)); } - - for (set::const_iterator + + for (set::const_iterator anc = ancestors.begin(); anc != ancestors.end(); ++anc) - cout << "Ancestor: " << *anc << "\n"; + *out << "Ancestor: " << *anc << "\n"; - log_certs(cout, app, rid, author_name, "Author: ", false); - log_certs(cout, app, rid, date_name, "Date: ", false); - log_certs(cout, app, rid, branch_name, "Branch: ", false); - log_certs(cout, app, rid, tag_name, "Tag: ", false); + log_certs(*out, app, rid, author_name, "Author: ", false); + log_certs(*out, app, rid, date_name, "Date: ", false); + log_certs(*out, app, rid, branch_name, "Branch: ", false); + log_certs(*out, app, rid, tag_name, "Tag: ", false); if (!app.opts.no_files && !csum.cs.empty()) { - cout << "\n"; - csum.print(cout, 70); - cout << "\n"; + *out << "\n"; + csum.print(*out, 70); + *out << "\n"; } - - log_certs(cout, app, rid, changelog_name, "ChangeLog: ", true); - log_certs(cout, app, rid, comment_name, "Comments: ", true); + + log_certs(*out, app, rid, changelog_name, "ChangeLog: ", true); + log_certs(*out, app, rid, comment_name, "Comments: ", true); } if (app.opts.diffs) @@ -860,7 +870,7 @@ CMD(log, N_("informative"), N_("[FILE] . for (edge_map::const_iterator e = rev.edges.begin(); e != rev.edges.end(); ++e) { - dump_diffs(edge_changes(e), app, true, cout, + dump_diffs(edge_changes(e), app, true, *out, diff_paths, !mask.empty()); } } @@ -874,7 +884,14 @@ CMD(log, N_("informative"), N_("[FILE] . last--; } - cout.flush(); + out->flush(); + if (graph) { + // an ASCII-k graph was requested + set parents; + app.db.get_revision_parents(rid, parents); + graph->print(rid, parents, static_cast(out)->str()); + delete out; + } } set interesting; @@ -886,7 +903,7 @@ CMD(log, N_("informative"), N_("[FILE] . } else { - if (next > 0) + if (next > 0) { app.db.get_revision_children(rid, interesting); } @@ -910,6 +927,8 @@ CMD(log, N_("informative"), N_("[FILE] . frontier.push(make_pair(height, *i)); } } + if (graph) + delete graph; } // Local Variables: ============================================================ --- options_list.hh bdf99561b7ca94bcf196ca26b8d192d8d74f1492 +++ options_list.hh 32e67fa380672bec58a2a66f520044c5b8983242 @@ -369,6 +369,14 @@ OPT(no_files, "no-files", bool, false, } #endif +OPT(no_graph, "no-graph", bool, false, + gettext_noop("do not use ASCII graph to display ancestry")) +#ifdef option_bodies +{ + no_graph = true; +} +#endif + OPT(no_ignore, "no-respect-ignore", bool, false, gettext_noop("do not ignore any files")) #ifdef option_bodies