main.go (3616B)
1 // Executable dbconvert processes a given directory recursively and inserts all legacy template files, menu files and bytecode files into corresponding db.Db entries of the chosen backend. 2 package main 3 4 import ( 5 "context" 6 "flag" 7 "fmt" 8 "io" 9 "io/fs" 10 "log" 11 "os" 12 "path/filepath" 13 "path" 14 "strings" 15 16 "git.defalsify.org/vise.git/db" 17 fsdb "git.defalsify.org/vise.git/db/fs" 18 gdbmdb "git.defalsify.org/vise.git/db/gdbm" 19 "git.defalsify.org/vise.git/logging" 20 ) 21 22 var ( 23 binaryPrefix = ".bin" 24 menuPrefix = "menu" 25 staticloadPrefix = ".txt" 26 templatePrefix = "" 27 scan = make(map[string]string) 28 logg = logging.NewVanilla() 29 dbg = map[uint8]string{ 30 db.DATATYPE_BIN: "BIN", 31 db.DATATYPE_TEMPLATE: "TEMPLATE", 32 db.DATATYPE_MENU: "MENU", 33 db.DATATYPE_STATICLOAD: "STATICLOAD", 34 } 35 ) 36 37 type scanner struct { 38 ctx context.Context 39 db db.Db 40 } 41 42 func newScanner(ctx context.Context, db db.Db) (*scanner, error) { 43 return &scanner{ 44 ctx: ctx, 45 db: db, 46 }, nil 47 } 48 49 func(sc *scanner) Close() error { 50 return sc.db.Close() 51 } 52 53 func(sc *scanner) Scan(fp string, d fs.DirEntry, err error) error { 54 if err != nil { 55 return err 56 } 57 if d.IsDir() { 58 return nil 59 } 60 fx := path.Ext(fp) 61 fb := path.Base(fp) 62 if (len(fb) == 0) { 63 return nil 64 } 65 if (fb[0] < 0x61 || fb[0] > 0x7A) { 66 return nil 67 } 68 sc.db.SetPrefix(db.DATATYPE_UNKNOWN) 69 switch fx { 70 case binaryPrefix: 71 sc.db.SetPrefix(db.DATATYPE_BIN) 72 //typ = db.DATATYPE_BIN 73 case templatePrefix: 74 if strings.Contains(fb, "_menu") { 75 sc.db.SetPrefix(db.DATATYPE_TEMPLATE) 76 //typ = db.DATATYPE_TEMPLATE 77 } else { 78 sc.db.SetPrefix(db.DATATYPE_MENU) 79 //typ = db.DATATYPE_MENU 80 } 81 case staticloadPrefix: 82 sc.db.SetPrefix(db.DATATYPE_STATICLOAD) 83 default: 84 log.Printf("skip foreign file: %s", fp) 85 return nil 86 } 87 f, err := os.Open(fp) 88 defer f.Close() 89 if err != nil{ 90 return err 91 } 92 v, err := io.ReadAll(f) 93 if err != nil{ 94 return err 95 } 96 97 logg.TraceCtxf(sc.ctx, "put record", "fx", fx, "fb", fb) 98 ft := fb[:len(fb)-len(fx)] 99 err = sc.db.Put(sc.ctx, []byte(ft), v) 100 if err != nil { 101 return err 102 } 103 //k := db.ToDbKey(typ, []byte(ft), nil) 104 //err = sc.db.Store(k, v, true) 105 //if err != nil { 106 // return err 107 //} 108 return nil 109 } 110 111 func main() { 112 var store db.Db 113 var err error 114 var dir string 115 var dbPath string 116 var dbFile string 117 var dbBackend string 118 flag.StringVar(&dbPath, "d", "", "output directory") 119 flag.StringVar(&dbBackend, "backend", "gdbm", "db backend. valid choices are: gdbm (default), fs") 120 flag.Parse() 121 122 ctx := context.Background() 123 switch dbBackend { 124 case "gdbm": 125 store = gdbmdb.NewGdbmDb() 126 dbFile = "vise_resources.gdbm" 127 case "fs": 128 store = fsdb.NewFsDb() 129 } 130 131 dir = flag.Arg(0) 132 133 if dbPath == "" { 134 dbPath, err = os.MkdirTemp(dir, "vise-dbconvert-*") 135 } else { 136 err = os.MkdirAll(dir, 0700) 137 } 138 if err != nil { 139 fmt.Fprintf(os.Stderr, "failed to create output dir") 140 os.Exit(1) 141 } 142 if dbFile != "" { 143 dbPath = path.Join(dbPath, dbFile) 144 } 145 if dir == dbPath { 146 fmt.Fprintf(os.Stderr, "input and output dir cannot be the same") 147 } 148 149 err = store.Connect(ctx, dbPath) 150 if err != nil { 151 fmt.Fprintf(os.Stderr, "failed to connect to output db: %s", err) 152 os.Exit(1) 153 } 154 155 store.SetLock(db.DATATYPE_BIN, false) 156 store.SetLock(db.DATATYPE_TEMPLATE, false) 157 store.SetLock(db.DATATYPE_MENU, false) 158 store.SetLock(db.DATATYPE_STATICLOAD, false) 159 160 o, err := newScanner(ctx, store) 161 if err != nil { 162 fmt.Fprintf(os.Stderr, "failed to open scanner") 163 os.Exit(1) 164 } 165 err = filepath.WalkDir(dir, o.Scan) 166 if err != nil { 167 fmt.Fprintf(os.Stderr, "failed to process input: %s", err) 168 os.Exit(1) 169 } 170 fmt.Fprintf(os.Stdout, dbPath) 171 }