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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4d3d330529ea03b189dc54e18be90d35bb2bfb79374917e9e22a2fcd3d7d79ca
4
- data.tar.gz: feaf13c15e37ea24c5ed45f52a842b0a8d4413cc2a27f1ee6de5a03a0975d527
3
+ metadata.gz: 618cad45c3de8f52cf2579f2616d27df2ecd69d35dce35c6b80822dab1a0f8ac
4
+ data.tar.gz: 7b07b32f66e9109e037582827bc2dc602b19479d93b6be3e526f263cd499062e
5
5
  SHA512:
6
- metadata.gz: 3da2ef173bd6e6ac212cf3ae73243a887ae0d136fc01f03a06b383f00a6ea19a55d2f461f5fadff10d6991dd295c6fb9c826edf6557f1d2a831fe32f2782dfdf
7
- data.tar.gz: e12c6bdf4efc55e51fbf6dbe3ddb12494b8f3b090e9786bdf6deb002a6966505e9a6a63440fdb43fb23da9c20fce7b0c40d2b2e5425dd095a97dfe1648102dfb
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
- @active = 0
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 and no reads are left
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 response.eof?
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
- raise StatusException.new(response, "read #{entry.remote}")
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
- request_reads(entry)
522
- close_file(entry) if entry.pending.zero?
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 2. Setting this
51
- # higher might improve throughput. Reducing it will reduce throughput.
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
- @active = 0
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 = 2
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. Raises StatusException if the
376
- # write failed, otherwise it calls #write_next_chunk to continue the
377
- # write.
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
- raise StatusException.new(response, "write #{file.remote}") unless response.ok?
382
- write_next_chunk(file)
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
- update_progress(:close, file)
449
- if preserve? && file.attributes.any?
450
- @active += 1
451
- request = sftp.fsetstat(file.handle, file.attributes, &method(:on_fsetstat))
452
- request[:file] = file
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)
@@ -52,7 +52,7 @@ module Net
52
52
  MINOR = 1
53
53
 
54
54
  # The tiny component of this version of the Net::SFTP library
55
- TINY = 0
55
+ TINY = 1
56
56
 
57
57
  # The prerelease component of this version of the Net::SFTP library
58
58
  # nil allowed
data.tar.gz.sig CHANGED
@@ -1 +1,2 @@
1
- l{������G���>~��g�� ���w} �Z
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.0
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: exe
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-27 00:00:00.000000000 Z
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
- �|��6G��c����k��@f�w���IR���]*�O��ks���`��G�c�v�
2
- ��* |;��g/�V��T{���>�.��I��_��� ѭt5E3��#
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
@@ -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
@@ -1,7 +0,0 @@
1
- pkg
2
- doc
3
- coverage
4
- ri
5
- *.swp
6
- Gemfile.lock
7
- lib/net/sftp/version.rb.old
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