twpayne / chezmoi

Manage your dotfiles across multiple diverse machines, securely.
https://www.chezmoi.io/
MIT License
13.25k stars 493 forks source link

OneDrive PC folder backup causes non-portable paths #2138

Closed cglong closed 2 years ago

cglong commented 2 years ago

Describe the bug

My organization uses OneDrive PC folder backup to sync my Documents folder on Windows to OneDrive for Business. When I add a file in my Documents folder to Chezmoi, the path is ./OneDrive - {organization}/Documents, which isn't compatible with non-work machines.

To reproduce

  1. Enable PC folder backup.
  2. Open Windows PowerShell and run New-Item $PROFILE to ensure the file exists.
  3. From Windows PowerShell, run chezmoi add $PROFILE.

Expected behavior

When the file is added to Chezmoi, it should just be at ./Documents.

Output of command with the --verbose flag

Note that I've replaced my organization's name with {organization} for obfuscation purposes 🙂

PS C:\Users\chris> echo $PROFILE
C:\Users\chris\OneDrive - {organization}\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
PS C:\Users\chris> chezmoi --verbose add $PROFILE
diff --git a/OneDrive - {organization} b/OneDrive - {organization}
new file mode 40777
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
--- /dev/null
+++ b/OneDrive - {organization}
diff --git a/OneDrive - {organization}/Documents b/OneDrive - {organization}/Documents
new file mode 40777
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
--- /dev/null
+++ b/OneDrive - {organization}/Documents
diff --git a/OneDrive - {organization}/Documents/WindowsPowerShell b/OneDrive - {organization}/Documents/WindowsPowerShell
new file mode 40777
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
--- /dev/null
+++ b/OneDrive - {organization}/Documents/WindowsPowerShell
diff --git a/OneDrive - {organization}/Documents/WindowsPowerShell/Microsoft.PowerShell_profile.ps1 b/OneDrive - {organization}/Documents/WindowsPowerShell/Microsoft.PowerShell_profile.ps1
new file mode 100666
index 0000000000000000000000000000000000000000..63d931a73ce7383c5a417f0884588b16838f9f37
--- /dev/null
+++ b/OneDrive - {organization}/Documents/WindowsPowerShell/Microsoft.PowerShell_profile.ps1
@@ -0,0 +1,2 @@
+New-Alias -Name "open" Invoke-Item
+New-Alias -Name "code" code-insiders.exe

Output of chezmoi doctor

```console PS C:\Users\chris> chezmoi doctor RESULT CHECK MESSAGE ok version v2.17.1, commit 565cbbe117746aa6bfec5f2cee20ae4cbbb5e645, built at 2022-05-30T10:24:34Z, built by goreleaser ok latest-version v2.17.1 ok os-arch windows/amd64 ok systeminfo Microsoft Windows 11 Enterprise (10.0.22000 N/A Build 22000) ok go-version go1.18.2 (gc) ok executable ~/scoop/apps/chezmoi/current/chezmoi.exe ok upgrade-method replace-executable ok config-file ~/.config/chezmoi/chezmoi.toml ok source-dir ~/.local/share/chezmoi is a directory ok suspicious-entries no suspicious entries ok working-tree ~/.local/share/chezmoi is a directory ok dest-dir ~ is a directory ok shell-command found C:/WINDOWS/system32/cmd.exe ok shell-args 'C:\\WINDOWS\\system32\\cmd.exe' ok cd-command found C:/WINDOWS/system32/cmd.exe ok cd-args 'C:\\WINDOWS\\system32\\cmd.exe' ok edit-command found C:/WINDOWS/system32/notepad.exe ok edit-args 'C:\\WINDOWS\\system32\\notepad.exe' info diff-command not set ok git-command found ~/scoop/shims/git.exe, version 2.36.1 warning merge-command vimdiff not found in $PATH info age-command age not found in $PATH info gpg-command gpg not found in $PATH info pinentry-command not set info 1password-command op not found in $PATH info bitwarden-command bw not found in $PATH info gopass-command gopass not found in $PATH info keepassxc-command keepassxc-cli not found in $PATH info keeper-command keeper not found in $PATH info keepassxc-db not set info lastpass-command lpass not found in $PATH info pass-command pass not found in $PATH info vault-command vault not found in $PATH info secret-command not set ```

Additional context

It appears there are a few ways to get the correct value of these folders:

cglong commented 2 years ago

I actually just realized that, assuming I'm okay with my organization name being part of the source state, this can be accomplished using this method. Therefore, I guess this is more of a feature request 🙂

twpayne commented 2 years ago

I don't quite understand what you want here. Is the suggestion that chezmoi should somehow automatically re-write directory names using registry keys?

cglong commented 2 years ago

No worries! Thank you for getting back to me 🙂

The suggestion would be for Chezmoi to detect shell folders (e.g. Documents) and automatically sync them consistently across different systems. So C:\Users\chris\Documents on one system and C:\Users\chris\OneDrive - {organization}\Documents on another would receive the same target state.

Since opening this issue, I realized this is special-casing that may be considered out-of-scope, so I totally understand if this will be closed 🙂

twpayne commented 2 years ago

Ah, thank you for the further details :)

I think you're on to something good here. I think there's potentially a much better way to handle the "handle different file locations on different systems with the same contents" problem whose FAQ entry you linked to.

Roughly it could look something like:

  1. In your config file, you specify something like:

    [rewriteTargetPaths]
        "Documents" = "One Drive - {organization}/Documents"
  2. This would tell chezmoi that whenever it finds Documents in your source state it should replace it with One Drive - {organization}/Documents in the target state.

  3. To handle machine-to-machine differences, there's the existing config file generation mechanism which we can use. So, for example, your config file template would look something like:

    [rewriteTargetPaths]
        "Documents" = "One Drive - {{ registry "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders\Personal" }}"

    (assuming the addition of a registry template function to get values from the Windows registry)

  4. For the use case of different directories in the FAQ entry, the config file template would look something like:

    {{ if .chezmoi.os == "darwin" }}
    # config file directory locations are different on macOS (darwin)
    [rewriteTargetPaths]
        ".config/app" = "Library/Application Support/App"
    {{ end }}

Implementing this has some subtleties (e.g. what should happen if multiple source directories are re-written to a single target directory) and will likely be non-trivial to implement, but you're definitely on to something here :)

twpayne commented 2 years ago

Created #2273 to track this.