e621_export_downloader 0.0.18 → 0.0.19

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: 7259f8077bf1df8805620f4efa3fbeac43c29616e496bea576518275794c5fef
4
- data.tar.gz: 4b23216298e535aeed4ceaeb7f38f581bf6fc6fb68c1f7fa94975e9157f7bf71
3
+ metadata.gz: c5d969922b067f0eb6f92d7f73497105d17a2d228b86a34931f24eaed48c2312
4
+ data.tar.gz: f85056aa89a468b019ae03585b53470d0b1c1d8d31c335f1c47e000e7727c743
5
5
  SHA512:
6
- metadata.gz: 50436457d2de9e91e8f938631484653a71d8102122ec58f77c8c6287454092c38ef6719215a4aa20cb676978d659ce936750338667d892045027b4ee0a0fa0ed
7
- data.tar.gz: b8a0c19646cd5b7ed2076b023adabc016962700dcc4c755ef2b66d3f3b018349be45aafca1c4be1dc8c0be9c8f2dd6de5f1529f6ea27f45a04df5660d6f6f1a9
6
+ metadata.gz: df8d73bb8eaea951cb41e26c0384647f5219ec71518962986d88a014ded3592454e8ea64bf07c2f4acf44a23b42de0e47b1bbda8134dd42631481ccafb6a3615
7
+ data.tar.gz: c7fce51d4283904e52f3defd64fa1de02a4a624a52983cd571123a9124349f4b71edb934d40f7f68d34dd4bbb28c580b28bc423fd221413082771c0d91ec12e5
@@ -49,9 +49,11 @@ module E621
49
49
  model.connection.execute("TRUNCATE #{model.quoted_table_name}") if truncate
50
50
  indexes.each_key { |name| model.connection.execute("DROP INDEX IF EXISTS #{name}") }
51
51
 
52
- count = copy_csv(csv_path, chunk_bytes: chunk_bytes)
53
-
54
- indexes.each_value { |ddl| model.connection.execute(ddl) }
52
+ count = begin
53
+ copy_csv(csv_path, chunk_bytes: chunk_bytes)
54
+ ensure
55
+ indexes.each_value { |ddl| model.connection.execute(ddl) }
56
+ end
55
57
  self.row_count = count
56
58
  count
57
59
  end
@@ -55,7 +55,7 @@ module E621ExportDownloader
55
55
  client.debug("downloading export", header: ["export:#{type.serialize}"])
56
56
 
57
57
  FileUtils.mkdir_p(Constants::TEMP_DIR)
58
- digest = T.let(client.options.validate_checksum ? Digest::MD5.new : nil, T.nilable(Digest::MD5))
58
+ digest = T.let(client.options.validate_checksum ? Digest::SHA256.new : nil, T.nilable(Digest::SHA256))
59
59
  File.open(file_path, "wb") do |file|
60
60
  inflater = Zlib::Inflate.new(Zlib::MAX_WBITS + 16)
61
61
 
@@ -4,7 +4,7 @@
4
4
  # loaded by bundler
5
5
  module E621ExportDownloader
6
6
  module Constants
7
- VERSION = "0.0.18"
7
+ VERSION = "0.0.19"
8
8
  WEBSITE = "https://github.com/DonovanDMC/E621ExportDownloader.rb"
9
9
  end
10
10
  end
