ruby-git-lacravate 0.0.1

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.
data/lib/git/base.rb ADDED
@@ -0,0 +1,485 @@
1
+ module Git
2
+
3
+ class Base
4
+
5
+ # opens a bare Git Repository - no working directory options
6
+ def self.bare(git_dir, opts = {})
7
+ self.new({:repository => git_dir}.merge(opts))
8
+ end
9
+
10
+ # opens a new Git Project from a working directory
11
+ # you can specify non-standard git_dir and index file in the options
12
+ def self.open(working_dir, opts={})
13
+ self.new({:working_directory => working_dir}.merge(opts))
14
+ end
15
+
16
+ # initializes a git repository
17
+ #
18
+ # options:
19
+ # :repository
20
+ # :index_file
21
+ #
22
+ def self.init(working_dir, opts = {})
23
+ opts = {
24
+ :working_directory => working_dir,
25
+ :repository => File.join(working_dir, '.git')
26
+ }.merge(opts)
27
+
28
+ FileUtils.mkdir_p(opts[:working_directory]) if opts[:working_directory] && !File.directory?(opts[:working_directory])
29
+
30
+ # run git_init there
31
+ Git::Lib.new(opts).init
32
+
33
+ self.new(opts)
34
+ end
35
+
36
+ # clones a git repository locally
37
+ #
38
+ # repository - http://repo.or.cz/w/sinatra.git
39
+ # name - sinatra
40
+ #
41
+ # options:
42
+ # :repository
43
+ #
44
+ # :bare
45
+ # or
46
+ # :working_directory
47
+ # :index_file
48
+ #
49
+ def self.clone(repository, name, opts = {})
50
+ # run git-clone
51
+ self.new(Git::Lib.new.clone(repository, name, opts))
52
+ end
53
+
54
+ def initialize(options = {})
55
+ if working_dir = options[:working_directory]
56
+ options[:repository] ||= File.join(working_dir, '.git')
57
+ options[:index] ||= File.join(working_dir, '.git', 'index')
58
+ end
59
+ if options[:log]
60
+ @logger = options[:log]
61
+ @logger.info("Starting Git")
62
+ else
63
+ @logger = nil
64
+ end
65
+
66
+ @working_directory = options[:working_directory] ? Git::WorkingDirectory.new(options[:working_directory]) : nil
67
+ @repository = options[:repository] ? Git::Repository.new(options[:repository]) : nil
68
+ @index = options[:index] ? Git::Index.new(options[:index], false) : nil
69
+ end
70
+
71
+
72
+ # returns a reference to the working directory
73
+ # @git.dir.path
74
+ # @git.dir.writeable?
75
+ def dir
76
+ @working_directory
77
+ end
78
+
79
+ # returns reference to the git repository directory
80
+ # @git.dir.path
81
+ def repo
82
+ @repository
83
+ end
84
+
85
+ # returns reference to the git index file
86
+ def index
87
+ @index
88
+ end
89
+
90
+
91
+ def set_working(work_dir, check = true)
92
+ @lib = nil
93
+ @working_directory = Git::WorkingDirectory.new(work_dir.to_s, check)
94
+ end
95
+
96
+ def set_index(index_file, check = true)
97
+ @lib = nil
98
+ @index = Git::Index.new(index_file.to_s, check)
99
+ end
100
+
101
+ # changes current working directory for a block
102
+ # to the git working directory
103
+ #
104
+ # example
105
+ # @git.chdir do
106
+ # # write files
107
+ # @git.add
108
+ # @git.commit('message')
109
+ # end
110
+ def chdir # :yields: the Git::Path
111
+ Dir.chdir(dir.path) do
112
+ yield dir.path
113
+ end
114
+ end
115
+
116
+ # returns the repository size in bytes
117
+ def repo_size
118
+ size = 0
119
+ Dir.chdir(repo.path) do
120
+ (size, dot) = `du -s`.chomp.split
121
+ end
122
+ size.to_i
123
+ end
124
+
125
+ #g.config('user.name', 'Scott Chacon') # sets value
126
+ #g.config('user.email', 'email@email.com') # sets value
127
+ #g.config('user.name') # returns 'Scott Chacon'
128
+ #g.config # returns whole config hash
129
+ def config(name = nil, value = nil)
130
+ if(name && value)
131
+ # set value
132
+ lib.config_set(name, value)
133
+ elsif (name)
134
+ # return value
135
+ lib.config_get(name)
136
+ else
137
+ # return hash
138
+ lib.config_list
139
+ end
140
+ end
141
+
142
+ # factory methods
143
+
144
+ # returns a Git::Object of the appropriate type
145
+ # you can also call @git.gtree('tree'), but that's
146
+ # just for readability. If you call @git.gtree('HEAD') it will
147
+ # still return a Git::Object::Commit object.
148
+ #
149
+ # @git.object calls a factory method that will run a rev-parse
150
+ # on the objectish and determine the type of the object and return
151
+ # an appropriate object for that type
152
+ def object(objectish)
153
+ Git::Object.new(self, objectish)
154
+ end
155
+
156
+ def gtree(objectish)
157
+ Git::Object.new(self, objectish, 'tree')
158
+ end
159
+
160
+ def gcommit(objectish)
161
+ Git::Object.new(self, objectish, 'commit')
162
+ end
163
+
164
+ def gblob(objectish)
165
+ Git::Object.new(self, objectish, 'blob')
166
+ end
167
+
168
+ # returns a Git::Log object with count commits
169
+ def log(count = 30)
170
+ Git::Log.new(self, count)
171
+ end
172
+
173
+ # returns a Git::Status object
174
+ def status
175
+ Git::Status.new(self)
176
+ end
177
+
178
+ # returns a Git::Branches object of all the Git::Branch objects for this repo
179
+ def branches
180
+ Git::Branches.new(self)
181
+ end
182
+
183
+ # returns a Git::Branch object for branch_name
184
+ # -- addition of options noticeably to implement
185
+ # --t switch on 'git branch' command
186
+ def branch(branch_name = 'master', options={})
187
+ #
188
+ Git::Branch.new(self, branch_name, options[:track])
189
+ end
190
+
191
+ # returns +true+ if the branch exists locally
192
+ def is_local_branch?(branch)
193
+ branch_names = self.branches.local.map {|b| b.name}
194
+ branch_names.include?(branch)
195
+ end
196
+
197
+ # returns +true+ if the branch exists remotely
198
+ def is_remote_branch?(branch)
199
+ branch_names = self.branches.local.map {|b| b.name}
200
+ branch_names.include?(branch)
201
+ end
202
+
203
+ # returns +true+ if the branch exists
204
+ def is_branch?(branch)
205
+ branch_names = self.branches.map {|b| b.name}
206
+ branch_names.include?(branch)
207
+ end
208
+
209
+ # returns a Git::Remote object
210
+ def remote(remote_name = 'origin')
211
+ Git::Remote.new(self, remote_name)
212
+ end
213
+
214
+ # this is a convenience method for accessing the class that wraps all the
215
+ # actual 'git' forked system calls. At some point I hope to replace the Git::Lib
216
+ # class with one that uses native methods or libgit C bindings
217
+ def lib
218
+ @lib ||= Git::Lib.new(self, @logger)
219
+ end
220
+
221
+ # will run a grep for 'string' on the HEAD of the git repository
222
+ #
223
+ # to be more surgical in your grep, you can call grep() off a specific
224
+ # git object. for example:
225
+ #
226
+ # @git.object("v2.3").grep('TODO')
227
+ #
228
+ # in any case, it returns a hash of arrays of the type:
229
+ # hsh[tree-ish] = [[line_no, match], [line_no, match2]]
230
+ # hsh[tree-ish] = [[line_no, match], [line_no, match2]]
231
+ #
232
+ # so you might use it like this:
233
+ #
234
+ # @git.grep("TODO").each do |sha, arr|
235
+ # puts "in blob #{sha}:"
236
+ # arr.each do |match|
237
+ # puts "\t line #{match[0]}: '#{match[1]}'"
238
+ # end
239
+ # end
240
+ def grep(string, path_limiter = nil, opts = {})
241
+ self.object('HEAD').grep(string, path_limiter, opts)
242
+ end
243
+
244
+ # returns a Git::Diff object
245
+ def diff(objectish = 'HEAD', obj2 = nil)
246
+ Git::Diff.new(self, objectish, obj2)
247
+ end
248
+
249
+ # adds files from the working directory to the git repository
250
+ def add(path = '.')
251
+ self.lib.add(path)
252
+ end
253
+
254
+ # removes file(s) from the git repository
255
+ def remove(path = '.', opts = {})
256
+ self.lib.remove(path, opts)
257
+ end
258
+
259
+ # resets the working directory to the provided commitish
260
+ def reset(commitish = nil, opts = {})
261
+ self.lib.reset(commitish, opts)
262
+ end
263
+
264
+ # resets the working directory to the commitish with '--hard'
265
+ def reset_hard(commitish = nil, opts = {})
266
+ opts = {:hard => true}.merge(opts)
267
+ self.lib.reset(commitish, opts)
268
+ end
269
+
270
+ # commits all pending changes in the index file to the git repository
271
+ #
272
+ # options:
273
+ # :add_all
274
+ # :allow_empty
275
+ # :author
276
+ def commit(message, opts = {})
277
+ self.lib.commit(message, opts)
278
+ end
279
+
280
+ # commits all pending changes in the index file to the git repository,
281
+ # but automatically adds all modified files without having to explicitly
282
+ # calling @git.add() on them.
283
+ def commit_all(message, opts = {})
284
+ opts = {:add_all => true}.merge(opts)
285
+ self.lib.commit(message, opts)
286
+ end
287
+
288
+ # checks out a branch as the new git working directory
289
+ def checkout(branch = 'master', opts = {})
290
+ self.lib.checkout(branch, opts)
291
+ end
292
+
293
+ # checks out an old version of a file
294
+ def checkout_file(version, file)
295
+ self.lib.checkout_file(version,file)
296
+ end
297
+
298
+ # fetches changes from a remote branch - this does not modify the working directory,
299
+ # it just gets the changes from the remote if there are any
300
+ def fetch(remote = 'origin')
301
+ self.lib.fetch(remote)
302
+ end
303
+
304
+ # pushes changes to a remote repository - easiest if this is a cloned repository,
305
+ # otherwise you may have to run something like this first to setup the push parameters:
306
+ #
307
+ # @git.config('remote.remote-name.push', 'refs/heads/master:refs/heads/master')
308
+ #
309
+ def push(remote = 'origin', branch = 'master', tags = false)
310
+ self.lib.push(remote, branch, tags)
311
+ end
312
+
313
+ # merges one or more branches into the current working branch
314
+ #
315
+ # you can specify more than one branch to merge by passing an array of branches
316
+ def merge(branch, message = 'merge')
317
+ self.lib.merge(branch, message)
318
+ end
319
+
320
+ # iterates over the files which are unmerged
321
+ def each_conflict(&block) # :yields: file, your_version, their_version
322
+ self.lib.conflicts(&block)
323
+ end
324
+
325
+ # fetches a branch from a remote and merges it into the current working branch
326
+ def pull(remote = 'origin', branch = 'master', message = 'origin pull')
327
+ fetch(remote)
328
+ merge(branch, message)
329
+ end
330
+
331
+ # returns an array of Git:Remote objects
332
+ def remotes
333
+ self.lib.remotes.map { |r| Git::Remote.new(self, r) }
334
+ end
335
+
336
+ # adds a new remote to this repository
337
+ # url can be a git url or a Git::Base object if it's a local reference
338
+ #
339
+ # @git.add_remote('scotts_git', 'git://repo.or.cz/rubygit.git')
340
+ # @git.fetch('scotts_git')
341
+ # @git.merge('scotts_git/master')
342
+ #
343
+ def add_remote(name, url, opts = {})
344
+ url = url.repo.path if url.is_a?(Git::Base)
345
+ self.lib.remote_add(name, url, opts)
346
+ Git::Remote.new(self, name)
347
+ end
348
+
349
+ # returns an array of all Git::Tag objects for this repository
350
+ def tags
351
+ self.lib.tags.map { |r| tag(r) }
352
+ end
353
+
354
+ # returns a Git::Tag object
355
+ def tag(tag_name)
356
+ Git::Object.new(self, tag_name, 'tag', true)
357
+ end
358
+
359
+ # creates a new git tag (Git::Tag)
360
+ def add_tag(tag_name)
361
+ self.lib.tag(tag_name)
362
+ tag(tag_name)
363
+ end
364
+
365
+ # creates an archive file of the given tree-ish
366
+ def archive(treeish, file = nil, opts = {})
367
+ self.object(treeish).archive(file, opts)
368
+ end
369
+
370
+ # repacks the repository
371
+ def repack
372
+ self.lib.repack
373
+ end
374
+
375
+ def gc
376
+ self.lib.gc
377
+ end
378
+
379
+ def apply(file)
380
+ if File.exists?(file)
381
+ self.lib.apply(file)
382
+ end
383
+ end
384
+
385
+ def apply_mail(file)
386
+ self.lib.apply_mail(file) if File.exists?(file)
387
+ end
388
+
389
+ ## LOWER LEVEL INDEX OPERATIONS ##
390
+
391
+ def with_index(new_index) # :yields: new_index
392
+ old_index = @index
393
+ set_index(new_index, false)
394
+ return_value = yield @index
395
+ set_index(old_index)
396
+ return_value
397
+ end
398
+
399
+ def with_temp_index &blk
400
+ tempfile = Tempfile.new('temp-index')
401
+ temp_path = tempfile.path
402
+ tempfile.unlink
403
+ with_index(temp_path, &blk)
404
+ end
405
+
406
+ def checkout_index(opts = {})
407
+ self.lib.checkout_index(opts)
408
+ end
409
+
410
+ def read_tree(treeish, opts = {})
411
+ self.lib.read_tree(treeish, opts)
412
+ end
413
+
414
+ def write_tree
415
+ self.lib.write_tree
416
+ end
417
+
418
+ def commit_tree(tree = nil, opts = {})
419
+ Git::Object::Commit.new(self, self.lib.commit_tree(tree, opts))
420
+ end
421
+
422
+ def write_and_commit_tree(opts = {})
423
+ tree = write_tree
424
+ commit_tree(tree, opts)
425
+ end
426
+
427
+ def update_ref(branch, commit)
428
+ branch(branch).update_ref(commit)
429
+ end
430
+
431
+
432
+ def ls_files(location=nil)
433
+ self.lib.ls_files(location)
434
+ end
435
+
436
+ def with_working(work_dir) # :yields: the Git::WorkingDirectory
437
+ return_value = false
438
+ old_working = @working_directory
439
+ set_working(work_dir)
440
+ Dir.chdir work_dir do
441
+ return_value = yield @working_directory
442
+ end
443
+ set_working(old_working)
444
+ return_value
445
+ end
446
+
447
+ def with_temp_working &blk
448
+ tempfile = Tempfile.new("temp-workdir")
449
+ temp_dir = tempfile.path
450
+ tempfile.unlink
451
+ Dir.mkdir(temp_dir, 0700)
452
+ with_working(temp_dir, &blk)
453
+ end
454
+
455
+
456
+ # runs git rev-parse to convert the objectish to a full sha
457
+ #
458
+ # @git.revparse("HEAD^^")
459
+ # @git.revparse('v2.4^{tree}')
460
+ # @git.revparse('v2.4:/doc/index.html')
461
+ #
462
+ def revparse(objectish)
463
+ self.lib.revparse(objectish)
464
+ end
465
+
466
+ # -- addition of options noticeably to implement
467
+ # a recursive ls_tree
468
+ def ls_tree(objectish, options={})
469
+ #
470
+ self.lib.ls_tree(objectish, options)
471
+ end
472
+
473
+ def cat_file(objectish)
474
+ self.lib.object_contents(objectish)
475
+ end
476
+
477
+ # returns the name of the branch the working directory is currently on
478
+ def current_branch
479
+ self.lib.branch_current
480
+ end
481
+
482
+
483
+ end
484
+
485
+ end
data/lib/git/branch.rb ADDED
@@ -0,0 +1,111 @@
1
+ module Git
2
+ class Branch < Path
3
+
4
+ attr_accessor :full, :remote, :name
5
+
6
+ # -- addition of track parameter for --t switch
7
+ def initialize(base, name, track=nil)
8
+ #
9
+ @remote = nil
10
+ @full = name
11
+ @base = base
12
+ @gcommit = nil
13
+ @stashes = nil
14
+
15
+ # -- addition of track attribute to implement
16
+ # --t switch
17
+ @track = track
18
+ name, remote = name.split(' ').first.split('/').reverse
19
+ if remote
20
+ @remote = Git::Remote.new(@base, remote)
21
+ name = "#{remote}/#{name}"
22
+ end
23
+ @name = name
24
+ #
25
+ end
26
+
27
+ def gcommit
28
+ @gcommit ||= @base.gcommit(@full)
29
+ @gcommit
30
+ end
31
+
32
+ def stashes
33
+ @stashes ||= Git::Stashes.new(@base)
34
+ end
35
+
36
+ def checkout
37
+ check_if_create
38
+ @base.checkout(@full)
39
+ end
40
+
41
+ def archive(file, opts = {})
42
+ @base.lib.archive(@full, file, opts)
43
+ end
44
+
45
+ # g.branch('new_branch').in_branch do
46
+ # # create new file
47
+ # # do other stuff
48
+ # return true # auto commits and switches back
49
+ # end
50
+ def in_branch (message = 'in branch work')
51
+ old_current = @base.lib.branch_current
52
+ checkout
53
+ if yield
54
+ @base.commit_all(message)
55
+ else
56
+ @base.reset_hard
57
+ end
58
+ @base.checkout(old_current)
59
+ end
60
+
61
+ def create
62
+ check_if_create
63
+ end
64
+
65
+ def delete
66
+ @base.lib.branch_delete(@name)
67
+ end
68
+
69
+ def current
70
+ determine_current
71
+ end
72
+
73
+ def merge(branch = nil, message = nil)
74
+ if branch
75
+ in_branch do
76
+ @base.merge(branch, message)
77
+ false
78
+ end
79
+ # merge a branch into this one
80
+ else
81
+ # merge this branch into the current one
82
+ @base.merge(@name)
83
+ end
84
+ end
85
+
86
+ def update_ref(commit)
87
+ @base.lib.update_ref(@full, commit)
88
+ end
89
+
90
+ def to_a
91
+ [@full]
92
+ end
93
+
94
+ def to_s
95
+ @full
96
+ end
97
+
98
+ private
99
+
100
+ def check_if_create
101
+ # -- addition of track attribute
102
+ @base.lib.branch_new(@name, @track) rescue nil
103
+ #
104
+ end
105
+
106
+ def determine_current
107
+ @base.lib.branch_current == @name
108
+ end
109
+
110
+ end
111
+ end
@@ -0,0 +1,48 @@
1
+ module Git
2
+
3
+ # object that holds all the available branches
4
+ class Branches
5
+ include Enumerable
6
+
7
+ def initialize(base)
8
+ @branches = {}
9
+
10
+ @base = base
11
+
12
+ @base.lib.branches_all.each do |b|
13
+ @branches[b[0]] = Git::Branch.new(@base, b[0])
14
+ end
15
+ end
16
+
17
+ def local
18
+ self.select { |b| !b.remote }
19
+ end
20
+
21
+ def remote
22
+ self.select { |b| b.remote }
23
+ end
24
+
25
+ # array like methods
26
+
27
+ def size
28
+ @branches.size
29
+ end
30
+
31
+ def each(&block)
32
+ @branches.values.each(&block)
33
+ end
34
+
35
+ def [](symbol)
36
+ @branches[symbol.to_s]
37
+ end
38
+
39
+ def to_s
40
+ out = ''
41
+ @branches.each do |k, b|
42
+ out << (b.current ? '* ' : ' ') << b.to_s << "\n"
43
+ end
44
+ out
45
+ end
46
+
47
+ end
48
+ end