use reusable I/O utils, better error handling and integration
Robert 'phaylon' Sedlacek [Thu, 10 May 2012 02:05:48 +0000 (02:05 +0000)]
lib/System/Introspector/Repositories/Git.pm

index 72af8ed..cf611ea 100644 (file)
@@ -1,6 +1,12 @@
 package System::Introspector::Repositories::Git;
 use Moo;
 
+use System::Introspector::Util qw(
+    handle_from_command
+    transform_exceptions
+    lines_from_command
+);
+
 has root => (
     is      => 'ro',
     default => sub { '/' },
@@ -8,50 +14,58 @@ has root => (
 
 sub gather {
     my ($self) = @_;
-    my $pipe = $self->_open_locate_git_config_pipe;
-    my %location;
-    while (defined( my $line = <$pipe> )) {
-        chomp $line;
-        next unless $line =~ m{^(.+)/\.git/config$};
-        my $base = $1;
-        $location{ $base } = $self->_gather_git_info($line);
-    }
-    return \%location;
+    return transform_exceptions {
+        my $pipe = $self->_open_locate_git_config_pipe;
+        my %location;
+        while (defined( my $line = <$pipe> )) {
+            chomp $line;
+            next unless $line =~ m{^(.+)/\.git/config$};
+            my $base = $1;
+            $location{ $base } = $self->_gather_git_info($line);
+        }
+        return { git => \%location };
+    };
 }
 
 sub _gather_git_info {
     my ($self, $config) = @_;
     return {
-        config_file     => $config,
-        config          => $self->_gather_git_config($config),
-        tracked         => $self->_gather_track_info($config),
+        config_file => $config,
+        config      => transform_exceptions {
+            $self->_gather_git_config($config);
+        },
+        tracked     => transform_exceptions {
+            $self->_gather_track_info($config);
+        },
     };
 }
 
 sub _gather_track_info {
     my ($self, $config) = @_;
     (my $git_dir = $config) =~ s{/config$}{};
-    my @tracked = $self->_find_tracking($git_dir);
+    return $self->_find_tracking($git_dir);
 }
 
 sub _find_tracking {
     my ($self, $dir) = @_;
-    my $command = sprintf
-        q{GIT_DIR=%s git for-each-ref --format '%s' refs/heads},
-        $dir,
-        q{OK %(refname:short) %(upstream:short)};
-    my @lines = `$command 2>&1`;
-    chomp @lines;
+    local $ENV{GIT_DIR} = $dir;
+    my @lines = lines_from_command
+        ['git', 'for-each-ref',
+            '--format', q{'OK %(refname:short) %(upstream:short)'},
+            'refs/heads',
+        ];
     my %branch;
     for my $line (@lines) {
         if ($line =~ m{^OK\s+(\S+)\s+(\S+)?$}) {
             my ($local, $remote) = ($1, $2);
             $branch{ $local } = {
                 upstream => $remote,
-                changed_files
-                    => $self->_find_changes($dir, $local, $remote),
-                local_commit_count
-                    => $self->_find_commits($dir, $local, $remote),
+                changed_files => transform_exceptions {
+                    $self->_find_changes($dir, $local, $remote);
+                },
+                local_commit_count => transform_exceptions {
+                    $self->_find_commits($dir, $local, $remote);
+                },
             }
         }
         else {
@@ -65,23 +79,20 @@ sub _find_commits {
     my ($self, $dir, $local, $remote) = @_;
     return { error => "No remote" }
         unless defined $remote;
-    my $command = sprintf
-        q{GIT_DIR=%s git log --oneline %s..%s},
-        $dir, $remote, $local;
-    my @lines = `$command 2>&1`;
-    return scalar @lines;
+    local $ENV{GIT_DIR} = $dir;
+    my @lines = lines_from_command
+        ['git', 'log', '--oneline', "$remote..$local"];
+    return { count => scalar @lines };
 }
 
 sub _find_changes {
     my ($self, $dir, $local, $remote) = @_;
     return { error => "No remote" }
         unless defined $remote;
-    my $command = sprintf
-        q{GIT_DIR=%s git diff --name-only %s %s},
-        $dir, $local, $remote;
-    my @lines = `$command 2>&1`;
-    chomp @lines;
-    return \@lines;
+    local $ENV{GIT_DIR} = $dir;
+    my @lines = lines_from_command
+        ['git', 'diff', '--name-only', $local, $remote];
+    return { list => \@lines };
 }
 
 sub _gather_git_config {
@@ -93,25 +104,19 @@ sub _gather_git_config {
         my ($name, $value) = split m{=}, $line, 2;
         $config{ $name } = $value;
     }
-    return \%config;
+    return { contents => \%config };
 }
 
 sub _open_git_config_pipe {
     my ($self, $config) = @_;
-    my $command = "git config --file $config --list";
-    open my $pipe, '-|', $command
-        or die "Unable to open pipe to '$command': $!\n";
-    return $pipe;
+    return handle_from_command "git config --file $config --list";
 }
 
 sub _open_locate_git_config_pipe {
     my ($self) = @_;
-    my $root = $self->root;
-    $root =~ s{/$}{};
-    my $command = sprintf q{locate --regex '^%s/.*\\.git/config$'}, $root;
-    open my $pipe, '-|', $command
-        or die "Unable to open pipe to '$command': $!\n";
-    return $pipe;
+    (my $root = $self->root) =~ s{/$}{};
+    return handle_from_command sprintf
+        q{locate --regex '^%s/.*\\.git/config$'}, $root;
 }
 
 1;