Run rubocop

This commit is contained in:
Netscape Navigator 2020-04-25 10:11:25 -05:00
parent 2d7c1b2f26
commit e0d0739af6
21 changed files with 129 additions and 78 deletions

View File

@ -1,5 +1,3 @@
# frozen_string_literal: true
source "https://rubygems.org"
gem "ed25519"

View File

@ -41,4 +41,4 @@ DEPENDENCIES
thor
BUNDLED WITH
2.0.2
2.1.4

View File

@ -91,7 +91,8 @@ TODO
- [X] Check block list before ingesting bundles.
- [X] Need a way of importing / exporting a feeds blobs. (see "Bundle Brainstorming" below)
- [X] Need a way of adding peers messages / gossip to bundles. (see "Bundle Brainstorming" below)
- [ ] Rename `who_am_i` as `get_who_am_i` to follow VERB + NOUN convention.
- [X] Rename `who_am_i` as `get_who_am_i` to follow VERB + NOUN convention.
- [ ] Find that non-deterministic runaway loop in the test suite.
- [ ] Update README.md / tutorial.rb (user manual for `Pigeon::Database`).
- [ ] Update spec document CLI usage examples to reflect API changes in 2020.
- [ ] Publish to RubyGems

View File

@ -1,5 +1,4 @@
#!/usr/bin/env ruby
require_relative "../lib/pigeon"
require "thor"
@ -7,13 +6,13 @@ def db
if File.file?(Pigeon::PIGEON_DB_PATH)
$db ||= Pigeon::Database.new
else
STDERR.puts("You must first run `pigeon-cli identity new`.")
warn("You must first run `pigeon-cli identity new`.")
exit 1
end
end
def bail(msg)
$stderr.puts msg
warn msg
exit 1
end
@ -55,7 +54,7 @@ module Pigeon
desc "set", "Copy arbitrary binary data into the database"
def set(data = "")
blob = (data != "") ? data : STDIN.read
blob = data != "" ? data : STDIN.read
puts db.add_blob(blob)
end
@ -102,7 +101,7 @@ module Pigeon
desc "append", "Add a key/value pair to the current DRAFT"
def append(key, raw_value = "")
v = (raw_value != "") ? raw_value : STDIN.read
v = raw_value != "" ? raw_value : STDIN.read
if db.get_draft
db.update_draft(key, v)
puts db.get_draft.render_as_draft

View File

