Skip to content

✨ feat: add fork environment support#65

Merged
SigureMo merged 3 commits into
mainfrom
feat/fork-command-20260501
Apr 30, 2026
Merged

✨ feat: add fork environment support#65
SigureMo merged 3 commits into
mainfrom
feat/fork-command-20260501

Conversation

@SigureMo
Copy link
Copy Markdown
Contributor

@SigureMo SigureMo commented Apr 30, 2026

Summary

  • add a dedicated meowda fork / meowda env fork command and remove fork-specific flags from create
  • split create and fork workflows in the CLI and VenvService, with fork mechanics moved into src/venv/fork.rs
  • rename the former backend layer to venv and update the README examples and command reference

Closes #59.

Testing

  • cargo +stable fmt --all
  • cargo +stable clippy --all-targets --all-features -- -D warnings
  • cargo +stable test
This PR is driven by @copilot (gpt-5.4 xhigh)

Copilot AI review requested due to automatic review settings April 30, 2026 21:41
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@SigureMo SigureMo changed the title Refactor forking into a dedicated command ✨ feat: add fork environment support Apr 30, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the β€œfork environment” workflow into a dedicated CLI command (meowda fork / meowda env fork), splitting create vs fork logic in the service layer and moving fork mechanics into a new src/venv/fork.rs module.

Changes:

  • Introduce meowda fork / meowda env fork commands and wire them into the CLI entrypoint.
  • Split VenvBackend into VenvService, extracting venv creation into src/venv/create.rs and fork implementation into src/venv/fork.rs.
  • Update scope handling and documentation/examples to reflect the new commands and module layout.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/venv/mod.rs Renames backend to VenvService, adds create/fork APIs with option structs, and hooks into new fork module.
src/venv/fork.rs New fork implementation: resolves source env/executable, creates target venv, copies site-packages/scripts, rewrites paths, adds tests.
src/venv/create.rs New helper to run uv venv with consistent flags.
src/store/venv_store.rs Makes ScopeType Copy to support reuse across CLI/service flows.
src/main.rs Rewires entrypoint to venv::VenvService and new fork command routes.
src/cli/mod.rs Exposes new cli::fork module.
src/cli/fork.rs Implements meowda fork command handler and invokes VenvService::fork.
src/cli/env.rs Updates env subcommands to use VenvService and new CreateOptions.
src/cli/args.rs Adds Fork command and ForkArgs, updates CreateArgs python handling.
src/cli/install.rs Renames backend parameter usage to VenvService.
src/cli/link.rs Renames backend parameter usage to VenvService.
README.md Documents meowda fork usage and updates command reference.
Comments suppressed due to low confidence (1)

src/cli/args.rs:89

  • Same default_value = "false" issue as CreateArgs::clear: this may turn --clear into an option that expects an explicit boolean value, instead of a simple flag. Remove the default_value (or set action = clap::ArgAction::SetTrue) so meowda fork ... --clear works as intended.
    #[arg(
        short,
        long,
        default_value = "false",
        help = "Clear existing virtual environment"
    )]
    pub clear: bool,

πŸ’‘ Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/cli/args.rs Outdated
Comment on lines +62 to +68
#[arg(
short,
long,
default_value = "3.13",
help = "Python version/path to use"
default_value = "false",
help = "Clear existing virtual environment"
)]
pub clear: bool,
Copy link

Copilot AI Apr 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clear: bool flags already default to false with clap derive. Setting default_value = "false" can change the argument into a value-taking option (potentially requiring --clear <true|false>), which would break the documented --clear usage. Drop default_value and keep this as a simple presence flag (or explicitly set action = clap::ArgAction::SetTrue).

Copilot uses AI. Check for mistakes.
Comment thread src/venv/fork.rs Outdated
Comment on lines +357 to +358
include_system_site_packages: prefix.join("pyvenv.cfg").exists()
&& (prefix != base_prefix || !real_prefix.is_empty() || include_system_site_packages),
Copy link

Copilot AI Apr 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

include_system_site_packages is computed as pyvenv.cfg exists && (prefix != base_prefix || ...), which will be true for most virtual environments (since sys.prefix != sys.base_prefix). This will cause create_with_source to pass --system-site-packages when forking from a normal venv, unintentionally exposing system packages. Compute this field strictly from pyvenv.cfg's include-system-site-packages value (and keep any "is venv" detection as a separate boolean if needed).

Suggested change
include_system_site_packages: prefix.join("pyvenv.cfg").exists()
&& (prefix != base_prefix || !real_prefix.is_empty() || include_system_site_packages),
include_system_site_packages,

Copilot uses AI. Check for mistakes.
Comment thread src/venv/fork.rs Outdated
Comment on lines +266 to +269
let link_is_dir = fs::metadata(source)
.map(|meta| meta.is_dir())
.unwrap_or(false);
create_symlink(&rewritten_target, target, link_is_dir)?;
Copy link

Copilot AI Apr 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Windows, symlink_dir vs symlink_file needs the correct is_dir value. Here link_is_dir is derived from fs::metadata(source) (follows the link) and falls back to false on error, which will mis-handle broken dir symlinks and can make the fork fail. Consider resolving link_target relative to the symlink's parent and checking metadata on that path, or attempting symlink_dir then symlink_file (or vice versa) when the target can't be inspected.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ’‘ Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fc51e3a710

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with πŸ‘.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/venv/mod.rs
Comment on lines +209 to +210
if options.clear {
Self::remove_venv(store, name)?;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reject self-fork before deleting an existing target env

When fork is called with --clear, the target environment is removed before we validate that the source and target are different. If a user runs something like meowda fork myenv --from myenv --clear (or points --from at the same path), this branch deletes myenv and then create_with_source later aborts on the same-source check in src/venv/fork.rs, resulting in destructive data loss instead of a clean validation error. The source/target identity check should happen before remove_venv is executed.

Useful? React with πŸ‘Β / πŸ‘Ž.

Co-authored-by: Codex <noreply@openai.com>

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@SigureMo SigureMo merged commit dd297e8 into main Apr 30, 2026
16 checks passed
@SigureMo SigureMo deleted the feat/fork-command-20260501 branch April 30, 2026 22:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

添加 fork ηŽ―ε’ƒζ”―ζŒ

2 participants