diff --git a/doc/TODO b/doc/TODO
index 847c6985f32..85be0de6e50 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -32,7 +32,3 @@ xbps-repo:
create the file from scratch, for performance.
* Some problems when installing binpkgs with repos:
- If first repo is valid but second is not, will fail.
-
-lib:
- * Dependency code has a problem yet: fix the order of dependencies with
- the same priority, as seen by xbps-base-{chroot,system}.
diff --git a/doc/dependency_chain.plist b/doc/dependency_chain.plist
deleted file mode 100644
index 7cb8677bd63..00000000000
--- a/doc/dependency_chain.plist
+++ /dev/null
@@ -1,84 +0,0 @@
-
- -- Dependency chain for a package --
-
- The order to which dependencies are installed is:
-
- 1- Indirect deps with high->low priority.
- 2- Direct deps with high->low priority.
-
- Priority is increased by one any time a packages depends on, so a
- package that is needed by 30 packages will be installed before
- one that is needed by 10 packages.
-
-
-
- missing_deps
-
-
- pkgname
- blurb
- version
- 2.1
-
-
-
-
-
- installed_deps
-
-
- pkgname
- blah
- version
- 1.2
- requiredby
- foo-2.0
-
- ...
-
-
-
-
- direct_deps
-
-
- pkgname
- blob
- version
- 2.0
- repository
- /blah/foo
- requiredby
- foo-2.0
- priority
- 100
- filename
- blob-2.0.i686.xbps
-
- ...
-
-
-
-
- indirect_deps
-
-
- pkgname
- X
- version
- 1.0
- repository
- /blah/foo
- requiredby
- blob-2.0
- priority
- 90
- filename
- X-1.0.i686.xbps
-
- ...
-
-
diff --git a/include/install.h b/include/install.h
index 101e3307df8..4cd19aadb35 100644
--- a/include/install.h
+++ b/include/install.h
@@ -27,16 +27,19 @@
#define _XBPS_INSTALL_H_
/* From lib/install.c, lib/depends.c and lib/unpack.c */
-int xbps_install_pkg_deps(prop_dictionary_t, const char *);
-int xbps_install_binary_pkg(const char *, const char *);
-int xbps_install_binary_pkg_fini(prop_dictionary_t, prop_dictionary_t,
- const char *);
-int xbps_register_pkg(prop_dictionary_t, const char *, const char *,
- const char *);
-int xbps_unpack_binary_pkg(prop_dictionary_t, prop_dictionary_t,
- const char *,
- void (*cb_print)(prop_dictionary_t));
-int xbps_update_pkg_requiredby(prop_array_t, prop_dictionary_t);
-int xbps_find_deps_in_pkg(prop_dictionary_t, prop_dictionary_t);
+int xbps_install_pkg_deps(prop_dictionary_t, const char *);
+int xbps_install_binary_pkg(const char *, const char *);
+int xbps_install_binary_pkg_fini(prop_dictionary_t, prop_dictionary_t,
+ const char *);
+int xbps_register_pkg(prop_dictionary_t, const char *, const char *,
+ const char *);
+int xbps_unpack_binary_pkg(prop_dictionary_t, prop_dictionary_t,
+ const char *,
+ void (*cb_print)(prop_dictionary_t));
+int xbps_update_pkg_requiredby(prop_array_t, prop_dictionary_t);
+int xbps_find_deps_in_pkg(prop_dictionary_t, prop_dictionary_t);
+
+/* From lib/sortdeps.c */
+int xbps_sort_pkg_deps(prop_dictionary_t);
#endif /* !_XBPS_INSTALL_H_ */
diff --git a/lib/Makefile b/lib/Makefile
index 96677ddc81a..0c065e9deb4 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -10,7 +10,7 @@ LIBXBPS_LDFLAGS = -larchive -lprop -shared -Wl,-soname,$(LIBXBPS).$(MAJOR)
OBJECTS = cmpver.o depends.o fexec.o humanize_number.o install.o
OBJECTS += plist.o remove.o repository.o requiredby.o sha256.o
-OBJECTS += unpack.o util.o
+OBJECTS += sortdeps.o unpack.o util.o
all: $(LIBXBPS)
.PHONY: all
diff --git a/lib/depends.c b/lib/depends.c
index b5043aedb65..ac7fe79a4b0 100644
--- a/lib/depends.c
+++ b/lib/depends.c
@@ -44,7 +44,7 @@ static prop_dictionary_t chaindeps;
static int
create_deps_dictionary(void)
{
- prop_array_t installed, direct, indirect, missing;
+ prop_array_t installed, unsorted, missing;
int rv = 0;
chaindeps = prop_dictionary_create();
@@ -63,40 +63,28 @@ create_deps_dictionary(void)
goto fail2;
}
- direct = prop_array_create();
- if (direct == NULL) {
+ unsorted = prop_array_create();
+ if (unsorted == NULL) {
rv = ENOMEM;
goto fail3;
}
- indirect = prop_array_create();
- if (indirect == NULL) {
- rv = ENOMEM;
- goto fail4;
- }
-
if (!xbps_add_obj_to_dict(chaindeps, missing, "missing_deps")) {
rv = EINVAL;
- goto fail5;
+ goto fail4;
}
if (!xbps_add_obj_to_dict(chaindeps, installed, "installed_deps")) {
rv = EINVAL;
- goto fail5;
+ goto fail4;
}
- if (!xbps_add_obj_to_dict(chaindeps, direct, "direct_deps")) {
+ if (!xbps_add_obj_to_dict(chaindeps, unsorted, "unsorted_deps")) {
rv = EINVAL;
- goto fail5;
- }
- if (!xbps_add_obj_to_dict(chaindeps, indirect, "indirect_deps")) {
- rv = EINVAL;
- goto fail5;
+ goto fail4;
}
return rv;
-fail5:
- prop_object_release(indirect);
fail4:
- prop_object_release(direct);
+ prop_object_release(unsorted);
fail3:
prop_object_release(installed);
fail2:
@@ -111,14 +99,16 @@ static int
store_dependency(prop_dictionary_t origind, prop_dictionary_t depd,
prop_dictionary_t repod)
{
- prop_dictionary_t dict, curpkgdir, curpkgindir;
- prop_array_t array, rundeps_array;
+ prop_dictionary_t dict, curdict;
+ prop_array_t array, rundeps_array, reqby_array;
+ prop_string_t reqbystr;
uint32_t prio = 0;
- size_t len = 0;
+ size_t len = 0, dirdepscnt = 0, indirdepscnt = 0;
const char *pkgname, *version, *reqbyname, *reqbyver;
const char *repoloc, *binfile, *array_key, *originpkg, *short_desc;
char *reqby;
int rv = 0;
+ bool indirectdep = false;
assert(origind != NULL);
assert(depd != NULL);
@@ -142,6 +132,7 @@ store_dependency(prop_dictionary_t origind, prop_dictionary_t depd,
return ENOMEM;
(void)snprintf(reqby, len, "%s-%s", reqbyname, reqbyver);
+ reqbystr = prop_string_create_cstring(reqby);
/*
* Check if dependency is already installed to select the
@@ -158,40 +149,37 @@ store_dependency(prop_dictionary_t origind, prop_dictionary_t depd,
} else {
/*
* Required dependency is not installed. Check if it's
- * already registered in the chain, and update priority
+ * already registered in the chain, and update some objects
* or add the object into array otherwise.
*/
- prop_dictionary_get_cstring_nocopy(chaindeps, "origin",
- &originpkg);
- curpkgdir = xbps_find_pkg_in_dict(chaindeps,
- "direct_deps", pkgname);
- curpkgindir = xbps_find_pkg_in_dict(chaindeps,
- "indirect_deps", pkgname);
-
- if (strcmp(originpkg, reqbyname) == 0)
- array_key = "direct_deps";
- else
- array_key = "indirect_deps";
-
- if (curpkgdir && curpkgindir) {
- goto out;
-
- } else if (curpkgdir) {
- /*
- * Update the priority.
- */
- prop_dictionary_get_uint32(curpkgdir,
- "priority", &prio);
- prop_dictionary_set_uint32(curpkgdir,
- "priority", ++prio);
- goto out;
- } else if (curpkgindir) {
- prop_dictionary_get_uint32(curpkgindir,
- "priority", &prio);
- prop_dictionary_set_uint32(curpkgindir,
- "priority", ++prio);
+ array_key = "unsorted_deps";
+ prop_dictionary_get_cstring_nocopy(chaindeps,
+ "origin", &originpkg);
+ curdict = xbps_find_pkg_in_dict(chaindeps, array_key, pkgname);
+ /*
+ * Update priority and required_by objects.
+ */
+ if (curdict) {
+ prop_dictionary_get_uint32(curdict, "priority", &prio);
+ prop_dictionary_set_uint32(curdict, "priority", ++prio);
+ reqby_array = prop_dictionary_get(curdict,
+ "required_by");
+ if (!xbps_find_string_in_array(reqby_array, reqby))
+ prop_array_add(reqby_array, reqbystr);
goto out;
}
+ if (strcmp(originpkg, reqbyname)) {
+ indirectdep = true;
+ prop_dictionary_get_uint32(chaindeps,
+ "indirectdeps_count", &indirdepscnt);
+ prop_dictionary_set_uint32(chaindeps,
+ "indirectdeps_count", ++indirdepscnt);
+ } else {
+ prop_dictionary_get_uint32(chaindeps,
+ "directdeps_count", &dirdepscnt);
+ prop_dictionary_set_uint32(chaindeps,
+ "directdeps_count", ++dirdepscnt);
+ }
}
/*
@@ -215,17 +203,25 @@ store_dependency(prop_dictionary_t origind, prop_dictionary_t depd,
*/
prop_dictionary_set_cstring(dict, "pkgname", pkgname);
prop_dictionary_set_cstring(dict, "version", version);
- prop_dictionary_set_cstring(dict, "requiredby", reqby);
rundeps_array = prop_dictionary_get(depd, "run_depends");
if (rundeps_array && prop_array_count(rundeps_array) > 0)
prop_dictionary_set(dict, "run_depends", rundeps_array);
- if ((strcmp(array_key, "direct_deps") == 0) ||
- (strcmp(array_key, "indirect_deps") == 0)) {
+ reqby_array = prop_array_create();
+ if (reqby_array == NULL) {
+ prop_object_release(dict);
+ rv = ENOMEM;
+ goto out;
+ }
+ prop_array_add(reqby_array, reqbystr);
+ prop_dictionary_set(dict, "required_by", reqby_array);
+
+ if (strcmp(array_key, "unsorted_deps") == 0) {
prop_dictionary_set_cstring(dict, "repository", repoloc);
prop_dictionary_set_cstring(dict, "filename", binfile);
prop_dictionary_set_uint32(dict, "priority", prio);
prop_dictionary_set_cstring(dict, "short_desc", short_desc);
+ prop_dictionary_set_bool(dict, "indirect_dep", indirectdep);
}
/*
* Add the dictionary into the array.
@@ -238,6 +234,7 @@ store_dependency(prop_dictionary_t origind, prop_dictionary_t depd,
out:
free(reqby);
+ prop_object_release(reqbystr);
return rv;
}
@@ -252,6 +249,9 @@ add_missing_reqdep(const char *pkgname, const char *version)
assert(pkgname != NULL);
assert(version != NULL);
+ /*
+ * Adds a package into the missing deps array.
+ */
if (check_missing_reqdep(pkgname, version, &idx) == 0)
return EEXIST;
@@ -292,6 +292,9 @@ check_missing_reqdep(const char *pkgname, const char *version,
if (iter == NULL)
return ENOMEM;
+ /*
+ * Finds the index of a package in the missing deps array.
+ */
while ((obj = prop_object_iterator_next(iter)) != NULL) {
prop_dictionary_get_cstring_nocopy(obj, "pkgname", &missname);
prop_dictionary_get_cstring_nocopy(obj, "version", &missver);
@@ -413,101 +416,39 @@ out:
int
xbps_install_pkg_deps(prop_dictionary_t pkg, const char *destdir)
{
- prop_array_t array, installed, direct, indirect;
- prop_dictionary_t dict;
+ prop_array_t required;
prop_object_t obj;
prop_object_iterator_t iter;
- uint32_t maxprio = 0, prio = 0;
- size_t curidx = 0, idx = 0;
- const char *array_key, *reqby, *curname, *curver;
int rv = 0;
assert(pkg != NULL);
/*
- * Install required dependencies of a package.
- * The order for installation will be:
- *
- * - Indirect deps with high->low prio.
- * - Direct deps with high->low prio.
+ * Sort the dependency chain into an array.
*/
+ if ((rv = xbps_sort_pkg_deps(chaindeps)) != 0)
+ goto out;
- /*
- * First case: all deps are satisfied.
- */
- installed = prop_dictionary_get(chaindeps, "installed_deps");
- direct = prop_dictionary_get(chaindeps, "direct_deps");
- indirect = prop_dictionary_get(chaindeps, "indirect_deps");
- if (prop_array_count(direct) == 0 && prop_array_count(indirect) == 0 &&
- prop_array_count(installed) > 0)
+ required = prop_dictionary_get(chaindeps, "required_deps");
+ if (required == NULL)
return 0;
- /*
- * Second case: only direct deps are required.
- */
- if (prop_array_count(indirect) == 0 && prop_array_count(direct) > 0)
- array_key = "direct_deps";
- else
- array_key = "indirect_deps";
-
-again:
- array = prop_dictionary_get(chaindeps, array_key);
- if (array && prop_array_count(array) == 0) {
- rv = 0;
- goto out;
- } else if (array == NULL || prop_array_count(array) == 0) {
- rv = EINVAL;
- goto out;
- }
-
- iter = prop_array_iterator(array);
+ iter = prop_array_iterator(required);
if (iter == NULL) {
rv = ENOMEM;
goto out;
}
+ /*
+ * Install all required dependencies, previously sorted.
+ */
while ((obj = prop_object_iterator_next(iter)) != NULL) {
- prop_dictionary_get_uint32(obj, "priority", &prio);
- if (maxprio < prio) {
- curidx = idx;
- maxprio = prio;
- }
- idx++;
+ rv = xbps_install_binary_pkg_fini(NULL, obj, destdir);
+ if (rv != 0)
+ goto out;
}
prop_object_iterator_release(iter);
- dict = prop_array_get(array, curidx);
- if (dict == NULL) {
- rv = ENOENT;
- goto out;
- }
-
- prop_dictionary_get_cstring_nocopy(dict, "pkgname", &curname);
- prop_dictionary_get_cstring_nocopy(dict, "version", &curver);
- prop_dictionary_get_cstring_nocopy(dict, "requiredby", &reqby);
-
- printf("Installing %s-%s required by %s...\n", curname, curver, reqby);
- rv = xbps_install_binary_pkg_fini(NULL, dict, destdir);
- if (rv != 0) {
- printf("Error while installing %s-%s (%s)\n", curname, curver,
- strerror(rv));
- goto out;
- }
-
- prop_array_remove(array, curidx);
- if (prop_array_count(array) > 0) {
- prio = maxprio = 0;
- curidx = idx = 0;
- goto again;
- } else {
- prio = maxprio = 0;
- curidx = idx = 0;
- array_key = "direct_deps";
- goto again;
- }
-
out:
- prop_object_release(chaindeps);
-
return rv;
}
diff --git a/lib/sortdeps.c b/lib/sortdeps.c
new file mode 100644
index 00000000000..6983fd725cb
--- /dev/null
+++ b/lib/sortdeps.c
@@ -0,0 +1,316 @@
+/*-
+ * Copyright (c) 2009 Juan Romero Pardines.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+struct sorted_dependency {
+ TAILQ_ENTRY(sorted_dependency) chain;
+ prop_dictionary_t dict;
+ size_t idx;
+ ssize_t newidx;
+ bool unsorted;
+ bool reorg;
+};
+
+static TAILQ_HEAD(sdep_head, sorted_dependency) sdep_list =
+ TAILQ_HEAD_INITIALIZER(sdep_list);
+
+static ssize_t
+find_pkgdict_with_highest_prio(prop_array_t array, uint32_t *maxprio,
+ bool do_indirect)
+{
+ prop_object_t obj;
+ prop_object_iterator_t iter;
+ uint32_t prio = 0;
+ size_t idx = 0;
+ ssize_t curidx = -1;
+ bool indirect;
+
+ assert(array != NULL);
+
+ iter = prop_array_iterator(array);
+ if (iter == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ /*
+ * Finds the index of a package with the highest priority.
+ */
+ while ((obj = prop_object_iterator_next(iter)) != NULL) {
+ prop_dictionary_get_uint32(obj, "priority", &prio);
+ prop_dictionary_get_bool(obj, "indirect_dep", &indirect);
+
+ if (do_indirect) {
+ if ((*maxprio <= prio) && indirect) {
+ curidx = idx;
+ *maxprio = prio;
+ }
+ } else {
+ if ((*maxprio <= prio) && !indirect) {
+ curidx = idx;
+ *maxprio = prio;
+ }
+ }
+ idx++;
+ }
+ prop_object_iterator_release(iter);
+
+ if (curidx == -1)
+ errno = ENOENT;
+
+ return curidx;
+}
+
+static struct sorted_dependency *
+find_sorteddep_by_name(const char *pkgname)
+{
+ struct sorted_dependency *sdep;
+ const char *curname;
+
+ TAILQ_FOREACH(sdep, &sdep_list, chain) {
+ prop_dictionary_get_cstring_nocopy(sdep->dict,
+ "pkgname", &curname);
+ if (strcmp(pkgname, curname) == 0)
+ break;
+ }
+
+ return sdep;
+}
+
+int
+xbps_sort_pkg_deps(prop_dictionary_t chaindeps)
+{
+ prop_array_t installed, sorted, unsorted, rundeps_array;
+ prop_dictionary_t dict;
+ prop_object_t obj;
+ prop_object_iterator_t iter;
+ struct sorted_dependency *sdep, *sdep2;
+ uint32_t maxprio = 0;
+ size_t curidx = 0, indirdepscnt = 0, dirdepscnt = 0, cnt = 0;
+ const char *curpkg, *rundep;
+ char *pkgname;
+ int rv = 0;
+
+ assert(chaindeps != NULL);
+
+ sorted = prop_array_create();
+ if (sorted == NULL)
+ return ENOMEM;
+
+ /*
+ * All required deps are satisfied (already installed).
+ */
+ installed = prop_dictionary_get(chaindeps, "installed_deps");
+ unsorted = prop_dictionary_get(chaindeps, "unsorted_deps");
+ if (prop_array_count(unsorted) == 0 && prop_array_count(installed) > 0)
+ return 0;
+
+ prop_dictionary_get_uint32(chaindeps, "indirectdeps_count",
+ &indirdepscnt);
+ prop_dictionary_get_uint32(chaindeps, "directdeps_count",
+ &dirdepscnt);
+ unsorted = prop_dictionary_get(chaindeps, "unsorted_deps");
+ /*
+ * Pass 1: order indirect deps by priority.
+ */
+ while (cnt < indirdepscnt) {
+ curidx = find_pkgdict_with_highest_prio(unsorted,
+ &maxprio, true);
+ if (curidx == -1) {
+ rv = errno;
+ goto out;
+ }
+ dict = prop_array_get(unsorted, curidx);
+ if (dict == NULL) {
+ rv = errno;
+ goto out;
+ }
+ sdep = calloc(1, sizeof(*sdep));
+ if (sdep == NULL) {
+ rv = ENOMEM;
+ goto out;
+ }
+ sdep->dict = prop_dictionary_copy(dict);
+ sdep->idx = cnt;
+ sdep->newidx = -1;
+ TAILQ_INSERT_TAIL(&sdep_list, sdep, chain);
+ prop_array_remove(unsorted, curidx);
+ maxprio = 0;
+ cnt++;
+ }
+
+ cnt = 0;
+ /*
+ * Pass 2: order direct deps by priority.
+ */
+ while (cnt < dirdepscnt) {
+ curidx = find_pkgdict_with_highest_prio(unsorted,
+ &maxprio, false);
+ if (curidx == -1) {
+ rv = errno;
+ goto out;
+ }
+ dict = prop_array_get(unsorted, curidx);
+ if (dict == NULL) {
+ rv = errno;
+ goto out;
+ }
+ sdep = calloc(1, sizeof(*sdep));
+ if (sdep == NULL) {
+ rv = ENOMEM;
+ goto out;
+ }
+ sdep->dict = prop_dictionary_copy(dict);
+ sdep->idx = cnt + indirdepscnt;
+ sdep->newidx = -1;
+ TAILQ_INSERT_TAIL(&sdep_list, sdep, chain);
+ prop_array_remove(unsorted, curidx);
+ maxprio = 0;
+ cnt++;
+ }
+
+ /*
+ * Pass 3: update new index position by looking at run_depends and
+ * its current index position.
+ */
+ TAILQ_FOREACH(sdep, &sdep_list, chain) {
+ prop_dictionary_get_cstring_nocopy(sdep->dict,
+ "pkgname", &curpkg);
+ rundeps_array = prop_dictionary_get(sdep->dict, "run_depends");
+ if (rundeps_array == NULL)
+ continue;
+
+ iter = prop_array_iterator(rundeps_array);
+ if (iter == NULL) {
+ rv = ENOMEM;
+ goto out;
+ }
+ curidx = sdep->idx;
+
+ while ((obj = prop_object_iterator_next(iter)) != NULL) {
+ rundep = prop_string_cstring_nocopy(obj);
+ pkgname = xbps_get_pkg_name(rundep);
+ /*
+ * If package is installed, pass to the next one.
+ */
+ if (xbps_check_is_installed_pkgname(pkgname)) {
+ free(pkgname);
+ continue;
+ }
+ /* Ignore itself */
+ if (strcmp(curpkg, pkgname) == 0) {
+ free(pkgname);
+ continue;
+ }
+
+ sdep2 = find_sorteddep_by_name(pkgname);
+ free(pkgname);
+ /*
+ * If required dependency is before current package,
+ * pass to the next one.
+ */
+ if (curidx > sdep2->idx)
+ continue;
+ /*
+ * Update index position for the two objects.
+ */
+ if (!sdep2->unsorted) {
+ sdep2->unsorted = true;
+ sdep2->newidx = curidx;
+ sdep->newidx = curidx + 1;
+ }
+ }
+ prop_object_iterator_release(iter);
+ }
+ prop_dictionary_remove(chaindeps, "unsorted_deps");
+
+ /*
+ * Pass 4: copy dictionaries into the final array with the
+ * correct index position for all dependencies.
+ */
+ TAILQ_FOREACH(sdep, &sdep_list, chain) {
+ if (sdep->reorg)
+ continue;
+
+ if (sdep->newidx != -1) {
+ TAILQ_FOREACH(sdep2, &sdep_list, chain) {
+ if (sdep2->unsorted) {
+ if (!prop_array_set(sorted,
+ sdep2->newidx, sdep2->dict)) {
+ rv = errno;
+ goto out;
+ }
+ sdep2->newidx = -1;
+ sdep2->unsorted = false;
+ sdep2->reorg = true;
+ break;
+ }
+ }
+ if (!prop_array_set(sorted, sdep->newidx, sdep->dict)) {
+ rv = errno;
+ goto out;
+ }
+ sdep->newidx = -1;
+ } else {
+ if (!prop_array_add(sorted, sdep->dict)) {
+ rv = errno;
+ goto out;
+ }
+ }
+ }
+
+ /*
+ * Sanity check that the array contains the same number of
+ * objects than the total number of required dependencies.
+ */
+ cnt = dirdepscnt + indirdepscnt;
+ if (cnt != prop_array_count(sorted)) {
+ rv = EINVAL;
+ goto out;
+ }
+
+ if (!prop_dictionary_set(chaindeps, "required_deps", sorted))
+ rv = EINVAL;
+out:
+ /*
+ * Release resources used by temporary sorting.
+ */
+ prop_object_release(sorted);
+ while ((sdep = TAILQ_FIRST(&sdep_list)) != NULL) {
+ TAILQ_REMOVE(&sdep_list, sdep, chain);
+ prop_object_release(sdep->dict);
+ free(sdep);
+ }
+
+ return rv;
+}