diff options
Diffstat (limited to 'src/bin/git_remote_nostr')
| -rw-r--r-- | src/bin/git_remote_nostr/fetch.rs | 132 | ||||
| -rw-r--r-- | src/bin/git_remote_nostr/list.rs | 50 |
2 files changed, 87 insertions, 95 deletions
diff --git a/src/bin/git_remote_nostr/fetch.rs b/src/bin/git_remote_nostr/fetch.rs index b74e432..1b19347 100644 --- a/src/bin/git_remote_nostr/fetch.rs +++ b/src/bin/git_remote_nostr/fetch.rs | |||
| @@ -187,81 +187,83 @@ fn fetch_from_git_server_url( | |||
| 187 | let mut fetch_options = git2::FetchOptions::new(); | 187 | let mut fetch_options = git2::FetchOptions::new(); |
| 188 | let mut remote_callbacks = git2::RemoteCallbacks::new(); | 188 | let mut remote_callbacks = git2::RemoteCallbacks::new(); |
| 189 | remote_callbacks.sideband_progress(|data| { | 189 | remote_callbacks.sideband_progress(|data| { |
| 190 | let _ = term.clear_last_lines(1); | 190 | if let Ok(data) = str::from_utf8(data) { |
| 191 | let _ = term.write_line(format!("remote: {}", str::from_utf8(data).unwrap()).as_str()); | 191 | let data = data |
| 192 | true | 192 | .split(['\n', '\r']) |
| 193 | }); | 193 | .find(|line| !line.is_empty()) |
| 194 | remote_callbacks.transfer_progress(|stats| { | 194 | .unwrap_or(""); |
| 195 | let _ = term.clear_last_lines(1); | 195 | if !data.is_empty() { |
| 196 | if stats.received_objects() == stats.total_objects() { | 196 | let s = format!("remote: {data}"); |
| 197 | let _ = term.write_line( | 197 | let _ = term.clear_last_lines(1); |
| 198 | format!( | 198 | let _ = term.write_line(s.as_str()); |
| 199 | "Resolving deltas {}/{}\r", | 199 | if !s.contains('%') || s.contains("100%") { |
| 200 | stats.indexed_deltas(), | 200 | // print it twice so the next sideband_progress doesn't delete it |
| 201 | stats.total_deltas() | 201 | let _ = term.write_line(s.as_str()); |
| 202 | ) | 202 | } |
| 203 | .as_str(), | 203 | } |
| 204 | ); | ||
| 205 | } else if stats.total_objects() > 0 { | ||
| 206 | let _ = term.write_line( | ||
| 207 | format!( | ||
| 208 | "Received {}/{} objects ({}) in {} bytes\r", | ||
| 209 | stats.received_objects(), | ||
| 210 | stats.total_objects(), | ||
| 211 | stats.indexed_objects(), | ||
| 212 | stats.received_bytes() | ||
| 213 | ) | ||
| 214 | .as_str(), | ||
| 215 | ); | ||
| 216 | } | 204 | } |
| 217 | true | 205 | true |
| 218 | }); | 206 | }); |
| 207 | remote_callbacks.transfer_progress( | ||
| 208 | #[allow(clippy::cast_precision_loss)] | ||
| 209 | |stats| { | ||
| 210 | let _ = term.clear_last_lines(1); | ||
| 211 | report_on_transfer_progress(&stats, term, false); | ||
| 212 | true | ||
| 213 | }, | ||
| 214 | ); | ||
| 215 | |||
| 219 | if !dont_authenticate { | 216 | if !dont_authenticate { |
| 220 | remote_callbacks.credentials(auth.credentials(&git_config)); | 217 | remote_callbacks.credentials(auth.credentials(&git_config)); |
| 221 | } | 218 | } |
| 222 | fetch_options.remote_callbacks(remote_callbacks); | 219 | fetch_options.remote_callbacks(remote_callbacks); |
| 220 | term.write_line("")?; | ||
| 223 | git_server_remote.download(oids, Some(&mut fetch_options))?; | 221 | git_server_remote.download(oids, Some(&mut fetch_options))?; |
| 224 | { | 222 | |
| 225 | let stats = git_server_remote.stats(); | 223 | report_on_transfer_progress(&git_server_remote.stats(), term, true); |
| 226 | if stats.local_objects() > 0 { | 224 | |
| 227 | term.write_line( | ||
| 228 | format!( | ||
| 229 | "\rReceived {}/{} objects in {} bytes (used {} local \ | ||
| 230 | objects)", | ||
| 231 | stats.indexed_objects(), | ||
| 232 | stats.total_objects(), | ||
| 233 | stats.received_bytes(), | ||
| 234 | stats.local_objects() | ||
| 235 | ) | ||
| 236 | .as_str(), | ||
| 237 | )?; | ||
| 238 | } else { | ||
| 239 | term.write_line( | ||
| 240 | format!( | ||
| 241 | "\rReceived {}/{} objects in {} bytes", | ||
| 242 | stats.indexed_objects(), | ||
| 243 | stats.total_objects(), | ||
| 244 | stats.received_bytes() | ||
| 245 | ) | ||
| 246 | .as_str(), | ||
| 247 | )?; | ||
| 248 | } | ||
| 249 | } | ||
| 250 | git_server_remote.disconnect()?; | 225 | git_server_remote.disconnect()?; |
| 251 | Ok(()) | 226 | Ok(()) |
| 252 | } | 227 | } |
| 253 | 228 | ||
| 254 | fn fetch_from_git_server_url_unauthenticated( | 229 | #[allow(clippy::cast_precision_loss)] |
| 255 | git_repo: &Repository, | 230 | #[allow(clippy::float_cmp)] |
| 256 | oids: &[String], | 231 | fn report_on_transfer_progress(stats: &git2::Progress<'_>, term: &console::Term, complete: bool) { |
| 257 | git_server_url: &str, | 232 | let total = stats.total_objects() as f64; |
| 258 | ) -> Result<()> { | 233 | if total == 0.0 { |
| 259 | let mut git_server_remote = git_repo.remote_anonymous(git_server_url)?; | 234 | return; |
| 260 | let mut fetch_options = git2::FetchOptions::new(); | 235 | } |
| 261 | let remote_callbacks = git2::RemoteCallbacks::new(); | 236 | let received = stats.received_objects() as f64; |
| 262 | // TODO status update callback | 237 | let percentage = (received / total) * 100.0; |
| 263 | fetch_options.remote_callbacks(remote_callbacks); | 238 | |
| 264 | git_server_remote.download(oids, Some(&mut fetch_options))?; | 239 | // Get the total received bytes |
| 265 | git_server_remote.disconnect()?; | 240 | let received_bytes = stats.received_bytes() as f64; |
| 266 | Ok(()) | 241 | |
| 242 | // Determine whether to use KiB or MiB | ||
| 243 | let (size, unit) = if received_bytes >= (1024.0 * 1024.0) { | ||
| 244 | // Convert to MiB | ||
| 245 | (received_bytes / (1024.0 * 1024.0), "MiB") | ||
| 246 | } else { | ||
| 247 | // Convert to KiB | ||
| 248 | (received_bytes / 1024.0, "KiB") | ||
| 249 | }; | ||
| 250 | |||
| 251 | // Format the output for receiving objects | ||
| 252 | if received < total || complete { | ||
| 253 | let _ = term.write_line( | ||
| 254 | format!( | ||
| 255 | "Receiving objects: {percentage:.0}% ({received}/{total}) {size:.2} {unit}, done.\r" | ||
| 256 | ) | ||
| 257 | .as_str(), | ||
| 258 | ); | ||
| 259 | } | ||
| 260 | if received == total || complete { | ||
| 261 | let indexed_deltas = stats.indexed_deltas() as f64; | ||
| 262 | let total_deltas = stats.total_deltas() as f64; | ||
| 263 | let percentage = (indexed_deltas / total_deltas) * 100.0; | ||
| 264 | let _ = term.write_line( | ||
| 265 | format!("Resolving deltas: {percentage:.0}% ({indexed_deltas}/{total_deltas}) done.\r") | ||
| 266 | .as_str(), | ||
| 267 | ); | ||
| 268 | } | ||
| 267 | } | 269 | } |
diff --git a/src/bin/git_remote_nostr/list.rs b/src/bin/git_remote_nostr/list.rs index d3682ec..7dded6b 100644 --- a/src/bin/git_remote_nostr/list.rs +++ b/src/bin/git_remote_nostr/list.rs | |||
| @@ -164,19 +164,25 @@ pub fn list_from_remote( | |||
| 164 | 164 | ||
| 165 | for protocol in &protocols_to_attempt { | 165 | for protocol in &protocols_to_attempt { |
| 166 | term.write_line( | 166 | term.write_line( |
| 167 | format!("fetching {} ref list over {protocol}...", server_url.short_name(),).as_str(), | 167 | format!( |
| 168 | "fetching {} ref list over {protocol}...", | ||
| 169 | server_url.short_name(), | ||
| 170 | ) | ||
| 171 | .as_str(), | ||
| 168 | )?; | 172 | )?; |
| 169 | 173 | ||
| 170 | let formatted_url = server_url.format_as(protocol, &decoded_nostr_url.user)?; | 174 | let formatted_url = server_url.format_as(protocol, &decoded_nostr_url.user)?; |
| 171 | let res = if [ServerProtocol::UnauthHttps, ServerProtocol::UnauthHttp].contains(protocol) { | 175 | let res = list_from_remote_url( |
| 172 | list_from_remote_url_unauthenticated(git_repo, &formatted_url) | 176 | git_repo, |
| 173 | } else { | 177 | &formatted_url, |
| 174 | list_from_remote_url(git_repo, &formatted_url) | 178 | [ServerProtocol::UnauthHttps, ServerProtocol::UnauthHttp].contains(protocol), |
| 175 | }; | 179 | term, |
| 180 | ); | ||
| 176 | 181 | ||
| 177 | match res { | 182 | match res { |
| 178 | Ok(state) => { | 183 | Ok(state) => { |
| 179 | remote_state = Some(state); | 184 | remote_state = Some(state); |
| 185 | term.clear_last_lines(1)?; | ||
| 180 | if !failed_protocols.is_empty() { | 186 | if !failed_protocols.is_empty() { |
| 181 | term.write_line( | 187 | term.write_line( |
| 182 | format!( | 188 | format!( |
| @@ -189,6 +195,7 @@ pub fn list_from_remote( | |||
| 189 | break; | 195 | break; |
| 190 | } | 196 | } |
| 191 | Err(error) => { | 197 | Err(error) => { |
| 198 | term.clear_last_lines(1)?; | ||
| 192 | term.write_line( | 199 | term.write_line( |
| 193 | format!("list: {formatted_url} failed over {protocol}: {error}").as_str(), | 200 | format!("list: {formatted_url} failed over {protocol}: {error}").as_str(), |
| 194 | )?; | 201 | )?; |
| @@ -201,7 +208,6 @@ pub fn list_from_remote( | |||
| 201 | } | 208 | } |
| 202 | } | 209 | } |
| 203 | } | 210 | } |
| 204 | term.clear_last_lines(1)?; | ||
| 205 | } | 211 | } |
| 206 | if let Some(remote_state) = remote_state { | 212 | if let Some(remote_state) = remote_state { |
| 207 | Ok(remote_state) | 213 | Ok(remote_state) |
| @@ -221,31 +227,11 @@ pub fn list_from_remote( | |||
| 221 | } | 227 | } |
| 222 | } | 228 | } |
| 223 | 229 | ||
| 224 | fn list_from_remote_url_unauthenticated( | ||
| 225 | git_repo: &Repo, | ||
| 226 | git_server_remote_url: &str, | ||
| 227 | ) -> Result<HashMap<String, String>> { | ||
| 228 | let mut git_server_remote = git_repo.git_repo.remote_anonymous(git_server_remote_url)?; | ||
| 229 | let remote_callbacks = git2::RemoteCallbacks::new(); | ||
| 230 | git_server_remote.connect_auth(git2::Direction::Fetch, Some(remote_callbacks), None)?; | ||
| 231 | let mut state = HashMap::new(); | ||
| 232 | for head in git_server_remote.list()? { | ||
| 233 | if let Some(symbolic_reference) = head.symref_target() { | ||
| 234 | state.insert( | ||
| 235 | head.name().to_string(), | ||
| 236 | format!("ref: {symbolic_reference}"), | ||
| 237 | ); | ||
| 238 | } else { | ||
| 239 | state.insert(head.name().to_string(), head.oid().to_string()); | ||
| 240 | } | ||
| 241 | } | ||
| 242 | git_server_remote.disconnect()?; | ||
| 243 | Ok(state) | ||
| 244 | } | ||
| 245 | |||
| 246 | fn list_from_remote_url( | 230 | fn list_from_remote_url( |
| 247 | git_repo: &Repo, | 231 | git_repo: &Repo, |
| 248 | git_server_remote_url: &str, | 232 | git_server_remote_url: &str, |
| 233 | dont_authenticate: bool, | ||
| 234 | term: &console::Term, | ||
| 249 | ) -> Result<HashMap<String, String>> { | 235 | ) -> Result<HashMap<String, String>> { |
| 250 | let git_config = git_repo.git_repo.config()?; | 236 | let git_config = git_repo.git_repo.config()?; |
| 251 | 237 | ||
| @@ -253,8 +239,12 @@ fn list_from_remote_url( | |||
| 253 | // authentication may be required | 239 | // authentication may be required |
| 254 | let auth = GitAuthenticator::default(); | 240 | let auth = GitAuthenticator::default(); |
| 255 | let mut remote_callbacks = git2::RemoteCallbacks::new(); | 241 | let mut remote_callbacks = git2::RemoteCallbacks::new(); |
| 256 | remote_callbacks.credentials(auth.credentials(&git_config)); | 242 | if !dont_authenticate { |
| 243 | remote_callbacks.credentials(auth.credentials(&git_config)); | ||
| 244 | } | ||
| 245 | term.write_line("list: connecting...")?; | ||
| 257 | git_server_remote.connect_auth(git2::Direction::Fetch, Some(remote_callbacks), None)?; | 246 | git_server_remote.connect_auth(git2::Direction::Fetch, Some(remote_callbacks), None)?; |
| 247 | term.clear_last_lines(1)?; | ||
| 258 | let mut state = HashMap::new(); | 248 | let mut state = HashMap::new(); |
| 259 | for head in git_server_remote.list()? { | 249 | for head in git_server_remote.list()? { |
| 260 | if let Some(symbolic_reference) = head.symref_target() { | 250 | if let Some(symbolic_reference) = head.symref_target() { |