Commit b7f9f9bd authored by Timo Teräs's avatar Timo Teräs

info: implement who owns packages query (apk_info -W)

In quiet mode e.g. "apk info -q -W <file list>" a list of dependencies
suitable for .PKGINFO is output in one line.
parent c831ead6
- list of files on stdin, minimum dependencies on stdout
- way to test if packages is installed
- confirm whether to act (show changeset-size, installed, removed) if
other packages affected then the ones explicitly specified
......@@ -19,6 +16,9 @@
- Error handling and rollback
- Dependency manipulation API: deletion, overwrite, check compatibility
- Change fdb internally to has according to full filename (that's what we
use to lookup in install_archive_entry and also in info -W)
- New user/group creation
- Non-trivial solution finder
......
......@@ -102,6 +102,7 @@ void apk_db_close(struct apk_database *db);
struct apk_package *apk_db_pkg_add_file(struct apk_database *db, const char *file);
struct apk_package *apk_db_get_pkg(struct apk_database *db, csum_t sum);
struct apk_package *apk_db_get_file_owner(struct apk_database *db, apk_blob_t filename);
void apk_db_index_write(struct apk_database *db, struct apk_ostream *os);
......
......@@ -135,6 +135,12 @@ static struct apk_db_dir *apk_db_dir_get(struct apk_db_dir *dir)
return dir;
}
static struct apk_db_dir *apk_db_dir_query(struct apk_database *db,
apk_blob_t name)
{
return (struct apk_db_dir *) apk_hash_get(&db->installed.dirs, name);
}
static struct apk_db_dir *apk_db_dir_get_db(struct apk_database *db,
apk_blob_t name)
{
......@@ -145,7 +151,7 @@ static struct apk_db_dir *apk_db_dir_get_db(struct apk_database *db,
if (name.len && name.ptr[name.len-1] == '/')
name.len--;
dir = (struct apk_db_dir *) apk_hash_get(&db->installed.dirs, name);
dir = apk_db_dir_query(db, name);
if (dir != NULL)
return apk_db_dir_get(dir);
......@@ -643,6 +649,8 @@ static int apk_db_write_config(struct apk_database *db)
if (os == NULL)
return -1;
n = apk_deps_format(buf, sizeof(buf), db->world);
if (n < sizeof(buf))
buf[n++] = '\n';
os->write(os, buf, n);
os->close(os);
......@@ -677,7 +685,6 @@ void apk_db_close(struct apk_database *db)
}
}
for (i = 0; i < db->num_repos; i++)
free(db->repos[i].url);
for (i = 0; i < db->protected_paths->num; i++)
......@@ -700,6 +707,33 @@ struct apk_package *apk_db_get_pkg(struct apk_database *db, csum_t sum)
APK_BLOB_PTR_LEN((void*) sum, sizeof(csum_t)));
}
struct apk_package *apk_db_get_file_owner(struct apk_database *db,
apk_blob_t filename)
{
apk_blob_t dir, file;
struct apk_db_dir *ddir;
struct apk_db_file *dfile;
struct hlist_node *cur;
if (!apk_blob_rsplit(filename, '/', &dir, &file))
return NULL;
if (dir.ptr[0] == '/')
dir.ptr++, dir.len--;
ddir = apk_db_dir_query(db, dir);
if (ddir == NULL)
return NULL;
hlist_for_each_entry(dfile, cur, &ddir->files, dir_files_list) {
if (strncmp(dfile->filename, file.ptr, file.len) == 0 &&
dfile->filename[file.len] == 0)
return dfile->diri->pkg;
}
return NULL;
}
struct apk_package *apk_db_pkg_add_file(struct apk_database *db, const char *file)
{
struct apk_package *info;
......@@ -901,7 +935,7 @@ static int apk_db_install_archive_entry(void *_ctx,
ctx->diri = diri;
}
file = apk_db_file_get(db, name, ctx);
file = apk_db_file_get(db, bfile, ctx);
if (file == NULL) {
apk_error("%s: Failed to create fdb entry for '%*s'\n",
pkg->name->name, name.len, name.ptr);
......
......@@ -54,6 +54,38 @@ static int info_exists(struct apk_database *db, int argc, char **argv)
return 0;
}
static int info_who_owns(struct apk_database *db, int argc, char **argv)
{
struct apk_package *pkg;
struct apk_dependency_array *deps = NULL;
struct apk_dependency dep;
int i;
for (i = 0; i < argc; i++) {
pkg = apk_db_get_file_owner(db, APK_BLOB_STR(argv[i]));
if (pkg == NULL)
continue;
if (apk_quiet) {
dep = (struct apk_dependency) {
.name = pkg->name,
};
apk_deps_add(&deps, &dep);
} else {
printf("%s is owned by %s-%s\n", argv[i],
pkg->name->name, pkg->version);
}
}
if (apk_quiet && deps != NULL) {
char buf[512];
apk_deps_format(buf, sizeof(buf), deps);
printf("%s\n", buf);
free(deps);
}
return 0;
}
static int info_parse(void *ctx, int optch, int optindex, const char *optarg)
{
struct info_ctx *ictx = (struct info_ctx *) ctx;
......@@ -62,6 +94,9 @@ static int info_parse(void *ctx, int optch, int optindex, const char *optarg)
case 'e':
ictx->action = info_exists;
break;
case 'W':
ictx->action = info_who_owns;
break;
default:
return -1;
}
......@@ -88,6 +123,7 @@ static int info_main(void *ctx, int argc, char **argv)
static struct option info_options[] = {
{ "installed", no_argument, NULL, 'e' },
{ "who-owns", no_argument, NULL, 'W' },
};
static struct apk_applet apk_info = {
......
......@@ -141,13 +141,13 @@ int apk_deps_format(char *buf, int size,
if (depends == NULL)
return 0;
for (i = 0; i < depends->num - 1; i++)
for (i = 0; i < depends->num; i++) {
if (i && n < size)
buf[n++] = ' ';
n += snprintf(&buf[n], size-n,
"%s ",
"%s",
depends->item[i].name->name);
n += snprintf(&buf[n], size-n,
"%s\n",
depends->item[i].name->name);
}
return n;
}
......@@ -545,6 +545,8 @@ apk_blob_t apk_pkg_format_index_entry(struct apk_package *info, int size,
if (info->depends != NULL) {
n += snprintf(&buf[n], size-n, "D:");
n += apk_deps_format(&buf[n], size-n, info->depends);
if (n < size)
buf[n++] = '\n';
}
n += snprintf(&buf[n], size-n, "C:");
n += apk_hexdump_format(size-n, &buf[n],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment