filedepot 0.1.0 → 0.2.0
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/lib/filedepot/cli.rb +87 -18
- data/lib/filedepot/config.rb +4 -1
- data/lib/filedepot/storage/base.rb +71 -0
- data/lib/filedepot/storage_ssh.rb +176 -0
- data/lib/filedepot/version.rb +1 -1
- data/lib/filedepot.rb +2 -0
- metadata +33 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d3adae8af29b5bf23fca9832843d431f9ecac1a3a185309185858109de26c9ea
|
|
4
|
+
data.tar.gz: 180afd3e6ad41a51a63c3ddd8ecfa5920519c9135180c74ea1cc10de631dd629
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2324d4048ddc0d01ad140393850b36c4615cf6104d60251d868563171499b6f5505f761ed1b225a0aa9851fcfadc7b9c6aed1bc9b6ddb068f51d4b9eee6c4d40
|
|
7
|
+
data.tar.gz: aea6ac1df0926cff12f09f9547126cb6c449343e62c91f40c1615397396c80608c531c4c2a02faf957f885e18357c92982abf9510f8e7a22c8e3589a3d41627c
|
data/lib/filedepot/cli.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "fileutils"
|
|
3
4
|
require "thor"
|
|
4
5
|
|
|
5
6
|
module Filedepot
|
|
@@ -15,16 +16,24 @@ module Filedepot
|
|
|
15
16
|
HELP
|
|
16
17
|
push: <<~HELP,
|
|
17
18
|
Usage:
|
|
18
|
-
filedepot push HANDLE
|
|
19
|
+
filedepot push HANDLE FILE
|
|
19
20
|
|
|
20
|
-
Send a file with a specific handle
|
|
21
|
+
Send a file to the current storage with a specific handle.
|
|
22
|
+
Example: filedepot push test test.txt
|
|
21
23
|
HELP
|
|
22
24
|
pull: <<~HELP,
|
|
23
25
|
Usage:
|
|
24
|
-
filedepot pull HANDLE [VERSION]
|
|
25
|
-
|
|
26
|
-
Get
|
|
27
|
-
|
|
26
|
+
filedepot pull HANDLE [--path PATH] [--version VERSION]
|
|
27
|
+
|
|
28
|
+
Get a file from storage. By default gets the latest version and saves to current directory.
|
|
29
|
+
Options:
|
|
30
|
+
--path PATH Save to this local path (e.g. ./test/file.txt)
|
|
31
|
+
--version N Get specific version (default: latest)
|
|
32
|
+
Examples:
|
|
33
|
+
filedepot pull test
|
|
34
|
+
filedepot pull test --path ./test/file.txt
|
|
35
|
+
filedepot pull test --version 2
|
|
36
|
+
filedepot pull test --version 2 --path ./test/file.txt
|
|
28
37
|
HELP
|
|
29
38
|
versions: <<~HELP,
|
|
30
39
|
Usage:
|
|
@@ -49,23 +58,53 @@ module Filedepot
|
|
|
49
58
|
exec(editor, config_path)
|
|
50
59
|
end
|
|
51
60
|
|
|
52
|
-
desc "push HANDLE", "Send a file with a specific handle
|
|
53
|
-
def push(handle
|
|
54
|
-
|
|
55
|
-
|
|
61
|
+
desc "push HANDLE FILE", "Send a file to the current storage with a specific handle"
|
|
62
|
+
def push(handle, file_path)
|
|
63
|
+
source = Config.current_source
|
|
64
|
+
if source.nil?
|
|
65
|
+
puts "Error: No storage source configured. Run 'filedepot config' to set up."
|
|
56
66
|
return
|
|
57
67
|
end
|
|
58
|
-
|
|
68
|
+
|
|
69
|
+
storage = Storage::Base.for(source)
|
|
70
|
+
storage.push(handle, file_path)
|
|
71
|
+
puts "Pushed #{file_path} as #{handle} (version #{storage.current_version(handle)})"
|
|
59
72
|
end
|
|
60
73
|
|
|
61
|
-
desc "pull HANDLE
|
|
62
|
-
|
|
74
|
+
desc "pull HANDLE", "Get file from storage"
|
|
75
|
+
method_option :path, type: :string, desc: "Local path to save the file"
|
|
76
|
+
method_option :version, type: :string, desc: "Version number to pull (default: latest)"
|
|
77
|
+
def pull(handle = nil)
|
|
63
78
|
if handle.nil?
|
|
64
79
|
puts COMMAND_HELP[:pull]
|
|
65
80
|
return
|
|
66
81
|
end
|
|
67
|
-
|
|
68
|
-
|
|
82
|
+
|
|
83
|
+
source = Config.current_source
|
|
84
|
+
if source.nil?
|
|
85
|
+
puts "Error: No storage source configured. Run 'filedepot config' to set up."
|
|
86
|
+
return
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
local_path = options[:path]
|
|
90
|
+
version = (options[:version].nil? || options[:version].empty?) ? nil : options[:version].to_i
|
|
91
|
+
|
|
92
|
+
storage = Storage::Base.for(source)
|
|
93
|
+
info = storage.pull_info(handle, version, local_path)
|
|
94
|
+
target_path = info[:target_path]
|
|
95
|
+
|
|
96
|
+
parent_dir = File.dirname(target_path)
|
|
97
|
+
unless parent_dir == "." || File.directory?(parent_dir)
|
|
98
|
+
return unless confirm?("create local directory #{parent_dir}, y/n?")
|
|
99
|
+
FileUtils.mkdir_p(parent_dir)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
if File.exist?(target_path)
|
|
103
|
+
return unless confirm?("overwrite local #{target_path}, y/n?")
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
storage.pull(handle, version, target_path)
|
|
107
|
+
puts "Pulled #{handle} (version #{info[:version_num]}) to #{target_path}"
|
|
69
108
|
end
|
|
70
109
|
|
|
71
110
|
desc "versions HANDLE", "List all versions of a handle (each version has an integer from 1 to n)"
|
|
@@ -74,7 +113,26 @@ module Filedepot
|
|
|
74
113
|
puts COMMAND_HELP[:versions]
|
|
75
114
|
return
|
|
76
115
|
end
|
|
77
|
-
|
|
116
|
+
|
|
117
|
+
source = Config.current_source
|
|
118
|
+
if source.nil?
|
|
119
|
+
puts "Error: No storage source configured. Run 'filedepot config' to set up."
|
|
120
|
+
return
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
storage = Storage::Base.for(source)
|
|
124
|
+
versions_list = storage.versions(handle)
|
|
125
|
+
if versions_list.empty?
|
|
126
|
+
puts "No versions found for handle: #{handle}"
|
|
127
|
+
else
|
|
128
|
+
max_display = 10
|
|
129
|
+
to_show = versions_list.first(max_display)
|
|
130
|
+
to_show.each { |v, date_str| puts date_str.empty? ? v.to_s : "#{v} - #{date_str}" }
|
|
131
|
+
if versions_list.size > max_display
|
|
132
|
+
remaining = versions_list.size - max_display
|
|
133
|
+
puts "... and #{remaining} other ones for a total of #{versions_list.size} versions"
|
|
134
|
+
end
|
|
135
|
+
end
|
|
78
136
|
end
|
|
79
137
|
|
|
80
138
|
desc "delete HANDLE [VERSION]", "After confirmation, delete all versions of a file; or only a specific version if specified"
|
|
@@ -105,8 +163,8 @@ module Filedepot
|
|
|
105
163
|
puts ""
|
|
106
164
|
puts "Available commands:"
|
|
107
165
|
puts " filedepot config Open config file using $EDITOR"
|
|
108
|
-
puts " filedepot push HANDLE
|
|
109
|
-
puts " filedepot pull HANDLE [
|
|
166
|
+
puts " filedepot push HANDLE FILE Send file to current storage"
|
|
167
|
+
puts " filedepot pull HANDLE [--path PATH] [--version N] Get file from storage"
|
|
110
168
|
puts " filedepot versions HANDLE List all versions of a handle"
|
|
111
169
|
puts " filedepot delete HANDLE [VER] Delete file(s) after confirmation"
|
|
112
170
|
puts ""
|
|
@@ -116,5 +174,16 @@ module Filedepot
|
|
|
116
174
|
def self.exit_on_failure?
|
|
117
175
|
true
|
|
118
176
|
end
|
|
177
|
+
|
|
178
|
+
private
|
|
179
|
+
|
|
180
|
+
def confirm?(prompt)
|
|
181
|
+
print "#{prompt} "
|
|
182
|
+
input = $stdin.gets&.strip&.downcase
|
|
183
|
+
input == "y" || input == "yes"
|
|
184
|
+
rescue Interrupt
|
|
185
|
+
puts
|
|
186
|
+
false
|
|
187
|
+
end
|
|
119
188
|
end
|
|
120
189
|
end
|
data/lib/filedepot/config.rb
CHANGED
|
@@ -36,7 +36,10 @@ module Filedepot
|
|
|
36
36
|
config = load
|
|
37
37
|
default = config["default_source"]
|
|
38
38
|
sources = config["sources"] || []
|
|
39
|
-
|
|
39
|
+
return nil if sources.empty?
|
|
40
|
+
|
|
41
|
+
source = sources.find { |s| (s["name"] || s[:name]) == default }
|
|
42
|
+
source || sources.first
|
|
40
43
|
end
|
|
41
44
|
end
|
|
42
45
|
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Filedepot
|
|
4
|
+
module Storage
|
|
5
|
+
class Base
|
|
6
|
+
def self.for(source)
|
|
7
|
+
if source["ssh"]
|
|
8
|
+
SshStorage.new(source)
|
|
9
|
+
else
|
|
10
|
+
raise ArgumentError, "Unknown storage type for source: #{source["name"]}"
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def initialize(source)
|
|
15
|
+
@source = source
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def current_version(handle)
|
|
19
|
+
path = current_version_path(handle)
|
|
20
|
+
path.nil? || path.to_s.empty? ? 0 : File.basename(path).to_i
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def next_version(handle)
|
|
24
|
+
current_version(handle) + 1
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def next_version_path(handle)
|
|
28
|
+
File.join(remote_handle_path(handle), next_version(handle).to_s)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def current_version_path(handle)
|
|
32
|
+
raise "not implemented"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def test
|
|
36
|
+
raise "not implemented"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def ls
|
|
40
|
+
raise "not implemented"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def push(handle, local_path)
|
|
44
|
+
raise "not implemented"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def pull(handle, version = nil, local_path = nil)
|
|
48
|
+
raise "not implemented"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def versions(handle)
|
|
52
|
+
raise "not implemented"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def delete(handle, version = nil)
|
|
56
|
+
raise "not implemented"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
protected
|
|
60
|
+
|
|
61
|
+
def remote_base_path
|
|
62
|
+
@source["base_path"] || "/tmp/filedepot"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def remote_handle_path(handle)
|
|
66
|
+
safe_handle = handle.to_s.gsub(%r{[^\w\-./]}, "_")
|
|
67
|
+
File.join(remote_base_path, safe_handle)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "shellwords"
|
|
4
|
+
require "net/ssh"
|
|
5
|
+
require "net/scp"
|
|
6
|
+
|
|
7
|
+
module Filedepot
|
|
8
|
+
module Storage
|
|
9
|
+
class SshStorage < Base
|
|
10
|
+
def test
|
|
11
|
+
ssh_session do |ssh|
|
|
12
|
+
result = ssh.exec!("echo ok")
|
|
13
|
+
raise "Connection failed" unless result&.include?("ok")
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def ls
|
|
18
|
+
handles = []
|
|
19
|
+
ssh_session do |ssh|
|
|
20
|
+
result = ssh.exec!("ls -1 #{shell_escape(remote_base_path)} 2>/dev/null || true")
|
|
21
|
+
return [] if result.nil? || result.strip.empty?
|
|
22
|
+
|
|
23
|
+
handles = result.strip.split("\n").select { |line| !line.empty? }
|
|
24
|
+
end
|
|
25
|
+
handles
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def push(handle, local_path)
|
|
29
|
+
path = File.expand_path(local_path)
|
|
30
|
+
raise "File not found: #{local_path}" unless File.file?(path)
|
|
31
|
+
|
|
32
|
+
push_path = next_version_path(handle)
|
|
33
|
+
|
|
34
|
+
ssh_session do |ssh|
|
|
35
|
+
ssh.exec!("mkdir -p #{shell_escape(push_path)}")
|
|
36
|
+
# Upload to directory - SCP places file with original name inside
|
|
37
|
+
ssh.scp.upload!(path, push_path)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def current_version_path(handle)
|
|
42
|
+
ssh_session do |ssh|
|
|
43
|
+
handle_dir = remote_handle_path(handle)
|
|
44
|
+
ssh.exec!("mkdir -p #{shell_escape(handle_dir)}")
|
|
45
|
+
|
|
46
|
+
result = ssh.exec!("ls -1 #{shell_escape(handle_dir)} 2>/dev/null || true")
|
|
47
|
+
versions = parse_versions(result)
|
|
48
|
+
|
|
49
|
+
if versions.empty?
|
|
50
|
+
nil
|
|
51
|
+
else
|
|
52
|
+
File.join(handle_dir, versions.max.to_s)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def pull(handle, version = nil, local_path = nil)
|
|
58
|
+
ssh_session do |ssh|
|
|
59
|
+
versions_list = versions_for(ssh, handle)
|
|
60
|
+
raise "No versions found for handle: #{handle}" if versions_list.empty?
|
|
61
|
+
|
|
62
|
+
version_num = version ? version.to_i : versions_list.max
|
|
63
|
+
raise "Version #{version} not found" unless versions_list.include?(version_num)
|
|
64
|
+
|
|
65
|
+
version_dir = File.join(remote_handle_path(handle), version_num.to_s)
|
|
66
|
+
remote_file = first_file_in_dir(ssh, version_dir)
|
|
67
|
+
raise "No file found in version #{version_num}" if remote_file.nil?
|
|
68
|
+
|
|
69
|
+
remote_filename = File.basename(remote_file)
|
|
70
|
+
target_path = resolve_local_path(local_path, remote_filename)
|
|
71
|
+
|
|
72
|
+
ssh.scp.download!(remote_file, target_path)
|
|
73
|
+
target_path
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def pull_info(handle, version = nil, local_path = nil)
|
|
78
|
+
ssh_session do |ssh|
|
|
79
|
+
versions_list = versions_for(ssh, handle)
|
|
80
|
+
raise "No versions found for handle: #{handle}" if versions_list.empty?
|
|
81
|
+
|
|
82
|
+
version_num = version ? version.to_i : versions_list.max
|
|
83
|
+
raise "Version #{version} not found" unless versions_list.include?(version_num)
|
|
84
|
+
|
|
85
|
+
version_dir = File.join(remote_handle_path(handle), version_num.to_s)
|
|
86
|
+
remote_file = first_file_in_dir(ssh, version_dir)
|
|
87
|
+
raise "No file found in version #{version_num}" if remote_file.nil?
|
|
88
|
+
|
|
89
|
+
remote_filename = File.basename(remote_file)
|
|
90
|
+
target_path = resolve_local_path(local_path, remote_filename)
|
|
91
|
+
|
|
92
|
+
{ remote_filename: remote_filename, version_num: version_num, target_path: target_path }
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def versions(handle)
|
|
97
|
+
ssh_session do |ssh|
|
|
98
|
+
versions_list = versions_for(ssh, handle).sort.reverse
|
|
99
|
+
versions_list.map do |v|
|
|
100
|
+
version_dir = File.join(remote_handle_path(handle), v.to_s)
|
|
101
|
+
epoch = stat_mtime(ssh, version_dir)
|
|
102
|
+
date_str = epoch ? Time.at(epoch).to_s : ""
|
|
103
|
+
[v, date_str]
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def delete(handle, version = nil)
|
|
109
|
+
ssh_session do |ssh|
|
|
110
|
+
handle_dir = remote_handle_path(handle)
|
|
111
|
+
|
|
112
|
+
if version
|
|
113
|
+
version_dir = File.join(handle_dir, version.to_s)
|
|
114
|
+
ssh.exec!("rm -rf #{shell_escape(version_dir)}")
|
|
115
|
+
versions_remaining = versions_for(ssh, handle)
|
|
116
|
+
ssh.exec!("rmdir #{shell_escape(handle_dir)} 2>/dev/null || true") if versions_remaining.empty?
|
|
117
|
+
else
|
|
118
|
+
ssh.exec!("rm -rf #{shell_escape(handle_dir)}")
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
private
|
|
124
|
+
|
|
125
|
+
def shell_escape(path)
|
|
126
|
+
Shellwords.shellescape(path.to_s)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def ssh_session
|
|
130
|
+
host = @source["host"] || "localhost"
|
|
131
|
+
user = @source["username"].to_s.strip
|
|
132
|
+
user = ENV["USER"] if user.empty?
|
|
133
|
+
|
|
134
|
+
Net::SSH.start(host, user) do |ssh|
|
|
135
|
+
yield ssh
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def versions_for(ssh, handle)
|
|
140
|
+
remote_dir = remote_handle_path(handle)
|
|
141
|
+
result = ssh.exec!("ls -1 #{shell_escape(remote_dir)} 2>/dev/null || true")
|
|
142
|
+
parse_versions(result)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def parse_versions(ls_result)
|
|
146
|
+
return [] if ls_result.nil? || ls_result.strip.empty?
|
|
147
|
+
|
|
148
|
+
ls_result.strip.split("\n").map(&:to_i).select { |v| v.positive? }
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def first_file_in_dir(ssh, dir)
|
|
152
|
+
result = ssh.exec!("ls -1 #{shell_escape(dir)} 2>/dev/null || true")
|
|
153
|
+
return nil if result.nil? || result.strip.empty?
|
|
154
|
+
|
|
155
|
+
first = result.strip.split("\n").first
|
|
156
|
+
first ? File.join(dir, first) : nil
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def stat_mtime(ssh, path)
|
|
160
|
+
# Linux: stat -c %Y; macOS: stat -f %m
|
|
161
|
+
result = ssh.exec!("stat -c %Y #{shell_escape(path)} 2>/dev/null || stat -f %m #{shell_escape(path)} 2>/dev/null")
|
|
162
|
+
result&.strip&.to_i
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def resolve_local_path(local_path_param, remote_filename)
|
|
166
|
+
if local_path_param.nil? || local_path_param.empty?
|
|
167
|
+
File.join(Dir.pwd, remote_filename)
|
|
168
|
+
elsif local_path_param.end_with?("/") || (File.exist?(local_path_param) && File.directory?(local_path_param))
|
|
169
|
+
File.join(File.expand_path(local_path_param), remote_filename)
|
|
170
|
+
else
|
|
171
|
+
File.expand_path(local_path_param)
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
data/lib/filedepot/version.rb
CHANGED
data/lib/filedepot.rb
CHANGED
metadata
CHANGED
|
@@ -1,15 +1,42 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: filedepot
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Filedepot
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: net-scp
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '4.0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '4.0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: net-ssh
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '7.0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '7.0'
|
|
13
40
|
- !ruby/object:Gem::Dependency
|
|
14
41
|
name: thor
|
|
15
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -37,6 +64,8 @@ files:
|
|
|
37
64
|
- lib/filedepot.rb
|
|
38
65
|
- lib/filedepot/cli.rb
|
|
39
66
|
- lib/filedepot/config.rb
|
|
67
|
+
- lib/filedepot/storage/base.rb
|
|
68
|
+
- lib/filedepot/storage_ssh.rb
|
|
40
69
|
- lib/filedepot/version.rb
|
|
41
70
|
homepage: https://github.com/filedepot/filedepot
|
|
42
71
|
licenses:
|
|
@@ -44,7 +73,6 @@ licenses:
|
|
|
44
73
|
metadata:
|
|
45
74
|
homepage_uri: https://github.com/filedepot/filedepot
|
|
46
75
|
source_code_uri: https://github.com/filedepot/filedepot
|
|
47
|
-
post_install_message:
|
|
48
76
|
rdoc_options: []
|
|
49
77
|
require_paths:
|
|
50
78
|
- lib
|
|
@@ -59,8 +87,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
59
87
|
- !ruby/object:Gem::Version
|
|
60
88
|
version: '0'
|
|
61
89
|
requirements: []
|
|
62
|
-
rubygems_version:
|
|
63
|
-
signing_key:
|
|
90
|
+
rubygems_version: 4.0.6
|
|
64
91
|
specification_version: 4
|
|
65
92
|
summary: Sync files on remote storage
|
|
66
93
|
test_files: []
|