Skip to content

Commit 277803a

Browse files
committed
Decode commit objects correctly
1 parent 4b17745 commit 277803a

File tree

6 files changed

+54
-17
lines changed

6 files changed

+54
-17
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ t/checkout/*
1212
test-project-packs/*
1313
test-project-packs2/*
1414
test-project/*
15+
test-encoding/*
1516
MANIFEST
1617
*~
1718

Makefile.PL

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,6 @@ requires 'MooseX::Types::Path::Class' => '0';
2626
requires 'namespace::autoclean';
2727

2828
test_requires 'Test::More' => '0.88';
29+
test_requires 'Test::utf8' => '0.02';
2930

3031
WriteAll;

lib/Git/PurePerl/Object/Commit.pm

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package Git::PurePerl::Object::Commit;
22
use Moose;
33
use MooseX::StrictConstructor;
44
use Moose::Util::TypeConstraints;
5+
use Encode qw/decode/;
56
use namespace::autoclean;
67

78
extends 'Git::PurePerl::Object';
@@ -16,6 +17,7 @@ has 'committer' =>
1617
( is => 'rw', isa => 'Git::PurePerl::Actor', required => 0 );
1718
has 'committed_time' => ( is => 'rw', isa => 'DateTime', required => 0 );
1819
has 'comment' => ( is => 'rw', isa => 'Str', required => 0 );
20+
has 'encoding' => ( is => 'rw', isa => 'Str', required => 0 );
1921

2022
my %method_map = (
2123
'tree' => 'tree_sha1',
@@ -28,27 +30,37 @@ sub BUILD {
2830
my $self = shift;
2931
return unless $self->content;
3032
my @lines = split "\n", $self->content;
33+
my %header;
3134
while ( my $line = shift @lines ) {
3235
last unless $line;
3336
my ( $key, $value ) = split ' ', $line, 2;
34-
if ( $key eq 'committer' or $key eq 'author' ) {
35-
my @data = split ' ', $value;
36-
my ( $email, $epoch, $tz ) = splice( @data, -3 );
37-
$email = substr( $email, 1, -1 );
38-
my $name = join ' ', @data;
39-
my $actor
40-
= Git::PurePerl::Actor->new( name => $name, email => $email );
41-
$self->$key($actor);
42-
$key = $method_map{$key};
43-
my $dt
44-
= DateTime->from_epoch( epoch => $epoch, time_zone => $tz );
45-
$self->$key($dt);
46-
} else {
47-
$key = $method_map{$key} || $key;
48-
$self->$key($value);
37+
push @{$header{$key}}, $value;
38+
}
39+
$header{encoding}
40+
||= [ $self->git->config->get(key => "i18n.commitEncoding") || "utf-8" ];
41+
my $encoding = $header{encoding}->[-1];
42+
for my $key (keys %header) {
43+
for my $value (@{$header{$key}}) {
44+
$value = decode($encoding, $value);
45+
if ( $key eq 'committer' or $key eq 'author' ) {
46+
my @data = split ' ', $value;
47+
my ( $email, $epoch, $tz ) = splice( @data, -3 );
48+
$email = substr( $email, 1, -1 );
49+
my $name = join ' ', @data;
50+
my $actor
51+
= Git::PurePerl::Actor->new( name => $name, email => $email );
52+
$self->$key($actor);
53+
$key = $method_map{$key};
54+
my $dt
55+
= DateTime->from_epoch( epoch => $epoch, time_zone => $tz );
56+
$self->$key($dt);
57+
} else {
58+
$key = $method_map{$key} || $key;
59+
$self->$key($value);
60+
}
4961
}
5062
}
51-
$self->comment( join "\n", @lines );
63+
$self->comment( decode($encoding, join "\n", @lines) );
5264
}
5365

5466

t/00_setup.t

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use warnings;
44
use Test::More;
55
use Archive::Extract;
66

7-
foreach my $name qw(test-project test-project-packs test-project-packs2) {
7+
foreach my $name qw(test-project test-project-packs test-project-packs2 test-encoding) {
88
next if -d $name;
99
my $ae = Archive::Extract->new( archive => "$name.tgz" );
1010
$ae->extract;

t/encoding.t

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!perl
2+
use strict;
3+
use warnings;
4+
use Test::More;
5+
use Git::PurePerl;
6+
use Test::utf8;
7+
8+
my $git = Git::PurePerl->new( directory => "test-encoding" );
9+
10+
for ([$git->master, "utf-8", $git->master->parent, "iso-8859-1"]) {
11+
my ($commit, $encoding) = @{$_};
12+
is( $commit->encoding, $encoding );
13+
for my $role (qw(author committer)) {
14+
is_flagged_utf8( $commit->$role->name );
15+
is_sane_utf8( $commit->$role->name );
16+
is( $commit->author->name, "T\x{e9}st User" );
17+
}
18+
is_flagged_utf8( $commit->comment );
19+
is_sane_utf8( $commit->comment );
20+
is( $commit->comment, "Touch\x{e9}");
21+
}
22+
23+
done_testing;

test-encoding.tgz

7.45 KB
Binary file not shown.

0 commit comments

Comments
 (0)