Compare commits

...

30 Commits

Author SHA1 Message Date
Dylan Baker 90232914cd ci: run meson test with the address sanitizer enabled
Set the ASAN_OPTION so that the exitcode is not 1, this avoids asan
returning the exitcode that the tests already expect from a normal
pkgconf error
2022-08-04 15:22:29 -07:00
Dylan Baker 576ef1b949 pkg: prevent circular ownership
Otherwise in a case where A references B, and B references A, A and B
will have mutual ownership of each other and prevent each other from
being free'd.
2022-08-04 15:21:52 -07:00
Dylan Baker d3237407c4 queue: free unused dependencies when flattening 2022-08-04 15:21:52 -07:00
Dylan Baker 3bcf96dd01 dependency: zero list after freeing 2022-08-04 15:19:19 -07:00
Dylan Baker 1ac1cb51af dependency: add debug information for dependency refcounting 2022-08-04 15:19:19 -07:00
Dylan Baker c8933409aa pkg: add name of pkg being refed/unrefed to debug outpu 2022-08-04 15:19:19 -07:00
Dylan Baker f083d8d448 queue: when collecting dependents don't iterate private twice
Currently, the private field is iterated collecting private deps and
normal deps. It should only be iterated when collecting private deps.
2022-08-04 15:19:14 -07:00
Dylan Baker 7c671b155d main: do cleanup when checking required version 2022-08-04 15:19:05 -07:00
Dylan Baker 7fe770bec7 pkg: use goto cleanup idiom 2022-08-04 15:19:05 -07:00
Dylan Baker b26f19cebf main: goto cleanup in validate case too
This fixes leaks in two tests
2022-08-04 15:19:05 -07:00
Dylan Baker 2133830c21 cache: clear the cache with pkgconf_cache_remove
Which results in more code re-use.
2022-08-04 15:19:05 -07:00
Dylan Baker 2b310c570f queue: when flattening do nothing if the flattened deps are empty 2022-08-04 15:19:05 -07:00
Dylan Baker 43d5328575 queue: unref dependency in all cases 2022-08-04 15:19:05 -07:00
Dylan Baker 04a3346b8e queue: ensure cleanup happens when applying 2022-08-04 15:19:05 -07:00
Dylan Baker 388bd61a61 dependency: Fix reference counting of dependency_addraw
We only want a reference to be added for the value inserted into the
list, not the one returned. The returned one is unowned until it reaches
the public dependency_add function, which returns an owned pointer
instead. This makes things semantically more correct.

