0
|
1 #!/usr/bin/perl -w
|
|
2
|
5
|
3 use JSON;
|
|
4 use YAML::XS qw(LoadFile Dump);
|
|
5 use URI;
|
|
6 use XML::Writer;
|
|
7 use IPC::Run qw(run);
|
|
8
|
1
|
9 our @ClassPath = qw(
|
|
10 /usr/share/java/xalan-j2-serializer.jar
|
|
11 /usr/share/java/xalan-j2.jar
|
|
12 /usr/share/java/xerces-j2.jar
|
|
13 /usr/share/java/xml-commons-resolver.jar
|
|
14 .
|
|
15 );
|
|
16
|
5
|
17 my $config = LoadFile("config.yaml");
|
|
18
|
|
19 if ( !( $config->{bugzilla}{url} =~ /\/$/ ) ) {
|
|
20 $config->{bugzilla}{url} .= "/";
|
|
21 }
|
|
22
|
|
23 my $bz = BzRest->new(
|
|
24 url => $config->{bugzilla}{url},
|
|
25 apikey => $config->{bugzilla}{apikey}
|
|
26 );
|
|
27
|
|
28 my $bugs = $bz->GetBugs( { ids => [ 283, 284 ] } );
|
|
29
|
|
30 my @fields = qw(
|
|
31 id
|
|
32 creation_time
|
|
33 last_change_time
|
|
34 creator
|
|
35 assigned_to
|
|
36
|
|
37 status
|
|
38 resolution
|
|
39
|
|
40 priority
|
|
41 severity
|
|
42 url
|
|
43
|
|
44 blocks
|
|
45 depends_on
|
|
46 cc
|
|
47
|
|
48 component
|
|
49 product
|
|
50 classification
|
|
51 version
|
|
52
|
|
53 actual_time
|
|
54 estimated_time
|
|
55 remainig_time
|
|
56 deadline
|
|
57 );
|
|
58
|
|
59 my %fieldsMap = (
|
|
60 id => 'bug_id',
|
|
61 creator => 'reporter',
|
|
62 status => 'bug_status',
|
|
63 severity => 'bug_severity',
|
|
64 blocks => 'blocked',
|
|
65 depends_on => 'dependson',
|
|
66 creation_time => 'creation_ts',
|
|
67 last_change_time => 'delta_ts'
|
1
|
68 );
|
0
|
69
|
5
|
70 my $writer = XML::Writer->new( OUTPUT => \*STDOUT, ENCODING => 'utf-8' );
|
|
71
|
|
72 $writer->xmlDecl("UTF-8");
|
|
73 $writer->startTag("bugzilla");
|
|
74
|
|
75 foreach my $bug ( @$bugs ) {
|
|
76 $writer->startTag("bug");
|
|
77 foreach my $field ( @fields ) {
|
|
78 next unless $bug->{$field};
|
|
79
|
|
80 my $tagName = $fieldsMap{$field} || $field;
|
|
81 my @values = ref($bug->{$field}) && ref($bug->{$field}) eq 'ARRAY' ? @{$bug->{$field}} : $bug->{$field};
|
|
82
|
|
83 foreach my $v (@values) {
|
|
84 $writer->dataElement($tagName, $v);
|
|
85 }
|
|
86 }
|
|
87 $writer->endTag();
|
|
88 }
|
|
89
|
|
90 $writer->endTag();
|
|
91
|
|
92
|
|
93
|
|
94 #xalan(
|
|
95 # -IN => "bug-list2.xml",
|
|
96 # -XSL => "bug-list.xsl",
|
|
97 # -URIRESOLVER => "org.apache.xml.resolver.tools.CatalogResolver",
|
|
98 # -ENTITYRESOLVER => "org.apache.xml.resolver.tools.CatalogResolver",
|
|
99 # -PARAM => (chargeset => "dev")
|
|
100 #);
|
|
101
|
0
|
102 sub xalan {
|
5
|
103 my @params = @_;
|
1
|
104 return system 'java',
|
|
105 -cp => join( ':', @ClassPath ),
|
5
|
106 "org.apache.xalan.xslt.Process", @params;
|
|
107 }
|
|
108
|
|
109 package BzRest;
|
|
110 use fields qw(url apikey);
|
|
111 use LWP::UserAgent;
|
|
112 use XMLRPC::Lite;
|
|
113 use YAML::XS qw(Dump);
|
|
114
|
|
115 use constant { SELF => __PACKAGE__ };
|
|
116
|
|
117 sub new {
|
|
118 my $class = shift;
|
|
119 $class = ref $class || $class;
|
|
120
|
|
121 my $inst = fields::new($class);
|
|
122 $inst->CTOR(@_);
|
|
123
|
|
124 return $inst;
|
|
125 }
|
|
126
|
|
127 sub CTOR {
|
|
128 my SELF $this = shift;
|
|
129 my %params = @_;
|
|
130
|
|
131 $this->{url} = $params{url} or die "An url is required";
|
|
132 $this->{apikey} = $params{apikey} if $params{apikey};
|
|
133 }
|
|
134
|
|
135 sub GetBug {
|
|
136 my SELF $this = shift;
|
|
137 my $id = shift;
|
|
138 my %params = @_;
|
|
139
|
|
140 $params{api_key} = $this->{apikey};
|
|
141
|
|
142 my $bugurl = URI->new_abs( 'rest/bug/' . $id, $this->{url} );
|
|
143 $bugurl->query_form( \%params );
|
|
144
|
|
145 my $agent = LWP::UserAgent->new();
|
|
146 my $res = $agent->get($bugurl);
|
|
147
|
|
148 return $this->_AssertResponse( $res, $bugurl );
|
|
149 }
|
|
150
|
|
151 sub GetBugs {
|
|
152 my SELF $this = shift;
|
|
153
|
|
154 return $this->CallXMLRPC( 'Bug.get', shift )->{bugs};
|
|
155 }
|
|
156
|
|
157 sub CallXMLRPC {
|
|
158 my SELF $this = shift;
|
|
159 my ( $method, $params ) = @_;
|
|
160
|
|
161 die "Method must be specified" unless $method;
|
|
162 $params ||= {};
|
|
163
|
|
164 $params->{api_key} = $this->{apikey};
|
|
165 my $url = URI->new_abs( 'xmlrpc.cgi', $this->{url} );
|
|
166
|
|
167 my $result = XMLRPC::Lite->proxy($url)->call( $method, $params );
|
|
168
|
|
169 die $result->fault if $result->fault;
|
|
170 return $result->result;
|
|
171 }
|
|
172
|
|
173 sub _AssertResponse {
|
|
174 my SELF $this = shift;
|
|
175 my ( $res, $url ) = @_;
|
|
176
|
|
177 die "Failed to get any response: " . $url unless $res;
|
|
178
|
|
179 die "Failed to fetch: " . $url . ": " . $res->code unless $res->is_success;
|
|
180
|
|
181 my $bug = JSON->new()->utf8()->decode( $res->content );
|
|
182
|
|
183 die "Bugzilla failed: " . $bug->{message} if $bug->{error};
|
|
184
|
|
185 return $bug->{bugs};
|
0
|
186 }
|
|
187
|
|
188 __END__
|
|
189
|
|
190 =pod
|
|
191
|
|
192 =head1 NAME
|
|
193
|
|
194 C<translate.pl> - translates bugzilla xml buglist to TaskJuggler format
|
|
195
|
|
196 =head1 METHODS
|
|
197
|
|
198 =head2 xalan(%args)
|
|
199
|
|
200 =over
|
|
201
|
|
202 =item * -IN
|
|
203
|
|
204 Input file
|
|
205
|
|
206 =item * -OUT
|
|
207
|
|
208 Output file
|
|
209
|
|
210 =item * -XSL
|
|
211
|
|
212 XSLT file
|
|
213
|
|
214 =back
|
|
215
|
1
|
216 =cut
|