mirror of
https://https.git.savannah.gnu.org/git/gettext.git
synced 2026-01-26 15:39:11 +00:00
xgettext: Add an option to opt-out of the use of git for the POT-Creation-Date.
Reported by Serhii Tereshchenko at <https://savannah.gnu.org/bugs/?66865>. * autogen.sh (GNULIB_MODULES_TOOLS_FOR_SRC): Add stat-time. * gettext-tools/src/xgettext.c: Include stat-time.h. (xgettext_no_git): New variable. (long_options): Add option '--no-git'. (main): Handle the option --no-git. (usage): Document the option --no-git. (struct accumulator): New type, copied from gnulib/lib/vc-mtime.c. (accumulate): New function, copied from gnulib/lib/vc-mtime.c. (max_mtime_without_git): New function, based on gnulib/lib/vc-mtime.c. (finalize_header): Conditionally invoke max_mtime_without_git instead of max_vc_mtime. * gettext-tools/doc/xgettext.texi: Document the option --no-git. * NEWS: Mention the change.
This commit is contained in:
parent
8ce6f7d45e
commit
59782d1f8c
3
NEWS
3
NEWS
@ -3,7 +3,8 @@ Version 0.24.1 - May 2025
|
||||
* Bug fixes:
|
||||
- Fix bad interactions between autoreconf and autopoint.
|
||||
- xgettext: Creating the POT file of a package under Git version control
|
||||
is now faster.
|
||||
is now faster. Also, the use of Git can be turned off by specifying
|
||||
the option '--no-git'.
|
||||
|
||||
Version 0.24 - February 2025
|
||||
|
||||
|
||||
@ -238,6 +238,7 @@ if ! $skip_gnulib; then
|
||||
sigpipe
|
||||
sigprocmask
|
||||
spawn-pipe
|
||||
stat-time
|
||||
stdio-h
|
||||
stdlib-h
|
||||
stpcpy
|
||||
|
||||
@ -690,6 +690,25 @@ options at different times are guaranteed to produce the same results.
|
||||
Note that using this option will lead to an error if the resulting file
|
||||
would not entirely be in ASCII.
|
||||
|
||||
@item --no-git
|
||||
@opindex --no-git@r{, @code{xgettext} option}
|
||||
Don't use the @code{git} program
|
||||
to produce a reproducible @samp{POT-Creation-Date} field in the output.
|
||||
|
||||
Use this option, for speed, if
|
||||
your project has a very long @code{Git} history
|
||||
(hundreds of thousands of commits)
|
||||
or you are specifying thousands of input files.
|
||||
|
||||
By default, @code{xgettext} determines the @samp{POT-Creation-Date} as
|
||||
the maximum version-controlled modification time
|
||||
among all the given input files.
|
||||
With this option, you can specify that it should instead use
|
||||
the maximum modification time (time stamp on disk)
|
||||
among all the given input files.
|
||||
|
||||
By ``version control'', here we mean the @code{Git} version control system.
|
||||
|
||||
@item --copyright-holder=@var{string}
|
||||
@opindex --copyright-holder@r{, @code{xgettext} option}
|
||||
Set the copyright holder in the output. @var{string} should be the
|
||||
|
||||
@ -80,6 +80,7 @@
|
||||
#include "msgl-ascii.h"
|
||||
#include "msgl-ofn.h"
|
||||
#include "xg-check.h"
|
||||
#include "stat-time.h"
|
||||
#include "vc-mtime.h"
|
||||
#include "po-time.h"
|
||||
#include "msgl-header.h"
|
||||
@ -179,6 +180,9 @@ static catalog_output_format_ty output_syntax = &output_format_po;
|
||||
/* If nonzero omit header with information about this run. */
|
||||
int xgettext_omit_header;
|
||||
|
||||
/* If nonzero, don't use 'git' to compute a reproducible POT-Creation-Date. */
|
||||
static int xgettext_no_git;
|
||||
|
||||
/* Be more verbose. */
|
||||
int verbose = 0;
|
||||
|
||||
@ -271,6 +275,7 @@ static const struct option long_options[] =
|
||||
{ "msgstr-prefix", optional_argument, NULL, 'm' },
|
||||
{ "msgstr-suffix", optional_argument, NULL, 'M' },
|
||||
{ "no-escape", no_argument, NULL, 'e' },
|
||||
{ "no-git", no_argument, NULL, CHAR_MAX + 23 },
|
||||
{ "no-location", no_argument, NULL, CHAR_MAX + 16 },
|
||||
{ "no-wrap", no_argument, NULL, CHAR_MAX + 4 },
|
||||
{ "omit-header", no_argument, &xgettext_omit_header, 1 },
|
||||
@ -706,6 +711,10 @@ main (int argc, char *argv[])
|
||||
string_list_append (&files_for_vc_mtime, optarg);
|
||||
break;
|
||||
|
||||
case CHAR_MAX + 23: /* --no-git */
|
||||
xgettext_no_git = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
usage (EXIT_FAILURE);
|
||||
/* NOTREACHED */
|
||||
@ -1263,6 +1272,10 @@ Output details:\n"));
|
||||
printf (_("\
|
||||
--omit-header don't write header with 'msgid \"\"' entry\n"));
|
||||
printf (_("\
|
||||
--no-git don't use the git program to produce a\n\
|
||||
reproducible 'POT-Creation-Date' field in the\n\
|
||||
output.\n"));
|
||||
printf (_("\
|
||||
--copyright-holder=STRING set copyright holder in output\n"));
|
||||
printf (_("\
|
||||
--foreign-user omit FSF copyright in output for foreign user\n"));
|
||||
@ -2167,6 +2180,59 @@ FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.\n");
|
||||
return mp;
|
||||
}
|
||||
|
||||
/* Accumulating mtimes. */
|
||||
struct accumulator
|
||||
{
|
||||
bool has_some_mtimes;
|
||||
struct timespec max_of_mtimes;
|
||||
};
|
||||
|
||||
static void
|
||||
accumulate (struct accumulator *accu, struct timespec mtime)
|
||||
{
|
||||
if (accu->has_some_mtimes)
|
||||
{
|
||||
/* Compute the maximum of accu->max_of_mtimes and mtime. */
|
||||
if (accu->max_of_mtimes.tv_sec < mtime.tv_sec
|
||||
|| (accu->max_of_mtimes.tv_sec == mtime.tv_sec
|
||||
&& accu->max_of_mtimes.tv_nsec < mtime.tv_nsec))
|
||||
accu->max_of_mtimes = mtime;
|
||||
}
|
||||
else
|
||||
{
|
||||
accu->max_of_mtimes = mtime;
|
||||
accu->has_some_mtimes = true;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
max_mtime_without_git (struct timespec *max_of_mtimes,
|
||||
size_t nfiles, const char * const *filenames)
|
||||
{
|
||||
if (nfiles == 0)
|
||||
/* Invalid argument. */
|
||||
abort ();
|
||||
|
||||
struct accumulator accu = { false };
|
||||
|
||||
/* Always use the file's time stamp. */
|
||||
for (size_t n = 0; n < nfiles; n++)
|
||||
{
|
||||
struct stat statbuf;
|
||||
if (stat (filenames[n], &statbuf) < 0)
|
||||
return -1;
|
||||
|
||||
struct timespec mtime = get_stat_mtime (&statbuf);
|
||||
accumulate (&accu, mtime);
|
||||
}
|
||||
|
||||
/* Since nfiles > 0, we must have accumulated at least one mtime. */
|
||||
if (!accu.has_some_mtimes)
|
||||
abort ();
|
||||
*max_of_mtimes = accu.max_of_mtimes;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
finalize_header (msgdomain_list_ty *mdlp)
|
||||
{
|
||||
@ -2175,8 +2241,8 @@ finalize_header (msgdomain_list_ty *mdlp)
|
||||
time_t stamp;
|
||||
struct timespec max_of_mtimes;
|
||||
if (files_for_vc_mtime.nitems > 0
|
||||
&& max_vc_mtime (&max_of_mtimes,
|
||||
files_for_vc_mtime.nitems, files_for_vc_mtime.item)
|
||||
&& (xgettext_no_git ? max_mtime_without_git : max_vc_mtime)
|
||||
(&max_of_mtimes, files_for_vc_mtime.nitems, files_for_vc_mtime.item)
|
||||
== 0)
|
||||
/* Use the maximum of the encountered mtimes. */
|
||||
stamp = max_of_mtimes.tv_sec;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user