Subversion Repositories SvarDOS

Rev

Rev 1510 | Rev 1522 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
562 mateuszvis 1
<?php /*
2
 
3
  SvarDOS repo index builder
1267 mateusz.vi 4
  Copyright (C) Mateusz Viste 2012-2023
562 mateuszvis 5
 
734 bttr 6
  buildidx computes an index json file for the SvarDOS repository.
673 mateusz.vi 7
  it must be executed pointing to a directory that stores packages (*.svp)
562 mateuszvis 8
  files. buildidx will generate the index file and save it into the package
9
  repository.
10
 
11
  requires php-zip
12
 
1509 mateusz.vi 13
  24 aug 2023: load hwreq data from LSM and store them in the json index + skip the '.svn' dir
1267 mateusz.vi 14
  30 jun 2023: adapted for new CORE packages location (../packages-core)
999 mateusz.vi 15
  28 feb 2022: svarcom allowed to have a COMMAND.COM file without subdirectory
951 mateusz.vi 16
  24 feb 2022: added hardcoded hack to translate version 'x.xx' to '0.44' (NESticle)
941 mateusz.vi 17
  23 feb 2022: basic validation of source archives (not empty + matches an existing svp file)
912 mateusz.vi 18
  21 feb 2022: buildidx collects categories looking at the dir layout of each package + improved version string parsing (replaced version_compare call by dos_version_compare)
775 mateusz.vi 19
  17 feb 2022: checking for non-8+3 filenames in packages and duplicates + devload no longer part of CORE
736 mateusz.vi 20
  16 feb 2022: added warning about overlong version strings and wild files location
719 mateusz.vi 21
  15 feb 2022: index is generated as json, contains all filenames and alt versions
673 mateusz.vi 22
  14 feb 2022: packages are expected to have the *.svp extension
650 mateusz.vi 23
  12 feb 2022: skip source packages from being processed (*.src.zip)
562 mateuszvis 24
  20 jan 2022: rewritten the code from ANSI C to PHP for easier maintenance
25
  13 feb 2021: 'title' LSM field is no longer looked after
26
  11 feb 2021: lsm headers are no longer checked, so it is compatible with the simpler lsm format used by SvarDOS
27
  13 jan 2021: removed the identification line, changed CRC32 to bsum, not creating the listing.txt file and stopped compressing index
28
  23 apr 2017: uncompressed index is no longer created, added CRC32 of zib (bin only) files, if present
29
  28 aug 2016: listing.txt is always written inside the repo dir (instead of inside current dir)
30
  27 aug 2016: accepting full paths to repos (starting with /...)
31
  07 dec 2013: rewritten buildidx in ANSI C89
32
  19 aug 2013: add a compressed version of the index file to repos (index.gz)
33
  22 jul 2013: creating a listing.txt file with list of packages
34
  18 jul 2013: writing the number of packaged into the first line of the lst file
35
  11 jul 2013: added a switch to 7za to make it case insensitive when extracting lsm files
36
  10 jul 2013: changed unzip calls to 7za (to handle cases when appinfo is compressed with lzma)
37
  04 feb 2013: added CRC32 support
38
  22 sep 2012: forked 1st version from FDUPDATE builder
39
*/
40
 
1509 mateusz.vi 41
$PVER = "20230824";
562 mateuszvis 42
 
43
 
44
// computes the BSD sum of a file and returns it
45
function file2bsum($fname) {
46
  $result = 0;
47
 
48
  $fd = fopen($fname, 'rb');
49
  if ($fd === false) return(0);
50
 
51
  while (!feof($fd)) {
52
 
53
    $buff = fread($fd, 1024 * 1024);
54
 
563 mateuszvis 55
    $slen = strlen($buff);
56
    for ($i = 0; $i < $slen; $i++) {
562 mateuszvis 57
      // rotr
58
      $result = ($result >> 1) | ($result << 15);
59
      // add and truncate to 16 bits
563 mateuszvis 60
      $result += ord($buff[$i]);
562 mateuszvis 61
      $result &= 0xffff;
62
    }
63
  }
64
 
65
  fclose($fd);
66
  return($result);
67
}
68
 
69
 
912 mateusz.vi 70
// translates a version string into a array of integer values.
71
// Accepted formats follow:
72
//    300.12.1
73
//    1
74
//    12.2.34.2-4.5
75
//    1.2c
76
//    1.01 beta+3
77
//    2013-12-31
78
//    20220222 alpha
79
function vertoarr($verstr) {
80
  $subver = array(0,0,0,0);
81
 
82
  // switch string to lcase for easier processing and trim any leading or trailing white spaces
83
  $verstr = strtolower(trim($verstr));
84
 
85
  // replace all '-' and '/' characters to '.' (uniformization of sub-version parts delimiters)
86
  $verstr = strtr($verstr, '-/', '..');
87
 
88
  // is there a subversion value? (for example "+4" in "1.05+4")
89
  $i = strrpos($verstr, '+', 1);
90
  if ($i !== false) {
91
    // validate the svar-version is a proper integer
92
    $svarver = substr($verstr, $i + 1);
93
    if (! preg_match('/[1-9][0-9]*/', $svarver)) {
94
      return(false);
95
    }
96
    $subver[3] = intval($svarver); // set the +rev as a very minor item
97
    $verstr = substr($verstr, 0, $i);
98
  }
99
 
951 mateusz.vi 100
  // NESticls hack: version "x.xx" is translated to "0.44"... that sucks but that's how it is.
101
  // ref: https://web.archive.org/web/20070205074631/http://www.zophar.net/NESticle/
102
  if ($verstr == 'x.xx') $verstr = '0.44';
103
 
936 mateusz.vi 104
  // beta reordering: convert "beta 0.95" to "0.95 beta"
105
  if (preg_match('/^beta /', $verstr)) $verstr = substr($verstr, 5) . ' beta';
106
 
927 mateusz.vi 107
  // any occurence of alpha,beta,gamma,delta etc preceded by a digit should have a space separator added
108
  // example: "2.6.0pre9" becomes "2.6.0 pre9"
109
  $verstr = preg_replace('/([0-9])(alpha|beta|gamma|delta|pre|rc|patch)/', '$1 $2', $verstr);
110
 
111
  // same as above, but this time adding a trailing space separator
112
  // example: "2.6.0 pre9" becomes "2.6.0 pre 9"
113
  $verstr = preg_replace('/(alpha|beta|gamma|delta|pre|rc|patch)([0-9])/', '$1 $2', $verstr);
114
 
921 mateusz.vi 115
  // is the version ending with ' alpha', 'beta', etc?
922 mateusz.vi 116
  if (preg_match('/ (alpha|beta|gamma|delta|pre|rc|patch)( [0-9]{1,4}){0,1}$/', $verstr)) {
921 mateusz.vi 117
    // if there is a trailing beta-number, process it first
118
    if (preg_match('/ [0-9]{1,4}$/', $verstr)) {
119
      $i = strrpos($verstr, ' ');
120
      $subver[2] = intval(substr($verstr, $i + 1));
121
      $verstr = trim(substr($verstr, 0, $i));
122
    }
912 mateusz.vi 123
    $i = strrpos($verstr, ' ');
124
    $greek = substr($verstr, $i + 1);
125
    $verstr = trim(substr($verstr, 0, $i));
126
    if ($greek == 'alpha') {
921 mateusz.vi 127
      $subver[1] = 1;
912 mateusz.vi 128
    } else if ($greek == 'beta') {
921 mateusz.vi 129
      $subver[1] = 2;
920 mateusz.vi 130
    } else if ($greek == 'gamma') {
921 mateusz.vi 131
      $subver[1] = 3;
920 mateusz.vi 132
    } else if ($greek == 'delta') {
921 mateusz.vi 133
      $subver[1] = 4;
134
    } else if ($greek == 'pre') {
135
      $subver[1] = 5;
914 mateusz.vi 136
    } else if ($greek == 'rc') {
921 mateusz.vi 137
      $subver[1] = 6;
922 mateusz.vi 138
    } else if ($greek == 'patch') { // this is a POST-release version, as opposed to all above that are PRE-release versions
139
      $subver[1] = 99;
912 mateusz.vi 140
    } else {
141
      return(false);
142
    }
914 mateusz.vi 143
  } else {
922 mateusz.vi 144
    $subver[1] = 98; // one less than the 'patch' level
912 mateusz.vi 145
  }
146
 
147
  // does the version string have a single-letter subversion? (1.0c)
148
  if (preg_match('/[a-z]$/', $verstr)) {
921 mateusz.vi 149
    $subver[0] = ord(substr($verstr, -1));
912 mateusz.vi 150
    $verstr = substr_replace($verstr, '', -1); // remove last character from string
151
  }
152
 
926 mateusz.vi 153
  // convert "30-jan-99", "1999-jan-30" and "30-jan-1999" versions to "30jan99" or "30jan1999"
154
  // note that dashes have already been replaced by dots
155
  if (preg_match('/^([0-9][0-9]){1,2}\.(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\.([0-9][0-9]){1,2}$/', $verstr)) {
156
    $verstr = str_replace('.', '', $verstr);
157
  }
158
 
159
  // convert "2009mar17" versions to "17mar2009"
160
  if (preg_match('/^[0-9]{4}(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)[0-9]{2}$/', $verstr)) {
161
    $dy = substr($verstr, 7);
162
    $mo = substr($verstr, 4, 3);
163
    $ye = substr($verstr, 0, 4);
925 mateusz.vi 164
    $verstr = "{$dy}{$mo}{$ye}";
923 mateusz.vi 165
  }
166
 
167
  // convert "30jan99" versions to 99.1.30 and "30jan1999" to 1999.1.30
925 mateusz.vi 168
  if (preg_match('/^[0-3][0-9](jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)([0-9][0-9]){1,2}$/', $verstr)) {
923 mateusz.vi 169
    $months = array('jan' => 1, 'feb' => 2, 'mar' => 3, 'apr' => 4, 'may' => 5, 'jun' => 6, 'jul' => 7, 'aug' => 8, 'sep' => 9, 'oct' => 10, 'nov' => 11, 'dec' => 12);
170
    $dy = substr($verstr, 0, 2);
171
    $mo = $months[substr($verstr, 2, 3)];
172
    $ye = substr($verstr, 5);
173
    $verstr = "{$ye}.{$mo}.{$dy}";
174
  }
175
 
912 mateusz.vi 176
  // validate the format is supported, should be something no more complex than 1.05.3.33
919 mateusz.vi 177
  if (! preg_match('/^[0-9][0-9.]{0,20}$/', $verstr)) {
912 mateusz.vi 178
    return(false);
179
  }
180
 
181
  // NOTE: a zero right after a separator and trailed with a digit (as in 1.01)
182
  //       has a special meaning
183
  $exploded = explode('.', $verstr);
184
  if (count($exploded) > 16) {
185
    return(false);
186
  }
921 mateusz.vi 187
  $exploded[16] = $subver[0]; // a-z (1.0c)
188
  $exploded[17] = $subver[1]; // alpha/beta/gamma/delta/rc/pre
189
  $exploded[18] = $subver[2]; // alpha-beta-gamma subversion (eg. "beta 9")
912 mateusz.vi 190
  $exploded[19] = $subver[3]; // svar-ver (1.0+5)
191
  for ($i = 0; $i < 20; $i++) if (empty($exploded[$i])) $exploded[$i] = '0';
192
 
193
  ksort($exploded);
194
 
195
  return($exploded);
196
}
197
 
198
 
199
function dos_version_compare($v1, $v2) {
200
  $v1arr = vertoarr($v1);
201
  $v2arr = vertoarr($v2);
202
  for ($i = 0; $i < count($v1arr); $i++) {
921 mateusz.vi 203
    if ($v1arr[$i] > $v2arr[$i]) return(1);
204
    if ($v1arr[$i] < $v2arr[$i]) return(-1);
912 mateusz.vi 205
  }
206
  return(0);
207
}
208
 
209
 
562 mateuszvis 210
// reads file fil from zip archive z and returns its content, or false on error
211
function read_file_from_zip($z, $fil) {
212
  $zip = new ZipArchive;
213
  if ($zip->open($z, ZipArchive::RDONLY) !== true) {
214
    echo "ERROR: failed to open zip file '{$z}'\n";
215
    return(false);
216
  }
217
 
218
  // load the appinfo/pkgname.lsm file
219
  $res = $zip->getFromName($fil, 8192, ZipArchive::FL_NOCASE);
220
 
221
  $zip->close();
222
  return($res);
223
}
224
 
225
 
731 mateusz.vi 226
function read_list_of_files_in_zip($z) {
227
  $zip = new ZipArchive;
228
  if ($zip->open($z, ZipArchive::RDONLY) !== true) {
229
    echo "ERROR: failed to open zip file '{$z}'\n";
230
    return(false);
231
  }
232
 
233
  $res = array();
234
  for ($i = 0; $i < $zip->numFiles; $i++) $res[] = $zip->getNameIndex($i);
235
 
236
  $zip->close();
237
  return($res);
238
}
239
 