@ -8,22 +8,46 @@ module Pigeon
end
# === PEERS
def add_peer(p); store.add_peer(p); end
def block_peer(p); store.block_peer(p); end
def remove_peer(p); store.remove_peer(p); end
def peer_blocked?(p); store.peer_blocked?(p); end
def all_blocks(); store.all_blocks(); end
def all_peers(); store.all_peers(); end
def add_peer(p)
store.add_peer(p)
end
def block_peer(p)
store.block_peer(p)
end
def remove_peer(p)
store.remove_peer(p)
end
def peer_blocked?(p)
store.peer_blocked?(p)
end
def all_blocks
store.all_blocks
end
def all_peers
store.all_peers
end
# === MESSAGES
def all_messages(mhash = nil); store.all_messages(mhash); end
def message_saved?(multihash); store.message_saved?(multihash); end
def all_messages(mhash = nil)
store.all_messages(mhash)
end
def message_saved?(multihash)
store.message_saved?(multihash)
end
def _save_message(msg_obj)
store.insert_message(Helpers.verify_message(self, msg_obj))
end
def read_message(multihash); store.read_message(multihash); end
def read_message(multihash)
store.read_message(multihash)
end
def get_message_count_for(multihash)
store.get_message_count_for(multihash)
@ -57,13 +81,14 @@ module Pigeon
end
# === DRAFTS
def reset_draft; add_config(CURRENT_DRAFT, nil); end
def reset_draft
add_config(CURRENT_DRAFT, nil)
end
def new_draft(kind:, body: {})
old = get_config(CURRENT_DRAFT)
if old
raise "PUBLISH OR RESET CURRENT DRAFT (#{old.kind}) FIRST"
end
raise "PUBLISH OR RESET CURRENT DRAFT (#{old.kind}) FIRST" if old
save_draft(Draft.new(kind: kind, body: body))
end
@ -74,21 +99,22 @@ module Pigeon
def get_draft
draft = store.get_config(CURRENT_DRAFT)
if draft
return draft
else
unless draft
raise "THERE IS NO DRAFT. CREATE ONE FIRST."
end
draft
end
def update_draft(k, v); Helpers.update_draft(self, k, v); end
def update_draft(k, v)
Helpers.update_draft(self, k, v)
end
def reset_draft
add_config(CURRENT_DRAFT, nil)
end
# Author a new message.
def publish_draft(draft = self.get_draft)
def publish_draft(draft = get_draft)
Helpers.publish_draft(self, draft)
end
@ -113,12 +139,16 @@ module Pigeon
hash2filepath = Helpers.hash2file_path(mhash)
blob_path = File.join(file_path, hash2filepath)
blob = get_blob(mhash)
Helpers.write_to_disk(blob_path, mhash, blob) if blob
puts "=== EXPORT"
puts " blob_path: #{blob_path}"
puts " mhash: #{mhash}"
puts " blob: #{blob.length} bytes"
Helpers.write_to_disk(blob_path, mhash, blob)
end
# Render messages for all peers.
content = messages
.map { |message| message.render }
.map(&:render)
.join(BUNDLE_MESSAGE_SEPARATOR)
File.write(File.join(file_path, "gossip.pgn"), content + CR)
@ -127,27 +157,38 @@ module Pigeon
def import_bundle(file_path = DEFAULT_BUNDLE_PATH)
bundle = File.read(File.join(file_path, "gossip.pgn"))
tokens = Pigeon::Lexer.tokenize(bundle)
blobs = tokens.reduce(Set.new) do |set, (a, b, c)|
blobs = tokens.each_with_object(Set.new) do |(_a, b, c), set|
[b, c].map do |d|
set.add(d) if Helpers.blob_multihash?(d)
end
set
end.map do |multihash|
if !store.have_blob?(multihash)
binding.pry
end
binding.pry unless store.have_blob?(multihash)
end
Pigeon::Parser.parse(self, tokens)
end
# === BLOBS
def get_blob(b); store.get_blob(b); end
def add_blob(b); store.add_blob(b); end
def get_blob(b)
store.get_blob(b)
end
def add_blob(b)
store.add_blob(b)
end
# === DB Management
def get_config(k); store.get_config(k); end
def add_config(k, v); store.add_config(k, v); end
def reset_database; store.reset; init_ident; end
def get_config(k)
store.get_config(k)
end
def add_config(k, v)
store.add_config(k, v)
end
def reset_database
store.reset
init_ident
end
private

View File

@ -17,11 +17,12 @@ module Pigeon
end
def [](key)
self.body[key]
body[key]
end
def []=(key, value)
raise STRING_KEYS_ONLY unless key.is_a?(String)
case value[0]
when BLOB_SIGIL, MESSAGE_SIGIL, IDENTITY_SIGIL, STRING_SIGIL
body[key] = value

View File

@ -27,7 +27,7 @@ module Pigeon
def sign(string)
hex = @signing_key.sign(string)
b64 = Helpers.b32_encode(hex)
return b64 + SIG_FOOTER
b64 + SIG_FOOTER
end
end
end

View File

@ -9,7 +9,7 @@ module Pigeon
end
def multihash
tpl = self.render
tpl = render
digest = Digest::SHA256.digest(tpl)
sha256 = Helpers.b32_encode(digest)
"#{MESSAGE_SIGIL}#{sha256}#{BLOB_FOOTER}"
@ -23,6 +23,7 @@ module Pigeon
lipmaa:,
signature:)
raise MISSING_BODY if body.empty?
@author = author
@body = body
@depth = depth

View File

@ -4,7 +4,8 @@ module Pigeon
def self.parse(db, tokens)
raise "NO!" unless db.is_a?(Pigeon::Database)
self.new(db, tokens).parse
new(db, tokens).parse
end
def initialize(db, tokens)
@ -14,8 +15,8 @@ module Pigeon
@results = []
end
def parse()
@tokens.each_with_index do |token, i|
def parse
@tokens.each_with_index do |token, _i|
case token.first
when :AUTHOR then set(:author, token.last)
when :KIND then set(:kind, token.last)

View File

