…and backport all capabilities like progress reporting and interruptability to something that's semantically similar.
Showing the changes to gitoxide-core/src (1 of 4 files). Show all
Unified · Split
| @@ -97,6 +97,7 @@ pub fn create<W>( · 96 unmodified lines | |||
| 97 | where | 97 | where |
| 98 | W: std::io::Write, | 98 | W: std::io::Write, |
| 99 | { | 99 | { |
| 100 | // TODO: review need for Arc for the counting part, use different kinds of Easy depending on need | ||
| 100 | let repo = Arc::new(git_repository::discover(repository_path)?); | 101 | let repo = Arc::new(git_repository::discover(repository_path)?); |
| 101 | progress.init(Some(2), progress::steps()); | 102 | progress.init(Some(2), progress::steps()); |
| 102 | let tips = tips.into_iter(); | 103 | let tips = tips.into_iter(); |
| @@ -108,6 +109,7 @@ where · 5 unmodified lines | |||
| 108 | let tips = tips | 109 | let tips = tips |
| 109 | .map(|tip| { | 110 | .map(|tip| { |
| 110 | ObjectId::from_hex(&Vec::from_os_str_lossy(tip.as_ref())).or_else({ | 111 | ObjectId::from_hex(&Vec::from_os_str_lossy(tip.as_ref())).or_else({ |
| 112 | // TODO: Use Easy when ready… | ||
| 111 | let packed = repo.refs.packed().ok().flatten(); | 113 | let packed = repo.refs.packed().ok().flatten(); |
| 112 | let refs = &repo.refs; | 114 | let refs = &repo.refs; |
| 113 | let repo = Arc::clone(&repo); | 115 | let repo = Arc::clone(&repo); |
| @@ -132,12 +134,13 @@ where · 18 unmodified lines | |||
| 132 | Err(_) => unreachable!("there is only one instance left here"), | 134 | Err(_) => unreachable!("there is only one instance left here"), |
| 133 | }; | 135 | }; |
| 134 | let iter = Box::new( | 136 | let iter = Box::new( |
| 137 | // TODO: Easy-based traversal | ||
| 135 | traverse::commit::Ancestors::new(tips, traverse::commit::ancestors::State::default(), { | 138 | traverse::commit::Ancestors::new(tips, traverse::commit::ancestors::State::default(), { |
| 136 | let db = Arc::clone(&db); | 139 | let db = Arc::clone(&db); |
| 137 | move |oid, buf| db.find_existing_commit_iter(oid, buf, &mut pack::cache::Never).ok() | 140 | move |oid, buf| db.find_existing_commit_iter(oid, buf, &mut pack::cache::Never).ok() |
| 138 | }) | 141 | }) |
| 139 | .inspect(move |_| progress.inc()) | 142 | .map(Result::unwrap) |
| 140 | .map(Result::unwrap), | 143 | .inspect(move |_| progress.inc()), |
| 141 | ); // todo: should there be a better way, maybe let input support Option or Result | 144 | ); // todo: should there be a better way, maybe let input support Option or Result |
| 142 | (db, iter) | 145 | (db, iter) |
| 143 | } | 146 | } |
| @@ -157,44 +160,34 @@ where · 13 unmodified lines | |||
| 157 | }; | 160 | }; |
| 158 | 161 | ||
| 159 | let mut stats = Statistics::default(); | 162 | let mut stats = Statistics::default(); |
| 160 | let chunk_size = 200; | 163 | let chunk_size = 1000; // What's a good value for this? |
| 161 | let start = Instant::now(); | ||
| 162 | let counts = { | 164 | let counts = { |
| 163 | let mut progress = progress.add_child("counting"); | 165 | let mut progress = progress.add_child("counting"); |
| 164 | progress.init(None, progress::count("objects")); | 166 | progress.init(None, progress::count("objects")); |
| 165 | let mut interruptible_counts_iter = interrupt::Iter::new( | 167 | let (mut counts, count_stats) = pack::data::output::count::objects( |
| 166 | pack::data::output::count::iter_from_objects( | 168 | Arc::clone(&db), |
| 167 | Arc::clone(&db), | 169 | move || { |
| 168 | move || { | 170 | if nondeterministic_count { |
| 169 | if nondeterministic_count { | 171 | Box::new(pack::cache::lru::StaticLinkedList::<64>::default()) as Box<dyn DecodeEntry> |
| 170 | Box::new(pack::cache::lru::StaticLinkedList::<64>::default()) as Box<dyn DecodeEntry> | 172 | } else { |
| 171 | } else { | 173 | Box::new(pack::cache::lru::MemoryCappedHashmap::new(400 * 1024 * 1024)) as Box<dyn DecodeEntry> |
| 172 | Box::new(pack::cache::lru::MemoryCappedHashmap::new(400 * 1024 * 1024)) as Box<dyn DecodeEntry> | 174 | // todo: Make that configurable |
| 173 | // todo: Make that configurable | 175 | } |
| 174 | } | 176 | }, |
| 175 | }, | 177 | input, |
| 176 | input, | 178 | progress::ThroughputOnDrop::new(progress), |
| 177 | progress.add_child("threads"), | 179 | &interrupt::IS_INTERRUPTED, |
| 178 | pack::data::output::count::iter_from_objects::Options { | 180 | pack::data::output::count::iter_from_objects::Options { |
| 179 | thread_limit: if nondeterministic_count || matches!(expansion, ObjectExpansion::None) { | 181 | thread_limit: if nondeterministic_count || matches!(expansion, ObjectExpansion::None) { |
| 180 | thread_limit | 182 | thread_limit |
| 181 | } else { | 183 | } else { |
| 182 | Some(1) | 184 | Some(1) |
| 183 | }, | ||
| 184 | chunk_size, | ||
| 185 | input_object_expansion: expansion.into(), | ||
| 186 | }, | 185 | }, |
| 187 | ), | 186 | chunk_size, |
| 188 | make_cancellation_err, | 187 | input_object_expansion: expansion.into(), |
| 189 | ); | 188 | }, |
| 190 | let mut counts = Vec::new(); | 189 | )?; |
| 191 | for c in interruptible_counts_iter.by_ref() { | 190 | stats.counts = count_stats; |
| 192 | let c = c??; | ||
| 193 | progress.inc_by(c.len()); | ||
| 194 | counts.extend(c.into_iter()); | ||
| 195 | } | ||
| 196 | stats.counts = interruptible_counts_iter.into_inner().finalize()?; | ||
| 197 | progress.show_throughput(start); | ||
| 198 | counts.shrink_to_fit(); | 191 | counts.shrink_to_fit(); |
| 199 | counts | 192 | counts |
| 200 | }; | 193 | }; |