History

[pack] write packs to a directory with the proper name

Sebastian Thiel committed 5 years ago

Commit 3fbca7d1 parent f10adea8 files · +31 −25Browse files

Unified · Split

8 files
  1. Cargo.lock +1 −0
  2. git-pack/src/data/output/bytes.rs +10 −0
  3. gitoxide-core/Cargo.toml +1 −0
  4. gitoxide-core/src/pack/create.rs +6 −4
  5. src/plumbing/lean/main.rs +2 −7
  6. src/plumbing/lean/options.rs +4 −0
  7. src/plumbing/pretty/main.rs +3 −14
  8. src/plumbing/pretty/options.rs +4 −0
Cargo.lock+1−0
@@ -1210,6 +1210,7 @@ dependencies = [ · 1209 unmodified lines
1210 "rayon",1210 "rayon",
1211 "serde",1211 "serde",
1212 "serde_json",1212 "serde_json",
1213 "tempfile",
1213]1214]
1214 1215
1215[[package]]1216[[package]]
git-pack/src/data/output/bytes.rs+10−0
@@ -22,6 +22,8 @@ pub struct FromEntriesIter<I, W> { · 21 unmodified lines
22 pub input: I,22 pub input: I,
23 /// A way of writing encoded bytes.23 /// A way of writing encoded bytes.
24 output: hash::Write<W>,24 output: hash::Write<W>,
25 /// Our trailing hash when done writing all input entries
26 trailer: Option<git_hash::ObjectId>,
25 /// The amount of objects in the iteration and the version of the packfile to be written.27 /// The amount of objects in the iteration and the version of the packfile to be written.
26 /// Will be `None` to signal the header was written already.28 /// Will be `None` to signal the header was written already.
27 header_info: Option<(crate::data::Version, u32)>,29 header_info: Option<(crate::data::Version, u32)>,
@@ -62,6 +64,7 @@ where · 34 unmodified lines
62 FromEntriesIter {64 FromEntriesIter {
63 input,65 input,
64 output: hash::Write::new(output, hash_kind),66 output: hash::Write::new(output, hash_kind),
67 trailer: None,
65 entry_version: version,68 entry_version: version,
66 header_info: Some((version, num_entries)),69 header_info: Some((version, num_entries)),
67 is_done: false,70 is_done: false,
@@ -75,6 +78,12 @@ where · 7 unmodified lines
75 self.output.inner78 self.output.inner
76 }79 }
77 80
81 /// Returns the trailing hash over all written entries once done.
82 /// It's `None` if we are not yet done writing.
83 pub fn digest(&self) -> Option<git_hash::ObjectId> {
84 self.trailer.clone()
85 }
86
78 fn next_inner(&mut self) -> Result<u64, Error<E>> {87 fn next_inner(&mut self) -> Result<u64, Error<E>> {
79 let mut written = 0u64;88 let mut written = 0u64;
80 if let Some((version, num_entries)) = self.header_info.take() {89 if let Some((version, num_entries)) = self.header_info.take() {
@@ -98,6 +107,7 @@ where · 17 unmodified lines
98 written += digest.len() as u64;107 written += digest.len() as u64;
99 self.output.flush()?;108 self.output.flush()?;
100 self.is_done = true;109 self.is_done = true;
110 self.trailer = Some(git_hash::ObjectId::from(digest));
101 }111 }
102 };112 };
103 Ok(written)113 Ok(written)
gitoxide-core/Cargo.toml+1−0
@@ -36,6 +36,7 @@ anyhow = "1.0.31" · 35 unmodified lines
36quick-error = "2.0.0"36quick-error = "2.0.0"
37bytesize = "1.0.1"37bytesize = "1.0.1"
38serde_json = { version = "1.0.56", optional = true }38serde_json = { version = "1.0.56", optional = true }
39tempfile = "3.1.0"
39 40
40# for async-client41# for async-client
41async-trait = { version = "0.1.50", optional = true }42async-trait = { version = "0.1.50", optional = true }
gitoxide-core/src/pack/create.rs+6−4
@@ -74,7 +74,7 @@ pub fn create( · 73 unmodified lines
74 repository: impl AsRef<Path>,74 repository: impl AsRef<Path>,
75 tips: impl IntoIterator<Item = impl AsRef<OsStr>>,75 tips: impl IntoIterator<Item = impl AsRef<OsStr>>,
76 input: Option<impl io::BufRead + Send + 'static>,76 input: Option<impl io::BufRead + Send + 'static>,
77 out: impl io::Write,77 output_directory: impl AsRef<Path>,
78 mut progress: impl Progress,78 mut progress: impl Progress,
79 ctx: Context,79 ctx: Context,
80) -> anyhow::Result<()> {80) -> anyhow::Result<()> {
@@ -154,25 +154,27 @@ pub fn create( · 73 unmodified lines
154 write_progress.init(None, progress::bytes());154 write_progress.init(None, progress::bytes());
155 let start = Instant::now();155 let start = Instant::now();
156 156
157 let mut pack_file = tempfile::NamedTempFile::new_in(&output_directory)?;
157 let mut output_iter = pack::data::output::bytes::FromEntriesIter::new(158 let mut output_iter = pack::data::output::bytes::FromEntriesIter::new(
158 entries.inspect(|e| {159 entries.inspect(|e| {
159 if let Ok(entries) = e {160 if let Ok(entries) = e {
160 entries_progress.inc_by(entries.len())161 entries_progress.inc_by(entries.len())
161 }162 }
162 }),163 }),
163 out,164 &mut pack_file,
164 num_objects as u32,165 num_objects as u32,
165 pack::data::Version::default(),166 pack::data::Version::default(),
166 hash::Kind::default(),167 hash::Kind::default(),
167 );168 );
168 while let Some(io_res) = output_iter.next() {169 for io_res in output_iter.by_ref() {
169 if interrupt::is_triggered() {170 if interrupt::is_triggered() {
170 bail!("Cancelled by user")171 bail!("Cancelled by user")
171 }172 }
172 let written = io_res?;173 let written = io_res?;
173 write_progress.inc_by(written as usize);174 write_progress.inc_by(written as usize);
174 }175 }
175 output_iter.into_write().flush()?;176 let hash = output_iter.digest().expect("iteration is done");
177 pack_file.persist(output_directory.as_ref().join(format!("{}.pack", hash)))?;
176 178
177 write_progress.show_throughput(start);179 write_progress.show_throughput(start);
178 entries_progress.show_throughput(start);180 entries_progress.show_throughput(start);
src/plumbing/lean/main.rs+2−7
@@ -22,15 +22,10 @@ pub fn main() -> Result<()> { · 21 unmodified lines
22 repository,22 repository,
23 expansion,23 expansion,
24 tips,24 tips,
25 output_directory,
25 }) => {26 }) => {
26 let (_handle, progress) = prepare(verbose, "pack-create", Some(core::pack::create::PROGRESS_RANGE));27 let (_handle, progress) = prepare(verbose, "pack-create", Some(core::pack::create::PROGRESS_RANGE));
27 let has_tips = !tips.is_empty();28 let has_tips = !tips.is_empty();
28 let stdout = stdout();
29 let stdout_lock = stdout.lock();
30 #[cfg(feature = "atty")]
31 if atty::is(atty::Stream::Stdout) {
32 anyhow::bail!("Refusing to output pack data stream to stdout.")
33 }
34 let input = if has_tips {29 let input = if has_tips {
35 None30 None
36 } else {31 } else {
@@ -51,7 +46,7 @@ pub fn main() -> Result<()> { · 14 unmodified lines
51 repository.unwrap_or_else(|| PathBuf::from(".")),46 repository.unwrap_or_else(|| PathBuf::from(".")),
52 tips,47 tips,
53 input,48 input,
54 stdout_lock,49 output_directory,
55 DoOrDiscard::from(progress),50 DoOrDiscard::from(progress),
56 core::pack::create::Context {51 core::pack::create::Context {
57 expansion,52 expansion,
src/plumbing/lean/options.rs+4−0
@@ -176,6 +176,10 @@ pub struct PackCreate { · 175 unmodified lines
176 /// Possible values are "none" and "tree-traversal". Default is "none".176 /// Possible values are "none" and "tree-traversal". Default is "none".
177 pub expansion: Option<core::pack::create::ObjectExpansion>,177 pub expansion: Option<core::pack::create::ObjectExpansion>,
178 178
179 /// the directory into which to write the pack file.
180 #[argh(option, short = 'o')]
181 pub output_directory: PathBuf,
182
179 /// the tips from which to start the commit graph iteration.183 /// the tips from which to start the commit graph iteration.
180 ///184 ///
181 /// If empty, we expect to read objects on stdin and default to 'none' as expansion mode.185 /// If empty, we expect to read objects on stdin and default to 'none' as expansion mode.
src/plumbing/pretty/main.rs+3−14
@@ -28,23 +28,16 @@ pub fn main() -> Result<()> { · 27 unmodified lines
28 repository,28 repository,
29 expansion,29 expansion,
30 tips,30 tips,
31 output_directory,
31 } => {32 } => {
32 let has_tips = !tips.is_empty();33 let has_tips = !tips.is_empty();
33 let has_tui = progress;
34 if atty::is(if has_tui {
35 atty::Stream::Stderr
36 } else {
37 atty::Stream::Stdout
38 }) {
39 anyhow::bail!("Refusing to output pack data stream to stderr.")
40 }
41 prepare_and_run(34 prepare_and_run(
42 "pack-create",35 "pack-create",
43 verbose,36 verbose,
44 progress,37 progress,
45 progress_keep_open,38 progress_keep_open,
46 core::pack::create::PROGRESS_RANGE,39 core::pack::create::PROGRESS_RANGE,
47 move |progress, out, err| {40 move |progress, _out, _err| {
48 let input = if has_tips {41 let input = if has_tips {
49 None42 None
50 } else {43 } else {
@@ -67,11 +60,7 @@ pub fn main() -> Result<()> { · 16 unmodified lines
67 }),60 }),
68 };61 };
69 let progress = git_features::progress::DoOrDiscard::from(progress);62 let progress = git_features::progress::DoOrDiscard::from(progress);
70 if has_tui {63 core::pack::create(repository, tips, input, output_directory, progress, context)
71 core::pack::create(repository, tips, input, err, progress, context)
72 } else {
73 core::pack::create(repository, tips, input, out, progress, context)
74 }
75 },64 },
76 )65 )
77 }66 }
src/plumbing/pretty/options.rs+4−0
@@ -56,6 +56,10 @@ pub enum Subcommands { · 55 unmodified lines
56 /// Possible values are "none" and "tree-traversal". Default is "none".56 /// Possible values are "none" and "tree-traversal". Default is "none".
57 expansion: Option<core::pack::create::ObjectExpansion>,57 expansion: Option<core::pack::create::ObjectExpansion>,
58 58
59 /// The directory into which to write the pack file.
60 #[clap(long, short = 'o')]
61 output_directory: PathBuf,
62
59 /// the tips from which to start the commit graph iteration.63 /// the tips from which to start the commit graph iteration.
60 ///64 ///
61 /// If empty, we expect to read objects on stdin and default to 'none' as expansion mode.65 /// If empty, we expect to read objects on stdin and default to 'none' as expansion mode.