tools/modfiles: list files in a module.
[ccan] / tools / modfiles.c
1 /* List files in a module, or modules. */
2 #include <ccan/opt/opt.h>
3 #include <ccan/foreach/foreach.h>
4 #include <ccan/tal/str/str.h>
5 #include "manifest.h"
6 #include <stdio.h>
7
8 static void add_file(const struct ccan_file *f,
9                      bool fullpath, bool nul_term, bool gitonly)
10 {
11         /* Hacky way of seeing if git knows about this. */
12         if (gitonly) {
13                 char *cmd = tal_fmt(f, "git status --porcelain --ignored %s | grep -q '^ *[!?]'", f->fullname);
14                 if (system(cmd) == 0)
15                         return;
16         }
17         printf("%s%c", fullpath ? f->fullname : f->name,
18                nul_term ? '\0' : '\n');
19 }
20
21 int main(int argc, char *argv[])
22 {
23         bool code = true;
24         bool license = true;
25         bool tests = true;
26         bool other = true;
27         bool gitonly = false;
28         bool nul_term = false;
29         bool fullpath = false;
30         int i;
31
32         opt_register_noarg("--no-code", opt_set_invbool, &code,
33                            "Don't list .c and .h files");
34         opt_register_noarg("--no-license", opt_set_invbool, &license,
35                            "Don't list license file");
36         opt_register_noarg("--no-tests", opt_set_invbool, &tests,
37                            "Don't list test files");
38         opt_register_noarg("--no-other", opt_set_invbool, &other,
39                            "Don't list other files");
40         opt_register_noarg("--git-only", opt_set_bool, &gitonly,
41                            "Only include files in git");
42         opt_register_noarg("--fullpath", opt_set_bool, &fullpath,
43                            "Print full path names instead of module-relative ones");
44         opt_register_noarg("--null|-0", opt_set_bool, &nul_term,
45                            "Separate files with nul character instead of \\n");
46         opt_register_noarg("-h|--help", opt_usage_and_exit,
47                            "<moduledir>...",
48                            "Show usage");
49
50         opt_parse(&argc, argv, opt_log_stderr_exit);
51         if (argc < 2)
52                 opt_usage_exit_fail("Expected one or more module directories");
53
54         for (i = 1; i < argc; i++) {
55                 struct manifest *m = get_manifest(NULL, argv[i]);
56                 struct list_head *list;
57                 struct ccan_file *f;
58                 if (code) {
59                         foreach_ptr(list, &m->c_files, &m->h_files) {
60                                 list_for_each(list, f, list)
61                                         add_file(f, fullpath, nul_term, gitonly);
62                         }
63                 }
64                 if (license) {
65                         list_for_each(&m->other_files, f, list) {
66                                 if (streq(f->name, "LICENSE"))
67                                         add_file(f, fullpath, nul_term, gitonly);
68                         }
69                 }
70                 if (tests) {
71                         foreach_ptr(list, &m->run_tests, &m->api_tests,
72                                     &m->compile_ok_tests, &m->compile_fail_tests,
73                                     &m->other_test_c_files,
74                                     &m->other_test_files) {
75                                 list_for_each(list, f, list)
76                                         add_file(f, fullpath, nul_term, gitonly);
77                         }
78                 }
79                 if (other) {
80                         list_for_each(&m->other_files, f, list) {
81                                 if (!streq(f->name, "LICENSE"))
82                                         add_file(f, fullpath, nul_term, gitonly);
83                         }
84                 }
85         }
86         return 0;
87 }