Giter VIP home page Giter VIP logo

grit's Introduction

Grit

Grit is no longer maintained. Check out rugged.

Grit gives you object oriented read/write access to Git repositories via Ruby. The main goals are stability and performance. To this end, some of the interactions with Git repositories are done by shelling out to the system's git command, and other interactions are done with pure Ruby reimplementations of core Git functionality. This choice, however, is transparent to end users, and you need not know which method is being used.

This software was developed to power GitHub, and should be considered production ready. An extensive test suite is provided to verify its correctness.

Grit is maintained by Tom Preston-Werner, Scott Chacon, Chris Wanstrath, and PJ Hyett.

This documentation is accurate as of Grit 2.3.

Requirements

Install

Easiest install is via RubyGems:

$ gem install grit

Source

Grit's Git repo is available on GitHub, which can be browsed at:

http://github.com/mojombo/grit

and cloned with:

git clone git://github.com/mojombo/grit.git

Development

You will need these gems to get tests to pass:

  • mocha

Contributing

If you'd like to hack on Grit, follow these instructions. To get all of the dependencies, install the gem first.

  1. Fork the project to your own account
  2. Clone down your fork
  3. Create a thoughtfully named topic branch to contain your change
  4. Hack away
  5. Add tests and make sure everything still passes by running rake
  6. If you are adding new functionality, document it in README.md
  7. Do not change the version number, I will do that on my end
  8. If necessary, rebase your commits into logical chunks, without errors
  9. Push the branch up to GitHub
  10. Send a pull request for your branch

Usage

Grit gives you object model access to your Git repositories. Once you have created a Repo object, you can traverse it to find parent commits, trees, blobs, etc.

Initialize a Repo object

The first step is to create a Grit::Repo object to represent your repo. In this documentation I include the Grit module to reduce typing.

require 'grit'
repo = Grit::Repo.new("/Users/tom/dev/grit")

In the above example, the directory /Users/tom/dev/grit is my working directory and contains the .git directory. You can also initialize Grit with a bare repo.

repo = Repo.new("/var/git/grit.git")

Getting a list of commits

From the Repo object, you can get a list of commits as an array of Commit objects.

repo.commits
# => [#<Grit::Commit "e80bbd2ce67651aa18e57fb0b43618ad4baf7750">,
      #<Grit::Commit "91169e1f5fa4de2eaea3f176461f5dc784796769">,
      #<Grit::Commit "038af8c329ef7c1bae4568b98bd5c58510465493">,
      #<Grit::Commit "40d3057d09a7a4d61059bca9dca5ae698de58cbe">,
      #<Grit::Commit "4ea50f4754937bf19461af58ce3b3d24c77311d9">]

Called without arguments, Repo#commits returns a list of up to ten commits reachable by the master branch (starting at the latest commit). You can ask for commits beginning at a different branch, commit, tag, etc.

repo.commits('mybranch')
repo.commits('40d3057d09a7a4d61059bca9dca5ae698de58cbe')
repo.commits('v0.1')

You can specify the maximum number of commits to return.

repo.commits('master', 100)

If you need paging, you can specify a number of commits to skip.

repo.commits('master', 10, 20)

The above will return commits 21-30 from the commit list.

The Commit object

Commit objects contain information about that commit.

head = repo.commits.first

head.id
# => "e80bbd2ce67651aa18e57fb0b43618ad4baf7750"

head.parents
# => [#<Grit::Commit "91169e1f5fa4de2eaea3f176461f5dc784796769">]

head.tree
# => #<Grit::Tree "3536eb9abac69c3e4db583ad38f3d30f8db4771f">

head.author
# => #<Grit::Actor "Tom Preston-Werner <[email protected]>">

head.authored_date
# => Wed Oct 24 22:02:31 -0700 2007

head.committer
# => #<Grit::Actor "Tom Preston-Werner <[email protected]>">

head.committed_date
# => Wed Oct 24 22:02:31 -0700 2007

head.message
# => "add Actor inspect"

You can traverse a commit's ancestry by chaining calls to #parents.

repo.commits.first.parents[0].parents[0].parents[0]

The above corresponds to master^^^ or master~3 in Git parlance.

The Tree object

A tree records pointers to the contents of a directory. Let's say you want the root tree of the latest commit on the master branch.

tree = repo.commits.first.tree
# => #<Grit::Tree "3536eb9abac69c3e4db583ad38f3d30f8db4771f">

tree.id
# => "3536eb9abac69c3e4db583ad38f3d30f8db4771f"

Once you have a tree, you can get the contents.

contents = tree.contents
# => [#<Grit::Blob "4ebc8aea50e0a67e000ba29a30809d0a7b9b2666">,
      #<Grit::Blob "81d2c27608b352814cbe979a6acd678d30219678">,
      #<Grit::Tree "c3d07b0083f01a6e1ac969a0f32b8d06f20c62e5">,
      #<Grit::Tree "4d00fe177a8407dbbc64a24dbfc564762c0922d8">]

This tree contains two Blob objects and two Tree objects. The trees are subdirectories and the blobs are files. Trees below the root have additional attributes.

contents.last.name
# => "lib"

contents.last.mode
# => "040000"

There is a convenience method that allows you to get a named sub-object from a tree.

tree / "lib"
# => #<Grit::Tree "e74893a3d8a25cbb1367cf241cc741bfd503c4b2">

You can also get a tree directly from the repo if you know its name.

repo.tree
# => #<Grit::Tree "master">

repo.tree("91169e1f5fa4de2eaea3f176461f5dc784796769")
# => #<Grit::Tree "91169e1f5fa4de2eaea3f176461f5dc784796769">

The Blob object

A blob represents a file. Trees often contain blobs.

blob = tree.contents.first
# => #<Grit::Blob "4ebc8aea50e0a67e000ba29a30809d0a7b9b2666">

A blob has certain attributes.

blob.id
# => "4ebc8aea50e0a67e000ba29a30809d0a7b9b2666"

blob.name
# => "README.txt"

blob.mode
# => "100644"

blob.size
# => 7726

You can get the data of a blob as a string.

blob.data
# => "Grit is a library to ..."

You can also get a blob directly from the repo if you know its name.

repo.blob("4ebc8aea50e0a67e000ba29a30809d0a7b9b2666")
# => #<Grit::Blob "4ebc8aea50e0a67e000ba29a30809d0a7b9b2666">

Other

There are many more API methods available that are not documented here. Please reference the code for more functionality.

Copyright

Copyright (c) 2010 Tom Preston-Werner. See LICENSE for details.

grit's People

Contributors

binki avatar bkeepers avatar chapados avatar cho45 avatar cristibalan avatar davetron5000 avatar defunkt avatar dysinger avatar gramgibson avatar halorgium avatar hans avatar holman avatar js avatar koraktor avatar mojombo avatar pda avatar peff avatar pjhyett avatar rsanheim avatar rtomayko avatar sbryant avatar schacon avatar smtlaissezfaire avatar sr avatar technoweenie avatar therealadam avatar tmm1 avatar vmg avatar voker57 avatar wvl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

grit's Issues

raise NoSuchPath when ls_tree_path gets a nil tree

We're getting a bunch of NoMethodErrors when someone hits non sensical URLs like: http://github.com/chregu/planet-php/blob/2c3126329d11cdfca31faca0ed87a8aef888e096/inc/config-admin.php.dist/dbase.php. Here, config-admin.php.dist is a blob so ls_tree_path gets back a nil tree but doesn't check for it.

Backtrace:

NoMethodError: private method `split' called for nil:NilClass
/data/github/current/ernie/../vendor/gems/grit/lib/grit/git-ruby/repository.rb:223:in `ls_tree_path'
/data/github/current/ernie/../vendor/gems/grit/lib/grit/git-ruby/repository.rb:230:in `ls_tree_path'
/data/github/current/ernie/../vendor/gems/grit/lib/grit/git-ruby/repository.rb:177:in `ls_tree'
/data/github/current/ernie/../vendor/gems/grit/lib/grit/git-ruby/repository.rb:176:in `each'
/data/github/current/ernie/../vendor/gems/grit/lib/grit/git-ruby/repository.rb:176:in `ls_tree'
/data/github/current/ernie/../vendor/gems/grit/lib/grit/git-ruby.rb:36:in `ls_tree'
/data/github/current/ernie/smoke.rb:67:in `send'
/data/github/current/ernie/smoke.rb:67:in `rpc'
/data/github/current/ernie/smoke.rb:110
/var/lib/gems/1.8/gems/ernie-1.3.0/lib/ernie.rb:79:in `call'
/var/lib/gems/1.8/gems/ernie-1.3.0/lib/ernie.rb:79:in `dispatch'
/var/lib/gems/1.8/gems/ernie-1.3.0/lib/ernie.rb:140:in `start'
/var/lib/gems/1.8/gems/ernie-1.3.0/lib/ernie.rb:128:in `loop'
/var/lib/gems/1.8/gems/ernie-1.3.0/lib/ernie.rb:128:in `start'
/var/lib/gems/1.8/gems/ernie-1.3.0/lib/ernie.rb:209
/data/github/current/ernie/smoke.rb:118

Patch:

http://github.com/rtomayko/grit/commit/no_tree

Difficult to get tree sha1 from repo/head

Consider the following code, where you want to avoid a commit if the tree is unchanged:

repo = Grit::Repo.new(param("repo_path"))
index = repo.index
index.add("some path", "some data")  # might be identical to existing data
index.commit("Backed up config", [repo.head.commit], nil, XXXX)

What goes into XXXX to prevent the commit taking place if the trees are identical? So far the best I can do is:

(repo.commit(repo.head.commit).tree.id rescue nil))

which isn't particularly neat. Should repo.head.commit return a commit object, rather than just the sha1?

Note that Commit#to_s gives to sha1 already, so having an array of Commit objects already works for the 'parents' argument.

update_ref is not atomic

update_ref and commit don't support (new_value, old_value) like the C git. This means it's not safe against overlapping commits by concurrent processes. Contrived example:

r1 = Grit::Repo.new(".")
=> #<Grit::Repo "/home/candlerb/tmp/tst1.git">
i1 = r1.index
=> #<Grit::Index:0xb7001204 @current_tree=nil, @repo=#<Grit::Repo "/home/candlerb/tmp/tst1.git">, @tree={}>
candlerb@candlerb-desktop:tst1.git$ irb --simple-prompt -rubygems -rgrit
r1 = Grit::Repo.new(".")
=> #<Grit::Repo "/home/candlerb/tmp/tst1.git">
i1 = r1.index
=> #<Grit::Index:0xb70051d8 @current_tree=nil, @repo=#<Grit::Repo "/home/candlerb/tmp/tst1.git">, @tree={}>
i1.add("foo","aaa")
=> "aaa"
i1.commit("Initial commit")
=> "a93019e0310492c8854c4b5e16d8f961ab16afff"
h = r1.head.commit
=> "a93019e0310492c8854c4b5e16d8f961ab16afff"
i1 = r1.index
=> #<Grit::Index:0xb6ff6a98 @current_tree=nil, @repo=#<Grit::Repo "/home/candlerb/tmp/tst1.git">, @tree={}>
i1.add("foo","bbb")
=> "bbb"

Now say a concurrent commit takes place

r2 = Grit::Repo.new(".")
=> #<Grit::Repo "/home/candlerb/tmp/tst1.git">
i2 = r2.index
=> #<Grit::Index:0xb6fee424 @current_tree=nil, @repo=#<Grit::Repo "/home/candlerb/tmp/tst1.git">, @tree={}>
i2.add("foo","ccc")
=> "ccc"
i2.commit("Commit two", [h])
=> "ac0e8461589b39738974f758d508e238d64fa9dd"
i1.commit("Conflicting commit", [h])
=> "f36d24ea4d820a9c109e35b22c8a77fed2060dcb"

One of the commits is silently lost

$ git log
commit f36d24ea4d820a9c109e35b22c8a77fed2060dcb
Author: Brian Candler [email protected]
Date: Mon Mar 22 05:11:20 2010 -0700

Conflicting commit

commit a93019e0310492c8854c4b5e16d8f961ab16afff
Author: Brian Candler [email protected]
Date: Mon Mar 22 05:10:00 2010 -0700

Initial commit

Suggested behaviour: update_ref and commit to take an (optional) 'previous head' value. Implement locking in update_ref, and if the previous head doesn't match, raise an exception.

Need to set --work-tree

In addition to --git-dir, otherwise the current working tree will be used (if a .git directory is present, even if the --git-dir points elsewhere)

Grit::GitRuby::Internal::LooseObjectError - size mismatch

In an exist git repository, I visit http://localhost:4567, then I write a first wiki, then submit it, and I got exception below:

