schacon-git 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/lib/git/log.rb ADDED
@@ -0,0 +1,94 @@
1
+ module Git
2
+
3
+ # object that holds the last X commits on given branch
4
+ class Log
5
+ include Enumerable
6
+
7
+ @base = nil
8
+ @commits = nil
9
+
10
+ @object = nil
11
+ @path = nil
12
+ @count = nil
13
+ @since = nil
14
+ @between = nil
15
+
16
+ @dirty_flag = nil
17
+
18
+ def initialize(base, count = 30)
19
+ dirty_log
20
+ @base = base
21
+ @count = count
22
+ end
23
+
24
+ def object(objectish)
25
+ dirty_log
26
+ @object = objectish
27
+ return self
28
+ end
29
+
30
+ def path(path)
31
+ dirty_log
32
+ @path = path
33
+ return self
34
+ end
35
+
36
+ def since(date)
37
+ dirty_log
38
+ @since = date
39
+ return self
40
+ end
41
+
42
+ def between(sha1, sha2 = nil)
43
+ dirty_log
44
+ @between = [sha1, sha2]
45
+ return self
46
+ end
47
+
48
+ def to_s
49
+ self.map { |c| c.to_s }.join("\n")
50
+ end
51
+
52
+
53
+ # forces git log to run
54
+
55
+ def size
56
+ check_log
57
+ @commits.size rescue nil
58
+ end
59
+
60
+ def each
61
+ check_log
62
+ @commits.each do |c|
63
+ yield c
64
+ end
65
+ end
66
+
67
+ def first
68
+ check_log
69
+ @commits.first rescue nil
70
+ end
71
+
72
+ private
73
+
74
+ def dirty_log
75
+ @dirty_flag = true
76
+ end
77
+
78
+ def check_log
79
+ if @dirty_flag
80
+ run_log
81
+ @dirty_flag = false
82
+ end
83
+ end
84
+
85
+ # actually run the 'git log' command
86
+ def run_log
87
+ log = @base.lib.full_log_commits(:count => @count, :object => @object,
88
+ :path_limiter => @path, :since => @since, :between => @between)
89
+ @commits = log.map { |c| Git::Object::Commit.new(@base, c['sha'], c) }
90
+ end
91
+
92
+ end
93
+
94
+ end
data/lib/git/object.rb ADDED
@@ -0,0 +1,296 @@
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, :size, :type, :mode
11
+
12
+ @base = nil
13
+ @contents = nil
14
+ @size = nil
15
+ @sha = nil
16
+
17
+ def initialize(base, objectish)
18
+ @base = base
19
+ @objectish = objectish.to_s
20
+ setup
21
+ end
22
+
23
+ def sha
24
+ @sha || @sha = @base.lib.revparse(@objectish)
25
+ end
26
+
27
+ def size
28
+ @size || @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. use this for large files so that they are not held
35
+ # in memory
36
+ def contents(&block)
37
+ if block_given?
38
+ @base.lib.object_contents(@objectish, &block)
39
+ else
40
+ @contents || @contents = @base.lib.object_contents(@objectish)
41
+ end
42
+ end
43
+
44
+ def contents_array
45
+ self.contents.split("\n")
46
+ end
47
+
48
+ def setup
49
+ raise NotImplementedError
50
+ end
51
+
52
+ def to_s
53
+ @objectish
54
+ end
55
+
56
+ def grep(string, path_limiter = nil, opts = {})
57
+ default = {:object => sha, :path_limiter => path_limiter}
58
+ grep_options = default.merge(opts)
59
+ @base.lib.grep(string, grep_options)
60
+ end
61
+
62
+ def diff(objectish)
63
+ Git::Diff.new(@base, @objectish, objectish)
64
+ end
65
+
66
+ def log(count = 30)
67
+ Git::Log.new(@base, count).object(@objectish)
68
+ end
69
+
70
+ # creates an archive of this object (tree)
71
+ def archive(file = nil, opts = {})
72
+ @base.lib.archive(@objectish, file, opts)
73
+ end
74
+
75
+ def tree?
76
+ @type == 'tree'
77
+ end
78
+
79
+ def blob?
80
+ @type == 'blob'
81
+ end
82
+
83
+ def commit?
84
+ @type == 'commit'
85
+ end
86
+
87
+ def tag?
88
+ @type == 'tag'
89
+ end
90
+
91
+ end
92
+
93
+
94
+ class Blob < AbstractObject
95
+
96
+ def initialize(base, sha, mode = nil)
97
+ super(base, sha)
98
+ @mode = mode
99
+ end
100
+
101
+ private
102
+
103
+ def setup
104
+ @type = 'blob'
105
+ end
106
+ end
107
+
108
+ class Tree < AbstractObject
109
+
110
+ @trees = nil
111
+ @blobs = nil
112
+
113
+ def initialize(base, sha, mode = nil)
114
+ super(base, sha)
115
+ @mode = mode
116
+ end
117
+
118
+ def children
119
+ blobs.merge(subtrees)
120
+ end
121
+
122
+ def blobs
123
+ check_tree
124
+ @blobs
125
+ end
126
+ alias_method :files, :blobs
127
+
128
+ def trees
129
+ check_tree
130
+ @trees
131
+ end
132
+ alias_method :subtrees, :trees
133
+ alias_method :subdirectories, :trees
134
+
135
+ def full_tree
136
+ @base.lib.full_tree(@objectish)
137
+ end
138
+
139
+ def depth
140
+ @base.lib.tree_depth(@objectish)
141
+ end
142
+
143
+ private
144
+
145
+ def setup
146
+ @type = 'tree'
147
+ end
148
+
149
+ # actually run the git command
150
+ def check_tree
151
+ if !@trees
152
+ @trees = {}
153
+ @blobs = {}
154
+ data = @base.lib.ls_tree(@objectish)
155
+ data['tree'].each { |k, d| @trees[k] = Git::Object::Tree.new(@base, d[:sha], d[:mode]) }
156
+ data['blob'].each { |k, d| @blobs[k] = Git::Object::Blob.new(@base, d[:sha], d[:mode]) }
157
+ end
158
+ end
159
+
160
+ end
161
+
162
+ class Commit < AbstractObject
163
+
164
+ @tree = nil
165
+ @parents = nil
166
+ @author = nil
167
+ @committer = nil
168
+ @message = nil
169
+
170
+ def initialize(base, sha, init = nil)
171
+ super(base, sha)
172
+ if init
173
+ set_commit(init)
174
+ end
175
+ end
176
+
177
+ def message
178
+ check_commit
179
+ @message
180
+ end
181
+
182
+ def name
183
+ @base.lib.namerev(sha)
184
+ end
185
+
186
+ def gtree
187
+ check_commit
188
+ Tree.new(@base, @tree)
189
+ end
190
+
191
+ def parent
192
+ parents.first
193
+ end
194
+
195
+ # array of all parent commits
196
+ def parents
197
+ check_commit
198
+ @parents
199
+ end
200
+
201
+ # git author
202
+ def author
203
+ check_commit
204
+ @author
205
+ end
206
+
207
+ def author_date
208
+ author.date
209
+ end
210
+
211
+ # git author
212
+ def committer
213
+ check_commit
214
+ @committer
215
+ end
216
+
217
+ def committer_date
218
+ committer.date
219
+ end
220
+ alias_method :date, :committer_date
221
+
222
+ def diff_parent
223
+ diff(parent)
224
+ end
225
+
226
+ def set_commit(data)
227
+ if data['sha']
228
+ @sha = data['sha']
229
+ end
230
+ @committer = Git::Author.new(data['committer'])
231
+ @author = Git::Author.new(data['author'])
232
+ @tree = Git::Object::Tree.new(@base, data['tree'])
233
+ @parents = data['parent'].map{ |sha| Git::Object::Commit.new(@base, sha) }
234
+ @message = data['message'].chomp
235
+ end
236
+
237
+ private
238
+
239
+ def setup
240
+ @type = 'commit'
241
+ end
242
+
243
+ # see if this object has been initialized and do so if not
244
+ def check_commit
245
+ if !@tree
246
+ data = @base.lib.commit_data(@objectish)
247
+ set_commit(data)
248
+ end
249
+ end
250
+
251
+ end
252
+
253
+ class Tag < AbstractObject
254
+ attr_accessor :name
255
+
256
+ def initialize(base, sha, name)
257
+ super(base, sha)
258
+ @name = name
259
+ end
260
+
261
+ private
262
+
263
+ def setup
264
+ @type = 'tag'
265
+ end
266
+
267
+ end
268
+
269
+ class << self
270
+ # if we're calling this, we don't know what type it is yet
271
+ # so this is our little factory method
272
+ def new(base, objectish, type = nil, is_tag = false)
273
+ if is_tag
274
+ sha = base.lib.tag_sha(objectish)
275
+ if sha == ''
276
+ raise Git::GitTagNameDoesNotExist.new(objectish)
277
+ end
278
+ return Git::Object::Tag.new(base, sha, objectish)
279
+ else
280
+ if !type
281
+ type = base.lib.object_type(objectish)
282
+ end
283
+ end
284
+
285
+ klass =
286
+ case type
287
+ when /blob/: Blob
288
+ when /commit/: Commit
289
+ when /tree/: Tree
290
+ end
291
+ klass::new(base, objectish)
292
+ end
293
+ end
294
+
295
+ end
296
+ end
data/lib/git/path.rb ADDED
@@ -0,0 +1,27 @@
1
+ module Git
2
+ class Path
3
+
4
+ attr_accessor :path
5
+
6
+ def initialize(path, check_path = true)
7
+ if !check_path || File.exists?(path)
8
+ @path = File.expand_path(path)
9
+ else
10
+ raise ArgumentError, "path does not exist", File.expand_path(path)
11
+ end
12
+ end
13
+
14
+ def readable?
15
+ File.readable?(@path)
16
+ end
17
+
18
+ def writable?
19
+ File.writable?(@path)
20
+ end
21
+
22
+ def to_s
23
+ @path
24
+ end
25
+
26
+ end
27
+ end
data/lib/git/remote.rb ADDED
@@ -0,0 +1,42 @@
1
+ module Git
2
+ class Remote < Path
3
+
4
+ attr_accessor :name, :url, :fetch_opts
5
+
6
+ @base = nil
7
+
8
+ def initialize(base, name)
9
+ @base = base
10
+ config = @base.lib.config_remote(name)
11
+ @name = name
12
+ @url = config['url']
13
+ @fetch_opts = config['fetch']
14
+ end
15
+
16
+ def remove
17
+ @base.remote_remove(@name)
18
+ end
19
+
20
+ def fetch
21
+ @base.fetch(@name)
22
+ end
23
+
24
+ # merge this remote locally
25
+ def merge(branch = 'master')
26
+ @base.merge("#{@name}/#{branch}")
27
+ end
28
+
29
+ def branch(branch = 'master')
30
+ Git::Branch.new(@base, "#{@name}/#{branch}")
31
+ end
32
+
33
+ def remove
34
+ @base.lib.remote_remove(@name)
35
+ end
36
+
37
+ def to_s
38
+ @name
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,4 @@
1
+ module Git
2
+ class Repository < Path
3
+ end
4
+ end
data/lib/git/stash.rb ADDED
@@ -0,0 +1,26 @@
1
+ module Git
2
+ class Stash
3
+ def initialize(base, message, existing=false)
4
+ @base = base
5
+ @message = message
6
+ save if existing == false
7
+ end
8
+
9
+ def save
10
+ @saved = @base.lib.stash_save(@message)
11
+ end
12
+
13
+ def saved?
14
+ @saved
15
+ end
16
+
17
+ def message
18
+ @message
19
+ end
20
+
21
+ def to_s
22
+ message
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,49 @@
1
+ module Git
2
+
3
+ # object that holds all the available stashes
4
+ class Stashes
5
+ include Enumerable
6
+
7
+ @base = nil
8
+ @stashes = nil
9
+
10
+ def initialize(base)
11
+ @stashes = []
12
+
13
+ @base = base
14
+
15
+ @base.lib.stashes_all.each do |id, message|
16
+ @stashes.unshift(Git::Stash.new(@base, message, true))
17
+ end
18
+ end
19
+
20
+ def save(message)
21
+ s = Git::Stash.new(@base, message)
22
+ @stashes.unshift(s) if s.saved?
23
+ end
24
+
25
+ def apply(index=0)
26
+ @base.lib.stash_apply(index.to_i)
27
+ end
28
+
29
+ def clear
30
+ @base.lib.stash_clear
31
+ @stashes = []
32
+ end
33
+
34
+ def size
35
+ @stashes.size
36
+ end
37
+
38
+ def each
39
+ @stashes.each do |s|
40
+ yield s
41
+ end
42
+ end
43
+
44
+ def [](index)
45
+ @stashes[index.to_i]
46
+ end
47
+
48
+ end
49
+ end
data/lib/git/status.rb ADDED
@@ -0,0 +1,118 @@
1
+ module Git
2
+
3
+ class Status
4
+ include Enumerable
5
+
6
+ @base = nil
7
+ @files = nil
8
+
9
+ def initialize(base)
10
+ @base = base
11
+ construct_status
12
+ end
13
+
14
+ def changed
15
+ @files.select { |k, f| f.type == 'M' }
16
+ end
17
+
18
+ def added
19
+ @files.select { |k, f| f.type == 'A' }
20
+ end
21
+
22
+ def deleted
23
+ @files.select { |k, f| f.type == 'D' }
24
+ end
25
+
26
+ def untracked
27
+ @files.select { |k, f| f.untracked }
28
+ end
29
+
30
+ def pretty
31
+ out = ''
32
+ self.each do |file|
33
+ out << file.path
34
+ out << "\n\tsha(r) " + file.sha_repo.to_s + ' ' + file.mode_repo.to_s
35
+ out << "\n\tsha(i) " + file.sha_index.to_s + ' ' + file.mode_index.to_s
36
+ out << "\n\ttype " + file.type.to_s
37
+ out << "\n\tstage " + file.stage.to_s
38
+ out << "\n\tuntrac " + file.untracked.to_s
39
+ out << "\n"
40
+ end
41
+ out << "\n"
42
+ out
43
+ end
44
+
45
+ # enumerable method
46
+
47
+ def [](file)
48
+ @files[file]
49
+ end
50
+
51
+ def each
52
+ @files.each do |k, file|
53
+ yield file
54
+ end
55
+ end
56
+
57
+ class StatusFile
58
+ attr_accessor :path, :type, :stage, :untracked
59
+ attr_accessor :mode_index, :mode_repo
60
+ attr_accessor :sha_index, :sha_repo
61
+
62
+ @base = nil
63
+
64
+ def initialize(base, hash)
65
+ @base = base
66
+ @path = hash[:path]
67
+ @type = hash[:type]
68
+ @stage = hash[:stage]
69
+ @mode_index = hash[:mode_index]
70
+ @mode_repo = hash[:mode_repo]
71
+ @sha_index = hash[:sha_index]
72
+ @sha_repo = hash[:sha_repo]
73
+ @untracked = hash[:untracked]
74
+ end
75
+
76
+ def blob(type = :index)
77
+ if type == :repo
78
+ @base.object(@sha_repo)
79
+ else
80
+ @base.object(@sha_index) rescue @base.object(@sha_repo)
81
+ end
82
+ end
83
+
84
+
85
+ end
86
+
87
+ private
88
+
89
+ def construct_status
90
+ @files = @base.lib.ls_files
91
+
92
+ # find untracked in working dir
93
+ Dir.chdir(@base.dir.path) do
94
+ Dir.glob('**/*') do |file|
95
+ if !@files[file]
96
+ @files[file] = {:path => file, :untracked => true} if !File.directory?(file)
97
+ end
98
+ end
99
+ end
100
+
101
+ # find modified in tree
102
+ @base.lib.diff_files.each do |path, data|
103
+ @files[path] ? @files[path].merge!(data) : @files[path] = data
104
+ end
105
+
106
+ # find added but not committed - new files
107
+ @base.lib.diff_index('HEAD').each do |path, data|
108
+ @files[path] ? @files[path].merge!(data) : @files[path] = data
109
+ end
110
+
111
+ @files.each do |k, file_hash|
112
+ @files[k] = StatusFile.new(@base, file_hash)
113
+ end
114
+ end
115
+
116
+ end
117
+
118
+ end
@@ -0,0 +1,4 @@
1
+ module Git
2
+ class WorkingDirectory < Git::Path
3
+ end
4
+ end