240
 
562 mateuszvis 241
// reads a LSM string and returns it in the form of an array
242
function parse_lsm($s) {
243
  $res = array();
244
  for ($l = strtok($s, "\n"); $l !== false; $l = strtok("\n")) {
245
    // the line is "token: value", let's find the colon
246
    $colpos = strpos($l, ':');
247
    if (($colpos === false) || ($colpos === 0)) continue;
248
    $tok = strtolower(trim(substr($l, 0, $colpos)));
249
    $val = trim(substr($l, $colpos + 1));
250
    $res[$tok] = $val;
251
  }
252
  return($res);
253
}
254
 
255
 
731 mateusz.vi 256
// on PHP 8+ there is str_starts_with(), but not on PHP 7 so I use this
257
function str_head_is($haystack, $needle) {
258
  return strpos($haystack, $needle) === 0;
259
}
260
 
261
 
791 mateusz.vi 262
// returns an array that contains CORE packages (populated from the core subdirectory in pkgdir)
1267 mateusz.vi 263
function load_core_list($repodir_core) {
791 mateusz.vi 264
  $res = array();
265
 
1267 mateusz.vi 266
  foreach (scandir($repodir_core) as $f) {
791 mateusz.vi 267
    if (!preg_match('/\.svp$/', $f)) continue;
268
    $res[] = explode('.', $f)[0];
269
  }
270
  return($res);
271
}
272
 
273
 
562 mateuszvis 274
// ***************** MAIN ROUTINE *********************************************
275
 
719 mateusz.vi 276
//echo "SvarDOS repository index generator ver {$PVER}\n";
562 mateuszvis 277
 
278
if (($_SERVER['argc'] != 2) || ($_SERVER['argv'][1][0] == '-')) {
279
  echo "usage: php buildidx.php repodir\n";
280
  exit(1);
281
}
282
 
283
$repodir = $_SERVER['argv'][1];
284
 
285
$pkgfiles = scandir($repodir);
286
$pkgcount = 0;
287
 
738 mateusz.vi 288
 
795 mateusz.vi 289
// load the list of CORE and MSDOS_COMPAT packages
738 mateusz.vi 290
 
1267 mateusz.vi 291
$core_packages_list = load_core_list($repodir . '/../packages-core/');
1037 bttr 292
$msdos_compat_list = explode(' ', 'append assign attrib callver chkdsk choice comp cpidos debug defrag deltree diskcomp diskcopy display edit edlin exe2bin fc fdapm fdisk find format help himemx kernel keyb label localcfg mem mirror mode more move nlsfunc print replace share shsucdx sort svarcom swsubst tree undelete unformat xcopy');
738 mateusz.vi 293
 
719 mateusz.vi 294
// do a list of all svp packages with their available versions and descriptions
562 mateuszvis 295
 
719 mateusz.vi 296
$pkgdb = array();
297
foreach ($pkgfiles as $fname) {
562 mateuszvis 298
 
941 mateusz.vi 299
  // zip files (ie. source archives)
300
  if (preg_match('/\.zip$/', $fname)) {
301
    // the zip archive should contain at least one file
302
    if (count(read_list_of_files_in_zip($repodir . '/' . $fname)) < 1) echo "WARNING: source archive {$fname} contains no files (either empty or corrupted)\n";
303
    // check that the file relates to an existing svp package
304
    $svpfname = preg_replace('/zip$/', 'svp', $fname);
305
    if (!file_exists($repodir . '/' . $svpfname)) echo "ERROR: orphaned source archive '{$fname}' (no matching svp file, expecting a package named '{$svpfname}')\n";
306
    // that is for zip files
307
    continue;
308
  }
309
 
1509 mateusz.vi 310
  // silently skip the hidden .svn directory
311
  if ($fname === '.svn') continue;
312
 
941 mateusz.vi 313
  // skip (and warn about) non-svp
314
  if (!preg_match('/\.svp$/', $fname)) {
1267 mateusz.vi 315
    $okfiles = array('.', '..', '_cats.json', '_index.json', '_buildidx.log');
941 mateusz.vi 316
    if (array_search($fname, $okfiles) !== false) continue;
1509 mateusz.vi 317
    echo "WARNING: wild file '{$fname}' (this is either an useless file that should be removed, or a misnamed package or source archive)'\n";
941 mateusz.vi 318
    continue;
319
  }
320
 
801 mateusz.vi 321
  if (!preg_match('/^[a-zA-Z0-9+. _-]*\.svp$/', $fname)) {
322
    echo "ERROR: {$fname} has a very weird name\n";
323
    continue;
324
  }
325
 
719 mateusz.vi 326
  $path_parts = pathinfo($fname);
327
  $pkgnam = explode('-', $path_parts['filename'])[0];
328
  $pkgfullpath = realpath($repodir . '/' . $fname);
562 mateuszvis 329
 
719 mateusz.vi 330
  $lsm = read_file_from_zip($pkgfullpath, "appinfo/{$pkgnam}.lsm");
562 mateuszvis 331
  if ($lsm == false) {
802 mateusz.vi 332
    echo "ERROR: {$fname} does not contain an LSM file at the expected location\n";
719 mateusz.vi 333
    continue;
562 mateuszvis 334
  }
335
  $lsmarray = parse_lsm($lsm);
336
  if (empty($lsmarray['version'])) {
719 mateusz.vi 337
    echo "ERROR: lsm file in {$fname} does not contain a version\n";
338
    continue;
562 mateuszvis 339
  }
730 mateusz.vi 340
  if (strlen($lsmarray['version']) > 16) {
737 mateusz.vi 341
    echo "ERROR: version string in lsm file of {$fname} is too long (16 chars max)\n";
730 mateusz.vi 342
    continue;
343
  }
562 mateuszvis 344
  if (empty($lsmarray['description'])) {
719 mateusz.vi 345
    echo "ERROR: lsm file in {$fname} does not contain a description\n";
346
    continue;
562 mateuszvis 347
  }
348
 
731 mateusz.vi 349
  // validate the files present in the archive
350
  $listoffiles = read_list_of_files_in_zip($pkgfullpath);
739 mateusz.vi 351
  $pkgdir = $pkgnam;
352
 
768 mateusz.vi 353
  // special rule for "parent and children" packages
354
  if (str_head_is($pkgnam, 'djgpp_')) $pkgdir = 'djgpp'; // djgpp_* packages put their files in djgpp
754 mateusz.vi 355
  if ($pkgnam == 'fbc_help') $pkgdir = 'fbc'; // FreeBASIC help goes to the FreeBASIC dir
802 mateusz.vi 356
  if ($pkgnam == 'clamdb') $pkgdir = 'clamav'; // data patterns for clamav
739 mateusz.vi 357
 
768 mateusz.vi 358
  // array used to detect duplicated entries after lower-case conversion
359
  $duparr = array();
360
 
909 mateusz.vi 361
  // will hold the list of categories that this package belongs to
362
  $catlist = array();
363
 
731 mateusz.vi 364
  foreach ($listoffiles as $f) {
365
    $f = strtolower($f);
768 mateusz.vi 366
    $path_array = explode('/', $f);
367
    // emit a warning when non-8+3 filenames are spotted and find duplicates
368
    foreach ($path_array as $item) {
369
      if (empty($item)) continue; // skip empty items at end of paths (eg. appinfo/)
370
      if (!preg_match("/[a-z0-9!#$%&'()@^_`{}~-]{1,8}(\.[a-z0-9!#$%&'()@^_`{}~-]{1,3}){0,1}/", $item)) {
371
        echo "WARNING: {$fname} contains a non-8+3 path (or weird char): {$item} (in $f)\n";
372
      }
373
    }
374
    // look for dups
375
    if (array_search($f, $duparr) !== false) {
376
      echo "WARNING: {$fname} contains a duplicated entry: '{$f}'\n";
377
    } else {
378
      $duparr[] = $f;
379
    }
731 mateusz.vi 380
    // LSM file is ok
381
    if ($f === "appinfo/{$pkgnam}.lsm") continue;
382
    if ($f === "appinfo/") continue;
795 mateusz.vi 383
    // CORE and MSDOS_COMPAT packages are premium citizens and can do a little more
909 mateusz.vi 384
    $core_or_msdoscompat = 0;
385
    if (array_search($pkgnam, $core_packages_list) !== false) {
386
      $catlist[] = 'core';
387
      $core_or_msdoscompat = 1;
388
    }
389
    if (array_search($pkgnam, $msdos_compat_list) !== false) {
390
      $catlist[] = 'msdos_compat';
391
      $core_or_msdoscompat = 1;
392
    }
393
    if ($core_or_msdoscompat == 1) {
736 mateusz.vi 394
      if (str_head_is($f, 'bin/')) continue;
779 mateusz.vi 395
      if (str_head_is($f, 'cpi/')) continue;
749 mateusz.vi 396
      if (str_head_is($f, "doc/{$pkgdir}/")) continue;
397
      if ($f === 'doc/') continue;
398
      if (str_head_is($f, "nls/{$pkgdir}.")) continue;
399
      if ($f === 'nls/') continue;
736 mateusz.vi 400
    }
999 mateusz.vi 401
    // SVARCOM is allowed to have a root-based COMMAND.COM file
402
    if ($pkgnam === 'svarcom') {
403
      if ($f === 'command.com') continue;
404
    }
798 mateusz.vi 405
    // the help package is allowed to put files in... help
406
    if (($pkgnam == 'help') && (str_head_is($f, 'help/'))) continue;
909 mateusz.vi 407
    // must be category-prefixed file, add it to the list of categories for this package
408
    $catlist[] = explode('/', $f)[0];
749 mateusz.vi 409
    // well-known "category" dirs are okay
739 mateusz.vi 410
    if (str_head_is($f, "progs/{$pkgdir}/")) continue;
731 mateusz.vi 411
    if ($f === 'progs/') continue;
739 mateusz.vi 412
    if (str_head_is($f, "devel/{$pkgdir}/")) continue;
731 mateusz.vi 413
    if ($f === 'devel/') continue;
739 mateusz.vi 414
    if (str_head_is($f, "games/{$pkgdir}/")) continue;
731 mateusz.vi 415
    if ($f === 'games/') continue;
739 mateusz.vi 416
    if (str_head_is($f, "drivers/{$pkgdir}/")) continue;
731 mateusz.vi 417
    if ($f === 'drivers/') continue;
768 mateusz.vi 418
    echo "WARNING: {$fname} contains a file in an illegal location: {$f}\n";
731 mateusz.vi 419
  }
420
 
912 mateusz.vi 421
  // do I understand the version string?
422
  if (vertoarr($lsmarray['version']) === false) echo "WARNING: {$fname} parsing of version string failed ('{$lsmarray['version']}')\n";
423
 
1511 mateusz.vi 424
  $meta = array();
719 mateusz.vi 425
  $meta['fname'] = $fname;
426
  $meta['desc'] = $lsmarray['description'];
909 mateusz.vi 427
  $meta['cats'] = array_unique($catlist);
1509 mateusz.vi 428
  if (!empty($lsmarray['hwreq'])) $meta['hwreq'] = $lsmarray['hwreq'];
719 mateusz.vi 429
 
430
  $pkgdb[$pkgnam][$lsmarray['version']] = $meta;
431
}
432
 
