1 package System::Introspector::Probe::Repositories::Git;
4 use System::Introspector::Util qw(
12 default => sub { '/' },
17 return transform_exceptions {
18 my $pipe = $self->_open_locate_git_config_pipe;
20 while (defined( my $line = <$pipe> )) {
22 next unless $line =~ m{^(.+)/\.git/config$};
24 $location{ $base } = $self->_gather_git_info($line);
26 return { git => \%location };
30 sub _gather_git_info {
31 my ($self, $config) = @_;
32 (my $git_dir = $config) =~ s{/config$}{};
34 config_file => $config,
35 current => transform_exceptions {
36 $self->_gather_current_state($git_dir);
38 config => transform_exceptions {
39 $self->_gather_git_config($config);
41 tracked => transform_exceptions {
42 $self->_gather_track_info($git_dir);
47 sub _gather_current_state {
48 my ($self, $git_dir) = @_;
49 local $ENV{GIT_DIR} = $git_dir;
51 map { s{^\s*\*\s+}{}; $_ }
52 grep { m{^\s*\*\s+(.+)$} }
53 lines_from_command ['git', 'branch'];
54 return { __error__ => 'No active branch' }
55 unless $active_branch;
56 my @log_lines = lines_from_command [
63 branch => $active_branch,
64 commit => [@log_lines],
65 origin => transform_exceptions {
66 my $count = $self->_find_commit_count(
69 "origin/$active_branch",
72 local_commit_count => $count,
78 sub _gather_track_info {
79 my ($self, $git_dir) = @_;
80 return $self->_find_tracking($git_dir);
84 my ($self, $dir) = @_;
85 local $ENV{GIT_DIR} = $dir;
86 my @lines = lines_from_command
87 ['git', 'for-each-ref',
88 '--format', q{OK %(refname:short) %(upstream:short)},
92 for my $line (@lines) {
93 if ($line =~ m{^OK\s+(\S+)\s+(\S+)?$}) {
94 my ($local, $remote) = ($1, $2);
97 changed_files => transform_exceptions {
98 $self->_find_changes($dir, $local, $remote);
100 local_commit_count => transform_exceptions {
101 $self->_find_commit_count($dir, $local, $remote);
106 return { __error__ => join "\n", @lines };
109 return { branches => \%branch };
112 sub _find_commit_count {
113 my ($self, $dir, $local, $remote) = @_;
114 return { __error__ => "No remote" }
115 unless defined $remote;
116 local $ENV{GIT_DIR} = $dir;
117 my @lines = lines_from_command
118 ['git', 'log', '--oneline', "$remote..$local"];
119 return scalar @lines;
123 my ($self, $dir, $local, $remote) = @_;
124 return { __error__ => "No remote" }
125 unless defined $remote;
126 local $ENV{GIT_DIR} = $dir;
127 my @lines = lines_from_command
128 ['git', 'diff', '--name-only', $local, $remote];
132 sub _gather_git_config {
133 my ($self, $config) = @_;
134 my $pipe = $self->_open_git_config_pipe($config);
136 while (defined( my $line = <$pipe> )) {
138 my ($name, $value) = split m{=}, $line, 2;
139 $config{ $name } = $value;
141 return { contents => \%config };
144 sub _open_git_config_pipe {
145 my ($self, $config) = @_;
146 return handle_from_command "git config --file $config --list";
149 sub _open_locate_git_config_pipe {
151 (my $root = $self->root) =~ s{/$}{};
152 return handle_from_command sprintf
153 q{locate --regex '^%s/.*\\.git/config$'}, $root;
162 System::Introspector::Probe::Repositories::Git - Gather Git repository info
166 Find Git repositories and gathers their information.
172 This is the root path for the search of git directories. Defaults to C</>.
178 =item L<System::Introspector>
184 Copyright (c) 2012 the L<System::Introspector>
185 L<AUTHOR|System::Introspector/AUTHOR>,
186 L<CONTRIBUTORS|System::Introspector/CONTRIBUTORS> and
187 L<SPONSORS|System::Introspector/SPONSORS>.
191 This library is free software and may be distributed under the same terms