1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
/*
* pkg - Orphan package finder
* https://rawnix.org
*
* Copyright (c) 2025 zorz@gmx.com
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "orphan.h"
/* Check if package is orphan, ignoring packages in ignore list */
static bool is_orphan_internal(const char *pkg, pkgdb_t *pkgdb,
depdb_t *depdb, strarray_t *ignore)
{
dep_entry_t *e;
strarray_t *rdeps;
bool orphan;
size_t i;
if (!pkg || !pkgdb || !depdb)
return false;
if (!pkgdb_installed(pkgdb, pkg))
return false;
e = depdb_find(depdb, pkg);
if (!e)
return false; /* not in dep db = assume manual */
if (e->reason != REASON_AUTO)
return false; /* manually installed = not orphan */
/* check reverse dependencies */
rdeps = depdb_rdeps(depdb, pkg);
orphan = true;
for (i = 0; i < rdeps->size; i++) {
if (!ignore || !strarray_contains(ignore, rdeps->data[i])) {
orphan = false;
break;
}
}
strarray_free(rdeps);
free(rdeps);
return orphan;
}
bool is_orphan(const char *pkg, pkgdb_t *pkgdb, depdb_t *depdb)
{
return is_orphan_internal(pkg, pkgdb, depdb, NULL);
}
/* Find all orphans using iterative algorithm */
strarray_t *find_orphans(pkgdb_t *pkgdb, depdb_t *depdb)
{
strarray_t *result, *installed, *found;
size_t i;
bool found_new;
result = xmalloc(sizeof(strarray_t));
strarray_init(result);
if (!pkgdb || !depdb)
return result;
found = xmalloc(sizeof(strarray_t));
strarray_init(found);
installed = pkgdb_list(pkgdb);
/* iterate until no new orphans discovered */
do {
found_new = false;
/* free strings from previous iteration before reuse */
strarray_free(found);
strarray_init(found);
for (i = 0; i < installed->size; i++) {
const char *name = installed->data[i];
if (strarray_contains(result, name))
continue;
if (is_orphan_internal(name, pkgdb, depdb, result)) {
strarray_add(found, name);
found_new = true;
}
}
/* add new orphans to result */
for (i = 0; i < found->size; i++)
strarray_add(result, found->data[i]);
} while (found_new);
strarray_free(found);
free(found);
strarray_free(installed);
free(installed);
return result;
}
|