Grit::GitRuby::Internal::LooseObjectError - size mismatch:
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/grit-2.4.1/lib/grit/git-ruby/internal/loose.rb:59:in get_raw_object' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/grit-2.4.1/lib/grit/git-ruby/internal/loose.rb:32:in[]'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/grit-2.4.1/lib/grit/git-ruby/repository.rb:84:in block in get_raw_object_by_sha1' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/grit-2.4.1/lib/grit/git-ruby/repository.rb:83:ineach'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/grit-2.4.1/lib/grit/git-ruby/repository.rb:83:in get_raw_object_by_sha1' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/grit-2.4.1/lib/grit/git-ruby/repository.rb:105:inget_object_by_sha1'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/grit-2.4.1/lib/grit/git-ruby/repository.rb:155:in cat_file' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/grit-2.4.1/lib/grit/git-ruby.rb:27:inblock in cat_file'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/grit-2.4.1/lib/grit/git-ruby.rb:224:in block in try_run' /Users/qichunren/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/timeout.rb:57:intimeout'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/grit-2.4.1/lib/grit/git-ruby.rb:223:in try_run' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/grit-2.4.1/lib/grit/git-ruby.rb:27:incat_file'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/grit-2.4.1/lib/grit/blob.rb:43:in data' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/gollum-1.3.0/lib/gollum/page.rb:151:inraw_data'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/gollum-1.3.0/lib/gollum/page.rb:160:in text_data' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/gollum-1.3.0/lib/gollum/markup.rb:14:ininitialize'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/gollum-1.3.0/lib/gollum/page.rb:171:in new' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/gollum-1.3.0/lib/gollum/page.rb:171:informatted_data'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/gollum-1.3.0/lib/gollum/frontend/app.rb:188:in show_page_or_file' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/gollum-1.3.0/lib/gollum/frontend/app.rb:42:inblock in class:App'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/sinatra-1.2.1/lib/sinatra/base.rb:1126:in call' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/sinatra-1.2.1/lib/sinatra/base.rb:1126:inblock in compile!'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/sinatra-1.2.1/lib/sinatra/base.rb:709:in instance_eval' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/sinatra-1.2.1/lib/sinatra/base.rb:709:inroute_eval'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/sinatra-1.2.1/lib/sinatra/base.rb:693:in block (2 levels) in route!' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/sinatra-1.2.1/lib/sinatra/base.rb:741:inblock in process_route'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/sinatra-1.2.1/lib/sinatra/base.rb:738:in catch' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/sinatra-1.2.1/lib/sinatra/base.rb:738:inprocess_route'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/sinatra-1.2.1/lib/sinatra/base.rb:692:in block in route!' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/sinatra-1.2.1/lib/sinatra/base.rb:691:ineach'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/sinatra-1.2.1/lib/sinatra/base.rb:691:in route!' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/sinatra-1.2.1/lib/sinatra/base.rb:826:indispatch!'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/sinatra-1.2.1/lib/sinatra/base.rb:619:in block in call!' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/sinatra-1.2.1/lib/sinatra/base.rb:791:ininstance_eval'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/sinatra-1.2.1/lib/sinatra/base.rb:791:in block in invoke' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/sinatra-1.2.1/lib/sinatra/base.rb:791:incatch'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/sinatra-1.2.1/lib/sinatra/base.rb:791:in invoke' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/sinatra-1.2.1/lib/sinatra/base.rb:619:incall!'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/sinatra-1.2.1/lib/sinatra/base.rb:604:in call' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/sinatra-1.2.1/lib/sinatra/showexceptions.rb:21:incall'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/sinatra-1.2.1/lib/sinatra/base.rb:1245:in block in call' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/sinatra-1.2.1/lib/sinatra/base.rb:1276:insynchronize'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/sinatra-1.2.1/lib/sinatra/base.rb:1245:in call' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/rack-1.2.2/lib/rack/content_length.rb:13:incall'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/rack-1.2.2/lib/rack/chunked.rb:15:in call' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/thin-1.2.8/lib/thin/connection.rb:84:inblock in pre_process'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/thin-1.2.8/lib/thin/connection.rb:82:in catch' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/thin-1.2.8/lib/thin/connection.rb:82:inpre_process'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/thin-1.2.8/lib/thin/connection.rb:57:in process' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/thin-1.2.8/lib/thin/connection.rb:42:inreceive_data'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/eventmachine-0.12.10/lib/eventmachine.rb:256:in run_machine' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/eventmachine-0.12.10/lib/eventmachine.rb:256:inrun'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/thin-1.2.8/lib/thin/backends/base.rb:61:in start' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/thin-1.2.8/lib/thin/server.rb:159:instart'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/rack-1.2.2/lib/rack/handler/thin.rb:14:in run' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/sinatra-1.2.1/lib/sinatra/base.rb:1208:inrun!'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/gems/gollum-1.3.0/bin/gollum:125:in <top (required)>' /Users/qichunren/.rvm/gems/ruby-1.9.2-p0/bin/gollum:19:inload'
/Users/qichunren/.rvm/gems/ruby-1.9.2-p0/bin/gollum:19:in `

'

.git/description missing on server

A newly cloned grit has a failing test out of the box because the server doesn't have the description file set. A work around is to copy test/dot_git/description to .git/description

I think just adding the description to the repo on github would solve the problem (might have to delete the repo and recreate from someone's local copy).

  1. Error:
    test_description(TestRepo):
    Errno::ENOENT: No such file or directory - /Users/brandon/Code/grit/.git/description

Getting GitTimeout when using commit_count on large repository

When doing some tests with Grit on my app i've got Grit::Errors::GitTimeout when using commit_count on a large repository (linux-2.6.38 in fact).

Running the command in shell just output a lot of hashes and no stale or stop. Is it a bug or how i can having it to not timeout ? It seems there is a Grit::Git.git_timeout but increasing the timeout if getting the error isn't really possible (and great...).

ruby-1.9.2-p180 :026 > z=Grit::Repo.new('/home/marc/src/linux-2.6.38.y')
 => #<Grit::Repo "/home/marc/src/linux-2.6.38.y/.git"> 
ruby-1.9.2-p180 :027 > z.commit_count('master')
D, [2011-05-02T15:20:35.169447 #20527] DEBUG -- : /usr/bin/git --git-dir=/home/marc/src/linux-2.6.38.y/.git --no-pager rev-list master
Grit::Errors::GitTimeout: Grit::Errors::GitTimeout
ruby-1.9.2-p180 :029 > Grit.version
 => "2.4.1"
% time /usr/bin/git --git-dir=/home/marc/src/linux-2.6.38.y/.git --no-pager rev-list master
/usr/bin/git --git-dir=/home/marc/src/linux-2.6.38.y/.git --no-pager rev-list  8,15s user 1,11s system 51% cpu 17,936 total

Warning about "spawn" method redefinition

How can I get rid of this warning?

/Users/microspino/.rvm/gems/ruby-1.9.2-p180/gems/grit-2.4.1/lib/grit/process.rb:289: warning: method redefined; discarding old spawn /Users/microspino/.rvm/gems/ruby-1.9.2-p180/gems/grit-2.4.1/lib/grit/process.rb:221: warning: previous definition of spawn was here

Environment:
OS X 10.6
ruby-1.9.2-p180
grit-2.4.1

Code:
#!/usr/bin/env ruby -wKU

require "grit"
repo = Grit::Repo.new("./project")

p repo.commits

Grit::Git#sh has problem with stdout.read on Passenger

Trying to use Grit on Passenger, and any command that uses Grit::Git#sh will return empty. One example is Grit::Repo#log, which will return an array of commits, except when using Passenger, which will return an empty array.

On Grit 2.0.0, I think the problem is on lib/grit/git.rb:250, where stdout.read(1024) always returns nil on Passenger, while other environments will return the Git output.

bug A log operation when there's trailing or leading white space on a file fails

The path is not quoted or escaped when the native command is called and so a filename with a leading or trailing space is never accessible by, for example git log. Quoting or escaping the path should solve such a problem:

repo.log('master', ' filename with evil leading and trailing space.txt ') should work, but doesn't.

win32 popen3

To support Windows, a very simple bit of code can be added:

if RUBY_PLATFORM =~ /mswin32/
  require "win32/open3"
end

I put it at the bottom of lib\open3_detach.rb, but really it can go anywhere, as long as it's imported after - it overwrites Open3.popen3.

Users will need to install the "win32-open3" gem, which is simple.

Tests pathed to creator's directory

Would recommend either using generic test data, relative paths or .gitignoring the test dir. Currently all examples point to creator's directories. Would just be nice to have these running out of the box.

More examples or more thorough README

This isn't a bug and it isn't really a feature, it's more of an enhancement request :) It would be great if the team could add some really detailed examples. Like:

Creating a bare repo
Adding a file and committing it
Adding a directory and files and commiting them
Checking the commit info
Removing a file with git rm and commit
Remote push/pull
Submodule example

Am I missing these examples or docs somewhere? If so, I apologize, just a newbie trying to learn....

fatal: corrupt tree file

Hi all,
Im trying to use gollum as a private wiki on my windows machine. When editing and saving an existing item git tells me that the tree file is corrupt. im assuming this is something in grit and not gollum.

fatal: corrupt tree file
this is verified on Windows only.
64,32bit, winxp, win2003, ruby187, ruby192, and jruby

git config --get-all not supported

Maybe I'm missing something obvious but it appears that Config.fetch does not support the ability to pull back an array of values like you would get with the --get-all option to git config and there is no other method that supports it.

Suggestion: add a fetch_all method that always returns an array (potentially empty if there are no matching keys)

init_bare ignores errors from git-init

init_bare appears to succeed, even when it doesn't.

Dir.mkdir("tst3.git")
=> 0
r = Grit::Repo.init_bare("tst3.git")
=> #<Grit::Repo "/home/candlerb/tmp/tst3.git">
Dir["tst3.git/*"]
=> []
Dir["tst3.git/.git"]
=> []

This is on an Ubuntu Hardy system with git-1.5.5.1, and I'm pretty sure it fails because git-init doesn't have the --bare option. But no error is raised.

$ git --version
git version 1.5.5.1
$ git-init --bare
usage: git-init [-q | --quiet] [--template=] [--shared]
$ echo $?
129

git.rev_list is incorrect for tags

Here is some sample output from a test repo, showing that git-rev-list will return the SHA of the 'real' commit for a tag, not the SHA of a tag node:

$ git rev-parse SJTag-1
e88867a8c8f085e42c092f8e9e8cc6d34ca6a898
$ git rev-list --max-count=1 SJTag-1
b6bc4884812c7489bcbb8f2750ef74f99d2441a7
$ git rev-parse master
f5f9894f71865f2141c6cebe0db878bc04d98198
$ git rev-list --max-count=1 master
f5f9894f71865f2141c6cebe0db878bc04d98198

Note that the SHAs are different for the tag, but not for master.

Now, if I do the same operation in a console using grit:

>> git
=> #<Grit::Git:0x102fe4e50 @work_tree="/src/TestGit", @git_dir="/src/TestGit/.git", @bytes_read=0>

>> git.rev_parse({},"SJTag-1")
=> "e88867a8c8f085e42c092f8e9e8cc6d34ca6a898"
>> git.rev_list({:max_count => 1},"SJTag-1")
=> "e88867a8c8f085e42c092f8e9e8cc6d34ca6a898"

>> git.rev_parse({},"master")
=> "f5f9894f71865f2141c6cebe0db878bc04d98198"
>> git.rev_list({:max_count => 1},"master")
=> "f5f9894f71865f2141c6cebe0db878bc04d98198"

git.rev_list appears to be wrong.

My use case for this is determining the commit represented by a ref which can be a SHA, SHA-ish, branch name, tag name, or 'master'. Tags are the tricky case as their own SHA is different from the desired commit.

Current workaround:

if @ref && @ref != 'master' && !(@ref =~ /\b[0-9a-f]{40}\b/i)
  real_commit_sha = repo.git.commit_from_sha(@commit.sha)
  unless real_commit_sha == @commit.sha
    @tag = @commit
    @commit = repo.commit(real_commit_sha)
  end
end

Tested with:
git version 1.7.3.2
git version 2.4.1 (didn't see anything related in recent commits..?)

NoSuchPathError when cloning remote repo via ssh. Cloning remote also seems a little difficult.

When I use the following with a github read-only repository URL it works fine:

root_tmp = './repos'
FileUtils.mkdir_p(root_tmp)
fillin_tmp = File.join(root_tmp, 'fill-in')
clone_tmp = File.join(root_tmp, 'hourz')
begin
  fillin_tmp_g = Grit::Git.new("#{fillin_tmp}")
  fillin_tmp_g.clone({:quiet => false, :verbose => true, :progress => true, :branch => '37s'}, "https://github.com/garysweaver/hourz", "#{clone_tmp}")
  g = Grit::Repo.new("#{clone_tmp}", {:is_bare => true})
rescue Exception => e
  puts "#{e.inspect}"
end

However, when the uri is an ssh uri to the git repository, it asks for the password (which I type in correctly), and I get:

#<Grit::NoSuchPathError: /path/to/project/repos/someproject>

I had this issue before and it was due to a malformed url (like using the http url from GitHub vs. the Git url). The remote repo url does not end in .git. What is the best way to clone a remote remote git repo via ssh url?

Is there an easier way to clone a repository that doesn't already exist locally (fresh clone)?

Thanks for Grit! It's awesome to be able to use git via Ruby.

Gary

Error when trying to get commits in the empty repo

g = Grit::Repo.new("D:\\test-git-repo")
p g.commits

If test-git-repo is an empty repo we get this error:
C:/Ruby192/lib/ruby/gems/1.9.1/gems/grit-2.4.1/lib/grit/process.rb:291:in spawn ': can't convert nil into String (TypeError) from C:/Ruby192/lib/ruby/gems/1.9.1/gems/grit-2.4.1/lib/grit/process.rb: 291:inspawn'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/grit-2.4.1/lib/grit/process.rb:
271:in popen4' from C:/Ruby192/lib/ruby/gems/1.9.1/gems/grit-2.4.1/lib/grit/process.rb: 97:inexec!'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/grit-2.4.1/lib/grit/process.rb:
68:in initialize' from C:/Ruby192/lib/ruby/gems/1.9.1/gems/grit-2.4.1/lib/grit/git.rb:301: innew'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/grit-2.4.1/lib/grit/git.rb:301:
in native' from C:/Ruby192/lib/ruby/gems/1.9.1/gems/grit-2.4.1/lib/grit/git.rb:325: inmethod_missing'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/grit-2.4.1/lib/grit/git-ruby.rb
:108:in rev_parse' from C:/Ruby192/lib/ruby/gems/1.9.1/gems/grit-2.4.1/lib/grit/git-ruby.rb :64:inrev_list'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/grit-2.4.1/lib/grit/commit.rb:1
21:in find_all' from C:/Ruby192/lib/ruby/gems/1.9.1/gems/grit-2.4.1/lib/grit/repo.rb:365 :incommits'
from D:/test.rb:4:in <main>'

Commit messages that begin with a new line cause an empty short_message

>> r.walker.commits('master').first.message
=> "\nDocumentation of \"BAD message\" and \"NO message\" via die()"
>> r.walker.commits('master').first.short_message
=> ""
>> sha = r.walker.commits('master').first.sha
=> "69c81affdea001d0f3f2489484467892f2ba80eb"
>> r.git.commit(sha).short_message
=> ""

git: 'command' is not a git command

After running a commit listing on a repository (linux 2.6.38 for my tests) i got this:

D, [2011-06-10T19:45:40.124701 #11551] DEBUG -- : 
D, [2011-06-10T19:50:57.074719 #11551] DEBUG -- : /usr/bin/git --git-dir=/home/marc/src/linux-2.6.38.y/.git command
D, [2011-06-10T19:50:57.156341 #11551] DEBUG -- : 
D, [2011-06-10T19:50:57.156704 #11551] DEBUG -- : git: 'command' is not a git command. See 'git --help'.

I've wrote a 'test' here: https://gist.github.com/1019440
And i use it with the linux 2.6.38 (linux-2.6.38.y) repository, any ideas about this problem ?

I'm using Grit 2.4.1 and ruby 1.9.2-p180.

Invalid tar file on windows

I use Redmine and its plugin gitrevision-download on Microsoft Windows.
tar files that the plugin generates have 2 problems that relate to Grit:

  1. Invalid tar file:
    Grit uses win32-open3 on windows and respect to the README of win32-open3 the default mode of output is 't' (i.e. text mode)
    This leads to invalid tar files. output mode should be set to 'b' . in order to this we should call Open3.popen3(command, 'b') in windows
  2. Extra ' prepended to file names:
    Also transform_options uses single quotations .e.g. --prefix='pre fix/' that leads to an extra ' prepended to file names e.g. 'pre fix/'my source.cs

I have forked and pushed a patch to Grit and Currently the issue is solved in my working copy

Tree#to_s to give sha1?

repo.commits[0]
=> #<Grit::Commit "f36d24ea4d820a9c109e35b22c8a77fed2060dcb">
repo.commits[0].to_s
=> "f36d24ea4d820a9c109e35b22c8a77fed2060dcb"
repo.commits[0].tree
=> #<Grit::Tree "020d33c4870e05e6ba96726da154c822d08750ed">
repo.commits[0].tree.to_s
=> "#Grit::Tree:0xb6fe8998"

For consistency and convenience, I suggest the last line could give the tree sha1 string instead.

Stack Level Too Deep in unpack_compressed

grit-2.4.1/lib/grit/git-ruby/internal/pack.rb:314: stack level too deep (SystemStackError)

the referenced line is
zstr = Zlib::Inflate.new

I can provide more details if you tell me what you need.
Judging by the comments in issue #41 this is not a duplicate.

unable to unpack files stored with pack.window 0

used
git --config pack.window 0
to get around an issue with git on win32.

now gitorious is failing with this error when I browse the file via the web interface:

Grit::GitRuby::Internal::PackFormatError (invalid type 5):
vendor/grit/lib/grit/git-ruby/internal/pack.rb:272:in unpack_object' vendor/grit/lib/grit/git-ruby/internal/pack.rb:299:inunpack_deltified'
vendor/grit/lib/grit/git-ruby/internal/pack.rb:267:in unpack_object' vendor/grit/lib/grit/git-ruby/internal/pack.rb:240:inblock in parse_object'
vendor/grit/lib/grit/git-ruby/internal/pack.rb:77:in with_packfile' vendor/grit/lib/grit/git-ruby/internal/pack.rb:239:inparse_object'
vendor/grit/lib/grit/git-ruby/internal/pack.rb:115:in []' vendor/grit/lib/grit/git-ruby/repository.rb:79:inblock in get_raw_object_by_sha1'
vendor/grit/lib/grit/git-ruby/repository.rb:78:in each' vendor/grit/lib/grit/git-ruby/repository.rb:78:inget_raw_object_by_sha1'
vendor/grit/lib/grit/git-ruby/repository.rb:187:in get_raw_tree' vendor/grit/lib/grit/git-ruby/repository.rb:212:inls_tree_path'
vendor/grit/lib/grit/git-ruby/repository.rb:178:in block in ls_tree' vendor/grit/lib/grit/git-ruby/repository.rb:177:ineach'
vendor/grit/lib/grit/git-ruby/repository.rb:177:in ls_tree' vendor/grit/lib/grit/git-ruby.rb:36:inls_tree'
vendor/grit/lib/grit/tree.rb:18:in construct' vendor/grit/lib/grit/repo.rb:234:intree'
app/controllers/trees_controller.rb:45:in show' vendor/rails/actionpack/lib/action_controller/base.rb:1331:inperform_action'
vendor/rails/actionpack/lib/action_controller/filters.rb:617:in call_filters' vendor/rails/actionpack/lib/action_controller/filters.rb:610:inperform_action_with_filters'
vendor/rails/actionpack/lib/action_controller/benchmarking.rb:68:in block in perform_action_with_benchmark' vendor/rails/activesupport/lib/active_support/core_ext/benchmark.rb:17:inblock in ms'
/opt/ruby192/lib/ruby/1.9.1/benchmark.rb:309:in realtime' vendor/rails/activesupport/lib/active_support/core_ext/benchmark.rb:17:inms'
vendor/rails/actionpack/lib/action_controller/benchmarking.rb:68:in perform_action_with_benchmark' vendor/rails/actionpack/lib/action_controller/rescue.rb:160:inperform_action_with_rescue'
vendor/rails/actionpack/lib/action_controller/flash.rb:146:in perform_action_with_flash' vendor/rails/actionpack/lib/action_controller/base.rb:532:inprocess'
vendor/rails/actionpack/lib/action_controller/filters.rb:606:in process_with_filters' vendor/rails/actionpack/lib/action_controller/base.rb:391:inprocess'
vendor/rails/actionpack/lib/action_controller/base.rb:386:in call' vendor/rails/actionpack/lib/action_controller/routing/route_set.rb:437:incall'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:87:in dispatch' vendor/rails/actionpack/lib/action_controller/dispatcher.rb:121:in_call'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:130:in block in build_middleware_stack' vendor/rails/activerecord/lib/active_record/query_cache.rb:29:incall'
vendor/rails/activerecord/lib/active_record/query_cache.rb:29:in block in call' vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:34:incache'
vendor/rails/activerecord/lib/active_record/query_cache.rb:9:in cache' vendor/rails/activerecord/lib/active_record/query_cache.rb:28:incall'
vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb:361:in call' vendor/rails/actionpack/lib/action_controller/string_coercion.rb:25:incall'
rack (1.0.1) lib/rack/head.rb:9:in call' rack (1.0.1) lib/rack/methodoverride.rb:24:incall'
vendor/rails/actionpack/lib/action_controller/params_parser.rb:15:in call' vendor/rails/railties/lib/rails/rack/metal.rb:47:incall'
vendor/rails/actionpack/lib/action_controller/session/cookie_store.rb:93:in call' vendor/rails/activesupport/lib/active_support/cache/strategy/local_cache.rb:24:incall'
vendor/rails/actionpack/lib/action_controller/failsafe.rb:26:in call' rack (1.0.1) lib/rack/lock.rb:11:inblock in call'
internal:prelude:10:in synchronize' rack (1.0.1) lib/rack/lock.rb:11:incall'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:106:in call' passenger (3.0.5) lib/phusion_passenger/rack/request_handler.rb:96:inprocess_request'
passenger (3.0.5) lib/phusion_passenger/abstract_request_handler.rb:513:in accept_and_process_next_request' passenger (3.0.5) lib/phusion_passenger/abstract_request_handler.rb:274:inmain_loop'
passenger (3.0.5) lib/phusion_passenger/classic_rails/application_spawner.rb:321:in start_request_handler' passenger (3.0.5) lib/phusion_passenger/classic_rails/application_spawner.rb:275:inblock in handle_spawn_application'
passenger (3.0.5) lib/phusion_passenger/utils.rb:479:in safe_fork' passenger (3.0.5) lib/phusion_passenger/classic_rails/application_spawner.rb:270:inhandle_spawn_application'
passenger (3.0.5) lib/phusion_passenger/abstract_server.rb:357:in server_main_loop' passenger (3.0.5) lib/phusion_passenger/abstract_server.rb:206:instart_synchronously'
passenger (3.0.5) lib/phusion_passenger/abstract_server.rb:180:in start' passenger (3.0.5) lib/phusion_passenger/classic_rails/application_spawner.rb:149:instart'
passenger (3.0.5) lib/phusion_passenger/spawn_manager.rb:219:in block (2 levels) in spawn_rails_application' passenger (3.0.5) lib/phusion_passenger/abstract_server_collection.rb:132:inlookup_or_add'
passenger (3.0.5) lib/phusion_passenger/spawn_manager.rb:214:in block in spawn_rails_application' passenger (3.0.5) lib/phusion_passenger/abstract_server_collection.rb:82:inblock in synchronize'
internal:prelude:10:in synchronize' passenger (3.0.5) lib/phusion_passenger/abstract_server_collection.rb:79:insynchronize'
passenger (3.0.5) lib/phusion_passenger/spawn_manager.rb:213:in spawn_rails_application' passenger (3.0.5) lib/phusion_passenger/spawn_manager.rb:132:inspawn_application'
passenger (3.0.5) lib/phusion_passenger/spawn_manager.rb:275:in handle_spawn_application' passenger (3.0.5) lib/phusion_passenger/abstract_server.rb:357:inserver_main_loop'
passenger (3.0.5) lib/phusion_passenger/abstract_server.rb:206:in start_synchronously' passenger (3.0.5) helper-scripts/passenger-spawn-server:99:in

'

r.head.commit is 'HEAD' in empty repo

With a non-empty repo:

r.head.commit
=> "f36d24ea4d820a9c109e35b22c8a77fed2060dcb"

But with an empty repo (no commits yet):

r = Grit::Repo.new(".")
=> #<Grit::Repo "/home/candlerb/tmp/tst2.git">
r.head.commit
=> "HEAD"

The upshot is if you use the following code for a commit, you end up with a corrupted repo:

i = r.index
=> #<Grit::Index:0xb70ae288 @current_tree=nil, @repo=#<Grit::Repo "/home/candlerb/tmp/tst2.git">, @tree={}>
i.add("foo","aaa")
=> "aaa"
i.commit("Message", [r.head.commit])
=> "115431315faec0c3427d02dc8694f7de1a38bdc6"

$ git log
error: bad parents in commit 115431315faec0c3427d02dc8694f7de1a38bdc6
fatal: bad object HEAD

Workaround:

parents = [r.head.commit]
parents = nil if parents == ['HEAD']
i.commit("Message", parents)

Perhaps r.head.commit would be better as nil if it doesn't exist? And perhaps commit should validate the parent commit IDs given to it?

head commit inconsistency

Even though repo.head and repo.heads.first are the same, the commit is different:

irb(main):001:0> require 'grit'
=> true
irb(main):002:0> repo = Grit::Repo.new(".")
=> #<Grit::Repo "S:/.git">
irb(main):003:0> repo.heads
=> [#<Grit::Head "master">, #<Grit::Head "ben">, #<Grit::Head "feature1">, #<Grit::Head "nokogiri">]
irb(main):004:0> repo.head
=> #<Grit::Head "master">
irb(main):005:0> repo.heads.first
=> #<Grit::Head "master">
irb(main):006:0> repo.head.commit
=> ""
irb(main):007:0> repo.heads.first.commit
=> #<Grit::Commit "743f50dad6e5646e4e1d978998b61d3a774ba64a">

how is it possible?

require 'grit'

=> true

c=Grit::Index.new("/tmp/dm-git-data/")

=> #<Grit::Index:0x000000034a2178 @repo="/tmp/dm-git-data/", @tree={}, @current_tree=nil>

c.read_tree("1c46299c7ec9bbf77bf42ec1f05f602524b93d45")

NoMethodError: undefined method `tree' for "/tmp/dm-git-data/":String
from /usr/lib/ruby/gems/1.9.1/gems/grit-2.3.0/lib/grit/index.rb:63:in `read_tree'
from (irb):5
from /usr/bin/irb:12:in `<main>'

Repo.commit deletes objects that don't exist on the FS

Example code:

idx = repo.index                                                            
idx.read_tree('master')
idx.add('db object 1', "Metadata 1")
idx.add('db object 2', "Metadata 2")
idx.commit('Added db-only objects')

puts "TREE CONTENTS AFTER INDEX-ADD:"
puts repo.tree.inspect
puts repo.git.ls_tree({}, 'master', [])
puts "."

name = 'fs_object'
File.open(name, 'w') { |f| f.puts 'User data'  }
repo.add(name)
repo.commit_index('Added fs object')

puts "TREE CONTENTS AFTER REPO-ADD:"
puts repo.tree.inspect
puts repo.git.ls_tree({}, 'master', [])
puts "."

This produces the following output:

TREE CONTENTS AFTER INDEX-ADD:

<Grit::Tree "master">

100644 blob 42c2824cd367d91de1fca29376857633241b8185 db object 1
100644 blob 5a741e1457a6f55702d9258231d317144108fddb db object 2
.
TREE CONTENTS AFTER REPO-ADD:

<Grit::Tree "master">

100644 blob 48de7d82a09381130aa193b9fb47dc7f67fd8676 fs_object
.

It seems as if 'git-update --remove' is getting called somewhere in grit, since the default behaviour for git (using the commands git-hash-object -w, git-update-index --add --cacheinfo, and git-add) is to ignore (not delete!) the objects in the database that are not on-disk.

In addition to all of this, there is the unexpected (but much less disturbing) behaviour of Repo#index. One would expect this to return the staging Index, or at least the same Index each time. This may be due to the fact that grit calls out to git-add for stuff like adding files instead of using its own index... but it makes the index appear to be an afterthought in grit.

UPDATE: I was mistaken about this working using the git command line tools; the second commit is what causes the stuff in the object database (and not the fs) to be removed. This happens whether I use grit or git.

Here is a shell script to test:

#!/bin/sh

echo Building test repo
rm -rf 'test'
mkdir 'test'
cd 'test'
git init .

echo Writing metadata

echo 'meta 1' | git hash-object -w --stdin
echo 'meta 2' | git hash-object -w --stdin
git update-index --add --cacheinfo 100644 41d1b9dbb485634b60349ac7fafdb2ebec03e85b db_obj_1
git update-index --add --cacheinfo 100644 afaf77a436aa213bd1031c2018329e7b9878bc86 db_obj_2
git write-tree
echo 'added metadata' | git commit-tree 9841ec9887bc2577aaad347d939312e8134f7a1b

echo writing FS data

echo 'data 1' > fs_object
git add fs_object

#git commit -m 'added fs object' .
git ls-files --cached --stage

1.9 Encoding Issue

I was trying to use the new Gollum project recently on 1.9 and ran into an encoding issue inside of Grit. Digging into it the fix was rather simple and I made a topic branch here.

