libgit2 / libgit2/rugged

Can git commit signing implementation be updated to be easier to use?

Open
#992 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C
Stars
2.3k
Forks
293
PR merge metrics
No merged PRs in 30d

Description

Been trying to implement signing of commits in a project we use.
I have sort of gotten it to work but the implementation between a none signed commit and signed commit differs a lot and i would like it to become much easier so the code in the project i use gets cleaner.

Basically this is how we implemented none signed today, it works for a newly created bare repo also.

oid = repo.write("This is a blob.", :blob)
index = repo.index
index.read_tree(repo.head.target.tree)
index.add(:path => "README.md", :oid => oid, :mode => 0100644)

options = {}
options[:tree] = index.write_tree(repo)

options[:author] = { :email => "testuser@github.com", :name => 'Test Author', :time => Time.now }
options[:committer] = { :email => "testuser@github.com", :name => 'Test Author', :time => Time.now }
options[:message] ||= "Making a commit via Rugged!"
options[:parents] = repo.empty? ? [] : [ repo.head.target ].compact
options[:update_ref] = 'HEAD'

@commitref = Rugged::Commit.create(repo, options)

index.write

But to make signed commits in a new bare repo the first part is the same with options but alot after differs.

oid = repo.write("This is a blob.", :blob)
index = repo.index
index.read_tree(repo.head.target.tree)
index.add(:path => "README.md", :oid => oid, :mode => 0100644)

options = {}
options[:tree] = index.write_tree(repo)

options[:author] = { :email => "testuser@github.com", :name => 'Test Author', :time => Time.now }
options[:committer] = { :email => "testuser@github.com", :name => 'Test Author', :time => Time.now }
options[:message] ||= "Making a commit via Rugged!"
options[:parents] = repo.empty? ? [] : [ repo.head.target ].compact
options[:update_ref] = 'HEAD'

# Create a string of the contents to be commited.
content = Rugged::Commit.create_to_s(repo, options)

# Sign the string.
crypto = GPGME::Crypto.new(armor: true)
signature = crypto.detach_sign(content, signers: @cfg.sign_key).to_s.strip

# Create a commit using the string and signature. 
@commitref = Rugged::Commit.create_with_signature(repo, content, signature, 'gpgsig')

# After doing this create_with_signature calling for index.write does not work.
# and i have to do this repo references else i cant see any commits when i do git log --show-signature

# Check if HEAD exists and handle accordingly
if repo.references.exist?("HEAD") && !repo.head_unborn?
  # HEAD exists and points to a real branch
  repo.references.update(repo.head.name, @commitref)
else
  # HEAD doesn't exist or is unborn - create default branch
  repo.references.create("refs/heads/master", @commitref)
end

I would like the implementation of signed commits to be as easy as doing a normal commit just that i have to specify the key i want to sign with.
e.g

# Just want a function i can call for as easy as Commit.create that signs my commits and update the reference on disk. 
Rugged::Commit.commit_with_signature(repo, options, signature)

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading Rugged::Commit.create, create_to_s, and create_with_signature, then trace how index.write and reference updates behave for a new bare repository. Done means a signed commit can be created through one Commit-level call with the signing input while preserving normal index and HEAD/reference behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
git, ruby
Domain
backend-api-design, devtools
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.