# # # patch "NEWS" # from [02bd18dac9795437536b6bbfc2e219c398e740f1] # to [e393f36663d768fa1481555c9066e67ebf741341] # # patch "annotate.cc" # from [797f71ea4777ab00858e20b283df08258375a3d0] # to [148031d40f893f9a31c9bcc5644e12e5601d5255] # # patch "annotate.hh" # from [042ec6df1e82fe99a453c341046089b0ddf8e7a3] # to [bae021e0ed2c6485f9428b8ad5f27d42fb7e7936] # # patch "cmd_diff_log.cc" # from [83d2bb41c536dbd438864353700ae3272c93f1e9] # to [740ad3ddb276b0d5a902287a4375ad4ad8a9ff1e] # # patch "cmd_files.cc" # from [1986733a6377cad7b391f4d936f08fa23a0e9224] # to [0e0f670c8b91d458f67261ddd56c7623bde50d71] # # patch "lua_hooks.cc" # from [9e358c5c997d6ef28d41c463b16b341182e77f6c] # to [d4f06492ebfd19893156cf0021b7afef29009332] # # patch "lua_hooks.hh" # from [e5ae9443d2eb45636e38769fc41839b03fd340f7] # to [e4bfa01a091e43739f11ecfc0b6c096e089b127e] # # patch "monotone.texi" # from [91c774105b13a0ea0f2e1daacf912ac5d62c9e5b] # to [671f22bb0656bb4eb0c3ce345218fead1c673941] # # patch "std_hooks.lua" # from [e8034da4b8f883a783910810714366dd920a57a1] # to [8d713fef5bf9921b78ac24e07f6d837524e35e9a] # # patch "vocab.hh" # from [61bc19598cbf8668c41855cfa0841af03079be30] # to [e572a01a4185be56e57287b83efdc44061c2baef] # ============================================================ --- NEWS 02bd18dac9795437536b6bbfc2e219c398e740f1 +++ NEWS e393f36663d768fa1481555c9066e67ebf741341 @@ -19,6 +19,12 @@ XXX XXX XX XX:XX:XX UTC 2010 default implementation of this hook attempts to produce valid git authors using several default pattern replacements. + - The 'get_date_format_spec' lua hook now has an additional parameter + which hints at the wanted format (f.e. a short date or a long date + time). The default implementation now returns '%x' for short and + long dates, '%X' for short and long times (currently unused) and + '%x %X' for short and long date times. + New features - Added portuguese translation (thanks to Américo Monteiro) @@ -32,6 +38,8 @@ XXX XXX XX XX:XX:XX UTC 2010 interrupted (^C); a couple of other bug have been fixed for this platform as well which generally improve the compatibility. + - The annotation of 'annotate' is now localized. + Other - Roster handling has been sped up significantly, and roster cache ============================================================ --- annotate.cc 797f71ea4777ab00858e20b283df08258375a3d0 +++ annotate.cc 148031d40f893f9a31c9bcc5644e12e5601d5255 @@ -59,7 +59,7 @@ public: class annotate_context { public: - annotate_context(project_t & project, file_id fid); + annotate_context(app_state & app, project_t & project, file_id fid); shared_ptr initial_lineage() const; @@ -86,6 +86,7 @@ private: private: void build_revisions_to_annotations(map & r2a) const; + app_state & app; project_t & project; /// keep a count so we can tell quickly whether we can terminate @@ -207,8 +208,8 @@ typedef multi_index_container< > work_units; -annotate_context::annotate_context(project_t & project, file_id fid) - : project(project), annotated_lines_completed(0) +annotate_context::annotate_context(app_state & app, project_t & project, file_id fid) + : app(app), project(project), annotated_lines_completed(0) { // initialize file_lines file_data fpacked; @@ -371,6 +372,18 @@ cert_string_value(vector const & c return ""; } +static string +cert_date_value(vector const & certs, + cert_name const & name, + bool from_start, bool from_end, + string const & fmt) +{ + string certval = cert_string_value(certs, name, from_start, from_end, ""); + if (fmt.empty()) + return certval; + return date_t(certval).as_formatted_localtime(fmt); +} + void annotate_context::build_revisions_to_annotations (map & revs_to_notations) const @@ -386,6 +399,14 @@ annotate_context::build_revisions_to_ann } size_t max_note_length = 0; + string date_fmt; + if (app.opts.format_dates) + { + if (!app.opts.date_fmt.empty()) + date_fmt = app.opts.date_fmt; + else + app.lua.hook_get_date_format_spec(date_short, date_fmt); + } // build revision -> annotation string mapping for (set::const_iterator i = seen.begin(); @@ -398,17 +419,12 @@ annotate_context::build_revisions_to_ann string author(cert_string_value(certs, author_cert_name, true, false, "@< ")); - string date(cert_string_value(certs, date_cert_name, - true, false, "T")); + string date(cert_date_value(certs, date_cert_name, true, false, date_fmt)); - string result; string hex_rev_str(encode_hexenc(i->inner()(), i->inner().made_from)); - result.append(hex_rev_str.substr(0, 8)); - result.append(".. by "); - result.append(author); - result.append(" "); - result.append(date); - result.append(": "); + string result = (F("%s.. by %s %s: ") + % hex_rev_str.substr(0, 8) + % author % date).str(); max_note_length = ((result.size() > max_note_length) ? result.size() @@ -820,14 +836,14 @@ void } void -do_annotate (project_t & project, const_file_t file_node, +do_annotate (app_state & app, project_t & project, const_file_t file_node, revision_id rid, bool just_revs) { L(FL("annotating file %s with content %s in revision %s") % file_node->self % file_node->content % rid); shared_ptr - acp(new annotate_context(project, file_node->content)); + acp(new annotate_context(app, project, file_node->content)); shared_ptr lineage = acp->initial_lineage(); ============================================================ --- annotate.hh 042ec6df1e82fe99a453c341046089b0ddf8e7a3 +++ annotate.hh bae021e0ed2c6485f9428b8ad5f27d42fb7e7936 @@ -12,12 +12,13 @@ #include "vocab.hh" #include "rev_types.hh" +#include "app_state.hh" class project_t; void -do_annotate(project_t & project, const_file_t file_node, revision_id rid, - bool just_revs); +do_annotate(app_state & app, project_t & project, const_file_t file_node, + revision_id rid, bool just_revs); #endif // defined __ANNOTATE_HH__ ============================================================ --- cmd_diff_log.cc 83d2bb41c536dbd438864353700ae3272c93f1e9 +++ cmd_diff_log.cc 740ad3ddb276b0d5a902287a4375ad4ad8a9ff1e @@ -749,7 +749,7 @@ CMD(log, "log", "", CMD_REF(informative) if (!app.opts.date_fmt.empty()) date_fmt = app.opts.date_fmt; else - app.lua.hook_get_date_format_spec(date_fmt); + app.lua.hook_get_date_format_spec(date_time_short, date_fmt); } long last = app.opts.last; ============================================================ --- cmd_files.cc 1986733a6377cad7b391f4d936f08fa23a0e9224 +++ cmd_files.cc 0e0f670c8b91d458f67261ddd56c7623bde50d71 @@ -193,7 +193,7 @@ CMD(annotate, "annotate", "", CMD_REF(in const_file_t file_node = downcast_to_file_t(node); L(FL("annotate for file_id %s") % file_node->self); - do_annotate(project, file_node, rid, app.opts.revs_only); + do_annotate(app, project, file_node, rid, app.opts.revs_only); } CMD(identify, "identify", "", CMD_REF(debug), N_("[PATH]"), ============================================================ --- lua_hooks.cc 9e358c5c997d6ef28d41c463b16b341182e77f6c +++ lua_hooks.cc d4f06492ebfd19893156cf0021b7afef29009332 @@ -625,18 +625,31 @@ bool } bool -lua_hooks::hook_get_date_format_spec(std::string & spec) +lua_hooks::hook_get_date_format_spec(date_format_spec in, std::string & out) { + string in_spec; + switch (in) + { + case date_long: in_spec = "date_long"; break; + case date_short: in_spec = "date_short"; break; + case time_long: in_spec = "time_long"; break; + case time_short: in_spec = "time_short"; break; + case date_time_long: in_spec = "date_time_long"; break; + case date_time_short: in_spec = "date_time_short"; break; + default: I(false); + } + bool exec_ok = Lua(st) .func("get_date_format_spec") - .call(0, 1) - .extract_str(spec) + .push_str(in_spec) + .call(1, 1) + .extract_str(out) .ok(); // If the hook fails, disable date formatting. if (!exec_ok) - spec = ""; + out = ""; return exec_ok; } ============================================================ --- lua_hooks.hh e5ae9443d2eb45636e38769fc41839b03fd340f7 +++ lua_hooks.hh e4bfa01a091e43739f11ecfc0b6c096e089b127e @@ -126,7 +126,7 @@ public: bool hook_get_default_command_options(commands::command_id const & cmd, args_vector & args); - bool hook_get_date_format_spec(std::string & spec); + bool hook_get_date_format_spec(date_format_spec in, std::string & out); // workspace hooks bool hook_use_inodeprints(); ============================================================ --- monotone.texi 91c774105b13a0ea0f2e1daacf912ac5d62c9e5b +++ monotone.texi 671f22bb0656bb4eb0c3ce345218fead1c673941 @@ -10060,7 +10060,7 @@ @section GIT from a monotone database with the following sql query: @verbatim -$ mtn db execute 'select distinct public_keys.name +$ mtn db execute 'select distinct public_keys.name from public_keys left join revision_certs on revision_certs.keypair_id = public_keys.id where revision_certs.name = "author"' @@ -10612,14 +10612,20 @@ @subsection User Defaults branches. Otherwise returns @code{false}. This hook has no default definition, therefore the default behavior is to list all branches. address@hidden get_date_format_spec () address@hidden get_date_format_spec (@var{wanted}) Returns a @code{strftime} format specification, which @command{mtn log} and similar commands will use to format dates, unless instructed -otherwise. The default definition returns @address@hidden"%d %b %Y, -%I:%M:%S %p"}}, which produces output like this: @address@hidden May 2009, -09:06:14 AM}}. +otherwise. The default definition returns @samp{%x} for long and short +date formats, @samp{%X} for long and short time formats and @samp{%x %X} +for long and short date time formats, which is equivalent to @samp{22/05/09}, address@hidden:06:14} and @samp{22/05/09 09:06:14} in an English locale. address@hidden can be one of @samp{date_long}, @samp{date_short}, address@hidden, @samp{time_short}, @samp{date_time_long} and address@hidden, though only @samp{date_short} and address@hidden are currently used. + @end ftable @subsection Netsync Permission Hooks ============================================================ --- std_hooks.lua e8034da4b8f883a783910810714366dd920a57a1 +++ std_hooks.lua 8d713fef5bf9921b78ac24e07f6d837524e35e9a @@ -290,10 +290,10 @@ function edit_comment(basetext, user_log elseif (program_exists_in_path("editor")) then exe = "editor" elseif (program_exists_in_path("vi")) then exe = "vi" elseif (string.sub(get_ostype(), 1, 6) ~= "CYGWIN" and - program_exists_in_path("notepad.exe")) then exe = "notepad" + program_exists_in_path("notepad.exe")) then exe = "notepad" else io.write(gettext("Could not find editor to enter commit message\n" - .. "Try setting the environment variable EDITOR\n")) + .. "Try setting the environment variable EDITOR\n")) return nil end @@ -316,22 +316,22 @@ function edit_comment(basetext, user_log if (not string.find(exe, "[^%w_.+-]")) then -- safe to call spawn directly if (execute(exe, tname) ~= 0) then - io.write(string.format(gettext("Error running editor '%s' ".. - "to enter log message\n"), + io.write(string.format(gettext("Error running editor '%s' ".. + "to enter log message\n"), exe)) - os.remove(tname) - return nil + os.remove(tname) + return nil end else -- must use shell local shell = os.getenv("SHELL") if (shell == nil) then shell = "sh" end if (not program_exists_in_path(shell)) then - io.write(string.format(gettext("Editor command '%s' needs a shell, ".. - "but '%s' is not to be found"), - exe, shell)) - os.remove(tname) - return nil + io.write(string.format(gettext("Editor command '%s' needs a shell, ".. + "but '%s' is not to be found"), + exe, shell)) + os.remove(tname) + return nil end -- Single-quoted strings in both Bourne shell and csh can contain @@ -339,11 +339,11 @@ function edit_comment(basetext, user_log local safe_tname = " '" .. string.gsub(tname, "'", "'\\''") .. "'" if (execute(shell, "-c", editor .. safe_tname) ~= 0) then - io.write(string.format(gettext("Error running editor '%s' ".. - "to enter log message\n"), + io.write(string.format(gettext("Error running editor '%s' ".. + "to enter log message\n"), exe)) - os.remove(tname) - return nil + os.remove(tname) + return nil end end @@ -377,14 +377,14 @@ end return false end -function get_date_format_spec() +function get_date_format_spec(wanted) -- Return the strftime(3) specification to be used to print dates -- in human-readable format after conversion to the local timezone. -- The default uses the preferred date and time representation for -- the current locale, e.g. the output looks like this: "09/08/2009 - -- 06:49:26 PM" for en_US, or "08.09.2009 18:49:26" for de_DE. - return "%x %X" - + -- 06:49:26 PM" for en_US and "date_time_long", or "08.09.2009" + -- for de_DE and "date_short" + -- -- A sampling of other possible formats you might want: -- default for your locale: "%c" (may include a confusing timezone label) -- 12 hour format: "%d %b %Y, %I:%M:%S %p" @@ -393,6 +393,14 @@ function get_date_format_spec() -- ISO 8601: "%Y-%m-%d %H:%M:%S" or "%Y-%m-%dT%H:%M:%S" -- -- ISO 8601, no timezone conversion: "" + --. + if (wanted == "date_long" or wanted == "date_short") then + return "%x" + end + if (wanted == "time_long" or wanted == "time_short") then + return "%X" + end + return "%x %X" end -- trust evaluation hooks @@ -464,9 +472,9 @@ mergers.meld = { mergers.meld = { cmd = function (tbl) io.write (string.format("\nWARNING: 'meld' was chosen to perform ".. - "an external 3-way merge.\n".. - "You must merge all changes to the ".. - "*CENTER* file.")) + "an external 3-way merge.\n".. + "You must merge all changes to the ".. + "*CENTER* file.")) local path = "meld" local ret = execute(path, tbl.lfile, tbl.afile, tbl.rfile) if (ret ~= 0) then @@ -513,9 +521,9 @@ mergers.vim = { end io.write (string.format("\nWARNING: 'vim' was chosen to perform ".. - "an external 3-way merge.\n".. - "You must merge all changes to the ".. - "*LEFT* file.\n")) + "an external 3-way merge.\n".. + "You must merge all changes to the ".. + "*LEFT* file.\n")) local vim if os.getenv ("DISPLAY") ~= nil and program_exists_in_path ("gvim") then ============================================================ --- vocab.hh 61bc19598cbf8668c41855cfa0841af03079be30 +++ vocab.hh e572a01a4185be56e57287b83efdc44061c2baef @@ -99,6 +99,18 @@ enum diff_type external_diff }; +// determines which kind of date format we request for date formatting +// only a subset of the following options are currently actually used +enum date_format_spec +{ + date_long, + date_short, + time_long, + time_short, + date_time_long, + date_time_short +}; + // do these belong here? inline bool null_id(id const & i)