Overhaul the repository link functionality
authorVincent Tondellier <tonton+hg@team1664.org>
Thu, 24 Sep 2015 01:49:55 +0200
changeset 75 e3912669678c
parent 74 e7eda506a66f
child 76 6a33901e2721
Overhaul the repository link functionality - Fix regex (repositories with number or other characters were not accepted) - Url escape template arguments by default (the "do not escape" <%== $var %> markers can be used if needed) - Also support a generic repository type instead of only repotype:repopath in the configuration ($repotype:$repopath has priority over $repotype if both are defined) - Cache compiled templates
lib/CrashTest/StackFilters/FileLink.pm
--- a/lib/CrashTest/StackFilters/FileLink.pm	Sat Sep 12 01:21:06 2015 +0200
+++ b/lib/CrashTest/StackFilters/FileLink.pm	Thu Sep 24 01:49:55 2015 +0200
@@ -24,31 +24,70 @@
     $thread->each_frame(sub {
             my $frame = shift;
 
-            $frame->file_link($self->scm_file_link($frame->file, $frame->line));
+            $frame->file_link($self->_scm_file_link($frame->file, $frame->line));
         }
     );
 
     return $thread;
 }
 
-sub scm_file_link {
+sub _link_template {
+    my ($self, $scm, $repo) = @_;
+
+    my $linkconf = "$scm:$repo";
+    if(defined($self->{_template_cache}->{$linkconf})) {
+        return $self->{_template_cache}->{$linkconf};
+    }
+    my $template = $self->config->{WebInterface}->{ScmLinks}->{$linkconf};
+
+    # try the generic repository type
+    if(!defined($template)) {
+        $linkconf = $scm;
+        if(defined($self->{_template_cache}->{$linkconf})) {
+            return $self->{_template_cache}->{$linkconf};
+        }
+        $template = $self->config->{WebInterface}->{ScmLinks}->{$linkconf};
+    }
+
+    return undef if !defined($template);
+
+    $self->app->log->debug("Building template for $linkconf");
+
+    my $mt = Mojo::Template->new
+        ->prepend('my ($repo, $scmpath, $rev, $line) = @_;')
+        ->auto_escape(1)
+        ->escape(sub {
+            my $str = shift;
+            return Mojo::ByteStream::b($str)->url_escape;
+        })
+        ->parse($template)
+        ->build;
+    my $e = $mt->compile;
+    if($e) {
+        $self->app->log->error($e);
+        return undef;
+    }
+
+    $self->{_template_cache}->{$linkconf} = $mt;
+    return $mt;
+}
+
+sub _scm_file_link {
     my ($self, $file, $line) = @_;
 
     return "" unless(defined($file));
 
     # if the file section looks like vcs:vcs_root_url:vcs_path:revision
-    if($file =~ qr{([a-z]+):([a-z/.]+):(.+):([a-zA-Z0-9]+)}) {
+    if($file =~ /([^:]+):([^:]+):([^:]+):(.+)/) {
         my ($scm, $repo, $scmpath, $rev) = ($1, $2, $3, $4);
         my $filename = File::Spec->splitpath($scmpath);
-        my $scmrepo = "$scm:$repo";
-        my $mt = Mojo::Template->new;
-        my $config = $self->config->{WebInterface}->{ScmLinks};
 
-        # and we have a browser configured for this repository
-        if(exists($config->{$scmrepo})) {
-            my $template = '% my ($repo, $scmpath, $rev, $line) = @_; ' . "\n" . $config->{$scmrepo};
-            my $url = $mt->render($template, $repo, $scmpath, $rev, $line);
-            # then create a link to it
+        # and we have a link template configured for this specific repository or repository type
+        my $template = $self->_link_template($scm, $repo);
+        if(defined($template)) {
+            # build url using the configured template
+            my $url = $template->interpret($repo, $scmpath, $rev, $line);
+            # and create a link to it
             return $self->app->link_to("$filename:$line" => $url);
         }
     }