OXYGENHUB

oxy git import says where it is 58dfe0e134eb

Every 500 commits the import reports the count, the merges so far and
the commit in hand (through the spinner, or a line on stderr with no
terminal), so an import of a whole large history is never silent and
one that dies under a memory cap says which commit it was on.
Repo::import_git_with takes the progress hook; import_git keeps its
signature.

refs #25
Author
Andy McCall @andymccall <[email protected]>
When
· 2026-10-04 03:41 UTC
Signature
✔ signed by Andy McCall
Hash
58dfe0e134eb09f139ae73e2dbb4d262907daf655e597ddc3e45eff7a37d13d4
Depends on
135212de5370 30ea9c1e70fa 75167672ebcd 79ab8528ff62 8f10a07a1dbe c3069537d7c5 fce44ae9ad29
Depended on by
d6e0d5b8b339 579afd107b9b ce118287d9da 810691ca6ce6 9935d490ddfb
In bookmarks
agents-in-readme bare-hashes carried-not-removed carry-identical doctor-trust identical-sides keyless-tags main merge-remote-bookmark only-help-103 paths-for-resolutions-and-amend push-notes show-stat subrepo-pin-state switch-says
In tags
v0.10.0 v0.11.0 v0.4.0 v0.4.1 v0.4.2 v0.4.3 v0.4.4 v0.4.5 v0.4.6 v0.5.0 v0.5.1 v0.6.0 v0.7.0 v0.8.0 v0.9.0
Edits
11 atoms, 0 tree operations, 2 files

Browse the tree at this change

modified crates/oxy-core/src/repo/git.rs +38 −3
…
297 unchanged lines
298 298
        {
299 299
            return fail(format!("{url} has no branch {branch:?}"));
300 300
        }
301 -
        self.import_git_commits(&mirror, branch, &format!("oxy git fetch {url} {branch}"))
301 +
        self.import_git_commits(
302 +
            &mirror,
303 +
            branch,
304 +
            &format!("oxy git fetch {url} {branch}"),
305 +
            &mut |_| {},
306 +
        )
302 307
    }
303 308
304 309
    /// Export the bookmark to `branch` of the Git repository at `url`
…
252 unchanged lines
557 562
    /// edits the difference between the union of its parents' states and its
558 563
    /// tree, so merge commits become resolutions. Submodules are skipped.
559 564
    pub fn import_git(&self, git_dir: &Path, branch: &str) -> Result<GitImportReport> {
565 +
        self.import_git_with(git_dir, branch, &mut |_| {})
566 +
    }
567 +
568 +
    /// `import_git`, telling `progress` where it is every few hundred
569 +
    /// commits: the count so far, the merges, and the commit in hand, so a
570 +
    /// long import is never silent and a run that dies says where.
571 +
    pub fn import_git_with(
572 +
        &self,
573 +
        git_dir: &Path,
574 +
        branch: &str,
575 +
        progress: crate::store::Progress<'_>,
576 +
    ) -> Result<GitImportReport> {
560 577
        if !self.bookmark_heads()?.is_empty() {
561 578
            return fail("git import needs an empty bookmark; import into a fresh repository");
562 579
        }
…
1 unchanged lines
564 581
            git_dir,
565 582
            branch,
566 583
            &format!("oxy git import {} {branch}", git_dir.display()),
584 +
            progress,
567 585
        )
568 586
    }
569 587
…
4 unchanged lines
574 592
        git_dir: &Path,
575 593
        branch: &str,
576 594
        command: &str,
595 +
        progress: crate::store::Progress<'_>,
577 596
    ) -> Result<GitImportReport> {
578 597
        let batch = self.store.begin_batch()?;
579 -
        let result = self.import_git_commits_batched(git_dir, branch, command);
598 +
        let result = self.import_git_commits_batched(git_dir, branch, command, progress);
580 599
        batch.finish()?;
581 600
        result
582 601
    }
…
3 unchanged lines
586 605
        git_dir: &Path,
587 606
        branch: &str,
588 607
        command: &str,
608 +
        progress: crate::store::Progress<'_>,
589 609
    ) -> Result<GitImportReport> {
590 610
        let commits = list_commits(git_dir, branch)?;
591 611
        let mut cat = CatFile::start(git_dir)?;
…
7 unchanged lines
599 619
        let mut blob_cache: HashMap<String, Vec<u8>> = HashMap::new();
600 620
        let mut cache_bytes: usize = 0;
601 621
602 -
        for gc in &commits {
622 +
        let total = commits.len();
623 +
        for (index, gc) in commits.iter().enumerate() {
603 624
            if known.imported.contains_key(&gc.sha) || known.exported.contains_key(&gc.sha) {
604 625
                continue;
626 +
            }
627 +
            if index % 500 == 0 {
628 +
                progress(&format!(
629 +
                    "{index} of {total} commits, {} merges; at {} {}",
630 +
                    report.merges,
631 +
                    &gc.sha[..12.min(gc.sha.len())],
632 +
                    gc.message
633 +
                        .lines()
634 +
                        .next()
635 +
                        .unwrap_or("")
636 +
                        .chars()
637 +
                        .take(60)
638 +
                        .collect::<String>()
639 +
                ));
605 640
            }
606 641
            // Base: union of every parent's state.
607 642
            let mut base = match (&gc.parents.first(), &last) {
…
324 unchanged lines
modified src/cli/sync.rs +1 −1
…
416 unchanged lines
417 417
    let repo = Repo::init(dest)?;
418 418
    let started = std::time::Instant::now();
419 419
    let sp = ui::spinner(&format!("Importing {} {branch}…", git_dir.display()));
420 -
    let r = repo.import_git(git_dir, branch)?;
420 +
    let r = repo.import_git_with(git_dir, branch, &mut |where_| sp.set(where_))?;
421 421
    sp.clear();
422 422
    println!(
423 423
        "{} {} ({} merges) from {} {} into {} {}",
…
198 unchanged lines