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.
data/Rakefile CHANGED
@@ -15,23 +15,137 @@ end
15
15
  task default: :spec
16
16
 
17
17
  namespace :release do
18
- desc "Tag git with the current Dotsync::VERSION"
19
- task :tag do
20
- require_relative "./lib/dotsync/version"
21
- version = Dotsync::VERSION
18
+ desc "Generate CHANGELOG entry for a new version"
19
+ # Usage: rake release:changelog[0.2.1]
20
+ task :changelog, [:version] do |_t, args|
21
+ version = args[:version]
22
+ unless version
23
+ require_relative "./lib/dotsync/version"
24
+ version = Dotsync::VERSION
25
+ end
26
+ version = version.sub(/^v/, "")
27
+ today = Date.today.strftime("%Y-%m-%d")
28
+
29
+ latest_tag = `git describe --tags --abbrev=0 2>/dev/null`.strip
30
+ commits = if latest_tag.empty?
31
+ `git log --oneline --no-decorate`.strip.split("\n")
32
+ else
33
+ `git log #{latest_tag}..HEAD --oneline --no-decorate`.strip.split("\n")
34
+ end
35
+
36
+ if commits.empty?
37
+ abort "No commits since #{latest_tag}. Nothing to release."
38
+ end
39
+
40
+ categories = { "Added" => [], "Changed" => [], "Fixed" => [], "Removed" => [], "Security" => [], "Dependencies" => [] }
41
+
42
+ commits.each do |commit|
43
+ message = commit.sub(/^[a-f0-9]+\s+/, "")
44
+ case message.downcase
45
+ when /^add|^feat|^implement|^create|^new|^support/i then categories["Added"] << message
46
+ when /^fix|^bugfix|^hotfix|^resolve|^correct/i then categories["Fixed"] << message
47
+ when /^remove|^delete|^drop/i then categories["Removed"] << message
48
+ when /^security|^vuln|^cve/i then categories["Security"] << message
49
+ when /^bump|^upgrade|^update.*dependency|^dep/i then categories["Dependencies"] << message
50
+ else categories["Changed"] << message
51
+ end
52
+ end
53
+
54
+ changelog_entry = "## [#{version}] - #{today}\n"
55
+ categories.each do |category, items|
56
+ next if items.empty?
57
+ changelog_entry += "\n### #{category}\n\n"
58
+ items.each { |item| changelog_entry += "- #{item}\n" }
59
+ end
60
+
61
+ changelog_path = "CHANGELOG.md"
62
+ abort "CHANGELOG.md not found." unless File.exist?(changelog_path)
63
+
64
+ changelog = File.read(changelog_path)
65
+ abort "Version #{version} already exists in CHANGELOG.md" if changelog.include?("[#{version}]")
66
+
67
+ match = changelog.match(/^## \[/m)
68
+ new_changelog = match ? changelog.sub(/^## \[/m, "#{changelog_entry}\n## [") : changelog.rstrip + "\n\n#{changelog_entry}"
69
+
70
+ repo_url = `git remote get-url origin`.strip.sub(/\.git$/, "").sub(/^git@github\.com:/, "https://github.com/")
71
+ previous_version = latest_tag.empty? ? "v0.0.0" : latest_tag
72
+ link_entry = "[#{version}]: #{repo_url}/compare/#{previous_version}...v#{version}"
73
+
74
+ new_changelog = if new_changelog.match?(/^\[[\d.]+\]:.*compare/m)
75
+ new_changelog.sub(/^(\[[\d.]+\]:.*compare)/m, "#{link_entry}\n\\1")
76
+ else
77
+ new_changelog.rstrip + "\n\n#{link_entry}\n"
78
+ end
79
+
80
+ File.write(changelog_path, new_changelog)
81
+ puts "Updated CHANGELOG.md with version #{version}"
82
+ puts "\n#{changelog_entry}"
83
+ end
84
+
85
+ desc "Create annotated git tag from CHANGELOG"
86
+ # Usage: rake release:tag[0.2.1] or just rake release:tag (uses Dotsync::VERSION)
87
+ task :tag, [:version] do |_t, args|
88
+ version = args[:version]
89
+ unless version
90
+ require_relative "./lib/dotsync/version"
91
+ version = Dotsync::VERSION
92
+ end
93
+ version = version.sub(/^v/, "")
22
94
  tag_name = "v#{version}"
23
95
 
24
- # Check if tag already exists
25
96
  if `git tag --list`.split.include?(tag_name)
26
97
  puts "Tag #{tag_name} already exists."
27
98
  exit(1)
28
99
  end
29
100
 
101
+ changelog_path = "CHANGELOG.md"
102
+ abort "CHANGELOG.md not found." unless File.exist?(changelog_path)
103
+
104
+ changelog = File.read(changelog_path)
105
+ version_regex = /^## \[#{Regexp.escape(version)}\] - (\d{4}-\d{2}-\d{2})\n(.*?)(?=^## \[|\z)/m
106
+ match = changelog.match(version_regex)
107
+
108
+ unless match
109
+ abort "Version #{version} not found in CHANGELOG.md\nRun 'rake release:changelog[#{version}]' first."
110
+ end
111
+
112
+ date = match[1]
113
+ content = match[2].strip
114
+ tag_message = "#{version} - #{date}\n\n#{content}"
115
+
30
116
  puts "Tagging commit as #{tag_name}..."
31
- sh "git tag -a #{tag_name} -m 'Release #{tag_name}'"
32
- puts "Pushing tag #{tag_name} to origin..."
33
- sh "git push origin #{tag_name}"
34
- puts "Done!"
117
+ sh "git", "tag", "-a", tag_name, "-m", tag_message
118
+ puts "Tag created. Push with: git push origin #{tag_name}"
119
+ end
120
+
121
+ desc "Full release: update changelog, commit, tag, and push"
122
+ # Usage: rake release:publish[0.2.1] or rake release:publish (uses Dotsync::VERSION)
123
+ task :publish, [:version] do |_t, args|
124
+ version = args[:version]
125
+ unless version
126
+ require_relative "./lib/dotsync/version"
127
+ version = Dotsync::VERSION
128
+ end
129
+ version = version.sub(/^v/, "")
130
+
131
+ status = `git status --porcelain`.strip
132
+ uncommitted = status.split("\n").reject { |line| line.end_with?("CHANGELOG.md") }
133
+ abort "Uncommitted changes:\n#{uncommitted.join("\n")}" unless uncommitted.empty?
134
+
135
+ Rake::Task["release:changelog"].invoke(version)
136
+ puts "\nReview CHANGELOG.md, then press Enter to continue..."
137
+ $stdin.gets
138
+
139
+ sh "git", "add", "CHANGELOG.md"
140
+ sh "git", "commit", "-m", "Update CHANGELOG for v#{version}\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>"
141
+
142
+ Rake::Task["release:tag"].reenable
143
+ Rake::Task["release:tag"].invoke(version)
144
+
145
+ branch = `git rev-parse --abbrev-ref HEAD`.strip
146
+ sh "git", "push", "origin", branch
147
+ sh "git", "push", "origin", "v#{version}"
148
+ puts "\n✅ Released v#{version}"
35
149
  end
36
150
  end
37
151
 
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
@@ -0,0 +1,191 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dotsync
4
+ # SyncMappings provides bidirectional mapping support.
5
+ # It reads [sync] section mappings and converts them to push or pull format.
6
+ #
7
+ # The [sync] section supports multiple sub-types:
8
+ #
9
+ # 1. Explicit mappings with [[sync.mappings]]:
10
+ # [[sync.mappings]]
11
+ # local = "$XDG_CONFIG_HOME/nvim"
12
+ # remote = "$XDG_CONFIG_HOME_MIRROR/nvim"
13
+ # force = true
14
+ # ignore = ["lazy-lock.json"]
15
+ #
16
+ # 2. XDG shorthand mappings that auto-expand environment variables:
17
+ # [[sync.xdg_config]]
18
+ # path = "nvim"
19
+ # force = true
20
+ # # Expands to: local=$XDG_CONFIG_HOME/nvim, remote=$XDG_CONFIG_HOME_MIRROR/nvim
21
+ #
22
+ # Supported shorthands:
23
+ # - sync.home: $HOME <-> $HOME_MIRROR
24
+ # - sync.xdg_config: $XDG_CONFIG_HOME <-> $XDG_CONFIG_HOME_MIRROR
25
+ # - sync.xdg_data: $XDG_DATA_HOME <-> $XDG_DATA_HOME_MIRROR
26
+ # - sync.xdg_cache: $XDG_CACHE_HOME <-> $XDG_CACHE_HOME_MIRROR
27
+ # - sync.xdg_bin: $XDG_BIN_HOME <-> $XDG_BIN_HOME_MIRROR
28
+ # - sync.mappings: explicit local/remote mappings
29
+ #
30
+ # For push: local → remote (src=local, dest=remote)
31
+ # For pull: remote → local (src=remote, dest=local)
32
+ module SyncMappings
33
+ SYNC_SECTION = "sync"
34
+ MAPPINGS_KEY = "mappings"
35
+
36
+ # Shorthand type definitions mapping to local/remote base paths
37
+ SHORTHANDS = {
38
+ "home" => { local: "$HOME", remote: "$HOME_MIRROR" },
39
+ "xdg_config" => { local: "$XDG_CONFIG_HOME", remote: "$XDG_CONFIG_HOME_MIRROR" },
40
+ "xdg_data" => { local: "$XDG_DATA_HOME", remote: "$XDG_DATA_HOME_MIRROR" },
41
+ "xdg_cache" => { local: "$XDG_CACHE_HOME", remote: "$XDG_CACHE_HOME_MIRROR" },
42
+ "xdg_bin" => { local: "$XDG_BIN_HOME", remote: "$XDG_BIN_HOME_MIRROR" }
43
+ }.freeze
44
+
45
+ def sync_mappings_for_push
46
+ all_sync_mappings(:push)
47
+ end
48
+
49
+ def sync_mappings_for_pull
50
+ all_sync_mappings(:pull)
51
+ end
52
+
53
+ def has_sync_mappings?
54
+ return false unless sync_section.is_a?(Hash)
55
+
56
+ explicit_mappings_raw.any? || shorthand_mappings_raw.any?
57
+ end
58
+
59
+ private
60
+ def all_sync_mappings(direction)
61
+ convert_explicit_mappings(direction: direction) + convert_shorthand_mappings(direction: direction)
62
+ end
63
+
64
+ def sync_section
65
+ @config[SYNC_SECTION]
66
+ end
67
+
68
+ # Explicit [[sync.mappings]] with local/remote keys
69
+ def explicit_mappings_raw
70
+ return [] unless sync_section.is_a?(Hash)
71
+ return [] unless sync_section.key?(MAPPINGS_KEY)
72
+
73
+ Array(sync_section[MAPPINGS_KEY])
74
+ end
75
+
76
+ def convert_explicit_mappings(direction:)
77
+ explicit_mappings_raw.map do |mapping|
78
+ converted = convert_explicit_mapping(mapping, direction)
79
+ Dotsync::Mapping.new(converted)
80
+ end
81
+ end
82
+
83
+ def convert_explicit_mapping(mapping, direction)
84
+ local = mapping["local"]
85
+ remote = mapping["remote"]
86
+
87
+ base = case direction
88
+ when :push
89
+ { "src" => local, "dest" => remote }
90
+ when :pull
91
+ { "src" => remote, "dest" => local }
92
+ end
93
+
94
+ # Preserve other options
95
+ base["force"] = mapping["force"] if mapping.key?("force")
96
+ base["ignore"] = mapping["ignore"] if mapping.key?("ignore")
97
+ base["only"] = mapping["only"] if mapping.key?("only")
98
+
99
+ base
100
+ end
101
+
102
+ # Shorthand mappings: [[sync.home]], [[sync.xdg_config]], etc.
103
+ def shorthand_mappings_raw
104
+ return [] unless sync_section.is_a?(Hash)
105
+
106
+ mappings = []
107
+ SHORTHANDS.each_key do |shorthand_type|
108
+ next unless sync_section.key?(shorthand_type)
109
+ Array(sync_section[shorthand_type]).each do |mapping|
110
+ mappings << { type: shorthand_type, mapping: mapping }
111
+ end
112
+ end
113
+ mappings
114
+ end
115
+
116
+ def convert_shorthand_mappings(direction:)
117
+ shorthand_mappings_raw.map do |entry|
118
+ converted = convert_shorthand_mapping(entry[:type], entry[:mapping], direction)
119
+ Dotsync::Mapping.new(converted)
120
+ end
121
+ end
122
+
123
+ def convert_shorthand_mapping(shorthand_type, mapping, direction)
124
+ shorthand_def = SHORTHANDS[shorthand_type]
125
+
126
+ # Support both 'path' for single paths and 'only' for multiple paths
127
+ path = mapping["path"]
128
+ only = mapping["only"]
129
+
130
+ local = build_path(shorthand_def[:local], path)
131
+ remote = build_path(shorthand_def[:remote], path)
132
+
133
+ base = case direction
134
+ when :push
135
+ { "src" => local, "dest" => remote }
136
+ when :pull
137
+ { "src" => remote, "dest" => local }
138
+ end
139
+
140
+ # Preserve other options
141
+ base["force"] = mapping["force"] if mapping.key?("force")
142
+ base["ignore"] = mapping["ignore"] if mapping.key?("ignore")
143
+ base["only"] = only if only
144
+
145
+ base
146
+ end
147
+
148
+ def build_path(base, path)
149
+ path ? File.join(base, path) : base
150
+ end
151
+
152
+ def validate_sync_mappings!
153
+ return unless sync_section
154
+
155
+ unless sync_section.is_a?(Hash)
156
+ raise Dotsync::ConfigError,
157
+ "Configuration error: [sync] must be a table, not an array. " \
158
+ "Use [[sync.mappings]] for explicit mappings."
159
+ end
160
+
161
+ validate_explicit_mappings!
162
+ validate_shorthand_mappings!
163
+ end
164
+
165
+ def validate_explicit_mappings!
166
+ return unless sync_section.key?(MAPPINGS_KEY)
167
+
168
+ explicit_mappings_raw.each_with_index do |mapping, index|
169
+ unless mapping.is_a?(Hash) && mapping.key?("local") && mapping.key?("remote")
170
+ raise Dotsync::ConfigError,
171
+ "Configuration error in sync.mappings ##{index + 1}: " \
172
+ "Each mapping must have 'local' and 'remote' keys."
173
+ end
174
+ end
175
+ end
176
+
177
+ def validate_shorthand_mappings!
178
+ SHORTHANDS.each_key do |shorthand_type|
179
+ next unless sync_section.key?(shorthand_type)
180
+
181
+ Array(sync_section[shorthand_type]).each_with_index do |mapping, index|
182
+ unless mapping.is_a?(Hash)
183
+ raise Dotsync::ConfigError,
184
+ "Configuration error in sync.#{shorthand_type} ##{index + 1}: " \
185
+ "Each mapping must be a table."
186
+ end
187
+ end
188
+ end
189
+ end
190
+ end
191
+ end
@@ -3,10 +3,10 @@
3
3
  module Dotsync
4
4
  class PullActionConfig < BaseConfig
5
5
  include XDGBaseDirectory
6
+ include SyncMappings
6
7
 
7
8
  def mappings
8
- mappings_list = section["mappings"]
9
- Array(mappings_list).map { |mapping| Dotsync::Mapping.new(mapping) }
9
+ section_mappings + sync_mappings_for_pull
10
10
  end
11
11
 
12
12
  def backups_root
@@ -20,13 +20,31 @@ module Dotsync
20
20
  SECTION_NAME
21
21
  end
22
22
 
23
+ def section_mappings
24
+ return [] unless section && section["mappings"]
25
+ Array(section["mappings"]).map { |mapping| Dotsync::Mapping.new(mapping) }
26
+ end
27
+
23
28
  def validate!
24
- validate_section_present!
25
- validate_key_present! "mappings"
29
+ validate_pull_or_sync_present!
30
+ validate_pull_mappings!
31
+ validate_sync_mappings!
32
+ end
33
+
34
+ def validate_pull_or_sync_present!
35
+ has_pull = @config.key?(section_name) && section["mappings"]&.any?
36
+
37
+ unless has_pull || has_sync_mappings?
38
+ raise_error "No [#{section_name}] mappings or [sync] mappings found in config file"
39
+ end
40
+ end
41
+
42
+ def validate_pull_mappings!
43
+ return unless section && section["mappings"]
26
44
 
27
45
  Array(section["mappings"]).each_with_index do |mapping, index|
28
46
  unless mapping.is_a?(Hash) && mapping.key?("src") && mapping.key?("dest")
29
- raise "Configuration error in mapping ##{index + 1}: Each mapping must have 'src' and 'dest' keys."
47
+ raise "Configuration error in pull mapping ##{index + 1}: Each mapping must have 'src' and 'dest' keys."
30
48
  end
31
49
  end
32
50
  end
@@ -2,9 +2,10 @@
2
2
 
3
3
  module Dotsync
4
4
  class PushActionConfig < BaseConfig
5
+ include SyncMappings
6
+
5
7
  def mappings
6
- mappings_list = section["mappings"]
7
- Array(mappings_list).map { |mapping| Dotsync::Mapping.new(mapping) }
8
+ section_mappings + sync_mappings_for_push
8
9
  end
9
10
 
10
11
  private
@@ -14,13 +15,31 @@ module Dotsync
14
15
  SECTION_NAME
15
16
  end
16
17
 
18
+ def section_mappings
19
+ return [] unless section && section["mappings"]
20
+ Array(section["mappings"]).map { |mapping| Dotsync::Mapping.new(mapping) }
21
+ end
22
+
17
23
  def validate!
18
- validate_section_present!
19
- validate_key_present! "mappings"
24
+ validate_push_or_sync_present!
25
+ validate_push_mappings!
26
+ validate_sync_mappings!
27
+ end
28
+
29
+ def validate_push_or_sync_present!
30
+ has_push = @config.key?(section_name) && section["mappings"]&.any?
31
+
32
+ unless has_push || has_sync_mappings?
33
+ raise_error "No [#{section_name}] mappings or [sync] mappings found in config file"
34
+ end
35
+ end
36
+
37
+ def validate_push_mappings!
38
+ return unless section && section["mappings"]
20
39
 
21
40
  Array(section["mappings"]).each_with_index do |mapping, index|
22
41
  unless mapping.is_a?(Hash) && mapping.key?("src") && mapping.key?("dest")
23
- raise "Configuration error in mapping ##{index + 1}: Each mapping must have 'src' and 'dest' keys."
42
+ raise "Configuration error in push mapping ##{index + 1}: Each mapping must have 'src' and 'dest' keys."
24
43
  end
25
44
  end
26
45
  end
@@ -16,6 +16,10 @@ require_relative "../utils/config_cache"
16
16
  require_relative "../models/mapping"
17
17
  require_relative "../models/diff"
18
18
 
19
+ # Config Concerns
20
+ require_relative "../config/concerns/xdg_base_directory"
21
+ require_relative "../config/concerns/sync_mappings"
22
+
19
23
  # Config
20
24
  require_relative "../config/base_config"
21
25
  require_relative "../config/pull_action_config"
@@ -16,6 +16,9 @@ require_relative "../utils/config_cache"
16
16
  require_relative "../models/mapping"
17
17
  require_relative "../models/diff"
18
18
 
19
+ # Config Concerns
20
+ require_relative "../config/concerns/sync_mappings"
21
+
19
22
  # Config
20
23
  require_relative "../config/base_config"
21
24
  require_relative "../config/push_action_config"
@@ -5,6 +5,7 @@ module Dotsync
5
5
  def initialize(logger: nil, config_path: nil)
6
6
  @logger = logger || Dotsync::Logger.new
7
7
  @config_path = config_path
8
+ Dotsync.config_path = config_path if config_path
8
9
  end
9
10
 
10
11
  # action_name should be a symbol, e.g., :pull, :watch, :sync
@@ -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.26"
5
5
  end
data/lib/dotsync.rb CHANGED
@@ -22,6 +22,7 @@ require_relative "dotsync/version"
22
22
 
23
23
  # Config Concerns (loaded early as they're used by other modules)
24
24
  require_relative "dotsync/config/concerns/xdg_base_directory"
25
+ require_relative "dotsync/config/concerns/sync_mappings"
25
26
 
26
27
  # Utils
27
28
  require_relative "dotsync/utils/path_utils"
metadata CHANGED
@@ -1,14 +1,13 @@
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.26
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Sáenz
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2025-11-15 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: toml-rb
@@ -285,9 +284,10 @@ extensions: []
285
284
  extra_rdoc_files: []
286
285
  files:
287
286
  - ".editorconfig"
288
- - ".github/workflows/gem-push.yml"
289
- - ".github/workflows/gem-push.yml.bak"
287
+ - ".github/workflows/ci.yml"
288
+ - ".github/workflows/release.yml"
290
289
  - ".gitignore"
290
+ - ".pre-commit-config.yaml"
291
291
  - ".rspec"
292
292
  - ".rubocop.yml"
293
293
  - ".ruby-version"
@@ -317,6 +317,7 @@ files:
317
317
  - lib/dotsync/actions/watch_action.rb
318
318
  - lib/dotsync/colors.rb
319
319
  - lib/dotsync/config/base_config.rb
320
+ - lib/dotsync/config/concerns/sync_mappings.rb
320
321
  - lib/dotsync/config/concerns/xdg_base_directory.rb
321
322
  - lib/dotsync/config/pull_action_config.rb
322
323
  - lib/dotsync/config/push_action_config.rb
@@ -346,7 +347,6 @@ metadata:
346
347
  homepage_uri: https://github.com/dsaenztagarro/dotsync
347
348
  source_code_uri: https://github.com/dsaenztagarro/dotsync
348
349
  changelog_uri: https://github.com/dsaenztagarro/dotsync/blob/master/CHANGELOG.md
349
- post_install_message:
350
350
  rdoc_options: []
351
351
  require_paths:
352
352
  - lib
@@ -361,8 +361,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
361
361
  - !ruby/object:Gem::Version
362
362
  version: '0'
363
363
  requirements: []
364
- rubygems_version: 3.4.19
365
- signing_key:
364
+ rubygems_version: 3.7.2
366
365
  specification_version: 4
367
366
  summary: Manage dotfiles like a boss
368
367
  test_files: []
@@ -1,45 +0,0 @@
1
- jobs:
2
- build:
3
- name: Build + Publish
4
- runs-on: ubuntu-latest
5
- permissions:
6
- contents: read
7
- packages: write
8
-
9
- steps:
10
- - uses: actions/checkout@v4
11
-
12
- - name: Publish to GPR
13
- run: |
14
- mkdir -p $HOME/.gem
15
- touch $HOME/.gem/credentials
16
- chmod 0600 $HOME/.gem/credentials
17
- printf -- "---\n:github: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
18
- gem build *.gemspec
19
- gem push --KEY github --host https://rubygems.pkg.github.com/${OWNER} *.gem
20
- env:
21
- GEM_HOST_API_KEY: "Bearer ${{secrets.GITHUB_TOKEN}}"
22
- OWNER: ${{ github.repository_owner }}
23
-
24
- publish:
25
- needs: test
26
- runs-on: ubuntu-latest
27
- if: github.ref == 'refs/heads/master' && matrix.ruby == '3.2'
28
-
29
- steps:
30
- - uses: actions/checkout@v4
31
-
32
- - name: Set up Ruby
33
- uses: ruby/setup-ruby@v1
34
- with:
35
- ruby-version: 3.2
36
- bundler-cache: true
37
-
38
- - name: Check if gem version has changed
39
- id: gem_version_check
40
- run: |
41
- gem build *.gemspec
42
- gem_name=$(ls *.gem | head -n 1)
43
- gem info $gem_name --remote || echo "new_version" > version_changed
44
- env:
45
- GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"