Some notes about libgit2/rugged

violet posted @ Nov 06, 2015 02:42:44 PM in 笔记 with tags ruby Rugged , 23227 阅读

I learned libgit2/rugged when I involved in a project which is to analysis a repository. I found it's a little hard to use Rugged to do the basic things, e.g. `git pull`, `git push`, etc. This is the purpose that I want to add some notes here. In case of someday there's someone likes me who encounter into these kinds of stuff. ლ(╹◡╹ლ)

- find a repository

repo = Rugged::Repository.new('path/to/my/repository')

repo = Rugged::Repository.discover("/Users/me/projects/repo/lib/subdir/")

 

- clone a repository

credentials = Rugged::Credentials::SshKey.new
options = {}
options.merge!(:credentials => credentials) if credentials.exist?
Rugged::Repository.clone_at(url, target_dir, options)
# url may like this for github: github.com:violetzijing/xxx.git
# username for github in credentials should be `git`
# options will pass your identity to github. Even you just clone a public repository.

 

- fetch from remote repo

repo.remotes.clear_refspecs
refspecs = [ "#{repo.local_ref.name}:#{repo.remote_ref.name}" ]
options = {}
options.merge!(credentials) if credentials
results = repo.remote.fetch(refspecs, options)
results.merge!(new_target: repo.remote_ref.target_id)
# Returns hash with the result of the action together with hash containing statistics
# for the fetch operation: :total_objects=>0, :indexed_objects=>6, :received_bytes=>0,
# received_objects=>0, :local_objects=>0, :total_deltas=>0, :indexed_deltas=>0.
# :new_target=>"iekcicie493kd049930202" will be added if some new data were fetched.
# If the action fails the hash will contain only :error=>"some error message"

- merge commits

This method is from this question http://stackoverflow.com/questions/21842783/rugged-fetch-pull-rebase-possible

merge_index = repo.merge_commits(
  Rugged::Branches.lookup(repo, "master").tip,
  Rugged::Branches.lookup(repo, "origin/master").tip
)

raise "Conflict detected!" if merge_index.conflicts?

merge_commit = Rugged::Commit.create(repo, {
  parents: [
    Rugged::Branches.lookup(repo, "master").tip,
    Rugged::Branches.lookup(repo, "origin/master").tip
  ],
  tree: merge_index.write_tree(repo),
  message: 'Merged `origin/master` into `master`',
  author:    { name: "User", email: "example@test.com" },
  committer: { name: "User", email: "example@test.com" },
  update_ref: 'master'
})

 

- pull from remote repo

Pull operation could be achieved by fetch + merge

- rebase

As it's said, rebase hasn't been implemented in libgit2. So we may just walk through the commit and update the reference to do rebase operation.

- create commit

index = repo.index
index.read_tree(repo.head.target.tree)
oid = Rugged::Blob.from_workdir repo, relative_path
index.add(:path => relative_path, :oid => oid, :mode => 0100644)
index.write
# This step hasn't been provided on github page, but this is necessary.

options = {}
options[:tree] = index.write_tree(repo)
options[:author] = { :email => "xx@xxx.com" :name => "XXX", :time => Time.now }
options[:committer] = { :email => "xx@xxx.com", :name => "XXX", :time => Time.now }
options[:message] ||= commit_info
options[:parents] = repo.empty? ? [] : [ repo.head.target ].compact
options[:update_ref] = 'HEAD'

Rugged::Commit.create(repo, options)

 

- create a branch

repo.create_branch branch_name

 

- checkout a branch

repo.checkout branch_name

 

- push to remote repo

repo.remotes.clear_refspecs
refspecs = ["refs/heads/#{branch_name}"]
options = {}
options.merge!(credentials: credentials) if credentials.exist?
repo.remotes.push refspecs, optionsrepo.remotes.clear_refspecs
refspecs = ["refs/heads/#{branch_name}"]
options = {}
options.merge!(credentials: credentials) if credentials.exist?
repo.remotes.push refspecs, options

# According to doc, it also provide repo.push operation. But it will call remote.push. And I'm not sure what exact parameter to the function(tooooooo complex).
So I recommend use Rugged::Remote.push.

 

- given tree and path of a file and find the oid of the file

found = nil
tree.walk(:postorder) {|root, entry| found = entry if path.eql? "#{root}#{entry[:name]}" }

# I just find it's easy to use oid of a file to locate the file, but it's not easy to do it oppositely.

 

 

  • 无匹配

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter