anishathalye / dotbot

A tool that bootstraps your dotfiles ⚡️
MIT License
6.9k stars 287 forks source link

BUG: If the same destination is used multiple times with globs, only the last one is taken into account. #300

Open ldorigo opened 2 years ago

ldorigo commented 2 years ago

Hi, I have two directories in my dotfiles: /services (systemd services that need to start on boot) and /timers (systemd timers with corresponding units). I want both to be linked into ~/.config/systemd/user.

I tried doing:

- link:
    ~/.config/systemd/user: 
      path: services/*
      glob: true
    ~/.config/systemd/user:
      path: timers/*
      glob: true

But it looks like it only links the second one (timers), not the first. Any workaround? (I can't just put them all into the same folder because I am also starting them up with dotbot - for services I need to start/enable the .service file, and for timers only the .timer file).

ldorigo commented 2 years ago

I also tried putting the three directories inside a common systemd/ directory and doing:

- link:
    ~/.config/systemd/user/: 
      glob: true
      path: systemd/**

But it doesn't work - it only links the directories, so systemd/services and systemd/timers, not the files in those directories. So the documentation is wrong (docs say "** matches any file, recursively").

And doing:

- link:
   ~/.config/systemd/user/: 
      glob: true
      path: systemd/**/*

Also doesn't work, it does link all the files but still within the folder structure (so it creates ~/.config/systemd/user/services/a.service, ~/.config/systemd/user/services/b.service, etc.)

ldorigo commented 2 years ago

I took a look at the source code, seems like this is due to a limitation of Yaml/Json - the destination paths are used as keys, and there can't be duplicate keys. This means it's not completely trivial to solve it, I see two possibilities:

  1. Allow specifying lists of paths rather than a single path. This should be relatively easy to implement - Yaml and Json both support lists, all it would take is adding an additional case in the Links plugin. But I'm not familiar enough with the codebase to see possible pitfalls. So my example would become:
    - link:
    ~/.config/systemd/user: 
      path: 
        - services/*
        - timers/*
      glob: true
  2. Add an additional option (something like "preserve_directory_tree") that lets you choose whether to link all files in subdirectories in a flat way vs. preserving the directory structure.

I think (1) is better - (2) is very specific to this usecase and could be confusing, while (1) is quite explicit (you need to pass a list of directories by hand). If you approve I can submit a PR later.

ldorigo commented 2 years ago

Wanted to get this working so I added a PR, let me know if there's any problems with it

anishathalye commented 2 years ago

Related to this point: note to self, maybe we should add an explanation of this to the documentation, that the yaml key: value pairs don't support duplicate keys.

brutus commented 1 year ago

I only skimmed the PR… just wanted to drop my usual work around for duplicated YAML keys:

- link:
    ~/.config/systemd/user: 
      path: services/*
      glob: true

- link:
    ~/.config/systemd/user: 
      path: timers/*
      glob: true