@ -47,15 +47,17 @@ module Pigeon
write do
a = store.fetch(CONF_NS)
raise "FIX SAVED DRAFTS" if value.instance_variable_get(:@db)
a[key] = value
end
end
def add_blob(data)
size = data.bytesize
if (size > BLOB_BYTE_LIMIT)
if size > BLOB_BYTE_LIMIT
raise "Blob size limit is #{BLOB_BYTE_LIMIT} bytes. Got #{size}"
end
raw_digest = Digest::SHA256.digest(data)
b32_hash = Helpers.b32_encode(raw_digest)
multihash = [BLOB_SIGIL, b32_hash, BLOB_FOOTER].join("")
@ -66,16 +68,15 @@ module Pigeon
def get_blob(blob_multihash)
path = File.join(Helpers.hash2file_path(blob_multihash))
path = File.join(PIGEON_BLOB_PATH, path)
if File.file?(path)
File.read(path)
else
nil
end
File.read(path) if File.file?(path)
end
# `nil` means "none"
def get_message_count_for(mhash)
raise "Expected string, got #{mhash.class}" unless mhash.is_a?(String) # Delete later
unless mhash.is_a?(String)
raise "Expected string, got #{mhash.class}"
end # Delete later
read { store[COUNT_INDEX_NS][mhash] || 0 }
end
@ -85,18 +86,21 @@ module Pigeon
depth = -1
last = ""
# TODO: This loop may become unresponsive.
until (last == nil) || (depth > 99999)
last = self.get_message_by_depth(author, depth += 1)
until last.nil? || (depth > 99_999)
last = get_message_by_depth(author, depth += 1)
all.push(last) if last
end
return all
all
else
read { store["messages"].keys }
end
end
def get_message_by_depth(multihash, depth)
raise "Expected string, got #{multihash.class}" unless multihash.is_a?(String) # Delete later
unless multihash.is_a?(String)
raise "Expected string, got #{multihash.class}"
end # Delete later
# Map<[multihash(str), depth(int)], Signature>
key = [multihash, depth].join(".")
read { store[MESSAGE_BY_DEPTH_NS][key] }
@ -108,12 +112,10 @@ module Pigeon
def insert_message(msg)
write do
if store[MESG_NS].fetch(msg.multihash, false)
return msg
end
return msg if store[MESG_NS].fetch(msg.multihash, false)
if store[BLCK_NS].member?(msg.author.multihash)
STDERR.puts("Blocked peer: #{msg.author.multihash}")
warn("Blocked peer: #{msg.author.multihash}")
return msg
end
@ -178,8 +180,16 @@ module Pigeon
store.transaction(is_read_only) { yield }
end
def write(&blk); transaction(false, &blk); end
def read(&blk); transaction(true, &blk); end
def on_disk?; File.file?(path); end
def write(&blk)
transaction(false, &blk)
end
def read(&blk)
transaction(true, &blk)
end
def on_disk?
File.file?(path)
end
end
end

View File

@ -12,6 +12,6 @@ Gem::Specification.new do |s|
s.homepage = "https://tildegit.org/PigeonProtocolConsortium/pigeon_ruby"
s.license = "GPL-3.0-or-later"
s.executables = "pigeon-cli"
s.add_runtime_dependency "thor", "~> 0.20", ">= 0.20.3"
s.add_runtime_dependency "ed25519", "~> 1.2", ">= 1.2.4"
s.add_runtime_dependency "thor", "~> 0.20", ">= 0.20.3"
end

View File

@ -18,8 +18,8 @@ RSpec.describe Pigeon::Message do
db.add_message("a", { "b" => db.add_blob("three") })]
normal = (1..10)
.to_a
.map do |n| { "foo" => ["bar", "123", SecureRandom.uuid].sample } end
.map do |d| db.add_message(SecureRandom.uuid, d) end
.map { |_n| { "foo" => ["bar", "123", SecureRandom.uuid].sample } }
.map { |d| db.add_message(SecureRandom.uuid, d) }
blobs + normal
end
@ -51,7 +51,7 @@ RSpec.describe Pigeon::Message do
db.add_blob(File.read("b.gif")) => db.add_blob(File.read("c.gif")),
})
db.export_bundle("./spec/fixtures/has_blobs")
STDERR.puts("The directory structure is not correct.")
warn("The directory structure is not correct.")
exit(1)
db.import_bundle("./spec/fixtures/has_blobs")
expect(db.all_messages.count).to eq(0)

View File

@ -102,7 +102,7 @@ RSpec.describe Pigeon::Lexer do
[:BODY_END],
[:SIGNATURE, "BBE732XXZ33XTCW1CRA9RG13FQ0FVMR61SAHD621VH8C64B4WA8C86JSTTAHG4CSGNBJJ7YSAVRF3YEBX6GTEB6RRWGDA84VJZPMR3R.sig.ed25519"],
[:MESSAGE_END],
]
].freeze
MESSAGE_LINES = [
"author @VG44QCHKA38E7754RQ5DAFBMMD2CCZQRZ8BR2J4MRHHGVTHGW670.ed25519",
@ -131,7 +131,7 @@ RSpec.describe Pigeon::Lexer do
it "tokenizes a bundle" do
bundle = File.read("./spec/fixtures/normal/gossip.pgn")
tokens = Pigeon::Lexer.tokenize(bundle)
EXPECTED_TOKENS1.each_with_index do |item, i|
EXPECTED_TOKENS1.each_with_index do |_item, i|
expect(tokens[i]).to eq(EXPECTED_TOKENS1[i])
end
end
@ -139,7 +139,7 @@ RSpec.describe Pigeon::Lexer do
it "tokenizes a single message" do
string = message.render
tokens = Pigeon::Lexer.tokenize(string)
hash = tokens.reduce({ BODY: {} }) do |h, token|
hash = tokens.each_with_object({ BODY: {} }) do |token, h|
case token.first
when :HEADER_END, :BODY_END, :MESSAGE_END
h
@ -148,7 +148,6 @@ RSpec.describe Pigeon::Lexer do
else
h[token.first] = token.last
end
h
end
expect(hash[:AUTHOR]).to eq(message.author.multihash)

View File

@ -157,7 +157,7 @@ RSpec.describe Pigeon::Message do
kind[rand(0...8)] = n
db.reset_draft
db.new_draft(kind: kind)
boom = ->() { db.publish_draft.render }
boom = -> { db.publish_draft.render }
expect(boom).to raise_error(Pigeon::Lexer::LexError)
end
end
@ -169,7 +169,7 @@ RSpec.describe Pigeon::Message do
key = SecureRandom.alphanumeric(8)
key[rand(0...8)] = n
db.update_draft(key, "should crash")
boom = ->() { Pigeon::Lexer.tokenize(db.publish_draft.render) }
boom = -> { Pigeon::Lexer.tokenize(db.publish_draft.render) }
expect(boom).to raise_error(Pigeon::Lexer::LexError)
end
end

View File

@ -20,7 +20,7 @@ RSpec.describe Pigeon::Lexer do
[:BODY_ENTRY, "duplicate", "This key is a duplicate."],
[:SIGNATURE, "DN7yPTE-m433ND3jBL4oM23XGxBKafjq0Dp9ArBQa_TIGU7DmCxTumieuPBN-NKxlx_0N7-c5zjLb5XXVHYPCQ==.sig.ed25519"],
[:MESSAGE_END],
]
].freeze
it "parses tokens" do
results = Pigeon::Parser.parse(db, tokens)

View File

@ -2,8 +2,8 @@ require "spec_helper"
RSpec.describe Pigeon::Storage do
LOGO_BLOB = File.read("./logo.png")
IDS = %w(@ZMWM5PSXRN7RFRMSWW1E3V5DNGC4XGGJTHKCAGB48SNRG4XXE5NG.ed25519
@VF0Q4KXQNY6WCAXF17GAZGDPAX8XKM70SB8N7V0NSD1H370ZCJBG.ed25519)
IDS = %w[@ZMWM5PSXRN7RFRMSWW1E3V5DNGC4XGGJTHKCAGB48SNRG4XXE5NG.ed25519
@VF0Q4KXQNY6WCAXF17GAZGDPAX8XKM70SB8N7V0NSD1H370ZCJBG.ed25519].freeze
let(:db) do
db = Pigeon::Database.new

View File

@ -1,7 +1,7 @@
require "spec_helper"
RSpec.describe Pigeon::MessageSerializer do
SHIM_ATTRS = [:author, :body, :kind, :depth, :prev, :signature, :lipmaa]
SHIM_ATTRS = %i[author body kind depth prev signature lipmaa].freeze
MessageShim = Struct.new(*SHIM_ATTRS)
TOP_HALF = ["author FAKE_AUTHOR",
"\nkind FAKE_KIND",

View File

@ -27,7 +27,7 @@
require_relative "lib/pigeon"
require "pry"
files = %w(a.gif b.gif c.gif)
files = %w[a.gif b.gif c.gif]
body = { "what" => "A simple bundle with a few blobs" }
db = Pigeon::Database.new(path: "new.db")
db.add_message("description", body)