dotsync 0.1.3 → 0.1.5

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: e8cf43f8c36d398e1f87c3dd0e84ec9e36a6b1da7de4b3002546f0bbacb3e4ff
4
- data.tar.gz: b32a336b5a4e63983a4a6ee3a7bcc4f50cb70ccd268a0066f8343e05fa8cf5d7
3
+ metadata.gz: 62ac42fee1c4a3358014f4b4d9bd8e63794b1815ad1beb5234d6a61f0815b58d
4
+ data.tar.gz: 3bad18f98f83603d52bbcb6b6278d8b8b5e41ca4386adddfd8303785a9892347
5
5
  SHA512:
6
- metadata.gz: 28e35c812f55e418525df64090b3b119f250561f209a1e2788218e4a0c41360824aaba93531cd6ad969d022795a0b7a92e046c26e62dad829d64535d7f7d995b
7
- data.tar.gz: d8812f07850fa2823448e59a78471655735a9b7f78f6d9983ab8e5c83aa8adf887b47dd4e517901046666d85d412bbd5ea08e07656aee8186aceeaf4f2f441bd
6
+ metadata.gz: 8d5db370521fbe7f210f27172d95301ebb182f058c391468359fd51f2aed9d1d2306deddd7911b0cb0b786150155b34667d3611b6aa6c22e606e6e74684f6a0c
7
+ data.tar.gz: cffff97956e3aaabd2f6de871ac76441a042abd0d7d0d51dc452c73d1c397cec8cf7e4121421bd814e3620cf5a047cbf1060c162e52f56c1d04d15ba23bcb068
@@ -29,6 +29,10 @@ jobs:
29
29
  run: |
30
30
  bundle exec rake
31
31
 
32
+ - name: Run RuboCop
33
+ run: |
34
+ bundle exec rubocop
35
+
32
36
  - name: Publish to RubyGems
33
37
  if: matrix.ruby == '3.2'
34
38
  run: |
