class PrecommitSign

Class for signing Git commit messages with a computed hash

Constants

SIG_KEY

Attributes

date[W]
message[RW]

Public Class Methods

from_message(message) click to toggle source
# File lib/pre-commit-sign.rb, line 18
def self.from_message(message)
  instance = new
  instance.message = message
  instance
end
new(message_file = nil) click to toggle source
# File lib/pre-commit-sign.rb, line 13
def initialize(message_file = nil)
  @message_file = message_file
  @message = IO.read(@message_file) unless @message_file.nil?
end

Public Instance Methods

commit_message() click to toggle source
# File lib/pre-commit-sign.rb, line 46
def commit_message
  real_message.split("\n")[2..-1].join("\n")
end
commit_signature?() click to toggle source
# File lib/pre-commit-sign.rb, line 54
def commit_signature?
  /^Precommit-Verified:/.match?(full_message)
end
commit_title() click to toggle source
# File lib/pre-commit-sign.rb, line 42
def commit_title
  real_message.split("\n").first
end
date() click to toggle source
# File lib/pre-commit-sign.rb, line 34
def date
  if ENV.key?('GIT_AUTHOR_DATE')
    DateTime.strptime(ENV['GIT_AUTHOR_DATE'], '@%s %z').to_time.utc
  else
    (@date || Time.now).utc
  end
end
existing_signature() click to toggle source
# File lib/pre-commit-sign.rb, line 62
def existing_signature
  /#{SIG_KEY}:\s*([a-f0-9]+)$/.match(full_message)&.captures&.first
end
full_message() click to toggle source
# File lib/pre-commit-sign.rb, line 24
def full_message
  message
end
real_message() click to toggle source

Ignores comments, leading and trailing whitespace and the signature footer

# File lib/pre-commit-sign.rb, line 29
def real_message
  m = full_message.split("\n").reject { |l| l.start_with?('#', "#{SIG_KEY}:") }.join("\n")
  /\A\s*(.*?)\s*\Z/m.match(m).captures.first
end
signature() click to toggle source
# File lib/pre-commit-sign.rb, line 50
def signature
  Digest::SHA256.hexdigest("#{real_message}#{date}")
end
valid_signature?() click to toggle source
# File lib/pre-commit-sign.rb, line 58
def valid_signature?
  existing_signature == signature
end
write_signature() click to toggle source

Real message with signature

# File lib/pre-commit-sign.rb, line 67
def write_signature
  self.message = "#{real_message.chomp}\n\n#{SIG_KEY}: #{signature}\n"
  IO.write(@message_file, message, 0, mode: 'w') unless @message_file.nil?
end