Check-in [5066f4ec9f]
Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Generates a "common-repo.json" list from specified files in a fossil repository. (Used with a glob param like "/repo.json/REPO/files/*.py" to slice out interesting meta information.) |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
5066f4ec9f8ad6d3eea94542c0d31de4 |
User & Date: | mario 2016-09-25 17:48:26 |
Context
2018-05-19
| ||
13:18 | Trivial ReadTheDocs theme port; documentation/wiki-only template. Does not embed the massive CSS theme, but binds it externally from media.readthedocs,, check-in: 17217f14b5 user: mario tags: trunk | |
2016-09-25
| ||
17:48 | Generates a "common-repo.json" list from specified files in a fossil repository. (Used with a glob param like "/repo.json/REPO/files/*.py" to slice out interesting meta information.) check-in: 5066f4ec9f user: mario tags: trunk | |
2016-09-04
| ||
12:37 | Fixed googlecode links to github raw CDN. check-in: 7cafda9321 user: mario tags: trunk | |
Changes
Added features/pluginconf-repo.php.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 | <?php /** * api: php * type: handler * title: Common.json repo list * description: Create json dict of selected fossil repository contents * version: 0.1 * depends: fossil:json * doc: http://fossil.include-once.org/streamtuner2/wiki?name=plugin+meta+data * https://pypi.python.org/pypi/pluginconf/ * * Generates a „common-repo“-json list for files from a fossil repository. * * · Used for streamtuner2 plugin manager - to refresh module list directly * from repositories. * * · Extracts key:value comments as seen above. * * · Accepts PATH_INFO specifiers using glob patterns `/reponame/src*dir/*.ext`. * * · You'll probably want to hook it beside the actual fossil server, using * using a RewriteRule or ScriptAliasMatch. * e.g. * RewriteRule ^(/?)repo.json/(.+)$ $1plugins.php/$2 * * · Each entry carries a faux $type, $dist and $file references, and all * extracted meta fields, no docs. (= The crudest implementation so far.) * */ // run $p = opts() and gen($p); /** * Request params * [WHITELIST] * * · assert alphanumeric repository.fossil name * · limit allowed glob specifiers and file paths * */ function opts() { preg_match( "~^ /(?<repo>[\w-]+) # fossil basename /(?<glob> (?: [/\w.-]+ # basedir prefix [*]? ){0,3} # up to 3 *-glob segments ) $~x", $_SERVER["PATH_INFO"], $groups ); return $groups; } /** * Handler * [MAIN] * * · invoked with $repo="projectname" and $glob="lib/*.src" * · scans files, converts into repo.json, and outputs that * */ function gen($kwargs) { extract($kwargs); header("Content-Type: json/common-repo; x-ver=0"); exit( json_encode( common_repo( query_files("/fossil.d/$repo.fossil", $glob), $repo ), JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT ) ); } /** * Read glob-specified files from repository * [EXEC] * * · scans fossil repos for given filespec, e.g. "lib/plugins/*.py" * · returns just first 2K from content * */ function query_files($R, $glob) { $r = []; if (!file_exists($R)) { return $r; } // loop through files $glob = escapeshellarg(preg_replace("~[^/\w.*-]~", "", $glob)); $sql = escapeshellarg(" SELECT name AS name, uuid, SUBSTR(HEX(CONTENT(uuid)),1,2048) AS content FROM (SELECT filename.name, bf.uuid, filename.fnid FROM filename JOIN mlink ON mlink.fnid=filename.fnid JOIN blob bf ON bf.rid=mlink.fid JOIN event ON event.objid=mlink.mid WHERE (mlink.fnid NOT IN (SELECT fnid FROM mlink WHERE fid=0)) AND filename.name GLOB $glob GROUP BY filename.name ORDER BY event.mtime DESC ) "); // Just retrieve as CSV list from fossil directly, // instead of using PDO handle and `fossil artifact` on each UUID $pipe = popen("fossil sqlite -R $R \".mode csv\" $sql", "rb"); while ($row = fgetcsv($pipe, 0, ",", '"', '"')) { // skip emtpy rows if (count($row) != 3) { continue; } // add file $r[$row[0]] = hex2bin($row[2]); } return $r; } /** * Convert attributes into list * [TRANSFORM] * * · from $fn=>$meta dict to [$pkg, $pkg] list * */ function common_repo($files, $R) { // extend each PMD key:value list $repo = meta_extract($files); foreach ($repo as $fn => $meta) { // basename, extension $id = strtok(basename($fn), "."); $ext = pathinfo($fn, PATHINFO_EXTENSION); $dir = basename(dirname($fn)); // add some stub fields $meta += [ "type" => "unknown", "api" => "$R", "title" => null, "description" => null, "version" => null, ]; // common repo fields carry a `$` sigil $repo[$fn] = array_merge( [ "\$name" => $id, # package basename "\$type" => "x-$ext", # e.g. "deb", "rpm" or "x-src" "\$dist" => "app/$R/$dir", # e.g. "trusty/main" or "app:pkg:part" "\$file" => "http://fossil.include-once.org/$R/cat/$fn", # resource locator ], $meta ); } return array_values($repo); } /** * Extract plugin meta data * [REGEX] * * · really just looks for scalar key:value lines * · comment/docs are not extracted * */ function meta_extract($files) { foreach ($files as $fn=>$cnt) { preg_match_all("~\s*(?:#|//|[*])\s*(\w+):\h*(.+)~m", $cnt, $fields); $meta = array_combine($fields[1], $fields[2]); $meta = array_change_key_case($meta); $files[$fn] = $meta; } return $files; } |