cho45-grit 0.8.2

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.
Files changed (56) hide show
  1. data/History.txt +6 -0
  2. data/Manifest.txt +56 -0
  3. data/README.txt +213 -0
  4. data/Rakefile +29 -0
  5. data/grit.gemspec +25 -0
  6. data/lib/grit/actor.rb +36 -0
  7. data/lib/grit/blob.rb +117 -0
  8. data/lib/grit/commit.rb +208 -0
  9. data/lib/grit/config.rb +44 -0
  10. data/lib/grit/diff.rb +70 -0
  11. data/lib/grit/errors.rb +7 -0
  12. data/lib/grit/git.rb +124 -0
  13. data/lib/grit/lazy.rb +31 -0
  14. data/lib/grit/ref.rb +110 -0
  15. data/lib/grit/repo.rb +318 -0
  16. data/lib/grit/tree.rb +99 -0
  17. data/lib/grit.rb +46 -0
  18. data/test/fixtures/blame +131 -0
  19. data/test/fixtures/cat_file_blob +1 -0
  20. data/test/fixtures/cat_file_blob_size +1 -0
  21. data/test/fixtures/diff_2 +54 -0
  22. data/test/fixtures/diff_2f +19 -0
  23. data/test/fixtures/diff_f +15 -0
  24. data/test/fixtures/diff_i +201 -0
  25. data/test/fixtures/diff_mode_only +1152 -0
  26. data/test/fixtures/diff_new_mode +17 -0
  27. data/test/fixtures/diff_p +610 -0
  28. data/test/fixtures/for_each_ref +0 -0
  29. data/test/fixtures/for_each_ref_remotes +0 -0
  30. data/test/fixtures/for_each_ref_tags +0 -0
  31. data/test/fixtures/ls_tree_a +7 -0
  32. data/test/fixtures/ls_tree_b +2 -0
  33. data/test/fixtures/ls_tree_commit +3 -0
  34. data/test/fixtures/rev_list +26 -0
  35. data/test/fixtures/rev_list_count +655 -0
  36. data/test/fixtures/rev_list_single +7 -0
  37. data/test/fixtures/rev_parse +1 -0
  38. data/test/fixtures/show_empty_commit +6 -0
  39. data/test/fixtures/simple_config +2 -0
  40. data/test/helper.rb +17 -0
  41. data/test/profile.rb +21 -0
  42. data/test/suite.rb +6 -0
  43. data/test/test_actor.rb +35 -0
  44. data/test/test_blob.rb +74 -0
  45. data/test/test_commit.rb +182 -0
  46. data/test/test_config.rb +58 -0
  47. data/test/test_diff.rb +18 -0
  48. data/test/test_git.rb +52 -0
  49. data/test/test_head.rb +22 -0
  50. data/test/test_real.rb +19 -0
  51. data/test/test_reality.rb +17 -0
  52. data/test/test_remote.rb +15 -0
  53. data/test/test_repo.rb +278 -0
  54. data/test/test_tag.rb +29 -0
  55. data/test/test_tree.rb +91 -0
  56. metadata +139 -0
