56 lines
1.4 KiB
Ruby
56 lines
1.4 KiB
Ruby
module Adr
|
|
# The docs/adr/ directory of one project. Scans files, derives the next ID
|
|
# from directory contents (never the index), reads and writes records.
|
|
class Repository
|
|
INDEX_FILENAME = "README.md"
|
|
|
|
Entry = Struct.new(:path, :record)
|
|
|
|
def initialize(root:)
|
|
@root = root
|
|
end
|
|
|
|
attr_reader :root
|
|
|
|
def dir = File.join(root, "docs", "adr")
|
|
def index_path = File.join(dir, INDEX_FILENAME)
|
|
|
|
def exists?
|
|
Dir.exist?(dir) && File.exist?(index_path)
|
|
end
|
|
|
|
def adr_paths
|
|
Dir.glob(File.join(dir, "[0-9][0-9][0-9][0-9]-*.md")).sort
|
|
end
|
|
|
|
# Only files in the os-adr format count as entries; legacy frontmatter-less
|
|
# files sharing docs/adr/ (pre-migration sources) are skipped, not errors.
|
|
def entries
|
|
adr_paths.filter_map do |path|
|
|
Entry.new(path, Record.parse(File.read(path)))
|
|
rescue Record::ParseError, Psych::SyntaxError
|
|
nil
|
|
end
|
|
end
|
|
|
|
def next_id
|
|
max = adr_paths.map { |path| File.basename(path)[0, 4].to_i }.max || 0
|
|
format("%04d", max + 1)
|
|
end
|
|
|
|
def find(id)
|
|
entries.find { |entry| entry.record.id == id }
|
|
end
|
|
|
|
def write(record)
|
|
path = File.join(dir, "#{record.id}-#{Adr.slugify(record.title)}.md")
|
|
File.write(path, record.to_markdown)
|
|
path
|
|
end
|
|
|
|
def write_entry(entry)
|
|
File.write(entry.path, entry.record.to_markdown)
|
|
end
|
|
end
|
|
end
|