package main import ( "github.com/charmbracelet/huh" "log/slog" "archive/zip" "fmt" "io" "io/ioutil" "net/http" "os" "path/filepath" "strings" ) func main() { xdg_cache_home := os.ExpandEnv("$XDG_CACHE_HOME") if xdg_cache_home == "" { slog.Info("Env var $XDG_CACHE_HOME not found, now using: ", os.ExpandEnv("$HOME/.cache")) xdg_cache_home = os.ExpandEnv("$HOME/.cache") } path_to_licenses := filepath.Join(xdg_cache_home, "licenses/") err := os.MkdirAll(path_to_licenses, os.ModePerm) Check(err) entries, err := ioutil.ReadDir(path_to_licenses) Check(err) if len(entries) < 2 { slog.Info("License cache empty. Proceeding to update license cache.") UpdateLicenseCache(path_to_licenses) } var licenses []huh.Option[string] var license string for _, entry := range entries { licenses = append(licenses, huh.NewOption(entry.Name(), entry.Name())) } form := huh.NewForm( huh.NewGroup( huh.NewSelect[string](). Title("Choose your license:"). Options(licenses...). Value(&license), ), ) err = form.Run() Check(err) current_dir, err := os.Getwd() Check(err) source, err := os.Open(filepath.Join(path_to_licenses, license)) Check(err) defer source.Close() destination, err := os.Create(filepath.Join(current_dir, "LICENSE")) Check(err) defer destination.Close() _, err = io.Copy(destination, source) Check(err) slog.Info("Wrote LICENSE with license: " + license) } func DownloadFile(url string, file_path string) int64 { resp, err := http.Get(url) Check(err) defer resp.Body.Close() f, err := os.Create(file_path) Check(err) defer f.Close() a, err := io.Copy(f, resp.Body) Check(err) return a } func UpdateLicenseCache(dir_path string) { tmp_path := "/tmp" zip_path := filepath.Join(tmp_path, "licenses.zip") slog.Info("Downloading license list data from: github.com/spdx/license-list-data v3.24.0") _ = DownloadFile("https://github.com/spdx/license-list-data/archive/refs/tags/v3.24.0.zip", zip_path) archive, err := zip.OpenReader(zip_path) Check(err) defer archive.Close() for _, f := range archive.File { file_path := filepath.Join(tmp_path, f.Name) if !strings.HasPrefix(file_path, filepath.Clean(tmp_path)+string(os.PathSeparator)) { fmt.Printf("invalid file path: %s\n", file_path) return } if f.FileInfo().IsDir() { os.MkdirAll(file_path, os.ModePerm) continue } err := os.MkdirAll(filepath.Dir(file_path), os.ModePerm) Check(err) destination_file, err := os.OpenFile(file_path, os.O_WRONLY | os.O_CREATE | os.O_TRUNC, f.Mode()) Check(err) defer destination_file.Close() file_in_archive, err := f.Open() Check(err) defer file_in_archive.Close() _, err = io.Copy(destination_file, file_in_archive) Check(err) } slog.Info("Moving files into license cache.") licenses_text_path := filepath.Join(tmp_path, "license-list-data-3.24.0/text") entries, err := os.ReadDir(licenses_text_path) Check(err) for _, file := range entries { Move(filepath.Join(licenses_text_path, file.Name()), filepath.Join(dir_path, file.Name())) } } func Move(source string, destination string) { slog.Info("Moving " + source + " to " + destination) os.Rename(source, destination) } func Check(err error) { if err != nil { panic(err) } }