mirror of
https://github.com/ankitects/anki.git
synced 2026-01-13 22:13:58 -05:00
Rust dep updates
- Rust 1.87 for now (1.88 due out in around a week) - Nom looks involved, so I left it for now - prost-reflect depends on a new prost version that got yanked
This commit is contained in:
parent
b86ffe5d7d
commit
033285b936
25 changed files with 1115 additions and 1194 deletions
|
|
@ -14,6 +14,7 @@ allow = [
|
||||||
"MIT",
|
"MIT",
|
||||||
"Apache-2.0",
|
"Apache-2.0",
|
||||||
"Apache-2.0 WITH LLVM-exception",
|
"Apache-2.0 WITH LLVM-exception",
|
||||||
|
"CDLA-Permissive-2.0",
|
||||||
"ISC",
|
"ISC",
|
||||||
"MPL-2.0",
|
"MPL-2.0",
|
||||||
"BSD-2-Clause",
|
"BSD-2-Clause",
|
||||||
|
|
|
||||||
1464
Cargo.lock
generated
1464
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
125
Cargo.toml
125
Cargo.toml
|
|
@ -33,7 +33,7 @@ git = "https://github.com/ankitects/linkcheck.git"
|
||||||
rev = "184b2ca50ed39ca43da13f0b830a463861adb9ca"
|
rev = "184b2ca50ed39ca43da13f0b830a463861adb9ca"
|
||||||
|
|
||||||
[workspace.dependencies.fsrs]
|
[workspace.dependencies.fsrs]
|
||||||
version = "4.0.0"
|
version = "4.1.1"
|
||||||
# git = "https://github.com/open-spaced-repetition/fsrs-rs.git"
|
# git = "https://github.com/open-spaced-repetition/fsrs-rs.git"
|
||||||
# rev = "a7f7efc10f0a26b14ee348cc7402155685f2a24f"
|
# rev = "a7f7efc10f0a26b14ee348cc7402155685f2a24f"
|
||||||
# path = "../open-spaced-repetition/fsrs-rs"
|
# path = "../open-spaced-repetition/fsrs-rs"
|
||||||
|
|
@ -52,103 +52,98 @@ ninja_gen = { "path" = "build/ninja_gen" }
|
||||||
unicase = "=2.6.0" # any changes could invalidate sqlite indexes
|
unicase = "=2.6.0" # any changes could invalidate sqlite indexes
|
||||||
|
|
||||||
# normal
|
# normal
|
||||||
ammonia = "4.0.0"
|
ammonia = "4.1.0"
|
||||||
anyhow = "1.0.90"
|
anyhow = "1.0.98"
|
||||||
apple-bundles = "0.17.0"
|
async-compression = { version = "0.4.24", features = ["zstd", "tokio"] }
|
||||||
async-compression = { version = "0.4.17", features = ["zstd", "tokio"] }
|
|
||||||
async-stream = "0.3.6"
|
async-stream = "0.3.6"
|
||||||
async-trait = "0.1.83"
|
async-trait = "0.1.88"
|
||||||
axum = { version = "0.7", features = ["multipart", "macros"] }
|
axum = { version = "0.8.4", features = ["multipart", "macros"] }
|
||||||
axum-client-ip = "0.6"
|
axum-client-ip = "1.1.3"
|
||||||
axum-extra = { version = "0.9.4", features = ["typed-header"] }
|
axum-extra = { version = "0.10.1", features = ["typed-header"] }
|
||||||
blake3 = "1.5.4"
|
blake3 = "1.8.2"
|
||||||
bytes = "1.7.2"
|
bytes = "1.10.1"
|
||||||
camino = "1.1.9"
|
camino = "1.1.10"
|
||||||
chrono = { version = "0.4.38", default-features = false, features = ["std", "clock"] }
|
chrono = { version = "0.4.41", default-features = false, features = ["std", "clock"] }
|
||||||
clap = { version = "4.5.20", features = ["derive"] }
|
clap = { version = "4.5.40", features = ["derive"] }
|
||||||
coarsetime = "0.1.34"
|
coarsetime = "0.1.36"
|
||||||
convert_case = "0.6.0"
|
convert_case = "0.8.0"
|
||||||
criterion = { version = "0.5.1" }
|
criterion = { version = "0.6.0" }
|
||||||
csv = "1.3.0"
|
csv = "1.3.1"
|
||||||
data-encoding = "2.6.0"
|
data-encoding = "2.9.0"
|
||||||
difflib = "0.4.0"
|
difflib = "0.4.0"
|
||||||
dirs = "5.0.1"
|
dirs = "6.0.0"
|
||||||
dunce = "1.0.5"
|
dunce = "1.0.5"
|
||||||
embed-resource = "2.4"
|
embed-resource = "3.0.4"
|
||||||
envy = "0.4.2"
|
envy = "0.4.2"
|
||||||
flate2 = "1.0.34"
|
flate2 = "1.1.2"
|
||||||
fluent = "0.16.1"
|
fluent = "0.17.0"
|
||||||
fluent-bundle = "0.15.3"
|
fluent-bundle = "0.16.0"
|
||||||
fluent-syntax = "0.11.1"
|
fluent-syntax = "0.12.0"
|
||||||
fnv = "1.0.7"
|
fnv = "1.0.7"
|
||||||
futures = "0.3.31"
|
futures = "0.3.31"
|
||||||
glob = "0.3.1"
|
globset = "0.4.16"
|
||||||
globset = "0.4.15"
|
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
htmlescape = "0.3.1"
|
htmlescape = "0.3.1"
|
||||||
hyper = "1"
|
hyper = "1"
|
||||||
id_tree = "1.8.0"
|
id_tree = "1.8.0"
|
||||||
inflections = "1.1.1"
|
inflections = "1.1.1"
|
||||||
intl-memoizer = "0.5.2"
|
intl-memoizer = "0.5.3"
|
||||||
itertools = "0.13.0"
|
itertools = "0.14.0"
|
||||||
junction = "1.2.0"
|
junction = "1.2.0"
|
||||||
lazy_static = "1.5.0"
|
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
libc-stdhandle = "0.1"
|
libc-stdhandle = "0.1"
|
||||||
maplit = "1.0.2"
|
maplit = "1.0.2"
|
||||||
nom = "7.1.3"
|
nom = "7.1.3"
|
||||||
num-format = "0.4.4"
|
num-format = "0.4.4"
|
||||||
num_cpus = "1.16.0"
|
num_cpus = "1.17.0"
|
||||||
num_enum = "0.7.3"
|
num_enum = "0.7.3"
|
||||||
once_cell = "1.20.2"
|
once_cell = "1.21.3"
|
||||||
pbkdf2 = { version = "0.12", features = ["simple"] }
|
pbkdf2 = { version = "0.12", features = ["simple"] }
|
||||||
phf = { version = "0.11.2", features = ["macros"] }
|
phf = { version = "0.11.3", features = ["macros"] }
|
||||||
pin-project = "1.1.6"
|
pin-project = "1.1.10"
|
||||||
plist = "1.7.0"
|
prettyplease = "0.2.34"
|
||||||
prettyplease = "0.2.24"
|
|
||||||
prost = "0.13"
|
prost = "0.13"
|
||||||
prost-build = "0.13"
|
prost-build = "0.13"
|
||||||
prost-reflect = "0.14"
|
prost-reflect = "0.14.7"
|
||||||
prost-types = "0.13"
|
prost-types = "0.13"
|
||||||
pulldown-cmark = "0.9.6"
|
pulldown-cmark = "0.13.0"
|
||||||
pyo3 = { version = "0.24", features = ["extension-module", "abi3", "abi3-py39"] }
|
pyo3 = { version = "0.25.1", features = ["extension-module", "abi3", "abi3-py39"] }
|
||||||
rand = "0.8.5"
|
rand = "0.9.1"
|
||||||
regex = "1.11.0"
|
regex = "1.11.1"
|
||||||
reqwest = { version = "0.12.8", default-features = false, features = ["json", "socks", "stream", "multipart"] }
|
reqwest = { version = "0.12.20", default-features = false, features = ["json", "socks", "stream", "multipart"] }
|
||||||
rusqlite = { version = "0.30.0", features = ["trace", "functions", "collation", "bundled"] }
|
rusqlite = { version = "0.36.0", features = ["trace", "functions", "collation", "bundled"] }
|
||||||
rustls-pemfile = "2.2.0"
|
rustls-pemfile = "2.2.0"
|
||||||
scopeguard = "1.2.0"
|
scopeguard = "1.2.0"
|
||||||
serde = { version = "1.0.210", features = ["derive"] }
|
serde = { version = "1.0.219", features = ["derive"] }
|
||||||
serde-aux = "4.5.0"
|
serde-aux = "4.7.0"
|
||||||
serde_json = "1.0.132"
|
serde_json = "1.0.140"
|
||||||
serde_repr = "0.1.19"
|
serde_repr = "0.1.20"
|
||||||
serde_tuple = "0.5.0"
|
serde_tuple = "1.1.0"
|
||||||
sha1 = "0.10.6"
|
sha1 = "0.10.6"
|
||||||
sha2 = { version = "0.10.8" }
|
sha2 = { version = "0.10.9" }
|
||||||
simple-file-manifest = "0.11.0"
|
|
||||||
snafu = { version = "0.8.6", features = ["rust_1_61"] }
|
snafu = { version = "0.8.6", features = ["rust_1_61"] }
|
||||||
strum = { version = "0.26.3", features = ["derive"] }
|
strum = { version = "0.27.1", features = ["derive"] }
|
||||||
syn = { version = "2.0.82", features = ["parsing", "printing"] }
|
syn = { version = "2.0.103", features = ["parsing", "printing"] }
|
||||||
tar = "0.4.42"
|
tar = "0.4.44"
|
||||||
tempfile = "3.13.0"
|
tempfile = "3.20.0"
|
||||||
termcolor = "1.4.1"
|
termcolor = "1.4.1"
|
||||||
tokio = { version = "1.40", features = ["fs", "rt-multi-thread", "macros", "signal"] }
|
tokio = { version = "1.45", features = ["fs", "rt-multi-thread", "macros", "signal"] }
|
||||||
tokio-util = { version = "0.7.12", features = ["io"] }
|
tokio-util = { version = "0.7.15", features = ["io"] }
|
||||||
tower-http = { version = "0.5", features = ["trace"] }
|
tower-http = { version = "0.6.6", features = ["trace"] }
|
||||||
tracing = { version = "0.1.40", features = ["max_level_trace", "release_max_level_debug"] }
|
tracing = { version = "0.1.41", features = ["max_level_trace", "release_max_level_debug"] }
|
||||||
tracing-appender = "0.2.3"
|
tracing-appender = "0.2.3"
|
||||||
tracing-subscriber = { version = "0.3.18", features = ["fmt", "env-filter"] }
|
tracing-subscriber = { version = "0.3.19", features = ["fmt", "env-filter"] }
|
||||||
tugger-windows-codesign = "0.10.0"
|
unic-langid = { version = "0.9.6", features = ["macros"] }
|
||||||
unic-langid = { version = "0.9.5", features = ["macros"] }
|
|
||||||
unic-ucd-category = "0.9.0"
|
unic-ucd-category = "0.9.0"
|
||||||
unicode-normalization = "0.1.24"
|
unicode-normalization = "0.1.24"
|
||||||
walkdir = "2.5.0"
|
walkdir = "2.5.0"
|
||||||
which = "5.0.0"
|
which = "8.0.0"
|
||||||
winapi = { version = "0.3", features = ["wincon"] }
|
winapi = { version = "0.3", features = ["wincon"] }
|
||||||
wiremock = "0.6.2"
|
windows = { version = "0.61.3", features = ["Media_SpeechSynthesis", "Foundation_Collections", "Storage_Streams"] }
|
||||||
|
wiremock = "0.6.3"
|
||||||
xz2 = "0.1.7"
|
xz2 = "0.1.7"
|
||||||
zip = { version = "0.6.6", default-features = false, features = ["deflate", "time"] }
|
zip = { version = "4.1.0", default-features = false, features = ["deflate", "time"] }
|
||||||
zstd = { version = "0.13.2", features = ["zstdmt"] }
|
zstd = { version = "0.13.3", features = ["zstdmt"] }
|
||||||
|
|
||||||
# Apply mild optimizations to our dependencies in dev mode, which among other things
|
# Apply mild optimizations to our dependencies in dev mode, which among other things
|
||||||
# improves sha2 performance by about 21x. Opt 1 chosen due to
|
# improves sha2 performance by about 21x. Opt 1 chosen due to
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
// Copyright: Ankitects Pty Ltd and contributors
|
// Copyright: Ankitects Pty Ltd and contributors
|
||||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
use std::io::ErrorKind;
|
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
use anki_io::create_dir_all;
|
use anki_io::create_dir_all;
|
||||||
|
|
@ -44,7 +43,7 @@ fn split_env(s: &str) -> Result<(String, String), std::io::Error> {
|
||||||
if let Some((k, v)) = s.split_once('=') {
|
if let Some((k, v)) = s.split_once('=') {
|
||||||
Ok((k.into(), v.into()))
|
Ok((k.into(), v.into()))
|
||||||
} else {
|
} else {
|
||||||
Err(std::io::Error::new(ErrorKind::Other, "invalid env var"))
|
Err(std::io::Error::other("invalid env var"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -106,6 +106,5 @@ unicode-normalization.workspace = true
|
||||||
zip.workspace = true
|
zip.workspace = true
|
||||||
zstd.workspace = true
|
zstd.workspace = true
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies.windows]
|
[target.'cfg(windows)'.dependencies]
|
||||||
version = "0.56.0"
|
windows.workspace = true
|
||||||
features = ["Media_SpeechSynthesis", "Foundation_Collections", "Storage_Streams"]
|
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ impl CheckableUrl {
|
||||||
fn anchor(&self) -> Cow<str> {
|
fn anchor(&self) -> Cow<str> {
|
||||||
match *self {
|
match *self {
|
||||||
Self::HelpPage(page) => help_page_link_suffix(page).into(),
|
Self::HelpPage(page) => help_page_link_suffix(page).into(),
|
||||||
Self::String(s) => s.split('#').last().unwrap_or_default().into(),
|
Self::String(s) => s.split('#').next_back().unwrap_or_default().into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -146,8 +146,12 @@ pub(crate) fn export_collection(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn file_options_stored() -> FileOptions {
|
fn file_options_stored() -> FileOptions<'static, ()> {
|
||||||
FileOptions::default().compression_method(CompressionMethod::Stored)
|
FileOptions::<'static, ()>::default().compression_method(CompressionMethod::Stored)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn file_options_default() -> FileOptions<'static, ()> {
|
||||||
|
FileOptions::<'static, ()>::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_collection(
|
fn write_collection(
|
||||||
|
|
@ -160,7 +164,7 @@ fn write_collection(
|
||||||
zip.start_file(meta.collection_filename(), file_options_stored())?;
|
zip.start_file(meta.collection_filename(), file_options_stored())?;
|
||||||
zstd_copy(col, zip, size)?;
|
zstd_copy(col, zip, size)?;
|
||||||
} else {
|
} else {
|
||||||
zip.start_file(meta.collection_filename(), FileOptions::default())?;
|
zip.start_file(meta.collection_filename(), file_options_default())?;
|
||||||
io::copy(col, zip)?;
|
io::copy(col, zip)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ fn maybe_restore_media_file(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn restore_media_file(meta: &Meta, zip_file: &mut ZipFile, path: &Path) -> Result<()> {
|
fn restore_media_file(meta: &Meta, zip_file: &mut ZipFile<File>, path: &Path) -> Result<()> {
|
||||||
let mut tempfile = new_tempfile_in_parent_of(path)?;
|
let mut tempfile = new_tempfile_in_parent_of(path)?;
|
||||||
meta.copy(zip_file, &mut tempfile)
|
meta.copy(zip_file, &mut tempfile)
|
||||||
.with_context(|_| FileIoSnafu {
|
.with_context(|_| FileIoSnafu {
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,10 @@ impl SafeMediaEntry {
|
||||||
media_folder.join(&self.name)
|
media_folder.join(&self.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn fetch_file<'a>(&self, archive: &'a mut ZipArchive<File>) -> Result<ZipFile<'a>> {
|
pub(super) fn fetch_file<'a>(
|
||||||
|
&self,
|
||||||
|
archive: &'a mut ZipArchive<File>,
|
||||||
|
) -> Result<ZipFile<'a, File>> {
|
||||||
match archive.by_name(&self.index.to_string()) {
|
match archive.by_name(&self.index.to_string()) {
|
||||||
Ok(file) => Ok(file),
|
Ok(file) => Ok(file),
|
||||||
Err(err) => invalid_input!(err, "{} missing from archive", self.index),
|
Err(err) => invalid_input!(err, "{} missing from archive", self.index),
|
||||||
|
|
|
||||||
|
|
@ -352,7 +352,7 @@ impl Collection {
|
||||||
|
|
||||||
fn random_position(highest_position: u32) -> u32 {
|
fn random_position(highest_position: u32) -> u32 {
|
||||||
let mut rng = StdRng::seed_from_u64(highest_position as u64);
|
let mut rng = StdRng::seed_from_u64(highest_position as u64);
|
||||||
rng.gen_range(1..highest_position.max(1000))
|
rng.random_range(1..highest_position.max(1000))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ impl CardStateUpdater {
|
||||||
if secs >= upper_exclusive {
|
if secs >= upper_exclusive {
|
||||||
secs
|
secs
|
||||||
} else {
|
} else {
|
||||||
rng.gen_range(secs..upper_exclusive)
|
rng.random_range(secs..upper_exclusive)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
secs
|
secs
|
||||||
|
|
|
||||||
|
|
@ -630,7 +630,7 @@ fn get_fuzz_seed_for_id_and_reps(card_id: CardId, card_reps: u32) -> Option<u64>
|
||||||
/// Return a fuzz factor from the range `0.0..1.0`, using the provided seed.
|
/// Return a fuzz factor from the range `0.0..1.0`, using the provided seed.
|
||||||
/// None if seed is None.
|
/// None if seed is None.
|
||||||
fn get_fuzz_factor(seed: Option<u64>) -> Option<f32> {
|
fn get_fuzz_factor(seed: Option<u64>) -> Option<f32> {
|
||||||
seed.map(|s| StdRng::seed_from_u64(s).gen_range(0.0..1.0))
|
seed.map(|s| StdRng::seed_from_u64(s).random_range(0.0..1.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ pub(crate) fn apply_load_balance_and_easy_days(
|
||||||
sibling_modifier: 1.0,
|
sibling_modifier: 1.0,
|
||||||
easy_days_modifier: easy_days_modifier[interval_index],
|
easy_days_modifier: easy_days_modifier[interval_index],
|
||||||
});
|
});
|
||||||
let fuzz_seed = rng.gen();
|
let fuzz_seed = rng.random();
|
||||||
select_weighted_interval(intervals, Some(fuzz_seed)).unwrap() as f32
|
select_weighted_interval(intervals, Some(fuzz_seed)).unwrap() as f32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -106,7 +106,7 @@ fn create_review_priority_fn(
|
||||||
|
|
||||||
// Random ordering
|
// Random ordering
|
||||||
Random => {
|
Random => {
|
||||||
wrap!(move |_c, _w| rand::thread_rng().gen_range(0..deck_size) as i32)
|
wrap!(move |_c, _w| rand::rng().random_range(0..deck_size) as i32)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not implemented yet
|
// Not implemented yet
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,7 @@ fn nids_in_desired_order(cards: &[Card], order: NewCardDueOrder) -> Vec<NoteId>
|
||||||
nids.sort_unstable();
|
nids.sort_unstable();
|
||||||
}
|
}
|
||||||
NewCardDueOrder::Random => {
|
NewCardDueOrder::Random => {
|
||||||
nids.shuffle(&mut rand::thread_rng());
|
nids.shuffle(&mut rand::rng());
|
||||||
}
|
}
|
||||||
NewCardDueOrder::Preserve => unreachable!(),
|
NewCardDueOrder::Preserve => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::LazyLock;
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
use rand::distributions::Distribution;
|
use rand::distr::Distribution;
|
||||||
use rand::distributions::Uniform;
|
use rand::distr::Uniform;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
use super::answering::CardAnswer;
|
use super::answering::CardAnswer;
|
||||||
|
|
@ -114,8 +114,8 @@ impl Collection {
|
||||||
let spec = parse_due_date_str(days)?;
|
let spec = parse_due_date_str(days)?;
|
||||||
let usn = self.usn()?;
|
let usn = self.usn()?;
|
||||||
let today = self.timing_today()?.days_elapsed;
|
let today = self.timing_today()?.days_elapsed;
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::rng();
|
||||||
let distribution = Uniform::from(spec.min..=spec.max);
|
let distribution = Uniform::new_inclusive(spec.min, spec.max).unwrap();
|
||||||
let mut decks_initial_ease: HashMap<DeckId, f32> = HashMap::new();
|
let mut decks_initial_ease: HashMap<DeckId, f32> = HashMap::new();
|
||||||
self.transact(Op::SetDueDate, |col| {
|
self.transact(Op::SetDueDate, |col| {
|
||||||
for mut card in col.all_cards_for_ids(cids, false)? {
|
for mut card in col.all_cards_for_ids(cids, false)? {
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@ use std::collections::HashMap;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use chrono::Datelike;
|
use chrono::Datelike;
|
||||||
use rand::distributions::Distribution;
|
use rand::distr::weighted::WeightedIndex;
|
||||||
use rand::distributions::WeightedIndex;
|
use rand::distr::Distribution;
|
||||||
use rand::rngs::StdRng;
|
use rand::rngs::StdRng;
|
||||||
use rand::SeedableRng;
|
use rand::SeedableRng;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ use fsrs::FSRS5_DEFAULT_DECAY;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use rusqlite::functions::FunctionFlags;
|
use rusqlite::functions::FunctionFlags;
|
||||||
use rusqlite::params;
|
use rusqlite::params;
|
||||||
|
use rusqlite::trace::TraceEvent;
|
||||||
use rusqlite::Connection;
|
use rusqlite::Connection;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use unicase::UniCase;
|
use unicase::UniCase;
|
||||||
|
|
@ -47,10 +48,13 @@ pub struct SqliteStorage {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open_or_create_collection_db(path: &Path) -> Result<Connection> {
|
fn open_or_create_collection_db(path: &Path) -> Result<Connection> {
|
||||||
let mut db = Connection::open(path)?;
|
let db = Connection::open(path)?;
|
||||||
|
|
||||||
if std::env::var("TRACESQL").is_ok() {
|
if std::env::var("TRACESQL").is_ok() {
|
||||||
db.trace(Some(trace));
|
db.trace_v2(
|
||||||
|
rusqlite::trace::TraceEventCodes::SQLITE_TRACE_STMT,
|
||||||
|
Some(trace),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
db.busy_timeout(std::time::Duration::from_secs(0))?;
|
db.busy_timeout(std::time::Duration::from_secs(0))?;
|
||||||
|
|
@ -415,8 +419,10 @@ fn schema_version(db: &Connection) -> Result<(bool, u8)> {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trace(s: &str) {
|
fn trace(event: TraceEvent) {
|
||||||
println!("sql: {}", s.trim().replace('\n', " "));
|
if let TraceEvent::Stmt(_, sql) = event {
|
||||||
|
println!("sql: {}", sql.trim().replace('\n', " "));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SqliteStorage {
|
impl SqliteStorage {
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ use anki_io::create_dir_all;
|
||||||
use axum::extract::DefaultBodyLimit;
|
use axum::extract::DefaultBodyLimit;
|
||||||
use axum::routing::get;
|
use axum::routing::get;
|
||||||
use axum::Router;
|
use axum::Router;
|
||||||
use axum_client_ip::SecureClientIpSource;
|
use axum_client_ip::ClientIpSource;
|
||||||
use pbkdf2::password_hash::PasswordHash;
|
use pbkdf2::password_hash::PasswordHash;
|
||||||
use pbkdf2::password_hash::PasswordHasher;
|
use pbkdf2::password_hash::PasswordHasher;
|
||||||
use pbkdf2::password_hash::PasswordVerifier;
|
use pbkdf2::password_hash::PasswordVerifier;
|
||||||
|
|
@ -69,7 +69,7 @@ pub struct SyncServerConfig {
|
||||||
#[serde(default = "default_base", rename = "base")]
|
#[serde(default = "default_base", rename = "base")]
|
||||||
pub base_folder: PathBuf,
|
pub base_folder: PathBuf,
|
||||||
#[serde(default = "default_ip_header")]
|
#[serde(default = "default_ip_header")]
|
||||||
pub ip_header: SecureClientIpSource,
|
pub ip_header: ClientIpSource,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_host() -> IpAddr {
|
fn default_host() -> IpAddr {
|
||||||
|
|
@ -86,8 +86,8 @@ fn default_base() -> PathBuf {
|
||||||
.join(".syncserver")
|
.join(".syncserver")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn default_ip_header() -> SecureClientIpSource {
|
pub fn default_ip_header() -> ClientIpSource {
|
||||||
SecureClientIpSource::ConnectInfo
|
ClientIpSource::ConnectInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SimpleServerInner {
|
impl SimpleServerInner {
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ async fn sync_handler<P: SyncProtocol>(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn collection_sync_router<P: SyncProtocol + Clone>() -> Router<P> {
|
pub fn collection_sync_router<P: SyncProtocol + Clone>() -> Router<P> {
|
||||||
Router::new().route("/:method", post(sync_handler::<P>))
|
Router::new().route("/{method}", post(sync_handler::<P>))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The Rust code used to send a GET with query params, which was inconsistent
|
/// The Rust code used to send a GET with query params, which was inconsistent
|
||||||
|
|
@ -112,5 +112,5 @@ pub fn media_sync_router<P: MediaSyncProtocol + Clone>() -> Router<P> {
|
||||||
"/begin",
|
"/begin",
|
||||||
get(media_begin_get::<P>).post(media_begin_post::<P>),
|
get(media_begin_get::<P>).post(media_begin_post::<P>),
|
||||||
)
|
)
|
||||||
.route("/:method", post(media_sync_handler::<P>))
|
.route("/{method}", post(media_sync_handler::<P>))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -283,15 +283,20 @@ fn row_to_name_and_checksum(row: &Row) -> error::Result<(String, Sha1Hash)> {
|
||||||
Ok((file_name, sha1))
|
Ok((file_name, sha1))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trace(s: &str) {
|
fn trace(event: rusqlite::trace::TraceEvent) {
|
||||||
println!("sql: {}", s)
|
if let rusqlite::trace::TraceEvent::Stmt(_, sql) = event {
|
||||||
|
println!("sql: {}", sql);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn open_or_create<P: AsRef<Path>>(path: P) -> error::Result<Connection> {
|
pub(crate) fn open_or_create<P: AsRef<Path>>(path: P) -> error::Result<Connection> {
|
||||||
let mut db = Connection::open(path)?;
|
let mut db = Connection::open(path)?;
|
||||||
|
|
||||||
if std::env::var("TRACESQL").is_ok() {
|
if std::env::var("TRACESQL").is_ok() {
|
||||||
db.trace(Some(trace));
|
db.trace_v2(
|
||||||
|
rusqlite::trace::TraceEventCodes::SQLITE_TRACE_STMT,
|
||||||
|
Some(trace),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
db.pragma_update(None, "page_size", 4096)?;
|
db.pragma_update(None, "page_size", 4096)?;
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,8 @@ pub struct ZipFileMetadata {
|
||||||
/// The metadata is in a different format to the upload case, since deletions
|
/// The metadata is in a different format to the upload case, since deletions
|
||||||
/// don't need to be represented.
|
/// don't need to be represented.
|
||||||
pub fn zip_files_for_download(files: Vec<(String, Vec<u8>)>) -> Result<Vec<u8>> {
|
pub fn zip_files_for_download(files: Vec<(String, Vec<u8>)>) -> Result<Vec<u8>> {
|
||||||
let options = FileOptions::default().compression_method(zip::CompressionMethod::Stored);
|
let options: FileOptions<'_, ()> =
|
||||||
|
FileOptions::default().compression_method(zip::CompressionMethod::Stored);
|
||||||
let mut zip = ZipWriter::new(io::Cursor::new(vec![]));
|
let mut zip = ZipWriter::new(io::Cursor::new(vec![]));
|
||||||
let mut entries = HashMap::new();
|
let mut entries = HashMap::new();
|
||||||
|
|
||||||
|
|
@ -47,7 +48,8 @@ pub fn zip_files_for_download(files: Vec<(String, Vec<u8>)>) -> Result<Vec<u8>>
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn zip_files_for_upload(entries_: Vec<(String, Option<Vec<u8>>)>) -> Result<Vec<u8>> {
|
pub fn zip_files_for_upload(entries_: Vec<(String, Option<Vec<u8>>)>) -> Result<Vec<u8>> {
|
||||||
let options = FileOptions::default().compression_method(zip::CompressionMethod::Stored);
|
let options: FileOptions<'_, ()> =
|
||||||
|
FileOptions::default().compression_method(zip::CompressionMethod::Stored);
|
||||||
let mut zip = ZipWriter::new(io::Cursor::new(vec![]));
|
let mut zip = ZipWriter::new(io::Cursor::new(vec![]));
|
||||||
let mut entries = vec![];
|
let mut entries = vec![];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,13 @@ use std::marker::PhantomData;
|
||||||
use std::net::IpAddr;
|
use std::net::IpAddr;
|
||||||
use std::sync::LazyLock;
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
|
||||||
use axum::body::Body;
|
use axum::body::Body;
|
||||||
use axum::extract::FromRequest;
|
use axum::extract::FromRequest;
|
||||||
use axum::extract::Multipart;
|
use axum::extract::Multipart;
|
||||||
use axum::http::Request;
|
use axum::http::Request;
|
||||||
use axum::http::StatusCode;
|
use axum::http::StatusCode;
|
||||||
use axum::RequestPartsExt;
|
use axum::RequestPartsExt;
|
||||||
use axum_client_ip::SecureClientIp;
|
use axum_client_ip::ClientIp;
|
||||||
use axum_extra::TypedHeader;
|
use axum_extra::TypedHeader;
|
||||||
use header_and_stream::SyncHeader;
|
use header_and_stream::SyncHeader;
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
|
|
@ -101,19 +100,18 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
impl<S, T> FromRequest<S> for SyncRequest<T>
|
||||||
impl<S, T> FromRequest<S, Body> for SyncRequest<T>
|
|
||||||
where
|
where
|
||||||
S: Send + Sync,
|
S: Send + Sync,
|
||||||
T: DeserializeOwned,
|
T: DeserializeOwned,
|
||||||
{
|
{
|
||||||
type Rejection = HttpError;
|
type Rejection = HttpError;
|
||||||
|
|
||||||
async fn from_request(req: Request<Body>, state: &S) -> HttpResult<Self, Self::Rejection> {
|
async fn from_request(req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> {
|
||||||
let (mut parts, body) = req.into_parts();
|
let (mut parts, body) = req.into_parts();
|
||||||
|
|
||||||
let ip = parts
|
let ip = parts
|
||||||
.extract::<SecureClientIp>()
|
.extract::<ClientIp>()
|
||||||
.await
|
.await
|
||||||
.map_err(|_| {
|
.map_err(|_| {
|
||||||
HttpError::new_without_source(StatusCode::INTERNAL_SERVER_ERROR, "missing ip")
|
HttpError::new_without_source(StatusCode::INTERNAL_SERVER_ERROR, "missing ip")
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
[toolchain]
|
[toolchain]
|
||||||
# older versions may fail to compile; newer versions may fail the clippy tests
|
# older versions may fail to compile; newer versions may fail the clippy tests
|
||||||
channel = "1.85.0"
|
channel = "1.87.0"
|
||||||
|
|
|
||||||
|
|
@ -206,7 +206,7 @@ fn sveltekit_temp_file(path: &str) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_cargo_deny() -> Result<()> {
|
fn check_cargo_deny() -> Result<()> {
|
||||||
Command::run("cargo install cargo-deny@0.18.2")?;
|
Command::run("cargo install cargo-deny@0.18.3")?;
|
||||||
Command::run("cargo deny check")?;
|
Command::run("cargo deny check")?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue