grit 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grit might be problematic. Click here for more details.

@@ -1,8 +1,38 @@
1
- == 1.0.1 / 2008-02-10
1
+ == 1.1.0 / 2009-03-29
2
+ * Backwards breaking changes
3
+ * Diff#a_commit -> Diff#a_blob, Diff#b_commit -> Diff#b_blob
4
+ * Major Enhancments
5
+ * Ruby 1.9 compatibility [github.com/chapados, github.com/js]
6
+ * Minor Enhancements
7
+ * Convert readme to markdown
8
+ * Added a shortcut for commit_stats as Commit#stats [github.com/js]
9
+ * Add a #basename method to Submodule, Blob and Tree for retrieving the name [github.com/js]
10
+ * Make Grit::Submodule grasp the concept of non-unix lineendings [github.com/js]
11
+ * Added Repo#commit_deltas_from [github.com/js]
12
+ * do some mild shell escaping when running commands [github.com/js]
13
+ * Added two shortcut methods to Tree, for picking trees/blobs only [github.com/Voker57]
14
+ * Added <=> method to Blob, needed for sorting tree [github.com/Voker57]
15
+ * Make the number of bytes to be read from git's stdout configurable [github.com/josb]
16
+ * Repo.archive_to_file accepts extra parameters making plain zipping possible [github.com/darwin]
17
+ * Handle commit stats that summarize commits with binary changes [github.com/therealadam]
18
+ * Add a DiffStat class for easy access to diff stats [github.com/therealadam]
19
+ * Don't split git logs that contain blank lines into two CommitStats [github.com/therealadam]
20
+ * Add DiffStat#net for total change count [github.com/therealadam]
21
+
22
+ == 1.0.3 / 2009-02-13
23
+ * Minor Enhancements
24
+ * Added Grit::Commit#to_patch for plaintext formatted patches.
25
+ * Fixed Grit::Tag to work with annotated tags.
26
+
27
+ == 1.0.2 / 2009-02-10
28
+ * Minor Enhancements
29
+ * Implement Grit.version to use VERSION.yml file
30
+
31
+ == 1.0.1 / 2009-02-10
2
32
  * Bug Fixes
3
33
  * Add diff-lcs as a dependency
4
34
 
5
- == 1.0.0 / 2008-01-27
35
+ == 1.0.0 / 2009-01-27
6
36
  * Tons of awesome in here. Also, we suck at updating the history.
7
37
  * Let's do better at that from now on.
8
38
 
