]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 1377232 - Revert code from bug 1361890
authorDylan William Hardison <dylan@hardison.net>
Mon, 3 Jul 2017 19:38:38 +0000 (12:38 -0700)
committerDylan William Hardison <dylan@hardison.net>
Thu, 6 Jul 2017 22:19:20 +0000 (18:19 -0400)
22 files changed:
.gitignore
.htaccess
Bugzilla.pm
Bugzilla/CGI.pm
Bugzilla/Constants.pm
Bugzilla/Install/AssetManager.pm [deleted file]
Bugzilla/Install/Filesystem.pm
Bugzilla/Template.pm
checksetup.pl
extensions/BugModal/template/en/default/bug_modal/edit.html.tmpl
extensions/BugmailFilter/template/en/default/account/prefs/bugmail_filter.html.tmpl
extensions/ComponentWatching/template/en/default/account/prefs/component_watch.html.tmpl
extensions/OpenGraph/template/en/default/hook/global/header-start.html.tmpl
extensions/ProdCompSearch/template/en/default/prodcompsearch/form.html.tmpl
template/en/default/attachment/diff-header.html.tmpl
template/en/default/bug/comments.html.tmpl
template/en/default/flag/list.html.tmpl
template/en/default/global/header.html.tmpl
template/en/default/list/list-simple.html.tmpl
template/en/default/reports/duplicates-simple.html.tmpl
template/en/default/rest.html.tmpl
template/en/default/search/boolean-charts.html.tmpl

index 5287b1ea0967f66c98b69aa97077fc1c74406a13..18f2d0a1730c57f04873849348d25f2ba4c2addc 100644 (file)
@@ -14,7 +14,6 @@
 /skins/custom
 /graphs
 /data
-/assets
 /localconfig
 /localconfig.*
 /index.html
index 30aff3458ae92816f9a7c184016bfc14178d2216..b07ce9a0d69f8c5cc790562444bb51147e8522d4 100644 (file)
--- a/.htaccess
+++ b/.htaccess
@@ -2,6 +2,27 @@
 <FilesMatch (\.pm|\.pl|\.tmpl|\.swf|localconfig.*|cpanfile)$>
   deny from all
 </FilesMatch>
+<IfModule mod_expires.c>
+<IfModule mod_headers.c>
+<IfModule mod_env.c>
+  <FilesMatch (\.js|\.css)$>
+    ExpiresActive On
+    # According to RFC 2616, "1 year in the future" means "never expire".
+    # We change the name of the file's URL whenever its modification date
+    # changes, so browsers can cache any individual JS or CSS URL forever.
+    # However, since all JS and CSS URLs involve a ? in them (for the changing
+    # name) we have to explicitly set an Expires header or browsers won't
+    # *ever* cache them.
+    ExpiresDefault "now plus 1 years"
+    Header append Cache-Control "public"
+  </FilesMatch>
+
+  # This lets Bugzilla know that we are properly sending Cache-Control
+  # and Expires headers for CSS and JS files.
+  SetEnv BZ_CACHE_CONTROL 1
+</IfModule>
+</IfModule>
+</IfModule>
 
 # Allow ZeroClipboard for access to the clipboard
 <Files "ZeroClipboard.swf">
index 55dc93e985e8e04631707ca0867f16fa31918d53..33a6583233adc1e8a0779008c55c3eee9b2bfd1a 100644 (file)
@@ -36,7 +36,6 @@ use Bugzilla::Flag;
 use Bugzilla::Hook;
 use Bugzilla::Install::Localconfig qw(read_localconfig);
 use Bugzilla::Install::Util qw(init_console include_languages);
-use Bugzilla::Install::AssetManager;
 use Bugzilla::Memcached;
 use Bugzilla::Template;
 use Bugzilla::Token;
@@ -255,11 +254,6 @@ sub extensions {
     return $cache->{extensions};
 }
 
-sub asset_manager {
-    state $asset_manager = Bugzilla::Install::AssetManager->new;
-    return $asset_manager;
-}
-
 sub cgi {
     return $_[0]->request_cache->{cgi} ||= new Bugzilla::CGI();
 }
index 65e36a24f254f1b847794caf4b41974e8d327b57..2402e997b8566f618399a6451403e77a7d4f9312 100644 (file)
@@ -441,20 +441,12 @@ sub header {
         %headers = ('-type' => shift(@_));
     }
     else {
-        # we always want headers to be in lower case, to avoid
-        # for instance -Cache_Control vs. -cache_control.
-        my %tmp = @_;
-        foreach my $key (keys %tmp) {
-            my $lc_key = lc $key;
-            warn "duplicate header: $key" if exists $headers{$lc_key};
-            $headers{$lc_key} = $tmp{$key};
-        }
+        %headers = @_;
     }
 
     if ($self->{'_content_disp'}) {
         $headers{'-content_disposition'} = $self->{'_content_disp'};
     }
-    $headers{'-cache_control'} //= 'no-cache, no-store, must-revalidate';
 
     if (!$user->id && $user->authorizer->can_login
         && !$self->cookie('Bugzilla_login_request_cookie'))
index 4cb838f94922730f4e6e9aa9d08e8a9cf0688592..9c8f39b4a1f11772b22ea46f0adad3db803a62ce 100644 (file)
@@ -26,6 +26,8 @@ use Memoize;
 
     bz_locations
 
+    CONCATENATE_ASSETS
+
     IS_NULL
     NOT_NULL
 
@@ -217,6 +219,11 @@ use constant REST_DOC => "http://www.bugzilla.org/docs/tip/en/html/api/";
 use constant REMOTE_FILE => 'http://updates.bugzilla.org/bugzilla-update.xml';
 use constant LOCAL_FILE  => 'bugzilla-update.xml'; # Relative to datadir.
 
+# When true CSS and JavaScript assets will be concatanted and minified at
+# run-time, to reduce the number of requests required to render a page.
+# Setting this to a false value can help debugging.
+use constant CONCATENATE_ASSETS => 1;
+
 # These are unique values that are unlikely to match a string or a number,
 # to be used in criteria for match() functions and other things. They start
 # and end with spaces because most Bugzilla stuff has trim() called on it,
@@ -695,7 +702,7 @@ sub _bz_locations {
         # The script should really generate these graphs directly...
         'webdotdir'      => "$datadir/webdot",
         'extensionsdir'  => "$libpath/extensions",
-        'assetsdir'      => "$libpath/assets",
+        'assetsdir'      => "$datadir/assets",
         # error_reports store error/warnings destined for sentry
         'error_reports'  => "$libpath/error_reports",
     };
