Skip to content

Commit

Permalink
Add "bundle serve" command
Browse files Browse the repository at this point in the history
  • Loading branch information
let-def committed May 23, 2024
1 parent 71494b2 commit e552a9d
Showing 1 changed file with 74 additions and 0 deletions.
74 changes: 74 additions & 0 deletions src/bin/tectonic/v2cli/commands/bundle.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use clap::{Parser, Subcommand};
use std::io::Write;
use tectonic::{
config::PersistentConfig,
docmodel::{DocumentExt, DocumentSetupOptions},
errors::Result,
io::{InputFeatures, OpenResult},
tt_note,
};
use tectonic_bundles::Bundle;
Expand Down Expand Up @@ -60,20 +62,26 @@ enum BundleCommands {
#[command(name = "search")]
/// Filter the list of filenames contained in the bundle
Search(BundleSearchCommand),

#[command(name = "serve")]
/// Dump the contents of files requested on standard input
Serve(BundleServeCommand),
}

impl TectonicCommand for BundleCommand {
fn customize(&self, cc: &mut CommandCustomizations) {
match &self.command {
BundleCommands::Cat(c) => c.customize(cc),
BundleCommands::Search(c) => c.customize(cc),
BundleCommands::Serve(c) => c.customize(cc),
}
}

fn execute(self, config: PersistentConfig, status: &mut dyn StatusBackend) -> Result<i32> {
match self.command {
BundleCommands::Cat(c) => c.execute(config, status),
BundleCommands::Search(c) => c.execute(config, status),
BundleCommands::Serve(c) => c.execute(config, status),
}
}
}
Expand Down Expand Up @@ -138,3 +146,69 @@ impl BundleSearchCommand {
Ok(0)
}
}

#[derive(Debug, Eq, PartialEq, Parser)]
struct BundleServeCommand {
/// Use only resource files cached locally
#[arg(short = 'C', long)]
only_cached: bool,
}

impl BundleServeCommand {
fn customize(&self, cc: &mut CommandCustomizations) {
cc.always_stderr = true;
}

fn execute(self, config: PersistentConfig, status: &mut dyn StatusBackend) -> Result<i32> {
let mut bundle = get_a_bundle(config, self.only_cached, status)?;
let mut filename = String::new();
let stdin = std::io::stdin();
let mut stdout = std::io::stdout();
loop {
stdout.flush()?;
filename.clear();
match stdin.read_line(&mut filename) {
| Err(error) => {
eprintln!("error: {error}");
return Ok(1);
}
| Ok(0) => return Ok(0),
| Ok(_) => {
let name = filename.trim_end();
let error = match bundle.input_path(name, status) {
OpenResult::Err(e) => e,
OpenResult::Ok(path) => {
let mut path = path.as_os_str().as_encoded_bytes();
let size = path.len() as u64;
stdout.write_all(&[b'P'])?;
stdout.write_all(&size.to_le_bytes())?;
let copied = std::io::copy(&mut path, &mut stdout)?;
assert!(size == copied);
continue
},
OpenResult::NotAvailable => {
match bundle.input_open_name(name, status).must_exist() {
Ok(mut t) => {
let size = t.get_size()? as u64;
stdout.write_all(&[b'C'])?;
stdout.write_all(&size.to_le_bytes())?;
let copied = std::io::copy(&mut t, &mut stdout)?;
assert!(size == copied);
continue
}
Err(e) => e
}
}
};
let text = error.to_string();
let bytes = text.as_bytes();
let size = bytes.len() as u64;
stdout.write_all(&[b'E'])?;
stdout.write_all(&size.to_le_bytes())?;
stdout.write_all(&bytes)?;
}
};
stdout.flush().unwrap();
}
}
}

0 comments on commit e552a9d

Please sign in to comment.