| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Net::Google::Code::Issue::Search; |
|
2
|
2
|
|
|
2
|
|
57491
|
use Any::Moose; |
|
|
2
|
|
|
|
|
32799
|
|
|
|
2
|
|
|
|
|
16
|
|
|
3
|
2
|
|
|
2
|
|
2143
|
use Params::Validate qw(:all); |
|
|
2
|
|
|
|
|
9228
|
|
|
|
2
|
|
|
|
|
677
|
|
|
4
|
2
|
|
|
2
|
|
16
|
use Any::Moose 'Util::TypeConstraints'; |
|
|
2
|
|
|
|
|
5
|
|
|
|
2
|
|
|
|
|
15
|
|
|
5
|
|
|
|
|
|
|
with 'Net::Google::Code::Role::URL'; |
|
6
|
|
|
|
|
|
|
with 'Net::Google::Code::Role::Fetchable'; |
|
7
|
|
|
|
|
|
|
with 'Net::Google::Code::Role::Pageable'; |
|
8
|
|
|
|
|
|
|
with 'Net::Google::Code::Role::HTMLTree'; |
|
9
|
2
|
|
|
2
|
|
1510
|
use Net::Google::Code::Issue; |
|
|
2
|
|
|
|
|
5
|
|
|
|
2
|
|
|
|
|
2003
|
|
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
our %CAN_MAP = ( |
|
12
|
|
|
|
|
|
|
'all' => 1, |
|
13
|
|
|
|
|
|
|
'open' => 2, |
|
14
|
|
|
|
|
|
|
'new' => 6, |
|
15
|
|
|
|
|
|
|
'verify' => 7, |
|
16
|
|
|
|
|
|
|
); |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
has 'project' => ( |
|
20
|
|
|
|
|
|
|
isa => 'Str', |
|
21
|
|
|
|
|
|
|
is => 'rw', |
|
22
|
|
|
|
|
|
|
); |
|
23
|
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
has 'results' => ( |
|
25
|
|
|
|
|
|
|
isa => 'ArrayRef[Net::Google::Code::Issue]', |
|
26
|
|
|
|
|
|
|
is => 'rw', |
|
27
|
|
|
|
|
|
|
default => sub { [] }, |
|
28
|
|
|
|
|
|
|
); |
|
29
|
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
sub updated_after { |
|
31
|
4
|
|
|
4
|
1
|
12054
|
my $self = shift; |
|
32
|
4
|
|
|
|
|
87
|
my ( $after, $fallback_to_search ) = |
|
33
|
|
|
|
|
|
|
validate_pos( @_, { isa => 'DateTime' }, |
|
34
|
|
|
|
|
|
|
{ optional => 1, default => 1 } ); |
|
35
|
|
|
|
|
|
|
|
|
36
|
4
|
|
|
|
|
205
|
my @results; |
|
37
|
|
|
|
|
|
|
|
|
38
|
4
|
|
|
|
|
48
|
my $content = $self->fetch( $self->base_feeds_url . 'issueupdates/basic' ); |
|
39
|
4
|
|
|
|
|
2336
|
require Net::Google::Code::AtomParser; |
|
40
|
4
|
|
|
|
|
28
|
my $atom_parser = Net::Google::Code::AtomParser->new; |
|
41
|
4
|
|
|
|
|
24
|
my ( $feed, $entries ) = $atom_parser->parse( $content ); |
|
42
|
4
|
50
|
|
|
|
18
|
if (@$entries) { |
|
43
|
4
|
|
|
|
|
40
|
my $min_updated = |
|
44
|
|
|
|
|
|
|
Net::Google::Code::DateTime->new_from_string( $entries->[-1]->{updated} ); |
|
45
|
4
|
100
|
|
|
|
1634
|
if ( $min_updated < $after ) { |
|
46
|
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
# yeah! we can get all the results by parsing the feed |
|
48
|
2
|
|
|
|
|
641
|
my %seen; |
|
49
|
2
|
|
|
|
|
8
|
for my $entry (@$entries) { |
|
50
|
40
|
|
|
|
|
6450
|
my $updated = Net::Google::Code::DateTime->new_from_string( |
|
51
|
|
|
|
|
|
|
$entry->{updated} ); |
|
52
|
40
|
100
|
|
|
|
11620
|
next unless $updated >= $after; |
|
53
|
11
|
50
|
|
|
|
1647
|
if ( $entry->{title} =~ /issue\s+(\d+)/i ) { |
|
54
|
11
|
100
|
|
|
|
53
|
next if $seen{$1}++; |
|
55
|
4
|
|
|
|
|
97
|
push @results, |
|
56
|
|
|
|
|
|
|
Net::Google::Code::Issue->new( |
|
57
|
|
|
|
|
|
|
project => $self->project, |
|
58
|
|
|
|
|
|
|
id => $1, |
|
59
|
|
|
|
|
|
|
); |
|
60
|
|
|
|
|
|
|
} |
|
61
|
|
|
|
|
|
|
} |
|
62
|
2
|
|
|
|
|
682
|
$_->load for @results; |
|
63
|
2
|
|
|
|
|
2098
|
return $self->results( \@results ); |
|
64
|
|
|
|
|
|
|
} |
|
65
|
|
|
|
|
|
|
} |
|
66
|
|
|
|
|
|
|
|
|
67
|
2
|
50
|
|
|
|
484
|
return unless $fallback_to_search; |
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
# now we have to find issues by search |
|
70
|
2
|
50
|
|
|
|
14
|
if ( $self->search( load_after_search => 1, can => 'all', q => '' ) ) { |
|
71
|
2
|
|
|
|
|
10
|
my $results = $self->results; |
|
72
|
2
|
|
|
|
|
9
|
@$results = grep { $_->updated >= $after } @$results; |
|
|
16
|
|
|
|
|
1141
|
|
|
73
|
|
|
|
|
|
|
} |
|
74
|
|
|
|
|
|
|
} |
|
75
|
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
sub search { |
|
77
|
3
|
|
|
3
|
1
|
1651
|
my $self = shift; |
|
78
|
3
|
|
|
|
|
30
|
my %args = ( |
|
79
|
|
|
|
|
|
|
limit => 999_999_999, |
|
80
|
|
|
|
|
|
|
load_after_search => 1, |
|
81
|
|
|
|
|
|
|
can => 2, |
|
82
|
|
|
|
|
|
|
colspec => 'ID+Type+Status+Priority+Milestone+Owner+Summary', |
|
83
|
|
|
|
|
|
|
@_ |
|
84
|
|
|
|
|
|
|
); |
|
85
|
|
|
|
|
|
|
|
|
86
|
3
|
100
|
|
|
|
40
|
if ( $args{can} !~ /^\d$/ ) { |
|
87
|
2
|
|
|
|
|
9
|
$args{can} = $CAN_MAP{ $args{can} }; |
|
88
|
|
|
|
|
|
|
} |
|
89
|
|
|
|
|
|
|
|
|
90
|
3
|
|
|
|
|
6
|
my @results; |
|
91
|
|
|
|
|
|
|
|
|
92
|
3
|
|
|
|
|
29
|
my $mech = $self->mech; |
|
93
|
3
|
|
|
|
|
32
|
my $url = $self->base_url . 'issues/list?'; |
|
94
|
3
|
|
|
|
|
9
|
for my $type (qw/can q sort colspec/) { |
|
95
|
12
|
100
|
|
|
|
42
|
next unless defined $args{$type}; |
|
96
|
8
|
|
|
|
|
24
|
$url .= $type . '=' . $args{$type} . '&'; |
|
97
|
|
|
|
|
|
|
} |
|
98
|
3
|
|
|
|
|
251
|
$self->fetch($url); |
|
99
|
|
|
|
|
|
|
|
|
100
|
3
|
50
|
|
|
|
41
|
die "Server threw an error " . $mech->response->status_line . 'when search' |
|
101
|
|
|
|
|
|
|
unless $mech->response->is_success; |
|
102
|
|
|
|
|
|
|
|
|
103
|
3
|
|
|
|
|
273
|
my $content = $mech->response->content; |
|
104
|
3
|
|
|
|
|
348
|
utf8::downgrade( $content, 1 ); |
|
105
|
|
|
|
|
|
|
|
|
106
|
3
|
50
|
|
|
|
14
|
if ( $mech->title =~ /issue\s+(\d+)/i ) { |
|
|
|
50
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
# get only one ticket |
|
109
|
0
|
|
|
|
|
0
|
my $issue = Net::Google::Code::Issue->new( |
|
110
|
|
|
|
|
|
|
project => $self->project, |
|
111
|
|
|
|
|
|
|
id => $1, |
|
112
|
|
|
|
|
|
|
); |
|
113
|
0
|
|
|
|
|
0
|
@results = $issue; |
|
114
|
|
|
|
|
|
|
} |
|
115
|
|
|
|
|
|
|
elsif ( $mech->title =~ /issues/i ) { |
|
116
|
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
# get a ticket list |
|
118
|
3
|
|
|
|
|
67
|
my @rows = $self->rows( |
|
119
|
|
|
|
|
|
|
html => $content, |
|
120
|
|
|
|
|
|
|
limit => $args{limit}, |
|
121
|
|
|
|
|
|
|
); |
|
122
|
|
|
|
|
|
|
|
|
123
|
3
|
|
|
|
|
13
|
for my $row (@rows) { |
|
124
|
24
|
|
|
|
|
599
|
push @results, |
|
125
|
|
|
|
|
|
|
Net::Google::Code::Issue->new( |
|
126
|
|
|
|
|
|
|
project => $self->project, |
|
127
|
|
|
|
|
|
|
%$row, |
|
128
|
|
|
|
|
|
|
); |
|
129
|
|
|
|
|
|
|
} |
|
130
|
|
|
|
|
|
|
} |
|
131
|
|
|
|
|
|
|
else { |
|
132
|
0
|
|
|
|
|
0
|
warn "no idea what the content like"; |
|
133
|
0
|
|
|
|
|
0
|
return; |
|
134
|
|
|
|
|
|
|
} |
|
135
|
|
|
|
|
|
|
|
|
136
|
3
|
100
|
|
|
|
27
|
if ( $args{load_after_search} ) { |
|
137
|
2
|
|
|
|
|
17
|
$_->load for @results; |
|
138
|
|
|
|
|
|
|
} |
|
139
|
3
|
|
|
|
|
7807
|
$self->results( \@results ); |
|
140
|
|
|
|
|
|
|
} |
|
141
|
|
|
|
|
|
|
|
|
142
|
2
|
|
|
2
|
|
20
|
no Any::Moose; |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
23
|
|
|
143
|
|
|
|
|
|
|
__PACKAGE__->meta->make_immutable; |
|
144
|
|
|
|
|
|
|
1; |
|
145
|
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
__END__ |