dotsync 0.1.24 → 0.1.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4ee97490d95db52087796f0da0615d71e3dacf7ac7a89834864abac834006b36
4
- data.tar.gz: c0f9ad979444a1ba28fdf7397fa7660e140dd483f8c5e7062d14cfc86852471a
3
+ metadata.gz: 89c25a6529e3557dc1383f3facf677f0775053d7db53863b7cc61a5b44d13b11
4
+ data.tar.gz: 1cfadbe1c539923fb6bf9c27eafde24beeab527feeaadf2b88d997d762f972b4
5
5
  SHA512:
6
- metadata.gz: c66534cc5d286e4fe7e85a4bff3edecd323db8ad30e653d4bee9d73dfde7277c46305f3c740626223ee302f171ae5f3bddca390805a4af366057a1a17da10a31
7
- data.tar.gz: 4fc6b7b11d3e8086292d85d53cdb54de1d0ddcb11d77761c6e834f915d0db1fdd2cb7a95b56753ddbf426eb8170e697df15c86a4c4a51eb01b945ccc5191b6b8
6
+ metadata.gz: 2b7012240c48cd7b9d84cf8e20d54efa913fd08324720b08d270db0c39e46f87a1f63f124e6d562d06ab2bef7f0fd017bb686e666b40866fc89eceae831de1bf
7
+ data.tar.gz: 87f03124b8dc8cad8c3588d3391858414ac0a577416c7a227465702a081c8de9fa36648e5eb5c642ba9b6beae81c19043259c25b536a634cd3bfcd3b83a7cfc9
@@ -1,4 +1,4 @@
1
- name: Ruby Gem
1
+ name: CI
2
2
 
3
3
  on:
4
4
  push:
@@ -0,0 +1,50 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ permissions:
9
+ contents: write
10
+
11
+ jobs:
12
+ release:
13
+ runs-on: ubuntu-latest
14
+
15
+ steps:
16
+ - name: Checkout code
17
+ uses: actions/checkout@v6
18
+
19
+ - name: Get version from tag
20
+ id: version
21
+ run: echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
22
+
23
+ - name: Extract changelog for version
24
+ id: changelog
25
+ run: |
26
+ # Extract the section for this version from CHANGELOG.md
27
+ # Matches from "## [X.Y.Z]" until the next "## [" or end of file
28
+ VERSION="${{ steps.version.outputs.version }}"
29
+ CHANGELOG=$(awk -v ver="$VERSION" '
30
+ /^## \[/ {
31
+ if (found) exit
32
+ if ($0 ~ "\\[" ver "\\]") found=1
33
+ }
34
+ found { print }
35
+ ' CHANGELOG.md | tail -n +2)
36
+
37
+ # Use heredoc for multiline output
38
+ echo "content<<EOF" >> $GITHUB_OUTPUT
39
+ echo "$CHANGELOG" >> $GITHUB_OUTPUT
40
+ echo "EOF" >> $GITHUB_OUTPUT
41
+
42
+ - name: Create GitHub Release
43
+ uses: softprops/action-gh-release@v2
44
+ with:
45
+ name: v${{ steps.version.outputs.version }}
46
+ body: ${{ steps.changelog.outputs.content }}
47
+ draft: false
48
+ prerelease: false
49
+ env:
50
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
data/.gitignore CHANGED
@@ -9,3 +9,5 @@
9
9
 
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
+
13
+ .claude/
@@ -0,0 +1,9 @@
1
+ repos:
2
+ - repo: local
3
+ hooks:
4
+ - id: rubocop
5
+ name: rubocop
6
+ entry: bundle exec rubocop --autocorrect --force-exclusion
7
+ language: system
8
+ types: [ruby]
9
+ pass_filenames: true
data/CHANGELOG.md CHANGED
@@ -1,3 +1,58 @@
1
+ ## [0.1.26] - 2025-01-11
2
+
3
+ **Breaking Changes:**
4
+ - The explicit sync mapping syntax has changed from `[[sync]]` to `[[sync.mappings]]`
5
+ - Old: `[[sync]]` with `local`/`remote` keys
6
+ - New: `[[sync.mappings]]` with `local`/`remote` keys
7
+ - This allows combining explicit mappings with XDG shorthands in the same config
8
+ - See README for migration examples
9
+
10
+ **New Features:**
11
+ - Add bidirectional `[[sync.mappings]]` DSL for two-way synchronization
12
+ - Simplified syntax replaces separate push/pull mappings
13
+ - Automatic expansion to bidirectional mappings (local ↔ remote)
14
+ - Supports all existing options: `force`, `only`, `ignore`
15
+ - Add XDG shorthand DSL for sync mappings
16
+ - `[[sync.home]]` - syncs $HOME ↔ $HOME_MIRROR
17
+ - `[[sync.xdg_config]]` - syncs $XDG_CONFIG_HOME ↔ $XDG_CONFIG_HOME_MIRROR
18
+ - `[[sync.xdg_data]]` - syncs $XDG_DATA_HOME ↔ $XDG_DATA_HOME_MIRROR
19
+ - `[[sync.xdg_cache]]` - syncs $XDG_CACHE_HOME ↔ $XDG_CACHE_HOME_MIRROR
20
+ - `[[sync.xdg_bin]]` - syncs $XDG_BIN_HOME ↔ $XDG_BIN_HOME_MIRROR (new)
21
+ - Use `path` for specific subdirectories or `only` for multiple paths
22
+ - Fix custom config path (`-c` flag) not being applied to Runner
23
+
24
+ **Documentation:**
25
+ - Document bidirectional sync mappings with examples
26
+ - Document XDG shorthand DSL with usage examples
27
+ - Update README with new configuration options and supported shorthands table
28
+
29
+ **Infrastructure:**
30
+ - Rename GitHub workflow to ci.yml
31
+ - Add sync_mappings concern to push and pull loaders
32
+
33
+ ## [0.1.25]
34
+
35
+ **Features:**
36
+ - Add support for file-specific paths in 'only' configuration option
37
+ - Enable specifying individual files within directories: `only = ["bundle/config", "ghc/ghci.conf"]`
38
+ - Parent directories are automatically created as needed
39
+ - Sibling files in the same directory remain unaffected
40
+ - Works with deeply nested paths: `only = ["nvim/lua/plugins/init.lua"]`
41
+ - Fix DirectoryDiffer to use bidirectional_include? for proper file traversal
42
+
43
+ **Documentation:**
44
+ - Completely rewrite 'force', 'only', and 'ignore' options section in README
45
+ - Add 4 detailed examples showing different use cases
46
+ - Add warnings and notes about combining options
47
+ - Document important behaviors and edge cases
48
+
49
+ **Testing:**
50
+ - Add comprehensive test coverage for file-specific paths in 'only' option
51
+ - Add tests for FileTransfer with nested file paths
52
+ - Add tests for DirectoryDiffer with file-specific only paths
53
+ - Add tests with force mode enabled
54
+ - All 396 tests pass with 96.61% line coverage
55
+
1
56
  # 0.1.24
2
57
 
3
58
  **Performance Optimizations:**
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dotsync (0.1.24)
4
+ dotsync (0.1.26)
5
5
  fileutils (~> 1.7.3)
6
6
  find (~> 0.2.0)
7
7
  listen (~> 3.9.0)
data/README.md CHANGED
@@ -13,7 +13,8 @@
13
13
  Dotsync is a powerful Ruby gem for managing and synchronizing your dotfiles across machines. Whether you're setting up a new development environment or keeping configurations in sync, Dotsync makes it effortless.
14
14
 
15
15
  **Key Features:**
