SecBSD's official ports repository
This commit is contained in:
commit
2c0afcbbf3
64331 changed files with 5339189 additions and 0 deletions
66
databases/sqlports/Makefile
Normal file
66
databases/sqlports/Makefile
Normal file
|
@ -0,0 +1,66 @@
|
|||
CATEGORIES = databases
|
||||
V = 7.39
|
||||
DISTNAME = sqlports-$V
|
||||
DISTFILES =
|
||||
COMMENT-main = sqlite database of ports
|
||||
COMMENT-list = full list of pkgpaths in ports
|
||||
MAINTAINER = Marc Espie <espie@openbsd.org>
|
||||
PKGNAME-list = portslist-$V
|
||||
|
||||
PERMIT_PACKAGE = Yes
|
||||
MULTI_PACKAGES = -main -list
|
||||
|
||||
DBNAME = sqlports
|
||||
SQLCACHE = ${DBNAME}_cache.sql
|
||||
SQLVIEWS = ${DBNAME}_views.sql
|
||||
DBS = ${DBNAME}.list ${DBNAME} ports-INDEX ${SQLCACHE}
|
||||
BUILD_DEPENDS = databases/p5-DBD-SQLite \
|
||||
databases/sqlite3
|
||||
RUN_DEPENDS-main = databases/sqlite3
|
||||
FLAVORS = nonstrict
|
||||
FLAVOR =
|
||||
|
||||
.if ${FLAVOR:Mnonstrict}
|
||||
STRICT =
|
||||
.else
|
||||
STRICT =-s
|
||||
.endif
|
||||
|
||||
# for debugging the ports tree purposes, start at this dir
|
||||
#STARTDIR = -S games/stepmania
|
||||
SCRIPTS = print-ports-index show-reverse-deps rebuild-sqlports-cache
|
||||
MANS = show-reverse-deps.1 sqlports.5
|
||||
|
||||
do-build:
|
||||
@PORTSDIR=${PORTSDIR} ${MAKE_ENV} perl ${FILESDIR}/mksqlitedb -v -V $V -p ${WRKBUILD}/ouch ${STRICT} -C ${WRKBUILD}/${SQLCACHE} -w ${WRKBUILD}/${SQLVIEWS} ${STARTDIR} ${WRKBUILD}/${DBNAME}
|
||||
@if test -s ${WRKBUILD}/ouch; then \
|
||||
cat ${WRKBUILD}/ouch; \
|
||||
exit 1; \
|
||||
fi
|
||||
cd ${WRKBUILD} && sqlite3 <${SQLCACHE} ${DBNAME}
|
||||
|
||||
alter-tables:
|
||||
@${MAKE_ENV} ${SUDO} -u ${BUILD_USER} perl ${FILESDIR}/rebuild_schema -v -V $V ${WRKBUILD/${DBNAME}
|
||||
@${SUDO} -u ${BUILD_USER} ${MAKE} post-build
|
||||
|
||||
post-build:
|
||||
@cd ${WRKBUILD} && ${LOCALBASE}/bin/sqlite3 ${DBNAME} 'select min(_paths.fullpkgpath) from _paths join _ports on _paths.id=_ports.fullpkgpath where _ports.static_plist=1 group by fullpkgname order by _paths.fullpkgpath' >${DBNAME}.list
|
||||
@cd ${WRKBUILD} && sh ${FILESDIR}/scripts/print-ports-index ${DBNAME} >ports-INDEX
|
||||
|
||||
do-install:
|
||||
if [[ `wc -l < ${WRKBUILD}/ports-INDEX` -le 666 ]]; then echo "Unexpectedly short file."; exit 1; fi
|
||||
${INSTALL_PROGRAM_DIR} ${PREFIX}/bin
|
||||
.for s in ${SCRIPTS}
|
||||
@${SUBST_PROGRAM} ${FILESDIR}/scripts/$s ${PREFIX}/bin/$s
|
||||
.endfor
|
||||
.for s in ${MANS}
|
||||
@${SUBST_MAN} ${FILESDIR}/man/$s ${PREFIX}/man/man${s:E}/$s
|
||||
.endfor
|
||||
@for i in ${DBS}; do \
|
||||
${INSTALL_DATA} ${WRKBUILD}/$$i ${PREFIX}/share; \
|
||||
done
|
||||
|
||||
NO_TEST = Yes
|
||||
NO_CHECKSUM = Yes
|
||||
|
||||
.include <bsd.port.mk>
|
176
databases/sqlports/files/Info.pm
Normal file
176
databases/sqlports/files/Info.pm
Normal file
|
@ -0,0 +1,176 @@
|
|||
# $OpenBSD: Info.pm,v 1.38 2023/06/16 04:54:20 espie Exp $
|
||||
#
|
||||
# Copyright (c) 2012 Marc Espie <espie@openbsd.org>
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# example script that shows how to store all variable values into a
|
||||
# database, using SQLite for that purpose.
|
||||
#
|
||||
# usage: cd /usr/ports && make dump-vars |mksqlitedb
|
||||
|
||||
use v5.36;
|
||||
use Var;
|
||||
|
||||
package Info;
|
||||
our $vars = {
|
||||
AUTOCONF_VERSION => 'AutoVersionVar',
|
||||
AUTOMAKE_VERSION => 'AutoVersionVar',
|
||||
BROKEN => 'BrokenVar',
|
||||
BUILD_DEPENDS => 'BuildDependsVar',
|
||||
CATEGORIES => 'CategoriesVar',
|
||||
COMES_WITH => 'DefinedVar',
|
||||
COMMENT => 'AnyVar',
|
||||
COMPILER_LINKS => 'CompilerLinksVar',
|
||||
CONFIGURE_ARGS => 'ConfigureArgsVar',
|
||||
CONFIGURE_STYLE => 'ConfigureVar',
|
||||
DEBUG_CONFIGURE_ARGS => 'DebugConfigureArgsVar',
|
||||
DEBUG_PACKAGES => 'DebugPackagesVar',
|
||||
DESCR => 'DescrVar',
|
||||
DISTFILES => 'SupdistfilesVar',
|
||||
DPB_PROPERTIES => 'DPBPropertiesVar',
|
||||
PATCHFILES => 'PatchfilesVar',
|
||||
DISTNAME => 'AnyVar',
|
||||
DIST_SUBDIR => 'DefinedVar',
|
||||
EPOCH => 'AnyVar',
|
||||
FLAVORS => 'FlavorsVar',
|
||||
FULLPKGNAME => 'FullpkgnameVar',
|
||||
GH_ACCOUNT => 'DefinedVar',
|
||||
GH_COMMIT => 'DefinedVar',
|
||||
GH_PROJECT => 'DefinedVar',
|
||||
GH_TAGNAME => 'DefinedVar',
|
||||
HOMEPAGE => 'AnyVar',
|
||||
IGNORE => 'DefinedVar',
|
||||
IS_INTERACTIVE => 'AnyVar',
|
||||
LIB_DEPENDS => 'LibDependsVar',
|
||||
MAINTAINER=> 'EmailVar',
|
||||
MAKEFILE_LIST => 'MakefilesListVar',
|
||||
MASTER_SITES => 'MasterSitesVar',
|
||||
MASTER_SITES0 => 'MasterSitesVar',
|
||||
MASTER_SITES1 => 'MasterSitesVar',
|
||||
MASTER_SITES2 => 'MasterSitesVar',
|
||||
MASTER_SITES3 => 'MasterSitesVar',
|
||||
MASTER_SITES4=> 'MasterSitesVar',
|
||||
MASTER_SITES5 => 'MasterSitesVar',
|
||||
MASTER_SITES6 => 'MasterSitesVar',
|
||||
MASTER_SITES7 => 'MasterSitesVar',
|
||||
MASTER_SITES8 => 'MasterSitesVar',
|
||||
MASTER_SITES9=> 'MasterSitesVar',
|
||||
MODULES => 'ModulesVar',
|
||||
MULTI_PACKAGES => 'MultiVar',
|
||||
NO_BUILD => 'YesNoVar',
|
||||
NO_TEST => 'YesNoVar',
|
||||
NOT_FOR_ARCHS => 'NotForArchListVar',
|
||||
ONLY_FOR_ARCHS => 'OnlyForArchListVar',
|
||||
PERMIT_DISTFILES=> 'YesKeyVar',
|
||||
PERMIT_PACKAGE=> 'YesKeyVar',
|
||||
PKGNAME => 'AnyVar',
|
||||
PKGSPEC => 'AnyVar',
|
||||
PKGSTEM => 'AnyVar',
|
||||
PREFIX => 'PrefixKeyVar',
|
||||
PKG_ARCH => 'ArchKeyVar',
|
||||
PORTROACH => 'DefinedVar',
|
||||
PORTROACH_COMMENT => 'DefinedVar',
|
||||
PSEUDO_FLAVOR => 'AnyVar',
|
||||
PSEUDO_FLAVORS => 'PseudoFlavorsVar',
|
||||
TEST_DEPENDS => 'TestDependsVar',
|
||||
TEST_IS_INTERACTIVE => 'AnyVar',
|
||||
REVISION => 'AnyVar',
|
||||
README => 'ReadmeVar',
|
||||
RUN_DEPENDS => 'RunDependsVar',
|
||||
SEPARATE_BUILD => 'YesKeyVar',
|
||||
SHARED_LIBS => 'SharedLibsVar',
|
||||
STATIC_PLIST => 'StaticPlistVar',
|
||||
SUBPACKAGE => 'DefinedVar',
|
||||
SUBST_VARS => 'SubstVar',
|
||||
SUPDISTFILES => 'SupdistfilesVar',
|
||||
TARGETS => 'TargetsVar',
|
||||
UPDATE_PLIST_ARGS => 'DefinedVar',
|
||||
USE_GMAKE => 'YesNoVar',
|
||||
USE_GROFF => 'YesNoVar',
|
||||
USE_LIBTOOL => 'YesNoGnuVar',
|
||||
USE_NOBTCFI => 'YesNoVar',
|
||||
USE_NOEXECONLY => 'YesNoVar',
|
||||
USE_WXNEEDED => 'YesNoSpecialVar',
|
||||
COMPILER => 'DefinedVar',
|
||||
COMPILER_LANGS => 'DefinedVar',
|
||||
WANTLIB => 'WantlibVar',
|
||||
FIX_EXTRACT_PERMISSIONS => 'YesNoVar',
|
||||
USE_LLD => 'YesNoVar',
|
||||
PKGPATHS => 'PkgPathsVar',
|
||||
# XXX those variables are part of the dump for dpb, but really should
|
||||
# not end up in sqlports. But make sure we know about them.
|
||||
BUILD_PACKAGES => 'IgnoredVar',
|
||||
CHECKSUM_FILE => 'IgnoredVar',
|
||||
FETCH_MANUALLY => 'IgnoredVar',
|
||||
FLAVOR => 'IgnoredVar',
|
||||
MISSING_FILES => 'IgnoredVar',
|
||||
FIX_CRLF_FILES => 'CRLFFiles',
|
||||
};
|
||||
|
||||
my @indexed = qw(FULLPKGNAME RUN_DEPENDS LIB_DEPENDS IGNORE
|
||||
COMMENT PKGNAME ONLY_FOR_ARCHS NOT_FOR_ARCHS PKGSPEC PKGSTEM PREFIX
|
||||
PERMIT_PACKAGE_FTP PERMIT_PACKAGE_CDROM WANTLIB CATEGORIES DESCR
|
||||
EPOCH REVISION STATIC_PLIST PKG_ARCH);
|
||||
|
||||
my $indexed = {map {($_, 1)} @indexed};
|
||||
our $unknown = {};
|
||||
|
||||
sub is_indexed($class, $name)
|
||||
{
|
||||
return $indexed->{$name};
|
||||
}
|
||||
|
||||
sub new($class, $p)
|
||||
{
|
||||
bless {path => $p, vars => {}}, $class;
|
||||
}
|
||||
|
||||
sub create($self, $var, $value, $arch, $path)
|
||||
{
|
||||
my $k = $var;
|
||||
if (defined $arch) {
|
||||
$k .= "-$arch";
|
||||
}
|
||||
if (defined $vars->{$var}) {
|
||||
$self->{vars}{$k} = $vars->{$var}->new($var, $value, $arch,
|
||||
$path);
|
||||
} else {
|
||||
$unknown->{$k} //= $path;
|
||||
}
|
||||
}
|
||||
|
||||
sub variables($self)
|
||||
{
|
||||
return values %{$self->{vars}};
|
||||
}
|
||||
|
||||
sub value($self, $name)
|
||||
{
|
||||
if (defined $self->{vars}{$name}) {
|
||||
return $self->{vars}{$name}->value;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
sub reclaim($self)
|
||||
{
|
||||
my $n = {};
|
||||
for my $k (qw(SUBPACKAGE FLAVOR)) {
|
||||
$n->{$k} = $self->{vars}{$k};
|
||||
}
|
||||
$self->{vars} = $n;
|
||||
}
|
||||
|
||||
1;
|
306
databases/sqlports/files/Inserter.pm
Normal file
306
databases/sqlports/files/Inserter.pm
Normal file
|
@ -0,0 +1,306 @@
|
|||
#! /usr/bin/perl
|
||||
# $OpenBSD: Inserter.pm,v 1.42 2023/06/16 04:54:20 espie Exp $
|
||||
#
|
||||
# Copyright (c) 2006-2010 Marc Espie <espie@openbsd.org>
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
use v5.36;
|
||||
use Sql;
|
||||
|
||||
package Inserter;
|
||||
# this is the object to use to put stuff into the db...
|
||||
sub new($class, $db, $i, $verbose, $create)
|
||||
{
|
||||
$db->do("PRAGMA foreign_keys=ON");
|
||||
bless {
|
||||
db => $db,
|
||||
transaction => 0,
|
||||
threshold => $i,
|
||||
vars => {},
|
||||
created => {},
|
||||
create => $create,
|
||||
errors => [],
|
||||
done => {},
|
||||
todo => {},
|
||||
verbose => $verbose,
|
||||
}, $class;
|
||||
}
|
||||
|
||||
# $self->add_error($msg)
|
||||
sub add_error($, $)
|
||||
{
|
||||
}
|
||||
|
||||
sub current_path($self)
|
||||
{
|
||||
return $self->{current_path};
|
||||
}
|
||||
|
||||
sub create_tables($self, $vars)
|
||||
{
|
||||
my $t = $self->{ports_table} = Sql::Create::Table->new("_Ports");
|
||||
my $v = $self->{ports_view} = Sql::Create::View->new("Ports",
|
||||
origin => '_Ports');
|
||||
$self->create_path_table;
|
||||
# XXX sort it
|
||||
for my $i (sort keys %$vars) {
|
||||
$vars->{$i}->prepare_tables($self, $i);
|
||||
}
|
||||
|
||||
$t->sort;
|
||||
$self->{varlist} = [$t->column_names];
|
||||
$t->prepend(AnyVar->fullpkgpath);
|
||||
|
||||
$v->sort;
|
||||
$v->prepend(AnyVar->pathref);
|
||||
$self->create_meta;
|
||||
$self->create_schema;
|
||||
print '-'x50, "\n" if $self->{verbose};
|
||||
}
|
||||
|
||||
sub add_to_ports_table($self, @column)
|
||||
{
|
||||
$self->{ports_table}->add(@column);
|
||||
}
|
||||
|
||||
sub add_to_ports_view($self, @o)
|
||||
{
|
||||
$self->{ports_view}->add(@o);
|
||||
}
|
||||
|
||||
sub make_ordered_view($self, $class)
|
||||
{
|
||||
my $view = $self->view_name($class->table."_ordered");
|
||||
my @subselect = $class->subselect;
|
||||
my @select = (Sql::Column::View->new('FullPkgPath')->group_by,
|
||||
Sql::Column::View::Concat->new("Value"), $class->select);
|
||||
Sql::Create::View->new($view, origin => 'o')->add(
|
||||
Sql::With->new('o', origin => $self->table_name($class->table))
|
||||
->add(@subselect),
|
||||
@select);
|
||||
}
|
||||
|
||||
sub set($self, $ref)
|
||||
{
|
||||
$self->{ref} = $ref;
|
||||
}
|
||||
|
||||
sub db($self)
|
||||
{
|
||||
return $self->{db};
|
||||
}
|
||||
|
||||
sub last_id($self)
|
||||
{
|
||||
return $self->db->func('last_insert_rowid');
|
||||
}
|
||||
|
||||
sub insert_done($self)
|
||||
{
|
||||
$self->{transaction}++;
|
||||
}
|
||||
|
||||
sub new_sql($self, $sql)
|
||||
{
|
||||
my $n = $sql->name;
|
||||
return if defined $self->{created}{$n};
|
||||
$self->{created}{$n} = 1;
|
||||
my $drop = $sql->drop;
|
||||
# print "$drop\n" if $self->{verbose};
|
||||
$self->db->do($drop);
|
||||
my $request = $sql->stringize;
|
||||
print "$request\n" if $self->{verbose};
|
||||
$self->db->do($request);
|
||||
}
|
||||
|
||||
sub create_schema($self)
|
||||
{
|
||||
if ($self->{create}) {
|
||||
for my $t (Sql::Create->all_tables) {
|
||||
$self->new_sql($t);
|
||||
}
|
||||
for my $t (Sql::Create->all_tables) {
|
||||
my $i = $t->inserter;
|
||||
print $i, "\n";
|
||||
$self->{insert}{$t->name} = $self->prepare($i);
|
||||
}
|
||||
for my $i (Sql::Create->all_indices) {
|
||||
$self->new_sql($i);
|
||||
}
|
||||
}
|
||||
for my $v (Sql::Create->all_views) {
|
||||
$self->new_sql($v);
|
||||
}
|
||||
$self->commit_to_db;
|
||||
}
|
||||
|
||||
sub prepare($self, $s)
|
||||
{
|
||||
return $self->db->prepare($s);
|
||||
}
|
||||
|
||||
sub finish_port($self)
|
||||
{
|
||||
my @values = ($self->ref);
|
||||
for my $i (@{$self->{varlist}}) {
|
||||
push(@values, $self->{vars}{$i});
|
||||
}
|
||||
$self->insert('_Ports', @values);
|
||||
$self->{vars} = {};
|
||||
if ($self->{transaction} >= $self->{threshold}) {
|
||||
$self->commit_to_db;
|
||||
$self->{transaction} = 0;
|
||||
}
|
||||
}
|
||||
|
||||
sub add_to_port($self, $var, $value)
|
||||
{
|
||||
$self->{vars}{$var} = $value;
|
||||
}
|
||||
|
||||
sub ref($self)
|
||||
{
|
||||
return $self->{ref};
|
||||
}
|
||||
|
||||
sub insert($self, $table, @p)
|
||||
{
|
||||
$self->{insert}{$table}->execute(@p);
|
||||
$self->insert_done;
|
||||
}
|
||||
|
||||
sub add_var($self, $v)
|
||||
{
|
||||
$v->add($self);
|
||||
}
|
||||
|
||||
sub create_canonical_depends($self, $class)
|
||||
{
|
||||
my $t = $self->table_name($class->table);
|
||||
my $p = $self->table_name("Paths");
|
||||
Sql::Create::View->new("_canonical_depends", origin=>$t)->add(
|
||||
Sql::Column::View->new("FullPkgPath", origin=>"Id")
|
||||
->join(Sql::Join->new($p)
|
||||
->add(Sql::Equal->new("Canonical", "FullPkgPath"))),
|
||||
Sql::Column::View->new("DependsPath", origin=>"Canonical")
|
||||
->join(Sql::Join->new($p)
|
||||
->add(Sql::Equal->new("Id", "DependsPath"))),
|
||||
Sql::Column::View->new("Type"));
|
||||
|
||||
Sql::Create::View->new("canonical_depends", origin=>$t)->add(
|
||||
Sql::Column::View->new("FullPkgPath")
|
||||
->join(Sql::Join->new($p)
|
||||
->add(Sql::Equal->new("Canonical", "FullPkgPath"))),
|
||||
Sql::Column::View->new("DependsPath", origin=>"FullPkgPath")
|
||||
->join(Sql::Join->new($p)
|
||||
->add(Sql::Equal->new("Id", "DependsPath")),
|
||||
Sql::Join->new($p)
|
||||
->add(Sql::Equal->new("Id", "canonical"))),
|
||||
Sql::Column::View->new("Type"));
|
||||
}
|
||||
|
||||
sub commit_to_db($self)
|
||||
{
|
||||
$self->db->commit;
|
||||
}
|
||||
|
||||
sub table_name($class, $name)
|
||||
{
|
||||
return "_$name";
|
||||
}
|
||||
|
||||
sub view_name($class, $name)
|
||||
{
|
||||
return $name;
|
||||
}
|
||||
|
||||
sub adjust($self)
|
||||
{
|
||||
return $self->{adjust} //= $self->prepare("UPDATE _Paths set Canonical=? where Id=?");
|
||||
}
|
||||
|
||||
sub create_meta($)
|
||||
{
|
||||
Sql::Create::Table->new("Meta")->add(
|
||||
Sql::Column::Text->new("SchemaVersion"),
|
||||
Sql::Column::Text->new("Hash"),
|
||||
Sql::Column::CurrentDate->new("CreationDate"));
|
||||
}
|
||||
|
||||
sub create_path_table($)
|
||||
{
|
||||
my $t = "_Paths";
|
||||
my $v = "Paths";
|
||||
Sql::Create::Table->new($t)->add(
|
||||
Sql::Column::Key->new("Id")->noautoincrement,
|
||||
Sql::Column::Text->new("FullPkgPath")->notnull->unique,
|
||||
Sql::Column::Integer->new("PkgPath")->references($t),
|
||||
Sql::Column::Integer->new("Canonical")->references($t)->indexed);
|
||||
|
||||
Sql::Create::View->new($v, origin => $t)->add(
|
||||
Sql::Column::View->new("PathId", origin => "Id"),
|
||||
Sql::Column::View->new("FullPkgPath"),
|
||||
Sql::Column::View->new("PkgPath", origin => "FullPkgPath")
|
||||
->join(Sql::Join->new($t)->add(
|
||||
Sql::Equal->new("Id", "PkgPath"))),
|
||||
Sql::Column::View->new("Canonical", origin => "FullPkgPath")
|
||||
->join(Sql::Join->new($t)->add(
|
||||
Sql::Equal->new("Id", "Canonical")))
|
||||
);
|
||||
}
|
||||
|
||||
my $path_cache = {};
|
||||
my $newid = 1;
|
||||
sub find_pathkey($self, $key)
|
||||
{
|
||||
if (!defined $key or $key eq '') {
|
||||
say STDERR "Empty pathkey";
|
||||
return 0;
|
||||
}
|
||||
if (defined $path_cache->{$key}) {
|
||||
return $path_cache->{$key};
|
||||
}
|
||||
|
||||
# if none, we create one
|
||||
my $path = $key;
|
||||
$path =~ s/\,.*//;
|
||||
if ($path ne $key) {
|
||||
$path = $self->find_pathkey($path);
|
||||
} else {
|
||||
$path = $newid;
|
||||
}
|
||||
$self->insert('_Paths', $newid, $key, $path, $newid);
|
||||
my $r = $self->last_id;
|
||||
$path_cache->{$key} = $r;
|
||||
$newid++;
|
||||
return $r;
|
||||
}
|
||||
|
||||
sub add_path($self, $key, $alias)
|
||||
{
|
||||
$self->adjust->execute($path_cache->{$alias}, $path_cache->{$key});
|
||||
}
|
||||
|
||||
sub set_newkey($self, $key)
|
||||
{
|
||||
$self->set($self->find_pathkey($key));
|
||||
$self->{current_path} = $key;
|
||||
}
|
||||
|
||||
# $self->write_log($fh)
|
||||
sub write_log($, $)
|
||||
{
|
||||
}
|
||||
|
||||
1;
|
86
databases/sqlports/files/PkgPath.pm
Normal file
86
databases/sqlports/files/PkgPath.pm
Normal file
|
@ -0,0 +1,86 @@
|
|||
# ex:ts=8 sw=4:
|
||||
# $OpenBSD: PkgPath.pm,v 1.7 2023/06/15 12:53:07 espie Exp $
|
||||
#
|
||||
# Copyright (c) 2012 Marc Espie <espie@openbsd.org>
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
use v5.36;
|
||||
|
||||
my $ports1;
|
||||
|
||||
BEGIN {
|
||||
$ports1 = $ENV{PORTSDIR} || '/usr/ports';
|
||||
}
|
||||
use lib ("$ports1/infrastructure/lib");
|
||||
|
||||
use DPB::BasePkgPath;
|
||||
|
||||
package PkgPath;
|
||||
our @ISA = qw(DPB::BasePkgPath);
|
||||
use Info;
|
||||
|
||||
sub init($)
|
||||
{
|
||||
}
|
||||
|
||||
sub clone_properties($n, $o)
|
||||
{
|
||||
$n->{info} //= $o->{info};
|
||||
}
|
||||
|
||||
sub subpackage($self)
|
||||
{
|
||||
return $self->{info}->value('SUBPACKAGE');
|
||||
}
|
||||
|
||||
sub flavor($self)
|
||||
{
|
||||
my $value = $self->{info}->value('FLAVOR');
|
||||
$value =~ s/^\s+//;
|
||||
$value =~ s/\s+$//;
|
||||
my @l = split(/\s+/, $value);
|
||||
my %values = map {($_,1)} @l;
|
||||
|
||||
return \%values;
|
||||
}
|
||||
|
||||
# $class->equates($hash)
|
||||
sub equates($, $)
|
||||
{
|
||||
}
|
||||
|
||||
sub simplifies_to($self, $simpler, $walker)
|
||||
{
|
||||
$walker->{equivs}{$self->fullpkgpath} = $simpler->fullpkgpath;
|
||||
}
|
||||
|
||||
sub change_multi($path, $multi)
|
||||
{
|
||||
# make a tmp copy, non registered
|
||||
my $tmp = ref($path)->create($path->fullpkgpath);
|
||||
if ($multi eq '-main') {
|
||||
$tmp->{m} = undef;
|
||||
} else {
|
||||
$tmp->{m} = $multi;
|
||||
}
|
||||
return $tmp->normalize;
|
||||
}
|
||||
|
||||
sub break($path, $message)
|
||||
{
|
||||
$path->{parent} //= '?';
|
||||
say STDERR $path->fullpkgpath, "(", $path->{parent}, "):", $message;
|
||||
}
|
||||
|
||||
1;
|
977
databases/sqlports/files/Sql.pm
Normal file
977
databases/sqlports/files/Sql.pm
Normal file
|
@ -0,0 +1,977 @@
|
|||
#! /usr/bin/perl
|
||||
# $OpenBSD: Sql.pm,v 1.36 2023/06/15 14:33:13 espie Exp $
|
||||
#
|
||||
# Copyright (c) 2018 Marc Espie <espie@openbsd.org>
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# This does implement objects for an Sql Tree.
|
||||
|
||||
use v5.36;
|
||||
|
||||
package Sql::Object;
|
||||
sub new($class, $name, %rest)
|
||||
{
|
||||
my $o = \%rest;
|
||||
$o->{name} = $name;
|
||||
bless $o, $class;
|
||||
}
|
||||
|
||||
sub indent($self, $string, $plus)
|
||||
{
|
||||
$self->{level} //= 0;
|
||||
return ' 'x(($self->{level}+$plus)).$string;
|
||||
}
|
||||
|
||||
sub name($self)
|
||||
{
|
||||
return $self->{name};
|
||||
}
|
||||
|
||||
sub drop($self)
|
||||
{
|
||||
return "DROP ".$self->type." IF EXISTS ".$self->name;
|
||||
}
|
||||
|
||||
sub dump($self)
|
||||
{
|
||||
say $self->stringize;
|
||||
}
|
||||
|
||||
sub add($self, @p)
|
||||
{
|
||||
for my $o (@p) {
|
||||
$o->add_to($self);
|
||||
}
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub add_to($o, $c)
|
||||
{
|
||||
$o->{parent} = $c;
|
||||
push(@{$c->{$o->category}}, $o);
|
||||
}
|
||||
|
||||
sub prepend($self, @p)
|
||||
{
|
||||
for my $o (reverse @p) {
|
||||
$o->prepend_to($self);
|
||||
}
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub prepend_to($o, $c)
|
||||
{
|
||||
$o->{parent} = $c;
|
||||
unshift(@{$c->{$o->category}}, $o);
|
||||
}
|
||||
|
||||
sub is_table($)
|
||||
{
|
||||
0
|
||||
}
|
||||
|
||||
sub origin($self)
|
||||
{
|
||||
return $self->{origin};
|
||||
}
|
||||
|
||||
sub normalize($self, $v)
|
||||
{
|
||||
$v =~ tr/A-Z/a-z/;
|
||||
return $v;
|
||||
}
|
||||
|
||||
sub identify($self)
|
||||
{
|
||||
my $string = "object ".ref($self)." named ".$self->name;
|
||||
if (exists $self->{origin}) {
|
||||
$string .= " (from $self->{origin})";
|
||||
}
|
||||
if (defined $self->{parent}) {
|
||||
$string .= "(parent ".$self->{parent}->identify.")";
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
|
||||
sub is_view($)
|
||||
{
|
||||
0
|
||||
}
|
||||
|
||||
sub is_index($)
|
||||
{
|
||||
0
|
||||
}
|
||||
|
||||
package Sql::Create;
|
||||
our @ISA = qw(Sql::Object);
|
||||
|
||||
my $register;
|
||||
|
||||
sub stringize($self)
|
||||
{
|
||||
return "CREATE ".($self->{temp} ? "TEMP ": "").$self->type.
|
||||
" ".$self->name." ".join("\n", $self->contents);
|
||||
}
|
||||
|
||||
sub sort($self)
|
||||
{
|
||||
$self->{columns} = [ sort {$a->name cmp $b->name} @{$self->{columns}}];
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub all_tables($class)
|
||||
{
|
||||
return grep {$_->is_table} (sort {$a->name cmp $b->name} values %$register);
|
||||
}
|
||||
|
||||
sub all_views($class)
|
||||
{
|
||||
return grep {$_->is_view} (sort {$a->name cmp $b->name} values %$register);
|
||||
}
|
||||
|
||||
sub all_indices($class)
|
||||
{
|
||||
return grep {$_->is_index} (sort {$a->name cmp $b->name} values %$register);
|
||||
}
|
||||
|
||||
sub key($class, $name)
|
||||
{
|
||||
return $class->find($name)->{key};
|
||||
}
|
||||
|
||||
sub find($class, $name)
|
||||
{
|
||||
return $register->{$class->normalize($name)};
|
||||
}
|
||||
|
||||
sub dump_all($class)
|
||||
{
|
||||
for my $v (values %$register) {
|
||||
$v->dump;
|
||||
}
|
||||
}
|
||||
|
||||
sub register($self)
|
||||
{
|
||||
$register->{$self->normalize($self->name)} = $self;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub add_column_names($self, $name)
|
||||
{
|
||||
my $o = $self->find($name);
|
||||
if (!defined $o) {
|
||||
# print STDERR $name, "\n";
|
||||
return;
|
||||
}
|
||||
$self->add_column_names_from($o);
|
||||
}
|
||||
|
||||
sub add_column_names_from($self, $o)
|
||||
{
|
||||
for my $c ($o->columns) {
|
||||
$self->{column_names}{$self->normalize($c->name)}++;
|
||||
}
|
||||
}
|
||||
|
||||
sub known_column($self, $name)
|
||||
{
|
||||
$name = $self->normalize($name);
|
||||
for my $c ($self->columns) {
|
||||
if ($self->normalize($c->name) eq $name) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub is_table_column($self, $table, $name)
|
||||
{
|
||||
my $t = $self->find($table);
|
||||
if (defined $t) {
|
||||
return $t->known_column($name);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
sub columns($self)
|
||||
{
|
||||
return @{$self->{columns}};
|
||||
}
|
||||
|
||||
sub column_names($self)
|
||||
{
|
||||
my @names;
|
||||
for my $c ($self->columns) {
|
||||
next if $c->is_key;
|
||||
push(@names, $c->name);
|
||||
}
|
||||
return @names;
|
||||
}
|
||||
|
||||
sub temp($self)
|
||||
{
|
||||
$self->{temp} = 1;
|
||||
return $self;
|
||||
}
|
||||
|
||||
package Sql::Create::Table;
|
||||
our @ISA = qw(Sql::Create);
|
||||
|
||||
sub type($)
|
||||
{
|
||||
"TABLE"
|
||||
}
|
||||
|
||||
sub is_table($)
|
||||
{
|
||||
1
|
||||
}
|
||||
|
||||
sub contents($self)
|
||||
{
|
||||
my @c;
|
||||
my @d;
|
||||
for my $col (@{$self->{columns}}) {
|
||||
if ($col->{want_index}) {
|
||||
Sql::Create::Index->new($self, $col);
|
||||
}
|
||||
push(@c, $col->stringize);
|
||||
if ($col->{is_constraint}) {
|
||||
push(@d, $col->name);
|
||||
}
|
||||
}
|
||||
if (@d > 0) {
|
||||
push(@c, "UNIQUE(".join(", ", @d). ")");
|
||||
}
|
||||
return "(". join(', ', @c).")";
|
||||
}
|
||||
|
||||
sub inserter($self)
|
||||
{
|
||||
my (@names, @placeholders);
|
||||
my $alt = $self->{ignore} ? " OR IGNORE" :
|
||||
($self->{noreplace} ? "" : " OR REPLACE");
|
||||
for my $c ($self->columns) {
|
||||
next if $c->is_key;
|
||||
push @names, $c->name;
|
||||
push @placeholders, $c->placeholder;
|
||||
}
|
||||
return "INSERT$alt INTO ".$self->name." (".
|
||||
join(', ', @names).") VALUES (".join(', ', @placeholders).")";
|
||||
}
|
||||
|
||||
sub noreplace($self)
|
||||
{
|
||||
$self->{noreplace} = 1;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub ignore($self)
|
||||
{
|
||||
$self->{ignore} = 1;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub new($class, @p)
|
||||
{
|
||||
$class->SUPER::new(@p)->register;
|
||||
}
|
||||
|
||||
package Sql::Create::View;
|
||||
our @ISA = qw(Sql::Create);
|
||||
sub type($)
|
||||
{
|
||||
"VIEW"
|
||||
}
|
||||
|
||||
sub is_view($)
|
||||
{
|
||||
1
|
||||
}
|
||||
|
||||
sub new($class, @p)
|
||||
{
|
||||
my $o = $class->SUPER::new(@p);
|
||||
my $a = "T0001";
|
||||
$o->{alias} = \$a;
|
||||
$o->{select} = Sql::Select->new(@p);
|
||||
$o->register;
|
||||
}
|
||||
|
||||
sub cache($self, $name = $self->name."_Cache")
|
||||
{
|
||||
return "CREATE TABLE $name (". $self->{select}->cache. ")";
|
||||
}
|
||||
|
||||
sub contents($self)
|
||||
{
|
||||
my @parts = ();
|
||||
|
||||
$self->{select}{level} = ($self->{level}//0)+4;
|
||||
$self->{select}{alias} = $self->{alias};
|
||||
|
||||
return ("AS", $self->{select}->contents);
|
||||
}
|
||||
|
||||
sub columns($self)
|
||||
{
|
||||
if (!defined $self->{select}{columns}) {
|
||||
die $self->identify, " has no columns";
|
||||
}
|
||||
return @{$self->{select}{columns}};
|
||||
}
|
||||
|
||||
sub add($self, @p)
|
||||
{
|
||||
$self->{select}->add(@p);
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub prepend($self, @p)
|
||||
{
|
||||
$self->{select}->prepend(@p);
|
||||
return $self;
|
||||
}
|
||||
sub sort($self)
|
||||
{
|
||||
$self->{select}->sort;
|
||||
return $self;
|
||||
}
|
||||
|
||||
package Sql::Select;
|
||||
our @ISA = qw(Sql::Create);
|
||||
|
||||
|
||||
sub contents($self)
|
||||
{
|
||||
my @parts = ();
|
||||
# compute the joins
|
||||
my $joins = {};
|
||||
my @joins = ();
|
||||
|
||||
# figure out used tables
|
||||
my $tables = {};
|
||||
|
||||
if (!defined $self->{origin}) {
|
||||
die "Missing origin in ", $self->identify;
|
||||
}
|
||||
# and column names
|
||||
$self->{column_names} = {};
|
||||
|
||||
for my $w (@{$self->{with}}) {
|
||||
$w->{alias} = $self->{alias};
|
||||
# this stuff should use double dispatch
|
||||
$self->add_column_names_from($w);
|
||||
push(@parts, $self->indent("WITH ".$w->name." AS", 0));
|
||||
my @c = $w->contents;
|
||||
my $one = shift @c;
|
||||
my $last = pop @c;
|
||||
push(@parts, $self->indent("($one", 4));
|
||||
for my $c (@c) {
|
||||
push(@parts, $self->indent($c, 5));
|
||||
}
|
||||
push(@parts, $self->indent("$last)", 5));
|
||||
}
|
||||
|
||||
# this stuff should use double dispatch
|
||||
$self->add_column_names($self->origin);
|
||||
|
||||
$tables->{$self->normalize($self->origin)}++;
|
||||
|
||||
for my $c (@{$self->{columns}}) {
|
||||
my $j = $c->{join};
|
||||
while (defined $j) {
|
||||
if (!defined $joins->{$j}) {
|
||||
# this stuff should use double dispatch
|
||||
$self->add_column_names($j->name);
|
||||
push(@joins, $j);
|
||||
$joins->{$j} = $j;
|
||||
if (++$tables->{$self->normalize($j->name)} == 1) {
|
||||
delete $j->{alias};
|
||||
} else {
|
||||
$j->{alias} = ${$self->{alias}}++;
|
||||
}
|
||||
}
|
||||
$j = $j->{join};
|
||||
}
|
||||
}
|
||||
|
||||
push(@parts, $self->indent("SELECT", 0));
|
||||
my @c = @{$self->{columns}};
|
||||
while (@c != 0) {
|
||||
my $c = shift @c;
|
||||
my $sep = @c == 0 ? '' : ',';
|
||||
my @lines = split /\n/, $c->stringize;
|
||||
while (@lines > 1) {
|
||||
push(@parts, $self->indent(shift @lines, 4));
|
||||
}
|
||||
push(@parts, $self->indent(shift @lines, 4).$sep);
|
||||
}
|
||||
|
||||
push(@parts, $self->indent("FROM ".$self->origin, 0));
|
||||
for my $j (@joins) {
|
||||
push(@parts, $self->indent($j->join_part, 4));
|
||||
# next if $j->is_natural;
|
||||
my @p = $j->on_part($self);
|
||||
if (@p > 0) {
|
||||
push(@parts, $self->indent("ON ".join(" AND ", @p), 8));
|
||||
}
|
||||
}
|
||||
if (defined $self->{group}) {
|
||||
push(@parts, $self->indent("GROUP BY ".
|
||||
join(", ", map {$_->name} @{$self->{group}}), 4));
|
||||
}
|
||||
if (defined $self->{order}) {
|
||||
push(@parts, $self->indent("ORDER BY ".
|
||||
join(", ", map {$_->name} @{$self->{order}}), 4));
|
||||
}
|
||||
return @parts;
|
||||
}
|
||||
|
||||
sub is_unique_name($self, $name)
|
||||
{
|
||||
my $c = $self->{column_names}{$self->normalize($name)};
|
||||
if (!defined $c) {
|
||||
die "$name not registed in ", $self->identify;
|
||||
}
|
||||
return $c == 1;
|
||||
}
|
||||
|
||||
sub cache($self)
|
||||
{
|
||||
my @c;
|
||||
my $base = Sql::Create->find($self->origin);
|
||||
for my $c (@{$self->{columns}}) {
|
||||
my $type = "TEXT";
|
||||
if (defined $c->{join}) {
|
||||
my $t = Sql::Create->find($c->{join}->name);
|
||||
for my $c2 (@{$t->{columns}}) {
|
||||
if ($c2->name eq $c->origin) {
|
||||
$type = $c2->type;
|
||||
last;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for my $c2 (@{$base->{columns}}) {
|
||||
if ($c2->name eq $c->origin) {
|
||||
$type = $c2->type;
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
push @c, $c->name." ".$type;
|
||||
}
|
||||
return join(', ', @c);
|
||||
}
|
||||
|
||||
package Sql::With;
|
||||
our @ISA = qw(Sql::Object);
|
||||
sub category($)
|
||||
{
|
||||
"with"
|
||||
}
|
||||
|
||||
sub new($class, @p)
|
||||
{
|
||||
my $o = $class->SUPER::new(@p);
|
||||
$o->{select} = Sql::Select->new(@p);
|
||||
return $o;
|
||||
}
|
||||
|
||||
sub contents($self)
|
||||
{
|
||||
return $self->{select}->contents;
|
||||
}
|
||||
|
||||
sub add($self, @p)
|
||||
{
|
||||
$self->{select}->add(@p);
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub prepend($self, @p)
|
||||
{
|
||||
$self->{select}->prepend(@p);
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub columns($self)
|
||||
{
|
||||
return $self->{select}->columns;
|
||||
}
|
||||
|
||||
package Sql::Order;
|
||||
our @ISA = qw(Sql::Object);
|
||||
sub category($)
|
||||
{
|
||||
"order"
|
||||
}
|
||||
|
||||
package Sql::Group;
|
||||
our @ISA = qw(Sql::Object);
|
||||
sub category($)
|
||||
{
|
||||
"group"
|
||||
}
|
||||
|
||||
package Sql::Column;
|
||||
our @ISA = qw(Sql::Object);
|
||||
sub category($)
|
||||
{
|
||||
"columns"
|
||||
}
|
||||
|
||||
sub notnull($self)
|
||||
{
|
||||
$self->{notnull} = 1;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub null($self)
|
||||
{
|
||||
delete $self->{notnull};
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub unique($self)
|
||||
{
|
||||
$self->{unique} = 1;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub indexed($self)
|
||||
{
|
||||
$self->{want_index} = 1;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub stringize($self)
|
||||
{
|
||||
my @c = ($self->name, $self->type);
|
||||
if ($self->{notnull}) {
|
||||
push(@c, "NOT NULL");
|
||||
}
|
||||
if ($self->{unique}) {
|
||||
push(@c, "UNIQUE");
|
||||
}
|
||||
if ($self->{references}) {
|
||||
push(@c, "REFERENCES $self->{references}{table}(".
|
||||
$self->reference_field.")");
|
||||
}
|
||||
return join(" ", @c);
|
||||
}
|
||||
|
||||
sub placeholder($)
|
||||
{
|
||||
'?';
|
||||
}
|
||||
|
||||
sub is_key($)
|
||||
{
|
||||
0
|
||||
}
|
||||
|
||||
sub constraint($self)
|
||||
{
|
||||
$self->{is_constraint} = 1;
|
||||
return $self;
|
||||
}
|
||||
package Sql::Column::Integer;
|
||||
our @ISA = qw(Sql::Column);
|
||||
|
||||
sub type($)
|
||||
{
|
||||
"INTEGER"
|
||||
}
|
||||
|
||||
sub reference_field($self)
|
||||
{
|
||||
if (defined $self->{references}{field}) {
|
||||
return $self->{references}{field};
|
||||
} else {
|
||||
my $table = $self->{references}{table};
|
||||
my $k = Sql::Create::Table->key($table);
|
||||
if (defined $k) {
|
||||
return $k->name;
|
||||
} else {
|
||||
my $parent = "???";
|
||||
if (defined $self->{parent}) {
|
||||
$parent = $self->{parent}->name;
|
||||
}
|
||||
die "Can't reference $table from field ",$self->name,
|
||||
" in $parent";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub may_reference($self, $table, $field = undef)
|
||||
{
|
||||
$self->{references}{table} = $table;
|
||||
$self->{references}{field} = $field if defined $field;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub references($self, $table, $field = undef)
|
||||
{
|
||||
return $self->may_reference($table, $field)->notnull;
|
||||
}
|
||||
|
||||
sub placeholder($self)
|
||||
{
|
||||
if (!defined $self->{references}) {
|
||||
return '?';
|
||||
}
|
||||
my $table = $self->{references}{table};
|
||||
|
||||
my ($key, $value);
|
||||
for my $c (Sql::Create->find($table)->columns) {
|
||||
if ($c->is_key) {
|
||||
$key = $c->name;
|
||||
} elsif (defined $value) {
|
||||
return '?'; # can't match multiple fields
|
||||
} else {
|
||||
$value = $c->name;
|
||||
}
|
||||
}
|
||||
if (defined $key && defined $value) {
|
||||
return "(SELECT $key FROM $table WHERE $value=?)";
|
||||
} else {
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
package Sql::Column::View;
|
||||
our @ISA = qw(Sql::Column);
|
||||
|
||||
# this is the code I need to rewrite to provide column names based on the
|
||||
# container or the join
|
||||
sub stringize($self)
|
||||
{
|
||||
if ($self->{parent}->is_unique_name($self->origin)) {
|
||||
if ($self->origin eq $self->name) {
|
||||
return $self->name;
|
||||
} else {
|
||||
return $self->origin." AS ".$self->name;
|
||||
}
|
||||
} else {
|
||||
return $self->stringize_with_alias;
|
||||
}
|
||||
}
|
||||
|
||||
sub stringize_with_alias($self)
|
||||
{
|
||||
return $self->expr." AS ".$self->name;
|
||||
}
|
||||
|
||||
sub expr($self, @p)
|
||||
{
|
||||
return $self->column(@p);
|
||||
}
|
||||
|
||||
|
||||
sub column($self, $name = $self->origin)
|
||||
{
|
||||
if ($self->{parent}->is_unique_name($name)) {
|
||||
return $name;
|
||||
}
|
||||
if (defined $self->{join} &&
|
||||
Sql::Create->is_table_column($self->{join}->name, $name)) {
|
||||
return $self->{join}->join_table.".".$name;
|
||||
} else {
|
||||
return $self->{parent}->origin.".".$name;
|
||||
}
|
||||
}
|
||||
|
||||
sub group_by($self)
|
||||
{
|
||||
$self->{group_by} = 1;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub join_table($self)
|
||||
{
|
||||
return $self->{parent}->origin;
|
||||
}
|
||||
|
||||
sub join($self, @j)
|
||||
{
|
||||
my $subject = $self;
|
||||
for my $j (@j) {
|
||||
$subject->{join} = $j;
|
||||
$j->{previous} = $subject;
|
||||
$subject = $j;
|
||||
}
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub left($self)
|
||||
{
|
||||
if (defined $self->{join}) {
|
||||
$self->{join}->left;
|
||||
}
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub new($class, @p)
|
||||
{
|
||||
my $o = $class->SUPER::new(@p);
|
||||
$o->{origin} //= $o->name;
|
||||
return $o;
|
||||
}
|
||||
|
||||
sub add_to($self, $container)
|
||||
{
|
||||
$self->SUPER::add_to($container);
|
||||
if ($self->{group_by}) {
|
||||
push(@{$container->{group}}, $self);
|
||||
}
|
||||
}
|
||||
|
||||
sub prepend_to($self, $container)
|
||||
{
|
||||
$self->SUPER::prepend_to($container);
|
||||
if ($self->{group_by}) {
|
||||
unshift(@{$container->{group}}, $self);
|
||||
}
|
||||
}
|
||||
|
||||
package Sql::Column::View::Expr;
|
||||
our @ISA = qw(Sql::Column::View);
|
||||
|
||||
sub stringize($self)
|
||||
{
|
||||
return $self->stringize_with_alias;
|
||||
}
|
||||
|
||||
package Sql::Column::View::Concat;
|
||||
our @ISA = qw(Sql::Column::View::Expr);
|
||||
|
||||
sub new($class, @p)
|
||||
{
|
||||
my $o = $class->SUPER::new(@p);
|
||||
$o->{separator} //= ' ';
|
||||
return $o;
|
||||
}
|
||||
|
||||
sub expr($self)
|
||||
{
|
||||
return "group_concat(".$self->column.", '".$self->{separator}."')";
|
||||
}
|
||||
|
||||
package Sql::Column::Text;
|
||||
our @ISA = qw(Sql::Column);
|
||||
sub type($)
|
||||
{
|
||||
"TEXT";
|
||||
}
|
||||
|
||||
package Sql::Column::CurrentDate;
|
||||
our @ISA = qw(Sql::Column::Text);
|
||||
sub placeholder($)
|
||||
{
|
||||
"CURRENT_DATE";
|
||||
}
|
||||
|
||||
package Sql::Column::Key;
|
||||
our @ISA = qw(Sql::Column::Integer);
|
||||
sub new($class, @p)
|
||||
{
|
||||
my $o = $class->SUPER::new(@p);
|
||||
$o->{autoincrement} = 1;
|
||||
return $o;
|
||||
}
|
||||
|
||||
sub is_key($self)
|
||||
{
|
||||
return $self->{autoincrement};
|
||||
}
|
||||
|
||||
sub add_to($self, $c)
|
||||
{
|
||||
$c->{key} = $self;
|
||||
$self->SUPER::add_to($c);
|
||||
}
|
||||
|
||||
|
||||
sub prepend_to($self, $c)
|
||||
{
|
||||
$c->{key} = $self;
|
||||
$self->SUPER::prepend_to($c);
|
||||
}
|
||||
|
||||
sub noautoincrement($self)
|
||||
{
|
||||
$self->{autoincrement} = 0;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub type($self)
|
||||
{
|
||||
if ($self->{autoincrement}) {
|
||||
return "INTEGER PRIMARY KEY AUTOINCREMENT";
|
||||
} else {
|
||||
return "INTEGER PRIMARY KEY";
|
||||
}
|
||||
}
|
||||
|
||||
package Sql::Join;
|
||||
our @ISA = qw(Sql::Object);
|
||||
sub category($)
|
||||
{
|
||||
"joins"
|
||||
}
|
||||
|
||||
sub join_part($self)
|
||||
{
|
||||
my $s = "JOIN ".$self->name;
|
||||
if (defined $self->{alias}) {
|
||||
$s .= " ".$self->{alias};
|
||||
}
|
||||
if ($self->{left}) {
|
||||
$s = "LEFT ".$s;
|
||||
}
|
||||
# if ($self->is_natural) {
|
||||
# $s = "NATURAL ".$s;
|
||||
# }
|
||||
return $s;
|
||||
}
|
||||
|
||||
sub join_table($self)
|
||||
{
|
||||
return $self->{alias} // $self->name;
|
||||
}
|
||||
|
||||
sub on_part($self, $view)
|
||||
{
|
||||
return map {$_->equation($self, $view)} @{$self->{equals}};
|
||||
|
||||
}
|
||||
|
||||
sub is_natural($self)
|
||||
{
|
||||
for my $e (@{$self->{equals}}) {
|
||||
return 0 if !$e->is_natural;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub left($self)
|
||||
{
|
||||
$self->{left} = 1;
|
||||
return $self;
|
||||
}
|
||||
|
||||
package Sql::Equal;
|
||||
our @ISA = qw(Sql::Object);
|
||||
|
||||
sub new($class, $a, $b)
|
||||
{
|
||||
bless {a => $a, b => $b}, $class;
|
||||
}
|
||||
|
||||
sub category($)
|
||||
{
|
||||
"equals"
|
||||
}
|
||||
|
||||
sub equation($self, $join, $view)
|
||||
{
|
||||
my $a = $self->{a};
|
||||
my $b = $self->{b};
|
||||
if (!$view->is_unique_name($a)) {
|
||||
$a = $join->join_table.".".$a;
|
||||
}
|
||||
if (!$view->is_unique_name($b)) {
|
||||
$b = $join->{previous}->join_table.".".$b;
|
||||
}
|
||||
return "$a=$b";
|
||||
}
|
||||
|
||||
sub is_natural($self)
|
||||
{
|
||||
return $self->{a} eq $self->{b};
|
||||
}
|
||||
|
||||
package Sql::EqualConstant;
|
||||
our @ISA = qw(Sql::Equal);
|
||||
sub equation($self, $join, $view)
|
||||
{
|
||||
my $a = $self->{a};
|
||||
if (!$view->is_unique_name($a)) {
|
||||
$a = $join->join_table.".".$a;
|
||||
}
|
||||
|
||||
return "$a=$self->{b}";
|
||||
}
|
||||
|
||||
sub is_natural($)
|
||||
{
|
||||
0
|
||||
}
|
||||
|
||||
package Sql::IsNull;
|
||||
our @ISA = qw(Sql::Equal);
|
||||
|
||||
# :IsNull is a "kind of" equal but it has only one single value
|
||||
# it's okay because everything referencing b is overriden.
|
||||
sub new($class, $a)
|
||||
{
|
||||
bless {a => $a}, $class;
|
||||
}
|
||||
|
||||
sub equation($self, $join, $view)
|
||||
{
|
||||
my $a = $self->{a};
|
||||
if (!$view->is_unique_name($a)) {
|
||||
$a = $join->join_table.".".$a;
|
||||
}
|
||||
|
||||
return "$a IS NULL";
|
||||
}
|
||||
|
||||
sub is_natural($)
|
||||
{
|
||||
0
|
||||
}
|
||||
|
||||
package Sql::Create::Index;
|
||||
our @ISA = qw(Sql::Create);
|
||||
|
||||
sub type($)
|
||||
{
|
||||
"INDEX"
|
||||
}
|
||||
|
||||
sub is_index($)
|
||||
{
|
||||
1
|
||||
}
|
||||
|
||||
sub new($class, $table, $col)
|
||||
{
|
||||
my $name = $table->name."_".$col->name;
|
||||
my $o = bless { name => $name, table => $table, col => $col}, $class;
|
||||
$o->register;
|
||||
}
|
||||
|
||||
sub contents($self)
|
||||
{
|
||||
return "ON ". $self->{table}->name."(".$self->{col}->name.")";
|
||||
}
|
||||
|
||||
1;
|
91
databases/sqlports/files/Trace.pm
Normal file
91
databases/sqlports/files/Trace.pm
Normal file
|
@ -0,0 +1,91 @@
|
|||
# ex:ts=8 sw=4:
|
||||
# $OpenBSD: Trace.pm,v 1.2 2023/06/16 04:17:56 espie Exp $
|
||||
#
|
||||
# Copyright (c) 2015-2018 Marc Espie <espie@openbsd.org>
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
use v5.36;
|
||||
package Trace;
|
||||
|
||||
# inspired by Carp::Always
|
||||
sub trace_message()
|
||||
{
|
||||
my $msg = '';
|
||||
my $x = 1;
|
||||
while (1) {
|
||||
my @c;
|
||||
{
|
||||
package DB;
|
||||
our @args;
|
||||
@c = caller($x+1);
|
||||
}
|
||||
last if !@c;
|
||||
$msg .= "$c[3](".
|
||||
join(', ', map {
|
||||
if (!defined $_) {
|
||||
'<undef>';
|
||||
} else {
|
||||
my $string;
|
||||
eval { $string = $_->debug_dump };
|
||||
if (defined $string) {
|
||||
"$_($string)";
|
||||
} else {
|
||||
$_;
|
||||
}
|
||||
}
|
||||
} @DB::args).
|
||||
") called at $c[1] line $c[2]\n";
|
||||
$x++;
|
||||
}
|
||||
return $msg;
|
||||
}
|
||||
|
||||
my ($sig, $olddie, $oldwarn);
|
||||
|
||||
sub setup($class, $sig)
|
||||
{
|
||||
$olddie = $SIG{__DIE__};
|
||||
$oldwarn = $SIG{__WARN__};
|
||||
$sig->{__WARN__} = sub {
|
||||
$sig->{__WARN__} = $oldwarn;
|
||||
my $a = pop @_;
|
||||
$a =~ s/(.*)( at .*? line .*?)\n$/$1$2/s;
|
||||
push @_, $a;
|
||||
my $msg = join("\n", @_, &trace_message());
|
||||
warn $msg;
|
||||
};
|
||||
|
||||
$sig->{__DIE__} = sub {
|
||||
die @_ if $^S;
|
||||
$sig->{__DIE__} = $olddie;
|
||||
my $a = pop @_;
|
||||
$a =~ s/(.*)( at .*? line .*?)\n$/$1$2/s;
|
||||
push @_, $a;
|
||||
my $msg = join("\n", @_, &trace_message());
|
||||
die $msg;
|
||||
};
|
||||
|
||||
$sig->{INFO} = sub {
|
||||
print "Trace:\n", &trace_message();
|
||||
sleep 1;
|
||||
};
|
||||
}
|
||||
|
||||
END {
|
||||
$sig->{__DIE__} = $olddie;
|
||||
$sig->{__WARN__} = $oldwarn;
|
||||
}
|
||||
|
||||
1;
|
||||
|
152
databases/sqlports/files/TreeWalker.pm
Normal file
152
databases/sqlports/files/TreeWalker.pm
Normal file
|
@ -0,0 +1,152 @@
|
|||
#! /usr/bin/perl
|
||||
# $OpenBSD: TreeWalker.pm,v 1.18 2023/06/15 12:53:07 espie Exp $
|
||||
#
|
||||
# Copyright (c) 2006-2013 Marc Espie <espie@openbsd.org>
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
use v5.36;
|
||||
use warnings;
|
||||
|
||||
package TreeWalker;
|
||||
use PkgPath;
|
||||
|
||||
sub new($class, $strict, $startdir)
|
||||
{
|
||||
return bless { strict => $strict, startdir => $startdir }, $class;
|
||||
}
|
||||
|
||||
sub subdirlist($self, $list)
|
||||
{
|
||||
return join(' ', sort keys %$list);
|
||||
}
|
||||
|
||||
sub dump_dirs($self, $subdirs = undef)
|
||||
{
|
||||
my ($pid, $fd);
|
||||
unless (defined($pid = open($fd, "-|"))) {
|
||||
die "can't fork : $!";
|
||||
}
|
||||
if ($pid) {
|
||||
$self->parse_dump($fd, $subdirs);
|
||||
close $fd || die $!;
|
||||
} else {
|
||||
my %myenv = ();
|
||||
my $portsdir = $ENV{PORTSDIR};
|
||||
if (defined $subdirs) {
|
||||
$myenv{'SUBDIR'} = $self->subdirlist($subdirs);
|
||||
} elsif (defined $ENV{SUBDIRLIST}) {
|
||||
$myenv{'SUBDIRLIST'} = $ENV{SUBDIRLIST};
|
||||
} elsif (defined $self->{startdir}) {
|
||||
$myenv{'STARTDIR'} = $self->{startdir};
|
||||
}
|
||||
$myenv{'NO_IGNORE'} = 'Yes';
|
||||
$myenv{PORTSDIR} = $portsdir;
|
||||
close STDERR;
|
||||
open STDERR, '>&STDOUT';
|
||||
chdir $portsdir;
|
||||
%ENV = %myenv;
|
||||
my @vars = ('LIBECXX=$${LIBECXX}',
|
||||
'COMPILER_LIBCXX=$${COMPILER_LIBCXX}');
|
||||
if (!$self->{strict}) {
|
||||
push(@vars, "PORTSDIR_PATH=$portsdir");
|
||||
}
|
||||
exec {'make'} ("make", "dump-vars", @vars);
|
||||
die $!;
|
||||
}
|
||||
}
|
||||
|
||||
sub parse_dump($self, $fd, $subdirs)
|
||||
{
|
||||
my $h = {};
|
||||
my $seen = {};
|
||||
my $subdir;
|
||||
my $reset = sub() {
|
||||
$h = PkgPath->handle_equivalences($self, $h, $subdirs);
|
||||
for my $pkgpath (sort values %$h) {
|
||||
$self->handle_path($pkgpath, $self->{equivs});
|
||||
}
|
||||
$h = {};
|
||||
};
|
||||
|
||||
while (<$fd>) {
|
||||
chomp;
|
||||
# kill noise
|
||||
if (m/^\=\=\=\>\s*Exiting (.*) with an error$/) {
|
||||
my $dir = PkgPath->new($1);
|
||||
$dir->break("exiting with an error");
|
||||
$h->{$dir} = $dir;
|
||||
$h = {};
|
||||
next;
|
||||
}
|
||||
if (m/^\=\=\=\>\s*(.*)/) {
|
||||
$subdir = PkgPath->new($1);
|
||||
&$reset();
|
||||
} elsif (my ($pkgpath, $var, $arch, $value) =
|
||||
m/^(.*?)\.([A-Z][A-Z_0-9]*)(?:\-([a-z0-9]+))?\=\s*(.*)\s*$/) {
|
||||
if ($value =~ m/^\"(.*)\"$/) {
|
||||
$value = $1;
|
||||
}
|
||||
my $o = PkgPath->compose($pkgpath, $subdir);
|
||||
$h->{$o} = $o;
|
||||
$self->handle_value($o, $var, $value, $arch);
|
||||
# Note we did it !
|
||||
} elsif (m/^\>\>\s*Broken dependency:\s*(.*?)\s*non existent/) {
|
||||
my $dir = PkgPath->new($1);
|
||||
$dir->break("broken dependency");
|
||||
$h->{$dir} = $dir;
|
||||
$h= {};
|
||||
}
|
||||
}
|
||||
&$reset();
|
||||
}
|
||||
|
||||
# $self->handle_value($o, $var, $value, $arch)
|
||||
sub handle_value($, $, $, $, $)
|
||||
{
|
||||
}
|
||||
|
||||
# $self->handle_path($pkgpath, $equivs)
|
||||
sub handle_path($, $, $)
|
||||
{
|
||||
}
|
||||
|
||||
sub dump_all_dirs($self)
|
||||
{
|
||||
$self->dump_dirs;
|
||||
|
||||
my $i = 1;
|
||||
while (1) {
|
||||
my $subdirlist = {};
|
||||
for my $v (PkgPath->seen) {
|
||||
if (defined $v->{info}) {
|
||||
delete $v->{tried};
|
||||
if (defined $v->{want}) {
|
||||
delete $v->{want};
|
||||
}
|
||||
next;
|
||||
}
|
||||
if (defined $v->{tried}) {
|
||||
} elsif ($v->{want}) {
|
||||
$v->add_to_subdirlist($subdirlist);
|
||||
$v->{tried} = 1;
|
||||
}
|
||||
}
|
||||
last if (keys %$subdirlist) == 0;
|
||||
$i++;
|
||||
say "pass #$i";
|
||||
$self->dump_dirs($subdirlist);
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
1226
databases/sqlports/files/Var.pm
Normal file
1226
databases/sqlports/files/Var.pm
Normal file
File diff suppressed because it is too large
Load diff
58
databases/sqlports/files/man/show-reverse-deps.1
Normal file
58
databases/sqlports/files/man/show-reverse-deps.1
Normal file
|
@ -0,0 +1,58 @@
|
|||
.\" $OpenBSD: show-reverse-deps.1,v 1.3 2020/06/11 19:55:15 espie Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2020 Marc Espie <espie@openbsd.org>
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, and distribute this software for any
|
||||
.\" purpose with or without fee is hereby granted, provided that the above
|
||||
.\" copyright notice and this permission notice appear in all copies.
|
||||
.\"
|
||||
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: June 11 2020 $
|
||||
.Dt SHOW-REVERSE-DEPS 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm show-reverse-deps
|
||||
.Nd show reverse dependencies for a given port
|
||||
.Sh SYNOPSIS
|
||||
.Nm show-reverse-deps
|
||||
.Op Fl ftv
|
||||
.Op Fl d Ar database
|
||||
.Ar pkgpath
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
quickly computes all ports dependent on a given port through a recursive sql
|
||||
query to
|
||||
.Pa sqlports .
|
||||
.Pp
|
||||
The
|
||||
.Ar pkgpath
|
||||
parameter should normally be the fullpkgpath of the port to depend on.
|
||||
.Pp
|
||||
Options are as follows:
|
||||
.Bl -tag -width flagdatabase
|
||||
.It Fl d Ar database
|
||||
Choose an sqlite3 database other than the default
|
||||
.Pa ${TRUEPREFIX}/share/sqlports .
|
||||
.It Fl f
|
||||
Fuzzy matching, show dependencies for any path which contains the
|
||||
.Ar pkgpath
|
||||
parameter.
|
||||
.It Fl t
|
||||
Also include test dependencies.
|
||||
By default, only other types of dependencies are considered.
|
||||
.It Fl v
|
||||
Show verbose results: instead of a list of pkgpath, show every
|
||||
dependency in the form "fullpkgpath|dependspath|TYPE", where TYPE
|
||||
is one of
|
||||
.Ev LIB_DEPENDS , RUN_DEPENDS , BUILD_DEPENDS , TEST_DEPENDS .
|
||||
Results can be rather large!
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr sqlite3 1
|
287
databases/sqlports/files/man/sqlports.5
Normal file
287
databases/sqlports/files/man/sqlports.5
Normal file
|
@ -0,0 +1,287 @@
|
|||
.\" $OpenBSD: sqlports.5,v 1.8 2023/08/08 11:12:06 espie Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2020 Marc Espie <espie@openbsd.org>
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, and distribute this software for any
|
||||
.\" purpose with or without fee is hereby granted, provided that the above
|
||||
.\" copyright notice and this permission notice appear in all copies.
|
||||
.\"
|
||||
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: August 8 2023 $
|
||||
.Dt SQLPORTS 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm sqlports
|
||||
.Nd sqlite database for ports meta information
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is built as a port by parsing the output of
|
||||
.Li make dump-vars
|
||||
over the full ports tree.
|
||||
.Pp
|
||||
The database contains tables for automated tools, along with nice views
|
||||
for human consumption.
|
||||
.Pp
|
||||
Table names are prefixed with underscore, .e.g,
|
||||
.Sq _Ports
|
||||
contrary to views, e.g.,
|
||||
.Sq Paths .
|
||||
.Pp
|
||||
The special table
|
||||
.Sq Meta
|
||||
contains only one entry, detailing the current database.
|
||||
.Bl -tag -offset indent -width keyword
|
||||
.It Meta (SchemaVersion, Hash, CurrentDate)
|
||||
SchemaVersion follows the usual major.minor rules as shared libraries,
|
||||
Hash is unique to each generated database,
|
||||
CurrentDate is the date the database was generated.
|
||||
.El
|
||||
.Pp
|
||||
Other tables are as follows:
|
||||
.Bl -tag -offset indent -width keyword
|
||||
.It _Paths (ID, FULLPKGPATH, PKGPATH, CANONICAL)
|
||||
PKGPATH points to a PATHS entry corresponding to the stripped down version of
|
||||
FULLPKGPATH, without flavors or subpackage markers, or is null if FULLPKGPATH
|
||||
is already stripped.
|
||||
Every other FULLPKGPATH, PKGPATH, DEPENDSPATH entry
|
||||
in the database points to this table.
|
||||
The FULLPKGPATH is complete, including flavors and pseudo flavors markers.
|
||||
For every port with MULTI_PACKAGES settings, one entry is written
|
||||
for each SUBPACKAGE.
|
||||
CANONICAL points to the actual ID to use as an entry in other tables, for
|
||||
FULLPKGPATH which don't have their own entry.
|
||||
.It _Ports(FULLPKGPATH, ...)
|
||||
holds all the information retrieved through various variables that is not
|
||||
stored in specialized tables, e.g.,:
|
||||
.Bl -tag -width AUTOMAKE_VERSION -offset indent -compact
|
||||
.It AUTOCONF_VERSION
|
||||
.It AUTOMAKE_VERSION
|
||||
.It COMES_WITH
|
||||
.It COMMENT
|
||||
.It COMPILER
|
||||
.It COMPILER_LANGS
|
||||
.It DISTFILES
|
||||
.It DISTNAME
|
||||
.It DIST_SUBDIR
|
||||
.It EPOCH
|
||||
.It FIX_EXTRACT_PERMISSIONS
|
||||
.It FULLPKGNAME
|
||||
.It GH_*
|
||||
.It HOMEPAGE
|
||||
.It IGNORE
|
||||
.It IS_INTERACTIVE
|
||||
.It MAINTAINER
|
||||
.It NO_*
|
||||
.It PERMIT_*
|
||||
.It PKGNAME
|
||||
.It PKGSPEC
|
||||
.It PKGSTEM
|
||||
.It PKG_ARCH
|
||||
.It PORTROACH
|
||||
.It PORTROACH_COMMENT
|
||||
.It PREFIX
|
||||
.It PSEUDO_FLAVOR
|
||||
.It REVISION
|
||||
.It SEPARATE_BUILD
|
||||
.It STATIC_PLIST
|
||||
.It SUBPACKAGE
|
||||
.It SUPDISTFILES
|
||||
.It TEST_IS_INTERACTIVE
|
||||
.It UPDATE_PLIST_ARGS
|
||||
.It USE_*
|
||||
.El
|
||||
Some of this information is stored as indexes in keyword tables,
|
||||
and Yes/No variables have been replaced with 1/0.
|
||||
Variables not present in a given port are left undefined.
|
||||
.Pp
|
||||
Specifically, AUTOCONF_VERSION and AUTOMAKE_VERSION reference _AutoVersion,
|
||||
MAINTAINER references _EMail, PERMIT_DISTFILES and SEPARATE_BUILD
|
||||
reference _Keywords2, PKG_ARCH references _Arch, and PREFIX references _Prefix.
|
||||
Note that USE_LIBTOOL is 3-valued: 2 is gnu, 1 is yes, undef is no.
|
||||
Note that USE_WXNEEDED is 3-valued: 2 is special, 1 is yes, undef is no.
|
||||
.Pp
|
||||
MULTI_PACKAGES ports hold several entries with corresponding FULLPKGPATH
|
||||
(after canonicalisation).
|
||||
.It _Flavors(FULLPKGPATH, VALUE, N)
|
||||
.It _PseudoFlavors(FULLPKGPATH, VALUE, N)
|
||||
.It _Categories(FULLPKGPATH, VALUE, N)
|
||||
.It _Multi(FULLPKGPATH, VALUE, SUBPKGPATH, N)
|
||||
No values are stored for SUBPKGPATH=-.
|
||||
.It _Modules(FULLPKGPATH, VALUE, N)
|
||||
.It _Configure(FULLPKGPATH, VALUE, N)
|
||||
Corresponds to CONFIGURE_STYLE
|
||||
.It _ConfigureArgs(FULLPKGPATH, VALUE, N, QUOTETYPE)
|
||||
.It _DebugConfigureArgs(FULLPKGPATH, VALUE, N, QUOTETYPE)
|
||||
.It _MasterSites(FULLPKGPATH, N, VALUE)
|
||||
.It _Makefiles(FULLPKGPATH, VALUE, N)
|
||||
This tables contains only Makefiles from MAKE_FILE_LIST that are not
|
||||
.Sq default values
|
||||
(always included makefiles).
|
||||
.It _FixCRLFFiles(FULLPKGPATH, VALUE, N)
|
||||
.It _NotForArch(FULLPKGPATH, VALUE, N)
|
||||
.It _OnlyForArch(FULLPKGPATH, VALUE, N)
|
||||
All of these variable values are actually ordered lists (hence the N).
|
||||
.Pp
|
||||
Each keyword table follows the same scheme
|
||||
TABLENAME(KEYREF, VALUE)
|
||||
.It _Depends(FULLPKGPATH, FULLDEPENDS, PKGSPEC, REST, DEPENDSPATH, TYPE, N)
|
||||
All depends are stored in a single table, the type is
|
||||
.Bl -tag -width 10 -offset indent -compact
|
||||
.It 0
|
||||
LIB_DEPENDS
|
||||
.It 1
|
||||
RUN_DEPENDS
|
||||
.It 2
|
||||
BUILD_DEPENDS
|
||||
.It 3
|
||||
TEST_DEPENDS
|
||||
.El
|
||||
FULLDEPENDS is the full text of the dependency, which parses as DEPENDSPATH,
|
||||
the actual PKGPATH we depend upon, PKGSPEC, the spec we depend upon
|
||||
(if explicit), and REST the remainder of the text (things like :configure and
|
||||
such).
|
||||
.It _Distfiles(FULLPKGPATH, VALUE, N, Type)
|
||||
All distfiles/patchfiles/supdistfiles are stored in a single table, with Type
|
||||
.Bl -tag -width 10 -offset indent -compact
|
||||
.It 0
|
||||
distfiles
|
||||
.It 1
|
||||
patchfiles
|
||||
.It 2
|
||||
supdistfiles
|
||||
.El
|
||||
Note that N is :N from mastersites, those are not considered ordered lists.
|
||||
.It _DPBProperties (FULLPKGPATH, VALUE, N)
|
||||
.It _Wantlib(FULLPKGPATH, VALUE, EXTRA)
|
||||
All the libraries the FULLPKGPATH depends upon, with optional version
|
||||
number specification stored in EXTRA
|
||||
coming from the WANTLIB variable.
|
||||
.It _Multi(FULLPKGPATH, VALUE, SUBPKGPATH, N)
|
||||
also contains the normalized pkgpath for the corresponding subpackage.
|
||||
.It _DebugPackages(FULLPKGPATH, VALUE, SUBPKGPATH, N)
|
||||
contrary to _Multi, also contains
|
||||
.Sq -
|
||||
entries for packages without subpackages which have debug packages.
|
||||
.It _PkgPaths(FULLPKGPATH, Value, N)
|
||||
all build_packages associated to a fullpkgpath.
|
||||
.It _Broken(FULLPKGPATH, ARCH, TEXT)
|
||||
.It _Shared_Libs(FULLPKGPATH, LIBNAME, VERSION)
|
||||
.It _SubstVars(FULLPKGPATH, VALUE, N)
|
||||
.It _TARGETS(FULLPKGPATH, VALUE)
|
||||
.El
|
||||
Some information, both in the main table and in secondary tables
|
||||
is stored as keyword references to other tables:
|
||||
.Bl -tag -width AUTOMAKE_VERSIONblablabla -offset indent -compact
|
||||
.It AUTOCONF_VERSION , AUTOMAKE_VERSION
|
||||
_AUTOVERSION
|
||||
.It FixCRLFFiles
|
||||
_FILENAME2
|
||||
.It _DPBProperties.value
|
||||
_DPBKeys
|
||||
.It MAINTAINER
|
||||
_EMAIL
|
||||
.It CATEGORIES
|
||||
_CATEGORYKEYS
|
||||
.It CONFIGURE
|
||||
_CONFIGURE_KEYS
|
||||
.It MAKEFILES
|
||||
_FILENAME
|
||||
.It MODULES
|
||||
_MODULEKEYS
|
||||
.It PREFIX
|
||||
_PREFIX
|
||||
.It _WANTLIB.VALUE , _SHARED_LIBS.LIBNAME
|
||||
_LIBRARY
|
||||
.It PERMIT_* , SEPARATE_BUILD
|
||||
_KEYWORDS2
|
||||
.It FLAVORS , PSEUDO_FLAVORS
|
||||
_KEYWORDS
|
||||
.It NOT_FOR_ARCHS , ONLY_FOR_ARCHS , PKG_ARCH
|
||||
_ARCH
|
||||
.It _SubstVars.value
|
||||
_substvarskey
|
||||
.It TARGETS
|
||||
_TARGETKEYS
|
||||
.It _Distfiles.value
|
||||
_Fetchfiles
|
||||
.El
|
||||
A few views are provided for convenience while building complex requests.
|
||||
.Bl -bullet -offset indent
|
||||
.It
|
||||
Ports:
|
||||
contains all info from _ports and from secondary tables with indices
|
||||
replaced with text values.
|
||||
.It
|
||||
* Depends_ordered, Categories_ordered, CompilerLinks_Ordered,
|
||||
Configureargs_ordered, Configure_ordered, DebugConfigureArgs_Ordered,
|
||||
DPBProperties_ordered,
|
||||
Flavors_ordered, Makefiles_ordered, Modules_ordered, NotForArch_ordered,
|
||||
OnlyforArch_ordered, PkgPaths_ordered, PseudoFlavors_ordered,
|
||||
SubstVars_ordered, Targets_ordered, distfiles_ordered, wantlib_ordered:
|
||||
reconstituted lists of text values as a single string from the
|
||||
corresponding table.
|
||||
.It
|
||||
each "keyword" list also has a corresponding view, e.g.,
|
||||
_BROKEN -> BROKEN (PathId, FULLPKGPATH, Arch, Value)
|
||||
with text fields, and PathId still the index entry for the fullpkgpath,
|
||||
suitable for further joins.
|
||||
.It
|
||||
canonical_depends: fullpkgpath/dependspath/dependstype from _depends but
|
||||
normalized as canonical paths.
|
||||
.El
|
||||
.Pp
|
||||
The database also contains a caching table named
|
||||
.Sq PortsQ
|
||||
that contains the actual data from the
|
||||
.Sq Ports
|
||||
view.
|
||||
.Sh EXAMPLES
|
||||
Looking at the details of a view:
|
||||
.Bd -literal -offset indent
|
||||
sqlite> .schema depends
|
||||
CREATE VIEW Depends AS
|
||||
SELECT
|
||||
_Paths.Id AS PathId,
|
||||
_Paths.FullPkgPath AS FullPkgPath,
|
||||
FullDepends,
|
||||
PkgSpec,
|
||||
Rest,
|
||||
T0001.FullPkgpath AS DependsPath,
|
||||
Type,
|
||||
N
|
||||
FROM _Depends
|
||||
JOIN _Paths
|
||||
ON _Paths.Canonical=_Depends.FullPkgPath
|
||||
JOIN _Paths T0001
|
||||
ON T0001.Canonical=DependsPath
|
||||
/* Depends(PathId,FullPkgPath,FullDepends,PkgSpec,Rest,DependsPath,Type,N) */;
|
||||
.Ed
|
||||
List the fullpkgpaths of leaf ports (not a dependency of anything):
|
||||
.Bd -literal -offset indent
|
||||
sqlite> select distinct fullpkgpath from _paths where pkgpath not in
|
||||
(select pkgpath from _paths
|
||||
join _depends on _depends.dependspath=_paths.id);
|
||||
.Ed
|
||||
.Sh BUGS AND LIMITATIONS
|
||||
The optimizer in
|
||||
.Xr sqlite 1
|
||||
doesn't care for non-standard constructs such as
|
||||
.Sq group_concat
|
||||
and doesn't optimize left joins away when it should,
|
||||
so even if you don't ask for agregated columns in the
|
||||
.Sq Ports
|
||||
view, it will compute them irregardless.
|
||||
Hence the
|
||||
.Sq PortsQ
|
||||
cache.
|
||||
.Sh FILES
|
||||
.Pa ${TRUEPREFIX}/share/sqlports
|
||||
.Sh SEE ALSO
|
||||
.Xr sqlite3 1
|
174
databases/sqlports/files/mksqlitedb
Normal file
174
databases/sqlports/files/mksqlitedb
Normal file
|
@ -0,0 +1,174 @@
|
|||
#! /usr/bin/perl
|
||||
# $OpenBSD: mksqlitedb,v 1.60 2023/06/16 04:54:20 espie Exp $
|
||||
#
|
||||
# Copyright (c) 2006-2010 Marc Espie <espie@openbsd.org>
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# example script that shows how to store all variable values into a
|
||||
# database, using SQLite for that purpose.
|
||||
#
|
||||
# usage: cd /usr/ports && mksqlitedb
|
||||
|
||||
use v5.36;
|
||||
use FindBin;
|
||||
use lib $FindBin::Bin;
|
||||
use Getopt::Std;
|
||||
use Var;
|
||||
use Inserter;
|
||||
use DBI;
|
||||
use PkgPath;
|
||||
use Info;
|
||||
use TreeWalker;
|
||||
use Trace;
|
||||
|
||||
|
||||
package MyTreeWalker;
|
||||
our @ISA = (qw(TreeWalker));
|
||||
|
||||
sub new($class, $inserter, @r)
|
||||
{
|
||||
my $o = $class->SUPER::new(@r);
|
||||
$o->{inserter} = $inserter;
|
||||
return $o;
|
||||
}
|
||||
|
||||
sub inserter($self)
|
||||
{
|
||||
return $self->{inserter};
|
||||
}
|
||||
|
||||
sub handle_value($self, $o, $var, $value, $arch)
|
||||
{
|
||||
$o->{info} //= Info->new($o);
|
||||
$o->{info}->create($var, $value, $arch, $o);
|
||||
}
|
||||
|
||||
sub parse_dump($self, $fd, $subdirs)
|
||||
{
|
||||
$self->SUPER::parse_dump($fd, $subdirs);
|
||||
$self->inserter->commit_to_db;
|
||||
}
|
||||
|
||||
sub create_missing_vars($self, $o)
|
||||
{
|
||||
for my $name (qw(SHARED_LIBS TARGETS)) {
|
||||
if (!defined $o->{info}->{vars}{$name}) {
|
||||
$o->{info}->create($name, '', undef, $o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub handle_path($self, $pkgpath, $equivs)
|
||||
{
|
||||
$self->create_missing_vars($pkgpath);
|
||||
my $key = $pkgpath->fullpkgpath;
|
||||
while (defined $equivs->{$key}) {
|
||||
$key = $equivs->{$key};
|
||||
}
|
||||
if ($pkgpath->{info}{done}) {
|
||||
print "--- $key (already done)\n";
|
||||
return;
|
||||
}
|
||||
print "+++ $key\n";
|
||||
$self->inserter->set_newkey($key);
|
||||
for my $var ($pkgpath->{info}->variables) {
|
||||
$self->inserter->add_var($var);
|
||||
}
|
||||
$pkgpath->{info}->reclaim;
|
||||
$pkgpath->{info}{done} = 1;
|
||||
$pkgpath->{done} = 1;
|
||||
$self->inserter->finish_port;
|
||||
}
|
||||
|
||||
package main;
|
||||
use Digest::SHA;
|
||||
use MIME::Base64;
|
||||
|
||||
sub digest($filename)
|
||||
{
|
||||
my $d = Digest::SHA->new(256);
|
||||
$d->addfile($filename);
|
||||
return encode_base64($d->digest, '');
|
||||
}
|
||||
|
||||
our ($opt_v, $opt_q, $opt_p, $opt_V, $opt_C, $opt_w, $opt_s, $opt_S);
|
||||
|
||||
Trace->setup(\%SIG);
|
||||
getopts('svq:p:V:C:w:S:');
|
||||
my $dbname;
|
||||
if (@ARGV == 1) {
|
||||
$dbname = shift;
|
||||
} elsif (@ARGV == 0) {
|
||||
$dbname = 'sqlports';
|
||||
} else {
|
||||
exit 1;
|
||||
}
|
||||
|
||||
my $db = DBI->connect("dbi:SQLite:dbname=$dbname", '', '', {AutoCommit => 0});
|
||||
my $inserter = Inserter->new($db, 1000, $opt_v, 1);
|
||||
|
||||
|
||||
$inserter->create_tables($Info::vars);
|
||||
|
||||
if ($opt_p) {
|
||||
$ENV{'REPORT_PROBLEM_LOGFILE'}= $opt_p;
|
||||
}
|
||||
|
||||
my $walker = MyTreeWalker->new($inserter, $opt_s, $opt_S);
|
||||
if (defined $opt_C) {
|
||||
open(my $f, '>', $opt_C) or die;
|
||||
my $cache = "PortsQ";
|
||||
say $f "DROP TABLE if exists $cache;";
|
||||
say $f Sql::Create->find('ports')->cache($cache), ";";
|
||||
say $f "INSERT INTO $cache select * from Ports;";
|
||||
say $f "ANALYZE;";
|
||||
close $f;
|
||||
}
|
||||
|
||||
if (defined $opt_w) {
|
||||
open(my $f, '>', $opt_w) or die;
|
||||
for my $v (Sql::Create->all_views) {
|
||||
say $f $v->drop, ";";
|
||||
say $f $v->stringize, ";";
|
||||
}
|
||||
close $f;
|
||||
}
|
||||
|
||||
$walker->dump_all_dirs;
|
||||
|
||||
# Create aliases, we have to sort the keys so that they are
|
||||
# created in the right pkgpath order
|
||||
for my $p (sort keys %{$walker->{equivs}}) {
|
||||
my $a = $p;
|
||||
while (defined $walker->{equivs}{$a}) {
|
||||
$a = $walker->{equivs}{$a};
|
||||
}
|
||||
$walker->inserter->add_path($p, $a);
|
||||
}
|
||||
|
||||
$walker->inserter->commit_to_db;
|
||||
$walker->inserter->insert("Meta", $opt_V, digest($dbname));
|
||||
$walker->inserter->commit_to_db;
|
||||
$db->disconnect;
|
||||
|
||||
while (my ($k, $v) = each %$Info::unknown) {
|
||||
say STDERR "Unknown variable $k in ", $v->fullpkgpath;
|
||||
}
|
||||
|
||||
if (defined $opt_q) {
|
||||
open(my $log, ">", $opt_q) or die $!;
|
||||
$walker->inserter->write_log($log);
|
||||
} else {
|
||||
$walker->inserter->write_log(\*STDERR);
|
||||
}
|
60
databases/sqlports/files/rebuild_schema
Normal file
60
databases/sqlports/files/rebuild_schema
Normal file
|
@ -0,0 +1,60 @@
|
|||
#! /usr/bin/perl
|
||||
# $OpenBSD: rebuild_schema,v 1.3 2019/03/15 11:29:53 espie Exp $
|
||||
#
|
||||
# Copyright (c) 2018 Marc Espie <espie@openbsd.org>
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# example script that shows how to store all variable values into a
|
||||
# database, using SQLite for that purpose.
|
||||
#
|
||||
# usage: cd /usr/ports && mksqlitedb
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use FindBin;
|
||||
use lib $FindBin::Bin;
|
||||
use Getopt::Std;
|
||||
use Var;
|
||||
use Inserter;
|
||||
use DBI;
|
||||
use PkgPath;
|
||||
use Info;
|
||||
use Trace;
|
||||
|
||||
|
||||
package main;
|
||||
|
||||
our ($opt_v, $opt_q, $opt_p, $opt_V);
|
||||
|
||||
Trace->setup(\%SIG);
|
||||
getopts('vq:p:V:');
|
||||
my $dbname;
|
||||
if (@ARGV == 1) {
|
||||
$dbname = shift;
|
||||
} elsif (@ARGV == 0) {
|
||||
$dbname = 'sqlports';
|
||||
} else {
|
||||
exit 1;
|
||||
}
|
||||
|
||||
my $db = DBI->connect("dbi:SQLite:dbname=$dbname", '', '', {AutoCommit => 0});
|
||||
my $inserter = Inserter->new($db, 1000, $opt_v, 0);
|
||||
|
||||
|
||||
$inserter->create_tables($Info::vars);
|
||||
|
||||
my $stmt = $db->prepare("UPDATE Meta set SchemaVersion=?");
|
||||
$stmt->execute($opt_V);
|
||||
|
||||
$inserter->commit_to_db;
|
37
databases/sqlports/files/scripts/normalize-schema
Executable file
37
databases/sqlports/files/scripts/normalize-schema
Executable file
|
@ -0,0 +1,37 @@
|
|||
#! /usr/bin/perl
|
||||
|
||||
# a small script that takes a sqlite3 schema and creates
|
||||
# a normalized version (zaps extraneous spaces, rewrites
|
||||
# everything as lowercase, sorts by table/view name)
|
||||
|
||||
use v5.36;
|
||||
|
||||
my ($object, $comment);
|
||||
|
||||
my $stmt = '';
|
||||
while(<STDIN>) {
|
||||
chomp;
|
||||
$stmt .= " ".lc($_);
|
||||
if (m/\;/) {
|
||||
$stmt =~ s/\s+/ /g;
|
||||
$stmt =~ s/^\s//;
|
||||
$stmt =~ s/\s?\(\s?/\(/g;
|
||||
$stmt =~ s/\s?\)\s?/\)/g;
|
||||
if ($stmt =~ m/^create table (\S+)/) {
|
||||
$object->{$1} = $stmt;
|
||||
} elsif ($stmt =~ m/^create view (\S+)/) {
|
||||
$object->{$1} = $stmt;
|
||||
} else {
|
||||
say $stmt;
|
||||
}
|
||||
$stmt = '';
|
||||
}
|
||||
}
|
||||
|
||||
for my $k (sort keys %$object) {
|
||||
if ($object->{$k} =~ m,\s/\*,) {
|
||||
say "$`\n/*$'\n";
|
||||
} else {
|
||||
say $object->{$k}, "\n";
|
||||
}
|
||||
}
|
64
databases/sqlports/files/scripts/print-ports-index
Normal file
64
databases/sqlports/files/scripts/print-ports-index
Normal file
|
@ -0,0 +1,64 @@
|
|||
#! /bin/sh
|
||||
# $OpenBSD: print-ports-index,v 1.12 2019/07/14 11:27:19 espie Exp $
|
||||
#
|
||||
# Copyright (c) 2018 Marc Espie <espie@openbsd.org>
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# recreate index file, identical to /usr/ports/INDEX
|
||||
set -e
|
||||
|
||||
if [ $# -ge 1 ]
|
||||
then
|
||||
file=$1
|
||||
else
|
||||
file=${TRUEPREFIX}/share/sqlports
|
||||
fi
|
||||
cat <<'EOSQL' |sqlite3 $file
|
||||
-- in order for group_concat to sort, you must do it in two steps
|
||||
with
|
||||
d1 (d, p, t) as
|
||||
(select
|
||||
distinct((case pkgspec when '' then '' else pkgspec||":" end)||_paths.fullpkgpath) as fd,
|
||||
_depends.fullpkgpath, type
|
||||
from _depends join _paths on _Paths.Id=_depends.dependspath order by fd),
|
||||
-- and now the part that's going to be used 3 times in the main request
|
||||
d2 as
|
||||
(select group_concat(d, ' ') as dlist, p, t
|
||||
from d1 group by p, t)
|
||||
select fullpkgname, ports.fullpkgpath,
|
||||
(case prefix when '/usr/local' THEN "" else prefix end),
|
||||
comment,descr, maintainer,categories,
|
||||
libd.dlist, buildd.dlist, rund.dlist,
|
||||
|
||||
|
||||
case 1
|
||||
when only_for_archs is null then
|
||||
case 1
|
||||
when not_for_archs is null
|
||||
then 'any'
|
||||
else '!'||not_for_archs
|
||||
end
|
||||
else only_for_archs
|
||||
end,
|
||||
'?',
|
||||
(case lower(PERMIT_PACKAGE) when "yes" then "y" else "n" end),
|
||||
(case lower(PERMIT_DISTFILES) when "yes" then "y" else "n" end)
|
||||
from ports
|
||||
left join d2 as libd on libd.p=ports.pathid and libd.t=0
|
||||
left join d2 as buildd on buildd.p=ports.pathid and buildd.t=2
|
||||
left join d2 as rund on rund.p=ports.pathid and rund.t=1
|
||||
where ports.pathid in (select distinct canonical from _paths)
|
||||
group by ports.fullpkgpath
|
||||
order by ports.fullpkgpath;
|
||||
EOSQL
|
25
databases/sqlports/files/scripts/rebuild-sqlports-cache
Normal file
25
databases/sqlports/files/scripts/rebuild-sqlports-cache
Normal file
|
@ -0,0 +1,25 @@
|
|||
#! /bin/sh
|
||||
# $OpenBSD: rebuild-sqlports-cache,v 1.2 2019/06/04 16:05:52 espie Exp $
|
||||
#
|
||||
# Copyright (c) 2019 Marc Espie <espie@openbsd.org>
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
set -e
|
||||
if [ $# -ge 1 ]
|
||||
then
|
||||
file=$1
|
||||
else
|
||||
file=${TRUEPREFIX}/share/sqlports
|
||||
fi
|
||||
sqlite3 $file <${TRUEPREFIX}/share/sqlports_cache.sql
|
106
databases/sqlports/files/scripts/show-reverse-deps
Normal file
106
databases/sqlports/files/scripts/show-reverse-deps
Normal file
|
@ -0,0 +1,106 @@
|
|||
#! /bin/sh
|
||||
# $OpenBSD: show-reverse-deps,v 1.10 2020/06/11 19:55:15 espie Exp $
|
||||
#
|
||||
# Copyright (c) 2018 Marc Espie <espie@openbsd.org>
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# compute reverse dependencies
|
||||
# XXX this is not perfect yet! it *does* require collating lib-depends over
|
||||
# multi-packages setup, which this is NOT doing yet, but it is close to
|
||||
# actually doing it.
|
||||
# we just require a few more views for that.
|
||||
|
||||
usage="Usage: show-reverse-deps [-ftv] [-d sqlite_db] pkgpath"
|
||||
args=`getopt d:ftv $*`
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo 2>&1 $usage
|
||||
fi
|
||||
set -e
|
||||
|
||||
db=${TRUEPREFIX}/share/sqlports
|
||||
type_root="root.type!=3"
|
||||
type_child="child.type!=3"
|
||||
fuzzy=false
|
||||
verbose=false
|
||||
|
||||
set -- $args
|
||||
while [ $# -ne 0 ]
|
||||
do
|
||||
case "$1" in
|
||||
-d)
|
||||
db="$2"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
-f)
|
||||
fuzzy=true
|
||||
shift
|
||||
;;
|
||||
-t)
|
||||
type_root=true
|
||||
type_child=true
|
||||
shift
|
||||
;;
|
||||
-v)
|
||||
verbose=true
|
||||
shift
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -ne 1 ]
|
||||
then
|
||||
echo 2>&1 $usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if $fuzzy
|
||||
then
|
||||
query="p2.fullpkgpath like \"%$1%\""
|
||||
else
|
||||
query="p2.fullpkgpath=\"$1\""
|
||||
fi
|
||||
if $verbose
|
||||
then
|
||||
adj=", _paths2.fullpkgpath, case d.type when 0 then 'LIB_DEPENDS' when 1 then 'RUN_DEPENDS' when 2 then 'BUILD_DEPENDS' when 3 then 'TEST_DEPENDS' end"
|
||||
join_adj="join _paths _paths2 on _paths2.id=d.dependspath"
|
||||
else
|
||||
adj=""
|
||||
join_adj=""
|
||||
fi
|
||||
|
||||
sqlite3 "$db" <<EOSQL
|
||||
with recursive d (fullpkgpath, dependspath, type) as
|
||||
(select root.fullpkgpath, root.dependspath, root.type
|
||||
from _canonical_depends root
|
||||
join _paths
|
||||
on root.dependspath=_paths.canonical
|
||||
join _paths p2
|
||||
on $query and p2.id=_paths.pkgpath
|
||||
where $type_root
|
||||
union
|
||||
select child.fullpkgpath, child.dependspath, child.type
|
||||
from d parent, _canonical_depends child
|
||||
where parent.fullpkgpath=child.dependspath and $type_child)
|
||||
select distinct _paths.fullpkgpath $adj from d
|
||||
join _paths
|
||||
on _paths.id=d.fullpkgpath
|
||||
$join_adj
|
||||
order by _paths.fullpkgpath $adj;
|
||||
EOSQL
|
3
databases/sqlports/pkg/DESCR-list
Normal file
3
databases/sqlports/pkg/DESCR-list
Normal file
|
@ -0,0 +1,3 @@
|
|||
Reduced list of every fullpkgpath reachable in the ports tree, with
|
||||
duplicate pkgnames removed, and with ports without static plists taken
|
||||
out.
|
12
databases/sqlports/pkg/DESCR-main
Normal file
12
databases/sqlports/pkg/DESCR-main
Normal file
|
@ -0,0 +1,12 @@
|
|||
SQLite database of every port in the system. This can be queried through
|
||||
e.g., sqlitebrowser, or any kind of programming interface.
|
||||
|
||||
This schema is mostly optimized for tools, and cumbersome to query by
|
||||
hand.
|
||||
|
||||
Human users are strongly advised to mostly use views on those tables.
|
||||
|
||||
The default flavor only looks in PORTSDIR, use nonstrict to heed
|
||||
PORTSDIR_PATH fully.
|
||||
|
||||
The database scheme is documented in sqlports(5)
|
3
databases/sqlports/pkg/PLIST-list
Normal file
3
databases/sqlports/pkg/PLIST-list
Normal file
|
@ -0,0 +1,3 @@
|
|||
@option always-update
|
||||
share/ports-INDEX
|
||||
share/sqlports.list
|
10
databases/sqlports/pkg/PLIST-main
Normal file
10
databases/sqlports/pkg/PLIST-main
Normal file
|
@ -0,0 +1,10 @@
|
|||
@option always-update
|
||||
@conflict sqlports-compact-<7.0
|
||||
@pkgpath databases/sqlports,-compact
|
||||
bin/print-ports-index
|
||||
bin/rebuild-sqlports-cache
|
||||
bin/show-reverse-deps
|
||||
@man man/man1/show-reverse-deps.1
|
||||
@man man/man5/sqlports.5
|
||||
share/sqlports
|
||||
share/sqlports_cache.sql
|
Loading…
Add table
Add a link
Reference in a new issue