net-sftp 4.1.0 → 4.1.1
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
- checksums.yaml.gz.sig +0 -0
- data/CHANGES.txt +7 -0
- data/lib/net/sftp/operations/download.rb +42 -18
- data/lib/net/sftp/operations/upload.rb +59 -26
- data/lib/net/sftp/version.rb +1 -1
- data.tar.gz.sig +2 -1
- metadata +3 -15
- metadata.gz.sig +2 -4
- data/.github/pull_request_template.md +0 -1
- data/.github/workflows/changelog.yml +0 -18
- data/.github/workflows/ci.yml +0 -37
- data/.gitignore +0 -7
- data/CONTRIBUTING.md +0 -33
- data/Gemfile +0 -20
- data/Manifest +0 -55
- data/Rakefile +0 -176
- data/changelog.d/README.md +0 -1
- data/net-sftp-public_cert.pem +0 -21
- data/net-sftp.gemspec +0 -49
- data/setup.rb +0 -1331
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 618cad45c3de8f52cf2579f2616d27df2ecd69d35dce35c6b80822dab1a0f8ac
|
|
4
|
+
data.tar.gz: 7b07b32f66e9109e037582827bc2dc602b19479d93b6be3e526f263cd499062e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 47d88176bf4883648da4339a5d250e69c84921bc96a5424ff9bb5bb65d4c83b97fa2543e2a11f03d3043c6a04bf8bde5026c167ef6ccd9c1d880f7e8dcb08d10
|
|
7
|
+
data.tar.gz: c7568857412af07782a37dbc7516fb59af76e47bff76e9229a9fa2429076fca96ca06d92b6f9706de20c700917ecb887ea8e793d23d03c969fa698ad79c37280
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/CHANGES.txt
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
=== 4.1.1
|
|
2
|
+
|
|
3
|
+
* A read error during a single-file download is raised once, after the outstanding reads complete and the handle is closed, instead of once per in-flight read [#212]
|
|
4
|
+
* `abort!` now stops uploads and downloads: no new write or read is sent, the requests in flight finish and the open files are closed, so `wait` returns once their replies arrive. Previously the transfer kept running to the end, and an upload reported `:finish` twice. [#211]
|
|
5
|
+
* Single-file uploads keep up to `:requests` writes in flight (default 64, like OpenSSH's sftp client, previously 2) so large uploads are no longer bound by round-trip time. The file is closed once every write is acknowledged, and a failed write is raised once, after the close. [#210]
|
|
6
|
+
* Package only `lib`, `CHANGES.txt`, `LICENSE.txt` and `README.rdoc` in the gem, about 20% smaller. Thanks @yuri-zubov [#199]
|
|
7
|
+
|
|
1
8
|
=== 4.1.0
|
|
2
9
|
|
|
3
10
|
* BREAKING: Require Ruby 2.6 or later. Bundler on older Rubies resolves to 4.0.2. [#207]
|
|
@@ -169,6 +169,7 @@ module Net; module SFTP; module Operations
|
|
|
169
169
|
@progress = progress || options[:progress]
|
|
170
170
|
@options = options
|
|
171
171
|
@active = 0
|
|
172
|
+
@aborted = false
|
|
172
173
|
@directories = []
|
|
173
174
|
@properties = options[:properties] || {}
|
|
174
175
|
requests
|
|
@@ -196,9 +197,10 @@ module Net; module SFTP; module Operations
|
|
|
196
197
|
@active > 0 || stack.any?
|
|
197
198
|
end
|
|
198
199
|
|
|
199
|
-
# Forces the transfer to stop.
|
|
200
|
+
# Forces the transfer to stop. Reads already sent are left to finish,
|
|
201
|
+
# then each open file is closed, so #wait returns once that is done.
|
|
200
202
|
def abort!
|
|
201
|
-
@
|
|
203
|
+
@aborted = true
|
|
202
204
|
@stack.clear
|
|
203
205
|
end
|
|
204
206
|
|
|
@@ -226,7 +228,7 @@ module Net; module SFTP; module Operations
|
|
|
226
228
|
# A simple struct for encapsulating information about a single remote
|
|
227
229
|
# file or directory that needs to be downloaded.
|
|
228
230
|
Entry = Struct.new(:remote, :local, :directory, :size, :handle, :offset, :sink,
|
|
229
|
-
:next_read, :pending, :window, :chunks, :eof, :attributes)
|
|
231
|
+
:next_read, :pending, :window, :chunks, :eof, :attributes, :error)
|
|
230
232
|
|
|
231
233
|
#--
|
|
232
234
|
# "ruby -w" hates private attributes, so we have to do these longhand
|
|
@@ -368,7 +370,7 @@ module Net; module SFTP; module Operations
|
|
|
368
370
|
# and #process_next_entry is called.
|
|
369
371
|
def on_readdir(response)
|
|
370
372
|
entry = response.request[:parent]
|
|
371
|
-
if response.eof?
|
|
373
|
+
if response.eof? || @aborted
|
|
372
374
|
request = sftp.close(entry.handle, &method(:on_closedir))
|
|
373
375
|
request[:parent] = entry
|
|
374
376
|
elsif !response.ok?
|
|
@@ -444,7 +446,7 @@ module Net; module SFTP; module Operations
|
|
|
444
446
|
raise StatusException.new(response, "open #{entry.remote}") unless response.ok?
|
|
445
447
|
|
|
446
448
|
entry.handle = response[:handle]
|
|
447
|
-
if entry.attributes || entry.local.respond_to?(:write)
|
|
449
|
+
if @aborted || entry.attributes || entry.local.respond_to?(:write)
|
|
448
450
|
start_download(entry)
|
|
449
451
|
else
|
|
450
452
|
request = sftp.fstat(entry.handle, &method(:on_fstat))
|
|
@@ -460,6 +462,8 @@ module Net; module SFTP; module Operations
|
|
|
460
462
|
end
|
|
461
463
|
|
|
462
464
|
def start_download(entry)
|
|
465
|
+
return close_aborted_file(entry) if @aborted
|
|
466
|
+
|
|
463
467
|
entry.sink = entry.local.respond_to?(:write) ? entry.local : open_local_file(entry)
|
|
464
468
|
entry.offset = 0
|
|
465
469
|
entry.next_read = 0
|
|
@@ -474,7 +478,7 @@ module Net; module SFTP; module Operations
|
|
|
474
478
|
# the server reports EOF. The window starts at one and grows with each
|
|
475
479
|
# data reply, so small files don't cost a burst of reads past their end.
|
|
476
480
|
def request_reads(entry)
|
|
477
|
-
while !entry.eof && entry.pending < entry.window
|
|
481
|
+
while !entry.eof && !@aborted && entry.pending < entry.window
|
|
478
482
|
read_range(entry, entry.next_read, read_size)
|
|
479
483
|
entry.next_read += read_size
|
|
480
484
|
end
|
|
@@ -490,36 +494,40 @@ module Net; module SFTP; module Operations
|
|
|
490
494
|
|
|
491
495
|
# Called when a read from a file finishes. Replies can arrive out of
|
|
492
496
|
# order, so data is buffered until everything before it has been
|
|
493
|
-
# written. Once the server has reported EOF
|
|
494
|
-
# outstanding, the file is closed.
|
|
497
|
+
# written. Once the server has reported EOF or a read has failed, and
|
|
498
|
+
# no reads are left outstanding, the file is closed.
|
|
495
499
|
def on_read(response)
|
|
496
500
|
entry = response.request[:entry]
|
|
497
501
|
entry.pending -= 1
|
|
498
502
|
|
|
499
|
-
if
|
|
503
|
+
if entry.error
|
|
504
|
+
# The rest of the file is no longer wanted.
|
|
505
|
+
elsif response.eof?
|
|
500
506
|
entry.eof = true
|
|
501
507
|
elsif !response.ok?
|
|
502
|
-
|
|
508
|
+
entry.error = StatusException.new(response, "read #{entry.remote}")
|
|
509
|
+
elsif response[:data].empty? || response[:data].bytesize > response.request[:length]
|
|
510
|
+
entry.error = Net::SFTP::Exception.new("read #{entry.remote} returned #{response[:data].bytesize} bytes for a #{response.request[:length]} byte request")
|
|
503
511
|
else
|
|
504
512
|
offset = response.request[:offset]
|
|
505
513
|
length = response.request[:length]
|
|
506
514
|
data = response[:data]
|
|
507
515
|
|
|
508
|
-
if data.empty? || data.bytesize > length
|
|
509
|
-
raise Net::SFTP::Exception, "read #{entry.remote} returned #{data.bytesize} bytes for a #{length} byte request"
|
|
510
|
-
end
|
|
511
|
-
|
|
512
516
|
# Servers may return less than asked for without being at EOF, and
|
|
513
517
|
# the reads after this one have already been sent.
|
|
514
|
-
read_range(entry, offset + data.bytesize, length - data.bytesize) if data.bytesize < length
|
|
518
|
+
read_range(entry, offset + data.bytesize, length - data.bytesize) if data.bytesize < length && !@aborted
|
|
515
519
|
|
|
516
520
|
entry.chunks[offset] = data
|
|
517
521
|
write_buffered_chunks(entry)
|
|
518
522
|
entry.window += 1 if entry.window < read_window_limit
|
|
519
523
|
end
|
|
520
524
|
|
|
521
|
-
|
|
522
|
-
|
|
525
|
+
if entry.error
|
|
526
|
+
close_failed_file(entry) if entry.pending.zero?
|
|
527
|
+
else
|
|
528
|
+
request_reads(entry)
|
|
529
|
+
close_file(entry) if entry.pending.zero?
|
|
530
|
+
end
|
|
523
531
|
end
|
|
524
532
|
|
|
525
533
|
def write_buffered_chunks(entry)
|
|
@@ -531,7 +539,7 @@ module Net; module SFTP; module Operations
|
|
|
531
539
|
end
|
|
532
540
|
|
|
533
541
|
def close_file(entry)
|
|
534
|
-
if entry.chunks.any?
|
|
542
|
+
if entry.chunks.any? && !@aborted
|
|
535
543
|
raise Net::SFTP::Exception, "read #{entry.remote} hit EOF at #{entry.offset} but the server returned data beyond it"
|
|
536
544
|
end
|
|
537
545
|
|
|
@@ -549,14 +557,30 @@ module Net; module SFTP; module Operations
|
|
|
549
557
|
request[:entry] = entry
|
|
550
558
|
end
|
|
551
559
|
|
|
560
|
+
# The local file is left untouched: it may hold an earlier copy.
|
|
561
|
+
def close_aborted_file(entry)
|
|
562
|
+
update_progress(:close, entry)
|
|
563
|
+
request = sftp.close(entry.handle, &method(:on_close))
|
|
564
|
+
request[:entry] = entry
|
|
565
|
+
end
|
|
566
|
+
|
|
552
567
|
# Called when a file handle is closed.
|
|
553
568
|
def on_close(response)
|
|
554
569
|
@active -= 1
|
|
555
570
|
entry = response.request[:entry]
|
|
571
|
+
raise entry.error if entry.error
|
|
556
572
|
raise StatusException.new(response, "close #{entry.remote}") unless response.ok?
|
|
557
573
|
process_next_entry
|
|
558
574
|
end
|
|
559
575
|
|
|
576
|
+
# Waiting for every reply before raising keeps the remote handle from
|
|
577
|
+
# leaking and the error from being raised again by each later reply.
|
|
578
|
+
def close_failed_file(entry)
|
|
579
|
+
entry.sink.close unless entry.sink.equal?(local)
|
|
580
|
+
request = sftp.close(entry.handle, &method(:on_close))
|
|
581
|
+
request[:entry] = entry
|
|
582
|
+
end
|
|
583
|
+
|
|
560
584
|
# If a progress callback or object has been set, this will report
|
|
561
585
|
# the progress to that callback or object.
|
|
562
586
|
def update_progress(hook, *args)
|
|
@@ -47,8 +47,9 @@ module Net; module SFTP; module Operations
|
|
|
47
47
|
# callback. See the discussion of "progress monitoring" below.
|
|
48
48
|
# * <tt>:requests</tt> - the number of pending SFTP requests to allow at
|
|
49
49
|
# any given time. When uploading an entire directory tree recursively,
|
|
50
|
-
# this will default to 16, otherwise it will default to
|
|
51
|
-
# higher might improve throughput. Reducing it
|
|
50
|
+
# this will default to 16, otherwise it will default to 64, like OpenSSH's
|
|
51
|
+
# sftp client. Setting this higher might improve throughput. Reducing it
|
|
52
|
+
# will reduce throughput.
|
|
52
53
|
# * <tt>:read_size</tt> - the maximum number of bytes to read at a time
|
|
53
54
|
# from the source. Increasing this value might improve throughput. It
|
|
54
55
|
# defaults to 32,000 bytes. Each chunk is sent as one write request, so
|
|
@@ -163,6 +164,7 @@ module Net; module SFTP; module Operations
|
|
|
163
164
|
@options = options
|
|
164
165
|
@properties = options[:properties] || {}
|
|
165
166
|
@active = 0
|
|
167
|
+
@aborted = false
|
|
166
168
|
@directories = []
|
|
167
169
|
|
|
168
170
|
self.logger = sftp.logger
|
|
@@ -209,11 +211,11 @@ module Net; module SFTP; module Operations
|
|
|
209
211
|
@active > 0 || @stack.any?
|
|
210
212
|
end
|
|
211
213
|
|
|
212
|
-
# Forces the transfer to stop.
|
|
214
|
+
# Forces the transfer to stop. Writes already sent are left to finish,
|
|
215
|
+
# then each open file is closed, so #wait returns once that is done.
|
|
213
216
|
def abort!
|
|
214
|
-
@
|
|
217
|
+
@aborted = true
|
|
215
218
|
@stack.clear
|
|
216
|
-
@uploads.clear
|
|
217
219
|
end
|
|
218
220
|
|
|
219
221
|
# Blocks until the upload has completed.
|
|
@@ -264,13 +266,13 @@ module Net; module SFTP; module Operations
|
|
|
264
266
|
|
|
265
267
|
# A simple struct for recording metadata about the file currently being
|
|
266
268
|
# uploaded.
|
|
267
|
-
LiveFile = Struct.new(:local, :remote, :io, :size, :handle, :attributes)
|
|
269
|
+
LiveFile = Struct.new(:local, :remote, :io, :size, :handle, :attributes, :pending, :error)
|
|
268
270
|
|
|
269
271
|
# The default # of bytes to read from disk at a time.
|
|
270
272
|
DEFAULT_READ_SIZE = 32_000
|
|
271
273
|
|
|
272
274
|
# The number of readers to use when uploading a single file.
|
|
273
|
-
SINGLE_FILE_READERS =
|
|
275
|
+
SINGLE_FILE_READERS = 64
|
|
274
276
|
|
|
275
277
|
# The number of readers to use when uploading a directory.
|
|
276
278
|
RECURSIVE_READERS = 16
|
|
@@ -336,7 +338,7 @@ module Net; module SFTP; module Operations
|
|
|
336
338
|
end
|
|
337
339
|
|
|
338
340
|
attributes = local.respond_to?(:read) ? {} : attributes_for(file.stat)
|
|
339
|
-
metafile = LiveFile.new(name, remote, file, size, nil, attributes)
|
|
341
|
+
metafile = LiveFile.new(name, remote, file, size, nil, attributes, 0)
|
|
340
342
|
update_progress(:open, metafile)
|
|
341
343
|
|
|
342
344
|
request = sftp.open(remote, "w", attributes, &method(:on_open))
|
|
@@ -372,14 +374,25 @@ module Net; module SFTP; module Operations
|
|
|
372
374
|
end
|
|
373
375
|
end
|
|
374
376
|
|
|
375
|
-
# Called when a +write+ request finishes.
|
|
376
|
-
#
|
|
377
|
-
#
|
|
377
|
+
# Called when a +write+ request finishes. The first failed write stops
|
|
378
|
+
# the file from being read further and is recorded, to be raised once
|
|
379
|
+
# the file is closed. The file is closed once the whole file has been
|
|
380
|
+
# sent or a write has failed, and no writes are left outstanding.
|
|
378
381
|
def on_write(response)
|
|
379
382
|
@active -= 1
|
|
380
383
|
file = response.request[:file]
|
|
381
|
-
|
|
382
|
-
|
|
384
|
+
file.pending -= 1
|
|
385
|
+
|
|
386
|
+
if !response.ok? && !file.error
|
|
387
|
+
file.error = StatusException.new(response, "write #{file.remote}")
|
|
388
|
+
stop_reading(file)
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
if file.io.nil? && file.pending.zero?
|
|
392
|
+
close_file(file)
|
|
393
|
+
elsif !file.error
|
|
394
|
+
write_next_chunk(file)
|
|
395
|
+
end
|
|
383
396
|
end
|
|
384
397
|
|
|
385
398
|
# Called when a +close+ request finishes. Raises a StatusException if the
|
|
@@ -388,6 +401,7 @@ module Net; module SFTP; module Operations
|
|
|
388
401
|
def on_close(response)
|
|
389
402
|
@active -= 1
|
|
390
403
|
file = response.request[:file]
|
|
404
|
+
raise file.error if file.error
|
|
391
405
|
raise StatusException.new(response, "close #{file.remote}") unless response.ok?
|
|
392
406
|
process_next_entry
|
|
393
407
|
end
|
|
@@ -441,23 +455,18 @@ module Net; module SFTP; module Operations
|
|
|
441
455
|
if file.io.nil?
|
|
442
456
|
process_next_entry
|
|
443
457
|
else
|
|
444
|
-
@active += 1
|
|
445
458
|
offset = file.io.pos
|
|
446
|
-
data = file.io.read(read_size)
|
|
459
|
+
data = file.io.read(read_size) unless @aborted
|
|
447
460
|
if data.nil?
|
|
448
|
-
|
|
449
|
-
if
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
461
|
+
stop_reading(file)
|
|
462
|
+
if file.pending.zero?
|
|
463
|
+
close_file(file)
|
|
464
|
+
else
|
|
465
|
+
process_next_entry
|
|
453
466
|
end
|
|
454
|
-
request = sftp.close(file.handle, &method(:on_close))
|
|
455
|
-
request[:file] = file
|
|
456
|
-
# An IO passed in by the caller is theirs to close.
|
|
457
|
-
file.io.close unless file.io.equal?(local)
|
|
458
|
-
file.io = nil
|
|
459
|
-
@uploads.delete(file)
|
|
460
467
|
else
|
|
468
|
+
@active += 1
|
|
469
|
+
file.pending += 1
|
|
461
470
|
update_progress(:put, file, offset, data)
|
|
462
471
|
request = sftp.write(file.handle, offset, data, &method(:on_write))
|
|
463
472
|
request[:file] = file
|
|
@@ -465,6 +474,30 @@ module Net; module SFTP; module Operations
|
|
|
465
474
|
end
|
|
466
475
|
end
|
|
467
476
|
|
|
477
|
+
def stop_reading(file)
|
|
478
|
+
# An IO passed in by the caller is theirs to close.
|
|
479
|
+
file.io.close unless file.io.equal?(local)
|
|
480
|
+
file.io = nil
|
|
481
|
+
@uploads.delete(file)
|
|
482
|
+
end
|
|
483
|
+
|
|
484
|
+
# Like OpenSSH's sftp client, CLOSE waits for every write to be
|
|
485
|
+
# acknowledged, so a failed write is raised once and the remote handle
|
|
486
|
+
# is not leaked.
|
|
487
|
+
def close_file(file)
|
|
488
|
+
@active += 1
|
|
489
|
+
unless file.error
|
|
490
|
+
update_progress(:close, file)
|
|
491
|
+
if preserve? && file.attributes.any?
|
|
492
|
+
@active += 1
|
|
493
|
+
request = sftp.fsetstat(file.handle, file.attributes, &method(:on_fsetstat))
|
|
494
|
+
request[:file] = file
|
|
495
|
+
end
|
|
496
|
+
end
|
|
497
|
+
request = sftp.close(file.handle, &method(:on_close))
|
|
498
|
+
request[:file] = file
|
|
499
|
+
end
|
|
500
|
+
|
|
468
501
|
# Returns all directory entries for the given path, removing the '.'
|
|
469
502
|
# and '..' relative paths.
|
|
470
503
|
def entries_for(local)
|
data/lib/net/sftp/version.rb
CHANGED
data.tar.gz.sig
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
�_�<.}U�h�y��xx��[�v]
|
|
2
|
+
���G�3�B�E[e��g����_�L���cJ��� M������)�ׅ�����~��uY2�pI����G���8*�k,�up��~��,t�K9q��(6���W��
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: net-sftp
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.1.
|
|
4
|
+
version: 4.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jamis Buck
|
|
8
8
|
- Delano Mandelbaum
|
|
9
9
|
- Miklós Fazekas
|
|
10
10
|
autorequire:
|
|
11
|
-
bindir:
|
|
11
|
+
bindir: bin
|
|
12
12
|
cert_chain:
|
|
13
13
|
- |
|
|
14
14
|
-----BEGIN CERTIFICATE-----
|
|
@@ -32,7 +32,7 @@ cert_chain:
|
|
|
32
32
|
mMdUtmMoVbjbik3hqkY/18G03c3PoFNpL38VLKuyyROYz1DaCqOaRju3sbOoirD+
|
|
33
33
|
piQTZDCWxeKuX0Iuxq02uxkYHfoGB6In0y3OOQ==
|
|
34
34
|
-----END CERTIFICATE-----
|
|
35
|
-
date: 2026-10-
|
|
35
|
+
date: 2026-10-29 00:00:00.000000000 Z
|
|
36
36
|
dependencies:
|
|
37
37
|
- !ruby/object:Gem::Dependency
|
|
38
38
|
name: net-ssh
|
|
@@ -91,18 +91,9 @@ extra_rdoc_files:
|
|
|
91
91
|
- LICENSE.txt
|
|
92
92
|
- README.rdoc
|
|
93
93
|
files:
|
|
94
|
-
- ".github/pull_request_template.md"
|
|
95
|
-
- ".github/workflows/changelog.yml"
|
|
96
|
-
- ".github/workflows/ci.yml"
|
|
97
|
-
- ".gitignore"
|
|
98
94
|
- CHANGES.txt
|
|
99
|
-
- CONTRIBUTING.md
|
|
100
|
-
- Gemfile
|
|
101
95
|
- LICENSE.txt
|
|
102
|
-
- Manifest
|
|
103
96
|
- README.rdoc
|
|
104
|
-
- Rakefile
|
|
105
|
-
- changelog.d/README.md
|
|
106
97
|
- lib/net/sftp.rb
|
|
107
98
|
- lib/net/sftp/constants.rb
|
|
108
99
|
- lib/net/sftp/errors.rb
|
|
@@ -130,9 +121,6 @@ files:
|
|
|
130
121
|
- lib/net/sftp/response.rb
|
|
131
122
|
- lib/net/sftp/session.rb
|
|
132
123
|
- lib/net/sftp/version.rb
|
|
133
|
-
- net-sftp-public_cert.pem
|
|
134
|
-
- net-sftp.gemspec
|
|
135
|
-
- setup.rb
|
|
136
124
|
homepage: https://github.com/net-ssh/net-sftp
|
|
137
125
|
licenses:
|
|
138
126
|
- MIT
|
metadata.gz.sig
CHANGED
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
eL���~k]��2c�SZ�n�Ziن���z���p�\:�GM�85=:�,y�ؚW�R��,������Ҿ �'ȭF%ƨ<�m��.
|
|
4
|
-
��[�#�|�E�U��,�����>6?[�@�rhh��jD��3dR�(ŷ�bJ+��.E=
|
|
1
|
+
I�rWi��<��7����1��j�T+��N�2ˬ�pw����ڐ�O����a�EW�5��(�}����tzg�{������*;�[2F�9�M ��0o�'��$�,oO;���4Ru�w,�����$�]��B&�C�v��\$�Äx�
|
|
2
|
+
�M����1��SX��5��bQ�����
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<!-- After opening the PR, add a changelog.d/<PR number>.<type>.txt fragment (none, change, security, breaking or breaking-security) instead of editing CHANGES.txt; see CONTRIBUTING.md#changelog. -->
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
name: Changelog
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
pull_request:
|
|
5
|
-
types: [opened, synchronize, reopened, labeled, unlabeled]
|
|
6
|
-
|
|
7
|
-
permissions:
|
|
8
|
-
contents: read
|
|
9
|
-
|
|
10
|
-
jobs:
|
|
11
|
-
changelog:
|
|
12
|
-
runs-on: ubuntu-latest
|
|
13
|
-
steps:
|
|
14
|
-
- uses: actions/checkout@v4
|
|
15
|
-
with:
|
|
16
|
-
# HEAD is the PR merged into the base branch; HEAD^1 is the base it was merged into.
|
|
17
|
-
fetch-depth: 2
|
|
18
|
-
- uses: net-ssh/changelogd@v1
|
data/.github/workflows/ci.yml
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
name: CI
|
|
2
|
-
on:
|
|
3
|
-
pull_request:
|
|
4
|
-
push: { branches: master }
|
|
5
|
-
permissions:
|
|
6
|
-
contents: read
|
|
7
|
-
jobs:
|
|
8
|
-
test:
|
|
9
|
-
# setup-ruby has no builds of Ruby 3.1 and older for ubuntu-latest (26.04).
|
|
10
|
-
runs-on: ubuntu-24.04
|
|
11
|
-
strategy:
|
|
12
|
-
fail-fast: false
|
|
13
|
-
matrix:
|
|
14
|
-
ruby-version: ['2.6', '2.7', '3.0', '3.1', '3.2', '3.3', '3.4', '4.0', 'ruby-head', 'jruby', 'truffleruby']
|
|
15
|
-
continue-on-error: ${{ contains(fromJSON('["ruby-head", "jruby", "truffleruby"]'), matrix.ruby-version) }}
|
|
16
|
-
steps:
|
|
17
|
-
- uses: actions/checkout@v4
|
|
18
|
-
- name: Set up Ruby ${{ matrix.ruby-version }}
|
|
19
|
-
uses: ruby/setup-ruby@v1
|
|
20
|
-
with:
|
|
21
|
-
ruby-version: ${{ matrix.ruby-version }}
|
|
22
|
-
bundler-cache: true
|
|
23
|
-
- name: Run Tests
|
|
24
|
-
run: bundle exec rake test
|
|
25
|
-
frozen-string-literal:
|
|
26
|
-
runs-on: ubuntu-latest
|
|
27
|
-
steps:
|
|
28
|
-
- uses: actions/checkout@v4
|
|
29
|
-
- name: Set up Ruby
|
|
30
|
-
uses: ruby/setup-ruby@v1
|
|
31
|
-
with:
|
|
32
|
-
ruby-version: '4.0'
|
|
33
|
-
bundler-cache: true
|
|
34
|
-
- name: Run Tests with frozen string literals
|
|
35
|
-
run: bundle exec rake test
|
|
36
|
-
env:
|
|
37
|
-
RUBYOPT: --enable-frozen-string-literal
|
data/.gitignore
DELETED
data/CONTRIBUTING.md
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# Contributing to net-sftp
|
|
2
|
-
|
|
3
|
-
Run the tests with `bundle exec rake test`.
|
|
4
|
-
|
|
5
|
-
## Changelog
|
|
6
|
-
|
|
7
|
-
Don't edit `CHANGES.txt`. Instead, add a fragment file to `changelog.d/` in your PR; the release's version bump (`rake vbump:*`) moves all fragments into a new `=== <version>` section at the top of `CHANGES.txt` and deletes them.
|
|
8
|
-
|
|
9
|
-
A fragment is named `<number>.<type>.txt`, where `<number>` is the PR number (so open the PR first, then add the fragment), and contains a single UTF-8 paragraph: the entry as it should read in `CHANGES.txt`, without the bullet or prefix. Lines are joined, so it can be wrapped. If it doesn't end with a reference list such as `[#106, #107]` or `[GHSA-xxxx-xxxx-xxxx]`, ` [#<number>]` is appended.
|
|
10
|
-
|
|
11
|
-
| Type | Written as | Use for |
|
|
12
|
-
| ------------------- | ------------------------------ | ------------------------------------------------------------ |
|
|
13
|
-
| `breaking-security` | `* BREAKING: Security: <text>` | an incompatible change made for security |
|
|
14
|
-
| `breaking` | `* BREAKING: <text>` | an incompatible change |
|
|
15
|
-
| `security` | `* Security: <text>` | a security fix or hardening |
|
|
16
|
-
| `change` | `* <text>` | any other user-visible fix or feature |
|
|
17
|
-
| `none` | nothing | PRs with no user-visible change (tests, CI, docs, refactors) |
|
|
18
|
-
|
|
19
|
-
Examples:
|
|
20
|
-
|
|
21
|
-
```sh
|
|
22
|
-
rake "changelog:new[184,change,Fixed downloading files with multibyte names]"
|
|
23
|
-
# changelog.d/184.change.txt -> * Fixed downloading files with multibyte names [#184]
|
|
24
|
-
|
|
25
|
-
echo 'Refuse symlinks that point outside the download directory [GHSA-xxxx-xxxx-xxxx]' > changelog.d/185.security.txt
|
|
26
|
-
touch changelog.d/186.none.txt
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
For several entries from one PR add a suffix: `184.change.txt`, `184.change.2.txt` (`changelog:new` picks the next free one).
|
|
30
|
-
|
|
31
|
-
`rake changelog:check` validates the fragments and `rake changelog:preview` prints the section the next release would add. CI fails a PR that edits `CHANGES.txt` or doesn't add or modify a `changelog.d/<PR number>.<type>.txt` fragment, unless it only touches `changelog.d/` or a maintainer adds the `skip-changelog` label; Dependabot PRs are skipped.
|
|
32
|
-
|
|
33
|
-
The full rules, including how a release orders the entries, are in the [changelogd README](https://github.com/net-ssh/changelogd#readme).
|
data/Gemfile
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
source 'https://rubygems.org'
|
|
2
|
-
|
|
3
|
-
# Specify your gem's dependencies in mygem.gemspec
|
|
4
|
-
gemspec
|
|
5
|
-
|
|
6
|
-
# TODO: add to gemspec
|
|
7
|
-
gem "bundler", ">= 1.11"
|
|
8
|
-
gem "rake", ">= 12.0"
|
|
9
|
-
gem "rdoc"
|
|
10
|
-
gem "logger" # no longer a default gem in Ruby 4.0+
|
|
11
|
-
|
|
12
|
-
# git: rather than github:, which Bundler 1.x (the default on Ruby 2.6) expands to an unsupported git:// URL.
|
|
13
|
-
gem "changelogd", git: "https://github.com/net-ssh/changelogd.git", tag: "v1", group: :development
|
|
14
|
-
|
|
15
|
-
gem 'byebug', group: %i[development test] if !Gem.win_platform? && RUBY_ENGINE == "ruby"
|
|
16
|
-
|
|
17
|
-
if ENV["CI"]
|
|
18
|
-
gem 'codecov', require: false, group: :test
|
|
19
|
-
gem 'simplecov', require: false, group: :test
|
|
20
|
-
end
|
data/Manifest
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
CHANGELOG.rdoc
|
|
2
|
-
lib/net/sftp/constants.rb
|
|
3
|
-
lib/net/sftp/errors.rb
|
|
4
|
-
lib/net/sftp/operations/dir.rb
|
|
5
|
-
lib/net/sftp/operations/download.rb
|
|
6
|
-
lib/net/sftp/operations/file.rb
|
|
7
|
-
lib/net/sftp/operations/file_factory.rb
|
|
8
|
-
lib/net/sftp/operations/upload.rb
|
|
9
|
-
lib/net/sftp/packet.rb
|
|
10
|
-
lib/net/sftp/protocol/01/attributes.rb
|
|
11
|
-
lib/net/sftp/protocol/01/base.rb
|
|
12
|
-
lib/net/sftp/protocol/01/name.rb
|
|
13
|
-
lib/net/sftp/protocol/02/base.rb
|
|
14
|
-
lib/net/sftp/protocol/03/base.rb
|
|
15
|
-
lib/net/sftp/protocol/04/attributes.rb
|
|
16
|
-
lib/net/sftp/protocol/04/base.rb
|
|
17
|
-
lib/net/sftp/protocol/04/name.rb
|
|
18
|
-
lib/net/sftp/protocol/05/base.rb
|
|
19
|
-
lib/net/sftp/protocol/06/attributes.rb
|
|
20
|
-
lib/net/sftp/protocol/06/base.rb
|
|
21
|
-
lib/net/sftp/protocol/base.rb
|
|
22
|
-
lib/net/sftp/protocol.rb
|
|
23
|
-
lib/net/sftp/request.rb
|
|
24
|
-
lib/net/sftp/response.rb
|
|
25
|
-
lib/net/sftp/session.rb
|
|
26
|
-
lib/net/sftp/version.rb
|
|
27
|
-
lib/net/sftp.rb
|
|
28
|
-
Rakefile
|
|
29
|
-
README.rdoc
|
|
30
|
-
setup.rb
|
|
31
|
-
test/common.rb
|
|
32
|
-
test/protocol/01/test_attributes.rb
|
|
33
|
-
test/protocol/01/test_base.rb
|
|
34
|
-
test/protocol/01/test_name.rb
|
|
35
|
-
test/protocol/02/test_base.rb
|
|
36
|
-
test/protocol/03/test_base.rb
|
|
37
|
-
test/protocol/04/test_attributes.rb
|
|
38
|
-
test/protocol/04/test_base.rb
|
|
39
|
-
test/protocol/04/test_name.rb
|
|
40
|
-
test/protocol/05/test_base.rb
|
|
41
|
-
test/protocol/06/test_attributes.rb
|
|
42
|
-
test/protocol/06/test_base.rb
|
|
43
|
-
test/protocol/test_base.rb
|
|
44
|
-
test/test_all.rb
|
|
45
|
-
test/test_dir.rb
|
|
46
|
-
test/test_download.rb
|
|
47
|
-
test/test_file.rb
|
|
48
|
-
test/test_file_factory.rb
|
|
49
|
-
test/test_packet.rb
|
|
50
|
-
test/test_protocol.rb
|
|
51
|
-
test/test_request.rb
|
|
52
|
-
test/test_response.rb
|
|
53
|
-
test/test_session.rb
|
|
54
|
-
test/test_upload.rb
|
|
55
|
-
Manifest
|