Files
vsclean/main.go
PhatPhuckDave 1d71fe5aca Clean up
Final production version (1.0 at least)
2024-08-13 10:15:18 +02:00

227 lines
5.9 KiB
Go

package main
import (
"database/sql"
"encoding/json"
"fmt"
"io"
"log"
"net/url"
"os"
"path"
"strings"
_ "github.com/mattn/go-sqlite3"
)
var Error *log.Logger
func init() {
log.SetFlags(log.Lmicroseconds | log.Lshortfile)
logFile, err := os.Create("main.log")
if err != nil {
log.Printf("Error creating log file: %v", err)
os.Exit(1)
}
logger := io.MultiWriter(os.Stdout, logFile)
log.SetOutput(logger)
Error = log.New(io.MultiWriter(logFile, os.Stderr, os.Stdout),
fmt.Sprintf("%sERROR:%s ", "\033[0;101m", "\033[0m"),
log.Lmicroseconds|log.Lshortfile)
}
const projectsFile = `C:\Users\Administrator\Seafile\VSCode\Code\User\globalStorage\state.vscdb`
const (
TABLE = "ItemTable"
KEY = "history.recentlyOpenedPathsList"
)
var scanFolders []string = []string{
`C:\Users\Administrator\Seafile\Projects-Clion\ClionProjects`,
`C:\Users\Administrator\Seafile\Projects-Elixir\ElixirProjects`,
`C:\Users\Administrator\Seafile\Projects-Go\GoProjects`,
`C:\Users\Administrator\Seafile\Projects-Idea\IdeaProjects`,
`C:\Users\Administrator\Seafile\Projects-Other\Projects`,
`C:\Users\Administrator\Seafile\Projects-Pycharm\PycharmProjects`,
`C:\Users\Administrator\Seafile\Projects-Rider\RiderProjects`,
`C:\Users\Administrator\Seafile\Projects-Webstorm\WebstormProjects`,
}
func main() {
for idx, folder := range scanFolders {
scanFolders[idx] = path.Clean(folder)
}
// config, err := ReadDiskConfig()
config, err := ReadDBConfig()
if err != nil {
Error.Fatalf("Error reading database config: %v", err)
return
}
log.Printf("Loaded %d entries", len(config.Entries))
cleanConfig := CleanConfig(config)
log.Printf("%d after cleaning config", len(cleanConfig))
cleaned := 0
for ipath := range cleanConfig {
file, err := os.Open(ipath)
if err != nil {
if os.IsNotExist(err) {
log.Printf("Discarding non existing directory %s", ipath)
delete(cleanConfig, ipath)
cleaned++
} else {
// Maybe we fail to open it for some other reason...
// Could be it still does exist
Error.Printf("Error opening file %s: %v", ipath, err)
continue
}
continue
}
file.Close()
}
log.Printf("Cleaned %d invalid entries, %d valid entries remain", cleaned, len(cleanConfig))
added := 0
for _, folder := range scanFolders {
files, err := os.ReadDir(folder)
if err != nil {
log.Printf("Error reading folder %s: %v", folder, err)
continue
}
for _, fileEntry := range files {
if !fileEntry.IsDir() {
continue
}
newEntry := Entry{
FolderURI: path.Clean(path.Join(folder, fileEntry.Name())),
}
_, exists := cleanConfig[newEntry.FolderURI]
if exists {
log.Printf("Folder %s already exists in config", newEntry.FolderURI)
continue
}
cleanConfig[newEntry.FolderURI] = &newEntry
added++
}
}
log.Printf("Added %d new entries from scan folders, now %d total", added, len(cleanConfig))
originalFormat := Config{
Entries: make([]Entry, 0, len(cleanConfig)),
}
for _, entry := range cleanConfig {
originalFormat.Entries = append(originalFormat.Entries, *entry)
}
escapedConfig := EscapeConfig(originalFormat)
err = WriteDBConfig(escapedConfig)
if err != nil {
Error.Printf("Failed to write config: %v", err)
return
}
}
func ReadDBConfig() (Config, error) {
var res = Config{}
conn, err := sql.Open("sqlite3", projectsFile)
if err != nil {
return res, err
}
row := conn.QueryRow(fmt.Sprintf("SELECT * FROM %s WHERE key = '%s'", TABLE, KEY))
var key string
var value string
err = row.Scan(&key, &value)
if err != nil {
return res, err
}
conn.Close()
err = json.NewDecoder(strings.NewReader(value)).Decode(&res)
if err != nil {
return res, fmt.Errorf("error decoding JSON: %v", err)
}
return res, nil
}
func ReadDiskConfig() (Config, error) {
var res = Config{}
file, err := os.Open("dump.json")
if err != nil {
return res, fmt.Errorf("error opening file: %v", err)
}
err = json.NewDecoder(file).Decode(&res)
if err != nil {
return res, fmt.Errorf("error decoding JSON: %v", err)
}
return res, nil
}
func CleanConfig(config Config) map[string]*Entry {
var res = make(map[string]*Entry)
for _, entry := range config.Entries {
entry.FileURI = UnescapePath(entry.FileURI)
entry.FolderURI = UnescapePath(entry.FolderURI)
relevantPath := entry.FileURI
if relevantPath == "" {
relevantPath = entry.FolderURI
}
res[relevantPath] = &entry
}
return res
}
func UnescapePath(input string) string {
if input == "" {
return input
}
input = strings.TrimPrefix(input, "file:///")
// For some reason QueryUnescape does not handle :
input = strings.ReplaceAll(input, "%3A", ":")
decoded, err := url.QueryUnescape(input)
if err != nil {
Error.Printf("Error decoding URI %s: %v", input, err)
return input
}
input = path.Clean(decoded)
return input
}
func EscapeConfig(config Config) Config {
for idx, entry := range config.Entries {
config.Entries[idx].FolderURI = EscapePath(entry.FolderURI)
config.Entries[idx].FileURI = EscapePath(entry.FileURI)
}
return config
}
func EscapePath(input string) string {
if input == "" {
return input
}
input = strings.TrimPrefix(input, "file:///")
escaped := url.QueryEscape(input)
escaped = strings.ReplaceAll(escaped, "%2F", "/")
escaped = strings.ReplaceAll(escaped, "%5C", "/")
escaped = strings.ReplaceAll(escaped, "+", "%20")
escaped = "file:///" + escaped
return escaped
}
func WriteDBConfig(config Config) error {
parsedConfig, err := json.Marshal(config)
if err != nil {
return err
}
conn, err := sql.Open("sqlite3", projectsFile)
if err != nil {
return err
}
_, err = conn.Exec(fmt.Sprintf("UPDATE %s SET value = ? WHERE key = '%s'", TABLE, KEY), string(parsedConfig))
if err != nil {
return err
}
return nil
}