Proper recursive dependencies (came from libantithread work)
[ccan] / tools / depends.c
1 #include "talloc/talloc.h"
2 #include "string/string.h"
3 #include "tools.h"
4 #include <err.h>
5 #include <stdbool.h>
6
7 static char ** __attribute__((format(printf, 3, 4)))
8 lines_from_cmd(const void *ctx, unsigned int *num, char *format, ...)
9 {
10         va_list ap;
11         char *cmd, *buffer;
12         FILE *p;
13
14         va_start(ap, format);
15         cmd = talloc_vasprintf(ctx, format, ap);
16         va_end(ap);
17
18         p = popen(cmd, "r");
19         if (!p)
20                 err(1, "Executing '%s'", cmd);
21
22         buffer = grab_fd(ctx, fileno(p));
23         if (!buffer)
24                 err(1, "Reading from '%s'", cmd);
25         pclose(p);
26
27         return split(ctx, buffer, "\n", num);
28 }
29
30 static char **get_one_deps(const void *ctx, const char *dir, unsigned int *num)
31 {
32         char **deps, *cmd;
33
34         cmd = talloc_asprintf(ctx, "%s/_info depends", dir);
35         deps = lines_from_cmd(cmd, num, "%s", cmd);
36         if (!deps)
37                 err(1, "Could not run '%s'", cmd);
38         return deps;
39 }
40
41 static bool have_dep(char **deps, unsigned int num, const char *dep)
42 {
43         unsigned int i;
44
45         for (i = 0; i < num; i++)
46                 if (streq(deps[i], dep))
47                         return true;
48         return false;
49 }
50
51 /* Gets all the dependencies, recursively. */
52 char **get_deps(const void *ctx, const char *dir)
53 {
54         char **deps;
55         unsigned int i, num;
56
57         deps = get_one_deps(ctx, dir, &num);
58         for (i = 0; i < num; i++) {
59                 char **newdeps;
60                 unsigned int j, newnum;
61
62                 if (!strstarts(deps[i], "ccan/"))
63                         continue;
64
65                 newdeps = get_one_deps(ctx, deps[i], &newnum);
66
67                 /* Should be short, so brute-force out dups. */
68                 for (j = 0; j < newnum; j++) {
69                         if (have_dep(deps, num, newdeps[j]))
70                                 continue;
71
72                         deps = talloc_realloc(NULL, deps, char *, num + 2);
73                         deps[num++] = newdeps[j];
74                         deps[num] = NULL;
75                 }
76         }
77         return deps;
78 }