Unfortunately, this means in a few cases we have to write some ugly
code like:
```c
pkgconf_dependency_t *dep = pkgcond_dependency_add("args");
pkgconf_dependency_unref(dep->owner, dep);
```
2022-08-04 15:19:05 -07:00
Dylan Baker e41e464152 cache: when removing a package from the cache unset the cached flag 2022-08-03 15:53:16 -07:00
Dylan Baker 01c3e6f8b5 cache: free the cache table when it is empty and set to NULL
We do the latter for the benefit of libpkgconf. This cleans up a
significant number of memory leaks in the cache handling.
2022-08-03 15:53:16 -07:00
Dylan Baker 125a13d3b9 meson: add -Wmisleading-indentation
A useful warning when loop and conditional statements are allowed
without braces.
2022-08-03 12:03:15 -07:00
Dylan Baker 96c61cbab0 libpkgconf: remove trailing ; from macro definition
GCC has a lovely bug (which I will report as soon as I have an account),
which causes -Wmisleading-indentation to miss cases of misleading
indentation after a `;;`, since the macro adds `;`, and in call cases
the caller also adds `;`, we end up with a double macro and gcc fails to
warn.
2022-08-03 12:03:15 -07:00
Ariadne Conill a042827951 Merge pull request 'meson cleanups and fixes' (#240) from dcbaker/pkgconf:submit/meson-cleanups into master
Reviewed-on: ariadne/pkgconf#240
2022-08-02 23:09:24 +00:00
Dylan Baker dd779ad9f8 meson: add check to run_command
Because we really should be checking that it succeeds, and because not
setting it is deprecated.
2022-08-01 09:40:08 -07:00
Dylan Baker c04097e491 meson: pass configured files idiomatically
Instead of attempting to figure out what the paths will be, take the
returned file object and pass that around, meson will then automatically
figure out the correct paths.
2022-08-01 09:40:08 -07:00
Dylan Baker 06fe2e23b0 meson: use current_source_dir and current_build_dir instead of *_root
The latter doesn't work correctly when being used as a subproject, as it
returns the *absolute* root. So if pkgconf is being built as part of
muon, then it will return muon's source root. current_source_dir, on the
other hand returns the directory correctly whether being built as a
subproject or superproject.
2022-08-01 09:40:08 -07:00
Dylan Baker 1f993bc095 meson: use string methods to avoid repeating data
Instead of writing `['HAVE_FOO_H', 'foo.h']`, use meson's string methods
to just write `['foo.h']`, and let meson create `HAVE_FOO_H` for us.
2022-08-01 09:40:08 -07:00
Dylan Baker f947af057f meson: use str.format for improved readability 2022-08-01 09:40:08 -07:00
Dylan Baker 5ba74dec93 meson: use straight indexing instead of array.get()
It's more terse, and we don't need the support of a fallback value.
2022-08-01 09:40:08 -07:00
Dylan Baker bf307c1d95 ci: set meson to build with -Werror
This will help catch any new warnings added in CI.
2022-08-01 09:40:08 -07:00
Dylan Baker 4a2c9c285f meson: use C99 as the standard
autoconf uses either C99 or Gnu99. Meson does not provide a graceful way
to select gnu99 if possible or c99 (though there are several proposals
currently happening to get there), so I've selected c99 as the
conservative default. Without this, the compiler uses whatever it's
default happens to be, which may or may not work out correctly, and
hides bugs from CI that are present with c99 as the default.
2022-07-29 10:23:18 -07:00
Dylan Baker 40ec08594e meson: add warning for implicit-function-declarations
This would be triggered without the previous addition of -D_BSD_SOURCE
for strdup, among others
2022-07-29 10:23:18 -07:00
Dylan Baker 71974d8c54 meson: Add _BSD_SOURCE and _DEFAULT_SOURCE
To avoid warnings about string functions like strdup which are otherwise
undefined, but succeed at linking anyway when the C standard is c99.
2022-07-29 10:23:02 -07:00
11 changed files with 188 additions and 105 deletions

View File

@ -53,13 +53,37 @@ jobs:
- name: Build - name: Build
run: | run: |
meson _build meson _build -Dwerror=true
meson compile -C _build meson compile -C _build
- name: Run tests - name: Run tests
run: | run: |
meson test -v -C _build meson test -v -C _build
debian-meson-asan:
runs-on: ubuntu-latest
container:
image: debian:testing
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Update system and add dependencies
run: |
apt-get update
apt-get install -y kyua atf-sh build-essential meson
- name: Build
run: |
meson _build -Db_sanitize=address
meson compile -C _build
- name: Run tests
run: |
meson test -v -C _build
env:
ASAN_OPTIONS: "exitcode=7"
debian-autotools: debian-autotools:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: container:
@ -98,7 +122,7 @@ jobs:
- name: Build - name: Build
run: | run: |
meson _build meson _build -Dwerror=true
meson compile -C _build meson compile -C _build
- name: Run tests - name: Run tests

View File

@ -4,7 +4,22 @@ pipeline:
commands: commands:
- apt-get update - apt-get update
- apt-get install -y kyua atf-sh build-essential meson - apt-get install -y kyua atf-sh build-essential meson
- meson _build - meson _build -Dwerror=true
- meson compile -C _build
- meson test -v -C _build
when:
matrix:
IMAGE: debian
BUILD: meson
debian-meson-asan:
image: debian:testing
environment:
- ASAN_OPTIONS="exitcode=7"
commands:
- apt-get update
- apt-get install -y kyua atf-sh build-essential meson
- meson _build -Db_sanitize=address
- meson compile -C _build - meson compile -C _build
- meson test -v -C _build - meson test -v -C _build
when: when:
@ -30,7 +45,7 @@ pipeline:
image: alpine image: alpine
commands: commands:
- apk add -U --no-cache kyua atf build-base meson - apk add -U --no-cache kyua atf build-base meson
- meson _build - meson _build -Dwerror=true
- meson compile -C _build - meson compile -C _build
- meson test -v -C _build - meson test -v -C _build
when: when:

View File

@ -1183,17 +1183,21 @@ main(int argc, char *argv[])
pkgconf_error(&pkg_client, "Package '%s' was not found\n", pkgiter->package); pkgconf_error(&pkg_client, "Package '%s' was not found\n", pkgiter->package);
ret = EXIT_FAILURE; ret = EXIT_FAILURE;
goto out; goto cleanup;
} }
if (pkgconf_compare_version(pkg->version, required_module_version) >= 0) if (pkgconf_compare_version(pkg->version, required_module_version) >= 0)
{ {
ret = EXIT_SUCCESS; ret = EXIT_SUCCESS;
goto out; goto cleanup;
} }
} }
ret = EXIT_FAILURE; ret = EXIT_FAILURE;
cleanup:
if (pkg)
pkgconf_pkg_unref(&pkg_client, pkg);
pkgconf_dependency_free(&deplist);
goto out; goto out;
} }
else if (required_exact_module_version != NULL) else if (required_exact_module_version != NULL)
@ -1219,17 +1223,21 @@ main(int argc, char *argv[])
pkgconf_error(&pkg_client, "Package '%s' was not found\n", pkgiter->package); pkgconf_error(&pkg_client, "Package '%s' was not found\n", pkgiter->package);
ret = EXIT_FAILURE; ret = EXIT_FAILURE;
goto out; goto cleanup2;
} }
if (pkgconf_compare_version(pkg->version, required_exact_module_version) == 0) if (pkgconf_compare_version(pkg->version, required_exact_module_version) == 0)
{ {
ret = EXIT_SUCCESS; ret = EXIT_SUCCESS;
goto out; goto cleanup2;
} }
} }
ret = EXIT_FAILURE; ret = EXIT_FAILURE;
cleanup2:
if (pkg)
pkgconf_pkg_unref(&pkg_client, pkg);
pkgconf_dependency_free(&deplist);
goto out; goto out;
} }
else if (required_max_module_version != NULL) else if (required_max_module_version != NULL)
@ -1255,17 +1263,21 @@ main(int argc, char *argv[])
pkgconf_error(&pkg_client, "Package '%s' was not found\n", pkgiter->package); pkgconf_error(&pkg_client, "Package '%s' was not found\n", pkgiter->package);
ret = EXIT_FAILURE; ret = EXIT_FAILURE;
goto out; goto cleanup3;
} }
if (pkgconf_compare_version(pkg->version, required_max_module_version) <= 0) if (pkgconf_compare_version(pkg->version, required_max_module_version) <= 0)
{ {
ret = EXIT_SUCCESS; ret = EXIT_SUCCESS;
goto out; goto cleanup3;
} }
} }
ret = EXIT_FAILURE; ret = EXIT_FAILURE;
cleanup3:
if (pkg)
pkgconf_pkg_unref(&pkg_client, pkg);
pkgconf_dependency_free(&deplist);
goto out; goto out;
} }
@ -1337,7 +1349,7 @@ main(int argc, char *argv[])
} }
if ((want_flags & PKG_VALIDATE) == PKG_VALIDATE) if ((want_flags & PKG_VALIDATE) == PKG_VALIDATE)
return 0; goto out;
if ((want_flags & PKG_UNINSTALLED) == PKG_UNINSTALLED) if ((want_flags & PKG_UNINSTALLED) == PKG_UNINSTALLED)
{ {

View File

@ -16,6 +16,8 @@
#include <libpkgconf/stdinc.h> #include <libpkgconf/stdinc.h>
#include <libpkgconf/libpkgconf.h> #include <libpkgconf/libpkgconf.h>
#include <assert.h>
/* /*
* !doc * !doc
* *
@ -86,6 +88,9 @@ cache_dump(const pkgconf_client_t *client)
pkgconf_pkg_t * pkgconf_pkg_t *
pkgconf_cache_lookup(pkgconf_client_t *client, const char *id) pkgconf_cache_lookup(pkgconf_client_t *client, const char *id)
{ {
if (client->cache_table == NULL)
return NULL;
pkgconf_pkg_t **pkg; pkgconf_pkg_t **pkg;
pkg = bsearch(id, client->cache_table, pkg = bsearch(id, client->cache_table,
@ -150,6 +155,9 @@ pkgconf_cache_add(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
void void
pkgconf_cache_remove(pkgconf_client_t *client, pkgconf_pkg_t *pkg) pkgconf_cache_remove(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
{ {
if (client->cache_table == NULL)
return;
if (pkg == NULL) if (pkg == NULL)
return; return;
@ -167,6 +175,8 @@ pkgconf_cache_remove(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
if (slot == NULL) if (slot == NULL)
return; return;
(*slot)->flags &= ~PKGCONF_PKG_PROPF_CACHED;
pkgconf_pkg_unref(client, *slot);
*slot = NULL; *slot = NULL;
qsort(client->cache_table, client->cache_count, qsort(client->cache_table, client->cache_count,
@ -181,19 +191,15 @@ pkgconf_cache_remove(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
} }
client->cache_count--; client->cache_count--;
client->cache_table = pkgconf_reallocarray(client->cache_table, if (client->cache_count > 0)
client->cache_count, sizeof(void *));
}
static inline void
clear_dependency_matches(pkgconf_list_t *list)
{
pkgconf_node_t *iter;
PKGCONF_FOREACH_LIST_ENTRY(list->head, iter)
{ {
pkgconf_dependency_t *dep = iter->data; client->cache_table = pkgconf_reallocarray(client->cache_table,
dep->match = NULL; client->cache_count, sizeof(void *));
}
else
{
free(client->cache_table);
client->cache_table = NULL;
} }
} }
@ -211,30 +217,15 @@ clear_dependency_matches(pkgconf_list_t *list)
void void
pkgconf_cache_free(pkgconf_client_t *client) pkgconf_cache_free(pkgconf_client_t *client)
{ {
pkgconf_pkg_t **cache_table; if (client->cache_table == NULL)
size_t i, count; return;
cache_table = pkgconf_reallocarray(NULL, client->cache_count, sizeof (void *)); while (client->cache_count > 0)
memcpy(cache_table, client->cache_table, pkgconf_cache_remove(client, client->cache_table[0]);
client->cache_count * sizeof (void *));
/* first we clear cached match pointers */ free(client->cache_table);
for (i = 0, count = client->cache_count; i < count; i++) client->cache_table = NULL;
{ client->cache_count = 0;
pkgconf_pkg_t *pkg = cache_table[i];
clear_dependency_matches(&pkg->required);
clear_dependency_matches(&pkg->requires_private);
clear_dependency_matches(&pkg->provides);
clear_dependency_matches(&pkg->conflicts);
}
/* now forcibly free everything */
for (i = 0, count = client->cache_count; i < count; i++)
{
pkgconf_pkg_t *pkg = cache_table[i];
pkgconf_pkg_free(client, pkg);
}
PKGCONF_TRACE(client, "cleared package cache"); PKGCONF_TRACE(client, "cleared package cache");
} }