data/.rubocop.yml ADDED
@@ -0,0 +1,353 @@
1
+ plugins:
2
+ - rubocop-rspec
3
+ - rubocop-performance
4
+ - rubocop-md
5
+ - rubocop-rake
6
+
7
+ AllCops:
8
+ # RuboCop has a bunch of cops enabled by default. This setting tells RuboCop
9
+ # to ignore them, so only the ones explicitly set in this file are enabled.
10
+ DisabledByDefault: true
11
+
12
+ Performance:
13
+ Exclude:
14
+ - '**/test/**/*'
15
+
16
+ # Prefer &&/|| over and/or.
17
+ Style/AndOr:
18
+ Enabled: true
19
+
20
+ Layout/ClosingHeredocIndentation:
21
+ Enabled: true
22
+
23
+ Layout/ClosingParenthesisIndentation:
24
+ Enabled: true
25
+
26
+ # Align comments with method definitions.
27
+ Layout/CommentIndentation:
28
+ Enabled: true
29
+
30
+ Layout/DefEndAlignment:
31
+ Enabled: true
32
+
33
+ Layout/ElseAlignment:
34
+ Enabled: true
35
+
36
+ # Align `end` with the matching keyword or starting expression except for
37
+ # assignments, where it should be aligned with the LHS.
38
+ Layout/EndAlignment:
39
+ Enabled: true
40
+ EnforcedStyleAlignWith: variable
41
+ AutoCorrect: true
42
+
43
+ Layout/EndOfLine:
44
+ Enabled: true
45
+
46
+ Layout/EmptyLineAfterMagicComment:
47
+ Enabled: true
48
+
49
+ Layout/EmptyLinesAroundAccessModifier:
50
+ Enabled: true
51
+ EnforcedStyle: only_before
52
+
53
+ Layout/EmptyLinesAroundBlockBody:
54
+ Enabled: true
55
+
56
+ # In a regular class definition, no empty lines around the body.
57
+ Layout/EmptyLinesAroundClassBody:
58
+ Enabled: true
59
+
60
+ # In a regular method definition, no empty lines around the body.
61
+ Layout/EmptyLinesAroundMethodBody:
62
+ Enabled: true
63
+
64
+ # In a regular module definition, no empty lines around the body.
65
+ Layout/EmptyLinesAroundModuleBody:
66
+ Enabled: true
67
+
68
+ # Use Ruby >= 1.9 syntax for hashes. Prefer { a: :b } over { :a => :b }.
69
+ Style/HashSyntax:
70
+ Enabled: true
71
+ EnforcedShorthandSyntax: either
72
+
73
+ # Method definitions after `private` or `protected` isolated calls need one
74
+ # extra level of indentation.
75
+ Layout/IndentationConsistency:
76
+ Enabled: true
77
+ EnforcedStyle: indented_internal_methods
78
+ Exclude:
79
+ - '**/*.md'
80
+
81
+ # Two spaces, no tabs (for indentation).
82
+ Layout/IndentationWidth:
83
+ Enabled: true
84
+
85
+ Layout/LeadingCommentSpace:
86
+ Enabled: true
87
+
88
+ Layout/SpaceAfterColon:
89
+ Enabled: true
90
+
91
+ Layout/SpaceAfterComma:
92
+ Enabled: true
93
+
94
+ Layout/SpaceAfterSemicolon:
95
+ Enabled: true
96
+
97
+ Layout/SpaceAroundEqualsInParameterDefault:
98
+ Enabled: true
99
+
100
+ Layout/SpaceAroundKeyword:
101
+ Enabled: true
102
+
103
+ Layout/SpaceAroundOperators:
104
+ Enabled: true
105
+
106
+ Layout/SpaceBeforeComma:
107
+ Enabled: true
108
+
109
+ Layout/SpaceBeforeComment:
110
+ Enabled: true
111
+
112
+ Layout/SpaceBeforeFirstArg:
113
+ Enabled: true
114
+
115
+ Style/DefWithParentheses:
116
+ Enabled: true
117
+
118
+ # Defining a method with parameters needs parentheses.
119
+ Style/MethodDefParentheses:
120
+ Enabled: true
121
+
122
+ Style/ExplicitBlockArgument:
123
+ Enabled: true
124
+
125
+ Style/FrozenStringLiteralComment:
126
+ Enabled: true
127
+ EnforcedStyle: always
128
+ Exclude:
129
+ - 'actionview/test/**/*.builder'
130
+ - 'actionview/test/**/*.ruby'
131
+ - 'actionpack/test/**/*.builder'
132
+ - 'actionpack/test/**/*.ruby'
133
+ - 'activestorage/db/migrate/**/*.rb'
134
+ - 'activestorage/db/update_migrate/**/*.rb'
135
+ - 'actionmailbox/db/migrate/**/*.rb'
136
+ - 'actiontext/db/migrate/**/*.rb'
137
+ - '**/*.md'
138
+
139
+ Style/MapToHash:
140
+ Enabled: true
141
+
142
+ Style/RedundantFreeze:
143
+ Enabled: true
144
+
145
+ # Use `foo {}` not `foo{}`.
146
+ Layout/SpaceBeforeBlockBraces:
147
+ Enabled: true
148
+
149
+ # Use `foo { bar }` not `foo {bar}`.
150
+ Layout/SpaceInsideBlockBraces:
151
+ Enabled: true
152
+ EnforcedStyleForEmptyBraces: space
153
+
154
+ # Use `{ a: 1 }` not `{a:1}`.
155
+ Layout/SpaceInsideHashLiteralBraces:
156
+ Enabled: true
157
+
158
+ Layout/SpaceInsideParens:
159
+ Enabled: true
160
+
161
+ # Check quotes usage according to lint rule below.
162
+ Style/StringLiterals:
163
+ Enabled: true
164
+ EnforcedStyle: double_quotes
165
+
166
+ # Detect hard tabs, no hard tabs.
167
+ Layout/IndentationStyle:
168
+ Enabled: true
169
+
170
+ # Empty lines should not have any spaces.
171
+ Layout/TrailingEmptyLines:
172
+ Enabled: true
173
+
174
+ # No trailing whitespace.
175
+ Layout/TrailingWhitespace:
176
+ Enabled: true
177
+
178
+ # Use quotes for string literals when they are enough.
179
+ Style/RedundantPercentQ:
180
+ Enabled: true
181
+
182
+ Lint/NestedMethodDefinition:
183
+ Enabled: true
184
+
185
+ Lint/AmbiguousOperator:
186
+ Enabled: true
187
+
188
+ Lint/AmbiguousRegexpLiteral:
189
+ Enabled: true
190
+
191
+ Lint/Debugger:
192
+ Enabled: true
193
+ DebuggerRequires:
194
+ - debug
195
+
196
+ Lint/DuplicateRequire:
197
+ Enabled: true
198
+
199
+ Lint/DuplicateMagicComment:
200
+ Enabled: true
201
+
202
+ Lint/DuplicateMethods:
203
+ Enabled: true
204
+
205
+ Lint/ErbNewArguments:
206
+ Enabled: true
207
+
208
+ Lint/EnsureReturn:
209
+ Enabled: true
210
+
211
+ Lint/MissingCopEnableDirective:
212
+ Enabled: true
213
+
214
+ # Use my_method(my_arg) not my_method( my_arg ) or my_method my_arg.
215
+ Lint/RequireParentheses:
216
+ Enabled: true
217
+
218
+ Lint/RedundantCopDisableDirective:
219
+ Enabled: true
220
+
221
+ Lint/RedundantCopEnableDirective:
222
+ Enabled: true
223
+
224
+ Lint/RedundantRequireStatement:
225
+ Enabled: true
226
+
227
+ Lint/RedundantStringCoercion:
228
+ Enabled: true
229
+
230
+ Lint/RedundantSafeNavigation:
231
+ Enabled: true
232
+
233
+ Lint/UriEscapeUnescape:
234
+ Enabled: true
235
+
236
+ Lint/UselessAssignment:
237
+ Enabled: true
238
+
239
+ Lint/DeprecatedClassMethods:
240
+ Enabled: true
241
+
242
+ Lint/InterpolationCheck:
243
+ Enabled: true
244
+ Exclude:
245
+ - '**/test/**/*'
246
+
247
+ Lint/SafeNavigationChain:
248
+ Enabled: true
249
+
250
+ Style/EvalWithLocation:
251
+ Enabled: true
252
+ Exclude:
253
+ - '**/test/**/*'
254
+
255
+ Style/ParenthesesAroundCondition:
256
+ Enabled: true
257
+
258
+ Style/HashTransformKeys:
259
+ Enabled: true
260
+
261
+ Style/HashTransformValues:
262
+ Enabled: true
263
+
264
+ Style/RedundantBegin:
265
+ Enabled: true
266
+
267
+ Style/RedundantReturn:
268
+ Enabled: true
269
+ AllowMultipleReturnValues: true
270
+
271
+ Style/RedundantRegexpEscape:
272
+ Enabled: true
273
+
274
+ Style/Semicolon:
275
+ Enabled: true
276
+ AllowAsExpressionSeparator: true
277
+
278
+ # Prefer Foo.method over Foo::method
279
+ Style/ColonMethodCall:
280
+ Enabled: true
281
+
282
+ Style/TrivialAccessors:
283
+ Enabled: true
284
+
285
+ # Prefer a = b || c over a = b ? b : c
286
+ Style/RedundantCondition:
287
+ Enabled: true
288
+
289
+ Style/RedundantDoubleSplatHashBraces:
290
+ Enabled: true
291
+
292
+ Style/OpenStructUse:
293
+ Enabled: true
294
+
295
+ Style/ArrayIntersect:
296
+ Enabled: true
297
+
298
+ Style/KeywordArgumentsMerging:
299
+ Enabled: true
300
+
301
+ Performance/BindCall:
302
+ Enabled: true
303
+
304
+ Performance/FlatMap:
305
+ Enabled: true
306
+
307
+ Performance/MapCompact:
308
+ Enabled: true
309
+
310
+ Performance/SelectMap:
311
+ Enabled: true
312
+
313
+ Performance/RedundantMerge:
314
+ Enabled: true
315
+
316
+ Performance/StartWith:
317
+ Enabled: true
318
+
319
+ Performance/EndWith:
320
+ Enabled: true
321
+
322
+ Performance/RegexpMatch:
323
+ Enabled: true
324
+
325
+ Performance/ReverseEach:
326
+ Enabled: true
327
+
328
+ Performance/StringReplacement:
329
+ Enabled: true
330
+
331
+ Performance/DeletePrefix:
332
+ Enabled: true
333
+
334
+ Performance/DeleteSuffix:
335
+ Enabled: true
336
+
337
+ Performance/InefficientHashSearch:
338
+ Enabled: true
339
+
340
+ Performance/ConstantRegexp:
341
+ Enabled: true
342
+
343
+ Performance/RedundantStringChars:
344
+ Enabled: true
345
+
346
+ Performance/StringInclude:
347
+ Enabled: true
348
+
349
+ Markdown:
350
+ # Whether to run RuboCop against non-valid snippets
351
+ WarnInvalid: true
352
+ # Whether to lint codeblocks without code attributes
353
+ Autodetect: false
data/CHANGELOG.md CHANGED
@@ -1,12 +1,23 @@
1
+ # 0.1.5
2
+
3
+ - Fixes backup when destination folder does not exist
4
+ - Add rubocop
5
+
6
+
7
+ # 0.1.4
8
+
9
+ - Colorized environment variables
10
+ - Fixed colorized mapping entries
11
+
1
12
  # 0.1.3
