#
# patch "ChangeLog"
# from [02d9f88ecd8c8f495bff7f366bfd5e0551292ec9]
# to [20da57258f07e3fecb32253bcadcbfb237f81f6b]
#
# patch "app_state.cc"
# from [976ea774c4fd1df5e9d63ee5b19f1a925899c12b]
# to [8efdcd302100554f04d225c9e5ddfe9ddc1bff3a]
#
# patch "app_state.hh"
# from [ad40f04b056e67723f755a752d17e0ab7107dac4]
# to [15ba734efc432db709cc66ee01c7c104e5554e50]
#
# patch "commands.cc"
# from [668364db356c8b18906474160174ee9b30d7d699]
# to [41f74675806bc533e9ecc46b5dfb5c3ffb09d263]
#
# patch "diff_patch.cc"
# from [fbef84d6f575c4f14850b8a8e7d78e42021a0e80]
# to [022e125cb1265ea8d0a484289b952587060053cc]
#
# patch "diff_patch.hh"
# from [18be28ae5d744c23da230988bd4a48f6556cb4b4]
# to [f499e229bf13e49c06c4c9129a1e48b2b1a7ef65]
#
# patch "lua.cc"
# from [a8af56ad7fe0d9baa85c265b05dd94877a806c19]
# to [7f7d2cd8e90e9224d82fc66216093307306fa653]
#
# patch "lua.hh"
# from [0c4f6966a60230b591f07d0a0519485bf451a349]
# to [517f80335c5433b0134e70a53f0d26f9563151dc]
#
# patch "monotone.cc"
# from [240b0908b7d873c84df7cd1ca676d44a490b778f]
# to [46cbc3c75c039ef547e3d566c79fd33a2acdcf52]
#
# patch "monotone.texi"
# from [80f97d74395a57fc85b24b54329d0c10f1639c99]
# to [9e37ce22ceb10715bf1ed4efa1fe44f1b1d02a22]
#
# patch "options.hh"
# from [2d21f8009f424d24e5513c3894c0ff321e79feb0]
# to [814c3c354201a830e7bce20f0a8dc48d79b9cf8c]
#
# patch "std_hooks.lua"
# from [072c95bc58425ade43dc08e8361c7aca49275dd4]
# to [80a530bdeb7e4526a8b97c9f9d6c071a7b1f05e0]
#
# patch "tests/t_crlf.at"
# from [ac04c64a00a9691b7599320562dacdb34641779c]
# to [c77173aa37c0c6a9e628aa5528069ef3afddf6cb]
#
# patch "tests/t_restrictions.at"
# from [be72348a94c89d89703de67b40c886edc2bef302]
# to [84972130299ee9cc3449101f4a4135795cf863f0]
#
# patch "vocab.hh"
# from [77bb3d7df9abc7e4e5202cb20b313c925dad2c13]
# to [d6352245e0e2260db3f53cd0f7731a7bc07fd225]
#
--- ChangeLog
+++ ChangeLog
@@ -1,3 +1,22 @@
+2005-07-16 Vladimir Vukicevic
+
+ * lua.{cc,hh} (hook_external_diff): New hook.
+ * std_hooks.lua (external_diff): Add default definition.
+ * monotone.texi (Hooks): Document external_diff hook.
+ * app_state.{cc,hh}, options.hh, monotone.cc: Add --context,
+ --external, --unified, --diff-args options.
+ * commands.cc (do_external_diff): New function.
+ (dump_diffs): Put a == line between each file's diffs.
+ Pass file_ids of pre- and post-states to make_diff.
+ (diff): Take new options.
+ (cdiff): Remove.
+ * diff_patch.{cc,hh} (make_diff): Print file ids in diff file
+ headers.
+ (unidiff_append_test): Update.
+ (enum diff_type): Move to...
+ * vocab.hh: ...here.
+ * tests/t_restrictions.at, tests/t_crlf.at: Update.
+
2005-07-16 Nathaniel Smith
* manifest.cc (build_restricted_manifest_map): Remove doubled
--- app_state.cc
+++ app_state.cc
@@ -34,7 +34,7 @@
app_state::app_state()
: branch_name(""), db(""), stdhooks(true), rcfiles(true), diffs(false),
no_merges(false), set_default(false), verbose(false), search_root("/"),
- depth(-1), last(-1)
+ depth(-1), last(-1), diff_format(unified_diff)
{
db.set_app(this);
}
@@ -352,6 +352,18 @@
}
void
+app_state::set_diff_format(diff_type dtype)
+{
+ diff_format = dtype;
+}
+
+void
+app_state::set_diff_args(utf8 const & args)
+{
+ diff_args = args;
+}
+
+void
app_state::set_stdhooks(bool b)
{
stdhooks = b;
--- app_state.hh
+++ app_state.hh
@@ -50,6 +50,8 @@
long depth;
long last;
fs::path pidfile;
+ diff_type diff_format;
+ utf8 diff_args;
void allow_working_copy();
void require_working_copy(std::string const & explanation = "");
@@ -82,6 +84,8 @@
void set_pidfile(utf8 const & pidfile);
void add_revision(utf8 const & selector);
void add_exclude(utf8 const & exclude_pattern);
+ void set_diff_format(diff_type dtype);
+ void set_diff_args(utf8 const & args);
void set_stdhooks(bool b);
void set_rcfiles(bool b);
--- commands.cc
+++ commands.cc
@@ -2527,7 +2527,51 @@
ALIAS(ci, commit);
+static void
+do_external_diff(change_set::delta_map const & deltas,
+ app_state & app,
+ bool new_is_archived)
+{
+ for (change_set::delta_map::const_iterator i = deltas.begin();
+ i != deltas.end(); ++i)
+ {
+ data data_old;
+ data data_new;
+ if (!null_id(delta_entry_src(i)))
+ {
+ 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(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(delta_entry_path(i),
+ data_old,
+ data_new,
+ is_binary,
+ app.diff_args(),
+ delta_entry_src(i).inner()(),
+ delta_entry_dst(i).inner()());
+ }
+}
+
static void
dump_diffs(change_set::delta_map const & deltas,
app_state & app,
@@ -2562,8 +2606,9 @@
split_into_lines(unpacked(), lines);
if (! lines.empty())
{
- cout << (F("--- %s\n") % delta_entry_path(i))
- << (F("+++ %s\n") % delta_entry_path(i))
+ cout << "===============================================\n";
+ cout << (F("--- %s\t%s\n") % delta_entry_path(i) % delta_entry_src(i))
+ << (F("+++ %s\t%s\n") % delta_entry_path(i) % delta_entry_dst(i))
<< (F("@@ -0,0 +1,%d @@\n") % lines.size());
for (vector::const_iterator j = lines.begin();
j != lines.end(); ++j)
@@ -2603,6 +2648,8 @@
split_into_lines(data_new(), new_lines);
make_diff(delta_entry_path(i)(),
delta_entry_path(i)(),
+ delta_entry_src(i),
+ delta_entry_dst(i),
old_lines, new_lines,
cout, type);
}
@@ -2610,14 +2657,19 @@
}
}
-void do_diff(const string & name,
- app_state & app,
- vector const & args,
- diff_type type)
+CMD(diff, "informative", "[PATH]...",
+ "show current diffs on stdout.\n"
+ "If one revision is given, the diff between the working directory and\n"
+ "that revision is shown. If two revisions are given, the diff between\n"
+ "them is given. If no format is specified, unified is used by default.",
+ OPT_BRANCH_NAME % OPT_REVISION % OPT_DEPTH %
+ OPT_UNIFIED_DIFF % OPT_CONTEXT_DIFF % OPT_EXTERNAL_DIFF %
+ OPT_EXTERNAL_DIFF_ARGS)
{
revision_set r_old, r_new;
manifest_map m_new;
bool new_is_archived;
+ diff_type type = app.diff_format;
change_set composite;
@@ -2726,29 +2778,12 @@
}
cout << "# " << endl;
- dump_diffs(composite.deltas, app, new_is_archived, type);
+ if (type == external_diff) {
+ do_external_diff(composite.deltas, app, new_is_archived);
+ } else
+ dump_diffs(composite.deltas, app, new_is_archived, type);
}
-CMD(cdiff, "informative", "[PATH]...",
- "show current context diffs on stdout.\n"
- "If one revision is given, the diff between the working directory and\n"
- "that revision is shown. If two revisions are given, the diff between\n"
- "them is given.",
- OPT_BRANCH_NAME % OPT_REVISION % OPT_DEPTH)
-{
- do_diff(name, app, args, context_diff);
-}
-
-CMD(diff, "informative", "[PATH]...",
- "show current unified diffs on stdout.\n"
- "If one revision is given, the diff between the working directory and\n"
- "that revision is shown. If two revisions are given, the diff between\n"
- "them is given.",
- OPT_BRANCH_NAME % OPT_REVISION % OPT_DEPTH)
-{
- do_diff(name, app, args, unified_diff);
-}
-
CMD(lca, "debug", "LEFT RIGHT", "print least common ancestor", OPT_NONE)
{
if (args.size() != 2)
--- diff_patch.cc
+++ diff_patch.cc
@@ -1079,6 +1079,8 @@
void make_diff(string const & filename1,
string const & filename2,
+ file_id const & id1,
+ file_id const & id2,
vector const & lines1,
vector const & lines2,
ostream & ost,
@@ -1110,8 +1112,9 @@
{
case unified_diff:
{
- ost << "--- " << filename1 << endl;
- ost << "+++ " << filename2 << endl;
+ ost << "===============================================" << endl;
+ ost << "--- " << filename1 << "\t" << id1 << endl;
+ ost << "+++ " << filename2 << "\t" << id2 << endl;
unidiff_hunk_writer hunks(lines1, lines2, 3, ost);
walk_hunk_consumer(lcs, left_interned, right_interned, hunks);
@@ -1119,13 +1122,20 @@
}
case context_diff:
{
- ost << "*** " << filename1 << endl;
- ost << "--- " << filename2 << endl;
+ ost << "===============================================" << endl;
+ ost << "*** " << filename1 << "\t" << id1 << endl;
+ ost << "--- " << filename2 << "\t" << id2 << endl;
cxtdiff_hunk_writer hunks(lines1, lines2, 3, ost);
walk_hunk_consumer(lcs, left_interned, right_interned, hunks);
break;
}
+ default:
+ {
+ // should never reach this; the external_diff type is not
+ // handled by this function.
+ I(false);
+ }
}
}
@@ -1195,8 +1205,9 @@
+ "}\n"
+ "\n");
- string ud(string("--- hello.c\n")
- + "+++ hello.c\n"
+ string ud(string("===============================================\n")
+ + "--- hello.c\t0123456789abcdef0123456789abcdef01234567\n"
+ + "+++ hello.c\tabcdef0123456789abcdef0123456789abcdef01\n"
+ "@@ -9,3 +9,9 @@\n"
+ " {\n"
+ " say_hello();\n"
@@ -1212,7 +1223,11 @@
split_into_lines(src, src_lines);
split_into_lines(dst, dst_lines);
stringstream sst;
- make_diff("hello.c", "hello.c", src_lines, dst_lines, sst, unified_diff);
+ make_diff("hello.c", "hello.c",
+ file_id(id("0123456789abcdef0123456789abcdef01234567")),
+ file_id(id("abcdef0123456789abcdef0123456789abcdef01")),
+ src_lines, dst_lines, sst, unified_diff);
+ cout << sst.str() << std::endl;
BOOST_CHECK(sst.str() == ud);
}
--- diff_patch.hh
+++ diff_patch.hh
@@ -19,15 +19,10 @@
// this file is to contain some stripped down, in-process implementations
// of GNU-diffutils-like things (diff, diff3, maybe patch..)
-
-enum diff_type
-{
- unified_diff,
- context_diff
-};
-
void make_diff(std::string const & filename1,
std::string const & filename2,
+ file_id const & id1,
+ file_id const & id2,
std::vector const & lines1,
std::vector const & lines2,
std::ostream & ost,
--- lua.cc
+++ lua.cc
@@ -1023,7 +1023,41 @@
return ok;
}
+bool
+lua_hooks::hook_external_diff(file_path const & path,
+ data const & data_old,
+ data const & data_new,
+ bool is_binary,
+ std::string const & diff_args,
+ std::string const & oldrev,
+ std::string const & newrev)
+{
+ Lua ll(st);
+ ll
+ .func("external_diff")
+ .push_str(path());
+
+ if (oldrev.length() != 0)
+ ll.push_str(data_old());
+ else
+ ll.push_nil();
+
+ ll.push_str(data_new());
+
+ ll.push_bool(is_binary);
+
+ if (diff_args.length() != 0)
+ ll.push_str(diff_args);
+ else
+ ll.push_nil();
+
+ ll.push_str(oldrev);
+ ll.push_str(newrev);
+
+ return ll.call(7,0).ok();
+}
+
bool
lua_hooks::hook_use_inodeprints()
{
--- lua.hh
+++ lua.hh
@@ -95,6 +95,14 @@
file_path const & b,
file_path & res);
+ bool hook_external_diff(file_path const & path,
+ data const & data_old,
+ data const & data_new,
+ bool is_binary,
+ std::string const & diff_args,
+ std::string const & oldrev,
+ std::string const & newrev);
+
// working copy hooks
bool hook_use_inodeprints();
--- monotone.cc
+++ monotone.cc
@@ -59,6 +59,10 @@
{"no-merges", 0, POPT_ARG_NONE, NULL, OPT_NO_MERGES, "skip merges when printing logs", NULL},
{"set-default", 0, POPT_ARG_NONE, NULL, OPT_SET_DEFAULT, "use the current arguments as the future default", NULL},
{"exclude", 0, POPT_ARG_STRING, &argstr, OPT_EXCLUDE, "leave out branches matching a pattern", NULL},
+ {"unified", 0, POPT_ARG_NONE, NULL, OPT_UNIFIED_DIFF, "Use unified diff format", NULL},
+ {"context", 0, POPT_ARG_NONE, NULL, OPT_CONTEXT_DIFF, "Use context diff format", NULL},
+ {"external", 0, POPT_ARG_NONE, NULL, OPT_EXTERNAL_DIFF, "Use external diff hook for generating diffs", NULL},
+ {"diff-args", 0, POPT_ARG_STRING, &argstr, OPT_EXTERNAL_DIFF_ARGS, "Argument to pass external diff hook", NULL},
{ NULL, 0, 0, NULL, 0, NULL, NULL }
};
@@ -407,6 +411,22 @@
my_poptStuffArgFile(ctx(), utf8(string(argstr)));
break;
+ case OPT_UNIFIED_DIFF:
+ app.set_diff_format(unified_diff);
+ break;
+
+ case OPT_CONTEXT_DIFF:
+ app.set_diff_format(context_diff);
+ break;
+
+ case OPT_EXTERNAL_DIFF:
+ app.set_diff_format(external_diff);
+ break;
+
+ case OPT_EXTERNAL_DIFF_ARGS:
+ app.set_diff_args(utf8(string(argstr)));
+ break;
+
case OPT_HELP:
default:
requested_help = true;
--- monotone.texi
+++ monotone.texi
@@ -5835,6 +5835,20 @@
The @code{binary_file} function is also defined as a lua hook. See
@ref{Default hooks}.
address@hidden external_diff (@var{file_path}, @var{old_data}, @var{new_data}, @var{is_binary},
+ @var{diff_args}, @var{old_rev}, @var{new_rev})
+
+Called for each file when @command{diff} is given the
address@hidden command. @var{file_path} is the pathname of the
+file that is being diffed. @var{old_data} and @var{new_data} are the
+data contents of the old and the new file. If the data is binary,
address@hidden will be true, otherwise false. @var{old_rev} and
address@hidden are the revision IDs of the old and new data.
+
+If an extra arguments are given via @option{--diff-args}, the string
+will be passed in as @var{diff_args}. Otherwise @var{diff_args} will
+be nil.
+
@end ftable
@page
--- options.hh
+++ options.hh
@@ -37,3 +37,7 @@
#define OPT_VERBOSE 28
#define OPT_SET_DEFAULT 29
#define OPT_EXCLUDE 30
+#define OPT_UNIFIED_DIFF 31
+#define OPT_CONTEXT_DIFF 32
+#define OPT_EXTERNAL_DIFF 33
+#define OPT_EXTERNAL_DIFF_ARGS 34
--- std_hooks.lua
+++ std_hooks.lua
@@ -610,3 +610,14 @@
function use_inodeprints()
return false
end
+
+-- default external diff, works for gnu diff
+function external_diff(file_path, data_old, data_new, is_binary, diff_args, rev_old, rev_new)
+ local old_file = write_to_temporary_file(data_old);
+ local new_file = write_to_temporary_file(data_new);
+
+ execute("diff", "-upNU8", "--label", file_path .. "\told", old_file, "--label", file_path .. "\tnew", new_file);
+
+ os.remove (old_file);
+ os.remove (new_file);
+end
--- tests/t_crlf.at
+++ tests/t_crlf.at
@@ -12,6 +12,6 @@
AT_CHECK(MONOTONE diff, [], [stdout], [ignore])
LINES=`wc -l ;
#endif
+// diff type
+enum diff_type
+{
+ unified_diff,
+ context_diff,
+ external_diff
+};
+
+
#endif // __VOCAB_HH__