SQLite-backed Key / Value Store
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #17 from Tyrannican/v0.10/db-store

v0.10.0

authored by

Graham Keenan and committed by
GitHub
1cb1d0cf c713d1b4

+2005 -235
+1
.gitignore
··· 1 1 /target 2 2 safir/target 3 3 safir-mem/target 4 + *.json
+13
CHANGELOG.md
··· 2 2 3 3 Documenting changes between versions beginning from v0.3.0 4 4 5 + ## v0.10.0 6 + 7 + * SQLite DB support 8 + * Safir now supports using either a JSON file as storage or an SQLite database 9 + * Activate this by running `safir mode database` or `safir mode file` 10 + 11 + * Environments 12 + * Safir now supports storing Key-Value pairs in specific environments 13 + * Calling `safir use [environment-name]` will activate the specific environment 14 + * New environments are created empty and stored KV pairs will remain in this environment 15 + * A default environment called `default` is used initially 16 + * Old stores from previous versions will be ported to this new format automatically 17 + 5 18 ## v0.9.0 6 19 7 20 **THIS IS A BREAKING CHANGE**
+1407 -39
Cargo.lock
··· 3 3 version = 3 4 4 5 5 [[package]] 6 + name = "addr2line" 7 + version = "0.22.0" 8 + source = "registry+https://github.com/rust-lang/crates.io-index" 9 + checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" 10 + dependencies = [ 11 + "gimli", 12 + ] 13 + 14 + [[package]] 15 + name = "adler" 16 + version = "1.0.2" 17 + source = "registry+https://github.com/rust-lang/crates.io-index" 18 + checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 19 + 20 + [[package]] 21 + name = "ahash" 22 + version = "0.8.11" 23 + source = "registry+https://github.com/rust-lang/crates.io-index" 24 + checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" 25 + dependencies = [ 26 + "cfg-if", 27 + "getrandom", 28 + "once_cell", 29 + "version_check", 30 + "zerocopy", 31 + ] 32 + 33 + [[package]] 34 + name = "allocator-api2" 35 + version = "0.2.18" 36 + source = "registry+https://github.com/rust-lang/crates.io-index" 37 + checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" 38 + 39 + [[package]] 6 40 name = "anstream" 7 41 version = "0.3.2" 8 42 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 38 72 source = "registry+https://github.com/rust-lang/crates.io-index" 39 73 checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" 40 74 dependencies = [ 41 - "windows-sys", 75 + "windows-sys 0.48.0", 42 76 ] 43 77 44 78 [[package]] ··· 48 82 checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" 49 83 dependencies = [ 50 84 "anstyle", 51 - "windows-sys", 85 + "windows-sys 0.48.0", 52 86 ] 53 87 54 88 [[package]] ··· 56 90 version = "1.0.86" 57 91 source = "registry+https://github.com/rust-lang/crates.io-index" 58 92 checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" 93 + 94 + [[package]] 95 + name = "async-trait" 96 + version = "0.1.80" 97 + source = "registry+https://github.com/rust-lang/crates.io-index" 98 + checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" 99 + dependencies = [ 100 + "proc-macro2", 101 + "quote", 102 + "syn 2.0.66", 103 + ] 104 + 105 + [[package]] 106 + name = "atoi" 107 + version = "2.0.0" 108 + source = "registry+https://github.com/rust-lang/crates.io-index" 109 + checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" 110 + dependencies = [ 111 + "num-traits", 112 + ] 113 + 114 + [[package]] 115 + name = "autocfg" 116 + version = "1.3.0" 117 + source = "registry+https://github.com/rust-lang/crates.io-index" 118 + checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" 119 + 120 + [[package]] 121 + name = "backtrace" 122 + version = "0.3.73" 123 + source = "registry+https://github.com/rust-lang/crates.io-index" 124 + checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" 125 + dependencies = [ 126 + "addr2line", 127 + "cc", 128 + "cfg-if", 129 + "libc", 130 + "miniz_oxide", 131 + "object", 132 + "rustc-demangle", 133 + ] 134 + 135 + [[package]] 136 + name = "base64" 137 + version = "0.21.7" 138 + source = "registry+https://github.com/rust-lang/crates.io-index" 139 + checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" 140 + 141 + [[package]] 142 + name = "base64ct" 143 + version = "1.6.0" 144 + source = "registry+https://github.com/rust-lang/crates.io-index" 145 + checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" 59 146 60 147 [[package]] 61 148 name = "bitflags" ··· 64 151 checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 65 152 66 153 [[package]] 154 + name = "bitflags" 155 + version = "2.5.0" 156 + source = "registry+https://github.com/rust-lang/crates.io-index" 157 + checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" 158 + dependencies = [ 159 + "serde", 160 + ] 161 + 162 + [[package]] 163 + name = "block-buffer" 164 + version = "0.10.4" 165 + source = "registry+https://github.com/rust-lang/crates.io-index" 166 + checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 167 + dependencies = [ 168 + "generic-array", 169 + ] 170 + 171 + [[package]] 172 + name = "byteorder" 173 + version = "1.5.0" 174 + source = "registry+https://github.com/rust-lang/crates.io-index" 175 + checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 176 + 177 + [[package]] 178 + name = "bytes" 179 + version = "1.6.0" 180 + source = "registry+https://github.com/rust-lang/crates.io-index" 181 + checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" 182 + 183 + [[package]] 67 184 name = "cc" 68 - version = "1.0.79" 185 + version = "1.0.99" 69 186 source = "registry+https://github.com/rust-lang/crates.io-index" 70 - checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" 187 + checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" 71 188 72 189 [[package]] 73 190 name = "cfg-if" ··· 94 211 dependencies = [ 95 212 "anstream", 96 213 "anstyle", 97 - "bitflags", 214 + "bitflags 1.3.2", 98 215 "clap_lex", 99 216 "strsim", 100 217 ] ··· 108 225 "heck", 109 226 "proc-macro2", 110 227 "quote", 111 - "syn", 228 + "syn 2.0.66", 112 229 ] 113 230 114 231 [[package]] ··· 124 241 checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" 125 242 126 243 [[package]] 244 + name = "const-oid" 245 + version = "0.9.6" 246 + source = "registry+https://github.com/rust-lang/crates.io-index" 247 + checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" 248 + 249 + [[package]] 250 + name = "cpufeatures" 251 + version = "0.2.12" 252 + source = "registry+https://github.com/rust-lang/crates.io-index" 253 + checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" 254 + dependencies = [ 255 + "libc", 256 + ] 257 + 258 + [[package]] 259 + name = "crc" 260 + version = "3.2.1" 261 + source = "registry+https://github.com/rust-lang/crates.io-index" 262 + checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" 263 + dependencies = [ 264 + "crc-catalog", 265 + ] 266 + 267 + [[package]] 268 + name = "crc-catalog" 269 + version = "2.4.0" 270 + source = "registry+https://github.com/rust-lang/crates.io-index" 271 + checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" 272 + 273 + [[package]] 274 + name = "crossbeam-queue" 275 + version = "0.3.11" 276 + source = "registry+https://github.com/rust-lang/crates.io-index" 277 + checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" 278 + dependencies = [ 279 + "crossbeam-utils", 280 + ] 281 + 282 + [[package]] 283 + name = "crossbeam-utils" 284 + version = "0.8.20" 285 + source = "registry+https://github.com/rust-lang/crates.io-index" 286 + checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" 287 + 288 + [[package]] 289 + name = "crypto-common" 290 + version = "0.1.6" 291 + source = "registry+https://github.com/rust-lang/crates.io-index" 292 + checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 293 + dependencies = [ 294 + "generic-array", 295 + "typenum", 296 + ] 297 + 298 + [[package]] 299 + name = "der" 300 + version = "0.7.9" 301 + source = "registry+https://github.com/rust-lang/crates.io-index" 302 + checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" 303 + dependencies = [ 304 + "const-oid", 305 + "pem-rfc7468", 306 + "zeroize", 307 + ] 308 + 309 + [[package]] 310 + name = "digest" 311 + version = "0.10.7" 312 + source = "registry+https://github.com/rust-lang/crates.io-index" 313 + checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 314 + dependencies = [ 315 + "block-buffer", 316 + "const-oid", 317 + "crypto-common", 318 + "subtle", 319 + ] 320 + 321 + [[package]] 127 322 name = "dirs" 128 323 version = "5.0.1" 129 324 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 141 336 "libc", 142 337 "option-ext", 143 338 "redox_users", 144 - "windows-sys", 339 + "windows-sys 0.48.0", 340 + ] 341 + 342 + [[package]] 343 + name = "dotenvy" 344 + version = "0.15.7" 345 + source = "registry+https://github.com/rust-lang/crates.io-index" 346 + checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" 347 + 348 + [[package]] 349 + name = "either" 350 + version = "1.12.0" 351 + source = "registry+https://github.com/rust-lang/crates.io-index" 352 + checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" 353 + dependencies = [ 354 + "serde", 145 355 ] 146 356 147 357 [[package]] 358 + name = "equivalent" 359 + version = "1.0.1" 360 + source = "registry+https://github.com/rust-lang/crates.io-index" 361 + checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 362 + 363 + [[package]] 148 364 name = "errno" 149 - version = "0.3.1" 365 + version = "0.3.9" 150 366 source = "registry+https://github.com/rust-lang/crates.io-index" 151 - checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" 367 + checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" 152 368 dependencies = [ 153 - "errno-dragonfly", 154 369 "libc", 155 - "windows-sys", 370 + "windows-sys 0.52.0", 371 + ] 372 + 373 + [[package]] 374 + name = "etcetera" 375 + version = "0.8.0" 376 + source = "registry+https://github.com/rust-lang/crates.io-index" 377 + checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" 378 + dependencies = [ 379 + "cfg-if", 380 + "home", 381 + "windows-sys 0.48.0", 382 + ] 383 + 384 + [[package]] 385 + name = "event-listener" 386 + version = "2.5.3" 387 + source = "registry+https://github.com/rust-lang/crates.io-index" 388 + checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" 389 + 390 + [[package]] 391 + name = "fastrand" 392 + version = "2.1.0" 393 + source = "registry+https://github.com/rust-lang/crates.io-index" 394 + checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" 395 + 396 + [[package]] 397 + name = "flume" 398 + version = "0.11.0" 399 + source = "registry+https://github.com/rust-lang/crates.io-index" 400 + checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" 401 + dependencies = [ 402 + "futures-core", 403 + "futures-sink", 404 + "spin 0.9.8", 405 + ] 406 + 407 + [[package]] 408 + name = "form_urlencoded" 409 + version = "1.2.1" 410 + source = "registry+https://github.com/rust-lang/crates.io-index" 411 + checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 412 + dependencies = [ 413 + "percent-encoding", 414 + ] 415 + 416 + [[package]] 417 + name = "futures-channel" 418 + version = "0.3.30" 419 + source = "registry+https://github.com/rust-lang/crates.io-index" 420 + checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" 421 + dependencies = [ 422 + "futures-core", 423 + "futures-sink", 424 + ] 425 + 426 + [[package]] 427 + name = "futures-core" 428 + version = "0.3.30" 429 + source = "registry+https://github.com/rust-lang/crates.io-index" 430 + checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" 431 + 432 + [[package]] 433 + name = "futures-executor" 434 + version = "0.3.30" 435 + source = "registry+https://github.com/rust-lang/crates.io-index" 436 + checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" 437 + dependencies = [ 438 + "futures-core", 439 + "futures-task", 440 + "futures-util", 156 441 ] 157 442 158 443 [[package]] 159 - name = "errno-dragonfly" 160 - version = "0.1.2" 444 + name = "futures-intrusive" 445 + version = "0.5.0" 161 446 source = "registry+https://github.com/rust-lang/crates.io-index" 162 - checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" 447 + checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" 163 448 dependencies = [ 164 - "cc", 165 - "libc", 449 + "futures-core", 450 + "lock_api", 451 + "parking_lot", 452 + ] 453 + 454 + [[package]] 455 + name = "futures-io" 456 + version = "0.3.30" 457 + source = "registry+https://github.com/rust-lang/crates.io-index" 458 + checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" 459 + 460 + [[package]] 461 + name = "futures-sink" 462 + version = "0.3.30" 463 + source = "registry+https://github.com/rust-lang/crates.io-index" 464 + checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" 465 + 466 + [[package]] 467 + name = "futures-task" 468 + version = "0.3.30" 469 + source = "registry+https://github.com/rust-lang/crates.io-index" 470 + checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" 471 + 472 + [[package]] 473 + name = "futures-util" 474 + version = "0.3.30" 475 + source = "registry+https://github.com/rust-lang/crates.io-index" 476 + checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" 477 + dependencies = [ 478 + "futures-core", 479 + "futures-io", 480 + "futures-sink", 481 + "futures-task", 482 + "memchr", 483 + "pin-project-lite", 484 + "pin-utils", 485 + "slab", 486 + ] 487 + 488 + [[package]] 489 + name = "generic-array" 490 + version = "0.14.7" 491 + source = "registry+https://github.com/rust-lang/crates.io-index" 492 + checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 493 + dependencies = [ 494 + "typenum", 495 + "version_check", 166 496 ] 167 497 168 498 [[package]] ··· 177 507 ] 178 508 179 509 [[package]] 510 + name = "gimli" 511 + version = "0.29.0" 512 + source = "registry+https://github.com/rust-lang/crates.io-index" 513 + checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" 514 + 515 + [[package]] 516 + name = "hashbrown" 517 + version = "0.14.5" 518 + source = "registry+https://github.com/rust-lang/crates.io-index" 519 + checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 520 + dependencies = [ 521 + "ahash", 522 + "allocator-api2", 523 + ] 524 + 525 + [[package]] 526 + name = "hashlink" 527 + version = "0.8.4" 528 + source = "registry+https://github.com/rust-lang/crates.io-index" 529 + checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" 530 + dependencies = [ 531 + "hashbrown", 532 + ] 533 + 534 + [[package]] 180 535 name = "heck" 181 536 version = "0.4.1" 182 537 source = "registry+https://github.com/rust-lang/crates.io-index" 183 538 checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 539 + dependencies = [ 540 + "unicode-segmentation", 541 + ] 184 542 185 543 [[package]] 186 544 name = "hermit-abi" ··· 189 547 checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" 190 548 191 549 [[package]] 550 + name = "hex" 551 + version = "0.4.3" 552 + source = "registry+https://github.com/rust-lang/crates.io-index" 553 + checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 554 + 555 + [[package]] 556 + name = "hkdf" 557 + version = "0.12.4" 558 + source = "registry+https://github.com/rust-lang/crates.io-index" 559 + checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" 560 + dependencies = [ 561 + "hmac", 562 + ] 563 + 564 + [[package]] 565 + name = "hmac" 566 + version = "0.12.1" 567 + source = "registry+https://github.com/rust-lang/crates.io-index" 568 + checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" 569 + dependencies = [ 570 + "digest", 571 + ] 572 + 573 + [[package]] 574 + name = "home" 575 + version = "0.5.9" 576 + source = "registry+https://github.com/rust-lang/crates.io-index" 577 + checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" 578 + dependencies = [ 579 + "windows-sys 0.52.0", 580 + ] 581 + 582 + [[package]] 583 + name = "idna" 584 + version = "0.5.0" 585 + source = "registry+https://github.com/rust-lang/crates.io-index" 586 + checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" 587 + dependencies = [ 588 + "unicode-bidi", 589 + "unicode-normalization", 590 + ] 591 + 592 + [[package]] 593 + name = "indexmap" 594 + version = "2.2.6" 595 + source = "registry+https://github.com/rust-lang/crates.io-index" 596 + checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" 597 + dependencies = [ 598 + "equivalent", 599 + "hashbrown", 600 + ] 601 + 602 + [[package]] 192 603 name = "io-lifetimes" 193 604 version = "1.0.11" 194 605 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 196 607 dependencies = [ 197 608 "hermit-abi", 198 609 "libc", 199 - "windows-sys", 610 + "windows-sys 0.48.0", 200 611 ] 201 612 202 613 [[package]] ··· 207 618 dependencies = [ 208 619 "hermit-abi", 209 620 "io-lifetimes", 210 - "rustix", 211 - "windows-sys", 621 + "rustix 0.37.19", 622 + "windows-sys 0.48.0", 212 623 ] 213 624 214 625 [[package]] ··· 218 629 checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" 219 630 220 631 [[package]] 632 + name = "lazy_static" 633 + version = "1.4.0" 634 + source = "registry+https://github.com/rust-lang/crates.io-index" 635 + checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 636 + dependencies = [ 637 + "spin 0.5.2", 638 + ] 639 + 640 + [[package]] 221 641 name = "libc" 222 - version = "0.2.144" 642 + version = "0.2.155" 643 + source = "registry+https://github.com/rust-lang/crates.io-index" 644 + checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" 645 + 646 + [[package]] 647 + name = "libm" 648 + version = "0.2.8" 649 + source = "registry+https://github.com/rust-lang/crates.io-index" 650 + checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" 651 + 652 + [[package]] 653 + name = "libsqlite3-sys" 654 + version = "0.27.0" 223 655 source = "registry+https://github.com/rust-lang/crates.io-index" 224 - checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" 656 + checksum = "cf4e226dcd58b4be396f7bd3c20da8fdee2911400705297ba7d2d7cc2c30f716" 657 + dependencies = [ 658 + "cc", 659 + "pkg-config", 660 + "vcpkg", 661 + ] 225 662 226 663 [[package]] 227 664 name = "linux-raw-sys" ··· 230 667 checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" 231 668 232 669 [[package]] 670 + name = "linux-raw-sys" 671 + version = "0.4.14" 672 + source = "registry+https://github.com/rust-lang/crates.io-index" 673 + checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" 674 + 675 + [[package]] 676 + name = "lock_api" 677 + version = "0.4.12" 678 + source = "registry+https://github.com/rust-lang/crates.io-index" 679 + checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" 680 + dependencies = [ 681 + "autocfg", 682 + "scopeguard", 683 + ] 684 + 685 + [[package]] 686 + name = "log" 687 + version = "0.4.21" 688 + source = "registry+https://github.com/rust-lang/crates.io-index" 689 + checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" 690 + 691 + [[package]] 692 + name = "md-5" 693 + version = "0.10.6" 694 + source = "registry+https://github.com/rust-lang/crates.io-index" 695 + checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" 696 + dependencies = [ 697 + "cfg-if", 698 + "digest", 699 + ] 700 + 701 + [[package]] 702 + name = "memchr" 703 + version = "2.7.4" 704 + source = "registry+https://github.com/rust-lang/crates.io-index" 705 + checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 706 + 707 + [[package]] 708 + name = "minimal-lexical" 709 + version = "0.2.1" 710 + source = "registry+https://github.com/rust-lang/crates.io-index" 711 + checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 712 + 713 + [[package]] 714 + name = "miniz_oxide" 715 + version = "0.7.4" 716 + source = "registry+https://github.com/rust-lang/crates.io-index" 717 + checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" 718 + dependencies = [ 719 + "adler", 720 + ] 721 + 722 + [[package]] 723 + name = "mio" 724 + version = "0.8.11" 725 + source = "registry+https://github.com/rust-lang/crates.io-index" 726 + checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" 727 + dependencies = [ 728 + "libc", 729 + "wasi", 730 + "windows-sys 0.48.0", 731 + ] 732 + 733 + [[package]] 734 + name = "nom" 735 + version = "7.1.3" 736 + source = "registry+https://github.com/rust-lang/crates.io-index" 737 + checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 738 + dependencies = [ 739 + "memchr", 740 + "minimal-lexical", 741 + ] 742 + 743 + [[package]] 744 + name = "num-bigint-dig" 745 + version = "0.8.4" 746 + source = "registry+https://github.com/rust-lang/crates.io-index" 747 + checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" 748 + dependencies = [ 749 + "byteorder", 750 + "lazy_static", 751 + "libm", 752 + "num-integer", 753 + "num-iter", 754 + "num-traits", 755 + "rand", 756 + "smallvec", 757 + "zeroize", 758 + ] 759 + 760 + [[package]] 761 + name = "num-integer" 762 + version = "0.1.46" 763 + source = "registry+https://github.com/rust-lang/crates.io-index" 764 + checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" 765 + dependencies = [ 766 + "num-traits", 767 + ] 768 + 769 + [[package]] 770 + name = "num-iter" 771 + version = "0.1.45" 772 + source = "registry+https://github.com/rust-lang/crates.io-index" 773 + checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" 774 + dependencies = [ 775 + "autocfg", 776 + "num-integer", 777 + "num-traits", 778 + ] 779 + 780 + [[package]] 781 + name = "num-traits" 782 + version = "0.2.19" 783 + source = "registry+https://github.com/rust-lang/crates.io-index" 784 + checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 785 + dependencies = [ 786 + "autocfg", 787 + "libm", 788 + ] 789 + 790 + [[package]] 791 + name = "num_cpus" 792 + version = "1.16.0" 793 + source = "registry+https://github.com/rust-lang/crates.io-index" 794 + checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" 795 + dependencies = [ 796 + "hermit-abi", 797 + "libc", 798 + ] 799 + 800 + [[package]] 801 + name = "object" 802 + version = "0.36.0" 803 + source = "registry+https://github.com/rust-lang/crates.io-index" 804 + checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" 805 + dependencies = [ 806 + "memchr", 807 + ] 808 + 809 + [[package]] 233 810 name = "once_cell" 234 - version = "1.17.2" 811 + version = "1.19.0" 235 812 source = "registry+https://github.com/rust-lang/crates.io-index" 236 - checksum = "9670a07f94779e00908f3e686eab508878ebb390ba6e604d3a284c00e8d0487b" 813 + checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" 237 814 238 815 [[package]] 239 816 name = "option-ext" ··· 242 819 checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" 243 820 244 821 [[package]] 822 + name = "parking_lot" 823 + version = "0.12.3" 824 + source = "registry+https://github.com/rust-lang/crates.io-index" 825 + checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" 826 + dependencies = [ 827 + "lock_api", 828 + "parking_lot_core", 829 + ] 830 + 831 + [[package]] 832 + name = "parking_lot_core" 833 + version = "0.9.10" 834 + source = "registry+https://github.com/rust-lang/crates.io-index" 835 + checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" 836 + dependencies = [ 837 + "cfg-if", 838 + "libc", 839 + "redox_syscall 0.5.2", 840 + "smallvec", 841 + "windows-targets 0.52.5", 842 + ] 843 + 844 + [[package]] 845 + name = "paste" 846 + version = "1.0.15" 847 + source = "registry+https://github.com/rust-lang/crates.io-index" 848 + checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 849 + 850 + [[package]] 851 + name = "pem-rfc7468" 852 + version = "0.7.0" 853 + source = "registry+https://github.com/rust-lang/crates.io-index" 854 + checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" 855 + dependencies = [ 856 + "base64ct", 857 + ] 858 + 859 + [[package]] 860 + name = "percent-encoding" 861 + version = "2.3.1" 862 + source = "registry+https://github.com/rust-lang/crates.io-index" 863 + checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 864 + 865 + [[package]] 866 + name = "pin-project-lite" 867 + version = "0.2.14" 868 + source = "registry+https://github.com/rust-lang/crates.io-index" 869 + checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" 870 + 871 + [[package]] 872 + name = "pin-utils" 873 + version = "0.1.0" 874 + source = "registry+https://github.com/rust-lang/crates.io-index" 875 + checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 876 + 877 + [[package]] 878 + name = "pkcs1" 879 + version = "0.7.5" 880 + source = "registry+https://github.com/rust-lang/crates.io-index" 881 + checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" 882 + dependencies = [ 883 + "der", 884 + "pkcs8", 885 + "spki", 886 + ] 887 + 888 + [[package]] 889 + name = "pkcs8" 890 + version = "0.10.2" 891 + source = "registry+https://github.com/rust-lang/crates.io-index" 892 + checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" 893 + dependencies = [ 894 + "der", 895 + "spki", 896 + ] 897 + 898 + [[package]] 899 + name = "pkg-config" 900 + version = "0.3.30" 901 + source = "registry+https://github.com/rust-lang/crates.io-index" 902 + checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" 903 + 904 + [[package]] 905 + name = "ppv-lite86" 906 + version = "0.2.17" 907 + source = "registry+https://github.com/rust-lang/crates.io-index" 908 + checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" 909 + 910 + [[package]] 245 911 name = "proc-macro2" 246 912 version = "1.0.85" 247 913 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 260 926 ] 261 927 262 928 [[package]] 929 + name = "rand" 930 + version = "0.8.5" 931 + source = "registry+https://github.com/rust-lang/crates.io-index" 932 + checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 933 + dependencies = [ 934 + "libc", 935 + "rand_chacha", 936 + "rand_core", 937 + ] 938 + 939 + [[package]] 940 + name = "rand_chacha" 941 + version = "0.3.1" 942 + source = "registry+https://github.com/rust-lang/crates.io-index" 943 + checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 944 + dependencies = [ 945 + "ppv-lite86", 946 + "rand_core", 947 + ] 948 + 949 + [[package]] 950 + name = "rand_core" 951 + version = "0.6.4" 952 + source = "registry+https://github.com/rust-lang/crates.io-index" 953 + checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 954 + dependencies = [ 955 + "getrandom", 956 + ] 957 + 958 + [[package]] 263 959 name = "redox_syscall" 264 960 version = "0.2.16" 265 961 source = "registry+https://github.com/rust-lang/crates.io-index" 266 962 checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 267 963 dependencies = [ 268 - "bitflags", 964 + "bitflags 1.3.2", 965 + ] 966 + 967 + [[package]] 968 + name = "redox_syscall" 969 + version = "0.4.1" 970 + source = "registry+https://github.com/rust-lang/crates.io-index" 971 + checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" 972 + dependencies = [ 973 + "bitflags 1.3.2", 974 + ] 975 + 976 + [[package]] 977 + name = "redox_syscall" 978 + version = "0.5.2" 979 + source = "registry+https://github.com/rust-lang/crates.io-index" 980 + checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" 981 + dependencies = [ 982 + "bitflags 2.5.0", 269 983 ] 270 984 271 985 [[package]] ··· 275 989 checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" 276 990 dependencies = [ 277 991 "getrandom", 278 - "redox_syscall", 992 + "redox_syscall 0.2.16", 279 993 "thiserror", 280 994 ] 281 995 282 996 [[package]] 997 + name = "rsa" 998 + version = "0.9.6" 999 + source = "registry+https://github.com/rust-lang/crates.io-index" 1000 + checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" 1001 + dependencies = [ 1002 + "const-oid", 1003 + "digest", 1004 + "num-bigint-dig", 1005 + "num-integer", 1006 + "num-traits", 1007 + "pkcs1", 1008 + "pkcs8", 1009 + "rand_core", 1010 + "signature", 1011 + "spki", 1012 + "subtle", 1013 + "zeroize", 1014 + ] 1015 + 1016 + [[package]] 1017 + name = "rustc-demangle" 1018 + version = "0.1.24" 1019 + source = "registry+https://github.com/rust-lang/crates.io-index" 1020 + checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" 1021 + 1022 + [[package]] 283 1023 name = "rustix" 284 1024 version = "0.37.19" 285 1025 source = "registry+https://github.com/rust-lang/crates.io-index" 286 1026 checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" 287 1027 dependencies = [ 288 - "bitflags", 1028 + "bitflags 1.3.2", 289 1029 "errno", 290 1030 "io-lifetimes", 291 1031 "libc", 292 - "linux-raw-sys", 293 - "windows-sys", 1032 + "linux-raw-sys 0.3.8", 1033 + "windows-sys 0.48.0", 1034 + ] 1035 + 1036 + [[package]] 1037 + name = "rustix" 1038 + version = "0.38.34" 1039 + source = "registry+https://github.com/rust-lang/crates.io-index" 1040 + checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" 1041 + dependencies = [ 1042 + "bitflags 2.5.0", 1043 + "errno", 1044 + "libc", 1045 + "linux-raw-sys 0.4.14", 1046 + "windows-sys 0.52.0", 294 1047 ] 295 1048 296 1049 [[package]] ··· 301 1054 302 1055 [[package]] 303 1056 name = "safir" 304 - version = "0.9.0" 1057 + version = "0.10.0" 305 1058 dependencies = [ 306 1059 "anyhow", 1060 + "async-trait", 307 1061 "clap", 308 1062 "dirs", 1063 + "serde", 309 1064 "serde_json", 1065 + "sqlx", 1066 + "tokio", 310 1067 ] 311 1068 312 1069 [[package]] 1070 + name = "scopeguard" 1071 + version = "1.2.0" 1072 + source = "registry+https://github.com/rust-lang/crates.io-index" 1073 + checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 1074 + 1075 + [[package]] 313 1076 name = "serde" 314 1077 version = "1.0.203" 315 1078 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 326 1089 dependencies = [ 327 1090 "proc-macro2", 328 1091 "quote", 329 - "syn", 1092 + "syn 2.0.66", 330 1093 ] 331 1094 332 1095 [[package]] ··· 341 1104 ] 342 1105 343 1106 [[package]] 1107 + name = "sha1" 1108 + version = "0.10.6" 1109 + source = "registry+https://github.com/rust-lang/crates.io-index" 1110 + checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" 1111 + dependencies = [ 1112 + "cfg-if", 1113 + "cpufeatures", 1114 + "digest", 1115 + ] 1116 + 1117 + [[package]] 1118 + name = "sha2" 1119 + version = "0.10.8" 1120 + source = "registry+https://github.com/rust-lang/crates.io-index" 1121 + checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" 1122 + dependencies = [ 1123 + "cfg-if", 1124 + "cpufeatures", 1125 + "digest", 1126 + ] 1127 + 1128 + [[package]] 1129 + name = "signal-hook-registry" 1130 + version = "1.4.2" 1131 + source = "registry+https://github.com/rust-lang/crates.io-index" 1132 + checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" 1133 + dependencies = [ 1134 + "libc", 1135 + ] 1136 + 1137 + [[package]] 1138 + name = "signature" 1139 + version = "2.2.0" 1140 + source = "registry+https://github.com/rust-lang/crates.io-index" 1141 + checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" 1142 + dependencies = [ 1143 + "digest", 1144 + "rand_core", 1145 + ] 1146 + 1147 + [[package]] 1148 + name = "slab" 1149 + version = "0.4.9" 1150 + source = "registry+https://github.com/rust-lang/crates.io-index" 1151 + checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 1152 + dependencies = [ 1153 + "autocfg", 1154 + ] 1155 + 1156 + [[package]] 1157 + name = "smallvec" 1158 + version = "1.13.2" 1159 + source = "registry+https://github.com/rust-lang/crates.io-index" 1160 + checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" 1161 + 1162 + [[package]] 1163 + name = "socket2" 1164 + version = "0.5.7" 1165 + source = "registry+https://github.com/rust-lang/crates.io-index" 1166 + checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" 1167 + dependencies = [ 1168 + "libc", 1169 + "windows-sys 0.52.0", 1170 + ] 1171 + 1172 + [[package]] 1173 + name = "spin" 1174 + version = "0.5.2" 1175 + source = "registry+https://github.com/rust-lang/crates.io-index" 1176 + checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" 1177 + 1178 + [[package]] 1179 + name = "spin" 1180 + version = "0.9.8" 1181 + source = "registry+https://github.com/rust-lang/crates.io-index" 1182 + checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" 1183 + dependencies = [ 1184 + "lock_api", 1185 + ] 1186 + 1187 + [[package]] 1188 + name = "spki" 1189 + version = "0.7.3" 1190 + source = "registry+https://github.com/rust-lang/crates.io-index" 1191 + checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" 1192 + dependencies = [ 1193 + "base64ct", 1194 + "der", 1195 + ] 1196 + 1197 + [[package]] 1198 + name = "sqlformat" 1199 + version = "0.2.4" 1200 + source = "registry+https://github.com/rust-lang/crates.io-index" 1201 + checksum = "f895e3734318cc55f1fe66258926c9b910c124d47520339efecbb6c59cec7c1f" 1202 + dependencies = [ 1203 + "nom", 1204 + "unicode_categories", 1205 + ] 1206 + 1207 + [[package]] 1208 + name = "sqlx" 1209 + version = "0.7.4" 1210 + source = "registry+https://github.com/rust-lang/crates.io-index" 1211 + checksum = "c9a2ccff1a000a5a59cd33da541d9f2fdcd9e6e8229cc200565942bff36d0aaa" 1212 + dependencies = [ 1213 + "sqlx-core", 1214 + "sqlx-macros", 1215 + "sqlx-mysql", 1216 + "sqlx-postgres", 1217 + "sqlx-sqlite", 1218 + ] 1219 + 1220 + [[package]] 1221 + name = "sqlx-core" 1222 + version = "0.7.4" 1223 + source = "registry+https://github.com/rust-lang/crates.io-index" 1224 + checksum = "24ba59a9342a3d9bab6c56c118be528b27c9b60e490080e9711a04dccac83ef6" 1225 + dependencies = [ 1226 + "ahash", 1227 + "atoi", 1228 + "byteorder", 1229 + "bytes", 1230 + "crc", 1231 + "crossbeam-queue", 1232 + "either", 1233 + "event-listener", 1234 + "futures-channel", 1235 + "futures-core", 1236 + "futures-intrusive", 1237 + "futures-io", 1238 + "futures-util", 1239 + "hashlink", 1240 + "hex", 1241 + "indexmap", 1242 + "log", 1243 + "memchr", 1244 + "once_cell", 1245 + "paste", 1246 + "percent-encoding", 1247 + "serde", 1248 + "serde_json", 1249 + "sha2", 1250 + "smallvec", 1251 + "sqlformat", 1252 + "thiserror", 1253 + "tokio", 1254 + "tokio-stream", 1255 + "tracing", 1256 + "url", 1257 + ] 1258 + 1259 + [[package]] 1260 + name = "sqlx-macros" 1261 + version = "0.7.4" 1262 + source = "registry+https://github.com/rust-lang/crates.io-index" 1263 + checksum = "4ea40e2345eb2faa9e1e5e326db8c34711317d2b5e08d0d5741619048a803127" 1264 + dependencies = [ 1265 + "proc-macro2", 1266 + "quote", 1267 + "sqlx-core", 1268 + "sqlx-macros-core", 1269 + "syn 1.0.109", 1270 + ] 1271 + 1272 + [[package]] 1273 + name = "sqlx-macros-core" 1274 + version = "0.7.4" 1275 + source = "registry+https://github.com/rust-lang/crates.io-index" 1276 + checksum = "5833ef53aaa16d860e92123292f1f6a3d53c34ba8b1969f152ef1a7bb803f3c8" 1277 + dependencies = [ 1278 + "dotenvy", 1279 + "either", 1280 + "heck", 1281 + "hex", 1282 + "once_cell", 1283 + "proc-macro2", 1284 + "quote", 1285 + "serde", 1286 + "serde_json", 1287 + "sha2", 1288 + "sqlx-core", 1289 + "sqlx-mysql", 1290 + "sqlx-sqlite", 1291 + "syn 1.0.109", 1292 + "tempfile", 1293 + "tokio", 1294 + "url", 1295 + ] 1296 + 1297 + [[package]] 1298 + name = "sqlx-mysql" 1299 + version = "0.7.4" 1300 + source = "registry+https://github.com/rust-lang/crates.io-index" 1301 + checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418" 1302 + dependencies = [ 1303 + "atoi", 1304 + "base64", 1305 + "bitflags 2.5.0", 1306 + "byteorder", 1307 + "bytes", 1308 + "crc", 1309 + "digest", 1310 + "dotenvy", 1311 + "either", 1312 + "futures-channel", 1313 + "futures-core", 1314 + "futures-io", 1315 + "futures-util", 1316 + "generic-array", 1317 + "hex", 1318 + "hkdf", 1319 + "hmac", 1320 + "itoa", 1321 + "log", 1322 + "md-5", 1323 + "memchr", 1324 + "once_cell", 1325 + "percent-encoding", 1326 + "rand", 1327 + "rsa", 1328 + "serde", 1329 + "sha1", 1330 + "sha2", 1331 + "smallvec", 1332 + "sqlx-core", 1333 + "stringprep", 1334 + "thiserror", 1335 + "tracing", 1336 + "whoami", 1337 + ] 1338 + 1339 + [[package]] 1340 + name = "sqlx-postgres" 1341 + version = "0.7.4" 1342 + source = "registry+https://github.com/rust-lang/crates.io-index" 1343 + checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e" 1344 + dependencies = [ 1345 + "atoi", 1346 + "base64", 1347 + "bitflags 2.5.0", 1348 + "byteorder", 1349 + "crc", 1350 + "dotenvy", 1351 + "etcetera", 1352 + "futures-channel", 1353 + "futures-core", 1354 + "futures-io", 1355 + "futures-util", 1356 + "hex", 1357 + "hkdf", 1358 + "hmac", 1359 + "home", 1360 + "itoa", 1361 + "log", 1362 + "md-5", 1363 + "memchr", 1364 + "once_cell", 1365 + "rand", 1366 + "serde", 1367 + "serde_json", 1368 + "sha2", 1369 + "smallvec", 1370 + "sqlx-core", 1371 + "stringprep", 1372 + "thiserror", 1373 + "tracing", 1374 + "whoami", 1375 + ] 1376 + 1377 + [[package]] 1378 + name = "sqlx-sqlite" 1379 + version = "0.7.4" 1380 + source = "registry+https://github.com/rust-lang/crates.io-index" 1381 + checksum = "b244ef0a8414da0bed4bb1910426e890b19e5e9bccc27ada6b797d05c55ae0aa" 1382 + dependencies = [ 1383 + "atoi", 1384 + "flume", 1385 + "futures-channel", 1386 + "futures-core", 1387 + "futures-executor", 1388 + "futures-intrusive", 1389 + "futures-util", 1390 + "libsqlite3-sys", 1391 + "log", 1392 + "percent-encoding", 1393 + "serde", 1394 + "sqlx-core", 1395 + "tracing", 1396 + "url", 1397 + "urlencoding", 1398 + ] 1399 + 1400 + [[package]] 1401 + name = "stringprep" 1402 + version = "0.1.5" 1403 + source = "registry+https://github.com/rust-lang/crates.io-index" 1404 + checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" 1405 + dependencies = [ 1406 + "unicode-bidi", 1407 + "unicode-normalization", 1408 + "unicode-properties", 1409 + ] 1410 + 1411 + [[package]] 344 1412 name = "strsim" 345 1413 version = "0.10.0" 346 1414 source = "registry+https://github.com/rust-lang/crates.io-index" 347 1415 checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 348 1416 349 1417 [[package]] 1418 + name = "subtle" 1419 + version = "2.6.0" 1420 + source = "registry+https://github.com/rust-lang/crates.io-index" 1421 + checksum = "0d0208408ba0c3df17ed26eb06992cb1a1268d41b2c0e12e65203fbe3972cee5" 1422 + 1423 + [[package]] 1424 + name = "syn" 1425 + version = "1.0.109" 1426 + source = "registry+https://github.com/rust-lang/crates.io-index" 1427 + checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 1428 + dependencies = [ 1429 + "proc-macro2", 1430 + "quote", 1431 + "unicode-ident", 1432 + ] 1433 + 1434 + [[package]] 350 1435 name = "syn" 351 1436 version = "2.0.66" 352 1437 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 358 1443 ] 359 1444 360 1445 [[package]] 1446 + name = "tempfile" 1447 + version = "3.10.1" 1448 + source = "registry+https://github.com/rust-lang/crates.io-index" 1449 + checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" 1450 + dependencies = [ 1451 + "cfg-if", 1452 + "fastrand", 1453 + "rustix 0.38.34", 1454 + "windows-sys 0.52.0", 1455 + ] 1456 + 1457 + [[package]] 361 1458 name = "thiserror" 362 1459 version = "1.0.40" 363 1460 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 374 1471 dependencies = [ 375 1472 "proc-macro2", 376 1473 "quote", 377 - "syn", 1474 + "syn 2.0.66", 1475 + ] 1476 + 1477 + [[package]] 1478 + name = "tinyvec" 1479 + version = "1.6.0" 1480 + source = "registry+https://github.com/rust-lang/crates.io-index" 1481 + checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" 1482 + dependencies = [ 1483 + "tinyvec_macros", 1484 + ] 1485 + 1486 + [[package]] 1487 + name = "tinyvec_macros" 1488 + version = "0.1.1" 1489 + source = "registry+https://github.com/rust-lang/crates.io-index" 1490 + checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 1491 + 1492 + [[package]] 1493 + name = "tokio" 1494 + version = "1.38.0" 1495 + source = "registry+https://github.com/rust-lang/crates.io-index" 1496 + checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" 1497 + dependencies = [ 1498 + "backtrace", 1499 + "bytes", 1500 + "libc", 1501 + "mio", 1502 + "num_cpus", 1503 + "parking_lot", 1504 + "pin-project-lite", 1505 + "signal-hook-registry", 1506 + "socket2", 1507 + "tokio-macros", 1508 + "windows-sys 0.48.0", 1509 + ] 1510 + 1511 + [[package]] 1512 + name = "tokio-macros" 1513 + version = "2.3.0" 1514 + source = "registry+https://github.com/rust-lang/crates.io-index" 1515 + checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" 1516 + dependencies = [ 1517 + "proc-macro2", 1518 + "quote", 1519 + "syn 2.0.66", 378 1520 ] 379 1521 380 1522 [[package]] 1523 + name = "tokio-stream" 1524 + version = "0.1.15" 1525 + source = "registry+https://github.com/rust-lang/crates.io-index" 1526 + checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" 1527 + dependencies = [ 1528 + "futures-core", 1529 + "pin-project-lite", 1530 + "tokio", 1531 + ] 1532 + 1533 + [[package]] 1534 + name = "tracing" 1535 + version = "0.1.40" 1536 + source = "registry+https://github.com/rust-lang/crates.io-index" 1537 + checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" 1538 + dependencies = [ 1539 + "log", 1540 + "pin-project-lite", 1541 + "tracing-attributes", 1542 + "tracing-core", 1543 + ] 1544 + 1545 + [[package]] 1546 + name = "tracing-attributes" 1547 + version = "0.1.27" 1548 + source = "registry+https://github.com/rust-lang/crates.io-index" 1549 + checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" 1550 + dependencies = [ 1551 + "proc-macro2", 1552 + "quote", 1553 + "syn 2.0.66", 1554 + ] 1555 + 1556 + [[package]] 1557 + name = "tracing-core" 1558 + version = "0.1.32" 1559 + source = "registry+https://github.com/rust-lang/crates.io-index" 1560 + checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" 1561 + dependencies = [ 1562 + "once_cell", 1563 + ] 1564 + 1565 + [[package]] 1566 + name = "typenum" 1567 + version = "1.17.0" 1568 + source = "registry+https://github.com/rust-lang/crates.io-index" 1569 + checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" 1570 + 1571 + [[package]] 1572 + name = "unicode-bidi" 1573 + version = "0.3.15" 1574 + source = "registry+https://github.com/rust-lang/crates.io-index" 1575 + checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" 1576 + 1577 + [[package]] 381 1578 name = "unicode-ident" 382 1579 version = "1.0.9" 383 1580 source = "registry+https://github.com/rust-lang/crates.io-index" 384 1581 checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" 385 1582 386 1583 [[package]] 1584 + name = "unicode-normalization" 1585 + version = "0.1.23" 1586 + source = "registry+https://github.com/rust-lang/crates.io-index" 1587 + checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" 1588 + dependencies = [ 1589 + "tinyvec", 1590 + ] 1591 + 1592 + [[package]] 1593 + name = "unicode-properties" 1594 + version = "0.1.1" 1595 + source = "registry+https://github.com/rust-lang/crates.io-index" 1596 + checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291" 1597 + 1598 + [[package]] 1599 + name = "unicode-segmentation" 1600 + version = "1.11.0" 1601 + source = "registry+https://github.com/rust-lang/crates.io-index" 1602 + checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" 1603 + 1604 + [[package]] 1605 + name = "unicode_categories" 1606 + version = "0.1.1" 1607 + source = "registry+https://github.com/rust-lang/crates.io-index" 1608 + checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" 1609 + 1610 + [[package]] 1611 + name = "url" 1612 + version = "2.5.2" 1613 + source = "registry+https://github.com/rust-lang/crates.io-index" 1614 + checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" 1615 + dependencies = [ 1616 + "form_urlencoded", 1617 + "idna", 1618 + "percent-encoding", 1619 + ] 1620 + 1621 + [[package]] 1622 + name = "urlencoding" 1623 + version = "2.1.3" 1624 + source = "registry+https://github.com/rust-lang/crates.io-index" 1625 + checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" 1626 + 1627 + [[package]] 387 1628 name = "utf8parse" 388 1629 version = "0.2.1" 389 1630 source = "registry+https://github.com/rust-lang/crates.io-index" 390 1631 checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" 391 1632 392 1633 [[package]] 1634 + name = "vcpkg" 1635 + version = "0.2.15" 1636 + source = "registry+https://github.com/rust-lang/crates.io-index" 1637 + checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 1638 + 1639 + [[package]] 1640 + name = "version_check" 1641 + version = "0.9.4" 1642 + source = "registry+https://github.com/rust-lang/crates.io-index" 1643 + checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 1644 + 1645 + [[package]] 393 1646 name = "wasi" 394 1647 version = "0.11.0+wasi-snapshot-preview1" 395 1648 source = "registry+https://github.com/rust-lang/crates.io-index" 396 1649 checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 397 1650 398 1651 [[package]] 1652 + name = "wasite" 1653 + version = "0.1.0" 1654 + source = "registry+https://github.com/rust-lang/crates.io-index" 1655 + checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" 1656 + 1657 + [[package]] 1658 + name = "whoami" 1659 + version = "1.5.1" 1660 + source = "registry+https://github.com/rust-lang/crates.io-index" 1661 + checksum = "a44ab49fad634e88f55bf8f9bb3abd2f27d7204172a112c7c9987e01c1c94ea9" 1662 + dependencies = [ 1663 + "redox_syscall 0.4.1", 1664 + "wasite", 1665 + ] 1666 + 1667 + [[package]] 399 1668 name = "windows-sys" 400 1669 version = "0.48.0" 401 1670 source = "registry+https://github.com/rust-lang/crates.io-index" 402 1671 checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 403 1672 dependencies = [ 404 - "windows-targets", 1673 + "windows-targets 0.48.0", 1674 + ] 1675 + 1676 + [[package]] 1677 + name = "windows-sys" 1678 + version = "0.52.0" 1679 + source = "registry+https://github.com/rust-lang/crates.io-index" 1680 + checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 1681 + dependencies = [ 1682 + "windows-targets 0.52.5", 405 1683 ] 406 1684 407 1685 [[package]] ··· 410 1688 source = "registry+https://github.com/rust-lang/crates.io-index" 411 1689 checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" 412 1690 dependencies = [ 413 - "windows_aarch64_gnullvm", 414 - "windows_aarch64_msvc", 415 - "windows_i686_gnu", 416 - "windows_i686_msvc", 417 - "windows_x86_64_gnu", 418 - "windows_x86_64_gnullvm", 419 - "windows_x86_64_msvc", 1691 + "windows_aarch64_gnullvm 0.48.0", 1692 + "windows_aarch64_msvc 0.48.0", 1693 + "windows_i686_gnu 0.48.0", 1694 + "windows_i686_msvc 0.48.0", 1695 + "windows_x86_64_gnu 0.48.0", 1696 + "windows_x86_64_gnullvm 0.48.0", 1697 + "windows_x86_64_msvc 0.48.0", 1698 + ] 1699 + 1700 + [[package]] 1701 + name = "windows-targets" 1702 + version = "0.52.5" 1703 + source = "registry+https://github.com/rust-lang/crates.io-index" 1704 + checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" 1705 + dependencies = [ 1706 + "windows_aarch64_gnullvm 0.52.5", 1707 + "windows_aarch64_msvc 0.52.5", 1708 + "windows_i686_gnu 0.52.5", 1709 + "windows_i686_gnullvm", 1710 + "windows_i686_msvc 0.52.5", 1711 + "windows_x86_64_gnu 0.52.5", 1712 + "windows_x86_64_gnullvm 0.52.5", 1713 + "windows_x86_64_msvc 0.52.5", 420 1714 ] 421 1715 422 1716 [[package]] ··· 426 1720 checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" 427 1721 428 1722 [[package]] 1723 + name = "windows_aarch64_gnullvm" 1724 + version = "0.52.5" 1725 + source = "registry+https://github.com/rust-lang/crates.io-index" 1726 + checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" 1727 + 1728 + [[package]] 429 1729 name = "windows_aarch64_msvc" 430 1730 version = "0.48.0" 431 1731 source = "registry+https://github.com/rust-lang/crates.io-index" 432 1732 checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" 433 1733 434 1734 [[package]] 1735 + name = "windows_aarch64_msvc" 1736 + version = "0.52.5" 1737 + source = "registry+https://github.com/rust-lang/crates.io-index" 1738 + checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" 1739 + 1740 + [[package]] 435 1741 name = "windows_i686_gnu" 436 1742 version = "0.48.0" 437 1743 source = "registry+https://github.com/rust-lang/crates.io-index" 438 1744 checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" 439 1745 440 1746 [[package]] 1747 + name = "windows_i686_gnu" 1748 + version = "0.52.5" 1749 + source = "registry+https://github.com/rust-lang/crates.io-index" 1750 + checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" 1751 + 1752 + [[package]] 1753 + name = "windows_i686_gnullvm" 1754 + version = "0.52.5" 1755 + source = "registry+https://github.com/rust-lang/crates.io-index" 1756 + checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" 1757 + 1758 + [[package]] 441 1759 name = "windows_i686_msvc" 442 1760 version = "0.48.0" 443 1761 source = "registry+https://github.com/rust-lang/crates.io-index" 444 1762 checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" 445 1763 446 1764 [[package]] 1765 + name = "windows_i686_msvc" 1766 + version = "0.52.5" 1767 + source = "registry+https://github.com/rust-lang/crates.io-index" 1768 + checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" 1769 + 1770 + [[package]] 447 1771 name = "windows_x86_64_gnu" 448 1772 version = "0.48.0" 449 1773 source = "registry+https://github.com/rust-lang/crates.io-index" 450 1774 checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" 451 1775 452 1776 [[package]] 1777 + name = "windows_x86_64_gnu" 1778 + version = "0.52.5" 1779 + source = "registry+https://github.com/rust-lang/crates.io-index" 1780 + checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" 1781 + 1782 + [[package]] 453 1783 name = "windows_x86_64_gnullvm" 454 1784 version = "0.48.0" 455 1785 source = "registry+https://github.com/rust-lang/crates.io-index" 456 1786 checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" 457 1787 458 1788 [[package]] 1789 + name = "windows_x86_64_gnullvm" 1790 + version = "0.52.5" 1791 + source = "registry+https://github.com/rust-lang/crates.io-index" 1792 + checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" 1793 + 1794 + [[package]] 459 1795 name = "windows_x86_64_msvc" 460 1796 version = "0.48.0" 461 1797 source = "registry+https://github.com/rust-lang/crates.io-index" 462 1798 checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" 1799 + 1800 + [[package]] 1801 + name = "windows_x86_64_msvc" 1802 + version = "0.52.5" 1803 + source = "registry+https://github.com/rust-lang/crates.io-index" 1804 + checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" 1805 + 1806 + [[package]] 1807 + name = "zerocopy" 1808 + version = "0.7.34" 1809 + source = "registry+https://github.com/rust-lang/crates.io-index" 1810 + checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" 1811 + dependencies = [ 1812 + "zerocopy-derive", 1813 + ] 1814 + 1815 + [[package]] 1816 + name = "zerocopy-derive" 1817 + version = "0.7.34" 1818 + source = "registry+https://github.com/rust-lang/crates.io-index" 1819 + checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" 1820 + dependencies = [ 1821 + "proc-macro2", 1822 + "quote", 1823 + "syn 2.0.66", 1824 + ] 1825 + 1826 + [[package]] 1827 + name = "zeroize" 1828 + version = "1.8.1" 1829 + source = "registry+https://github.com/rust-lang/crates.io-index" 1830 + checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
+6 -2
Cargo.toml
··· 1 1 [package] 2 2 name = "safir" 3 - version = "0.9.0" 3 + version = "0.10.0" 4 4 edition = "2021" 5 - authors = ["Graham Keenan graham.keenan@outlook.com"] 5 + authors = ["Graham Keenan <graham.keenan@outlook.com>"] 6 6 license = "MIT OR Apache-2.0" 7 7 description = "Key/Value store to share values between different shell sessions" 8 8 readme = "README.md" ··· 16 16 anyhow = "1.0.75" 17 17 dirs = "5.0.1" 18 18 serde_json = "1.0.108" 19 + serde = { version = "1.0.203", features = ["derive"] } 20 + tokio = { version = "1.38.0", features = ["full"] } 21 + sqlx = { version = "0.7.4", features = ["runtime-tokio", "sqlite"] } 22 + async-trait = "0.1.80" 19 23 20 24 # The profile that 'cargo dist' will build with 21 25 [profile.dist]
+34
README.md
··· 33 33 rm Remove values from the store 34 34 alias Output the alias command for key / value pairs 35 35 export Output the export command for a key / value pairs 36 + mode Sets the mode for Safir (active on the next run of Safir) 36 37 list List all values in the store 37 38 clear Clear all keys/values from the store 38 39 purge Purges the .safirstore directory, removing it and its contents 40 + use Use / create an environment to store key / value pairs 39 41 help Print this message or the help of the given subcommand(s) 40 42 41 43 Options: 42 44 -h, --help Print help 43 45 -V, --version Print version 44 46 ``` 47 + 48 + ## File Mode vs Database Mode 49 + 50 + File mode is just like the old version of `safir` - all KV pairs are stored in a JSON value like before. 51 + 52 + Database mode uses an SQLite database as storage instead which is _technically_ more secure. 53 + 54 + Switching between modes does not carry over any changes from the previous mode (i.e. KV pairs added in File mode are not present in Database mode unless you add them yourself). 55 + 56 + This could change in a future release 57 + 58 + ## Environments 59 + 60 + Safir now supports storing KV pairs in specific environments which will declutter the `list` command and also keep all related KV pairs in one single place. 61 + 62 + When Safir is loaded initially, it creates a new `default` environment (or loads an existing one) and uses that unlesss you switch environment. 63 + 64 + Stores from older versions of Safir will automatically be ported over to this new format so there is no worry of lost data! 45 65 46 66 ## Examples 47 67 ··· 103 123 ```bash 104 124 safir purge # Will remove the .safirstore directory 105 125 ``` 126 + 127 + Setting an environment: 128 + 129 + ```bash 130 + safir use [environment-name] # This will create an empty environment or load an existing one 131 + ``` 132 + 133 + Switching between `file` and `database` mode: 134 + 135 + ```bash 136 + safir mode file # Switch to using a JSON file for storage 137 + 138 + safir mode database # Switch to using an SQLite database for storage 139 + ```
+8
migrations/20240620173629_create_db.sql
··· 1 + -- Add migration script here 2 + create table if not exists safir ( 3 + key text not null primary key, 4 + value text not null, 5 + environment text not null 6 + ); 7 + 8 + create index if not exists idx_key on safir(key);
+39 -42
src/cli.rs
··· 1 1 //! CLI for using the Safir binary 2 - pub use clap::{Args, Parser, Subcommand}; 2 + use crate::store::config::SafirMode; 3 + pub use clap::{Parser, Subcommand}; 3 4 4 5 /// CLI arguments for running the program 5 6 #[derive(Parser, Debug)] ··· 16 17 #[derive(Subcommand, Debug)] 17 18 pub enum Commands { 18 19 /// Add a value to the store with the given key 19 - Add(AddArgs), 20 + Add { 21 + /// Key for the value 22 + key: String, 23 + 24 + /// Value to add 25 + value: String, 26 + }, 20 27 21 28 /// Get values from the store 22 - Get(GetArgs), 29 + Get { 30 + /// Keys for values to retrieve from the store 31 + keys: Vec<String>, 32 + }, 23 33 24 34 /// Remove values from the store 25 - Rm(RemoveArgs), 35 + Rm { 36 + /// Keys for values to remove from the store 37 + keys: Vec<String>, 38 + }, 39 + 40 + /// Output the alias command for key / value pairs 41 + Alias { 42 + /// Keys to alias the values 43 + keys: Vec<String>, 44 + }, 26 45 27 - /// Output the alias command for key / value pairs 28 - Alias(SetArgs), 46 + /// Output the export command for a key / value pairs 47 + Export { 48 + /// Keys to export the values 49 + keys: Vec<String>, 50 + }, 29 51 30 - /// Output the export command for a key / value pairs 31 - Export(SetArgs), 52 + /// Sets the mode for Safir (active on the next run of Safir) 53 + Mode { 54 + /// Mode to set (KV-file store or SQLite DB store) 55 + mode: SafirMode, 56 + }, 32 57 33 58 /// List all values in the store 34 59 List, ··· 38 63 39 64 /// Purges the .safirstore directory, removing it and its contents 40 65 Purge, 41 - } 42 - 43 - /// Arguments for adding a value to the store with a given key 44 - #[derive(Args, Debug)] 45 - pub struct AddArgs { 46 - /// Name of the item to store 47 - pub key: String, 48 - 49 - /// Value to store 50 - pub value: String, 51 - } 52 - 53 - /// Arguments for retrieving values from the store with the given keys 54 - #[derive(Args, Debug)] 55 - pub struct GetArgs { 56 - /// Keys to retrieve the values for 57 - /// 58 - /// Returns nothing if the key does not exist 59 - pub keys: Vec<String>, 60 - } 61 66 62 - /// Arguments for removing values from the store with given keys 63 - #[derive(Args, Debug)] 64 - pub struct RemoveArgs { 65 - /// Name of the keys to remove from the store 66 - /// 67 - /// Does nothing if the keys do not exist 68 - pub keys: Vec<String>, 69 - } 70 - 71 - /// Arguments for outputting commands with a given prefix 72 - #[derive(Args, Debug)] 73 - pub struct SetArgs { 74 - /// Name of the keys to display (e.g. alias / export) 75 - pub keys: Vec<String>, 67 + /// Use / create an environment to store key / value pairs 68 + Use { 69 + /// Name of the environment to use / create 70 + #[arg(default_value_t = String::from("default"))] 71 + environment: String, 72 + }, 76 73 }
+34 -25
src/main.rs
··· 1 1 mod cli; 2 - mod utils; 3 2 mod store; 3 + mod utils; 4 4 5 5 use cli::*; 6 - use store::Store; 7 6 8 - use anyhow::Result; 9 - 7 + use anyhow::{Context, Result}; 10 8 11 - fn main() -> Result<()> { 9 + #[tokio::main] 10 + async fn main() -> Result<()> { 12 11 let cli = Cli::parse(); 13 - let mut safir = Store::init_safir(); 12 + let mut safir = store::init_safir().await.context("loading safir store")?; 14 13 15 - match &cli.command { 16 - Commands::Add(args) => { 17 - safir.add(args.key.to_owned(), args.value.to_owned()); 14 + match cli.command { 15 + Commands::Add { key, value } => safir.add(key.to_owned(), value.to_owned()).await?, 16 + Commands::Get { keys } => { 17 + let kvs = safir.get(keys.to_owned()).await?; 18 + utils::display_multiple_kv(kvs); 18 19 } 19 - Commands::Get(args) => { 20 - safir.get(args.keys.to_owned()); 20 + Commands::Rm { keys } => safir.remove(keys.to_owned()).await?, 21 + Commands::Alias { keys } => { 22 + let kvs = safir.get(keys.to_owned()).await?; 23 + utils::custom_display("alias", kvs); 21 24 } 22 - Commands::Rm(args) => { 23 - safir.remove(args.keys.to_owned()); 24 - } 25 - Commands::Alias(args) => { 26 - safir.custom_display("alias", args.keys.to_owned()); 27 - } 28 - Commands::Export(args) => { 29 - safir.custom_display("export", args.keys.to_owned()); 25 + Commands::Export { keys } => { 26 + let kvs = safir.get(keys.to_owned()).await?; 27 + utils::custom_display("export", kvs); 30 28 } 31 29 Commands::List => { 32 - safir.list(); 30 + let kvs = safir.list().await?; 31 + utils::display_multiple_kv(kvs); 33 32 } 34 - Commands::Clear => { 35 - safir.clear(); 33 + Commands::Clear => safir.clear().await?, 34 + Commands::Purge => safir.purge().await?, 35 + Commands::Mode { mode } => { 36 + let mut cfg = safir.get_config(); 37 + cfg.mode = mode; 38 + cfg.write().context("writing config out")?; 39 + println!( 40 + "Set store mode to: '{:?}'\nActive on the next run of Safir!", 41 + cfg.mode 42 + ); 36 43 } 37 - Commands::Purge => { 38 - safir.purge(); 44 + Commands::Use { environment } => { 45 + let mut cfg = safir.get_config(); 46 + cfg.environment = environment.clone(); 47 + cfg.write().context("writing config out")?; 48 + println!("Using environment '{}'", environment); 39 49 } 40 50 } 41 51 42 - utils::write_store(&safir.store, &safir.file); 43 52 Ok(()) 44 53 }
-98
src/store.rs
··· 1 - use crate::utils; 2 - use std::{fs, path::PathBuf, collections::HashMap}; 3 - 4 - pub struct Store { 5 - pub path: PathBuf, 6 - pub file: PathBuf, 7 - pub store: HashMap<String, String> 8 - } 9 - 10 - impl Store { 11 - pub fn init_safir() -> Self { 12 - match dirs::home_dir() { 13 - Some(home) => { 14 - let working_dir = home.join(".safirstore"); 15 - fs::create_dir_all(&working_dir) 16 - .expect("unable to create main directory"); 17 - 18 - let store_path = working_dir.join("safirstore.json"); 19 - let store = if store_path.exists() { 20 - utils::load_store(&store_path) 21 - } else { 22 - let store = HashMap::new(); 23 - utils::write_store(&store, &store_path); 24 - store 25 - }; 26 - 27 - return Self { 28 - path: working_dir, 29 - file: store_path, 30 - store, 31 - }; 32 - } 33 - None => { 34 - eprintln!("unable to obtain home directory path!"); 35 - std::process::exit(-1); 36 - } 37 - } 38 - } 39 - 40 - pub fn add(&mut self, key: String, value: String) { 41 - if let Some(v) = self.store.get(&key) { 42 - let confirm_msg = format!("Key {key} already exists ({v}), Replace?"); 43 - if utils::confirm_entry(&confirm_msg) { 44 - self.store.insert(key, value); 45 - } 46 - } else { 47 - self.store.insert(key, value); 48 - } 49 - } 50 - 51 - pub fn get(&self, keys: Vec<String>) { 52 - for key in keys.iter() { 53 - if let Some(value) = self.store.get(key) { 54 - utils::display_kv(key, value); 55 - } 56 - } 57 - } 58 - 59 - pub fn list(&self) { 60 - for (key, value) in self.store.iter() { 61 - utils::display_kv(key, value); 62 - } 63 - } 64 - 65 - pub fn remove(&mut self, keys: Vec<String>) { 66 - for key in keys.iter() { 67 - if let Some(v) = self.store.get(key) { 68 - let confirm_msg = format!("Remove {key} ({v}) from the store?"); 69 - if utils::confirm_entry(&confirm_msg) { 70 - self.store.remove(key); 71 - } 72 - } 73 - } 74 - } 75 - 76 - pub fn custom_display(&self, display_cmd: &str, keys: Vec<String>) { 77 - for key in keys.iter() { 78 - if let Some(value) = self.store.get(key) { 79 - println!("{display_cmd} {key}=\"{value}\""); 80 - } 81 - } 82 - } 83 - 84 - pub fn clear(&mut self) { 85 - let confirm_msg = "Are you sure you want to clear the cache of all contents?"; 86 - if utils::confirm_entry(&confirm_msg) { 87 - self.store.clear(); 88 - } 89 - } 90 - 91 - pub fn purge(&mut self) { 92 - let confirm_msg = "Are you sure you want to remove the .safirstore directory and ALL contents?"; 93 - if utils::confirm_entry(&confirm_msg) { 94 - utils::purge_directory(self.path.clone()); 95 - std::process::exit(0); 96 - } 97 - } 98 - }
+59
src/store/config.rs
··· 1 + use anyhow::{Context, Result}; 2 + use clap::ValueEnum; 3 + use serde::{Deserialize, Serialize}; 4 + 5 + use std::path::{Path, PathBuf}; 6 + 7 + #[derive(ValueEnum, Default, Debug, Copy, PartialEq, Eq, Clone, Serialize, Deserialize)] 8 + #[serde(rename_all = "lowercase")] 9 + pub enum SafirMode { 10 + #[default] 11 + File, 12 + Database, 13 + } 14 + 15 + #[derive(Default, Debug, Clone, Serialize, Deserialize)] 16 + pub struct SafirConfig { 17 + #[serde(skip)] 18 + pub filepath: PathBuf, 19 + 20 + pub environment: String, 21 + 22 + pub mode: SafirMode, 23 + } 24 + 25 + impl SafirConfig { 26 + pub fn load(workdir: impl AsRef<Path>) -> Result<Self> { 27 + let fp = workdir.as_ref().join("safirstore.cfg"); 28 + if !fp.exists() { 29 + let cfg = Self { 30 + filepath: fp, 31 + environment: "default".to_string(), 32 + mode: SafirMode::File, 33 + }; 34 + cfg.write().context("writing config out")?; 35 + 36 + return Ok(cfg); 37 + } 38 + let contents = std::fs::read_to_string(&fp).context("loading safir config")?; 39 + let mut cfg: SafirConfig = 40 + serde_json::from_str(&contents).context("deserializing safir config")?; 41 + 42 + cfg.filepath = fp; 43 + 44 + Ok(cfg) 45 + } 46 + 47 + pub fn write(&self) -> Result<()> { 48 + use std::io::Write; 49 + 50 + let contents = serde_json::to_string_pretty(&self).context("serializing config")?; 51 + let mut fd = 52 + std::fs::File::create(&self.filepath).context("creating config file descriptor")?; 53 + 54 + fd.write_all(contents.as_bytes()) 55 + .context("writing config contents")?; 56 + 57 + Ok(()) 58 + } 59 + }
+139
src/store/db_store.rs
··· 1 + use anyhow::{Context, Result}; 2 + use async_trait::async_trait; 3 + use sqlx::sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePool, SqlitePoolOptions}; 4 + 5 + use std::path::PathBuf; 6 + use std::str::FromStr; 7 + 8 + use crate::{ 9 + store::{config::SafirConfig, SafirStore}, 10 + utils::{confirm_entry, load_safir_workspace, purge_directory, KVPair}, 11 + }; 12 + 13 + #[derive(Debug, Clone)] 14 + pub struct SqliteStore { 15 + pool: SqlitePool, 16 + config: SafirConfig, 17 + } 18 + 19 + impl SqliteStore { 20 + pub(crate) async fn load(ws: PathBuf, config: SafirConfig) -> Result<Self> { 21 + let lead = PathBuf::from("sqlite:/"); 22 + let db_name = lead.join(ws).join("safirstore.db"); 23 + 24 + let connect_opts = SqliteConnectOptions::from_str(db_name.to_str().unwrap())? 25 + .optimize_on_close(true, None) 26 + .journal_mode(SqliteJournalMode::Wal) 27 + .create_if_missing(true); 28 + 29 + let pool = SqlitePoolOptions::new() 30 + .acquire_timeout(std::time::Duration::from_secs_f64(0.1)) 31 + .connect_with(connect_opts) 32 + .await 33 + .context("creating database")?; 34 + 35 + Self::setup_db(&pool).await?; 36 + Ok(Self { pool, config }) 37 + } 38 + 39 + async fn setup_db(pool: &SqlitePool) -> Result<()> { 40 + sqlx::migrate!("./migrations") 41 + .run(pool) 42 + .await 43 + .context("running database migrations")?; 44 + 45 + Ok(()) 46 + } 47 + } 48 + 49 + #[async_trait] 50 + impl SafirStore for SqliteStore { 51 + async fn add(&mut self, key: String, value: String) -> Result<()> { 52 + sqlx::query("insert into safir(key, value, environment) values(?1, ?2, ?3)") 53 + .bind(&key) 54 + .bind(&value) 55 + .bind(&self.config.environment) 56 + .execute(&self.pool) 57 + .await 58 + .with_context(|| format!("insert {key} - {value} into database"))?; 59 + 60 + Ok(()) 61 + } 62 + 63 + async fn get(&self, keys: Vec<String>) -> Result<Vec<KVPair>> { 64 + let keys = keys 65 + .into_iter() 66 + .map(|k| format!("'{k}'")) 67 + .collect::<Vec<String>>(); 68 + 69 + let query = format!( 70 + "select * from safir where environment = '{}' and key in ({})", 71 + &self.config.environment, 72 + keys.join(", ") 73 + ); 74 + let results: Vec<KVPair> = sqlx::query_as::<_, KVPair>(&query) 75 + .fetch_all(&self.pool) 76 + .await?; 77 + 78 + Ok(results) 79 + } 80 + 81 + async fn list(&self) -> Result<Vec<KVPair>> { 82 + let query = format!( 83 + "select * from safir where environment = '{}'", 84 + self.config.environment 85 + ); 86 + let results: Vec<KVPair> = sqlx::query_as::<_, KVPair>(&query) 87 + .fetch_all(&self.pool) 88 + .await?; 89 + 90 + Ok(results) 91 + } 92 + 93 + async fn remove(&mut self, keys: Vec<String>) -> Result<()> { 94 + let keys = keys 95 + .into_iter() 96 + .map(|k| format!("'{k}'")) 97 + .collect::<Vec<String>>(); 98 + 99 + let query = format!( 100 + "delete from safir where environment = '{}' and key in ({})", 101 + self.config.environment, 102 + keys.join(", ") 103 + ); 104 + let _ = sqlx::query_as::<_, KVPair>(&query) 105 + .fetch_all(&self.pool) 106 + .await?; 107 + 108 + Ok(()) 109 + } 110 + 111 + async fn clear(&mut self) -> Result<()> { 112 + if confirm_entry("Are you sure you want to clear the safirstore?") { 113 + let query = format!( 114 + "delete from safir where environment = '{}'", 115 + self.config.environment 116 + ); 117 + let _ = sqlx::query_as::<_, KVPair>(&query) 118 + .fetch_all(&self.pool) 119 + .await?; 120 + } 121 + 122 + Ok(()) 123 + } 124 + 125 + async fn purge(&mut self) -> Result<()> { 126 + let ws = load_safir_workspace(); 127 + let confirm_msg = 128 + "Are you sure you want to purge the safirstore?\nThis will delete the folder and any data inside!"; 129 + 130 + if confirm_entry(&confirm_msg) { 131 + purge_directory(ws); 132 + } 133 + Ok(()) 134 + } 135 + 136 + fn get_config(&self) -> SafirConfig { 137 + self.config.clone() 138 + } 139 + }
+193
src/store/file_store.rs
··· 1 + use crate::{ 2 + store::{config::SafirConfig, SafirStore}, 3 + utils::{self, KVPair}, 4 + }; 5 + 6 + use anyhow::Result; 7 + use async_trait::async_trait; 8 + use serde_json::Value; 9 + 10 + use std::{ 11 + collections::HashMap, 12 + path::{Path, PathBuf}, 13 + }; 14 + 15 + #[derive(Debug, Clone)] 16 + pub struct KVStore { 17 + loc: PathBuf, 18 + environment: String, 19 + store: HashMap<String, HashMap<String, String>>, 20 + config: SafirConfig, 21 + } 22 + 23 + impl KVStore { 24 + pub fn load(ws: PathBuf, config: SafirConfig) -> Self { 25 + let store_path = ws.join("safirstore.json"); 26 + let safir = if store_path.exists() { 27 + let store = Self::load_store(&store_path, &config); 28 + Self { 29 + loc: store_path, 30 + environment: config.environment.clone(), 31 + config, 32 + store, 33 + } 34 + } else { 35 + let mut store = HashMap::new(); 36 + store.insert(config.environment.clone(), HashMap::new()); 37 + 38 + Self { 39 + loc: store_path, 40 + store, 41 + environment: config.environment.clone(), 42 + config, 43 + } 44 + }; 45 + 46 + safir.write_store(); 47 + safir 48 + } 49 + 50 + /// Loads the store from disk 51 + /// This is stupid having to reload the map but it will allow users that had 52 + /// the old format to port over to the new format seamlessly 53 + pub fn load_store( 54 + path: impl AsRef<Path>, 55 + config: &SafirConfig, 56 + ) -> HashMap<String, HashMap<String, String>> { 57 + let contents = std::fs::read_to_string(path.as_ref()).expect("unable to store contents"); 58 + 59 + let store: HashMap<String, Value> = 60 + serde_json::from_str(&contents).expect("unable to deserialize contents"); 61 + 62 + // If they're all objects then this is the new format, load appropriately 63 + if store.values().all(|v| v.is_object()) { 64 + return serde_json::from_str::<HashMap<String, HashMap<String, String>>>(&contents) 65 + .unwrap(); 66 + } 67 + 68 + // Old map (no environment) - Load and create new environment 69 + let old_map = serde_json::from_str::<HashMap<String, String>>(&contents).unwrap(); 70 + let mut new_map = HashMap::new(); 71 + new_map.insert(config.environment.clone(), HashMap::new()); 72 + 73 + let env = new_map.get_mut(config.environment.as_str()).unwrap(); 74 + for (key, value) in old_map.into_iter() { 75 + env.insert(key, value); 76 + } 77 + 78 + new_map 79 + } 80 + 81 + /// Writes the store to disk 82 + pub fn write_store(&self) { 83 + use std::io::Write; 84 + let str_store = 85 + serde_json::to_string_pretty(&self.store).expect("unable to serialize store contents"); 86 + 87 + let mut file = std::fs::File::create(&self.loc).expect("unable to get file handle"); 88 + 89 + file.write_all(str_store.as_bytes()) 90 + .expect("unable to write store out to disk"); 91 + } 92 + 93 + pub fn get_environment(&mut self) -> &mut HashMap<String, String> { 94 + self.store 95 + .entry(self.environment.clone()) 96 + .or_insert(HashMap::new()); 97 + 98 + self.store.get_mut(&self.environment).unwrap() 99 + } 100 + } 101 + 102 + #[async_trait] 103 + impl SafirStore for KVStore { 104 + async fn add(&mut self, key: String, value: String) -> Result<()> { 105 + let env = self.get_environment(); 106 + if let Some(v) = env.get(&key) { 107 + let confirm_msg = format!("Key {key} already exists ({v}), Replace?"); 108 + if utils::confirm_entry(&confirm_msg) { 109 + env.insert(key, value); 110 + } 111 + } else { 112 + env.insert(key, value); 113 + } 114 + 115 + self.write_store(); 116 + 117 + Ok(()) 118 + } 119 + 120 + async fn get(&self, keys: Vec<String>) -> Result<Vec<KVPair>> { 121 + let inner = match self.store.get(&self.environment) { 122 + Some(inner) => inner, 123 + None => return Ok(vec![]), 124 + }; 125 + 126 + let kvs: Vec<KVPair> = keys 127 + .into_iter() 128 + .filter_map(|key| match inner.get(&key) { 129 + Some(value) => Some((key, value.clone())), 130 + None => None, 131 + }) 132 + .collect(); 133 + 134 + Ok(kvs) 135 + } 136 + 137 + async fn list(&self) -> Result<Vec<KVPair>> { 138 + let inner = match self.store.get(&self.environment) { 139 + Some(inner) => inner, 140 + None => return Ok(vec![]), 141 + }; 142 + 143 + let kvs: Vec<KVPair> = inner 144 + .iter() 145 + .map(|(key, value)| (key.clone(), value.clone())) 146 + .collect(); 147 + 148 + Ok(kvs) 149 + } 150 + 151 + async fn remove(&mut self, keys: Vec<String>) -> Result<()> { 152 + let inner = self.get_environment(); 153 + for key in keys.iter() { 154 + if let Some(v) = inner.get(key) { 155 + let confirm_msg = format!("Remove {key} ({v}) from the store?"); 156 + if utils::confirm_entry(&confirm_msg) { 157 + inner.remove(key); 158 + } 159 + } 160 + } 161 + 162 + self.write_store(); 163 + 164 + Ok(()) 165 + } 166 + async fn clear(&mut self) -> Result<()> { 167 + let inner = self.get_environment(); 168 + let confirm_msg = "Are you sure you want to clear the cache of all contents?"; 169 + if utils::confirm_entry(&confirm_msg) { 170 + inner.clear(); 171 + } 172 + 173 + self.write_store(); 174 + 175 + Ok(()) 176 + } 177 + 178 + async fn purge(&mut self) -> Result<()> { 179 + let confirm_msg = 180 + "Are you sure you want to remove the .safirstore directory and ALL contents?"; 181 + let ws = utils::load_safir_workspace(); 182 + if utils::confirm_entry(&confirm_msg) { 183 + utils::purge_directory(ws); 184 + std::process::exit(0); 185 + } 186 + 187 + Ok(()) 188 + } 189 + 190 + fn get_config(&self) -> SafirConfig { 191 + self.config.clone() 192 + } 193 + }
+32
src/store/mod.rs
··· 1 + pub mod config; 2 + pub mod db_store; 3 + pub mod file_store; 4 + 5 + use crate::utils::{load_safir_workspace, KVPair}; 6 + use config::{SafirConfig, SafirMode}; 7 + 8 + use anyhow::Result; 9 + use async_trait::async_trait; 10 + use db_store::SqliteStore; 11 + use file_store::KVStore; 12 + 13 + #[async_trait] 14 + pub trait SafirStore { 15 + async fn add(&mut self, key: String, value: String) -> Result<()>; 16 + async fn get(&self, keys: Vec<String>) -> Result<Vec<KVPair>>; 17 + async fn list(&self) -> Result<Vec<KVPair>>; 18 + async fn remove(&mut self, keys: Vec<String>) -> Result<()>; 19 + async fn clear(&mut self) -> Result<()>; 20 + async fn purge(&mut self) -> Result<()>; 21 + fn get_config(&self) -> SafirConfig; 22 + } 23 + 24 + pub async fn init_safir() -> Result<Box<dyn SafirStore>> { 25 + let ws = load_safir_workspace(); 26 + let cfg = SafirConfig::load(&ws).expect("can't load safir config"); 27 + 28 + match cfg.mode { 29 + SafirMode::File => Ok(Box::new(KVStore::load(ws, cfg))), 30 + SafirMode::Database => Ok(Box::new(SqliteStore::load(ws, cfg).await?)), 31 + } 32 + }
+40 -29
src/utils.rs
··· 1 - use std::{io::Write, collections::HashMap, path::Path}; 1 + use std::{ 2 + fs, 3 + io::Write, 4 + path::{Path, PathBuf}, 5 + }; 6 + 7 + /// Type to represent a KVPair 8 + pub type KVPair = (String, String); 2 9 3 10 /// Confirmation dialog for important calls 4 11 pub fn confirm_entry(msg: &str) -> bool { ··· 11 18 .expect("unable to get input from user"); 12 19 13 20 let answer = answer.trim().to_lowercase(); 14 - if answer == "y" || answer == "yes" { 15 - return true; 16 - } 17 21 18 - false 22 + answer == "y" || answer == "yes" 19 23 } 20 24 21 - /// Outputs the Key-Value pair 22 - pub fn display_kv(key: &str, value: &str) { 23 - println!("{key}=\"{value}\"") 25 + /// Outputs multiple KV pairs 26 + pub fn display_multiple_kv(kvs: Vec<KVPair>) { 27 + for kv in kvs.into_iter() { 28 + let (key, value) = kv; 29 + println!("{key}=\"{value}\""); 30 + } 24 31 } 25 32 26 - /// Loads the store from disk 27 - pub fn load_store(path: impl AsRef<Path>) -> HashMap<String, String> { 28 - let contents = std::fs::read_to_string(path.as_ref()) 29 - .expect("unable to store contents"); 33 + /// Output key-value pairs with a leading string (e.g. alias or export) 34 + pub fn custom_display(display_cmd: &str, kvs: Vec<KVPair>) { 35 + for kv in kvs.into_iter() { 36 + let (key, value) = kv; 37 + println!("{display_cmd} {key}=\"{value}\""); 38 + } 39 + } 30 40 31 - return serde_json::from_str::<HashMap<String, String>>(&contents) 32 - .expect("unable to deserialize store contents"); 41 + /// Remove the .safirstore directory 42 + pub fn purge_directory(path: impl AsRef<Path>) { 43 + if path.as_ref().exists() { 44 + std::fs::remove_dir_all(path).expect("unable to remove safirstore directory"); 45 + } 33 46 } 34 47 35 - /// Writes the store to disk 36 - pub fn write_store(store: &HashMap<String, String>, path: impl AsRef<Path>) { 37 - let str_store = serde_json::to_string_pretty(store) 38 - .expect("unable to serialize store contents"); 39 - 40 - let mut file = std::fs::File::create(&path) 41 - .expect("unable to get file handle"); 42 - 43 - file.write_all(str_store.as_bytes()) 44 - .expect("unable to write store out to disk"); 45 - } 48 + /// Create the .safirstore directory in the user HOME 49 + pub fn load_safir_workspace() -> PathBuf { 50 + match dirs::home_dir() { 51 + Some(home) => { 52 + let working_dir = home.join(".safirstore"); 53 + fs::create_dir_all(&working_dir).expect("unable to create main directory"); 46 54 47 - /// Remove the .safirstore directory 48 - pub fn purge_directory(path: impl AsRef<Path>) { 49 - std::fs::remove_dir_all(path) 50 - .expect("unable to remove safirstore directory"); 55 + working_dir 56 + } 57 + None => { 58 + eprintln!("unable to obtain home directory path!"); 59 + std::process::exit(-1); 60 + } 61 + } 51 62 }