Grit::GitRuby::Repository.rev_list can produce results in the wrong order (parent before child)

First of all, thanks! Grit is awesome!!

This is my first time playing with Grit or even poking around in git internals, so I apologize if I've gotten confused somewhere here, but it looks like the pure-ruby version of rev_list is assuming that chronological order is correct, but it may not be if two commits have the same timestamp.

With "git rev-list --date-order" (the default ordering anyway) "no parent comes before all of its children".

But GitRuby::Repository.rev_list simply orders by date which can result in a parent coming after it's child if they have the same timestamp.

At least that's my best guess as to what's happening. The original problem I was having was that repo.commits.first wasn't actually the most recent commit, and I think this is the cause.

I know this sounds like a far-out edge case, but I'm using Grit to commit programmatically and it happens in all of my test cases.

Here's an example output from the ruby version of rev_list:

commit f4c455ea040e7fc340b99a4b7dcb36b540531e5b
tree d6b0a59a8caceb37e71da988cc773b86bb30e1cf
author Foo Bar <[email protected]> 1287448438 -0700
committer Foo Bar <[email protected]> 1287448438 -0700

    Commit #2

commit ed9dc105ca608fc4fb05029920f78dc0851a014b
tree 0600b590f843fb6bcf3fc69541bf77c8b38db72b
parent f4c455ea040e7fc340b99a4b7dcb36b540531e5b
author Foo Bar <[email protected]> 1287448438 -0700
committer Foo Bar <[email protected]> 1287448438 -0700

    Commit #1