801 mateusz.vi 433
 
719 mateusz.vi 434
$db = array();
909 mateusz.vi 435
$cats = array();
719 mateusz.vi 436
 
909 mateusz.vi 437
// ******** compute the version-sorted list of packages with a single *********
438
// ******** description and category list for each package ********************
439
 
719 mateusz.vi 440
// iterate over each svp package
441
foreach ($pkgdb as $pkg => $versions) {
442
 
443
  // sort filenames by version, highest first
912 mateusz.vi 444
  uksort($versions, "dos_version_compare");
719 mateusz.vi 445
  $versions = array_reverse($versions, true);
446
 
447
  foreach ($versions as $ver => $meta) {
448
    $fname = $meta['fname'];
449
    $desc = $meta['desc'];
450
 
451
    $bsum = file2bsum(realpath($repodir . '/' . $fname));
452
 
1511 mateusz.vi 453
    $meta2 = array();
719 mateusz.vi 454
    $meta2['ver'] = strval($ver);
455
    $meta2['bsum'] = $bsum;
1510 mateusz.vi 456
    if (!empty($meta['hwreq'])) $meta2['hwreq'] = strtolower($meta['hwreq']);
719 mateusz.vi 457
 
458
    if (empty($db[$pkg]['desc'])) $db[$pkg]['desc'] = $desc;
909 mateusz.vi 459
    if (empty($db[$pkg]['cats'])) {
460
      $db[$pkg]['cats'] = $meta['cats'];
461
      $cats = array_unique(array_merge($cats, $meta['cats']));
462
    }
719 mateusz.vi 463
    $db[$pkg]['versions'][$fname] = $meta2;
464
  }
465
 
562 mateuszvis 466
  $pkgcount++;
467
 
468
}
469
 
