dotsync 0.1.14 → 0.1.15
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 +1 -1
- data/CHANGELOG.md +7 -0
- data/Gemfile.lock +1 -1
- data/README.md +8 -0
- data/docs/images/dotsync_pull.png +0 -0
- data/docs/images/dotsync_push.png +0 -0
- data/lib/dotsync/actions/concerns/mappings_transfer.rb +1 -1
- data/lib/dotsync/models/mapping.rb +26 -10
- data/lib/dotsync/utils/directory_differ.rb +5 -0
- 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
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c1bdf9f9ccaf7c8fb89e69d1e2f8cd95b72bc7b089d2e582fb358a84ebefb6d2
|
|
4
|
+
data.tar.gz: e05942884ce70c0921c8bfa18f7a9e8be1d8f92ff06912b1f9d09098088ff8fc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f33b7f4c6293a0a50c263560f433f7712f6b7d67f997222db3070c7c72b35837b7ed7d92c1b7fcc3b05574d047db6d4daa8a97bd20438e1237ed9f1ffbd8fba8
|
|
7
|
+
data.tar.gz: 15e81bab5c0eaba1ab206c7a8c720f1baaacceb1e8ee5429e7ec1df20515329466c1a43949a637a8485219d92578d2e6acefc3768a529aef9136b90ab6d6b34a
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -114,6 +114,14 @@ dest = "$DOTFILES_DIR/config/alacritty"
|
|
|
114
114
|
Each mapping entry supports the following options:
|
|
115
115
|
|
|
116
116
|
- **`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.
|
|
117
|
+
- **`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:
|
|
118
|
+
```toml
|
|
119
|
+
[[push.mappings]]
|
|
120
|
+
src = "$XDG_CONFIG_HOME"
|
|
121
|
+
dest = "$DOTFILES_DIR/config"
|
|
122
|
+
only = ["config.yml", "themes"]
|
|
123
|
+
|
|
124
|
+
```
|
|
117
125
|
- **`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
126
|
|
|
119
127
|
These options apply when the source is a directory and are relevant for both `push` and `pull` operations.
|
|
Binary file
|
|
Binary file
|
|
@@ -6,7 +6,7 @@ module Dotsync
|
|
|
6
6
|
|
|
7
7
|
LEGEND = [
|
|
8
8
|
[Dotsync::Icons.force, "The source will overwrite the destination"],
|
|
9
|
-
[Dotsync::Icons.only, "
|
|
9
|
+
[Dotsync::Icons.only, "Paths designated explicitly as source only"],
|
|
10
10
|
[Dotsync::Icons.ignore, "Paths configured to be ignored in the destination"],
|
|
11
11
|
[Dotsync::Icons.invalid, "Invalid paths detected in the source or destination"]
|
|
12
12
|
]
|
|
@@ -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)
|
|
@@ -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
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.15
|
|
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-07 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: toml-rb
|