Very simple code license picker.
1package main
2
3import (
4 "github.com/charmbracelet/huh"
5 "log/slog"
6 "archive/zip"
7 "fmt"
8 "io"
9 "io/ioutil"
10 "net/http"
11 "os"
12 "path/filepath"
13 "strings"
14)
15
16func main() {
17 xdg_cache_home := os.ExpandEnv("$XDG_CACHE_HOME")
18 if xdg_cache_home == "" {
19 slog.Info("Env var $XDG_CACHE_HOME not found, now using: ", os.ExpandEnv("$HOME/.cache"))
20 xdg_cache_home = os.ExpandEnv("$HOME/.cache")
21 }
22
23 path_to_licenses := filepath.Join(xdg_cache_home, "licenses/")
24
25 err := os.MkdirAll(path_to_licenses, os.ModePerm)
26 Check(err)
27 entries, err := ioutil.ReadDir(path_to_licenses)
28 Check(err)
29 if len(entries) < 2 {
30 slog.Info("License cache empty. Proceeding to update license cache.")
31 UpdateLicenseCache(path_to_licenses)
32 }
33
34 var licenses []huh.Option[string]
35 var license string
36 for _, entry := range entries {
37 licenses = append(licenses, huh.NewOption(entry.Name(), entry.Name()))
38 }
39 form := huh.NewForm(
40 huh.NewGroup(
41 huh.NewSelect[string]().
42 Title("Choose your license:").
43 Options(licenses...).
44 Value(&license),
45 ),
46 )
47
48 err = form.Run()
49 Check(err)
50
51 current_dir, err := os.Getwd()
52 Check(err)
53
54 source, err := os.Open(filepath.Join(path_to_licenses, license))
55 Check(err)
56 defer source.Close()
57
58 destination, err := os.Create(filepath.Join(current_dir, "LICENSE"))
59 Check(err)
60 defer destination.Close()
61
62 _, err = io.Copy(destination, source)
63 Check(err)
64 slog.Info("Wrote LICENSE with license: " + license)
65}
66
67func DownloadFile(url string, file_path string) int64 {
68 resp, err := http.Get(url)
69 Check(err)
70 defer resp.Body.Close()
71
72 f, err := os.Create(file_path)
73 Check(err)
74 defer f.Close()
75
76 a, err := io.Copy(f, resp.Body)
77 Check(err)
78 return a
79}
80
81func UpdateLicenseCache(dir_path string) {
82 tmp_path := "/tmp"
83 zip_path := filepath.Join(tmp_path, "licenses.zip")
84 slog.Info("Downloading license list data from: github.com/spdx/license-list-data v3.24.0")
85
86 _ = DownloadFile("https://github.com/spdx/license-list-data/archive/refs/tags/v3.24.0.zip", zip_path)
87
88 archive, err := zip.OpenReader(zip_path)
89 Check(err)
90 defer archive.Close()
91
92 for _, f := range archive.File {
93 file_path := filepath.Join(tmp_path, f.Name)
94
95 if !strings.HasPrefix(file_path, filepath.Clean(tmp_path)+string(os.PathSeparator)) {
96 fmt.Printf("invalid file path: %s\n", file_path)
97 return
98 }
99
100 if f.FileInfo().IsDir() {
101 os.MkdirAll(file_path, os.ModePerm)
102 continue
103 }
104
105 err := os.MkdirAll(filepath.Dir(file_path), os.ModePerm)
106 Check(err)
107
108 destination_file, err := os.OpenFile(file_path, os.O_WRONLY | os.O_CREATE | os.O_TRUNC, f.Mode())
109 Check(err)
110 defer destination_file.Close()
111
112 file_in_archive, err := f.Open()
113 Check(err)
114 defer file_in_archive.Close()
115
116 _, err = io.Copy(destination_file, file_in_archive)
117 Check(err)
118 }
119
120 slog.Info("Moving files into license cache.")
121 licenses_text_path := filepath.Join(tmp_path, "license-list-data-3.24.0/text")
122
123 entries, err := os.ReadDir(licenses_text_path)
124 Check(err)
125
126 for _, file := range entries {
127 Move(filepath.Join(licenses_text_path, file.Name()), filepath.Join(dir_path, file.Name()))
128 }
129}
130
131func Move(source string, destination string) {
132 slog.Info("Moving " + source + " to " + destination)
133 os.Rename(source, destination)
134}
135
136func Check(err error) {
137 if err != nil {
138 panic(err)
139 }
140}