filedepot 0.2.1 → 0.2.3

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: 3323f568d221fde7de4cd30f7450b46444f48bcfe71b2e0dd16acfe84d97fd14
4
- data.tar.gz: 39318899de695422ef75292f4e5c5a8cf3271b91ef0d474fdc1305ebfd78dead
3
+ metadata.gz: f80cd1081d4c69688ad58719d89075aed90a478c06f072c0f3d6d30c15cff7a5
4
+ data.tar.gz: 2130f1375526a13365fa3d0f2a4205f6179eaedbc88bdaea61f3c09447ac57a4
5
5
  SHA512:
6
- metadata.gz: 37f23733b8942db6547ab12960cef9308717f1836ff4c1ae6959c3a1196c00195508f4a5d996d8b9efd10a7ac93552799d633fa11e475f6575ddccee690985ee
7
- data.tar.gz: 70f21d4037d84be1cc71c12032eb7e31253b304511af80e8d6fb7e397823e87a9c4718db35466bfe746ca3cfc249a089bc65e534d1e3330240196a5dc703c8a0
6
+ metadata.gz: 86e661e4fcf117a4e52372c44be2d2d5526c222c37a6dbf109e3e092f3cb53785b337b5d39fdd0a7ac58c983c5cf05d9068122e1640ddb6e5a4142d9cd52c8ae
7
+ data.tar.gz: 136db28f96ecccebfb575f199bca70f0309d40386ecdd719d4792f6d72c8646aef0aba464997fdeafa0c9b232856c5cd2c162883516b0c88fc666ed903ee3e5a
data/README.md CHANGED
@@ -30,17 +30,66 @@ sources:
30
30
  base_path: /Users/user/filedepot
