rcm icon indicating copy to clipboard operation
rcm copied to clipboard

optional .local suffix for colliding files from multiple sources

Open qrkourier opened this issue 2 years ago • 3 comments

I'm trying to avoid renaming the colliding dotfiles in my personal repo so that I can use them on systems where I'm not also using thoughtbotdotfiles with the .local convention. Collisions are ignored by rcup today, and here's how an rcup -L option could modify that behavior.

# two dotfiles with the same name exist in multiple sources
# ~/Sites/thoughtbotdotfiles/zshrc
# ~/Sites/qrkourier/dotfiles/zshrc
$ rcup -d ~/Sites/thoughtbotdotfiles -d ~/Sites/qrkourier/dotfiles -L
$ ls -l ~/.zshrc{,.local}
lrwxrwxrwx 1 qrkourier qrkourier 45 Sep 22 18:32 /home/qrkourier/.zshrc -> /home/qrkourier/Sites/thoughtbotdotfiles/zshrc
lrwxrwxrwx 1 qrkourier qrkourier 35 Sep 18 11:55 /home/qrkourier/.zshrc.local -> /home/qrkourier/Sites/dotfiles/zshrc

qrkourier avatar Sep 24 '21 03:09 qrkourier

Though I'm unfamiliar, I noticed there were some additional env vars or configuration files or both that might serve to add more granularity to this new behavior. Even without additional controls a simple default to .local suffix when a name is already claimed by a prior source file would immediately make rcup more useful for me. A few years ago when I first encountered this limitation I wrote a shell function emulating rcup and implementing the .local suffix for collisions. I don't know why I did that instead of adding the option myself, but it does work well.

rcupl (){
  #
  # qrkourer: 2016
  #
  DEBUG=""
  test -d "$1" || { echo "Expects the link target dir as the first argument, bye"; return 1; }
  test -d "$2" || { echo "Expects the link location dir as the second argument, bye"; return 1; }
  # set the optional dotfile prefix accepting 'nil' to mean no prefix
  case "$3" in
    "") local RCPRE='.';;
 "nil") local RCPRE='';;
     *) local RCPRE="$3";;
  esac
  for RCTGT in $1/*;do
    [[ $RCTGT == $1/\* ]] && continue
    local RCLNK="$2/${RCPRE}$(basename $RCTGT)"
    # test whether the target is a directory
    if test -d "$RCTGT";then
      # make the corresponding link directory and a shortcut link sans prefix
      # (e.g., ./bin -> ./.bin)
      $DEBUG mkdir -pv "$RCLNK"
      $DEBUG ln -sTnv "$RCLNK" \
        "${RCLNK/\/$RCPRE$(basename $RCTGT)/\/$(basename $RCTGT)}" 2>/dev/null
    fi
    # test whether another file or intact link already exists
    if test -e "$RCLNK"; then
      # test whether the existing file is a link
      if test -L "$RCLNK";then
        # test whether the existing link already points to the intended target
        if [[ "$(readlink -f $RCTGT)" == "$(readlink -f $RCLNK)" ]]; then
          # skip to next RCTGT
          continue
        else
	  # if a link pointing elsewhere then assume it is a thoughtbot dotfile
	  # and create the expected local include variant
          RCLNK="${RCLNK}.local"
          $DEBUG ln -sfnv "$RCTGT" "$RCLNK"
        fi
      # test whether the existing file is a directory
      elif test -d "$RCLNK";then
        # recurse
        rcupl "$RCTGT" "$RCLNK" nil
      # if a regular file then warn
      else
        echo "not clobbering existing regular file $RCLNK" >&2
      fi
    else
      # if not exists or broken link then create the normal link
      $DEBUG ln -sfnv "$RCTGT" "$RCLNK"
    fi
  done
}

qrkourier avatar Sep 24 '21 03:09 qrkourier

I got so far as to realize that rcup consumes the list of managed files from lsrc which omits collisions. One way to handle this would be for lsrc -L -F to instead signify collisions local overrides with sigil L. That way, rcup could handle the local override with a ${dest}.local.

Another way of identifying local overrides in the Thoughtbot convention could be to use a reserved tag for this purpose like "local". Dotfiles with the special tag could always receive the .local suffix when a collision occurs.

qrkourier avatar Sep 24 '21 04:09 qrkourier

Hello @qrkourier ,

My raw thoughts: You only have two dotfiles repos, but some people have more, and rcm will not be able to suggest other extensions if there is more than one collision for a file. And what to do if we have a file and a folder with the same name ? Moreover, it would mean that the order of the paths is important, and I am not sure it is in the specs. Your suggestion about the local tag may be an option, but that does not scale,

My afterthought: rcm may need a spec on how to handle collisions. Current specs seems to be ''last one wins''. Can you try to elaborate a spec with what would happen in the following situations (at least):

  • one repo with file configrc
  • two repos with file configrc
  • three repos with file configrc
  • one repo with file configrc and one repo with folder configrc
  • what would happen if I ran rcup -d repoA, and I after run rcup -d repoB -d repoA (where, in your case, repoB is the thoughtbot one)

Thank you

mat-m avatar Jul 27 '22 21:07 mat-m

Thank you!

qrkourier avatar Apr 13 '23 15:04 qrkourier