You can see that the second one is the parent of the first. "git rev-list --pretty=raw" outputs them in the opposite order.

If I comment out Grit::GitRuby.rev_list (and let method_missing take care of it), then I get the correct result.

If that all sounds right I'd be happy to try to fix it but I wanted to get a sanity check first.

Thanks.

Grit::Git#clone does not when passed option :quite => true

require 'grit'
require 'fileutils'

include Grit

FileUtils.mkdir_p('/tmp/test')
gritty = Grit::Git.new('/tmp/test')
gritty.clone({:quite => true, :branch => 'origin/master'}, "git://github.com/cookbooks/cc-aws.git", '/tmp/test')
Dir.entries('/tmp/test').size
# => 2

gritty.clone({:quite => false, :branch => 'origin/master'}, "git://github.com/cookbooks/cc-aws.git", '/tmp/test')
Dir.entries('/tmp/test').size
# => 10

Env details are:

$ gem list grit

*** LOCAL GEMS ***

grit (2.3.0)



$ rvm info

ruby-1.9.2-p0@test-chef:

system:
uname: "Linux desktop 2.6.32-26-generic #48-Ubuntu SMP Wed Nov 24 10:14:11 UTC 2010 x86_64 GNU/Linux"
bash: "/bin/bash => GNU bash, version 4.1.5(1)-release (x86_64-pc-linux-gnu)"
zsh: " => not installed"

rvm:
version: "rvm 1.0.16 by Wayne E. Seguin ([email protected]) [http://rvm.beginrescueend.com/]"

ruby:
interpreter: "ruby"
version: "1.9.2p0"
date: "2010-08-18"
platform: "x86_64-linux"
patchlevel: "2010-08-18 revision 29036"
full_version: "ruby 1.9.2p0 (2010-08-18 revision 29036) [x86_64-linux]"

