Skip to content

Commit 5660801

Browse files
arglfiji-flo
andauthored
chore(redirects): fixup redirects across all locales (#46)
* add fix redirects command * Add fixing redirects to sync translated content * better help strings on CLI, comment on fix_redirect function --------- Co-authored-by: Florian Dieminger <[email protected]>
1 parent 661dbd2 commit 5660801

File tree

3 files changed

+76
-6
lines changed

3 files changed

+76
-6
lines changed

crates/rari-cli/main.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use rari_tools::add_redirect::add_redirect;
2525
use rari_tools::history::gather_history;
2626
use rari_tools::popularities::update_popularities;
2727
use rari_tools::r#move::r#move;
28+
use rari_tools::redirects::fix_redirects;
2829
use rari_tools::remove::remove;
2930
use rari_tools::sidebars::fmt_sidebars;
3031
use rari_tools::sync_translated_content::sync_translated_content;
@@ -65,6 +66,7 @@ enum Commands {
6566
Popularities,
6667
Update(UpdateArgs),
6768
ExportSchema(ExportSchemaArgs),
69+
/// Subcommands for altering content programmatically
6870
#[command(subcommand)]
6971
Content(ContentSubcommand),
7072
}
@@ -76,12 +78,23 @@ struct ExportSchemaArgs {
7678

7779
#[derive(Subcommand)]
7880
enum ContentSubcommand {
79-
/// Moves content from one slug to another
81+
/// Moves content pages from one slug to another.
8082
Move(MoveArgs),
83+
/// Deletes content pages.
8184
Delete(DeleteArgs),
85+
/// Adds a redirect from->to pair to the redirect map.
86+
///
87+
/// The locale is inferred from the from_url.
8288
AddRedirect(AddRedirectArgs),
89+
/// Syncs translated content for all or a list of locales.
8390
SyncTranslatedContent(SyncTranslatedContentArgs),
91+
/// Formats all sidebars.
8492
FmtSidebars,
93+
/// Fixes redirects across all locales.
94+
///
95+
/// This shortens multiple redirect chains to single ones.
96+
/// This is also run as part of sync_translated_content.
97+
FixRedirects,
8598
}
8699

87100
#[derive(Args)]
@@ -387,6 +400,9 @@ fn main() -> Result<(), Error> {
387400
ContentSubcommand::FmtSidebars => {
388401
fmt_sidebars()?;
389402
}
403+
ContentSubcommand::FixRedirects => {
404+
fix_redirects()?;
405+
}
390406
},
391407
Commands::Update(args) => update(args.version)?,
392408
Commands::ExportSchema(args) => export_schema(args)?,

crates/rari-tools/src/redirects.rs

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@ use url::Url;
1919
use crate::error::{RedirectError, ToolError};
2020

2121
const REDIRECT_FILE_HEADER: &str = r#"# DO NOT EDIT THIS FILE MANUALLY.
22-
# Use the CLI instead::
23-
#
24-
# rari content add-redirect <fromURL> <toURL>
22+
# Use the CLI instead.
2523
#
2624
# FROM-URL TO-URL
2725
"#;
@@ -242,6 +240,57 @@ pub fn add_redirects(locale: Locale, update_pairs: &[(String, String)]) -> Resul
242240
Ok(())
243241
}
244242

243+
/// Optimizes redirect rules based on all suported locales.
244+
///
245+
/// It loads all redirects into a singel structure and runs the short_cuts algorithm on it.
246+
/// The goal is to optimize redirects across locale boundaries.
247+
///
248+
/// This function overwrites all redirect files.
249+
///
250+
/// # Returns
251+
///
252+
/// - `Ok(())` if all operations complete successfully.
253+
/// - `Err(ToolError)` if any step fails, such as:
254+
/// - Invalid locale strings that cannot be parsed.
255+
/// - I/O errors during file reading or writing.
256+
/// - Errors from the `short_cuts` processing function.
257+
pub fn fix_redirects() -> Result<(), ToolError> {
258+
let locales = Locale::for_generic_and_spas();
259+
let mut pairs = HashMap::new();
260+
for locale in locales {
261+
let path = redirects_path(*locale)?;
262+
read_redirects_raw(&path, &mut pairs)?;
263+
}
264+
let clean_pairs: HashMap<String, String> = short_cuts(&pairs)?.into_iter().collect();
265+
266+
// Split the clean pairs into their respective locales
267+
let locale_pairs = clean_pairs.into_iter().try_fold(
268+
HashMap::<Locale, HashMap<String, String>>::new(),
269+
|mut acc, (from, to)| -> Result<HashMap<Locale, HashMap<String, String>>, ToolError> {
270+
// Extract the locale string from the 'from' path
271+
let locale_str = from.split('/').nth(1).unwrap_or_default();
272+
273+
// Parse the locale string into a Locale enum
274+
let locale = Locale::from_str(locale_str).map_err(|_| {
275+
ToolError::InvalidLocale(Cow::Owned(format!(
276+
"Cannot detect a valid locale for '{}'. Search for a '{}\t{}' pair in all _redirects.txt files to locate the problem.",
277+
from, from, to
278+
)))
279+
})?;
280+
let locale_map = acc.entry(locale).or_default();
281+
locale_map.insert(from, to);
282+
Ok(acc)
283+
},
284+
)?;
285+
286+
// Write the updated maps back to their redirects files
287+
for (locale, pairs) in &locale_pairs {
288+
let path = redirects_path(*locale)?;
289+
write_redirects(&path, pairs)?;
290+
}
291+
Ok(())
292+
}
293+
245294
/// Gets the path to the redirects file for a specific locale.
246295
pub(crate) fn redirects_path(locale: Locale) -> Result<PathBuf, ToolError> {
247296
let root = root_for_locale(locale)?;

crates/rari-tools/src/sync_translated_content.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use sha2::{Digest, Sha256};
1313

1414
use crate::error::ToolError;
1515
use crate::git::exec_git_with_test_fallback;
16-
use crate::redirects::add_redirects;
16+
use crate::redirects::{add_redirects, fix_redirects};
1717
use crate::utils::{get_redirects_map, read_all_doc_pages};
1818
use crate::wikihistory::update_wiki_history;
1919

@@ -31,11 +31,16 @@ pub fn sync_translated_content(
3131
println!(
3232
"{}",
3333
green.apply_to(format!(
34-
"Syncing translated content for locales: {:?}. Reading documents.",
34+
"Syncing translated content for locales: {:?}.\nFixing cross-locale redirects.",
3535
locales
3636
)),
3737
);
3838
}
39+
fix_redirects()?;
40+
41+
if verbose {
42+
println!("{}", green.apply_to("Reading all documents."));
43+
}
3944

4045
let docs = read_all_doc_pages()?;
4146
let redirects_maps: HashMap<Locale, HashMap<String, String>> = locales

0 commit comments

Comments
 (0)