line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Git::Database::Object::Tree; |
2
|
|
|
|
|
|
|
$Git::Database::Object::Tree::VERSION = '0.011'; |
3
|
7
|
|
|
7
|
|
3658
|
use Moo; |
|
7
|
|
|
|
|
14
|
|
|
7
|
|
|
|
|
43
|
|
4
|
7
|
|
|
7
|
|
2192
|
use namespace::clean; |
|
7
|
|
|
|
|
17
|
|
|
7
|
|
|
|
|
74
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
with 'Git::Database::Role::Object'; |
7
|
|
|
|
|
|
|
|
8
|
7
|
|
|
7
|
|
5174
|
use Git::Database::DirectoryEntry; |
|
7
|
|
|
|
|
24
|
|
|
7
|
|
|
|
|
4298
|
|
9
|
|
|
|
|
|
|
|
10
|
945
|
|
|
945
|
1
|
208492
|
sub kind {'tree'} |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
has directory_entries => ( |
13
|
|
|
|
|
|
|
is => 'rwp', |
14
|
|
|
|
|
|
|
required => 0, |
15
|
|
|
|
|
|
|
predicate => 1, |
16
|
|
|
|
|
|
|
lazy => 1, |
17
|
|
|
|
|
|
|
builder => 1, |
18
|
|
|
|
|
|
|
); |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
sub BUILD { |
21
|
610
|
|
|
610
|
0
|
413819
|
my ($self) = @_; |
22
|
|
|
|
|
|
|
|
23
|
610
|
100
|
100
|
|
|
7476
|
die "One of 'digest' or 'content' or 'directory_entries' is required" |
|
|
|
100
|
|
|
|
|
24
|
|
|
|
|
|
|
if !$self->has_digest |
25
|
|
|
|
|
|
|
&& !$self->has_content |
26
|
|
|
|
|
|
|
&& !$self->has_directory_entries; |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
# sort directory entries |
29
|
|
|
|
|
|
|
$self->_set_directory_entries( |
30
|
120
|
|
|
|
|
4439
|
[ sort { $a->filename cmp $b->filename } |
31
|
603
|
100
|
|
|
|
11366
|
@{ $self->directory_entries } |
|
200
|
|
|
|
|
4476
|
|
32
|
|
|
|
|
|
|
] |
33
|
|
|
|
|
|
|
) if $self->has_directory_entries; |
34
|
|
|
|
|
|
|
} |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
sub _build_content { |
37
|
298
|
|
|
298
|
|
4375
|
my ($self) = @_; |
38
|
|
|
|
|
|
|
|
39
|
298
|
100
|
|
|
|
1861
|
if ( !$self->has_directory_entries ) { |
40
|
98
|
|
|
|
|
901
|
my $attr = $self->_get_object_attributes(); |
41
|
84
|
50
|
|
|
|
2193
|
return $attr->{content} if exists $attr->{content}; |
42
|
|
|
|
|
|
|
|
43
|
0
|
0
|
|
|
|
0
|
if ( exists $attr->{directory_entries} ) { |
44
|
0
|
|
|
|
|
0
|
$self->_set_directory_entries( $attr->{directory_entries} ); |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
else { |
47
|
0
|
|
|
|
|
0
|
die "Can't build content from these attributes: " |
48
|
|
|
|
|
|
|
. join( ', ', sort keys %$attr ); |
49
|
|
|
|
|
|
|
} |
50
|
|
|
|
|
|
|
} |
51
|
|
|
|
|
|
|
|
52
|
200
|
|
|
|
|
743
|
return join '', map $_->as_content, @{ $self->directory_entries }; |
|
200
|
|
|
|
|
4403
|
|
53
|
|
|
|
|
|
|
} |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
# assumes content is set |
56
|
|
|
|
|
|
|
sub _build_directory_entries { |
57
|
239
|
|
|
239
|
|
14310
|
my ($self) = @_; |
58
|
|
|
|
|
|
|
|
59
|
239
|
100
|
|
|
|
1776
|
if ( !$self->has_content ) { |
60
|
35
|
|
|
|
|
188
|
my $attr = $self->_get_object_attributes(); |
61
|
28
|
50
|
|
|
|
260
|
return $attr->{directory_entries} if exists $attr->{directory_entries}; |
62
|
|
|
|
|
|
|
|
63
|
28
|
50
|
|
|
|
200
|
if ( exists $attr->{content} ) { |
64
|
28
|
|
|
|
|
260
|
$self->_set_content( $attr->{content} ); |
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
else { |
67
|
0
|
|
|
|
|
0
|
die "Can't build content from these attributes: " |
68
|
|
|
|
|
|
|
. join( ', ', sort keys %$attr ); |
69
|
|
|
|
|
|
|
} |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
|
72
|
232
|
|
|
|
|
5685
|
my $content = $self->content; |
73
|
232
|
100
|
|
|
|
3277
|
return [] unless $content; |
74
|
|
|
|
|
|
|
|
75
|
208
|
|
|
|
|
550
|
my @directory_entries; |
76
|
208
|
|
|
|
|
821
|
while ($content) { |
77
|
364
|
|
|
|
|
13447
|
my $space_index = index( $content, ' ' ); |
78
|
364
|
|
|
|
|
1314
|
my $mode = substr( $content, 0, $space_index ); |
79
|
364
|
|
|
|
|
1294
|
$content = substr( $content, $space_index + 1 ); |
80
|
364
|
|
|
|
|
866
|
my $null_index = index( $content, "\0" ); |
81
|
364
|
|
|
|
|
845
|
my $filename = substr( $content, 0, $null_index ); |
82
|
364
|
|
|
|
|
1343
|
$content = substr( $content, $null_index + 1 ); |
83
|
364
|
|
|
|
|
1813
|
my $digest = unpack( 'H*', substr( $content, 0, 20 ) ); |
84
|
364
|
|
|
|
|
1236
|
$content = substr( $content, 20 ); |
85
|
364
|
|
|
|
|
10830
|
push @directory_entries, |
86
|
|
|
|
|
|
|
Git::Database::DirectoryEntry->new( |
87
|
|
|
|
|
|
|
mode => $mode, |
88
|
|
|
|
|
|
|
filename => $filename, |
89
|
|
|
|
|
|
|
digest => $digest, |
90
|
|
|
|
|
|
|
); |
91
|
|
|
|
|
|
|
} |
92
|
208
|
|
|
|
|
13630
|
return \@directory_entries; |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
sub as_string { |
96
|
244
|
|
|
244
|
1
|
344651
|
return join '', map $_->as_string, @{ $_[0]->directory_entries }; |
|
244
|
|
|
|
|
7952
|
|
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
1; |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
=pod |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
=for Pod::Coverage |
104
|
|
|
|
|
|
|
BUILD |
105
|
|
|
|
|
|
|
has_directory_entries |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
=head1 NAME |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
Git::Database::Object::Tree - A tree object in the Git object database |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
=head1 VERSION |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
version 0.011 |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
=head1 SYNOPSIS |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
my $r = Git::Database->new(); # current Git repository |
118
|
|
|
|
|
|
|
my $tree = $r->get_object('b52168'); # abbreviated digest |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
# attributes |
121
|
|
|
|
|
|
|
$tree->kind; # tree |
122
|
|
|
|
|
|
|
$tree->digest; # b52168be5ea341e918a9cbbb76012375170a439f |
123
|
|
|
|
|
|
|
...; # etc., see below |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
=head1 DESCRIPTION |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
Git::Database::Object::Tree represents a C<tree> object |
128
|
|
|
|
|
|
|
obtained via L<Git::Database> from a Git object database. |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
=head1 ATTRIBUTES |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
All attributes have a predicate method. |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
=head2 kind |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
The object kind: C<tree>. |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
=head2 digest |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
The SHA-1 digest of the tree object. |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=head2 content |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
The object's actual content. |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
=head2 size |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
The size (in bytes) of the object content. |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
=head2 directory_entries |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
An array reference containing a list of L<Git::Database::DirectoryEntry> |
153
|
|
|
|
|
|
|
objects representing the content of the tree. |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
=head1 METHODS |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
=head2 new() |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
Create a new Git::Object::Database::Commit object. |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
One (and only one) of the C<content> or C<directory_entries> arguments |
162
|
|
|
|
|
|
|
is required. |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
C<directory_entires> is an array reference containing a list of |
165
|
|
|
|
|
|
|
L<Git::Database::DirectoryEntry> objects representing the content |
166
|
|
|
|
|
|
|
of the tree. |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
=head2 as_string() |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
The content of the tree object, in the format returned by C<git ls-tree>. |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
=head1 SEE ALSO |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
L<Git::Database>, |
175
|
|
|
|
|
|
|
L<Git::Database::Role::Object>. |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
=head1 AUTHOR |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
Philippe Bruhat (BooK) <book@cpan.org>. |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
=head1 COPYRIGHT |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
Copyright 2013-2016 Philippe Bruhat (BooK), all rights reserved. |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
=head1 LICENSE |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
188
|
|
|
|
|
|
|
under the same terms as Perl itself. |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
=cut |