16
- - **Bidirectional Sync**: Push local dotfiles to your repository or pull from repository to local machine
16
+ - **Bidirectional Sync Mappings**: Define once, sync both ways eliminates config duplication with `[[sync.mappings]]` syntax
17
+ - **XDG Shorthand DSL**: Concise `[[sync.home]]`, `[[sync.xdg_config]]`, `[[sync.xdg_data]]`, `[[sync.xdg_bin]]` syntax for common directory patterns
17
18
  - **Preview Mode**: See what changes would be made before applying them (dry-run by default)
18
19
  - **Smart Filtering**: Use `force`, `only`, and `ignore` options to precisely control what gets synced
19
20
  - **Automatic Backups**: Pull operations create timestamped backups for easy recovery
@@ -29,6 +30,9 @@ Dotsync is a powerful Ruby gem for managing and synchronizing your dotfiles acro
29
30
  - [Usage](#usage)
30
31
  - [Executable Commands](#executable-commands)
31
32
  - [Configuration](#configuration)
33
+ - [Bidirectional Sync Mappings (Recommended)](#bidirectional-sync-mappings-recommended)
34
+ - [Alternative: Unidirectional Mappings](#alternative-unidirectional-mappings)
35
+ - [Mapping Options (force, only, ignore)](#force-only-and-ignore-options-in-mappings)
32
36
  - [Safety Features](#safety-features)
33
37
  - [Customizing Icons](#customizing-icons)
34
38
  - [Automatic Update Checks](#automatic-update-checks)
@@ -76,22 +80,29 @@ Get started with Dotsync in just a few steps:
76
80
  ```
77
81
  This creates `~/.config/dotsync.toml` with example mappings.
78
82
 
79
- 3. **Edit the configuration** (`~/.config/dotsync.toml`) to define your dotfile mappings:
83
+ 3. **Edit the configuration** (`~/.config/dotsync.toml`) to define your dotfile mappings using bidirectional sync:
80
84
  ```toml
81
- [[pull.mappings]]
82
- src = "$HOME/dotfiles/config"
83
- dest = "$HOME/.config"
85
+ # Sync your shell config
86
+ [[sync.home]]
87
+ path = ".zshenv"
88
+
89
+ # Sync XDG config directories
90
+ [[sync.xdg_config]]
91
+ only = ["nvim", "alacritty", "zsh", "git"]
92
+ force = true
84
93
  ```
85
94
 
86
95
  4. **Preview your changes** (dry-run mode):
87
96
  ```shell
88
- dotsync pull
97
+ dotsync pull # Preview pulling from repo to local
98
+ dotsync push # Preview pushing from local to repo
89
99
  ```
90
100
  This shows what would be changed without modifying any files.
91
101
 
92
102
  5. **Apply changes** when you're ready:
93
103
  ```shell
94
- dotsync pull --apply
104
+ dotsync pull --apply # Apply repo → local
105
+ dotsync push --apply # Apply local → repo
95
106
  ```
96
107
 
97
108
  ## Usage
@@ -127,7 +138,7 @@ Dotsync provides the following commands to manage your dotfiles:
127
138
  ```shell
128
139
  dotsync watch [OPTIONS]
129
140
  ```
130
-
141
+
131
142
  The watch command supports the same output control options as push and pull (e.g., `--quiet`, `--no-legend`, `--no-mappings`).
132
143
 
133
144
  - **Setup** (alias: **init**): Generate a default configuration file at `~/.config/dotsync.toml` with example mappings for `pull`, `push`, and `watch`.
@@ -212,68 +223,258 @@ dotsync watch --quiet # Watch with minimal output
212
223
 
213
224
  ### Configuration
214
225
 
215
- The configuration file uses a `mappings` structure to define the source and destination of your dotfiles. Here is an example:
226
+ Dotsync uses TOML configuration files to define mappings between your local machine and your dotfiles repository. The recommended approach is **bidirectional sync mappings**, which eliminate duplication and keep your config clean.
227
+
228
+ > [!TIP]
229
+ > Set up mirror environment variables for cleaner configuration:
230
+ > ```bash
231
+ > # Add to your ~/.zshrc or ~/.bashrc
232
+ > export DOTFILES_DIR="$HOME/Code/dotfiles"
233
+ > export XDG_CONFIG_HOME_MIRROR="$DOTFILES_DIR/xdg_config_home"
234
+ > export XDG_DATA_HOME_MIRROR="$DOTFILES_DIR/xdg_data_home"
235
+ > export HOME_MIRROR="$DOTFILES_DIR/home"
236
+ > ```
237
+
238
+ #### Bidirectional Sync Mappings (Recommended)
239
+
240
+ Use `[[sync]]` mappings to define paths that sync in both directions. This is the **preferred approach** as it eliminates duplication between push and pull configurations.
241
+
242
+ ##### XDG Shorthand Syntax
243
+
244
+ The most concise way to define mappings for standard XDG directories:
216
245
 
217
246
  ```toml
218
- [[pull.mappings]]
219
- src = "$XDG_CONFIG_HOME_MIRROR"
220
- dest = "$XDG_CONFIG_HOME"
221
- ignore = ["nvim"]
247
+ # Sync home directory files
248
+ [[sync.home]]
249
+ path = ".zshenv"
250
+
251
+ # Sync multiple configs from XDG_CONFIG_HOME
252
+ [[sync.xdg_config]]
253
+ only = ["alacritty", "git", "zsh", "starship.toml"]
254
+ force = true
255
+
256
+ # Sync specific config with custom options
257
+ [[sync.xdg_config]]
258
+ path = "nvim"
259
+ force = true
260
+ ignore = ["lazy-lock.json"]
261
+
262
+ # Sync XDG data directories
263
+ [[sync.xdg_data]]
264
+ path = "git"
265
+ force = true
266
+ ```
267
+
268
+ **Supported shorthands:**
269
+
270
+ | Shorthand | Local | Remote |
271
+ |-----------|-------|--------|
272
+ | `sync.home` | `$HOME` | `$HOME_MIRROR` |
273
+ | `sync.xdg_config` | `$XDG_CONFIG_HOME` | `$XDG_CONFIG_HOME_MIRROR` |
274
+ | `sync.xdg_data` | `$XDG_DATA_HOME` | `$XDG_DATA_HOME_MIRROR` |
275
+ | `sync.xdg_cache` | `$XDG_CACHE_HOME` | `$XDG_CACHE_HOME_MIRROR` |
276
+ | `sync.xdg_bin` | `$XDG_BIN_HOME` | `$XDG_BIN_HOME_MIRROR` |
277
+
278
+ **Options:**
279
+ - `path` (optional): Relative path within the directory. If omitted, syncs the entire directory.
280
+ - `force`, `ignore`, `only`: All standard mapping options are supported.
281
+
282
+ ##### Explicit Sync Syntax
283
+
284
+ For custom paths that don't follow XDG conventions, use explicit `[[sync.mappings]]` entries:
285
+
286
+ ```toml
287
+ [[sync.mappings]]
288
+ local = "$XDG_CONFIG_HOME/nvim"
289
+ remote = "$XDG_CONFIG_HOME_MIRROR/nvim"
290
+ force = true
291
+ ignore = ["lazy-lock.json"]
292
+
293
+ [[sync.mappings]]
294
+ local = "$HOME/.zshenv"
295
+ remote = "$HOME_MIRROR/.zshenv"
296
+
297
+ # Sync config file to a different location in repo
298
+ [[sync.mappings]]
299
+ local = "$XDG_CONFIG_HOME/dotsync.toml"
300
+ remote = "$XDG_CONFIG_HOME_MIRROR/dotsync/dotsync.macbook.toml"
301
+ ```
302
+
303
+ **How it works:**
304
+ - `local` is your local machine path (e.g., `~/.config/nvim`)
305
+ - `remote` is your dotfiles repository path (e.g., `~/dotfiles/config/nvim`)
306
+ - For **push** operations: `local` → `remote`
307
+ - For **pull** operations: `remote` → `local`
308
+ - All standard options (`force`, `ignore`, `only`) are supported
222
309
 
310
+ ##### Complete Example
311
+
312
+ Here's a real-world configuration using bidirectional sync:
313
+
314
+ ```toml
315
+ ## BIDIRECTIONAL SYNC CONFIGURATION
316
+
317
+ # Home directory files
318
+ [[sync.home]]
319
+ path = ".zshenv"
320
+
321
+ # Bulk sync multiple configs
322
+ [[sync.xdg_config]]
323
+ only = [
324
+ "alacritty",
325
+ "brewfile",
326
+ "git",
327
+ "lazygit",
328
+ "tmux",
329
+ "zellij",
330
+ "starship.toml"
331
+ ]
332
+ force = true
333
+
334
+ # Zsh with ignored files
335
+ [[sync.xdg_config]]
336
+ path = "zsh"
337
+ ignore = [".zsh_sessions", ".zsh_history", ".zcompdump"]
338
+
339
+ # Neovim with force sync
340
+ [[sync.xdg_config]]
341
+ path = "nvim"
342
+ force = true
343
+ ignore = ["lazy-lock.json"]
344
+
345
+ # Git templates in data directory
346
+ [[sync.xdg_data]]
347
+ path = "git"
348
+ force = true
349
+
350
+ # This config file itself
351
+ [[sync.mappings]]
352
+ local = "$XDG_CONFIG_HOME/dotsync.toml"
353
+ remote = "$XDG_CONFIG_HOME_MIRROR/dotsync/dotsync.macbook.toml"
354
+ ```
355
+
356
+ #### Alternative: Unidirectional Mappings
357
+
358
+ For asymmetric sync scenarios where push and pull need different configurations, you can use separate `[[push.mappings]]` and `[[pull.mappings]]` sections:
359
+
360
+ ```toml
361
+ # Pull from repo to local (repo → local)
223
362
  [[pull.mappings]]
224
363
  src = "$XDG_CONFIG_HOME_MIRROR/nvim"
225
364
  dest = "$XDG_CONFIG_HOME/nvim"
226
- # FEATURE: forces the deletion of destination folder
227
365
  force = true
228
- # FEATURE: use relative paths to "dest" to ignore files and folders
229
366
  ignore = ["lazy-lock.json"]
230
367
 
231
- [[pull.mappings]]
232
- src = "$HOME_MIRROR/.zshenv"
233
- dest = "$HOME"
368
+ # Push from local to repo (local → repo)
369
+ [[push.mappings]]
370
+ src = "$XDG_CONFIG_HOME/alacritty"
371
+ dest = "$XDG_CONFIG_HOME_MIRROR/alacritty"
372
+ only = ["alacritty.toml", "themes"]
373
+
374
+ # Watch for live syncing
375
+ [[watch.mappings]]
376
+ src = "$XDG_CONFIG_HOME/nvim"
377
+ dest = "$XDG_CONFIG_HOME_MIRROR/nvim"
378
+ ```
234
379
 
380
+ > [!NOTE]
381
+ > You can mix `[[sync.mappings]]`, XDG shorthands (`[[sync.home]]`, `[[sync.xdg_config]]`, etc.), and `[[push.mappings]]`/`[[pull.mappings]]` in the same config file. Use bidirectional sync for symmetric mappings and unidirectional for special cases.
235
382
 
236
- [[push.mappings]]
237
- src = "$HOME/.zshenv"
238
- dest = "$HOME_MIRROR/.zshenv"
383
+ #### `force`, `only`, and `ignore` Options in Mappings
239
384
 
240
- [[push.mappings]]
241
- src = "$XDG_CONFIG_HOME/alacritty"
242
- dest = "$DOTFILES_DIR/config/alacritty"
243
- # FEATURE: transfer only relative paths of files and folders passed here
385
+ Each mapping entry supports the following options:
386
+
387
+ ##### `force` Option
388
+
389
+ A boolean (true/false) value. When set to `true`, it forces deletion of files in the destination directory that don't exist in the source. This is particularly useful when you need to ensure the destination stays synchronized with the source.
390
+
391
+ **Example:**
392
+ ```toml
393
+ [[sync.xdg_config]]
394
+ path = "nvim"
395
+ force = true
396
+ ignore = ["lazy-lock.json"]
397
+ ```
398
+
399
+ > [!WARNING]
400
+ > When using `force = true` with the `only` option, only files matching the `only` filter will be managed. Other files in the destination remain untouched.
401
+
402
+ ##### `only` Option
403
+
404
+ An array of relative paths (files or directories) to selectively transfer from the source. This option provides precise control over which files get synchronized.
405
+
406
+ **How it works:**
407
+ - Paths are relative to the `src` directory
408
+ - You can specify entire directories or individual files
409
+ - Parent directories are automatically created as needed
410
+ - Other files in the source are ignored
411
+ - With `force = true`, only files matching the `only` filter are cleaned up in the destination
412
+
413
+ **Example 1: Selecting specific directories**
414
+ ```toml
415
+ [[sync.xdg_config]]
416
+ only = ["nvim", "alacritty", "zsh"]
417
+ ```
418
+ This transfers only the `nvim/`, `alacritty/`, and `zsh/` directories.
419
+
420
+ **Example 2: Selecting specific files**
421
+ ```toml
422
+ [[sync.xdg_config]]
423
+ path = "alacritty"
244
424
  only = ["alacritty.toml", "rose-pine.toml"]
425
+ ```
426
+ This transfers only two specific TOML files from the alacritty config directory.
245
427
 
428
+ **Example 3: Selecting files inside nested directories**
429
+ ```toml
430
+ [[sync.xdg_config]]
431
+ only = ["bundle/config", "ghc/ghci.conf", "cabal/config"]
432
+ ```
433
+ This transfers only specific configuration files from different subdirectories:
434
+ - `bundle/config` file from the `bundle/` directory
435
+ - `ghc/ghci.conf` file from the `ghc/` directory
436
+ - `cabal/config` file from the `cabal/` directory
246
437
 
247
- [[watch.mappings]]
248
- src = "$HOME/.zshenv"
249
- dest = "$HOME_MIRROR/.zshenv"
438
+ The parent directories (`bundle/`, `ghc/`, `cabal/`) are created automatically in the destination, but other files in those directories are not transferred.
250
439
 
251
- [[watch.mappings]]
252
- src = "$XDG_CONFIG_HOME/alacritty"
253
- dest = "$DOTFILES_DIR/config/alacritty"
440
+ **Example 4: Deeply nested paths**
441
+ ```toml
442
+ [[sync.xdg_config]]
443
+ only = ["nvim/lua/plugins/init.lua", "nvim/lua/config/settings.lua"]
254
444
  ```
445
+ This transfers only specific Lua files from deeply nested paths within the nvim configuration.
255
446
 
256
- > [!TIP]
257
- > I use mirror environment variables to cleaner configuration
258
- >
259
- > ```bash
260
- > export XDG_CONFIG_HOME_MIRROR="$HOME/Code/dotfiles/xdg_config_home"
261
- > ```
447
+ **Important behaviors:**
448
+ - **File-specific paths**: When specifying individual files (e.g., `"bundle/config"`), only that file is managed. Sibling files in the same directory are not affected, even with `force = true`.
449
+ - **Directory paths**: When specifying directories (e.g., `"nvim"`), all contents of that directory are managed, including subdirectories.
450
+ - **Combining with `force`**: With `force = true` and directory paths, files in the destination directory that don't exist in the source are removed. With file-specific paths, only that specific file is managed.
262
451
 
263
- #### `force`, `only`, and `ignore` Options in Mappings
452
+ ##### `ignore` Option
264
453
 
265
- Each mapping entry supports the following options:
454
+ An array of relative paths or patterns to exclude during transfer. This allows you to skip certain files or folders.
266
455
 
267
- - **`force`**: A boolean (true/false) value. When set to `true`, it forces deletion of the destination folder before transferring files from the source. This is particularly useful when you need to ensure that the destination is clean before a transfer.
268
- - **`only`**: An array of files or folders. This option ensures that only the specified files or folders from the `src` directory are transferred to the `dest` directory. Example:
269
- ```toml
270
- [[push.mappings]]
271
- src = "$XDG_CONFIG_HOME"
272
- dest = "$DOTFILES_DIR/config"
273
- only = ["config.yml", "themes"]
456
+ **Example:**
457
+ ```toml
458
+ [[sync.xdg_config]]
459
+ path = "nvim"
460
+ ignore = ["lazy-lock.json", "plugin/packer_compiled.lua"]
461
+ ```
274
462
 
275
- ```
276
- - **`ignore`**: An array of patterns or file names to exclude during the transfer. This allows you to specify files or folders that should not be copied from the source to the destination.
463
+ **Combining options:**
464
+ ```toml
465
+ [[sync.xdg_config]]
466
+ path = "nvim"
467
+ only = ["lua", "init.lua"]
468
+ ignore = ["lua/plugin/packer_compiled.lua"]
469
+ force = true
470
+ ```
471
+ This configuration:
472
+ 1. Transfers only the `lua/` directory and `init.lua` file (`only`)
473
+ 2. Excludes `lua/plugin/packer_compiled.lua` even though it's in the `lua/` directory (`ignore`)
474
+ 3. Removes files in the destination that don't exist in the source (`force`)
475
+
476
+ > [!NOTE]
477
+ > When `ignore` and `only` both match a path, `ignore` takes precedence.
277
478
 
278
479
  These options apply when the source is a directory and are relevant for both `push` and `pull` operations.
279
480
 
@@ -335,7 +536,7 @@ By default, all `push` and `pull` commands run in preview mode:
335
536
 
336
537
  Dotsync provides clear, actionable error messages for common issues:
337
538
 
338
- - **Permission Errors**:
539
+ - **Permission Errors**:
339
540
  ```
340
541
  Permission denied: /path/to/file
341
542
  Try: chmod +w <path> or check file permissions
@@ -405,10 +606,8 @@ diff_created = "✨" # New files created
405
606
  diff_updated = "📝" # Files modified
406
607
  diff_removed = "🗑️ " # Files deleted
407
608
 
408
- # Example mappings section
409
- [[pull.mappings]]
410
- src = "$XDG_CONFIG_HOME_MIRROR"
411
- dest = "$XDG_CONFIG_HOME"
609
+ # Example sync mapping
610
+ [[sync.xdg_config]]
412
611
  ignore = ["cache"]
413
612
  ```
414
613
 
@@ -459,10 +658,10 @@ The check runs after your command completes and uses a cached timestamp to avoid
459
658
  ```bash
460
659
  # Work dotfiles
461
660
  dotsync -c ~/work-dotfiles.toml push --apply
462
-
661
+
463
662
  # Personal dotfiles
464
663
  dotsync -c ~/.config/personal.toml pull --apply
465
-
664
+
466
665
  # Server configs
467
666
  dotsync --config ~/server.toml push --apply
468
667
  ```
@@ -471,7 +670,7 @@ The check runs after your command completes and uses a cached timestamp to avoid
471
670
  ```shell
472
671
  # In a script or CI/CD pipeline
473
672
  dotsync pull --apply --yes --quiet
474
-
673
+
475
674
  # Shorthand
476
675
  dotsync push -ayq
477
676
  ```
@@ -513,14 +712,13 @@ The check runs after your command completes and uses a cached timestamp to avoid
513
712
 
514
713
  ## Common Use Cases
515
714
 
516
- Here are some practical examples of how to use Dotsync for popular configuration files:
715
+ Here are practical examples using bidirectional sync for popular configuration files:
517
716
 
518
717
  ### Syncing Neovim Configuration
519
718
 
520
719
  ```toml
521
- [[pull.mappings]]
522
- src = "$HOME/dotfiles/config/nvim"
523
- dest = "$HOME/.config/nvim"
720
+ [[sync.xdg_config]]
721
+ path = "nvim"
524
722
  force = true
525
723
  ignore = ["lazy-lock.json", ".luarc.json"]
526
724
  ```
@@ -528,31 +726,49 @@ ignore = ["lazy-lock.json", ".luarc.json"]
528
726
  ### Syncing Terminal Emulator (Alacritty)
529
727
 
530
728
  ```toml
531
- [[push.mappings]]
532
- src = "$HOME/.config/alacritty"
533
- dest = "$HOME/dotfiles/config/alacritty"
729
+ [[sync.xdg_config]]
730
+ path = "alacritty"
534
731
  only = ["alacritty.toml", "themes"]
535
732
  ```
536
733
 
537
734
  ### Syncing Shell Configuration
538
735
 
539
736
  ```toml
540
- [[pull.mappings]]
541
- src = "$HOME/dotfiles/shell/.zshrc"
542
- dest = "$HOME"
737
+ [[sync.home]]
738
+ path = ".zshenv"
543
739
 
544
- [[pull.mappings]]
545
- src = "$HOME/dotfiles/shell/.zshenv"
546
- dest = "$HOME"
740
+ [[sync.xdg_config]]
741
+ path = "zsh"
742
+ ignore = [".zsh_sessions", ".zsh_history", ".zcompdump"]
547
743
  ```
548
744
 
549
745
  ### Syncing Multiple Config Directories
550
746
 
551
747
  ```toml
552
- [[pull.mappings]]
553
- src = "$HOME/dotfiles/config"
554
- dest = "$HOME/.config"
555
- ignore = ["nvim", "cache", "*.log"]
748
+ [[sync.xdg_config]]
749
+ only = ["nvim", "alacritty", "git", "zsh", "tmux", "starship.toml"]
750
+ force = true
751
+ ```
752
+
753
+ ### Per-Machine Configuration Files
754
+
755
+ Use different config files for different machines:
756
+
757
+ ```toml
758
+ # In dotsync.macbook.toml
759
+ [[sync.mappings]]
760
+ local = "$XDG_CONFIG_HOME/dotsync.toml"
761
+ remote = "$XDG_CONFIG_HOME_MIRROR/dotsync/dotsync.macbook.toml"
762
+
763
+ # In dotsync.work.toml
764
+ [[sync.mappings]]
765
+ local = "$XDG_CONFIG_HOME/dotsync.toml"
766
+ remote = "$XDG_CONFIG_HOME_MIRROR/dotsync/dotsync.work.toml"
767
+ ```
768
+
769
+ Then use `-c` flag to select the appropriate config:
770
+ ```shell
771
+ dotsync -c ~/.config/dotsync/dotsync.macbook.toml push --apply
556
772
  ```
557
773
 
558
774
  ## Troubleshooting
@@ -561,7 +777,7 @@ ignore = ["nvim", "cache", "*.log"]
561
777
 
562
778
  **Problem**: Icons appear as boxes, question marks, or strange characters.
563
779
 
564
- **Solution**:
780
+ **Solution**:
565
781
  - Install a [Nerd Font](https://www.nerdfonts.com/) and configure your terminal to use it
566
782
  - Or customize icons in `~/.config/dotsync.toml` using UTF-8 emojis or regular characters:
567
783
  ```toml