ccanlint: offer to insert license comments where they're missing.
authorRusty Russell <rusty@rustcorp.com.au>
Mon, 10 Nov 2014 04:30:26 +0000 (15:00 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Mon, 10 Nov 2014 04:30:26 +0000 (15:00 +1030)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
tools/ccanlint/licenses.c
tools/ccanlint/licenses.h
tools/ccanlint/tests/license_comment.c

index 45684974f528a506ef2a7be9b09db2ea877ce434..ca8bc73d0d58e0be508ab6e5f4cc5352a0af1072 100644 (file)
@@ -6,75 +6,88 @@
 
 const struct license_info licenses[] = {
        { "LGPLv2+", "LGPL",
+         "GNU LGPL version 2 (or later)",
          { "gnu lesser general public license",
            "version 2",
            "or at your option any later version"
          }
        },
        { "LGPLv2", "LGPL",
+         "GNU LGPL version 2",
          { "gnu lesser general public license",
            "version 2",
            NULL
          }
        },
        { "LGPLv3", "LGPL",
+         "GNU LGPL version 3",
          { "gnu lesser general public license",
            "version 3",
            NULL
          }
        },
        { "LGPL", "LGPL",
+         "GNU LGPL",
          { "gnu lesser general public license",
            NULL,
            NULL
          }
        },
        { "GPLv2+", "GPL",
+         "GNU GPL version 2 (or later)",
          { "gnu general public license",
            "version 2",
            "or at your option any later version"
          }
        },
        { "GPLv2", "GPL",
+         "GNU GPL version 2",
          { "gnu general public license",
            "version 2",
            NULL
          }
        },
        { "GPLv3", "GPL",
+         "GNU GPL version 3 (or later)",
          { "gnu general public license",
            "version 3",
            NULL
          }
        },
        { "GPL", "GPL",
+         "GNU GPL",
          { "gnu general public license",
            NULL,
            NULL
          }
        },
        { "BSD-3CLAUSE", "BSD",
+         "3-clause BSD license",
          { "redistributions of source code must retain",
            "redistributions in binary form must reproduce",
            "endorse or promote"
          }
        },
        { "BSD-MIT", "MIT",
+         "MIT (BSD) license",
          { "without restriction",
            "above copyright notice",
            "without warranty"
          }
        },
        { "CC0", "CC0",
+         "CC0 license (public domain)",
          { "Waiver.",
            "unconditionally waives",
            NULL
          }
        },
        { "Public domain", "Public domain",
+         NULL,
          { NULL, NULL, NULL  }
        },
        { "Unknown license", "Unknown license",
+         NULL,
          { NULL, NULL, NULL  }
        },
 };
@@ -216,3 +229,9 @@ struct doc_section *find_license_tag(const struct manifest *m)
        }
        return NULL;
 }
+
+const char *get_license_oneliner(const tal_t *ctx, enum license license)
+{
+       return tal_fmt(ctx, "/* %s - see LICENSE file for details */",
+                      licenses[license].describe);
+}
index ed1e9ad7fbacec775ef05a8e927bc4952bbb4f91..60d203763cf99417ba818c6dbdd7ad219b03253c 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef CCANLINT_LICENSES_H
 #define CCANLINT_LICENSES_H
 #include <stdbool.h>
+#include <ccan/tal/tal.h>
 
 enum license {
        LICENSE_LGPLv2_PLUS,
@@ -23,6 +24,7 @@ enum license {
 struct license_info {
        const char *name;
        const char *shortname;
+       const char *describe;
        /* Edit distance is expensive, and this works quite well. */
        const char *clause[NUM_CLAUSES];
 };
@@ -41,4 +43,6 @@ enum license which_license(struct doc_section *d);
 struct manifest;
 struct doc_section *find_license_tag(const struct manifest *m);
 
+const char *get_license_oneliner(const tal_t *ctx, enum license license);
+
 #endif /* CCANLINT_LICENSES_H */
index 18a60813fdead9db0a5ef47fc6a4bc55a2fa784c..9548d87cbb17af759c5e173e8ab0966990168b54 100644 (file)
@@ -57,10 +57,49 @@ static void check_license_comment(struct manifest *m,
        }
 }
 
+static void add_license_comment(struct manifest *m, struct score *score)
+{
+       struct file_error *e;
+       const char *license_desc = get_license_oneliner(score, m->license);
+       char *files = tal_strdup(score, ""), *q;
+
+       list_for_each(&score->per_file_errors, e, list)
+               tal_append_fmt(&files, "  %s\n", e->file->name);
+
+       q = tal_fmt(score, "The following files don't have a comment:\n%s\n"
+                   "Should I prepend '%s'?", files, license_desc);
+       if (!ask(q))
+               return;
+
+       list_for_each(&score->per_file_errors, e, list) {
+               char *tmpname;
+               FILE *out;
+               unsigned int i;
+
+               tmpname = temp_file(score, ".licensed", e->file->name);
+               out = fopen(tmpname, "w");
+               if (!out)
+                       err(1, "Opening %s", tmpname);
+               if (fprintf(out, "%s\n", license_desc) < 0)
+                       err(1, "Writing %s", tmpname);
+
+               for (i = 0; e->file->lines[i]; i++)
+                       if (fprintf(out, "%s\n", e->file->lines[i]) < 0)
+                               err(1, "Writing %s", tmpname);
+
+               if (fclose(out) != 0)
+                       err(1, "Closing %s", tmpname);
+
+               if (!move_file(tmpname, e->file->fullname))
+                       err(1, "Moving %s to %s", tmpname, e->file->fullname);
+       }
+}
+
 struct ccanlint license_comment = {
        .key = "license_comment",
        .name = "Source and header files refer to LICENSE",
        .check = check_license_comment,
+       .handle = add_license_comment,
        .needs = "license_exists"
 };
 REGISTER_TEST(license_comment);