dotsync 0.1.14 → 0.1.16
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 +4 -4
- data/.github/workflows/gem-push.yml +6 -1
- data/CHANGELOG.md +15 -0
- data/Gemfile.lock +1 -1
- data/README.md +39 -4
- data/Rakefile +20 -3
- data/docs/images/dotsync_pull.png +0 -0
- data/docs/images/dotsync_push.png +0 -0
- data/exe/dotsync +50 -4
- data/lib/dotsync/actions/concerns/mappings_transfer.rb +40 -23
- data/lib/dotsync/actions/concerns/output_sections.rb +25 -0
- data/lib/dotsync/actions/pull_action.rb +10 -5
- data/lib/dotsync/actions/push_action.rb +10 -5
- data/lib/dotsync/icons.rb +28 -2
- data/lib/dotsync/models/diff.rb +4 -0
- data/lib/dotsync/models/mapping.rb +26 -10
- data/lib/dotsync/utils/directory_differ.rb +6 -1
- data/lib/dotsync/utils/file_transfer.rb +10 -13
- data/lib/dotsync/utils/path_utils.rb +6 -0
- data/lib/dotsync/version.rb +1 -1
- data/lib/dotsync.rb +1 -0
- metadata +5 -6
- /data/{exe → bin}/console +0 -0
- /data/{exe → bin}/setup +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 653f18b457e91c025888eb6fca1d14de2718aa0ee7253c30d80e699c6fdc720a
|
|
4
|
+
data.tar.gz: 9c180933f5b35c186fbfaf754a38a9217fcdd459fae3c75d67787d43516f3871
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0aedae57228a61723b3f4f929e64387dce6fbc227d2f9d68271512eafa7ff15c7ac780fc0f2be80b60868266f309d52403b0ea24d7222770f5ce16edce102df9
|
|
7
|
+
data.tar.gz: 19cb8d65ba7216aa1e2577eb77876a363267e1f7a73f5b5c7dd9ce26c4490988613d30be2199e1580971ac10c45515f86d145bd6565b98edd6d0035dacd352c5
|
|
@@ -34,7 +34,7 @@ jobs:
|
|
|
34
34
|
bundle exec rubocop
|
|
35
35
|
|
|
36
36
|
- name: Publish to RubyGems
|
|
37
|
-
if: matrix.ruby == '3.2'
|
|
37
|
+
if: matrix.ruby == '3.2' && github.ref_name == 'master'
|
|
38
38
|
run: |
|
|
39
39
|
mkdir -p $HOME/.gem
|
|
40
40
|
touch $HOME/.gem/credentials
|
|
@@ -44,3 +44,8 @@ jobs:
|
|
|
44
44
|
gem push *.gem
|
|
45
45
|
env:
|
|
46
46
|
GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
|
|
47
|
+
|
|
48
|
+
- name: Generate release tag
|
|
49
|
+
if: matrix.ruby == '3.2' && github.ref_name == 'master'
|
|
50
|
+
run: |
|
|
51
|
+
bundle exec rake release:tag
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
# 0.1.16
|
|
2
|
+
|
|
3
|
+
- DirectoryDiffer: fixes path on removal difference
|
|
4
|
+
- MappingsTransfer: fixes "Differences" label text for clarity
|
|
5
|
+
- Add Difference Legend
|
|
6
|
+
- Show Difference Legend only if there are any difference
|
|
7
|
+
- OutputSections: added new options to hide output
|
|
8
|
+
|
|
9
|
+
# 0.1.15
|
|
10
|
+
|
|
11
|
+
- Readme: update screenshots in docs
|
|
12
|
+
- Consistent order of icons on Legend and Mappings
|
|
13
|
+
- DirectoryDiffer: implements only option
|
|
14
|
+
- Show Flags icons closer
|
|
15
|
+
|
|
1
16
|
# 0.1.14
|
|
2
17
|
|
|
3
18
|
- Render environment variables and mappings with a table
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -35,15 +35,37 @@ Dotsync provides the following commands to manage your dotfiles:
|
|
|
35
35
|
|
|
36
36
|
- **Push**: Transfer dotfiles from your local machine to the destination repository.
|
|
37
37
|
```shell
|
|
38
|
-
dotsync push --apply
|
|
38
|
+
dotsync push --apply [OPTION]
|
|
39
39
|
```
|
|
40
|
+
Options:
|
|
41
|
+
- `-q, --quiet`: Hide all non-essential output (only errors or final status).
|
|
42
|
+
- `--no-legend`: Hide all legends for config, mappings, and differences.
|
|
43
|
+
- `--no-config`: Hide the config section in the output.
|
|
44
|
+
- `--no-mappings`: Hide the mappings and their legend.
|
|
45
|
+
- `--no-diff-legend`: Hide the differences legend only.
|
|
46
|
+
- `--no-diff`: Hide the differences section itself.
|
|
47
|
+
- `--only-diff`: Show only the differences section.
|
|
48
|
+
- `--only-config`: Show only the config section.
|
|
49
|
+
- `--only-mappings`: Show only the mappings section.
|
|
50
|
+
- `-v, --verbose`: Force showing all available information.
|
|
40
51
|
|
|
41
52
|

