OXYGENHUB

A carried switch no longer says carried files were removed 44f1ebe7aa5b

After a switch that carried the working copy's changes, oxy printed
'removed from disk (the bookmark does not have them)' for new files that
were still there: the checkout takes them off and the carry writes them
back, but the report still counted them. It now leaves carried files out
of what was removed, and the switch names what it carried.

Closes #120
Author
Andy McCall @andymccall <[email protected]>
via
agent agent:claude@andymccall <[email protected]> · keyless, under your grant for changes,refs,seal · key 9bd48baaa42d
When
· 2026-10-18 16:21 UTC
Signature
◈ sealed by agent:claude@andymccall
Hash
44f1ebe7aa5b73866f02f4194eb0d41266d4d7f4d47486b63ba9c78f7e1f58ae
Depends on
1a3b62032ed9 61e3bce7ea5b 7b9809e67c3d 982864068a59 9b723f69b032 d4dbab97e948 fce44ae9ad29
Depended on by
4afe288b7946
In bookmarks
carried-not-removed doctor-trust identical-sides keyless-tags main paths-for-resolutions-and-amend push-notes subrepo-pin-state
In tags
v0.10.0 v0.11.0 v0.5.0 v0.5.1 v0.6.0 v0.7.0 v0.8.0 v0.9.0
Edits
8 atoms, 0 tree operations, 3 files

Browse the tree at this change

modified crates/oxy-core/src/repo/bookmarks.rs +14 −1
…
552 unchanged lines
553 553
            };
554 554
            carried.push((p.clone(), item));
555 555
        }
556 -
        let report = self.checkout_keeping(heads, true, command, &keep)?;
556 +
        let mut report = self.checkout_keeping(heads, true, command, &keep)?;
557 557
        for (p, item) in &carried {
558 558
            match item {
559 559
                Carried::Symlink(target) => self.write_symlink(p, target)?,
…
4 unchanged lines
564 564
                Carried::Subrepo => {}
565 565
            }
566 566
        }
567 +
        // What was carried is on disk, not removed (oxygen#120): a new file
568 +
        // the target lacks is taken off by the checkout and written back, so
569 +
        // the report names only what is really gone.
570 +
        let back: BTreeSet<&str> = carried
571 +
            .iter()
572 +
            .filter(|(p, item)| {
573 +
                matches!(item, Carried::File(..) | Carried::Symlink(_))
574 +
                    && !target_state.files.contains_key(p)
575 +
            })
576 +
            .map(|(p, _)| p.as_str())
577 +
            .collect();
578 +
        report.removed = report.removed.saturating_sub(back.len());
579 +
        report.removed_paths.retain(|p| !back.contains(p.as_str()));
567 580
        self.drop_manifest();
568 581
        self.snapshot(command)?;
569 582
        Ok((report, carried.into_iter().map(|(p, _)| p).collect()))
…
107 unchanged lines
modified crates/oxy-core/src/repo/tests.rs +7 −1
…
5176 unchanged lines
5177 5177
    write(root, "a.txt", b"a\nmore\n");
5178 5178
    write(root, "new.txt", b"new\n");
5179 5179
    fs::remove_file(root.join("gone.txt")).unwrap();
5180 -
    let (_, carried) = repo.bookmark_switch_carry("feature").unwrap();
5180 +
    let (report, carried) = repo.bookmark_switch_carry("feature").unwrap();
5181 5181
    assert_eq!(carried, vec!["a.txt", "gone.txt", "new.txt"]);
5182 +
    // oxygen#120: the new file was carried, not removed.
5183 +
    assert_eq!(
5184 +
        (report.removed, report.removed_paths.len()),
5185 +
        (0, 0),
5186 +
        "{report:?}"
5187 +
    );
5182 5188
    assert_eq!(repo.config.bookmark, "feature");
5183 5189
    assert_eq!(fs::read(root.join("a.txt")).unwrap(), b"a\nmore\n");
5184 5190
    assert_eq!(fs::read(root.join("new.txt")).unwrap(), b"new\n");
…
3338 unchanged lines
modified src/cli/workspace.rs +24 −0
…
126 unchanged lines
127 127
    );
128 128
}
129 129
130 +
/// Name the work a switch carried (oxygen#120): it is still on disk, as it
131 +
/// was, on the new bookmark.
132 +
fn print_carried(paths: &[String]) {
133 +
    if paths.is_empty() {
134 +
        return;
135 +
    }
136 +
    let shown: Vec<&str> = paths.iter().take(10).map(String::as_str).collect();
137 +
    let more = paths.len().saturating_sub(shown.len());
138 +
    println!(
139 +
        "  {} {}",
140 +
        ui::note(),
141 +
        ui::dim(format!(
142 +
            "carried, as they were: {}{}",
143 +
            shown.join(", "),
144 +
            if more > 0 {
145 +
                format!(" and {more} more")
146 +
            } else {
147 +
                String::new()
148 +
            }
149 +
        ))
150 +
    );
151 +
}
152 +
130 153
/// Folders holding a repository of their own, which oxy leaves out (oxygen#43):
131 154
/// named, with how to track them.
132 155
fn print_untracked_nested(repo: &Repo, nested: &[String]) {
…
2626 unchanged lines
2759 2782
        }
2760 2783
    ));
2761 2784
    print_removed(&r);
2785 +
    print_carried(&carried);
2762 2786
    if r.conflicted {
2763 2787
        println!(
2764 2788
            "  {} {}",
…
166 unchanged lines