Mercurial > pub > buggler
changeset 5:d2efec56373f
working buglist transform and bugs fetching
author | cin |
---|---|
date | Tue, 01 Sep 2015 19:47:30 +0300 |
parents | f8f966388b68 |
children | 2a5f38eb25a9 |
files | bug-list.xsl translate.pl |
diffstat | 2 files changed, 344 insertions(+), 67 deletions(-) [+] |
line wrap: on
line diff
--- a/bug-list.xsl Mon Aug 24 20:50:23 2015 +0300 +++ b/bug-list.xsl Tue Sep 01 19:47:30 2015 +0300 @@ -4,6 +4,19 @@ extension-element-prefixes="exsl"> <xsl:output method="text" indent="yes" /> + <!-- PARAMETERS --> + + <!-- chargeset - название аккаунта, на который вести расходы --> + <xsl:param name="chargeset" /> + + <!-- root_task_id - id корневой задачи, в которую будут организованы все + задачи --> + <xsl:param name="root_task_id" /> + + <!-- root_task - описание корневой задачи --> + <xsl:param name="root_task" /> + + <!-- GLOBAL VARIABLES --> <xsl:variable name="resources" select="document('resources.xml')/resources/resource" /> @@ -22,7 +35,7 @@ <xsl:element name="bug"> <xsl:attribute name="id"><xsl:value-of select="bug_id" /></xsl:attribute> <xsl:if test="component = 'product' or not(number(estimated_time))"> - <xsl:attribute name="product"><xsl:value-of select="boolean(1)" /></xsl:attribute> + <xsl:attribute name="group"><xsl:value-of select="boolean(1)" /></xsl:attribute> </xsl:if> <xsl:for-each select="dependson"> <xsl:apply-templates mode="tree" select="key('bugid', .)" /> @@ -48,11 +61,11 @@ <xsl:variable name="bugid" select="@id" /> <xsl:variable name="path" select="ancestor::bug" /> <xsl:variable name="level" select="count($path)" /> - <xsl:for-each select="$path[@product]"> + <xsl:for-each select="$path[@group]"> <xsl:variable name="pos" select="position()" /> <xsl:variable name="rank" select="$level - $pos" /> <rel container="{@id}" rank="{$rank}" level="{$level}"> - <xsl:for-each select="$path[position() >= $pos and @product]"> + <xsl:for-each select="$path[position() >= $pos and @group]"> <bug id="{@id}" /> </xsl:for-each> </rel> @@ -74,62 +87,123 @@ </xsl:template> <xsl:variable name="structure"> - <xsl:apply-templates select="$roots" mode="structure" /> + <xsl:choose> + <xsl:when test="$root_task"> + <bug id="_root" desc="{$root_task}" group="true"> + <xsl:apply-templates select="$roots" mode="structure"/> + </bug> + </xsl:when> + <xsl:otherwise> + <xsl:apply-templates select="$roots" mode="structure"/> + </xsl:otherwise> + </xsl:choose> </xsl:variable> <xsl:template match="bug" mode="structure"> <xsl:variable name="id" select="string(bug_id)" /> <xsl:variable name="self" select="." /> - <bug id="{$id}"> - <xsl:for-each select="exsl:node-set($parents)/bug[@parent = $id]"> - <xsl:variable name="child" select="@id" /> - <xsl:apply-templates select="$bugs[bug_id = $child]" - mode="structure" /> - </xsl:for-each> + <xsl:variable name="children" + select="exsl:node-set($parents)/bug[@parent = $id]" /> + <xsl:element name="bug"> + <xsl:attribute name="id"><xsl:value-of select="$id" /></xsl:attribute> + <xsl:attribute name="desc"><xsl:value-of select="short_desc" /></xsl:attribute> + + <xsl:if test="$children"> + <xsl:attribute name="group"><xsl:value-of select="boolean($children)" /></xsl:attribute> + + <xsl:for-each select="$children"> + <xsl:variable name="child" select="@id" /> + <xsl:apply-templates select="$bugs[bug_id = $child]" + mode="structure" /> + </xsl:for-each> + + </xsl:if> + + <!-- filter out dependencies --> <xsl:variable name="dependencies" select="dependson[not(text() = exsl:node-set($parents)/bug[@parent = $id]/@id)]" /> - <xsl:if test="$dependencies"> - <depends> - <xsl:for-each select="$dependencies"> - <bug id="{.}" /> - </xsl:for-each> - </depends> - </xsl:if> - </bug> + <xsl:for-each select="$dependencies"> + <dependency id="{.}" /> + </xsl:for-each> + </xsl:element> </xsl:template> <!-- output --> <xsl:template match="/"> <xsl:apply-templates select="exsl:node-set($structure)/bug"> <xsl:with-param name="indent" select="0" /> + <xsl:with-param name="chargeset" select="$chargeset"/> </xsl:apply-templates> </xsl:template> <xsl:template match="bug"> <xsl:param name="indent" select="0" /> + <xsl:param name="chargeset" /> <xsl:variable name="id" select="@id" /> <xsl:variable name="details" select="$bugs[bug_id = $id]" /> + + <!-- task header --> <xsl:call-template name="start-task"> <xsl:with-param name="indent" select="$indent" /> - <xsl:with-param name="id" select="@id" /> - <xsl:with-param name="desc" select="$details/short_desc" /> + <xsl:with-param name="id"> + <xsl:call-template name="bug-local-name"> + <xsl:with-param name="id" select="@id" /> + </xsl:call-template> + </xsl:with-param> + <xsl:with-param name="desc" select="@desc" /> </xsl:call-template> + + <xsl:if test="$chargeset"> + <xsl:call-template name="println"> + <xsl:with-param name="indent" select="$indent + 1"/> + <xsl:with-param name="text" select="concat('chargeset ', $chargeset)"/> + </xsl:call-template> + </xsl:if> + + <!-- task details --> + <xsl:choose> + <xsl:when test="@group"> + <!-- DEBUG --> + <xsl:call-template name="comment"> + <xsl:with-param name="indent" select="$indent + 1" /> + <xsl:with-param name="comment" select="'group'" /> + </xsl:call-template> + - <xsl:for-each select="$details/*"> - <xsl:variable name="directive"> - <xsl:apply-templates select="." mode="task-details" /> - </xsl:variable> - <xsl:if test="string($directive)"> - <xsl:call-template name="begin-line"> + <xsl:apply-templates select="$details/node()" + mode="group-details"> <xsl:with-param name="indent" select="$indent + 1" /> - </xsl:call-template> - <xsl:value-of select="$directive" /> - <xsl:call-template name="end-line" /> - </xsl:if> - </xsl:for-each> + </xsl:apply-templates> + <xsl:if + test="number($details/estimated_time) or number($details/actual_time) or number($details/remaining_time)"> + <xsl:call-template name="start-task"> + <xsl:with-param name="indent" select="$indent + 1" /> + <xsl:with-param name="id" select="'manage'" /> + <xsl:with-param name="desc" select="@desc" /> + </xsl:call-template> + <xsl:apply-templates + select="$details/estimated_time | $details/actual_time | $details/remaining_time | $details/assigned_to" + mode="task-details"> + <xsl:with-param name="indent" select="$indent + 2" /> + </xsl:apply-templates> + <xsl:call-template name="end-task"> + <xsl:with-param name="indent" select="$indent + 1" /> + </xsl:call-template> + </xsl:if> + </xsl:when> + <xsl:otherwise> + <xsl:apply-templates select="$details/node()" + mode="task-details"> + <xsl:with-param name="indent" select="$indent + 1" /> + </xsl:apply-templates> + </xsl:otherwise> + </xsl:choose> + + <!-- subtasks and dependencies --> <xsl:apply-templates> <xsl:with-param name="indent" select="$indent + 1" /> + <xsl:with-param name="referer" select="." /> </xsl:apply-templates> <xsl:call-template name="end-task"> @@ -137,47 +211,66 @@ </xsl:call-template> </xsl:template> + <xsl:template match="dependency"> + <xsl:param name="indent" /> + <xsl:param name="referer" /> + <xsl:call-template name="println"> + <xsl:with-param name="indent" select="$indent" /> + <xsl:with-param name="text"> + <xsl:text>depends </xsl:text> + <xsl:call-template name="bug-reference"> + <xsl:with-param name="id" select="@id" /> + <xsl:with-param name="referer" select="$referer" /> + </xsl:call-template> + </xsl:with-param> + </xsl:call-template> + </xsl:template> + + + <xsl:template match="text()" /> + + <!-- TASK ATTRIBUTES --> + <xsl:template match="estimated_time" mode="task-details"> + <xsl:param name="indent" /> <xsl:if test="number(.)"> - <xsl:value-of select="concat('effort ', .,'h')" /> + <xsl:call-template name="println"> + <xsl:with-param name="indent" select="$indent" /> + <xsl:with-param name="text" select="concat('effort ', .,'h')" /> + </xsl:call-template> </xsl:if> </xsl:template> <xsl:template match="assigned_to" mode="task-details"> + <xsl:param name="indent" /> <xsl:variable name="email" select="string(.)" /> <xsl:variable name="resource" select="$resources[@email = $email]/@id" /> <xsl:if test="$resource"> - <xsl:value-of select="concat('allocate ', $resource)" /> + <xsl:call-template name="println"> + <xsl:with-param name="indent" select="$indent" /> + <xsl:with-param name="text" select="concat('allocate ', $resource)" /> + </xsl:call-template> </xsl:if> </xsl:template> <xsl:template match="text()" mode="task-details"> </xsl:template> - <xsl:template match="depends"> - <xsl:param name="indent" select="0" /> - <xsl:call-template name="begin-line"> - <xsl:with-param name="indent" select="$indent" /> - </xsl:call-template> - <xsl:text>depends </xsl:text> - <xsl:apply-templates> - <xsl:with-param name="referer" select=".." /> - </xsl:apply-templates> - <xsl:call-template name="end-line" /> + <xsl:template match="assigned_to" mode="group-details"> + <xsl:param name="indent" /> + <xsl:variable name="email" select="string(.)" /> + <xsl:variable name="resource" select="$resources[@email = $email]/@id" /> + <xsl:if test="$resource"> + <xsl:call-template name="println"> + <xsl:with-param name="indent" select="$indent" /> + <xsl:with-param name="text" + select="concat('responsible ', $resource)" /> + </xsl:call-template> + </xsl:if> + </xsl:template> + <xsl:template match="text()" mode="group-details"> </xsl:template> - <xsl:template match="depends/bug"> - <xsl:param name="referer" /> - <xsl:call-template name="bug-reference"> - <xsl:with-param name="id" select="@id" /> - <xsl:with-param name="referer" select="$referer" /> - </xsl:call-template> - <xsl:if test="position() != last()"> - <xsl:text>, </xsl:text> - </xsl:if> - </xsl:template> - - - <xsl:template match="text()" /> + <!-- PRIMITIVES --> @@ -200,7 +293,7 @@ <xsl:variable name="targetPathFragment"> <bug id="#root" /> <xsl:for-each - select="exsl:node-set($structure)//bug[local-name(..) != 'depends' and @id = $id]/ancestor-or-self::bug"> + select="exsl:node-set($structure)//bug[@id = $id]/ancestor-or-self::bug"> <bug id="{@id}" /> </xsl:for-each> </xsl:variable> @@ -250,9 +343,7 @@ <xsl:with-param name="indent" select="$indent" /> </xsl:call-template> <xsl:text>task </xsl:text> - <xsl:call-template name="bug-local-name"> - <xsl:with-param name="id" select="$id" /> - </xsl:call-template> + <xsl:value-of select="$id" /> <xsl:value-of select="concat(' "',$desc,'" {')" /> <xsl:call-template name="end-line" /> </xsl:template> @@ -275,6 +366,7 @@ </xsl:call-template> </xsl:if> </xsl:template> + <xsl:template name="end-line"> <xsl:text>
</xsl:text> </xsl:template> @@ -291,4 +383,26 @@ </xsl:call-template> </xsl:if> </xsl:template> + + <xsl:template name="comment"> + <xsl:param name="indent" /> + <xsl:param name="comment" /> + <xsl:call-template name="println"> + <xsl:with-param name="indent" select="$indent" /> + <xsl:with-param name="text"> + <xsl:text># </xsl:text> + <xsl:value-of select="$comment" /> + </xsl:with-param> + </xsl:call-template> + </xsl:template> + + <xsl:template name="println"> + <xsl:param name="indent" /> + <xsl:param name="text" /> + <xsl:call-template name="begin-line"> + <xsl:with-param name="indent" select="$indent" /> + </xsl:call-template> + <xsl:value-of select="$text" /> + <xsl:call-template name="end-line" /> + </xsl:template> </xsl:stylesheet> \ No newline at end of file
--- a/translate.pl Mon Aug 24 20:50:23 2015 +0300 +++ b/translate.pl Tue Sep 01 19:47:30 2015 +0300 @@ -1,5 +1,11 @@ #!/usr/bin/perl -w +use JSON; +use YAML::XS qw(LoadFile Dump); +use URI; +use XML::Writer; +use IPC::Run qw(run); + our @ClassPath = qw( /usr/share/java/xalan-j2-serializer.jar /usr/share/java/xalan-j2.jar @@ -8,18 +14,175 @@ . ); -xalan( - -IN => "bug-list1.xml", - -XSL => "bug-list.xsl", - -URIRESOLVER => "org.apache.xml.resolver.tools.CatalogResolver", - -ENTITYRESOLVER => "org.apache.xml.resolver.tools.CatalogResolver" +my $config = LoadFile("config.yaml"); + +if ( !( $config->{bugzilla}{url} =~ /\/$/ ) ) { + $config->{bugzilla}{url} .= "/"; +} + +my $bz = BzRest->new( + url => $config->{bugzilla}{url}, + apikey => $config->{bugzilla}{apikey} +); + +my $bugs = $bz->GetBugs( { ids => [ 283, 284 ] } ); + +my @fields = qw( + id + creation_time + last_change_time + creator + assigned_to + + status + resolution + + priority + severity + url + + blocks + depends_on + cc + + component + product + classification + version + + actual_time + estimated_time + remainig_time + deadline +); + +my %fieldsMap = ( + id => 'bug_id', + creator => 'reporter', + status => 'bug_status', + severity => 'bug_severity', + blocks => 'blocked', + depends_on => 'dependson', + creation_time => 'creation_ts', + last_change_time => 'delta_ts' ); +my $writer = XML::Writer->new( OUTPUT => \*STDOUT, ENCODING => 'utf-8' ); + +$writer->xmlDecl("UTF-8"); +$writer->startTag("bugzilla"); + +foreach my $bug ( @$bugs ) { + $writer->startTag("bug"); + foreach my $field ( @fields ) { + next unless $bug->{$field}; + + my $tagName = $fieldsMap{$field} || $field; + my @values = ref($bug->{$field}) && ref($bug->{$field}) eq 'ARRAY' ? @{$bug->{$field}} : $bug->{$field}; + + foreach my $v (@values) { + $writer->dataElement($tagName, $v); + } + } + $writer->endTag(); +} + +$writer->endTag(); + + + +#xalan( +# -IN => "bug-list2.xml", +# -XSL => "bug-list.xsl", +# -URIRESOLVER => "org.apache.xml.resolver.tools.CatalogResolver", +# -ENTITYRESOLVER => "org.apache.xml.resolver.tools.CatalogResolver", +# -PARAM => (chargeset => "dev") +#); + sub xalan { - my %params = @_; + my @params = @_; return system 'java', -cp => join( ':', @ClassPath ), - "org.apache.xalan.xslt.Process", %params; + "org.apache.xalan.xslt.Process", @params; +} + +package BzRest; +use fields qw(url apikey); +use LWP::UserAgent; +use XMLRPC::Lite; +use YAML::XS qw(Dump); + +use constant { SELF => __PACKAGE__ }; + +sub new { + my $class = shift; + $class = ref $class || $class; + + my $inst = fields::new($class); + $inst->CTOR(@_); + + return $inst; +} + +sub CTOR { + my SELF $this = shift; + my %params = @_; + + $this->{url} = $params{url} or die "An url is required"; + $this->{apikey} = $params{apikey} if $params{apikey}; +} + +sub GetBug { + my SELF $this = shift; + my $id = shift; + my %params = @_; + + $params{api_key} = $this->{apikey}; + + my $bugurl = URI->new_abs( 'rest/bug/' . $id, $this->{url} ); + $bugurl->query_form( \%params ); + + my $agent = LWP::UserAgent->new(); + my $res = $agent->get($bugurl); + + return $this->_AssertResponse( $res, $bugurl ); +} + +sub GetBugs { + my SELF $this = shift; + + return $this->CallXMLRPC( 'Bug.get', shift )->{bugs}; +} + +sub CallXMLRPC { + my SELF $this = shift; + my ( $method, $params ) = @_; + + die "Method must be specified" unless $method; + $params ||= {}; + + $params->{api_key} = $this->{apikey}; + my $url = URI->new_abs( 'xmlrpc.cgi', $this->{url} ); + + my $result = XMLRPC::Lite->proxy($url)->call( $method, $params ); + + die $result->fault if $result->fault; + return $result->result; +} + +sub _AssertResponse { + my SELF $this = shift; + my ( $res, $url ) = @_; + + die "Failed to get any response: " . $url unless $res; + + die "Failed to fetch: " . $url . ": " . $res->code unless $res->is_success; + + my $bug = JSON->new()->utf8()->decode( $res->content ); + + die "Bugzilla failed: " . $bug->{message} if $bug->{error}; + + return $bug->{bugs}; } __END__