homes:
gem: "/home/hedge/.rvm/gems/ruby-1.9.2-p0@test-chef"
ruby: "/home/hedge/.rvm/rubies/ruby-1.9.2-p0"

binaries:
ruby: "/home/hedge/.rvm/rubies/ruby-1.9.2-p0/bin/ruby"
irb: "/home/hedge/.rvm/rubies/ruby-1.9.2-p0/bin/irb"
gem: "/home/hedge/.rvm/rubies/ruby-1.9.2-p0/bin/gem"
rake: "/home/hedge/.rvm/gems/ruby-1.9.2-p0@global/bin/rake"

environment:
PATH: "/home/hedge/.rvm/gems/ruby-1.9.2-p0@test-chef/bin:/home/hedge/.rvm/gems/ruby-1.9.2-p0@global/bin:/home/hedge/.rvm/rubies/ruby-1.9.2-p0/bin:/home/hedge/.rvm/bin:/home/hedge/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games"
GEM_HOME: "/home/hedge/.rvm/gems/ruby-1.9.2-p0@test-chef"
GEM_PATH: "/home/hedge/.rvm/gems/ruby-1.9.2-p0@test-chef:/home/hedge/.rvm/gems/ruby-1.9.2-p0@global"
BUNDLE_PATH: "/home/hedge/.rvm/gems/ruby-1.9.2-p0@test-chef"
MY_RUBY_HOME: "/home/hedge/.rvm/rubies/ruby-1.9.2-p0"
IRBRC: "/home/hedge/.rvm/rubies/ruby-1.9.2-p0/.irbrc"
RUBYOPT: ""
gemset: "test-chef"

repo.log fails

The "log" methods of the Grit::Repo class fails. It calls the method "log" from the Grit:Git class which doesn't exist.

Close opened files

There's a few places where we're opening files but not closing them, relying on finalization or process exit to clean things up. In some cases, this is causes minute delays in unmounting filesystems. Here's a patch that makes sure files are closed immediately when no longer needed:

http://github.com/rtomayko/grit/compare/upstream...closefiles

I've already applied this to our vendor'd grit, btw.

test_tag.rb 's ordering of tags disagrees with git(1).

  1. Failure:
    test_list_from_string(TestTag)
    [./test/test_tag.rb:19:in test_list_from_string' /usr/lib64/ruby/gems/1.8/gems/mocha-0.9.8/lib/mocha/integration/test_unit/ruby_version_186_and_above.rb:19:insend'
    /usr/lib64/ruby/gems/1.8/gems/mocha-0.9.8/lib/mocha/integration/test_unit/ruby_version_186_and_above.rb:19:in `run']:
    <"not_annotated"> expected but was
    <"annotated">.

  2. Failure:
    test_list_from_string_for_annotated_tag(TestTag)
    [./test/test_tag.rb:37:in test_list_from_string_for_annotated_tag' /usr/lib64/ruby/gems/1.8/gems/mocha-0.9.8/lib/mocha/integration/test_unit/ruby_version_186_and_above.rb:19:insend'
    /usr/lib64/ruby/gems/1.8/gems/mocha-0.9.8/lib/mocha/integration/test_unit/ruby_version_186_and_above.rb:19:in `run']:
    <"annotated"> expected but was
    <"not_annotated">.

  3. Failure:
    test_reads_annotated_tag_contents(TestTag)
    [./test/test_tag.rb:93:in test_reads_annotated_tag_contents' /usr/lib64/ruby/gems/1.8/gems/mocha-0.9.8/lib/mocha/integration/test_unit/ruby_version_186_and_above.rb:19:insend'
    /usr/lib64/ruby/gems/1.8/gems/mocha-0.9.8/lib/mocha/integration/test_unit/ruby_version_186_and_above.rb:19:in `run']:
    <"annotated"> expected but was
    <"not_annotated">.

  4. Failure:
    test_reads_light_tag_contents(TestTag)
    [./test/test_tag.rb:81:in test_reads_light_tag_contents' /usr/lib64/ruby/gems/1.8/gems/mocha-0.9.8/lib/mocha/integration/test_unit/ruby_version_186_and_above.rb:19:insend'
    /usr/lib64/ruby/gems/1.8/gems/mocha-0.9.8/lib/mocha/integration/test_unit/ruby_version_186_and_above.rb:19:in `run']:
    <"not_annotated"> expected but was
    <"annotated">.

190 tests, 436 assertions, 4 failures, 0 errors

ohnobinki@ohnopublishing ~/grit2 $ git --git-dir=test/dot_git tag
annotated
not_annotated
packed
packed_annotated
v0.7.0

The test's codes suggests that there is some reason for git to always output 'not_annotated' before it outputs 'annotated'.

Git pull and reset

I cannot find how to do: git reset (hard) and git pull.
There are examples in API.txt, like Git#reset_hard, but this method doesn't exist.
Currently I am using gem git (where those methods are implemented),
Are they really missing in grit gem?

Make remote/HEAD resolve to a commit id

The remote/HEAD references currently do not resolve to a commit id because the HEAD file contains a ref rather than a sha:

% irb -r grit
>> puts Grit::Repo.new('.').remotes.map {|remote| "#{remote.name}: #{remote.commit.id}" }.join("\n")
origin/HEAD: ref:
origin/master: 0bd0c5ff037c7368b2b1827fadc66741d1ed14ed
=> nil
>> exit

% cat .git/refs/remotes/origin/HEAD 
ref: refs/remotes/origin/master

A patch is here: bahuvrihi@31bf65df77e6d9b3df75d9e314e2e9c57a48384d

Should throw errors

Trying to do things like

Grit::Repo.new("/path/to/nonbare/repo").git.commit({}, '-a', '-m', 'hello', '-author', 'fred')

fails silently. I had to fire up git to try and work out what the problem could be (in this case a mal-formed author parameter)

Get remote origin from repository

I need to be able to get the remote origin of the git repository that you can get at command-line via "git remote show origin". It'd be nice if Grit could provide this. Is there a way in current version to do it? (Didn't see a way in the docs.)

Invalid tar file on windows

I use Redmine and its plugin gitrevision-download on Microsoft Windows.
tar files that the plugin generates have 2 problems that relate to Grit:

  1. Invalid tar file:
    Grit uses win32-open3 on windows and respect to the README of win32-open3 the default mode of output is 't' (i.e. text mode)
    This leads to invalid tar files. output mode should be set to 'b' . in order to this we should call Open3.popen3(command, 'b') in windows
  2. Extra ' prepended to file names:
    Also transform_options uses single quotations .e.g. --prefix='pre fix/' that leads to an extra ' prepended to file names e.g. 'pre fix/'my source.cs

I have forked and pushed a patch to Grit and Currently the issue is solved in my working copy

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.