diff --git a/.cargo/config.toml b/.cargo/config.toml
new file mode 100644
index 0000000..6879f8b
--- /dev/null
+++ b/.cargo/config.toml
@@ -0,0 +1,3 @@
+[target.x86_64-unknown-linux-gnu]
+linker = "clang"
+rustflags = ["-C", "link-arg=-fuse-ld=/home/golds/mold-2.3.3-x86_64-linux/bin/mold"]
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 8a53831..edf2892 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,9 @@ __pycache__/
# C extensions
*.so
+# Test DB
+testy.db
+
# Distribution / packaging
.Python
.venv/
@@ -72,4 +75,13 @@ docs/_build/
.python-version
out.txt
requirements.txt
-ptest
\ No newline at end of file
+ptest
+
+# Pyscan
+.pyscan/
+.pyscan/
+.pyscan/
+.pyscan/
+.pyscan/
+.pyscan/
+.pyscan/
\ No newline at end of file
diff --git a/.sqlx/query-1143eed8e081ab8548c45cac31fb8f82e4dbd0c15f8f4c79e647e9b6195eb4a1.json b/.sqlx/query-1143eed8e081ab8548c45cac31fb8f82e4dbd0c15f8f4c79e647e9b6195eb4a1.json
new file mode 100644
index 0000000..12ccd0c
--- /dev/null
+++ b/.sqlx/query-1143eed8e081ab8548c45cac31fb8f82e4dbd0c15f8f4c79e647e9b6195eb4a1.json
@@ -0,0 +1,12 @@
+{
+ "db_name": "SQLite",
+ "query": "\n UPDATE ProjectInfo SET path = ?\n WHERE project_id = ?\n ",
+ "describe": {
+ "columns": [],
+ "parameters": {
+ "Right": 2
+ },
+ "nullable": []
+ },
+ "hash": "1143eed8e081ab8548c45cac31fb8f82e4dbd0c15f8f4c79e647e9b6195eb4a1"
+}
diff --git a/.sqlx/query-2021d6a744f4f134e1380f38f3b03295c54a5f92122c5a0c2a020f6088ca1b5b.json b/.sqlx/query-2021d6a744f4f134e1380f38f3b03295c54a5f92122c5a0c2a020f6088ca1b5b.json
new file mode 100644
index 0000000..4b43023
--- /dev/null
+++ b/.sqlx/query-2021d6a744f4f134e1380f38f3b03295c54a5f92122c5a0c2a020f6088ca1b5b.json
@@ -0,0 +1,12 @@
+{
+ "db_name": "SQLite",
+ "query": "\n CREATE TABLE IF NOT EXISTS ProjectInfo (\n id INTEGER PRIMARY_KEY AUTO_INCREMENT,\n project_id TEXT NOT NULL,\n path TEXT NOT NULL,\n added TEXT NOT NULL\n ); \n ",
+ "describe": {
+ "columns": [],
+ "parameters": {
+ "Right": 0
+ },
+ "nullable": []
+ },
+ "hash": "2021d6a744f4f134e1380f38f3b03295c54a5f92122c5a0c2a020f6088ca1b5b"
+}
diff --git a/.sqlx/query-2b189cea9b80ec6b40a3e580079efc81213d13ccdb0f60f48a9490efe44047ac.json b/.sqlx/query-2b189cea9b80ec6b40a3e580079efc81213d13ccdb0f60f48a9490efe44047ac.json
new file mode 100644
index 0000000..4b6abbe
--- /dev/null
+++ b/.sqlx/query-2b189cea9b80ec6b40a3e580079efc81213d13ccdb0f60f48a9490efe44047ac.json
@@ -0,0 +1,20 @@
+{
+ "db_name": "SQLite",
+ "query": "\n SELECT hash from DependencyChanges \n WHERE hash = ?;\n ",
+ "describe": {
+ "columns": [
+ {
+ "name": "hash",
+ "ordinal": 0,
+ "type_info": "Text"
+ }
+ ],
+ "parameters": {
+ "Right": 1
+ },
+ "nullable": [
+ false
+ ]
+ },
+ "hash": "2b189cea9b80ec6b40a3e580079efc81213d13ccdb0f60f48a9490efe44047ac"
+}
diff --git a/.sqlx/query-2b4b1116ae1a9edeae070ed2ca233d44eafdcad589034ed13ba0bdf738c0fc4f.json b/.sqlx/query-2b4b1116ae1a9edeae070ed2ca233d44eafdcad589034ed13ba0bdf738c0fc4f.json
new file mode 100644
index 0000000..c18055b
--- /dev/null
+++ b/.sqlx/query-2b4b1116ae1a9edeae070ed2ca233d44eafdcad589034ed13ba0bdf738c0fc4f.json
@@ -0,0 +1,12 @@
+{
+ "db_name": "SQLite",
+ "query": "\n INSERT INTO Vulnerability (cve, name)\n VALUES (?,?);\n ",
+ "describe": {
+ "columns": [],
+ "parameters": {
+ "Right": 2
+ },
+ "nullable": []
+ },
+ "hash": "2b4b1116ae1a9edeae070ed2ca233d44eafdcad589034ed13ba0bdf738c0fc4f"
+}
diff --git a/.sqlx/query-476ee627b3c8d37fabe9af81e56d5808fff59f2d643914ff90643ea05170cf0f.json b/.sqlx/query-476ee627b3c8d37fabe9af81e56d5808fff59f2d643914ff90643ea05170cf0f.json
new file mode 100644
index 0000000..29e71b7
--- /dev/null
+++ b/.sqlx/query-476ee627b3c8d37fabe9af81e56d5808fff59f2d643914ff90643ea05170cf0f.json
@@ -0,0 +1,12 @@
+{
+ "db_name": "SQLite",
+ "query": "\n INSERT INTO Dependency (name, version, added, updated)\n VALUES (?,?,?,?);\n ",
+ "describe": {
+ "columns": [],
+ "parameters": {
+ "Right": 4
+ },
+ "nullable": []
+ },
+ "hash": "476ee627b3c8d37fabe9af81e56d5808fff59f2d643914ff90643ea05170cf0f"
+}
diff --git a/.sqlx/query-4d8756d5416f1b10aa78ee233276e1cdf656926408208aee8cbdbaf4a03f500c.json b/.sqlx/query-4d8756d5416f1b10aa78ee233276e1cdf656926408208aee8cbdbaf4a03f500c.json
new file mode 100644
index 0000000..9beccbf
--- /dev/null
+++ b/.sqlx/query-4d8756d5416f1b10aa78ee233276e1cdf656926408208aee8cbdbaf4a03f500c.json
@@ -0,0 +1,12 @@
+{
+ "db_name": "SQLite",
+ "query": "CREATE TABLE IF NOT EXISTS pipcache (\n name TEXT NOT NULL,\n version TEXT NOT NULL)",
+ "describe": {
+ "columns": [],
+ "parameters": {
+ "Right": 0
+ },
+ "nullable": []
+ },
+ "hash": "4d8756d5416f1b10aa78ee233276e1cdf656926408208aee8cbdbaf4a03f500c"
+}
diff --git a/.sqlx/query-7771f0e39a33e95603e67c8204dd21ee7456826574118c0d6c2637281925dedb.json b/.sqlx/query-7771f0e39a33e95603e67c8204dd21ee7456826574118c0d6c2637281925dedb.json
new file mode 100644
index 0000000..5b589d0
--- /dev/null
+++ b/.sqlx/query-7771f0e39a33e95603e67c8204dd21ee7456826574118c0d6c2637281925dedb.json
@@ -0,0 +1,12 @@
+{
+ "db_name": "SQLite",
+ "query": "\n CREATE TABLE IF NOT EXISTS VulnerabilityDependency (\n vulnerability_cve TEXT NOT NULL,\n dependency_name TEXT NOT NULL,\n FOREIGN KEY (vulnerability_cve) REFERENCES Vulnerability(cve) ON DELETE CASCADE,\n FOREIGN KEY (dependency_name) REFERENCES Dependency(name) ON DELETE CASCADE,\n PRIMARY KEY (vulnerability_cve, dependency_name)\n );\n ",
+ "describe": {
+ "columns": [],
+ "parameters": {
+ "Right": 0
+ },
+ "nullable": []
+ },
+ "hash": "7771f0e39a33e95603e67c8204dd21ee7456826574118c0d6c2637281925dedb"
+}
diff --git a/.sqlx/query-7cdbc2f0e6add5ee02740df272d992f492fcf2f05af4579cfad4711736b76c95.json b/.sqlx/query-7cdbc2f0e6add5ee02740df272d992f492fcf2f05af4579cfad4711736b76c95.json
new file mode 100644
index 0000000..4cac8f2
--- /dev/null
+++ b/.sqlx/query-7cdbc2f0e6add5ee02740df272d992f492fcf2f05af4579cfad4711736b76c95.json
@@ -0,0 +1,12 @@
+{
+ "db_name": "SQLite",
+ "query": "\n INSERT INTO ProjectInfo (project_id, path, added)\n VALUES (?,?,?)\n ",
+ "describe": {
+ "columns": [],
+ "parameters": {
+ "Right": 3
+ },
+ "nullable": []
+ },
+ "hash": "7cdbc2f0e6add5ee02740df272d992f492fcf2f05af4579cfad4711736b76c95"
+}
diff --git a/.sqlx/query-8b33c9cf8336f4b6e8bc642846f261a42f0b7a5264a534ff8b1c5c85fa236482.json b/.sqlx/query-8b33c9cf8336f4b6e8bc642846f261a42f0b7a5264a534ff8b1c5c85fa236482.json
new file mode 100644
index 0000000..e5c5534
--- /dev/null
+++ b/.sqlx/query-8b33c9cf8336f4b6e8bc642846f261a42f0b7a5264a534ff8b1c5c85fa236482.json
@@ -0,0 +1,26 @@
+{
+ "db_name": "SQLite",
+ "query": "\n SELECT key,value FROM Settings;\n ",
+ "describe": {
+ "columns": [
+ {
+ "name": "key",
+ "ordinal": 0,
+ "type_info": "Text"
+ },
+ {
+ "name": "value",
+ "ordinal": 1,
+ "type_info": "Text"
+ }
+ ],
+ "parameters": {
+ "Right": 0
+ },
+ "nullable": [
+ false,
+ false
+ ]
+ },
+ "hash": "8b33c9cf8336f4b6e8bc642846f261a42f0b7a5264a534ff8b1c5c85fa236482"
+}
diff --git a/.sqlx/query-999850da2250924c4d747405c0f97ebf294102c39f6bbd6b6166fb0c6a52a5a0.json b/.sqlx/query-999850da2250924c4d747405c0f97ebf294102c39f6bbd6b6166fb0c6a52a5a0.json
new file mode 100644
index 0000000..7310f77
--- /dev/null
+++ b/.sqlx/query-999850da2250924c4d747405c0f97ebf294102c39f6bbd6b6166fb0c6a52a5a0.json
@@ -0,0 +1,32 @@
+{
+ "db_name": "SQLite",
+ "query": "\n SELECT project_id as identifier, path, added FROM ProjectInfo;\n ",
+ "describe": {
+ "columns": [
+ {
+ "name": "identifier",
+ "ordinal": 0,
+ "type_info": "Text"
+ },
+ {
+ "name": "path",
+ "ordinal": 1,
+ "type_info": "Text"
+ },
+ {
+ "name": "added",
+ "ordinal": 2,
+ "type_info": "Text"
+ }
+ ],
+ "parameters": {
+ "Right": 0
+ },
+ "nullable": [
+ false,
+ false,
+ false
+ ]
+ },
+ "hash": "999850da2250924c4d747405c0f97ebf294102c39f6bbd6b6166fb0c6a52a5a0"
+}
diff --git a/.sqlx/query-a88738dacb155b6e1bd2e5089a90292901401f843c266892618bb261080b887a.json b/.sqlx/query-a88738dacb155b6e1bd2e5089a90292901401f843c266892618bb261080b887a.json
new file mode 100644
index 0000000..24a74ff
--- /dev/null
+++ b/.sqlx/query-a88738dacb155b6e1bd2e5089a90292901401f843c266892618bb261080b887a.json
@@ -0,0 +1,12 @@
+{
+ "db_name": "SQLite",
+ "query": "\n CREATE TABLE IF NOT EXISTS DependencyChanges (\n hash TEXT NOT NULL,\n name TEXT NOT NULL,\n change CHAR(1) NOT NULL,\n timestamp INTEGER NOT NULL\n );\n ",
+ "describe": {
+ "columns": [],
+ "parameters": {
+ "Right": 0
+ },
+ "nullable": []
+ },
+ "hash": "a88738dacb155b6e1bd2e5089a90292901401f843c266892618bb261080b887a"
+}
diff --git a/.sqlx/query-a9456623d7d27b076db135743f5517b45beb0173d3181e62b912edabdf778c11.json b/.sqlx/query-a9456623d7d27b076db135743f5517b45beb0173d3181e62b912edabdf778c11.json
new file mode 100644
index 0000000..9a49943
--- /dev/null
+++ b/.sqlx/query-a9456623d7d27b076db135743f5517b45beb0173d3181e62b912edabdf778c11.json
@@ -0,0 +1,12 @@
+{
+ "db_name": "SQLite",
+ "query": "\n CREATE TABLE IF NOT EXISTS Vulnerability (\n cve TEXT PRIMARY KEY,\n name TEXT NOT NULL\n ); \n ",
+ "describe": {
+ "columns": [],
+ "parameters": {
+ "Right": 0
+ },
+ "nullable": []
+ },
+ "hash": "a9456623d7d27b076db135743f5517b45beb0173d3181e62b912edabdf778c11"
+}
diff --git a/.sqlx/query-ad897b700f9bea8d672f9353c45c20135bd9e32b67dbe15a73e2c5a430dd93b4.json b/.sqlx/query-ad897b700f9bea8d672f9353c45c20135bd9e32b67dbe15a73e2c5a430dd93b4.json
new file mode 100644
index 0000000..e9f7433
--- /dev/null
+++ b/.sqlx/query-ad897b700f9bea8d672f9353c45c20135bd9e32b67dbe15a73e2c5a430dd93b4.json
@@ -0,0 +1,12 @@
+{
+ "db_name": "SQLite",
+ "query": "\n UPDATE Dependency SET name = ?, version = ?, added = ?, updated = ?\n WHERE name = ?;\n ",
+ "describe": {
+ "columns": [],
+ "parameters": {
+ "Right": 5
+ },
+ "nullable": []
+ },
+ "hash": "ad897b700f9bea8d672f9353c45c20135bd9e32b67dbe15a73e2c5a430dd93b4"
+}
diff --git a/.sqlx/query-b27b0c2a270b3f55a59416f9d806da76349d98ed75eba7def35ecefef1b1c05d.json b/.sqlx/query-b27b0c2a270b3f55a59416f9d806da76349d98ed75eba7def35ecefef1b1c05d.json
new file mode 100644
index 0000000..12e1f5c
--- /dev/null
+++ b/.sqlx/query-b27b0c2a270b3f55a59416f9d806da76349d98ed75eba7def35ecefef1b1c05d.json
@@ -0,0 +1,12 @@
+{
+ "db_name": "SQLite",
+ "query": "UPDATE pipcache SET name = ?, version = ?",
+ "describe": {
+ "columns": [],
+ "parameters": {
+ "Right": 2
+ },
+ "nullable": []
+ },
+ "hash": "b27b0c2a270b3f55a59416f9d806da76349d98ed75eba7def35ecefef1b1c05d"
+}
diff --git a/.sqlx/query-b41442dba317483596c926d276354b33aaa3751840042f93718533277977158e.json b/.sqlx/query-b41442dba317483596c926d276354b33aaa3751840042f93718533277977158e.json
new file mode 100644
index 0000000..1028787
--- /dev/null
+++ b/.sqlx/query-b41442dba317483596c926d276354b33aaa3751840042f93718533277977158e.json
@@ -0,0 +1,12 @@
+{
+ "db_name": "SQLite",
+ "query": "\n CREATE TABLE IF NOT EXISTS Dependency (\n name TEXT PRIMARY KEY,\n version TEXT NOT NULL,\n added TEXT NOT NULL,\n updated TEXT NOT NULL\n ); \n ",
+ "describe": {
+ "columns": [],
+ "parameters": {
+ "Right": 0
+ },
+ "nullable": []
+ },
+ "hash": "b41442dba317483596c926d276354b33aaa3751840042f93718533277977158e"
+}
diff --git a/.sqlx/query-bc812d92b2320efb123ecaa67caf53b3f669e668a7a3c1ff5748b4cacf6d8976.json b/.sqlx/query-bc812d92b2320efb123ecaa67caf53b3f669e668a7a3c1ff5748b4cacf6d8976.json
new file mode 100644
index 0000000..2502344
--- /dev/null
+++ b/.sqlx/query-bc812d92b2320efb123ecaa67caf53b3f669e668a7a3c1ff5748b4cacf6d8976.json
@@ -0,0 +1,12 @@
+{
+ "db_name": "SQLite",
+ "query": "INSERT INTO pipcache (name, version) VALUES (?, ?)",
+ "describe": {
+ "columns": [],
+ "parameters": {
+ "Right": 2
+ },
+ "nullable": []
+ },
+ "hash": "bc812d92b2320efb123ecaa67caf53b3f669e668a7a3c1ff5748b4cacf6d8976"
+}
diff --git a/.sqlx/query-d0e102115b330f41819727bf826f6ab9241d4926706174e52c87dde259c4b71d.json b/.sqlx/query-d0e102115b330f41819727bf826f6ab9241d4926706174e52c87dde259c4b71d.json
new file mode 100644
index 0000000..1f3b4e9
--- /dev/null
+++ b/.sqlx/query-d0e102115b330f41819727bf826f6ab9241d4926706174e52c87dde259c4b71d.json
@@ -0,0 +1,12 @@
+{
+ "db_name": "SQLite",
+ "query": "\n INSERT OR IGNORE INTO Settings (key,value) VALUES (?,?);\n UPDATE Settings SET key = ?, value = ?\n WHERE key = ?;\n ",
+ "describe": {
+ "columns": [],
+ "parameters": {
+ "Right": 5
+ },
+ "nullable": []
+ },
+ "hash": "d0e102115b330f41819727bf826f6ab9241d4926706174e52c87dde259c4b71d"
+}
diff --git a/.sqlx/query-d67357dd230e09ecaee19dc47c55b0ba46b450baa3796b488af423be6d41dfd6.json b/.sqlx/query-d67357dd230e09ecaee19dc47c55b0ba46b450baa3796b488af423be6d41dfd6.json
new file mode 100644
index 0000000..b9460d2
--- /dev/null
+++ b/.sqlx/query-d67357dd230e09ecaee19dc47c55b0ba46b450baa3796b488af423be6d41dfd6.json
@@ -0,0 +1,32 @@
+{
+ "db_name": "SQLite",
+ "query": "\n SELECT project_id as identifier, path, added FROM ProjectInfo\n WHERE project_id = ?;\n ",
+ "describe": {
+ "columns": [
+ {
+ "name": "identifier",
+ "ordinal": 0,
+ "type_info": "Text"
+ },
+ {
+ "name": "path",
+ "ordinal": 1,
+ "type_info": "Text"
+ },
+ {
+ "name": "added",
+ "ordinal": 2,
+ "type_info": "Text"
+ }
+ ],
+ "parameters": {
+ "Right": 1
+ },
+ "nullable": [
+ false,
+ false,
+ false
+ ]
+ },
+ "hash": "d67357dd230e09ecaee19dc47c55b0ba46b450baa3796b488af423be6d41dfd6"
+}
diff --git a/.sqlx/query-ee7767c6132c0b4781867d39fe62590c14883fd7536407f6c70df0677801e934.json b/.sqlx/query-ee7767c6132c0b4781867d39fe62590c14883fd7536407f6c70df0677801e934.json
new file mode 100644
index 0000000..98ef27a
--- /dev/null
+++ b/.sqlx/query-ee7767c6132c0b4781867d39fe62590c14883fd7536407f6c70df0677801e934.json
@@ -0,0 +1,12 @@
+{
+ "db_name": "SQLite",
+ "query": "\n CREATE TABLE IF NOT EXISTS Settings (\n key TEXT UNIQUE NOT NULL,\n value TEXT NOT NULL\n ); \n ",
+ "describe": {
+ "columns": [],
+ "parameters": {
+ "Right": 0
+ },
+ "nullable": []
+ },
+ "hash": "ee7767c6132c0b4781867d39fe62590c14883fd7536407f6c70df0677801e934"
+}
diff --git a/.sqlx/query-ef096d4ac618bb69b7485e8cdcc193d0b66a0414440ad3e420a2167d12685f31.json b/.sqlx/query-ef096d4ac618bb69b7485e8cdcc193d0b66a0414440ad3e420a2167d12685f31.json
new file mode 100644
index 0000000..11a203e
--- /dev/null
+++ b/.sqlx/query-ef096d4ac618bb69b7485e8cdcc193d0b66a0414440ad3e420a2167d12685f31.json
@@ -0,0 +1,12 @@
+{
+ "db_name": "SQLite",
+ "query": "DELETE FROM pipcache WHERE name = ?;",
+ "describe": {
+ "columns": [],
+ "parameters": {
+ "Right": 1
+ },
+ "nullable": []
+ },
+ "hash": "ef096d4ac618bb69b7485e8cdcc193d0b66a0414440ad3e420a2167d12685f31"
+}
diff --git a/Cargo.lock b/Cargo.lock
index bbd1e3f..0a0ad3d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,6 +2,21 @@
# It is not intended for manual editing.
version = 3
+[[package]]
+name = "addr2line"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
+dependencies = [
+ "gimli",
+]
+
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
[[package]]
name = "ahash"
version = "0.8.3"
@@ -9,19 +24,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
dependencies = [
"cfg-if",
+ "getrandom",
"once_cell",
"version_check",
]
[[package]]
name = "aho-corasick"
-version = "1.0.1"
+version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04"
+checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
dependencies = [
"memchr",
]
+[[package]]
+name = "allocator-api2"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
+
+[[package]]
+name = "android-tzdata"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
+
[[package]]
name = "android_system_properties"
version = "0.1.5"
@@ -33,30 +61,29 @@ dependencies = [
[[package]]
name = "anstream"
-version = "0.3.2"
+version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163"
+checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
- "is-terminal",
"utf8parse",
]
[[package]]
name = "anstyle"
-version = "1.0.0"
+version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d"
+checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
[[package]]
name = "anstyle-parse"
-version = "0.2.0"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee"
+checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140"
dependencies = [
"utf8parse",
]
@@ -72,25 +99,72 @@ dependencies = [
[[package]]
name = "anstyle-wincon"
-version = "1.0.1"
+version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188"
+checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628"
dependencies = [
"anstyle",
"windows-sys 0.48.0",
]
+[[package]]
+name = "anyhow"
+version = "1.0.75"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
+
+[[package]]
+name = "async-trait"
+version = "0.1.74"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.38",
+]
+
+[[package]]
+name = "atoi"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528"
+dependencies = [
+ "num-traits",
+]
+
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+[[package]]
+name = "backtrace"
+version = "0.3.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
+dependencies = [
+ "addr2line",
+ "cc",
+ "cfg-if",
+ "libc",
+ "miniz_oxide",
+ "object",
+ "rustc-demangle",
+]
+
[[package]]
name = "base64"
-version = "0.21.0"
+version = "0.21.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2"
+
+[[package]]
+name = "base64ct"
+version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
+checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
[[package]]
name = "bitflags"
@@ -98,23 +172,50 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+[[package]]
+name = "bitflags"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "block-buffer"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
+dependencies = [
+ "generic-array",
+]
+
[[package]]
name = "bumpalo"
-version = "3.12.2"
+version = "3.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
+
+[[package]]
+name = "byteorder"
+version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c6ed94e98ecff0c12dd1b04c15ec0d7d9458ca8fe806cea6f12954efe74c63b"
+checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
-version = "1.4.0"
+version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
+checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
[[package]]
name = "cc"
-version = "1.0.79"
+version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
+checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
+dependencies = [
+ "libc",
+]
[[package]]
name = "cfg-if"
@@ -124,24 +225,23 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
-version = "0.4.24"
+version = "0.4.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b"
+checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
dependencies = [
+ "android-tzdata",
"iana-time-zone",
"js-sys",
- "num-integer",
"num-traits",
- "time",
"wasm-bindgen",
- "winapi",
+ "windows-targets 0.48.5",
]
[[package]]
name = "chumsky"
-version = "1.0.0-alpha.4"
+version = "1.0.0-alpha.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc3172a80699de358070dd99f80ea8badc6cdf8ac2417cb5a96e6d81bf5fe06d"
+checksum = "379cdc19530b72a1e76d94a350676eaea1455375533eb38f18dfa712f9996902"
dependencies = [
"hashbrown 0.13.2",
"stacker",
@@ -149,45 +249,43 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.2.7"
+version = "4.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34d21f9bf1b425d2968943631ec91202fe5e837264063503708b83013f8fc938"
+checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956"
dependencies = [
"clap_builder",
"clap_derive",
- "once_cell",
]
[[package]]
name = "clap_builder"
-version = "4.2.7"
+version = "4.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "914c8c79fb560f238ef6429439a30023c862f7a28e688c58f7203f12b29970bd"
+checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45"
dependencies = [
"anstream",
"anstyle",
- "bitflags",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
-version = "4.2.0"
+version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4"
+checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873"
dependencies = [
"heck",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.38",
]
[[package]]
name = "clap_lex"
-version = "0.4.1"
+version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1"
+checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961"
[[package]]
name = "colorchoice"
@@ -197,17 +295,23 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "console"
-version = "0.15.5"
+version = "0.15.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3d79fbe8970a77e3e34151cc13d3b3e248aa0faaecb9f6091fa07ebefe5ad60"
+checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8"
dependencies = [
"encode_unicode",
"lazy_static",
"libc",
"unicode-width",
- "windows-sys 0.42.0",
+ "windows-sys 0.45.0",
]
+[[package]]
+name = "const-oid"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f"
+
[[package]]
name = "core-foundation"
version = "0.9.3"
@@ -224,6 +328,118 @@ version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
+[[package]]
+name = "cpufeatures"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "crc"
+version = "3.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe"
+dependencies = [
+ "crc-catalog",
+]
+
+[[package]]
+name = "crc-catalog"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484"
+
+[[package]]
+name = "crossbeam-queue"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
+[[package]]
+name = "der"
+version = "0.7.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c"
+dependencies = [
+ "const-oid",
+ "pem-rfc7468",
+ "zeroize",
+]
+
+[[package]]
+name = "digest"
+version = "0.10.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
+dependencies = [
+ "block-buffer",
+ "const-oid",
+ "crypto-common",
+ "subtle",
+]
+
+[[package]]
+name = "dirs"
+version = "5.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
+dependencies = [
+ "dirs-sys",
+]
+
+[[package]]
+name = "dirs-sys"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
+dependencies = [
+ "libc",
+ "option-ext",
+ "redox_users",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "dotenvy"
+version = "0.15.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
+
+[[package]]
+name = "either"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
+dependencies = [
+ "serde",
+]
+
[[package]]
name = "encode_unicode"
version = "0.3.6"
@@ -232,41 +448,67 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]]
name = "encoding_rs"
-version = "0.8.32"
+version = "0.8.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394"
+checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1"
dependencies = [
"cfg-if",
]
+[[package]]
+name = "equivalent"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+
[[package]]
name = "errno"
-version = "0.3.1"
+version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
+checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860"
dependencies = [
- "errno-dragonfly",
"libc",
"windows-sys 0.48.0",
]
[[package]]
-name = "errno-dragonfly"
-version = "0.1.2"
+name = "etcetera"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
+checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943"
dependencies = [
- "cc",
- "libc",
+ "cfg-if",
+ "home",
+ "windows-sys 0.48.0",
]
+[[package]]
+name = "event-listener"
+version = "2.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
+
[[package]]
name = "fastrand"
-version = "1.9.0"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
+
+[[package]]
+name = "finl_unicode"
+version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
+checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6"
+
+[[package]]
+name = "flume"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181"
dependencies = [
- "instant",
+ "futures-core",
+ "futures-sink",
+ "spin 0.9.8",
]
[[package]]
@@ -292,9 +534,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "form_urlencoded"
-version = "1.1.0"
+version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
+checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
dependencies = [
"percent-encoding",
]
@@ -341,6 +583,17 @@ dependencies = [
"futures-util",
]
+[[package]]
+name = "futures-intrusive"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f"
+dependencies = [
+ "futures-core",
+ "lock_api",
+ "parking_lot",
+]
+
[[package]]
name = "futures-io"
version = "0.3.28"
@@ -355,7 +608,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.38",
]
[[package]]
@@ -388,11 +641,38 @@ dependencies = [
"slab",
]
+[[package]]
+name = "generic-array"
+version = "0.14.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "gimli"
+version = "0.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
+
[[package]]
name = "h2"
-version = "0.3.19"
+version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782"
+checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833"
dependencies = [
"bytes",
"fnv",
@@ -400,7 +680,7 @@ dependencies = [
"futures-sink",
"futures-util",
"http",
- "indexmap",
+ "indexmap 1.9.3",
"slab",
"tokio",
"tokio-util",
@@ -422,26 +702,72 @@ dependencies = [
"ahash",
]
+[[package]]
+name = "hashbrown"
+version = "0.14.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12"
+dependencies = [
+ "ahash",
+ "allocator-api2",
+]
+
+[[package]]
+name = "hashlink"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7"
+dependencies = [
+ "hashbrown 0.14.1",
+]
+
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+dependencies = [
+ "unicode-segmentation",
+]
[[package]]
name = "hermit-abi"
-version = "0.2.6"
+version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
+checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
+
+[[package]]
+name = "hex"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+
+[[package]]
+name = "hkdf"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437"
dependencies = [
- "libc",
+ "hmac",
]
[[package]]
-name = "hermit-abi"
-version = "0.3.1"
+name = "hmac"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
+dependencies = [
+ "digest",
+]
+
+[[package]]
+name = "home"
+version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
+checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb"
+dependencies = [
+ "windows-sys 0.48.0",
+]
[[package]]
name = "http"
@@ -473,15 +799,15 @@ checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
[[package]]
name = "httpdate"
-version = "1.0.2"
+version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
+checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "hyper"
-version = "0.14.26"
+version = "0.14.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4"
+checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468"
dependencies = [
"bytes",
"futures-channel",
@@ -494,7 +820,7 @@ dependencies = [
"httpdate",
"itoa",
"pin-project-lite",
- "socket2",
+ "socket2 0.4.9",
"tokio",
"tower-service",
"tracing",
@@ -516,16 +842,16 @@ dependencies = [
[[package]]
name = "iana-time-zone"
-version = "0.1.56"
+version = "0.1.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c"
+checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
- "windows",
+ "windows-core",
]
[[package]]
@@ -539,9 +865,9 @@ dependencies = [
[[package]]
name = "idna"
-version = "0.3.0"
+version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
+checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
dependencies = [
"unicode-bidi",
"unicode-normalization",
@@ -558,54 +884,41 @@ dependencies = [
]
[[package]]
-name = "instant"
-version = "0.1.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "io-lifetimes"
-version = "1.0.10"
+name = "indexmap"
+version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
+checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897"
dependencies = [
- "hermit-abi 0.3.1",
- "libc",
- "windows-sys 0.48.0",
+ "equivalent",
+ "hashbrown 0.14.1",
]
[[package]]
name = "ipnet"
-version = "2.7.2"
+version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f"
+checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6"
[[package]]
-name = "is-terminal"
-version = "0.4.7"
+name = "itertools"
+version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
+checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
dependencies = [
- "hermit-abi 0.3.1",
- "io-lifetimes",
- "rustix",
- "windows-sys 0.48.0",
+ "either",
]
[[package]]
name = "itoa"
-version = "1.0.6"
+version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
+checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]]
name = "js-sys"
-version = "0.3.62"
+version = "0.3.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68c16e1bfd491478ab155fd8b4896b86f9ede344949b641e61501e07c2b8b4d5"
+checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a"
dependencies = [
"wasm-bindgen",
]
@@ -615,6 +928,9 @@ name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+dependencies = [
+ "spin 0.5.2",
+]
[[package]]
name = "lenient_semver"
@@ -659,47 +975,95 @@ dependencies = [
[[package]]
name = "libc"
-version = "0.2.144"
+version = "0.2.149"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
+checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b"
[[package]]
-name = "linux-raw-sys"
-version = "0.3.7"
+name = "libm"
+version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f"
+checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
[[package]]
-name = "log"
-version = "0.4.17"
+name = "libsqlite3-sys"
+version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
+checksum = "afc22eff61b133b115c6e8c74e818c628d6d5e7a502afea6f64dee076dd94326"
dependencies = [
- "cfg-if",
+ "cc",
+ "pkg-config",
+ "vcpkg",
]
[[package]]
-name = "memchr"
-version = "2.5.0"
+name = "linux-raw-sys"
+version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f"
[[package]]
-name = "mime"
-version = "0.3.17"
+name = "lock_api"
+version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
+checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
+
+[[package]]
+name = "md-5"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
+dependencies = [
+ "cfg-if",
+ "digest",
+]
+
+[[package]]
+name = "memchr"
+version = "2.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
+
+[[package]]
+name = "mime"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
+
+[[package]]
+name = "minimal-lexical"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
+[[package]]
+name = "miniz_oxide"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
+dependencies = [
+ "adler",
+]
[[package]]
name = "mio"
-version = "0.8.6"
+version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
+checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
dependencies = [
"libc",
- "log",
- "wasi 0.11.0+wasi-snapshot-preview1",
- "windows-sys 0.45.0",
+ "wasi",
+ "windows-sys 0.48.0",
]
[[package]]
@@ -720,6 +1084,33 @@ dependencies = [
"tempfile",
]
+[[package]]
+name = "nom"
+version = "7.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
+dependencies = [
+ "memchr",
+ "minimal-lexical",
+]
+
+[[package]]
+name = "num-bigint-dig"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151"
+dependencies = [
+ "byteorder",
+ "lazy_static",
+ "libm",
+ "num-integer",
+ "num-iter",
+ "num-traits",
+ "rand",
+ "smallvec",
+ "zeroize",
+]
+
[[package]]
name = "num-integer"
version = "0.1.45"
@@ -730,25 +1121,46 @@ dependencies = [
"num-traits",
]
+[[package]]
+name = "num-iter"
+version = "0.1.43"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
+dependencies = [
+ "autocfg",
+ "num-integer",
+ "num-traits",
+]
+
[[package]]
name = "num-traits"
-version = "0.2.15"
+version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
+checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
dependencies = [
"autocfg",
+ "libm",
]
[[package]]
name = "num_cpus"
-version = "1.15.0"
+version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
+checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
- "hermit-abi 0.2.6",
+ "hermit-abi",
"libc",
]
+[[package]]
+name = "object"
+version = "0.32.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
+dependencies = [
+ "memchr",
+]
+
[[package]]
name = "once_cell"
version = "1.18.0"
@@ -757,11 +1169,11 @@ checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "openssl"
-version = "0.10.52"
+version = "0.10.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01b8574602df80f7b85fdfc5392fa884a4e3b3f4f35402c070ab34c3d3f78d56"
+checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c"
dependencies = [
- "bitflags",
+ "bitflags 2.4.1",
"cfg-if",
"foreign-types",
"libc",
@@ -778,7 +1190,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.38",
]
[[package]]
@@ -789,9 +1201,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-sys"
-version = "0.9.87"
+version = "0.9.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e17f59264b2809d77ae94f0e1ebabc434773f370d6ca667bd223ea10e06cc7e"
+checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d"
dependencies = [
"cc",
"libc",
@@ -800,25 +1212,60 @@ dependencies = [
]
[[package]]
-name = "pep-508"
-version = "0.3.0"
+name = "option-ext"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
+
+[[package]]
+name = "parking_lot"
+version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "daec7940032badfd65fe9a11705ecbea49c77269ca81934060f33952af010da3"
+checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
- "chumsky",
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall 0.4.1",
+ "smallvec",
+ "windows-targets 0.48.5",
+]
+
+[[package]]
+name = "paste"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
+
+[[package]]
+name = "pem-rfc7468"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412"
+dependencies = [
+ "base64ct",
]
[[package]]
name = "percent-encoding"
-version = "2.2.0"
+version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
+checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
[[package]]
name = "pin-project-lite"
-version = "0.2.9"
+version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
+checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
[[package]]
name = "pin-utils"
@@ -826,17 +1273,44 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+[[package]]
+name = "pkcs1"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f"
+dependencies = [
+ "der",
+ "pkcs8",
+ "spki",
+]
+
+[[package]]
+name = "pkcs8"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
+dependencies = [
+ "der",
+ "spki",
+]
+
[[package]]
name = "pkg-config"
version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
+[[package]]
+name = "ppv-lite86"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
+
[[package]]
name = "proc-macro2"
-version = "1.0.57"
+version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4ec6d5fe0b140acb27c9a0444118cf55bfbb4e0b259739429abb4521dd67c16"
+checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
dependencies = [
"unicode-ident",
]
@@ -854,46 +1328,122 @@ dependencies = [
name = "pyscan"
version = "0.1.6"
dependencies = [
+ "anyhow",
+ "async-trait",
"chrono",
+ "chumsky",
"clap",
"console",
+ "dirs",
"futures",
"lazy_static",
"lenient_semver",
"once_cell",
- "pep-508",
"regex",
"reqwest",
"semver",
"serde",
"serde_json",
+ "sqlx",
"tokio",
"toml",
+ "xxhash-rust",
]
[[package]]
name = "quote"
-version = "1.0.27"
+version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500"
+checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
dependencies = [
"proc-macro2",
]
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
+dependencies = [
+ "bitflags 1.3.2",
+]
+
[[package]]
name = "redox_syscall"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
+dependencies = [
+ "bitflags 1.3.2",
+]
+
+[[package]]
+name = "redox_users"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
+dependencies = [
+ "getrandom",
+ "redox_syscall 0.2.16",
+ "thiserror",
]
[[package]]
name = "regex"
-version = "1.8.1"
+version = "1.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370"
+checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
dependencies = [
"aho-corasick",
"memchr",
@@ -902,15 +1452,15 @@ dependencies = [
[[package]]
name = "regex-syntax"
-version = "0.7.1"
+version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c"
+checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]]
name = "reqwest"
-version = "0.11.17"
+version = "0.11.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13293b639a097af28fc8a90f22add145a9c954e49d77da06263d58cf44d5fb91"
+checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b"
dependencies = [
"base64",
"bytes",
@@ -933,6 +1483,7 @@ dependencies = [
"serde",
"serde_json",
"serde_urlencoded",
+ "system-configuration",
"tokio",
"tokio-native-tls",
"tower-service",
@@ -943,15 +1494,42 @@ dependencies = [
"winreg",
]
+[[package]]
+name = "rsa"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ab43bb47d23c1a631b4b680199a45255dce26fa9ab2fa902581f624ff13e6a8"
+dependencies = [
+ "byteorder",
+ "const-oid",
+ "digest",
+ "num-bigint-dig",
+ "num-integer",
+ "num-iter",
+ "num-traits",
+ "pkcs1",
+ "pkcs8",
+ "rand_core",
+ "signature",
+ "spki",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
+
[[package]]
name = "rustix"
-version = "0.37.19"
+version = "0.38.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d"
+checksum = "745ecfa778e66b2b63c88a61cb36e0eea109e803b0b86bf9879fbc77c70e86ed"
dependencies = [
- "bitflags",
+ "bitflags 2.4.1",
"errno",
- "io-lifetimes",
"libc",
"linux-raw-sys",
"windows-sys 0.48.0",
@@ -959,26 +1537,32 @@ dependencies = [
[[package]]
name = "ryu"
-version = "1.0.13"
+version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
+checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
[[package]]
name = "schannel"
-version = "0.1.21"
+version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3"
+checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88"
dependencies = [
- "windows-sys 0.42.0",
+ "windows-sys 0.48.0",
]
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
[[package]]
name = "security-framework"
-version = "2.9.0"
+version = "2.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca2855b3715770894e67cbfa3df957790aa0c9edc3bf06efa1a84d77fa0839d1"
+checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de"
dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
"core-foundation",
"core-foundation-sys",
"libc",
@@ -987,9 +1571,9 @@ dependencies = [
[[package]]
name = "security-framework-sys"
-version = "2.9.0"
+version = "2.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7"
+checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a"
dependencies = [
"core-foundation-sys",
"libc",
@@ -997,35 +1581,35 @@ dependencies = [
[[package]]
name = "semver"
-version = "1.0.17"
+version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
+checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090"
[[package]]
name = "serde"
-version = "1.0.163"
+version = "1.0.189"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2"
+checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.163"
+version = "1.0.189"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e"
+checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.38",
]
[[package]]
name = "serde_json"
-version = "1.0.96"
+version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
+checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
dependencies = [
"itoa",
"ryu",
@@ -1034,9 +1618,9 @@ dependencies = [
[[package]]
name = "serde_spanned"
-version = "0.6.1"
+version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4"
+checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186"
dependencies = [
"serde",
]
@@ -1053,15 +1637,53 @@ dependencies = [
"serde",
]
+[[package]]
+name = "sha1"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
+name = "sha2"
+version = "0.10.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
+name = "signature"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500"
+dependencies = [
+ "digest",
+ "rand_core",
+]
+
[[package]]
name = "slab"
-version = "0.4.8"
+version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d"
+checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
+[[package]]
+name = "smallvec"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
+
[[package]]
name = "socket2"
version = "0.4.9"
@@ -1072,6 +1694,251 @@ dependencies = [
"winapi",
]
+[[package]]
+name = "socket2"
+version = "0.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e"
+dependencies = [
+ "libc",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "spin"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
+
+[[package]]
+name = "spin"
+version = "0.9.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
+dependencies = [
+ "lock_api",
+]
+
+[[package]]
+name = "spki"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a"
+dependencies = [
+ "base64ct",
+ "der",
+]
+
+[[package]]
+name = "sqlformat"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6b7b278788e7be4d0d29c0f39497a0eef3fba6bbc8e70d8bf7fde46edeaa9e85"
+dependencies = [
+ "itertools",
+ "nom",
+ "unicode_categories",
+]
+
+[[package]]
+name = "sqlx"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0e50c216e3624ec8e7ecd14c6a6a6370aad6ee5d8cfc3ab30b5162eeeef2ed33"
+dependencies = [
+ "sqlx-core",
+ "sqlx-macros",
+ "sqlx-mysql",
+ "sqlx-postgres",
+ "sqlx-sqlite",
+]
+
+[[package]]
+name = "sqlx-core"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d6753e460c998bbd4cd8c6f0ed9a64346fcca0723d6e75e52fdc351c5d2169d"
+dependencies = [
+ "ahash",
+ "atoi",
+ "byteorder",
+ "bytes",
+ "chrono",
+ "crc",
+ "crossbeam-queue",
+ "dotenvy",
+ "either",
+ "event-listener",
+ "futures-channel",
+ "futures-core",
+ "futures-intrusive",
+ "futures-io",
+ "futures-util",
+ "hashlink",
+ "hex",
+ "indexmap 2.0.2",
+ "log",
+ "memchr",
+ "once_cell",
+ "paste",
+ "percent-encoding",
+ "serde",
+ "serde_json",
+ "sha2",
+ "smallvec",
+ "sqlformat",
+ "thiserror",
+ "tokio",
+ "tokio-stream",
+ "tracing",
+ "url",
+]
+
+[[package]]
+name = "sqlx-macros"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a793bb3ba331ec8359c1853bd39eed32cdd7baaf22c35ccf5c92a7e8d1189ec"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "sqlx-core",
+ "sqlx-macros-core",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "sqlx-macros-core"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a4ee1e104e00dedb6aa5ffdd1343107b0a4702e862a84320ee7cc74782d96fc"
+dependencies = [
+ "dotenvy",
+ "either",
+ "heck",
+ "hex",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "serde",
+ "serde_json",
+ "sha2",
+ "sqlx-core",
+ "sqlx-mysql",
+ "sqlx-postgres",
+ "sqlx-sqlite",
+ "syn 1.0.109",
+ "tempfile",
+ "tokio",
+ "url",
+]
+
+[[package]]
+name = "sqlx-mysql"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "864b869fdf56263f4c95c45483191ea0af340f9f3e3e7b4d57a61c7c87a970db"
+dependencies = [
+ "atoi",
+ "base64",
+ "bitflags 2.4.1",
+ "byteorder",
+ "bytes",
+ "chrono",
+ "crc",
+ "digest",
+ "dotenvy",
+ "either",
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-util",
+ "generic-array",
+ "hex",
+ "hkdf",
+ "hmac",
+ "itoa",
+ "log",
+ "md-5",
+ "memchr",
+ "once_cell",
+ "percent-encoding",
+ "rand",
+ "rsa",
+ "serde",
+ "sha1",
+ "sha2",
+ "smallvec",
+ "sqlx-core",
+ "stringprep",
+ "thiserror",
+ "tracing",
+ "whoami",
+]
+
+[[package]]
+name = "sqlx-postgres"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb7ae0e6a97fb3ba33b23ac2671a5ce6e3cabe003f451abd5a56e7951d975624"
+dependencies = [
+ "atoi",
+ "base64",
+ "bitflags 2.4.1",
+ "byteorder",
+ "chrono",
+ "crc",
+ "dotenvy",
+ "etcetera",
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-util",
+ "hex",
+ "hkdf",
+ "hmac",
+ "home",
+ "itoa",
+ "log",
+ "md-5",
+ "memchr",
+ "once_cell",
+ "rand",
+ "serde",
+ "serde_json",
+ "sha1",
+ "sha2",
+ "smallvec",
+ "sqlx-core",
+ "stringprep",
+ "thiserror",
+ "tracing",
+ "whoami",
+]
+
+[[package]]
+name = "sqlx-sqlite"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d59dc83cf45d89c555a577694534fcd1b55c545a816c816ce51f20bbe56a4f3f"
+dependencies = [
+ "atoi",
+ "chrono",
+ "flume",
+ "futures-channel",
+ "futures-core",
+ "futures-executor",
+ "futures-intrusive",
+ "futures-util",
+ "libsqlite3-sys",
+ "log",
+ "percent-encoding",
+ "serde",
+ "sqlx-core",
+ "tracing",
+ "url",
+]
+
[[package]]
name = "stacker"
version = "0.1.15"
@@ -1085,45 +1952,103 @@ dependencies = [
"winapi",
]
+[[package]]
+name = "stringprep"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb41d74e231a107a1b4ee36bd1214b11285b77768d2e3824aedafa988fd36ee6"
+dependencies = [
+ "finl_unicode",
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+[[package]]
+name = "subtle"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
+
[[package]]
name = "syn"
-version = "2.0.16"
+version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
+[[package]]
+name = "syn"
+version = "2.0.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "system-configuration"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
+dependencies = [
+ "bitflags 1.3.2",
+ "core-foundation",
+ "system-configuration-sys",
+]
+
+[[package]]
+name = "system-configuration-sys"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
[[package]]
name = "tempfile"
-version = "3.5.0"
+version = "3.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998"
+checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef"
dependencies = [
"cfg-if",
"fastrand",
- "redox_syscall",
+ "redox_syscall 0.3.5",
"rustix",
- "windows-sys 0.45.0",
+ "windows-sys 0.48.0",
]
[[package]]
-name = "time"
-version = "0.1.45"
+name = "thiserror"
+version = "1.0.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
+checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4"
dependencies = [
- "libc",
- "wasi 0.10.0+wasi-snapshot-preview1",
- "winapi",
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.49"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.38",
]
[[package]]
@@ -1143,17 +2068,17 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
-version = "1.28.1"
+version = "1.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105"
+checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653"
dependencies = [
- "autocfg",
+ "backtrace",
"bytes",
"libc",
"mio",
"num_cpus",
"pin-project-lite",
- "socket2",
+ "socket2 0.5.4",
"tokio-macros",
"windows-sys 0.48.0",
]
@@ -1166,7 +2091,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.38",
]
[[package]]
@@ -1179,11 +2104,22 @@ dependencies = [
"tokio",
]
+[[package]]
+name = "tokio-stream"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+ "tokio",
+]
+
[[package]]
name = "tokio-util"
-version = "0.7.8"
+version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d"
+checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d"
dependencies = [
"bytes",
"futures-core",
@@ -1195,9 +2131,9 @@ dependencies = [
[[package]]
name = "toml"
-version = "0.7.3"
+version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b403acf6f2bb0859c93c7f0d967cb4a75a7ac552100f9322faf64dc047669b21"
+checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257"
dependencies = [
"serde",
"serde_spanned",
@@ -1207,20 +2143,20 @@ dependencies = [
[[package]]
name = "toml_datetime"
-version = "0.6.1"
+version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622"
+checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
-version = "0.19.8"
+version = "0.19.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13"
+checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
dependencies = [
- "indexmap",
+ "indexmap 2.0.2",
"serde",
"serde_spanned",
"toml_datetime",
@@ -1235,20 +2171,32 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
[[package]]
name = "tracing"
-version = "0.1.37"
+version = "0.1.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
+checksum = "ee2ef2af84856a50c1d430afce2fdded0a4ec7eda868db86409b4543df0797f9"
dependencies = [
- "cfg-if",
+ "log",
"pin-project-lite",
+ "tracing-attributes",
"tracing-core",
]
+[[package]]
+name = "tracing-attributes"
+version = "0.1.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.38",
+]
+
[[package]]
name = "tracing-core"
-version = "0.1.31"
+version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a"
+checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
dependencies = [
"once_cell",
]
@@ -1259,6 +2207,12 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
+[[package]]
+name = "typenum"
+version = "1.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
+
[[package]]
name = "unicode-bidi"
version = "0.3.13"
@@ -1267,9 +2221,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
[[package]]
name = "unicode-ident"
-version = "1.0.8"
+version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-normalization"
@@ -1280,17 +2234,29 @@ dependencies = [
"tinyvec",
]
+[[package]]
+name = "unicode-segmentation"
+version = "1.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
+
[[package]]
name = "unicode-width"
-version = "0.1.10"
+version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
+checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
+
+[[package]]
+name = "unicode_categories"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
[[package]]
name = "url"
-version = "2.3.1"
+version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
+checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5"
dependencies = [
"form_urlencoded",
"idna",
@@ -1317,20 +2283,13 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "want"
-version = "0.3.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
+checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
dependencies = [
- "log",
"try-lock",
]
-[[package]]
-name = "wasi"
-version = "0.10.0+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
-
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
@@ -1339,9 +2298,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
-version = "0.2.85"
+version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b6cb788c4e39112fbe1822277ef6fb3c55cd86b95cb3d3c4c1c9597e4ac74b4"
+checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@@ -1349,24 +2308,24 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
-version = "0.2.85"
+version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "35e522ed4105a9d626d885b35d62501b30d9666283a5c8be12c14a8bdafe7822"
+checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.38",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
-version = "0.4.35"
+version = "0.4.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "083abe15c5d88556b77bdf7aef403625be9e327ad37c62c4e4129af740168163"
+checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03"
dependencies = [
"cfg-if",
"js-sys",
@@ -1376,9 +2335,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.85"
+version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "358a79a0cb89d21db8120cbfb91392335913e4890665b1a7981d9e956903b434"
+checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -1386,33 +2345,39 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.85"
+version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4783ce29f09b9d93134d41297aded3a712b7b979e9c6f28c32cb88c973a94869"
+checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.38",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.85"
+version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a901d592cafaa4d711bc324edfaff879ac700b19c3dfd60058d2b445be2691eb"
+checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
[[package]]
name = "web-sys"
-version = "0.3.62"
+version = "0.3.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16b5f940c7edfdc6d12126d98c9ef4d1b3d470011c47c76a6581df47ad9ba721"
+checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b"
dependencies = [
"js-sys",
"wasm-bindgen",
]
+[[package]]
+name = "whoami"
+version = "1.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22fc3756b8a9133049b26c7f61ab35416c130e8c09b660f5b3958b446f52cc50"
+
[[package]]
name = "winapi"
version = "0.3.9"
@@ -1436,27 +2401,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
-name = "windows"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
-dependencies = [
- "windows-targets 0.48.0",
-]
-
-[[package]]
-name = "windows-sys"
-version = "0.42.0"
+name = "windows-core"
+version = "0.51.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
+checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64"
dependencies = [
- "windows_aarch64_gnullvm 0.42.2",
- "windows_aarch64_msvc 0.42.2",
- "windows_i686_gnu 0.42.2",
- "windows_i686_msvc 0.42.2",
- "windows_x86_64_gnu 0.42.2",
- "windows_x86_64_gnullvm 0.42.2",
- "windows_x86_64_msvc 0.42.2",
+ "windows-targets 0.48.5",
]
[[package]]
@@ -1474,7 +2424,7 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
- "windows-targets 0.48.0",
+ "windows-targets 0.48.5",
]
[[package]]
@@ -1494,17 +2444,17 @@ dependencies = [
[[package]]
name = "windows-targets"
-version = "0.48.0"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
+checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
- "windows_aarch64_gnullvm 0.48.0",
- "windows_aarch64_msvc 0.48.0",
- "windows_i686_gnu 0.48.0",
- "windows_i686_msvc 0.48.0",
- "windows_x86_64_gnu 0.48.0",
- "windows_x86_64_gnullvm 0.48.0",
- "windows_x86_64_msvc 0.48.0",
+ "windows_aarch64_gnullvm 0.48.5",
+ "windows_aarch64_msvc 0.48.5",
+ "windows_i686_gnu 0.48.5",
+ "windows_i686_msvc 0.48.5",
+ "windows_x86_64_gnu 0.48.5",
+ "windows_x86_64_gnullvm 0.48.5",
+ "windows_x86_64_msvc 0.48.5",
]
[[package]]
@@ -1515,9 +2465,9 @@ checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
[[package]]
name = "windows_aarch64_gnullvm"
-version = "0.48.0"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
+checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_msvc"
@@ -1527,9 +2477,9 @@ checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
[[package]]
name = "windows_aarch64_msvc"
-version = "0.48.0"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
+checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_i686_gnu"
@@ -1539,9 +2489,9 @@ checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]]
name = "windows_i686_gnu"
-version = "0.48.0"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
+checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_msvc"
@@ -1551,9 +2501,9 @@ checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]]
name = "windows_i686_msvc"
-version = "0.48.0"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
+checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_x86_64_gnu"
@@ -1563,9 +2513,9 @@ checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
[[package]]
name = "windows_x86_64_gnu"
-version = "0.48.0"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
+checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnullvm"
@@ -1575,9 +2525,9 @@ checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
[[package]]
name = "windows_x86_64_gnullvm"
-version = "0.48.0"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
+checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_msvc"
@@ -1587,24 +2537,37 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]]
name = "windows_x86_64_msvc"
-version = "0.48.0"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
+checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "winnow"
-version = "0.4.6"
+version = "0.5.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61de7bac303dc551fe038e2b3cef0f571087a47571ea6e79a87692ac99b99699"
+checksum = "a3b801d0e0a6726477cc207f60162da452f3a95adb368399bef20a946e06f65c"
dependencies = [
"memchr",
]
[[package]]
name = "winreg"
-version = "0.10.1"
+version = "0.50.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
+checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
dependencies = [
- "winapi",
+ "cfg-if",
+ "windows-sys 0.48.0",
]
+
+[[package]]
+name = "xxhash-rust"
+version = "0.8.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9828b178da53440fa9c766a3d2f73f7cf5d0ac1fe3980c1e5018d899fd19e07b"
+
+[[package]]
+name = "zeroize"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"
diff --git a/Cargo.toml b/Cargo.toml
index d8e2ffc..0208b36 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,12 +13,11 @@ categories = ["command-line-utilities"]
[dependencies]
-chrono = "0.4.24"
+chrono = "0.4.31"
clap = {version="4.2.1", features=["derive"]}
console = "0.15.5"
lazy_static = "1.4.0"
once_cell = "1.18.0"
-pep-508 = "0.3.0"
regex = "1.7.3"
reqwest = {version="0.11.16"}
serde = {version="1.0.160", features=["derive", "serde_derive"]}
@@ -28,3 +27,12 @@ lenient_semver = { version = "0.4.2", features = [ "version_semver"] }
semver = "1.0.17"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
futures = "0.3.28"
+sqlx = { version = "0.7", features = [ "runtime-tokio", "sqlite", "chrono" ] }
+dirs = "5.0.1"
+anyhow = "1.0.75"
+chumsky = "=1.0.0-alpha.3"
+async-trait = "0.1.74"
+
+[dependencies.xxhash-rust]
+version = "0.8.5"
+features = ["xxh3"]
\ No newline at end of file
diff --git a/README.md b/README.md
index 2490fd7..799e1ed 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
-
+
diff --git a/assets/2pyscan-repository.png b/assets/2pyscan-repository.png
new file mode 100644
index 0000000..29d859e
Binary files /dev/null and b/assets/2pyscan-repository.png differ
diff --git a/assets/pyscan-repository.png b/assets/pyscan-repository.png
deleted file mode 100644
index 28bf623..0000000
Binary files a/assets/pyscan-repository.png and /dev/null differ
diff --git a/src/display/mod.rs b/src/display/mod.rs
index d9686bc..ea9ee1a 100644
--- a/src/display/mod.rs
+++ b/src/display/mod.rs
@@ -79,7 +79,7 @@ pub fn display_queried(
.as_str(),
);
} // display the safe deps
- let _ = display_summary(&collected);
+ let _ = display_summary(collected);
}
pub fn display_summary(collected: &Vec) -> io::Result<()> {
diff --git a/src/main.rs b/src/main.rs
index e5dcb32..07e3889 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -9,19 +9,23 @@ mod parser;
mod scanner;
mod docker;
mod display;
+mod map;
+mod store;
+mod pep_508;
use std::env;
use tokio::task;
-use crate::{utils::get_version, parser::structs::{Dependency, VersionStatus}};
+use crate::{utils::get_version, parser::structs::{Dependency, VersionStatus}, store::{queries::PyscanData, paths::{populate_data_dir, pyscan_init_jobs}}};
+use store::paths::{PYSCAN_ROOT, populate_project_dir};
#[derive(Parser, Debug)]
-#[command(author="aswinnnn",version="0.1.6",about="python dependency vulnerability scanner.\n\ndo 'pyscan [subcommand] --help' for specific help.")]
+#[command(author="aswinnnn",version="0.1.6",about="python dependency vulnerability scanner.\nrun 'pyscan' to do a scan.\n\ndo 'pyscan [subcommand] --help' for specific help.")]
struct Cli {
/// path to source. (default: current directory)
#[arg(long,short,default_value=None,value_name="DIRECTORY")]
dir: Option,
- /// export the result to a desired format. [json]
+ /// export the result to a desired format. [only json for now]
#[arg(long,short, required=false, value_name="FILENAME")]
output: Option,
@@ -50,7 +54,7 @@ struct Cli {
#[arg(long, required=false,action=clap::ArgAction::SetTrue)]
pypi: bool,
- /// turns off the caching of pip packages at the starting of execution.
+ /// turns off the caching of pip packages at starting.
#[arg(long="cache-off", required=false,action=clap::ArgAction::SetTrue)]
cache_off: bool,
@@ -58,6 +62,10 @@ struct Cli {
#[derive(Subcommand, Debug, Clone)]
enum SubCommand {
+
+ /// initialize a pyscan data store and enable persistent analysis. [required for advanced features]
+ Init,
+
/// query for a single python package
Package {
/// name of the package
@@ -68,6 +76,7 @@ enum SubCommand {
#[arg(long, short, default_value=None)]
version: Option
},
+
/// scan inside a docker image
Docker {
@@ -122,6 +131,24 @@ async fn main() {
docker::list_files_in_docker_image(name, path.to_path_buf()).await
.expect("Error in scanning files from Docker image.");
exit(0)
+ },
+ Some(SubCommand::Init) => {
+ // unwrapping the static forces an initialization since its lazy.
+ // if unwrapping fails it tells the user it could not initialize.
+
+ let r = PYSCAN_ROOT.clone().unwrap_or_else( |()|{
+ let cwd = env::current_dir();
+ if let Ok(path) = cwd {
+ eprintln!("Could not initialize a .pyscan directory at {}", path.display()); exit(1)
+ }
+ else {
+ eprintln!("Pyscan encountered a problem identifying your current working directory.\n Report this at github.com/aswinnnn/pyscan/issues"); exit(1);
+ }
+ });
+ let _ = pyscan_init_jobs(&r).await.map_err(|e| {eprintln!("error: {}", e)});
+
+ println!("Initialized persistent vigilance at {}\nYou can now run 'pyscan' or 'pyscan map' to start gathering data. See 'pyscan help' for more info.", r.display()); exit(0)
+
}
None => ()
}
diff --git a/src/map/mod.rs b/src/map/mod.rs
new file mode 100644
index 0000000..91865f7
--- /dev/null
+++ b/src/map/mod.rs
@@ -0,0 +1,2 @@
+mod structs;
+mod parser;
\ No newline at end of file
diff --git a/src/map/parser.rs b/src/map/parser.rs
new file mode 100644
index 0000000..9cbd7a9
--- /dev/null
+++ b/src/map/parser.rs
@@ -0,0 +1,18 @@
+use lazy_static::lazy_static;
+use regex::Regex;
+
+lazy_static! {
+ static ref REQUIRES_REGEX: Regex = Regex::new(r"Requires: (.*)").unwrap();
+}
+
+fn extract_dependencies(pip_show_output: &str) -> Vec {
+ if let Some(captures) = REQUIRES_REGEX.captures(pip_show_output) {
+ if let Some(deps) = captures.get(1) {
+ // Split the dependencies by a comma and trim whitespace
+ let deps_str = deps.as_str();
+ return deps_str.split(',').map(|s| s.trim().to_string()).collect();
+ }
+ }
+
+ Vec::new() // Return an empty vector if "Requires:" line is not found or empty
+}
diff --git a/src/map/structs.rs b/src/map/structs.rs
new file mode 100644
index 0000000..5e54b7a
--- /dev/null
+++ b/src/map/structs.rs
@@ -0,0 +1,36 @@
+struct DependencyGraph {
+ inner: Vec
+}
+
+struct DependencyNode {
+ inner: String,
+ version: String,
+ node: Vec
+}
+
+impl DependencyGraph {
+ // ... your existing methods ...
+
+ fn display_ascii_tree(&self) {
+ self.display_ascii_tree_recursive(&self.inner, &mut " ".to_string(), self.inner.len() <= 1);
+ }
+
+ fn display_ascii_tree_recursive(&self, nodes: &Vec, pad: &mut String, is_child: bool) {
+ if nodes.is_empty() {
+ return;
+ }
+
+ let parent = "|->";
+ let mut new_pad = pad.clone();
+ if is_child {
+ new_pad.push_str(". ");
+ }
+
+ for (i, node) in nodes.iter().enumerate() {
+ let is_last = i == nodes.len() - 1;
+ let connector = if is_last { "> " } else { "^-- " };
+ println!("{}{}{} {}", new_pad, if i == 0 { parent } else { connector }, node.inner, node.version);
+ self.display_ascii_tree_recursive(&node.node, &mut new_pad, true); // Pass true for is_child
+ }
+ }
+}
diff --git a/src/parser/extractor.rs b/src/parser/extractor.rs
index 97a1e11..6393142 100644
--- a/src/parser/extractor.rs
+++ b/src/parser/extractor.rs
@@ -1,17 +1,13 @@
-use std::process::exit;
-
/// for the parser module, extractor.rs is the backbone of all parsing
/// it takes a String and a mutable reference to a Vec.
/// String is the contents of a source file, while the mut ref vector will
/// be used to collect the dependencies that we have extracted from the contents.
+use std::process::exit;
use super::structs::{Dependency, VersionStatus};
-
use lazy_static::lazy_static;
-use pep_508::{self, Spec};
+use crate::pep_508;
+use crate::pep_508::Spec;
use regex::Regex;
-
-
-
use toml::{de::Error, Value};
pub fn extract_imports_python(text: String, imp: &mut Vec) {
@@ -146,7 +142,7 @@ pub fn extract_imports_setup_py(setup_py_content: &str, imp: &mut Vec res.pyproject_found {
@@ -183,6 +185,7 @@ async fn find_pyproject_imports(f: &Vec) {
}
// println!("{:?}", imports.clone());
// cons.clear_last_lines(1).unwrap();
+
// --- pass the dependencies to the scanner/api ---
scanner::start(imports).await.unwrap();
}
diff --git a/src/parser/structs.rs b/src/parser/structs.rs
index afc9275..054d783 100644
--- a/src/parser/structs.rs
+++ b/src/parser/structs.rs
@@ -1,14 +1,9 @@
use console::style;
use std::{ffi::OsString, process::exit};
-
+use crate::pep_508;
use crate::{scanner::models::Query, utils, ARGS};
-
use super::scanner::models::Vulnerability;
-// struct Python;
-// struct Requirements;
-// struct Pyproject;
-
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum FileTypes {
Python,
@@ -97,16 +92,16 @@ impl Dependency {
}
#[derive(Debug, Clone)]
+/// pyscan may get version info from a lot of places. This keeps it in check.
pub struct VersionStatus {
- // pyscan may get version info from a lot of places. This keeps it in check.
pub pypi: bool,
pub pip: bool,
pub source: bool,
}
/// implementation for VersionStatus which can get return versions while updating the status, also pick the one decided via arguments, a nice abstraction really.
+/// retreives versions from pip and pypi.org in (pip, pypi) format.
impl VersionStatus {
- /// retreives versions from pip and pypi.org in (pip, pypi) format.
pub async fn _full_check(&mut self, name: &str) -> (String, String) {
let pip = utils::get_python_package_version(name);
let pip_v = if let Err(e) = pip {
diff --git a/src/pep_508/macros.rs b/src/pep_508/macros.rs
new file mode 100644
index 0000000..69f9e65
--- /dev/null
+++ b/src/pep_508/macros.rs
@@ -0,0 +1,7 @@
+macro_rules! set {
+ ($($tt:tt)+) => {
+ ::chumsky::primitive::any().filter(|c| matches!(c, $($tt)+))
+ };
+}
+
+pub(crate) use set;
diff --git a/src/pep_508/mod.rs b/src/pep_508/mod.rs
new file mode 100644
index 0000000..0425b02
--- /dev/null
+++ b/src/pep_508/mod.rs
@@ -0,0 +1,290 @@
+//! Python dependency parser for [PEP 508](https://peps.python.org/pep-0508)
+//!
+//! ```
+//! # use pep_508::*;
+//! let dep = "requests[security, socks] <= 2.28.1, == 2.28.*; python_version > '3.7' and extra == 'http'";
+//! let parsed = parse(dep).unwrap();
+//! let expected = Dependency {
+//! name: "requests",
+//! extras: vec!["security", "socks"],
+//! spec: Some(Spec::Version(vec![
+//! VersionSpec {
+//! comparator: Comparator::Le,
+//! version: "2.28.1",
+//! },
+//! VersionSpec {
+//! comparator: Comparator::Eq,
+//! version: "2.28.*",
+//! },
+//! ])),
+//! marker: Some(Marker::And(
+//! Box::new(Marker::Operator(
+//! Variable::PythonVersion,
+//! Operator::Comparator(Comparator::Gt),
+//! Variable::String("3.7"),
+//! )),
+//! Box::new(Marker::Operator(
+//! Variable::Extra,
+//! Operator::Comparator(Comparator::Eq),
+//! Variable::String("http"),
+//! )),
+//! )),
+//! };
+//! assert_eq!(parsed, expected);
+//! ```
+mod macros;
+mod url;
+
+use chumsky::{
+ error::Error,
+ extra::Full,
+ prelude::Simple,
+ primitive::{any, choice, empty, end, group, just},
+ recursive::recursive,
+ IterParser, Parser,
+};
+
+use macros::set;
+
+/// Python dependency specified by [PEP 508](https://peps.python.org/pep-0508)
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Dependency<'a> {
+ /// Name of the dependency
+ pub name: &'a str,
+ /// Extras for the dependency, things that go inside `[]`
+ pub extras: Vec<&'a str>,
+ /// Version specification or URL
+ pub spec: Option>,
+ /// Environment markers, conditions that go after `;`
+ pub marker: Option>,
+}
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum Spec<'a> {
+ /// `foo @ https://example.com`
+ Url(&'a str),
+ /// `foo >= 0.1.0, < 0.2.0`
+ Version(Vec>),
+}
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct VersionSpec<'a> {
+ pub comparator: Comparator,
+ pub version: &'a str,
+}
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum Marker<'a> {
+ And(Box>, Box>),
+ Or(Box>, Box>),
+ Operator(Variable<'a>, Operator, Variable<'a>),
+}
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum Variable<'a> {
+ PythonVersion,
+ PythonFullVersion,
+ OsName,
+ SysPlatform,
+ PlatformRelease,
+ PlatformSystem,
+ PlatformVersion,
+ PlatformMachine,
+ PlatformPythonImplementation,
+ ImplementationName,
+ ImplementationVersion,
+ Extra,
+ String(&'a str),
+}
+
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum Operator {
+ Comparator(Comparator),
+ /// `in`
+ In,
+ /// `not in`
+ NotIn,
+}
+
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum Comparator {
+ /// `foo < '0.1.0'`
+ Lt,
+ /// `foo < '0.1.0'`
+ Le,
+ /// `foo != '0.1.0'`
+ Ne,
+ /// `foo == '0.1.0'`
+ Eq,
+ /// `foo >= '0.1.0'`
+ Ge,
+ /// `foo > '0.1.0'`
+ Gt,
+ /// `foo ~= '0.1.0'`
+ Cp,
+ /// `foo === '0.1.0'`
+ Ae,
+}
+
+/// Parse a [PEP 508](https://peps.python.org/pep-0508) string into a [Dependency]
+/// ```
+/// # use pep_508::parse;
+/// assert_eq!(parse("requests >= 2").unwrap().name, "requests");
+/// assert_eq!(parse("numpy").unwrap().name, "numpy");
+/// ```
+pub fn parse(dependency: &str) -> Result>> {
+ parser().then_ignore(end()).parse(dependency).into_result()
+}
+
+/// Create a [chumsky](https://docs.rs/chumsky) parser,
+/// allows more customization than [parse]
+pub fn parser<'a, E: Error<'a, &'a str> + 'a>(
+) -> impl Parser<'a, &'a str, Dependency<'a>, Full> {
+ let ws = set!(' ' | '\t').repeated().ignored();
+ let ident = any()
+ .filter(char::is_ascii_alphanumeric)
+ .then(
+ set!('-' | '_' | '.')
+ .or_not()
+ .then(any().filter(char::is_ascii_alphanumeric))
+ .repeated(),
+ )
+ .slice();
+
+ let cmp = choice((
+ just("===").to(Comparator::Ae),
+ just("<=").to(Comparator::Le),
+ just("!=").to(Comparator::Ne),
+ just("==").to(Comparator::Eq),
+ just(">=").to(Comparator::Ge),
+ just("~=").to(Comparator::Cp),
+ just('<').to(Comparator::Lt),
+ just('>').to(Comparator::Gt),
+ ));
+
+ let version_spec = cmp
+ .then_ignore(ws)
+ .then(
+ set!(
+ 'A' ..= 'Z' | 'a' ..= 'z' | '0' ..= '9' | '-' | '_' | '.' | '*' | '+' | '!'
+ )
+ .repeated()
+ .at_least(1)
+ .slice(),
+ )
+ .map(|(comparator, version)| VersionSpec {
+ comparator,
+ version,
+ })
+ .then_ignore(ws)
+ .separated_by(just(',').ignore_then(ws))
+ .at_least(1)
+ .collect();
+
+ group((
+ ws.ignore_then(ident).then_ignore(ws),
+ ident
+ .then_ignore(ws)
+ .separated_by(just(',').ignore_then(ws))
+ .at_least(1)
+ .collect()
+ .delimited_by(just('[').ignore_then(ws), just(']'))
+ .then_ignore(ws)
+ .or(empty().map(|_| Vec::new())),
+ just('@')
+ .ignore_then(ws)
+ .ignore_then(url::parser())
+ .map(Spec::Url)
+ .or(version_spec
+ .delimited_by(just('(').then_ignore(ws), just(')'))
+ .or(version_spec)
+ .map(Spec::Version))
+ .then_ignore(ws)
+ .or_not(),
+ just(';')
+ .ignore_then(ws)
+ .ignore_then(recursive(|marker_or| {
+ macro_rules! c {
+ () => {
+ ' ' | '\t' | 'A' ..= 'Z' | 'a' ..= 'z' | '0' ..= '9' | '(' | ')' | '.' |
+ '{' | '}' | '-' | '_' | '*' | '#' | ':' | ';' | ',' | '/' | '?' | '[' |
+ ']' | '!' | '~' | '`' | '@' | '$' | '%' | '^' | '&' | '=' | '+' | '|' |
+ '<' | '>'
+ };
+ }
+
+ let marker_var = choice((
+ just('\'')
+ .ignore_then(set!(c!() | '"').repeated().slice())
+ .then_ignore(just('\''))
+ .map(Variable::String),
+ just('"')
+ .ignore_then(set!(c!() | '\'').repeated().slice())
+ .then_ignore(just('"'))
+ .map(Variable::String),
+ just("python_version").to(Variable::PythonVersion),
+ just("python_full_version").to(Variable::PythonFullVersion),
+ just("os_name").to(Variable::OsName),
+ just("sys_platform").to(Variable::SysPlatform),
+ just("platform_release").to(Variable::PlatformRelease),
+ just("platform_system").to(Variable::PlatformSystem),
+ just("platform_version").to(Variable::PlatformVersion),
+ just("platform_machine").to(Variable::PlatformMachine),
+ just("platform_python_implementation")
+ .to(Variable::PlatformPythonImplementation),
+ just("implementation_name").to(Variable::ImplementationName),
+ just("implementation_version").to(Variable::ImplementationVersion),
+ just("extra").to(Variable::Extra),
+ ));
+
+ let marker_expr = group((
+ marker_var.clone().then_ignore(ws),
+ cmp.map(Operator::Comparator)
+ .or(just("in").to(Operator::In).or(just("not")
+ .ignore_then(set!(' ' | '\t').repeated().at_least(1))
+ .ignore_then(just("in"))
+ .to(Operator::NotIn)))
+ .then_ignore(ws),
+ marker_var,
+ ))
+ .map(|(lhs, op, rhs)| Marker::Operator(lhs, op, rhs))
+ .or(marker_or
+ .then_ignore(ws)
+ .delimited_by(just('(').then_ignore(ws), just(')')));
+
+ let marker_and = marker_expr
+ .clone()
+ .then(
+ ws.ignore_then(just("and"))
+ .ignore_then(ws)
+ .ignore_then(marker_expr)
+ .or_not(),
+ )
+ .map(|(lhs, rhs)| match rhs {
+ Some(rhs) => Marker::And(Box::new(lhs), Box::new(rhs)),
+ None => lhs,
+ });
+
+ marker_and
+ .clone()
+ .then(
+ ws.ignore_then(just("or"))
+ .ignore_then(ws)
+ .ignore_then(marker_and)
+ .or_not(),
+ )
+ .map(|(lhs, rhs)| match rhs {
+ Some(rhs) => Marker::Or(Box::new(lhs), Box::new(rhs)),
+ None => lhs,
+ })
+ }))
+ .or_not(),
+ ))
+ .then_ignore(ws)
+ .map(|(name, extras, spec, marker)| Dependency {
+ name,
+ extras,
+ spec,
+ marker,
+ })
+}
diff --git a/src/pep_508/url.rs b/src/pep_508/url.rs
new file mode 100644
index 0000000..15137df
--- /dev/null
+++ b/src/pep_508/url.rs
@@ -0,0 +1,205 @@
+use chumsky::{
+ error::Error,
+ extra::Full,
+ primitive::{any, choice, group, just},
+ Parser,
+};
+
+use super::macros::set;
+
+macro_rules! c {
+ () => {
+ 'A' ..= 'Z' | 'a' ..= 'z' | '0' ..= '9' | '-' | '.' | '_' | '~' |
+ '!' | '$' | '&' | '\'' | '(' | ')' | '*' | '+' | ',' | ';' | '='
+ };
+}
+
+pub(crate) fn parser<'a, E: Error<'a, &'a str> + 'a>(
+) -> impl Parser<'a, &'a str, &'a str, Full> {
+ let c = set!(c!());
+ let digit = any().filter(char::is_ascii_digit);
+ let hex = any().filter(char::is_ascii_hexdigit);
+ let percent = just('%').then_ignore(hex.repeated().exactly(2).rewind());
+ let reg = percent.or(c);
+ let pchar = percent.or(set!(c!() | ':' | '@'));
+
+ let octet = choice((
+ group((just('1'), digit, digit)).ignored(),
+ just('2')
+ .then(
+ set!('0' ..= '4')
+ .then(digit)
+ .or(just('5').then(set!('0' ..= '5'))),
+ )
+ .ignored(),
+ set!('1' ..= '9').then(digit).ignored(),
+ digit.map(|c| vec![c]).ignored(),
+ ));
+ let ipv4 = group((octet, just('.'), octet, just('.'), octet, just('.'), octet)).ignored();
+ let h16 = hex.repeated().at_least(1).at_most(4);
+ let h16r = just(':').then(h16).repeated();
+ let ls32 = group((h16, just(':'), h16)).ignored().or(ipv4);
+
+ let segments = just('/').then(pchar.repeated()).repeated();
+ let frag = percent.or(set!(c!() | ':' | '@' | '/' | '?')).repeated();
+ let frags = just('?')
+ .then(frag)
+ .or_not()
+ .then(just('#').then(frag).or_not());
+
+ let path = just('/')
+ .then(
+ group((
+ just('/'),
+ percent
+ .or(set!(c!() | ':'))
+ .repeated()
+ .then(just('@'))
+ .or_not(),
+ choice((
+ just('[')
+ .then(choice((
+ group((
+ just('v'),
+ hex.repeated().at_least(1),
+ just('.'),
+ set!(c!() | ':').repeated().at_least(1),
+ ))
+ .ignored(),
+ h16.then(just(':'))
+ .repeated()
+ .exactly(6)
+ .then(ls32)
+ .ignored(),
+ group((just("::"), h16r.exactly(5), ls32)).ignored(),
+ group((h16.or_not(), just("::"), h16r.exactly(4), ls32)).ignored(),
+ group((
+ h16.then(just(':')).or_not().then(h16).or_not(),
+ just("::"),
+ h16r.exactly(3),
+ ls32,
+ ))
+ .ignored(),
+ group((
+ h16.then(h16r.at_most(2)).or_not(),
+ just(':'),
+ just(':'),
+ h16r.exactly(2),
+ ls32,
+ ))
+ .ignored(),
+ group((
+ h16.then(h16r.at_most(3)).or_not(),
+ just("::"),
+ h16,
+ just(':'),
+ ls32,
+ ))
+ .ignored(),
+ group((h16.then(h16r.at_most(4)).or_not(), just("::"), ls32)).ignored(),
+ group((h16.then(h16r.at_most(5)).or_not(), just("::"), h16)).ignored(),
+ h16.then(h16r.at_most(6))
+ .or_not()
+ .then(just("::"))
+ .ignored(),
+ )))
+ .then(just(']'))
+ .ignored(),
+ ipv4,
+ reg.repeated(),
+ )),
+ just(':').then(digit.repeated()).or_not(),
+ segments,
+ ))
+ .ignored()
+ .or(pchar
+ .repeated()
+ .at_least(1)
+ .then(segments)
+ .or_not()
+ .ignored())
+ .or_not(),
+ )
+ .ignored();
+
+ choice((
+ group((
+ any().filter(char::is_ascii_alphabetic),
+ set!('A' ..= 'Z' | 'a' ..= 'z' | '0' ..= '9' | '+' | '-' | '.').repeated(),
+ just(':'),
+ path.or(pchar.repeated().at_least(1).then(segments).ignored()),
+ ))
+ .ignored(),
+ path,
+ percent
+ .or(set!(c!() | '@'))
+ .repeated()
+ .at_least(1)
+ .then(segments)
+ .ignored(),
+ ))
+ .then(frags)
+ .slice()
+}
+
+#[cfg(test)]
+mod tests {
+ use chumsky::{prelude::Rich, primitive::end, Parser};
+
+ use super::parser;
+
+ fn parse(s: &str) -> Result<&str, Vec>> {
+ parser().then_ignore(end()).parse(s).into_result()
+ }
+
+ fn check(urls: impl IntoIterator- >) {
+ for url in urls {
+ let url = url.as_ref();
+ assert_eq!(url, parse(url).expect(url));
+ }
+ }
+
+ #[test]
+ fn basic() {
+ check([
+ "https://github.com/figsoda/pep-508",
+ "https://crates.io/search?q=pep-508&sort=recent-downloads",
+ "http://127.0.0.1:8000?some=query#anchor",
+ "/relative/url?query=good",
+ "another/relative/url#this",
+ ]);
+
+ assert!(parse("").is_err());
+ assert!(parse("https://example.com ").is_err());
+ }
+
+ // examples from https://datatracker.ietf.org/doc/html/rfc3986.htm
+ #[test]
+ fn examples() {
+ check([
+ "ftp://ftp.is.co.za/rfc/rfc1808.txt",
+ "http://www.ietf.org/rfc/rfc2396.txt",
+ "ldap://[2001:db8::7]/c=GB?objectClass?one",
+ "mailto:John.Doe@example.com",
+ "news:comp.infosystems.www.servers.unix",
+ "tel:+1-816-555-1212",
+ "telnet://192.0.2.16:80/",
+ "urn:oasis:names:specification:docbook:dtd:xml:4.1.2",
+ ]);
+ }
+
+ #[test]
+ fn ipv6() {
+ check([
+ "https://[::]",
+ "https://[::1]",
+ "https://[0:0:0:0:0:0:0:0]",
+ "https://[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]",
+ ]);
+
+ assert!(parse("[::]").is_err());
+ assert!(parse("https://[:::1]").is_err());
+ assert!(parse("https://[ffff:ffff:ffff:ffff:ffff:ffff:ffff]").is_err());
+ assert!(parse("https://[0:0:0:0:0:0:0:0:0]").is_err());
+ }
+}
diff --git a/src/scanner/api.rs b/src/scanner/api.rs
index efd0b76..a01c495 100644
--- a/src/scanner/api.rs
+++ b/src/scanner/api.rs
@@ -126,7 +126,7 @@ impl Osv {
if let Ok(dir) = env::current_dir() {
let r = fs::write(dir.join(filename), restext);
if let Err(er) = r {
- eprintln!("Could not write output to file: {}", er.to_string());
+ eprintln!("Could not write output to file: {}", er);
exit(1)
}
else {
diff --git a/src/scanner/models.rs b/src/scanner/models.rs
index c861438..e7cd2b7 100644
--- a/src/scanner/models.rs
+++ b/src/scanner/models.rs
@@ -7,7 +7,7 @@ use serde::{Serialize, Deserialize};
use crate::parser::structs::ScannedDependency;
-
+/// contains a vector of vulnerabilities.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Vulnerability {
#[serde(rename = "vulns")]
diff --git a/src/store/cache.rs b/src/store/cache.rs
new file mode 100644
index 0000000..ea3e704
--- /dev/null
+++ b/src/store/cache.rs
@@ -0,0 +1,54 @@
+use anyhow::Error;
+
+use chrono::{Utc, DateTime};
+
+use super::queries::retrieve_root;
+
+
+struct PipCache {
+ connected: bool,
+ last_update: DateTime,
+}
+
+impl PipCache {
+ pub async fn create_table() -> Result<(),Error> {
+ let (conn, tx) = retrieve_root().await?;
+
+ sqlx::query!(r#"CREATE TABLE IF NOT EXISTS pipcache (
+ name TEXT NOT NULL,
+ version TEXT NOT NULL)"#).execute(&conn).await?;
+ tx.commit().await?;
+ Ok(())
+ }
+
+ pub async fn add(name: &str, version: &str) -> Result<(), Error> {
+ let (conn, tx) = retrieve_root().await?;
+
+ sqlx::query!("INSERT INTO pipcache (name, version) VALUES (?, ?)", name, version).execute(&conn).await?;
+
+ tx.commit().await?;
+
+ Ok(())
+ }
+ pub async fn update(name: &str, version: &str) -> Result<(), Error> {
+ let (conn, tx) = retrieve_root().await?;
+
+ sqlx::query!("UPDATE pipcache SET name = ?, version = ?", name, version).execute(&conn).await?;
+
+ tx.commit().await?;
+
+ Ok(())
+ }
+
+ pub async fn remove(name: &str) -> Result<(), Error> {
+ let (conn, tx) = retrieve_root().await?;
+
+ sqlx::query!("DELETE FROM pipcache WHERE name = ?;", name).execute(&conn).await?;
+
+ tx.commit().await?;
+
+ Ok(())
+ }
+
+}
+
diff --git a/src/store/changes.rs b/src/store/changes.rs
new file mode 100644
index 0000000..57ec35f
--- /dev/null
+++ b/src/store/changes.rs
@@ -0,0 +1,12 @@
+//! Dependency changes! A way to track the evolution of the user's dependency configuration over time
+//! in a config type agnostic way. They could switch from using a pyproject to a requirements.txt or setup.py
+//! and shit should remain the same on how we track the information.
+//! This involves:
+//! - encoding dependency info to a format and saving it to /changes
+//! - decoding it
+//!
+//! the change names are the hashes of the config file for easier change discovery.
+//! each change begins with the hash of the previous change but instead of delta encoding
+//! each file has the full dependency info of the time because i do not wanna do too many I/O calls
+//! or deal with delta encoding for such a small project.
+
diff --git a/src/store/mod.rs b/src/store/mod.rs
new file mode 100644
index 0000000..b3a2118
--- /dev/null
+++ b/src/store/mod.rs
@@ -0,0 +1,290 @@
+//! This module deals with data storage. Databases, Caches, Paths, etc.
+pub mod cache;
+pub mod paths;
+pub mod queries;
+pub mod changes;
+
+use std::collections::HashSet;
+
+use anyhow::Error;
+use async_trait::async_trait;
+use chrono::NaiveDate;
+use queries::retrieve_root;
+use sqlx::query;
+use xxhash_rust::xxh3::xxh3_64;
+
+/// Represents the single, in-database Dependency row. NOT TO BE CONFUSED with the struct with same name in `parser::structs`
+#[derive(PartialEq, Eq, Hash)]
+pub struct Dependency {
+ pub name: String,
+ pub version: String,
+ pub added: NaiveDate,
+ pub updated: NaiveDate,
+}
+/// Represents the single, in-database Vulnerability. NOT TO BE CONFUSED with the struct with same name in `scanner::models`
+pub struct Vulnerability {
+ pub cve: String,
+ pub name: String,
+}
+/// Represents the (many-to-many) relation between vulnerabilities and python packages.
+pub struct VulnerabilityDependency {
+ pub cve: String,
+ pub package: String,
+}
+
+// TODO HASH LOOKUP CHANGES
+// use a dot (graphviz) file fs system
+
+/// in-database table for logging dependency changes.
+pub struct DependencyChanges {
+ pub hash: u64,
+ pub name: String,
+ pub change: char,
+ pub timestamp: i64,
+}
+
+/// Used to represent multiple dependencies.
+/// Makes it easier to spot differences (between changes) and keeps it unique.
+pub type Dependencies = HashSet;
+
+enum DatabaseTable {
+ Dependency(Dependency),
+ Vulnerability(Vulnerability),
+ VulnerabilityDependency(VulnerabilityDependency),
+ DependencyChanges(DependencyChanges),
+}
+
+/// Database of a single individual project being watched by Pyscan.
+/// All manipulations are done via functions.
+/// To execute queries directly see `queries::retrieve_root`
+struct ProjectDatabase;
+
+impl DatabaseOps for ProjectDatabase {}
+
+/// Database operations for different tables.
+/// - Used by `ProjectDatabase` struct.
+/// - Makes it so that its easy to update different tables just by passing structs.
+#[async_trait]
+trait DatabaseOps {
+ async fn insert(d: DatabaseTable) -> Result<(), Error> {
+ let (conn, tx) = retrieve_root().await?;
+ match d {
+ DatabaseTable::Dependency(dep) => {
+ query!(
+ "
+ INSERT INTO Dependency (name, version, added, updated)
+ VALUES (?,?,?,?);
+ ",
+ dep.name,
+ dep.version,
+ dep.added,
+ dep.updated
+ )
+ .execute(&conn)
+ .await?;
+ tx.commit().await?;
+ Ok(())
+ }
+ DatabaseTable::Vulnerability(v) => {
+ query!(
+ "
+ INSERT INTO Vulnerability (cve, name)
+ VALUES (?,?);
+ ",
+ v.cve,
+ v.name
+ )
+ .execute(&conn)
+ .await?;
+ tx.commit().await?;
+ Ok(())
+ }
+ DatabaseTable::VulnerabilityDependency(vd) => {
+ // have to use function here because the query macro doesnt agree with what
+ // i'm doing for some reason
+ sqlx::query(
+ r#"
+ INSERT INTO VulnerabilityDependency (vulnerability_cve, dependency_name)
+ VALUES (?,?);
+ "#,
+ )
+ .bind(vd.cve)
+ .bind(vd.package)
+ .execute(&conn)
+ .await?;
+ tx.commit().await?;
+ Ok(())
+ }
+ DatabaseTable::DependencyChanges(dc) => {
+ sqlx::query(
+ "
+ INSERT INTO DependencyChanges (hash, name, change, timestamp)
+ VALUES (?,?,?,?);
+ ",
+ )
+ .bind(dc.hash.to_string())
+ .bind(dc.name)
+ .bind(dc.change.to_string())
+ .bind(dc.timestamp)
+ .execute(&conn)
+ .await?;
+ tx.commit().await?;
+ Ok(())
+ }
+ }
+ }
+
+ async fn update(d: DatabaseTable) -> Result<(), Error> {
+ let (conn, tx) = retrieve_root().await?;
+ match d {
+ DatabaseTable::Dependency(dep) => {
+ query!("
+ UPDATE Dependency SET name = ?, version = ?, added = ?, updated = ?
+ WHERE name = ?;
+ ", dep.name, dep.version, dep.added, dep.updated, dep.name).execute(&conn).await?;
+ tx.commit().await?;
+ Ok(())
+ },
+ DatabaseTable::Vulnerability(v) => {
+ Err(Error::msg(format!("There is no reason to update the Vuln table. Rows should either be removed or created upon discovering and discarding Vulnerabilities.\nAn update attempt was made:\n {}", v)))
+ }
+ DatabaseTable::VulnerabilityDependency(vd) => {
+ Err(Error::msg(format!("There is no reason to update the VD table. Rows should either be removed or created upon discovering and discarding vulns in packages.\nAn update attempt was made with this row:\n {}", vd)))
+ },
+ DatabaseTable::DependencyChanges(dc) => {
+ Err(Error::msg(format!("Why would you try to update a row in a table that tracks changes? Its a logger, there's no need to do changes, only insertion and deletion.\nAn update attempt was made with this row:\n {}", dc)))
+ }
+ }
+ }
+
+ async fn delete(d: DatabaseTable) -> Result<(), Error> {
+ let (conn, tx) = retrieve_root().await?;
+ match d {
+ DatabaseTable::Dependency(dep) => {
+ sqlx::query(
+ r#"
+ DELETE FROM VulnerabilityDependency
+ WHERE dependency_name = ?;
+ DELETE FROM Dependency
+ WHERE name = ?;
+ "#,
+ )
+ .bind(&dep.name)
+ .bind(&dep.name)
+ .execute(&conn)
+ .await?;
+ tx.commit().await?;
+ Ok(())
+ }
+ DatabaseTable::Vulnerability(v) => {
+ sqlx::query(
+ r#"
+ DELETE FROM VulnerabilityDependency
+ WHERE vulnerability_cve = ?;
+ DELETE FROM Vulnerability
+ WHERE cve = ?;
+ "#,
+ )
+ .bind(v.cve)
+ .execute(&conn)
+ .await?;
+ tx.commit().await?;
+ Ok(())
+ }
+ DatabaseTable::VulnerabilityDependency(vd) => {
+ sqlx::query(
+ r#"
+ DELETE FROM VulnerabilityDependency
+ WHERE vulnerability_cve = ? AND dependency_name = ?;
+ "#,
+ )
+ .bind(vd.cve)
+ .bind(vd.package)
+ .execute(&conn)
+ .await?;
+ tx.commit().await?;
+ Ok(())
+ }
+ DatabaseTable::DependencyChanges(dc) => {
+ sqlx::query(
+ r#"
+ DELETE FROM DependencyChanges
+ WHERE hash = ? AND name = ? AND change = ? AND timestamp = ?;
+ "#,
+ )
+ .bind(dc.hash.to_string())
+ .bind(dc.name)
+ .bind(dc.change.to_string())
+ .bind(dc.timestamp)
+ .execute(&conn)
+ .await?;
+ tx.commit().await?;
+ Ok(())
+ }
+ }
+ }
+}
+
+/// Trait for representing changes in the configuration files.
+#[async_trait]
+pub trait Change {
+ /// returns `Ok(true)` if a change has been detected by doing a hash look-up
+ async fn has_changed(s: &str) -> anyhow::Result {
+ let (conn, tx) = retrieve_root().await?;
+ let shash = xxh3_64(s.as_bytes()).to_string();
+ let r = sqlx::query!(
+ r#"
+ SELECT hash from DependencyChanges
+ WHERE hash = ?;
+ "#,
+ shash
+ )
+ .fetch_optional(&conn)
+ .await?;
+ tx.commit().await?;
+
+ if r.is_some() { // file hasnt been changed (or reverted)
+ Ok(true)
+ } else {
+ Ok(false)
+ }
+ }
+}
+
+impl Change for DependencyChanges {}
+
+impl std::fmt::Display for Dependency {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
+ write!(
+ f,
+ "Dependency: {},\nVersion: {},\nAdded: {},\nUpdated: {}\n",
+ self.name, self.version, self.added, self.updated
+ )
+ }
+}
+
+impl std::fmt::Display for Vulnerability {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
+ write!(f, "CVE: {},\nName: {}\n", self.cve, self.name)
+ }
+}
+
+impl std::fmt::Display for VulnerabilityDependency {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
+ write!(
+ f,
+ "Vulnerability {} was found in {}",
+ self.cve, self.package
+ )
+ }
+}
+
+impl std::fmt::Display for DependencyChanges {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
+ write!(
+ f,
+ "Dependency: {},\nChange: {},\nTimestamp: {},\nHash: {}\n",
+ self.name, self.change, self.timestamp, self.hash
+ )
+ }
+}
diff --git a/src/store/paths.rs b/src/store/paths.rs
new file mode 100644
index 0000000..8c41e55
--- /dev/null
+++ b/src/store/paths.rs
@@ -0,0 +1,345 @@
+//! Functions and statics concerning with paths and directories important for pyscan's functionality.
+use super::queries::{retrieve_root, retrieve_home, Project, self, PyscanData};
+use anyhow::Error;
+use once_cell::sync::Lazy;
+use std::{
+ env,
+ fs::{self, File, OpenOptions},
+ io::Write,
+ path::PathBuf,
+ process::exit,
+};
+
+// contains data on all projects being watched across the user's system
+pub static PYSCAN_HOME: Lazy> = Lazy::new(init_data_dir);
+
+// TODO ! : reinitialize if db already exists (add project to HOME db)
+
+// at the project's root directory after `pyscan init`
+pub static PYSCAN_ROOT: Lazy> = Lazy::new(init_project_dir);
+
+fn init_data_dir() -> Result {
+ //! checks for a pyscan data directory (different to a project directory), otherwise creates one.
+ //! returns `Ok(path)` if exists or has been created, exits otherwise.
+ //! exits because:
+ //! - whatever needs this function MUST use the data directory,
+ //! which only gets made if the user has done `pyscan init`
+ //! - it would be troublesome if the user already had `pyscan init`ed
+ //! but couldn't find a data directory, which keeps track of the
+ //! projects being watched by pyscan.
+ let dir = dirs::data_dir();
+ if let Some(d) = dir {
+ let path = d.join("pyscan");
+ if let Err(e) = path.try_exists() {
+ eprintln!(
+ "There was an error while checking for pyscan's data in {}.\nerror: {}",
+ path.display(),
+ e
+ );
+ exit(1)
+ } else {
+ // unwrapping should be fine since Err value is accounted for above.
+ if path.try_exists().unwrap() {
+ Ok(path)
+ } else {
+ let r = fs::create_dir(path.clone());
+ if let Err(e) = r {
+ eprintln!("Pyscan failed to create a folder on your system's data directory.\ndirectory: {}\nerror: {}", d.display(), e);
+ exit(1)
+ } else {
+ Ok(path)
+ }
+ }
+ }
+ } else {
+ eprintln!("Pyscan failed to recognize a data directory for your OS. This rarely happens and should be reported at github.com/aswinnnn/pyscan/issues");
+ exit(1)
+ }
+}
+
+fn init_project_dir() -> Result {
+ //! Creates a project directory OR if it exists, returns its path.
+ //! This directory contains the sqlite db and most of the persistent stuff useful for an individual project's security.
+ //! - created on `pyscan init` and NOWHERE else
+ //! - its used inside a lazy static, which should be the main way of getting the project dir's path
+ //! - usage of the static should be done in a context where `pyscan init` has been confirmed to be run except for `pyscan init`.
+ let dir = env::current_dir();
+ if let Ok(d) = dir {
+ let mut dpath = d.clone();
+ if let Ok(Some(r)) = exists_check(&mut dpath) {
+ Ok(r)
+ } else {
+ let r = fs::create_dir(d.clone().join(".pyscan"));
+ if let Err(e) = r {
+ eprintln!("Pyscan failed to create a folder on the current directory.\ndirectory: {}\nerror: {}", d.display(), e);
+ exit(1)
+ } else {
+ Ok(d.join(".pyscan"))
+ }
+ }
+ } else {
+ eprintln!("Pyscan failed to get the current working directory. This should not happen and should be reported at github.com/aswinnnn/pyscan/issues");
+ exit(1)
+ }
+}
+
+pub async fn populate_project_dir() -> Result<(), Error> {
+ //! populates the .pyscan directory with a database and its tables.
+ //! this is only called on creation.
+ //! - creates .store file, creates tables
+ //! - adds .pyscan to gitignore
+
+ let dbpath = PYSCAN_ROOT.clone().unwrap().join(".store");
+ if let Ok(exists) = dbpath.try_exists() {
+ if !exists {
+ let r = fs::File::create(&dbpath);
+ if let Err(e) = r {
+ return Err(Error::msg(format!(
+ "failed to create database.\npath: {}\nerror: {}\n",
+ dbpath.display(),
+ e
+ )));
+ }
+ }
+ }
+
+ let (conn, tx) = retrieve_root().await?;
+
+ sqlx::query!(
+ r#"
+ CREATE TABLE IF NOT EXISTS Vulnerability (
+ cve TEXT PRIMARY KEY,
+ name TEXT NOT NULL
+ );
+ "#
+ )
+ .execute(&conn)
+ .await?;
+
+ sqlx::query!(
+ r#"
+ CREATE TABLE IF NOT EXISTS Dependency (
+ name TEXT PRIMARY KEY,
+ version TEXT NOT NULL,
+ added TEXT NOT NULL,
+ updated TEXT NOT NULL
+ );
+ "#
+ )
+ .execute(&conn)
+ .await?;
+
+ sqlx::query!(
+ r#"
+ CREATE TABLE IF NOT EXISTS VulnerabilityDependency (
+ vulnerability_cve TEXT NOT NULL,
+ dependency_name TEXT NOT NULL,
+ FOREIGN KEY (vulnerability_cve) REFERENCES Vulnerability(cve) ON DELETE CASCADE,
+ FOREIGN KEY (dependency_name) REFERENCES Dependency(name) ON DELETE CASCADE,
+ PRIMARY KEY (vulnerability_cve, dependency_name)
+ );
+ "#
+ )
+ .execute(&conn)
+ .await?;
+
+ sqlx::query!(
+ r#"
+ CREATE TABLE IF NOT EXISTS DependencyChanges (
+ hash TEXT NOT NULL,
+ name TEXT NOT NULL,
+ change CHAR(1) NOT NULL,
+ timestamp INTEGER NOT NULL
+ );
+ "#
+ )
+ .execute(&conn)
+ .await?;
+ tx.commit().await?;
+
+ gitignore(); // add .pyscan to .gitignore
+
+ Ok(())
+}
+
+pub async fn populate_data_dir() -> Result<(), Error> {
+ //! populates the pyscan directory (at user's data directory) with a database and its tables.
+ //! this is only called once, first time running pyscan.
+ //! - creates pdata (pyscan data) file, creates tables
+
+ let dbpath = PYSCAN_HOME.clone().unwrap().join("pdata");
+ if let Ok(exists) = dbpath.try_exists() {
+ if !exists {
+ let r = fs::File::create(&dbpath);
+ if let Err(e) = r {
+ return Err(Error::msg(format!(
+ "failed to create database.\npath: {}\nerror: {}\n",
+ dbpath.display(),
+ e
+ )));
+ }
+ }
+ }
+
+ let (conn, tx) = retrieve_home().await?;
+
+ sqlx::query!(
+ r#"
+ CREATE TABLE IF NOT EXISTS Settings (
+ key TEXT UNIQUE NOT NULL,
+ value TEXT NOT NULL
+ );
+ "#
+ )
+ .execute(&conn).await?;
+
+ sqlx::query!(
+ r#"
+ CREATE TABLE IF NOT EXISTS ProjectInfo (
+ id INTEGER PRIMARY_KEY AUTO_INCREMENT,
+ project_id TEXT NOT NULL,
+ path TEXT NOT NULL,
+ added TEXT NOT NULL
+ );
+ "#)
+ .execute(&conn).await?;
+ tx.commit().await?;
+ Ok(())
+}
+
+/// perform checks to see if the .pyscan exists in a directory or its parent directory.
+/// - checks cwd, its parent, and then its parent.
+/// - `Ok(PathBuf)` => path exists
+/// - `Ok(None)` => path does not exist
+/// - `Err` => Error
+fn exists_check(path: &mut PathBuf) -> Result