Browse Source

ccanlint: offer to insert license comments where they're missing.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Rusty Russell 11 years ago
parent
commit
2ea90b45cf
3 changed files with 62 additions and 0 deletions
  1. 19 0
      tools/ccanlint/licenses.c
  2. 4 0
      tools/ccanlint/licenses.h
  3. 39 0
      tools/ccanlint/tests/license_comment.c

+ 19 - 0
tools/ccanlint/licenses.c

@@ -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);
+}

+ 4 - 0
tools/ccanlint/licenses.h

@@ -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 */

+ 39 - 0
tools/ccanlint/tests/license_comment.c

@@ -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);