2
13
 
3
- PushAction: Avoid error on missing destination
4
- Unify mappings print. Use icon for ignores presence.
5
- Extracted icons to its own module
6
- Reviewed icons
7
- Updated README with existing mapping entries icons
8
- Customizable icons
9
- Logger review
14
+ - PushAction: Avoid error on missing destination
15
+ - Unify mappings print. Use icon for ignores presence.
16
+ - Extracted icons to its own module
17
+ - Reviewed icons
18
+ - Updated README with existing mapping entries icons
19
+ - Customizable icons
20
+ - Logger review
10
21
 
11
22
  # 0.1.2
12
23
 
data/Gemfile CHANGED
@@ -4,10 +4,3 @@ source "https://rubygems.org"
4
4
 
5
5
  # Specify your gem's dependencies in dotsync.gemspec
6
6
  gemspec
7
-
8
- # gem "irb"
9
- # gem "rake", "~> 13.0"
10
- #
11
- # gem "rspec", "~> 3.0"
12
- #
13
- # gem "rubocop", "~> 1.21"
data/Gemfile.lock CHANGED
@@ -1,10 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dotsync (0.1.3)
4
+ dotsync (0.1.5)
5
5
  fileutils (~> 1.7.3)
6
6
  listen (~> 3.9.0)
7
7
  logger (~> 1.7.0)
8
+ ostruct (~> 0.6.3)
8
9
  toml-rb (~> 4.0.0)
9
10
 
10
11
  GEM
@@ -25,18 +26,19 @@ GEM
25
26
  ffi (1.17.2-x86_64-linux-gnu)