diff --git a/Bugzilla/Install/AssetManager.pm b/Bugzilla/Install/AssetManager.pm
deleted file mode 100644 (file)
index 073e012..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#
-# This Source Code Form is "Incompatible With Secondary Licenses", as
-# defined by the Mozilla Public License, v. 2.0.
-
-package Bugzilla::Install::AssetManager;
-
-use 5.10.1;
-use strict;
-use warnings;
-
-use Moo;
-use MooX::StrictConstructor;
-use Type::Utils;
-use Types::Standard qw(Bool Str ArrayRef);
-
-use Digest::SHA ();
-use File::Copy qw(cp);
-use File::Find qw(find);
-use File::Basename qw(dirname);
-use File::Spec;
-use JSON::XS ();
-use MIME::Base64 qw(encode_base64);
-use File::Slurp;
-use List::MoreUtils qw(any all);
-use Carp;
-
-use Bugzilla::Constants qw(bz_locations);
-
-our $VERSION = 1;
-
-my $SHA_VERSION = '224';
-
-my $ABSOLUTE_DIR = declare as Str, where { File::Spec->file_name_is_absolute($_) && -d $_ }
-message {"must be an absolute path to a directory"};
-
-has 'base_dir'  => ( is => 'lazy', isa => $ABSOLUTE_DIR );
-has 'asset_dir' => ( is => 'lazy', isa => $ABSOLUTE_DIR );
-has 'source_dirs' => ( is => 'lazy' );
-has 'state'       => ( is => 'lazy' );
-has 'state_file'  => ( is => 'lazy' );
-has 'json'        => ( is => 'lazy' );
-
-sub asset_file {
-    my ( $self, $file, $relative_to ) = @_;
-    $relative_to //= $self->base_dir;
-    my $asset_file = $self->state->{asset_map}->{$file}
-        or return $file;
-
-    return File::Spec->abs2rel( File::Spec->catfile( $self->asset_dir, $asset_file ), $relative_to );
-}
-
-sub asset_files {
-    my ( $self, @files ) = @_;
-
-    return \@files;
-}
-
-sub asset_sri {
-    my ( $self, $asset_file ) = @_;
-    my ($hex) = $asset_file =~ m!([[:xdigit:]]+)\.\w+$!;
-    my $data = pack "H*", $hex;
-    return "sha$SHA_VERSION-" . encode_base64( $data, "" );
-}
-
-sub compile_file {
-    my ( $self, $file ) = @_;
-    return unless -f $file;
-    my $base_dir  = $self->base_dir;
-    my $asset_dir = $self->asset_dir;
-    my $asset_map = $self->state->{asset_map};
-
-    my $key = File::Spec->abs2rel( $file, $base_dir );
-    return if $asset_map->{$key};
-
-    if ( $file =~ /\.(jpe?g|png|gif|ico|woff|js)$/i ) {
-        my $ext        = $1;
-        my $digest     = $self->_digest_file($file) or die "invalid digest for $file";
-        my $asset_file = File::Spec->catfile( $asset_dir, "$digest.$ext" );
-        cp( $file, $asset_file ) or die "failed to copy $file to $asset_file: $!";
-        if ( $digest eq $self->_digest_file($asset_file) ) {
-            $asset_map->{$key} = File::Spec->abs2rel( $asset_file, $asset_dir );
-        }
-        else {
-            die "failed to write $asset_file";
-        }
-    }
-    elsif ( $file =~ /\.css$/ ) {
-        my $content = read_file($file);
-
-        $content =~ s{(?<!=)url\(([^\)]+)\)}{$self->_css_url_rewrite($1, $file)}eig;
-        my $digest = $self->_digest_string($content);
-        my $asset_file = File::Spec->catfile( $asset_dir, "$digest.css" );
-        write_file( $asset_file, $content ) or die "failed to write $asset_file: $!";
-        if ( $digest eq $self->_digest_file($asset_file) ) {
-            $asset_map->{$key} = File::Spec->abs2rel( $asset_file, $asset_dir );
-        }
-        else {
-            die "failed to write $asset_file";
-        }
-    }
-}
-
-sub compile_all {
-    my ($self) = @_;
-    my $asset_map = $self->state->{asset_map} = {};
-
-    my $wanted = sub {
-        $self->compile_file($File::Find::name);
-    };
-
-    find( { wanted => $wanted, no_chdir => 1 }, @{ $self->source_dirs } );
-
-    $self->_save_state();
-}
-
-sub _css_url_rewrite {
-    my ( $self, $url, $file ) = @_;
-    my $dir = dirname($file);
-
-    # rewrite relative urls as the unified stylesheet lives in a different
-    # directory from the source
-    $url =~ s/(^['"]|['"]$)//g;
-    if ( $url =~ m!^(/|data:)! ) {
-        return 'url(' . $url . ')';
-    }
-    else {
-        my $url_file = File::Spec->rel2abs( $url, $dir );
-        my $ref_file = File::Spec->abs2rel( $url_file, $self->base_dir );
-        $self->compile_file($url_file);
-        return sprintf( "url(%s)", $self->asset_file( $ref_file, $self->asset_dir ) );
-    }
-}
-
-sub _new_digest { Digest::SHA->new($SHA_VERSION) }
-
-sub _digest_file {
-    my ( $self, $file ) = @_;
-    my $digest = $self->_new_digest;
-    $digest->addfile( $file, "b" );
-    return $digest->hexdigest;
-}
-
-sub _digest_string {
-    my ( $self, $string ) = @_;
-    my $digest = $self->_new_digest;
-    $digest->add($string);
-    return $digest->hexdigest;
-}
-
-sub _build_base_dir {
-    Cwd::realpath( File::Spec->rel2abs( bz_locations->{cgi_path} ) );
-}
-
-sub _build_asset_dir {
-    my ($self) = @_;
-    my $dir
-        = Cwd::realpath( File::Spec->rel2abs( bz_locations->{assetsdir} ) );
-
-    if ( $dir && -d $dir ) {
-        my $version_dir = File::Spec->catdir( $dir, "v" . $self->VERSION );
-        unless ( -d $version_dir ) {
-            mkdir $version_dir or die "mkdir $version_dir failed: $!";
-        }
-        return $version_dir;
-    }
-    else {
-        return $dir;
-    }
-}
-
-sub _build_source_dirs {
-    my ($self)  = @_;
-    my $base    = $self->base_dir;
-    my $ext_dir = "$base/extensions";
-    opendir my $ext_dir_handle, $ext_dir or die "unable to open $ext_dir: $!";
-    my @dirs = grep { -d $_ } map {"$ext_dir/$_/web"} grep { !/^\.\.?$/ } readdir $ext_dir_handle;
-    closedir $ext_dir_handle;
-
-    return [ "$base/images", "$base/skins", "$base/js", grep { -d $_ } @dirs ];
-}
-
-sub _build_state_file {
-    my ($self) = @_;
-    return $self->asset_dir . "/state.json";
-}
-
-sub _build_state {
-    my ($self) = @_;
-    my $state;
-    if ( open my $fh, '<:bytes', $self->state_file ) {
-        local $/ = undef;
-        my $json = <$fh>;
-        close $fh;
-        $state = $self->json->decode($json);
-    }
-    else {
-        $state = {};
-    }
-
-    $state->{asset_map} //= {};
-
-    return $state;
-}
-
-sub _build_json { JSON::XS->new->canonical->utf8 }
-
-sub _save_state {
-    my ($self) = @_;
-    open my $fh, '>:bytes', $self->state_file
-        or die "unable to write state file: $!";
-    print $fh $self->json->encode( $self->state );
-    close $fh;
-}
-
-1;
index 162e324f79657579aaf862862c23d4c712e5cbc1..22ec34a95b8b4230122c09bca5695ccc82b060e8 100644 (file)
@@ -31,7 +31,6 @@ use File::Path;
 use File::Basename;
 use File::Copy qw(move);
 use File::Spec;
-use File::stat;
 use Cwd ();
 use File::Slurp;
 use IO::File;
@@ -82,16 +81,12 @@ EOT
 
 use constant HT_ASSETS_DIR => <<'EOT';
 # Allow access to .css and js files
-<FilesMatch state\.json$>
-    Deny from all
+<FilesMatch \.(css|js)$>
+  Allow from all
 </FilesMatch>
 
-FileETag None
-Header set Cache-Control "public, immutable, max-age=31536000"
-Header set Content-Security-Policy "default-src 'none';"
-
 # And no directory listings, either.
-Options -Indexes
+Deny from all
 EOT
 
 use constant INDEX_HTML => <<'EOT';
@@ -349,7 +344,7 @@ sub FILESYSTEM {
         $attachdir              => DIR_CGI_WRITE,
         $graphsdir              => DIR_CGI_WRITE | DIR_ALSO_WS_SERVE,
         $webdotdir              => DIR_CGI_WRITE | DIR_ALSO_WS_SERVE,
-        $assetsdir              => DIR_WS_SERVE,
+        $assetsdir              => DIR_CGI_WRITE | DIR_ALSO_WS_SERVE,
         $template_cache         => DIR_CGI_WRITE,
         $error_reports          => DIR_CGI_WRITE,
         # Directories that contain content served directly by the web server.
@@ -451,13 +446,8 @@ sub FILESYSTEM {
         "$webdotdir/.htaccess"       => { perms => WS_SERVE,
                                           contents => HT_WEBDOT_DIR },
         "$assetsdir/.htaccess"       => { perms => WS_SERVE,
-                                          contents  => HT_ASSETS_DIR },
+                                          contents => HT_ASSETS_DIR },
     );
-    my $mtime = stat(__FILE__)->mtime;
-    foreach my $file (keys %htaccess) {
-        my $file_stat = stat($file);
-        $htaccess{$file}{overwrite} = $file_stat && $mtime > $file_stat->mtime;
-    }
 
     Bugzilla::Hook::process('install_filesystem', {
         files            => \%files,
@@ -571,6 +561,7 @@ sub update_filesystem {
 
     _remove_empty_css_files();
     _convert_single_file_skins();
+    _remove_dynamic_assets();
 }
 
 sub _css_url_fix {
@@ -636,6 +627,27 @@ sub _convert_single_file_skins {
     }
 }
 
+# delete all automatically generated css/js files to force recreation at the
+# next request.
+sub _remove_dynamic_assets {
+    my @files = (
+        glob(bz_locations()->{assetsdir} . '/*.css'),
+        glob(bz_locations()->{assetsdir} . '/*.js'),
+    );
+    foreach my $file (@files) {
+        unlink($file);
+    }
+
+    # remove old skins/assets directory
+    my $old_path = bz_locations()->{skinsdir} . '/assets';
+    if (-d $old_path) {
+        foreach my $file (glob("$old_path/*.css")) {
+            unlink($file);
+        }
+        rmdir($old_path);
+    }
+}
+
 sub create_htaccess {
     _create_files(%{FILESYSTEM()->{htaccess}});
 
index 663e467c63b6014841307a35d23115f539613b69..5bef599d4f37e718a6e5fd25c1511dbd26b30f03 100644 (file)
@@ -401,13 +401,7 @@ sub css_files {
 
     unshift @requested_css, "skins/yui.css" unless $no_yui;
 
-    my @css_sets = map { _css_link_set($_) } sort {
-        my $first_a = $a =~ m!js/jquery!;
-        my $first_b = $b =~ m!js/jquery!;
-        return -1 if $first_a && !$first_b;
-        return 1 if !$first_a && $first_b;
-        return 0;
-    } @requested_css;
+    my @css_sets = map { _css_link_set($_) } @requested_css;
 
     my %by_type = (standard => [], skin => [], custom => []);
     foreach my $set (@css_sets) {
@@ -416,13 +410,18 @@ sub css_files {
         }
     }
 
+    # build unified
+    $by_type{unified_standard_skin} = _concatenate_css($by_type{standard},
+                                                       $by_type{skin});
+    $by_type{unified_custom} = _concatenate_css($by_type{custom});
+
     return \%by_type;
 }
 
 sub _css_link_set {
     my ($file_name) = @_;
 
-    my %set = (standard => $file_name);
+    my %set = (standard => mtime_filter($file_name));
 
     # We use (?:^|/) to allow Extensions to use the skins system if they want.
     if ($file_name !~ m{(?:^|/)skins/standard/}) {
@@ -433,19 +432,127 @@ sub _css_link_set {
     my $cgi_path = bz_locations()->{'cgi_path'};
     my $skin_file_name = $file_name;
     $skin_file_name =~ s{(?:^|/)skins/standard/}{skins/contrib/$skin/};
-    if (-f "$cgi_path/$skin_file_name") {
-        $set{skin} = $skin_file_name;
+    if (my $mtime = _mtime("$cgi_path/$skin_file_name")) {
+        $set{skin} = mtime_filter($skin_file_name, $mtime);
     }
 
     my $custom_file_name = $file_name;
     $custom_file_name =~ s{(?:^|/)skins/standard/}{skins/custom/};
-    if (-f "$cgi_path/$custom_file_name") {
-        $set{custom} = $custom_file_name;
+    if (my $custom_mtime = _mtime("$cgi_path/$custom_file_name")) {
+        $set{custom} = mtime_filter($custom_file_name, $custom_mtime);
     }
 
     return \%set;
 }
 
+sub _concatenate_css {
+    my @sources = map { @$_ } @_;
+    return unless @sources;
+
+    my %files =
+        map {
+            (my $file = $_) =~ s/(^[^\?]+)\?.+/$1/;
+            $_ => $file;
+        } @sources;
+
+    my $cgi_path   = bz_locations()->{cgi_path};
+    my $skins_path = bz_locations()->{assetsdir};
+
+    # build minified files
+    my @minified;
+    foreach my $source (@sources) {
+        next unless -e "$cgi_path/$files{$source}";
+        my $file = $skins_path . '/' . md5_hex($source) . '.css';
+        if (!-e $file) {
+            my $content = read_file("$cgi_path/$files{$source}");
+
+            # minify
+            $content =~ s{/\*.*?\*/}{}sg;   # comments
+            $content =~ s{(^\s+|\s+$)}{}mg; # leading/trailing whitespace
+            $content =~ s{\n}{}g;           # single line
+
+            # rewrite urls
+            $content =~ s{url\(([^\)]+)\)}{_css_url_rewrite($source, $1)}eig;
+
+            write_file($file, "/* $files{$source} */\n" . $content . "\n");
+        }
+        push @minified, $file;
+    }
+
+    # concat files
+    my $file = $skins_path . '/' . md5_hex(join(' ', @sources)) . '.css';
+    if (!-e $file) {
+        my $content = '';
+        foreach my $source (@minified) {
+            $content .= read_file($source);
+        }
+        write_file($file, $content);
+    }
+
+    $file =~ s/^\Q$cgi_path\E\///o;
+    return mtime_filter($file);
+}
+
+sub _css_url_rewrite {
+    my ($source, $url) = @_;
+    # rewrite relative urls as the unified stylesheet lives in a different
+    # directory from the source
+    $url =~ s/(^['"]|['"]$)//g;
+    if (substr($url, 0, 1) eq '/' || substr($url, 0, 5) eq 'data:') {
+        return 'url(' . $url . ')';
+    }
+    return 'url(../../' . dirname($source) . '/' . $url . ')';
+}
+
+sub _concatenate_js {
+    return @_ unless CONCATENATE_ASSETS;
+    my ($sources) = @_;
+    return [] unless $sources;
+    $sources = ref($sources) ? $sources : [ $sources ];
+
+    my %files =
+        map {
+            (my $file = $_) =~ s/(^[^\?]+)\?.+/$1/;
+            $_ => $file;
+        } @$sources;
+
+    my $cgi_path   = bz_locations()->{cgi_path};
+    my $skins_path = bz_locations()->{assetsdir};
+
+    # build minified files
+    my @minified;
+    foreach my $source (@$sources) {
+        next unless -e "$cgi_path/$files{$source}";
+        my $file = $skins_path . '/' . md5_hex($source) . '.js';
+        if (!-e $file) {
+            my $content = read_file("$cgi_path/$files{$source}");
+
+            # minimal minification
+            $content =~ s#/\*.*?\*/##sg;    # block comments
+            $content =~ s#(^ +| +$)##gm;    # leading/trailing spaces
+            $content =~ s#^//.+$##gm;       # single line comments
+            $content =~ s#\n{2,}#\n#g;      # blank lines
+            $content =~ s#(^\s+|\s+$)##g;   # whitespace at the start/end of file
+
+            write_file($file, "/* $files{$source} */\n" . $content . "\n");
+        }
+        push @minified, $file;
+    }
+
+    # concat files
+    my $file = $skins_path . '/' . md5_hex(join(' ', @$sources)) . '.js';
+    if (!-e $file) {
+        my $content = '';
+        foreach my $source (@minified) {
+            $content .= read_file($source);
+        }
+        write_file($file, $content);
+    }
+
+    $file =~ s/^\Q$cgi_path\E\///o;
+    return [ $file ];
+}
+
 # YUI dependency resolution
 sub yui_resolve_deps {
     my ($yui, $yui_deps) = @_;
@@ -793,7 +900,7 @@ sub create {
             html_light => \&Bugzilla::Util::html_light_quote,
 
             email => \&Bugzilla::Util::email_filter,
-
+            
             mtime => \&mtime_filter,
 
             # iCalendar contentline filter
@@ -891,14 +998,6 @@ sub create {
                 }
             },
 
-            asset_file => sub {
-                return Bugzilla->asset_manager->asset_file($_[0]);
-            },
-
-            asset_files => sub {
-                return Bugzilla->asset_manager->asset_files(@{ $_[0] });
-            },
-
             json_encode => sub {
                 return encode_json($_[0]);
             },
@@ -992,6 +1091,7 @@ sub create {
 
             'css_files' => \&css_files,
             yui_resolve_deps => \&yui_resolve_deps,
+            concatenate_js => \&_concatenate_js,
 
             # Whether or not keywords are enabled, in this Bugzilla.
             'use_keywords' => sub { return Bugzilla::Keyword->any_exist; },
index b7a852e0f7b9028bad02fb45b56dee07c0cbd739..d9ce9e8a994c62dc769f48875b51f257a53694b2 100755 (executable)
@@ -52,7 +52,6 @@ GetOptions(\%switch, 'help|h|?',
                      'no-templates|t', 'verbose|v|no-silent',
                      'cpanm:s', 'check-modules',
                      'make-admin=s', 'reset-password=s', 'version|V',
-                     'no-assets',
                      'default-localconfig',
                      'no-database', 'no-permissions|p');
 
@@ -194,11 +193,6 @@ my %old_params = $switch{'no-database'} ? () : update_params();
 Bugzilla::Template::precompile_templates(!$silent)
     unless $switch{'no-templates'};
 
-unless ($switch{'no-assets'}) {
-    say "Compiling assets..." unless $silent;
-    Bugzilla->asset_manager->compile_all;
-}
-
 ###########################################################################
 # Set proper rights (--CHMOD--)
 ###########################################################################
index 18faf19cc54a5e15c9af523e607466cf96935596..5ece7880561777cab17114e93d97d547cdb21274 100644 (file)
         <button type="button" id="mode-btn" class="major">
           <span id="mode-btn-readonly" title="Enable editing fields for [% terms.bug %] metadata">Edit [% terms.Bug %]</span>
           <span id="mode-btn-loading">
-            <img id="edit-throbber" src="[% asset_file('extensions/BugModal/web/throbber.gif') FILTER html %]" width="16" height="11">
+            <img id="edit-throbber" src="extensions/BugModal/web/throbber.gif" width="16" height="11">
             Fetching
           </span>
         </button>
         %]
         <button id="product-search" type="button" class="minor">Search</button>
         <button id="product-search-cancel" type="button" class="minor" style="display:none">X</button>
-        <img id="product-throbber" src="[% asset_file('extensions/BugModal/web/throbber.gif') FILTER html %]"
+        <img id="product-throbber" src="extensions/BugModal/web/throbber.gif"
           width="16" height="11" style="display:none">
         <img id="product-search-error" class="tt" src="extensions/BugModal/web/error.png"
           width="16" height="16" style="display:none">
index e09a16e3985626c07655a0035865c0d77034ab49..e7e0ed74934724b08f5aeaaed48325fae733daa8 100644 (file)
@@ -6,10 +6,10 @@
   # defined by the Mozilla Public License, v. 2.0.
   #%]
 
-<link href="[% asset_file("extensions/BugmailFilter/web/style/bugmail-filter.css") FILTER html %]"
+<link href="[% "extensions/BugmailFilter/web/style/bugmail-filter.css" FILTER mtime %]"
       rel="stylesheet" type="text/css">
 <script type="text/javascript"
-        src="[% asset_file("extensions/BugmailFilter/web/js/bugmail-filter.js") FILTER html %]"></script>
+        src="[% "extensions/BugmailFilter/web/js/bugmail-filter.js" FILTER mtime %]"></script>
 
 [% SET selectable_products = user.get_selectable_products %]
 [% SET dont_show_button = 1 %]
@@ -26,7 +26,7 @@ var cpts = new Array();
   [% n = n + 1 %]
 [% END %]
 </script>
-<script type="text/javascript" src="[% asset_file('js/productform.js') FILTER html %]">
+<script type="text/javascript" src="[% 'js/productform.js' FILTER mtime FILTER html %]">
 </script>
 
 <hr>
index 8252cdb9e1bb735fbe5ecd422ba2bddc1ddafd1e..5e27c1247833854a24a1d3f59d0a76c937ca143f 100644 (file)
@@ -44,7 +44,7 @@ var watch_users = new Array();
   [% END %]
 [% END %]
 </script>
-<script type="text/javascript" src="[% asset_file('js/productform.js') FILTER html %]">
+<script type="text/javascript" src="[% 'js/productform.js' FILTER mtime FILTER html %]">
 </script>
 
 <script>
index 112118280341fcceee28d96c860841a48a605d3c..10f501965bfb05d3b7016a5e653600ce4ada7a48 100644 (file)
@@ -8,6 +8,6 @@
 
 [% USE Bugzilla %]
 <meta property="og:type" content="website">
-<meta property="og:image" content='[% urlbase FILTER none %][% asset_file("extensions/OpenGraph/web/moz-social-bw-rgb-32x32.png") FILTER html %]'>
+<meta property="og:image" content="[% urlbase FILTER none %]extensions/OpenGraph/web/moz-social-bw-rgb-32x32.png">
 <meta property="og:title" content="[% title FILTER none %]">
 <meta property="og:url" content="[% Bugzilla.cgi.self_url FILTER html %]">
index bbd0cfc40b0aa2d8cdb96cc4fddce42e1b931301..c232f677d6e51a04b8d9c0c1f2c0d614ca6df25a 100644 (file)
@@ -33,7 +33,7 @@
   <div class="pcs-header">
     [% input_label FILTER none %]&nbsp;
     <img id="[% id FILTER html %]-throbber"
-      src="[% asset_file('extensions/ProdCompSearch/web/images/throbber.gif') FILTER html %]"
+      src="extensions/ProdCompSearch/web/images/throbber.gif"
       style="display:none" width="16" height="11">
     <span class="pcs-message" id="[% id FILTER html %]-no_results" style="display:none">
       No components found
index 3e56ab2f4e89b3390e8a55eccc07b33081096aac..b407b4f3ae80edcba2c83af625111a1931ac324f 100644 (file)
@@ -57,9 +57,9 @@ Interdiff of #[% oldid %] and #[% newid %] for [% terms.bug %] #[% bugid %]
 [% ELSE %]
   <html>
   <head>
-  <link href="[% asset_file('skins/standard/attachment.css') FILTER html %]"
+  <link href="[% 'skins/standard/attachment.css' FILTER mtime %]" 
         rel="stylesheet" type="text/css">
-  <script src="[% asset_file('js/attachment.js') FILTER html %]" 
+  <script src="[% 'js/attachment.js' FILTER mtime %]" 
           type="text/javascript"></script>
   </head>
   <body onload="[% onload FILTER html %]">
index eb7d240b661f7dc11d938d88b3137220412119b4..2f8658c9cba5ef9e552095458b16bbaf7f6274e2 100644 (file)
@@ -22,7 +22,8 @@
 
 [% PROCESS bug/time.html.tmpl %]
 
-<script src="[% asset_file('js/comments.js') FILTER html %]" type="text/javascript"></script>
+<script src="[% 'js/comments.js' FILTER mtime %]" type="text/javascript">
+</script>
 
 <script type="text/javascript">
 <!--
index 09113bbf33d086f5b19a4f41cbaff78eeff7809f..55184c47b5b53af28d6471d393b7f93ed1be6648 100644 (file)
@@ -30,7 +30,7 @@
 
 [% DEFAULT flag_table_id = "flags" %]
 
-<script src="[% asset_file('js/flag.js') FILTER html %]" type="text/javascript"></script>
+<script src="[% 'js/flag.js' FILTER mtime %]" type="text/javascript"></script>
 
 <table id="[% flag_table_id FILTER html %]">
   [% UNLESS flag_no_header %]
index 57088ac2a92d71fd35cf800e9a87e8ddc3e45476..107c69069e07875883c535ea136b3a5051cde44e 100644 (file)
@@ -52,6 +52,7 @@
   style_urls = []
   no_yui = 0
   jquery = []
+  jquery_css = []
   generate_api_token = 0
 %]
 
@@ -72,7 +73,7 @@
   "js/jquery/ui/jquery-ui-structure-min.css",
   "js/jquery/ui/jquery-ui-theme-min.css",
 ] %]
-[% CALL style_urls.import(jq_css_urls) %]
+[% style_urls.import(jquery_css, jq_css_urls) FILTER null %]
 
 [%# Add our required jQuery plugins %]
 [% jquery.push("cookie", "devbridgeAutocomplete") %]
     [% PROCESS 'global/setting-descs.none.tmpl' %]
 
     [% SET css_sets = css_files(style_urls.unique, no_yui) %]
-    [% SET css_standard_and_skin = css_sets.standard %]
-    [% CALL css_standard_and_skin.import(css_sets.skin) %]
-    [% IF style %]
-      [% FOREACH asset_url = asset_files(css_standard_and_skin) %]
+    [% IF constants.CONCATENATE_ASSETS %]
+      [% PROCESS format_css_link asset_url = css_sets.unified_standard_skin %]
+    [% ELSE %]
+      [% FOREACH asset_url = css_sets.standard %]
+        [% PROCESS format_css_link %]
+      [% END %]
+      [% FOREACH asset_url = css_sets.skin %]
         [% PROCESS format_css_link %]
       [% END %]
+    [% END %]
 
+    [% IF style %]
       <style type="text/css">
         [% style %]
       </style>
+    [% END %]
 
-      [% FOREACH asset_url = asset_files(css_sets.custom) %]
-        [% PROCESS format_css_link %]
-      [% END %]
-    [% ELSE %]
-      [% SET css_all = [] %]
-      [% CALL css_all.import(css_standard_and_skin, css_sets.custom) %]
-      [% FOREACH asset_url = asset_files(css_all) %]
-        [% PROCESS format_css_link %]
+    [% IF css_sets.unified_custom %]
+      [% IF constants.CONCATENATE_ASSETS %]
+        [% PROCESS format_css_link asset_url = css_sets.unified_custom %]
+      [% ELSE %]
+        [% FOREACH asset_url = css_sets.custom %]
+          [% PROCESS format_css_link %]
+        [% END %]
       [% END %]
     [% END %]
 
     [% END %]
     [% starting_js_urls.push('js/global.js') %]
 
+    [% FOREACH asset_url = concatenate_js(starting_js_urls) %]
+      [% PROCESS format_js_link %]
+    [% END %]
+
     [% inline_javascript = BLOCK %]
         [% IF NOT no_yui %]
           YAHOO.namespace('bugzilla');
           [% javascript %]
         [% END %]
     [% END %]
-
     [% IF inline_javascript.search("\\S") %]
-      [% FOREACH asset_url = asset_files(starting_js_urls) %]
-        [% PROCESS format_js_link %]
-      [% END %]
-
       <script [% script_nonce FILTER none %]>
         [% inline_javascript FILTER none %]
       </script>
+    [% END %]
 
-      [% FOREACH asset_url = asset_files(javascript_urls) %]
-        [% PROCESS format_js_link %]
-      [% END %]
-    [% ELSE %]
-      [% SET js_all = [] %]
-      [% CALL js_all.import(starting_js_urls) %]
-      [% CALL js_all.import(javascript_urls) %]
-      [% FOREACH asset_url = asset_files(js_all) %]
-        [% PROCESS format_js_link %]
-      [% END %]
+    [% FOREACH asset_url = concatenate_js(javascript_urls) %]
+      [% PROCESS format_js_link %]
     [% END %]
 
     [%# this puts the live bookmark up on firefox for the Atom feed %]
       </td>
       <td id="moz_tab">
         <a href="https://www.mozilla.org/" title="Mozilla - Home of the Mozilla Project">
-          <img src="[% asset_file('images/tabzilla.png') FILTER html %]" border="0" height="42" width="154"></a>
+          <img src="images/tabzilla.png" border="0" height="42" width="154"></a>
       </td>
     </tr>
     </table>
 [% END %]
 
 [% BLOCK format_css_link %]
-  <link data-file="[% asset_url FILTER html %]" href="[% asset_file(asset_url) FILTER html %]" rel="stylesheet" type="text/css">
-[%+ END %]
+  <link href="[% asset_url FILTER html %]" rel="stylesheet" type="text/css">
+[% END %]
 
 [% BLOCK format_js_link %]
-  <script [% script_nonce FILTER none %] data-file="[% asset_url FILTER html %]" type="text/javascript" src="[% asset_file(asset_url) FILTER html %]"></script>
-[%+ END %]
+  <script [% script_nonce FILTER none %] type="text/javascript" src="[% asset_url FILTER mtime FILTER html %]"></script>
+[% END %]
index 4c186e2072c446a0046f3235a1a1fc930ebbd893..f4c3549ed083a9e7842135ad2349b7275b84305e 100644 (file)
@@ -39,7 +39,7 @@
   <head>
     <title>[% title FILTER html %]</title>
     <base href="[% urlbase FILTER html %]">
-    <link href="[% asset_file('skins/standard/buglist.css') FILTER html %]" 
+    <link href="[% 'skins/standard/buglist.css' FILTER mtime %]" 
           rel="stylesheet" type="text/css">
   </head>
 
index 88f14b910492a4536ebdb0b615056fd8334841d5..a085227903cd80cf88a9241c37c2cdf8253dd9a4 100644 (file)
@@ -39,9 +39,9 @@
 
   <head>
     <title>[% title FILTER html %]</title>
-    <link href="[% asset_file('skins/standard/global.css') FILTER html %]"
+    <link href="[% 'skins/standard/global.css' FILTER mtime %]"
           rel="stylesheet" type="text/css">
-    <link href="[% asset_file('skins/standard/duplicates.css') FILTER html %]"
+    <link href="[% 'skins/standard/duplicates.css' FILTER mtime %]"
           rel="stylesheet" type="text/css">
   </head>
 
index bc9c5b6fdc9a9d6551f714fc948c0a7921824626..0b8321dd13352d0fb50dad70283795210e46acc5 100644 (file)
@@ -10,7 +10,7 @@
 <html>
   <head>
     <title>Bugzilla::REST::API</title>
-    <link href="[% urlbase FILTER none %][% asset_file('skins/standard/global.css') FILTER html %]"
+    <link href="[% urlbase FILTER none %][% 'skins/standard/global.css' FILTER mtime %]"
           rel="stylesheet" type="text/css">
   </head>
   <body>
index e3b149969a26e4dd177c0a8cbb4bb05fc5dbc202..3fb1f8eae8bbc0084ac513522f8b1d371e5a7f21 100644 (file)
@@ -76,8 +76,8 @@
     TUI_alternates['custom_search_advanced'] = "Show Advanced Features";
     TUI_hide_default('custom_search_advanced');
   </script>
-  <script type="text/javascript" src="[% asset_file('js/custom-search.js') FILTER html %]"></script>
-  <script type="text/javascript" src="[% asset_file('js/history.js/native.history.js') FILTER html %]"></script>
+  <script type="text/javascript" src="[% 'js/custom-search.js' FILTER mtime %]"></script>
+  <script type="text/javascript" src="[% 'js/history.js/native.history.js' FILTER mtime %]"></script>
   <script type="text/javascript">
     redirect_html4_browsers();
     [%# These are alternative labels for the AND and OR options in and_all_select %]