use crate::common::database::PathData;
use crate::common::fastresume::Fastresume;
use crate::config::Config;
use crate::db::query;
use rusqlite::{named_params, Connection};
use std::error::Error;
#[derive(Debug)]
pub struct SavePath {
pub old_unix: String,
pub new_unix: String,
pub old: String,
pub new: String,
pub separator: String,
}
pub fn change_save_path(
db: &Connection,
save_path: &SavePath,
config: &Config,
) -> Result<(), Box<dyn Error>> {
println!(
"Save path: replacing {} with {}",
save_path.old, save_path.new
);
let all_torrents = query::fetch_all_torrents::<PathData>(
db,
"
SELECT id, torrent_id, target_save_path, libtorrent_resume_data
FROM torrents
",
)?;
let mut num_torrents_updated = 0;
for torrent in all_torrents {
let mut trigger_update = false;
let bencoded_resume_data = torrent.libtorrent_resume_data.as_slice();
let mut resume_data: Fastresume = serde_bencode::from_bytes(bencoded_resume_data)?;
let resume_data_save_path = String::from_utf8(resume_data.save_path)?;
if resume_data_save_path.contains(&save_path.old) {
trigger_update = true;
}
let mut target_save_path: Option<String> = None;
if torrent.target_save_path.is_some() {
target_save_path = Some(
torrent
.target_save_path
.unwrap()
.replace(&save_path.old_unix, &save_path.new_unix),
);
}
if save_path.separator == *"\\" {
resume_data.save_path = resume_data_save_path
.replace(&save_path.old, &save_path.new)
.replace('/', &save_path.separator)
.into();
} else {
resume_data.save_path = resume_data_save_path
.replace(&save_path.old, &save_path.new)
.replace('\\', &save_path.separator)
.into();
}
if trigger_update {
let mut update_stmt = db.prepare(
"
UPDATE torrents
SET target_save_path = :tsp, libtorrent_resume_data = :lrd
WHERE id = :id
RETURNING torrent_id;
",
)?;
update_stmt.query_row(
named_params! {":tsp": target_save_path, ":lrd": serde_bencode::to_bytes(&resume_data)?, ":id": torrent.id},
|row| {
let updated_row_id = row.get::<usize, String>(0)?;
if config.verbose {
println!("Save path: updated save path for {}", updated_row_id);
println!("{}: new target_save_path is '{:?}'", updated_row_id, target_save_path);
println!("{}: new libtorrent_resume_data path is {:?}", updated_row_id, String::from_utf8(resume_data.save_path).unwrap());
}
num_torrents_updated +=1;
Ok(())
}
)?;
}
}
match num_torrents_updated {
0 => println!("Save path: no torrents were updated"),
1 => println!("Save path: 1 torrent was updated"),
_ => println!("Save path: {} torrents were updated", num_torrents_updated),
}
Ok(())
}