#
#
# patch "ChangeLog"
# from [dccb6e1883e29ab316de6bbd602c762b229d3545]
# to [9710d177621d9a9d07ee431fb2d4ddf3c2e0ddbe]
#
# patch "automate.cc"
# from [18458490c7f2fd24860839b4a474e4e2197f56dd]
# to [fdadb677f9ae73cd6fccfe9faa181fdf731779c6]
#
# patch "cmd.hh"
# from [7142b69f986d070ea15a283a19fa16e4fb9edd59]
# to [288b76d82d3f84e98ac280e660c03018ad9da22e]
#
# patch "cmd_diff_log.cc"
# from [9bf839e131811070ee4518463761205937bf6e6f]
# to [eda0cb4e16eccb3f65d97e59f7a478b1d3c75763]
#
# patch "commands.cc"
# from [c9e6fdb67f72a37dc491317be70923b5c701748a]
# to [0b458fd786d390b71125302a999cd2ad075f7f0d]
#
============================================================
--- ChangeLog dccb6e1883e29ab316de6bbd602c762b229d3545
+++ ChangeLog 9710d177621d9a9d07ee431fb2d4ddf3c2e0ddbe
@@ -1,3 +1,15 @@
+2006-10-19 Thomas Keller
+
+ * automate.cc: added content_diff command which makes the output of mtn diff
+ (minus the revision part) available via mtn automate
+ * automate.cc: fixed "introduced in" of get_content_changed and
+ get_corresponding_path (this was in 3.1, not 3.2)
+ * cmd_automate.cc: bumped interface version to 3.2
+ * cmd_diff_log.cc: moved dump_diff and do_external_diff ...
+ * commands.*: ...here and added an additional ostream parameter to
+ dump_diff to be able to use this with automate stdio
+ * TODO: docs and tests
+
2006-10-15 Timothy Brownawell
Propagate the rerwite of 'automate stdio' (in branch
============================================================
--- automate.cc 18458490c7f2fd24860839b4a474e4e2197f56dd
+++ automate.cc fdadb677f9ae73cd6fccfe9faa181fdf731779c6
@@ -1499,7 +1499,7 @@ AUTOMATE(get_option, N_("OPTION"))
// Arguments:
// 1: a revision ID
// 2: a file name
-// Added in: 3.2
+// Added in: 3.1
// Purpose: Returns a list of revision IDs in which the content
// was most recently changed, relative to the revision ID specified
// in argument 1. This equates to a content mark following
@@ -1556,7 +1556,7 @@ AUTOMATE(get_content_changed, N_("REV FI
// 1: a source revision ID
// 2: a file name (in the source revision)
// 3: a target revision ID
-// Added in: 3.2
+// Added in: 3.1
// Purpose: Given a the file name in the source revision, a filename
// will if possible be returned naming the file in the target revision.
// This allows the same file to be matched between revisions, accounting
@@ -1612,6 +1612,154 @@ AUTOMATE(get_corresponding_path, N_("REV
output.write(prt.buf.data(), prt.buf.size());
}
+// Name: content_diff
+// Arguments:
+// 1: (optional) one or more files to include
+// 2: (optional) if given, left rev is workspace and right is this rev
+// 3: (optional) if given, 2) is left rev and this is the right rev
+// Added in: 3.2
+// Purpose: Availability of mtn diff as automate command.
+//
+// Output format: Like mtn diff, but with the header part omitted (as this is
+// doubles the output of automate get_revision). If no content changes happened,
+// the output is empty. All file operations beside mtn add are omitted,
+// as they don't change the content of the file.
+AUTOMATE(content_diff, N_("[FILE [...] [REV1 [REV2]]]"))
+{
+ vector rev_ids;
+ vector other_args;
+ revision_id ident;
+
+ // check for revision and file arguments, go from right to left
+ for (int i=args.size()-1; i>=0; i--)
+ {
+ ident = revision_id();
+ if (app.db.revision_exists(ident))
+ {
+ rev_ids.push_back(ident);
+ continue;
+ }
+
+ // then maybe this is a path...?
+ other_args.push_back(utf8(idx(args, i)()));
+ }
+
+ int rev_count = rev_ids.size();
+
+ // check if we got more than the expected two revids
+ N(rev_count <= 2,
+ F("expected zero, one or two REVISION arguments"));
+
+ // if we didn't receive two revision ids, we require a workspace against
+ // we can diff
+ if (rev_count < 2)
+ app.require_workspace();
+
+ temp_node_id_source nis;
+ cset included, excluded;
+ bool new_is_archived;
+
+ //
+ // What follows is pretty much copied from cmd_diff_log.cc line 202ff
+ // with some slight adaptions noted with separate FIXMEs
+ // TODO: someone with a better overview should probably factor this
+ // out somewhere
+ //
+ if (rev_count == 0)
+ {
+ roster_t new_roster, old_roster;
+ revision_id old_rid;
+
+ app.work.get_base_and_current_roster_shape(old_roster, new_roster, nis);
+ app.work.get_revision_id(old_rid);
+
+ //node_restriction mask(args_to_paths(args),
+ node_restriction mask(args_to_paths(other_args),
+ args_to_paths(app.exclude_patterns),
+ app.depth,
+ old_roster, new_roster, app);
+
+ app.work.update_current_roster_from_filesystem(new_roster, mask);
+ make_restricted_csets(old_roster, new_roster,
+ included, excluded, mask);
+ check_restricted_cset(old_roster, included);
+
+ new_is_archived = false;
+ // FIXME: not needed here, automate get_revision does the same
+ //header << "# old_revision [" << old_rid << "]" << "\n";
+ }
+ else if (rev_count == 1)
+ {
+ roster_t new_roster, old_roster;
+ revision_id r_old_id;
+
+ // FIXME: not needed here, since we require complete revids and
+ // already have checked their existence
+ //complete(app, idx(app.revision_selectors, 0)(), r_old_id);
+ //N(app.db.revision_exists(r_old_id),
+ // F("no such revision '%s'") % r_old_id);
+
+ app.work.get_base_and_current_roster_shape(old_roster, new_roster, nis);
+ // Clobber old_roster with the one specified
+ app.db.get_roster(r_old_id, old_roster);
+
+ // FIXME: handle no ancestor case
+ // N(r_new.edges.size() == 1, F("current revision has no ancestor"));
+
+ //node_restriction mask(args_to_paths(args),
+ node_restriction mask(args_to_paths(other_args),
+ args_to_paths(app.exclude_patterns),
+ app.depth,
+ old_roster, new_roster, app);
+
+ app.work.update_current_roster_from_filesystem(new_roster, mask);
+ make_restricted_csets(old_roster, new_roster,
+ included, excluded, mask);
+ check_restricted_cset(old_roster, included);
+
+ new_is_archived = false;
+ // FIXME: not needed here, automate get_revision does the same
+ //header << "# old_revision [" << r_old_id << "]" << "\n";
+ }
+ else
+ {
+ roster_t new_roster, old_roster;
+ revision_id r_old_id, r_new_id;
+
+ // FIXME: not needed here, since we require complete revids and
+ // already have checked their existence
+ //complete(app, idx(app.revision_selectors, 0)(), r_old_id);
+ //complete(app, idx(app.revision_selectors, 1)(), r_new_id);
+ //N(app.db.revision_exists(r_old_id),
+ // F("no such revision '%s'") % r_old_id);
+ //N(app.db.revision_exists(r_new_id),
+ // F("no such revision '%s'") % r_new_id);
+
+ app.db.get_roster(r_old_id, old_roster);
+ app.db.get_roster(r_new_id, new_roster);
+
+ node_restriction mask(args_to_paths(args),
+ args_to_paths(app.exclude_patterns),
+ app.depth,
+ old_roster, new_roster, app);
+
+ // FIXME: this is *possibly* a UI bug, insofar as we [...]
+ // (see cmd_diff_log.cc for the full comment)
+
+ make_restricted_csets(old_roster, new_roster,
+ included, excluded, mask);
+ check_restricted_cset(old_roster, included);
+
+ new_is_archived = true;
+ }
+
+ //
+ // copy from cmd_diff_log.cc end
+ //
+
+ dump_diffs(included, app, new_is_archived, output);
+}
+
// Local Variables:
// mode: C++
// fill-column: 76
============================================================
--- cmd.hh 7142b69f986d070ea15a283a19fa16e4fb9edd59
+++ cmd.hh 288b76d82d3f84e98ac280e660c03018ad9da22e
@@ -87,6 +87,25 @@ void
revision_id const & id);
void
+dump_diffs(cset const & cs,
+ app_state & app,
+ bool new_is_archived,
+ std::ostream & output);
+
+void
+dump_diffs(cset const & cs,
+ app_state & app,
+ bool new_is_archived,
+ std::ostream & output,
+ std::set const & paths,
+ bool limit_paths=false);
+
+void
+do_external_diff(cset const & cs,
+ app_state & app,
+ bool new_is_archived);
+
+void
complete(app_state & app,
std::string const & str,
revision_id & completion,
============================================================
--- cmd_diff_log.cc 9bf839e131811070ee4518463761205937bf6e6f
+++ cmd_diff_log.cc eda0cb4e16eccb3f65d97e59f7a478b1d3c75763
@@ -14,7 +14,6 @@
#include "cmd.hh"
#include "diff_patch.hh"
-#include "localized_file_io.hh"
#include "restrictions.hh"
#include "revision.hh"
#include "simplestring_xform.hh"
@@ -172,162 +171,6 @@ changes_summary::print(ostream & os, siz
}
}
-static void
-do_external_diff(cset const & cs,
- app_state & app,
- bool new_is_archived)
-{
- for (map >::const_iterator
- i = cs.deltas_applied.begin();
- i != cs.deltas_applied.end(); ++i)
- {
- data data_old;
- data data_new;
-
- file_data f_old;
- app.db.get_file_version(delta_entry_src(i), f_old);
- data_old = f_old.inner();
-
- if (new_is_archived)
- {
- file_data f_new;
- app.db.get_file_version(delta_entry_dst(i), f_new);
- data_new = f_new.inner();
- }
- else
- {
- read_localized_data(file_path(delta_entry_path(i)),
- data_new, app.lua);
- }
-
- bool is_binary = false;
- if (guess_binary(data_old()) ||
- guess_binary(data_new()))
- is_binary = true;
-
- app.lua.hook_external_diff(file_path(delta_entry_path(i)),
- data_old,
- data_new,
- is_binary,
- app.diff_args_provided,
- app.diff_args(),
- delta_entry_src(i).inner()(),
- delta_entry_dst(i).inner()());
- }
-}
-
-static void
-dump_diffs(cset const & cs,
- app_state & app,
- bool new_is_archived,
- set const & paths,
- bool limit_paths = false)
-{
- // 60 is somewhat arbitrary, but less than 80
- string patch_sep = string(60, '=');
-
- for (map::const_iterator
- i = cs.files_added.begin();
- i != cs.files_added.end(); ++i)
- {
- if (limit_paths && paths.find(i->first) == paths.end())
- continue;
-
- cout << patch_sep << "\n";
- data unpacked;
- vector lines;
-
- if (new_is_archived)
- {
- file_data dat;
- app.db.get_file_version(i->second, dat);
- unpacked = dat.inner();
- }
- else
- {
- read_localized_data(file_path(i->first),
- unpacked, app.lua);
- }
-
- std::string pattern("");
- if (app.diff_show_encloser)
- app.lua.hook_get_encloser_pattern(file_path(i->first),
- pattern);
-
- make_diff(file_path(i->first).as_internal(),
- file_path(i->first).as_internal(),
- i->second,
- i->second,
- data(), unpacked,
- cout, app.diff_format, pattern);
- }
-
- map reverse_rename_map;
-
- for (map::const_iterator
- i = cs.nodes_renamed.begin();
- i != cs.nodes_renamed.end(); ++i)
- {
- reverse_rename_map.insert(make_pair(i->second, i->first));
- }
-
- for (map >::const_iterator
- i = cs.deltas_applied.begin();
- i != cs.deltas_applied.end(); ++i)
- {
- if (limit_paths && paths.find(i->first) == paths.end())
- continue;
-
- file_data f_old;
- data data_old, data_new;
-
- cout << patch_sep << "\n";
-
- app.db.get_file_version(delta_entry_src(i), f_old);
- data_old = f_old.inner();
-
- if (new_is_archived)
- {
- file_data f_new;
- app.db.get_file_version(delta_entry_dst(i), f_new);
- data_new = f_new.inner();
- }
- else
- {
- read_localized_data(file_path(delta_entry_path(i)),
- data_new, app.lua);
- }
-
- split_path dst_path = delta_entry_path(i);
- split_path src_path = dst_path;
- map::const_iterator re;
- re = reverse_rename_map.find(dst_path);
- if (re != reverse_rename_map.end())
- src_path = re->second;
-
- std::string pattern("");
- if (app.diff_show_encloser)
- app.lua.hook_get_encloser_pattern(file_path(src_path),
- pattern);
-
- make_diff(file_path(src_path).as_internal(),
- file_path(dst_path).as_internal(),
- delta_entry_src(i),
- delta_entry_dst(i),
- data_old, data_new,
- cout, app.diff_format, pattern);
- }
-}
-
-static void
-dump_diffs(cset const & cs,
- app_state & app,
- bool new_is_archived)
-{
- set dummy;
- dump_diffs(cs, app, new_is_archived, dummy);
-}
-
CMD(diff, N_("informative"), N_("[PATH]..."),
N_("show current diffs on stdout.\n"
"If one revision is given, the diff between the workspace and\n"
@@ -481,7 +324,7 @@ CMD(diff, N_("informative"), N_("[PATH].
if (app.diff_format == external_diff) {
do_external_diff(included, app, new_is_archived);
} else
- dump_diffs(included, app, new_is_archived);
+ dump_diffs(included, app, new_is_archived, cout);
}
static void
@@ -728,8 +571,8 @@ 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, diff_paths,
- !mask.empty());
+ dump_diffs(edge_changes(e), app, true, cout,
+ diff_paths, !mask.empty());
}
}
============================================================
--- commands.cc c9e6fdb67f72a37dc491317be70923b5c701748a
+++ commands.cc 0b458fd786d390b71125302a999cd2ad075f7f0d
@@ -12,7 +12,9 @@
#include "transforms.hh"
#include "simplestring_xform.hh"
+#include "localized_file_io.hh"
#include "charset.hh"
+#include "diff_patch.hh"
#include "inodeprint.hh"
#include "cert.hh"
#include "ui.hh"
@@ -24,6 +26,8 @@ using std::cin;
#endif
using std::cin;
+using std::map;
+using std::ostream;
using std::pair;
using std::set;
using std::string;
@@ -474,6 +478,165 @@ process_commit_message_args(bool & given
given = false;
}
+void
+do_external_diff(cset const & cs,
+ app_state & app,
+ bool new_is_archived)
+{
+ for (map >::const_iterator
+ i = cs.deltas_applied.begin();
+ i != cs.deltas_applied.end(); ++i)
+ {
+ data data_old;
+ data data_new;
+
+ file_data f_old;
+ app.db.get_file_version(delta_entry_src(i), f_old);
+ data_old = f_old.inner();
+
+ if (new_is_archived)
+ {
+ file_data f_new;
+ app.db.get_file_version(delta_entry_dst(i), f_new);
+ data_new = f_new.inner();
+ }
+ else
+ {
+ read_localized_data(file_path(delta_entry_path(i)),
+ data_new, app.lua);
+ }
+
+ bool is_binary = false;
+ if (guess_binary(data_old()) ||
+ guess_binary(data_new()))
+ is_binary = true;
+
+ app.lua.hook_external_diff(file_path(delta_entry_path(i)),
+ data_old,
+ data_new,
+ is_binary,
+ app.diff_args_provided,
+ app.diff_args(),
+ delta_entry_src(i).inner()(),
+ delta_entry_dst(i).inner()());
+ }
+}
+
+void
+dump_diffs(cset const & cs,
+ app_state & app,
+ bool new_is_archived,
+ ostream & output,
+ set const & paths,
+ bool limit_paths)
+{
+ // 60 is somewhat arbitrary, but less than 80
+ string patch_sep = string(60, '=');
+
+ for (map::const_iterator
+ i = cs.files_added.begin();
+ i != cs.files_added.end(); ++i)
+ {
+ if (limit_paths && paths.find(i->first) == paths.end())
+ continue;
+
+ output << patch_sep << "\n";
+ data unpacked;
+ vector lines;
+
+ if (new_is_archived)
+ {
+ file_data dat;
+ app.db.get_file_version(i->second, dat);
+ unpacked = dat.inner();
+ }
+ else
+ {
+ read_localized_data(file_path(i->first),
+ unpacked, app.lua);
+ }
+
+ std::string pattern("");
+ if (app.diff_show_encloser)
+ app.lua.hook_get_encloser_pattern(file_path(i->first),
+ pattern);
+
+ make_diff(file_path(i->first).as_internal(),
+ file_path(i->first).as_internal(),
+ i->second,
+ i->second,
+ data(), unpacked,
+ output, app.diff_format, pattern);
+ }
+
+ map reverse_rename_map;
+
+ for (map::const_iterator
+ i = cs.nodes_renamed.begin();
+ i != cs.nodes_renamed.end(); ++i)
+ {
+ reverse_rename_map.insert(make_pair(i->second, i->first));
+ }
+
+ for (map >::const_iterator
+ i = cs.deltas_applied.begin();
+ i != cs.deltas_applied.end(); ++i)
+ {
+ if (limit_paths && paths.find(i->first) == paths.end())
+ continue;
+
+ file_data f_old;
+ data data_old, data_new;
+
+ output << patch_sep << "\n";
+
+ app.db.get_file_version(delta_entry_src(i), f_old);
+ data_old = f_old.inner();
+
+ if (new_is_archived)
+ {
+ file_data f_new;
+ app.db.get_file_version(delta_entry_dst(i), f_new);
+ data_new = f_new.inner();
+ }
+ else
+ {
+ read_localized_data(file_path(delta_entry_path(i)),
+ data_new, app.lua);
+ }
+
+ split_path dst_path = delta_entry_path(i);
+ split_path src_path = dst_path;
+ map::const_iterator re;
+ re = reverse_rename_map.find(dst_path);
+ if (re != reverse_rename_map.end())
+ src_path = re->second;
+
+ std::string pattern("");
+ if (app.diff_show_encloser)
+ app.lua.hook_get_encloser_pattern(file_path(src_path),
+ pattern);
+
+ make_diff(file_path(src_path).as_internal(),
+ file_path(dst_path).as_internal(),
+ delta_entry_src(i),
+ delta_entry_dst(i),
+ data_old, data_new,
+ output, app.diff_format, pattern);
+ }
+}
+
+void
+dump_diffs(cset const & cs,
+ app_state & app,
+ bool new_is_archived,
+ ostream & output)
+{
+ set dummy;
+ dump_diffs(cs, app, new_is_archived, output, dummy);
+}
+
+
// Local Variables:
// mode: C++
// fill-column: 76