1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
- use structopt::StructOpt;
- use std::io::prelude::*;
- use std::io;
- use std::fs::File;
- use std::path::{PathBuf, Path};
- use log::*;
- use indicatif::{ProgressBar, ProgressStyle};
- use sha1::Sha1;
- use anyhow::Result;
- use happylog::set_progress;
- use crate::db::{DbOpts, CopyRequest};
- use crate::tracking::{Stage, StageOpts};
- use crate::io::{HashWrite};
- use super::Command;
- const PB_STYLE: &'static str = "{prefix}: {elapsed_precise} {bar} {percent}% {bytes}/{total_bytes} (eta: {eta})";
- /// Concatenate one or more files with a progress bar
- #[derive(StructOpt, Debug)]
- #[structopt(name="pcat")]
- pub struct PCat {
- #[structopt(flatten)]
- dbo: DbOpts,
- #[structopt(flatten)]
- stage: StageOpts,
- /// Input file
- #[structopt(name = "FILE", parse(from_os_str))]
- infiles: Vec<PathBuf>,
- /// Destination table
- #[structopt(long="table", short="t")]
- table: Option<String>,
- /// Input format
- #[structopt(long="format", short="f")]
- format: Option<String>
- }
- /// Cat a file from input to output, hashing on the way.
- fn cat_file<'o, 'c, P: AsRef<Path>, W: Write>(stage: &mut Stage<'o, 'c>, inf: P, out: &mut W) -> Result<()> {
- let inf: &Path = inf.as_ref();
- let fstr = inf.to_string_lossy();
- info!("opening file {:?}", inf);
- let fs = File::open(inf)?;
- let pb = ProgressBar::new(fs.metadata().unwrap().len());
- pb.set_style(ProgressStyle::default_bar().template(PB_STYLE));
- pb.set_prefix(&fstr);
- let _pbs = set_progress(&pb);
- let mut sf = stage.source_file(inf);
- let read = sf.wrap_read(fs);
- let mut pbr = pb.wrap_read(read);
- io::copy(&mut pbr, out)?;
- drop(pbr);
- let hash = sf.record()?;
- write!(stage, "READ {:?} {}", inf, hash)?;
- Ok(())
- }
- impl Command for PCat {
- fn exec(self) -> Result<()> {
- match self.table {
- Some(ref t) => self.db_cat(t),
- None => self.raw_cat()
- }
- }
- }
- impl PCat {
- fn raw_cat(&self) -> Result<()> {
- let stdout = io::stdout();
- let mut out = stdout.lock();
- let mut stage = self.stage.empty();
- for inf in &self.infiles {
- cat_file(&mut stage, inf, &mut out)?;
- }
- Ok(())
- }
- fn db_cat(&self, table: &str) -> Result<()> {
- let db = self.dbo.open()?;
- let mut stage = self.stage.begin_stage(&db)?;
- let mut req = CopyRequest::new(&self.dbo, table)?.truncate(true);
- if let Some(ref fmt) = self.format {
- req = req.with_format(fmt);
- }
- info!("copying to table {}", table);
- writeln!(stage, "COPY TO {}", table)?;
- let out = req.open()?;
- let mut out_hash = Sha1::new();
- let mut out = HashWrite::create(out, &mut out_hash);
- for inf in &self.infiles {
- let inf = inf.as_path();
- cat_file(&mut stage, inf, &mut out)?;
- }
- drop(out);
- let hash = out_hash.hexdigest();
- stage.end(&Some(hash))?;
- Ok(())
- }
- }
|