View File

@ -98,6 +98,8 @@ pkgconf_client_init(pkgconf_client_t *client, pkgconf_error_handler_func_t error
client->error_handler_data = error_handler_data; client->error_handler_data = error_handler_data;
client->error_handler = error_handler; client->error_handler = error_handler;
client->auditf = NULL; client->auditf = NULL;
client->cache_table = NULL;
client->cache_count = 0;
#ifndef PKGCONF_LITE #ifndef PKGCONF_LITE
if (client->trace_handler == NULL) if (client->trace_handler == NULL)

View File

@ -113,9 +113,16 @@ add_or_replace_dependency_node(pkgconf_client_t *client, pkgconf_dependency_t *d
} }
PKGCONF_TRACE(client, "added dependency [%s] to list @%p; flags=%x", dependency_to_str(dep, depbuf, sizeof depbuf), list, dep->flags); PKGCONF_TRACE(client, "added dependency [%s] to list @%p; flags=%x", dependency_to_str(dep, depbuf, sizeof depbuf), list, dep->flags);
pkgconf_node_insert_tail(&dep->iter, dep, list); pkgconf_node_insert_tail(&dep->iter, pkgconf_dependency_ref(dep->owner, dep), list);
return pkgconf_dependency_ref(dep->owner, dep); /* This dependency is intentionally unowned.
*
* Internally we have no use for the returned type, and usually just
* discard it. However, there is a publig pkgconf_dependency_add
* function, which references this return value before returning it,
* giving ownership at that point.
*/
return dep;
} }
static inline pkgconf_dependency_t * static inline pkgconf_dependency_t *
@ -156,10 +163,10 @@ pkgconf_dependency_addraw(pkgconf_client_t *client, pkgconf_list_t *list, const
pkgconf_dependency_t * pkgconf_dependency_t *
pkgconf_dependency_add(pkgconf_client_t *client, pkgconf_list_t *list, const char *package, const char *version, pkgconf_pkg_comparator_t compare, unsigned int flags) pkgconf_dependency_add(pkgconf_client_t *client, pkgconf_list_t *list, const char *package, const char *version, pkgconf_pkg_comparator_t compare, unsigned int flags)
{ {
if (version != NULL) pkgconf_dependency_t *dep;
return pkgconf_dependency_addraw(client, list, package, strlen(package), version, strlen(version), compare, flags); dep = pkgconf_dependency_addraw(client, list, package, strlen(package), version,
version != NULL ? strlen(version) : 0, compare, flags);
return pkgconf_dependency_addraw(client, list, package, strlen(package), NULL, 0, compare, flags); return pkgconf_dependency_ref(dep->owner, dep);
} }
/* /*
@ -222,6 +229,7 @@ pkgconf_dependency_ref(pkgconf_client_t *client, pkgconf_dependency_t *dep)
return NULL; return NULL;
dep->refcount++; dep->refcount++;
PKGCONF_TRACE(client, "%s refcount@%p: %d", dep->package, dep, dep->refcount);
return dep; return dep;
} }
@ -242,7 +250,10 @@ pkgconf_dependency_unref(pkgconf_client_t *client, pkgconf_dependency_t *dep)
if (client != dep->owner) if (client != dep->owner)
return; return;
if (--dep->refcount <= 0) --dep->refcount;
PKGCONF_TRACE(client, "%s refcount@%p: %d", dep->package, dep, dep->refcount);
if (dep->refcount <= 0)
pkgconf_dependency_free_one(dep); pkgconf_dependency_free_one(dep);
} }
@ -268,6 +279,8 @@ pkgconf_dependency_free(pkgconf_list_t *list)
pkgconf_node_delete(&dep->iter, list); pkgconf_node_delete(&dep->iter, list);
pkgconf_dependency_unref(dep->owner, dep); pkgconf_dependency_unref(dep->owner, dep);
} }
pkgconf_list_zero(list);
} }
/* /*

View File

@ -298,11 +298,11 @@ PKGCONF_API bool pkgconf_default_error_handler(const char *msg, const pkgconf_cl
#if defined(__GNUC__) || defined(__INTEL_COMPILER) #if defined(__GNUC__) || defined(__INTEL_COMPILER)
#define PKGCONF_TRACE(client, ...) do { \ #define PKGCONF_TRACE(client, ...) do { \
pkgconf_trace(client, __FILE__, __LINE__, __PRETTY_FUNCTION__, __VA_ARGS__); \ pkgconf_trace(client, __FILE__, __LINE__, __PRETTY_FUNCTION__, __VA_ARGS__); \
} while (0); } while (0)
#else #else
#define PKGCONF_TRACE(client, ...) do { \ #define PKGCONF_TRACE(client, ...) do { \
pkgconf_trace(client, __FILE__, __LINE__, __func__, __VA_ARGS__); \ pkgconf_trace(client, __FILE__, __LINE__, __func__, __VA_ARGS__); \
} while (0); } while (0)
#endif #endif
#else #else
#define PKGCONF_TRACE(client, ...) #define PKGCONF_TRACE(client, ...)

View File

@ -451,7 +451,8 @@ pkgconf_pkg_new_from_file(pkgconf_client_t *client, const char *filename, FILE *
return NULL; return NULL;
} }
pkgconf_dependency_add(client, &pkg->provides, pkg->id, pkg->version, PKGCONF_CMP_EQUAL, 0); pkgconf_dependency_t *dep = pkgconf_dependency_add(client, &pkg->provides, pkg->id, pkg->version, PKGCONF_CMP_EQUAL, 0);
pkgconf_dependency_unref(dep->owner, dep);
return pkgconf_pkg_ref(client, pkg); return pkgconf_pkg_ref(client, pkg);
} }
@ -536,7 +537,7 @@ pkgconf_pkg_ref(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
PKGCONF_TRACE(client, "WTF: client %p refers to package %p owned by other client %p", client, pkg, pkg->owner); PKGCONF_TRACE(client, "WTF: client %p refers to package %p owned by other client %p", client, pkg, pkg->owner);
pkg->refcount++; pkg->refcount++;
PKGCONF_TRACE(client, "refcount@%p: %d", pkg, pkg->refcount); PKGCONF_TRACE(client, "%s refcount@%p: %d", pkg->id, pkg, pkg->refcount);
return pkg; return pkg;
} }
@ -559,7 +560,7 @@ pkgconf_pkg_unref(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
PKGCONF_TRACE(client, "WTF: client %p unrefs package %p owned by other client %p", client, pkg, pkg->owner); PKGCONF_TRACE(client, "WTF: client %p unrefs package %p owned by other client %p", client, pkg, pkg->owner);
pkg->refcount--; pkg->refcount--;
PKGCONF_TRACE(pkg->owner, "refcount@%p: %d", pkg, pkg->refcount); PKGCONF_TRACE(pkg->owner, "%s refcount@%p: %d", pkg->id, pkg, pkg->refcount);
if (pkg->refcount <= 0) if (pkg->refcount <= 0)
pkgconf_pkg_free(pkg->owner, pkg); pkgconf_pkg_free(pkg->owner, pkg);
@ -1444,9 +1445,9 @@ pkgconf_pkg_walk_list(pkgconf_client_t *client,
unsigned int skip_flags) unsigned int skip_flags)
{ {
unsigned int eflags = PKGCONF_PKG_ERRF_OK; unsigned int eflags = PKGCONF_PKG_ERRF_OK;
pkgconf_node_t *node; pkgconf_node_t *node, *next;
PKGCONF_FOREACH_LIST_ENTRY(deplist->head, node) PKGCONF_FOREACH_LIST_ENTRY_SAFE(deplist->head, next, node)
{ {
unsigned int eflags_local = PKGCONF_PKG_ERRF_OK; unsigned int eflags_local = PKGCONF_PKG_ERRF_OK;
pkgconf_dependency_t *depnode = node->data; pkgconf_dependency_t *depnode = node->data;
@ -1469,21 +1470,26 @@ pkgconf_pkg_walk_list(pkgconf_client_t *client,
if (pkgdep->serial == client->serial) if (pkgdep->serial == client->serial)
{ {
pkgdep->hits++; pkgdep->hits++;
pkgconf_pkg_unref(client, pkgdep); /* In this case we have a circular reference.
continue; * We break that by deleteing the circular node from the
* the list, so that we dont create a situation where
* memory is leaked due to circular ownership.
* i.e: A owns B owns A
*/
pkgconf_node_delete(node, deplist);
pkgconf_dependency_unref(client, depnode);
goto next;
} }
if (skip_flags && (depnode->flags & skip_flags) == skip_flags) if (skip_flags && (depnode->flags & skip_flags) == skip_flags)
{ goto next;
pkgconf_pkg_unref(client, pkgdep);
continue;
}
pkgconf_audit_log_dependency(client, pkgdep, depnode); pkgconf_audit_log_dependency(client, pkgdep, depnode);
pkgdep->hits++; pkgdep->hits++;
pkgdep->serial = client->serial; pkgdep->serial = client->serial;
eflags |= pkgconf_pkg_traverse_main(client, pkgdep, func, data, depth - 1, skip_flags); eflags |= pkgconf_pkg_traverse_main(client, pkgdep, func, data, depth - 1, skip_flags);
next:
pkgconf_pkg_unref(client, pkgdep); pkgconf_pkg_unref(client, pkgdep);
} }

View File

@ -116,22 +116,27 @@ pkgconf_queue_collect_dependents(pkgconf_client_t *client, pkgconf_pkg_t *pkg, v
if (pkg == world) if (pkg == world)
return; return;
PKGCONF_FOREACH_LIST_ENTRY(pkg->required.head, node) if (!(pkg->flags & PKGCONF_PKG_PKGF_SEARCH_PRIVATE))
{ {
pkgconf_dependency_t *flattened_dep; PKGCONF_FOREACH_LIST_ENTRY(pkg->required.head, node)
{
pkgconf_dependency_t *flattened_dep;
flattened_dep = pkgconf_dependency_copy(client, node->data); flattened_dep = pkgconf_dependency_copy(client, node->data);
pkgconf_node_insert(&flattened_dep->iter, flattened_dep, &world->required); pkgconf_node_insert(&flattened_dep->iter, flattened_dep, &world->required);
}
} }
else
PKGCONF_FOREACH_LIST_ENTRY(pkg->requires_private.head, node)
{ {
pkgconf_dependency_t *flattened_dep; PKGCONF_FOREACH_LIST_ENTRY(pkg->requires_private.head, node)
{
pkgconf_dependency_t *flattened_dep;
flattened_dep = pkgconf_dependency_copy(client, node->data); flattened_dep = pkgconf_dependency_copy(client, node->data);
pkgconf_node_insert(&flattened_dep->iter, flattened_dep, &world->requires_private); pkgconf_node_insert(&flattened_dep->iter, flattened_dep, &world->requires_private);
}
} }
} }
@ -147,11 +152,11 @@ dep_sort_cmp(const void *a, const void *b)
static inline void static inline void
flatten_dependency_set(pkgconf_client_t *client, pkgconf_list_t *list) flatten_dependency_set(pkgconf_client_t *client, pkgconf_list_t *list)
{ {
pkgconf_node_t *node; pkgconf_node_t *node, *next;
pkgconf_dependency_t **deps = NULL; pkgconf_dependency_t **deps = NULL;
size_t dep_count = 0, i; size_t dep_count = 0, i;
PKGCONF_FOREACH_LIST_ENTRY(list->head, node) PKGCONF_FOREACH_LIST_ENTRY_SAFE(list->head, next, node)
{ {
pkgconf_dependency_t *dep = node->data; pkgconf_dependency_t *dep = node->data;
pkgconf_pkg_t *pkg = pkgconf_pkg_verify_dependency(client, dep, NULL); pkgconf_pkg_t *pkg = pkgconf_pkg_verify_dependency(client, dep, NULL);
@ -160,7 +165,11 @@ flatten_dependency_set(pkgconf_client_t *client, pkgconf_list_t *list)
continue; continue;
if (pkg->serial == client->serial) if (pkg->serial == client->serial)
continue; {
pkgconf_node_delete(node, list);
pkgconf_dependency_unref(client, dep);
goto next;
}
if (dep->match == NULL) if (dep->match == NULL)
{ {
@ -190,10 +199,13 @@ flatten_dependency_set(pkgconf_client_t *client, pkgconf_list_t *list)
deps[dep_count - 1] = dep; deps[dep_count - 1] = dep;
PKGCONF_TRACE(client, "added %s to dep table", dep->package); PKGCONF_TRACE(client, "added %s to dep table", dep->package);
next:
next:; pkgconf_pkg_unref(client, pkg);
} }
if (deps == NULL)
return;
qsort(deps, dep_count, sizeof (void *), dep_sort_cmp); qsort(deps, dep_count, sizeof (void *), dep_sort_cmp);
/* zero the list and start readding */ /* zero the list and start readding */
@ -261,6 +273,7 @@ pkgconf_queue_verify(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_lis
bool bool
pkgconf_queue_apply(pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_queue_apply_func_t func, int maxdepth, void *data) pkgconf_queue_apply(pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_queue_apply_func_t func, int maxdepth, void *data)
{ {
bool ret = false;
pkgconf_pkg_t world = { pkgconf_pkg_t world = {
.id = "virtual:world", .id = "virtual:world",
.realname = "virtual world package", .realname = "virtual world package",
@ -272,18 +285,17 @@ pkgconf_queue_apply(pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_queu
maxdepth = -1; maxdepth = -1;
if (pkgconf_queue_verify(client, &world, list, maxdepth) != PKGCONF_PKG_ERRF_OK) if (pkgconf_queue_verify(client, &world, list, maxdepth) != PKGCONF_PKG_ERRF_OK)
return false; goto cleanup;
/* the world dependency set is flattened after it is returned from pkgconf_queue_verify */ /* the world dependency set is flattened after it is returned from pkgconf_queue_verify */
if (!func(client, &world, data, maxdepth)) if (!func(client, &world, data, maxdepth))
{ goto cleanup;
pkgconf_pkg_free(client, &world);
return false;
}
ret = true;
cleanup:
pkgconf_pkg_free(client, &world); pkgconf_pkg_free(client, &world);
return ret;
return true;
} }
/* /*

View File

@ -1,27 +1,37 @@
project('pkgconf', 'c', project('pkgconf', 'c',
version : '1.8.0', version : '1.8.0',
license : 'ISC', license : 'ISC',
meson_version : '>=0.47') meson_version : '>=0.47',
default_options : ['c_std=c99'],
)
cc = meson.get_compiler('c') cc = meson.get_compiler('c')
add_project_arguments(
'-D_BSD_SOURCE',
'-D_DEFAULT_SOURCE',
cc.get_supported_arguments(
'-Wimplicit-function-declaration',
'-Wmisleading-indentation',
),
language : 'c',
)
cdata = configuration_data() cdata = configuration_data()
check_functions = [ check_functions = [
['HAVE_STRLCAT', 'strlcat', 'string.h'], ['strlcat', 'string.h'],
['HAVE_STRLCPY', 'strlcpy', 'string.h'], ['strlcpy', 'string.h'],
['HAVE_STRNDUP', 'strndup', 'string.h'], ['strndup', 'string.h'],
['HAVE_STRDUP', 'strdup', 'string.h'], ['strdup', 'string.h'],
['HAVE_STRNCASECMP', 'strncasecmp', 'strings.h'], ['strncasecmp', 'strings.h'],
['HAVE_STRCASECMP', 'strcasecmp', 'strings.h'], ['strcasecmp', 'strings.h'],
['HAVE_REALLOCARRAY', 'reallocarray', 'stdlib.h'], ['reallocarray', 'stdlib.h'],
] ]
foreach f : check_functions foreach f : check_functions
if cc.has_function(f.get(1), prefix : '#define _BSD_SOURCE\n#include <' + f.get(2) + '>') and cc.has_header_symbol(f.get(2), f.get(1), prefix : '#define _BSD_SOURCE') if cc.has_function(f[0], prefix : '#define _BSD_SOURCE\n#include <@0@>'.format(f[1])) and cc.has_header_symbol(f[1], f[0], prefix : '#define _BSD_SOURCE')
cdata.set(f.get(0), 1) cdata.set('HAVE_@0@'.format(f[0].to_upper().underscorify()), 1)
endif endif
endforeach endforeach
@ -42,8 +52,8 @@ cdata.set_quoted('PERSONALITY_PATH', ':'.join(personality_path))
cdata.set_quoted('PACKAGE_NAME', meson.project_name()) cdata.set_quoted('PACKAGE_NAME', meson.project_name())
cdata.set_quoted('PACKAGE_VERSION', meson.project_version()) cdata.set_quoted('PACKAGE_VERSION', meson.project_version())
cdata.set_quoted('PACKAGE_BUGREPORT', 'https://todo.sr.ht/~kaniini/pkgconf') cdata.set_quoted('PACKAGE_BUGREPORT', 'https://todo.sr.ht/~kaniini/pkgconf')
cdata.set('abs_top_srcdir', meson.source_root()) cdata.set('abs_top_srcdir', meson.current_source_dir())
cdata.set('abs_top_builddir', meson.build_root()) cdata.set('abs_top_builddir', meson.current_build_dir())
subdir('libpkgconf') subdir('libpkgconf')
@ -110,10 +120,8 @@ pkgconf_exe = executable('pkgconf',
if get_option('tests') if get_option('tests')
kyua_exe = find_program('kyua') kyua_exe = find_program('kyua')
atf_sh_exe = find_program('atf-sh') atf_sh_exe = find_program('atf-sh')
test('kyua', kyua_exe, args : ['--config=none', 'test', '--kyuafile=' + join_paths(meson.build_root(), 'Kyuafile'), '--build-root=' + meson.build_root()]) kyuafile = configure_file(input : 'Kyuafile.in', output : 'Kyuafile', configuration : cdata)
test('kyua', kyua_exe, args : ['--config=none', 'test', '--kyuafile', kyuafile, '--build-root', meson.current_build_dir()])
configure_file(input : 'Kyuafile.in', output : 'Kyuafile', configuration : cdata)
subdir('tests') subdir('tests')
endif endif

View File

@ -18,6 +18,6 @@ tests = [
# yuck # yuck
foreach test : tests foreach test : tests
configure_file(input: test + '.sh', output: test, copy: true) test_file = configure_file(input: test + '.sh', output: test, copy: true)
run_command('chmod', '755', join_paths(meson.build_root(), 'tests', test)) run_command('chmod', '755', test_file, check : true)
endforeach endforeach