Collection of themes/skins for the Fossil SCM

βŒˆβŒ‹ βŽ‡ branch:  Fossil Skins Extra


Hex Artifact Content

Artifact 0141366ae62a99209f534a7837f03fb684e8bb24:

  • Executable file features/fossil-stats-table.php — part of check-in [d17961d962] at 2020-11-13 21:06:08 on branch trunk — Changed *.py color (user: mario size: 14410)

0000: 23 21 2f 75 73 72 2f 62 69 6e 2f 70 68 70 20 2d  #!/usr/bin/php -
0010: 71 43 0a 3c 3f 70 68 70 0a 2f 2a 2a 0a 20 2a 20  qC.<?php./**. * 
0020: 74 79 70 65 3a 20 63 6c 69 0a 20 2a 20 64 65 73  type: cli. * des
0030: 63 72 69 70 74 69 6f 6e 3a 20 43 72 65 61 74 65  cription: Create
0040: 2f 75 70 64 61 74 65 20 60 66 78 5f 73 74 61 74  /update `fx_stat
0050: 73 60 20 74 61 62 6c 65 20 69 6e 20 66 6f 73 73  s` table in foss
0060: 69 6c 20 72 65 70 6f 73 69 74 6f 72 69 65 73 0a  il repositories.
0070: 20 2a 20 76 65 72 73 69 6f 6e 3a 20 30 2e 39 2e   * version: 0.9.
0080: 31 0a 20 2a 20 64 65 70 65 6e 64 73 3a 20 66 6f  1. * depends: fo
0090: 73 73 69 6c 3a 6a 73 6f 6e 2c 20 66 6f 73 73 69  ssil:json, fossi
00a0: 6c 3a 74 68 31 2d 73 65 74 75 70 0a 20 2a 0a 20  l:th1-setup. *. 
00b0: 2a 20 4c 6f 6f 70 73 20 74 68 72 6f 75 67 68 20  * Loops through 
00c0: 2a 2e 66 6f 73 73 69 6c 20 72 65 70 6f 73 69 74  *.fossil reposit
00d0: 6f 72 69 65 73 2c 0a 20 2a 20 20 20 6f 70 65 6e  ories,. *   open
00e0: 65 64 20 61 73 20 72 61 77 20 73 71 6c 69 74 65  ed as raw sqlite
00f0: 20 64 61 74 61 62 61 73 65 2c 0a 20 2a 20 20 20   database,. *   
0100: 66 65 74 63 68 65 73 20 63 68 65 63 6b 65 64 2d  fetches checked-
0110: 69 6e 20 66 69 6c 65 73 20 70 65 72 20 66 6f 73  in files per fos
0120: 73 69 6c 20 63 6f 6d 6d 61 6e 64 6c 69 6e 65 2e  sil commandline.
0130: 0a 20 2a 0a 20 2a 20 41 6c 73 6f 20 63 72 65 61  . *. * Also crea
0140: 74 65 73 20 61 20 60 66 78 5f 73 74 61 74 73 60  tes a `fx_stats`
0150: 20 74 61 62 6c 65 2c 0a 20 2a 20 20 20 63 6f 75   table,. *   cou
0160: 6e 74 69 6e 67 20 66 69 6c 65 73 20 62 79 20 70  nting files by p
0170: 72 6f 67 72 61 6d 6d 69 6e 67 20 6c 61 6e 67 75  rogramming langu
0180: 61 67 65 2c 0a 20 2a 20 20 20 61 70 70 72 6f 78  age,. *   approx
0190: 69 6d 61 74 69 6e 67 20 74 68 65 20 61 6d 6f 75  imating the amou
01a0: 6e 74 20 6f 66 20 63 6f 6d 6d 65 6e 74 73 20 77  nt of comments w
01b0: 69 74 68 69 6e 2e 0a 20 2a 0a 20 2a 20 41 64 64  ithin.. *. * Add
01c0: 73 20 74 6f 20 60 70 72 6f 6a 65 63 74 73 2e 6a  s to `projects.j
01d0: 73 6f 6e 60 20 66 69 6c 65 3b 0a 20 2a 20 20 20  son` file;. *   
01e0: 67 65 74 73 20 61 20 22 6a 73 6f 6e 20 73 74 61  gets a "json sta
01f0: 74 22 20 64 75 6d 70 20 66 72 6f 6d 20 65 61 63  t" dump from eac
0200: 68 20 2a 2e 66 6f 73 73 69 6c 0a 20 2a 20 20 20  h *.fossil. *   
0210: 73 74 6f 72 65 73 20 70 72 6f 6a 65 63 74 2d 69  stores project-i
0220: 6e 66 6f 2c 20 70 72 6f 6a 65 63 74 2d 64 65 73  nfo, project-des
0230: 63 72 69 70 74 69 6f 6e 0a 20 2a 20 20 20 69 6e  cription. *   in
0240: 20 61 73 73 6f 63 69 61 74 69 76 65 20 22 6e 61   associative "na
0250: 6d 65 22 3a 20 7b 20 2e 2e 2e 20 7d 2c 20 6c 69  me": { ... }, li
0260: 73 74 2e 0a 20 2a 20 20 20 54 6f 67 65 74 68 65  st.. *   Togethe
0270: 72 20 77 69 74 68 20 60 74 69 63 6b 65 74 73 60  r with `tickets`
0280: 20 73 75 62 61 72 72 61 79 2e 0a 20 2a 0a 20 2a   subarray.. *. *
0290: 2f 0a 0a 0a 2f 2f 20 43 6f 6e 66 69 67 75 72 65  /...// Configure
02a0: 20 72 65 70 6f 73 69 74 6f 72 79 20 6c 6f 63 61   repository loca
02b0: 74 69 6f 6e 73 20 28 75 6e 6c 65 73 73 20 63 6d  tions (unless cm
02c0: 64 6c 69 6e 65 20 61 72 67 75 6d 65 6e 74 20 67  dline argument g
02d0: 69 76 65 6e 29 0a 24 72 65 70 6f 73 20 3d 20 61  iven).$repos = a
02e0: 72 72 61 79 5f 73 6c 69 63 65 28 24 5f 53 45 52  rray_slice($_SER
02f0: 56 45 52 5b 22 61 72 67 76 22 5d 2c 20 31 29 20  VER["argv"], 1) 
0300: 6f 72 0a 24 72 65 70 6f 73 20 3d 20 67 6c 6f 62  or.$repos = glob
0310: 28 22 2f 77 77 77 2f 66 6f 73 73 69 6c 2e 64 2f  ("/www/fossil.d/
0320: 2a 2e 66 6f 73 73 69 6c 22 29 3b 0a 0a 2f 2f 20  *.fossil");..// 
0330: 52 65 70 6f 73 69 74 6f 72 79 20 75 72 6c 73 0a  Repository urls.
0340: 64 65 66 69 6e 65 28 22 50 55 42 4c 49 43 5f 55  define("PUBLIC_U
0350: 52 4c 22 2c 20 22 68 74 74 70 3a 2f 2f 66 6f 73  RL", "http://fos
0360: 73 69 6c 2e 69 6e 63 6c 75 64 65 2d 6f 6e 63 65  sil.include-once
0370: 2e 6f 72 67 2f 25 73 2f 22 29 3b 0a 0a 2f 2f 20  .org/%s/");..// 
0380: 50 6f 70 75 6c 61 74 65 20 60 66 78 5f 73 74 61  Populate `fx_sta
0390: 74 73 60 20 73 6f 75 72 63 65 20 63 6f 64 65 20  ts` source code 
03a0: 6c 61 6e 67 75 61 67 65 20 70 65 72 63 65 6e 74  language percent
03b0: 61 67 65 73 0a 64 65 66 69 6e 65 28 22 46 58 5f  ages.define("FX_
03c0: 53 54 41 54 53 22 2c 20 31 29 3b 0a 0a 2f 2f 20  STATS", 1);..// 
03d0: 41 70 70 72 6f 78 69 6d 61 74 65 20 63 6f 64 65  Approximate code
03e0: 20 63 6f 6d 6d 65 6e 74 73 20 61 6e 64 20 74 65   comments and te
03f0: 78 74 20 66 69 6c 65 73 0a 64 65 66 69 6e 65 28  xt files.define(
0400: 22 46 58 5f 53 54 41 54 53 5f 44 4f 43 22 2c 20  "FX_STATS_DOC", 
0410: 31 29 3b 0a 0a 2f 2f 20 49 6e 63 6c 75 64 65 20  1);..// Include 
0420: 62 69 6e 61 72 69 65 73 20 69 6e 20 73 74 61 74  binaries in stat
0430: 69 73 74 69 63 0a 64 65 66 69 6e 65 28 22 46 58  istic.define("FX
0440: 5f 53 54 41 54 53 5f 42 49 4e 22 2c 20 30 29 3b  _STATS_BIN", 0);
0450: 0a 0a 2f 2f 20 41 64 64 20 73 6f 63 69 61 6c 5f  ..// Add social_
0460: 63 6f 75 6e 74 20 74 6f 20 73 74 61 74 73 20 74  count to stats t
0470: 61 62 6c 65 0a 64 65 66 69 6e 65 28 22 46 58 5f  able.define("FX_
0480: 53 4d 4c 22 2c 20 31 29 3b 0a 0a 2f 2f 20 47 65  SML", 1);..// Ge
0490: 74 20 67 65 6e 65 72 61 6c 20 69 6e 66 6f 20 66  t general info f
04a0: 72 6f 6d 20 65 61 63 68 20 2a 2e 66 6f 73 73 69  rom each *.fossi
04b0: 6c 20 72 65 70 6f 0a 64 65 66 69 6e 65 28 22 46  l repo.define("F
04c0: 4f 53 53 49 4c 5f 4a 53 4f 4e 5f 4c 49 53 54 22  OSSIL_JSON_LIST"
04d0: 2c 20 31 29 3b 0a 0a 2f 2f 20 66 6f 73 73 69 6c  , 1);..// fossil
04e0: 20 62 69 6e 61 72 79 0a 24 66 6f 73 73 69 6c 62   binary.$fossilb
04f0: 69 6e 20 3d 20 22 66 6f 73 73 69 6c 22 3b 0a 0a  in = "fossil";..
0500: 2f 2f 20 43 6f 6c 6c 65 63 74 20 70 72 6f 6a 65  // Collect proje
0510: 63 74 73 2e 6a 73 6f 6e 20 69 6e 66 6f 0a 24 6a  cts.json info.$j
0520: 73 6f 6e 5f 70 72 6f 6a 65 63 74 5f 73 74 6f 72  son_project_stor
0530: 65 20 3d 20 22 2f 77 77 77 2f 66 6f 73 73 69 6c  e = "/www/fossil
0540: 2e 64 2f 2e 72 65 70 6f 73 2e 6a 73 6f 6e 22 3b  .d/.repos.json";
0550: 0a 0a 0a 0a 0a 0a 2f 2f 20 4c 6f 6f 70 20 6f 76  ......// Loop ov
0560: 65 72 20 2a 2e 66 6f 73 73 69 6c 20 66 69 6c 65  er *.fossil file
0570: 73 0a 24 6a 73 6f 6e 5f 70 72 6f 6a 65 63 74 5f  s.$json_project_
0580: 6c 69 73 74 20 3d 20 61 72 72 61 79 28 29 3b 0a  list = array();.
0590: 66 6f 72 65 61 63 68 20 28 24 72 65 70 6f 73 20  foreach ($repos 
05a0: 61 73 20 24 72 65 70 6f 29 20 7b 0a 0a 20 20 20  as $repo) {..   
05b0: 24 66 6e 20 3d 20 62 61 73 65 6e 61 6d 65 28 24  $fn = basename($
05c0: 72 65 70 6f 2c 20 22 2e 66 6f 73 73 69 6c 22 29  repo, ".fossil")
05d0: 3b 0a 20 20 20 70 72 69 6e 74 20 22 3c 6c 69 3e  ;.   print "<li>
05e0: 24 66 6e 5c 6e 22 3b 0a 0a 20 20 20 69 66 20 28  $fn\n";..   if (
05f0: 46 58 5f 53 54 41 54 53 29 20 7b 0a 20 20 20 20  FX_STATS) {.    
0600: 20 20 20 6d 6b 5f 74 61 62 6c 65 28 24 72 65 70     mk_table($rep
0610: 6f 2c 20 24 66 6e 29 3b 0a 20 20 20 7d 0a 0a 20  o, $fn);.   }.. 
0620: 20 20 69 66 20 28 46 4f 53 53 49 4c 5f 4a 53 4f    if (FOSSIL_JSO
0630: 4e 5f 4c 49 53 54 29 20 7b 0a 20 20 20 20 20 20  N_LIST) {.      
0640: 20 24 6a 73 6f 6e 5f 70 72 6f 6a 65 63 74 5f 6c   $json_project_l
0650: 69 73 74 5b 24 66 6e 5d 20 3d 20 66 6f 73 73 69  ist[$fn] = fossi
0660: 6c 5f 6a 73 6f 6e 3a 3a 73 74 61 74 28 24 72 65  l_json::stat($re
0670: 70 6f 29 3b 0a 20 20 20 20 20 20 20 24 6a 73 6f  po);.       $jso
0680: 6e 5f 70 72 6f 6a 65 63 74 5f 6c 69 73 74 5b 24  n_project_list[$
0690: 66 6e 5d 5b 22 74 69 63 6b 65 74 73 22 5d 20 3d  fn]["tickets"] =
06a0: 20 66 6f 73 73 69 6c 5f 6a 73 6f 6e 3a 3a 7b 22   fossil_json::{"
06b0: 74 69 6d 65 6c 69 6e 65 20 74 69 63 6b 65 74 22  timeline ticket"
06c0: 7d 28 24 72 65 70 6f 29 5b 22 74 69 6d 65 6c 69  }($repo)["timeli
06d0: 6e 65 22 5d 3b 0a 20 20 20 7d 0a 0a 20 20 20 73  ne"];.   }..   s
06e0: 65 74 5f 74 69 6d 65 5f 6c 69 6d 69 74 28 33 30  et_time_limit(30
06f0: 29 3b 0a 7d 0a 0a 2f 2f 20 73 61 76 65 20 6a 73  );.}..// save js
0700: 6f 6e 5f 6c 69 73 74 0a 69 66 20 28 46 4f 53 53  on_list.if (FOSS
0710: 49 4c 5f 4a 53 4f 4e 5f 4c 49 53 54 29 20 7b 0a  IL_JSON_LIST) {.
0720: 20 20 20 20 66 69 6c 65 5f 70 75 74 5f 63 6f 6e      file_put_con
0730: 74 65 6e 74 73 28 24 6a 73 6f 6e 5f 70 72 6f 6a  tents($json_proj
0740: 65 63 74 5f 73 74 6f 72 65 2c 20 6a 73 6f 6e 5f  ect_store, json_
0750: 65 6e 63 6f 64 65 28 24 6a 73 6f 6e 5f 70 72 6f  encode($json_pro
0760: 6a 65 63 74 5f 6c 69 73 74 2c 20 4a 53 4f 4e 5f  ject_list, JSON_
0770: 50 52 45 54 54 59 5f 50 52 49 4e 54 7c 4a 53 4f  PRETTY_PRINT|JSO
0780: 4e 5f 55 4e 45 53 43 41 50 45 44 5f 53 4c 41 53  N_UNESCAPED_SLAS
0790: 48 45 53 29 29 3b 0a 7d 0a 0a 0a 0a 0a 2f 2f 20  HES));.}.....// 
07a0: 54 72 61 76 65 72 73 65 20 63 6f 6e 74 65 6e 74  Traverse content
07b0: 20 61 6e 64 20 73 74 6f 72 65 20 69 6e 20 60 73   and store in `s
07c0: 65 61 72 63 68 60 20 74 61 62 6c 65 0a 66 75 6e  earch` table.fun
07d0: 63 74 69 6f 6e 20 6d 6b 5f 74 61 62 6c 65 28 24  ction mk_table($
07e0: 72 65 70 6f 2c 20 24 72 65 70 6f 5f 66 6e 29 20  repo, $repo_fn) 
07f0: 7b 0a 20 20 20 67 6c 6f 62 61 6c 20 24 66 6f 73  {.   global $fos
0800: 73 69 6c 62 69 6e 3b 0a 0a 20 20 20 23 2d 2d 20  silbin;..   #-- 
0810: 63 6f 6d 6d 61 6e 64 20 66 6f 72 20 72 65 74 72  command for retr
0820: 69 65 76 61 6c 20 28 67 65 74 3d 3e 29 20 61 6e  ieval (get=>) an
0830: 64 20 66 6f 72 20 6c 61 74 65 72 20 64 69 73 70  d for later disp
0840: 6c 61 79 20 28 77 65 62 3d 3e 29 0a 20 20 20 24  lay (web=>).   $
0850: 52 20 3d 20 65 73 63 61 70 65 73 68 65 6c 6c 61  R = escapeshella
0860: 72 67 28 24 72 65 70 6f 29 3b 0a 20 20 20 24 73  rg($repo);.   $s
0870: 74 61 74 73 20 3d 20 61 72 72 61 79 28 0a 20 20  tats = array(.  
0880: 20 20 20 20 22 6c 61 6e 67 22 20 3d 3e 20 61 72      "lang" => ar
0890: 72 61 79 28 29 2c 0a 20 20 20 20 20 20 22 74 6f  ray(),.      "to
08a0: 74 61 6c 5f 73 69 7a 65 22 20 3d 3e 20 24 74 6f  tal_size" => $to
08b0: 74 61 6c 5f 73 69 7a 65 20 3d 20 30 2c 0a 20 20  tal_size = 0,.  
08c0: 20 29 3b 0a 0a 0a 0a 20 20 20 23 2d 2d 20 6f 70   );....   #-- op
08d0: 65 6e 20 66 6f 73 73 69 6c 2e 64 62 0a 20 20 20  en fossil.db.   
08e0: 24 64 62 20 3d 20 6e 65 77 20 50 44 4f 28 22 73  $db = new PDO("s
08f0: 71 6c 69 74 65 3a 24 72 65 70 6f 22 29 3b 0a 20  qlite:$repo");. 
0900: 20 20 24 64 62 2d 3e 73 65 74 41 74 74 72 69 62    $db->setAttrib
0910: 75 74 65 28 50 44 4f 3a 3a 41 54 54 52 5f 45 52  ute(PDO::ATTR_ER
0920: 52 4d 4f 44 45 2c 20 50 44 4f 3a 3a 45 52 52 4d  RMODE, PDO::ERRM
0930: 4f 44 45 5f 57 41 52 4e 49 4e 47 29 3b 0a 20 20  ODE_WARNING);.  
0940: 20 24 64 62 2d 3e 73 71 6c 69 74 65 43 72 65 61   $db->sqliteCrea
0950: 74 65 46 75 6e 63 74 69 6f 6e 28 22 72 65 67 65  teFunction("rege
0960: 78 70 22 2c 20 66 75 6e 63 74 69 6f 6e 28 24 72  xp", function($r
0970: 2c 20 24 73 29 20 7b 20 72 65 74 75 72 6e 20 70  , $s) { return p
0980: 72 65 67 5f 6d 61 74 63 68 28 22 5c 31 24 72 5c  reg_match("\1$r\
0990: 31 69 22 2c 20 24 73 29 3b 20 7d 2c 20 32 29 3b  1i", $s); }, 2);
09a0: 0a 0a 20 20 20 2f 2f 20 73 65 74 74 69 6e 67 73  ..   // settings
09b0: 0a 20 20 20 24 63 66 67 20 3d 20 61 72 72 61 79  .   $cfg = array
09c0: 5f 63 6f 6c 75 6d 6e 28 24 64 62 2d 3e 71 75 65  _column($db->que
09d0: 72 79 28 22 53 45 4c 45 43 54 20 6e 61 6d 65 2c  ry("SELECT name,
09e0: 76 61 6c 75 65 20 46 52 4f 4d 20 63 6f 6e 66 69  value FROM confi
09f0: 67 22 29 2d 3e 66 65 74 63 68 41 6c 6c 28 29 2c  g")->fetchAll(),
0a00: 20 22 76 61 6c 75 65 22 2c 20 22 6e 61 6d 65 22   "value", "name"
0a10: 29 3b 0a 20 20 20 24 69 67 6e 6f 72 65 5f 67 6c  );.   $ignore_gl
0a20: 6f 62 20 3d 20 40 28 24 63 66 67 5b 22 69 67 6e  ob = @($cfg["ign
0a30: 6f 72 65 2d 67 6c 6f 62 22 5d 29 3b 20 20 2f 2f  ore-glob"]);  //
0a40: 20 6a 75 73 74 20 61 20 73 69 6e 67 6c 65 20 2a   just a single *
0a50: 2e 65 78 74 20 75 73 65 64 20 68 65 72 65 0a 0a  .ext used here..
0a60: 0a 20 20 20 23 2d 2d 20 73 65 74 75 70 20 74 61  .   #-- setup ta
0a70: 62 6c 65 0a 20 20 20 2f 2f 24 64 62 2d 3e 71 75  ble.   //$db->qu
0a80: 65 72 79 28 22 44 52 4f 50 20 54 41 42 4c 45 20  ery("DROP TABLE 
0a90: 49 46 20 45 58 49 53 54 53 20 66 78 5f 73 65 61  IF EXISTS fx_sea
0aa0: 72 63 68 22 29 3b 20 2f 2f 20 6f 62 73 6f 6c 65  rch"); // obsole
0ab0: 74 65 0a 0a 0a 20 20 20 23 2d 2d 20 6c 6f 6f 70  te...   #-- loop
0ac0: 20 74 68 72 6f 75 67 68 20 66 69 6c 65 73 0a 20   through files. 
0ad0: 20 20 24 73 71 6c 20 3d 20 65 73 63 61 70 65 73    $sql = escapes
0ae0: 68 65 6c 6c 61 72 67 28 22 0a 20 20 20 20 20 20  hellarg(".      
0af0: 53 45 4c 45 43 54 20 27 66 69 6c 65 27 20 41 53  SELECT 'file' AS
0b00: 20 74 79 70 65 2c 20 20 20 6e 61 6d 65 20 41 53   type,   name AS
0b10: 20 6e 61 6d 65 2c 20 20 20 20 75 75 69 64 2c 20   name,    uuid, 
0b20: 20 20 20 48 45 58 28 43 4f 4e 54 45 4e 54 28 75     HEX(CONTENT(u
0b30: 75 69 64 29 29 20 41 53 20 63 6f 6e 74 65 6e 74  uid)) AS content
0b40: 0a 20 20 20 20 20 20 20 20 20 46 52 4f 4d 20 28  .         FROM (
0b50: 53 45 4c 45 43 54 20 20 66 69 6c 65 6e 61 6d 65  SELECT  filename
0b60: 2e 6e 61 6d 65 2c 20 62 66 2e 75 75 69 64 2c 20  .name, bf.uuid, 
0b70: 66 69 6c 65 6e 61 6d 65 2e 66 6e 69 64 20 0a 20  filename.fnid . 
0b80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 46 52                FR
0b90: 4f 4d 20 66 69 6c 65 6e 61 6d 65 20 20 4a 4f 49  OM filename  JOI
0ba0: 4e 20 6d 6c 69 6e 6b 20 4f 4e 20 6d 6c 69 6e 6b  N mlink ON mlink
0bb0: 2e 66 6e 69 64 3d 66 69 6c 65 6e 61 6d 65 2e 66  .fnid=filename.f
0bc0: 6e 69 64 20 4a 4f 49 4e 20 62 6c 6f 62 20 62 66  nid JOIN blob bf
0bd0: 20 4f 4e 20 62 66 2e 72 69 64 3d 6d 6c 69 6e 6b   ON bf.rid=mlink
0be0: 2e 66 69 64 0a 20 20 20 20 20 20 20 20 20 20 20  .fid.           
0bf0: 20 20 20 20 20 20 20 20 20 4a 4f 49 4e 20 65 76           JOIN ev
0c00: 65 6e 74 20 4f 4e 20 65 76 65 6e 74 2e 6f 62 6a  ent ON event.obj
0c10: 69 64 3d 6d 6c 69 6e 6b 2e 6d 69 64 0a 20 20 20  id=mlink.mid.   
0c20: 20 20 20 20 20 20 20 20 20 20 20 20 57 48 45 52              WHER
0c30: 45 20 28 6d 6c 69 6e 6b 2e 66 6e 69 64 20 4e 4f  E (mlink.fnid NO
0c40: 54 20 49 4e 20 28 53 45 4c 45 43 54 20 66 6e 69  T IN (SELECT fni
0c50: 64 20 46 52 4f 4d 20 6d 6c 69 6e 6b 20 57 48 45  d FROM mlink WHE
0c60: 52 45 20 66 69 64 3d 30 29 29 0a 20 20 20 20 20  RE fid=0)).     
0c70: 20 20 20 20 20 20 20 20 20 20 47 52 4f 55 50 20            GROUP 
0c80: 42 59 20 66 69 6c 65 6e 61 6d 65 2e 6e 61 6d 65  BY filename.name
0c90: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
0ca0: 4f 52 44 45 52 20 42 59 20 65 76 65 6e 74 2e 6d  ORDER BY event.m
0cb0: 74 69 6d 65 20 44 45 53 43 0a 20 20 20 20 20 20  time DESC.      
0cc0: 20 20 20 20 20 20 20 20 29 0a 20 20 20 22 29 3b          ).   ");
0cd0: 0a 20 20 20 2f 2f 20 4a 75 73 74 20 72 65 74 72  .   // Just retr
0ce0: 69 65 76 65 20 61 73 20 43 53 56 20 6c 69 73 74  ieve as CSV list
0cf0: 20 66 72 6f 6d 20 66 6f 73 73 69 6c 20 64 69 72   from fossil dir
0d00: 65 63 74 6c 79 2c 20 69 6e 73 74 65 61 64 20 6f  ectly, instead o
0d10: 66 20 75 73 69 6e 67 20 50 44 4f 20 68 61 6e 64  f using PDO hand
0d20: 6c 65 20 61 6e 64 20 60 66 6f 73 73 69 6c 20 61  le and `fossil a
0d30: 72 74 69 66 61 63 74 60 20 6f 6e 20 65 61 63 68  rtifact` on each
0d40: 20 55 55 49 44 0a 20 20 20 24 70 69 70 65 20 3d   UUID.   $pipe =
0d50: 20 70 6f 70 65 6e 28 22 66 6f 73 73 69 6c 20 73   popen("fossil s
0d60: 71 6c 69 74 65 20 2d 52 20 24 52 20 5c 22 2e 6d  qlite -R $R \".m
0d70: 6f 64 65 20 63 73 76 5c 22 20 24 73 71 6c 22 2c  ode csv\" $sql",
0d80: 20 22 72 62 22 29 3b 0a 20 20 20 77 68 69 6c 65   "rb");.   while
0d90: 20 28 24 72 6f 77 20 3d 20 66 67 65 74 63 73 76   ($row = fgetcsv
0da0: 28 24 70 69 70 65 2c 20 30 2c 20 22 2c 22 2c 20  ($pipe, 0, ",", 
0db0: 27 22 27 2c 20 27 22 27 29 29 20 7b 0a 0a 20 20  '"', '"')) {..  
0dc0: 20 20 20 20 23 2d 2d 20 70 72 65 70 61 72 65 20      #-- prepare 
0dd0: 65 6e 74 72 79 20 61 74 74 72 69 62 75 74 65 73  entry attributes
0de0: 0a 20 20 20 20 20 20 69 66 20 28 63 6f 75 6e 74  .      if (count
0df0: 28 24 72 6f 77 29 20 21 3d 20 34 29 20 7b 20 63  ($row) != 4) { c
0e00: 6f 6e 74 69 6e 75 65 3b 20 7d 0a 20 20 20 20 20  ontinue; }.     
0e10: 20 6c 69 73 74 28 24 74 79 70 65 2c 20 24 6e 61   list($type, $na
0e20: 6d 65 2c 20 24 75 75 69 64 2c 20 24 63 6f 6e 74  me, $uuid, $cont
0e30: 65 6e 74 29 20 3d 20 24 72 6f 77 3b 0a 20 20 20  ent) = $row;.   
0e40: 20 20 20 24 63 6f 6e 74 65 6e 74 20 3d 20 68 65     $content = he
0e50: 78 32 62 69 6e 28 24 63 6f 6e 74 65 6e 74 29 3b  x2bin($content);
0e60: 0a 20 20 20 20 20 20 65 63 68 6f 20 22 e2 86 92  .      echo "β†’
0e70: 20 22 2c 20 24 6e 61 6d 65 2c 20 22 20 22 2c 20   ", $name, " ", 
0e80: 73 74 72 6c 65 6e 28 24 63 6f 6e 74 65 6e 74 29  strlen($content)
0e90: 2c 20 22 5c 6e 22 3b 0a 0a 20 20 20 20 20 20 23  , "\n";..      #
0ea0: 2d 2d 20 73 74 61 74 69 73 74 69 63 73 0a 20 20  -- statistics.  
0eb0: 20 20 20 20 69 66 20 28 46 58 5f 53 54 41 54 53      if (FX_STATS
0ec0: 20 61 6e 64 20 24 74 79 70 65 20 3d 3d 20 22 66   and $type == "f
0ed0: 69 6c 65 22 29 20 7b 0a 0a 20 20 20 20 20 20 20  ile") {..       
0ee0: 20 20 20 2f 2f 20 69 67 6e 6f 72 65 2d 67 6c 6f     // ignore-glo
0ef0: 62 20 28 65 2e 67 2e 20 2a 2e 68 74 6d 6c 29 0a  b (e.g. *.html).
0f00: 20 20 20 20 20 20 20 20 20 20 69 66 20 28 66 6e            if (fn
0f10: 6d 61 74 63 68 28 24 69 67 6e 6f 72 65 5f 67 6c  match($ignore_gl
0f20: 6f 62 2c 20 24 6e 61 6d 65 29 29 20 7b 0a 20 20  ob, $name)) {.  
0f30: 20 20 20 20 20 20 20 20 20 20 20 20 63 6f 6e 74              cont
0f40: 69 6e 75 65 3b 0a 20 20 20 20 20 20 20 20 20 20  inue;.          
0f50: 7d 0a 0a 20 20 20 20 20 20 20 20 20 20 2f 2f 20  }..          // 
0f60: 61 64 64 20 69 66 20 6d 61 74 63 68 65 64 20 6c  add if matched l
0f70: 61 6e 67 75 61 67 65 2c 20 6e 6f 74 20 62 69 6e  anguage, not bin
0f80: 61 72 79 2c 20 65 74 63 2e 0a 20 20 20 20 20 20  ary, etc..      
0f90: 20 20 20 20 69 66 20 28 24 6c 61 6e 67 20 3d 20      if ($lang = 
0fa0: 6c 61 6e 67 75 61 67 65 5f 74 79 70 65 28 24 6e  language_type($n
0fb0: 61 6d 65 2c 20 24 63 6f 6e 74 65 6e 74 29 20 6f  ame, $content) o
0fc0: 72 20 46 58 5f 53 54 41 54 53 5f 42 49 4e 20 61  r FX_STATS_BIN a
0fd0: 6e 64 20 24 6c 61 6e 67 20 3d 20 22 62 69 6e 22  nd $lang = "bin"
0fe0: 29 20 7b 0a 0a 20 20 20 20 20 20 20 20 20 20 20  ) {..           
0ff0: 20 20 20 2f 2f 20 73 74 72 69 70 20 63 6f 6d 6d     // strip comm
1000: 65 6e 74 73 20 66 72 6f 6d 20 63 6f 64 65 0a 20  ents from code. 
1010: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
1020: 28 46 58 5f 53 54 41 54 53 5f 44 4f 43 20 26 26  (FX_STATS_DOC &&
1030: 20 24 74 79 70 65 20 21 3d 20 22 62 69 6e 22 29   $type != "bin")
1040: 20 7b 0a 20 20 20 20 20 20 20 20 20 20 20 20 20   {.             
1050: 20 20 20 20 20 24 63 6f 6d 6d 65 6e 74 73 20 3d       $comments =
1060: 20 65 78 74 72 5f 63 6f 6d 6d 65 6e 74 73 28 24   extr_comments($
1070: 63 6f 6e 74 65 6e 74 2c 20 24 6c 61 6e 67 29 3b  content, $lang);
1080: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 7d  .              }
1090: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65  .              e
10a0: 6c 73 65 20 7b 0a 20 20 20 20 20 20 20 20 20 20  lse {.          
10b0: 20 20 20 20 20 20 20 20 24 63 6f 6d 6d 65 6e 74          $comment
10c0: 73 20 3d 20 22 22 3b 0a 20 20 20 20 20 20 20 20  s = "";.        
10d0: 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 20 20        }.        
10e0: 20 20 20 20 20 20 0a 20 20 20 20 20 20 20 20 20        .         
10f0: 20 20 20 20 20 2f 2f 20 61 64 64 20 74 6f 20 6c       // add to l
1100: 61 6e 67 75 61 67 65 20 73 74 61 74 69 73 74 69  anguage statisti
1110: 63 73 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  cs.             
1120: 20 40 24 73 74 61 74 73 5b 22 6c 61 6e 67 22 5d   @$stats["lang"]
1130: 5b 24 6c 61 6e 67 5d 20 2b 3d 20 73 74 72 6c 65  [$lang] += strle
1140: 6e 28 24 63 6f 6e 74 65 6e 74 29 20 2d 20 73 74  n($content) - st
1150: 72 6c 65 6e 28 24 63 6f 6d 6d 65 6e 74 73 29 3b  rlen($comments);
1160: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 40  .              @
1170: 24 73 74 61 74 73 5b 22 6c 61 6e 67 22 5d 5b 22  $stats["lang"]["
1180: 63 6f 6d 6d 65 6e 74 73 22 5d 20 2b 3d 20 73 74  comments"] += st
1190: 72 6c 65 6e 28 24 63 6f 6d 6d 65 6e 74 73 29 3b  rlen($comments);
11a0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 24  .              $
11b0: 74 6f 74 61 6c 5f 73 69 7a 65 20 2b 3d 20 73 74  total_size += st
11c0: 72 6c 65 6e 28 24 63 6f 6e 74 65 6e 74 29 3b 0a  rlen($content);.
11d0: 20 20 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20            }.    
11e0: 20 20 7d 0a 20 20 20 7d 0a 0a 0a 20 20 20 23 2d    }.   }...   #-
11f0: 2d 20 60 66 78 5f 73 74 61 74 73 60 20 70 6f 70  - `fx_stats` pop
1200: 75 6c 61 74 69 6f 6e 0a 20 20 20 24 64 62 2d 3e  ulation.   $db->
1210: 71 75 65 72 79 28 22 43 52 45 41 54 45 20 54 41  query("CREATE TA
1220: 42 4c 45 20 49 46 20 4e 4f 54 20 45 58 49 53 54  BLE IF NOT EXIST
1230: 53 20 66 78 5f 73 74 61 74 73 20 28 6e 61 6d 65  S fx_stats (name
1240: 20 54 45 58 54 2c 20 74 79 70 65 20 54 45 58 54   TEXT, type TEXT
1250: 2c 20 76 61 6c 75 65 20 54 45 58 54 29 22 29 3b  , value TEXT)");
1260: 0a 20 20 20 24 64 62 2d 3e 71 75 65 72 79 28 22  .   $db->query("
1270: 44 45 4c 45 54 45 20 46 52 4f 4d 20 66 78 5f 73  DELETE FROM fx_s
1280: 74 61 74 73 22 29 3b 0a 20 20 20 24 69 6e 73 65  tats");.   $inse
1290: 72 74 20 3d 20 24 64 62 2d 3e 70 72 65 70 61 72  rt = $db->prepar
12a0: 65 28 22 49 4e 53 45 52 54 20 49 4e 54 4f 20 66  e("INSERT INTO f
12b0: 78 5f 73 74 61 74 73 20 28 6e 61 6d 65 2c 20 74  x_stats (name, t
12c0: 79 70 65 2c 20 76 61 6c 75 65 29 20 56 41 4c 55  ype, value) VALU
12d0: 45 53 20 28 3f 2c 3f 2c 3f 29 22 29 3b 0a 0a 20  ES (?,?,?)");.. 
12e0: 20 20 2f 2f 20 72 65 63 61 6c 63 75 6c 61 74 65    // recalculate
12f0: 20 69 6e 74 6f 20 66 6c 6f 61 74 73 0a 20 20 20   into floats.   
1300: 69 66 20 28 24 74 6f 74 61 6c 5f 73 69 7a 65 29  if ($total_size)
1310: 20 7b 0a 20 20 20 20 20 20 20 61 72 73 6f 72 74   {.       arsort
1320: 28 24 73 74 61 74 73 5b 22 6c 61 6e 67 22 5d 29  ($stats["lang"])
1330: 3b 0a 20 20 20 20 20 20 20 66 6f 72 65 61 63 68  ;.       foreach
1340: 20 28 24 73 74 61 74 73 5b 22 6c 61 6e 67 22 5d   ($stats["lang"]
1350: 20 61 73 20 24 6c 61 6e 67 20 3d 3e 20 24 62 79   as $lang => $by
1360: 74 65 73 29 20 7b 0a 0a 20 20 20 20 20 20 20 20  tes) {..        
1370: 20 20 20 2f 2f 20 61 64 64 20 61 73 20 70 72 65     // add as pre
1380: 70 61 72 65 64 20 54 48 31 20 61 72 72 61 79 20  pared TH1 array 
1390: 76 61 72 20 6e 61 6d 65 20 60 24 6c 61 6e 67 28  var name `$lang(
13a0: 6a 73 29 3d 30 2e 33 37 60 0a 20 20 20 20 20 20  js)=0.37`.      
13b0: 20 20 20 20 20 24 69 6e 73 65 72 74 2d 3e 65 78       $insert->ex
13c0: 65 63 75 74 65 28 61 72 72 61 79 28 20 22 6c 61  ecute(array( "la
13d0: 6e 67 28 24 6c 61 6e 67 29 22 2c 20 22 6c 61 6e  ng($lang)", "lan
13e0: 67 22 2c 20 72 6f 75 6e 64 28 24 62 79 74 65 73  g", round($bytes
13f0: 2f 24 74 6f 74 61 6c 5f 73 69 7a 65 2c 20 33 29  /$total_size, 3)
1400: 20 29 29 3b 0a 20 20 20 20 20 20 20 20 20 20 20   ));.           
1410: 24 69 6e 73 65 72 74 2d 3e 65 78 65 63 75 74 65  $insert->execute
1420: 28 61 72 72 61 79 28 20 22 6c 61 6e 67 5f 63 6f  (array( "lang_co
1430: 6c 6f 72 28 24 6c 61 6e 67 29 22 2c 20 22 63 6f  lor($lang)", "co
1440: 6c 6f 72 22 2c 20 6c 61 6e 67 5f 63 6f 6c 6f 72  lor", lang_color
1450: 28 24 6c 61 6e 67 29 20 29 29 3b 0a 20 20 20 20  ($lang) ));.    
1460: 20 20 20 7d 0a 20 20 20 7d 0a 0a 20 20 20 2f 2f     }.   }..   //
1470: 20 6e 6f 72 6d 61 6c 20 54 43 4c 20 76 61 72 73   normal TCL vars
1480: 0a 20 20 20 24 69 6e 73 65 72 74 2d 3e 65 78 65  .   $insert->exe
1490: 63 75 74 65 28 61 72 72 61 79 28 22 74 6f 74 61  cute(array("tota
14a0: 6c 5f 73 69 7a 65 22 2c 20 22 62 79 74 65 73 22  l_size", "bytes"
14b0: 2c 20 24 74 6f 74 61 6c 5f 73 69 7a 65 29 29 3b  , $total_size));
14c0: 0a 20 20 20 24 69 6e 73 65 72 74 2d 3e 65 78 65  .   $insert->exe
14d0: 63 75 74 65 28 61 72 72 61 79 28 22 6c 61 6e 67  cute(array("lang
14e0: 5f 6c 69 73 74 22 2c 20 22 6c 69 73 74 22 2c 20  _list", "list", 
14f0: 6a 6f 69 6e 28 22 20 22 2c 20 61 72 72 61 79 5f  join(" ", array_
1500: 6b 65 79 73 28 61 72 72 61 79 5f 66 69 6c 74 65  keys(array_filte
1510: 72 28 24 73 74 61 74 73 5b 22 6c 61 6e 67 22 5d  r($stats["lang"]
1520: 29 29 29 20 29 29 3b 0a 0a 0a 20 20 20 2f 2a 2a  ))) ));...   /**
1530: 0a 20 20 20 20 2a 20 4f 74 68 65 72 20 73 74 61  .    * Other sta
1540: 74 73 0a 20 20 20 20 2a 20 28 74 68 65 73 65 20  ts.    * (these 
1550: 61 72 65 20 6d 6f 73 74 6c 79 20 66 69 78 65 64  are mostly fixed
1560: 20 76 65 72 73 69 6f 6e 73 20 6f 66 20 74 68 65   versions of the
1570: 20 54 48 31 78 20 71 75 65 72 69 65 73 2e 29 0a   TH1x queries.).
1580: 20 20 20 20 2a 0a 20 20 20 20 2a 2f 0a 20 20 20      *.    */.   
1590: 24 6f 74 68 65 72 20 3d 20 61 72 72 61 79 28 0a  $other = array(.
15a0: 20 20 20 20 20 20 22 73 6f 63 69 61 6c 22 20 3d        "social" =
15b0: 3e 20 73 6f 63 69 61 6c 5f 6d 65 64 69 61 5f 6c  > social_media_l
15c0: 69 6e 6b 73 5f 63 6f 75 6e 74 28 24 72 65 70 6f  inks_count($repo
15d0: 5f 66 6e 2c 20 24 64 62 29 2c 0a 20 20 20 20 20  _fn, $db),.     
15e0: 20 22 63 68 65 63 6b 69 6e 73 22 20 3d 3e 20 22   "checkins" => "
15f0: 53 45 4c 45 43 54 20 63 6f 75 6e 74 28 6f 62 6a  SELECT count(obj
1600: 69 64 29 20 46 52 4f 4d 20 65 76 65 6e 74 20 57  id) FROM event W
1610: 48 45 52 45 20 74 79 70 65 3d 27 63 69 27 20 4c  HERE type='ci' L
1620: 49 4d 49 54 20 31 22 2c 0a 20 20 20 20 20 20 22  IMIT 1",.      "
1630: 66 69 6c 65 73 22 20 3d 3e 20 22 53 45 4c 45 43  files" => "SELEC
1640: 54 20 63 6f 75 6e 74 28 6e 61 6d 65 29 20 46 52  T count(name) FR
1650: 4f 4d 20 66 69 6c 65 6e 61 6d 65 20 4c 49 4d 49  OM filename LIMI
1660: 54 20 31 22 2c 0a 20 20 20 20 20 20 22 74 69 63  T 1",.      "tic
1670: 6b 65 74 73 22 20 3d 3e 20 22 53 45 4c 45 43 54  kets" => "SELECT
1680: 20 63 6f 75 6e 74 28 73 74 61 74 75 73 29 20 46   count(status) F
1690: 52 4f 4d 20 74 69 63 6b 65 74 20 4c 49 4d 49 54  ROM ticket LIMIT
16a0: 20 31 22 2c 0a 20 20 20 20 20 20 22 64 65 76 65   1",.      "deve
16b0: 6c 6f 70 65 72 73 22 20 3d 3e 20 22 53 45 4c 45  lopers" => "SELE
16c0: 43 54 20 63 6f 75 6e 74 28 44 49 53 54 49 4e 43  CT count(DISTINC
16d0: 54 20 75 73 65 72 29 20 46 52 4f 4d 20 65 76 65  T user) FROM eve
16e0: 6e 74 20 4c 49 4d 49 54 20 31 22 2c 0a 20 20 20  nt LIMIT 1",.   
16f0: 20 20 20 22 62 72 61 6e 63 68 65 73 22 20 3d 3e     "branches" =>
1700: 20 22 53 45 4c 45 43 54 20 63 6f 75 6e 74 28 44   "SELECT count(D
1710: 49 53 54 49 4e 43 54 20 76 61 6c 75 65 29 20 46  ISTINCT value) F
1720: 52 4f 4d 20 74 61 67 78 72 65 66 20 57 48 45 52  ROM tagxref WHER
1730: 45 20 74 61 67 69 64 3d 38 22 2c 0a 20 20 20 20  E tagid=8",.    
1740: 20 20 22 74 61 67 73 22 20 3d 3e 20 22 53 45 4c    "tags" => "SEL
1750: 45 43 54 20 63 6f 75 6e 74 28 74 61 67 6e 61 6d  ECT count(tagnam
1760: 65 29 20 46 52 4f 4d 20 74 61 67 20 57 48 45 52  e) FROM tag WHER
1770: 45 20 74 61 67 6e 61 6d 65 20 4c 49 4b 45 20 27  E tagname LIKE '
1780: 73 79 6d 2d 25 27 22 2c 0a 20 20 20 20 20 20 22  sym-%'",.      "
1790: 66 6f 72 6b 73 22 20 3d 3e 20 22 53 45 4c 45 43  forks" => "SELEC
17a0: 54 20 43 4f 55 4e 54 28 6e 61 6d 65 29 20 46 52  T COUNT(name) FR
17b0: 4f 4d 20 63 6f 6e 66 69 67 20 57 48 45 52 45 20  OM config WHERE 
17c0: 6e 61 6d 65 20 47 4c 4f 42 20 27 62 61 73 65 75  name GLOB 'baseu
17d0: 72 6c 3a 2a 27 20 4f 52 20 6e 61 6d 65 20 47 4c  rl:*' OR name GL
17e0: 4f 42 20 27 63 6b 6f 75 74 3a 2a 27 22 2c 0a 20  OB 'ckout:*'",. 
17f0: 20 20 20 20 20 22 72 65 6c 65 61 73 65 73 22 20       "releases" 
1800: 3d 3e 20 22 53 45 4c 45 43 54 20 63 6f 75 6e 74  => "SELECT count
1810: 28 74 61 67 6e 61 6d 65 29 20 46 52 4f 4d 20 74  (tagname) FROM t
1820: 61 67 20 57 48 45 52 45 20 74 61 67 6e 61 6d 65  ag WHERE tagname
1830: 20 52 45 47 45 58 50 20 27 5e 73 79 6d 5b 2d 61   REGEXP '^sym[-a
1840: 2d 7a 30 2d 39 5f 2e 5d 2b 5c 64 2b 5c 2e 5c 64  -z0-9_.]+\d+\.\d
1850: 2b 27 22 2c 0a 20 20 20 20 20 20 22 6e 61 6d 65  +'",.      "name
1860: 2c 74 65 78 74 22 20 3d 3e 20 22 53 45 4c 45 43  ,text" => "SELEC
1870: 54 20 76 61 6c 75 65 20 46 52 4f 4d 20 63 6f 6e  T value FROM con
1880: 66 69 67 20 57 48 45 52 45 20 6e 61 6d 65 3d 27  fig WHERE name='
1890: 70 72 6f 6a 65 63 74 2d 6e 61 6d 65 27 22 2c 0a  project-name'",.
18a0: 20 20 20 20 20 20 22 64 65 73 63 72 69 70 74 69        "descripti
18b0: 6f 6e 2c 68 74 6d 6c 22 20 3d 3e 20 22 53 45 4c  on,html" => "SEL
18c0: 45 43 54 20 76 61 6c 75 65 20 46 52 4f 4d 20 63  ECT value FROM c
18d0: 6f 6e 66 69 67 20 57 48 45 52 45 20 6e 61 6d 65  onfig WHERE name
18e0: 3d 27 70 72 6f 6a 65 63 74 2d 64 65 73 63 72 69  ='project-descri
18f0: 70 74 69 6f 6e 27 22 2c 0a 20 20 20 29 3b 0a 20  ption'",.   );. 
1900: 20 20 66 6f 72 65 61 63 68 20 28 24 6f 74 68 65    foreach ($othe
1910: 72 20 61 73 20 24 6b 65 79 3d 3e 24 73 71 6c 29  r as $key=>$sql)
1920: 20 7b 0a 20 20 20 20 20 20 20 6c 69 73 74 28 24   {.       list($
1930: 6b 65 79 2c 20 24 74 79 70 2c 20 29 20 3d 20 65  key, $typ, ) = e
1940: 78 70 6c 6f 64 65 28 22 2c 22 2c 20 22 24 6b 65  xplode(",", "$ke
1950: 79 2c 69 6e 74 22 29 3b 0a 20 20 20 20 20 20 20  y,int");.       
1960: 24 64 62 2d 3e 71 75 65 72 79 28 22 49 4e 53 45  $db->query("INSE
1970: 52 54 20 49 4e 54 4f 20 66 78 5f 73 74 61 74 73  RT INTO fx_stats
1980: 20 28 60 6e 61 6d 65 60 2c 20 60 74 79 70 65 60   (`name`, `type`
1990: 2c 20 60 76 61 6c 75 65 60 29 20 56 41 4c 55 45  , `value`) VALUE
19a0: 53 20 28 27 73 74 61 74 73 5f 24 6b 65 79 27 2c  S ('stats_$key',
19b0: 20 27 24 74 79 70 27 2c 20 28 24 73 71 6c 29 29   '$typ', ($sql))
19c0: 22 29 3b 0a 20 20 20 7d 0a 20 20 20 2f 2f 20 6c  ");.   }.   // l
19d0: 61 74 65 73 74 5f 76 65 72 73 69 6f 6e 0a 20 20  atest_version.  
19e0: 20 24 71 76 20 3d 20 24 64 62 2d 3e 71 75 65 72   $qv = $db->quer
19f0: 79 28 22 53 45 4c 45 43 54 20 74 61 67 6e 61 6d  y("SELECT tagnam
1a00: 65 20 46 52 4f 4d 20 74 61 67 20 57 48 45 52 45  e FROM tag WHERE
1a10: 20 74 61 67 6e 61 6d 65 20 52 45 47 45 58 50 20   tagname REGEXP 
1a20: 27 5e 73 79 6d 5b 2d 61 2d 7a 30 2d 39 5f 2e 5d  '^sym[-a-z0-9_.]
1a30: 2b 5c 64 2b 5c 2e 5c 64 2b 27 20 4f 52 44 45 52  +\d+\.\d+' ORDER
1a40: 20 42 59 20 74 61 67 69 64 20 44 45 53 43 20 4c   BY tagid DESC L
1a50: 49 4d 49 54 20 31 22 29 3b 0a 20 20 20 69 66 20  IMIT 1");.   if 
1a60: 28 24 71 76 2d 3e 65 78 65 63 75 74 65 28 29 20  ($qv->execute() 
1a70: 61 6e 64 20 70 72 65 67 5f 6d 61 74 63 68 28 22  and preg_match("
1a80: 2f 28 5c 64 2b 5c 2e 5c 64 2b 2e 2a 29 24 2f 22  /(\d+\.\d+.*)$/"
1a90: 2c 20 24 71 76 2d 3e 66 65 74 63 68 28 29 5b 22  , $qv->fetch()["
1aa0: 74 61 67 6e 61 6d 65 22 5d 2c 20 24 6d 29 29 20  tagname"], $m)) 
1ab0: 7b 0a 20 20 20 20 20 20 20 24 64 62 2d 3e 70 72  {.       $db->pr
1ac0: 65 70 61 72 65 28 22 49 4e 53 45 52 54 20 49 4e  epare("INSERT IN
1ad0: 54 4f 20 66 78 5f 73 74 61 74 73 20 28 60 6e 61  TO fx_stats (`na
1ae0: 6d 65 60 2c 20 60 74 79 70 65 60 2c 20 60 76 61  me`, `type`, `va
1af0: 6c 75 65 60 29 20 56 41 4c 55 45 53 20 28 27 73  lue`) VALUES ('s
1b00: 74 61 74 73 5f 6c 61 74 65 73 74 5f 76 65 72 73  tats_latest_vers
1b10: 69 6f 6e 27 2c 20 27 74 65 78 74 27 2c 20 3f 29  ion', 'text', ?)
1b20: 22 29 0a 20 20 20 20 20 20 20 20 20 20 2d 3e 65  ").          ->e
1b30: 78 65 63 75 74 65 28 5b 24 6d 5b 31 5d 5d 29 3b  xecute([$m[1]]);
1b40: 0a 20 20 20 7d 0a 0a 0a 7d 0a 0a 0a 0a 0a 0a 0a  .   }...}.......
1b50: 0a 0a 0a 0a 2f 2f 20 64 65 74 65 72 6d 69 6e 65  ....// determine
1b60: 20 70 72 6f 67 72 61 6d 6d 69 6e 67 20 6c 61 6e   programming lan
1b70: 67 75 61 67 65 20 66 72 6f 6d 20 66 69 6c 65 20  guage from file 
1b80: 65 78 74 65 6e 73 69 6f 6e 2c 20 6f 72 20 73 68  extension, or sh
1b90: 65 62 61 6e 67 0a 66 75 6e 63 74 69 6f 6e 20 6c  ebang.function l
1ba0: 61 6e 67 75 61 67 65 5f 74 79 70 65 28 24 6e 61  anguage_type($na
1bb0: 6d 65 2c 20 24 63 6f 6e 74 65 6e 74 29 20 7b 0a  me, $content) {.
1bc0: 0a 20 20 20 20 2f 2f 20 63 68 65 63 6b 20 69 66  .    // check if
1bd0: 20 62 69 6e 61 72 79 0a 20 20 20 20 69 66 20 28   binary.    if (
1be0: 70 72 65 67 5f 6d 61 74 63 68 5f 61 6c 6c 28 22  preg_match_all("
1bf0: 2f 5b 5c 5c 78 30 30 2d 5c 5c 78 30 36 5c 5c 78  /[\\x00-\\x06\\x
1c00: 30 45 2d 5c 5c 78 31 46 5d 2b 2f 22 2c 20 24 63  0E-\\x1F]+/", $c
1c10: 6f 6e 74 65 6e 74 2c 20 24 6d 29 0a 20 20 20 20  ontent, $m).    
1c20: 20 20 20 61 6e 64 20 24 62 69 6e 20 3d 20 73 74     and $bin = st
1c30: 72 6c 65 6e 28 6a 6f 69 6e 28 24 6d 5b 30 5d 29  rlen(join($m[0])
1c40: 29 0a 20 20 20 20 20 20 20 61 6e 64 20 24 62 69  ).       and $bi
1c50: 6e 20 3e 3d 20 73 74 72 6c 65 6e 28 24 63 6f 6e  n >= strlen($con
1c60: 74 65 6e 74 29 2f 33 32 0a 20 20 20 20 20 20 20  tent)/32.       
1c70: 6f 72 20 73 74 72 70 6f 73 28 24 6e 61 6d 65 2c  or strpos($name,
1c80: 20 22 66 69 6c 65 73 79 73 74 65 6d 5f 6c 69 73   "filesystem_lis
1c90: 74 22 29 29 0a 20 20 20 20 7b 0a 20 20 20 20 20  t")).    {.     
1ca0: 20 20 20 72 65 74 75 72 6e 20 4e 55 4c 4c 3b 0a     return NULL;.
1cb0: 20 20 20 20 7d 0a 20 20 20 20 0a 20 20 20 20 0a      }.    .    .
1cc0: 20 20 20 20 2f 2f 20 66 69 6c 65 20 65 78 74 65      // file exte
1cd0: 6e 73 69 6f 6e 0a 20 20 20 20 69 66 20 28 24 65  nsion.    if ($e
1ce0: 78 74 20 3d 20 70 61 74 68 69 6e 66 6f 28 24 6e  xt = pathinfo($n
1cf0: 61 6d 65 2c 20 50 41 54 48 49 4e 46 4f 5f 45 58  ame, PATHINFO_EX
1d00: 54 45 4e 53 49 4f 4e 29 29 20 7b 0a 20 20 20 20  TENSION)) {.    
1d10: 20 20 20 20 24 6c 61 6e 67 20 3d 20 24 65 78 74      $lang = $ext
1d20: 3b 0a 20 20 20 20 7d 0a 20 20 20 20 0a 20 20 20  ;.    }.    .   
1d30: 20 2f 2f 20 73 68 65 62 61 6e 67 0a 20 20 20 20   // shebang.    
1d40: 65 6c 73 65 69 66 20 28 70 72 65 67 5f 6d 61 74  elseif (preg_mat
1d50: 63 68 28 22 7e 5e 23 21 5c 73 2a 5b 5c 77 2e 2f  ch("~^#!\s*[\w./
1d60: 2d 5d 2b 2f 28 3f 3a 65 6e 76 5c 73 2b 29 3f 28  -]+/(?:env\s+)?(
1d70: 3f 3c 69 6e 74 3e 5c 77 2b 29 7e 22 2c 20 24 63  ?<int>\w+)~", $c
1d80: 6f 6e 74 65 6e 74 2c 20 24 6d 29 29 20 7b 0a 20  ontent, $m)) {. 
1d90: 20 20 20 20 20 20 20 24 6c 61 6e 67 20 3d 20 24         $lang = $
1da0: 6d 5b 22 69 6e 74 22 5d 3b 0a 20 20 20 20 7d 0a  m["int"];.    }.
1db0: 20 20 20 20 0a 20 20 20 20 2f 2f 20 65 6c 73 65      .    // else
1dc0: 20 64 65 63 6c 61 72 65 20 69 74 20 64 6f 63 75   declare it docu
1dd0: 6d 65 6e 74 61 74 69 6f 6e 20 6f 66 20 73 6f 72  mentation of sor
1de0: 74 73 0a 20 20 20 20 65 6c 73 65 20 7b 0a 20 20  ts.    else {.  
1df0: 20 20 20 20 20 20 24 6c 61 6e 67 20 3d 20 22 74        $lang = "t
1e00: 65 78 74 22 3b 0a 20 20 20 20 7d 0a 20 20 20 20  ext";.    }.    
1e10: 0a 20 20 20 20 2f 2f 20 61 6c 69 61 73 65 73 0a  .    // aliases.
1e20: 20 20 20 20 24 6d 61 70 20 3d 20 61 72 72 61 79      $map = array
1e30: 28 0a 20 20 20 20 20 20 20 20 22 63 2b 2b 22 20  (.        "c++" 
1e40: 3d 3e 20 22 63 70 70 22 2c 20 20 20 20 20 22 63  => "cpp",     "c
1e50: 78 78 22 20 3d 3e 20 22 63 70 70 22 2c 20 20 20  xx" => "cpp",   
1e60: 20 20 20 22 68 2b 2b 22 20 3d 3e 20 22 63 70 70     "h++" => "cpp
1e70: 22 2c 20 20 20 20 20 22 68 78 78 22 20 3d 3e 20  ",     "hxx" => 
1e80: 22 63 70 70 22 2c 20 20 20 20 20 22 68 70 70 22  "cpp",     "hpp"
1e90: 20 3d 3e 20 22 63 70 70 22 2c 20 20 20 20 20 22   => "cpp",     "
1ea0: 68 68 22 20 3d 3e 20 22 63 70 70 22 2c 0a 20 20  hh" => "cpp",.  
1eb0: 20 20 20 20 20 20 22 63 63 22 20 3d 3e 20 22 63        "cc" => "c
1ec0: 22 2c 20 20 20 20 20 20 20 20 22 68 22 20 3d 3e  ",        "h" =>
1ed0: 20 22 63 22 2c 0a 20 20 20 20 20 20 20 20 22 74   "c",.        "t
1ee0: 63 6c 73 68 22 20 3d 3e 20 22 74 63 6c 22 2c 20  clsh" => "tcl", 
1ef0: 20 20 22 77 69 73 68 22 20 3d 3e 20 22 74 63 6c    "wish" => "tcl
1f00: 22 2c 20 20 20 20 20 22 74 68 31 22 20 3d 3e 20  ",     "th1" => 
1f10: 22 74 63 6c 22 2c 0a 20 20 20 20 20 20 20 20 22  "tcl",.        "
1f20: 70 79 74 68 6f 6e 22 20 3d 3e 20 22 70 79 22 2c  python" => "py",
1f30: 20 20 20 22 70 79 74 68 6f 6e 33 22 20 3d 3e 20     "python3" => 
1f40: 22 70 79 22 2c 0a 20 20 20 20 20 20 20 20 22 65  "py",.        "e
1f50: 72 62 22 20 3d 3e 20 22 72 62 22 2c 0a 20 20 20  rb" => "rb",.   
1f60: 20 20 20 20 20 22 62 61 73 68 22 20 3d 3e 20 22       "bash" => "
1f70: 73 68 22 2c 20 20 20 20 20 22 64 61 73 68 22 20  sh",     "dash" 
1f80: 3d 3e 20 22 73 68 22 2c 20 20 20 20 20 20 22 63  => "sh",      "c
1f90: 73 68 22 20 3d 3e 20 22 73 68 22 2c 20 20 20 20  sh" => "sh",    
1fa0: 20 22 6b 73 68 22 20 3d 3e 20 22 73 68 22 2c 0a   "ksh" => "sh",.
1fb0: 20 20 20 20 20 20 20 20 22 6a 22 20 3d 3e 20 22          "j" => "
1fc0: 6a 61 76 61 22 2c 20 20 20 20 20 20 22 6a 73 70  java",      "jsp
1fd0: 22 20 3d 3e 20 22 6a 61 76 61 22 2c 0a 20 20 20  " => "java",.   
1fe0: 20 20 20 20 20 22 70 65 72 6c 22 20 3d 3e 20 22       "perl" => "
1ff0: 70 6c 22 2c 20 20 20 20 20 22 70 6d 22 20 3d 3e  pl",     "pm" =>
2000: 20 22 70 6c 22 2c 0a 20 20 20 20 20 20 20 20 22   "pl",.        "
2010: 73 76 67 22 20 3d 3e 20 22 78 6d 6c 22 2c 0a 20  svg" => "xml",. 
2020: 20 20 20 20 20 20 20 22 68 74 6d 22 20 3d 3e 20         "htm" => 
2030: 22 68 74 6d 6c 22 2c 20 20 20 20 22 73 68 74 6d  "html",    "shtm
2040: 6c 22 20 3d 3e 20 22 68 74 6d 6c 22 2c 20 20 20  l" => "html",   
2050: 22 78 68 74 6d 6c 22 20 3d 3e 20 22 68 74 6d 6c  "xhtml" => "html
2060: 22 2c 0a 20 20 20 20 20 20 20 20 22 70 68 74 6d  ",.        "phtm
2070: 6c 22 20 3d 3e 20 22 70 68 70 22 2c 20 20 20 22  l" => "php",   "
2080: 70 68 70 34 22 20 3d 3e 20 22 70 68 70 22 2c 20  php4" => "php", 
2090: 20 20 20 20 22 70 68 70 35 22 20 3d 3e 20 22 70      "php5" => "p
20a0: 68 70 22 2c 20 20 20 22 69 6e 63 22 20 3d 3e 20  hp",   "inc" => 
20b0: 22 70 68 70 22 2c 0a 20 20 20 20 20 20 20 20 22  "php",.        "
20c0: 74 78 74 22 20 3d 3e 20 22 74 65 78 74 22 2c 20  txt" => "text", 
20d0: 20 20 20 22 61 73 63 22 20 3d 3e 20 22 74 65 78     "asc" => "tex
20e0: 74 22 2c 20 20 20 20 20 22 70 6f 74 22 20 3d 3e  t",     "pot" =>
20f0: 20 22 74 65 78 74 22 2c 0a 20 20 20 20 20 20 20   "text",.       
2100: 20 22 31 22 20 3d 3e 20 22 6d 61 6e 22 2c 20 20   "1" => "man",  
2110: 20 20 20 20 20 22 67 72 6f 66 66 22 20 3d 3e 20       "groff" => 
2120: 22 6d 61 6e 22 2c 20 20 20 20 22 74 72 6f 66 66  "man",    "troff
2130: 22 20 3d 3e 20 22 6d 61 6e 22 2c 0a 20 20 20 20  " => "man",.    
2140: 29 3b 0a 20 20 20 20 69 66 20 28 69 73 73 65 74  );.    if (isset
2150: 28 24 6d 61 70 5b 24 6c 61 6e 67 5d 29 29 20 7b  ($map[$lang])) {
2160: 0a 20 20 20 20 20 20 20 24 6c 61 6e 67 20 3d 20  .       $lang = 
2170: 24 6d 61 70 5b 24 6c 61 6e 67 5d 3b 0a 20 20 20  $map[$lang];.   
2180: 20 7d 0a 20 20 20 20 0a 20 20 20 20 72 65 74 75   }.    .    retu
2190: 72 6e 20 24 6c 61 6e 67 3b 0a 7d 0a 0a 0a 2f 2f  rn $lang;.}...//
21a0: 20 65 78 74 72 61 63 74 20 63 6f 6d 6d 6d 65 6e   extract commmen
21b0: 74 73 20 61 63 63 6f 72 64 69 6e 67 20 74 6f 20  ts according to 
21c0: 6c 61 6e 67 75 61 67 65 0a 66 75 6e 63 74 69 6f  language.functio
21d0: 6e 20 65 78 74 72 5f 63 6f 6d 6d 65 6e 74 73 28  n extr_comments(
21e0: 24 63 6f 6e 74 65 6e 74 2c 20 24 6c 61 6e 67 29  $content, $lang)
21f0: 20 7b 0a 0a 20 20 20 20 23 20 72 65 67 65 78 20   {..    # regex 
2200: 63 6f 6d 6d 65 6e 74 20 74 79 70 65 73 0a 20 20  comment types.  
2210: 20 20 24 7b 22 2f 2a 22 7d 20 3d 20 22 5c 2f 5c    ${"/*"} = "\/\
2220: 2a 5b 5c 73 5c 53 5d 2a 3f 5c 2a 5c 2f 22 3b 20  *[\s\S]*?\*\/"; 
2230: 20 20 20 20 20 20 20 23 20 20 2f 2a 20 2e 2e 2e         #  /* ...
2240: 20 2a 2f 20 20 20 20 20 20 20 20 20 20 20 20 20   */             
2250: 20 20 20 20 28 2a 29 0a 20 20 20 20 24 7b 22 2f      (*).    ${"/
2260: 2f 22 7d 20 3d 20 22 28 5e 7c 3b 29 5c 73 2a 2f  /"} = "(^|;)\s*/
2270: 2f 2e 2a 3f 24 22 3b 20 20 20 20 20 20 20 20 20  /.*?$";         
2280: 20 23 20 20 2f 2f 20 2e 2e 2e 20 20 20 20 20 20   #  // ...      
2290: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 28 2a                (*
22a0: 29 0a 20 20 20 20 24 7b 22 23 22 7d 20 20 3d 20  ).    ${"#"}  = 
22b0: 22 28 5e 7c 3b 29 5c 73 2a 5c 23 2e 2a 3f 24 22  "(^|;)\s*\#.*?$"
22c0: 3b 20 20 20 20 20 20 20 20 20 20 23 20 20 23 20  ;          #  # 
22d0: 2e 2e 2e 20 20 20 20 20 20 20 20 20 20 20 20 20  ...             
22e0: 20 20 20 20 20 20 20 20 28 2a 29 0a 20 20 20 20          (*).    
22f0: 24 7b 22 3b 22 7d 20 20 3d 20 22 5e 5c 73 2a 3b  ${";"}  = "^\s*;
2300: 2e 2a 3f 24 22 3b 20 20 20 20 20 20 20 20 20 20  .*?$";          
2310: 20 20 20 20 20 23 20 20 3b 20 2e 2e 2e 20 20 20       #  ; ...   
2320: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2330: 20 20 28 69 6e 69 29 0a 20 20 20 20 24 7b 22 2d    (ini).    ${"-
2340: 2d 22 7d 20 3d 20 22 5e 5c 73 2a 2d 2d 2e 2a 3f  -"} = "^\s*--.*?
2350: 24 22 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  $";             
2360: 20 23 20 20 2d 2d 20 2e 2e 2e 20 20 20 20 20 20   #  -- ...      
2370: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 28 53                (S
2380: 51 4c 29 0a 20 20 20 20 24 7b 22 52 4d 22 7d 20  QL).    ${"RM"} 
2390: 3d 20 22 5e 5c 73 2a 52 45 4d 5c 73 2b 2e 2b 3f  = "^\s*REM\s+.+?
23a0: 24 2f 22 3b 20 20 20 20 20 20 20 20 20 23 20 20  $/";         #  
23b0: 52 45 4d 20 2e 2e 2e 23 20 20 20 20 20 20 20 20  REM ...#        
23c0: 20 20 20 20 20 20 20 20 20 20 28 42 61 73 69 63            (Basic
23d0: 29 0a 20 20 20 20 24 7b 22 54 51 22 7d 20 3d 20  ).    ${"TQ"} = 
23e0: 27 22 22 22 5b 5c 73 5c 53 5d 22 22 22 27 3b 20  '"""[\s\S]"""'; 
23f0: 20 20 20 20 20 20 20 20 20 20 20 23 20 20 22 22             #  ""
2400: 22 20 2e 2e 2e 20 22 22 22 20 20 20 20 20 20 20  " ... """       
2410: 20 20 20 20 20 20 20 20 28 50 79 74 68 6f 6e 29          (Python)
2420: 0a 20 20 20 20 24 7b 22 7b 2a 22 7d 20 3d 20 22  .    ${"{*"} = "
2430: 5c 7b 5c 2a 5b 5c 73 5c 53 5d 2a 3f 5c 2a 5c 7d  \{\*[\s\S]*?\*\}
2440: 22 3b 20 20 20 20 20 20 20 20 23 20 20 7b 2a 20  ";        #  {* 
2450: 2e 2e 2e 20 2a 7d 20 20 20 20 20 20 20 20 20 20  ... *}          
2460: 20 20 20 20 20 20 20 28 50 61 73 63 61 6c 29 0a         (Pascal).
2470: 20 20 20 20 24 7b 22 28 2a 22 7d 20 3d 20 22 5c      ${"(*"} = "\
2480: 28 5c 2a 5b 5c 73 5c 53 5d 2a 3f 5c 2a 5c 29 22  (\*[\s\S]*?\*\)"
2490: 3b 20 20 20 20 20 20 20 20 23 20 20 28 2a 20 2e  ;        #  (* .
24a0: 2e 2e 20 2a 29 20 20 20 20 20 20 20 20 20 20 20  .. *)           
24b0: 20 20 20 20 20 20 28 44 65 6c 70 68 69 29 0a 20        (Delphi). 
24c0: 20 20 20 24 7b 22 3c 23 22 7d 20 3d 20 22 3c 5c     ${"<#"} = "<\
24d0: 23 5b 5c 73 5c 53 5d 2a 3f 5c 23 3e 22 3b 20 20  #[\s\S]*?\#>";  
24e0: 20 20 20 20 20 20 20 20 23 20 20 3c 23 20 2e 2e          #  <# ..
24f0: 2e 20 23 3e 20 20 20 20 20 20 20 20 20 20 20 20  . #>            
2500: 20 20 20 20 20 28 53 68 65 6c 6c 2f 41 57 4b 29       (Shell/AWK)
2510: 0a 20 20 20 20 24 7b 22 2f 2b 22 7d 20 3d 20 22  .    ${"/+"} = "
2520: 5c 2f 5c 2b 28 5b 5c 73 5c 53 5d 7c 28 3f 31 29  \/\+([\s\S]|(?1)
2530: 29 5c 2b 5c 2f 22 3b 20 20 20 23 20 20 2f 2b 20  )\+\/";   #  /+ 
2540: 2e 2e 2e 20 2b 2f 20 20 20 20 20 20 20 20 20 20  ... +/          
2550: 20 20 20 20 20 20 20 28 44 3b 20 6e 65 73 74 65         (D; neste
2560: 64 29 0a 20 20 20 20 24 7b 22 3c 21 22 7d 20 3d  d).    ${"<!"} =
2570: 20 22 3c 21 2d 2d 5b 5c 73 5c 53 5d 2d 2d 3e 22   "<!--[\s\S]-->"
2580: 3b 20 20 20 20 20 20 20 20 20 20 20 23 20 20 3c  ;           #  <
2590: 21 2d 2d 20 2e 2e 20 2d 2d 3e 20 20 20 20 20 20  !-- .. -->      
25a0: 20 20 20 20 20 20 20 20 20 28 48 54 4d 4c 29 0a           (HTML).
25b0: 20 20 20 20 24 7b 22 3d 62 22 7d 20 3d 20 22 5e      ${"=b"} = "^
25c0: 3d 62 65 67 69 6e 5b 5c 73 5c 53 5d 2a 3f 5e 3d  =begin[\s\S]*?^=
25d0: 28 63 75 74 7c 65 6e 64 29 2f 22 3b 20 20 23 20  (cut|end)/";  # 
25e0: 3d 62 65 67 69 6e 20 2e 2e 2e 20 3d 65 6e 64 20  =begin ... =end 
25f0: 20 20 20 20 20 20 28 50 65 72 6c 2f 52 75 62 79        (Perl/Ruby
2600: 29 0a 20 20 20 20 24 7b 22 7b 2d 22 7d 20 3d 20  ).    ${"{-"} = 
2610: 22 5c 7b 2d 28 5b 5c 73 5c 53 5d 7c 28 3f 31 29  "\{-([\s\S]|(?1)
2620: 29 2a 3f 2d 5c 7d 22 3b 20 20 20 23 20 20 7b 2d  )*?-\}";   #  {-
2630: 20 2e 2e 2e 20 2d 7d 20 20 20 20 20 20 20 20 20   ... -}         
2640: 20 20 20 20 20 20 20 20 28 48 61 73 6b 65 6c 6c          (Haskell
2650: 3b 20 6e 65 73 74 65 64 29 0a 20 20 20 20 24 7b  ; nested).    ${
2660: 22 23 7c 22 7d 20 3d 20 22 5c 23 5c 7c 5b 5c 73  "#|"} = "\#\|[\s
2670: 5c 53 5d 2a 3f 5c 7c 5c 23 2f 22 3b 20 20 20 20  \S]*?\|\#/";    
2680: 20 20 20 23 20 20 23 7c 20 2e 2e 2e 20 7c 23 20     #  #| ... |# 
2690: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
26a0: 28 4c 69 73 70 2f 53 63 68 65 6d 65 29 0a 20 20  (Lisp/Scheme).  
26b0: 20 20 24 7b 22 2e 5c 5c 22 7d 20 3d 22 5e 5c 2e    ${".\\"} ="^\.
26c0: 5c 5c 5c 5c 5c 22 2f 22 3b 20 20 20 20 20 20 20  \\\\\"/";       
26d0: 20 20 20 20 20 20 20 23 20 20 2e 5c 22 20 20 20         #  .\"   
26e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
26f0: 20 20 20 20 28 6d 61 6e 2f 74 72 6f 66 66 29 0a      (man/troff).
2700: 0a 20 20 20 20 23 20 6c 61 6e 67 75 61 67 65 73  .    # languages
2710: 0a 20 20 20 20 24 6c 61 6e 67 72 78 20 3d 20 61  .    $langrx = a
2720: 72 72 61 79 28 0a 20 20 20 20 20 20 20 22 2a 22  rray(.       "*"
2730: 20 20 20 3d 3e 20 22 7e 28 20 24 7b 27 2f 2a 27     => "~( ${'/*'
2740: 7d 20 7c 20 24 7b 27 2f 2f 27 7d 20 7c 20 24 7b  } | ${'//'} | ${
2750: 27 23 27 7d 20 29 7e 6d 78 22 2c 0a 20 20 20 20  '#'} )~mx",.    
2760: 20 20 20 22 70 68 70 22 20 3d 3e 20 22 7e 28 20     "php" => "~( 
2770: 24 7b 27 2f 2a 27 7d 20 7c 20 24 7b 27 2f 2f 27  ${'/*'} | ${'//'
2780: 7d 20 7c 20 24 7b 27 23 27 7d 20 29 7e 6d 78 22  } | ${'#'} )~mx"
2790: 2c 0a 20 20 20 20 20 20 20 22 70 79 22 20 20 3d  ,.       "py"  =
27a0: 3e 20 22 7e 28 20 24 7b 27 23 27 7d 20 20 7c 20  > "~( ${'#'}  | 
27b0: 24 7b 27 54 51 27 7d 20 20 20 20 20 20 20 20 20  ${'TQ'}         
27c0: 20 29 7e 6d 78 22 2c 0a 20 20 20 20 20 20 20 22   )~mx",.       "
27d0: 70 6c 22 20 20 3d 3e 20 22 7e 28 20 24 7b 27 3d  pl"  => "~( ${'=
27e0: 62 27 7d 20 7c 20 24 7b 27 23 27 7d 20 20 20 20  b'} | ${'#'}    
27f0: 20 20 20 20 20 20 20 29 7e 6d 78 22 2c 0a 20 20         )~mx",.  
2800: 20 20 20 20 20 22 73 68 22 20 20 3d 3e 20 22 7e       "sh"  => "~
2810: 28 20 24 7b 27 23 27 7d 20 20 7c 20 24 7b 27 3c  ( ${'#'}  | ${'<
2820: 23 27 7d 20 20 20 20 20 20 20 20 20 20 29 7e 6d  #'}          )~m
2830: 78 22 2c 0a 20 20 20 20 20 20 20 22 63 22 20 20  x",.       "c"  
2840: 20 3d 3e 20 22 7e 28 20 24 7b 27 2f 2a 27 7d 20   => "~( ${'/*'} 
2850: 7c 20 24 7b 27 2f 2f 27 7d 20 20 20 20 20 20 20  | ${'//'}       
2860: 20 20 20 29 7e 6d 78 22 2c 0a 20 20 20 20 20 20     )~mx",.      
2870: 20 22 63 70 70 22 20 3d 3e 20 22 7e 28 20 24 7b   "cpp" => "~( ${
2880: 27 2f 2a 27 7d 20 7c 20 24 7b 27 2f 2f 27 7d 20  '/*'} | ${'//'} 
2890: 20 20 20 20 20 20 20 20 20 29 7e 6d 78 22 2c 0a           )~mx",.
28a0: 20 20 20 20 20 20 20 22 68 74 6d 6c 22 3d 3e 20         "html"=> 
28b0: 22 7e 28 20 24 7b 27 3c 21 27 7d 20 20 20 20 20  "~( ${'<!'}     
28c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 29                 )
28d0: 7e 6d 78 22 2c 0a 20 20 20 20 20 20 20 22 78 6d  ~mx",.       "xm
28e0: 6c 22 20 3d 3e 20 22 7e 28 20 24 7b 27 3c 21 27  l" => "~( ${'<!'
28f0: 7d 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  }               
2900: 20 20 20 20 20 29 7e 6d 78 22 2c 0a 20 20 20 20       )~mx",.    
2910: 20 20 20 22 63 73 73 22 20 3d 3e 20 22 7e 28 20     "css" => "~( 
2920: 24 7b 27 2f 2a 27 7d 20 7c 20 24 7b 27 2f 2f 27  ${'/*'} | ${'//'
2930: 7d 20 20 20 20 20 20 20 20 20 20 29 7e 6d 78 22  }          )~mx"
2940: 2c 0a 20 20 20 20 20 20 20 22 6a 73 22 20 20 3d  ,.       "js"  =
2950: 3e 20 22 7e 28 20 24 7b 27 2f 2a 27 7d 20 7c 20  > "~( ${'/*'} | 
2960: 24 7b 27 2f 2f 27 7d 20 20 20 20 20 20 20 20 20  ${'//'}         
2970: 20 29 7e 6d 78 22 2c 0a 20 20 20 20 20 20 20 22   )~mx",.       "
2980: 74 63 6c 22 20 3d 3e 20 22 7e 28 20 24 7b 27 2f  tcl" => "~( ${'/
2990: 2a 27 7d 20 7c 20 24 7b 27 2f 2f 27 7d 20 7c 20  *'} | ${'//'} | 
29a0: 24 7b 27 23 27 7d 20 29 7e 6d 78 22 2c 0a 20 20  ${'#'} )~mx",.  
29b0: 20 20 20 20 20 22 70 61 73 22 20 3d 3e 20 22 7e       "pas" => "~
29c0: 28 20 24 7b 27 28 2a 27 7d 20 7c 20 24 7b 27 7b  ( ${'(*'} | ${'{
29d0: 2a 27 7d 20 20 20 20 20 20 20 20 20 20 29 7e 6d  *'}          )~m
29e0: 78 22 2c 0a 20 20 20 20 20 20 20 22 64 22 20 20  x",.       "d"  
29f0: 20 3d 3e 20 22 7e 28 20 24 7b 27 2f 2b 27 7d 20   => "~( ${'/+'} 
2a00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2a10: 20 20 20 29 7e 6d 78 22 2c 0a 20 20 20 20 20 20     )~mx",.      
2a20: 20 22 69 6e 69 22 20 3d 3e 20 22 7e 28 20 24 7b   "ini" => "~( ${
2a30: 27 3b 27 7d 20 20 20 20 20 20 20 20 20 20 20 20  ';'}            
2a40: 20 20 20 20 20 20 20 20 20 29 7e 6d 78 22 2c 0a           )~mx",.
2a50: 20 20 20 20 20 20 20 22 6a 61 76 61 22 3d 3e 20         "java"=> 
2a60: 22 7e 28 20 24 7b 27 2f 2a 27 7d 20 7c 20 24 7b  "~( ${'/*'} | ${
2a70: 27 2f 2f 27 7d 20 20 20 20 20 20 20 20 20 20 29  '//'}          )
2a80: 7e 6d 78 22 2c 0a 20 20 20 20 20 20 20 22 62 61  ~mx",.       "ba
2a90: 73 22 20 3d 3e 20 22 7e 28 20 24 7b 27 52 4d 27  s" => "~( ${'RM'
2aa0: 7d 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  }               
2ab0: 20 20 20 20 20 29 7e 6d 78 22 2c 0a 20 20 20 20       )~mx",.    
2ac0: 20 20 20 22 6d 61 6e 22 20 3d 3e 20 22 7e 28 20     "man" => "~( 
2ad0: 24 7b 27 2e 5c 5c 27 7d 20 20 20 20 20 20 20 20  ${'.\\'}        
2ae0: 20 20 20 20 20 20 20 20 20 20 20 29 7e 6d 78 22             )~mx"
2af0: 2c 0a 20 20 20 20 29 3b 0a 20 20 20 20 0a 20 20  ,.    );.    .  
2b00: 20 20 23 20 6d 61 74 63 68 0a 20 20 20 20 69 66    # match.    if
2b10: 20 28 65 6d 70 74 79 28 24 6c 61 6e 67 72 78 5b   (empty($langrx[
2b20: 24 6c 61 6e 67 5d 29 29 20 7b 0a 20 20 20 20 20  $lang])) {.     
2b30: 20 20 20 24 6c 61 6e 67 20 3d 20 22 2a 22 3b 0a     $lang = "*";.
2b40: 20 20 20 20 7d 0a 20 20 20 20 72 65 74 75 72 6e      }.    return
2b50: 20 70 72 65 67 5f 6d 61 74 63 68 5f 61 6c 6c 28   preg_match_all(
2b60: 24 6c 61 6e 67 72 78 5b 24 6c 61 6e 67 5d 2c 20  $langrx[$lang], 
2b70: 24 63 6f 6e 74 65 6e 74 2c 20 24 6d 61 74 63 68  $content, $match
2b80: 29 20 3f 20 6a 6f 69 6e 28 22 22 2c 20 24 6d 61  ) ? join("", $ma
2b90: 74 63 68 5b 31 5d 29 20 3a 20 22 22 3b 0a 7d 0a  tch[1]) : "";.}.
2ba0: 0a 0a 0a 2f 2f 20 67 65 74 73 20 64 65 66 61 75  ...// gets defau
2bb0: 6c 74 20 63 6f 6c 6f 72 20 73 63 68 65 6d 65 20  lt color scheme 
2bc0: 66 6f 72 20 6c 61 6e 67 75 61 67 65 20 28 74 68  for language (th
2bd0: 69 73 20 73 68 6f 75 6c 64 20 61 63 74 75 61 6c  is should actual
2be0: 6c 79 20 67 6f 20 69 6e 20 61 20 73 74 79 6c 65  ly go in a style
2bf0: 73 68 65 65 74 2c 20 62 75 74 20 74 68 65 73 65  sheet, but these
2c00: 20 61 72 65 20 74 68 65 20 65 78 70 65 63 74 65   are the expecte
2c10: 64 20 64 65 66 61 75 6c 74 73 29 0a 66 75 6e 63  d defaults).func
2c20: 74 69 6f 6e 20 6c 61 6e 67 5f 63 6f 6c 6f 72 28  tion lang_color(
2c30: 24 6e 61 6d 65 29 0a 7b 0a 20 20 20 20 2f 2f 20  $name).{.    // 
2c40: 65 78 63 65 72 70 74 20 66 72 6f 6d 20 68 74 74  excerpt from htt
2c50: 70 73 3a 2f 2f 67 69 74 68 75 62 2e 63 6f 6d 2f  ps://github.com/
2c60: 64 6f 64 61 2f 67 69 74 68 75 62 2d 6c 61 6e 67  doda/github-lang
2c70: 75 61 67 65 2d 63 6f 6c 6f 72 73 0a 20 20 20 24  uage-colors.   $
2c80: 63 6f 6c 20 3d 20 61 72 72 61 79 28 0a 20 20 20  col = array(.   
2c90: 20 20 20 27 63 6f 6d 6d 65 6e 74 73 27 20 3d 3e     'comments' =>
2ca0: 20 22 37 37 37 3b 20 62 61 63 6b 67 72 6f 75 6e   "777; backgroun
2cb0: 64 3a 6c 69 6e 65 61 72 2d 67 72 61 64 69 65 6e  d:linear-gradien
2cc0: 74 28 31 36 35 64 65 67 2c 23 39 39 39 2c 23 62  t(165deg,#999,#b
2cd0: 62 62 2c 23 66 63 35 2c 23 64 64 64 2c 23 61 61  bb,#fc5,#ddd,#aa
2ce0: 61 29 3b 22 2c 20 2f 2f 20 73 70 65 63 69 61 6c  a);", // special
2cf0: 20 6c 61 6e 67 28 63 6f 6d 6d 65 6e 74 73 29 20   lang(comments) 
2d00: 70 72 6f 70 65 72 74 79 20 6f 66 20 66 78 5f 73  property of fx_s
2d10: 74 61 74 73 20 0a 20 20 20 20 20 20 27 62 69 6e  tats .      'bin
2d20: 27 20 3d 3e 20 22 37 63 38 3b 20 62 61 63 6b 67  ' => "7c8; backg
2d30: 72 6f 75 6e 64 3a 6c 69 6e 65 61 72 2d 67 72 61  round:linear-gra
2d40: 64 69 65 6e 74 28 31 37 37 64 65 67 2c 23 35 62  dient(177deg,#5b
2d50: 36 2c 23 36 63 37 2c 23 63 38 37 2c 23 36 38 65  6,#6c7,#c87,#68e
2d60: 2c 23 35 37 64 29 3b 22 2c 20 2f 2f 20 62 69 6e  ,#57d);", // bin
2d70: 61 72 69 65 73 2c 20 69 66 20 65 6e 61 62 6c 65  aries, if enable
2d80: 64 0a 20 20 20 20 20 20 23 27 70 79 27 20 3d 3e  d.      #'py' =>
2d90: 20 22 33 32 36 62 39 61 3b 20 62 61 63 6b 67 72   "326b9a; backgr
2da0: 6f 75 6e 64 3a 72 65 70 65 61 74 69 6e 67 2d 6c  ound:repeating-l
2db0: 69 6e 65 61 72 2d 67 72 61 64 69 65 6e 74 28 31  inear-gradient(1
2dc0: 34 35 64 65 67 2c 23 33 35 38 31 62 61 2c 23 33  45deg,#3581ba,#3
2dd0: 35 38 31 62 61 2c 23 66 66 65 30 35 65 2c 23 61  581ba,#ffe05e,#a
2de0: 65 38 64 30 30 20 32 35 25 29 3b 22 2c 20 2f 2f  e8d00 25%);", //
2df0: 20 62 6c 75 65 2f 79 65 6c 6c 6f 77 0a 20 20 20   blue/yellow.   
2e00: 20 20 20 27 74 65 78 74 27 20 3d 3e 20 22 63 30     'text' => "c0
2e10: 63 38 63 66 22 2c 0a 20 20 20 20 20 20 27 27 20  c8cf",.      '' 
2e20: 3d 3e 20 22 66 31 35 35 30 31 22 2c 20 2f 2f 20  => "f15501", // 
2e30: 62 69 6e 0a 20 20 20 20 20 20 22 6a 61 76 61 22  bin.      "java"
2e40: 20 3d 3e 20 22 62 30 37 32 31 39 22 2c 20 20 22   => "b07219",  "
2e50: 73 63 61 6c 61 22 20 3d 3e 20 22 37 64 64 33 62  scala" => "7dd3b
2e60: 30 22 2c 20 20 22 70 61 73 22 20 3d 3e 20 22 62  0",  "pas" => "b
2e70: 30 63 65 34 65 22 2c 20 20 22 70 6c 22 20 3d 3e  0ce4e",  "pl" =>
2e80: 20 22 30 32 39 38 63 33 22 2c 0a 20 20 20 20 20   "0298c3",.     
2e90: 20 22 6c 75 61 22 20 3d 3e 20 22 66 61 31 66 61   "lua" => "fa1fa
2ea0: 31 22 2c 20 20 20 22 72 22 20 3d 3e 20 22 31 39  1",   "r" => "19
2eb0: 38 63 65 37 22 2c 20 20 20 20 20 20 22 6e 75 22  8ce7",      "nu"
2ec0: 20 3d 3e 20 22 63 39 64 66 34 30 22 2c 20 20 20   => "c9df40",   
2ed0: 22 63 6c 6a 22 20 3d 3e 20 22 64 62 35 38 35 35  "clj" => "db5855
2ee0: 22 2c 0a 20 20 20 20 20 20 22 73 68 22 20 3d 3e  ",.      "sh" =>
2ef0: 20 22 35 38 36 31 63 65 22 2c 20 20 20 20 22 61   "5861ce",    "a
2f00: 73 6d 22 20 3d 3e 20 22 61 36 37 32 31 39 22 2c  sm" => "a67219",
2f10: 20 20 20 20 22 70 69 72 22 20 3d 3e 20 22 66 33      "pir" => "f3
2f20: 63 61 30 61 22 2c 20 20 22 6c 69 73 70 22 20 3d  ca0a",  "lisp" =
2f30: 3e 20 22 33 66 62 36 38 62 22 2c 0a 20 20 20 20  > "3fb68b",.    
2f40: 20 20 22 64 61 72 74 22 20 3d 3e 20 22 63 63 63    "dart" => "ccc
2f50: 63 63 63 22 2c 20 20 22 63 73 22 20 3d 3e 20 22  ccc",  "cs" => "
2f60: 32 34 34 37 37 36 22 2c 20 20 20 20 20 22 68 73  244776",     "hs
2f70: 22 20 3d 3e 20 22 32 39 62 35 34 34 22 2c 20 20  " => "29b544",  
2f80: 20 22 72 75 62 79 22 20 3d 3e 20 22 37 30 31 35   "ruby" => "7015
2f90: 31 36 22 2c 0a 20 20 20 20 20 20 22 63 22 20 3d  16",.      "c" =
2fa0: 3e 20 22 35 35 35 22 2c 20 20 20 20 20 20 20 20  > "555",        
2fb0: 22 6a 73 22 20 3d 3e 20 22 66 31 35 35 30 31 22  "js" => "f15501"
2fc0: 2c 20 20 20 20 20 22 64 22 20 3d 3e 20 22 66 63  ,     "d" => "fc
2fd0: 64 34 36 64 22 2c 20 20 20 20 22 63 70 70 22 20  d46d",    "cpp" 
2fe0: 3d 3e 20 22 66 33 34 62 37 64 22 2c 0a 20 20 20  => "f34b7d",.   
2ff0: 20 20 20 22 6f 62 6a 63 22 20 3d 3e 20 22 66 31     "objc" => "f1
3000: 35 35 30 31 22 2c 20 20 22 72 75 73 74 22 20 3d  5501",  "rust" =
3010: 3e 20 22 64 65 61 35 38 34 22 2c 20 20 20 22 74  > "dea584",   "t
3020: 63 6c 22 20 3d 3e 20 22 65 34 63 63 39 38 22 2c  cl" => "e4cc98",
3030: 0a 20 20 20 20 20 20 22 67 6f 22 20 3d 3e 20 22  .      "go" => "
3040: 38 64 30 34 65 62 22 2c 20 20 20 20 22 62 61 73  8d04eb",    "bas
3050: 22 20 3d 3e 20 22 39 34 35 64 62 37 22 2c 20 20  " => "945db7",  
3060: 20 20 22 70 68 70 22 20 3d 3e 20 22 36 65 30 33    "php" => "6e03
3070: 63 31 22 2c 20 20 22 73 73 22 20 3d 3e 20 22 31  c1",  "ss" => "1
3080: 65 34 61 65 63 22 2c 0a 20 20 20 20 20 20 22 76  e4aec",.      "v
3090: 61 6c 61 22 20 3d 3e 20 22 33 35 38 31 62 61 22  ala" => "3581ba"
30a0: 2c 20 20 22 63 23 22 20 3d 3e 20 22 62 62 39 32  ,  "c#" => "bb92
30b0: 61 66 22 2c 20 20 20 20 20 22 70 79 22 20 3d 3e  af",     "py" =>
30c0: 20 22 33 35 38 31 62 61 22 2c 0a 20 20 20 29 3b   "3581ba",.   );
30d0: 0a 0a 20 20 20 2f 2f 20 69 66 20 6e 6f 20 70 72  ..   // if no pr
30e0: 65 64 65 66 69 6e 65 64 20 6e 61 6d 65 2c 20 66  edefined name, f
30f0: 61 6c 6c 20 62 61 63 6b 20 6f 6e 20 63 72 63 33  all back on crc3
3100: 32 28 29 20 6f 66 20 6c 61 6e 67 75 61 67 65 20  2() of language 
3110: 6e 61 6d 65 0a 20 20 20 72 65 74 75 72 6e 20 69  name.   return i
3120: 73 73 65 74 28 24 63 6f 6c 5b 24 6e 61 6d 65 5d  sset($col[$name]
3130: 29 0a 20 20 20 20 20 20 20 20 3f 20 24 63 6f 6c  ).        ? $col
3140: 5b 24 6e 61 6d 65 5d 0a 20 20 20 20 20 20 20 20  [$name].        
3150: 3a 20 73 75 62 73 74 72 28 73 74 72 5f 70 61 64  : substr(str_pad
3160: 28 64 65 63 68 65 78 28 63 72 63 33 32 28 24 6e  (dechex(crc32($n
3170: 61 6d 65 29 29 2c 20 36 2c 20 22 30 22 2c 20 53  ame)), 6, "0", S
3180: 54 52 5f 50 41 44 5f 4c 45 46 54 29 2c 20 30 2c  TR_PAD_LEFT), 0,
3190: 20 36 29 3b 0a 7d 0a 0a 0a 0a 2f 2a 2a 0a 20 2a   6);.}..../**. *
31a0: 20 46 65 74 63 68 20 67 65 6e 65 72 61 6c 20 72   Fetch general r
31b0: 65 70 6f 20 69 6e 66 6f 72 6d 61 74 69 6f 6e 20  epo information 
31c0: 66 6f 72 20 63 6f 6d 62 69 6e 65 64 20 6c 69 73  for combined lis
31d0: 74 0a 20 2a 20 20 c2 b7 20 66 6f 73 73 69 6c 5f  t. *  Β· fossil_
31e0: 6a 73 6f 6e 3a 3a 73 74 61 74 28 24 72 65 70 6f  json::stat($repo
31f0: 29 0a 20 2a 20 20 c2 b7 20 66 6f 73 73 69 6c 5f  ). *  Β· fossil_
3200: 6a 73 6f 6e 3a 3a 72 65 70 6f 72 74 e2 90 a3 6c  json::report␣l
3210: 69 73 74 28 24 72 65 70 6f 29 0a 20 2a 2f 0a 63  ist($repo). */.c
3220: 6c 61 73 73 20 66 6f 73 73 69 6c 5f 6a 73 6f 6e  lass fossil_json
3230: 20 7b 0a 20 20 20 20 2f 2f 20 66 65 74 63 68 20   {.    // fetch 
3240: 6a 73 6f 6e 20 62 6c 6f 62 0a 20 20 20 20 73 74  json blob.    st
3250: 61 74 69 63 20 66 75 6e 63 74 69 6f 6e 20 5f 5f  atic function __
3260: 63 61 6c 6c 53 74 61 74 69 63 28 24 66 75 6e 63  callStatic($func
3270: 2c 20 24 61 72 67 73 29 20 7b 0a 20 20 20 20 20  , $args) {.     
3280: 20 20 20 24 72 65 70 6f 20 3d 20 65 73 63 61 70     $repo = escap
3290: 65 73 68 65 6c 6c 61 72 67 28 24 61 72 67 73 5b  eshellarg($args[
32a0: 30 5d 29 3b 0a 20 20 20 20 20 20 20 20 72 65 74  0]);.        ret
32b0: 75 72 6e 20 6a 73 6f 6e 5f 64 65 63 6f 64 65 28  urn json_decode(
32c0: 60 2f 75 73 72 2f 6c 6f 63 61 6c 2f 62 69 6e 2f  `/usr/local/bin/
32d0: 66 6f 73 73 69 6c 20 6a 73 6f 6e 20 24 66 75 6e  fossil json $fun
32e0: 63 20 2d 52 20 24 72 65 70 6f 60 2c 20 54 52 55  c -R $repo`, TRU
32f0: 45 29 5b 22 70 61 79 6c 6f 61 64 22 5d 3b 0a 20  E)["payload"];. 
3300: 20 20 20 7d 0a 7d 0a 0a 0a 2f 2f 20 63 6f 6e 76     }.}...// conv
3310: 65 72 74 73 20 6a 75 73 74 20 73 70 61 63 65 73  erts just spaces
3320: 2c 20 23 20 61 6e 64 20 3f 20 2d 20 6c 65 61 76  , # and ? - leav
3330: 65 73 20 70 61 74 68 73 20 61 6c 6f 6e 65 0a 66  es paths alone.f
3340: 75 6e 63 74 69 6f 6e 20 62 61 73 69 63 5f 75 72  unction basic_ur
3350: 6c 65 6e 63 6f 64 65 28 24 73 29 20 7b 0a 20 20  lencode($s) {.  
3360: 20 20 72 65 74 75 72 6e 20 73 74 72 74 72 28 24    return strtr($
3370: 73 2c 20 61 72 72 61 79 28 22 20 22 3d 3e 22 2b  s, array(" "=>"+
3380: 22 2c 20 22 2b 22 3d 3e 22 25 32 42 22 2c 20 22  ", "+"=>"%2B", "
3390: 23 22 3d 3e 22 25 32 33 22 2c 20 22 3f 22 3d 3e  #"=>"%23", "?"=>
33a0: 22 25 33 46 22 29 29 3b 0a 7d 0a 0a 0a 0a 2f 2f  "%3F"));.}....//
33b0: 20 72 65 70 6c 61 63 65 20 27 24 76 61 72 6e 61   replace '$varna
33c0: 6d 65 27 20 72 65 66 65 72 65 6e 63 65 73 20 69  me' references i
33d0: 6e 20 73 74 72 69 6e 67 20 77 69 74 68 20 76 61  n string with va
33e0: 6c 75 65 73 20 66 72 6f 6d 20 61 72 72 61 79 2c  lues from array,
33f0: 20 61 6e 64 20 65 73 63 61 70 65 20 69 74 73 20   and escape its 
3400: 76 61 6c 75 65 0a 66 75 6e 63 74 69 6f 6e 20 69  value.function i
3410: 6e 74 65 72 70 6f 6c 61 74 65 5f 76 61 72 28 24  nterpolate_var($
3420: 73 74 72 69 6e 67 2c 20 24 72 6f 77 2c 20 24 65  string, $row, $e
3430: 73 63 61 70 65 29 20 7b 0a 20 20 20 20 72 65 74  scape) {.    ret
3440: 75 72 6e 20 70 72 65 67 5f 72 65 70 6c 61 63 65  urn preg_replace
3450: 5f 63 61 6c 6c 62 61 63 6b 28 0a 20 20 20 20 20  _callback(.     
3460: 20 20 20 22 2f 5b 5c 24 5d 28 5c 77 2b 29 2f 22     "/[\$](\w+)/"
3470: 2c 0a 20 20 20 20 20 20 20 20 66 75 6e 63 74 69  ,.        functi
3480: 6f 6e 20 28 24 6d 61 74 63 68 29 20 75 73 65 20  on ($match) use 
3490: 28 24 72 6f 77 2c 20 24 65 73 63 61 70 65 29 20  ($row, $escape) 
34a0: 7b 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65  {.            re
34b0: 74 75 72 6e 20 24 65 73 63 61 70 65 28 24 72 6f  turn $escape($ro
34c0: 77 5b 24 6d 61 74 63 68 5b 31 5d 5d 29 3b 0a 20  w[$match[1]]);. 
34d0: 20 20 20 20 20 20 20 7d 2c 0a 20 20 20 20 20 20         },.      
34e0: 20 20 24 73 74 72 69 6e 67 0a 20 20 20 20 29 3b    $string.    );
34f0: 0a 7d 0a 0a 0a 2f 2f 20 72 65 74 72 69 65 76 65  .}...// retrieve
3500: 20 47 2b 2f 46 42 2f 54 77 2f 52 64 2f 65 74 63   G+/FB/Tw/Rd/etc
3510: 2e 20 62 61 63 6b 6c 69 6e 6b 20 63 6f 75 6e 74  . backlink count
3520: 0a 66 75 6e 63 74 69 6f 6e 20 73 6f 63 69 61 6c  .function social
3530: 5f 6d 65 64 69 61 5f 6c 69 6e 6b 73 5f 63 6f 75  _media_links_cou
3540: 6e 74 28 24 72 65 70 6f 5f 66 6e 2c 20 24 64 62  nt($repo_fn, $db
3550: 29 20 7b 0a 20 20 20 69 6e 69 5f 73 65 74 28 22  ) {.   ini_set("
3560: 75 73 65 72 5f 61 67 65 6e 74 22 2c 20 22 4d 6f  user_agent", "Mo
3570: 7a 69 6c 6c 61 2f 35 2e 30 20 28 66 6f 73 73 69  zilla/5.0 (fossi
3580: 6c 2d 73 74 61 74 73 2d 74 61 62 6c 65 2f 30 2e  l-stats-table/0.
3590: 39 3b 20 55 3b 20 50 48 50 29 22 29 3b 0a 0a 20  9; U; PHP)");.. 
35a0: 20 20 24 75 72 6c 20 3d 20 72 65 70 6f 5f 68 6f    $url = repo_ho
35b0: 6d 65 70 61 67 65 28 24 72 65 70 6f 5f 66 6e 2c  mepage($repo_fn,
35c0: 20 24 64 62 29 3b 0a 20 20 20 70 72 69 6e 74 20   $db);.   print 
35d0: 22 46 65 74 63 68 20 73 6f 63 69 61 6c 20 6d 65  "Fetch social me
35e0: 64 69 61 20 62 61 63 6b 6c 69 6e 6b 20 63 6f 75  dia backlink cou
35f0: 6e 74 20 66 6f 72 20 24 75 72 6c 5c 6e 22 3b 0a  nt for $url\n";.
3600: 0a 20 20 20 72 65 74 75 72 6e 20 69 6e 74 76 61  .   return intva
3610: 6c 28 0a 20 20 20 20 20 61 72 72 61 79 5f 73 75  l(.     array_su
3620: 6d 28 0a 20 20 20 20 20 20 20 6a 73 6f 6e 5f 64  m(.       json_d
3630: 65 63 6f 64 65 28 0a 20 20 20 20 20 20 20 20 20  ecode(.         
3640: 66 69 6c 65 5f 67 65 74 5f 63 6f 6e 74 65 6e 74  file_get_content
3650: 73 28 22 68 74 74 70 3a 2f 2f 61 70 69 2e 69 6e  s("http://api.in
3660: 63 6c 75 64 65 2d 6f 6e 63 65 2e 6f 72 67 2f 6c  clude-once.org/l
3670: 69 6e 6b 73 2f 73 6f 63 69 61 6c 2e 61 6a 61 78  inks/social.ajax
3680: 2e 70 68 70 3f 75 72 6c 3d 24 75 72 6c 22 29 2c  .php?url=$url"),
3690: 0a 20 20 20 20 20 20 20 20 20 54 52 55 45 0a 20  .         TRUE. 
36a0: 20 20 20 20 20 20 29 0a 20 20 20 20 20 29 0a 20        ).     ). 
36b0: 20 20 29 3b 0a 7d 0a 0a 2f 2f 20 75 73 65 20 50    );.}..// use P
36c0: 55 42 4c 49 43 5f 55 52 4c 20 6f 72 20 63 6f 6e  UBLIC_URL or con
36d0: 66 69 67 20 60 68 6f 6d 65 70 61 67 65 60 20 66  fig `homepage` f
36e0: 72 6f 6d 20 44 42 2c 20 73 65 74 20 76 69 61 20  rom DB, set via 
36f0: 60 49 4e 53 45 52 54 20 49 4e 54 4f 20 63 6f 6e  `INSERT INTO con
3700: 66 69 67 20 56 41 4c 55 45 53 20 28 27 68 6f 6d  fig VALUES ('hom
3710: 65 70 61 67 65 27 2c 27 68 74 74 70 3a 2f 2f 65  epage','http://e
3720: 78 61 6d 70 6c 65 2e 63 6f 6d 2f 27 2c 6e 6f 77  xample.com/',now
3730: 28 29 29 3b 60 0a 66 75 6e 63 74 69 6f 6e 20 72  ());`.function r
3740: 65 70 6f 5f 68 6f 6d 65 70 61 67 65 28 24 69 64  epo_homepage($id
3750: 2c 20 24 64 62 29 20 7b 0a 20 20 20 20 69 66 20  , $db) {.    if 
3760: 28 24 72 20 3d 20 24 64 62 2d 3e 71 75 65 72 79  ($r = $db->query
3770: 28 22 53 45 4c 45 43 54 20 76 61 6c 75 65 20 46  ("SELECT value F
3780: 52 4f 4d 20 63 6f 6e 66 69 67 20 57 48 45 52 45  ROM config WHERE
3790: 20 6e 61 6d 65 20 49 4e 20 28 27 68 6f 6d 65 70   name IN ('homep
37a0: 61 67 65 27 2c 20 27 70 72 6f 6a 65 63 74 2d 68  age', 'project-h
37b0: 6f 6d 65 70 61 67 65 27 29 22 29 0a 20 20 20 20  omepage')").    
37c0: 61 6e 64 20 24 75 72 6c 20 3d 20 24 72 2d 3e 66  and $url = $r->f
37d0: 65 74 63 68 43 6f 6c 75 6d 6e 28 30 29 29 0a 20  etchColumn(0)). 
37e0: 20 20 20 7b 0a 20 20 20 20 20 20 20 20 72 65 74     {.        ret
37f0: 75 72 6e 20 24 75 72 6c 3b 0a 20 20 20 20 7d 0a  urn $url;.    }.
3800: 20 20 20 20 65 6c 73 65 20 7b 0a 20 20 20 20 20      else {.     
3810: 20 20 20 72 65 74 75 72 6e 20 75 72 6c 65 6e 63     return urlenc
3820: 6f 64 65 28 73 70 72 69 6e 74 66 28 50 55 42 4c  ode(sprintf(PUBL
3830: 49 43 5f 55 52 4c 2c 20 24 69 64 29 29 3b 0a 20  IC_URL, $id));. 
3840: 20 20 20 7d 0a 7d 0a 0a 0a 0a                       }.}....