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

Commits:

8 changed files:

Changes:

  • .gitlab/issue_templates/Release Prep - Tor Browser Stable.md
    ... ... @@ -39,6 +39,8 @@ Tor Browser Stable lives in the various `maint-$(TOR_BROWSER_MAJOR).$(TOR_BROWSE
    39 39
       - [ ] `var/torbrowser_version` : update to next version
    
    40 40
       - [ ] `var/torbrowser_build` : update to `$(TOR_BROWSER_BUILD_N)`
    
    41 41
       - [ ] `var/browser_release_date` : update to build date. For the build to be reproducible, the date should be in the past when building.
    
    42
    +  - [ ] `var/torbrowser_legacy_version` : update to next version in the legacy-13.5 branch
    
    43
    +  - [ ] `var/torbrowser_legacy_platform_version` : update to firefox platform version in the legacy-13.5 branch
    
    42 44
       - [ ] ***(Desktop Only)***`var/torbrowser_incremental_from` : update to previous Desktop version
    
    43 45
         - **NOTE**: We try to build incrementals for the previous 3 desktop versions except in the case of a watershed update
    
    44 46
         - **IMPORTANT**: Really *actually* make sure this is the previous Desktop version or else the `make torbrowser-incrementals-*` step will fail
    

  • projects/release/create_update_responses_tar
    1 1
     #!/bin/bash
    
    2 2
     [% c("var/set_default_env") -%]
    
    3
    -[% shell_quote(c("basedir")) %]/tools/update-responses/update_responses
    
    4
    -mkdir -p [% shell_quote(path(dest_dir)) %]/update-responses
    
    5 3
     [% SET channel = c('var/channel') -%]
    
    4
    +[% shell_quote(c("basedir")) %]/tools/update-responses/update_responses [% channel %]
    
    5
    +mkdir -p [% shell_quote(path(dest_dir)) %]/update-responses
    
    6 6
     mv [% shell_quote(c("basedir")) %]/tools/update-responses/htdocs/[% channel %] [% channel %]
    
    7 7
     chmod 775 [% channel %]
    
    8 8
     chmod 664 [% channel %]/.htaccess [% channel %]/*
    

  • projects/release/update_responses_config.yml
    ... ... @@ -27,7 +27,11 @@ build_targets:
    27 27
           - Darwin_x86_64-gcc3
    
    28 28
           - Darwin_aarch64-gcc3
    
    29 29
     channels:
    
    30
    -    [% c('var/channel') %]: [% c("var/torbrowser_version") %]
    
    30
    +    [% c('var/channel') %]:
    
    31
    +      - [% c("var/torbrowser_version") %]
    
    32
    +[% IF c("var/torbrowser_legacy_version") -%]
    
    33
    +      - [% c("var/torbrowser_legacy_version") %]
    
    34
    +[% END -%]
    
    31 35
     versions:
    
    32 36
         [% c("var/torbrowser_version") %]:
    
    33 37
     [% IF c("var/create_unsigned_incrementals") -%]
    
    ... ... @@ -68,6 +72,26 @@ versions:
    68 72
                 minSupportedInstructionSet: SSE2
    
    69 73
             linux-x86_64:
    
    70 74
                 minSupportedInstructionSet: SSE2
    
    75
    +[% IF c("var/torbrowser_legacy_version") -%]
    
    76
    +    [% c("var/torbrowser_legacy_version") %]:
    
    77
    +        mar_channel_id: [% c('var/mar_channel_id') %]
    
    78
    +        platformVersion: [% c('var/torbrowser_legacy_platform_version') %]
    
    79
    +        detailsURL: https://blog.torproject.org/new[% IF c("var/alpha") %]-alpha[% END %]-release-tor-browser-[% c("var/torbrowser_legacy_version") FILTER remove('\.') %]
    
    80
    +        incremental_from: []
    
    81
    +        # minSupportedOsVersion on macOS corresponds to the Darwin version ( https://en.wikipedia.org/wiki/Darwin_(operating_system) )
    
    82
    +        macos:
    
    83
    +            # macOS v10.12.0
    
    84
    +            minSupportedOSVersion: 16.0.0
    
    85
    +        # minSupportedOsVersion on Windows corresponds to the operating system version ( https://docs.microsoft.com/en-us/windows/win32/sysinfo/operating-system-version )
    
    86
    +        windows-i686:
    
    87
    +            # Windows 7
    
    88
    +            minSupportedOSVersion: 6.1
    
    89
    +            minSupportedInstructionSet: SSE2
    
    90
    +        windows-x86_64:
    
    91
    +            # Windows 7
    
    92
    +            minSupportedOSVersion: 6.1
    
    93
    +            minSupportedInstructionSet: SSE2
    
    94
    +[% END -%]
    
    71 95
     mar_compression: xz
    
    72 96
     [% IF c("var/tor-browser") -%]
    
    73 97
     tag: 'tbb-[% c("var/torbrowser_version") %]-[% c("var/torbrowser_build") %]'
    

  • rbm.conf
    ... ... @@ -87,6 +87,9 @@ var:
    87 87
         - 14.0a4
    
    88 88
       mar_channel_id: '[% c("var/projectname") %]-torproject-[% c("var/channel") %]'
    
    89 89
     
    
    90
    +  torbrowser_legacy_version: 13.5a11
    
    91
    +  torbrowser_legacy_platform_version: 115.16.0
    
    92
    +
    
    90 93
       # By default, we sort the list of installed packages. This allows sharing
    
    91 94
       # containers with identical list of packages, even if they are not listed
    
    92 95
       # in the same order. In the cases where the installation order is
    

  • tools/signing/nightly/config.yml
    1 1
     ---
    
    2
    +hashes_in_responses: 1
    
    2 3
     martools_version: 9.0.2
    
    3 4
     martools_url: https://archive.torproject.org/tor-package-archive/torbrowser/
    
    4 5
     martools_gpg_keyring: keyring/torbrowser.gpg
    

  • tools/signing/nightly/sign-nightly
    ... ... @@ -256,7 +256,7 @@ sub update_responses {
    256 256
         my $htdocsdir = "$topdir/tools/update-responses/htdocs/nightly";
    
    257 257
         path($htdocsdir)->remove_tree({ safe => 0 });
    
    258 258
         exit_error "Error running update_responses for $publish_dir" unless
    
    259
    -       system("$topdir/tools/update-responses/update_responses") == 0;
    
    259
    +       system("$topdir/tools/update-responses/update_responses", 'nightly') == 0;
    
    260 260
         path("$topdir/nightly/updates/$publish_dir/nightly")->remove_tree({ safe => 0 });
    
    261 261
         make_path("$topdir/nightly/updates/$publish_dir");
    
    262 262
         dirmove($htdocsdir, "$topdir/nightly/updates/$publish_dir/nightly")
    

  • tools/update-responses/get_channel_version deleted
    1
    -update_responses
    \ No newline at end of file

  • tools/update-responses/update_responses
    ... ... @@ -42,6 +42,10 @@ sub exit_error {
    42 42
         exit (exists $_[1] ? $_[1] : 1);
    
    43 43
     }
    
    44 44
     
    
    45
    +sub as_array {
    
    46
    +    ref $_[0] eq 'ARRAY' ? $_[0] : [ $_[0] ];
    
    47
    +}
    
    48
    +
    
    45 49
     sub get_tmpdir {
    
    46 50
         my ($config) = @_;
    
    47 51
         return File::Temp->newdir($config->{tmp_dir} ?
    
    ... ... @@ -72,13 +76,11 @@ sub write_htdocs {
    72 76
     }
    
    73 77
     
    
    74 78
     sub clean_htdocs {
    
    75
    -    my (@channels) = @_;
    
    76
    -    foreach my $channel (@channels) {
    
    77
    -        opendir(my $d, "$htdocsdir/$channel");
    
    78
    -        my @files = grep { ! $htdocsfiles{$channel}->{$_} } readdir $d;
    
    79
    -        closedir $d;
    
    80
    -        unlink map { "$htdocsdir/$channel/$_" } @files;
    
    81
    -    }
    
    79
    +    my ($channel) = @_;
    
    80
    +    opendir(my $d, "$htdocsdir/$channel");
    
    81
    +    my @files = grep { ! $htdocsfiles{$channel}->{$_} } readdir $d;
    
    82
    +    closedir $d;
    
    83
    +    unlink map { "$htdocsdir/$channel/$_" } @files;
    
    82 84
     }
    
    83 85
     
    
    84 86
     sub get_sha512_hex_of_file {
    
    ... ... @@ -105,8 +107,10 @@ sub get_version_files {
    105 107
                     type => 'complete',
    
    106 108
                     URL => "$download_url/$file",
    
    107 109
                     size => -s "$vdir/$file",
    
    108
    -                hashFunction => 'SHA512',
    
    109
    -                hashValue => get_sha512_hex_of_file("$vdir/$file"),
    
    110
    +                $config->{hashes_in_responses} ? (
    
    111
    +                    hashFunction => 'SHA512',
    
    112
    +                    hashValue => get_sha512_hex_of_file("$vdir/$file"),
    
    113
    +                ) : (),
    
    110 114
                 };
    
    111 115
                 next;
    
    112 116
             }
    
    ... ... @@ -116,9 +120,11 @@ sub get_version_files {
    116 120
                     type => 'partial',
    
    117 121
                     URL => "$download_url/$file",
    
    118 122
                     size => -s "$vdir/$file",
    
    119
    -                hashFunction => 'SHA512',
    
    120
    -                hashValue => get_sha512_hex_of_file("$vdir/$file"),
    
    121
    -            }
    
    123
    +                $config->{hashes_in_responses} ? (
    
    124
    +                    hashFunction => 'SHA512',
    
    125
    +                    hashValue => get_sha512_hex_of_file("$vdir/$file"),
    
    126
    +                ) : (),
    
    127
    +            };
    
    122 128
             }
    
    123 129
         }
    
    124 130
         closedir $d;
    
    ... ... @@ -239,8 +245,10 @@ sub create_incremental_mar {
    239 245
                 type => 'partial',
    
    240 246
                 URL => "$download_url/$mar_file",
    
    241 247
                 size => -s $mar_file_path,
    
    242
    -            hashFunction => 'SHA512',
    
    243
    -            hashValue => get_sha512_hex_of_file($mar_file_path),
    
    248
    +            $config->{hashes_in_responses} ? (
    
    249
    +                hashFunction => 'SHA512',
    
    250
    +                hashValue => get_sha512_hex_of_file($mar_file_path),
    
    251
    +            ) : (),
    
    244 252
             };
    
    245 253
         };
    
    246 254
         return if $pm->start($finished_file);
    
    ... ... @@ -307,16 +315,6 @@ sub version_dir {
    307 315
         return get_config($config, $version, 'any', 'releases_dir') . "/$version";
    
    308 316
     }
    
    309 317
     
    
    310
    -sub channel_to_version {
    
    311
    -    my ($config, @channels) = @_;
    
    312
    -    return values %{$config->{channels}} unless @channels;
    
    313
    -    foreach my $channel (@channels) {
    
    314
    -        exit_error "Unknown channel $channel"
    
    315
    -                unless $config->{channels}{$channel};
    
    316
    -    }
    
    317
    -    return map { $config->{channels}{$_} } @channels;
    
    318
    -}
    
    319
    -
    
    320 318
     sub get_buildinfos {
    
    321 319
         my ($config, $version) = @_;
    
    322 320
         return if exists $config->{versions}{$version}{buildID};
    
    ... ... @@ -347,49 +345,58 @@ sub get_buildinfos {
    347 345
     }
    
    348 346
     
    
    349 347
     sub get_response {
    
    350
    -    my ($config, $version, $os, @patches) = @_;
    
    348
    +    my ($config, $versions, $os, $lang, $from_version) = @_;
    
    351 349
         my $res;
    
    352 350
         my $writer = XML::Writer->new(OUTPUT => \$res, ENCODING => 'UTF-8');
    
    353 351
         $writer->xmlDecl;
    
    354 352
         $writer->startTag('updates');
    
    355
    -    if (get_config($config, $version, $os, 'unsupported')) {
    
    353
    +    foreach my $version (@$versions) {
    
    354
    +        if (get_config($config, $version, $os, 'unsupported')) {
    
    355
    +            $writer->startTag('update',
    
    356
    +                unsupported => 'true',
    
    357
    +                detailsURL => get_config($config, $version, $os, 'detailsURL'),
    
    358
    +            );
    
    359
    +            goto CLOSETAGS;
    
    360
    +        }
    
    361
    +        my $minversion = get_config($config, $version, $os, 'minSupportedOSVersion');
    
    362
    +        my $mininstruc = get_config($config, $version, $os, 'minSupportedInstructionSet');
    
    356 363
             $writer->startTag('update',
    
    357
    -            unsupported => 'true',
    
    364
    +            type => 'minor',
    
    365
    +            displayVersion => $version,
    
    366
    +            appVersion => $version,
    
    367
    +            platformVersion => get_config($config, $version, $os, 'platformVersion'),
    
    368
    +            buildID => get_config($config, $version, $os, 'buildID'),
    
    358 369
                 detailsURL => get_config($config, $version, $os, 'detailsURL'),
    
    370
    +            actions => 'showURL',
    
    371
    +            openURL => get_config($config, $version, $os, 'detailsURL'),
    
    372
    +            defined $minversion ? ( minSupportedOSVersion => $minversion ) : (),
    
    373
    +            defined $mininstruc ? ( minSupportedInstructionSet => $mininstruc ) : (),
    
    359 374
             );
    
    360
    -        goto CLOSETAGS;
    
    361
    -    }
    
    362
    -    my $minversion = get_config($config, $version, $os, 'minSupportedOSVersion');
    
    363
    -    my $mininstruc = get_config($config, $version, $os, 'minSupportedInstructionSet');
    
    364
    -    $writer->startTag('update',
    
    365
    -        type => 'minor',
    
    366
    -        displayVersion => $version,
    
    367
    -        appVersion => $version,
    
    368
    -        platformVersion => get_config($config, $version, $os, 'platformVersion'),
    
    369
    -        buildID => get_config($config, $version, $os, 'buildID'),
    
    370
    -        detailsURL => get_config($config, $version, $os, 'detailsURL'),
    
    371
    -        actions => 'showURL',
    
    372
    -        openURL => get_config($config, $version, $os, 'detailsURL'),
    
    373
    -        defined $minversion ? ( minSupportedOSVersion => $minversion ) : (),
    
    374
    -        defined $mininstruc ? ( minSupportedInstructionSet => $mininstruc ) : (),
    
    375
    -    );
    
    376
    -    foreach my $patch (@patches) {
    
    377
    -        my @sorted_patch = map { $_ => $patch->{$_} } sort keys %$patch;
    
    378
    -        $writer->startTag('patch', @sorted_patch);
    
    379
    -        $writer->endTag('patch');
    
    375
    +        if (my $patch = $config->{versions}{$version}{files}{$os}{$lang}{complete}) {
    
    376
    +            my @sorted_patch = map { $_ => $patch->{$_} } sort keys %$patch;
    
    377
    +            $writer->startTag('patch', @sorted_patch);
    
    378
    +            $writer->endTag('patch');
    
    379
    +        }
    
    380
    +        if ($from_version) {
    
    381
    +            if (my $patch = $config->{versions}{$version}{files}{$os}{$lang}{partial}{$from_version}) {
    
    382
    +                my @sorted_patch = map { $_ => $patch->{$_} } sort keys %$patch;
    
    383
    +                $writer->startTag('patch', @sorted_patch);
    
    384
    +                $writer->endTag('patch');
    
    385
    +            }
    
    386
    +        }
    
    387
    +        CLOSETAGS:
    
    388
    +        $writer->endTag('update');
    
    380 389
         }
    
    381
    -    CLOSETAGS:
    
    382
    -    $writer->endTag('update');
    
    383 390
         $writer->endTag('updates');
    
    384 391
         $writer->end;
    
    385 392
         return $res;
    
    386 393
     }
    
    387 394
     
    
    388 395
     sub write_responses {
    
    389
    -    my ($config, @channels) = @_;
    
    390
    -    @channels = keys %{$config->{channels}} unless @channels;
    
    391
    -    foreach my $channel (@channels) {
    
    392
    -        my $version = $config->{channels}{$channel};
    
    396
    +    my ($config, $channel) = @_;
    
    397
    +    my $versions = as_array($config->{channels}{$channel});
    
    398
    +    my (%oses, %langs, %from_versions);
    
    399
    +    foreach my $version (@$versions) {
    
    393 400
             get_version_files($config, $version);
    
    394 401
             get_buildinfos($config, $version);
    
    395 402
             my $files = $config->{versions}{$version}{files};
    
    ... ... @@ -398,79 +405,96 @@ sub write_responses {
    398 405
                 my $new_os = $migrate_archs->{$old_os};
    
    399 406
                 foreach my $lang (keys %{$files->{$new_os}}) {
    
    400 407
                     $files->{$old_os}{$lang}{complete} =
    
    401
    -                        $files->{$new_os}{$lang}{complete};
    
    408
    +                    $files->{$new_os}{$lang}{complete};
    
    402 409
                 }
    
    403 410
             }
    
    404 411
             foreach my $os (keys %$files) {
    
    412
    +            $oses{$os} = 1;
    
    405 413
                 foreach my $lang (keys %{$files->{$os}}) {
    
    406
    -                my $resp = get_response($config, $version, $os,
    
    407
    -                                $files->{$os}{$lang}{complete});
    
    408
    -                write_htdocs($channel, "$version-$os-$lang.xml", $resp);
    
    414
    +                $langs{$lang} = 1;
    
    409 415
                     foreach my $from_version (keys %{$files->{$os}{$lang}{partial}}) {
    
    410
    -                    $resp = get_response($config, $version, $os,
    
    411
    -                                $files->{$os}{$lang}{complete},
    
    412
    -                                $files->{$os}{$lang}{partial}{$from_version});
    
    413
    -                    write_htdocs($channel, "$from_version-$version-$os-$lang.xml", $resp);
    
    416
    +                    $from_versions{$from_version} = 1;
    
    414 417
                     }
    
    415 418
                 }
    
    416 419
             }
    
    417
    -        write_htdocs($channel, 'no-update.xml',
    
    418
    -            '<?xml version="1.0" encoding="UTF-8"?>'
    
    419
    -            . "\n<updates></updates>\n");
    
    420 420
         }
    
    421
    +    my $versions_str = join('+', @$versions);
    
    422
    +    foreach my $os (keys %oses) {
    
    423
    +        foreach my $lang (keys %langs) {
    
    424
    +            my $resp = get_response($config, $versions, $os, $lang);
    
    425
    +            write_htdocs($channel, "$versions_str-$os-$lang.xml", $resp);
    
    426
    +            foreach my $from_version (keys %from_versions) {
    
    427
    +                $resp = get_response($config, $versions, $os, $lang, $from_version);
    
    428
    +                write_htdocs($channel, "$from_version-$versions_str-$os-$lang.xml", $resp);
    
    429
    +            }
    
    430
    +        }
    
    431
    +    }
    
    432
    +    write_htdocs($channel, 'no-update.xml',
    
    433
    +        '<?xml version="1.0" encoding="UTF-8"?>'
    
    434
    +        . "\n<updates></updates>\n");
    
    421 435
     }
    
    422 436
     
    
    423 437
     sub write_htaccess {
    
    424
    -    my ($config, @channels) = @_;
    
    425
    -    @channels = keys %{$config->{channels}} unless @channels;
    
    438
    +    my ($config, $channel) = @_;
    
    426 439
         my $flags = "[last]";
    
    427
    -    foreach my $channel (@channels) {
    
    428
    -        my $htaccess = "RewriteEngine On\n";
    
    429
    -        $htaccess .= $config->{htaccess_rewrite_rules}{$channel} // '';
    
    430
    -        my $version = $config->{channels}{$channel};
    
    431
    -        my $migrate_langs = $config->{versions}{$version}{migrate_langs} // {};
    
    440
    +    my $htaccess = "RewriteEngine On\n";
    
    441
    +    $htaccess .= $config->{htaccess_rewrite_rules}{$channel} // '';
    
    442
    +    my $versions = as_array($config->{channels}{$channel});
    
    443
    +    my $versions_str = join('+', @$versions);
    
    444
    +    my (%oses, %langs, %from_versions);
    
    445
    +    my $migrate_langs;
    
    446
    +    foreach my $version (@$versions) {
    
    447
    +        $migrate_langs = $config->{versions}{$version}{migrate_langs}
    
    448
    +                                if $config->{versions}{$version}{migrate_langs};
    
    432 449
             my $files = $config->{versions}{$version}{files};
    
    433
    -        $htaccess .= "RewriteRule ^[^\/]+/$version/ no-update.xml $flags\n";
    
    434
    -        foreach my $os (sort keys %$files) {
    
    435
    -            foreach my $bt (build_targets_by_os($os)) {
    
    436
    -                foreach my $lang (sort keys %{$files->{$os}}) {
    
    437
    -                    foreach my $from_version (sort keys %{$files->{$os}{$lang}{partial}}) {
    
    438
    -                        $htaccess .= "RewriteRule ^$bt/$from_version/$lang "
    
    439
    -                                  .  "$from_version-$version-$os-$lang.xml $flags\n";
    
    440
    -                    }
    
    441
    -                    $htaccess .= "RewriteRule ^$bt/[^\/]+/$lang "
    
    442
    -                              .  "$version-$os-$lang.xml $flags\n";
    
    450
    +        foreach my $os (keys %$files) {
    
    451
    +            $oses{$os} = 1;
    
    452
    +            foreach my $lang (keys %{$files->{$os}}) {
    
    453
    +                $langs{$lang} = 1;
    
    454
    +                foreach my $from_version (keys %{$files->{$os}{$lang}{partial}}) {
    
    455
    +                    $from_versions{$from_version} = 1;
    
    443 456
                     }
    
    444
    -                foreach my $lang (sort keys %$migrate_langs) {
    
    445
    -                    $htaccess .= "RewriteRule ^$bt/[^\/]+/$lang "
    
    446
    -                              .  "$version-$os-$migrate_langs->{$lang}.xml $flags\n";
    
    457
    +            }
    
    458
    +        }
    
    459
    +        $htaccess .= "RewriteRule ^[^\/]+/$version/ no-update.xml $flags\n";
    
    460
    +    }
    
    461
    +    foreach my $os (sort keys %oses) {
    
    462
    +        foreach my $bt (build_targets_by_os($os)) {
    
    463
    +            foreach my $lang (sort keys %langs) {
    
    464
    +                foreach my $from_version (sort keys %from_versions) {
    
    465
    +                    $htaccess .= "RewriteRule ^$bt/$from_version/$lang "
    
    466
    +                              .  "$from_version-$versions_str-$os-$lang.xml $flags\n";
    
    447 467
                     }
    
    448
    -                $htaccess .= "RewriteRule ^$bt/ $version-$os-ALL.xml $flags\n";
    
    468
    +                $htaccess .= "RewriteRule ^$bt/[^\/]+/$lang "
    
    469
    +                          .  "$versions_str-$os-$lang.xml $flags\n";
    
    470
    +            }
    
    471
    +            foreach my $lang (sort keys %$migrate_langs) {
    
    472
    +                $htaccess .= "RewriteRule ^$bt/[^\/]+/$lang "
    
    473
    +                          .  "$versions_str-$os-$migrate_langs->{$lang}.xml $flags\n";
    
    449 474
                 }
    
    475
    +            $htaccess .= "RewriteRule ^$bt/ $versions_str-$os-ALL.xml $flags\n";
    
    450 476
             }
    
    451
    -        write_htdocs($channel, '.htaccess', $htaccess);
    
    452 477
         }
    
    478
    +    write_htdocs($channel, '.htaccess', $htaccess);
    
    453 479
     }
    
    454 480
     
    
    455 481
     sub write_downloads_json {
    
    456
    -    my ($config, @channels) = @_;
    
    482
    +    my ($config, $channel) = @_;
    
    457 483
         return unless $config->{create_downloads_json};
    
    458
    -    @channels = keys %{$config->{channels}} unless @channels;
    
    459
    -    foreach my $channel (@channels) {
    
    460
    -        my $version = $config->{channels}{$channel};
    
    461
    -        my $tag = get_config($config, $version, 'any', 'tag');
    
    462
    -        my $data = {
    
    463
    -            version => "$version",
    
    464
    -            tag => "$tag",
    
    465
    -            downloads => get_version_downloads($config, $version),
    
    466
    -        };
    
    467
    -        write_htdocs($channel, 'downloads.json',
    
    468
    -            JSON->new->utf8->canonical->encode($data));
    
    469
    -        my $pp_downloads = get_perplatform_downloads($config, $version, $tag);
    
    470
    -        foreach my $os (keys %{$pp_downloads}) {
    
    471
    -          write_htdocs($channel, "download-$os.json",
    
    484
    +    my $versions = as_array($config->{channels}{$channel});
    
    485
    +    my ($version) = @$versions;
    
    486
    +    my $tag = get_config($config, $version, 'any', 'tag');
    
    487
    +    my $data = {
    
    488
    +        version => "$version",
    
    489
    +        tag => "$tag",
    
    490
    +        downloads => get_version_downloads($config, $version),
    
    491
    +    };
    
    492
    +    write_htdocs($channel, 'downloads.json',
    
    493
    +        JSON->new->utf8->canonical->encode($data));
    
    494
    +    my $pp_downloads = get_perplatform_downloads($config, $version, $tag);
    
    495
    +    foreach my $os (keys %{$pp_downloads}) {
    
    496
    +        write_htdocs($channel, "download-$os.json",
    
    472 497
                 JSON->new->utf8->canonical->encode($pp_downloads->{$os}));
    
    473
    -        }
    
    474 498
         }
    
    475 499
     }
    
    476 500
     
    
    ... ... @@ -486,8 +510,10 @@ sub marzip_path {
    486 510
     }
    
    487 511
     
    
    488 512
     my $martools_tmpdir;
    
    513
    +my $extracted_martools;
    
    489 514
     sub extract_martools {
    
    490 515
         my ($config, $version) = @_;
    
    516
    +    return if $extracted_martools;
    
    491 517
         my $marzip = marzip_path($config, $version);
    
    492 518
         $martools_tmpdir = get_tmpdir($config);
    
    493 519
         my $old_cwd = getcwd;
    
    ... ... @@ -503,6 +529,7 @@ sub extract_martools {
    503 529
         } else {
    
    504 530
             $ENV{LD_LIBRARY_PATH} = "$martools_tmpdir/mar-tools";
    
    505 531
         }
    
    532
    +    $extracted_martools = 1;
    
    506 533
     }
    
    507 534
     
    
    508 535
     sub log_step {
    
    ... ... @@ -559,7 +586,8 @@ sub build_targets_list {
    559 586
     
    
    560 587
     sub check_update_responses_channel {
    
    561 588
         my ($config, $base_url, $channel) = @_;
    
    562
    -    my $channel_version = $config->{channels}{$channel};
    
    589
    +    my $channel_versions = as_array($config->{channels}{$channel});
    
    590
    +    my ($channel_version) = @$channel_versions;
    
    563 591
         foreach my $build_target (build_targets_list()) {
    
    564 592
             foreach my $lang (qw(en-US de)) {
    
    565 593
                 my $url = "$base_url/$channel/$build_target/1.0/$lang";
    
    ... ... @@ -621,11 +649,11 @@ sub download_version {
    621 649
     }
    
    622 650
     
    
    623 651
     sub download_missing_versions {
    
    624
    -    my ($config, @channels) = @_;
    
    625
    -    foreach my $channel (@channels) {
    
    626
    -        exit_error "Unknown channel $channel"
    
    627
    -                unless $config->{channels}{$channel};
    
    628
    -        my $cversion = $config->{channels}{$channel};
    
    652
    +    my ($config, $channel) = @_;
    
    653
    +    exit_error "Unknown channel $channel"
    
    654
    +        unless $config->{channels}{$channel};
    
    655
    +    my $cversions = as_array($config->{channels}{$channel});
    
    656
    +    foreach my $cversion (@$cversions) {
    
    629 657
             next unless $config->{versions}{$cversion}{incremental_from};
    
    630 658
             foreach my $version (@{$config->{versions}{$cversion}{incremental_from}}) {
    
    631 659
                 next if -d version_dir($config, $version);
    
    ... ... @@ -636,11 +664,9 @@ sub download_missing_versions {
    636 664
     
    
    637 665
     sub check_update_responses {
    
    638 666
         my ($config) = @_;
    
    639
    -    exit_error "usage: $PROGRAM_NAME <base_url> [channels...]" unless @ARGV;
    
    640
    -    my ($base_url, @channels) = @ARGV;
    
    641
    -    foreach my $channel (@channels ? @channels : keys %{$config->{channels}}) {
    
    642
    -        check_update_responses_channel($config, $base_url, $channel);
    
    643
    -    }
    
    667
    +    exit_error "usage: $PROGRAM_NAME <base_url> <channel>" unless @ARGV;
    
    668
    +    my ($base_url, $channel) = @ARGV;
    
    669
    +    check_update_responses_channel($config, $base_url, $channel);
    
    644 670
         if (!@check_errors) {
    
    645 671
             print "\n\nNo errors\n";
    
    646 672
             return;
    
    ... ... @@ -660,38 +686,34 @@ sub check_update_responses {
    660 686
     my %actions = (
    
    661 687
         update_responses => sub {
    
    662 688
             my ($config) = @_;
    
    663
    -        my @channels = @ARGV ? @ARGV : keys %{$config->{channels}};
    
    664
    -        foreach my $channel (@channels) {
    
    665
    -            exit_error "Unknown channel $channel"
    
    666
    -                unless $config->{channels}{$channel};
    
    667
    -            $htdocsfiles{$channel} = { '.' => 1, '..' => 1 };
    
    668
    -        }
    
    669
    -        write_responses($config, @channels);
    
    670
    -        write_htaccess($config, @channels);
    
    671
    -        write_downloads_json($config, @channels);
    
    672
    -        clean_htdocs(@channels);
    
    689
    +        exit_error "Wrong arguments" unless @ARGV == 1;
    
    690
    +        my $channel = $ARGV[0];
    
    691
    +        exit_error "Unknown channel $channel" unless $config->{channels}{$channel};
    
    692
    +        $htdocsfiles{$channel} = { '.' => 1, '..' => 1 };
    
    693
    +        write_responses($config, $channel);
    
    694
    +        write_htaccess($config, $channel);
    
    695
    +        write_downloads_json($config, $channel);
    
    696
    +        clean_htdocs($channel);
    
    673 697
         },
    
    674 698
         gen_incrementals => sub {
    
    675 699
             my ($config) = @_;
    
    676
    -        foreach my $channel (@ARGV) {
    
    677
    -            my ($version) = channel_to_version($config, $channel);
    
    700
    +        exit_error "Wrong arguments" unless @ARGV == 1;
    
    701
    +        my $channel = $ARGV[0];
    
    702
    +        exit_error "Unknown channel" unless $config->{channels}{$channel};
    
    703
    +        my $versions = as_array($config->{channels}{$channel});
    
    704
    +        foreach my $version (@$versions) {
    
    678 705
                 extract_martools($config, $version);
    
    679 706
                 get_version_files($config, $version);
    
    680 707
                 create_incremental_mars_for_version($config, $version, $channel);
    
    681 708
             }
    
    682 709
         },
    
    683 710
         download_missing_versions => sub {
    
    684
    -        my ($config) = @_;
    
    685
    -        my @channels = @ARGV ? @ARGV : keys %{$config->{channels}};
    
    686
    -        download_missing_versions($config, @channels);
    
    687
    -    },
    
    688
    -    check_update_responses_deployement => \&check_update_responses,
    
    689
    -    get_channel_version => sub {
    
    690 711
             my ($config) = @_;
    
    691 712
             exit_error "Wrong arguments" unless @ARGV == 1;
    
    692
    -        exit_error "Unknown channel" unless $config->{channels}{$ARGV[0]};
    
    693
    -        print $config->{channels}{$ARGV[0]}, "\n";
    
    713
    +        my $channel = $ARGV[0];
    
    714
    +        download_missing_versions($config, $channel);
    
    694 715
         },
    
    716
    +    check_update_responses_deployement => \&check_update_responses,
    
    695 717
     );
    
    696 718
     
    
    697 719
     my $action = fileparse($PROGRAM_NAME);