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
12101210 "rayon",
12111211 "serde",
12121212 "serde_json",
1213+ "tempfile",
12131214 ]
12141215
12151216 [[package]]
git-pack/src/data/output/bytes.rs+10−0
@@ -22,6 +22,8 @@ pub struct FromEntriesIter<I, W> { · 21 unmodified lines
2222 pub input: I,
2323 /// A way of writing encoded bytes.
2424 output: hash::Write<W>,
25+ /// Our trailing hash when done writing all input entries
26+ trailer: Option<git_hash::ObjectId>,
2527 /// The amount of objects in the iteration and the version of the packfile to be written.
2628 /// Will be `None` to signal the header was written already.
2729 header_info: Option<(crate::data::Version, u32)>,
@@ -62,6 +64,7 @@ where · 34 unmodified lines
6264 FromEntriesIter {
6365 input,
6466 output: hash::Write::new(output, hash_kind),
67+ trailer: None,
6568 entry_version: version,
6669 header_info: Some((version, num_entries)),
6770 is_done: false,
@@ -75,6 +78,12 @@ where · 7 unmodified lines
7578 self.output.inner
7679 }
7780
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+
7887 fn next_inner(&mut self) -> Result<u64, Error<E>> {
7988 let mut written = 0u64;
8089 if let Some((version, num_entries)) = self.header_info.take() {
@@ -98,6 +107,7 @@ where · 17 unmodified lines
98107 written += digest.len() as u64;
99108 self.output.flush()?;
100109 self.is_done = true;
110+ self.trailer = Some(git_hash::ObjectId::from(digest));
101111 }
102112 };
103113 Ok(written)
gitoxide-core/Cargo.toml+1−0
@@ -36,6 +36,7 @@ anyhow = "1.0.31" · 35 unmodified lines
3636 quick-error = "2.0.0"
3737 bytesize = "1.0.1"
3838 serde_json = { version = "1.0.56", optional = true }
39+tempfile = "3.1.0"
3940
4041 # for async-client
4142 async-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
7474 repository: impl AsRef<Path>,
7575 tips: impl IntoIterator<Item = impl AsRef<OsStr>>,
7676 input: Option<impl io::BufRead + Send + 'static>,
77− out: impl io::Write,
77+ output_directory: impl AsRef<Path>,
7878 mut progress: impl Progress,
7979 ctx: Context,
8080 ) -> anyhow::Result<()> {
@@ -154,25 +154,27 @@ pub fn create( · 73 unmodified lines
154154 write_progress.init(None, progress::bytes());
155155 let start = Instant::now();
156156
157+ let mut pack_file = tempfile::NamedTempFile::new_in(&output_directory)?;
157158 let mut output_iter = pack::data::output::bytes::FromEntriesIter::new(
158159 entries.inspect(|e| {
159160 if let Ok(entries) = e {
160161 entries_progress.inc_by(entries.len())
161162 }
162163 }),
163− out,
164+ &mut pack_file,
164165 num_objects as u32,
165166 pack::data::Version::default(),
166167 hash::Kind::default(),
167168 );
168− while let Some(io_res) = output_iter.next() {
169+ for io_res in output_iter.by_ref() {
169170 if interrupt::is_triggered() {
170171 bail!("Cancelled by user")
171172 }
172173 let written = io_res?;
173174 write_progress.inc_by(written as usize);
174175 }
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)))?;
176178
177179 write_progress.show_throughput(start);
178180 entries_progress.show_throughput(start);
src/plumbing/lean/main.rs+2−7
@@ -22,15 +22,10 @@ pub fn main() -> Result<()> { · 21 unmodified lines
2222 repository,
2323 expansion,
2424 tips,
25+ output_directory,
2526 }) => {
2627 let (_handle, progress) = prepare(verbose, "pack-create", Some(core::pack::create::PROGRESS_RANGE));
2728 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− }
3429 let input = if has_tips {
3530 None
3631 } else {
@@ -51,7 +46,7 @@ pub fn main() -> Result<()> { · 14 unmodified lines
5146 repository.unwrap_or_else(|| PathBuf::from(".")),
5247 tips,
5348 input,
54− stdout_lock,
49+ output_directory,
5550 DoOrDiscard::from(progress),
5651 core::pack::create::Context {
5752 expansion,
src/plumbing/lean/options.rs+4−0
@@ -176,6 +176,10 @@ pub struct PackCreate { · 175 unmodified lines
176176 /// Possible values are "none" and "tree-traversal". Default is "none".
177177 pub expansion: Option<core::pack::create::ObjectExpansion>,
178178
179+ /// the directory into which to write the pack file.
180+ #[argh(option, short = 'o')]
181+ pub output_directory: PathBuf,
182+
179183 /// the tips from which to start the commit graph iteration.
180184 ///
181185 /// 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
2828 repository,
2929 expansion,
3030 tips,
31+ output_directory,
3132 } => {
3233 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− }
4134 prepare_and_run(
4235 "pack-create",
4336 verbose,
4437 progress,
4538 progress_keep_open,
4639 core::pack::create::PROGRESS_RANGE,
47− move |progress, out, err| {
40+ move |progress, _out, _err| {
4841 let input = if has_tips {
4942 None
5043 } else {
@@ -67,11 +60,7 @@ pub fn main() -> Result<()> { · 16 unmodified lines
6760 }),
6861 };
6962 let progress = git_features::progress::DoOrDiscard::from(progress);
70− if has_tui {
71− core::pack::create(repository, tips, input, err, progress, context)
72− } else {
73− core::pack::create(repository, tips, input, out, progress, context)
74− }
63+ core::pack::create(repository, tips, input, output_directory, progress, context)
7564 },
7665 )
7766 }
src/plumbing/pretty/options.rs+4−0
@@ -56,6 +56,10 @@ pub enum Subcommands { · 55 unmodified lines
5656 /// Possible values are "none" and "tree-traversal". Default is "none".
5757 expansion: Option<core::pack::create::ObjectExpansion>,
5858
59+ /// The directory into which to write the pack file.
60+ #[clap(long, short = 'o')]
61+ output_directory: PathBuf,
62+
5963 /// the tips from which to start the commit graph iteration.
6064 ///
6165 /// If empty, we expect to read objects on stdin and default to 'none' as expansion mode.