719 mateusz.vi 470
if ($pkgcount < 100) echo "WARNING: an unexpectedly low number of packages has been found in the repo ({$pkgcount})\n";
562 mateuszvis 471
 
801 mateusz.vi 472
$json_blob = json_encode($db);
473
if ($json_blob === false) {
474
  echo "ERROR: JSON convertion failed! -> ";
475
  switch (json_last_error()) {
476
    case JSON_ERROR_DEPTH:
477
      echo 'maximum stack depth exceeded';
478
      break;
479
    case JSON_ERROR_STATE_MISMATCH:
480
      echo 'underflow of the modes mismatch';
481
      break;
482
    case JSON_ERROR_CTRL_CHAR:
483
      echo 'unexpected control character found';
484
      break;
485
    case JSON_ERROR_UTF8:
486
      echo 'malformed utf-8 characters';
487
      break;
488
    default:
489
      echo "unknown error";
490
      break;
491
  }
492
  echo "\n";
493
}
494
 
909 mateusz.vi 495
file_put_contents($repodir . '/_index.json', $json_blob);
562 mateuszvis 496
 
909 mateusz.vi 497
$cats_json = json_encode($cats);
498
file_put_contents($repodir . '/_cats.json', $cats_json);
499
 
562 mateuszvis 500
exit(0);
501
 
502
?>