smeagol 0.6.0 → 0.6.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.
- checksums.yaml +7 -0
- data/.index +82 -0
- data/HISTORY.md +14 -0
- data/lib/smeagol.rb +2 -1
- data/lib/smeagol/app.rb +1 -1
- data/lib/smeagol/gollum/file.rb +1 -1
- data/lib/smeagol/wiki.rb +1 -0
- data/vendor/grit/lib/grit.rb +75 -0
- data/vendor/grit/lib/grit/actor.rb +52 -0
- data/vendor/grit/lib/grit/blame.rb +70 -0
- data/vendor/grit/lib/grit/blob.rb +126 -0
- data/vendor/grit/lib/grit/commit.rb +313 -0
- data/vendor/grit/lib/grit/commit_stats.rb +128 -0
- data/vendor/grit/lib/grit/config.rb +44 -0
- data/vendor/grit/lib/grit/diff.rb +79 -0
- data/vendor/grit/lib/grit/errors.rb +10 -0
- data/vendor/grit/lib/grit/git-ruby.rb +262 -0
- data/vendor/grit/lib/grit/git-ruby/commit_db.rb +52 -0
- data/vendor/grit/lib/grit/git-ruby/git_object.rb +353 -0
- data/vendor/grit/lib/grit/git-ruby/internal/file_window.rb +58 -0
- data/vendor/grit/lib/grit/git-ruby/internal/loose.rb +137 -0
- data/vendor/grit/lib/grit/git-ruby/internal/pack.rb +397 -0
- data/vendor/grit/lib/grit/git-ruby/internal/raw_object.rb +44 -0
- data/vendor/grit/lib/grit/git-ruby/repository.rb +775 -0
- data/vendor/grit/lib/grit/git.rb +501 -0
- data/vendor/grit/lib/grit/index.rb +222 -0
- data/vendor/grit/lib/grit/lazy.rb +35 -0
- data/vendor/grit/lib/grit/merge.rb +45 -0
- data/vendor/grit/lib/grit/ref.rb +78 -0
- data/vendor/grit/lib/grit/repo.rb +709 -0
- data/vendor/grit/lib/grit/ruby1.9.rb +7 -0
- data/vendor/grit/lib/grit/status.rb +153 -0
- data/vendor/grit/lib/grit/submodule.rb +88 -0
- data/vendor/grit/lib/grit/tag.rb +102 -0
- data/vendor/grit/lib/grit/tree.rb +125 -0
- metadata +125 -56
- data/.ruby +0 -80
@@ -0,0 +1,222 @@
|
|
1
|
+
module Grit
|
2
|
+
|
3
|
+
class Index
|
4
|
+
# Public: Gets/Sets the Grit::Repo to which this index belongs.
|
5
|
+
attr_accessor :repo
|
6
|
+
|
7
|
+
# Public: Gets/Sets the Hash tree map that holds the changes to be made
|
8
|
+
# in the next commit.
|
9
|
+
attr_accessor :tree
|
10
|
+
|
11
|
+
# Public: Gets/Sets the Grit::Tree object representing the tree upon
|
12
|
+
# which the next commit will be based.
|
13
|
+
attr_accessor :current_tree
|
14
|
+
|
15
|
+
# Public: if a tree or commit is written, this stores the size of that object
|
16
|
+
attr_reader :last_tree_size
|
17
|
+
attr_reader :last_commit_size
|
18
|
+
|
19
|
+
# Initialize a new Index object.
|
20
|
+
#
|
21
|
+
# repo - The Grit::Repo to which the index belongs.
|
22
|
+
#
|
23
|
+
# Returns the newly initialized Grit::Index.
|
24
|
+
def initialize(repo)
|
25
|
+
self.repo = repo
|
26
|
+
self.tree = {}
|
27
|
+
self.current_tree = nil
|
28
|
+
end
|
29
|
+
|
30
|
+
# Public: Add a file to the index.
|
31
|
+
#
|
32
|
+
# path - The String file path including filename (no slash prefix).
|
33
|
+
# data - The String binary contents of the file.
|
34
|
+
#
|
35
|
+
# Returns nothing.
|
36
|
+
def add(path, data)
|
37
|
+
path = path.split('/')
|
38
|
+
filename = path.pop
|
39
|
+
|
40
|
+
current = self.tree
|
41
|
+
|
42
|
+
path.each do |dir|
|
43
|
+
current[dir] ||= {}
|
44
|
+
node = current[dir]
|
45
|
+
current = node
|
46
|
+
end
|
47
|
+
|
48
|
+
current[filename] = data
|
49
|
+
end
|
50
|
+
|
51
|
+
# Public: Delete the given file from the index.
|
52
|
+
#
|
53
|
+
# path - The String file path including filename (no slash prefix).
|
54
|
+
#
|
55
|
+
# Returns nothing.
|
56
|
+
def delete(path)
|
57
|
+
add(path, false)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Public: Read the contents of the given Tree into the index to use as a
|
61
|
+
# starting point for the index.
|
62
|
+
#
|
63
|
+
# tree - The String branch/tag/sha of the Git tree object.
|
64
|
+
#
|
65
|
+
# Returns nothing.
|
66
|
+
def read_tree(tree)
|
67
|
+
self.current_tree = self.repo.tree(tree)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Public: Commit the contents of the index. This method supports two
|
71
|
+
# formats for arguments:
|
72
|
+
#
|
73
|
+
# message - The String commit message.
|
74
|
+
# options - An optional Hash of index options.
|
75
|
+
# :parents - Array of String commit SHA1s or Grit::Commit
|
76
|
+
# objects to attach this commit to to form a
|
77
|
+
# new head (default: nil).
|
78
|
+
# :actor - The Grit::Actor details of the user making
|
79
|
+
# the commit (default: nil).
|
80
|
+
# :last_tree - The String SHA1 of a tree to compare with
|
81
|
+
# in order to avoid making empty commits
|
82
|
+
# (default: nil).
|
83
|
+
# :head - The String branch name to write this head to
|
84
|
+
# (default: nil).
|
85
|
+
# :committed_date - The Time that the commit was made.
|
86
|
+
# (Default: Time.now)
|
87
|
+
# :authored_date - The Time that the commit was authored.
|
88
|
+
# (Default: committed_date)
|
89
|
+
#
|
90
|
+
# The legacy argument style looks like:
|
91
|
+
#
|
92
|
+
# message - The String commit message.
|
93
|
+
# parents - Array of String commit SHA1s or Grit::Commit objects to
|
94
|
+
# attach this commit to to form a new head (default: nil).
|
95
|
+
# actor - The Grit::Actor details of the user making the commit
|
96
|
+
# (default: nil).
|
97
|
+
# last_tree - The String SHA1 of a tree to compare with in order to avoid
|
98
|
+
# making empty commits (default: nil).
|
99
|
+
# head - The String branch name to write this head to
|
100
|
+
# (default: "master").
|
101
|
+
#
|
102
|
+
# Returns a String of the SHA1 of the new commit.
|
103
|
+
def commit(message, parents = nil, actor = nil, last_tree = nil, head = 'master')
|
104
|
+
commit_tree_sha = nil
|
105
|
+
if parents.is_a?(Hash)
|
106
|
+
commit_tree_sha = parents[:commit_tree_sha]
|
107
|
+
actor = parents[:actor]
|
108
|
+
committer = parents[:committer]
|
109
|
+
author = parents[:author]
|
110
|
+
last_tree = parents[:last_tree]
|
111
|
+
head = parents[:head]
|
112
|
+
committed_date = parents[:committed_date]
|
113
|
+
authored_date = parents[:authored_date]
|
114
|
+
parents = parents[:parents]
|
115
|
+
end
|
116
|
+
|
117
|
+
committer ||= actor
|
118
|
+
author ||= committer
|
119
|
+
|
120
|
+
if commit_tree_sha
|
121
|
+
tree_sha1 = commit_tree_sha
|
122
|
+
else
|
123
|
+
tree_sha1 = write_tree(self.tree, self.current_tree)
|
124
|
+
end
|
125
|
+
|
126
|
+
# don't write identical commits
|
127
|
+
return false if tree_sha1 == last_tree
|
128
|
+
|
129
|
+
contents = []
|
130
|
+
contents << ['tree', tree_sha1].join(' ')
|
131
|
+
parents.each do |p|
|
132
|
+
contents << ['parent', p].join(' ')
|
133
|
+
end if parents
|
134
|
+
|
135
|
+
committer ||= begin
|
136
|
+
config = Config.new(self.repo)
|
137
|
+
Actor.new(config['user.name'], config['user.email'])
|
138
|
+
end
|
139
|
+
author ||= committer
|
140
|
+
committed_date ||= Time.now
|
141
|
+
authored_date ||= committed_date
|
142
|
+
|
143
|
+
contents << ['author', author.output(authored_date)].join(' ')
|
144
|
+
contents << ['committer', committer.output(committed_date)].join(' ')
|
145
|
+
contents << ''
|
146
|
+
contents << message
|
147
|
+
|
148
|
+
contents = contents.join("\n")
|
149
|
+
@last_commit_size = contents.size
|
150
|
+
commit_sha1 = self.repo.git.put_raw_object(contents, 'commit')
|
151
|
+
|
152
|
+
self.repo.update_ref(head, commit_sha1) if head
|
153
|
+
commit_sha1
|
154
|
+
end
|
155
|
+
|
156
|
+
# Recursively write a tree to the index.
|
157
|
+
#
|
158
|
+
# tree - The Hash tree map:
|
159
|
+
# key - The String directory or filename.
|
160
|
+
# val - The Hash submap or the String contents of the file.
|
161
|
+
# now_tree - The Grit::Tree representing the a previous tree upon which
|
162
|
+
# this tree will be based (default: nil).
|
163
|
+
#
|
164
|
+
# Returns the String SHA1 String of the tree.
|
165
|
+
def write_tree(tree = nil, now_tree = nil)
|
166
|
+
tree = self.tree if !tree
|
167
|
+
tree_contents = {}
|
168
|
+
|
169
|
+
# fill in original tree
|
170
|
+
now_tree = read_tree(now_tree) if(now_tree && now_tree.is_a?(String))
|
171
|
+
now_tree.contents.each do |obj|
|
172
|
+
sha = [obj.id].pack("H*")
|
173
|
+
k = obj.name
|
174
|
+
k += '/' if (obj.class == Grit::Tree)
|
175
|
+
tmode = obj.mode.to_i.to_s ## remove zero-padding
|
176
|
+
tree_contents[k] = "%s %s\0%s" % [tmode, obj.name, sha]
|
177
|
+
end if now_tree
|
178
|
+
|
179
|
+
# overwrite with new tree contents
|
180
|
+
tree.each do |k, v|
|
181
|
+
case v
|
182
|
+
when Array
|
183
|
+
sha, mode = v
|
184
|
+
if sha.size == 40 # must be a sha
|
185
|
+
sha = [sha].pack("H*")
|
186
|
+
mode = mode.to_i.to_s # leading 0s not allowed
|
187
|
+
k = k.split('/').last # slashes not allowed
|
188
|
+
str = "%s %s\0%s" % [mode, k, sha]
|
189
|
+
tree_contents[k] = str
|
190
|
+
end
|
191
|
+
when String
|
192
|
+
sha = write_blob(v)
|
193
|
+
sha = [sha].pack("H*")
|
194
|
+
str = "%s %s\0%s" % ['100644', k, sha]
|
195
|
+
tree_contents[k] = str
|
196
|
+
when Hash
|
197
|
+
ctree = now_tree/k if now_tree
|
198
|
+
sha = write_tree(v, ctree)
|
199
|
+
sha = [sha].pack("H*")
|
200
|
+
str = "%s %s\0%s" % ['40000', k, sha]
|
201
|
+
tree_contents[k + '/'] = str
|
202
|
+
when false
|
203
|
+
tree_contents.delete(k)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
tr = tree_contents.sort.map { |k, v| v }.join('')
|
208
|
+
@last_tree_size = tr.size
|
209
|
+
self.repo.git.put_raw_object(tr, 'tree')
|
210
|
+
end
|
211
|
+
|
212
|
+
# Write a blob to the index.
|
213
|
+
#
|
214
|
+
# data - The String data to write.
|
215
|
+
#
|
216
|
+
# Returns the String SHA1 of the new blob.
|
217
|
+
def write_blob(data)
|
218
|
+
self.repo.git.put_raw_object(data, 'blob')
|
219
|
+
end
|
220
|
+
end # Index
|
221
|
+
|
222
|
+
end # Grit
|
@@ -0,0 +1,35 @@
|
|
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 self.extended(klass)
|
20
|
+
klass.send(:attr_writer, :lazy_source)
|
21
|
+
end
|
22
|
+
|
23
|
+
def lazy_reader(*args)
|
24
|
+
args.each do |arg|
|
25
|
+
ivar = "@#{arg}"
|
26
|
+
define_method(arg) do
|
27
|
+
if instance_variable_defined?(ivar)
|
28
|
+
val = instance_variable_get(ivar)
|
29
|
+
return val if val
|
30
|
+
end
|
31
|
+
instance_variable_set(ivar, (@lazy_source ||= lazy_source).send(arg))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Grit
|
2
|
+
|
3
|
+
class Merge
|
4
|
+
|
5
|
+
STATUS_BOTH = 'both'
|
6
|
+
STATUS_OURS = 'ours'
|
7
|
+
STATUS_THEIRS = 'theirs'
|
8
|
+
|
9
|
+
attr_reader :conflicts, :text, :sections
|
10
|
+
|
11
|
+
def initialize(str)
|
12
|
+
status = STATUS_BOTH
|
13
|
+
|
14
|
+
section = 1
|
15
|
+
@conflicts = 0
|
16
|
+
@text = {}
|
17
|
+
|
18
|
+
lines = str.split("\n")
|
19
|
+
lines.each do |line|
|
20
|
+
if /^<<<<<<< (.*?)/.match(line)
|
21
|
+
status = STATUS_OURS
|
22
|
+
@conflicts += 1
|
23
|
+
section += 1
|
24
|
+
elsif line == '======='
|
25
|
+
status = STATUS_THEIRS
|
26
|
+
elsif /^>>>>>>> (.*?)/.match(line)
|
27
|
+
status = STATUS_BOTH
|
28
|
+
section += 1
|
29
|
+
else
|
30
|
+
@text[section] ||= {}
|
31
|
+
@text[section][status] ||= []
|
32
|
+
@text[section][status] << line
|
33
|
+
end
|
34
|
+
end
|
35
|
+
@text = @text.values
|
36
|
+
@sections = @text.size
|
37
|
+
end
|
38
|
+
|
39
|
+
# Pretty object inspection
|
40
|
+
def inspect
|
41
|
+
%Q{#<Grit::Merge}
|
42
|
+
end
|
43
|
+
end # Merge
|
44
|
+
|
45
|
+
end # Grit
|
@@ -0,0 +1,78 @@
|
|
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
|
+
refs = repo.git.refs(options, prefix)
|
14
|
+
refs.split("\n").map do |ref|
|
15
|
+
name, id = *ref.split(' ')
|
16
|
+
commit = Commit.create(repo, :id => id)
|
17
|
+
self.new(name, commit)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def prefix
|
24
|
+
"refs/#{name.to_s.gsub(/^.*::/, '').downcase}s"
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_reader :name
|
30
|
+
attr_reader :commit
|
31
|
+
|
32
|
+
# Instantiate a new Head
|
33
|
+
# +name+ is the name of the head
|
34
|
+
# +commit+ is the Commit that the head points to
|
35
|
+
#
|
36
|
+
# Returns Grit::Head (baked)
|
37
|
+
def initialize(name, commit)
|
38
|
+
@name = name
|
39
|
+
@commit = commit
|
40
|
+
end
|
41
|
+
|
42
|
+
# Pretty object inspection
|
43
|
+
def inspect
|
44
|
+
%Q{#<#{self.class.name} "#{@name}">}
|
45
|
+
end
|
46
|
+
end # Ref
|
47
|
+
|
48
|
+
# A Head is a named reference to a Commit. Every Head instance contains a name
|
49
|
+
# and a Commit object.
|
50
|
+
#
|
51
|
+
# r = Grit::Repo.new("/path/to/repo")
|
52
|
+
# h = r.heads.first
|
53
|
+
# h.name # => "master"
|
54
|
+
# h.commit # => #<Grit::Commit "1c09f116cbc2cb4100fb6935bb162daa4723f455">
|
55
|
+
# h.commit.id # => "1c09f116cbc2cb4100fb6935bb162daa4723f455"
|
56
|
+
class Head < Ref
|
57
|
+
|
58
|
+
# Get the HEAD revision of the repo.
|
59
|
+
# +repo+ is the Repo
|
60
|
+
# +options+ is a Hash of options
|
61
|
+
#
|
62
|
+
# Returns Grit::Head (baked)
|
63
|
+
def self.current(repo, options = {})
|
64
|
+
head = repo.git.fs_read('HEAD').chomp
|
65
|
+
if /ref: refs\/heads\/(.*)/.match(head)
|
66
|
+
id = repo.git.rev_parse(options, 'HEAD')
|
67
|
+
commit = Commit.create(repo, :id => id)
|
68
|
+
self.new($1, commit)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end # Head
|
73
|
+
|
74
|
+
class Remote < Ref; end
|
75
|
+
|
76
|
+
class Note < Ref; end
|
77
|
+
|
78
|
+
end # Grit
|
@@ -0,0 +1,709 @@
|
|
1
|
+
module Grit
|
2
|
+
|
3
|
+
class Repo
|
4
|
+
DAEMON_EXPORT_FILE = 'git-daemon-export-ok'
|
5
|
+
BATCH_PARSERS = {
|
6
|
+
'commit' => ::Grit::Commit
|
7
|
+
}
|
8
|
+
|
9
|
+
# Public: The String path of the Git repo.
|
10
|
+
attr_accessor :path
|
11
|
+
|
12
|
+
# Public: The String path to the working directory of the repo, or nil if
|
13
|
+
# there is no working directory.
|
14
|
+
attr_accessor :working_dir
|
15
|
+
|
16
|
+
# Public: The Boolean of whether or not the repo is bare.
|
17
|
+
attr_reader :bare
|
18
|
+
|
19
|
+
# Public: The Grit::Git command line interface object.
|
20
|
+
attr_accessor :git
|
21
|
+
|
22
|
+
# Public: Create a new Repo instance.
|
23
|
+
#
|
24
|
+
# path - The String path to either the root git directory or the bare
|
25
|
+
# git repo. Bare repos are expected to end with ".git".
|
26
|
+
# options - A Hash of options (default: {}):
|
27
|
+
# :is_bare - Boolean whether to consider the repo as bare even
|
28
|
+
# if the repo name does not end with ".git".
|
29
|
+
#
|
30
|
+
# Examples
|
31
|
+
#
|
32
|
+
# r = Repo.new("/Users/tom/dev/normal")
|
33
|
+
# r = Repo.new("/Users/tom/public/bare.git")
|
34
|
+
# r = Repo.new("/Users/tom/public/bare", {:is_bare => true})
|
35
|
+
#
|
36
|
+
# Returns a newly initialized Grit::Repo.
|
37
|
+
# Raises Grit::InvalidGitRepositoryError if the path exists but is not
|
38
|
+
# a Git repository.
|
39
|
+
# Raises Grit::NoSuchPathError if the path does not exist.
|
40
|
+
def initialize(path, options = {})
|
41
|
+
epath = File.expand_path(path)
|
42
|
+
|
43
|
+
if File.exist?(File.join(epath, '.git'))
|
44
|
+
self.working_dir = epath
|
45
|
+
self.path = File.join(epath, '.git')
|
46
|
+
@bare = false
|
47
|
+
elsif File.exist?(epath) && (epath =~ /\.git$/ || options[:is_bare])
|
48
|
+
self.path = epath
|
49
|
+
@bare = true
|
50
|
+
elsif File.exist?(epath)
|
51
|
+
raise InvalidGitRepositoryError.new(epath)
|
52
|
+
else
|
53
|
+
raise NoSuchPathError.new(epath)
|
54
|
+
end
|
55
|
+
|
56
|
+
self.git = Git.new(self.path)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Public: Initialize a git repository (create it on the filesystem). By
|
60
|
+
# default, the newly created repository will contain a working directory.
|
61
|
+
# If you would like to create a bare repo, use Grit::Repo.init_bare.
|
62
|
+
#
|
63
|
+
# path - The String full path to the repo. Traditionally ends with
|
64
|
+
# "/<name>.git".
|
65
|
+
# git_options - A Hash of additional options to the git init command
|
66
|
+
# (default: {}).
|
67
|
+
# repo_options - A Hash of additional options to the Grit::Repo.new call
|
68
|
+
# (default: {}).
|
69
|
+
#
|
70
|
+
# Examples
|
71
|
+
#
|
72
|
+
# Grit::Repo.init('/var/git/myrepo.git')
|
73
|
+
#
|
74
|
+
# Returns the newly created Grit::Repo.
|
75
|
+
def self.init(path, git_options = {}, repo_options = {})
|
76
|
+
git_options = {:base => false}.merge(git_options)
|
77
|
+
git = Git.new(path)
|
78
|
+
git.fs_mkdir('..')
|
79
|
+
git.init(git_options, path)
|
80
|
+
self.new(path, repo_options)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Public: Initialize a bare git repository (create it on the filesystem).
|
84
|
+
#
|
85
|
+
# path - The String full path to the repo. Traditionally ends with
|
86
|
+
# "/<name>.git".
|
87
|
+
# git_options - A Hash of additional options to the git init command
|
88
|
+
# (default: {}).
|
89
|
+
# repo_options - A Hash of additional options to the Grit::Repo.new call
|
90
|
+
# (default: {}).
|
91
|
+
#
|
92
|
+
# Examples
|
93
|
+
#
|
94
|
+
# Grit::Repo.init_bare('/var/git/myrepo.git')
|
95
|
+
#
|
96
|
+
# Returns the newly created Grit::Repo.
|
97
|
+
def self.init_bare(path, git_options = {}, repo_options = {})
|
98
|
+
git_options = {:bare => true}.merge(git_options)
|
99
|
+
git = Git.new(path)
|
100
|
+
git.fs_mkdir('..')
|
101
|
+
git.init(git_options)
|
102
|
+
repo_options = {:is_bare => true}.merge(repo_options)
|
103
|
+
self.new(path, repo_options)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Public: Initialize a bare Git repository (create it on the filesystem)
|
107
|
+
# or, if the repo already exists, simply return it.
|
108
|
+
#
|
109
|
+
# path - The String full path to the repo. Traditionally ends with
|
110
|
+
# "/<name>.git".
|
111
|
+
# git_options - A Hash of additional options to the git init command
|
112
|
+
# (default: {}).
|
113
|
+
# repo_options - A Hash of additional options to the Grit::Repo.new call
|
114
|
+
# (default: {}).
|
115
|
+
#
|
116
|
+
# Returns the new or existing Grit::Repo.
|
117
|
+
def self.init_bare_or_open(path, git_options = {}, repo_options = {})
|
118
|
+
git = Git.new(path)
|
119
|
+
|
120
|
+
unless git.exist?
|
121
|
+
git.fs_mkdir(path)
|
122
|
+
git.init(git_options)
|
123
|
+
end
|
124
|
+
|
125
|
+
self.new(path, repo_options)
|
126
|
+
end
|
127
|
+
|
128
|
+
# Public: Create a bare fork of this repository.
|
129
|
+
#
|
130
|
+
# path - The String full path of where to create the new fork.
|
131
|
+
# Traditionally ends with "/<name>.git".
|
132
|
+
# options - The Hash of additional options to the git clone command.
|
133
|
+
# These options will be merged on top of the default Hash:
|
134
|
+
# {:bare => true, :shared => true}.
|
135
|
+
#
|
136
|
+
# Returns the newly forked Grit::Repo.
|
137
|
+
def fork_bare(path, options = {})
|
138
|
+
default_options = {:bare => true, :shared => true}
|
139
|
+
real_options = default_options.merge(options)
|
140
|
+
Git.new(path).fs_mkdir('..')
|
141
|
+
self.git.clone(real_options, self.path, path)
|
142
|
+
Repo.new(path)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Public: Fork a bare git repository from another repo.
|
146
|
+
#
|
147
|
+
# path - The String full path of the repo from which to fork..
|
148
|
+
# Traditionally ends with "/<name>.git".
|
149
|
+
# options - The Hash of additional options to the git clone command.
|
150
|
+
# These options will be merged on top of the default Hash:
|
151
|
+
# {:bare => true, :shared => true}.
|
152
|
+
#
|
153
|
+
# Returns the newly forked Grit::Repo.
|
154
|
+
def fork_bare_from(path, options = {})
|
155
|
+
default_options = {:bare => true, :shared => true}
|
156
|
+
real_options = default_options.merge(options)
|
157
|
+
Git.new(self.path).fs_mkdir('..')
|
158
|
+
self.git.clone(real_options, path, self.path)
|
159
|
+
Repo.new(self.path)
|
160
|
+
end
|
161
|
+
|
162
|
+
# Public: Return the full Git objects from the given SHAs. Only Commit
|
163
|
+
# objects are parsed for now.
|
164
|
+
#
|
165
|
+
# *shas - Array of String SHAs.
|
166
|
+
#
|
167
|
+
# Returns an Array of Grit objects (Grit::Commit).
|
168
|
+
def batch(*shas)
|
169
|
+
shas.flatten!
|
170
|
+
text = git.native(:cat_file, {:batch => true, :input => (shas * "\n")})
|
171
|
+
parse_batch(text)
|
172
|
+
end
|
173
|
+
|
174
|
+
# Parses `git cat-file --batch` output, returning an array of Grit objects.
|
175
|
+
#
|
176
|
+
# text - Raw String output.
|
177
|
+
#
|
178
|
+
# Returns an Array of Grit objects (Grit::Commit).
|
179
|
+
def parse_batch(text)
|
180
|
+
io = StringIO.new(text)
|
181
|
+
objects = []
|
182
|
+
while line = io.gets
|
183
|
+
sha, type, size = line.split(" ", 3)
|
184
|
+
parser = BATCH_PARSERS[type]
|
185
|
+
if type == 'missing' || !parser
|
186
|
+
io.seek(size.to_i + 1, IO::SEEK_CUR)
|
187
|
+
objects << nil
|
188
|
+
next
|
189
|
+
end
|
190
|
+
|
191
|
+
object = io.read(size.to_i + 1)
|
192
|
+
objects << parser.parse_batch(self, sha, size, object)
|
193
|
+
end
|
194
|
+
objects
|
195
|
+
end
|
196
|
+
|
197
|
+
# The project's description. Taken verbatim from GIT_REPO/description
|
198
|
+
#
|
199
|
+
# Returns String
|
200
|
+
def description
|
201
|
+
self.git.fs_read('description').chomp
|
202
|
+
end
|
203
|
+
|
204
|
+
def blame(file, commit = nil)
|
205
|
+
Blame.new(self, file, commit)
|
206
|
+
end
|
207
|
+
|
208
|
+
# An array of Head objects representing the branch heads in
|
209
|
+
# this repo
|
210
|
+
#
|
211
|
+
# Returns Grit::Head[] (baked)
|
212
|
+
def heads
|
213
|
+
Head.find_all(self)
|
214
|
+
end
|
215
|
+
|
216
|
+
alias_method :branches, :heads
|
217
|
+
|
218
|
+
def get_head(head_name)
|
219
|
+
heads.find { |h| h.name == head_name }
|
220
|
+
end
|
221
|
+
|
222
|
+
def is_head?(head_name)
|
223
|
+
get_head(head_name)
|
224
|
+
end
|
225
|
+
|
226
|
+
# Object reprsenting the current repo head.
|
227
|
+
#
|
228
|
+
# Returns Grit::Head (baked)
|
229
|
+
def head
|
230
|
+
Head.current(self)
|
231
|
+
end
|
232
|
+
|
233
|
+
|
234
|
+
# Commits current index
|
235
|
+
#
|
236
|
+
# Returns true/false if commit worked
|
237
|
+
def commit_index(message)
|
238
|
+
self.git.commit({}, '-m', message)
|
239
|
+
end
|
240
|
+
|
241
|
+
# Commits all tracked and modified files
|
242
|
+
#
|
243
|
+
# Returns true/false if commit worked
|
244
|
+
def commit_all(message)
|
245
|
+
self.git.commit({}, '-a', '-m', message)
|
246
|
+
end
|
247
|
+
|
248
|
+
# Adds files to the index
|
249
|
+
def add(*files)
|
250
|
+
self.git.add({}, *files.flatten)
|
251
|
+
end
|
252
|
+
|
253
|
+
# Remove files from the index
|
254
|
+
def remove(*files)
|
255
|
+
self.git.rm({}, *files.flatten)
|
256
|
+
end
|
257
|
+
|
258
|
+
|
259
|
+
def blame_tree(commit, path = nil)
|
260
|
+
commit_array = self.git.blame_tree(commit, path)
|
261
|
+
|
262
|
+
final_array = {}
|
263
|
+
commit_array.each do |file, sha|
|
264
|
+
final_array[file] = commit(sha)
|
265
|
+
end
|
266
|
+
final_array
|
267
|
+
end
|
268
|
+
|
269
|
+
def status
|
270
|
+
Status.new(self)
|
271
|
+
end
|
272
|
+
|
273
|
+
|
274
|
+
# An array of Tag objects that are available in this repo
|
275
|
+
#
|
276
|
+
# Returns Grit::Tag[] (baked)
|
277
|
+
def tags
|
278
|
+
Tag.find_all(self)
|
279
|
+
end
|
280
|
+
|
281
|
+
# Finds the most recent annotated tag name that is reachable from a commit.
|
282
|
+
#
|
283
|
+
# @repo.recent_tag_name('master')
|
284
|
+
# # => "v1.0-0-abcdef"
|
285
|
+
#
|
286
|
+
# committish - optional commit SHA, branch, or tag name.
|
287
|
+
# options - optional hash of options to pass to git.
|
288
|
+
# Default: {:always => true}
|
289
|
+
# :tags => true # use lightweight tags too.
|
290
|
+
# :abbrev => Integer # number of hex digits to form the unique
|
291
|
+
# name. Defaults to 7.
|
292
|
+
# :long => true # always output tag + commit sha
|
293
|
+
# # see `git describe` docs for more options.
|
294
|
+
#
|
295
|
+
# Returns the String tag name, or just the commit if no tag is
|
296
|
+
# found. If there have been updates since the tag was made, a
|
297
|
+
# suffix is added with the number of commits since the tag, and
|
298
|
+
# the abbreviated object name of the most recent commit.
|
299
|
+
# Returns nil if the committish value is not found.
|
300
|
+
def recent_tag_name(committish = nil, options = {})
|
301
|
+
value = git.describe({:always => true}.update(options), committish.to_s).to_s.strip
|
302
|
+
value.size.zero? ? nil : value
|
303
|
+
end
|
304
|
+
|
305
|
+
# An array of Remote objects representing the remote branches in
|
306
|
+
# this repo
|
307
|
+
#
|
308
|
+
# Returns Grit::Remote[] (baked)
|
309
|
+
def remotes
|
310
|
+
Remote.find_all(self)
|
311
|
+
end
|
312
|
+
|
313
|
+
def remote_list
|
314
|
+
self.git.list_remotes
|
315
|
+
end
|
316
|
+
|
317
|
+
def remote_add(name, url)
|
318
|
+
self.git.remote({}, 'add', name, url)
|
319
|
+
end
|
320
|
+
|
321
|
+
def remote_fetch(name)
|
322
|
+
self.git.fetch({}, name)
|
323
|
+
end
|
324
|
+
|
325
|
+
# takes an array of remote names and last pushed dates
|
326
|
+
# fetches from all of the remotes where the local fetch
|
327
|
+
# date is earlier than the passed date, then records the
|
328
|
+
# last fetched date
|
329
|
+
#
|
330
|
+
# { 'origin' => date,
|
331
|
+
# 'peter => date,
|
332
|
+
# }
|
333
|
+
def remotes_fetch_needed(remotes)
|
334
|
+
remotes.each do |remote, date|
|
335
|
+
# TODO: check against date
|
336
|
+
self.remote_fetch(remote)
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
|
341
|
+
# An array of Ref objects representing the refs in
|
342
|
+
# this repo
|
343
|
+
#
|
344
|
+
# Returns Grit::Ref[] (baked)
|
345
|
+
def refs
|
346
|
+
[ Head.find_all(self), Tag.find_all(self), Remote.find_all(self) ].flatten
|
347
|
+
end
|
348
|
+
|
349
|
+
# returns an array of hashes representing all references
|
350
|
+
def refs_list
|
351
|
+
refs = self.git.for_each_ref
|
352
|
+
refarr = refs.split("\n").map do |line|
|
353
|
+
shatype, ref = line.split("\t")
|
354
|
+
sha, type = shatype.split(' ')
|
355
|
+
[ref, sha, type]
|
356
|
+
end
|
357
|
+
refarr
|
358
|
+
end
|
359
|
+
|
360
|
+
def delete_ref(ref)
|
361
|
+
self.git.native(:update_ref, {:d => true}, ref)
|
362
|
+
end
|
363
|
+
|
364
|
+
def commit_stats(start = 'master', max_count = 10, skip = 0)
|
365
|
+
options = {:max_count => max_count,
|
366
|
+
:skip => skip}
|
367
|
+
|
368
|
+
CommitStats.find_all(self, start, options)
|
369
|
+
end
|
370
|
+
|
371
|
+
# An array of Commit objects representing the history of a given ref/commit
|
372
|
+
# +start+ is the branch/commit name (default 'master')
|
373
|
+
# +max_count+ is the maximum number of commits to return (default 10, use +false+ for all)
|
374
|
+
# +skip+ is the number of commits to skip (default 0)
|
375
|
+
#
|
376
|
+
# Returns Grit::Commit[] (baked)
|
377
|
+
def commits(start = 'master', max_count = 10, skip = 0)
|
378
|
+
options = {:max_count => max_count,
|
379
|
+
:skip => skip}
|
380
|
+
|
381
|
+
Commit.find_all(self, start, options)
|
382
|
+
end
|
383
|
+
|
384
|
+
# The Commits objects that are reachable via +to+ but not via +from+
|
385
|
+
# Commits are returned in chronological order.
|
386
|
+
# +from+ is the branch/commit name of the younger item
|
387
|
+
# +to+ is the branch/commit name of the older item
|
388
|
+
#
|
389
|
+
# Returns Grit::Commit[] (baked)
|
390
|
+
def commits_between(from, to)
|
391
|
+
Commit.find_all(self, "#{from}..#{to}").reverse
|
392
|
+
end
|
393
|
+
|
394
|
+
def fast_forwardable?(to, from)
|
395
|
+
mb = self.git.native(:merge_base, {}, [to, from]).strip
|
396
|
+
mb == from
|
397
|
+
end
|
398
|
+
|
399
|
+
# The Commits objects that are newer than the specified date.
|
400
|
+
# Commits are returned in chronological order.
|
401
|
+
# +start+ is the branch/commit name (default 'master')
|
402
|
+
# +since+ is a string representing a date/time
|
403
|
+
# +extra_options+ is a hash of extra options
|
404
|
+
#
|
405
|
+
# Returns Grit::Commit[] (baked)
|
406
|
+
def commits_since(start = 'master', since = '1970-01-01', extra_options = {})
|
407
|
+
options = {:since => since}.merge(extra_options)
|
408
|
+
|
409
|
+
Commit.find_all(self, start, options)
|
410
|
+
end
|
411
|
+
|
412
|
+
# The number of commits reachable by the given branch/commit
|
413
|
+
# +start+ is the branch/commit name (default 'master')
|
414
|
+
#
|
415
|
+
# Returns Integer
|
416
|
+
def commit_count(start = 'master')
|
417
|
+
Commit.count(self, start)
|
418
|
+
end
|
419
|
+
|
420
|
+
# The Commit object for the specified id
|
421
|
+
# +id+ is the SHA1 identifier of the commit
|
422
|
+
#
|
423
|
+
# Returns Grit::Commit (baked)
|
424
|
+
def commit(id)
|
425
|
+
options = {:max_count => 1}
|
426
|
+
|
427
|
+
Commit.find_all(self, id, options).first
|
428
|
+
end
|
429
|
+
|
430
|
+
# Returns a list of commits that is in +other_repo+ but not in self
|
431
|
+
#
|
432
|
+
# Returns Grit::Commit[]
|
433
|
+
def commit_deltas_from(other_repo, ref = "master", other_ref = "master")
|
434
|
+
# TODO: we should be able to figure out the branch point, rather than
|
435
|
+
# rev-list'ing the whole thing
|
436
|
+
repo_refs = self.git.rev_list({}, ref).strip.split("\n")
|
437
|
+
other_repo_refs = other_repo.git.rev_list({}, other_ref).strip.split("\n")
|
438
|
+
|
439
|
+
(other_repo_refs - repo_refs).map do |refn|
|
440
|
+
Commit.find_all(other_repo, refn, {:max_count => 1}).first
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
444
|
+
def objects(refs)
|
445
|
+
refs = refs.split(/\s+/) if refs.respond_to?(:to_str)
|
446
|
+
self.git.rev_list({:objects => true, :timeout => false}, *refs).
|
447
|
+
split("\n").map { |a| a[0, 40] }
|
448
|
+
end
|
449
|
+
|
450
|
+
def commit_objects(refs)
|
451
|
+
refs = refs.split(/\s+/) if refs.respond_to?(:to_str)
|
452
|
+
self.git.rev_list({:timeout => false}, *refs).split("\n").map { |a| a[0, 40] }
|
453
|
+
end
|
454
|
+
|
455
|
+
def objects_between(ref1, ref2 = nil)
|
456
|
+
if ref2
|
457
|
+
refs = "#{ref2}..#{ref1}"
|
458
|
+
else
|
459
|
+
refs = ref1
|
460
|
+
end
|
461
|
+
self.objects(refs)
|
462
|
+
end
|
463
|
+
|
464
|
+
def diff_objects(commit_sha, parents = true)
|
465
|
+
revs = []
|
466
|
+
Grit.no_quote = true
|
467
|
+
if parents
|
468
|
+
# PARENTS:
|
469
|
+
revs = self.git.diff_tree({:timeout => false, :r => true, :t => true, :m => true}, commit_sha).
|
470
|
+
strip.split("\n").map{ |a| r = a.split(' '); r[3] if r[1] != '160000' }
|
471
|
+
else
|
472
|
+
# NO PARENTS:
|
473
|
+
revs = self.git.native(:ls_tree, {:timeout => false, :r => true, :t => true}, commit_sha).
|
474
|
+
split("\n").map{ |a| a.split("\t").first.split(' ')[2] }
|
475
|
+
end
|
476
|
+
revs << self.commit(commit_sha).tree.id
|
477
|
+
Grit.no_quote = false
|
478
|
+
return revs.uniq.compact
|
479
|
+
end
|
480
|
+
|
481
|
+
# The Tree object for the given treeish reference
|
482
|
+
# +treeish+ is the reference (default 'master')
|
483
|
+
# +paths+ is an optional Array of directory paths to restrict the tree (default [])
|
484
|
+
#
|
485
|
+
# Examples
|
486
|
+
# repo.tree('master', ['lib/'])
|
487
|
+
#
|
488
|
+
# Returns Grit::Tree (baked)
|
489
|
+
def tree(treeish = 'master', paths = [])
|
490
|
+
Tree.construct(self, treeish, paths)
|
491
|
+
end
|
492
|
+
|
493
|
+
# quick way to get a simple array of hashes of the entries
|
494
|
+
# of a single tree or recursive tree listing from a given
|
495
|
+
# sha or reference
|
496
|
+
# +treeish+ is the reference (default 'master')
|
497
|
+
# +options+ is a hash or options - currently only takes :recursive
|
498
|
+
#
|
499
|
+
# Examples
|
500
|
+
# repo.lstree('master', :recursive => true)
|
501
|
+
#
|
502
|
+
# Returns array of hashes - one per tree entry
|
503
|
+
def lstree(treeish = 'master', options = {})
|
504
|
+
# check recursive option
|
505
|
+
opts = {:timeout => false, :l => true, :t => true}
|
506
|
+
if options[:recursive]
|
507
|
+
opts[:r] = true
|
508
|
+
end
|
509
|
+
# mode, type, sha, size, path
|
510
|
+
revs = self.git.native(:ls_tree, opts, treeish)
|
511
|
+
lines = revs.split("\n")
|
512
|
+
revs = lines.map do |a|
|
513
|
+
stuff, path = a.split("\t")
|
514
|
+
mode, type, sha, size = stuff.split(" ")
|
515
|
+
entry = {:mode => mode, :type => type, :sha => sha, :path => path}
|
516
|
+
entry[:size] = size.strip.to_i if size.strip != '-'
|
517
|
+
entry
|
518
|
+
end
|
519
|
+
revs
|
520
|
+
end
|
521
|
+
|
522
|
+
def object(sha)
|
523
|
+
obj = git.get_git_object(sha)
|
524
|
+
raw = Grit::GitRuby::Internal::RawObject.new(obj[:type], obj[:content])
|
525
|
+
object = Grit::GitRuby::GitObject.from_raw(raw)
|
526
|
+
object.sha = sha
|
527
|
+
object
|
528
|
+
end
|
529
|
+
|
530
|
+
# The Blob object for the given id
|
531
|
+
# +id+ is the SHA1 id of the blob
|
532
|
+
#
|
533
|
+
# Returns Grit::Blob (unbaked)
|
534
|
+
def blob(id)
|
535
|
+
Blob.create(self, :id => id)
|
536
|
+
end
|
537
|
+
|
538
|
+
# The commit log for a treeish
|
539
|
+
#
|
540
|
+
# Returns Grit::Commit[]
|
541
|
+
def log(commit = 'master', path = nil, options = {})
|
542
|
+
default_options = {:pretty => "raw"}
|
543
|
+
actual_options = default_options.merge(options)
|
544
|
+
arg = path ? [commit, '--', path] : [commit]
|
545
|
+
commits = self.git.log(actual_options, *arg)
|
546
|
+
Commit.list_from_string(self, commits)
|
547
|
+
end
|
548
|
+
|
549
|
+
# The diff from commit +a+ to commit +b+, optionally restricted to the given file(s)
|
550
|
+
# +a+ is the base commit
|
551
|
+
# +b+ is the other commit
|
552
|
+
# +paths+ is an optional list of file paths on which to restrict the diff
|
553
|
+
def diff(a, b, *paths)
|
554
|
+
diff = self.git.native('diff', {}, a, b, '--', *paths)
|
555
|
+
|
556
|
+
if diff =~ /diff --git a/
|
557
|
+
diff = diff.sub(/.*?(diff --git a)/m, '\1')
|
558
|
+
else
|
559
|
+
diff = ''
|
560
|
+
end
|
561
|
+
Diff.list_from_string(self, diff)
|
562
|
+
end
|
563
|
+
|
564
|
+
# The commit diff for the given commit
|
565
|
+
# +commit+ is the commit name/id
|
566
|
+
#
|
567
|
+
# Returns Grit::Diff[]
|
568
|
+
def commit_diff(commit)
|
569
|
+
Commit.diff(self, commit)
|
570
|
+
end
|
571
|
+
|
572
|
+
# Archive the given treeish
|
573
|
+
# +treeish+ is the treeish name/id (default 'master')
|
574
|
+
# +prefix+ is the optional prefix
|
575
|
+
#
|
576
|
+
# Examples
|
577
|
+
# repo.archive_tar
|
578
|
+
# # => <String containing tar archive>
|
579
|
+
#
|
580
|
+
# repo.archive_tar('a87ff14')
|
581
|
+
# # => <String containing tar archive for commit a87ff14>
|
582
|
+
#
|
583
|
+
# repo.archive_tar('master', 'myproject/')
|
584
|
+
# # => <String containing tar archive and prefixed with 'myproject/'>
|
585
|
+
#
|
586
|
+
# Returns String (containing tar archive)
|
587
|
+
def archive_tar(treeish = 'master', prefix = nil)
|
588
|
+
options = {}
|
589
|
+
options[:prefix] = prefix if prefix
|
590
|
+
self.git.archive(options, treeish)
|
591
|
+
end
|
592
|
+
|
593
|
+
# Archive and gzip the given treeish
|
594
|
+
# +treeish+ is the treeish name/id (default 'master')
|
595
|
+
# +prefix+ is the optional prefix
|
596
|
+
#
|
597
|
+
# Examples
|
598
|
+
# repo.archive_tar_gz
|
599
|
+
# # => <String containing tar.gz archive>
|
600
|
+
#
|
601
|
+
# repo.archive_tar_gz('a87ff14')
|
602
|
+
# # => <String containing tar.gz archive for commit a87ff14>
|
603
|
+
#
|
604
|
+
# repo.archive_tar_gz('master', 'myproject/')
|
605
|
+
# # => <String containing tar.gz archive and prefixed with 'myproject/'>
|
606
|
+
#
|
607
|
+
# Returns String (containing tar.gz archive)
|
608
|
+
def archive_tar_gz(treeish = 'master', prefix = nil)
|
609
|
+
options = {}
|
610
|
+
options[:prefix] = prefix if prefix
|
611
|
+
self.git.archive(options, treeish, "| gzip -n")
|
612
|
+
end
|
613
|
+
|
614
|
+
# Write an archive directly to a file
|
615
|
+
# +treeish+ is the treeish name/id (default 'master')
|
616
|
+
# +prefix+ is the optional prefix (default nil)
|
617
|
+
# +filename+ is the name of the file (default 'archive.tar.gz')
|
618
|
+
# +format+ is the optional format (default nil)
|
619
|
+
# +pipe+ is the command to run the output through (default 'gzip')
|
620
|
+
#
|
621
|
+
# Returns nothing
|
622
|
+
def archive_to_file(treeish = 'master', prefix = nil, filename = 'archive.tar.gz', format = nil, pipe = "gzip")
|
623
|
+
options = {}
|
624
|
+
options[:prefix] = prefix if prefix
|
625
|
+
options[:format] = format if format
|
626
|
+
self.git.archive(options, treeish, "| #{pipe} > #{filename}")
|
627
|
+
end
|
628
|
+
|
629
|
+
# Enable git-daemon serving of this repository by writing the
|
630
|
+
# git-daemon-export-ok file to its git directory
|
631
|
+
#
|
632
|
+
# Returns nothing
|
633
|
+
def enable_daemon_serve
|
634
|
+
self.git.fs_write(DAEMON_EXPORT_FILE, '')
|
635
|
+
end
|
636
|
+
|
637
|
+
# Disable git-daemon serving of this repository by ensuring there is no
|
638
|
+
# git-daemon-export-ok file in its git directory
|
639
|
+
#
|
640
|
+
# Returns nothing
|
641
|
+
def disable_daemon_serve
|
642
|
+
self.git.fs_delete(DAEMON_EXPORT_FILE)
|
643
|
+
end
|
644
|
+
|
645
|
+
def gc_auto
|
646
|
+
self.git.gc({:auto => true})
|
647
|
+
end
|
648
|
+
|
649
|
+
# The list of alternates for this repo
|
650
|
+
#
|
651
|
+
# Returns Array[String] (pathnames of alternates)
|
652
|
+
def alternates
|
653
|
+
alternates_path = "objects/info/alternates"
|
654
|
+
self.git.fs_read(alternates_path).strip.split("\n")
|
655
|
+
rescue Errno::ENOENT
|
656
|
+
[]
|
657
|
+
end
|
658
|
+
|
659
|
+
# Sets the alternates
|
660
|
+
# +alts+ is the Array of String paths representing the alternates
|
661
|
+
#
|
662
|
+
# Returns nothing
|
663
|
+
def alternates=(alts)
|
664
|
+
alts.each do |alt|
|
665
|
+
unless File.exist?(alt)
|
666
|
+
raise "Could not set alternates. Alternate path #{alt} must exist"
|
667
|
+
end
|
668
|
+
end
|
669
|
+
|
670
|
+
if alts.empty?
|
671
|
+
self.git.fs_write('objects/info/alternates', '')
|
672
|
+
else
|
673
|
+
self.git.fs_write('objects/info/alternates', alts.join("\n"))
|
674
|
+
end
|
675
|
+
end
|
676
|
+
|
677
|
+
def config
|
678
|
+
@config ||= Config.new(self)
|
679
|
+
end
|
680
|
+
|
681
|
+
def index
|
682
|
+
Index.new(self)
|
683
|
+
end
|
684
|
+
|
685
|
+
def update_ref(head, commit_sha)
|
686
|
+
return nil if !commit_sha || (commit_sha.size != 40)
|
687
|
+
self.git.fs_write("refs/heads/#{head}", commit_sha)
|
688
|
+
commit_sha
|
689
|
+
end
|
690
|
+
|
691
|
+
# Rename the current repository directory.
|
692
|
+
# +name+ is the new name
|
693
|
+
#
|
694
|
+
# Returns nothing
|
695
|
+
def rename(name)
|
696
|
+
if @bare
|
697
|
+
self.git.fs_move('/', "../#{name}")
|
698
|
+
else
|
699
|
+
self.git.fs_move('/', "../../#{name}")
|
700
|
+
end
|
701
|
+
end
|
702
|
+
|
703
|
+
# Pretty object inspection
|
704
|
+
def inspect
|
705
|
+
%Q{#<Grit::Repo "#{@path}">}
|
706
|
+
end
|
707
|
+
end # Repo
|
708
|
+
|
709
|
+
end # Grit
|