|
|
42
53
|
|
|
43
54
|
- **Pull**: Synchronize dotfiles from the repository to your local machine.
|
|
44
55
|
```shell
|
|
45
|
-
dotsync pull --apply
|
|
56
|
+
dotsync pull --apply [OPTION]
|
|
46
57
|
```
|
|
58
|
+
Options:
|
|
59
|
+
- `-q, --quiet`: Hide all non-essential output (only errors or final status).
|
|
60
|
+
- `--no-legend`: Hide all legends for config, mappings, and differences.
|
|
61
|
+
- `--no-config`: Hide the config section in the output.
|
|
62
|
+
- `--no-mappings`: Hide the mappings and their legend.
|
|
63
|
+
- `--no-diff-legend`: Hide the differences legend only.
|
|
64
|
+
- `--no-diff`: Hide the differences section itself.
|
|
65
|
+
- `--only-diff`: Show only the differences section.
|
|
66
|
+
- `--only-config`: Show only the config section.
|
|
67
|
+
- `--only-mappings`: Show only the mappings section.
|
|
68
|
+
- `-v, --verbose`: Force showing all available information.
|
|
47
69
|
|
|
48
70
|
During the `pull` operation, `Dotsync::PullAction` creates a backup of the existing files on the destination. These backups are stored in a directory under the XDG path, with each backup organized by a timestamp. To prevent excessive storage usage, only the 10 most recent backups are retained. Older backups are automatically purged, ensuring efficient storage management.
|
|
49
71
|
|
|
@@ -114,6 +136,14 @@ dest = "$DOTFILES_DIR/config/alacritty"
|
|
|
114
136
|
Each mapping entry supports the following options:
|
|
115
137
|
|
|
116
138
|
- **`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.
|
|
139
|
+
- **`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:
|
|
140
|
+
```toml
|
|
141
|
+
[[push.mappings]]
|
|
142
|
+
src = "$XDG_CONFIG_HOME"
|
|
143
|
+
dest = "$DOTFILES_DIR/config"
|
|
144
|
+
only = ["config.yml", "themes"]
|
|
145
|
+
|
|
146
|
+
```
|
|
117
147
|
- **`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.
|
|
118
148
|
|
|
119
149
|
These options apply when the source is a directory and are relevant for both `push` and `pull` operations.
|
|
@@ -157,9 +187,14 @@ When running `push` or `pull` actions, the mappings are rendered in the console
|
|
|
157
187
|
|
|
158
188
|
## Development
|
|
159
189
|
|
|
160
|
-
After checking out the repo, run `bin/setup` to install dependencies.
|
|
190
|
+
- After checking out the repo, run `bin/setup` to install dependencies.
|
|
191
|
+
- Then, run `rake spec` to run the tests.
|
|
192
|
+
- You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
193
|
+
- To install this gem onto your local machine, run `bundle exec rake install`.
|
|
161
194
|
|
|
162
|
-
|
|
195
|
+
### Releasing a new version
|
|
196
|
+
- Update the version number in `version.rb`.
|
|
197
|
+
- Run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
163
198
|
|
|
164
199
|
## Contributing
|
|
165
200
|
|
data/Rakefile
CHANGED
|
@@ -14,11 +14,28 @@ end
|
|
|
14
14
|
|
|
15
15
|
task default: :spec
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
|
22
|
+
tag_name = "v#{version}"
|
|
23
|
+
|
|
24
|
+
# Check if tag already exists
|
|
25
|
+
if `git tag --list`.split.include?(tag_name)
|
|
26
|
+
puts "Tag #{tag_name} already exists."
|
|
27
|
+
exit(1)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
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!"
|
|
35
|
+
end
|
|
20
36
|
end
|
|
21
37
|
|
|
38
|
+
|
|
22
39
|
namespace :dotsync do
|
|
23
40
|
desc "Pull Dotfiles"
|
|
24
41
|
task :pull do
|
|
Binary file
|
|
Binary file
|
data/exe/dotsync
CHANGED
|
@@ -18,12 +18,58 @@ opt_parser = OptionParser.new do |opts|
|
|
|
18
18
|
setup Initialize a default configuration file
|
|
19
19
|
|
|
20
20
|
Options:
|
|
21
|
-
-a, --apply
|
|
22
|
-
-
|
|
21
|
+
-a, --apply Apply changes (push or pull)
|
|
22
|
+
-q, --quiet Hide all non-essential output (only errors or final status)
|
|
23
|
+
--no-legend Hide all legends for config, mappings, and differences
|
|
24
|
+
--no-config Hide the config section in the output
|
|
25
|
+
--no-mappings Hide the mappings and their legend
|
|
26
|
+
--no-diff-legend Hide the differences legend only
|
|
27
|
+
--no-diff Hide the differences section itself
|
|
28
|
+
--only-diff Show only the differences section
|
|
29
|
+
--only-config Show only the config section
|
|
30
|
+
--only-mappings Show only the mappings section
|
|
31
|
+
-v, --verbose Force showing all available information
|
|
32
|
+
-h, --help Show this help message
|
|
23
33
|
BANNER
|
|
24
34
|
|
|
25
|
-
opts.on("-
|
|
26
|
-
options[:
|
|
35
|
+
opts.on("-q", "--quiet", "Hide all non-essential output (only errors or final status)") do
|
|
36
|
+
options[:quiet] = true
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
opts.on("--no-legend", "Hide all legends for config, mappings, and differences") do
|
|
40
|
+
options[:no_legend] = true
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
opts.on("--no-config", "Hide the config section in the output") do
|
|
44
|
+
options[:no_config] = true
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
opts.on("--no-mappings", "Hide the mappings and their legend") do
|
|
48
|
+
options[:no_mappings] = true
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
opts.on("--no-diff-legend", "Hide the differences legend only") do
|
|
52
|
+
options[:no_diff_legend] = true
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
opts.on("--no-diff", "Hide the differences section itself") do
|
|
56
|
+
options[:no_diff] = true
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
opts.on("--only-diff", "Show only the differences section") do
|
|
60
|
+
options[:only_diff] = true
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
opts.on("--only-config", "Show only the config section") do
|
|
64
|
+
options[:only_config] = true
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
opts.on("--only-mappings", "Show only the mappings section") do
|
|
68
|
+
options[:only_mappings] = true
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
opts.on("-v", "--verbose", "Force showing all available information") do
|
|
72
|
+
options[:verbose] = true
|
|
27
73
|
end
|
|
28
74
|
|
|
29
75
|
opts.on("-h", "--help", "Show this help message") do
|
|
@@ -4,11 +4,17 @@ module Dotsync
|
|
|
4
4
|
module MappingsTransfer
|
|
5
5
|
include Dotsync::PathUtils
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
[
|
|
9
|
-
[
|
|
10
|
-
[
|
|
11
|
-
[
|
|
7
|
+
MAPPINGS_LEGEND = [
|
|
8
|
+
[Icons.force, "The source will overwrite the destination"],
|
|
9
|
+
[Icons.only, "Paths designated explicitly as source only"],
|
|
10
|
+
[Icons.ignore, "Paths configured to be ignored in the destination"],
|
|
11
|
+
[Icons.invalid, "Invalid paths detected in the source or destination"]
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
DIFFERENCES_LEGEND = [
|
|
15
|
+
[Icons.diff_created, "Created/added file"],
|
|
16
|
+
[Icons.diff_updated, "Updated/modified file"],
|
|
17
|
+
[Icons.diff_removed, "Removed/deleted file"]
|
|
12
18
|
]
|
|
13
19
|
|
|
14
20
|
extend Forwardable # def_delegator
|
|
@@ -28,8 +34,8 @@ module Dotsync
|
|
|
28
34
|
end
|
|
29
35
|
|
|
30
36
|
def show_mappings_legend
|
|
31
|
-
info("Legend:", icon: :legend)
|
|
32
|
-
table = Terminal::Table.new(rows:
|
|
37
|
+
info("Mappings Legend:", icon: :legend)
|
|
38
|
+
table = Terminal::Table.new(rows: MAPPINGS_LEGEND)
|
|
33
39
|
logger.log(table)
|
|
34
40
|
logger.log("")
|
|
35
41
|
end
|
|
@@ -49,25 +55,26 @@ module Dotsync
|
|
|
49
55
|
logger.log("")
|
|
50
56
|
end
|
|
51
57
|
|
|
52
|
-
def
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
def show_differences_legend
|
|
59
|
+
info("Differences Legend:", icon: :legend)
|
|
60
|
+
table = Terminal::Table.new(rows: DIFFERENCES_LEGEND)
|
|
61
|
+
logger.log(table)
|
|
62
|
+
logger.log("")
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def show_differences
|
|
66
|
+
info("Differences:", icon: :diff)
|
|
67
|
+
differs.flat_map(&:additions).sort.each do |path|
|
|
68
|
+
logger.log("#{Icons.diff_created}#{path}", color: Colors.diff_additions)
|
|
61
69
|
end
|
|
62
|
-
|
|
63
|
-
logger.log("
|
|
64
|
-
has_diff = true
|
|
70
|
+
differs.flat_map(&:modifications).sort.each do |path|
|
|
71
|
+
logger.log("#{Icons.diff_updated}#{path}", color: Colors.diff_modifications)
|
|
65
72
|
end
|
|
66
|
-
|
|
67
|
-
logger.log("
|
|
68
|
-
has_diff = true
|
|
73
|
+
differs.flat_map(&:removals).sort.each do |path|
|
|
74
|
+
logger.log("#{Icons.diff_removed}#{path}", color: Colors.diff_removals)
|
|
69
75
|
end
|
|
70
|
-
logger.log(" No differences") unless
|
|
76
|
+
logger.log(" No differences") unless has_differences?
|
|
77
|
+
logger.log("")
|
|
71
78
|
end
|
|
72
79
|
|
|
73
80
|
def transfer_mappings
|
|
@@ -77,6 +84,16 @@ module Dotsync
|
|
|
77
84
|
end
|
|
78
85
|
|
|
79
86
|
private
|
|
87
|
+
def differs
|
|
88
|
+
@differs ||= valid_mappings.map do |mapping|
|
|
89
|
+
Dotsync::DirectoryDiffer.new(mapping).diff
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def has_differences?
|
|
94
|
+
differs.any? { |differ| differ.any? }
|
|
95
|
+
end
|
|
96
|
+
|
|
80
97
|
def mappings_env_vars
|
|
81
98
|
paths = mappings.flat_map do |mapping|
|
|
82
99
|
[mapping.original_src, mapping.original_dest]
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Dotsync
|
|
4
|
+
module OutputSections
|
|
5
|
+
def compute_output_sections(options)
|
|
6
|
+
quiet = options[:quiet]
|
|
7
|
+
verbose = options[:verbose]
|
|
8
|
+
|
|
9
|
+
output_sections = {
|
|
10
|
+
options: !(quiet || options[:only_diff] || options[:only_mappings]),
|
|
11
|
+
env_vars: !(quiet || options[:only_diff] || options[:only_mappings]),
|
|
12
|
+
mappings_legend: !(quiet || options[:no_legend] || options[:no_mappings] || options[:only_diff]),
|
|
13
|
+
mappings: !(quiet || options[:no_mappings] || options[:only_diff]),
|
|
14
|
+
differences_legend: !(quiet || options[:no_legend] || options[:no_diff_legend] || options[:no_diff] || options[:only_config]),
|
|
15
|
+
differences: !(quiet || options[:no_diff] || options[:only_mappings] || options[:only_config])
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if verbose
|
|
19
|
+
output_sections.transform_values! { |_| true }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
output_sections
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -3,15 +3,20 @@
|
|
|
3
3
|
module Dotsync
|
|
4
4
|
class PullAction < BaseAction
|
|
5
5
|
include MappingsTransfer
|
|
6
|
+
include OutputSections
|
|
6
7
|
|
|
7
8
|
def_delegator :@config, :backups_root
|
|
8
9
|
|
|
9
10
|
def execute(options = {})
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
output_sections = compute_output_sections(options)
|
|
12
|
+
|
|
13
|
+
show_options(options) if output_sections[:options]
|
|
14
|
+
show_env_vars if output_sections[:env_vars]
|
|
15
|
+
show_mappings_legend if output_sections[:mappings_legend]
|
|
16
|
+
show_mappings if output_sections[:mappings]
|
|
17
|
+
show_differences_legend if has_differences? && output_sections[:differences_legend]
|
|
18
|
+
show_differences if output_sections[:differences]
|
|
19
|
+
|
|
15
20
|
return unless options[:apply]
|
|
16
21
|
|
|
17
22
|
if create_backup
|
|
@@ -3,13 +3,18 @@
|
|
|
3
3
|
module Dotsync
|
|
4
4
|
class PushAction < BaseAction
|
|
5
5
|
include MappingsTransfer
|
|
6
|
+
include OutputSections
|
|
6
7
|
|
|
7
8
|
def execute(options = {})
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
output_sections = compute_output_sections(options)
|
|
10
|
+
|
|
11
|
+
show_options(options) if output_sections[:options]
|
|
12
|
+
show_env_vars if output_sections[:env_vars]
|
|
13
|
+
show_mappings_legend if output_sections[:mappings_legend]
|
|
14
|
+
show_mappings if output_sections[:mappings]
|
|
15
|
+
show_differences_legend if has_differences? && output_sections[:differences_legend]
|
|
16
|
+
show_differences if output_sections[:differences]
|
|
17
|
+
|
|
13
18
|
return unless options[:apply]
|
|
14
19
|
|
|
15
20
|
transfer_mappings
|
data/lib/dotsync/icons.rb
CHANGED
|
@@ -13,12 +13,17 @@ module Dotsync
|
|
|
13
13
|
CONFIG = " "
|
|
14
14
|
DIFF = " "
|
|
15
15
|
|
|
16
|
-
# Default
|
|
16
|
+
# Default Mappings Legend icons
|
|
17
17
|
DEFAULT_FORCE = " "
|
|
18
18
|
DEFAULT_ONLY = " "
|
|
19
19
|
DEFAULT_IGNORE = " "
|
|
20
20
|
DEFAULT_INVALID = " "
|
|
21
21
|
|
|
22
|
+
# Default Mappings Differences icons
|
|
23
|
+
DEFAULT_DIFF_CREATED = " "
|
|
24
|
+
DEFAULT_DIFF_UPDATED = " "
|
|
25
|
+
DEFAULT_DIFF_REMOVED = " "
|
|
26
|
+
|
|
22
27
|
# Action icons
|
|
23
28
|
PULL = " "
|
|
24
29
|
PUSH = " "
|
|
@@ -39,13 +44,20 @@ module Dotsync
|
|
|
39
44
|
|
|
40
45
|
def self.load_custom_icons(config)
|
|
41
46
|
@custom_icons = {
|
|
47
|
+
# Mappings Legend
|
|
42
48
|
force: config.dig("icons", "force") || DEFAULT_FORCE,
|
|
43
49
|
only: config.dig("icons", "only") || DEFAULT_ONLY,
|
|
44
50
|
ignore: config.dig("icons", "ignore") || DEFAULT_IGNORE,
|
|
45
|
-
invalid: config.dig("icons", "invalid") || DEFAULT_INVALID
|
|
51
|
+
invalid: config.dig("icons", "invalid") || DEFAULT_INVALID,
|
|
52
|
+
# Differences Legend
|
|
53
|
+
diff_created: config.dig("icons", "diff_created") || DEFAULT_DIFF_CREATED,
|
|
54
|
+
diff_updated: config.dig("icons", "diff_updated") || DEFAULT_DIFF_UPDATED,
|
|
55
|
+
diff_removed: config.dig("icons", "diff_removed") || DEFAULT_DIFF_REMOVED,
|
|
46
56
|
}
|
|
47
57
|
end
|
|
48
58
|
|
|
59
|
+
# Mappings Legend methods
|
|
60
|
+
|
|
49
61
|
def self.force
|
|
50
62
|
@custom_icons[:force] || DEFAULT_FORCE
|
|
51
63
|
end
|
|
@@ -62,6 +74,20 @@ module Dotsync
|
|
|
62
74
|
@custom_icons[:invalid] || DEFAULT_INVALID
|
|
63
75
|
end
|
|
64
76
|
|
|
77
|
+
# Differences Legend methods
|
|
78
|
+
|
|
79
|
+
def self.diff_created
|
|
80
|
+
@custom_icons[:diff_created] || DEFAULT_DIFF_CREATED
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def self.diff_updated
|
|
84
|
+
@custom_icons[:diff_updated] || DEFAULT_DIFF_UPDATED
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def self.diff_removed
|
|
88
|
+
@custom_icons[:diff_removed] || DEFAULT_DIFF_REMOVED
|
|
89
|
+
end
|
|
90
|
+
|
|
65
91
|
# https://www.nerdfonts.com
|
|
66
92
|
MAPPINGS = {
|
|
67
93
|
info: INFO,
|
data/lib/dotsync/models/diff.rb
CHANGED
|
@@ -13,7 +13,7 @@ module Dotsync
|
|
|
13
13
|
@original_only = Array(attributes["only"])
|
|
14
14
|
@force = attributes["force"] || false
|
|
15
15
|
|
|
16
|
-
@sanitized_src, @sanitized_dest, @
|
|
16
|
+
@sanitized_src, @sanitized_dest, @sanitized_ignores, @sanitized_only = process_paths(
|
|
17
17
|
@original_src,
|
|
18
18
|
@original_dest,
|
|
19
19
|
@original_ignores,
|
|
@@ -30,7 +30,7 @@ module Dotsync
|
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
def ignores
|
|
33
|
-
@
|
|
33
|
+
@sanitized_ignores
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def inclusions
|
|
@@ -77,11 +77,11 @@ module Dotsync
|
|
|
77
77
|
|
|
78
78
|
def icons
|
|
79
79
|
msg = []
|
|
80
|
-
msg << Icons.invalid unless valid?
|
|
81
|
-
msg << Icons.only if only?
|
|
82
|
-
msg << Icons.ignore if ignores?
|
|
83
80
|
msg << Icons.force if force?
|
|
84
|
-
msg.
|
|
81
|
+
msg << Icons.only if has_inclusions?
|
|
82
|
+
msg << Icons.ignore if has_ignores?
|
|
83
|
+
msg << Icons.invalid unless valid?
|
|
84
|
+
msg.join
|
|
85
85
|
end
|
|
86
86
|
|
|
87
87
|
def to_s
|
|
@@ -114,25 +114,41 @@ module Dotsync
|
|
|
114
114
|
)
|
|
115
115
|
end
|
|
116
116
|
|
|
117
|
+
def include?(path)
|
|
118
|
+
return true unless has_inclusions?
|
|
119
|
+
return true if path == src
|
|
120
|
+
inclusions.any? { |inclusion| path_is_parent_or_same?(inclusion, path) }
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def bidirectional_include?(path)
|
|
124
|
+
return true unless has_inclusions?
|
|
125
|
+
return true if path == src
|
|
126
|
+
inclusions.any? { |inclusion| path_is_parent_or_same?(inclusion, path) || path_is_parent_or_same?(path, inclusion) }
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def ignore?(path)
|
|
130
|
+
ignores.any? { |ignore| path.start_with?(ignore) }
|
|
131
|
+
end
|
|
132
|
+
|
|
117
133
|
private
|
|
118
|
-
def
|
|
134
|
+
def has_ignores?
|
|
119
135
|
@original_ignores.any?
|
|
120
136
|
end
|
|
121
137
|
|
|
122
|
-
def
|
|
138
|
+
def has_inclusions?
|
|
123
139
|
@original_only.any?
|
|
124
140
|
end
|
|
125
141
|
|
|
126
142
|
def process_paths(raw_src, raw_dest, raw_ignores, raw_only)
|
|
127
143
|
sanitized_src = sanitize_path(raw_src)
|
|
128
144
|
sanitized_dest = sanitize_path(raw_dest)
|
|
129
|
-
|
|
145
|
+
sanitized_ignores = raw_ignores.flat_map do |path|
|
|
130
146
|
[File.join(sanitized_src, path), File.join(sanitized_dest, path)]
|
|
131
147
|
end
|
|
132
148
|
sanitized_only = raw_only.map do |path|
|
|
133
149
|
File.join(sanitized_src, path)
|
|
134
150
|
end
|
|
135
|
-
[sanitized_src, sanitized_dest,
|
|
151
|
+
[sanitized_src, sanitized_dest, sanitized_ignores, sanitized_only]
|
|
136
152
|
end
|
|
137
153
|
end
|
|
138
154
|
end
|
|
@@ -36,6 +36,11 @@ 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)
|
|
40
|
+
Find.prune
|
|
41
|
+
next
|
|
42
|
+
end
|
|
43
|
+
|
|
39
44
|
dest_path = File.join(mapping_dest, rel_path)
|
|
40
45
|
|
|
41
46
|
if !File.exist?(dest_path)
|
|
@@ -62,7 +67,7 @@ module Dotsync
|
|
|
62
67
|
|
|
63
68
|
additions = relative_to_absolute(filter_ignores(additions), mapping_original_dest)
|
|
64
69
|
modifications = relative_to_absolute(filter_ignores(modifications), mapping_original_dest)
|
|
65
|
-
removals = relative_to_absolute(filter_ignores(removals),
|
|
70
|
+
removals = relative_to_absolute(filter_ignores(removals), mapping_original_dest)
|
|
66
71
|
|
|
67
72
|
Dotsync::Diff.new(additions: additions, modifications: modifications, removals: removals)
|
|
68
73
|
end
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
module Dotsync
|
|
4
4
|
class FileTransfer
|
|
5
|
-
attr_reader :ignores
|
|
6
|
-
|
|
7
5
|
# Initializes a new FileTransfer instance
|
|
8
6
|
#
|
|
9
7
|
# @param mapping [Dotsync::Mapping] the mapping object containing source, destination, force, and ignore details
|
|
@@ -12,6 +10,7 @@ module Dotsync
|
|
|
12
10
|
# @option mapping [Boolean] :force? optional flag to force actions
|
|
13
11
|
# @option mapping [Array<String>] :ignores optional list of files/directories to ignore
|
|
14
12
|
def initialize(mapping)
|
|
13
|
+
@mapping = mapping
|
|
15
14
|
@src = mapping.src
|
|
16
15
|
@dest = mapping.dest
|
|
17
16
|
@force = mapping.force?
|
|
@@ -29,6 +28,8 @@ module Dotsync
|
|
|
29
28
|
end
|
|
30
29
|
|
|
31
30
|
private
|
|
31
|
+
attr_reader :mapping, :ignores
|
|
32
|
+
|
|
32
33
|
def transfer_file(file_src, file_dest)
|
|
33
34
|
FileUtils.mkdir_p(File.dirname(file_dest))
|
|
34
35
|
FileUtils.cp(file_src, file_dest)
|
|
@@ -36,12 +37,17 @@ module Dotsync
|
|
|
36
37
|
|
|
37
38
|
def transfer_folder(folder_src, folder_dest)
|
|
38
39
|
FileUtils.mkdir_p(folder_dest)
|
|
40
|
+
|
|
41
|
+
# `Dir.glob("#{folder_src}/*")` retrieves only the immediate contents
|
|
42
|
+
# (files and directories) within the specified directory (`folder_src`),
|
|
43
|
+
# without descending into subdirectories.
|
|
44
|
+
|
|
39
45
|
Dir.glob("#{folder_src}/*", File::FNM_DOTMATCH).each do |path|
|
|
40
46
|
next if [".", ".."].include?(File.basename(path))
|
|
41
47
|
|
|
42
48
|
full_path = File.expand_path(path)
|
|
43
|
-
next unless
|
|
44
|
-
next if ignore?(full_path)
|
|
49
|
+
next unless mapping.bidirectional_include?(full_path)
|
|
50
|
+
next if mapping.ignore?(full_path)
|
|
45
51
|
|
|
46
52
|
target = File.join(folder_dest, File.basename(path))
|
|
47
53
|
if File.file?(full_path)
|
|
@@ -77,14 +83,5 @@ module Dotsync
|
|
|
77
83
|
end
|
|
78
84
|
end
|
|
79
85
|
end
|
|
80
|
-
|
|
81
|
-
def inclusion?(path)
|
|
82
|
-
return true unless @inclusions.any?
|
|
83
|
-
@inclusions.any? { |inclusion| path.start_with?(inclusion) || inclusion.start_with?(path) }
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
def ignore?(path)
|
|
87
|
-
@ignores.any? { |ignore| path.start_with?(ignore) }
|
|
88
|
-
end
|
|
89
86
|
end
|
|
90
87
|
end
|
|
@@ -24,6 +24,12 @@ module Dotsync
|
|
|
24
24
|
paths.map { |path| File.join(base_path, path) }
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
+
def path_is_parent_or_same?(parent, child)
|
|
28
|
+
parent = Pathname.new(parent).expand_path
|
|
29
|
+
child = Pathname.new(child).expand_path
|
|
30
|
+
child.ascend.any? { |ancestor| ancestor == parent }
|
|
31
|
+
end
|
|
32
|
+
|
|
27
33
|
# Translates /tmp paths to /private/tmp paths on macOS
|
|
28
34
|
# Retains other paths as-is
|
|
29
35
|
# @param [String] path The input path to translate
|
data/lib/dotsync/version.rb
CHANGED
data/lib/dotsync.rb
CHANGED
|
@@ -38,6 +38,7 @@ require_relative "dotsync/config/watch_action_config"
|
|
|
38
38
|
|
|
39
39
|
# Actions Concerns
|
|
40
40
|
require_relative "dotsync/actions/concerns/mappings_transfer"
|
|
41
|
+
require_relative "dotsync/actions/concerns/output_sections"
|
|
41
42
|
|
|
42
43
|
# Actions
|
|
43
44
|
require_relative "dotsync/actions/base_action"
|
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.
|
|
4
|
+
version: 0.1.16
|
|
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-
|
|
11
|
+
date: 2025-11-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: toml-rb
|
|
@@ -252,9 +252,7 @@ description: Keep in sync your dotfiles across machines with a single TOML file
|
|
|
252
252
|
email:
|
|
253
253
|
- david.saenz.tagarro@gmail.com
|
|
254
254
|
executables:
|
|
255
|
-
- console
|
|
256
255
|
- dotsync
|
|
257
|
-
- setup
|
|
258
256
|
extensions: []
|
|
259
257
|
extra_rdoc_files: []
|
|
260
258
|
files:
|
|
@@ -272,16 +270,17 @@ files:
|
|
|
272
270
|
- README.md
|
|
273
271
|
- RELEASING.md
|
|
274
272
|
- Rakefile
|
|
273
|
+
- bin/console
|
|
274
|
+
- bin/setup
|
|
275
275
|
- docs/images/dotsync_pull.png
|
|
276
276
|
- docs/images/dotsync_push.png
|
|
277
277
|
- docs/images/dotsync_push_apply.png
|
|
278
278
|
- dotsync.gemspec
|
|
279
|
-
- exe/console
|
|
280
279
|
- exe/dotsync
|
|
281
|
-
- exe/setup
|
|
282
280
|
- lib/dotsync.rb
|
|
283
281
|
- lib/dotsync/actions/base_action.rb
|
|
284
282
|
- lib/dotsync/actions/concerns/mappings_transfer.rb
|
|
283
|
+
- lib/dotsync/actions/concerns/output_sections.rb
|
|
285
284
|
- lib/dotsync/actions/pull_action.rb
|
|
286
285
|
- lib/dotsync/actions/push_action.rb
|
|
287
286
|
- lib/dotsync/actions/watch_action.rb
|
/data/{exe → bin}/console
RENAMED
|
File without changes
|
/data/{exe → bin}/setup
RENAMED
|
File without changes
|