db = new DB_SQLite3($repo_file, SQLITE3_OPEN_READONLY); $this->db->createFunction('repo_url', [$this, 'getURL']); $this->url = $url; } public function getURL($uri = '') { return $this->url . $uri; } public function listUnversioned() { return $this->db->getGrouped('SELECT uvid, name, sz AS size, mtime, hash, repo_url(\'uv/\' || name) AS url FROM unversioned WHERE hash IS NOT NULL ORDER BY mtime DESC;'); } public function getTicketsStatus() { return $this->db->get('SELECT DISTINCT status FROM ticket;'); } public function getTicketsTypes() { return $this->db->get('SELECT DISTINCT type FROM ticket;'); } public function listTickets(array $filters = []) { $query = 'SELECT *, repo_url(\'tktview?name=\' || substr(tkt_uuid, 1, 10)) AS url FROM ticket WHERE 1'; $args = []; foreach ($filters as $field => $value) { $query .= ' AND ' . $field . ' = ?'; $args[] = $value; } $query .= ' ORDER BY tkt_mtime DESC;'; return $this->db->get($query, $args); } public function bundlePreview($file, $force = false) { if (!is_readable($file)) { throw new \RuntimeException('Cannot read file: ' . $file); } try { $this->db->preparedQuery('ATTACH ? AS b1;', [$file]); $a = $this->db->prepare('SELECT bcname, bcvalue FROM b1.bconfig LIMIT 1;'); $b = $this->db->prepare('SELECT blobid, uuid, sz, delta, notes, data FROM b1.bblob;'); if (!$a || !$b) { return false; } } catch (\Exception $e) { $this->db->exec('DETACH b1;'); throw new \RuntimeException('Not a valid bundle file: ' . $e->getMessage(), 0, $e); } /* Only import a bundle that was generated from a repo with the same ** project code, unless the --force flag is true */ if (!$force) { $exists = $this->db->firstColumn('SELECT 1 FROM config, bconfig WHERE config.name = \'project-code\' AND bconfig.bcname = \'project-code\' AND config.value = bconfig.bcvalue;'); if (!$exists) { $this->db->exec('DETACH b1;'); throw new \RuntimeException('project-code in the bundle does not match the repository project code.'); } } /* If the bundle contains deltas with a basis that is external to the ** bundle and those external basis files are missing from the local ** repo, then the delta encodings cannot be decoded and the bundle cannot ** be extracted. */ $missing_deltas = $this->db->firstColumn('SELECT group_concat(substr(delta,1,10), \' \') FROM bblob WHERE typeof(delta) = \'text\' AND length(delta) >= ? AND NOT EXISTS(SELECT 1 FROM blob WHERE uuid = bblob.delta)', self::HNAME_MIN); if ($missing_deltas) { $this->db->exec('DETACH b1;'); throw new \RuntimeException('delta basis artifacts not found in repository: ' . $missing_deltas); } $this->db->begin(); $this->db->exec('CREATE TEMP TABLE bix( blobid INTEGER PRIMARY KEY, delta INTEGER ); CREATE INDEX bixdelta ON bix(delta); INSERT INTO bix(blobid,delta) SELECT blobid, CASE WHEN typeof(delta)==\'integer\' THEN delta ELSE 0 END FROM bblob WHERE NOT EXISTS(SELECT 1 FROM blob WHERE uuid=bblob.uuid AND size>=0); CREATE TEMP TABLE got(rid INTEGER PRIMARY KEY ON CONFLICT IGNORE);'); /* manifest_crosslink_begin(); bundle_import_elements(0, 0, isPriv); manifest_crosslink_end(0); describe_artifacts_to_stdout("IN got", "Imported content:"); */ $this->db->commit(); // gzuncompress on each delta $this->db->exec('DETACH b1;'); } }