…there really should be control over where to write them exactly
Showing the changes to gitoxide-core/src (1 of 10 files). Show all
Unified · Split
| @@ -1,9 +1,12 @@ | |||
| 1 | use crate::{remote::refs::JsonRef, OutputFormat, Protocol}; | 1 | use crate::{remote::refs::JsonRef, OutputFormat, Protocol}; |
| 2 | use git_features::progress::Progress; | 2 | use git_features::progress::Progress; |
| 3 | use git_object::owned; | 3 | use git_object::{bstr::ByteSlice, owned}; |
| 4 | use git_odb::pack; | 4 | use git_odb::pack; |
| 5 | use git_protocol::fetch::{Action, Arguments, Ref, Response}; | 5 | use git_protocol::fetch::{Action, Arguments, Ref, Response}; |
| 6 | use std::{io, io::BufRead, path::PathBuf}; | 6 | use std::{ |
| 7 | io::{self, BufRead}, | ||
| 8 | path::PathBuf, | ||
| 9 | }; | ||
| 7 | 10 | ||
| 8 | pub const PROGRESS_RANGE: std::ops::RangeInclusive<u8> = 1..=3; | 11 | pub const PROGRESS_RANGE: std::ops::RangeInclusive<u8> = 1..=3; |
| 9 | 12 | ||
| @@ -16,6 +19,7 @@ pub struct Context<W: io::Write> { · 6 unmodified lines | |||
| 16 | struct CloneDelegate<W: io::Write> { | 19 | struct CloneDelegate<W: io::Write> { |
| 17 | ctx: Context<W>, | 20 | ctx: Context<W>, |
| 18 | directory: Option<PathBuf>, | 21 | directory: Option<PathBuf>, |
| 22 | write_refs: bool, | ||
| 19 | } | 23 | } |
| 20 | 24 | ||
| 21 | impl<W: io::Write> git_protocol::fetch::Delegate for CloneDelegate<W> { | 25 | impl<W: io::Write> git_protocol::fetch::Delegate for CloneDelegate<W> { |
| @@ -43,8 +47,30 @@ impl<W: io::Write> git_protocol::fetch::Delegate for CloneDelegate<W> { · 21 unmodified lines | |||
| 43 | index_kind: pack::index::Kind::V2, | 47 | index_kind: pack::index::Kind::V2, |
| 44 | iteration_mode: pack::data::iter::Mode::Verify, | 48 | iteration_mode: pack::data::iter::Mode::Verify, |
| 45 | }; | 49 | }; |
| 46 | let outcome = pack::bundle::Bundle::write_stream_to_directory(input, self.directory.take(), progress, options) | 50 | let outcome = pack::bundle::Bundle::write_stream_to_directory(input, self.directory.clone(), progress, options) |
| 47 | .map_err(|err| io::Error::new(io::ErrorKind::Other, err))?; | 51 | .map_err(|err| io::Error::new(io::ErrorKind::Other, err))?; |
| 52 | |||
| 53 | if let Some(directory) = self.directory.take() { | ||
| 54 | let assure_dir = |path: &git_object::bstr::BString| { | ||
| 55 | assert!(!path.starts_with_str("/"), "no ref start with a /, they are relative"); | ||
| 56 | let path = directory.join(path.to_path_lossy()); | ||
| 57 | std::fs::create_dir_all(path.parent().expect("multi-component path")).map(|_| path) | ||
| 58 | }; | ||
| 59 | if self.write_refs { | ||
| 60 | for r in refs { | ||
| 61 | match r { | ||
| 62 | Ref::Symbolic { path, target, .. } => { | ||
| 63 | assure_dir(path).map(|path| (path, format!("ref: {}", target))) | ||
| 64 | } | ||
| 65 | Ref::Peeled { path, tag: object, .. } | Ref::Direct { path, object } => { | ||
| 66 | assure_dir(path).map(|path| (path, object.to_string())) | ||
| 67 | } | ||
| 68 | } | ||
| 69 | .and_then(|(path, content)| std::fs::write(path, content.as_bytes()))?; | ||
| 70 | } | ||
| 71 | } | ||
| 72 | } | ||
| 73 | |||
| 48 | match self.ctx.format { | 74 | match self.ctx.format { |
| 49 | OutputFormat::Human => drop(print(&mut self.ctx.out, outcome, refs)), | 75 | OutputFormat::Human => drop(print(&mut self.ctx.out, outcome, refs)), |
| 50 | #[cfg(feature = "serde1")] | 76 | #[cfg(feature = "serde1")] |
| @@ -118,6 +144,7 @@ pub fn receive<P, W: io::Write>( · 67 unmodified lines | |||
| 118 | protocol: Option<Protocol>, | 144 | protocol: Option<Protocol>, |
| 119 | url: &str, | 145 | url: &str, |
| 120 | directory: Option<PathBuf>, | 146 | directory: Option<PathBuf>, |
| 147 | write_refs: bool, | ||
| 121 | progress: P, | 148 | progress: P, |
| 122 | ctx: Context<W>, | 149 | ctx: Context<W>, |
| 123 | ) -> anyhow::Result<()> | 150 | ) -> anyhow::Result<()> |
| @@ -127,7 +154,11 @@ where · 3 unmodified lines | |||
| 127 | <<P as Progress>::SubProgress as Progress>::SubProgress: Send, | 154 | <<P as Progress>::SubProgress as Progress>::SubProgress: Send, |
| 128 | { | 155 | { |
| 129 | let transport = git_protocol::git_transport::client::connect(url.as_bytes(), protocol.unwrap_or_default().into())?; | 156 | let transport = git_protocol::git_transport::client::connect(url.as_bytes(), protocol.unwrap_or_default().into())?; |
| 130 | let mut delegate = CloneDelegate { ctx, directory }; | 157 | let mut delegate = CloneDelegate { |
| 158 | ctx, | ||
| 159 | directory, | ||
| 160 | write_refs, | ||
| 161 | }; | ||
| 131 | git_protocol::fetch(transport, &mut delegate, git_protocol::credentials::helper, progress)?; | 162 | git_protocol::fetch(transport, &mut delegate, git_protocol::credentials::helper, progress)?; |
| 132 | Ok(()) | 163 | Ok(()) |
| 133 | } | 164 | } |