@@ -0,0 +1,210 @@
1
+ Grit
2
+ ====
3
+
4
+ Grit gives you object oriented read/write access to Git repositories via Ruby.
5
+ The main goals are stability and performance. To this end, some of the
6
+ interactions with Git repositories are done by shelling out to the system's
7
+ `git` command, and other interactions are done with pure Ruby
8
+ reimplementations of core Git functionality. This choice, however, is
9
+ transparent to end users, and you need not know which method is being used.
10
+
11
+ This software was developed to power GitHub, and should be considered
12
+ production ready. An extensive test suite is provided to verify its correctness.
13
+
14
+ Grit is maintained by Tom Preston-Werner, Scott Chacon, Chris Wanstrath, and
15
+ PJ Hyett.
16
+
17
+ This documentation is accurate as of Grit 1.0.2.
18
+
19
+
20
+ ## Requirements #############################################################
21
+
22
+ * git (http://git-scm.com) tested with 1.6.0.2
23
+
24
+
25
+ ## Install ##################################################################
26
+
27
+ Easiest install is via RubyGems:
28
+
29
+ $ gem install grit
30
+
31
+ or
32
+
33
+ $ gem sources -a http://gems.github.com/ (you only need to do this once)
34
+ $ gem install mojombo-grit
35
+
36
+ The gem from GitHub will generally be available sooner than the gem from
37
+ Rubyforge. Both sources will eventually contain the same releases.
38
+
39
+
40
+ ## Source ###################################################################
41
+
42
+ Grit's Git repo is available on GitHub, which can be browsed at:
43
+
44
+ http://github.com/mojombo/grit
45
+
46
+ and cloned with:
47
+
48
+ git clone git://github.com/mojombo/grit.git
49
+
50
+
51
+ ## Usage ####################################################################
52
+
53
+ Grit gives you object model access to your Git repositories. Once you have
54
+ created a `Repo` object, you can traverse it to find parent commits,
55
+ trees, blobs, etc.
56
+
57
+ ### Initialize a Repo object
58
+
59
+ The first step is to create a `Grit::Repo` object to represent your repo. In
60
+ this documentation I include the `Grit` module to reduce typing.
61
+
62
+ require 'grit'
63
+ include Grit
64
+ repo = Repo.new("/Users/tom/dev/grit")
65
+
66
+ In the above example, the directory `/Users/tom/dev/grit` is my working
67
+ directory and contains the `.git` directory. You can also initialize Grit with
68
+ a bare repo.
69
+
70
+ repo = Repo.new("/var/git/grit.git")
71
+
72
+ ### Getting a list of commits
73
+
74
+ From the `Repo` object, you can get a list of commits as an array of `Commit`
75
+ objects.
76
+
77
+ repo.commits
78
+ # => [#<Grit::Commit "e80bbd2ce67651aa18e57fb0b43618ad4baf7750">,
79
+ #<Grit::Commit "91169e1f5fa4de2eaea3f176461f5dc784796769">,
80
+ #<Grit::Commit "038af8c329ef7c1bae4568b98bd5c58510465493">,
81
+ #<Grit::Commit "40d3057d09a7a4d61059bca9dca5ae698de58cbe">,
82
+ #<Grit::Commit "4ea50f4754937bf19461af58ce3b3d24c77311d9">]
83
+
84
+ Called without arguments, `Repo#commits` returns a list of up to ten commits
85
+ reachable by the **master** branch (starting at the latest commit). You can
86
+ ask for commits beginning at a different branch, commit, tag, etc.
87
+
88
+ repo.commits('mybranch')
89
+ repo.commits('40d3057d09a7a4d61059bca9dca5ae698de58cbe')
90
+ repo.commits('v0.1')
91
+
92
+ You can specify the maximum number of commits to return.
93
+
94
+ repo.commits('master', 100)
95
+
96
+ If you need paging, you can specify a number of commits to skip.
97
+
98
+ repo.commits('master', 10, 20)
99
+
100
+ The above will return commits 21-30 from the commit list.
101
+
102
+ ### The Commit object
103
+
104
+ `Commit` objects contain information about that commit.
105
+
106
+ head = repo.commits.first
107
+
108
+ head.id
109
+ # => "e80bbd2ce67651aa18e57fb0b43618ad4baf7750"
110
+
111
+ head.parents
112
+ # => [#<Grit::Commit "91169e1f5fa4de2eaea3f176461f5dc784796769">]
113
+
114
+ head.tree
115
+ # => #<Grit::Tree "3536eb9abac69c3e4db583ad38f3d30f8db4771f">
116
+
117
+ head.author
118
+ # => #<Grit::Actor "Tom Preston-Werner <tom@mojombo.com>">
119
+
120
+ head.authored_date
121
+ # => Wed Oct 24 22:02:31 -0700 2007
122
+
123
+ head.committer
124
+ # => #<Grit::Actor "Tom Preston-Werner <tom@mojombo.com>">
125
+
126
+ head.committed_date
127
+ # => Wed Oct 24 22:02:31 -0700 2007
128
+
129
+ head.message
130
+ # => "add Actor inspect"
131
+
132
+ You can traverse a commit's ancestry by chaining calls to `#parents`.
133
+
134
+ repo.commits.first.parents[0].parents[0].parents[0]
135
+
136
+ The above corresponds to **master^^^** or **master~3** in Git parlance.
137
+
138
+ ### The Tree object
139
+
140
+ A tree records pointers to the contents of a directory. Let's say you want
141
+ the root tree of the latest commit on the **master** branch.
142
+
143
+ tree = repo.commits.first.tree
144
+ # => #<Grit::Tree "3536eb9abac69c3e4db583ad38f3d30f8db4771f">
145
+
146
+ tree.id
147
+ # => "3536eb9abac69c3e4db583ad38f3d30f8db4771f"
148
+
149
+ Once you have a tree, you can get the contents.
150
+
151
+ contents = tree.contents
152
+ # => [#<Grit::Blob "4ebc8aea50e0a67e000ba29a30809d0a7b9b2666">,
153
+ #<Grit::Blob "81d2c27608b352814cbe979a6acd678d30219678">,
154
+ #<Grit::Tree "c3d07b0083f01a6e1ac969a0f32b8d06f20c62e5">,
155
+ #<Grit::Tree "4d00fe177a8407dbbc64a24dbfc564762c0922d8">]
156
+
157
+ This tree contains two `Blob` objects and two `Tree` objects. The trees are
158
+ subdirectories and the blobs are files. Trees below the root have additional
159
+ attributes.
160
+
161
+ contents.last.name
162
+ # => "lib"
163
+
164
+ contents.last.mode
165
+ # => "040000"
166
+
167
+ There is a convenience method that allows you to get a named sub-object
168
+ from a tree.
169
+
170
+ tree / "lib"
171
+ # => #<Grit::Tree "e74893a3d8a25cbb1367cf241cc741bfd503c4b2">
172
+
173
+ You can also get a tree directly from the repo if you know its name.
174
+
175
+ repo.tree
176
+ # => #<Grit::Tree "master">
177
+
178
+ repo.tree("91169e1f5fa4de2eaea3f176461f5dc784796769")
179
+ # => #<Grit::Tree "91169e1f5fa4de2eaea3f176461f5dc784796769">
180
+
181
+ ### The Blob object
182
+
183
+ A blob represents a file. Trees often contain blobs.
184
+
185
+ blob = tree.contents.first
186
+ # => #<Grit::Blob "4ebc8aea50e0a67e000ba29a30809d0a7b9b2666">
187
+
188
+ A blob has certain attributes.
189
+
190
+ blob.id
191
+ # => "4ebc8aea50e0a67e000ba29a30809d0a7b9b2666"
192
+
193
+ blob.name
194
+ # => "README.txt"
195
+
196
+ blob.mode
197
+ # => "100644"
198
+
199
+ blob.size
200
+ # => 7726
201
+
202
+ You can get the data of a blob as a string.
203
+
204
+ blob.data
205
+ # => "Grit is a library to ..."
206
+
207
+ You can also get a blob directly from the repo if you know its name.
208
+
209
+ repo.blob("4ebc8aea50e0a67e000ba29a30809d0a7b9b2666")
210
+ # => #<Grit::Blob "4ebc8aea50e0a67e000ba29a30809d0a7b9b2666">
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 1
3
- :minor: 0
4
- :patch: 1
3
+ :minor: 1
4
+ :patch: 0
@@ -17,14 +17,19 @@ end
17
17
 
18
18
  # third party
19
19
  require 'rubygems'
20
+ gem "mime-types", ">=0"
20
21
  require 'mime/types'
21
22
 
23
+ # ruby 1.9 compatibility
24
+ require 'grit/ruby1.9'
25
+
22
26
  # internal requires
23
27
  require 'grit/lazy'
24
28
  require 'grit/errors'
25
29
  require 'grit/git-ruby'
26
30
  require 'grit/git'
27
31
  require 'grit/ref'
32
+ require 'grit/tag'
28
33
  require 'grit/commit'
29
34
  require 'grit/commit_stats'
30
35
  require 'grit/tree'
@@ -41,7 +46,6 @@ require 'grit/merge'
41
46
 
42
47
 
43
48
  module Grit
44
-
45
49
  class << self
46
50
  # Set +debug+ to true to log all git calls and responses
47
51
  attr_accessor :debug
@@ -54,8 +58,11 @@ module Grit
54
58
  end
55
59
  self.debug = false
56
60
  self.use_git_ruby = true
57
-
61
+
58
62
  @logger ||= ::Logger.new(STDOUT)
59
-
60
- VERSION = '1.0.0'
63
+
64
+ def self.version
65
+ yml = YAML.load(File.read(File.join(File.dirname(__FILE__), *%w[.. VERSION.yml])))
66
+ "#{yml[:major]}.#{yml[:minor]}.#{yml[:patch]}"
67
+ end
61
68
  end
@@ -104,14 +104,23 @@ module Grit
104
104
  info = nil
105
105
  end
106
106
  end
107
-
107
+
108
108
  blames
109
109
  end
110
110
 
111
+ def basename
112
+ File.basename(name)
113
+ end
114
+
111
115
  # Pretty object inspection
112
116
  def inspect
113
117
  %Q{#<Grit::Blob "#{@id}">}
114
118
  end
119
+
120
+ # Compares blobs by name
121
+ def <=>(other)
122
+ name <=> other.name
123
+ end
115
124
  end # Blob
116
-
125
+
117
126
  end # Grit
@@ -1,5 +1,5 @@
1
1
  module Grit
2
-
2
+
3
3
  class Commit
4
4
  attr_reader :id
5
5
  lazy_reader :parents
@@ -11,7 +11,7 @@ module Grit
11
11
  lazy_reader :message
12
12
  lazy_reader :short_message
13
13
  lazy_reader :author_string
14
-
14
+
15
15
  # Instantiate a new Commit
16
16
  # +id+ is the id of the commit
17
17
  # +parents+ is an array of commit ids (will be converted into Commit instances)
@@ -35,11 +35,11 @@ module Grit
35
35
  @message = message.join("\n")
36
36
  @short_message = message[0] || ''
37
37
  end
38
-
38
+
39
39
  def id_abbrev
40
40
  @id_abbrev ||= @repo.git.rev_parse({}, self.id).chomp[0, 7]
41
41
  end
42
-
42
+
43
43
  # Create an unbaked Commit containing just the specified attributes
44
44
  # +repo+ is the Repo
45
45
  # +atts+ is a Hash of instance variable data
@@ -48,7 +48,7 @@ module Grit
48
48
  def self.create(repo, atts)
49
49
  self.allocate.create_initialize(repo, atts)
50
50
  end
51
-
51
+
52
52
  # Initializer for Commit.create
53
53
  # +repo+ is the Repo
54
54
  # +atts+ is a Hash of instance variable data
@@ -61,11 +61,11 @@ module Grit
61
61
  end
62
62
  self
63
63
  end
64
-
64
+
65
65
  def lazy_source
66
66
  self.class.find_all(@repo, @id, {:max_count => 1}).first
67
67
  end
68
-
68
+
69
69
  # Count the number of commits reachable from this ref
70
70
  # +repo+ is the Repo
71
71
  # +ref+ is the ref from which to begin (SHA1 or name)
@@ -74,7 +74,7 @@ module Grit
74
74
  def self.count(repo, ref)
75
75
  repo.git.rev_list({}, ref).size / 41
76
76
  end
77
-
77
+
78
78
  # Find all commits matching the given criteria.
79
79
  # +repo+ is the Repo
80
80
  # +ref+ is the ref from which to begin (SHA1 or name) or nil for --all
@@ -85,21 +85,21 @@ module Grit
85
85
  # Returns Grit::Commit[] (baked)
86
86
  def self.find_all(repo, ref, options = {})
87
87
  allowed_options = [:max_count, :skip, :since]
88
-
88
+
89
89
  default_options = {:pretty => "raw"}
90
90
  actual_options = default_options.merge(options)
91
-
91
+
92
92
  if ref
93
93
  output = repo.git.rev_list(actual_options, ref)
94
94
  else
95
95
  output = repo.git.rev_list(actual_options.merge(:all => true))
96
96
  end
97
-
97
+
98
98
  self.list_from_string(repo, output)
99
99
  rescue Grit::GitRuby::Repository::NoSuchShaFound
100
100
  []
101
101
  end
102
-
102
+
103
103
  # Parse out commit information into an array of baked Commit objects
104
104
  # +repo+ is the Repo
105
105
  # +text+ is the text output from the git command (raw format)
@@ -111,40 +111,40 @@ module Grit
111
111
  #
112
112
  def self.list_from_string(repo, text)
113
113
  lines = text.split("\n")
114
-
114
+
115
115
  commits = []
116
-
116
+
117
117
  while !lines.empty?
118
118
  id = lines.shift.split.last
119
119
  tree = lines.shift.split.last
120
-
120
+
121
121
  parents = []
122
122
  parents << lines.shift.split.last while lines.first =~ /^parent/
123
-
123
+
124
124
  author, authored_date = self.actor(lines.shift)
125
125
  committer, committed_date = self.actor(lines.shift)
126
-
126
+
127
127
  # not doing anything with this yet, but it's sometimes there
128
128
  encoding = lines.shift.split.last if lines.first =~ /^encoding/
129
-
129
+
130
130
  lines.shift
131
-
131
+
132
132
  message_lines = []
133
133
  message_lines << lines.shift[4..-1] while lines.first =~ /^ {4}/
134
-
134
+
135
135
  lines.shift while lines.first && lines.first.empty?
136
-
136
+
137
137
  commits << Commit.new(repo, id, parents, tree, author, authored_date, committer, committed_date, message_lines)
138
138
  end
139
-
139
+
140
140
  commits
141
141
  end
142
-
142
+
143
143
  # Show diffs between two trees:
144
144
  # +repo+ is the Repo
145
145
  # +a+ is a named commit
146
- # +b+ is an optional named commit. Passing an array assumes you
147
- # wish to omit the second named commit and limit the diff to the
146
+ # +b+ is an optional named commit. Passing an array assumes you
147
+ # wish to omit the second named commit and limit the diff to the
148
148
  # given paths.
149
149
  # +paths* is an array of paths to limit the diff.
150
150
  #
@@ -175,10 +175,14 @@ module Grit
175
175
  if parents.empty?
176
176
  show
177
177
  else
178
- self.class.diff(@repo, parents.first.id, @id)
178
+ self.class.diff(@repo, parents.first.id, @id)
179
179
  end
180
180
  end
181
181
 
182
+ def stats
183
+ stats = @repo.commit_stats(self.sha, 1)[0][-1]
184
+ end
185
+
182
186
  # Convert this Commit to a String which is just the SHA1 id
183
187
  def to_s
184
188
  @id
@@ -187,18 +191,22 @@ module Grit
187
191
  def sha
188
192
  @id
189
193
  end
190
-
194
+
191
195
  def date
192
196
  @committed_date
193
197
  end
194
-
198
+
199
+ def to_patch
200
+ @repo.git.format_patch({'1' => true, :stdout => true}, to_s)
201
+ end
202
+
195
203
  # Pretty object inspection
196
204
  def inspect
197
205
  %Q{#<Grit::Commit "#{@id}">}
198
206
  end
199
-
207
+
200
208
  # private
201
-
209
+
202
210
  # Parse out the actor (author or committer) info
203
211
  #
204
212
  # Returns [String (actor name and email), Time (acted at time)]
@@ -206,11 +214,11 @@ module Grit
206
214
  m, actor, epoch = *line.match(/^.+? (.*) (\d+) .*$/)
207
215
  [Actor.from_string(actor), Time.at(epoch.to_i)]
208
216
  end
209
-
217
+
210
218
  def author_string
211
219
  "%s <%s> %s %+05d" % [author.name, author.email, authored_date.to_i, 800]
212
220
  end
213
-
221
+
214
222
  def to_hash
215
223
  {
216
224
  'id' => id,
@@ -230,5 +238,5 @@ module Grit
230
238
  }
231
239
  end
232
240
  end # Commit
233
-
241
+
234
242
  end # Grit