26
27
  ffi (1.17.2-x86_64-linux-musl)
27
28
  fileutils (1.7.3)
28
- json (2.15.0)
29
+ json (2.15.2)
29
30
  language_server-protocol (3.17.0.5)
30
31
  lint_roller (1.1.0)
31
32
  listen (3.9.0)
32
33
  rb-fsevent (~> 0.10, >= 0.10.3)
33
34
  rb-inotify (~> 0.9, >= 0.9.10)
34
35
  logger (1.7.0)
36
+ ostruct (0.6.3)
35
37
  parallel (1.27.0)
36
38
  parser (3.3.9.0)
37
39
  ast (~> 2.4.1)
38
40
  racc
39
- prism (1.5.1)
41
+ prism (1.6.0)
40
42
  racc (1.8.1)
41
43
  rainbow (3.1.1)
42
44
  rake (13.3.0)
@@ -46,20 +48,20 @@ GEM
46
48
  rbs (3.9.5)
47
49
  logger
48
50
  regexp_parser (2.11.3)
49
- rspec (3.13.1)
51
+ rspec (3.13.2)
50
52
  rspec-core (~> 3.13.0)
51
53
  rspec-expectations (~> 3.13.0)
52
54
  rspec-mocks (~> 3.13.0)
53
- rspec-core (3.13.5)
55
+ rspec-core (3.13.6)
54
56
  rspec-support (~> 3.13.0)
55
57
  rspec-expectations (3.13.5)
56
58
  diff-lcs (>= 1.2.0, < 2.0)
57
59
  rspec-support (~> 3.13.0)
58
- rspec-mocks (3.13.5)
60
+ rspec-mocks (3.13.6)
59
61
  diff-lcs (>= 1.2.0, < 2.0)
60
62
  rspec-support (~> 3.13.0)
61
63
  rspec-support (3.13.6)
62
- rubocop (1.81.1)
64
+ rubocop (1.81.6)
63
65
  json (~> 2.3)
64
66
  language_server-protocol (~> 3.17.0.2)
65
67
  lint_roller (~> 1.1.0)
@@ -73,6 +75,19 @@ GEM
73
75
  rubocop-ast (1.47.1)
74
76
  parser (>= 3.3.7.2)
75
77
  prism (~> 1.4)
78
+ rubocop-md (2.0.3)
79
+ lint_roller (~> 1.1)
80
+ rubocop (>= 1.72.1)
81
+ rubocop-performance (1.26.1)
82
+ lint_roller (~> 1.1)
83
+ rubocop (>= 1.75.0, < 2.0)
84
+ rubocop-ast (>= 1.47.1, < 2.0)
85
+ rubocop-rake (0.7.1)
86
+ lint_roller (~> 1.1)
87
+ rubocop (>= 1.72.1)
88
+ rubocop-rspec (3.7.0)
89
+ lint_roller (~> 1.1)
90
+ rubocop (~> 1.72, >= 1.72.1)
76
91
  ruby-lsp (0.26.1)
77
92
  language_server-protocol (~> 3.17.0)
78
93
  prism (>= 1.2, < 2.0)
@@ -104,6 +119,10 @@ DEPENDENCIES
104
119
  rake (~> 13.3.0)
105
120
  rspec (~> 3.13.1)
106
121
  rubocop (~> 1.81.1)
122
+ rubocop-md
123
+ rubocop-performance
124
+ rubocop-rake
125
+ rubocop-rspec
107
126
  ruby-lsp (~> 0.26.1)
108
127
  timecop (~> 0.9.10)
109
128
 
data/README.md CHANGED
@@ -11,7 +11,7 @@ Welcome to Dotsync! This gem helps you manage and synchronize your dotfiles effo
11
11
  Add this line to your application's Gemfile:
12
12
 
13
13
  ```ruby
14
- gem 'dotsync'
14
+ gem "dotsync"
15
15
  ```
16
16
 
17
17
  And then execute:
data/Rakefile CHANGED
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "bundler/gem_tasks"
2
4
  require "rspec/core/rake_task"
3
5
 
4
- require 'dotsync'
6
+ require "dotsync"
5
7
 
6
8
  # Load all tasks
7
- Dir.glob(File.join(Gem.loaded_specs['dotsync'].full_gem_path, 'lib', 'dotsync', 'tasks', '**/*.rake')).each { |f| load f }
9
+ Dir.glob(File.join(Gem.loaded_specs["dotsync"].full_gem_path, "lib", "dotsync", "tasks", "**/*.rake")).each { |f| load f }
8
10
 
9
11
  RSpec::Core::RakeTask.new(:spec) do |t|
10
12
  # ENV['TEST_ENV'] = 'true'
data/dotsync.gemspec CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "lib/dotsync/version"
2
4
 
3
5
  Gem::Specification.new do |spec|
@@ -18,7 +20,7 @@ Gem::Specification.new do |spec|
18
20
 
19
21
  # Specify which files should be added to the gem when it is released.
20
22
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
21
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
23
+ spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
22
24
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
23
25
  end
24
26
  spec.bindir = "exe"
