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