git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] clone: Warn if LICENSE or COPYING file lacking and !clone.skiplicensecheck

From
David A. Wheeler <dwheeler@dwheeler.com>
Date
Mar 22, 2015, 00:16 UTC
Message-ID
<E1YZTZI-0002QE-3r@rmm6prod02.runbox.com>

Warn cloners if there is no LICENSE* or COPYING* file that makes the license clear. This is a useful warning, because if there is no license somewhere, then local copyright laws (which forbid many uses) and terms of service apply - and the cloner may not be expecting that. Many projects accidentally omit a license, so this is common enough to note.

You can disable this warning by setting "clone.skiplicensecheck" to "true".

For more info on the issue, feel free to see: http://choosealicense.com/no-license/ http://www.wired.com/2013/07/github-licenses/ https://twitter.com/stephenrwalli/status/247597785069789184

Signed-off-by: David A. Wheeler <dwheeler@dwheeler.com>
---
 builtin/clone.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)
diff --git a/builtin/clone.c b/builtin/clone.c
index 9572467..a3e8584 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -50,6 +50,7 @@ static int option_progress = -1;
 static struct string_list option_config;
 static struct string_list option_reference;
 static int option_dissociate;
+static int skip_license_check;
 
 static int opt_parse_reference(const struct option *opt, const char *arg, int unset)
 {
@@ -748,6 +749,44 @@ static void dissociate_from_references(void)
 		die_errno(_("cannot unlink temporary alternates file"));
 }
 
+static int starts_with_ignore_case(const char *str, const char *prefix)
+{
+	for (; ; str++, prefix++)
+		if (!*prefix)
+			return 1;
+		else if (tolower(*str) != tolower(*prefix))
+			return 0;
+}
+
+static int missing_license(void)
+{
+	DIR *dir = opendir("."); /* Examine current directory for license. */
+	struct dirent *e;
+	struct stat st;
+	int ret = 0;
+
+	if (!dir)
+		return 0; /* Empty directory, no need for license. */
+
+	while ((e = readdir(dir)) != NULL) {
+		if (starts_with_ignore_case(e->d_name, "license") ||
+		    starts_with_ignore_case(e->d_name, "copyright")) {
+			if (stat(e->d_name, &st) || st.st_size < 2)
+				continue;
+			ret = 0;
+			break;
+		}
+		if (!strcmp(e->d_name, ".") || !strcmp(e->d_name, "..") ||
+		    !strcmp(e->d_name, ".git"))
+			continue;
+		ret = 1; /* Non-empty directory */
+	}
+
+	closedir(dir);
+	return ret;
+}
+
+
 int cmd_clone(int argc, const char **argv, const char *prefix)
 {
 	int is_bundle = 0, is_local;
@@ -1016,6 +1055,11 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	junk_mode = JUNK_LEAVE_REPO;
 	err = checkout();
 
+	git_config_get_bool("clone.skiplicensecheck", &skip_license_check);
+	if (!option_no_checkout && !skip_license_check &&
+	    missing_license())
+		warning(_("Repository has no LICENSE or COPYING file with content."));
+
 	strbuf_release(&reflog_msg);
 	strbuf_release(&branch_top);
 	strbuf_release(&key);
-- 
2.3.3.221.g33aa87e.dirty
Next: Johannes Sixt
Message 1 of 3 in “clone: Warn if LICENSE or COPYING file lacking and !clone.skiplicensecheck”
  1. clone: Warn if LICENSE or COPYING file lacking and !clone.skiplicensecheckDavid A. Wheeler, Mar 22, 2015
  2. Johannes SixtMar 22, 2015
  3. Duy NguyenMar 22, 2015

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.