@@ -29,9 +31,14 @@ Gem::Specification.new do |spec|
29
31
  spec.add_dependency "listen", "~> 3.9.0"
30
32
  spec.add_dependency "fileutils", "~> 1.7.3"
31
33
  spec.add_dependency "logger", "~> 1.7.0" # No longer part of default gems from Ruby 3.5
34
+ spec.add_dependency "ostruct", "~> 0.6.3" # No longer part of default gems from Ruby 3.5
32
35
  spec.add_development_dependency "rake", "~> 13.3.0"
33
36
  spec.add_development_dependency "rspec", "~> 3.13.1"
34
37
  spec.add_development_dependency "rubocop", "~> 1.81.1"
38
+ spec.add_development_dependency "rubocop-rspec"
39
+ spec.add_development_dependency "rubocop-performance"
40
+ spec.add_development_dependency "rubocop-rake"
41
+ spec.add_development_dependency "rubocop-md"
35
42
  spec.add_development_dependency "timecop", "~> 0.9.10"
36
43
  spec.add_development_dependency "ruby-lsp", "~> 0.26.1"
37
44
  end
data/exe/console CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require "bundler/setup"
4
5
  require "dotsync"
data/exe/dotsync CHANGED
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- require_relative '../lib/dotsync'
4
- require 'optparse'
4
+ require_relative "../lib/dotsync"
5
+ require "optparse"
5
6
 
6
- options = {}
7
+ {}
7
8
 
8
9
  opt_parser = OptionParser.new do |opts|
9
10
  opts.banner = <<~BANNER
@@ -44,4 +45,3 @@ else
44
45
  end
45
46
  exit 1
46
47
  end
47
-
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dotsync
2
4
  class BaseAction
3
5
  include Dotsync::PathUtils
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dotsync
2
4
  module MappingsTransfer
3
5
  extend Forwardable # def_delegator
@@ -5,10 +7,10 @@ module Dotsync
5
7
  def_delegator :@config, :mappings
6
8
 
7
9
  def show_mappings
8
- info("Mappings:", icon: :config, )
10
+ info("Mappings:", icon: :config,)
9
11
 
10
12
  mappings.each do |mapping|
11
- info(" #{mapping}")
13
+ logger.log(" #{mapping}")
12
14
  end
13
15
  end
14
16
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dotsync
2
4
  # BaseConfig serves as an abstract class to define the structure
3
5
  # and validation rules for configuration files in the Dotsync system.
@@ -15,7 +17,6 @@ module Dotsync
15
17
  end
16
18
 
17
19
  private
18
-
19
20
  # Validates the configuration file.
20
21
  #
21
22
  # @raise [NotImplementedError] if not implemented by a subclass.
@@ -1,14 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dotsync
2
4
  class MappingEntry
3
5
  include Dotsync::PathUtils
4
6
 
5
7
  attr_reader :original_src, :original_dest, :original_ignores
6
8
 
7
- def initialize(hash)
8
- @original_src = hash["src"]
9
- @original_dest = hash["dest"]
10
- @original_ignores = Array(hash["ignore"])
11
- @force = hash["force"] || false
9
+ def initialize(attributes)
10
+ @original_src = attributes["src"]
11
+ @original_dest = attributes["dest"]
12
+ @original_ignores = Array(attributes["ignore"])
13
+ @force = attributes["force"] || false
12
14
 
13
15
  @sanitized_src = sanitize_path(@original_src)
14
16
  @sanitized_dest = sanitize_path(@original_dest)
@@ -32,11 +34,25 @@ module Dotsync
32
34
  end
33
35
 
34
36
  def valid?
35
- File.exist?(@sanitized_src) && File.exist?(File.dirname(@sanitized_dest))
37
+ (File.file?(src) && File.file?(dest)) ||
38
+ (File.directory?(src) && File.directory?(dest)) ||
39
+ (File.file?(src) && !File.exist?(dest) && File.directory?(File.dirname(dest)))
40
+ end
41
+
42
+ def backup_possible?
43
+ valid? && File.exist?(dest)
44
+ end
45
+
46
+ def backup_basename
47
+ return unless valid?
48
+ return File.dirname(dest) unless File.exist?(dest)
49
+ File.basename(dest)
36
50
  end
37
51
 
38
52
  def to_s
39
- msg = ["#{original_src} → #{original_dest}"]
53
+ colorized_src = colorize_env_vars(original_src)
54
+ colorized_dest = colorize_env_vars(original_dest)
55
+ msg = ["#{colorized_src} → #{colorized_dest}"]
40
56
  msg << Icons.force if force?
41
57
  msg << Icons.ignore if ignores?
42
58
  msg << Icons.invalid unless valid?
@@ -59,10 +75,8 @@ module Dotsync
59
75
  end
60
76
 
61
77
  private
62
-
63
- def ignores?
64
- @original_ignores.any?
65
- end
78
+ def ignores?
79
+ @original_ignores.any?
80
+ end
66
81
  end
67
82
  end
68
-
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dotsync
2
4
  class PullActionConfig < BaseConfig
3
5
  include XDGBaseDirectorySpec
@@ -12,7 +14,6 @@ module Dotsync
12
14
  end
