File Coverage

blib/lib/Git/Database/Backend/Git/Wrapper.pm
Criterion Covered Total %
statement 54 58 93.1
branch 12 18 66.6
condition n/a
subroutine 14 14 100.0
pod 0 8 0.0
total 80 98 81.6


line stmt bran cond sub pod time code
1             package Git::Database::Backend::Git::Wrapper;
2             $Git::Database::Backend::Git::Wrapper::VERSION = '0.012';
3 7     7   198205 use Cwd qw( cwd );
  7         58  
  7         1129  
4 7     7   241 use Git::Wrapper;
  7         77  
  7         605  
5 7     7   92 use Git::Version::Compare qw( ge_git );
  7         54  
  7         824  
6 7     7   96 use Sub::Quote;
  7         51  
  7         1166  
7              
8 7     7   93 use Moo;
  7         53  
  7         205  
9 7     7   27403 use namespace::clean;
  7         45  
  7         191  
10              
11             with
12             'Git::Database::Role::Backend',
13             'Git::Database::Role::ObjectReader',
14             'Git::Database::Role::ObjectWriter',
15             'Git::Database::Role::RefReader',
16             'Git::Database::Role::RefWriter',
17             ;
18              
19             has '+store' => (
20             isa => quote_sub( q{
21             die 'store is not a Git::Wrapper object'
22             if !eval { $_[0]->isa('Git::Wrapper') }
23             } ),
24             default => sub { Git::Wrapper->new( cwd() ) },
25             );
26              
27             # Git::Database::Role::Backend
28             sub hash_object {
29 95     95 0 27842 my ( $self, $object ) = @_;
30 95         2753 my @out = $self->store->hash_object( { -STDIN => $object->content },
31             '--stdin', '-t', $object->kind );
32 95         722734 return shift @out;
33             }
34              
35             # Git::Database::Role::ObjectReader
36             sub get_object_meta {
37 57     57 0 409 my ( $self, $digest ) = @_;
38 57         1369 my ($meta) =
39             $self->store->cat_file( { -STDIN => "$digest\n" }, '--batch-check' );
40 57 50       456117 warn join $/, @{ $self->store->ERR }, '' if @{ $self->store->ERR };
  0         0  
  57         703  
41              
42             # protect against weird cases like if $digest contains a space
43 57         2033 my @parts = split / /, $meta;
44 57 100       1903 return ( $digest, 'missing', undef ) if $parts[-1] eq 'missing';
45              
46 24         501 my ( $kind, $size ) = splice @parts, -2;
47 24         1238 return join( ' ', @parts ), $kind, $size;
48             }
49              
50             sub get_object_attributes {
51 156     156 0 1287 my ( $self, $digest ) = @_;
52              
53 156         3401 my @out = $self->store->cat_file( { -STDIN => "$digest\n" }, '--batch' );
54 156         1240995 my $meta = shift @out;
55 156 100       934 warn join $/, @{ $self->store->ERR }, '' if @{ $self->store->ERR };
  1         56  
  156         2123  
56              
57             # protect against weird cases like if $digest contains a space
58 156         5274 my ( $sha1, $kind, $size ) = my @parts = split / /, $meta;
59              
60             # git versions >= 2.11.0.rc0 throw more verbose errors
61 156 50       2446 return undef if $parts[0] =~ /^(?:symlink|dangling|loop|notdir)$/;
62              
63             # git versions >= 2.21.0.rc0 explicitely say if a sha1 is ambiguous
64 156 50       1435 return undef if $kind eq 'ambiguous';
65              
66             # object does not exist in the git object database
67 156 100       2722 return undef if $parts[-1] eq 'missing';
68              
69             return {
70 96         4423 kind => $kind,
71             size => $size,
72             content => join( $/, @out ), # I expect this to break on binary data
73             digest => $sha1
74             };
75             }
76              
77             sub all_digests {
78 11     11 0 245479 my ( $self, $kind ) = @_;
79 11         139 my $store = $self->store;
80 11 100       549 my $re = $kind ? qr/ \Q$kind\E / : qr/ /;
81              
82             # the --batch-all-objects option appeared in v2.6.0-rc0
83 11 50       224 if ( ge_git( $store->version, '2.6.0.rc0' ) ) {
84 11         117030 return map +( split / / )[0],
85             grep /$re/,
86             $store->cat_file(qw( --batch-check --batch-all-objects ));
87             }
88             else { # this won't return unreachable objects
89 0         0 my $revs = join "\n", map +( split / / )[0],
90             sort $store->rev_list(qw( --all --objects ));
91 0 0       0 return if !length $revs;
92 0         0 return map +( split / / )[0], grep /$re/,
93             $store->cat_file( qw( --batch-check ), { -STDIN => "$revs\n" } );
94             }
95             }
96              
97             # Git::Database::Role::ObjectWriter
98             sub put_object {
99 13     13 0 109 my ( $self, $object ) = @_;
100 13         193 my ($hash) = $self->store->hash_object( '-t', $object->kind, '-w',
101             { stdin => 1, -STDIN => $object->content } );
102 13         104205 return $hash;
103             }
104              
105             # Git::Database::Role::RefReader
106             sub refs {
107 20     20 0 77658 my ($self) = @_;
108             return {
109 20         532 reverse map +( split / / ),
110             $self->store->show_ref( { head => 1 } )
111             };
112             }
113              
114             # Git::Database::Role::RefWriter
115             sub put_ref {
116 2     2 0 26667 my ($self, $refname, $digest ) = @_;
117 2         120 $self->store->update_ref( $refname, $digest );
118             }
119              
120             sub delete_ref {
121 2     2 0 84 my ($self, $refname ) = @_;
122 2         61 $self->store->update_ref( '-d', $refname );
123             }
124              
125             1;
126              
127             __END__
128              
129             =pod
130              
131             =for Pod::Coverage
132             hash_object
133             get_object_attributes
134             get_object_meta
135             all_digests
136             put_object
137             refs
138             put_ref
139             delete_ref
140              
141             =head1 NAME
142              
143             Git::Database::Backend::Git::Wrapper - A Git::Database backend based on Git::Wrapper
144              
145             =head1 VERSION
146              
147             version 0.012
148              
149             =head1 SYNOPSIS
150              
151             # get a store
152             my $r = Git::Wrapper->new('/var/foo');
153              
154             # let Git::Database produce the backend
155             my $db = Git::Database->new( store => $r );
156              
157             =head1 DESCRIPTION
158              
159             This backend reads and writes data from a Git repository using the
160             L<Git::Wrapper> module.
161              
162             =head2 Git Database Roles
163              
164             This backend does the following roles
165             (check their documentation for a list of supported methods):
166             L<Git::Database::Role::Backend>,
167             L<Git::Database::Role::ObjectReader>,
168             L<Git::Database::Role::ObjectWriter>,
169             L<Git::Database::Role::RefReader>,
170             L<Git::Database::Role::RefWriter>.
171              
172             =head1 AUTHORS
173              
174             Philippe Bruhat (BooK) <book@cpan.org>
175              
176             Sergey Romanov provided the code to support the
177             L<Git::Database::Role::ObjectWriter>, L<Git::Database::Role::RefReader>,
178             and L<Git::Database::Role::RefWriter> roles.
179              
180             =head1 COPYRIGHT
181              
182             Copyright 2016-2019 Philippe Bruhat (BooK), all rights reserved.
183              
184             =head1 LICENSE
185              
186             This program is free software; you can redistribute it and/or modify it
187             under the same terms as Perl itself.
188              
189             =cut