package quikexport // Версия экспортёра ARQA: строка вида 12.1.5.2 внутри программы export. Кандидат сверяется с версией // установщика из .actions.log (install_quikexport-12.1.5.run), чтобы не принять чужую версию библиотеки. import ( "bytes" "os" "path/filepath" "regexp" "sync" "time" ) var ( exporterVerRe = regexp.MustCompile(`^\d{1,3}\.\d+\.\d+\.\d+$`) exporterInstallerRe = regexp.MustCompile(`install_quikexport-(\d+\.\d+\.\d+)\.run`) ) var exporterVerCache struct { sync.Mutex path string mod time.Time ver string } // exporterVersion — версия ARQA quikexport в каталоге dir ("" — не определена). func exporterVersion(dir string) string { bin := filepath.Join(dir, "export") fi, err := os.Stat(bin) if err != nil { return "" } exporterVerCache.Lock() defer exporterVerCache.Unlock() if exporterVerCache.path == bin && exporterVerCache.mod.Equal(fi.ModTime()) { return exporterVerCache.ver } installer := "" if log, err := os.ReadFile(filepath.Join(dir, ".actions.log")); err == nil { if m := exporterInstallerRe.FindAllSubmatch(log, -1); len(m) > 0 { installer = string(m[len(m)-1][1]) } } ver := "" if b, err := os.ReadFile(bin); err == nil { for _, tok := range bytes.Split(b, []byte{0}) { if len(tok) > 20 || !exporterVerRe.Match(tok) { continue } if installer == "" || bytes.HasPrefix(tok, []byte(installer+".")) { ver = string(tok) break } } } if ver == "" { ver = installer } exporterVerCache.path, exporterVerCache.mod, exporterVerCache.ver = bin, fi.ModTime(), ver return ver }