Add bin and edit workflow
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 9s

This commit is contained in:
2026-09-16 13:11:16 -06:00
parent c8ac4fcae5
commit 4cee170d66
17576 changed files with 895740 additions and 2 deletions
@@ -0,0 +1,363 @@
require 'enumerator'
module Hashery
# Hash with LRU expiry policy. There are at most max_size elements in a
# LRUHash. When adding more elements old elements are removed according
# to LRU policy.
#
# Based on Robert Klemme's LRUHash class.
#
# LRUHash, Copyright (c) 2010 Robert Klemme.
#
class LRUHash
include Enumerable
attr_reader :max_size
attr_accessor :default
attr_accessor :default_proc
attr_accessor :release_proc
#
# Initialize new LRUHash instance.
#
# max_size -
# default_value -
# block -
#
def initialize(max_size, default_value=nil, &block)
@max_size = normalize_max(max_size)
@default = default_value
@default_proc = block
@h = {}
@head = Node.new
@tail = front(Node.new)
end
#
# Iterate over each pair.
#
def each_pair
if block_given?
each_node do |n|
yield [n.key, n.value]
end
else
enum_for :each_pair
end
end
#
# Same as each pair.
#
alias each each_pair
#
# Iterate over each key.
#
def each_key
if block_given?
each_node do |n|
yield n.key
end
else
enum_for :each_key
end
end
#
# Iterate over each value.
#
def each_value
if block_given?
each_node do |n|
yield n.value
end
else
enum_for :each_value
end
end
#
# Size of the hash.
#
def size
@h.size
end
#
#
#
def empty?
@head.succ.equal? @tail
end
#
#
#
def fetch(key, &b)
n = @h[key]
if n
front(n).value
else
(b || FETCH)[key]
end
end
#
#
#
def [](key)
fetch(key) do |k|
@default_proc ? @default_proc[self, k] : default
end
end
#
#
#
def keys
@h.keys
end
#
#
#
def values
@h.map {|k,n| n.value}
end
#
#
#
def has_key?(key)
@h.has_key? key
end
alias key? has_key?
alias member? has_key?
alias include? has_key?
#
#
#
def has_value?(value)
each_pair do |k, v|
return true if value.eql? v
end
false
end
alias value? has_value?
def values_at(*key_list)
key_list.map {|k| self[k]}
end
#
#
#
def assoc(key)
n = @h[key]
if n
front(n)
[n.key, n.value]
end
end
#
#
#
def rassoc(value)
each_node do |n|
if value.eql? n.value
front(n)
return [n.key, n.value]
end
end
nil
end
#
#
#
def key(value)
pair = rassoc(value) and pair.first
end
#
#
#
def store(key, value)
# same optimization as in Hash
key = key.dup.freeze if String === key && !key.frozen?
n = @h[key]
unless n
if size == max_size
# reuse node to optimize memory usage
n = delete_oldest
n.key = key
n.value = value
else
n = Node.new key, value
end
@h[key] = n
end
front(n).value = value
end
alias []= store
#
#
#
def delete(key)
n = @h[key] and remove_node(n).value
end
#
#
#
def delete_if
each_node do |n|
remove_node n if yield n.key, n.value
end
end
#
#
#
def max_size=(limit)
limit = normalize_max(limit)
while size > limit
delete_oldest
end
@max_size = limit
end
#
#
#
def clear
until empty?
delete_oldest
end
self
end
#
#
#
def to_s
s = nil
each_pair {|k, v| (s ? (s << ', ') : s = '{') << k.to_s << '=>' << v.to_s}
s ? (s << '}') : '{}'
end
alias inspect to_s
private
#
# Iterate nodes.
#
def each_node
n = @head.succ
until n.equal? @tail
succ = n.succ
yield n
n = succ
end
self
end
#
# Move node to front.
#
# node - [Node]
#
def front(node)
node.insert_after(@head)
end
#
# Remove the node and invoke release_proc
# if set
#
# node - [Node]
#
def remove_node(node)
n = @h.delete(node.key)
n.unlink
release_proc and release_proc[n.key, n.value]
n
end
#
# Remove the oldest node returning the node
#
def delete_oldest
n = @tail.pred
raise "Cannot delete from empty hash" if @head.equal? n
remove_node n
end
#
# Normalize the argument in order to be usable as max_size
# criterion is that n.to_i must be an Integer and it must
# be larger than zero.
#
# n - [#to_i] max size
#
def normalize_max(n)
n = n.to_i
raise ArgumentError, 'Invalid max_size: %p' % n unless Integer === n && n > 0
n
end
#
FETCH = Proc.new {|k| raise KeyError, 'key not found'}
# A single node in the doubly linked LRU list of nodes.
Node = Struct.new :key, :value, :pred, :succ do
def unlink
pred.succ = succ if pred
succ.pred = pred if succ
self.succ = self.pred = nil
self
end
def insert_after(node)
raise 'Cannot insert after self' if equal? node
return self if node.succ.equal? self
unlink
self.succ = node.succ
self.pred = node
node.succ.pred = self if node.succ
node.succ = self
self
end
end
end
end