13
15
 
14
16
  private
15
-
16
17
  SECTION_NAME = "pull"
17
18
 
18
19
  def section_name
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dotsync
2
4
  class PushActionConfig < BaseConfig
3
5
  def mappings
@@ -6,7 +8,6 @@ module Dotsync
6
8
  end
7
9
 
8
10
  private
9
-
10
11
  SECTION_NAME = "push"
11
12
 
12
13
  def section_name
@@ -1,8 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dotsync
2
4
  class WatchActionConfig < PushActionConfig
3
-
4
5
  private
5
-
6
6
  SECTION_NAME = "watch"
7
7
 
8
8
  def section_name
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dotsync
2
4
  # https://specifications.freedesktop.org/basedir-spec/latest/
3
5
  module XDGBaseDirectorySpec
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dotsync
2
4
  class PullAction < BaseAction
3
5
  include MappingsTransfer
@@ -14,7 +16,6 @@ module Dotsync
14
16
  end
15
17
 
16
18
  private
17
-
18
19
  def show_config
19
20
  show_mappings
20
21
  end
@@ -22,44 +23,46 @@ module Dotsync
22
23
  def pull_dotfiles
23
24
  transfer_mappings
24
25
 
25
- action("Dotfiles pulled", icon: :copy)
26
+ action("Dotfiles pulled")
26
27
  end
27
28
 
28
29
  def show_backup
29
- action("Backup created:", icon: :backup)
30
- info(" #{backup_path}")
30
+ action("Backup created:")
31
+ logger.log(" #{backup_root_path}")
31
32
  end
32
33
 
33
34
  def timestamp
34
- Time.now.strftime('%Y%m%d%H%M%S')
35
+ Time.now.strftime("%Y%m%d%H%M%S")
35
36
  end
36
37
 
37
- def backup_path
38
- @backup_path ||= File.join(backups_root, timestamp)
38
+ def backup_root_path
39
+ @backup_root_path ||= File.join(backups_root, timestamp)
39
40
  end
40
41
 
41
42
  def create_backup
42
43
  return false unless valid_mappings.any?
43
- FileUtils.mkdir_p(backup_path)
44
- mappings.each do |mapping|
45
- next unless File.exist?(mapping.dest)
44
+ FileUtils.mkdir_p(backup_root_path)
45
+ valid_mappings.each do |mapping|
46
+ next unless mapping.backup_possible?
47
+ backup_path = File.join(backup_root_path, mapping.backup_basename)
46
48
  if File.file?(mapping.src)
47
- FileUtils.cp(mapping.dest, File.join(backup_path, File.basename(mapping.dest)))
49
+ FileUtils.cp(mapping.dest, backup_path)
48
50
  else
49
- FileUtils.cp_r(mapping.dest, File.join(backup_path, File.basename(mapping.dest)))
51
+ FileUtils.cp_r(mapping.dest, backup_path)
50
52
  end
51
53
  end
52
54
  true
53
55
  end
54
56
 
55
57
  def purge_old_backups
56
- backups = Dir[File.join(backups_root, '*')].sort.reverse
58
+ backups = Dir[File.join(backups_root, "*")].sort.reverse
57
59
  if backups.size > 10
58
- info("Maximum of 10 backups retained")
60
+ logger.log("Maximum of 10 backups retained")
59
61
 
62
+ action("Backup deleted:")
60
63
  backups[10..].each do |path|
61
64
  FileUtils.rm_rf(path)
62
- info("Old backup deleted: #{path}", icon: :delete)
65
+ logger.log(" #{path}")
63
66
  end
64
67
  end
65
68
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dotsync
2
4
  class PushAction < BaseAction
3
5
  include MappingsTransfer
@@ -8,15 +10,14 @@ module Dotsync
8
10
  end
9
11
 
10
12
  private
13
+ def show_config
14
+ show_mappings
15
+ end
11
16
 
12
- def show_config
13
- show_mappings
14
- end
15
-
16
- def push_dotfiles
17
- transfer_mappings
17
+ def push_dotfiles
18
+ transfer_mappings
18
19
 
19
- action("Dotfiles pushed", icon: :copy)
20
- end
20
+ action("Dotfiles pushed", icon: :copy)
21
+ end
21
22
  end
22
23
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dotsync
2
4
  class WatchAction < BaseAction
3
5
  def_delegator :@config, :mappings
@@ -19,7 +21,6 @@ module Dotsync
19
21
  end
20
22
 
21
23
  private
22
-
23
24
  def show_config
24
25
  logger.info("Mappings:", icon: :config)
25
26
  mappings.each { |mapping| logger.log(" #{mapping}") }
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dotsync
2
4
  class ConfigError < StandardError; end
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dotsync
2
4
  class FileTransfer
3
5
  attr_reader :ignores
@@ -13,37 +15,36 @@ module Dotsync
13
15
  if File.file?(@src)
14
16
  transfer_file(@src, @dest)
15
17
  else
16
- FileUtils.rm_rf(Dir.glob(File.join(@dest, '*'))) if @force
18
+ FileUtils.rm_rf(Dir.glob(File.join(@dest, "*"))) if @force
17
19
  transfer_folder(@src, @dest)
18
20
  end
19
21
  end
20
22
 
21
23
  private
24
+ def transfer_file(file_src, file_dest)
25
+ FileUtils.mkdir_p(File.dirname(file_dest))
26
+ FileUtils.cp(file_src, file_dest)
27
+ end
22
28
 
23
- def transfer_file(file_src, file_dest)
24
- FileUtils.mkdir_p(File.dirname(file_dest))
25
- FileUtils.cp(file_src, file_dest)
26
- end
27
-
28
- def transfer_folder(folder_src, folder_dest)
29
- FileUtils.mkdir_p(folder_dest)
30
- Dir.glob("#{folder_src}/*", File::FNM_DOTMATCH).each do |path|
31
- next if ['.', '..'].include?(File.basename(path))
29
+ def transfer_folder(folder_src, folder_dest)
30
+ FileUtils.mkdir_p(folder_dest)
31
+ Dir.glob("#{folder_src}/*", File::FNM_DOTMATCH).each do |path|
32
+ next if [".", ".."].include?(File.basename(path))
32
33
 
33
- full_path = File.expand_path(path)
34
- next if ignore?(full_path)
34
+ full_path = File.expand_path(path)
35
+ next if ignore?(full_path)
35
36
 
36
- target = File.join(folder_dest, File.basename(path))
37
- if File.file?(full_path)
38
- FileUtils.cp(full_path, target)
39
- else
40
- transfer_folder(full_path, target)
37
+ target = File.join(folder_dest, File.basename(path))
38
+ if File.file?(full_path)
39
+ FileUtils.cp(full_path, target)
40
+ else
41
+ transfer_folder(full_path, target)
42
+ end
41
43
  end
42
44
  end
43
- end
44
45
 
45
- def ignore?(path)
46
- @ignores.any? { |ignore| path.start_with?(ignore) }
47
- end
46
+ def ignore?(path)
47
+ @ignores.any? { |ignore| path.start_with?(ignore) }
48
+ end
48
49
  end
49
50
  end
data/lib/dotsync/icons.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dotsync
2
4
  module Icons
3
5
  # Log level icons
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dotsync
2
4
  class Logger
3
5
  attr_accessor :output
@@ -1,16 +1,24 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dotsync
2
4
  module PathUtils
5
+ ENV_VARS_COLOR = 104
6
+
3
7
  def expand_env_vars(path)
4
8
  path.gsub(/\$(\w+)/) { ENV[$1] }
5
9
  end
6
10
 
11
+ def colorize_env_vars(path)
12
+ path.gsub(/\$(\w+)/) { "\e[38;5;#{ENV_VARS_COLOR}m$#{$1}\e[0m" }
13
+ end
14
+
7
15
  # Translates /tmp paths to /private/tmp paths on macOS
8
16
  # Retains other paths as-is
9
17
  # @param [String] path The input path to translate
10
18
  # @return [String] The translated path
11
19
  def translate_tmp_path(path)
12
- if path.start_with?('/tmp') && RUBY_PLATFORM.include?('darwin')
13
- path.sub('/tmp', '/private/tmp')
20
+ if path.start_with?("/tmp") && RUBY_PLATFORM.include?("darwin")
21
+ path.sub("/tmp", "/private/tmp")
14
22
  else
15
23
  path
16
24
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dotsync
2
4
  class Runner
3
5
  def initialize(logger: nil)
@@ -32,42 +34,41 @@ module Dotsync
32
34
  end
33
35
 
34
36
  private
37
+ def setup_config
38
+ require "toml-rb"
39
+ require "fileutils"
35
40
 
36
- def setup_config
37
- require 'toml-rb'
38
- require 'fileutils'
39
-
40
- config_path = File.expand_path(Dotsync.config_path)
41
- FileUtils.mkdir_p(File.dirname(config_path))
41
+ config_path = File.expand_path(Dotsync.config_path)
42
+ FileUtils.mkdir_p(File.dirname(config_path))
42
43
 
