git-ce 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +94 -0
- data/CONTRIBUTING.md +135 -0
- data/LICENSE +21 -0
- data/MAINTAINERS.md +8 -0
- data/README.md +313 -0
- data/lib/git/author.rb +14 -0
- data/lib/git/base/factory.rb +75 -0
- data/lib/git/base.rb +555 -0
- data/lib/git/branch.rb +131 -0
- data/lib/git/branches.rb +71 -0
- data/lib/git/config.rb +22 -0
- data/lib/git/diff.rb +159 -0
- data/lib/git/index.rb +5 -0
- data/lib/git/lib.rb +1046 -0
- data/lib/git/log.rb +128 -0
- data/lib/git/object.rb +312 -0
- data/lib/git/path.rb +31 -0
- data/lib/git/remote.rb +36 -0
- data/lib/git/repository.rb +6 -0
- data/lib/git/stash.rb +27 -0
- data/lib/git/stashes.rb +55 -0
- data/lib/git/status.rb +199 -0
- data/lib/git/version.rb +5 -0
- data/lib/git/working_directory.rb +4 -0
- data/lib/git.rb +166 -0
- metadata +120 -0
data/lib/git/log.rb
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
module Git
|
2
|
+
|
3
|
+
# object that holds the last X commits on given branch
|
4
|
+
class Log
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
def initialize(base, count = 30)
|
8
|
+
dirty_log
|
9
|
+
@base = base
|
10
|
+
@count = count
|
11
|
+
|
12
|
+
@commits = nil
|
13
|
+
@author = nil
|
14
|
+
@grep = nil
|
15
|
+
@object = nil
|
16
|
+
@path = nil
|
17
|
+
@since = nil
|
18
|
+
@skip = nil
|
19
|
+
@until = nil
|
20
|
+
@between = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def object(objectish)
|
24
|
+
dirty_log
|
25
|
+
@object = objectish
|
26
|
+
return self
|
27
|
+
end
|
28
|
+
|
29
|
+
def author(regex)
|
30
|
+
dirty_log
|
31
|
+
@author = regex
|
32
|
+
return self
|
33
|
+
end
|
34
|
+
|
35
|
+
def grep(regex)
|
36
|
+
dirty_log
|
37
|
+
@grep = regex
|
38
|
+
return self
|
39
|
+
end
|
40
|
+
|
41
|
+
def path(path)
|
42
|
+
dirty_log
|
43
|
+
@path = path
|
44
|
+
return self
|
45
|
+
end
|
46
|
+
|
47
|
+
def skip(num)
|
48
|
+
dirty_log
|
49
|
+
@skip = num
|
50
|
+
return self
|
51
|
+
end
|
52
|
+
|
53
|
+
def since(date)
|
54
|
+
dirty_log
|
55
|
+
@since = date
|
56
|
+
return self
|
57
|
+
end
|
58
|
+
|
59
|
+
def until(date)
|
60
|
+
dirty_log
|
61
|
+
@until = date
|
62
|
+
return self
|
63
|
+
end
|
64
|
+
|
65
|
+
def between(sha1, sha2 = nil)
|
66
|
+
dirty_log
|
67
|
+
@between = [sha1, sha2]
|
68
|
+
return self
|
69
|
+
end
|
70
|
+
|
71
|
+
def to_s
|
72
|
+
self.map { |c| c.to_s }.join("\n")
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
# forces git log to run
|
77
|
+
|
78
|
+
def size
|
79
|
+
check_log
|
80
|
+
@commits.size rescue nil
|
81
|
+
end
|
82
|
+
|
83
|
+
def each(&block)
|
84
|
+
check_log
|
85
|
+
@commits.each(&block)
|
86
|
+
end
|
87
|
+
|
88
|
+
def first
|
89
|
+
check_log
|
90
|
+
@commits.first rescue nil
|
91
|
+
end
|
92
|
+
|
93
|
+
def last
|
94
|
+
check_log
|
95
|
+
@commits.last rescue nil
|
96
|
+
end
|
97
|
+
|
98
|
+
def [](index)
|
99
|
+
check_log
|
100
|
+
@commits[index] rescue nil
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
def dirty_log
|
107
|
+
@dirty_flag = true
|
108
|
+
end
|
109
|
+
|
110
|
+
def check_log
|
111
|
+
if @dirty_flag
|
112
|
+
run_log
|
113
|
+
@dirty_flag = false
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# actually run the 'git log' command
|
118
|
+
def run_log
|
119
|
+
log = @base.lib.full_log_commits(:count => @count, :object => @object,
|
120
|
+
:path_limiter => @path, :since => @since,
|
121
|
+
:author => @author, :grep => @grep, :skip => @skip,
|
122
|
+
:until => @until, :between => @between)
|
123
|
+
@commits = log.map { |c| Git::Object::Commit.new(@base, c['sha'], c) }
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
data/lib/git/object.rb
ADDED
@@ -0,0 +1,312 @@
|
|
1
|
+
module Git
|
2
|
+
|
3
|
+
class GitTagNameDoesNotExist< StandardError
|
4
|
+
end
|
5
|
+
|
6
|
+
# represents a git object
|
7
|
+
class Object
|
8
|
+
|
9
|
+
class AbstractObject
|
10
|
+
attr_accessor :objectish, :type, :mode
|
11
|
+
|
12
|
+
attr_writer :size
|
13
|
+
|
14
|
+
def initialize(base, objectish)
|
15
|
+
@base = base
|
16
|
+
@objectish = objectish.to_s
|
17
|
+
@contents = nil
|
18
|
+
@trees = nil
|
19
|
+
@size = nil
|
20
|
+
@sha = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def sha
|
24
|
+
@sha ||= @base.lib.revparse(@objectish)
|
25
|
+
end
|
26
|
+
|
27
|
+
def size
|
28
|
+
@size ||= @base.lib.object_size(@objectish)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Get the object's contents.
|
32
|
+
# If no block is given, the contents are cached in memory and returned as a string.
|
33
|
+
# If a block is given, it yields an IO object (via IO::popen) which could be used to
|
34
|
+
# read a large file in chunks.
|
35
|
+
#
|
36
|
+
# Use this for large files so that they are not held in memory.
|
37
|
+
def contents(&block)
|
38
|
+
if block_given?
|
39
|
+
@base.lib.object_contents(@objectish, &block)
|
40
|
+
else
|
41
|
+
@contents ||= @base.lib.object_contents(@objectish)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def contents_array
|
46
|
+
self.contents.split("\n")
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_s
|
50
|
+
@objectish
|
51
|
+
end
|
52
|
+
|
53
|
+
def grep(string, path_limiter = nil, opts = {})
|
54
|
+
opts = {:object => sha, :path_limiter => path_limiter}.merge(opts)
|
55
|
+
@base.lib.grep(string, opts)
|
56
|
+
end
|
57
|
+
|
58
|
+
def diff(objectish)
|
59
|
+
Git::Diff.new(@base, @objectish, objectish)
|
60
|
+
end
|
61
|
+
|
62
|
+
def log(count = 30)
|
63
|
+
Git::Log.new(@base, count).object(@objectish)
|
64
|
+
end
|
65
|
+
|
66
|
+
# creates an archive of this object (tree)
|
67
|
+
def archive(file = nil, opts = {})
|
68
|
+
@base.lib.archive(@objectish, file, opts)
|
69
|
+
end
|
70
|
+
|
71
|
+
def tree?; false; end
|
72
|
+
|
73
|
+
def blob?; false; end
|
74
|
+
|
75
|
+
def commit?; false; end
|
76
|
+
|
77
|
+
def tag?; false; end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
class Blob < AbstractObject
|
83
|
+
|
84
|
+
def initialize(base, sha, mode = nil)
|
85
|
+
super(base, sha)
|
86
|
+
@mode = mode
|
87
|
+
end
|
88
|
+
|
89
|
+
def blob?
|
90
|
+
true
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
class Tree < AbstractObject
|
96
|
+
|
97
|
+
def initialize(base, sha, mode = nil)
|
98
|
+
super(base, sha)
|
99
|
+
@mode = mode
|
100
|
+
@trees = nil
|
101
|
+
@blobs = nil
|
102
|
+
end
|
103
|
+
|
104
|
+
def children
|
105
|
+
blobs.merge(subtrees)
|
106
|
+
end
|
107
|
+
|
108
|
+
def blobs
|
109
|
+
@blobs ||= check_tree[:blobs]
|
110
|
+
end
|
111
|
+
alias_method :files, :blobs
|
112
|
+
|
113
|
+
def trees
|
114
|
+
@trees ||= check_tree[:trees]
|
115
|
+
end
|
116
|
+
alias_method :subtrees, :trees
|
117
|
+
alias_method :subdirectories, :trees
|
118
|
+
|
119
|
+
def full_tree
|
120
|
+
@base.lib.full_tree(@objectish)
|
121
|
+
end
|
122
|
+
|
123
|
+
def depth
|
124
|
+
@base.lib.tree_depth(@objectish)
|
125
|
+
end
|
126
|
+
|
127
|
+
def tree?
|
128
|
+
true
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
|
133
|
+
# actually run the git command
|
134
|
+
def check_tree
|
135
|
+
@trees = {}
|
136
|
+
@blobs = {}
|
137
|
+
|
138
|
+
data = @base.lib.ls_tree(@objectish)
|
139
|
+
|
140
|
+
data['tree'].each do |key, tree|
|
141
|
+
@trees[key] = Git::Object::Tree.new(@base, tree[:sha], tree[:mode])
|
142
|
+
end
|
143
|
+
|
144
|
+
data['blob'].each do |key, blob|
|
145
|
+
@blobs[key] = Git::Object::Blob.new(@base, blob[:sha], blob[:mode])
|
146
|
+
end
|
147
|
+
|
148
|
+
{
|
149
|
+
:trees => @trees,
|
150
|
+
:blobs => @blobs
|
151
|
+
}
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
class Commit < AbstractObject
|
157
|
+
|
158
|
+
def initialize(base, sha, init = nil)
|
159
|
+
super(base, sha)
|
160
|
+
@tree = nil
|
161
|
+
@parents = nil
|
162
|
+
@author = nil
|
163
|
+
@committer = nil
|
164
|
+
@message = nil
|
165
|
+
if init
|
166
|
+
set_commit(init)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def message
|
171
|
+
check_commit
|
172
|
+
@message
|
173
|
+
end
|
174
|
+
|
175
|
+
def name
|
176
|
+
@base.lib.namerev(sha)
|
177
|
+
end
|
178
|
+
|
179
|
+
def gtree
|
180
|
+
check_commit
|
181
|
+
Tree.new(@base, @tree)
|
182
|
+
end
|
183
|
+
|
184
|
+
def parent
|
185
|
+
parents.first
|
186
|
+
end
|
187
|
+
|
188
|
+
# array of all parent commits
|
189
|
+
def parents
|
190
|
+
check_commit
|
191
|
+
@parents
|
192
|
+
end
|
193
|
+
|
194
|
+
# git author
|
195
|
+
def author
|
196
|
+
check_commit
|
197
|
+
@author
|
198
|
+
end
|
199
|
+
|
200
|
+
def author_date
|
201
|
+
author.date
|
202
|
+
end
|
203
|
+
|
204
|
+
# git author
|
205
|
+
def committer
|
206
|
+
check_commit
|
207
|
+
@committer
|
208
|
+
end
|
209
|
+
|
210
|
+
def committer_date
|
211
|
+
committer.date
|
212
|
+
end
|
213
|
+
alias_method :date, :committer_date
|
214
|
+
|
215
|
+
def diff_parent
|
216
|
+
diff(parent)
|
217
|
+
end
|
218
|
+
|
219
|
+
def set_commit(data)
|
220
|
+
@sha ||= data['sha']
|
221
|
+
@committer = Git::Author.new(data['committer'])
|
222
|
+
@author = Git::Author.new(data['author'])
|
223
|
+
@tree = Git::Object::Tree.new(@base, data['tree'])
|
224
|
+
@parents = data['parent'].map{ |sha| Git::Object::Commit.new(@base, sha) }
|
225
|
+
@message = data['message'].chomp
|
226
|
+
end
|
227
|
+
|
228
|
+
def commit?
|
229
|
+
true
|
230
|
+
end
|
231
|
+
|
232
|
+
private
|
233
|
+
|
234
|
+
# see if this object has been initialized and do so if not
|
235
|
+
def check_commit
|
236
|
+
return if @tree
|
237
|
+
|
238
|
+
data = @base.lib.commit_data(@objectish)
|
239
|
+
set_commit(data)
|
240
|
+
end
|
241
|
+
|
242
|
+
end
|
243
|
+
|
244
|
+
class Tag < AbstractObject
|
245
|
+
attr_accessor :name
|
246
|
+
|
247
|
+
def initialize(base, sha, name)
|
248
|
+
super(base, sha)
|
249
|
+
@name = name
|
250
|
+
@annotated = nil
|
251
|
+
@loaded = false
|
252
|
+
end
|
253
|
+
|
254
|
+
def annotated?
|
255
|
+
@annotated ||= (@base.lib.object_type(self.name) == 'tag')
|
256
|
+
end
|
257
|
+
|
258
|
+
def message
|
259
|
+
check_tag()
|
260
|
+
return @message
|
261
|
+
end
|
262
|
+
|
263
|
+
def tag?
|
264
|
+
true
|
265
|
+
end
|
266
|
+
|
267
|
+
def tagger
|
268
|
+
check_tag()
|
269
|
+
return @tagger
|
270
|
+
end
|
271
|
+
|
272
|
+
private
|
273
|
+
|
274
|
+
def check_tag
|
275
|
+
return if @loaded
|
276
|
+
|
277
|
+
if !self.annotated?
|
278
|
+
@message = @tagger = nil
|
279
|
+
else
|
280
|
+
tdata = @base.lib.tag_data(@name)
|
281
|
+
@message = tdata['message'].chomp
|
282
|
+
@tagger = Git::Author.new(tdata['tagger'])
|
283
|
+
end
|
284
|
+
|
285
|
+
@loaded = true
|
286
|
+
end
|
287
|
+
|
288
|
+
end
|
289
|
+
|
290
|
+
# if we're calling this, we don't know what type it is yet
|
291
|
+
# so this is our little factory method
|
292
|
+
def self.new(base, objectish, type = nil, is_tag = false)
|
293
|
+
if is_tag
|
294
|
+
sha = base.lib.tag_sha(objectish)
|
295
|
+
if sha == ''
|
296
|
+
raise Git::GitTagNameDoesNotExist.new(objectish)
|
297
|
+
end
|
298
|
+
return Git::Object::Tag.new(base, sha, objectish)
|
299
|
+
end
|
300
|
+
|
301
|
+
type ||= base.lib.object_type(objectish)
|
302
|
+
klass =
|
303
|
+
case type
|
304
|
+
when /blob/ then Blob
|
305
|
+
when /commit/ then Commit
|
306
|
+
when /tree/ then Tree
|
307
|
+
end
|
308
|
+
klass.new(base, objectish)
|
309
|
+
end
|
310
|
+
|
311
|
+
end
|
312
|
+
end
|
data/lib/git/path.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
module Git
|
2
|
+
|
3
|
+
class Path
|
4
|
+
|
5
|
+
attr_accessor :path
|
6
|
+
|
7
|
+
def initialize(path, check_path=true)
|
8
|
+
path = File.expand_path(path)
|
9
|
+
|
10
|
+
if check_path && !File.exist?(path)
|
11
|
+
raise ArgumentError, 'path does not exist', [path]
|
12
|
+
end
|
13
|
+
|
14
|
+
@path = path
|
15
|
+
end
|
16
|
+
|
17
|
+
def readable?
|
18
|
+
File.readable?(@path)
|
19
|
+
end
|
20
|
+
|
21
|
+
def writable?
|
22
|
+
File.writable?(@path)
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_s
|
26
|
+
@path
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
data/lib/git/remote.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
module Git
|
2
|
+
class Remote < Path
|
3
|
+
|
4
|
+
attr_accessor :name, :url, :fetch_opts
|
5
|
+
|
6
|
+
def initialize(base, name)
|
7
|
+
@base = base
|
8
|
+
config = @base.lib.config_remote(name)
|
9
|
+
@name = name
|
10
|
+
@url = config['url']
|
11
|
+
@fetch_opts = config['fetch']
|
12
|
+
end
|
13
|
+
|
14
|
+
def fetch(opts={})
|
15
|
+
@base.fetch(@name, opts)
|
16
|
+
end
|
17
|
+
|
18
|
+
# merge this remote locally
|
19
|
+
def merge(branch = 'master')
|
20
|
+
@base.merge("#{@name}/#{branch}")
|
21
|
+
end
|
22
|
+
|
23
|
+
def branch(branch = 'master')
|
24
|
+
Git::Branch.new(@base, "#{@name}/#{branch}")
|
25
|
+
end
|
26
|
+
|
27
|
+
def remove
|
28
|
+
@base.lib.remote_remove(@name)
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
@name
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
data/lib/git/stash.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
module Git
|
2
|
+
class Stash
|
3
|
+
|
4
|
+
def initialize(base, message, existing=false)
|
5
|
+
@base = base
|
6
|
+
@message = message
|
7
|
+
save unless existing
|
8
|
+
end
|
9
|
+
|
10
|
+
def save
|
11
|
+
@saved = @base.lib.stash_save(@message)
|
12
|
+
end
|
13
|
+
|
14
|
+
def saved?
|
15
|
+
@saved
|
16
|
+
end
|
17
|
+
|
18
|
+
def message
|
19
|
+
@message
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
message
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
data/lib/git/stashes.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
module Git
|
2
|
+
|
3
|
+
# object that holds all the available stashes
|
4
|
+
class Stashes
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
def initialize(base)
|
8
|
+
@stashes = []
|
9
|
+
|
10
|
+
@base = base
|
11
|
+
|
12
|
+
@base.lib.stashes_all.each do |id, message|
|
13
|
+
@stashes.unshift(Git::Stash.new(@base, message, true))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
# Returns an multi-dimensional Array of elements that have been stash saved.
|
19
|
+
# Array is based on position and name. See Example
|
20
|
+
#
|
21
|
+
# @example Returns Array of items that have been stashed
|
22
|
+
# .all - [0, "testing-stash-all"]]
|
23
|
+
# @return [Array]
|
24
|
+
def all
|
25
|
+
@base.lib.stashes_all
|
26
|
+
end
|
27
|
+
|
28
|
+
def save(message)
|
29
|
+
s = Git::Stash.new(@base, message)
|
30
|
+
@stashes.unshift(s) if s.saved?
|
31
|
+
end
|
32
|
+
|
33
|
+
def apply(index=nil)
|
34
|
+
@base.lib.stash_apply(index)
|
35
|
+
end
|
36
|
+
|
37
|
+
def clear
|
38
|
+
@base.lib.stash_clear
|
39
|
+
@stashes = []
|
40
|
+
end
|
41
|
+
|
42
|
+
def size
|
43
|
+
@stashes.size
|
44
|
+
end
|
45
|
+
|
46
|
+
def each(&block)
|
47
|
+
@stashes.each(&block)
|
48
|
+
end
|
49
|
+
|
50
|
+
def [](index)
|
51
|
+
@stashes[index.to_i]
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|