Skip to content

Conversation

@David-Noble-at-work
Copy link

Summary

Fixes #127 - --force and --adopt options exhibit destructive behavior that creates empty directories instead of symlinks.

Changes

1. Fix symlink/file removal in remove_files_and_decide_if_adopt()

Before: The removal logic only handled is_dir() and is_file(), missing symlinks that don't resolve:

} else if target_file.is_dir() {
    fs::remove_dir_all(deleted_file).unwrap();
} else if target_file.is_file() {
    fs::remove_file(deleted_file).unwrap();
}

After: Uses exists() || is_symlink() to properly handle all file types including broken symlinks.

2. Fix --adopt deleting source when target doesn't exist

Before: The source file in the dotfiles repo was deleted unconditionally before checking if the target existed.

After: Now checks if target exists before deleting source, with a warning message if adopt is not possible.

3. Fix directory creation in SymlinkHandler::add()

Before: After removing a file, target_path.is_file() returns false, causing create_dir_all(&target_path) to create the target as a directory:

fs::create_dir_all(if target_path.is_file() {
    target_path.parent().unwrap()
} else {
    &target_path  // BUG: creates target as directory!
})

After: Always uses .parent() to only create parent directories.

Testing

  • cargo check passes
  • cargo test passes (except for pre-existing unrelated failure in ignore_garbage_files)
  • The add_and_remove_symlink test passes

Impact

These bugs caused 185+ files to become empty directories when using --force, affecting SSH keys, shell configs, fonts, and other critical dotfiles.

This fixes two critical bugs in the add command:

1. In remove_files_and_decide_if_adopt():
   - The removal logic only handled is_dir() and is_file(), missing symlinks
   - Now uses exists() || is_symlink() to properly handle all file types
   - For --adopt, now checks if target exists before deleting source file,
     preventing data loss when adopting non-existent files

2. In SymlinkHandler::add() removed_groups loop:
   - create_dir_all() was called with target_path when is_file() returned
     false (after file was deleted), creating the target as a directory
   - Now always uses parent() to only create parent directories

These bugs caused 185+ files to become empty directories when using
--force, affecting SSH keys, shell configs, fonts, and other dotfiles.

Fixes RaphGL#127
no_x_setup_yet = "Ainda nenhum %{x} foi configurado"
not_a_tuckr_dotfile = "`%{file}` não é um ficheiro do tuckr."
wrong_password = "Palavra-passe errada."
no_configs_dir_in_dotfiles = "Não existe um diretório Configs nos dotfiles (%{dotfiles})"
Copy link
Owner

Choose a reason for hiding this comment

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

Why is this added? The program should fail before this should even be necessary. Also no_x_setup_yet exists and is used throughout the program. introducing this is completely unncessary.

@RaphGL
Copy link
Owner

RaphGL commented Jan 5, 2026

I just opened your fork, your fork is outdated. I just did some work to fix the bad handling of multiple groups sharing files the recently. Please test the most recent version to see if the issue has been fixed.

@RaphGL
Copy link
Owner

RaphGL commented Jan 5, 2026

I cannot even replicate the issue you hint at here. Was this an AI PR?

@RaphGL RaphGL closed this Jan 5, 2026
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.

Critical: --force and --adopt create empty directories instead of symlinks

2 participants