Fix for infinite loop bug in blame.
Dan Brook [Sun, 5 Jun 2011 21:18:22 +0000 (23:18 +0200)]
Previously blame would get stuck in an infinite loop when processing
an empty file. Conceivably this a bug in git-blame as file content should
begin with a tab, even if it's empty.

Also adding a commit to repo1 involves fiddling lots tests so I won't
be doing that again.

Thanks to autarch for flagging this up in the first place!

lib/Gitalist/Git/Object/Commit.pm
t/02git_CollectionOfRepositories_FromDirectory.t
t/02git_Repository.t
t/02git_object.t
t/json_view.t
t/lib/repositories/repo1/objects/d6/ddf8b26be63066e01d96a0922c87cd8d6e2270 [new file with mode: 0644]
t/lib/repositories/repo1/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 [new file with mode: 0644]
t/lib/repositories/repo1/objects/f6/fc60f3f43501e81ff865b425b3c6c5a4142dd2 [new file with mode: 0644]
t/lib/repositories/repo1/refs/heads/master
t/lib/repositories/working/README [deleted file]

index f8e2e4f..1fd472c 100644 (file)
@@ -180,9 +180,9 @@ class Gitalist::Git::Object::Commit
 
       my $commit = $commitdata{$sha1};
       my $line;
