dotsync 0.1.24 → 0.1.25

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: 793ae0a7e00707a97255d631304eddae60e6ce6224d8c4d85c9550f54cbd59bd
4
+ data.tar.gz: 34fdbefc7f9b27a2f7fedd8dcbac9748ae59c99fb7cb15a970ebc67605e5ebe1
5
5
  SHA512:
6
- metadata.gz: c66534cc5d286e4fe7e85a4bff3edecd323db8ad30e653d4bee9d73dfde7277c46305f3c740626223ee302f171ae5f3bddca390805a4af366057a1a17da10a31
7
- data.tar.gz: 4fc6b7b11d3e8086292d85d53cdb54de1d0ddcb11d77761c6e834f915d0db1fdd2cb7a95b56753ddbf426eb8170e697df15c86a4c4a51eb01b945ccc5191b6b8
6
+ metadata.gz: 50471dd7fca75246adb01dd946b17dc217b590cc0df359253f608f4868ae190c08aeb5ce5c9302dafa2533f368c69f35b1f9b3f70143ed36066745729904030b
7
+ data.tar.gz: 2061b3db4dfb07aaec4750efba675091797ce8ebcb9979ce37ffca5e1b838f20d2ebec181925c45d5a0a6c52d4681d05f989953f4022540c0a6705dc8fc6dd76
data/CHANGELOG.md CHANGED
@@ -1,3 +1,26 @@
1
+ # 0.1.25
2
+
3
+ **Features:**
4
+ - Add support for file-specific paths in 'only' configuration option
5
+ - Enable specifying individual files within directories: `only = ["bundle/config", "ghc/ghci.conf"]`
6
+ - Parent directories are automatically created as needed
7
+ - Sibling files in the same directory remain unaffected
8
+ - Works with deeply nested paths: `only = ["nvim/lua/plugins/init.lua"]`
9
+ - Fix DirectoryDiffer to use bidirectional_include? for proper file traversal
10
+
11
+ **Documentation:**
12
+ - Completely rewrite 'force', 'only', and 'ignore' options section in README
13
+ - Add 4 detailed examples showing different use cases
14
+ - Add warnings and notes about combining options
15
+ - Document important behaviors and edge cases
16
+
17
+ **Testing:**
18
+ - Add comprehensive test coverage for file-specific paths in 'only' option
19
+ - Add tests for FileTransfer with nested file paths
20
+ - Add tests for DirectoryDiffer with file-specific only paths
21
+ - Add tests with force mode enabled
22
+ - All 396 tests pass with 96.61% line coverage
23
+
1
24
  # 0.1.24
2
25
 
3
26
  **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.25)
5
5
  fileutils (~> 1.7.3)
6
6
  find (~> 0.2.0)
7
7
  listen (~> 3.9.0)
data/README.md CHANGED
@@ -264,16 +264,107 @@ dest = "$DOTFILES_DIR/config/alacritty"
264
264
 
265
265
  Each mapping entry supports the following options:
266
266
 
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"]
267
+ ##### `force` Option
274
268
 
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.
269
+ 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.
270
+
271
+ **Example:**
272
+ ```toml
273
+ [[pull.mappings]]
274
+ src = "$XDG_CONFIG_HOME_MIRROR/nvim"
275
+ dest = "$XDG_CONFIG_HOME/nvim"
276
+ force = true
277
+ ignore = ["lazy-lock.json"]
278
+ ```
279
+
280
+ > [!WARNING]
281
+ > When using `force = true` with the `only` option, only files matching the `only` filter will be managed. Other files in the destination remain untouched.
282
+
283
+ ##### `only` Option
284
+
285
+ An array of relative paths (files or directories) to selectively transfer from the source. This option provides precise control over which files get synchronized.
286
+
287
+ **How it works:**
288
+ - Paths are relative to the `src` directory
289
+ - You can specify entire directories or individual files
290
+ - Parent directories are automatically created as needed
291
+ - Other files in the source are ignored
292
+ - With `force = true`, only files matching the `only` filter are cleaned up in the destination
293
+
294
+ **Example 1: Selecting specific directories**
295
+ ```toml
296
+ [[push.mappings]]
297
+ src = "$XDG_CONFIG_HOME"
298
+ dest = "$DOTFILES_DIR/config"
299
+ only = ["nvim", "alacritty", "zsh"]
300
+ ```
301
+ This transfers only the `nvim/`, `alacritty/`, and `zsh/` directories.
302
+
303
+ **Example 2: Selecting specific files**
304
+ ```toml
305
+ [[push.mappings]]
306
+ src = "$XDG_CONFIG_HOME/alacritty"
307
+ dest = "$DOTFILES_DIR/config/alacritty"
308
+ only = ["alacritty.toml", "rose-pine.toml"]
309
+ ```
310
+ This transfers only two specific TOML files from the alacritty config directory.
311
+
312
+ **Example 3: Selecting files inside nested directories**
313
+ ```toml
314
+ [[push.mappings]]
315
+ src = "$HOME/.config"
316
+ dest = "$DOTFILES_DIR/config"
317
+ only = ["bundle/config", "ghc/ghci.conf", "cabal/config"]
318
+ ```
319
+ This transfers only specific configuration files from different subdirectories:
320
+ - `bundle/config` file from the `bundle/` directory
321
+ - `ghc/ghci.conf` file from the `ghc/` directory
322
+ - `cabal/config` file from the `cabal/` directory
323
+
324
+ The parent directories (`bundle/`, `ghc/`, `cabal/`) are created automatically in the destination, but other files in those directories are not transferred.
325
+
326
+ **Example 4: Deeply nested paths**
327
+ ```toml
328
+ [[push.mappings]]
329
+ src = "$XDG_CONFIG_HOME"
330
+ dest = "$DOTFILES_DIR/config"
331
+ only = ["nvim/lua/plugins/init.lua", "nvim/lua/config/settings.lua"]
332
+ ```
333
+ This transfers only specific Lua files from deeply nested paths within the nvim configuration.
334
+
335
+ **Important behaviors:**
336
+ - **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`.
337
+ - **Directory paths**: When specifying directories (e.g., `"nvim"`), all contents of that directory are managed, including subdirectories.
338
+ - **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.
339
+
340
+ ##### `ignore` Option
341
+
342
+ An array of relative paths or patterns to exclude during transfer. This allows you to skip certain files or folders.
343
+
344
+ **Example:**
345
+ ```toml
346
+ [[pull.mappings]]
347
+ src = "$XDG_CONFIG_HOME_MIRROR/nvim"
348
+ dest = "$XDG_CONFIG_HOME/nvim"
349
+ ignore = ["lazy-lock.json", "plugin/packer_compiled.lua"]
350
+ ```
351
+
352
+ **Combining options:**
353
+ ```toml
354
+ [[push.mappings]]
355
+ src = "$XDG_CONFIG_HOME/nvim"
356
+ dest = "$DOTFILES_DIR/config/nvim"
357
+ only = ["lua", "init.lua"]
358
+ ignore = ["lua/plugin/packer_compiled.lua"]
359
+ force = true
360
+ ```
361
+ This configuration:
362
+ 1. Transfers only the `lua/` directory and `init.lua` file (`only`)
363
+ 2. Excludes `lua/plugin/packer_compiled.lua` even though it's in the `lua/` directory (`ignore`)
364
+ 3. Removes files in the destination that don't exist in the source (`force`)
365
+
366
+ > [!NOTE]
367
+ > When `ignore` and `only` both match a path, `ignore` takes precedence.
277
368
 
278
369
  These options apply when the source is a directory and are relevant for both `push` and `pull` operations.
279
370
 
data/exe/dotsync CHANGED
@@ -6,6 +6,10 @@ require_relative "../lib/dotsync/version"
6
6
 
7
7
  options = { apply: false, config_path: nil }
8
8
 
9
+ # Initialize logger early for consistent error handling
10
+ require_relative "../lib/dotsync/core"
11
+ logger = Dotsync::Logger.new
12
+
9
13
  opt_parser = OptionParser.new do |opts|
10
14
  opts.banner = <<~BANNER
11
15
  dotsync #{Dotsync::VERSION}
@@ -30,6 +34,7 @@ opt_parser = OptionParser.new do |opts|
30
34
  dotsync diff # Show what would change
31
35
  dotsync watch # Monitor and sync continuously
32
36
  dotsync -c ~/custom.toml push # Use custom config file
37
+ dotsync push --trace # Show full error backtraces
33
38
 
34
39
  Options:
35
40
  -a, --apply Apply changes (push or pull)
@@ -46,6 +51,7 @@ opt_parser = OptionParser.new do |opts|
46
51
  --only-config Show only the config section
47
52
  --only-mappings Show only the mappings section
48
53
  -v, --verbose Force showing all available information
54
+ --trace Show full error backtraces (for debugging)
49
55
  --version Show version number
50
56
  -h, --help Show this help message
51
57
  BANNER
@@ -106,6 +112,10 @@ opt_parser = OptionParser.new do |opts|
106
112
  options[:verbose] = true
107
113
  end
108
114
 
115
+ opts.on("--trace", "Show full error backtraces (for debugging)") do
116
+ options[:trace] = true
117
+ end
118
+
109
119
  opts.on("--version", "Show version number") do
110
120
  puts "dotsync #{Dotsync::VERSION}"
111
121
  exit
@@ -117,12 +127,29 @@ opt_parser = OptionParser.new do |opts|
117
127
  end
118
128
  end
119
129
 
120
- opt_parser.parse!
130
+ begin
131
+ opt_parser.parse!
132
+ rescue OptionParser::InvalidOption, OptionParser::InvalidArgument => e
133
+ # Extract just the problematic option from the error message
134
+ option_match = e.message.match(/invalid (?:option|argument): (.+)/)
135
+ problem = option_match ? option_match[1] : e.message
136
+
137
+ logger.error("Invalid option: #{problem}")
138
+ logger.info("See 'dotsync --help' for available options")
139
+
140
+ if options[:trace]
141
+ logger.log("\nFull backtrace:", color: 240)
142
+ e.backtrace.each { |line| logger.log(" #{line}", color: 240) }
143
+ end
144
+
145
+ exit 1
146
+ end
121
147
 
122
148
  command = ARGV.shift
123
149
 
124
150
  # Load only the dependencies needed for the specific command
125
- case command
151
+ begin
152
+ case command
126
153
  when "push"
127
154
  require_relative "../lib/dotsync/loaders/push_loader"
128
155
  Dotsync::Runner.new(config_path: options[:config_path]).run(:push, options)
@@ -153,9 +180,22 @@ when "diff"
153
180
  Dotsync::Runner.new(config_path: options[:config_path]).run(:push, diff_options)
154
181
  else
155
182
  if command
156
- puts "dotsync: no such command '#{command}'"
183
+ logger.error("Unknown command: '#{command}'")
184
+ logger.info("See 'dotsync --help' for available commands")
157
185
  else
158
186
  puts opt_parser.banner
159
187
  end
160
188
  exit 1
189
+ end
190
+ rescue => e
191
+ logger.error("Unexpected error: #{e.message}")
192
+
193
+ if options[:trace]
194
+ logger.log("\nFull backtrace:", color: 240)
195
+ e.backtrace.each { |line| logger.log(" #{line}", color: 240) }
196
+ else
197
+ logger.info("Run with --trace to see full error details")
198
+ end
199
+
200
+ exit 1
161
201
  end
@@ -36,7 +36,7 @@ module Dotsync
36
36
  Find.find(mapping_src) do |src_path|
37
37
  rel_path = src_path.sub(/^#{Regexp.escape(mapping_src)}\/?/, "")
38
38
 
39
- unless @mapping.include?(src_path)
39
+ unless @mapping.bidirectional_include?(src_path)
40
40
  Find.prune
41
41
  next
42
42
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dotsync
4
- VERSION = "0.1.24"
4
+ VERSION = "0.1.25"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dotsync
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.24
4
+ version: 0.1.25
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Sáenz
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-11-15 00:00:00.000000000 Z
11
+ date: 2025-11-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: toml-rb