Subversion Repositories SvarDOS

Rev

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