31
31
  ```
32
32
 
33
+ Optional `public_base_path` for public URLs (shown in info and after push):
34
+
35
+ ```yaml
36
+ sources:
37
+ - name: test
38
+ ssh: ssh
39
+ host: 127.0.0.1
40
+ base_path: /data/filedepot
41
+ public_base_path: https://example.com/files
42
+ ```
43
+
44
+ When `default_source` does not match any source name, the first source is used.
45
+
33
46
  ## Commands
34
47
 
35
48
  | Command | Description |
36
49
  |---------|-------------|
37
50
  | `filedepot` | Show current source and available commands |
38
51
  | `filedepot config` | Open config file with $EDITOR |
39
- | `filedepot push HANDLE` | Send file to current storage |
40
- | `filedepot pull HANDLE [VERSION]` | Get file from storage |
52
+ | `filedepot push HANDLE FILE` | Send file to current storage |
53
+ | `filedepot pull HANDLE [--path PATH] [--version N]` | Get file from storage |
54
+ | `filedepot handles` | List all handles in storage |
41
55
  | `filedepot versions HANDLE` | List all versions of a handle |
56
+ | `filedepot info HANDLE` | Show info for a handle |
42
57
  | `filedepot delete HANDLE [VERSION]` | Delete file(s) after confirmation |
43
58
 
59
+ ### Push
60
+
61
+ ```bash
62
+ filedepot push test test.txt
63
+ ```
64
+
65
+ Sends `test.txt` to storage with handle `test`. Each push creates a new version. When `public_base_path` is configured, the URL is shown after upload.
66
+
67
+ ### Pull
68
+
69
+ ```bash
70
+ filedepot pull test
71
+ filedepot pull test --path ./output/file.txt
72
+ filedepot pull test --version 2
73
+ filedepot pull test --version 2 --path ./output/file.txt
74
+ ```
75
+
76
+ Gets the latest version by default, or a specific version with `--version`. Use `--path` to specify the local destination. Prompts before creating directories or overwriting files.
77
+
78
+ ### Versions
79
+
80
+ Lists versions in descending order with creation datetime. Shows at most 10, with a summary if more exist.
81
+
82
+ ### Info
83
+
84
+ Shows handle, remote base path, current version, updated-at datetime, and latest version URL (when `public_base_path` is set).
85
+
86
+ ## Testing
87
+
88
+ ```bash
89
+ bundle install
90
+ bundle exec rake test
91
+ ```
92
+
44
93
  ## License
45
94
 
46
95
  MIT
data/lib/filedepot/cli.rb CHANGED
@@ -37,7 +37,8 @@ module Filedepot
37
37
  HELP
38
38
  versions: "Usage: filedepot versions HANDLE\n\nList all versions of a handle. Each version has an integer ID from 1 to n.",
39
39
  delete: "Usage: filedepot delete HANDLE [VERSION]\n\nAfter confirmation, deletes all versions of a file.\nIf VERSION is specified, deletes only that specific version.",
40
- info: "Usage: filedepot info HANDLE\n\nShow info for a handle: remote base path and current version."
40
+ info: "Usage: filedepot info HANDLE\n\nShow info for a handle: remote base path and current version.",
41
+ handles: "Usage: filedepot handles\n\nList all handles in storage."
41
42
  }.freeze
42
43
 
43
44
  desc "config", "Open the config file using $EDITOR"
@@ -50,6 +51,20 @@ module Filedepot
50
51
 
51
52
  desc "push HANDLE FILE", "Send a file to the current storage with a specific handle"
52
53
  def push(handle, file_path)
54
+ if handle.to_s.strip.empty?
55
+ puts "Error: Handle is required."
56
+ return
57
+ end
58
+ if file_path.to_s.strip.empty?
59
+ puts "Error: File path is required."
60
+ return
61
+ end
62
+ path = File.expand_path(file_path)
63
+ unless File.file?(path)
64
+ puts "Error: File not found: #{path}"
65
+ return
66
+ end
67
+
53
68
  source = Config.current_source
54
69
  if source.nil?
55
70
  puts "Error: No storage source configured. Run 'filedepot config' to set up."
@@ -57,11 +72,13 @@ module Filedepot
57
72
  end
58
73
 
59
74
  storage = Storage::Base.for(source)
60
- storage.push(handle, file_path)
75
+ storage.push(handle, path)
61
76
  version = storage.current_version(handle)
62
77
  puts "Pushed #{file_path} as #{handle} (version #{version})"
63
- uploaded_url = storage.url(handle, version, File.basename(file_path))
78
+ uploaded_url = storage.url(handle, version, File.basename(path))
64
79
  puts uploaded_url if uploaded_url
80
+ rescue RuntimeError => e
81
+ puts "Error: #{e.message}"
65
82
  end
66
83
 
67
84
  desc "pull HANDLE", "Get file from storage"
@@ -100,6 +117,8 @@ module Filedepot
100
117
 
101
118
  storage.pull(handle, version, target_path)
102
119
  puts "pulled to #{target_path}"
120
+ rescue RuntimeError => e
121
+ puts "Error: #{e.message}"
103
122
  end
104
123
 
105
124
  desc "versions HANDLE", "List all versions of a handle (each version has an integer from 1 to n)"
@@ -118,7 +137,7 @@ module Filedepot
118
137
  storage = Storage::Base.for(source)
119
138
  versions_list = storage.versions(handle)
120
139
  if versions_list.empty?
121
- puts "No versions found for handle: #{handle}"
140
+ puts "Error: Handle '#{handle}' not found."
122
141
  else
123
142
  max_display = 10
124
143
  to_show = versions_list.first(max_display)
@@ -144,6 +163,12 @@ module Filedepot
144
163
  end
145
164
 
146
165
  storage = Storage::Base.for(source)
166
+ versions_list = storage.versions(handle)
167
+ if versions_list.empty?
168
+ puts "Error: Handle '#{handle}' not found."
169
+ return
170
+ end
171
+
147
172
  data = storage.info(handle)
148
173
 
149
174
  puts "handle: #{data[:handle]}"
@@ -153,14 +178,69 @@ module Filedepot
153
178
  puts "latest version url: #{data[:latest_version_url]}" if data[:latest_version_url]
154
179
  end
155
180
 
181
+ desc "handles", "List all handles in storage"
182
+ def handles
183
+ source = Config.current_source
184
+ if source.nil?
185
+ puts "Error: No storage source configured. Run 'filedepot config' to set up."
186
+ return
187
+ end
188
+
189
+ storage = Storage::Base.for(source)
190
+ handles = storage.ls
191
+ if handles.empty?
192
+ puts "No handles found."
193
+ else
194
+ handles.each { |h| puts h }
195
+ end
196
+ end
197
+
156
198
  desc "delete HANDLE [VERSION]", "After confirmation, delete all versions of a file; or only a specific version if specified"
157
199
  def delete(handle = nil, version = nil)
158
200
  if handle.nil?
159
201
  puts COMMAND_HELP[:delete]
160
202
  return
161
203
  end
204
+
205
+ source = Config.current_source
206
+ if source.nil?
207
+ puts "Error: No storage source configured. Run 'filedepot config' to set up."
208
+ return
209
+ end
210
+
211
+ storage = Storage::Base.for(source)
212
+ versions_list = storage.versions(handle)
213
+ if versions_list.empty?
214
+ puts "Error: Handle '#{handle}' not found."
215
+ return
216
+ end
217
+ if version
218
+ version_nums = versions_list.map(&:first)
219
+ unless version_nums.include?(version.to_i)
220
+ puts "Error: Version #{version} not found for handle '#{handle}'."
221
+ return
222
+ end
223
+ end
224
+
162
225
  version_str = version ? " version #{version}" : " all versions"
163
- puts "delete: would delete file '#{handle}'#{version_str} after confirmation (not implemented)"
226
+ puts "This will delete '#{handle}'#{version_str}."
227
+ begin
228
+ print "Type the handle name to confirm: "
229
+ input = $stdin.gets&.strip
230
+ rescue Interrupt
231
+ puts
232
+ return
233
+ end
234
+
235
+ unless input == handle
236
+ puts "Aborted (handle name did not match)."
237
+ return
238
+ end
239
+
240
+ storage.delete(handle, version)
241
+ puts "Deleted handle#{handle}#{version ? " version #{version}" : ""}."
242
+ rescue RuntimeError => e
243
+ puts "Error: #{e.message}"
164
244
  end
165
245
 
166
246
  default_task :default
@@ -181,10 +261,11 @@ module Filedepot
181
261
  puts ""
182
262
  puts "Available commands:"
183
263
  puts " filedepot config Open config file using $EDITOR"
264
+ puts " filedepot info HANDLE Show info for a handle"
265
+ puts " filedepot handles List all handles in storage"
266
+ puts " filedepot versions HANDLE List all versions of a handle"
184
267
  puts " filedepot push HANDLE FILE Send file to current storage"
185
268
  puts " filedepot pull HANDLE [--path PATH] [--version N] Get file from storage"
186
- puts " filedepot versions HANDLE List all versions of a handle"
187
- puts " filedepot info HANDLE Show info for a handle"
188
269
  puts " filedepot delete HANDLE [VER] Delete file(s) after confirmation"
189
270
  puts ""
190
271
  puts "Use 'filedepot help COMMAND' for more information on a command."
@@ -5,7 +5,7 @@ module Filedepot
5
5
  class Base
6
6
  def self.for(source)
7
7
  if source["ssh"]
8
- SshStorage.new(source)
8
+ Ssh.new(source)
9
9
  else
10
10
  raise ArgumentError, "Unknown storage type for source: #{source["name"]}"
11
11
  end
@@ -74,10 +74,11 @@ module Filedepot
74
74
  end
75
75
 
76
76
  def url(handle, version, filename)
77
- base = @source["public_base_path"].to_s.sub(%r{/$}, "")
77
+ base = @source["public_base_path"].to_s.sub(%r{/+$}, "")
78
78
  return nil if base.empty? || filename.nil? || filename.empty?
79
79
 
80
- [base, handle, version, filename].join("/").gsub(%r{/+}, "/")
80
+ path = [handle, version, filename].join("/")
81
+ "#{base}/#{path}"
81
82
  end
82
83
 
83
84
  protected
@@ -6,7 +6,7 @@ require "net/scp"
6
6
 
7
7
  module Filedepot
8
8
  module Storage
9
- class SshStorage < Base
9
+ class Ssh < Base
10
10
  def test
11
11
  ssh_session do |ssh|
12
12
  result = ssh.exec!("echo ok")
@@ -27,7 +27,7 @@ module Filedepot
27
27
 
28
28
  def push(handle, local_path)
29
29
  path = File.expand_path(local_path)
30
- raise "File not found: #{local_path}" unless File.file?(path)
30
+ raise "File not found: #{path}" unless File.file?(path)
31
31
 
32
32
  push_path = next_version_path(handle)
33
33
 
@@ -57,14 +57,14 @@ module Filedepot
57
57
  def pull(handle, version = nil, local_path = nil)
58
58
  ssh_session do |ssh|
59
59
  versions_list = versions_for(ssh, handle)
60
- raise "No versions found for handle: #{handle}" if versions_list.empty?
60
+ raise "Handle '#{handle}' not found" if versions_list.empty?
61
61
 
62
62
  version_num = version ? version.to_i : versions_list.max
63
- raise "Version #{version} not found" unless versions_list.include?(version_num)
63
+ raise "Version #{version} not found for handle '#{handle}'" unless versions_list.include?(version_num)
64
64
 
65
65
  version_dir = File.join(remote_handle_path(handle), version_num.to_s)
66
66
  remote_file = first_file_in_dir(ssh, version_dir)
67
- raise "No file found in version #{version_num}" if remote_file.nil?
67
+ raise "No file found in version #{version_num} for handle '#{handle}'" if remote_file.nil?
68
68
 
69
69
  remote_filename = File.basename(remote_file)
70
70
  target_path = resolve_local_path(local_path, remote_filename)
@@ -77,14 +77,14 @@ module Filedepot
77
77
  def pull_info(handle, version = nil, local_path = nil)
78
78
  ssh_session do |ssh|
79
79
  versions_list = versions_for(ssh, handle)
80
- raise "No versions found for handle: #{handle}" if versions_list.empty?
80
+ raise "Handle '#{handle}' not found" if versions_list.empty?
81
81
 
82
82
  version_num = version ? version.to_i : versions_list.max
83
- raise "Version #{version} not found" unless versions_list.include?(version_num)
83
+ raise "Version #{version} not found for handle '#{handle}'" unless versions_list.include?(version_num)
84
84
 
85
85
  version_dir = File.join(remote_handle_path(handle), version_num.to_s)
86
86
  remote_file = first_file_in_dir(ssh, version_dir)
87
- raise "No file found in version #{version_num}" if remote_file.nil?
87
+ raise "No file found in version #{version_num} for handle '#{handle}'" if remote_file.nil?
88
88
 
89
89
  remote_filename = File.basename(remote_file)
90
90
  target_path = resolve_local_path(local_path, remote_filename)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Filedepot
4
- VERSION = "0.2.1"
4
+ VERSION = "0.2.3"
5
5
  end
data/lib/filedepot.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  require "filedepot/version"
4
4
  require "filedepot/config"
5
5
  require "filedepot/storage/base"
6
- require "filedepot/storage_ssh"
6
+ require "filedepot/storage/ssh"
7
7
  require "filedepot/cli"
8
8
 
9
9
  module Filedepot
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: filedepot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Filedepot
@@ -93,7 +93,7 @@ files:
93
93
  - lib/filedepot/cli.rb
94
94
  - lib/filedepot/config.rb
95
95
  - lib/filedepot/storage/base.rb
96
- - lib/filedepot/storage_ssh.rb
96
+ - lib/filedepot/storage/ssh.rb
97
97
  - lib/filedepot/version.rb
98
98
  homepage: https://github.com/filedepot/filedepot
99
99
  licenses: