dotsync 0.2.1 → 0.2.2

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: 446e27ae6f0c5fdf0e7404ef6c3af8469099f31f052f2b20fe6fc2a9e1d473d1
4
- data.tar.gz: 2d3f33174880e70147d73dea1eb61451bada64f368c3df41d7ac671b6f3759d2
3
+ metadata.gz: 0da622d8ef82d600401b7464c4ad28be7872fa942c252d00273378bcbdab2788
4
+ data.tar.gz: db97edbc75bb40ddd8353d97d2b3d255da9caa298dde368a58963e1f000bbc2d
5
5
  SHA512:
6
- metadata.gz: d0d9f9ade95a25d75762cb8e4531aa5cc68d23d6ea199cf3f57968c59c369dae54e34bf9c0b8c0b34da8e403df9ea400f580af2c7903f5c8927e43fa77b38f55
7
- data.tar.gz: 8a8ea902f8e1dd09c3c60895a9144761aa4e893e2411b5ee545088f011269fc9230e5ad5eb7d5a18c0438550adddfe979b9a93a534da6cac35c9ff58fcb61bfe
6
+ metadata.gz: f1f7fd2a2bb4d39df4c8a4286fb4ce750b55f5e3d4b0fb1a1bfa6a7902f5e6106919bb4dd1981057c583931fd4bf6534c64dc8161175caf38159bcb9dd5f93d5
7
+ data.tar.gz: a79078d32865500b76f5a27959bc426523a73ea31ec966aee7085b4786e024f9b7716dce1cb014323848228c64706618b91a9dfcd1a8ff5913817f165996c426
data/CHANGELOG.md CHANGED
@@ -1,3 +1,23 @@
1
+ ## [0.2.2] - 2025-02-07
2
+
3
+ **New Features:**
4
+ - Add glob pattern support to `only` filter (#15)
5
+ - `*` matches any sequence of characters (e.g., `local.*.plist`)
6
+ - `?` matches any single character (e.g., `config.?`)
7
+ - `[charset]` matches any character in the set (e.g., `log.[0-9]`)
8
+ - Glob and exact paths can be mixed in the same `only` array
9
+ - Non-glob entries retain existing exact path matching behavior
10
+
11
+ **Documentation:**
12
+ - Document glob pattern support in README with examples
13
+ - Add "Glob patterns" to the `only` option important behaviors section
14
+
15
+ **Testing:**
16
+ - Add unit tests for glob matching in `include?`, `bidirectional_include?`, `skip?`, `should_prune_directory?`
17
+ - Add integration tests for glob patterns in FileTransfer (including force mode)
18
+ - Add integration tests for glob patterns in DirectoryDiffer
19
+ - All 432 tests pass with 96.29% line coverage
20
+
1
21
  ## [0.2.1] - 2025-02-06
2
22
 
3
23
  **Performance Optimizations:**
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dotsync (0.2.1)
4
+ dotsync (0.2.2)
5
5
  fileutils (~> 1.7.3)
6
6
  find (~> 0.2.0)
7
7
  listen (~> 3.9.0)
data/README.md CHANGED
@@ -401,11 +401,11 @@ ignore = ["lazy-lock.json"]
401
401
 
402
402
  ##### `only` Option
403
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.
404
+ An array of relative paths (files or directories) or glob patterns to selectively transfer from the source. This option provides precise control over which files get synchronized.
405
405
 
406
406
  **How it works:**
407
407
  - Paths are relative to the `src` directory
408
- - You can specify entire directories or individual files
408
+ - You can specify entire directories, individual files, or glob patterns (`*`, `?`, `[charset]`)
409
409
  - Parent directories are automatically created as needed
410
410
  - Other files in the source are ignored
411
411
  - With `force = true`, only files matching the `only` filter are cleaned up in the destination
@@ -437,7 +437,27 @@ This transfers only specific configuration files from different subdirectories:
437
437
 
438
438
  The parent directories (`bundle/`, `ghc/`, `cabal/`) are created automatically in the destination, but other files in those directories are not transferred.
439
439
 
440
- **Example 4: Deeply nested paths**
440
+ **Example 4: Glob patterns**
441
+ ```toml
442
+ [[sync.home]]
443
+ path = "Library/LaunchAgents"
444
+ only = ["local.*.plist"]
445
+ ```
446
+ This transfers only files matching the glob pattern — e.g., `local.brew.upgrade.plist`, `local.ollama.plist` — while ignoring system-generated plists like `com.apple.*.plist`.
447
+
448
+ Supported glob characters:
449
+ - `*` — matches any sequence of characters (e.g., `local.*.plist`)
450
+ - `?` — matches any single character (e.g., `config.?`)
451
+ - `[charset]` — matches any character in the set (e.g., `log.[0-9]`)
452
+
453
+ Glob patterns can be mixed with exact paths in the same `only` array:
454
+ ```toml
455
+ [[sync.home]]
456
+ path = "Library/LaunchAgents"
457
+ only = ["local.*.plist", "README.md"]
458
+ ```
459
+
460
+ **Example 5: Deeply nested paths**
441
461
  ```toml
442
462
  [[sync.xdg_config]]
443
463
  only = ["nvim/lua/plugins/init.lua", "nvim/lua/config/settings.lua"]
@@ -447,7 +467,8 @@ This transfers only specific Lua files from deeply nested paths within the nvim
447
467
  **Important behaviors:**
448
468
  - **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
469
  - **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.
470
+ - **Glob patterns**: When using patterns (e.g., `"local.*.plist"`), only files whose names match the pattern are managed. Non-matching files in the same directory are untouched.
471
+ - **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 or glob patterns, only matching files are managed.
451
472
 
452
473
  ##### `ignore` Option
453
474
 
@@ -140,13 +140,13 @@ module Dotsync
140
140
  def include?(path)
141
141
  return true unless has_inclusions?
142
142
  return true if path == src
143
- inclusions.any? { |inclusion| path_is_parent_or_same?(inclusion, path) }
143
+ inclusions.any? { |inclusion| inclusion_matches?(inclusion, path) }
144
144
  end
145
145
 
146
146
  def bidirectional_include?(path)
147
147
  return true unless has_inclusions?
148
148
  return true if path == src
149
- inclusions.any? { |inclusion| path_is_parent_or_same?(inclusion, path) || path_is_parent_or_same?(path, inclusion) }
149
+ inclusions.any? { |inclusion| inclusion_matches?(inclusion, path) || inclusion_is_ancestor?(path, inclusion) }
150
150
  end
151
151
 
152
152
  def ignore?(path)
@@ -179,6 +179,26 @@ module Dotsync
179
179
  end
180
180
 
181
181
  private
182
+ def glob_pattern?(path)
183
+ path.match?(/[*?\[]/)
184
+ end
185
+
186
+ def inclusion_matches?(inclusion, path)
187
+ if glob_pattern?(inclusion)
188
+ File.fnmatch(inclusion, path)
189
+ else
190
+ path_is_parent_or_same?(inclusion, path)
191
+ end
192
+ end
193
+
194
+ def inclusion_is_ancestor?(path, inclusion)
195
+ if glob_pattern?(inclusion)
196
+ path_is_parent_or_same?(path, File.dirname(inclusion))
197
+ else
198
+ path_is_parent_or_same?(path, inclusion)
199
+ end
200
+ end
201
+
182
202
  def has_ignores?
183
203
  @original_ignores.any?
184
204
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dotsync
4
- VERSION = "0.2.1"
4
+ VERSION = "0.2.2"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dotsync
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Sáenz