-      until(($line = shift @blameout) =~ s/^\t//) {
-        $commit->{$1} = $2
-         if $line =~ /^(\S+) (.*)/;
+
+      until(@blameout == 0 || ($line = shift @blameout) =~ s/^\t//) {
+        $commit->{$1} = $2 if $line =~ /^(\S+) (.*)/;
       }
 
       unless(exists $commit->{author_dt}) {
index e045a44..2b3417e 100644 (file)
@@ -26,9 +26,6 @@ use Path::Class;
 my $repoBare = Path::Class::Dir->new('t/lib/repositories/bare.git');
 ok( $repo->_is_git_repo( $repoBare ), 'is_git_repo true for bare git repo' );
 
-# 'working' is a working copy w/ git repo in the repository dir
-my $repoWorking = Path::Class::Dir->new('t/lib/repositories/working');
-
 # 'empty.git' is an empty directory in the repository dir
 my $repoEmpty = Path::Class::Dir->new('t/lib/repositories/empty.git');
 ok( ! $repo->_is_git_repo( $repoEmpty ), 'is_git_repo is false for empty dir' );
index ba86a79..885a490 100644 (file)
@@ -47,13 +47,13 @@ isa_ok($proj->last_change, 'DateTime', 'last_change');
 
 my %references = %{$proj->references};
 ok(keys %references >= 2, '->references hash has elements');
-is($references{'36c6c6708b8360d7023e8a1649c45bcf9b3bd818'}->[0], 'heads/master', 'reference looks ok');
+is($references{'36c6c6708b8360d7023e8a1649c45bcf9b3bd818'}->[0], 'tags/0.01', 'reference looks ok');
 my @heads = @{$proj->heads};
 ok(scalar @heads > 1, '->heads list has more than one element');
 my $head = $heads[1];
 isa_ok($head, 'Gitalist::Git::Head');
-is($proj->head_hash, '36c6c6708b8360d7023e8a1649c45bcf9b3bd818', 'head_hash for HEAD is correct');
-is($proj->head_hash('refs/heads/master'), '36c6c6708b8360d7023e8a1649c45bcf9b3bd818', 'head_hash for refs/heads/master is correct');
+is($proj->head_hash, 'd6ddf8b26be63066e01d96a0922c87cd8d6e2270', 'head_hash for HEAD is correct');
+is($proj->head_hash('refs/heads/master'), 'd6ddf8b26be63066e01d96a0922c87cd8d6e2270', 'head_hash for refs/heads/master is correct');
 is($proj->head_hash('rafs/head/mister'), undef, 'head_hash for rafs/head/mister is undef');
 
 ok(scalar @{$proj->tags} == 1, '->tags list has one element');
@@ -90,28 +90,26 @@ is_deeply $proj->pack,  {
     heads       => [
         {
             __CLASS__   => 'Gitalist::Git::Head',
+            committer   => 'Dan Brook <broq@cpan.org>',
+            last_change => '2011-06-05T23:00:44Z',
+            name        => 'master',
+            sha1        => 'd6ddf8b26be63066e01d96a0922c87cd8d6e2270',
+        },
+        {
+            __CLASS__   => 'Gitalist::Git::Head',
             committer   => 'Zachary Stevens <zts@cryptocracy.com>',
             last_change => '2009-11-12T19:00:34Z',
             name        => 'branch1',
             sha1        => '0710a7c8ee11c73e8098d08f9384c2a839c65e4e'
         },
-        {
-            __CLASS__   => 'Gitalist::Git::Head',
-            committer   => 'Florian Ragwitz <rafl@debian.org>',
-            last_change => '2007-03-06T20:44:35Z',
-            name        => 'master',
-            sha1        => '36c6c6708b8360d7023e8a1649c45bcf9b3bd818'
-        }
     ],
     is_bare     => 1,
-    last_change => '2009-11-12T19:00:34Z',
+    last_change => '2011-06-05T23:00:44Z',
     name        => 'repo1',
     owner       => "T\351st",
     references  => {
-        "36c6c6708b8360d7023e8a1649c45bcf9b3bd818" => [
-            'heads/master',
-            'tags/0.01'
-        ],
+        "d6ddf8b26be63066e01d96a0922c87cd8d6e2270" => ['heads/master'],
+        "36c6c6708b8360d7023e8a1649c45bcf9b3bd818" => ['tags/0.01'],
         "0710a7c8ee11c73e8098d08f9384c2a839c65e4e" => [ 'heads/branch1' ]
     },
     tags        => [ {
index 16521a0..d05a54c 100644 (file)
@@ -24,7 +24,7 @@ BEGIN {
     use_ok 'Gitalist::Git::Object::Blob';
     use_ok 'Gitalist::Git::Object::Commit';
     use_ok 'Gitalist::Git::Object::Tag';
-    }
+}
 
 my $object = Gitalist::Git::Object::Tree->new(
     repository => $repository,
@@ -54,7 +54,7 @@ cmp_deeply $object->pack, {
              __CLASS__   => 'Gitalist::Git::Repository',
              description => 'some test repository',
              is_bare     => 1,
-             last_change => '2009-11-12T19:00:34Z',
+             last_change => '2011-06-05T23:00:44Z',
              name        => 'repo1',
              owner       => code(\&is_system_account_name),
          },
@@ -93,7 +93,7 @@ cmp_deeply $obj2->pack,  {
              __CLASS__   => 'Gitalist::Git::Repository',
              description => 'some test repository',
              is_bare     => 1,
-             last_change => '2009-11-12T19:00:34Z',
+             last_change => '2011-06-05T23:00:44Z',
              name        => 'repo1',
              owner       => code(\&is_system_account_name),
          },
@@ -120,7 +120,7 @@ cmp_deeply $commit_obj->pack,  {
              __CLASS__   => 'Gitalist::Git::Repository',
              description => 'some test repository',
              is_bare     => 1,
-             last_change => '2009-11-12T19:00:34Z',
+             last_change => '2011-06-05T23:00:44Z',
              name        => 'repo1',
              owner       => code(\&is_system_account_name),
          },
@@ -137,7 +137,7 @@ cmp_deeply $commit_obj->pack,  {
                  __CLASS__   => 'Gitalist::Git::Repository',
                  description => 'some test repository',
                  is_bare     => 1,
-                 last_change => '2009-11-12T19:00:34Z',
+                 last_change => '2011-06-05T23:00:44Z',
                  name        => 'repo1',
                  owner       => code(\&is_system_account_name),
              },
@@ -198,6 +198,19 @@ index 257cc56..5716ca5 100644
         'commit_obj->get_patch can return a patchset')
         or warn("Contents was $contents");
 }
+
+my $blame_this = Gitalist::Git::Object::Commit->new(
+    repository => $repository,
+    sha1       => 'd6ddf8b26be63066e01d96a0922c87cd8d6e2270',
+);
+
+{
+    local $SIG{ALRM} = sub { die "Regressions suck!" };
+    alarm 1;
+    eval { $blame_this->blame('empty-for-a-reason', $blame_this->sha1) };
+    is $@, '', "Silly infinite loop didn't manifest for an empty file.";
+}
+
 done_testing;
 
 sub is_system_account_name {
index e5a436c..2b68267 100644 (file)
@@ -29,7 +29,7 @@ delete $data->{owner}
 is_deeply $data, {
           'is_bare' => 1,
           '__CLASS__' => 'Gitalist::Git::Repository',
-          'last_change' => '2009-11-12T19:00:34Z',
+          'last_change' => '2011-06-05T23:00:44Z',
           'name' => 'repo1',
           'description' => 'some test repository'
         };
diff --git a/t/lib/repositories/repo1/objects/d6/ddf8b26be63066e01d96a0922c87cd8d6e2270 b/t/lib/repositories/repo1/objects/d6/ddf8b26be63066e01d96a0922c87cd8d6e2270
new file mode 100644 (file)
index 0000000..768e467
--- /dev/null
@@ -0,0 +1,4 @@
+x\ 1•Ž]Š\ 21\10„}Î)ú}A:I§'‚,"{\ 5\ fŸŽ\ e:\137\13a¿Á\e\bEQ|EA¥º,s\aC´ëM\ 4
+—ÄXl!ëP‹×¥xv‘Œ‹6qr4™œz†&k\a˃ò„>z˘'4V|ÐL‡D.¦rˆ6f¯½
+¯~«\r
+çVë\1dŽ±ÕßSz†u_Ûõ\e´Åiˆ‰à\v\r¢Jïk]>\1a©Ë&Ðoó\ 6e~ŒT¡ËÖ\a\11ˆ°\f\7f]áÝþIÞ«\7fO^L\17
\ No newline at end of file
diff --git a/t/lib/repositories/repo1/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 b/t/lib/repositories/repo1/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
new file mode 100644 (file)
index 0000000..7112238
Binary files /dev/null and b/t/lib/repositories/repo1/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 differ
diff --git a/t/lib/repositories/repo1/objects/f6/fc60f3f43501e81ff865b425b3c6c5a4142dd2 b/t/lib/repositories/repo1/objects/f6/fc60f3f43501e81ff865b425b3c6c5a4142dd2
new file mode 100644 (file)
index 0000000..bd3fcbd
Binary files /dev/null and b/t/lib/repositories/repo1/objects/f6/fc60f3f43501e81ff865b425b3c6c5a4142dd2 differ
index 7c4a265..4d5b369 100644 (file)
@@ -1 +1 @@
-36c6c6708b8360d7023e8a1649c45bcf9b3bd818
+d6ddf8b26be63066e01d96a0922c87cd8d6e2270
diff --git a/t/lib/repositories/working/README b/t/lib/repositories/working/README
deleted file mode 100644 (file)
index c14ab6d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-This directory represents a working git repository (as opposed to a bare one).