@@ -0,0 +1,44 @@
1
+ module Grit
2
+
3
+ class Config
4
+ def initialize(repo)
5
+ @repo = repo
6
+ end
7
+
8
+ def []=(key, value)
9
+ @repo.git.config({}, key, value)
10
+ @data = nil
11
+ end
12
+
13
+ def [](key)
14
+ data[key]
15
+ end
16
+
17
+ def fetch(key, default = nil)
18
+ data[key] || default || raise(IndexError.new("key not found"))
19
+ end
20
+
21
+ def keys
22
+ data.keys
23
+ end
24
+
25
+ protected
26
+ def data
27
+ @data ||= load_config
28
+ end
29
+
30
+ def load_config
31
+ hash = {}
32
+ config_lines.map do |line|
33
+ key, value = line.split(/=/, 2)
34
+ hash[key] = value
35
+ end
36
+ hash
37
+ end
38
+
39
+ def config_lines
40
+ @repo.git.config(:list => true).split(/\n/)
41
+ end
42
+ end # Config
43
+
44
+ end # Grit
data/lib/grit/diff.rb ADDED
@@ -0,0 +1,70 @@
1
+ module Grit
2
+
3
+ class Diff
4
+ attr_reader :a_path, :b_path
5
+ attr_reader :a_commit, :b_commit
6
+ attr_reader :a_mode, :b_mode
7
+ attr_reader :new_file, :deleted_file
8
+ attr_reader :diff
9
+
10
+ def initialize(repo, a_path, b_path, a_commit, b_commit, a_mode, b_mode, new_file, deleted_file, diff)
11
+ @repo = repo
12
+ @a_path = a_path
13
+ @b_path = b_path
14
+ @a_commit = a_commit =~ /^0{40}$/ ? nil : Commit.create(repo, :id => a_commit)
15
+ @b_commit = b_commit =~ /^0{40}$/ ? nil : Commit.create(repo, :id => b_commit)
16
+ @a_mode = a_mode
17
+ @b_mode = b_mode
18
+ @new_file = new_file
19
+ @deleted_file = deleted_file
20
+ @diff = diff
21
+ end
22
+
23
+ def self.list_from_string(repo, text)
24
+ lines = text.split("\n")
25
+
26
+ diffs = []
27
+
28
+ while !lines.empty?
29
+ m, a_path, b_path = *lines.shift.match(%r{^diff --git a/(.+?) b/(.+)$})
30
+
31
+ if lines.first =~ /^old mode/
32
+ m, a_mode = *lines.shift.match(/^old mode (\d+)/)
33
+ m, b_mode = *lines.shift.match(/^new mode (\d+)/)
34
+ end
35
+
36
+ if lines.empty? || lines.first =~ /^diff --git/
37
+ diffs << Diff.new(repo, a_path, b_path, nil, nil, a_mode, b_mode, false, false, nil)
38
+ next
39
+ end
40
+
41
+ new_file = false
42
+ deleted_file = false
43
+
44
+ if lines.first =~ /^new file/
45
+ m, b_mode = lines.shift.match(/^new file mode (.+)$/)
46
+ a_mode = nil
47
+ new_file = true
48
+ elsif lines.first =~ /^deleted file/
49
+ m, a_mode = lines.shift.match(/^deleted file mode (.+)$/)
50
+ b_mode = nil
51
+ deleted_file = true
52
+ end
53
+
54
+ m, a_commit, b_commit, b_mode = *lines.shift.match(%r{^index ([0-9A-Fa-f]+)\.\.([0-9A-Fa-f]+) ?(.+)?$})
55
+ b_mode.strip! if b_mode
56
+
57
+ diff_lines = []
58
+ while lines.first && lines.first !~ /^diff/
59
+ diff_lines << lines.shift
60
+ end
61
+ diff = diff_lines.join("\n")
62
+
63
+ diffs << Diff.new(repo, a_path, b_path, a_commit, b_commit, a_mode, b_mode, new_file, deleted_file, diff)
64
+ end
65
+
66
+ diffs
67
+ end
68
+ end # Diff
69
+
70
+ end # Grit
@@ -0,0 +1,7 @@
1
+ module Grit
2
+ class InvalidGitRepositoryError < StandardError
3
+ end
4
+
5
+ class NoSuchPathError < StandardError
6
+ end
7
+ end
data/lib/grit/git.rb ADDED
@@ -0,0 +1,124 @@
1
+ trap("CHLD") do
2
+ begin
3
+ Process.wait(-1, Process::WNOHANG)
4
+ rescue Object
5
+ end
6
+ end
7
+
8
+ module Grit
9
+
10
+ class Git
11
+ class GitTimeout < RuntimeError
12
+ attr_reader :command, :bytes_read
13
+
14
+ def initialize(command = nil, bytes_read = nil)
15
+ @command = command
16
+ @bytes_read = bytes_read
17
+ end
18
+ end
19
+
20
+ undef_method :clone
21
+
22
+ class << self
23
+ attr_accessor :git_binary, :git_timeout
24
+ end
25
+
26
+ self.git_binary = "/usr/bin/env git"
27
+ self.git_timeout = 5
28
+
29
+ attr_accessor :git_dir, :bytes_read
30
+
31
+ def initialize(git_dir)
32
+ self.git_dir = git_dir
33
+ self.bytes_read = 0
34
+ end
35
+
36
+ # Run the given git command with the specified arguments and return
37
+ # the result as a String
38
+ # +cmd+ is the command
39
+ # +options+ is a hash of Ruby style options
40
+ # +args+ is the list of arguments (to be joined by spaces)
41
+ #
42
+ # Examples
43
+ # git.rev_list({:max_count => 10, :header => true}, "master")
44
+ #
45
+ # Returns String
46
+ def method_missing(cmd, options = {}, *args)
47
+ run('', cmd, '', options, args)
48
+ end
49
+
50
+ def run(prefix, cmd, postfix, options, args)
51
+ timeout = options.delete(:timeout)
52
+ timeout = true if timeout.nil?
53
+
54
+ opt_args = transform_options(options)
55
+ ext_args = args.map { |a| a == '--' ? a : "'#{a}'" }
56
+
57
+ call = "#{prefix}#{Git.git_binary} --git-dir='#{self.git_dir}' #{cmd.to_s.gsub(/_/, '-')} #{(opt_args + ext_args).join(' ')}#{postfix}"
58
+ Grit.log(call) if Grit.debug
59
+ response = timeout ? sh(call) : wild_sh(call)
60
+ Grit.log(response) if Grit.debug
61
+ response
62
+ end
63
+
64
+ def sh(command)
65
+ ret, pid = nil, nil
66
+ Open4.popen4(command) do |id, _, io, _|
67
+ pid = id
68
+ ret = Timeout.timeout(self.class.git_timeout) { io.read }
69
+ @bytes_read += ret.size
70
+
71
+ if @bytes_read > 5242880 # 5.megabytes
72
+ bytes = @bytes_read
73
+ @bytes_read = 0
74
+ raise GitTimeout.new(command, bytes)
75
+ end
76
+ end
77
+ ret
78
+ rescue Errno::ECHILD
79
+ ret
80
+ rescue Object => e
81
+ Process.kill('KILL', pid) rescue nil
82
+ bytes = @bytes_read
83
+ @bytes_read = 0
84
+ raise GitTimeout.new(command, bytes)
85
+ end
86
+
87
+ def wild_sh(command)
88
+ ret = nil
89
+ Open4.popen4(command) {|pid, _, io, _|
90
+ ret = io.read
91
+ }
92
+ rescue Errno::ECHILD
93
+ ret
94
+ end
95
+
96
+ # Transform Ruby style options into git command line options
97
+ # +options+ is a hash of Ruby style options
98
+ #
99
+ # Returns String[]
100
+ # e.g. ["--max-count=10", "--header"]
101
+ def transform_options(options)
102
+ args = []
103
+ options.keys.each do |opt|
104
+ if opt.to_s.size == 1
105
+ if options[opt] == true
106
+ args << "-#{opt}"
107
+ else
108
+ val = options.delete(opt)
109
+ args << "-#{opt.to_s} '#{val}'"
110
+ end
111
+ else
112
+ if options[opt] == true
113
+ args << "--#{opt.to_s.gsub(/_/, '-')}"
114
+ else
115
+ val = options.delete(opt)
116
+ args << "--#{opt.to_s.gsub(/_/, '-')}='#{val}'"
117
+ end
118
+ end
119
+ end
120
+ args
121
+ end
122
+ end # Git
123
+
124
+ end # Grit
data/lib/grit/lazy.rb ADDED
@@ -0,0 +1,31 @@
1
+ ##
2
+ # Allows attributes to be declared as lazy, meaning that they won't be
3
+ # computed until they are asked for.
4
+ #
5
+ # Works by delegating each lazy_reader to a cached lazy_source method.
6
+ #
7
+ # class Person
8
+ # lazy_reader :eyes
9
+ #
10
+ # def lazy_source
11
+ # OpenStruct.new(:eyes => 2)
12
+ # end
13
+ # end
14
+ #
15
+ # >> Person.new.eyes
16
+ # => 2
17
+ #
18
+ module Lazy
19
+ def lazy_reader(*args)
20
+ args.each do |arg|
21
+ ivar = "@#{arg}"
22
+ define_method(arg) do
23
+ val = instance_variable_get(ivar)
24
+ return val if val
25
+ instance_variable_set(ivar, (@lazy_source ||= lazy_source).send(arg))
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ Object.extend Lazy unless Object.ancestors.include? Lazy
data/lib/grit/ref.rb ADDED
@@ -0,0 +1,110 @@
1
+ module Grit
2
+
3
+ class Ref
4
+
5
+ class << self
6
+
7
+ # Find all Refs
8
+ # +repo+ is the Repo
9
+ # +options+ is a Hash of options
10
+ #
11
+ # Returns Grit::Ref[] (baked)
12
+ def find_all(repo, options = {})
13
+ default_options = {:sort => "committerdate",
14
+ :format => "%(refname)%00%(objectname)"}
15
+
16
+ actual_options = default_options.merge(options)
17
+
18
+ output = repo.git.for_each_ref(actual_options, prefix)
19
+
20
+ self.list_from_string(repo, output)
21
+ end
22
+
23
+ # Parse out ref information into an array of baked refs objects
24
+ # +repo+ is the Repo
25
+ # +text+ is the text output from the git command
26
+ #
27
+ # Returns Grit::Ref[] (baked)
28
+ def list_from_string(repo, text)
29
+ refs = []
30
+
31
+ text.split("\n").each do |line|
32
+ refs << self.from_string(repo, line)
33
+ end
34
+
35
+ refs.sort { | x, y | x.name <=> y.name }
36
+ end
37
+
38
+ # Create a new Ref instance from the given string.
39
+ # +repo+ is the Repo
40
+ # +line+ is the formatted head information
41
+ #
42
+ # Format
43
+ # name: [a-zA-Z_/]+
44
+ # <null byte>
45
+ # id: [0-9A-Fa-f]{40}
46
+ #
47
+ # Returns Grit::Ref (baked)
48
+ def from_string(repo, line)
49
+ full_name, id = line.split("\0")
50
+ name = full_name.sub("#{prefix}/", '')
51
+ commit = Commit.create(repo, :id => id)
52
+ self.new(name, commit)
53
+ end
54
+
55
+ protected
56
+
57
+ def prefix
58
+ "refs/#{name.to_s.gsub(/^.*::/, '').downcase}s"
59
+ end
60
+
61
+ end
62
+
63
+ attr_reader :name
64
+ attr_reader :commit
65
+
66
+ # Instantiate a new Head
67
+ # +name+ is the name of the head
68
+ # +commit+ is the Commit that the head points to
69
+ #
70
+ # Returns Grit::Head (baked)
71
+ def initialize(name, commit)
72
+ @name = name
73
+ @commit = commit
74
+ end
75
+
76
+ # Pretty object inspection
77
+ def inspect
78
+ %Q{#<#{self.class.name} "#{@name}">}
79
+ end
80
+ end # Ref
81
+
82
+ # A Head is a named reference to a Commit. Every Head instance contains a name
83
+ # and a Commit object.
84
+ #
85
+ # r = Grit::Repo.new("/path/to/repo")
86
+ # h = r.heads.first
87
+ # h.name # => "master"
88
+ # h.commit # => #<Grit::Commit "1c09f116cbc2cb4100fb6935bb162daa4723f455">
89
+ # h.commit.id # => "1c09f116cbc2cb4100fb6935bb162daa4723f455"
90
+ class Head < Ref
91
+
92
+ # Get the HEAD revision of the repo.
93
+ # +repo+ is the Repo
94
+ # +options+ is a Hash of options
95
+ #
96
+ # Returns Grit::Head (baked)
97
+ def self.current(repo, options = {})
98
+ head = File.open(File.join(repo.path, 'HEAD')).read.chomp
99
+ if /ref: refs\/heads\/(.*)/.match(head)
100
+ self.new($1, repo.git.rev_parse(options, 'HEAD'))
101
+ end
102
+ end
103
+
104
+ end # Head
105
+
106
+ class Tag < Ref ; end
107
+
108
+ class Remote < Ref ; end
109
+
110
+ end # Grit
data/lib/grit/repo.rb ADDED
@@ -0,0 +1,318 @@
1
+ module Grit
2
+
3
+ class Repo
4
+ DAEMON_EXPORT_FILE = 'git-daemon-export-ok'
5
+
6
+ # The path of the git repo as a String
7
+ attr_accessor :path
8
+ attr_reader :bare
9
+
10
+ # The git command line interface object
11
+ attr_accessor :git
12
+
13
+ # Create a new Repo instance
14
+ # +path+ is the path to either the root git directory or the bare git repo
15
+ #
16
+ # Examples
17
+ # g = Repo.new("/Users/tom/dev/grit")
18
+ # g = Repo.new("/Users/tom/public/grit.git")
19
+ #
20
+ # Returns Grit::Repo
21
+ def initialize(path)
22
+ epath = File.expand_path(path)
23
+
24
+ if File.exist?(File.join(epath, '.git'))
25
+ self.path = File.join(epath, '.git')
26
+ @bare = false
27
+ elsif File.exist?(epath) && epath =~ /\.git$/
28
+ self.path = epath
29
+ @bare = true
30
+ elsif File.exist?(epath)
31
+ raise InvalidGitRepositoryError.new(epath)
32
+ else
33
+ raise NoSuchPathError.new(epath)
34
+ end
35
+
36
+ self.git = Git.new(self.path)
37
+ end
38
+
39
+ # The project's description. Taken verbatim from GIT_REPO/description
40
+ #
41
+ # Returns String
42
+ def description
43
+ File.open(File.join(self.path, 'description')).read.chomp
44
+ end
45
+
46
+ # An array of Head objects representing the branch heads in
47
+ # this repo
48
+ #
49
+ # Returns Grit::Head[] (baked)
50
+ def heads
51
+ Head.find_all(self)
52
+ end
53
+
54
+ alias_method :branches, :heads
55
+
56
+ # Object reprsenting the current repo head.
57
+ #
58
+ # Returns Grit::Head (baked)
59
+ def head
60
+ Head.current(self)
61
+ end
62
+
63
+ # An array of Tag objects that are available in this repo
64
+ #
65
+ # Returns Grit::Tag[] (baked)
66
+ def tags
67
+ Tag.find_all(self)
68
+ end
69
+
70
+ # An array of Remote objects representing the remote branches in
71
+ # this repo
72
+ #
73
+ # Returns Grit::Remote[] (baked)
74
+ def remotes
75
+ Remote.find_all(self)
76
+ end
77
+
78
+ # An array of Ref objects representing the refs in
79
+ # this repo
80
+ #
81
+ # Returns Grit::Ref[] (baked)
82
+ def refs
83
+ [ Head.find_all(self), Tag.find_all(self), Remote.find_all(self) ].flatten
84
+ end
85
+
86
+ # An array of Commit objects representing the history of a given ref/commit
87
+ # +start+ is the branch/commit name (default 'master')
88
+ # +max_count+ is the maximum number of commits to return (default 10)
89
+ # +skip+ is the number of commits to skip (default 0)
90
+ #
91
+ # Returns Grit::Commit[] (baked)
92
+ def commits(start = 'master', max_count = 10, skip = 0)
93
+ options = {:max_count => max_count,
94
+ :skip => skip}
95
+
96
+ Commit.find_all(self, start, options)
97
+ end
98
+
99
+ # The Commits objects that are reachable via +to+ but not via +from+
100
+ # Commits are returned in chronological order.
101
+ # +from+ is the branch/commit name of the younger item
102
+ # +to+ is the branch/commit name of the older item
103
+ #
104
+ # Returns Grit::Commit[] (baked)
105
+ def commits_between(from, to)
106
+ Commit.find_all(self, "#{from}..#{to}").reverse
107
+ end
108
+
109
+ # The Commits objects that are newer than the specified date.
110
+ # Commits are returned in chronological order.
111
+ # +start+ is the branch/commit name (default 'master')
112
+ # +since+ is a string represeting a date/time
113
+ # +extra_options+ is a hash of extra options
114
+ #
115
+ # Returns Grit::Commit[] (baked)
116
+ def commits_since(start = 'master', since = '1970-01-01', extra_options = {})
117
+ options = {:since => since}.merge(extra_options)
118
+
119
+ Commit.find_all(self, start, options)
120
+ end
121
+
122
+ # The number of commits reachable by the given branch/commit
123
+ # +start+ is the branch/commit name (default 'master')
124
+ #
125
+ # Returns Integer
126
+ def commit_count(start = 'master')
127
+ Commit.count(self, start)
128
+ end
129
+
130
+ # The Commit object for the specified id
131
+ # +id+ is the SHA1 identifier of the commit
132
+ #
133
+ # Returns Grit::Commit (baked)
134
+ def commit(id)
135
+ options = {:max_count => 1}
136
+
137
+ Commit.find_all(self, id, options).first
138
+ end
139
+
140
+ # The Tree object for the given treeish reference
141
+ # +treeish+ is the reference (default 'master')
142
+ # +paths+ is an optional Array of directory paths to restrict the tree (deafult [])
143
+ #
144
+ # Examples
145
+ # repo.tree('master', ['lib/'])
146
+ #
147
+ # Returns Grit::Tree (baked)
148
+ def tree(treeish = 'master', paths = [])
149
+ Tree.construct(self, treeish, paths)
150
+ end
151
+
152
+ # The Blob object for the given id
153
+ # +id+ is the SHA1 id of the blob
154
+ #
155
+ # Returns Grit::Blob (unbaked)
156
+ def blob(id)
157
+ Blob.create(self, :id => id)
158
+ end
159
+
160
+ # The commit log for a treeish
161
+ #
162
+ # Returns Grit::Commit[]
163
+ def log(commit = 'master', path = nil, options = {})
164
+ default_options = {:pretty => "raw"}
165
+ actual_options = default_options.merge(options)
166
+ arg = path ? [commit, '--', path] : [commit]
167
+ commits = self.git.log(actual_options, *arg)
168
+ Commit.list_from_string(self, commits)
169
+ end
170
+
171
+ # The diff from commit +a+ to commit +b+, optionally restricted to the given file(s)
172
+ # +a+ is the base commit
173
+ # +b+ is the other commit
174
+ # +paths+ is an optional list of file paths on which to restrict the diff
175
+ def diff(a, b, *paths)
176
+ self.git.diff({}, a, b, '--', *paths)
177
+ end
178
+
179
+ # The commit diff for the given commit
180
+ # +commit+ is the commit name/id
181
+ #
182
+ # Returns Grit::Diff[]
183
+ def commit_diff(commit)
184
+ Commit.diff(self, commit)
185
+ end
186
+
187
+ # Initialize a bare git repository at the given path
188
+ # +path+ is the full path to the repo (traditionally ends with /<name>.git)
189
+ # +options+ is any additional options to the git init command
190
+ #
191
+ # Examples
192
+ # Grit::Repo.init_bare('/var/git/myrepo.git')
193
+ #
194
+ # Returns Grit::Repo (the newly created repo)
195
+ def self.init_bare(path, options = {})
196
+ git = Git.new(path)
197
+ git.init(options)
198
+ self.new(path)
199
+ end
200
+
201
+ # Fork a bare git repository from this repo
202
+ # +path+ is the full path of the new repo (traditionally ends with /<name>.git)
203
+ # +options+ is any additional options to the git clone command
204
+ #
205
+ # Returns Grit::Repo (the newly forked repo)
206
+ def fork_bare(path, options = {})
207
+ default_options = {:bare => true, :shared => true}
208
+ real_options = default_options.merge(options)
209
+ self.git.clone(real_options, self.path, path)
210
+ Repo.new(path)
211
+ end
212
+
213
+ # Archive the given treeish
214
+ # +treeish+ is the treeish name/id (default 'master')
215
+ # +prefix+ is the optional prefix
216
+ #
217
+ # Examples
218
+ # repo.archive_tar
219
+ # # => <String containing tar archive>
220
+ #
221
+ # repo.archive_tar('a87ff14')
222
+ # # => <String containing tar archive for commit a87ff14>
223
+ #
224
+ # repo.archive_tar('master', 'myproject/')
225
+ # # => <String containing tar archive and prefixed with 'myproject/'>
226
+ #
227
+ # Returns String (containing tar archive)
228
+ def archive_tar(treeish = 'master', prefix = nil)
229
+ options = {}
230
+ options[:prefix] = prefix if prefix
231
+ self.git.archive(options, treeish)
232
+ end
233
+
234
+ # Archive and gzip the given treeish
235
+ # +treeish+ is the treeish name/id (default 'master')
236
+ # +prefix+ is the optional prefix
237
+ #
238
+ # Examples
239
+ # repo.archive_tar_gz
240
+ # # => <String containing tar.gz archive>
241
+ #
242
+ # repo.archive_tar_gz('a87ff14')
243
+ # # => <String containing tar.gz archive for commit a87ff14>
244
+ #
245
+ # repo.archive_tar_gz('master', 'myproject/')
246
+ # # => <String containing tar.gz archive and prefixed with 'myproject/'>
247
+ #
248
+ # Returns String (containing tar.gz archive)
249
+ def archive_tar_gz(treeish = 'master', prefix = nil)
250
+ options = {}
251
+ options[:prefix] = prefix if prefix
252
+ self.git.archive(options, treeish, "| gzip")
253
+ end
254
+
255
+ # Enable git-daemon serving of this repository by writing the
256
+ # git-daemon-export-ok file to its git directory
257
+ #
258
+ # Returns nothing
259
+ def enable_daemon_serve
260
+ FileUtils.touch(File.join(self.path, DAEMON_EXPORT_FILE))
261
+ end
262
+
263
+ # Disable git-daemon serving of this repository by ensuring there is no
264
+ # git-daemon-export-ok file in its git directory
265
+ #
266
+ # Returns nothing
267
+ def disable_daemon_serve
268
+ FileUtils.rm_f(File.join(self.path, DAEMON_EXPORT_FILE))
269
+ end
270
+
271
+ # The list of alternates for this repo
272
+ #
273
+ # Returns Array[String] (pathnames of alternates)
274
+ def alternates
275
+ alternates_path = File.join(self.path, *%w{objects info alternates})
276
+
277
+ if File.exist?(alternates_path)
278
+ File.read(alternates_path).strip.split("\n")
279
+ else
280
+ []
281
+ end
282
+ end
283
+
284
+ # Sets the alternates
285
+ # +alts+ is the Array of String paths representing the alternates
286
+ #
287
+ # Returns nothing
288
+ def alternates=(alts)
289
+ alts.each do |alt|
290
+ unless File.exist?(alt)
291
+ raise "Could not set alternates. Alternate path #{alt} must exist"
292
+ end
293
+ end
294
+
295
+ if alts.empty?
296
+ File.delete(File.join(self.path, *%w{objects info alternates}))
297
+ else
298
+ File.open(File.join(self.path, *%w{objects info alternates}), 'w') do |f|
299
+ f.write alts.join("\n")
300
+ end
301
+ end
302
+ end
303
+
304
+ def config
305
+ @config ||= Config.new(self)
306
+ end
307
+
308
+ def index
309
+ Index.new(self)
310
+ end
311
+
312
+ # Pretty object inspection
313
+ def inspect
314
+ %Q{#<Grit::Repo "#{@path}">}
315
+ end
316
+ end # Repo
317
+
318
+ end # Grit