morgan pushed to branch maint-14.0 at The Tor Project / Applications / tor-browser-build

Commits:

6 changed files:

Changes:

  • projects/release/create_update_responses_tar
    1 1
     #!/bin/bash
    
    2 2
     [% c("var/set_default_env") -%]
    
    3 3
     [% SET channel = c('var/channel') -%]
    
    4
    +rm -Rf [% shell_quote(c("basedir")) %]/tools/update-responses/htdocs/[% channel %]
    
    4 5
     [% shell_quote(c("basedir")) %]/tools/update-responses/update_responses [% channel %]
    
    5 6
     mkdir -p [% shell_quote(path(dest_dir)) %]/update-responses
    
    6 7
     mv [% shell_quote(c("basedir")) %]/tools/update-responses/htdocs/[% channel %] [% channel %]
    
    7
    -chmod 775 [% channel %]
    
    8
    -chmod 664 [% channel %]/.htaccess [% channel %]/*
    
    8
    +find [% channel %] -type d -exec chmod 775 {} \;
    
    9
    +find [% channel %] -type f -exec chmod 664 {} \;
    
    9 10
     tar cf [% shell_quote(path(dest_dir)) %]/update-responses/update-responses-[% channel %]-[%  c("version") %].tar [% channel %]

  • projects/release/update_responses_config.yml
    ... ... @@ -53,10 +53,6 @@ versions:
    53 53
               - [% ver %]
    
    54 54
     [%   END;
    
    55 55
        END -%]
    
    56
    -        # for example, osx32: osx64
    
    57
    -        migrate_archs:
    
    58
    -        # for example, pt-PT: pt-BR
    
    59
    -        migrate_langs:
    
    60 56
             # minSupportedOsVersion on macOS corresponds to the Darwin version ( https://en.wikipedia.org/wiki/Darwin_(operating_system) )
    
    61 57
             macos:
    
    62 58
                 # macOS v10.15.0
    

  • tools/dmg2mar
    ... ... @@ -102,7 +102,7 @@ sub get_dmg_files_from_sha256sums {
    102 102
             next unless $filename;
    
    103 103
             chomp $filename;
    
    104 104
             next unless $filename =~ m/^$appname_dmg-macos-(.+)\.dmg$/;
    
    105
    -        push @files, { filename => $filename, version => $1, lang => 'ALL' };
    
    105
    +        push @files, { filename => $filename, version => $1 };
    
    106 106
         }
    
    107 107
         return @files;
    
    108 108
     }
    
    ... ... @@ -116,11 +116,7 @@ sub convert_files {
    116 116
             print "Finished $_[2]\n";
    
    117 117
           });
    
    118 118
         foreach my $file (get_dmg_files_from_sha256sums) {
    
    119
    -        # The 'ja' locale is a special case: it is called 'ja-JP-mac'
    
    120
    -        # internally on OSX, but the dmg file still uses 'ja' to avoid
    
    121
    -        # confusing users.
    
    122
    -        my $mar_lang = $file->{lang} eq 'ja' ? 'ja-JP-mac' : $file->{lang};
    
    123
    -        my $output = "$appname_mar-macos-$file->{version}_$mar_lang.mar";
    
    119
    +        my $output = "$appname_mar-macos-$file->{version}_ALL.mar";
    
    124 120
             my $step_name = "$file->{filename} -> $output";
    
    125 121
             print "Starting $step_name\n";
    
    126 122
             $pm->start($step_name) and next;
    

  • tools/signing/functions
    ... ... @@ -23,7 +23,7 @@ function check_update_responses_repository_dir {
    23 23
       if test -z "$update_responses_repository_dir" || ! test -d "$update_responses_repository_dir"
    
    24 24
       then
    
    25 25
         cat << 'EOF' > /dev/stderr
    
    26
    -$aus1_repository_dir is not defined, or the directory does not exist
    
    26
    +$update_responses_repository_dir is not defined, or the directory does not exist
    
    27 27
     You should clone git@gitlab.torproject.org:tpo/applications/tor-browser-update-responses.git
    
    28 28
     and set $update_responses_repository_dir in set-config.update-responses
    
    29 29
     EOF
    

  • tools/signing/upload-update_responses-to-staticiforme
    ... ... @@ -39,8 +39,34 @@ do
    39 39
       mv "$file" "$tbb_version_type/$fname"
    
    40 40
     done
    
    41 41
     
    
    42
    +# Keep directory from previous release if they are not in the new release.
    
    43
    +# This happens when a release does not include some platforms.
    
    44
    +for file in $(ls -1 "$old_ur/$tbb_version_type")
    
    45
    +do
    
    46
    +  test -d "$old_ur/$tbb_version_type/$file" || continue
    
    47
    +  test -d "$tbb_version_type/$file" && continue
    
    48
    +  mv -f "$old_ur/$tbb_version_type/$file" "$tbb_version_type/$file"
    
    49
    +done
    
    50
    +
    
    51
    +# Commit each sub-directory separately
    
    52
    +for file in $(ls -1 "$tbb_version_type")
    
    53
    +do
    
    54
    +  test -d "$tbb_version_type/$file" || continue
    
    55
    +  git add "$tbb_version_type/$file"
    
    56
    +  git add "$tbb_version_type/download-$file.json"
    
    57
    +  git diff --quiet  --cached --exit-code || \
    
    58
    +    git commit -m "$tbb_version_type: new version, $tbb_version ($file)"
    
    59
    +done
    
    60
    +
    
    61
    +if is_project torbrowser; then
    
    62
    +  git add "$tbb_version_type"/download-android-*.json
    
    63
    +  git diff --quiet  --cached --exit-code || \
    
    64
    +    git commit -m "$tbb_version_type: new version, $tbb_version (android)"
    
    65
    +fi
    
    66
    +
    
    42 67
     git add "$tbb_version_type"
    
    43
    -git commit -m "$tbb_version_type: new version, $tbb_version"
    
    68
    +git diff --quiet  --cached --exit-code || \
    
    69
    +  git commit -m "$tbb_version_type: new version, $tbb_version"
    
    44 70
     git push
    
    45 71
     
    
    46 72
     # we just need to push mullvadbrowser's update responses to git, not deploy to staticiforme
    

  • tools/update-responses/update_responses
    ... ... @@ -29,7 +29,6 @@ setlocale(LC_ALL, "C");
    29 29
     
    
    30 30
     my $htdocsdir = "$FindBin::Bin/htdocs";
    
    31 31
     my $config = LoadFile("$FindBin::Bin/config.yml");
    
    32
    -my %htdocsfiles;
    
    33 32
     my $releases_dir = $config->{releases_dir};
    
    34 33
     $releases_dir = "$FindBin::Bin/$releases_dir" unless $releases_dir =~ m/^\//;
    
    35 34
     my @check_errors;
    
    ... ... @@ -51,12 +50,6 @@ sub get_tmpdir {
    51 50
                                     : ());
    
    52 51
     }
    
    53 52
     
    
    54
    -sub build_targets_by_os {
    
    55
    -    exit_error "Unknown build target for OS $_[0]" unless $config->{build_targets}{$_[0]};
    
    56
    -    my $r = $config->{build_targets}{$_[0]};
    
    57
    -    return ref $r eq 'ARRAY' ? @$r : ($r);
    
    58
    -}
    
    59
    -
    
    60 53
     sub get_nbprocs {
    
    61 54
         return $ENV{NUM_PROCS} if defined $ENV{NUM_PROCS};
    
    62 55
         if (-f '/proc/cpuinfo') {
    
    ... ... @@ -80,19 +73,11 @@ sub setup_martools {
    80 73
     }
    
    81 74
     
    
    82 75
     sub write_htdocs {
    
    83
    -    my ($channel, $file, $content) = @_;
    
    76
    +    my ($channel, $dir, $file, $content) = @_;
    
    84 77
         mkdir $htdocsdir unless -d $htdocsdir;
    
    85 78
         mkdir "$htdocsdir/$channel" unless -d "$htdocsdir/$channel";
    
    86
    -    write_file("$htdocsdir/$channel/$file", $content);
    
    87
    -    $htdocsfiles{$channel}->{$file} = 1;
    
    88
    -}
    
    89
    -
    
    90
    -sub clean_htdocs {
    
    91
    -    my ($channel) = @_;
    
    92
    -    opendir(my $d, "$htdocsdir/$channel");
    
    93
    -    my @files = grep { ! $htdocsfiles{$channel}->{$_} } readdir $d;
    
    94
    -    closedir $d;
    
    95
    -    unlink map { "$htdocsdir/$channel/$_" } @files;
    
    79
    +    mkdir "$htdocsdir/$channel/$dir" unless -d "$htdocsdir/$channel/$dir";
    
    80
    +    write_file("$htdocsdir/$channel/$dir/$file", $content);
    
    96 81
     }
    
    97 82
     
    
    98 83
     sub get_sha512_hex_of_file {
    
    ... ... @@ -113,9 +98,9 @@ sub get_version_files {
    113 98
         foreach my $file (readdir $d) {
    
    114 99
             next unless -f "$vdir/$file";
    
    115 100
             if ($file !~ m/incremental\.mar$/ &&
    
    116
    -            $file =~ m/^$appname-(.+)-${version}_(.+)\.mar$/) {
    
    117
    -            my ($os, $lang) = ($1, $2);
    
    118
    -            $files->{$os}{$lang}{complete} = {
    
    101
    +            $file =~ m/^$appname-(.+)-${version}_ALL\.mar$/) {
    
    102
    +            my $os = $1;
    
    103
    +            $files->{$os}{complete} = {
    
    119 104
                     type => 'complete',
    
    120 105
                     URL => "$download_url/$file",
    
    121 106
                     size => -s "$vdir/$file",
    
    ... ... @@ -126,9 +111,9 @@ sub get_version_files {
    126 111
                 };
    
    127 112
                 next;
    
    128 113
             }
    
    129
    -        if ($file =~ m/^$appname-(.+)--(.+)-${version}_(.+)\.incremental\.mar$/) {
    
    130
    -            my ($os, $from_version, $lang) = ($1, $2, $3);
    
    131
    -            $files->{$os}{$lang}{partial}{$from_version} = {
    
    114
    +        if ($file =~ m/^$appname-(.+)--(.+)-${version}_ALL\.incremental\.mar$/) {
    
    115
    +            my ($os, $from_version) = ($1, $2);
    
    116
    +            $files->{$os}{partial}{$from_version} = {
    
    132 117
                     type => 'partial',
    
    133 118
                     URL => "$download_url/$file",
    
    134 119
                     size => -s "$vdir/$file",
    
    ... ... @@ -235,14 +220,14 @@ sub extract_mar {
    235 220
     }
    
    236 221
     
    
    237 222
     sub mar_filename {
    
    238
    -    my ($config, $appname, $version, $os, $lang) = @_;
    
    239
    -    version_dir($config, $version) .  "/$appname-$os-${version}_$lang.mar";
    
    223
    +    my ($config, $appname, $version, $os) = @_;
    
    224
    +    version_dir($config, $version) .  "/$appname-$os-${version}_ALL.mar";
    
    240 225
     }
    
    241 226
     
    
    242 227
     sub create_incremental_mar {
    
    243
    -    my ($config, $pm, $from_version, $new_version, $os, $lang, $channel) = @_;
    
    228
    +    my ($config, $pm, $from_version, $new_version, $os, $channel) = @_;
    
    244 229
         my $appname = $config->{appname_marfile};
    
    245
    -    my $mar_file = "$appname-$os--${from_version}-${new_version}_$lang.incremental.mar";
    
    230
    +    my $mar_file = "$appname-$os--${from_version}-${new_version}_ALL.incremental.mar";
    
    246 231
         my $mar_file_path = version_dir($config, $new_version) . '/' . $mar_file;
    
    247 232
         if ($ENV{MAR_SKIP_EXISTING} && -f $mar_file_path) {
    
    248 233
             print "Skipping $mar_file\n";
    
    ... ... @@ -253,7 +238,7 @@ sub create_incremental_mar {
    253 238
         my $finished_file = sub {
    
    254 239
             exit_error "Error creating $mar_file" unless $_[1] == 0;
    
    255 240
             print "Finished $mar_file\n";
    
    256
    -        $config->{versions}{$new_version}{files}{$os}{$lang}{partial}{$from_version} = {
    
    241
    +        $config->{versions}{$new_version}{files}{$os}{partial}{$from_version} = {
    
    257 242
                 type => 'partial',
    
    258 243
                 URL => "$download_url/$mar_file",
    
    259 244
                 size => -s $mar_file_path,
    
    ... ... @@ -267,9 +252,9 @@ sub create_incremental_mar {
    267 252
         my $tmpdir = get_tmpdir($config);
    
    268 253
         my $mar_c_from = get_config($config, $from_version, $os, 'mar_compression');
    
    269 254
         my $mar_c_new = get_config($config, $new_version, $os, 'mar_compression');
    
    270
    -    extract_mar(mar_filename($config, $appname, $from_version, $os, $lang),
    
    255
    +    extract_mar(mar_filename($config, $appname, $from_version, $os),
    
    271 256
                     "$tmpdir/A", $mar_c_from);
    
    272
    -    extract_mar(mar_filename($config, $appname, $new_version, $os, $lang),
    
    257
    +    extract_mar(mar_filename($config, $appname, $new_version, $os),
    
    273 258
                     "$tmpdir/B", $mar_c_new);
    
    274 259
         # bug 26054: make sure previous macOS version is code signed
    
    275 260
         if (!$ENV{NO_CODESIGNATURE} && ($os eq 'macos')
    
    ... ... @@ -306,10 +291,8 @@ sub create_incremental_mars_for_version {
    306 291
             get_version_files($config, $from_version);
    
    307 292
             my $from_v = $config->{versions}{$from_version};
    
    308 293
             foreach my $os (keys %{$v->{files}}) {
    
    309
    -            foreach my $lang (keys %{$v->{files}{$os}}) {
    
    310
    -                next unless defined $from_v->{files}{$os}{$lang}{complete};
    
    311
    -                create_incremental_mar($config, $pm, $from_version, $version, $os, $lang, $channel);
    
    312
    -            }
    
    294
    +            next unless defined $from_v->{files}{$os}{complete};
    
    295
    +            create_incremental_mar($config, $pm, $from_version, $version, $os, $channel);
    
    313 296
             }
    
    314 297
         }
    
    315 298
         $pm->wait_all_children;
    
    ... ... @@ -333,31 +316,29 @@ sub get_buildinfos {
    333 316
         setup_martools;
    
    334 317
         my $files = $config->{versions}{$version}{files};
    
    335 318
         foreach my $os (keys %$files) {
    
    336
    -        foreach my $lang (keys %{$files->{$os}}) {
    
    337
    -            next unless $files->{$os}{$lang}{complete};
    
    338
    -            my $tmpdir = get_tmpdir($config);
    
    339
    -            my $mar_compression = get_config($config, $version, $os, 'mar_compression');
    
    340
    -            extract_mar(
    
    341
    -                mar_filename($config, $config->{appname_marfile}, $version, $os, $lang),
    
    342
    -                "$tmpdir",
    
    343
    -                $mar_compression);
    
    344
    -            my $appfile = "$tmpdir/application.ini" if -f "$tmpdir/application.ini";
    
    345
    -            $appfile = "$tmpdir/Contents/Resources/application.ini"
    
    346
    -                                if -f "$tmpdir/Contents/Resources/application.ini";
    
    347
    -            exit_error "Could not find application.ini" unless $appfile;
    
    348
    -            foreach my $line (read_file($appfile)) {
    
    349
    -                if ($line =~ m/^BuildID=(.*)$/) {
    
    350
    -                    $config->{versions}{$version}{buildID} = $1;
    
    351
    -                    return;
    
    352
    -                }
    
    319
    +        next unless $files->{$os}{complete};
    
    320
    +        my $tmpdir = get_tmpdir($config);
    
    321
    +        my $mar_compression = get_config($config, $version, $os, 'mar_compression');
    
    322
    +        extract_mar(
    
    323
    +            mar_filename($config, $config->{appname_marfile}, $version, $os),
    
    324
    +            "$tmpdir",
    
    325
    +            $mar_compression);
    
    326
    +        my $appfile = "$tmpdir/application.ini" if -f "$tmpdir/application.ini";
    
    327
    +        $appfile = "$tmpdir/Contents/Resources/application.ini"
    
    328
    +                if -f "$tmpdir/Contents/Resources/application.ini";
    
    329
    +        exit_error "Could not find application.ini" unless $appfile;
    
    330
    +        foreach my $line (read_file($appfile)) {
    
    331
    +            if ($line =~ m/^BuildID=(.*)$/) {
    
    332
    +                $config->{versions}{$version}{buildID} = $1;
    
    333
    +                return;
    
    353 334
                 }
    
    354
    -            exit_error "Could not extract buildID from application.ini";
    
    355 335
             }
    
    336
    +        exit_error "Could not extract buildID from application.ini";
    
    356 337
         }
    
    357 338
     }
    
    358 339
     
    
    359 340
     sub get_response {
    
    360
    -    my ($config, $versions, $os, $lang, $from_version) = @_;
    
    341
    +    my ($config, $versions, $os, $from_version) = @_;
    
    361 342
         my $res;
    
    362 343
         my $writer = XML::Writer->new(OUTPUT => \$res, ENCODING => 'UTF-8');
    
    363 344
         $writer->xmlDecl;
    
    ... ... @@ -384,13 +365,13 @@ sub get_response {
    384 365
                 defined $minversion ? ( minSupportedOSVersion => $minversion ) : (),
    
    385 366
                 defined $mininstruc ? ( minSupportedInstructionSet => $mininstruc ) : (),
    
    386 367
             );
    
    387
    -        if (my $patch = $config->{versions}{$version}{files}{$os}{$lang}{complete}) {
    
    368
    +        if (my $patch = $config->{versions}{$version}{files}{$os}{complete}) {
    
    388 369
                 my @sorted_patch = map { $_ => $patch->{$_} } sort keys %$patch;
    
    389 370
                 $writer->startTag('patch', @sorted_patch);
    
    390 371
                 $writer->endTag('patch');
    
    391 372
             }
    
    392 373
             if ($from_version) {
    
    393
    -            if (my $patch = $config->{versions}{$version}{files}{$os}{$lang}{partial}{$from_version}) {
    
    374
    +            if (my $patch = $config->{versions}{$version}{files}{$os}{partial}{$from_version}) {
    
    394 375
                     my @sorted_patch = map { $_ => $patch->{$_} } sort keys %$patch;
    
    395 376
                     $writer->startTag('patch', @sorted_patch);
    
    396 377
                     $writer->endTag('patch');
    
    ... ... @@ -407,87 +388,69 @@ sub get_response {
    407 388
     sub write_responses {
    
    408 389
         my ($config, $channel) = @_;
    
    409 390
         my $versions = as_array($config->{channels}{$channel});
    
    410
    -    my (%oses, %langs, %from_versions);
    
    391
    +    my (%oses, %from_versions);
    
    411 392
         foreach my $version (@$versions) {
    
    412 393
             get_version_files($config, $version);
    
    413 394
             get_buildinfos($config, $version);
    
    414 395
             my $files = $config->{versions}{$version}{files};
    
    415
    -        my $migrate_archs = $config->{versions}{$version}{migrate_archs} // {};
    
    416
    -        foreach my $old_os (keys %$migrate_archs) {
    
    417
    -            my $new_os = $migrate_archs->{$old_os};
    
    418
    -            foreach my $lang (keys %{$files->{$new_os}}) {
    
    419
    -                $files->{$old_os}{$lang}{complete} =
    
    420
    -                    $files->{$new_os}{$lang}{complete};
    
    421
    -            }
    
    422
    -        }
    
    423 396
             foreach my $os (keys %$files) {
    
    424 397
                 $oses{$os} = 1;
    
    425
    -            foreach my $lang (keys %{$files->{$os}}) {
    
    426
    -                $langs{$lang} = 1;
    
    427
    -                foreach my $from_version (keys %{$files->{$os}{$lang}{partial}}) {
    
    428
    -                    $from_versions{$from_version} = 1;
    
    429
    -                }
    
    398
    +            foreach my $from_version (keys %{$files->{$os}{partial}}) {
    
    399
    +                $from_versions{$from_version} = 1;
    
    430 400
                 }
    
    431 401
             }
    
    432 402
         }
    
    433 403
         my $versions_str = join('+', @$versions);
    
    434 404
         foreach my $os (keys %oses) {
    
    435
    -        foreach my $lang (keys %langs) {
    
    436
    -            my $resp = get_response($config, $versions, $os, $lang);
    
    437
    -            write_htdocs($channel, "$versions_str-$os-$lang.xml", $resp);
    
    438
    -            foreach my $from_version (keys %from_versions) {
    
    439
    -                $resp = get_response($config, $versions, $os, $lang, $from_version);
    
    440
    -                write_htdocs($channel, "$from_version-$versions_str-$os-$lang.xml", $resp);
    
    441
    -            }
    
    405
    +        my $resp = get_response($config, $versions, $os);
    
    406
    +        write_htdocs($channel, $os, "$versions_str-$os.xml", $resp);
    
    407
    +        foreach my $from_version (keys %from_versions) {
    
    408
    +            $resp = get_response($config, $versions, $os, $from_version);
    
    409
    +            write_htdocs($channel, $os, "$from_version-$versions_str-$os.xml", $resp);
    
    442 410
             }
    
    411
    +        write_htdocs($channel, $os, 'no-update.xml',
    
    412
    +            '<?xml version="1.0" encoding="UTF-8"?>'
    
    413
    +            . "\n<updates></updates>\n");
    
    443 414
         }
    
    444
    -    write_htdocs($channel, 'no-update.xml',
    
    445
    -        '<?xml version="1.0" encoding="UTF-8"?>'
    
    446
    -        . "\n<updates></updates>\n");
    
    447 415
     }
    
    448 416
     
    
    449 417
     sub write_htaccess {
    
    450 418
         my ($config, $channel) = @_;
    
    451
    -    my $flags = "[last]";
    
    452
    -    my $htaccess = "RewriteEngine On\n";
    
    453
    -    $htaccess .= $config->{htaccess_rewrite_rules}{$channel} // '';
    
    419
    +
    
    420
    +    my $htaccess_main = "RewriteEngine On\n";
    
    421
    +    $htaccess_main .= $config->{htaccess_rewrite_rules}{$channel} // '';
    
    454 422
         my $versions = as_array($config->{channels}{$channel});
    
    455 423
         my $versions_str = join('+', @$versions);
    
    456
    -    my (%oses, %langs, %from_versions);
    
    457
    -    my $migrate_langs;
    
    424
    +    foreach my $os (sort keys %{$config->{build_targets}}) {
    
    425
    +        foreach my $bt (@{ as_array($config->{build_targets}{$os}) }) {
    
    426
    +            $htaccess_main .= "RewriteRule ^$bt/(.*) $os/\$1 [last]\n";
    
    427
    +        }
    
    428
    +    }
    
    429
    +    write_htdocs($channel, '.', '.htaccess', $htaccess_main);
    
    430
    +
    
    431
    +    my (%oses, %from_versions);
    
    458 432
         foreach my $version (@$versions) {
    
    459
    -        $migrate_langs = $config->{versions}{$version}{migrate_langs}
    
    460
    -                                if $config->{versions}{$version}{migrate_langs};
    
    461 433
             my $files = $config->{versions}{$version}{files};
    
    462 434
             foreach my $os (keys %$files) {
    
    463 435
                 $oses{$os} = 1;
    
    464
    -            foreach my $lang (keys %{$files->{$os}}) {
    
    465
    -                $langs{$lang} = 1;
    
    466
    -                foreach my $from_version (keys %{$files->{$os}{$lang}{partial}}) {
    
    467
    -                    $from_versions{$from_version} = 1;
    
    468
    -                }
    
    436
    +            foreach my $from_version (keys %{$files->{$os}{partial}}) {
    
    437
    +                $from_versions{$from_version} = 1;
    
    469 438
                 }
    
    470 439
             }
    
    471
    -        $htaccess .= "RewriteRule ^[^\/]+/$version/ no-update.xml $flags\n";
    
    472 440
         }
    
    473
    -    foreach my $os (sort keys %oses) {
    
    474
    -        foreach my $bt (build_targets_by_os($os)) {
    
    475
    -            foreach my $lang (sort keys %langs) {
    
    476
    -                foreach my $from_version (sort keys %from_versions) {
    
    477
    -                    $htaccess .= "RewriteRule ^$bt/$from_version/$lang "
    
    478
    -                              .  "$from_version-$versions_str-$os-$lang.xml $flags\n";
    
    479
    -                }
    
    480
    -                $htaccess .= "RewriteRule ^$bt/[^\/]+/$lang "
    
    481
    -                          .  "$versions_str-$os-$lang.xml $flags\n";
    
    482
    -            }
    
    483
    -            foreach my $lang (sort keys %$migrate_langs) {
    
    484
    -                $htaccess .= "RewriteRule ^$bt/[^\/]+/$lang "
    
    485
    -                          .  "$versions_str-$os-$migrate_langs->{$lang}.xml $flags\n";
    
    441
    +    foreach my $version (@$versions) {
    
    442
    +        my $files = $config->{versions}{$version}{files};
    
    443
    +        foreach my $os (sort keys %oses) {
    
    444
    +            my $htaccess_os = "RewriteEngine On\n";
    
    445
    +            $htaccess_os .= "RewriteRule ^$version/ no-update.xml [last]\n";
    
    446
    +            foreach my $from_version (sort keys %from_versions) {
    
    447
    +                $htaccess_os .= "RewriteRule ^$from_version/ "
    
    448
    +                             .  "$from_version-$versions_str-$os.xml [last]\n";
    
    486 449
                 }
    
    487
    -            $htaccess .= "RewriteRule ^$bt/ $versions_str-$os-ALL.xml $flags\n";
    
    450
    +            $htaccess_os .= "RewriteRule ^[^\/]+/ $versions_str-$os.xml [last]\n";
    
    451
    +            write_htdocs($channel, $os, '.htaccess', $htaccess_os);
    
    488 452
             }
    
    489 453
         }
    
    490
    -    write_htdocs($channel, '.htaccess', $htaccess);
    
    491 454
     }
    
    492 455
     
    
    493 456
     sub write_downloads_json {
    
    ... ... @@ -501,11 +464,11 @@ sub write_downloads_json {
    501 464
             tag => "$tag",
    
    502 465
             downloads => get_version_downloads($config, $version),
    
    503 466
         };
    
    504
    -    write_htdocs($channel, 'downloads.json',
    
    467
    +    write_htdocs($channel, '.', 'downloads.json',
    
    505 468
             JSON->new->utf8->canonical->encode($data));
    
    506 469
         my $pp_downloads = get_perplatform_downloads($config, $version, $tag);
    
    507 470
         foreach my $os (keys %{$pp_downloads}) {
    
    508
    -        write_htdocs($channel, "download-$os.json",
    
    471
    +        write_htdocs($channel, '.', "download-$os.json",
    
    509 472
                 JSON->new->utf8->canonical->encode($pp_downloads->{$os}));
    
    510 473
         }
    
    511 474
     }
    
    ... ... @@ -567,28 +530,26 @@ sub check_update_responses_channel {
    567 530
         my $channel_versions = as_array($config->{channels}{$channel});
    
    568 531
         my ($channel_version) = @$channel_versions;
    
    569 532
         foreach my $build_target (build_targets_list()) {
    
    570
    -        foreach my $lang (qw(en-US de)) {
    
    571
    -            my $url = "$base_url/$channel/$build_target/1.0/$lang";
    
    572
    -            my $dom = get_remote_xml($url);
    
    573
    -            if ($dom) {
    
    574
    -                my $version = check_get_version($dom);
    
    575
    -                log_step($url, 'version', $version eq $channel_version,
    
    576
    -                         "expected: $channel_version received: $version");
    
    577
    -            }
    
    578
    -            $url = "$base_url/$channel/$build_target/$channel_version/$lang";
    
    533
    +        my $url = "$base_url/$channel/$build_target/1.0/ALL";
    
    534
    +        my $dom = get_remote_xml($url);
    
    535
    +        if ($dom) {
    
    536
    +            my $version = check_get_version($dom);
    
    537
    +            log_step($url, 'version', $version eq $channel_version,
    
    538
    +                "expected: $channel_version received: $version");
    
    539
    +        }
    
    540
    +        $url = "$base_url/$channel/$build_target/$channel_version/ALL";
    
    541
    +        $dom = get_remote_xml($url);
    
    542
    +        log_step($url, 'no_update', check_no_update($dom)) if $dom;
    
    543
    +        my @inc = @{$config->{versions}{$channel_version}{incremental_from}}
    
    544
    +                  if $config->{versions}{$channel_version}{incremental_from};
    
    545
    +        foreach my $inc_from (@inc) {
    
    546
    +            my $url = "$base_url/$channel/$build_target/$inc_from/ALL";
    
    579 547
                 $dom = get_remote_xml($url);
    
    580
    -            log_step($url, 'no_update', check_no_update($dom)) if $dom;
    
    581
    -            my @inc = @{$config->{versions}{$channel_version}{incremental_from}}
    
    582
    -                      if $config->{versions}{$channel_version}{incremental_from};
    
    583
    -            foreach my $inc_from (@inc) {
    
    584
    -                my $url = "$base_url/$channel/$build_target/$inc_from/$lang";
    
    585
    -                $dom = get_remote_xml($url);
    
    586
    -                next unless $dom;
    
    587
    -                my $version = check_get_version($dom);
    
    588
    -                log_step($url, 'version', $version eq $channel_version,
    
    589
    -                         "expected: $channel_version received: $version");
    
    590
    -                log_step($url, 'has_incremental', check_has_incremental($dom));
    
    591
    -            }
    
    548
    +            next unless $dom;
    
    549
    +            my $version = check_get_version($dom);
    
    550
    +            log_step($url, 'version', $version eq $channel_version,
    
    551
    +                     "expected: $channel_version received: $version");
    
    552
    +            log_step($url, 'has_incremental', check_has_incremental($dom));
    
    592 553
             }
    
    593 554
         }
    
    594 555
     }
    
    ... ... @@ -667,11 +628,9 @@ my %actions = (
    667 628
             exit_error "Wrong arguments" unless @ARGV == 1;
    
    668 629
             my $channel = $ARGV[0];
    
    669 630
             exit_error "Unknown channel $channel" unless $config->{channels}{$channel};
    
    670
    -        $htdocsfiles{$channel} = { '.' => 1, '..' => 1 };
    
    671 631
             write_responses($config, $channel);
    
    672 632
             write_htaccess($config, $channel);
    
    673 633
             write_downloads_json($config, $channel);
    
    674
    -        clean_htdocs($channel);
    
    675 634
         },
    
    676 635
         gen_incrementals => sub {
    
    677 636
             my ($config) = @_;