* [PATCH v3 12/14] i18n: send-email: mark warnings and errors for translation
From: Vasco Almeida @ 2016-10-05 17:21 UTC (permalink / raw)
To: git
Cc: Vasco Almeida, Jiang Xin, Ævar Arnfjörð Bjarmason,
Jean-Noël AVILA, Jakub Narębski, David Aguilar,
Junio C Hamano
In-Reply-To: <20161005172110.30801-1-vascomalmeida@sapo.pt>
Mark warnings, errors and other messages for translation.
Signed-off-by: Vasco Almeida <vascomalmeida@sapo.pt>
---
git-send-email.perl | 34 +++++++++++++++++-----------------
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/git-send-email.perl b/git-send-email.perl
index 78eb59b..982c6c0 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -118,20 +118,20 @@ sub format_2822_time {
my $localmin = $localtm[1] + $localtm[2] * 60;
my $gmtmin = $gmttm[1] + $gmttm[2] * 60;
if ($localtm[0] != $gmttm[0]) {
- die "local zone differs from GMT by a non-minute interval\n";
+ die __("local zone differs from GMT by a non-minute interval\n");
}
if ((($gmttm[6] + 1) % 7) == $localtm[6]) {
$localmin += 1440;
} elsif ((($gmttm[6] - 1) % 7) == $localtm[6]) {
$localmin -= 1440;
} elsif ($gmttm[6] != $localtm[6]) {
- die "local time offset greater than or equal to 24 hours\n";
+ die __("local time offset greater than or equal to 24 hours\n");
}
my $offset = $localmin - $gmtmin;
my $offhour = $offset / 60;
my $offmin = abs($offset % 60);
if (abs($offhour) >= 24) {
- die ("local time offset greater than or equal to 24 hours\n");
+ die __("local time offset greater than or equal to 24 hours\n");
}
return sprintf("%s, %2d %s %d %02d:%02d:%02d %s%02d%02d",
@@ -199,13 +199,13 @@ sub do_edit {
map {
system('sh', '-c', $editor.' "$@"', $editor, $_);
if (($? & 127) || ($? >> 8)) {
- die("the editor exited uncleanly, aborting everything");
+ die(__("the editor exited uncleanly, aborting everything"));
}
} @_;
} else {
system('sh', '-c', $editor.' "$@"', $editor, @_);
if (($? & 127) || ($? >> 8)) {
- die("the editor exited uncleanly, aborting everything");
+ die(__("the editor exited uncleanly, aborting everything"));
}
}
}
@@ -299,7 +299,7 @@ my $help;
my $rc = GetOptions("h" => \$help,
"dump-aliases" => \$dump_aliases);
usage() unless $rc;
-die "--dump-aliases incompatible with other options\n"
+die __("--dump-aliases incompatible with other options\n")
if !$help and $dump_aliases and @ARGV;
$rc = GetOptions(
"sender|from=s" => \$sender,
@@ -362,7 +362,7 @@ unless ($rc) {
usage();
}
-die "Cannot run git format-patch from outside a repository\n"
+die __("Cannot run git format-patch from outside a repository\n")
if $format_patch and not $repo;
# Now, let's fill any that aren't set in with defaults:
@@ -617,7 +617,7 @@ while (defined(my $f = shift @ARGV)) {
}
if (@rev_list_opts) {
- die "Cannot run git format-patch from outside a repository\n"
+ die __("Cannot run git format-patch from outside a repository\n")
unless $repo;
push @files, $repo->command('format-patch', '-o', tempdir(CLEANUP => 1), @rev_list_opts);
}
@@ -638,7 +638,7 @@ if (@files) {
print $_,"\n" for (@files);
}
} else {
- print STDERR "\nNo patch files specified!\n\n";
+ print STDERR __("\nNo patch files specified!\n\n");
usage();
}
@@ -730,7 +730,7 @@ EOT
$sender = $1;
next;
} elsif (/^(?:To|Cc|Bcc):/i) {
- print "To/Cc/Bcc fields are not interpreted yet, they have been ignored\n";
+ print __("To/Cc/Bcc fields are not interpreted yet, they have been ignored\n");
next;
}
print $c2 $_;
@@ -739,7 +739,7 @@ EOT
close $c2;
if ($summary_empty) {
- print "Summary email is empty, skipping it\n";
+ print __("Summary email is empty, skipping it\n");
$compose = -1;
}
} elsif ($annotate) {
@@ -1314,7 +1314,7 @@ Message-Id: $message_id
$_ = ask(__("Send this email? ([y]es|[n]o|[q]uit|[a]ll): "),
valid_re => qr/^(?:yes|y|no|n|quit|q|all|a)/i,
default => $ask_default);
- die "Send this email reply required" unless defined $_;
+ die __("Send this email reply required") unless defined $_;
if (/^n/i) {
return 0;
} elsif (/^q/i) {
@@ -1340,7 +1340,7 @@ Message-Id: $message_id
} else {
if (!defined $smtp_server) {
- die "The required SMTP server is not properly defined."
+ die __("The required SMTP server is not properly defined.")
}
if ($smtp_encryption eq 'ssl') {
@@ -1425,10 +1425,10 @@ Message-Id: $message_id
}
print $header, "\n";
if ($smtp) {
- print "Result: ", $smtp->code, ' ',
+ print __("Result: "), $smtp->code, ' ',
($smtp->message =~ /\n([^\n]+\n)$/s), "\n";
} else {
- print "Result: OK\n";
+ print __("Result: OK\n");
}
}
@@ -1701,7 +1701,7 @@ sub apply_transfer_encoding {
$message = MIME::Base64::decode($message)
if ($from eq 'base64');
- die "cannot send message as 7bit"
+ die __("cannot send message as 7bit")
if ($to eq '7bit' and $message =~ /[^[:ascii:]]/);
return $message
if ($to eq '7bit' or $to eq '8bit');
@@ -1709,7 +1709,7 @@ sub apply_transfer_encoding {
if ($to eq 'quoted-printable');
return MIME::Base64::encode($message, "\n")
if ($to eq 'base64');
- die "invalid transfer encoding";
+ die __("invalid transfer encoding");
}
sub unique_email_list {
--
2.7.4
^ permalink raw reply related
* [PATCH v3 11/14] i18n: send-email: mark strings for translation
From: Vasco Almeida @ 2016-10-05 17:21 UTC (permalink / raw)
To: git
Cc: Vasco Almeida, Jiang Xin, Ævar Arnfjörð Bjarmason,
Jean-Noël AVILA, Jakub Narębski, David Aguilar,
Junio C Hamano
In-Reply-To: <20161005172110.30801-1-vascomalmeida@sapo.pt>
Mark strings often displayed to the user for translation.
Signed-off-by: Vasco Almeida <vascomalmeida@sapo.pt>
---
git-send-email.perl | 52 ++++++++++++++++++++++++++++++----------------------
1 file changed, 30 insertions(+), 22 deletions(-)
diff --git a/git-send-email.perl b/git-send-email.perl
index da81be4..78eb59b 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -28,6 +28,7 @@ use File::Temp qw/ tempdir tempfile /;
use File::Spec::Functions qw(catfile);
use Error qw(:try);
use Git;
+use Git::I18N;
Getopt::Long::Configure qw/ pass_through /;
@@ -797,12 +798,12 @@ foreach my $f (@files) {
}
if (!defined $auto_8bit_encoding && scalar %broken_encoding) {
- print "The following files are 8bit, but do not declare " .
- "a Content-Transfer-Encoding.\n";
+ print __("The following files are 8bit, but do not declare " .
+ "a Content-Transfer-Encoding.\n");
foreach my $f (sort keys %broken_encoding) {
print " $f\n";
}
- $auto_8bit_encoding = ask("Which 8bit encoding should I declare [UTF-8]? ",
+ $auto_8bit_encoding = ask(__("Which 8bit encoding should I declare [UTF-8]? "),
valid_re => qr/.{4}/, confirm_only => 1,
default => "UTF-8");
}
@@ -829,7 +830,7 @@ if (defined $sender) {
# But it's a no-op to run sanitize_address on an already sanitized address.
$sender = sanitize_address($sender);
-my $to_whom = "To whom should the emails be sent (if anyone)?";
+my $to_whom = __("To whom should the emails be sent (if anyone)?");
my $prompting = 0;
if (!@initial_to && !defined $to_cmd) {
my $to = ask("$to_whom ",
@@ -859,7 +860,7 @@ sub expand_one_alias {
if ($thread && !defined $initial_reply_to && $prompting) {
$initial_reply_to = ask(
- "Message-ID to be used as In-Reply-To for the first email (if any)? ",
+ __("Message-ID to be used as In-Reply-To for the first email (if any)? "),
default => "",
valid_re => qr/\@.*\./, confirm_only => 1);
}
@@ -918,7 +919,10 @@ sub validate_address {
my $address = shift;
while (!extract_valid_address($address)) {
print STDERR "error: unable to extract a valid address from: $address\n";
- $_ = ask("What to do with this address? ([q]uit|[d]rop|[e]dit): ",
+ # TRANSLATORS: Make sure to include [q] [d] [e] in your
+ # translation. The program will only accept English input
+ # at this point.
+ $_ = ask(__("What to do with this address? ([q]uit|[d]rop|[e]dit): "),
valid_re => qr/^(?:quit|q|drop|d|edit|e)/i,
default => 'q');
if (/^d/i) {
@@ -1293,17 +1297,21 @@ Message-Id: $message_id
if ($needs_confirm eq "inform") {
$confirm_unconfigured = 0; # squelch this message for the rest of this run
$ask_default = "y"; # assume yes on EOF since user hasn't explicitly asked for confirmation
- print " The Cc list above has been expanded by additional\n";
- print " addresses found in the patch commit message. By default\n";
- print " send-email prompts before sending whenever this occurs.\n";
- print " This behavior is controlled by the sendemail.confirm\n";
- print " configuration setting.\n";
- print "\n";
- print " For additional information, run 'git send-email --help'.\n";
- print " To retain the current behavior, but squelch this message,\n";
- print " run 'git config --global sendemail.confirm auto'.\n\n";
+ print __(
+" The Cc list above has been expanded by additional
+ addresses found in the patch commit message. By default
+ send-email prompts before sending whenever this occurs.
+ This behavior is controlled by the sendemail.confirm
+ configuration setting.
+
+ For additional information, run 'git send-email --help'.
+ To retain the current behavior, but squelch this message,
+ run 'git config --global sendemail.confirm auto'."), "\n\n";
}
- $_ = ask("Send this email? ([y]es|[n]o|[q]uit|[a]ll): ",
+ # TRANSLATORS: Make sure to include [y] [n] [q] [a] in your
+ # translation. The program will only accept English input
+ # at this point.
+ $_ = ask(__("Send this email? ([y]es|[n]o|[q]uit|[a]ll): "),
valid_re => qr/^(?:yes|y|no|n|quit|q|all|a)/i,
default => $ask_default);
die "Send this email reply required" unless defined $_;
@@ -1405,7 +1413,7 @@ Message-Id: $message_id
if ($quiet) {
printf (($dry_run ? "Dry-" : "")."Sent %s\n", $subject);
} else {
- print (($dry_run ? "Dry-" : "")."OK. Log says:\n");
+ print($dry_run ? __("Dry-OK. Log says:\n") : __("OK. Log says:\n"));
if (!file_name_is_absolute($smtp_server)) {
print "Server: $smtp_server\n";
print "MAIL FROM:<$raw_from>\n";
@@ -1480,13 +1488,13 @@ foreach my $t (@files) {
$sauthor = sanitize_address($author);
next if $suppress_cc{'author'};
next if $suppress_cc{'self'} and $sauthor eq $sender;
- printf("(mbox) Adding cc: %s from line '%s'\n",
+ printf(__("(mbox) Adding cc: %s from line '%s'\n"),
$1, $_) unless $quiet;
push @cc, $1;
}
elsif (/^To:\s+(.*)$/i) {
foreach my $addr (parse_address_line($1)) {
- printf("(mbox) Adding to: %s from line '%s'\n",
+ printf(__("(mbox) Adding to: %s from line '%s'\n"),
$addr, $_) unless $quiet;
push @to, $addr;
}
@@ -1500,7 +1508,7 @@ foreach my $t (@files) {
} else {
next if ($suppress_cc{'cc'});
}
- printf("(mbox) Adding cc: %s from line '%s'\n",
+ printf(__("(mbox) Adding cc: %s from line '%s'\n"),
$addr, $_) unless $quiet;
push @cc, $addr;
}
@@ -1534,7 +1542,7 @@ foreach my $t (@files) {
# So let's support that, too.
$input_format = 'lots';
if (@cc == 0 && !$suppress_cc{'cc'}) {
- printf("(non-mbox) Adding cc: %s from line '%s'\n",
+ printf(__("(non-mbox) Adding cc: %s from line '%s'\n"),
$_, $_) unless $quiet;
push @cc, $_;
} elsif (!defined $subject) {
@@ -1557,7 +1565,7 @@ foreach my $t (@files) {
next if $suppress_cc{'bodycc'} and $what =~ /Cc/i;
}
push @cc, $c;
- printf("(body) Adding cc: %s from line '%s'\n",
+ printf(__("(body) Adding cc: %s from line '%s'\n"),
$c, $_) unless $quiet;
}
}
--
2.7.4
^ permalink raw reply related
* [PATCH v3 10/14] i18n: add--interactive: mark status words for translation
From: Vasco Almeida @ 2016-10-05 17:21 UTC (permalink / raw)
To: git
Cc: Vasco Almeida, Jiang Xin, Ævar Arnfjörð Bjarmason,
Jean-Noël AVILA, Jakub Narębski, David Aguilar,
Junio C Hamano
In-Reply-To: <20161005172110.30801-1-vascomalmeida@sapo.pt>
Mark words 'nothing', 'unchanged' and 'binary' used to display what has
been staged or not, in "git add -i" status command.
Signed-off-by: Vasco Almeida <vascomalmeida@sapo.pt>
---
git-add--interactive.perl | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index e81939f..0b4a27c 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -295,7 +295,7 @@ sub list_modified {
my ($change, $bin);
$file = unquote_path($file);
if ($add eq '-' && $del eq '-') {
- $change = 'binary';
+ $change = __('binary');
$bin = 1;
}
else {
@@ -304,7 +304,7 @@ sub list_modified {
$data{$file} = {
INDEX => $change,
BINARY => $bin,
- FILE => 'nothing',
+ FILE => __('nothing'),
}
}
elsif (($adddel, $file) =
@@ -320,7 +320,7 @@ sub list_modified {
$file = unquote_path($file);
my ($change, $bin);
if ($add eq '-' && $del eq '-') {
- $change = 'binary';
+ $change = __('binary');
$bin = 1;
}
else {
@@ -340,7 +340,7 @@ sub list_modified {
$file = unquote_path($2);
if (!exists $data{$file}) {
$data{$file} = +{
- INDEX => 'unchanged',
+ INDEX => __('unchanged'),
BINARY => 0,
};
}
@@ -355,10 +355,10 @@ sub list_modified {
if ($only) {
if ($only eq 'index-only') {
- next if ($it->{INDEX} eq 'unchanged');
+ next if ($it->{INDEX} eq __('unchanged'));
}
if ($only eq 'file-only') {
- next if ($it->{FILE} eq 'nothing');
+ next if ($it->{FILE} eq __('nothing'));
}
}
push @return, +{
--
2.7.4
^ permalink raw reply related
* [PATCH v3 09/14] i18n: add--interactive: remove %patch_modes entries
From: Vasco Almeida @ 2016-10-05 17:21 UTC (permalink / raw)
To: git
Cc: Vasco Almeida, Jiang Xin, Ævar Arnfjörð Bjarmason,
Jean-Noël AVILA, Jakub Narębski, David Aguilar,
Junio C Hamano
In-Reply-To: <20161005172110.30801-1-vascomalmeida@sapo.pt>
Remove unnecessary entries from %patch_modes. After the i18n conversion,
these entries are not used anymore.
Signed-off-by: Vasco Almeida <vascomalmeida@sapo.pt>
---
git-add--interactive.perl | 21 ---------------------
1 file changed, 21 deletions(-)
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index 5356d5a..e81939f 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -106,9 +106,6 @@ my %patch_modes = (
DIFF => 'diff-files -p',
APPLY => sub { apply_patch 'apply --cached', @_; },
APPLY_CHECK => 'apply --cached',
- VERB => 'Stage',
- TARGET => '',
- PARTICIPLE => 'staging',
FILTER => 'file-only',
IS_REVERSE => 0,
},
@@ -116,9 +113,6 @@ my %patch_modes = (
DIFF => 'diff-index -p HEAD',
APPLY => sub { apply_patch 'apply --cached', @_; },
APPLY_CHECK => 'apply --cached',
- VERB => 'Stash',
- TARGET => '',
- PARTICIPLE => 'stashing',
FILTER => undef,
IS_REVERSE => 0,
},
@@ -126,9 +120,6 @@ my %patch_modes = (
DIFF => 'diff-index -p --cached',
APPLY => sub { apply_patch 'apply -R --cached', @_; },
APPLY_CHECK => 'apply -R --cached',
- VERB => 'Unstage',
- TARGET => '',
- PARTICIPLE => 'unstaging',
FILTER => 'index-only',
IS_REVERSE => 1,
},
@@ -136,9 +127,6 @@ my %patch_modes = (
DIFF => 'diff-index -R -p --cached',
APPLY => sub { apply_patch 'apply --cached', @_; },
APPLY_CHECK => 'apply --cached',
- VERB => 'Apply',
- TARGET => ' to index',
- PARTICIPLE => 'applying',
FILTER => 'index-only',
IS_REVERSE => 0,
},
@@ -146,9 +134,6 @@ my %patch_modes = (
DIFF => 'diff-files -p',
APPLY => sub { apply_patch 'apply -R', @_; },
APPLY_CHECK => 'apply -R',
- VERB => 'Discard',
- TARGET => ' from worktree',
- PARTICIPLE => 'discarding',
FILTER => 'file-only',
IS_REVERSE => 1,
},
@@ -156,9 +141,6 @@ my %patch_modes = (
DIFF => 'diff-index -p',
APPLY => sub { apply_patch_for_checkout_commit '-R', @_ },
APPLY_CHECK => 'apply -R',
- VERB => 'Discard',
- TARGET => ' from index and worktree',
- PARTICIPLE => 'discarding',
FILTER => undef,
IS_REVERSE => 1,
},
@@ -166,9 +148,6 @@ my %patch_modes = (
DIFF => 'diff-index -R -p',
APPLY => sub { apply_patch_for_checkout_commit '', @_ },
APPLY_CHECK => 'apply',
- VERB => 'Apply',
- TARGET => ' to index and worktree',
- PARTICIPLE => 'applying',
FILTER => undef,
IS_REVERSE => 0,
},
--
2.7.4
^ permalink raw reply related
* [PATCH v3 08/14] i18n: add--interactive: mark edit_hunk_manually message for translation
From: Vasco Almeida @ 2016-10-05 17:21 UTC (permalink / raw)
To: git
Cc: Vasco Almeida, Jiang Xin, Ævar Arnfjörð Bjarmason,
Jean-Noël AVILA, Jakub Narębski, David Aguilar,
Junio C Hamano
In-Reply-To: <20161005172110.30801-1-vascomalmeida@sapo.pt>
Mark message of edit_hunk_manually displayed in the editing file when
user chooses 'e' option. The message had to be unfolded to allow
translation of the $participle verb.
Some messages end up being exactly the same for some uses cases, but
left it for easier change in the future, e.g., wanting to change wording
of one particular use case.
Signed-off-by: Vasco Almeida <vascomalmeida@sapo.pt>
---
git-add--interactive.perl | 45 ++++++++++++++++++++++++++++++++++-----------
1 file changed, 34 insertions(+), 11 deletions(-)
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index 35967fe..5356d5a 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -1058,6 +1058,30 @@ sub color_diff {
} @_;
}
+my %edit_hunk_manually_modes = (
+ stage => __(
+"# If the patch applies cleanly, the edited hunk will immediately be
+# marked for staging."),
+ stash => __(
+"# If the patch applies cleanly, the edited hunk will immediately be
+# marked for stashing."),
+ reset_head => __(
+"# If the patch applies cleanly, the edited hunk will immediately be
+# marked for unstaging."),
+ reset_nothead => __(
+"# If the patch applies cleanly, the edited hunk will immediately be
+# marked for applying."),
+ checkout_index => __(
+"# If the patch applies cleanly, the edited hunk will immediately be
+# marked for discarding"),
+ checkout_head => __(
+"# If the patch applies cleanly, the edited hunk will immediately be
+# marked for discarding."),
+ checkout_nothead => __(
+"# If the patch applies cleanly, the edited hunk will immediately be
+# marked for applying."),
+);
+
sub edit_hunk_manually {
my ($oldtext) = @_;
@@ -1065,22 +1089,21 @@ sub edit_hunk_manually {
my $fh;
open $fh, '>', $hunkfile
or die sprintf(__("failed to open hunk edit file for writing: %s"), $!);
- print $fh "# Manual hunk edit mode -- see bottom for a quick guide\n";
+ print $fh __("# Manual hunk edit mode -- see bottom for a quick guide\n");
print $fh @$oldtext;
- my $participle = $patch_mode_flavour{PARTICIPLE};
my $is_reverse = $patch_mode_flavour{IS_REVERSE};
my ($remove_plus, $remove_minus) = $is_reverse ? ('-', '+') : ('+', '-');
- print $fh <<EOF;
-# ---
-# To remove '$remove_minus' lines, make them ' ' lines (context).
-# To remove '$remove_plus' lines, delete them.
+ print $fh sprintf(__(
+"# ---
+# To remove '%s' lines, make them ' ' lines (context).
+# To remove '%s' lines, delete them.
# Lines starting with # will be removed.
-#
-# If the patch applies cleanly, the edited hunk will immediately be
-# marked for $participle. If it does not apply cleanly, you will be given
+#\n"), $remove_minus, $remove_plus),
+$edit_hunk_manually_modes{$patch_mode}, __(
+# TRANSLATORS: 'it' refers to the patch mentioned in the previous messages.
+" If it does not apply cleanly, you will be given
# an opportunity to edit again. If all lines of the hunk are removed,
-# then the edit is aborted and the hunk is left unchanged.
-EOF
+# then the edit is aborted and the hunk is left unchanged.\n");
close $fh;
chomp(my $editor = run_cmd_pipe(qw(git var GIT_EDITOR)));
--
2.7.4
^ permalink raw reply related
* [PATCH v3 07/14] i18n: add--interactive: i18n of help_patch_cmd
From: Vasco Almeida @ 2016-10-05 17:21 UTC (permalink / raw)
To: git
Cc: Vasco Almeida, Jiang Xin, Ævar Arnfjörð Bjarmason,
Jean-Noël AVILA, Jakub Narębski, David Aguilar,
Junio C Hamano
In-Reply-To: <20161005172110.30801-1-vascomalmeida@sapo.pt>
Mark help message of help_patch_cmd for translation. The message must
be unfolded to be free of variables so we can have high quality
translations.
Signed-off-by: Vasco Almeida <vascomalmeida@sapo.pt>
---
git-add--interactive.perl | 54 ++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 46 insertions(+), 8 deletions(-)
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index c8d5093..35967fe 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -1189,15 +1189,53 @@ sub edit_hunk_loop {
}
}
+my %help_patch_modes = (
+ stage => __(
+"y - stage this hunk
+n - do not stage this hunk
+q - quit; do not stage this hunk or any of the remaining ones
+a - stage this hunk and all later hunks in the file
+d - do not stage this hunk or any of the later hunks in the file"),
+ stash => __(
+"y - stash this hunk
+n - do not stash this hunk
+q - quit; do not stash this hunk or any of the remaining ones
+a - stash this hunk and all later hunks in the file
+d - do not stash this hunk or any of the later hunks in the file"),
+ reset_head => __(
+"y - unstage this hunk
+n - do not unstage this hunk
+q - quit; do not unstage this hunk or any of the remaining ones
+a - unstage this hunk and all later hunks in the file
+d - do not unstage this hunk or any of the later hunks in the file"),
+ reset_nothead => __(
+"y - apply this hunk to index
+n - do not apply this hunk to index
+q - quit; do not apply this hunk or any of the remaining ones
+a - apply this hunk and all later hunks in the file
+d - do not apply this hunk or any of the later hunks in the file"),
+ checkout_index => __(
+"y - discard this hunk from worktree
+n - do not discard this hunk from worktree
+q - quit; do not discard this hunk or any of the remaining ones
+a - discard this hunk and all later hunks in the file
+d - do not discard this hunk or any of the later hunks in the file"),
+ checkout_head => __(
+"y - discard this hunk from index and worktree
+n - do not discard this hunk from index and worktree
+q - quit; do not discard this hunk or any of the remaining ones
+a - discard this hunk and all later hunks in the file
+d - do not discard this hunk or any of the later hunks in the file"),
+ checkout_nothead => __(
+"y - apply this hunk to index and worktree
+n - do not apply this hunk to index and worktree
+q - quit; do not apply this hunk or any of the remaining ones
+a - apply this hunk and all later hunks in the file
+d - do not apply this hunk or any of the later hunks in the file"),
+);
+
sub help_patch_cmd {
- my $verb = lc $patch_mode_flavour{VERB};
- my $target = $patch_mode_flavour{TARGET};
- print colored $help_color, <<EOF ;
-y - $verb this hunk$target
-n - do not $verb this hunk$target
-q - quit; do not $verb this hunk or any of the remaining ones
-a - $verb this hunk and all later hunks in the file
-d - do not $verb this hunk or any of the later hunks in the file
+ print colored $help_color, $help_patch_modes{$patch_mode}, "\n", __ <<EOF ;
g - select a hunk to go to
/ - search for a hunk matching the given regex
j - leave this hunk undecided, see next undecided hunk
--
2.7.4
^ permalink raw reply related
* [PATCH v3 06/14] i18n: add--interactive: mark patch prompt for translation
From: Vasco Almeida @ 2016-10-05 17:21 UTC (permalink / raw)
To: git
Cc: Vasco Almeida, Jiang Xin, Ævar Arnfjörð Bjarmason,
Jean-Noël AVILA, Jakub Narębski, David Aguilar,
Junio C Hamano
In-Reply-To: <20161005172110.30801-1-vascomalmeida@sapo.pt>
Mark prompt message assembled in place for translation, unfolding each
use case for each entry in the %patch_modes hash table.
Previously, this script relied on whether $patch_mode was set to run the
command patch_update_cmd() or show status and loop the main loop. Now,
it uses $cmd to indicate we must run patch_update_cmd() and $patch_mode
is used to tell which flavor of the %patch_modes are we on. This is
introduced in order to be able to mark and unfold the message prompt
knowing in which context we are.
The tracking of context was done previously by point %patch_mode_flavour
hash table to the correct entry of %patch_modes, focusing only on value
of %patch_modes. Now, we are also interested in the key ('staged',
'stash', 'checkout_head', ...).
Signed-off-by: Vasco Almeida <vascomalmeida@sapo.pt>
---
git-add--interactive.perl | 54 ++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 46 insertions(+), 8 deletions(-)
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index 6bbde2d..c8d5093 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -93,6 +93,7 @@ sub colored {
}
# command line options
+my $cmd;
my $patch_mode;
my $patch_mode_revision;
@@ -173,7 +174,8 @@ my %patch_modes = (
},
);
-my %patch_mode_flavour = %{$patch_modes{stage}};
+$patch_mode = 'stage';
+my %patch_mode_flavour = %{$patch_modes{$patch_mode}};
sub run_cmd_pipe {
if ($^O eq 'MSWin32') {
@@ -1311,6 +1313,44 @@ sub display_hunks {
return $i;
}
+my %patch_update_prompt_modes = (
+ stage => {
+ mode => __("Stage mode change [y,n,q,a,d,/%s,?]? "),
+ deletion => __("Stage deletion [y,n,q,a,d,/%s,?]? "),
+ hunk => __("Stage this hunk [y,n,q,a,d,/%s,?]? "),
+ },
+ stash => {
+ mode => __("Stash mode change [y,n,q,a,d,/%s,?]? "),
+ deletion => __("Stash deletion [y,n,q,a,d,/%s,?]? "),
+ hunk => __("Stash this hunk [y,n,q,a,d,/%s,?]? "),
+ },
+ reset_head => {
+ mode => __("Unstage mode change [y,n,q,a,d,/%s,?]? "),
+ deletion => __("Unstage deletion [y,n,q,a,d,/%s,?]? "),
+ hunk => __("Unstage this hunk [y,n,q,a,d,/%s,?]? "),
+ },
+ reset_nothead => {
+ mode => __("Apply mode change to index [y,n,q,a,d,/%s,?]? "),
+ deletion => __("Apply deletion to index [y,n,q,a,d,/%s,?]? "),
+ hunk => __("Apply this hunk to index [y,n,q,a,d,/%s,?]? "),
+ },
+ checkout_index => {
+ mode => __("Discard mode change from worktree [y,n,q,a,d,/%s,?]? "),
+ deletion => __("Discard deletion from worktree [y,n,q,a,d,/%s,?]? "),
+ hunk => __("Discard this hunk from worktree [y,n,q,a,d,/%s,?]? "),
+ },
+ checkout_head => {
+ mode => __("Discard mode change from index and worktree [y,n,q,a,d,/%s,?]? "),
+ deletion => __("Discard deletion from index and worktree [y,n,q,a,d,/%s,?]? "),
+ hunk => __("Discard this hunk from index and worktree [y,n,q,a,d,/%s,?]? "),
+ },
+ checkout_nothead => {
+ mode => __("Apply mode change to index and worktree [y,n,q,a,d,/%s,?]? "),
+ deletion => __("Apply deletion to index and worktree [y,n,q,a,d,/%s,?]? "),
+ hunk => __("Apply this hunk to index and worktree [y,n,q,a,d,/%s,?]? "),
+ },
+);
+
sub patch_update_file {
my $quit = 0;
my ($ix, $num);
@@ -1383,12 +1423,9 @@ sub patch_update_file {
for (@{$hunk[$ix]{DISPLAY}}) {
print;
}
- print colored $prompt_color, $patch_mode_flavour{VERB},
- ($hunk[$ix]{TYPE} eq 'mode' ? ' mode change' :
- $hunk[$ix]{TYPE} eq 'deletion' ? ' deletion' :
- ' this hunk'),
- $patch_mode_flavour{TARGET},
- " [y,n,q,a,d,/$other,?]? ";
+ print colored $prompt_color,
+ sprintf($patch_update_prompt_modes{$patch_mode}{$hunk[$ix]{TYPE}}, $other);
+
my $line = prompt_single_character;
last unless defined $line;
if ($line) {
@@ -1644,6 +1681,7 @@ sub process_args {
die sprintf(__("invalid argument %s, expecting --"),
$arg) unless $arg eq "--";
%patch_mode_flavour = %{$patch_modes{$patch_mode}};
+ $cmd = 1;
}
elsif ($arg ne "--") {
die sprintf(__("invalid argument %s, expecting --"), $arg);
@@ -1680,7 +1718,7 @@ sub main_loop {
process_args();
refresh();
-if ($patch_mode) {
+if ($cmd) {
patch_update_cmd();
}
else {
--
2.7.4
^ permalink raw reply related
* [PATCH v3 01/14] i18n: add--interactive: mark strings for translation
From: Vasco Almeida @ 2016-10-05 17:20 UTC (permalink / raw)
To: git
Cc: Vasco Almeida, Jiang Xin, Ævar Arnfjörð Bjarmason,
Jean-Noël AVILA, Jakub Narębski, David Aguilar,
Junio C Hamano
In-Reply-To: <20161005172110.30801-1-vascomalmeida@sapo.pt>
Mark simple strings (without interpolation) for translation.
Brackets around first parameter of ternary operator is necessary because
otherwise xgettext fails to extract strings marked for translation from
the rest of the file.
Signed-off-by: Vasco Almeida <vascomalmeida@sapo.pt>
---
git-add--interactive.perl | 74 ++++++++++++++++++++++++++---------------------
1 file changed, 41 insertions(+), 33 deletions(-)
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index ee3d812..da0255b 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -4,6 +4,7 @@ use 5.008;
use strict;
use warnings;
use Git;
+use Git::I18N;
binmode(STDOUT, ":raw");
@@ -253,8 +254,9 @@ sub list_untracked {
run_cmd_pipe(qw(git ls-files --others --exclude-standard --), @ARGV);
}
-my $status_fmt = '%12s %12s %s';
-my $status_head = sprintf($status_fmt, 'staged', 'unstaged', 'path');
+# TRANSLATORS: you can adjust this to align "git add -i" status menu
+my $status_fmt = __('%12s %12s %s');
+my $status_head = sprintf($status_fmt, __('staged'), __('unstaged'), __('path'));
{
my $initial;
@@ -680,7 +682,7 @@ sub update_cmd {
my @mods = list_modified('file-only');
return if (!@mods);
- my @update = list_and_choose({ PROMPT => 'Update',
+ my @update = list_and_choose({ PROMPT => __('Update'),
HEADER => $status_head, },
@mods);
if (@update) {
@@ -692,7 +694,7 @@ sub update_cmd {
}
sub revert_cmd {
- my @update = list_and_choose({ PROMPT => 'Revert',
+ my @update = list_and_choose({ PROMPT => __('Revert'),
HEADER => $status_head, },
list_modified());
if (@update) {
@@ -726,13 +728,13 @@ sub revert_cmd {
}
sub add_untracked_cmd {
- my @add = list_and_choose({ PROMPT => 'Add untracked' },
+ my @add = list_and_choose({ PROMPT => __('Add untracked') },
list_untracked());
if (@add) {
system(qw(git update-index --add --), @add);
say_n_paths('added', @add);
} else {
- print "No untracked files.\n";
+ print __("No untracked files.\n");
}
print "\n";
}
@@ -1166,8 +1168,14 @@ sub edit_hunk_loop {
}
else {
prompt_yesno(
- 'Your edited hunk does not apply. Edit again '
- . '(saying "no" discards!) [y/n]? '
+ # TRANSLATORS: do not translate [y/n]
+ # The program will only accept that input
+ # at this point.
+ # Consider translating (saying "no" discards!) as
+ # (saying "n" for "no" discards!) if the translation
+ # of the word "no" does not start with n.
+ __('Your edited hunk does not apply. Edit again '
+ . '(saying "no" discards!) [y/n]? ')
) or return undef;
}
}
@@ -1213,11 +1221,11 @@ sub apply_patch_for_checkout_commit {
run_git_apply 'apply '.$reverse, @_;
return 1;
} elsif (!$applies_index) {
- print colored $error_color, "The selected hunks do not apply to the index!\n";
- if (prompt_yesno "Apply them to the worktree anyway? ") {
+ print colored $error_color, __("The selected hunks do not apply to the index!\n");
+ if (prompt_yesno __("Apply them to the worktree anyway? ")) {
return run_git_apply 'apply '.$reverse, @_;
} else {
- print colored $error_color, "Nothing was applied.\n";
+ print colored $error_color, __("Nothing was applied.\n");
return 0;
}
} else {
@@ -1237,9 +1245,9 @@ sub patch_update_cmd {
if (!@mods) {
if (@all_mods) {
- print STDERR "Only binary files changed.\n";
+ print STDERR __("Only binary files changed.\n");
} else {
- print STDERR "No changes.\n";
+ print STDERR __("No changes.\n");
}
return 0;
}
@@ -1397,12 +1405,12 @@ sub patch_update_file {
my $response = $1;
my $no = $ix > 10 ? $ix - 10 : 0;
while ($response eq '') {
- my $extra = "";
$no = display_hunks(\@hunk, $no);
if ($no < $num) {
- $extra = " (<ret> to see more)";
+ print __("go to which hunk (<ret> to see more)? ");
+ } else {
+ print __("go to which hunk? ");
}
- print "go to which hunk$extra? ";
$response = <STDIN>;
if (!defined $response) {
$response = '';
@@ -1439,7 +1447,7 @@ sub patch_update_file {
elsif ($line =~ m|^/(.*)|) {
my $regex = $1;
if ($1 eq "") {
- print colored $prompt_color, "search for regex? ";
+ print colored $prompt_color, __("search for regex? ");
$regex = <STDIN>;
if (defined $regex) {
chomp $regex;
@@ -1462,7 +1470,7 @@ sub patch_update_file {
$iy++;
$iy = 0 if ($iy >= $num);
if ($ix == $iy) {
- error_msg "No hunk matches the given pattern\n";
+ error_msg __("No hunk matches the given pattern\n");
last;
}
}
@@ -1474,7 +1482,7 @@ sub patch_update_file {
$ix--;
}
else {
- error_msg "No previous hunk\n";
+ error_msg __("No previous hunk\n");
}
next;
}
@@ -1483,7 +1491,7 @@ sub patch_update_file {
$ix++;
}
else {
- error_msg "No next hunk\n";
+ error_msg __("No next hunk\n");
}
next;
}
@@ -1496,13 +1504,13 @@ sub patch_update_file {
}
}
else {
- error_msg "No previous hunk\n";
+ error_msg __("No previous hunk\n");
}
next;
}
elsif ($line =~ /^j/) {
if ($other !~ /j/) {
- error_msg "No next hunk\n";
+ error_msg __("No next hunk\n");
next;
}
}
@@ -1560,18 +1568,18 @@ sub diff_cmd {
my @mods = list_modified('index-only');
@mods = grep { !($_->{BINARY}) } @mods;
return if (!@mods);
- my (@them) = list_and_choose({ PROMPT => 'Review diff',
+ my (@them) = list_and_choose({ PROMPT => __('Review diff'),
IMMEDIATE => 1,
HEADER => $status_head, },
@mods);
return if (!@them);
- my $reference = is_initial_commit() ? get_empty_tree() : 'HEAD';
+ my $reference = (is_initial_commit()) ? get_empty_tree() : 'HEAD';
system(qw(git diff -p --cached), $reference, '--',
map { $_->{VALUE} } @them);
}
sub quit_cmd {
- print "Bye.\n";
+ print __("Bye.\n");
exit(0);
}
@@ -1594,32 +1602,32 @@ sub process_args {
if ($1 eq 'reset') {
$patch_mode = 'reset_head';
$patch_mode_revision = 'HEAD';
- $arg = shift @ARGV or die "missing --";
+ $arg = shift @ARGV or die __("missing --");
if ($arg ne '--') {
$patch_mode_revision = $arg;
$patch_mode = ($arg eq 'HEAD' ?
'reset_head' : 'reset_nothead');
- $arg = shift @ARGV or die "missing --";
+ $arg = shift @ARGV or die __("missing --");
}
} elsif ($1 eq 'checkout') {
- $arg = shift @ARGV or die "missing --";
+ $arg = shift @ARGV or die __("missing --");
if ($arg eq '--') {
$patch_mode = 'checkout_index';
} else {
$patch_mode_revision = $arg;
$patch_mode = ($arg eq 'HEAD' ?
'checkout_head' : 'checkout_nothead');
- $arg = shift @ARGV or die "missing --";
+ $arg = shift @ARGV or die __("missing --");
}
} elsif ($1 eq 'stage' or $1 eq 'stash') {
$patch_mode = $1;
- $arg = shift @ARGV or die "missing --";
+ $arg = shift @ARGV or die __("missing --");
} else {
die "unknown --patch mode: $1";
}
} else {
$patch_mode = 'stage';
- $arg = shift @ARGV or die "missing --";
+ $arg = shift @ARGV or die __("missing --");
}
die "invalid argument $arg, expecting --"
unless $arg eq "--";
@@ -1641,10 +1649,10 @@ sub main_loop {
[ 'help', \&help_cmd, ],
);
while (1) {
- my ($it) = list_and_choose({ PROMPT => 'What now',
+ my ($it) = list_and_choose({ PROMPT => __('What now'),
SINGLETON => 1,
LIST_FLAT => 4,
- HEADER => '*** Commands ***',
+ HEADER => __('*** Commands ***'),
ON_EOF => \&quit_cmd,
IMMEDIATE => 1 }, @cmd);
if ($it) {
--
2.7.4
^ permalink raw reply related
* [PATCH v3 03/14] i18n: add--interactive: mark strings with interpolation for translation
From: Vasco Almeida @ 2016-10-05 17:20 UTC (permalink / raw)
To: git
Cc: Vasco Almeida, Jiang Xin, Ævar Arnfjörð Bjarmason,
Jean-Noël AVILA, Jakub Narębski, David Aguilar,
Junio C Hamano
In-Reply-To: <20161005172110.30801-1-vascomalmeida@sapo.pt>
Since at this point Git::I18N.perl lacks support for Perl i18n
placeholder substitution, use of sprintf following die or error_msg is
necessary for placeholder substitution take place.
Signed-off-by: Vasco Almeida <vascomalmeida@sapo.pt>
---
git-add--interactive.perl | 23 ++++++++++++-----------
1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index 3c10ced..50bcf94 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -615,12 +615,12 @@ sub list_and_choose {
else {
$bottom = $top = find_unique($choice, @stuff);
if (!defined $bottom) {
- error_msg "Huh ($choice)?\n";
+ error_msg sprintf(__("Huh (%s)?\n"), $choice);
next TOPLOOP;
}
}
if ($opts->{SINGLETON} && $bottom != $top) {
- error_msg "Huh ($choice)?\n";
+ error_msg sprintf(__("Huh (%s)?"), $choice);
next TOPLOOP;
}
for ($i = $bottom-1; $i <= $top-1; $i++) {
@@ -1056,7 +1056,7 @@ sub edit_hunk_manually {
my $hunkfile = $repo->repo_path . "/addp-hunk-edit.diff";
my $fh;
open $fh, '>', $hunkfile
- or die "failed to open hunk edit file for writing: " . $!;
+ or die sprintf(__("failed to open hunk edit file for writing: %s"), $!);
print $fh "# Manual hunk edit mode -- see bottom for a quick guide\n";
print $fh @$oldtext;
my $participle = $patch_mode_flavour{PARTICIPLE};
@@ -1083,7 +1083,7 @@ EOF
}
open $fh, '<', $hunkfile
- or die "failed to open hunk edit file for reading: " . $!;
+ or die sprintf(__("failed to open hunk edit file for reading: %s"), $!);
my @newtext = grep { !/^#/ } <$fh>;
close $fh;
unlink $hunkfile;
@@ -1236,7 +1236,7 @@ sub apply_patch_for_checkout_commit {
sub patch_update_cmd {
my @all_mods = list_modified($patch_mode_flavour{FILTER});
- error_msg "ignoring unmerged: $_->{VALUE}\n"
+ error_msg sprintf(__("ignoring unmerged: %s\n"), $_->{VALUE})
for grep { $_->{UNMERGED} } @all_mods;
@all_mods = grep { !$_->{UNMERGED} } @all_mods;
@@ -1418,7 +1418,8 @@ sub patch_update_file {
chomp $response;
}
if ($response !~ /^\s*\d+\s*$/) {
- error_msg "Invalid number: '$response'\n";
+ error_msg sprintf(__("Invalid number: '%s'\n"),
+ $response);
} elsif (0 < $response && $response <= $num) {
$ix = $response - 1;
} else {
@@ -1460,7 +1461,7 @@ sub patch_update_file {
if ($@) {
my ($err,$exp) = ($@, $1);
$err =~ s/ at .*git-add--interactive line \d+, <STDIN> line \d+.*$//;
- error_msg "Malformed search regexp $exp: $err\n";
+ error_msg sprintf(__("Malformed search regexp %s: %s\n"), $exp, $err);
next;
}
my $iy = $ix;
@@ -1625,18 +1626,18 @@ sub process_args {
$patch_mode = $1;
$arg = shift @ARGV or die __("missing --");
} else {
- die "unknown --patch mode: $1";
+ die sprintf(__("unknown --patch mode: %s"), $1);
}
} else {
$patch_mode = 'stage';
$arg = shift @ARGV or die __("missing --");
}
- die "invalid argument $arg, expecting --"
- unless $arg eq "--";
+ die sprintf(__("invalid argument %s, expecting --"),
+ $arg) unless $arg eq "--";
%patch_mode_flavour = %{$patch_modes{$patch_mode}};
}
elsif ($arg ne "--") {
- die "invalid argument $arg, expecting --";
+ die sprintf(__("invalid argument %s, expecting --"), $arg);
}
}
--
2.7.4
^ permalink raw reply related
* [PATCH v3 05/14] i18n: add--interactive: mark plural strings
From: Vasco Almeida @ 2016-10-05 17:21 UTC (permalink / raw)
To: git
Cc: Vasco Almeida, Jiang Xin, Ævar Arnfjörð Bjarmason,
Jean-Noël AVILA, Jakub Narębski, David Aguilar,
Junio C Hamano
In-Reply-To: <20161005172110.30801-1-vascomalmeida@sapo.pt>
Mark plural strings for translation. Unfold each action case in one
entire sentence.
Pass new keyword for xgettext to extract.
Update test to include new subroutine __n() for plural strings handling.
Update documentation to include a description of the new __n() subroutine.
Signed-off-by: Vasco Almeida <vascomalmeida@sapo.pt>
---
On the present re-roll, change name __Q to __n following the
Locale::Message convention.
Add documentation about __n().
Makefile | 3 ++-
git-add--interactive.perl | 27 ++++++++++++++++++---------
perl/Git/I18N.pm | 9 ++++++++-
t/t0202/test.pl | 11 ++++++++++-
4 files changed, 38 insertions(+), 12 deletions(-)
diff --git a/Makefile b/Makefile
index 1aad150..4ef0344 100644
--- a/Makefile
+++ b/Makefile
@@ -2111,7 +2111,8 @@ XGETTEXT_FLAGS_C = $(XGETTEXT_FLAGS) --language=C \
--keyword=_ --keyword=N_ --keyword="Q_:1,2"
XGETTEXT_FLAGS_SH = $(XGETTEXT_FLAGS) --language=Shell \
--keyword=gettextln --keyword=eval_gettextln
-XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --keyword=__ --language=Perl
+XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --language=Perl \
+ --keyword=__ --keyword="__n:1,2"
LOCALIZED_C = $(C_OBJ:o=c) $(LIB_H) $(GENERATED_H)
LOCALIZED_SH = $(SCRIPT_SH)
LOCALIZED_SH += git-parse-remote.sh
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index 50bcf94..6bbde2d 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -669,12 +669,18 @@ sub status_cmd {
sub say_n_paths {
my $did = shift @_;
my $cnt = scalar @_;
- print "$did ";
- if (1 < $cnt) {
- print "$cnt paths\n";
- }
- else {
- print "one path\n";
+ if ($did eq 'added') {
+ printf(__n("added %d path\n", "added %d paths\n",
+ $cnt), $cnt);
+ } elsif ($did eq 'updated') {
+ printf(__n("updated %d path\n", "updated %d paths\n",
+ $cnt), $cnt);
+ } elsif ($did eq 'reverted') {
+ printf(__n("reverted %d path\n", "reverted %d paths\n",
+ $cnt), $cnt);
+ } else {
+ printf(__n("touched %d path\n", "touched %d paths\n",
+ $cnt), $cnt);
}
}
@@ -1423,7 +1429,8 @@ sub patch_update_file {
} elsif (0 < $response && $response <= $num) {
$ix = $response - 1;
} else {
- error_msg "Sorry, only $num hunks available.\n";
+ error_msg sprintf(__n("Sorry, only %d hunk available.\n",
+ "Sorry, only %d hunks available.\n", $num), $num);
}
next;
}
@@ -1518,8 +1525,10 @@ sub patch_update_file {
elsif ($other =~ /s/ && $line =~ /^s/) {
my @split = split_hunk($hunk[$ix]{TEXT}, $hunk[$ix]{DISPLAY});
if (1 < @split) {
- print colored $header_color, "Split into ",
- scalar(@split), " hunks.\n";
+ print colored $header_color, sprintf(
+ __n("Split into %d hunk.\n",
+ "Split into %d hunks.\n",
+ scalar(@split)), scalar(@split));
}
splice (@hunk, $ix, 1, @split);
$num = scalar @hunk;
diff --git a/perl/Git/I18N.pm b/perl/Git/I18N.pm
index f889fd6..3f7ac25 100644
--- a/perl/Git/I18N.pm
+++ b/perl/Git/I18N.pm
@@ -13,7 +13,7 @@ BEGIN {
}
}
-our @EXPORT = qw(__);
+our @EXPORT = qw(__ __n);
our @EXPORT_OK = @EXPORT;
sub __bootstrap_locale_messages {
@@ -44,6 +44,7 @@ BEGIN
eval {
__bootstrap_locale_messages();
*__ = \&Locale::Messages::gettext;
+ *__n = \&Locale::Messages::ngettext;
1;
} or do {
# Tell test.pl that we couldn't load the gettext library.
@@ -51,6 +52,7 @@ BEGIN
# Just a fall-through no-op
*__ = sub ($) { $_[0] };
+ *__n = sub ($$$) { $_[2] == 1 ? $_[0] : $_[1] };
};
}
@@ -70,6 +72,8 @@ Git::I18N - Perl interface to Git's Gettext localizations
printf __("The following error occurred: %s\n"), $error;
+ printf __n("commited %d file", "commited %d files", $files), $files;
+
=head1 DESCRIPTION
Git's internal Perl interface to gettext via L<Locale::Messages>. If
@@ -87,6 +91,9 @@ it.
L<Locale::Messages>'s gettext function if all goes well, otherwise our
passthrough fallback function.
+=head2 __n($$$)
+L<Locale::Messages>'s ngettext function or passthrough fallback function.
+
=head1 AUTHOR
E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason <avarab@gmail.com>
diff --git a/t/t0202/test.pl b/t/t0202/test.pl
index 2c10cb4..4101833 100755
--- a/t/t0202/test.pl
+++ b/t/t0202/test.pl
@@ -4,7 +4,7 @@ use lib (split(/:/, $ENV{GITPERLLIB}));
use strict;
use warnings;
use POSIX qw(:locale_h);
-use Test::More tests => 8;
+use Test::More tests => 11;
use Git::I18N;
my $has_gettext_library = $Git::I18N::__HAS_LIBRARY;
@@ -31,6 +31,7 @@ is_deeply(\@Git::I18N::EXPORT, \@Git::I18N::EXPORT_OK, "sanity: Git::I18N export
# more gettext wrapper functions.
my %prototypes = (qw(
__ $
+ __n $$$
));
while (my ($sub, $proto) = each %prototypes) {
is(prototype(\&{"Git::I18N::$sub"}), $proto, "sanity: $sub has a $proto prototype");
@@ -46,6 +47,14 @@ is_deeply(\@Git::I18N::EXPORT, \@Git::I18N::EXPORT_OK, "sanity: Git::I18N export
my ($got, $expect) = (('TEST: A Perl test string') x 2);
is(__($got), $expect, "Passing a string through __() in the C locale works");
+
+ my ($got_singular, $got_plural, $expect_singular, $expect_plural) =
+ (('TEST: 1 file', 'TEST: n files') x 2);
+
+ is(__n($got_singular, $got_plural, 1), $expect_singular,
+ "Get singular string through __n() in C locale");
+ is(__n($got_singular, $got_plural, 2), $expect_plural,
+ "Get plural string through __n() in C locale");
}
# Test a basic message on different locales
--
2.7.4
^ permalink raw reply related
* [PATCH v3 04/14] i18n: clean.c: match string with git-add--interactive.perl
From: Vasco Almeida @ 2016-10-05 17:21 UTC (permalink / raw)
To: git
Cc: Vasco Almeida, Jiang Xin, Ævar Arnfjörð Bjarmason,
Jean-Noël AVILA, Jakub Narębski, David Aguilar,
Junio C Hamano
In-Reply-To: <20161005172110.30801-1-vascomalmeida@sapo.pt>
Change strings for help to match the ones in git-add--interactive.perl.
The strings now represent one entry to translate each rather then two
entries each different only by an ending newline character.
Signed-off-by: Vasco Almeida <vascomalmeida@sapo.pt>
---
builtin/clean.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/builtin/clean.c b/builtin/clean.c
index 0371010..d6bc3aa 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -287,11 +287,11 @@ static void pretty_print_menus(struct string_list *menu_list)
static void prompt_help_cmd(int singleton)
{
clean_print_color(CLEAN_COLOR_HELP);
- printf_ln(singleton ?
+ printf(singleton ?
_("Prompt help:\n"
"1 - select a numbered item\n"
"foo - select item based on unique prefix\n"
- " - (empty) select nothing") :
+ " - (empty) select nothing\n") :
_("Prompt help:\n"
"1 - select a single item\n"
"3-5 - select a range of items\n"
@@ -299,7 +299,7 @@ static void prompt_help_cmd(int singleton)
"foo - select item based on unique prefix\n"
"-... - unselect specified items\n"
"* - choose all items\n"
- " - (empty) finish selecting"));
+ " - (empty) finish selecting\n"));
clean_print_color(CLEAN_COLOR_RESET);
}
@@ -508,7 +508,7 @@ static int parse_choice(struct menu_stuff *menu_stuff,
if (top <= 0 || bottom <= 0 || top > menu_stuff->nr || bottom > top ||
(is_single && bottom != top)) {
clean_print_color(CLEAN_COLOR_ERROR);
- printf_ln(_("Huh (%s)?"), (*ptr)->buf);
+ printf(_("Huh (%s)?\n"), (*ptr)->buf);
clean_print_color(CLEAN_COLOR_RESET);
continue;
}
@@ -774,7 +774,7 @@ static int ask_each_cmd(void)
static int quit_cmd(void)
{
string_list_clear(&del_list, 0);
- printf_ln(_("Bye."));
+ printf(_("Bye.\n"));
return MENU_RETURN_NO_LOOP;
}
--
2.7.4
^ permalink raw reply related
* [PATCH v3 02/14] i18n: add--interactive: mark simple here-documents for translation
From: Vasco Almeida @ 2016-10-05 17:20 UTC (permalink / raw)
To: git
Cc: Vasco Almeida, Jiang Xin, Ævar Arnfjörð Bjarmason,
Jean-Noël AVILA, Jakub Narębski, David Aguilar,
Junio C Hamano
In-Reply-To: <20161005172110.30801-1-vascomalmeida@sapo.pt>
Mark messages in here-document without interpolation for translation.
The here-document delimiter \EOF, which is the same as 'EOF', indicate
that the text is to be treated literally without interpolation of its
content. Unfortunately xgettext is not able to extract here documents
with delimiter \EOF but it is with delimiter enclosed in single quotes.
Then change \EOF to 'EOF', although in this case does not make
difference what variation of here-document to use since there is nothing
to interpolate.
Signed-off-by: Vasco Almeida <vascomalmeida@sapo.pt>
---
git-add--interactive.perl | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index da0255b..3c10ced 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -639,7 +639,7 @@ sub list_and_choose {
}
sub singleton_prompt_help_cmd {
- print colored $help_color, <<\EOF ;
+ print colored $help_color, __ <<'EOF' ;
Prompt help:
1 - select a numbered item
foo - select item based on unique prefix
@@ -648,7 +648,7 @@ EOF
}
sub prompt_help_cmd {
- print colored $help_color, <<\EOF ;
+ print colored $help_color, __ <<'EOF' ;
Prompt help:
1 - select a single item
3-5 - select a range of items
@@ -1584,7 +1584,9 @@ sub quit_cmd {
}
sub help_cmd {
- print colored $help_color, <<\EOF ;
+# TRANSLATORS: please do not translate the command names
+# 'status', 'update', 'revert', etc.
+ print colored $help_color, __ <<'EOF' ;
status - show paths with changes
update - add working tree state to the staged set of changes
revert - revert staged set of changes back to the HEAD version
--
2.7.4
^ permalink raw reply related
* [PATCH v3 00/14] Mark strings in Perl scripts for translation
From: Vasco Almeida @ 2016-10-05 17:20 UTC (permalink / raw)
To: git
Cc: Vasco Almeida, Jiang Xin, Ævar Arnfjörð Bjarmason,
Jean-Noël AVILA, Jakub Narębski, David Aguilar,
Junio C Hamano
Mark messages in some perl scripts for translation.
Thanks for the reviews of Junio Hamano and Jakub Narębski. Although I think
Jakub Narębski's suggestions are overall good, I am not willing to go that path
because I cannot see huge benefits from them given what we already have and
also I lack Perl skills.
Interdiff bellow.
Vasco Almeida (14):
i18n: add--interactive: mark strings for translation
i18n: add--interactive: mark simple here-documents for translation
i18n: add--interactive: mark strings with interpolation for
translation
i18n: clean.c: match string with git-add--interactive.perl
i18n: add--interactive: mark plural strings
i18n: add--interactive: mark patch prompt for translation
i18n: add--interactive: i18n of help_patch_cmd
i18n: add--interactive: mark edit_hunk_manually message for
translation
i18n: add--interactive: remove %patch_modes entries
i18n: add--interactive: mark status words for translation
i18n: send-email: mark strings for translation
i18n: send-email: mark warnings and errors for translation
i18n: send-email: mark string with interpolation for translation
i18n: difftool: mark warnings for translation
Makefile | 3 +-
builtin/clean.c | 10 +-
git-add--interactive.perl | 318 ++++++++++++++++++++++++++++++----------------
git-difftool.perl | 22 ++--
git-send-email.perl | 176 +++++++++++++------------
perl/Git/I18N.pm | 9 +-
t/t0202/test.pl | 11 +-
7 files changed, 340 insertions(+), 209 deletions(-)
diff --git a/Makefile b/Makefile
index fc29d85..4ef0344 100644
--- a/Makefile
+++ b/Makefile
@@ -2112,7 +2112,7 @@ XGETTEXT_FLAGS_C = $(XGETTEXT_FLAGS) --language=C \
XGETTEXT_FLAGS_SH = $(XGETTEXT_FLAGS) --language=Shell \
--keyword=gettextln --keyword=eval_gettextln
XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --language=Perl \
- --keyword=__ --keyword="Q__:1,2"
+ --keyword=__ --keyword="__n:1,2"
LOCALIZED_C = $(C_OBJ:o=c) $(LIB_H) $(GENERATED_H)
LOCALIZED_SH = $(SCRIPT_SH)
LOCALIZED_SH += git-parse-remote.sh
diff --git a/builtin/clean.c b/builtin/clean.c
index 0371010..d6bc3aa 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -287,11 +287,11 @@ static void pretty_print_menus(struct string_list *menu_list)
static void prompt_help_cmd(int singleton)
{
clean_print_color(CLEAN_COLOR_HELP);
- printf_ln(singleton ?
+ printf(singleton ?
_("Prompt help:\n"
"1 - select a numbered item\n"
"foo - select item based on unique prefix\n"
- " - (empty) select nothing") :
+ " - (empty) select nothing\n") :
_("Prompt help:\n"
"1 - select a single item\n"
"3-5 - select a range of items\n"
@@ -299,7 +299,7 @@ static void prompt_help_cmd(int singleton)
"foo - select item based on unique prefix\n"
"-... - unselect specified items\n"
"* - choose all items\n"
- " - (empty) finish selecting"));
+ " - (empty) finish selecting\n"));
clean_print_color(CLEAN_COLOR_RESET);
}
@@ -508,7 +508,7 @@ static int parse_choice(struct menu_stuff *menu_stuff,
if (top <= 0 || bottom <= 0 || top > menu_stuff->nr || bottom > top ||
(is_single && bottom != top)) {
clean_print_color(CLEAN_COLOR_ERROR);
- printf_ln(_("Huh (%s)?"), (*ptr)->buf);
+ printf(_("Huh (%s)?\n"), (*ptr)->buf);
clean_print_color(CLEAN_COLOR_RESET);
continue;
}
@@ -774,7 +774,7 @@ static int ask_each_cmd(void)
static int quit_cmd(void)
{
string_list_clear(&del_list, 0);
- printf_ln(_("Bye."));
+ printf(_("Bye.\n"));
return MENU_RETURN_NO_LOOP;
}
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index b72cc97..0b4a27c 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -106,9 +106,6 @@ my %patch_modes = (
DIFF => 'diff-files -p',
APPLY => sub { apply_patch 'apply --cached', @_; },
APPLY_CHECK => 'apply --cached',
- VERB => 'Stage',
- TARGET => '',
- PARTICIPLE => 'staging',
FILTER => 'file-only',
IS_REVERSE => 0,
},
@@ -116,9 +113,6 @@ my %patch_modes = (
DIFF => 'diff-index -p HEAD',
APPLY => sub { apply_patch 'apply --cached', @_; },
APPLY_CHECK => 'apply --cached',
- VERB => 'Stash',
- TARGET => '',
- PARTICIPLE => 'stashing',
FILTER => undef,
IS_REVERSE => 0,
},
@@ -126,9 +120,6 @@ my %patch_modes = (
DIFF => 'diff-index -p --cached',
APPLY => sub { apply_patch 'apply -R --cached', @_; },
APPLY_CHECK => 'apply -R --cached',
- VERB => 'Unstage',
- TARGET => '',
- PARTICIPLE => 'unstaging',
FILTER => 'index-only',
IS_REVERSE => 1,
},
@@ -136,9 +127,6 @@ my %patch_modes = (
DIFF => 'diff-index -R -p --cached',
APPLY => sub { apply_patch 'apply --cached', @_; },
APPLY_CHECK => 'apply --cached',
- VERB => 'Apply',
- TARGET => ' to index',
- PARTICIPLE => 'applying',
FILTER => 'index-only',
IS_REVERSE => 0,
},
@@ -146,9 +134,6 @@ my %patch_modes = (
DIFF => 'diff-files -p',
APPLY => sub { apply_patch 'apply -R', @_; },
APPLY_CHECK => 'apply -R',
- VERB => 'Discard',
- TARGET => ' from worktree',
- PARTICIPLE => 'discarding',
FILTER => 'file-only',
IS_REVERSE => 1,
},
@@ -156,9 +141,6 @@ my %patch_modes = (
DIFF => 'diff-index -p',
APPLY => sub { apply_patch_for_checkout_commit '-R', @_ },
APPLY_CHECK => 'apply -R',
- VERB => 'Discard',
- TARGET => ' from index and worktree',
- PARTICIPLE => 'discarding',
FILTER => undef,
IS_REVERSE => 1,
},
@@ -166,9 +148,6 @@ my %patch_modes = (
DIFF => 'diff-index -R -p',
APPLY => sub { apply_patch_for_checkout_commit '', @_ },
APPLY_CHECK => 'apply',
- VERB => 'Apply',
- TARGET => ' to index and worktree',
- PARTICIPLE => 'applying',
FILTER => undef,
IS_REVERSE => 0,
},
@@ -256,7 +235,8 @@ sub list_untracked {
run_cmd_pipe(qw(git ls-files --others --exclude-standard --), @ARGV);
}
-my $status_fmt = '%12s %12s %s';
+# TRANSLATORS: you can adjust this to align "git add -i" status menu
+my $status_fmt = __('%12s %12s %s');
my $status_head = sprintf($status_fmt, __('staged'), __('unstaged'), __('path'));
{
@@ -315,7 +295,7 @@ sub list_modified {
my ($change, $bin);
$file = unquote_path($file);
if ($add eq '-' && $del eq '-') {
- $change = 'binary';
+ $change = __('binary');
$bin = 1;
}
else {
@@ -324,7 +304,7 @@ sub list_modified {
$data{$file} = {
INDEX => $change,
BINARY => $bin,
- FILE => 'nothing',
+ FILE => __('nothing'),
}
}
elsif (($adddel, $file) =
@@ -340,7 +320,7 @@ sub list_modified {
$file = unquote_path($file);
my ($change, $bin);
if ($add eq '-' && $del eq '-') {
- $change = 'binary';
+ $change = __('binary');
$bin = 1;
}
else {
@@ -360,7 +340,7 @@ sub list_modified {
$file = unquote_path($2);
if (!exists $data{$file}) {
$data{$file} = +{
- INDEX => 'unchanged',
+ INDEX => __('unchanged'),
BINARY => 0,
};
}
@@ -375,10 +355,10 @@ sub list_modified {
if ($only) {
if ($only eq 'index-only') {
- next if ($it->{INDEX} eq 'unchanged');
+ next if ($it->{INDEX} eq __('unchanged'));
}
if ($only eq 'file-only') {
- next if ($it->{FILE} eq 'nothing');
+ next if ($it->{FILE} eq __('nothing'));
}
}
push @return, +{
@@ -621,7 +601,7 @@ sub list_and_choose {
}
}
if ($opts->{SINGLETON} && $bottom != $top) {
- error_msg sprintf(__("Huh (%s)?\n"), $choice);
+ error_msg sprintf(__("Huh (%s)?"), $choice);
next TOPLOOP;
}
for ($i = $bottom-1; $i <= $top-1; $i++) {
@@ -640,25 +620,25 @@ sub list_and_choose {
}
sub singleton_prompt_help_cmd {
- print colored $help_color, __(
-"Prompt help:
+ print colored $help_color, __ <<'EOF' ;
+Prompt help:
1 - select a numbered item
foo - select item based on unique prefix
- - (empty) select nothing"),
-"\n";
+ - (empty) select nothing
+EOF
}
sub prompt_help_cmd {
- print colored $help_color, __(
-"Prompt help:
+ print colored $help_color, __ <<'EOF' ;
+Prompt help:
1 - select a single item
3-5 - select a range of items
2-3,6-9 - select multiple ranges
foo - select item based on unique prefix
-... - unselect specified items
* - choose all items
- - (empty) finish selecting"),
-"\n";
+ - (empty) finish selecting
+EOF
}
sub status_cmd {
@@ -671,16 +651,16 @@ sub say_n_paths {
my $did = shift @_;
my $cnt = scalar @_;
if ($did eq 'added') {
- printf(Q__("added one path\n", "added %d paths\n",
+ printf(__n("added %d path\n", "added %d paths\n",
$cnt), $cnt);
} elsif ($did eq 'updated') {
- printf(Q__("updated one path\n", "updated %d paths\n",
+ printf(__n("updated %d path\n", "updated %d paths\n",
$cnt), $cnt);
- } elsif ($did eq 'reversed') {
- printf(Q__("reversed one path\n", "reversed %d paths\n",
+ } elsif ($did eq 'reverted') {
+ printf(__n("reverted %d path\n", "reverted %d paths\n",
$cnt), $cnt);
} else {
- printf(Q__("touched one path\n", "touched %d paths\n",
+ printf(__n("touched %d path\n", "touched %d paths\n",
$cnt), $cnt);
}
}
@@ -1057,6 +1037,30 @@ sub color_diff {
} @_;
}
+my %edit_hunk_manually_modes = (
+ stage => __(
+"# If the patch applies cleanly, the edited hunk will immediately be
+# marked for staging."),
+ stash => __(
+"# If the patch applies cleanly, the edited hunk will immediately be
+# marked for stashing."),
+ reset_head => __(
+"# If the patch applies cleanly, the edited hunk will immediately be
+# marked for unstaging."),
+ reset_nothead => __(
+"# If the patch applies cleanly, the edited hunk will immediately be
+# marked for applying."),
+ checkout_index => __(
+"# If the patch applies cleanly, the edited hunk will immediately be
+# marked for discarding"),
+ checkout_head => __(
+"# If the patch applies cleanly, the edited hunk will immediately be
+# marked for discarding."),
+ checkout_nothead => __(
+"# If the patch applies cleanly, the edited hunk will immediately be
+# marked for applying."),
+);
+
sub edit_hunk_manually {
my ($oldtext) = @_;
@@ -1073,51 +1077,12 @@ sub edit_hunk_manually {
# To remove '%s' lines, make them ' ' lines (context).
# To remove '%s' lines, delete them.
# Lines starting with # will be removed.
-#"), $remove_minus, $remove_plus),
-"\n";
- if ($patch_mode eq 'stage') {
- print $fh __(
-"# If the patch applies cleanly, the edited hunk will immediately be
-# marked for staging. If it does not apply cleanly, you will be given
-# an opportunity to edit again. If all lines of the hunk are removed,
-# then the edit is aborted and the hunk is left unchanged.");
- } elsif ($patch_mode eq 'stash') {
- print $fh __(
-"# If the patch applies cleanly, the edited hunk will immediately be
-# marked for stashing. If it does not apply cleanly, you will be given
-# an opportunity to edit again. If all lines of the hunk are removed,
-# then the edit is aborted and the hunk is left unchanged.");
- } elsif ($patch_mode eq 'reset_head') {
- print $fh __(
-"# If the patch applies cleanly, the edited hunk will immediately be
-# marked for unstaging. If it does not apply cleanly, you will be given
+#\n"), $remove_minus, $remove_plus),
+$edit_hunk_manually_modes{$patch_mode}, __(
+# TRANSLATORS: 'it' refers to the patch mentioned in the previous messages.
+" If it does not apply cleanly, you will be given
# an opportunity to edit again. If all lines of the hunk are removed,
-# then the edit is aborted and the hunk is left unchanged.");
- } elsif ($patch_mode eq 'reset_nothead') {
- print $fh __(
-"# If the patch applies cleanly, the edited hunk will immediately be
-# marked for applying. If it does not apply cleanly, you will be given
-# an opportunity to edit again. If all lines of the hunk are removed,
-# then the edit is aborted and the hunk is left unchanged.");
- } elsif ($patch_mode eq 'checkout_index') {
- print $fh __(
-"# If the patch applies cleanly, the edited hunk will immediately be
-# marked for discarding. If it does not apply cleanly, you will be given
-# an opportunity to edit again. If all lines of the hunk are removed,
-# then the edit is aborted and the hunk is left unchanged.");
- } elsif ($patch_mode eq 'checkout_head') {
- print $fh __(
-"# If the patch applies cleanly, the edited hunk will immediately be
-# marked for discarding. If it does not apply cleanly, you will be given
-# an opportunity to edit again. If all lines of the hunk are removed,
-# then the edit is aborted and the hunk is left unchanged.");
- } elsif ($patch_mode eq 'checkout_nothead') {
- print $fh __(
-"# If the patch applies cleanly, the edited hunk will immediately be
-# marked for applying. If it does not apply cleanly, you will be given
-# an opportunity to edit again. If all lines of the hunk are removed,
-# then the edit is aborted and the hunk is left unchanged.");
- }
+# then the edit is aborted and the hunk is left unchanged.\n");
close $fh;
chomp(my $editor = run_cmd_pipe(qw(git var GIT_EDITOR)));
@@ -1216,6 +1181,9 @@ sub edit_hunk_loop {
# TRANSLATORS: do not translate [y/n]
# The program will only accept that input
# at this point.
+ # Consider translating (saying "no" discards!) as
+ # (saying "n" for "no" discards!) if the translation
+ # of the word "no" does not start with n.
__('Your edited hunk does not apply. Edit again '
. '(saying "no" discards!) [y/n]? ')
) or return undef;
@@ -1223,59 +1191,54 @@ sub edit_hunk_loop {
}
}
-sub help_patch_cmd {
- if ($patch_mode eq 'stage') {
- print colored $help_color, __(
+my %help_patch_modes = (
+ stage => __(
"y - stage this hunk
n - do not stage this hunk
q - quit; do not stage this hunk or any of the remaining ones
a - stage this hunk and all later hunks in the file
-d - do not stage this hunk or any of the later hunks in the file");
- } elsif ($patch_mode eq 'stash') {
- print colored $help_color, __(
+d - do not stage this hunk or any of the later hunks in the file"),
+ stash => __(
"y - stash this hunk
n - do not stash this hunk
q - quit; do not stash this hunk or any of the remaining ones
a - stash this hunk and all later hunks in the file
-d - do not stash this hunk or any of the later hunks in the file");
- } elsif ($patch_mode eq 'reset_head') {
- print colored $help_color, __(
+d - do not stash this hunk or any of the later hunks in the file"),
+ reset_head => __(
"y - unstage this hunk
n - do not unstage this hunk
q - quit; do not unstage this hunk or any of the remaining ones
a - unstage this hunk and all later hunks in the file
-d - do not unstage this hunk or any of the later hunks in the file");
- } elsif ($patch_mode eq 'reset_nothead') {
- print colored $help_color, __(
+d - do not unstage this hunk or any of the later hunks in the file"),
+ reset_nothead => __(
"y - apply this hunk to index
n - do not apply this hunk to index
q - quit; do not apply this hunk or any of the remaining ones
a - apply this hunk and all later hunks in the file
-d - do not apply this hunk or any of the later hunks in the file");
- } elsif ($patch_mode eq 'checkout_index') {
- print colored $help_color, __(
+d - do not apply this hunk or any of the later hunks in the file"),
+ checkout_index => __(
"y - discard this hunk from worktree
n - do not discard this hunk from worktree
q - quit; do not discard this hunk or any of the remaining ones
a - discard this hunk and all later hunks in the file
-d - do not discard this hunk or any of the later hunks in the file");
- } elsif ($patch_mode eq 'checkout_head') {
- print colored $help_color, __(
+d - do not discard this hunk or any of the later hunks in the file"),
+ checkout_head => __(
"y - discard this hunk from index and worktree
n - do not discard this hunk from index and worktree
q - quit; do not discard this hunk or any of the remaining ones
a - discard this hunk and all later hunks in the file
-d - do not discard this hunk or any of the later hunks in the file");
- } elsif ($patch_mode eq 'checkout_nothead') {
- print colored $help_color, __(
+d - do not discard this hunk or any of the later hunks in the file"),
+ checkout_nothead => __(
"y - apply this hunk to index and worktree
n - do not apply this hunk to index and worktree
q - quit; do not apply this hunk or any of the remaining ones
a - apply this hunk and all later hunks in the file
-d - do not apply this hunk or any of the later hunks in the file");
- }
- print colored $help_color, "\n", __(
-"g - select a hunk to go to
+d - do not apply this hunk or any of the later hunks in the file"),
+);
+
+sub help_patch_cmd {
+ print colored $help_color, $help_patch_modes{$patch_mode}, "\n", __ <<EOF ;
+g - select a hunk to go to
/ - search for a hunk matching the given regex
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
@@ -1283,8 +1246,8 @@ k - leave this hunk undecided, see previous undecided hunk
K - leave this hunk undecided, see previous hunk
s - split the current hunk into smaller hunks
e - manually edit the current hunk
-? - print help"),
-"\n";
+? - print help
+EOF
}
sub apply_patch {
@@ -1390,6 +1353,44 @@ sub display_hunks {
return $i;
}
+my %patch_update_prompt_modes = (
+ stage => {
+ mode => __("Stage mode change [y,n,q,a,d,/%s,?]? "),
+ deletion => __("Stage deletion [y,n,q,a,d,/%s,?]? "),
+ hunk => __("Stage this hunk [y,n,q,a,d,/%s,?]? "),
+ },
+ stash => {
+ mode => __("Stash mode change [y,n,q,a,d,/%s,?]? "),
+ deletion => __("Stash deletion [y,n,q,a,d,/%s,?]? "),
+ hunk => __("Stash this hunk [y,n,q,a,d,/%s,?]? "),
+ },
+ reset_head => {
+ mode => __("Unstage mode change [y,n,q,a,d,/%s,?]? "),
+ deletion => __("Unstage deletion [y,n,q,a,d,/%s,?]? "),
+ hunk => __("Unstage this hunk [y,n,q,a,d,/%s,?]? "),
+ },
+ reset_nothead => {
+ mode => __("Apply mode change to index [y,n,q,a,d,/%s,?]? "),
+ deletion => __("Apply deletion to index [y,n,q,a,d,/%s,?]? "),
+ hunk => __("Apply this hunk to index [y,n,q,a,d,/%s,?]? "),
+ },
+ checkout_index => {
+ mode => __("Discard mode change from worktree [y,n,q,a,d,/%s,?]? "),
+ deletion => __("Discard deletion from worktree [y,n,q,a,d,/%s,?]? "),
+ hunk => __("Discard this hunk from worktree [y,n,q,a,d,/%s,?]? "),
+ },
+ checkout_head => {
+ mode => __("Discard mode change from index and worktree [y,n,q,a,d,/%s,?]? "),
+ deletion => __("Discard deletion from index and worktree [y,n,q,a,d,/%s,?]? "),
+ hunk => __("Discard this hunk from index and worktree [y,n,q,a,d,/%s,?]? "),
+ },
+ checkout_nothead => {
+ mode => __("Apply mode change to index and worktree [y,n,q,a,d,/%s,?]? "),
+ deletion => __("Apply deletion to index and worktree [y,n,q,a,d,/%s,?]? "),
+ hunk => __("Apply this hunk to index and worktree [y,n,q,a,d,/%s,?]? "),
+ },
+);
+
sub patch_update_file {
my $quit = 0;
my ($ix, $num);
@@ -1462,84 +1463,9 @@ sub patch_update_file {
for (@{$hunk[$ix]{DISPLAY}}) {
print;
}
- if ($patch_mode eq 'stage') {
- if ($hunk[$ix]{TYPE} eq 'mode') {
- print colored $prompt_color,
- sprintf(__("Stage mode change [y,n,q,a,d,/%s,?]? "), $other);
- } elsif ($hunk[$ix]{TYPE} eq 'deletion') {
- print colored $prompt_color,
- sprintf(__("Stage deletion [y,n,q,a,d,/%s,?]? "), $other);
- } else {
- print colored $prompt_color,
- sprintf(__("Stage this hunk [y,n,q,a,d,/%s,?]? "), $other);
- }
- } elsif ($patch_mode eq 'stash') {
- if ($hunk[$ix]{TYPE} eq 'mode') {
- print colored $prompt_color,
- sprintf(__("Stash mode change [y,n,q,a,d,/%s,?]? "), $other);
- } elsif ($hunk[$ix]{TYPE} eq 'deletion') {
- print colored $prompt_color,
- sprintf(__("Stash deletion [y,n,q,a,d,/%s,?]? "), $other);
- } else {
- print colored $prompt_color,
- sprintf(__("Stash this hunk [y,n,q,a,d,/%s,?]? "), $other);
- }
- } elsif ($patch_mode eq 'reset_head') {
- if ($hunk[$ix]{TYPE} eq 'mode') {
- print colored $prompt_color,
- sprintf(__("Unstage mode change [y,n,q,a,d,/%s,?]? "), $other);
- } elsif ($hunk[$ix]{TYPE} eq 'deletion') {
- print colored $prompt_color,
- sprintf(__("Unstage deletion [y,n,q,a,d,/%s,?]? "), $other);
- } else {
- print colored $prompt_color,
- sprintf(__("Unstage this hunk [y,n,q,a,d,/%s,?]? "), $other);
- }
- } elsif ($patch_mode eq 'reset_nothead') {
- if ($hunk[$ix]{TYPE} eq 'mode') {
- print colored $prompt_color,
- sprintf(__("Apply mode change to index [y,n,q,a,d,/%s,?]? "), $other);
- } elsif ($hunk[$ix]{TYPE} eq 'deletion') {
- print colored $prompt_color,
- sprintf(__("Apply deletion to index [y,n,q,a,d,/%s,?]? "), $other);
- } else {
- print colored $prompt_color,
- sprintf(__("Apply this hunk to index [y,n,q,a,d,/%s,?]? "), $other);
- }
- } elsif ($patch_mode eq 'checkout_index') {
- if ($hunk[$ix]{TYPE} eq 'mode') {
- print colored $prompt_color,
- sprintf(__("Discard mode change from worktree [y,n,q,a,d,/%s,?]? "), $other);
- } elsif ($hunk[$ix]{TYPE} eq 'deletion') {
- print colored $prompt_color,
- sprintf(__("Discard deletion from worktree [y,n,q,a,d,/%s,?]? "), $other);
- } else {
- print colored $prompt_color,
- sprintf(__("Discard this hunk from worktree [y,n,q,a,d,/%s,?]? "), $other);
- }
- } elsif ($patch_mode eq 'checkout_head') {
- if ($hunk[$ix]{TYPE} eq 'mode') {
- print colored $prompt_color,
- sprintf(__("Discard mode change from index and worktree [y,n,q,a,d,/%s,?]? "), $other);
- } elsif ($hunk[$ix]{TYPE} eq 'deletion') {
- print colored $prompt_color,
- sprintf(__("Discard deletion from index and worktree [y,n,q,a,d,/%s,?]? "), $other);
- } else {
- print colored $prompt_color,
- sprintf(__("Discard this hunk from index and worktree [y,n,q,a,d,/%s,?]? "), $other);
- }
- } elsif ($patch_mode eq 'checkout_nothead') {
- if ($hunk[$ix]{TYPE} eq 'mode') {
- print colored $prompt_color,
- sprintf(__("Apply mode change to index and worktree [y,n,q,a,d,/%s,?]? "), $other);
- } elsif ($hunk[$ix]{TYPE} eq 'deletion') {
- print colored $prompt_color,
- sprintf(__("Apply deletion to index and worktree [y,n,q,a,d,/%s,?]? "), $other);
- } else {
- print colored $prompt_color,
- sprintf(__("Apply this hunk to index and worktree [y,n,q,a,d,/%s,?]? "), $other);
- }
- }
+ print colored $prompt_color,
+ sprintf($patch_update_prompt_modes{$patch_mode}{$hunk[$ix]{TYPE}}, $other);
+
my $line = prompt_single_character;
last unless defined $line;
if ($line) {
@@ -1580,8 +1506,8 @@ sub patch_update_file {
} elsif (0 < $response && $response <= $num) {
$ix = $response - 1;
} else {
- error_msg sprintf(__("Sorry, only %s hunks available.\n"),
- $num);
+ error_msg sprintf(__n("Sorry, only %d hunk available.\n",
+ "Sorry, only %d hunks available.\n", $num), $num);
}
next;
}
@@ -1677,7 +1603,7 @@ sub patch_update_file {
my @split = split_hunk($hunk[$ix]{TEXT}, $hunk[$ix]{DISPLAY});
if (1 < @split) {
print colored $header_color, sprintf(
- Q__("Split into %d hunk.\n",
+ __n("Split into %d hunk.\n",
"Split into %d hunks.\n",
scalar(@split)), scalar(@split));
}
@@ -1745,14 +1671,16 @@ sub quit_cmd {
}
sub help_cmd {
- print colored $help_color, __(
-"status - show paths with changes
+# TRANSLATORS: please do not translate the command names
+# 'status', 'update', 'revert', etc.
+ print colored $help_color, __ <<'EOF' ;
+status - show paths with changes
update - add working tree state to the staged set of changes
revert - revert staged set of changes back to the HEAD version
patch - pick hunks and update selectively
diff - view diff between HEAD and index
-add untracked - add contents of untracked files to the staged set of changes"),
-"\n";
+add untracked - add contents of untracked files to the staged set of changes
+EOF
}
sub process_args {
diff --git a/git-difftool.perl b/git-difftool.perl
index 0140c66..8d3632e 100755
--- a/git-difftool.perl
+++ b/git-difftool.perl
@@ -339,7 +339,7 @@ sub main
if (length($opts{difftool_cmd}) > 0) {
$ENV{GIT_DIFF_TOOL} = $opts{difftool_cmd};
} else {
- print "No <tool> given for --tool=<tool>\n";
+ print __("No <tool> given for --tool=<tool>\n");
usage(1);
}
}
@@ -347,7 +347,7 @@ sub main
if (length($opts{extcmd}) > 0) {
$ENV{GIT_DIFFTOOL_EXTCMD} = $opts{extcmd};
} else {
- print "No <cmd> given for --extcmd=<cmd>\n";
+ print __("No <cmd> given for --extcmd=<cmd>\n");
usage(1);
}
}
diff --git a/git-send-email.perl b/git-send-email.perl
index d4c72a9..5c01425 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -772,8 +772,8 @@ sub ask {
return $resp;
}
if ($confirm_only) {
- # TRANSLATORS: Keep [y/N] as is.
my $yesno = $term->readline(
+ # TRANSLATORS: please keep [y/N] as is.
sprintf(__("Are you sure you want to use <%s> [y/N]? "), $resp));
if (defined $yesno && $yesno =~ /y/i) {
return $resp;
@@ -816,9 +816,9 @@ if (!defined $auto_8bit_encoding && scalar %broken_encoding) {
if (!$force) {
for my $f (@files) {
if (get_patch_subject($f) =~ /\Q*** SUBJECT HERE ***\E/) {
- die "Refusing to send because the patch\n\t$f\n"
+ die sprintf(__("Refusing to send because the patch\n\t%s\n"
. "has the template subject '*** SUBJECT HERE ***'. "
- . "Pass --force if you really want to send.\n";
+ . "Pass --force if you really want to send.\n"), $f);
}
}
}
@@ -1311,8 +1311,7 @@ Message-Id: $message_id
For additional information, run 'git send-email --help'.
To retain the current behavior, but squelch this message,
- run 'git config --global sendemail.confirm auto'."),
-"\n\n";
+ run 'git config --global sendemail.confirm auto'."), "\n\n";
}
# TRANSLATORS: Make sure to include [y] [n] [q] [a] in your
# translation. The program will only accept English input
@@ -1396,8 +1395,8 @@ Message-Id: $message_id
}
if (!$smtp) {
- die "Unable to initialize SMTP properly. Check config and use --smtp-debug. ",
- "VALUES: server=$smtp_server ",
+ die __("Unable to initialize SMTP properly. Check config and use --smtp-debug."),
+ " VALUES: server=$smtp_server ",
"encryption=$smtp_encryption ",
"hello=$smtp_domain",
defined $smtp_server_port ? " port=$smtp_server_port" : "";
@@ -1414,12 +1413,12 @@ Message-Id: $message_id
$smtp->datasend("$line") or die $smtp->message;
}
$smtp->dataend() or die $smtp->message;
- $smtp->code =~ /250|200/ or die "Failed to send $subject\n".$smtp->message;
+ $smtp->code =~ /250|200/ or die sprintf(__("Failed to send %s\n"), $subject).$smtp->message;
}
if ($quiet) {
- printf (($dry_run ? "Dry-" : ""). __("Sent %s\n"), $subject);
+ printf($dry_run ? __("Dry-Sent %s\n") : __("Sent %s\n"), $subject);
} else {
- print (($dry_run ? "Dry-" : ""). __("OK. Log says:\n"));
+ print($dry_run ? __("Dry-OK. Log says:\n") : __("OK. Log says:\n"));
if (!file_name_is_absolute($smtp_server)) {
print "Server: $smtp_server\n";
print "MAIL FROM:<$raw_from>\n";
@@ -1669,7 +1668,7 @@ sub recipients_cmd {
my @addresses = ();
open my $fh, "-|", "$cmd \Q$file\E"
- or die "($prefix) Could not execute '$cmd'";
+ or die sprintf(__("(%s) Could not execute '%s'"), $prefix, $cmd);
while (my $address = <$fh>) {
$address =~ s/^\s*//g;
$address =~ s/\s*$//g;
@@ -1753,10 +1752,11 @@ sub handle_backup {
(substr($file, 0, $lastlen) eq $last) &&
($suffix = substr($file, $lastlen)) !~ /^[a-z0-9]/i) {
if (defined $known_suffix && $suffix eq $known_suffix) {
- print "Skipping $file with backup suffix '$known_suffix'.\n";
+ printf(__("Skipping %s with backup suffix '%s'.\n"), $file, $known_suffix);
$skip = 1;
} else {
- my $answer = ask("Do you really want to send $file? (y|N): ",
+ # TRANSLATORS: please keep "[y|N]" as is.
+ my $answer = ask(sprintf(__("Do you really want to send %s? [y|N]: "), $file),
valid_re => qr/^(?:y|n)/i,
default => 'n');
$skip = ($answer ne 'y');
diff --git a/perl/Git/I18N.pm b/perl/Git/I18N.pm
index 5a75dd5..3f7ac25 100644
--- a/perl/Git/I18N.pm
+++ b/perl/Git/I18N.pm
@@ -13,7 +13,7 @@ BEGIN {
}
}
-our @EXPORT = qw(__ Q__);
+our @EXPORT = qw(__ __n);
our @EXPORT_OK = @EXPORT;
sub __bootstrap_locale_messages {
@@ -44,7 +44,7 @@ BEGIN
eval {
__bootstrap_locale_messages();
*__ = \&Locale::Messages::gettext;
- *Q__ = \&Locale::Messages::ngettext;
+ *__n = \&Locale::Messages::ngettext;
1;
} or do {
# Tell test.pl that we couldn't load the gettext library.
@@ -52,7 +52,7 @@ BEGIN
# Just a fall-through no-op
*__ = sub ($) { $_[0] };
- *Q__ = sub ($$$) { $_[2] == 1 ? $_[0] : $_[1] };
+ *__n = sub ($$$) { $_[2] == 1 ? $_[0] : $_[1] };
};
}
@@ -72,6 +72,8 @@ Git::I18N - Perl interface to Git's Gettext localizations
printf __("The following error occurred: %s\n"), $error;
+ printf __n("commited %d file", "commited %d files", $files), $files;
+
=head1 DESCRIPTION
Git's internal Perl interface to gettext via L<Locale::Messages>. If
@@ -89,6 +91,9 @@ it.
L<Locale::Messages>'s gettext function if all goes well, otherwise our
passthrough fallback function.
+=head2 __n($$$)
+L<Locale::Messages>'s ngettext function or passthrough fallback function.
+
=head1 AUTHOR
E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason <avarab@gmail.com>
diff --git a/t/t0202/test.pl b/t/t0202/test.pl
index 98aa9a3..4101833 100755
--- a/t/t0202/test.pl
+++ b/t/t0202/test.pl
@@ -31,7 +31,7 @@ is_deeply(\@Git::I18N::EXPORT, \@Git::I18N::EXPORT_OK, "sanity: Git::I18N export
# more gettext wrapper functions.
my %prototypes = (qw(
__ $
- Q__ $$$
+ __n $$$
));
while (my ($sub, $proto) = each %prototypes) {
is(prototype(\&{"Git::I18N::$sub"}), $proto, "sanity: $sub has a $proto prototype");
@@ -51,10 +51,10 @@ is_deeply(\@Git::I18N::EXPORT, \@Git::I18N::EXPORT_OK, "sanity: Git::I18N export
my ($got_singular, $got_plural, $expect_singular, $expect_plural) =
(('TEST: 1 file', 'TEST: n files') x 2);
- is(Q__($got_singular, $got_plural, 1), $expect_singular,
- "Get singular string through Q__() in C locale");
- is(Q__($got_singular, $got_plural, 2), $expect_plural,
- "Get plural string through Q__() in C locale");
+ is(__n($got_singular, $got_plural, 1), $expect_singular,
+ "Get singular string through __n() in C locale");
+ is(__n($got_singular, $got_plural, 2), $expect_plural,
+ "Get plural string through __n() in C locale");
}
# Test a basic message on different locales
--
2.7.4
^ permalink raw reply related
* Re: git commit -p with file arguments
From: Junio C Hamano @ 2016-10-05 17:16 UTC (permalink / raw)
To: Duy Nguyen; +Cc: Christian Neukirchen, Git Mailing List
In-Reply-To: <20161005102633.GA9948@ash>
Duy Nguyen <pclouds@gmail.com> writes:
>> At the least I think we should clarify this in the document.
>
> How about something like this? Would it help?
>
> -- 8< --
> Subject: [PATCH] git-commit.txt: clarify --patch mode with pathspec
>
> How pathspec is used, with and without --interactive/--patch, is
> different. But this is not clear from the document. These changes hint
> the user to keep reading (to option #5) instead of stopping at #2 and
> assuming --patch/--interactive behaves the same way.
>
> And since all the options listed here always mention how the index is
> involved (or not) in the final commit, add that bit for #5 as well. This
> "on top of the index" is implied when you head over git-add(1), but if
> you just go straight to the "Interactive mode" and not read what git-add
> is for, you may miss it.
>
> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
> ---
Excellent.
> Documentation/git-commit.txt | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
> index b0a294d..f2ab0ee 100644
> --- a/Documentation/git-commit.txt
> +++ b/Documentation/git-commit.txt
> @@ -29,7 +29,8 @@ The content to be added can be specified in several ways:
> 2. by using 'git rm' to remove files from the working tree
> and the index, again before using the 'commit' command;
>
> -3. by listing files as arguments to the 'commit' command, in which
> +3. by listing files as arguments to the 'commit' command
> + (without --interactive or --patch switch), in which
> case the commit will ignore changes staged in the index, and instead
> record the current content of the listed files (which must already
> be known to Git);
> @@ -41,7 +42,8 @@ The content to be added can be specified in several ways:
> actual commit;
>
> 5. by using the --interactive or --patch switches with the 'commit' command
> - to decide one by one which files or hunks should be part of the commit,
> + to decide one by one which files or hunks should be part of the commit
> + in addition to contents in the index,
> before finalizing the operation. See the ``Interactive Mode'' section of
> linkgit:git-add[1] to learn how to operate these modes.
When re-reading these 5 bullet points, I feel there may be some
unrelated updates needed to clarify (e.g. it is unclear when reading
the description pretending to be a newbie, if it is the "changes"
that is recorded in the index, or if it is the "state"; the answer
is the latter but if the reader's world model is still the former,
the description can mislead to expect a different behaviour).
But regardless of such remaining potential issues, this is a clearly
good change. Thanks.
^ permalink raw reply
* Re: [RFC/PATCH] attr: Document a new possible thread safe API
From: Stefan Beller @ 2016-10-05 17:04 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git@vger.kernel.org, Brandon Williams
In-Reply-To: <xmqq8tu2ras4.fsf@gitster.mtv.corp.google.com>
On Wed, Oct 5, 2016 at 10:00 AM, Junio C Hamano <gitster@pobox.com> wrote:
> Stefan Beller <sbeller@google.com> writes:
>
>> I thought about that, but as I concluded that the get_all_attrs doesn't need
>> conversion to a threading environment, we can keep it as is.
>
> I agree that it is OK for get_all_attrs() to use its own way to ask
> a question and receive an answer to it, that is different from how
> git_check_attr() asks its question. The threading-support for it is
> an unrelated issue, though (not that I think it needs to be run from
> a multi-threaded caller).
>
>>> ... I'd expect the most
>>> typical caller to be
>>>
>>> static struct git_attr_check *check;
>>> struct git_attr_result result[2]; /* we want two */
>>>
>>> git_attr_check_initl(&check, "crlf", "ident", NULL);
>>> git_check_attr(path, check, result);
>>> /* result[0] has "crlf", result[1] has "ident" */
>>>
>>> or something like that.
>>
>> I see, that seems to be a clean API. So git_attr_check_initl
>> will lock the mutex and once it got the mutex it can either
>> * return early as someone else did the work
>> * needs to do the actual work
>> and then unlock. In any case the work was done.
>>
>> git_check_attr, which runs in all threads points to the same check,
>> but gets the different results.
>
> Yeah, something along that line. It seems that we are now on the
> same page?
>
I think so, instead of resending the documentation, maybe the header
file shows that we're on the same page, I converted everything except
attr.c to follow this header attr.h:
---8<---
#ifndef ATTR_H
#define ATTR_H
/* An attribute is a pointer to this opaque structure */
struct git_attr;
/*
* Given a string, return the gitattribute object that
* corresponds to it.
*/
extern struct git_attr *git_attr(const char *);
/*
* Return the name of the attribute represented by the argument. The
* return value is a pointer to a null-delimited string that is part
* of the internal data structure; it should not be modified or freed.
*/
extern const char *git_attr_name(const struct git_attr *);
extern int attr_name_valid(const char *name, size_t namelen);
extern void invalid_attr_name_message(struct strbuf *, const char *, int);
/* Internal use */
extern const char git_attr__true[];
extern const char git_attr__false[];
/* For public to check git_attr_check results */
#define ATTR_TRUE(v) ((v) == git_attr__true)
#define ATTR_FALSE(v) ((v) == git_attr__false)
#define ATTR_UNSET(v) ((v) == NULL)
struct git_attr_check {
int finalized;
int check_nr;
int check_alloc;
struct git_attr **attr;
};
struct git_attr_result {
int check_nr;
int check_alloc;
const char **value;
};
/*
* Initialize the `git_attr_check` via one of the following three functions:
*
* git_attr_check_alloc allocates an empty check, add more attributes via
* git_attr_check_append.
* git_all_attrs allocates a check and fills in all attributes that
* are set for the given path.
* git_attr_check_initl takes a pointer to where the check will be initialized,
* followed by all attributes that are to be checked.
* This makes it potentially thread safe as it could
* internally have a mutex for that memory location.
* Currently it is not thread safe!
*/
extern struct git_attr_check *git_attr_check_alloc(void);
extern void git_attr_check_append(struct git_attr_check *, const
struct git_attr *);
extern struct git_attr_check *git_all_attrs(const char *path);
extern void git_attr_check_initl(struct git_attr_check **, const char *, ...);
/* Query a path for its attributes */
extern struct git_attr_result *git_check_attr(const char *path,
struct git_attr_check *);
/* internal? */
extern void git_attr_check_clear(struct git_attr_check *);
/* After use free the check */
extern void git_attr_check_free(struct git_attr_check *);
enum git_attr_direction {
GIT_ATTR_CHECKIN,
GIT_ATTR_CHECKOUT,
GIT_ATTR_INDEX
};
void git_attr_set_direction(enum git_attr_direction, struct index_state *);
#endif /* ATTR_H */
^ permalink raw reply
* Re: [PATCH 5/5] versioncmp: cope with common leading parts in versionsort.prereleaseSuffix
From: Junio C Hamano @ 2016-10-05 17:01 UTC (permalink / raw)
To: SZEDER Gábor
Cc: Jeff King, Leho Kraav, Nguyễn Thái Ngọc Duy, git
In-Reply-To: <20161005033353.Horde.33pf2naqnF4HgwPWSy9DaHV@webmail.informatik.kit.edu>
SZEDER Gábor <szeder@ira.uka.de> writes:
> And a final sidenote: sorting based on the longest matching suffix
> also allows us to (ab)use version sort with prerelease suffixes to
> sort postrelease tags as we please, too:
>
> $ ~/src/git/git -c versionsort.prereleasesuffix=-alpha \
> -c versionsort.prereleasesuffix=-beta \
> -c versionsort.prereleasesuffix= \
> -c versionsort.prereleasesuffix=-gamma \
> -c versionsort.prereleasesuffix=-delta \
> tag -l --sort=version:refname 'v3.0*'
> v3.0-alpha1
> v3.0-beta1
> v3.0
> v3.0-gamma1
> v3.0-delta1
Assuming that gamma and delta are meant to indicate "these are
post-release updates", I think a mechanism that can yield the above
result is fantastic ;-)
^ permalink raw reply
* Re: [RFC/PATCH] attr: Document a new possible thread safe API
From: Junio C Hamano @ 2016-10-05 17:00 UTC (permalink / raw)
To: Stefan Beller; +Cc: git@vger.kernel.org, Brandon Williams
In-Reply-To: <CAGZ79kaFx++yipGmq=D2EPN4Gw9JhRXf_i4pFivTnkJmJXjFfg@mail.gmail.com>
Stefan Beller <sbeller@google.com> writes:
> I thought about that, but as I concluded that the get_all_attrs doesn't need
> conversion to a threading environment, we can keep it as is.
I agree that it is OK for get_all_attrs() to use its own way to ask
a question and receive an answer to it, that is different from how
git_check_attr() asks its question. The threading-support for it is
an unrelated issue, though (not that I think it needs to be run from
a multi-threaded caller).
>> ... I'd expect the most
>> typical caller to be
>>
>> static struct git_attr_check *check;
>> struct git_attr_result result[2]; /* we want two */
>>
>> git_attr_check_initl(&check, "crlf", "ident", NULL);
>> git_check_attr(path, check, result);
>> /* result[0] has "crlf", result[1] has "ident" */
>>
>> or something like that.
>
> I see, that seems to be a clean API. So git_attr_check_initl
> will lock the mutex and once it got the mutex it can either
> * return early as someone else did the work
> * needs to do the actual work
> and then unlock. In any case the work was done.
>
> git_check_attr, which runs in all threads points to the same check,
> but gets the different results.
Yeah, something along that line. It seems that we are now on the
same page?
Thanks.
^ permalink raw reply
* Re: [PATCH 5/6] Documentation/git-merge.txt: improve short description in DESCRIPTION
From: Jakub Narębski @ 2016-10-05 16:58 UTC (permalink / raw)
To: Sergey Organov, git; +Cc: Junio C Hamano
In-Reply-To: <e74ae8afc1bfc4cd9161ccaa56d926a89439551e.1475678515.git.sorganov@gmail.com>
W dniu 05.10.2016 o 16:46, sorganov@gmail.com pisze:
> From: Sergey Organov <sorganov@gmail.com>
>
> Old description had a few problems:
>
> - sounded as if commits have changes
>
> - stated that changes are taken since some "divergence point"
> that was not defined.
>
> New description rather uses "common ancestor" and "merge base",
> definitions of which are easily discoverable in the rest of GIT
> documentation.
This is a step in a good direction, but it has a few issues.
>
> Signed-off-by: Sergey Organov <sorganov@gmail.com>
> ---
> Documentation/git-merge.txt | 25 +++++++++++++++----------
> 1 file changed, 15 insertions(+), 10 deletions(-)
>
> diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt
> index cc0329d..351b8fc 100644
> --- a/Documentation/git-merge.txt
> +++ b/Documentation/git-merge.txt
> @@ -16,11 +16,16 @@ SYNOPSIS
>
> DESCRIPTION
> -----------
> -Incorporates changes from the named commits (since the time their
> -histories diverged from the current branch) into the current
> -branch. This command is used by 'git pull' to incorporate changes
> -from another repository and can be used by hand to merge changes
> -from one branch into another.
> +
> +Incorporates changes that lead to the named commits into the current
> +branch, and joins corresponding histories. The best common ancestor of
> +named commits and the current branch, called "merge base", is
> +calculated, and then net changes taken from the merge base to
> +the named commits are applied.
The first sentence is all right; it reads better than the original
without the introduced part in parentheses. The only minor issue
is with "joins corresponding histories" - it is a good description,
but may imply that the branch we are merging vanishes: it doesn't.
But all in all, it is a good change.
Second sentence has some problems. First, while it is a good idea
to use well defined term "merge base", I think writing "since the
time their histories diverged" or "(which is the point where histories
diverged)" would be a good plain language description; it was removed
entirely in the proposal.
Second, while "common ancestor" and "least common ancestor" are well
defined in mathematics of graphs, "best common ancestor" isn't...
but this is what git-merge-base(1) documentation uses.
Also, the "best common ancestor" doesn't need to be only one. There
might be many such ancestors... though Git would generate then a
virtual best common ancestor thanks to recursive merge strategy.
And usually there is only one "best common ancestor", that is a single
merge base. So this may need clarification, but it is not much of
a problem.
Third, and most important, is that "net changes taken from the merge
base to the named commits are applied" is simply not true. The
`git merge` command does not reapply changes - that is what rebase
and cherry-pick do. The merge operation uses 3-way merge strategy
(diff3) between merge-base, current branch, and merged commit.
That is, it finds differences between differences, and "applies"
that.
See "A Formal Investigation of Diff3" paper by Sanjeev Khanna,
Keshav Kunal, and Benjamin C. Pierce:
http://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf
I'm not sure how to explain it succintly. Perhaps
net changes between merge base to the current (merged into)
branch and named commits are integrated
There is description of trivial 3-way merge somewhere in Git docs,
though in very unobvious place; we can link it.
> +
> +This command is used by 'git pull' to incorporate changes from another
> +repository, and can be used by hand to merge changes from one branch
> +into another.
Rather "can be used by 'git pull'", or "is used by 'git pull' (unless
configured otherwise)"...
Separating this information makes a very good sense. Thanks.
>
> Assume the following history exists and the current branch is
> "`master`":
> @@ -31,11 +36,11 @@ Assume the following history exists and the current branch is
> D---E---F---G master
> ------------
>
> -Then "`git merge topic`" will replay the changes made on the
> -`topic` branch since it diverged from `master` (i.e., `E`) until
> -its current commit (`C`) on top of `master`, and record the result
> -in a new commit along with the names of the two parent commits and
> -a log message from the user describing the changes.
> +Then "`git merge topic`" will replay the changes made on the `topic`
> +branch since it diverged from `master` (i.e., `E`) until its current
> +commit (`C`) on top of `master`, and record the result in a new commit
> +along with references to the two parent commits and a log message from
> +the user describing the changes.
What the happened here!?! Please do not rewrap documentation, especially
not without changes!
>
> ------------
> A---B---C topic
>
--
Jakub Narębski
^ permalink raw reply
* Re: [PATCH] clone: detect errors in normalize_path_copy
From: Stefan Beller @ 2016-10-05 16:48 UTC (permalink / raw)
To: Jeff King; +Cc: git@vger.kernel.org
In-Reply-To: <20161005142929.l7fy3jxkme4iwunc@sigill.intra.peff.net>
On Wed, Oct 5, 2016 at 7:29 AM, Jeff King <peff@peff.net> wrote:
> When we are copying the alternates from the source
> repository, if we find a relative path that is too deep for
> the source (e.g., "../../../objects" from "/repo.git/objects"),
> then normalize_path_copy will report an error and leave
> trash in the buffer, which we will add to our new alternates
> file. Instead, let's detect the error, print a warning, and
> skip copying that alternate.
>
> There's no need to die. The relative path is probably just
> broken cruft in the source repo. If it turns out to have
> been important for accessing some objects, we rely on other
> parts of the clone to detect that, just as they would with a
> missing object in the source repo itself (though note that
> clones with "-s" are inherently local, which may do fewer
> object-quality checks in the first place).
This explanation and the implementation make sense.
Thanks!
>
> Signed-off-by: Jeff King <peff@peff.net>
> ---
> Noticed by coverity;
I saw them, too and wanted to start preparing a patch,
but I cannot quite compete with your speed here. ;)
> the recent alternates cleanups mean that all of the
> other calls to normalize_path_copy() are now checked, so it realized
> this one was an oddball and probably an error (I actually looked for
> others with `grep` when doing that series, but somehow missed this one;
> hooray for static analysis). The fix is independent of that series.
>
> builtin/clone.c | 7 +++++--
> 1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/builtin/clone.c b/builtin/clone.c
> index fb75f7e..6cf3b54 100644
> --- a/builtin/clone.c
> +++ b/builtin/clone.c
> @@ -345,8 +345,11 @@ static void copy_alternates(struct strbuf *src, struct strbuf *dst,
> continue;
> }
> abs_path = mkpathdup("%s/objects/%s", src_repo, line.buf);
> - normalize_path_copy(abs_path, abs_path);
> - add_to_alternates_file(abs_path);
> + if (!normalize_path_copy(abs_path, abs_path))
> + add_to_alternates_file(abs_path);
> + else
> + warning("skipping invalid relative alternate: %s/%s",
> + src_repo, line.buf);
> free(abs_path);
> }
> strbuf_release(&line);
> --
> 2.10.1.506.g904834d
^ permalink raw reply
* Re: [PATCH 06/18] t5613: clarify "too deep" recursion tests
From: Jacob Keller @ 2016-10-05 16:47 UTC (permalink / raw)
To: Jeff King
Cc: Jakub Narębski, Junio C Hamano, Stefan Beller,
Git mailing list, René Scharfe
In-Reply-To: <20161005144028.tjuvk3hkoqm3qjfd@sigill.intra.peff.net>
On Wed, Oct 5, 2016 at 7:40 AM, Jeff King <peff@peff.net> wrote:
> On Wed, Oct 05, 2016 at 03:58:53PM +0200, Jakub Narębski wrote:
>
>> I would prefer the following:
>>
>> # A --> B --> C --> D --> E --> F --> G --> H
>> # 0 1 2 3 4 5 6
>
> Yeah, that is also more visually pleasing.
>
> Here's a squashable update that uses that and clarifies the points in
> the discussion with Jacob.
>
> Junio, do you mind squashing this in to jk/alt-odb-cleanup?
>
> diff --git a/t/t5613-info-alternate.sh b/t/t5613-info-alternate.sh
> index b393613..62170b7 100755
> --- a/t/t5613-info-alternate.sh
> +++ b/t/t5613-info-alternate.sh
> @@ -39,13 +39,16 @@ test_expect_success 'preparing third repository' '
> )
> '
>
> -# Note: These tests depend on the hard-coded value of 5 as "too deep". We start
> -# the depth at 0 and count links, not repositories, so in a chain like:
> +# Note: These tests depend on the hard-coded value of 5 as the maximum depth
> +# we will follow recursion. We start the depth at 0 and count links, not
> +# repositories. This means that in a chain like:
> #
> -# A -> B -> C -> D -> E -> F -> G -> H
> -# 0 1 2 3 4 5 6
> +# A --> B --> C --> D --> E --> F --> G --> H
> +# 0 1 2 3 4 5 6
Yea this looks much better (when I view it locally, gmail still looks
aweful here but...)
> #
> -# we are OK at "G", but break at "H".
> +# we are OK at "G", but break at "H", even though "H" is actually the 8th
> +# repository, not the 6th, which you might expect. Counting the links allows
> +# N+1 repositories, and counting from 0 to 5 inclusive allows 6 links.
> #
... This is much more clear wording that helps me understand this a
lot more. Thanks!
Regards,
Jake
> # Note also that we must use "--bare -l" to make the link to H. The "-l"
> # ensures we do not do a connectivity check, and the "--bare" makes sure
> @@ -59,11 +62,11 @@ test_expect_success 'creating too deep nesting' '
> git clone --bare -l -s G H
> '
>
> -test_expect_success 'validity of fifth-deep repository' '
> +test_expect_success 'validity of seventh repository' '
> git -C G fsck
> '
>
> -test_expect_success 'invalidity of sixth-deep repository' '
> +test_expect_success 'invalidity of eighth repository' '
> test_must_fail git -C H fsck
> '
>
^ permalink raw reply
* RE: [musl] Re: Regression: git no longer works with musl libc's regex impl
From: writeonce @ 2016-10-05 16:37 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: musl, git, Jeff King
Hi Johannes,
>
>
> -------- Original Message --------
> Subject: RE: [musl] Re: Regression: git no longer works with musl libc's
> regex impl
> From: Johannes Schindelin <Johannes.Schindelin@gmx.de>
> Date: Wed, October 05, 2016 3:49 am
> To: writeonce@midipix.org
> Cc: musl@lists.openwall.com, git@vger.kernel.org, Jeff King
> <peff@peff.net>
>
> Hi writeonce,
>
> On Tue, 4 Oct 2016, writeonce@midipix.org wrote:
>
> > < On Tue, 4 Oct 2016, Rich Felker wrote:
> > <
> > < > On Tue, Oct 04, 2016 at 11:27:22AM -0400, Jeff King wrote:
> > < > > On Tue, Oct 04, 2016 at 11:08:48AM -0400, Rich Felker wrote:
> > < > >
> > < > > > 1. is nonzero mod page size, it just works; the remainder of the
> > < > > > last page reads as zero bytes when mmapped.
> > < > >
> > < > > Is that a portable assumption?
> > < >
> > < > Yes.
> > <
> > < No, it is not. You quote POSIX, but the matter of the fact is that we
> > < use a subset of POSIX in order to be able to keep things running on
> > < Windows.
> >
> > As far as I can tell (and as the attached program may help demonstrate),
> > the above assumption has been valid on all versions of Windows since at
> > least Windows 2000.
>
> And since W2K is already past its end of life, it would be safe for
> practical considerations.
>
> However, I have to add two comments to that:
>
> - it is *not* guaranteed. The behavior is undefined, even if you see
> consistent behavior so far. Future Windows versions might break that
> assumption freely, though.
>
That is of course the official language, and generally speaking a good
rule of thumb. However... there is enough information to suggest that
when it comes to mapping of file-backed sections, the NT kernel
developers will choose to keep things the way they are. In brief, here's
why:
Given a "gray zone" that spans from EOF to end-of-page, there are in
essence three possible behaviors:
[1] bytes in the gray zone are accessible and are all zero's. This is
the current behavior.
[2] bytes in the gray zone are not accessible; trying to read past EOF
would result in a segfault.
[3] bytes in the gray zone are accessible but might contain random data
or junk.
Assessment:
[1] backward-compatible, POSIX-compliant, single code path for both
WIN32 and LXW.
[2] requires changing memory access granularity from 4096 bytes to a
single byte, and is therefore extremely costly.
[3] introduces a whole new class of security vulnerabilities, and will
thus be a lot of fun to watch:-)
All in all taken, then, I'd argue that relying on the current behavior
is very reasonable. If you, too, find the above assessment valid, and
since you mentioned that you were a Microsoft employee, it would be
great if you could make a good-faith effort to have the current behavior
added to the Driver Documentation and thus guaranteed.
PS. this isn't to say that the regex extension should or should not be
used, only that a decision on the matter should not be based on the
undocumentedness of current behavior.
midipix
> - some implementations of the REG_STARTEND feature have the nice property
> that they can read past NUL characters. Granted, not all of them do
> (AFAIU one example is FreeBSD itself, the first platform to sport
> REG_STARTEND), but we at least reap the benefit whenever using a regex
> that *can* read past NUL characters.
>
> > In this context, one thing to remember is that the page-size for the mod
> > operation is 4096, whereas the POSIX page-size (for the purpose of mmap
> > and mremap) is 65536.
>
> Indeed. A colleague of mine spotted the segfault when diffing a file that
> was *exactly* 4,096 bytes.
>
> > Note also that in the case of file-backed mapped sections, using
> > kernel32.dll or msvcrt.dll or cygwin/newlib or midipix/musl is of little
> > significance, specifically since all invoke ZwCreateSection and
> > ZwMapViewOfSection under the hood.
>
> Right. It's all backed by the very same kernel functions.
>
> Ciao,
> Johannes
^ permalink raw reply
* Re: [musl] Re: Regression: git no longer works with musl libc's regex impl
From: Rich Felker @ 2016-10-05 16:27 UTC (permalink / raw)
To: Jeff King; +Cc: James B, Johannes Schindelin, musl, git
In-Reply-To: <20161005161158.62o7qmpwxdgf6zzk@sigill.intra.peff.net>
On Wed, Oct 05, 2016 at 12:11:58PM -0400, Jeff King wrote:
> On Wed, Oct 05, 2016 at 10:59:34PM +1100, James B wrote:
>
> > Number downloads does not make first-tier platform. You know that as
> > well as everyone else.
> >
> > First-tier support is the decision made by the maintainers that the
> > entire features of the software must be available on those first tier
> > platforms. So if Windows is indeed first-tier platform for git, it
> > means any features that don't work on git version of Windows must not
> > be used/developed or even castrated. That's a scary thought.
>
> Prepare to be scared, then, I guess. Ever since the msysgit project
> started years ago, we have made concessions in the code to work both
> with POSIX-ish systems and with the msys layer. E.g., see how git-daemon
> does not fork(), but actually re-spawns itself to handle connections.
>
> When possible we try to put our abstractions at a level where they can
> be implemented in a performant way on all platforms (the git-daemon
> things is probably the _most_ ugly in that respect; I think nobody has
> really cared about the performance enough to add back in a forking code
> path for POSIX systems).
>
> > So this decision that "Windows is now a first-tier platform for git" -
> > is your own opinion, or is this the collective opinion of *all* the
> > git maintainers?
>
> There is only one maintainer of git: Junio. However, you'll note that I
> also used "we" in the paragraphs above. And that is because the approach
> I am talking about is something that has been done over the course of
> many years by many members of the development community.
>
> You may disagree with that approach, but it is nothing new. The msysgit
> project started in 2007.
The goal of the midipix project is to make the need for FOSS projects
supporting Windows to do hacks like this obsolete. It still has a
little ways to go to be ready for mainstream use, but it's already
running a lot, and I hope you'll consider it for the future since it
simplifies things A LOT when you can just write to POSIX instead of
having to come up with abstraction layers that cater to Windows'
brokenness.
> > Well thank you for being honest. I can see now why you responded the
> > way you did (and still do). By being employed by Microsoft, and
> > especially paid to work on Git for Windows, you have all the
> > incentives to make it work best on Windows, and to make it as its
> > first-tier platform within the limitation of Windows.
>
> Please don't insinuate that Johannes is a Microsoft shill. He has been
> working on the Windows port of Git for over 9 years, and was only
> employed by Microsoft this year. Furthermore, his original REG_STARTEND
> patch actually did a run-time fallback of NUL-terminating the input
> buffers. It was _I_ who suggested that we should simply push people
> towards our compat/regex routines instead. So if you want to be mad at
> somebody, be mad at me.
I hope we can get this thread away from accusing and attacking people
and on to doing productive things to make the software better.
Rich
^ permalink raw reply
* Re: [PATCH v3 3/6] Make the require_clean_work_tree() function reusable
From: Junio C Hamano @ 2016-10-05 16:23 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git
In-Reply-To: <alpine.DEB.2.20.1610051324270.35196@virtualbox>
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>> The function "git pull" uses to stop the user when the working
>> tree has changes is useful in other places.
>
> I stumbled over this sentence. How about
>
> The function used by "git pull" to stop [...]
>
> instead?
Perfect. Thanks.
^ permalink raw reply
* gitk and hook script
From: GAUTHIER Geoffrey @ 2016-10-05 8:45 UTC (permalink / raw)
To: git@vger.kernel.org
Hello,
I want to deploy a hook script to control format of commit message. For this I use the prepare-commit-msg script.
I want to check if the commit message starts with a number of 3 digits. If this is the case, the script returns 0, otherwise 1.
It works fine for an utilisation with the git command, but it doesn't when used with gitk. When script returns 1, the commit is not aborded. I don't manage to display message either (an information message explaining why commit will be abort).
Is there a way to use hook script with gitk?
Thanks.
PS: I use git version 1.8.5.3
________________________________
This electronic message and its attachments are confidential and transmitted for the exclusive use of their addressee. Should you receive this message by mistake, you are not authorized to use it for any purpose whatsoever; please delete it and notify the sender at once. LACROIX reserves the right to initiate any legal proceedings against any individual and organization in case of unauthorized use, without prejudice to possible criminal sanctions.
________________________________
Ce message et ses pièces jointes sont confidentiels et exclusivement transmis à l'usage de leur destinataire. Si vous recevez ce message par erreur, vous n’êtes pas autorisés à en faire une quelconque utilisation ; merci de le détruire et d'en avertir immédiatement l'expéditeur. LACROIX se réserve le droit de poursuivre toute entité, personne physique ou morale qui en ferait un usage non autorisé, sans préjudice d'éventuelles sanctions pénales.
^ permalink raw reply
* Re: [musl] Re: Regression: git no longer works with musl libc's regex impl
From: Rich Felker @ 2016-10-05 16:15 UTC (permalink / raw)
To: Jakub Narębski; +Cc: musl, James B, Johannes Schindelin, Jeff King, git
In-Reply-To: <bc3da1a4-4b99-737f-050e-54ef5844c402@gmail.com>
On Wed, Oct 05, 2016 at 03:11:05PM +0200, Jakub Narębski wrote:
> W dniu 05.10.2016 o 00:33, Rich Felker pisze:
> > On Wed, Oct 05, 2016 at 09:06:25AM +1100, James B wrote:
> >> On Tue, 4 Oct 2016 18:08:33 +0200 (CEST)
> >> Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> >>>
> >>> No, it is not. You quote POSIX, but the matter of the fact is that we use
> >>> a subset of POSIX in order to be able to keep things running on Windows.
> >>>
> >>> And quite honestly, there are lots of reasons to keep things running on
> >>> Windows, and even to favor Windows support over musl support. Over four
> >>> million reasons: the Git for Windows users.
> >>
> >> Wow, I don't know that Windows is a git's first-tier platform now,
> >> and Linux/POSIX second. Are we talking about the same git that was
> >> originally written in Linus Torvalds, and is used to manage Linux
> >> kernel? Are you by any chance employed by Redmond, directly or
> >> indirectly?
> >>
> >> Sorry - can't help it.
>
> Windows is one of the major platforms, yes. I think there much, much
> more people using Git on Windows, than using Git with musl. More
> users = more important.
>
> Also, working with some inconvenience (requiring compilation with
> NO_REGEX=1) is better than not working at all.
>
> In CodingGuidelines we say:
>
> - Most importantly, we never say "It's in POSIX; we'll happily
> ignore your needs should your system not conform to it."
> We live in the real world.
>
> - However, we often say "Let's stay away from that construct,
> it's not even in POSIX".
I agree wholeheartedly with these points.
>
> - In spite of the above two rules, we sometimes say "Although
> this is not in POSIX, it (is so convenient | makes the code
> much more readable | has other good characteristics) and
> practically all the platforms we care about support it, so
> let's use it".
>
> The REG_STARTEND is 3rd point,
To begin with I wasn't clear that REG_STARDEND being nonstandard was
even noticed or compatibility considered when adding the dependency on
it, but it seems such discussion did take place and most targets have
it. Perhaps this means it should be proposed for standardization in
the next issue of POSIX.
> mmap shenningans looks like 1st...
>
> ....on the other hand midipix <writeonce@midipix.org> wrote in
> http://public-inbox.org/git/20161004200057.dc30d64f61e5ec441c34ffd4f788e58e.efa66ead67.wbe@email15.godaddy.com/
> that the proposed fix should work on all Windows version we are
> interested in (I think). Test program included / attached.
>
> The above-mentioned email also explains that the problem was
> caught on MS Windows; it triggers if file end falls on the mmapped
> page boundary, which is more likely to happen with 4096 mod size
> on Windows rather than 65536 mod size on Linux.
On Linux page-size (mmap granularity) varies by arch but it's 4k on
basically all archs that people care about. I think midipix's author
was talking about real page size on Windows (4k) vs the minimum
logical page size (mmap granularity) that can be used to get
POSIX-matching semantics in midipix (which is 64k due to some
technical reasons I forget, which he could probably remind me of).
> On the other hand, while the proposed solution of "add padding as
> to not end at page boundary, if necessary" doesn't have the
> performance impact of "memcpy into NUL-terminated buffer" that
> was originally proposed in patch series, it is still extra code
> to maintain.
*nod*
Rich
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox