1const std = @import("std");
2pub const licenses = @import("licenses-text");
3const leven = @import("leven");
4const nfs = @import("nfs");
5
6pub fn detect(alloc: std.mem.Allocator, license_src: []const u8) ![]const u8 {
7 var min: ?usize = null;
8 var ind: ?usize = null;
9
10 for (licenses.spdx, 0..) |item, i| {
11 const distance = try leven.leven(u8, alloc, license_src, item[1], min);
12
13 if (min == null or distance < min.?) {
14 min = distance;
15 ind = i;
16 }
17 }
18 return licenses.spdx[ind.?][0];
19}
20
21pub fn detectInDir(alloc: std.mem.Allocator, dir: nfs.Dir) !?[]const u8 {
22 const b = (try testLicenseFile(alloc, dir, "LICENSE")) orelse
23 (try testLicenseFile(alloc, dir, "LICENSE.md")) orelse
24 (try testLicenseFile(alloc, dir, "LICENSE.txt")) orelse
25 return null;
26 defer alloc.free(b);
27 return try detect(alloc, b);
28}
29
30pub fn testLicenseFile(alloc: std.mem.Allocator, dir: nfs.Dir, name: [:0]const u8) !?[]const u8 {
31 const file = dir.openFile(name, .{}) catch |err| switch (err) {
32 error.ENOENT => return null,
33 else => |e| return e,
34 };
35 defer file.close();
36 return try file.readAllAlloc(alloc, 1024 * 1024);
37}