mirror of
https://github.com/thegeneralist01/archivr
synced 2026-10-09 12:55:00 +02:00
Merge branch 'sol-ytdlp' into integration-all-three
This commit is contained in:
commit
fce3bb147e
4 changed files with 72 additions and 10 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -100,6 +100,7 @@ dependencies = [
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"rusqlite",
|
"rusqlite",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"tempfile",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
||||||
|
|
@ -16,3 +16,6 @@ regex.workspace = true
|
||||||
rusqlite.workspace = true
|
rusqlite.workspace = true
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
reqwest.workspace = true
|
reqwest.workspace = true
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
tempfile.workspace = true
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use archivr_core::{
|
||||||
archive,
|
archive,
|
||||||
capture::CaptureConfig,
|
capture::CaptureConfig,
|
||||||
downloader::ytdlp::{
|
downloader::ytdlp::{
|
||||||
pinned_yt_dlp, probe_version, resolve_yt_dlp, state_dir, state_dir_yt_dlp,
|
forced_yt_dlp, pinned_yt_dlp, probe_version, resolve_yt_dlp, state_dir, state_dir_yt_dlp,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
|
|
@ -147,22 +147,32 @@ fn yt_dlp_state_dir() -> Result<PathBuf> {
|
||||||
.context("could not determine a state directory (is $HOME set?)")
|
.context("could not determine a state directory (is $HOME set?)")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Renders one `status` row. Missing candidates show an em dash.
|
/// Formats one `status` row. Missing candidates show an em dash.
|
||||||
fn status_row(role: &str, path: Option<&Path>, chosen: &Path) {
|
fn format_status_row(role: &str, path: Option<&Path>, chosen: &Path) -> String {
|
||||||
match path {
|
match path {
|
||||||
Some(p) => {
|
Some(p) => {
|
||||||
let version = probe_version(p).unwrap_or_else(|| "—".to_string());
|
let version = probe_version(p).unwrap_or_else(|| "—".to_string());
|
||||||
let star = if p == chosen { "*" } else { "" };
|
let star = if p == chosen { "*" } else { "" };
|
||||||
println!("{role}\t{}\t{version}\t{star}", p.display());
|
format!("{role}\t{}\t{version}\t{star}", p.display())
|
||||||
}
|
}
|
||||||
None => println!("{role}\t—\t—\t"),
|
None => format!("{role}\t—\t—\t"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Prints one `status` row. Missing candidates show an em dash.
|
||||||
|
fn status_row(role: &str, path: Option<&Path>, chosen: &Path) {
|
||||||
|
println!("{}", format_status_row(role, path, chosen));
|
||||||
|
}
|
||||||
|
|
||||||
fn yt_dlp_status() -> Result<()> {
|
fn yt_dlp_status() -> Result<()> {
|
||||||
let chosen = resolve_yt_dlp();
|
let chosen = resolve_yt_dlp();
|
||||||
|
|
||||||
println!("role\tpath\tversion\tchosen");
|
println!("role\tpath\tversion\tchosen");
|
||||||
|
status_row(
|
||||||
|
"force (ARCHIVR_YT_DLP_FORCE)",
|
||||||
|
forced_yt_dlp().as_deref(),
|
||||||
|
&chosen,
|
||||||
|
);
|
||||||
status_row("env (ARCHIVR_YT_DLP)", pinned_yt_dlp().as_deref(), &chosen);
|
status_row("env (ARCHIVR_YT_DLP)", pinned_yt_dlp().as_deref(), &chosen);
|
||||||
|
|
||||||
// Show the state-dir slot even when empty, so users can see where an
|
// Show the state-dir slot even when empty, so users can see where an
|
||||||
|
|
@ -289,3 +299,48 @@ fn yt_dlp_update(requested_version: Option<&str>) -> Result<()> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::format_status_row;
|
||||||
|
use archivr_core::downloader::ytdlp::{
|
||||||
|
forced_yt_dlp, resolve_yt_dlp_uncached, YT_DLP_FORCE_ENV,
|
||||||
|
};
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
fn fake_yt_dlp(path: &Path, version: &str) {
|
||||||
|
std::fs::create_dir_all(path.parent().unwrap()).unwrap();
|
||||||
|
std::fs::write(path, format!("#!/bin/sh\necho {version}\n")).unwrap();
|
||||||
|
#[cfg(unix)]
|
||||||
|
{
|
||||||
|
use std::os::unix::fs::PermissionsExt;
|
||||||
|
std::fs::set_permissions(path, std::fs::Permissions::from_mode(0o755)).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn forced_candidate_is_rendered_and_selected() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let forced = tmp.path().join("forced/yt-dlp");
|
||||||
|
fake_yt_dlp(&forced, "2020.01.01");
|
||||||
|
unsafe { std::env::set_var(YT_DLP_FORCE_ENV, &forced) };
|
||||||
|
|
||||||
|
let candidate = forced_yt_dlp();
|
||||||
|
assert_eq!(candidate.as_deref(), Some(forced.as_path()));
|
||||||
|
let chosen = resolve_yt_dlp_uncached();
|
||||||
|
assert_eq!(chosen, forced);
|
||||||
|
assert_eq!(
|
||||||
|
format_status_row(
|
||||||
|
"force (ARCHIVR_YT_DLP_FORCE)",
|
||||||
|
candidate.as_deref(),
|
||||||
|
&chosen,
|
||||||
|
),
|
||||||
|
format!(
|
||||||
|
"force (ARCHIVR_YT_DLP_FORCE)\t{}\t2020.01.01\t*",
|
||||||
|
forced.display()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
unsafe { std::env::remove_var(YT_DLP_FORCE_ENV) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,12 @@ pub fn state_dir_yt_dlp() -> Option<PathBuf> {
|
||||||
state_dir().map(|d| d.join("yt-dlp").join("yt-dlp"))
|
state_dir().map(|d| d.join("yt-dlp").join("yt-dlp"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The explicit yt-dlp override, if it points to a file on disk.
|
||||||
|
pub fn forced_yt_dlp() -> Option<PathBuf> {
|
||||||
|
let p = PathBuf::from(env::var_os(YT_DLP_FORCE_ENV).filter(|v| !v.is_empty())?);
|
||||||
|
p.is_file().then_some(p)
|
||||||
|
}
|
||||||
|
|
||||||
/// The nix-pinned yt-dlp advertised via `ARCHIVR_YT_DLP`, if it exists on disk.
|
/// The nix-pinned yt-dlp advertised via `ARCHIVR_YT_DLP`, if it exists on disk.
|
||||||
pub fn pinned_yt_dlp() -> Option<PathBuf> {
|
pub fn pinned_yt_dlp() -> Option<PathBuf> {
|
||||||
let p = PathBuf::from(env::var_os(YT_DLP_ENV).filter(|v| !v.is_empty())?);
|
let p = PathBuf::from(env::var_os(YT_DLP_ENV).filter(|v| !v.is_empty())?);
|
||||||
|
|
@ -90,12 +96,9 @@ pub fn yt_dlp_candidates() -> Vec<(&'static str, PathBuf)> {
|
||||||
/// Priority: `ARCHIVR_YT_DLP_FORCE` > newest of (pinned, state-dir) by version
|
/// Priority: `ARCHIVR_YT_DLP_FORCE` > newest of (pinned, state-dir) by version
|
||||||
/// string > bare `yt-dlp` (PATH lookup, the historical behaviour).
|
/// string > bare `yt-dlp` (PATH lookup, the historical behaviour).
|
||||||
pub fn resolve_yt_dlp_uncached() -> PathBuf {
|
pub fn resolve_yt_dlp_uncached() -> PathBuf {
|
||||||
if let Some(forced) = env::var_os(YT_DLP_FORCE_ENV).filter(|v| !v.is_empty()) {
|
if let Some(forced) = forced_yt_dlp() {
|
||||||
let forced = PathBuf::from(forced);
|
|
||||||
if forced.is_file() {
|
|
||||||
return forced;
|
return forced;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
yt_dlp_candidates()
|
yt_dlp_candidates()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue