asyncgit/
remote_progress.rs1use crate::{
4 error::Result,
5 progress::ProgressPercent,
6 sync::remotes::push::{AsyncProgress, ProgressNotification},
7 AsyncGitNotification,
8};
9use crossbeam_channel::{Receiver, Sender};
10use git2::PackBuilderStage;
11use std::{
12 sync::{Arc, Mutex},
13 thread::{self, JoinHandle},
14};
15
16#[derive(Clone, Debug)]
18pub enum RemoteProgressState {
19 PackingAddingObject,
21 PackingDeltafiction,
23 Pushing,
25 Transfer,
27 Done,
29}
30
31#[derive(Clone, Debug)]
33pub struct RemoteProgress {
34 pub state: RemoteProgressState,
36 pub progress: ProgressPercent,
38}
39
40impl RemoteProgress {
41 pub fn new(
43 state: RemoteProgressState,
44 current: usize,
45 total: usize,
46 ) -> Self {
47 Self {
48 state,
49 progress: ProgressPercent::new(current, total),
50 }
51 }
52
53 pub const fn get_progress_percent(&self) -> u8 {
55 self.progress.progress
56 }
57
58 pub(crate) fn set_progress<T>(
59 progress: &Arc<Mutex<Option<T>>>,
60 state: Option<T>,
61 ) -> Result<()> {
62 let mut progress = progress.lock()?;
63
64 *progress = state;
65
66 Ok(())
67 }
68
69 pub(crate) fn spawn_receiver_thread<
71 T: 'static + AsyncProgress,
72 >(
73 notification_type: AsyncGitNotification,
74 sender: Sender<AsyncGitNotification>,
75 receiver: Receiver<T>,
76 progress: Arc<Mutex<Option<T>>>,
77 ) -> JoinHandle<()> {
78 thread::spawn(move || loop {
79 let incoming = receiver.recv();
80 match incoming {
81 Ok(update) => {
82 Self::set_progress(
83 &progress,
84 Some(update.clone()),
85 )
86 .expect("set progress failed");
87 sender
88 .send(notification_type)
89 .expect("Notification error");
90
91 thread::yield_now();
92
93 if update.is_done() {
94 break;
95 }
96 }
97 Err(e) => {
98 log::error!(
99 "remote progress receiver error: {e}",
100 );
101 break;
102 }
103 }
104 })
105 }
106}
107
108impl From<ProgressNotification> for RemoteProgress {
109 fn from(progress: ProgressNotification) -> Self {
110 match progress {
111 ProgressNotification::Packing {
112 stage,
113 current,
114 total,
115 } => match stage {
116 PackBuilderStage::AddingObjects => Self::new(
117 RemoteProgressState::PackingAddingObject,
118 current,
119 total,
120 ),
121 PackBuilderStage::Deltafication => Self::new(
122 RemoteProgressState::PackingDeltafiction,
123 current,
124 total,
125 ),
126 },
127 ProgressNotification::PushTransfer {
128 current,
129 total,
130 ..
131 } => Self::new(
132 RemoteProgressState::Pushing,
133 current,
134 total,
135 ),
136 ProgressNotification::Transfer {
137 objects,
138 total_objects,
139 ..
140 } => Self::new(
141 RemoteProgressState::Transfer,
142 objects,
143 total_objects,
144 ),
145 _ => Self::new(RemoteProgressState::Done, 1, 1),
146 }
147 }
148}