Allow checkouts of repositories into non-empty directories#2508
Conversation
3c5b2d5 to
352d216
Compare
Sebastian Thiel (Byron)
left a comment
There was a problem hiding this comment.
Thanks, but I think this needs test coverage.
I would also be afraid that it now allows writing non-empty directories, wiping data in the process.
What would you expect tests for this to look like? Checking out into a non empty directory with the flag both set and not set? The latter would just be a regular checkout. |
|
There needs to be a test that fails if the change of this PR isn't present.
It might already exist as well, in which case you can point it out to me. |
dfadc8b to
592b69d
Compare
|
I've added the tests. What I think should be done is to change the |
Sebastian Thiel (Byron)
left a comment
There was a problem hiding this comment.
I don't think I understand the premise. The reason that it won't allow cloning into a non-empty directory is that it will brutally overwrite everything. Git also rejects this, AFAIK.
❯ git clone https://github.com/GitoxideLabs/gitoxide ./src/
fatal: destination path './src' already exists and is not an empty directory.
The PR title is "Allow checkouts of empty repositories". Thus a test should show that empty repositories couldn't be checked out before, and after the fix they can.
I've added the tests. What I think should be done is to change the Default implementation to set destination_must_be_empty to true by default.
I agree, and wonder why I didn't that before.
One problem remains: I don't understand what the PR is trying to fix.
There was a problem hiding this comment.
Pull request overview
This PR adjusts gix::clone::PrepareFetch::new() to honor the caller-provided gix::create::Options instead of unconditionally requiring an empty destination directory for worktree clones, aligning clone initialization behavior with the documented semantics of create::Options. It also adds regression tests covering the new default behavior and the opt-in strict mode.
Changes:
- Stop forcing
create_opts.destination_must_be_empty = trueinPrepareFetch::new_inner(). - Add a test proving fetch+checkout into a non-empty destination directory works by default (and preserves pre-existing files).
- Add a test proving
destination_must_be_empty: truestill rejects non-empty destinations for worktree clones.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| gix/src/clone/mod.rs | Removes the unconditional override of destination_must_be_empty, so clone respects caller-provided creation options. |
| gix/tests/gix/clone.rs | Adds coverage for cloning into non-empty worktree destinations by default and for the strict “must be empty” option. |
Before my changes every code path set the |
|
I've updated the tests to better reflect the change and made it so |
d090222 to
e6727f1
Compare
## Summary
Closes 9 compat-mode rows in tests/journey/parity/branch.sh, lands three
reusable foundations consumed by future sprints (commit, push, tag, merge),
and folds in 6 upstream syncs that arrived during the sprint.
## Closed parity rows (all bytes-mode, steward-verified, on-disk state asserted)
- `-v` / `--verbose` — column-aligned name + SHA + subject
- `-vv` — adds `[upstream: ahead N, behind N]` tracking annotation
- `--abbrev=N` / `--no-abbrev` — SHA width override
- `--column=always` — column-major packing
- `-u` / `--set-upstream-to` — writes branch.<n>.{remote,merge}
- `--unset-upstream` — clears them; emits `fatal: branch '<n>' has no upstream information` + exit 128 when absent
- `--track` (create-side) — writes upstream config after ref creation
- `--edit-description` — spawns editor, writes branch.<n>.description
Plus three on-disk-state guard rows (chained gix → gix invocations) so
bytes-mode parity tests can no longer mask missing-side-effect regressions
in branch-config writers.
## Foundations introduced
- gix::Repository::{set_branch_upstream, unset_branch_upstream, set_branch_description}
with $GIT_DIR/config persistence via gix_config::File::write_to_filter
on Source::Local sections (matches gix/src/clone/fetch/util.rs::setup_branch_config).
- Branch::DESCRIPTION key constant + SnapshotMut::clear_subsection_value helper.
- gitoxide-core::shared::columns::write_columns — column-major packer (reusable
for status --column).
- gitoxide-core::shared::editor::edit_file — $GIT_EDITOR/core.editor/$VISUAL/$EDITOR/vi
resolver + shell-spawn (reusable for commit -e, tag --edit, merge --edit).
## Upstream syncs folded in
- merge: pull upstream gix-main into gix-brit (security hardening + fuzz expansion)
- merge: pull GitoxideLabs#2508 — allow checkouts into non-empty directories
- merge: pull GitoxideLabs#2375 — filters and partial cloning: initial support
- merge: pull GitoxideLabs#2503 — IOUC (UNTR extension) dirwalk speedup
- merge: pull GitoxideLabs#2457 — gix-blame: Incremental
- merge: pull GitoxideLabs#2465 — barebones server-side upload-pack
## Adjustments
- steward agent: surface idiomatic Rust as an explicit design priority,
reframing vendor/git as the *what* (flag surface, exit codes, output bytes)
while gitoxide idioms anchor *how*.
- Post-merge cleanup: dropped duplicate clone --filter stub (superseded by GitoxideLabs#2375)
and pr-2457's orphaned log helpers (our log_all already handles paths).
Plan: etc/plan/foundations-sprint-branch-render-and-config.md
Pre-squash backup tag: pre-squash-foundations
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
a71f6ad to
36f3805
Compare
|
Hi Sebastian Thiel (@Byron), this is rebased on top of Changes since you last looked:
The CI is green. |
Also make turn `destination_must_be_empty` into `Option<bool>`
add0e65 to
444ece4
Compare
Sebastian Thiel (Byron)
left a comment
There was a problem hiding this comment.
This PR got lucky as I nerd-sniped myself into probably putting more time in it as it would have cost me if I would have implemented this feature from the start.
Nowadays, I think it costs more to lift a mediocre PR into what's needed than to do it from scratch given agent support, and it's something I will consider in future, which probably leans more towards closing such PRs than engaging with it.
Lesson learned, I hope.
444ece4 to
d6da476
Compare
d6da476 to
c77081d
Compare
Co-authored-by: Sebastian Thiel <[email protected]>
c77081d to
8606b7a
Compare
Allow
gix::clone::PrepareFetchcallers to clone and check out into a destination directory that is not empty.Before this change,
PrepareFetch::new()unconditionally overrodecreate::Options::destination_must_be_emptytotrueregardless of what the caller passed, so the flag was effectively non-functional and there was no way to opt in to a non-empty destination through the public API.gix::create::Options::destination_must_be_emptynow controls this for non-bare repositories:None(default forgix::init) — the directory may already contain files as long as no.gitdirectory is present.Some(true)(effective default forprepare_clone/prepare_clone_bare) — require an empty destination, preserving the prior clone behavior.Some(false)— explicitly allow a non-empty destination for clones.Bare repositories always require an empty destination.
If a clone fails before completion and the prepare handle is dropped, only the
.gitdirectory created by the clone is removed; any pre-existing user files in the destination are preserved.