43
- example_mappings = {
44
- "pull" => {
45
- "mappings" => [
46
- { "src" => "$DOTFILES_DIR/config/", "dest" => "$XDG_CONFIG_HOME", "force" => false },
47
- { "src" => "$DOTFILES_DIR/home/.zshenv", "dest" => "$HOME" }
48
- ],
49
- },
50
- "push" => {
51
- "mappings" => [
52
- { "src" => "$HOME/.zshenv", "dest" => "$DOTFILES_DIR/home/.zshenv" },
53
- { "src" => "$XDG_CONFIG_HOME/alacritty", "dest" => "$DOTFILES_DIR/config/alacritty" }
54
- ]
55
- },
56
- "watch" => {
57
- "mappings" => [
58
- { "src" => "$HOME/.zshenv", "dest" => "$DOTFILES_DIR/home/.zshenv" },
59
- { "src" => "$XDG_CONFIG_HOME/alacritty", "dest" => "$DOTFILES_DIR/config/alacritty" }
60
- ]
44
+ example_mappings = {
45
+ "pull" => {
46
+ "mappings" => [
47
+ { "src" => "$DOTFILES_DIR/config/", "dest" => "$XDG_CONFIG_HOME", "force" => false },
48
+ { "src" => "$DOTFILES_DIR/home/.zshenv", "dest" => "$HOME" }
49
+ ],
50
+ },
51
+ "push" => {
52
+ "mappings" => [
53
+ { "src" => "$HOME/.zshenv", "dest" => "$DOTFILES_DIR/home/.zshenv" },
54
+ { "src" => "$XDG_CONFIG_HOME/alacritty", "dest" => "$DOTFILES_DIR/config/alacritty" }
55
+ ]
56
+ },
57
+ "watch" => {
58
+ "mappings" => [
59
+ { "src" => "$HOME/.zshenv", "dest" => "$DOTFILES_DIR/home/.zshenv" },
60
+ { "src" => "$XDG_CONFIG_HOME/alacritty", "dest" => "$DOTFILES_DIR/config/alacritty" }
61
+ ]
62
+ }
61
63
  }
62
- }
63
64
 
64
- File.write(config_path, TomlRB.dump(example_mappings))
65
- @logger.info("Configuration file created at #{config_path}")
66
- end
65
+ File.write(config_path, TomlRB.dump(example_mappings))
66
+ @logger.info("Configuration file created at #{config_path}")
67
+ end
67
68
 
68
- # Utility to convert 'pull' to 'Pull', 'sync' to 'Sync', etc.
69
- def camelize(str)
70
- str.split('_').map(&:capitalize).join
71
- end
69
+ # Utility to convert 'pull' to 'Pull', 'sync' to 'Sync', etc.
70
+ def camelize(str)
71
+ str.split("_").map(&:capitalize).join
72
+ end
72
73
  end
73
74
  end
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  desc "Sync Dotfiles"
2
4
  task :sync do
3
- ds = Dotsync::SyncAction.new
5
+ Dotsync::SyncAction.new
4
6
  end
5
7
 
6
8
  desc "Watch Dotfiles"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dotsync
2
- VERSION = "0.1.3"
4
+ VERSION = "0.1.5"
3
5
  end
data/lib/dotsync.rb CHANGED
@@ -1,19 +1,21 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Libs dependencies
2
- require 'fileutils'
3
- require 'listen'
4
- require 'toml-rb'
5
- require 'logger'
6
- require 'forwardable' # Ruby standard library
7
- require 'ostruct'
4
+ require "fileutils"
5
+ require "listen"
6
+ require "toml-rb"
7
+ require "logger"
8
+ require "forwardable" # Ruby standard library
9
+ require "ostruct"
8
10
 
9
11
  # Errors
10
12
  require_relative "dotsync/errors"
11
13
 
12
14
  # Utils
13
- require_relative 'dotsync/icons'
14
- require_relative 'dotsync/logger'
15
- require_relative 'dotsync/file_transfer'
16
- require_relative 'dotsync/path_utils'
15
+ require_relative "dotsync/icons"
16
+ require_relative "dotsync/logger"
17
+ require_relative "dotsync/file_transfer"
18
+ require_relative "dotsync/path_utils"
17
19
 
18
20
  # Config
19
21
  require_relative "dotsync/actions/config/xdg_base_directory_spec"
@@ -32,7 +34,7 @@ require_relative "dotsync/actions/pull_action"
32
34
  require_relative "dotsync/actions/push_action"
33
35
  require_relative "dotsync/actions/watch_action"
34
36
 
35
- require_relative 'dotsync/runner'
37
+ require_relative "dotsync/runner"
36
38
 
37
39
  require_relative "dotsync/version"
38
40
 
@@ -43,7 +45,7 @@ module Dotsync
43
45
  attr_writer :config_path
44
46
 
45
47
  def config_path
46
- @config_path ||= ENV['DOTSYNC_CONFIG'] || "~/.config/dotsync.toml"
48
+ @config_path ||= ENV["DOTSYNC_CONFIG"] || "~/.config/dotsync.toml"
47
49
  end
48
50
  end
49
51
  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.3
4
+ version: 0.1.5
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-10-26 00:00:00.000000000 Z
11
+ date: 2025-10-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: toml-rb
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: 1.7.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: ostruct
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.6.3
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.6.3
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rake
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -108,6 +122,62 @@ dependencies:
108
122
  - - "~>"
109
123
  - !ruby/object:Gem::Version
110
124
  version: 1.81.1
125
+ - !ruby/object:Gem::Dependency
126
+ name: rubocop-rspec
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rubocop-performance
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: rubocop-rake
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: rubocop-md
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
111
181
  - !ruby/object:Gem::Dependency
112
182
  name: timecop
113
183
  requirement: !ruby/object:Gem::Requirement
@@ -150,6 +220,7 @@ files:
150
220
  - ".github/workflows/gem-push.yml.bak"
151
221
  - ".gitignore"
152
222
  - ".rspec"
223
+ - ".rubocop.yml"
153
224
  - ".ruby-version"
154
225
  - CHANGELOG.md
155
226
  - CODE_OF_CONDUCT.md