@@ -0,0 +1,116 @@
1
+ # frozen_string_literal: true
2
+
3
+ require("minitest/autorun")
4
+ require("tempfile")
5
+ require("active_record")
6
+ require("e621_export_downloader")
7
+ require("e621/csv_importable")
8
+ require("e621/row_count")
9
+
10
+ class CsvImportablePostgresTestModel < ActiveRecord::Base
11
+ extend(E621::CsvImportable)
12
+
13
+ self.table_name = "import_index_test_tags"
14
+ self.record_timestamps = false
15
+ end
16
+
17
+ class CsvImportablePostgresTest < Minitest::Test
18
+ INDEX_NAME = "index_import_index_test_tags_on_name"
19
+
20
+ def setup
21
+ skip("set E621_TEST_DATABASE_URL to run PostgreSQL import tests") unless ENV["E621_TEST_DATABASE_URL"]
22
+
23
+ ActiveRecord::Base.establish_connection(ENV.fetch("E621_TEST_DATABASE_URL"))
24
+ @tempfiles = []
25
+ setup_schema
26
+ end
27
+
28
+ def teardown
29
+ return unless ENV["E621_TEST_DATABASE_URL"]
30
+
31
+ connection.execute("DROP TABLE IF EXISTS import_index_test_tags")
32
+ connection.execute("DROP TABLE IF EXISTS e621.row_counts")
33
+ @tempfiles&.each(&:unlink)
34
+ end
35
+
36
+ def test_recreate_indexes_restores_postgres_indexes_after_successful_import
37
+ count = CsvImportablePostgresTestModel.import_from_csv(csv_file(successful_csv), truncate: true, recreate_indexes: true, chunk_bytes: 8)
38
+
39
+ assert_equal(2, count)
40
+ assert_equal(2, CsvImportablePostgresTestModel.count)
41
+ assert_index_exists
42
+ end
43
+
44
+ def test_recreate_indexes_restores_postgres_indexes_after_import_error
45
+ error = assert_raises(StandardError) do
46
+ CsvImportablePostgresTestModel.import_from_csv(csv_file(invalid_csv), truncate: true, recreate_indexes: true, chunk_bytes: 8)
47
+ end
48
+
49
+ assert_match(/COPY|missing data|extra data|invalid input/i, error.message)
50
+ assert_index_exists
51
+ end
52
+
53
+ private
54
+
55
+ def setup_schema
56
+ connection.execute("CREATE SCHEMA IF NOT EXISTS e621")
57
+ connection.execute(<<~SQL)
58
+ CREATE TABLE IF NOT EXISTS e621.row_counts (
59
+ table_name varchar PRIMARY KEY,
60
+ count bigint NOT NULL DEFAULT 0
61
+ )
62
+ SQL
63
+ connection.execute("DROP TABLE IF EXISTS import_index_test_tags")
64
+ connection.execute(<<~SQL)
65
+ CREATE TABLE import_index_test_tags (
66
+ id bigint PRIMARY KEY,
67
+ name text NOT NULL,
68
+ post_count integer NOT NULL
69
+ )
70
+ SQL
71
+ connection.execute("CREATE INDEX #{INDEX_NAME} ON import_index_test_tags (name)")
72
+ end
73
+
74
+ def successful_csv
75
+ <<~CSV
76
+ id,name,post_count
77
+ 1,alpha,10
78
+ 2,beta,20
79
+ CSV
80
+ end
81
+
82
+ def invalid_csv
83
+ <<~CSV
84
+ id,name,post_count
85
+ 1,alpha
86
+ CSV
87
+ end
88
+
89
+ def csv_file(content)
90
+ file = Tempfile.new(["e621-import", ".csv"])
91
+ file.write(content)
92
+ file.close
93
+ @tempfiles << file
94
+ file.path
95
+ end
96
+
97
+ def assert_index_exists
98
+ assert(index_exists?, "expected PostgreSQL index #{INDEX_NAME} to exist")
99
+ end
100
+
101
+ def index_exists?
102
+ connection.select_value(<<~SQL)
103
+ SELECT EXISTS (
104
+ SELECT 1
105
+ FROM pg_class c
106
+ JOIN pg_namespace n ON n.oid = c.relnamespace
107
+ WHERE c.relkind = 'i'
108
+ AND c.relname = #{connection.quote(INDEX_NAME)}
109
+ )
110
+ SQL
111
+ end
112
+
113
+ def connection
114
+ ActiveRecord::Base.connection
115
+ end
116
+ end
data/test/export_test.rb CHANGED
@@ -39,7 +39,7 @@ class ExportChecksumTest < Minitest::Test
39
39
  def setup
40
40
  @csv_content = "id,name\n1,foo\n"
41
41
  @compressed = Zlib.gzip(@csv_content)
42
- @checksum = Digest::MD5.hexdigest(@compressed)
42
+ @checksum = Digest::SHA256.hexdigest(@compressed)
43
43
  # split across chunks to exercise streaming, matching how a real download arrives
44
44
  midpoint = @compressed.bytesize / 2
45
45
  @chunks = [@compressed.byteslice(0, midpoint), @compressed.byteslice(midpoint..)]
@@ -79,14 +79,14 @@ class ExportChecksumTest < Minitest::Test
79
79
  end
80
80
 
81
81
  def test_download_raises_and_removes_the_file_when_checksum_does_not_match
82
- export = build_export(checksum: "0" * 32, validate_checksum: true)
82
+ export = build_export(checksum: "0" * 64, validate_checksum: true)
83
83
  error = assert_raises(E621ExportDownloader::ResolveError) { export.download }
84
84
  assert_match(/Checksum mismatch/, error.message)
85
85
  assert_empty(Dir.children(E621ExportDownloader::Constants::TEMP_DIR))
86
86
  end
87
87
 
88
88
  def test_download_ignores_checksum_mismatch_when_validation_is_disabled
89
- export = build_export(checksum: "0" * 32, validate_checksum: false)
89
+ export = build_export(checksum: "0" * 64, validate_checksum: false)
90
90
  path = export.download
91
91
  assert(File.exist?(path))
92
92
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: e621_export_downloader
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.18
4
+ version: 0.0.19
5
5
  platform: ruby
6
6
  authors:
7
7
  - Donovan_DMC
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2026-07-05 00:00:00.000000000 Z
10
+ date: 2026-08-03 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: csv
@@ -223,6 +223,7 @@ files:
223
223
  - sorbet/rbi/todo.rbi
224
224
  - sorbet/tapioca/config.yml
225
225
  - sorbet/tapioca/require.rb
226
+ - test/csv_importable_postgres_test.rb
226
227
  - test/export_test.rb
227
228
  - test/generators/install_generator_test.rb
228
229
  homepage: https://github.com/DonovanDMC/E621ExportDownloader.rb