[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Monotone-commits-diffs] net.venge.monotone.colored-diff: d4165db330a17
From: |
code |
Subject: |
[Monotone-commits-diffs] net.venge.monotone.colored-diff: d4165db330a1781b7016a401c21a1c25fa952894 |
Date: |
Mon, 21 Mar 2011 14:40:29 +0100 (CET) |
revision: d4165db330a1781b7016a401c21a1c25fa952894
date: 2011-02-23T10:25:14
author: Richard Hopkins <address@hidden>
branch: net.venge.monotone.colored-diff
changelog:
propagate from branch 'net.venge.monotone' (head
9fa8e839780984c1028b5023f47d525066d99535)
to branch 'net.venge.monotone.colored-diff' (head
7b930320caeeaadddae9c9556a50fdd8ee18540a)
manifest:
format_version "1"
new_manifest [2712adbed9ffa51ba58c4188a7a333bb7e83c589]
old_revision [7b930320caeeaadddae9c9556a50fdd8ee18540a]
rename "test/func/netsync_key_hook"
to "test/func/netsync_key_hooks"
add_dir "test/func/netsync_bind_opt"
add_file "extra/bin/mtn-cleanup.1"
content [b898678b0775bf10a7428cfd8b52a4883edddbcc]
add_file "src/util/mtnopt.1"
content [8e24a1cafa100a7d6681cc19e30ee82a4cf517f4]
add_file "test/func/netsync_bind_opt/__driver__.lua"
content [153c2be3d3c3c37b4fea590633d2d3be9bae5e82]
add_file "test/func/netsync_key_hooks/server-hooks.lua"
content [434dab628a58b2c644f5ad6997420f1186cabbb5]
patch ".mtn-ignore"
from [ee776b54b58b1d3cc4265cdfa09a6d426ae1f6c5]
to [347361ce3fa47016cbe4f5ba29188696d939a1d8]
patch "Makefile.am"
from [3987cf2943284d2dbe2722925395ac1544b6d1fc]
to [ab8b3972917db2d7e2a0bfd42abaea31a66c143f]
patch "NEWS"
from [c99a1b030116f68845e9418fd53277c04eb53297]
to [fa80c1f7aeaaf7278731bb1f7c7cd0a94f7b3c4b]
patch "contrib/monotone-cluster-push.lua"
from [2ee0e849058ea7bbef9487fc21772d1fb66500d6]
to [3a4f3bd0394d70d5c07c9314ad42026b212a4983]
patch "doc/monotone.texi"
from [8d7a3efa8e20f906edc0883785c6c8f51cc6919c]
to [14de7e0ea6d88053129594b1628cac25ebf14506]
patch "extra/shell/monotone.bash_completion.in"
from [f7d35f2c13c6babc009800a11f6eff1eb69b01d9]
to [a878e6fa815f84f18961fb2366d0235376be8c29]
patch "src/cmd_list.cc"
from [12643b2161237863a8de6656c99328dc6ea3c7e6]
to [eede6b49bfe267b8e9b361c12bbcc26f53e86191]
patch "src/database.cc"
from [8966518247a144a25de01b4ab8fa9e515661edfb]
to [f61bd0d7d66a715c7a55cb943eb8521db6d91d68]
patch "src/keys.cc"
from [bdf4a6b94902d29411b16cb169851986a16b3956]
to [19db9fa939a1d87aba964f4e84743adcfff6fdd2]
patch "src/lua_hooks.cc"
from [cd982157b1248b75f37edda84723e8944c70c5bf]
to [81dd3985d253ac62743df0341e60a74d5b93b755]
patch "src/lua_hooks.hh"
from [a7ab69e459aa1f8450ac10704f0c22a595cc69e8]
to [51a2842d22554cba640dcea416103f5e70c63c3b]
patch "src/network/connection_info.cc"
from [78789566ad076c92d8795ea7e3877646c3749693]
to [b732c16161db2394aac449f50c6a6921e553ef22]
patch "src/network/connection_info.hh"
from [8841c299c1a214c46071b6f77c3a5dbadeaf4959]
to [0ba5fc1778b78fb3446ad345ec78e073fd9221e4]
patch "test/extra/mtn-cleanup/__driver__.lua"
from [c0a63dd6bbb69d30db6f6b64f7d59f2b5f1d00c7]
to [f650305a0d130a4ac6fb988eed58662a564dcc64]
patch "test/func/manpage/__driver__.lua"
from [2230d26ba35875be86cbb8000b4c0c8c7d36f735]
to [a381ef4517c907170547a4984923650617f69c60]
patch "test/func/netsync_key_hooks/__driver__.lua"
from [87963f895052ee9dd35d513e23004811169bca38]
to [d7fad5a70688d3db512a05ebb0e3643006f8c7e2]
patch "test/func/netsync_key_hooks/client-hooks.lua"
from [f60d553a6bff838e53904f94294588d9f9ed84ee]
to [e9eb38666d23a1f4a5be33404220902ee90756eb]
old_revision [9fa8e839780984c1028b5023f47d525066d99535]
add_file "src/colorizer.cc"
content [96964884a83e4d7d638c146821a554d033f396eb]
add_file "src/colorizer.hh"
content [eb3d0e3dad8d447e270e0c6264bf1a4ea139013f]
patch "Makefile.am"
from [6e6a3f7aaecccc749e261d452d84bd8431ba6cb7]
to [ab8b3972917db2d7e2a0bfd42abaea31a66c143f]
patch "NEWS"
from [848a8d23c760b709d5954ef1ca4a812c72404343]
to [fa80c1f7aeaaf7278731bb1f7c7cd0a94f7b3c4b]
patch "doc/monotone.texi"
from [5c18cff828089e592f5f2d53c2d60793715a4a40]
to [14de7e0ea6d88053129594b1628cac25ebf14506]
patch "src/asciik.cc"
from [cf946f9a14ad309615704bc960255c50e12b636a]
to [64600c9969226fa55cd05982364147342d3b734e]
patch "src/asciik.hh"
from [592aa966af256f50be9784bfd01c543f54d3447b]
to [3e0dcd90804053a5e558b0ddfa6e5f3dcc462d50]
patch "src/cmd_diff_log.cc"
from [94a354875b587d372e6d0898ab6fc8355ce29c21]
to [c8d5d47eecd08a5935b6739b640313effdfae100]
patch "src/cmd_files.cc"
from [7e9ffd4a06daeb0ef7ab7557d3a656c6b99ab2ad]
to [44c13d2a7ae5e2beb2b316d24202481680779f70]
patch "src/cmd_ws_commit.cc"
from [7b91a53d8eec4e78b062092f85c945bbaaefe23a]
to [e0bd38df40b3be50ffd8793c134fcc9edfb47bd9]
patch "src/diff_output.cc"
from [8df7c0bec2e64275f6c8e8b6ccb035c8fd0f684f]
to [db19431f96f35ca8c6b89c129c2a805ddd418f15]
patch "src/diff_output.hh"
from [9125ccd0d0fa725782c9910b5f34e844048d2da8]
to [168281addd27cdade1dc1320ee4814b28070feb8]
patch "src/lua_hooks.cc"
from [1c178085332c73dcefb4681d205d17b059e52080]
to [81dd3985d253ac62743df0341e60a74d5b93b755]
patch "src/lua_hooks.hh"
from [66412b9fa5db97cd3b3ec01cadf036fb346ac161]
to [51a2842d22554cba640dcea416103f5e70c63c3b]
patch "src/options_list.hh"
from [4af93dbcc45e76d732d073ced7ce21d20472cd00]
to [e7b13e91324a35e0b05be40e49f66cc654fa2f7e]
patch "src/rev_output.cc"
from [a2c70b893b31296917d1a2b974faa1da46c13f1e]
to [fec6728d80bca2d8d13ab49bb4ecd03310879fe5]
patch "src/rev_output.hh"
from [666dd3ed35e16d8b122b4932c2aad05a21a22e25]
to [5879a8268a59545c946583b65f66eda4491b979e]
patch "src/std_hooks.lua"
from [30949d110cc1ed86d98f4f437fda16778a3e85bb]
to [7669463d1a401dc786dbf65fc99d1a4853cf4a4f]
============================================================
--- Makefile.am 3987cf2943284d2dbe2722925395ac1544b6d1fc
+++ Makefile.am ab8b3972917db2d7e2a0bfd42abaea31a66c143f
@@ -250,14 +250,23 @@ mtnhooksdir = $(monotonedir)/hooks
monotonedir = $(datadir)/monotone
mtnhooksdir = $(monotonedir)/hooks
-mtnhooks_DATA = \
+dist_mtnhooks_DATA = \
extra/mtn-hooks/authorize_remote_automate.lua \
extra/mtn-hooks/get_passphrase_from_file.lua \
+ extra/mtn-hooks/monotone-ciabot.lua \
extra/mtn-hooks/monotone-mail-notify.lua
mtnscriptsdir = $(monotonedir)/scripts
-dist_mtnscripts_SCRIPTS = extra/mtn-hooks/monotone-mail-notify
+dist_mtnscripts_SCRIPTS = \
+ extra/mtn-hooks/monotone-ciabot.py \
+ extra/mtn-hooks/monotone-mail-notify
+# Some of the smaller programs do not have --help or --version,
+# make them exempt of the check for those. NOTE: use this sparingly!
+AM_INSTALLCHECK_STD_OPTIONS_EXEMPT = \
+ extra/bin/mtn-cleanup extra/mtn-hooks/monotone-ciabot.py \
+ extra/mtn-hooks/monotone-mail-notify
+
# flags
# sets DEFS for just this object (autoconf's -DHAVE_CONFIG_H is useless)
@@ -349,8 +358,7 @@ EXTRA_DIST = \
HACKING INSTALL INSTALL_windows_cygwin.txt \
INSTALL_windows_native.txt README.visualc8 UPGRADE \
util/audit-includes util/do-editor-vars.sh \
- $(wildcard $(srcdir)/m4/*.m4) doc/monotone.html doc/images \
- doc/texinfo.css src/schema.sql src/unix/README \
+ $(wildcard $(srcdir)/m4/*.m4) src/schema.sql src/unix/README \
src/util/mtnopt.in innosetup/README.txt \
innosetup/monotone.iss.in innosetup/modpath.iss \
innosetup/monotone.bmp innosetup/dlls.sh \
@@ -368,7 +376,11 @@ EXTRA_DIST = \
\
src/package_revision.txt src/package_full_revision_dist.txt \
\
- mac notes visualc $(contrib_data) $(examples_data) extra
+ mac notes visualc $(contrib_data) $(examples_data) \
+ \
+ extra/README extra/building/dump-test-logs.sh.in \
+ extra/shell/monotone.bash_completion.in \
+ extra/shell/monotone_gen_bash_completion_table.pl
# Message translation support
# INST_LINGUAS is set by configure, based on the po/LINGUAS file and
@@ -463,12 +475,6 @@ dist-nls: $(ALL_GMOFILES)
dist-nls: $(ALL_GMOFILES)
cp $(ALL_GMOFILES) $(distdir)/po
-# also, kill off any backup files that got pulled in by one of the
-# recursive subdirectory includes in EXTRA_DIST
-# note use of slightly non-portable "-delete" action
- find $(distdir) \( -name '*.bak' -o -name '*.orig' -o -name '*.rej' \
- -o -name '*~' -o -name '#*#' -o -name '*.swp' \) -delete
-
else
po/%.gmo: $(srcdir)/po/%.gmo
@@ -694,7 +700,8 @@ BUILT_SOURCES = $(PCH_FILE) $(PCH_BUILD)
BUILT_SOURCES = $(PCH_FILE) $(PCH_BUILD)
-CLEANFILES = $(bin_SCRIPTS) $(bashcomp_DATA) $(BUILT_SOURCES) $(CLEAN_SRCS) $(CLEAN_POFILES)
+CLEANFILES = $(bin_SCRIPTS) $(noinst_SCRIPTS) $(bashcomp_DATA) \
+ $(BUILT_SOURCES) $(CLEAN_SRCS) $(CLEAN_POFILES)
# automake provides no nice way to build a helper program to execute
# on the build machine, so we need our own rule. almost all the
@@ -723,11 +730,12 @@ do_subst = sed -e 's,address@hidden
do_subst = sed -e 's,address@hidden@],$(PACKAGE_VERSION),' \
-e 's,address@hidden@],$(sysconfdir),'
-%: src/util/%.in Makefile
+mtnopt: src/util/mtnopt.in Makefile
$(V_subst)$(do_subst) < $< > $@ && chmod +x $@
extra/shell/monotone.bash_completion: extra/shell/monotone.bash_completion.in \
- $(bin_PROGRAMS) extra/shell/monotone_gen_bash_completion_table.pl
+ $(bin_PROGRAMS) extra/shell/monotone_gen_bash_completion_table.pl \
+ Makefile
$(MKDIR_P) extra/shell
( sed -e '/address@hidden@]$$/,$$d' < $<; \
MTN=./mtn$(EXEEXT) \
@@ -827,6 +835,7 @@ man1_MANS = mtn.1
src/win32/main.cc src/unix/main.cc)
man1_MANS = mtn.1
+dist_man1_MANS = src/util/mtnopt.1 extra/bin/mtn-cleanup.1
# All local variants of automake-supported targets here, depending on all
# the things we want to do. This is to support multiple things to do in
@@ -838,11 +847,17 @@ check-local: check-testers
uninstall-contrib-data uninstall-examples-data
mostlyclean-local: mostlyclean-tests
check-local: check-testers
+
# All hooks supported by automake here, depending on all the things we want
# to hook in. This is to support multiple things into the same hook, as
# dependencies.
+distcheck-hook: distcheck-base.hh
dist-hook: dist-nls
-distcheck-hook: distcheck-base.hh
+# Kill off any backup files that got pulled in by one of the
+# recursive subdirectory includes in EXTRA_DIST
+# note use of slightly non-portable "-delete" action
+ find $(distdir) \( -name '*.bak' -o -name '*.orig' -o -name '*.rej' \
+ -o -name '*~' -o -name '#*#' -o -name '*.swp' \) -delete
mtn.1: mtn$(EXEEXT)
$(AM_V_GEN)REAL_BLDDIR=$$PWD/$(top_builddir); \
============================================================
--- NEWS c99a1b030116f68845e9418fd53277c04eb53297
+++ NEWS fa80c1f7aeaaf7278731bb1f7c7cd0a94f7b3c4b
@@ -29,6 +29,13 @@ XXX XXX XX XX:XX:XX UTC 2011
messages from mtn automate, regardless of the locale of the
calling process.
+ - The hook 'get_netsync_key' has been split up into two separate
+ hooks, one for client usage ('get_netsync_client_key', with
+ the same arguments as the original 'get_netsync_key') and one
+ for server usage ('get_netsync_server_key', with a single table
+ argument containing all the given '--bind' options). Please
+ review your custom hooks accordingly.
+
- Short options ('-b', '-d', ...) are no longer completed. This
fixes an invariant failure originating from wrong option usage.
(closes monotone issue 141)
@@ -87,6 +94,19 @@ XXX XXX XX XX:XX:XX UTC 2011
if no database is specified for these commands.
(fixes monotone issue 113)
+ - If 'mtn serve' is called with one or more '--bind' options, then
+ the arguments to these options can now be specified again
+ as follows:
+
+ '<ip-or-host>'
+ to listen to IP or host on the default port
+ '<ip-or-host>:<port>'
+ to listen to IP or host on the specified port - or
+ ':<port>'
+ to listen on all interfaces on the specified port
+
+ (fixes monotone issue 119)
+
- monotone does no longer enforce ".mtn" as file extension
for managed databases. Instead a new Lua hook,
get_default_database_glob(), is used to determine a pattern
============================================================
--- src/database.cc 8966518247a144a25de01b4ab8fa9e515661edfb
+++ src/database.cc f61bd0d7d66a715c7a55cb943eb8521db6d91d68
@@ -4974,7 +4974,7 @@ database_path_helper::get_database_path(
vector<system_path> search_paths;
E(lua.hook_get_default_database_locations(search_paths) && search_paths.size() > 0,
- origin::user, F("could not query default database locations"));
+ origin::user, F("no default database location configured"));
for (vector<system_path>::const_iterator i = search_paths.begin();
i != search_paths.end(); ++i)
============================================================
--- src/keys.cc bdf4a6b94902d29411b16cb169851986a16b3956
+++ src/keys.cc 19db9fa939a1d87aba964f4e84743adcfff6fdd2
@@ -183,13 +183,20 @@ cache_netsync_key(options const & opts,
found_key = true;
}
}
- else if (lua.hook_get_netsync_key(utf8(info->client.get_uri().resource(), origin::user),
- info->client.get_include_pattern(),
- info->client.get_exclude_pattern(),
- keys, project, key))
+ else if (info->info_type == netsync_connection_info::client_info &&
+ lua.hook_get_netsync_client_key(utf8(info->client.get_uri().resource(), origin::user),
+ info->client.get_include_pattern(),
+ info->client.get_exclude_pattern(),
+ keys, project, key))
{
found_key = true;
}
+ else if (info->info_type == netsync_connection_info::server_info &&
+ lua.hook_get_netsync_server_key(info->server.addrs,
+ keys, project, key))
+ {
+ found_key = true;
+ }
else
{
found_key = get_only_key(keys, key_requiredness, key);
============================================================
--- src/lua_hooks.cc cd982157b1248b75f37edda84723e8944c70c5bf
+++ src/lua_hooks.cc 81dd3985d253ac62743df0341e60a74d5b93b755
@@ -798,17 +798,17 @@ bool
}
bool
-lua_hooks::hook_get_netsync_key(utf8 const & server_address,
- globish const & include,
- globish const & exclude,
- key_store & keys,
- project_t & project,
- key_id & k)
+lua_hooks::hook_get_netsync_client_key(utf8 const & server_address,
+ globish const & include,
+ globish const & exclude,
+ key_store & keys,
+ project_t & project,
+ key_id & k)
{
string name;
bool exec_ok
= Lua(st)
- .func("get_netsync_key")
+ .func("get_netsync_client_key")
.push_str(server_address())
.push_str(include())
.push_str(exclude())
@@ -827,6 +827,41 @@ lua_hooks::hook_get_netsync_key(utf8 con
}
}
+bool
+lua_hooks::hook_get_netsync_server_key(vector<utf8> const & server_ports,
+ key_store & keys,
+ project_t & project,
+ key_id & k)
+{
+ string name;
+ Lua ll(st);
+ ll.func("get_netsync_server_key");
+
+ ll.push_table();
+ vector<utf8>::const_iterator i;
+ int j;
+ for (i = server_ports.begin(), j = 1; i != server_ports.end(); ++i, ++j)
+ {
+ ll.push_int(j);
+ ll.push_str((*i)());
+ ll.set_table();
+ }
+
+ bool exec_ok = ll.call(1, 1)
+ .extract_str(name)
+ .ok();
+
+ if (!exec_ok || name.empty())
+ return false;
+ else
+ {
+ key_identity_info identity;
+ project.get_key_identity(keys, *this, external_key_name(name, origin::user), identity);
+ k = identity.id;
+ return true;
+ }
+}
+
static void
push_uri(uri_t const & uri, Lua & ll)
{
============================================================
--- src/lua_hooks.hh a7ab69e459aa1f8450ac10704f0c22a595cc69e8
+++ src/lua_hooks.hh 51a2842d22554cba640dcea416103f5e70c63c3b
@@ -80,12 +80,16 @@ public:
map<key_id, bool> const & new_results);
// network hooks
- bool hook_get_netsync_key(utf8 const & server_address,
- globish const & include,
- globish const & exclude,
- key_store & keys,
- project_t & project,
- key_id & k);
+ bool hook_get_netsync_client_key(utf8 const & server_address,
+ globish const & include,
+ globish const & exclude,
+ key_store & keys,
+ project_t & project,
+ key_id & k);
+ bool hook_get_netsync_server_key(vector<utf8> const & server_ports,
+ key_store & keys,
+ project_t & project,
+ key_id & k);
bool hook_get_netsync_connect_command(uri_t const & uri,
globish const & include_pattern,
globish const & exclude_pattern,
============================================================
--- doc/monotone.texi 8d7a3efa8e20f906edc0883785c6c8f51cc6919c
+++ doc/monotone.texi 14de7e0ea6d88053129594b1628cac25ebf14506
@@ -4687,12 +4687,15 @@ @subsection Global Options
For a non-netsync command, the Lua hook @address@hidden is
called.
-For a netsync command, the Lua hook @address@hidden is
-called.
+For a client-side netsync command, the Lua hook
address@hidden@ref{get_netsync_client_key}} is called.
-If the hook returns non-nil, the return value is the name of the
-key.
+For a command that starts a monotone server, the Lua hook
address@hidden@ref{get_netsync_server_key}} is used.
+If any of the aforementioned hooks returns non-nil, the return value
+is the name of the key.
+
@item
If there is only one key in the keydir, that is the key.
@@ -11426,12 +11429,12 @@ @subsection User Defaults
There is no default definition for this hook; it returns nil.
address@hidden@item get_netsync_key(@var{server}, @var{include}, @var{exclude})
address@hidden@item get_netsync_client_key(@var{server}, @var{include}, @var{exclude})
-Called by the server and client when a netsync connection is being
-established, and @address@hidden was not given. Returns a string
-which is the name or hash of the key to use to authenticate the
-netsync connection.
+Called by the client when a netsync connection is being established,
+and @address@hidden was not given. Returns a string which is the name
+or hash of the key to use to authenticate the client side of a netsync
+connection.
Note that netsync commands do not need a signing key; they only transmit
already signed information.
@@ -11439,32 +11442,44 @@ @subsection User Defaults
See @address@hidden for a discussion of how monotone determines
what key to use.
-Arguments, when called by the server:
+Arguments, when called:
@table @var
@item server
-The address monotone is listening on.
+The scheme, user, host, port, and path fields from the URI provided on
+the command line. See @ref{netsync uri}.
@item include
-"*"
+The include pattern in the URI provided on the command line.
@item exclude
-""
+The exclude pattern in the URI provided on the command line.
+
@end table
-When called by the client:
address@hidden@item get_netsync_server_key(@var{addresses})
address@hidden @var
address@hidden server
-The scheme, user, host, port, and path fields from the URI provided on
-the command line. See @ref{netsync uri}.
+Called by the server when a new netsync server instance is created, and
address@hidden@ref{--key}} was not given. Returns a string which is the name
+or hash of the key to use to authenticate the server side of a netsync
+connection.
address@hidden include
-The include pattern in the URI provided on the command line.
+Note that netsync commands do not need a signing key; they only transmit
+already signed information.
address@hidden exclude
-The exclude pattern in the URI provided on the command line.
+See @address@hidden for a discussion of how monotone determines
+what key to use.
+Arguments, when called:
+
address@hidden @var
address@hidden addresses
+A table of addresses given to monotone via the @option{--bind} option that
+denote the addresses and / or ports monotone is listening on for connections.
+If the address in one of the table entries is omitted, the port must be given
+with a leading colon; in this case monotone listens on all interfaces on this
+port.
+
@end table
@address@hidden get_default_command_options(@var{command})
============================================================
--- .mtn-ignore ee776b54b58b1d3cc4265cdfa09a6d426ae1f6c5
+++ .mtn-ignore 347361ce3fa47016cbe4f5ba29188696d939a1d8
@@ -16,7 +16,8 @@
^doc/stamp-vti$
^doc/texinfo\.tex$
^doc/version\.texi$
-^html
+^extra/building/dump-test-logs.sh$
+^extra/shell/monotone.bash_completion$
^install-sh$
^m4/codeset\.m4$
^m4/gettext\.m4$
@@ -55,7 +56,7 @@
^po/insert-header\.sin$
^po/monotone\.pot$
^po/quot\.sed$
-^run_(func|tester|unit)_tests$
+^run_(extra|func|tester|unit)_tests$
^src/package_(full_)?revision(\.cc|\.txt|_(dist|raw)\.txt)$
^src/schema\.cc$
^src/std_hooks\.cc$
============================================================
--- src/cmd_list.cc 12643b2161237863a8de6656c99328dc6ea3c7e6
+++ src/cmd_list.cc eede6b49bfe267b8e9b361c12bbcc26f53e86191
@@ -681,7 +681,7 @@ CMD(databases, "databases", "dbs", CMD_R
vector<system_path> search_paths, files, dirs;
E(app.lua.hook_get_default_database_locations(search_paths), origin::user,
- F("could not query default database locations"));
+ F("no default database location configured"));
globish file_matcher;
E(app.lua.hook_get_default_database_glob(file_matcher), origin::user,
@@ -736,8 +736,8 @@ CMD(databases, "databases", "dbs", CMD_R
continue;
}
- cout << F("%s (in %s):") % db_alias % search_path << "\n";
- print_workspace_info(db, app.lua, cout, "\t");
+ cout << F("%s (in %s):") % db_alias % search_path << "\n";
+ print_workspace_info(db, app.lua, cout, "\t");
}
}
}
============================================================
--- test/func/netsync_key_hook/__driver__.lua 87963f895052ee9dd35d513e23004811169bca38
+++ test/func/netsync_key_hooks/__driver__.lua d7fad5a70688d3db512a05ebb0e3643006f8c7e2
@@ -1,6 +1,10 @@ mtn_setup()
includecommon("netsync.lua")
mtn_setup()
+
+--
+-- test get_netsync_client_key
+--
netsync.setup()
writefile("foo", "bar")
@@ -21,6 +25,7 @@ function client(what, ret)
"--keydir=keys",
"--db=test.db", srv.address,
"--rcfile=client-hooks.lua",
+ "--no-workspace",
"*"}
for k, v in pairs(args) do
table.insert(what, v)
@@ -34,3 +39,33 @@ srv:stop()
client({"pull", "address@hidden"}, 1)
srv:stop()
+
+--
+-- test get_netsync_server_key
+--
+
+get("server-hooks.lua")
+-- we send a SIGTERM to the server process to stop it, so this is also
+-- what we expect as (negated) return value
+SIGTERM=15
+
+function server(what, ret, exp_err)
+ local addr = "localhost:" .. math.random(1024, 65535)
+ args = {"--rcfile=test_hooks.lua",
+ "--keydir=keys",
+ "--db=test.db", "--bind=" .. addr,
+ "--no-workspace",
+ "serve"}
+ for k, v in pairs(args) do
+ table.insert(what, v)
+ end
+ srv = bg(raw_mtn(unpack(what)), ret, false, true)
+ srv:finish(3)
+ if exp_err ~= nil then
+ check(qgrep(exp_err, "stderr"))
+ end
+end
+
+server({}, 1, "you have multiple private keys")
+server({"--rcfile", "server-hooks.lua"}, -SIGTERM, "beginning service on localhost")
+
============================================================
--- test/func/netsync_key_hook/client-hooks.lua f60d553a6bff838e53904f94294588d9f9ed84ee
+++ test/func/netsync_key_hooks/client-hooks.lua e9eb38666d23a1f4a5be33404220902ee90756eb
@@ -1,3 +1,3 @@
-function get_netsync_key(server, include, exclude)
+function get_netsync_client_key(server, include, exclude)
return "address@hidden"
end
============================================================
--- contrib/monotone-cluster-push.lua 2ee0e849058ea7bbef9487fc21772d1fb66500d6
+++ contrib/monotone-cluster-push.lua 3a4f3bd0394d70d5c07c9314ad42026b212a4983
@@ -210,7 +210,7 @@ do
end
if certs_in > 0 or revs_in > 0 or keys_in > 0 then
local pattern_branches =
- process_rcfile("not_netsync_end", MCP_rcfile, nil)
+ process_rcfile("note_netsync_end", MCP_rcfile, nil)
if pattern_branches then
for pattern, servers in pairs(pattern_branches) do
if globish_match(pattern, branch) then
@@ -222,7 +222,7 @@ do
io.stderr:write("note_netsync_end: ",
"pushing pattern \"", pattern,
"\" to server ", server, "\n")
- server_request_sync("push", server, pattern, "")
+ server_request_sync("push", server.."?"..pattern, "")
end
end
end
@@ -232,7 +232,5 @@ do
end
}
- local saved_note_mtn_startup = note_mtn_startup
-
push_netsync_notifier(notifier)
end
============================================================
--- src/network/connection_info.cc 78789566ad076c92d8795ea7e3877646c3749693
+++ src/network/connection_info.cc b732c16161db2394aac449f50c6a6921e553ef22
@@ -279,7 +279,7 @@ netsync_connection_info::Client::set_raw
if (uri.scheme.empty())
uri.scheme = "mtn";
-
+
E(uri.scheme != "mtn" || !uri.host.empty(), origin::user,
F("a non-empty hostname is expected for the 'mtn' uri scheme"));
@@ -400,6 +400,7 @@ netsync_connection_info::setup_default(o
shared_conn_info & info)
{
info.reset(new netsync_connection_info(db, opts));
+ info->info_type = client_info;
info->client.conn_type = type;
info->client.ensure_completeness();
@@ -414,6 +415,7 @@ netsync_connection_info::setup_from_sync
shared_conn_info & info)
{
info.reset(new netsync_connection_info(db, opts));
+ info->info_type = client_info;
info->client.conn_type = netsync_connection;
info->client.set_raw_uri(request.address);
@@ -461,6 +463,7 @@ netsync_connection_info::setup_from_uri(
shared_conn_info & info)
{
info.reset(new netsync_connection_info(db, opts));
+ info->info_type = client_info;
info->client.conn_type = type;
info->client.set_raw_uri(uri());
@@ -497,6 +500,7 @@ netsync_connection_info::setup_from_serv
"please consider using the URI calling syntax instead"));
info.reset(new netsync_connection_info(db, opts));
+ info->info_type = client_info;
info->client.conn_type = type;
info->client.set_raw_uri(host());
@@ -515,6 +519,7 @@ netsync_connection_info::setup_for_serve
shared_conn_info & info)
{
info.reset(new netsync_connection_info(db, opts));
+ info->info_type = server_info;
info->server.addrs = opts.bind_uris;
info->client.conn_type = netsync_connection;
@@ -523,16 +528,6 @@ netsync_connection_info::setup_for_serve
E(lua.hook_persist_phrase_ok(), origin::user,
F("need permission to store persistent passphrase "
"(see hook persist_phrase_ok())"));
-
- // the uri as well as the include / exclude pattern are
- // not used directly for serve, but need to be configured
- // in order to let keys::cache_netsync_key() call the
- // get_netsync_key() hook properly
- if (!opts.bind_uris.empty())
- info->client.set_raw_uri((*opts.bind_uris.begin())());
-
- info->client.include_pattern = globish("*", origin::internal);
- info->client.exclude_pattern = globish("", origin::internal);
}
else if (!opts.bind_stdio)
W(F("The --no-transport-auth option is usually only used "
============================================================
--- src/network/connection_info.hh 8841c299c1a214c46071b6f77c3a5dbadeaf4959
+++ src/network/connection_info.hh 0ba5fc1778b78fb3446ad345ec78e073fd9221e4
@@ -102,6 +102,8 @@ struct netsync_connection_info
struct netsync_connection_info
{
+ enum { client_info, server_info } info_type;
+
class Server
{
public:
============================================================
--- test/func/manpage/__driver__.lua 2230d26ba35875be86cbb8000b4c0c8c7d36f735
+++ test/func/manpage/__driver__.lua a381ef4517c907170547a4984923650617f69c60
@@ -6,7 +6,7 @@ local s,e,version = string.find(readfile
-- check for a proper header line
check(mtn("version"), 0, true, false)
local s,e,version = string.find(readfile("stdout"), "(monotone %d+\.%d+%S*)")
-check(qgrep(".TH \"monotone\" 1 \"" .. os.date("%Y-%m-%d") .. "\" \"" .. version .. "\"", "manpage"))
+check(qgrep(".TH \"monotone\" 1 \"[0-9]{4}-[0-9]{2}-[0-9]{2}\" \"" .. version .. "\"", "manpage"))
-- check required sections
check(qgrep(".SH \"NAME\"", "manpage"))
@@ -20,6 +20,3 @@ check(qgrep(".SH \"COPYRIGHT\"", "manpag
check(qgrep(".SH \"BUGS\"", "manpage"))
check(qgrep(".SH \"AUTHORS\"", "manpage"))
check(qgrep(".SH \"COPYRIGHT\"", "manpage"))
-
--- ensure that the copyright is up-to-date
-check(qgrep("Copyright [(]c[)] 2004 - "..os.date("%Y"), "manpage"))
============================================================
--- extra/shell/monotone.bash_completion.in f7d35f2c13c6babc009800a11f6eff1eb69b01d9
+++ extra/shell/monotone.bash_completion.in a878e6fa815f84f18961fb2366d0235376be8c29
@@ -281,9 +281,10 @@ _monotone() {
elif [ $arg_cword -ge 0 ]; then
local args=( ${_monotone_command_args[$cmd_line]} )
local argtype=${args[$arg_cword]}
- if [ "$argtype" = "..." ]; then
+ if [ $arg_cword -ge 1 ] && [ "$argtype" = "..." ]; then
argtype=${args[$arg_cword-1]}
- elif [ -z "$argtype" -a "${args[${#args[*]}-1]}" = "..." ]; then
+ elif [ ${#args[*]} -ge 2 ] && \
+ [ -z "$argtype" -a "${args[${#args[*]}-1]}" = "..." ]; then
argtype=${args[${#args[*]}-2]}
fi
case $argtype in
============================================================
--- test/extra/mtn-cleanup/__driver__.lua c0a63dd6bbb69d30db6f6b64f7d59f2b5f1d00c7
+++ test/extra/mtn-cleanup/__driver__.lua f650305a0d130a4ac6fb988eed58662a564dcc64
@@ -17,7 +17,7 @@ writefile("workspace/test3", "baz")
check(indir("workspace", mtn("add", "test2")), 0, false, false)
writefile("workspace/test3", "baz")
-check(indir("workspace", {"./run-mtn-cleanup",srcdir,test.root}),
+check(indir("workspace", {"../run-mtn-cleanup",srcdir,test.root}),
0, true, false)
check(exists("workspace/test1"))
xfail(exists("workspace/test2"))
============================================================
--- /dev/null
+++ test/func/netsync_bind_opt/__driver__.lua 153c2be3d3c3c37b4fea590633d2d3be9bae5e82
@@ -0,0 +1,27 @@
+skip_if(not existsonpath("netstat"))
+
+includecommon("netsync.lua")
+mtn_setup()
+netsync.setup()
+
+math.randomseed(get_pid())
+local port = math.random(1024, 65535)
+
+-- test with host:port
+srv = netsync.start({"--bind", "localhost:" .. port})
+check({"netstat", "-a", "-n"}, 0, true, false)
+check(qgrep("127[.]0[.]0[.]1[.:]" .. port, "stdout"))
+srv:stop()
+
+-- test with ip:port
+srv = netsync.start({"--bind", "127.0.0.1:" .. port})
+check({"netstat", "-a", "-n"}, 0, true, false)
+check(qgrep("127[.]0[.]0[.]1[.:]" .. port, "stdout"))
+srv:stop()
+
+-- test only with :port
+srv = netsync.start({"--bind", ":" .. port})
+check({"netstat", "-a", "-n"}, 0, true, false)
+check(qgrep("([*]|0[.]0[.]0[.]0)[.:]" .. port, "stdout"))
+srv:stop()
+
============================================================
--- /dev/null
+++ test/func/netsync_key_hooks/server-hooks.lua 434dab628a58b2c644f5ad6997420f1186cabbb5
@@ -0,0 +1,3 @@
+function get_netsync_server_key(addresses)
+ return "address@hidden"
+end
============================================================
--- /dev/null
+++ extra/bin/mtn-cleanup.1 b898678b0775bf10a7428cfd8b52a4883edddbcc
@@ -0,0 +1,22 @@
+.TH "MTN-CLEANUP" 1 2011-02-22 monotone monotone
+.SH "NAME"
+mtn-cleanup \- generate shell variables from monotone workspace options
+.SH "SYNOPSIS"
+.B mtn-cleanup
+.br
+.SH "DESCRIPTION"
+.B mtn-cleanup
+returns a workspace to its pristine state with the minimum of change;
+missing files are restored, changed files are reverted and new files
+are removed.
+.SH "BUGS"
+.B mtn-cleanup
+doesn't look to see if the database happens to be somewhere in the
+workspace, and might therefore remove it. Future version may take a
+look at
+.I _MTN/options
+to check for this possibility.
+.SH "SEE ALSO"
+.BR mtn (1),
+.SH "AUTHOR"
+Written by Anthony Edward Cooper <address@hidden>.
============================================================
--- /dev/null
+++ src/util/mtnopt.1 8e24a1cafa100a7d6681cc19e30ee82a4cf517f4
@@ -0,0 +1,95 @@
+.TH MTNOPT 1 2011-02-22 monotone monotone
+.SH NAME
+mtnopt \- generate shell variables from monotone workspace options
+.SH SYNOPSIS
+.B mtnopt
+.RB [\| \-s \||\| \-c \||\| \-v \|]
+.RB [\| \-d
+.IR dir \|]
+.RB [\| \-k
+.IR keys \|]
+.br
+.B mtnopt -h
+.br
+.SH DESCRIPTION
+.B mtnopt
+prints shell variable assignments for each value in the file of
+monotone workspace options,
+.IR _MTN/options ,
+in the current directory. For instance, if
+.I _MTN/options
+contained this text:
+.IP
+\f(CWdatabase "/home/user/src/monotone.mtn"\fP
+.br
+\f(CW branch "net.venge.monotone"\fP
+.br
+\f(CW keydir "/home/user/.monotone/keys"\fP
+.PP
+.B mtnopt
+would print:
+.IP
+\f(CWMTN_database="/home/user/src/monotone.mtn";\fP
+.br
+\f(CWMTN_branch="net.venge.monotone";\fP
+.br
+\f(CWMTN_keydir="/home/user/.monotone/keys";\fP
+.PP
+By default,
+.B mtnopt
+attempts to guess appropriate syntax from the value of the
+.B SHELL
+environment variable. This can be overridden with the
+.B \-s
+and
+.B \-c
+command\(hyline options.
+.SH OPTIONS
+.TP
+.B \-s
+Print variable assignments in
+.BR sh (1)
+syntax.
+.TP
+.B \-c
+Print variable assignments in
+.BR csh (1)
+syntax.
+.TP
+.B \-v
+Print only the values, with no indication of the corresponding option keys.
+.TP
+.BI \-d\ directory
+Look for
+.I _MTN/options
+in
+.IR directory ,
+rather than in the current directory.
+.TP
+.BI \-k\ keys
+Print assignments for only those options that match the
+.BR egrep (1)
+regular _expression_
+.IR keys .
+.TP
+.B \-h
+Print a help message and exit.
+.SH BUGS
+.B mtnopt
+only looks in the current directory for the
+.I _MTN
+directory, so it will fail in a subdirectory of a workspace.
+.PP
+.B mtnopt
+should be aware of the set of possible options, rather than blindly
+printing whatever is in
+.IR _MTN/options .
+.PP
+The behavior when there is no
+.I _MTN/options
+file to be found is less than helpful.
+.SH SEE ALSO
+.BR mtn (1),
+.BR egrep (1),
+.BR sh (1),
+.BR csh (1)
============================================================
--- Makefile.am 6e6a3f7aaecccc749e261d452d84bd8431ba6cb7
+++ Makefile.am ab8b3972917db2d7e2a0bfd42abaea31a66c143f
@@ -47,6 +47,7 @@ MOST_SOURCES = \
src/automate_reader.cc src/automate_stdio_helpers.hh \
src/botan_pipe_cache.hh src/cache_logger.hh src/cache_logger.cc \
src/commands.cc src/commands.hh $(CMD_SOURCES) \
+ src/colorizer.cc src/colorizer.hh \
src/diff_output.cc src/diff_output.hh \
src/lua_hooks.cc src/lua_hooks.hh \
src/transforms.cc src/transforms.hh \
============================================================
--- NEWS 848a8d23c760b709d5954ef1ca4a812c72404343
+++ NEWS fa80c1f7aeaaf7278731bb1f7c7cd0a94f7b3c4b
@@ -392,6 +392,11 @@ Thu Oct 28 21:07:18 UTC 2010
- New 'k:' selector type to query revisions where at least one
certificate was signed with the given key.
+ - Monotone has a new global '--colorize' option which colors the
+ output of commands like 'diff', 'fdiff' or 'log' for better
+ readability in terminals that support output coloring and
+ formatting.
+
- New automate command 'log' which behaves identical to the
normal 'log' command, except that it only outputs the
revision ids.
============================================================
--- src/diff_output.cc 8df7c0bec2e64275f6c8e8b6ccb035c8fd0f684f
+++ src/diff_output.cc db19431f96f35ca8c6b89c129c2a805ddd418f15
@@ -17,6 +17,7 @@
#include "simplestring_xform.hh"
#include <ostream>
+#include <sstream>
#include <iterator>
#include <boost/scoped_ptr.hpp>
@@ -25,6 +26,7 @@ using std::string;
using std::ostream;
using std::ostream_iterator;
using std::string;
+using std::stringstream;
using std::vector;
using boost::scoped_ptr;
@@ -45,6 +47,8 @@ struct hunk_consumer
vector<string>::const_reverse_iterator encloser_last_match;
vector<string>::const_reverse_iterator encloser_last_search;
+ colorizer color;
+
virtual void flush_hunk(size_t pos) = 0;
virtual void advance_to(size_t newpos) = 0;
virtual void insert_at(size_t b_pos) = 0;
@@ -55,10 +59,12 @@ struct hunk_consumer
vector<string> const & b,
size_t ctx,
ostream & ost,
- string const & encloser_pattern)
+ string const & encloser_pattern,
+ colorizer const & color)
: a(a), b(b), ctx(ctx), ost(ost), encloser_re(0),
a_begin(0), b_begin(0), a_len(0), b_len(0), skew(0),
- encloser_last_match(a.rend()), encloser_last_search(a.rend())
+ encloser_last_match(a.rend()), encloser_last_search(a.rend()),
+ color(color)
{
if (encloser_pattern != "")
encloser_re.reset(new pcre::regex(encloser_pattern, origin::user));
@@ -170,21 +176,24 @@ struct unidiff_hunk_writer : public hunk
vector<string> const & b,
size_t ctx,
ostream & ost,
- string const & encloser_pattern)
- : hunk_consumer(a, b, ctx, ost, encloser_pattern)
+ string const & encloser_pattern,
+ colorizer const & color)
+ : hunk_consumer(a, b, ctx, ost, encloser_pattern, color)
{}
};
void unidiff_hunk_writer::insert_at(size_t b_pos)
{
b_len++;
- hunk.push_back(string("+") + b[b_pos]);
+ hunk.push_back(color.colorize(string("+") + b[b_pos],
+ colorizer::add));
}
void unidiff_hunk_writer::delete_at(size_t a_pos)
{
a_len++;
- hunk.push_back(string("-") + a[a_pos]);
+ hunk.push_back(color.colorize(string("-") + a[a_pos],
+ colorizer::remove));
}
void unidiff_hunk_writer::flush_hunk(size_t pos)
@@ -201,22 +210,23 @@ void unidiff_hunk_writer::flush_hunk(siz
}
// write hunk to stream
+ stringstream ss;
if (a_len == 0)
- ost << "@@ -0,0";
+ ss << "@@ -0,0";
else
{
- ost << "@@ -" << a_begin+1;
+ ss << "@@ -" << a_begin+1;
if (a_len > 1)
- ost << ',' << a_len;
+ ss << ',' << a_len;
}
-
+
if (b_len == 0)
- ost << " +0,0";
+ ss << " +0,0";
else
{
- ost << " +" << b_begin+1;
+ ss << " +" << b_begin+1;
if (b_len > 1)
- ost << ',' << b_len;
+ ss << ',' << b_len;
}
{
@@ -231,7 +241,11 @@ void unidiff_hunk_writer::flush_hunk(siz
}
find_encloser(a_begin + first_mod, encloser);
- ost << " @@" << encloser << '\n';
+ ss << " @@";
+
+ ost << color.colorize(ss.str(), colorizer::separator);
+ ost << color.colorize(encloser, colorizer::encloser);
+ ost << '\n';
}
copy(hunk.begin(), hunk.end(), ostream_iterator<string>(ost, "\n"));
}
@@ -297,8 +311,9 @@ struct cxtdiff_hunk_writer : public hunk
vector<string> const & b,
size_t ctx,
ostream & ost,
- string const & encloser_pattern)
- : hunk_consumer(a, b, ctx, ost, encloser_pattern),
+ string const & encloser_pattern,
+ colorizer const & colorizer)
+ : hunk_consumer(a, b, ctx, ost, encloser_pattern, colorizer),
have_insertions(false), have_deletions(false)
{}
};
@@ -360,7 +375,8 @@ void cxtdiff_hunk_writer::flush_hunk(siz
find_encloser(a_begin + min(first_insert, first_delete),
encloser);
- ost << "***************" << encloser << '\n';
+ ost << color.colorize("***************", colorizer::separator)
+ << color.colorize(encloser, colorizer::encloser) << '\n';
}
ost << "*** " << (a_begin + 1) << ',' << (a_begin + a_len) << " ****\n";
@@ -394,23 +410,33 @@ void cxtdiff_hunk_writer::flush_pending_
// if we have just insertions to flush, prefix them with "+"; if
// just deletions, prefix with "-"; if both, prefix with "!"
+ colorizer::purpose p = colorizer::normal;
if (inserts.empty() && !deletes.empty())
+ {
prefix = "-";
+ p = colorizer::remove;
+ }
else if (deletes.empty() && !inserts.empty())
+ {
prefix = "+";
+ p = colorizer::add;
+ }
else
+ {
prefix = "!";
+ p = colorizer::change;
+ }
for (vector<size_t>::const_iterator i = deletes.begin();
i != deletes.end(); ++i)
{
- from_file.push_back(prefix + string(" ") + a[*i]);
+ from_file.push_back(color.colorize(prefix + string(" ") + a[*i], p));
a_len++;
}
for (vector<size_t>::const_iterator i = inserts.begin();
i != inserts.end(); ++i)
{
- to_file.push_back(prefix + string(" ") + b[*i]);
+ to_file.push_back(color.colorize(prefix + string(" ") + b[*i], p));
b_len++;
}
@@ -471,16 +497,19 @@ make_diff(string const & filename1,
data const & data2,
ostream & ost,
diff_type type,
- string const & pattern)
+ string const & pattern,
+ colorizer const & color)
{
if (guess_binary(data1()) || guess_binary(data2()))
{
// If a file has been removed, filename2 will be "/dev/null".
// It doesn't make sense to output that.
if (filename2 == "/dev/null")
- ost << "# " << filename1 << " is binary\n";
+ ost << color.colorize(string("# ") + filename1 + " is binary",
+ colorizer::comment) << "\n";
else
- ost << "# " << filename2 << " is binary\n";
+ ost << color.colorize(string("# ") + filename2 + " is binary",
+ colorizer::comment) << "\n";
return;
}
@@ -569,23 +598,27 @@ make_diff(string const & filename1,
{
case unified_diff:
{
- ost << "--- " << filename1 << '\t'
- << id1 << '\n';
- ost << "+++ " << filename2 << '\t'
- << id2 << '\n';
+ ost << color.colorize(string("--- ") + filename1,
+ colorizer::remove)
+ << '\t' << id1 << '\n';
+ ost << color.colorize(string("+++ ") + filename2,
+ colorizer::add)
+ << '\t' << id2 << '\n';
- unidiff_hunk_writer hunks(lines1, lines2, 3, ost, pattern);
+ unidiff_hunk_writer hunks(lines1, lines2, 3, ost, pattern, color);
walk_hunk_consumer(lcs, left_interned, right_interned, hunks);
break;
}
case context_diff:
{
- ost << "*** " << filename1 << '\t'
- << id1 << '\n';
- ost << "--- " << filename2 << '\t'
- << id2 << '\n';
+ ost << color.colorize(string("*** ") + filename1,
+ colorizer::remove)
+ << '\t' << id1 << '\n';
+ ost << color.colorize(string("--- ") + filename2,
+ colorizer::add)
+ << '\t' << id2 << '\n';
- cxtdiff_hunk_writer hunks(lines1, lines2, 3, ost, pattern);
+ cxtdiff_hunk_writer hunks(lines1, lines2, 3, ost, pattern, color);
walk_hunk_consumer(lcs, left_interned, right_interned, hunks);
break;
}
============================================================
--- src/diff_output.hh 9125ccd0d0fa725782c9910b5f34e844048d2da8
+++ src/diff_output.hh 168281addd27cdade1dc1320ee4814b28070feb8
@@ -15,6 +15,7 @@
// of GNU-diffutils-like things (diff, diff3, maybe patch..)
#include "vocab.hh"
+#include "colorizer.hh"
void make_diff(std::string const & filename1,
std::string const & filename2,
@@ -24,7 +25,8 @@ void make_diff(std::string const & filen
data const & data2,
std::ostream & ost,
diff_type type,
- std::string const & pattern);
+ std::string const & pattern,
+ colorizer const & colorizer);
#endif // __DIFF_PATCH_HH__
============================================================
--- src/lua_hooks.cc 1c178085332c73dcefb4681d205d17b059e52080
+++ src/lua_hooks.cc 81dd3985d253ac62743df0341e60a74d5b93b755
@@ -770,6 +770,21 @@ bool
}
bool
+lua_hooks::hook_get_output_color(string const purpose, string & fg,
+ string & bg, string & style)
+{
+ Lua ll = Lua(st);
+
+ return ll.func("get_output_color")
+ .push_str(purpose)
+ .call(1, 3)
+ .extract_str(style).pop()
+ .extract_str(bg).pop()
+ .extract_str(fg)
+ .ok();
+}
+
+bool
lua_hooks::hook_use_inodeprints()
{
bool use = false, exec_ok = false;
============================================================
--- src/lua_hooks.hh 66412b9fa5db97cd3b3ec01cadf036fb346ac161
+++ src/lua_hooks.hh 51a2842d22554cba640dcea416103f5e70c63c3b
@@ -173,6 +173,9 @@ public:
bool hook_get_man_page_formatter_command(string & command);
+ bool hook_get_output_color(string const purpose, string & fg,
+ string & bg, string & style);
+
// notification hooks
bool hook_note_commit(revision_id const & new_id,
revision_data const & rdat,
============================================================
--- doc/monotone.texi 5c18cff828089e592f5f2d53c2d60793715a4a40
+++ doc/monotone.texi 14de7e0ea6d88053129594b1628cac25ebf14506
@@ -5858,7 +5858,7 @@ @section Informative
@code{fa36}. This command is intended to be used by programmable
completion systems, such as those in @command{bash} and @command{zsh}.
address@hidden address@hidden mtn diff [--unified] [--[no-]show-encloser]
address@hidden address@hidden mtn diff [--unified] [--[no-]show-encloser] [--[no-]colorize]
@itemx mtn diff --context [--[no-]show-encloser]
@itemx mtn diff --external address@hidden
@itemx mtn diff @var{pathname...}
@@ -5900,7 +5900,7 @@ @section Informative
changed within the current subdirectory of the workspace.
The output format of @command{diff} is controlled by the options
address@hidden, @option{--context}, @option{--no-show-encloser}, and
address@hidden, @option{--context}, @option{--no-show-encloser}, @option{--colorize}, and
@option{--external}. By default, monotone uses its built-in diff
algorithm to produce a listing in ``unified diff'' format (analogous
to running the program @command{diff @option{-u}}); you can also explicitly
@@ -5922,6 +5922,10 @@ @section Informative
@ref{get_encloser_pattern}. For the regular _expression_ syntax, see
@ref{Regexps}.
+Furthermore, when @option{--colorize} is given, monotone tries to print
+colored diff output if the underlying terminal supports it. This works
+in both modes as well.
+
Sometimes, you may want more flexibility in output formats; for these
cases, you can use @option{--external}, which causes monotone to
invoke an external program to generate the actual output. By default,
@@ -6149,7 +6153,7 @@ @section Informative
within this list. See @ref{Managed Databases} for more information.
@anchor{mtn address@hidden mtn log
address@hidden mtn log address@hidden address@hidden address@hidden [...]] [--clear-from] address@hidden [...]] [--clear-to] address@hidden [...]] [--[no-]brief] [--[no-]merges] [--[no-]files] [--[no-]graph] [--[no-]diffs] address@hidden
address@hidden mtn log address@hidden address@hidden address@hidden [...]] [--clear-from] address@hidden [...]] [--clear-to] address@hidden [...]] [--[no-]brief] [--[no-]merges] [--[no-]files] [--[no-]graph] [--[no-]diffs] [--[no-]colorize] address@hidden
See the online help for more options.
This command prints out a log, in forward ancestry order by default
@@ -6220,8 +6224,11 @@ @section Informative
prefix on log output lines.
Specifying @option{--diffs} causes the log output to include a unified
-diff of the changes in each revision.
+diff of the changes in each revision. If @option{--colorize} is given
+additionally, the diff output is colored if the underlying terminal
+supports that.
+
If one or more files are given, the command will only log the revisions
where those files are changed.
============================================================
--- src/std_hooks.lua 30949d110cc1ed86d98f4f437fda16778a3e85bb
+++ src/std_hooks.lua 7669463d1a401dc786dbf65fc99d1a4853cf4a4f
@@ -1532,3 +1532,41 @@ end
end
end
+function get_output_color(purpose)
+ -- Returns a triple containing the fore color, background color and
+ -- style to use for formatting the output.
+ -- The fore color and background color can be any of the following
+ -- red, green, blue, yellow, cyan, magenta, black, white
+ -- Alternatively, they can be the empty string and Monotone will
+ -- decide.
+ -- Valid values for style are
+ -- none, bold, italic, underline
+ -- Alternatively, it can be the empty string and Monotone will
+ -- decide.
+
+ local default_color = { fg = "", bg = "", style = "" }
+ local color_table =
+ {
+ normal = default_color,
+
+ add = { fg = "green", bg = "", style = "" },
+ change = { fg = "blue", bg = "", style = "" },
+ comment = { fg = "yellow", bg = "", style = "" },
+ encloser = { fg = "magenta", bg = "", style = "" },
+ log_revision = { fg = "", bg = "", style = "bold" },
+ remove = { fg = "red", bg = "", style = "" },
+ rename = { fg = "yellow", bg = "", style = "" },
+ rev_header = { fg = "", bg = "", style = "bold" },
+ separator = { fg = "", bg = "", style = "bold" },
+ set = { fg = "cyan", bg = "", style = "" },
+ unset = { fg = "magenta", bg = "", style = "" }
+ }
+
+ local chosen_color = color_table[purpose]
+
+ if chosen_color == nil then
+ return default_color
+ else
+ return chosen_color.fg, chosen_color.bg, chosen_color.style
+ end
+end
============================================================
--- src/cmd_diff_log.cc 94a354875b587d372e6d0898ab6fc8355ce29c21
+++ src/cmd_diff_log.cc c8d5d47eecd08a5935b6739b640313effdfae100
@@ -17,6 +17,7 @@
#include "asciik.hh"
#include "charset.hh"
#include "cmd.hh"
+#include "colorizer.hh"
#include "date_format.hh"
#include "diff_output.hh"
#include "file_io.hh"
@@ -70,6 +71,7 @@ dump_diff(lua_hooks & lua,
bool external_diff_args_given,
string external_diff_args,
string const & encloser,
+ colorizer const & colorizer,
ostream & output)
{
if (diff_format == external_diff)
@@ -111,7 +113,8 @@ dump_diff(lua_hooks & lua,
make_diff(left, right,
left_id, right_id,
left_data, right_data,
- output, diff_format, encloser);
+ output, diff_format,
+ encloser, colorizer);
}
}
@@ -134,7 +137,8 @@ dump_diffs(lua_hooks & lua,
string external_diff_args,
bool left_from_db,
bool right_from_db,
- bool show_encloser)
+ bool show_encloser,
+ colorizer const & colorizer)
{
// Put all node data in a multimap with the file path of the node as key
// which gets automatically sorted. For removed nodes the file path is
@@ -220,7 +224,7 @@ dump_diffs(lua_hooks & lua,
dat.left_id, dat.right_id,
left_data, right_data,
diff_format, external_diff_args_given, external_diff_args,
- encloser, output);
+ encloser, colorizer, output);
}
}
@@ -382,6 +386,7 @@ void dump_header(std::string const & rev
roster_t const & old_roster,
roster_t const & new_roster,
std::ostream & out,
+ colorizer const & colorizer,
bool show_if_empty)
{
cset changes;
@@ -394,19 +399,23 @@ void dump_header(std::string const & rev
vector<string> lines;
split_into_lines(summary(), lines);
- out << "#\n";
+ out << colorizer.colorize("#", colorizer::comment) << "\n";
if (!summary().empty())
{
- out << revs << "#\n";
+ out << colorizer.colorize(revs, colorizer::comment);
+ out << colorizer.colorize("#", colorizer::comment) << "\n";
+
for (vector<string>::iterator i = lines.begin();
i != lines.end(); ++i)
- out << "# " << *i << '\n';
+ out << colorizer.colorize(string("# ") + *i,
+ colorizer::comment) << "\n";
}
else
{
- out << "# " << _("no changes") << '\n';
+ out << colorizer.colorize(string("# ") + _("no changes"),
+ colorizer::comment) << "\n";
}
- out << "#\n";
+ out << colorizer.colorize("#", colorizer::comment) << "\n";
}
CMD_PRESET_OPTIONS(diff)
@@ -437,9 +446,11 @@ CMD(diff, "diff", "di", CMD_REF(informat
prepare_diff(app, db, old_roster, new_roster, args, old_from_db, new_from_db, revs);
+ colorizer colorizer(app.opts.colorize, app.lua);
+
if (app.opts.with_header)
{
- dump_header(revs, old_roster, new_roster, cout, true);
+ dump_header(revs, old_roster, new_roster, cout, colorizer, true);
}
dump_diffs(app.lua, db, old_roster, new_roster, cout,
@@ -447,7 +458,8 @@ CMD(diff, "diff", "di", CMD_REF(informat
app.opts.external_diff_args_given,
app.opts.external_diff_args,
old_from_db, new_from_db,
- !app.opts.no_show_encloser);
+ !app.opts.no_show_encloser,
+ colorizer);
}
@@ -476,16 +488,20 @@ CMD_AUTOMATE(content_diff, N_("[FILE [..
prepare_diff(app, db, old_roster, new_roster, args, old_from_db, new_from_db,
dummy_header);
+ // never colorize the diff output
+ colorizer colorizer(false, app.lua);
if (app.opts.with_header)
{
- dump_header(dummy_header, old_roster, new_roster, output, false);
+ dump_header(dummy_header, old_roster, new_roster, output, colorizer, false);
}
dump_diffs(app.lua, db, old_roster, new_roster, output,
app.opts.diff_format,
app.opts.external_diff_args_given, app.opts.external_diff_args,
- old_from_db, new_from_db, !app.opts.no_show_encloser);
+ old_from_db, new_from_db,
+ !app.opts.no_show_encloser,
+ colorizer);
}
@@ -550,6 +566,7 @@ log_print_rev (app_state & app,
revision_t & rev,
string date_fmt,
node_restriction mask,
+ colorizer const & color,
ostream & out)
{
cert_name const author_name(author_cert_name);
@@ -563,7 +580,8 @@ log_print_rev (app_state & app,
if (app.opts.brief)
{
- out << rid;
+ out << color.colorize(encode_hexenc(rid.inner()(), rid.inner().made_from),
+ colorizer::log_revision);
log_certs(certs, out, author_name);
if (app.opts.no_graph)
log_certs(certs, out, date_name, date_fmt);
@@ -578,7 +596,7 @@ log_print_rev (app_state & app,
else
{
utf8 header;
- revision_header(rid, rev, certs, date_fmt, header);
+ revision_header(rid, rev, certs, date_fmt, color, header);
external header_external;
utf8_to_system_best_effort(header, header_external);
@@ -587,7 +605,7 @@ log_print_rev (app_state & app,
if (!app.opts.no_files)
{
utf8 summary;
- revision_summary(rev, summary);
+ revision_summary(rev, color, summary);
external summary_external;
utf8_to_system_best_effort(summary, summary_external);
out << summary_external;
@@ -619,7 +637,8 @@ log_print_rev (app_state & app,
app.opts.external_diff_args_given,
app.opts.external_diff_args,
true, true,
- !app.opts.no_show_encloser);
+ !app.opts.no_show_encloser,
+ color);
}
}
}
@@ -838,8 +857,11 @@ log_common (app_state & app,
set<revision_id> seen;
revision_t rev;
+
+ colorizer color(app.opts.colorize && !automate, app.lua);
// this is instantiated even when not used, but it's lightweight
- asciik graph(output);
+ asciik graph(output, color);
+
while(!frontier.empty() && last != 0 && next != 0)
{
revision_id const & rid = frontier.top().second;
@@ -935,7 +957,7 @@ log_common (app_state & app,
else
{
ostringstream out;
- log_print_rev (app, db, project, rid, rev, date_fmt, mask_diff, out);
+ log_print_rev(app, db, project, rid, rev, date_fmt, mask_diff, color, out);
string out_system;
utf8_to_system_best_effort(utf8(out.str(), origin::internal), out_system);
@@ -983,7 +1005,7 @@ CMD(log, "log", "", CMD_REF(informative)
options::opts::brief | options::opts::diffs |
options::opts::depth | options::opts::exclude |
options::opts::no_merges | options::opts::no_files |
- options::opts::no_graph)
+ options::opts::no_graph )
{
log_common (app, args, false, cout);
}
============================================================
--- src/cmd_files.cc 7e9ffd4a06daeb0ef7ab7557d3a656c6b99ab2ad
+++ src/cmd_files.cc 44c13d2a7ae5e2beb2b316d24202481680779f70
@@ -14,6 +14,7 @@
#include "annotate.hh"
#include "revision.hh"
#include "cmd.hh"
+#include "colorizer.hh"
#include "diff_output.hh"
#include "merge_content.hh"
#include "file_io.hh"
@@ -132,7 +133,8 @@ CMD(fdiff, "fdiff", "", CMD_REF(debug),
make_diff(src_name, dst_name,
src_id, dst_id,
src.inner(), dst.inner(),
- cout, app.opts.diff_format, pattern);
+ cout, app.opts.diff_format,
+ pattern, colorizer(app.opts.colorize, app.lua));
}
CMD(annotate, "annotate", "", CMD_REF(informative), N_("PATH"),
============================================================
--- src/cmd_ws_commit.cc 7b91a53d8eec4e78b062092f85c945bbaaefe23a
+++ src/cmd_ws_commit.cc e0bd38df40b3be50ffd8793c134fcc9edfb47bd9
@@ -259,7 +259,8 @@ get_log_message_interactively(lua_hooks
}
utf8 summary;
- revision_summary(rev, summary);
+ colorizer color(false, lua);
+ revision_summary(rev, color, summary);
utf8 full_message(changelog() + cancel() + instructions() + editable() + ignored() +
notes() + summary(),
@@ -965,10 +966,11 @@ CMD(status, "status", "", CMD_REF(inform
utf8 header;
utf8 summary;
+ colorizer color(app.opts.colorize, app.lua);
revision_header(rid, rev, author, date_t::now(), app.opts.branch, changelog,
- date_fmt, header);
- revision_summary(rev, summary);
+ date_fmt, color, header);
+ revision_summary(rev, color, summary);
external header_external;
external summary_external;
============================================================
--- src/options_list.hh 4af93dbcc45e76d732d073ced7ce21d20472cd00
+++ src/options_list.hh e7b13e91324a35e0b05be40e49f66cc654fa2f7e
@@ -285,7 +285,8 @@ GROUPED_SIMPLE_OPTION(date_formats, no_f
"no-format-dates", bool,
gettext_noop("print date certs exactly as stored in the database"))
-
+GROUPED_SIMPLE_OPTION(globals, colorize, "colorize/no-colorize", bool,
+ gettext_noop("colorize output"))
OPTVAR(globals, db_type, dbname_type, )
OPTVAR(globals, std::string, dbname_alias, )
OPTVAR(globals, system_path, dbname, )
============================================================
--- src/asciik.cc cf946f9a14ad309615704bc960255c50e12b636a
+++ src/asciik.cc 64600c9969226fa55cd05982364147342d3b734e
@@ -135,8 +135,8 @@ 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, size_t min_width)
- : width(min_width), output(os)
+asciik::asciik(ostream & os, colorizer const & color, size_t min_width)
+ : width(min_width), output(os), color(color)
{
}
@@ -250,10 +250,13 @@ asciik::draw(size_t const curr_items,
// prints it out
//TODO convert line/interline/interline2 from ASCII to system charset
- output << line << " " << lines[0] << '\n';
- output << interline << " " << lines[1] << '\n';
+ output << color.colorize(line, colorizer::log_revision)
+ << " " << lines[0] << '\n';
+ output << color.colorize(interline, colorizer::log_revision)
+ << " " << lines[1] << '\n';
for (int i = 2; i < num_lines; ++i)
- output << interline2 << " " << lines[i] << '\n';
+ output << color.colorize(interline2, colorizer::log_revision)
+ << " " << lines[i] << '\n';
}
bool
@@ -387,7 +390,7 @@ CMD(asciik, "asciik", "", CMD_REF(debug)
toposort(db, revs, sorted);
reverse(sorted.begin(), sorted.end());
- asciik graph(std::cout, 10);
+ asciik graph(std::cout, colorizer(app.opts.colorize, app.lua), 10);
for (vector<revision_id>::const_iterator rev = sorted.begin();
rev != sorted.end(); ++rev)
============================================================
--- src/asciik.hh 592aa966af256f50be9784bfd01c543f54d3447b
+++ src/asciik.hh 3e0dcd90804053a5e558b0ddfa6e5f3dcc462d50
@@ -11,13 +11,14 @@
#define __ASCIIK_HH__
#include <set>
+#include "colorizer.hh"
#include "vector.hh"
#include "vocab.hh"
class asciik
{
public:
- asciik(std::ostream & os, size_t min_width = 0);
+ asciik(std::ostream & os, colorizer const & color, size_t min_width = 0);
// Prints an ASCII-k chunk using the given revisions.
// Multiple lines are supported in annotation (the graph will stretch
// accordingly); empty newlines at the end will be removed.
@@ -41,6 +42,7 @@ private:
// internal state
size_t width;
std::ostream & output;
+ colorizer const & color;
std::vector<revision_id> curr_row;
};
============================================================
--- src/rev_output.cc a2c70b893b31296917d1a2b974faa1da46c13f1e
+++ src/rev_output.cc fec6728d80bca2d8d13ab49bb4ecd03310879fe5
@@ -31,40 +31,40 @@ revision_header(revision_id const rid, r
revision_header(revision_id const rid, revision_t const & rev,
string const & author, date_t const date,
branch_name const & branch, utf8 const & changelog,
- string const & date_fmt, utf8 & header)
+ string const & date_fmt, colorizer const & color, utf8 & header)
{
vector<cert> certs;
key_id empty_key;
- certs.push_back(cert(rid, author_cert_name,
+ certs.push_back(cert(rid, author_cert_name,
cert_value(author, origin::user), empty_key));
- certs.push_back(cert(rid, date_cert_name,
+ certs.push_back(cert(rid, date_cert_name,
cert_value(date.as_iso_8601_extended(), origin::user),
empty_key));
- certs.push_back(cert(rid, branch_cert_name,
+ certs.push_back(cert(rid, branch_cert_name,
cert_value(branch(), origin::user), empty_key));
if (!changelog().empty())
- certs.push_back(cert(rid, changelog_cert_name,
+ certs.push_back(cert(rid, changelog_cert_name,
cert_value(changelog(), origin::user), empty_key));
- revision_header(rid, rev, certs, date_fmt, header);
+ revision_header(rid, rev, certs, date_fmt, color, header);
}
void
revision_header(revision_id const rid, revision_t const & rev,
vector<cert> const & certs, string const & date_fmt,
- utf8 & header)
+ colorizer const & color, utf8 & header)
{
ostringstream out;
- out << string(70, '-') << '\n'
- << _("Revision: ") << rid << '\n';
+ out << color.colorize(string(70, '-'), colorizer::log_revision) << '\n'
+ << color.colorize(_("Revision: "), colorizer::rev_header) << rid << '\n';
for (edge_map::const_iterator i = rev.edges.begin(); i != rev.edges.end(); ++i)
{
revision_id parent = edge_old_revision(*i);
if (!null_id(parent))
- out << _("Parent: ") << parent << '\n';
+ out << color.colorize(_("Parent: "), colorizer::rev_header) << parent << '\n';
}
cert_name const author(author_cert_name);
@@ -76,34 +76,40 @@ revision_header(revision_id const rid, r
for (vector<cert>::const_iterator i = certs.begin(); i != certs.end(); ++i)
if (i->name == author)
- out << _("Author: ") << i->value << '\n';
+ out << color.colorize(_("Author: "), colorizer::rev_header)
+ << i->value << '\n';
for (vector<cert>::const_iterator i = certs.begin(); i != certs.end(); ++i)
if (i->name == date)
{
if (date_fmt.empty())
- out << _("Date: ") << i->value << '\n';
+ out << color.colorize(_("Date: "), colorizer::rev_header)
+ << i->value << '\n';
else
{
date_t date(i->value());
- out << _("Date: ") << date.as_formatted_localtime(date_fmt) << '\n';
+ out << color.colorize(_("Date: "), colorizer::rev_header)
+ << date.as_formatted_localtime(date_fmt) << '\n';
}
}
for (vector<cert>::const_iterator i = certs.begin(); i != certs.end(); ++i)
if (i->name == branch)
- out << _("Branch: ") << i->value << '\n';
+ out << color.colorize(_("Branch: "), colorizer::rev_header)
+ << i->value << '\n';
for (vector<cert>::const_iterator i = certs.begin(); i != certs.end(); ++i)
if (i->name == tag)
- out << _("Tag: ") << i->value << '\n';
+ out << color.colorize(_("Tag: "), colorizer::rev_header)
+ << i->value << '\n';
out << "\n";
for (vector<cert>::const_iterator i = certs.begin(); i != certs.end(); ++i)
if (i->name == changelog)
{
- out << _("Changelog: ") << "\n\n" << i->value << '\n';
+ out << color.colorize(_("Changelog: "), colorizer::rev_header) << "\n\n"
+ << i->value << '\n';
if (!i->value().empty() && i->value()[i->value().length()-1] != '\n')
out << '\n';
}
@@ -111,7 +117,8 @@ revision_header(revision_id const rid, r
for (vector<cert>::const_iterator i = certs.begin(); i != certs.end(); ++i)
if (i->name == comment)
{
- out << _("Comments: ") << "\n\n" << i->value << '\n';
+ out << color.colorize(_("Comments: "), colorizer::rev_header) << "\n\n"
+ << i->value << '\n';
if (!i->value().empty() && i->value()[i->value().length()-1] != '\n')
out << '\n';
}
@@ -120,7 +127,7 @@ void
}
void
-revision_summary(revision_t const & rev, utf8 & summary)
+revision_summary(revision_t const & rev, colorizer const & color, utf8 & summary)
{
// We intentionally do not collapse the final \n into the format
// strings here, for consistency with newline conventions used by most
@@ -138,9 +145,9 @@ revision_summary(revision_t const & rev,
// A colon at the end of this string looked nicer, but it made
// double-click copying from terminals annoying.
if (null_id(parent))
- out << _("Changes") << "\n\n";
+ out << color.colorize(_("Changes"), colorizer::rev_header) << "\n\n";
else
- out << _("Changes against parent ") << parent << "\n\n";
+ out << color.colorize(_("Changes against parent "), colorizer::rev_header) << parent << "\n\n";
// presumably a merge rev could have an empty edge if one side won
if (cs.empty())
@@ -148,43 +155,53 @@ revision_summary(revision_t const & rev,
for (set<file_path>::const_iterator i = cs.nodes_deleted.begin();
i != cs.nodes_deleted.end(); ++i)
- out << (F(" dropped %s") %*i) << '\n';
+ out << color.colorize((F(" dropped %s") %*i).str(),
+ colorizer::remove) << '\n';
for (map<file_path, file_path>::const_iterator
i = cs.nodes_renamed.begin();
i != cs.nodes_renamed.end(); ++i)
- out << (F(" renamed %s\n"
- " to %s") % i->first % i->second) << '\n';
+ out << color.colorize((F(" renamed %s\n"
+ " to %s") % i->first
+ % i->second).str(),
+ colorizer::rename) << '\n';
for (set<file_path>::const_iterator i = cs.dirs_added.begin();
i != cs.dirs_added.end(); ++i)
- out << (F(" added %s") % *i) << '\n';
+ out << color.colorize((F(" added %s") % *i).str(),
+ colorizer::add) << '\n';
for (map<file_path, file_id>::const_iterator i = cs.files_added.begin();
i != cs.files_added.end(); ++i)
- out << (F(" added %s") % i->first) << '\n';
+ out << color.colorize((F(" added %s") % i->first).str(),
+ colorizer::add) << '\n';
for (map<file_path, pair<file_id, file_id> >::const_iterator
i = cs.deltas_applied.begin(); i != cs.deltas_applied.end(); ++i)
- out << (F(" patched %s") % i->first) << '\n';
+ out << color.colorize((F(" patched %s") % i->first).str(),
+ colorizer::change) << '\n';
for (map<pair<file_path, attr_key>, attr_value >::const_iterator
i = cs.attrs_set.begin(); i != cs.attrs_set.end(); ++i)
- out << (F(" attr on %s\n"
- " set %s\n"
- " to %s")
- % i->first.first % i->first.second % i->second) << '\n';
+ out << color.colorize((F(" attr on %s\n"
+ " set %s\n"
+ " to %s")
+ % i->first.first % i->first.second
+ % i->second).str(),
+ colorizer::set) << '\n';
// FIXME: naming here could not be more inconsistent
// the cset calls it attrs_cleared
// the command is attr drop
// here it is called unset
- // the revision text uses attr clear
+ // the revision text uses attr clear
for (set<pair<file_path, attr_key> >::const_iterator
i = cs.attrs_cleared.begin(); i != cs.attrs_cleared.end(); ++i)
- out << (F(" attr on %s\n"
- " unset %s") % i->first % i->second) << '\n';
+ out << color.colorize((F(" attr on %s\n"
+ " unset %s") % i->first
+ % i->second).str(),
+ colorizer::unset) << '\n';
out << '\n';
}
============================================================
--- src/rev_output.hh 666dd3ed35e16d8b122b4932c2aad05a21a22e25
+++ src/rev_output.hh 5879a8268a59545c946583b65f66eda4491b979e
@@ -10,6 +10,7 @@
#ifndef __REV_SUMMARY_HH__
#define __REV_SUMMARY_HH__
+#include "colorizer.hh"
#include "rev_types.hh"
#include "vocab.hh"
@@ -17,18 +18,19 @@ void
struct cert;
void
-revision_header(revision_id const rid, revision_t const & rev,
+revision_header(revision_id const rid, revision_t const & rev,
std::string const & author, date_t const date,
branch_name const & branch, utf8 const & changelog,
- std::string const & date_fmt, utf8 & header);
+ std::string const & date_fmt, colorizer const & color,
+ utf8 & header);
void
-revision_header(revision_id const rid, revision_t const & rev,
+revision_header(revision_id const rid, revision_t const & rev,
std::vector<cert> const & certs, std::string const & date_fmt,
- utf8 & header);
+ colorizer const & color, utf8 & header);
void
-revision_summary(revision_t const & rev, utf8 & summary);
+revision_summary(revision_t const & rev, colorizer const & color, utf8 & summary);
#endif // header guard
============================================================
--- /dev/null
+++ src/colorizer.cc 96964884a83e4d7d638c146821a554d033f396eb
@@ -0,0 +1,184 @@
+// Copyright (C) 2010 Thomas Keller <address@hidden>
+//
+// This program is made available under the GNU GPL version 2.0 or
+// greater. See the accompanying file COPYING for details.
+//
+// This program is distributed WITHOUT ANY WARRANTY; without even the
+// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+// PURPOSE.
+
+#include "base.hh"
+#include "colorizer.hh"
+#include "platform.hh"
+
+using std::string;
+using std::map;
+using std::make_pair;
+
+
+string colorizer::purpose_to_name(colorizer::purpose const p) const
+{
+ switch (p)
+ {
+ case normal:
+ return "normal";
+ case reset:
+ return "reset";
+
+ case add:
+ return "add";
+ case change:
+ return "change";
+ case comment:
+ return "comment";
+ case encloser:
+ return "encloser";
+ case log_revision:
+ return "log_revision";
+ case remove:
+ return "remove";
+ case rename:
+ return "rename";
+ case rev_header:
+ return "rev_header";
+ case separator:
+ return "separator";
+ case set:
+ return "set";
+ case unset:
+ return "unset";
+
+ default:
+ I(false); // should never get here
+ }
+}
+
+std::pair<colorizer::purpose, boost::tuple<string, string, string> > colorizer::map_output_color(
+ purpose const p)
+{
+ string fg, bg, style;
+ string purpose_name = purpose_to_name(p);
+
+ if (p == reset)
+ {
+ // the user doesn't need to know about reset - it's an implementation
+ // detail for us to handle
+ fg = bg = style = "";
+ }
+ else
+ {
+ lua.hook_get_output_color(purpose_name, fg, bg, style);
+ }
+
+ return std::make_pair(p, boost::make_tuple(fg_to_code(fg),
+ bg_to_code(bg),
+ style_to_code(style)));
+}
+
+string colorizer::fg_to_code(string const color) const
+{
+ if (color == "black")
+ return "\033[30m";
+ else if (color == "red")
+ return "\033[31m";
+ else if (color == "green")
+ return "\033[32m";
+ else if (color == "yellow")
+ return "\033[33m";
+ else if (color == "blue")
+ return "\033[34m";
+ else if (color == "magenta")
+ return "\033[35m";
+ else if (color == "cyan")
+ return "\033[36m";
+ else if (color == "white")
+ return "\033[37m";
+ else
+ return "\033[39m"; // default
+}
+
+string colorizer::bg_to_code(string const color) const
+{
+ if (color == "black")
+ return "\033[40m";
+ else if (color == "red")
+ return "\033[41m";
+ else if (color == "green")
+ return "\033[42m";
+ else if (color == "yellow")
+ return "\033[43m";
+ else if (color == "blue")
+ return "\033[44m";
+ else if (color == "magenta")
+ return "\033[45m";
+ else if (color == "cyan")
+ return "\033[46m";
+ else if (color == "white")
+ return "\033[47m";
+ else
+ return "\033[49m"; // default
+}
+
+string colorizer::style_to_code(string const style) const
+{
+ if (style == "none")
+ return "\033[22m\033[23m\033[24m";
+ else if (style == "bold")
+ return "\033[1m";
+ else if (style == "italic")
+ return "\033[3m";
+ else if (style == "underline")
+ return "\033[4m";
+ else
+ return "\033[22m\033[23m\033[24m"; // all off
+}
+
+colorizer::colorizer(bool enable, lua_hooks & lh)
+ : lua(lh)
+{
+ if (!have_smart_terminal())
+ enable = false;
+
+ if (enable)
+ {
+ colormap.insert(map_output_color(normal));
+ colormap.insert(map_output_color(reset));
+
+ colormap.insert(map_output_color(add));
+ colormap.insert(map_output_color(change));
+ colormap.insert(map_output_color(comment));
+ colormap.insert(map_output_color(encloser));
+ colormap.insert(map_output_color(log_revision));
+ colormap.insert(map_output_color(remove));
+ colormap.insert(map_output_color(rename));
+ colormap.insert(map_output_color(rev_header));
+ colormap.insert(map_output_color(separator));
+ colormap.insert(map_output_color(set));
+ colormap.insert(map_output_color(unset));
+ }
+}
+
+string
+colorizer::colorize(string const & in, purpose p) const
+{
+ if (colormap.find(p) == colormap.end())
+ return in;
+
+ return get_format(p) + in + get_format(reset);
+}
+
+string
+colorizer::get_format(purpose const p) const
+{
+ boost::tuple<string, string, string> format = colormap.find(p)->second;
+
+ return format.get<0>() + format.get<1>() + format.get<2>();
+}
+
+// Local Variables:
+// mode: C++
+// fill-column: 76
+// c-file-style: "gnu"
+// indent-tabs-mode: nil
+// End:
+// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:
============================================================
--- /dev/null
+++ src/colorizer.hh eb3d0e3dad8d447e270e0c6264bf1a4ea139013f
@@ -0,0 +1,66 @@
+// Copyright (C) 2010 Thomas Keller <address@hidden>
+//
+// This program is made available under the GNU GPL version 2.0 or
+// greater. See the accompanying file COPYING for details.
+//
+// This program is distributed WITHOUT ANY WARRANTY; without even the
+// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+// PURPOSE.
+
+#ifndef __COLORIZER_HH__
+#define __COLORIZER_HH__
+
+#include "lua_hooks.hh"
+#include "vocab.hh"
+#include <map>
+#include <boost/tuple/tuple.hpp>
+
+struct colorizer {
+
+ typedef enum { normal = 0,
+ reset,
+
+ add,
+ change,
+ comment,
+ encloser,
+ log_revision,
+ remove,
+ rename,
+ rev_header,
+ separator,
+ set,
+ unset
+ } purpose;
+
+ colorizer(bool enable, lua_hooks & lh);
+
+ std::string
+ colorize(std::string const & in, purpose p = normal) const;
+
+private:
+ std::map<purpose, boost::tuple<std::string, std::string, std::string> >
+ colormap;
+ lua_hooks & lua;
+
+ std::pair<purpose, boost::tuple<std::string, std::string, std::string> >
+ map_output_color(purpose const p);
+
+ std::string fg_to_code(std::string const color) const;
+ std::string bg_to_code(std::string const color) const;
+ std::string style_to_code(std::string const style) const;
+
+ std::string get_format(purpose const p) const;
+
+ std::string purpose_to_name(purpose const p) const;
+};
+
+#endif // __COLORIZER_HH__
+
+// Local Variables:
+// mode: C++
+// fill-column: 76
+// c-file-style: "gnu"
+// indent-tabs-mode: nil
+// End:
+// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Monotone-commits-diffs] net.venge.monotone.colored-diff: d4165db330a1781b7016a401c21a1c25fa952894,
code <=