| ... | 
... | 
@@ -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) = @_;
  |