smeagol 0.6.0 → 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- 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,153 @@
|
|
1
|
+
module Grit
|
2
|
+
|
3
|
+
class Status
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
attr_reader :files
|
7
|
+
|
8
|
+
@base = nil
|
9
|
+
@files = nil
|
10
|
+
|
11
|
+
def initialize(base)
|
12
|
+
@base = base
|
13
|
+
construct_status
|
14
|
+
end
|
15
|
+
|
16
|
+
def changed
|
17
|
+
@files.select { |k, f| f.type == 'M' }
|
18
|
+
end
|
19
|
+
|
20
|
+
def added
|
21
|
+
@files.select { |k, f| f.type == 'A' }
|
22
|
+
end
|
23
|
+
|
24
|
+
def deleted
|
25
|
+
@files.select { |k, f| f.type == 'D' }
|
26
|
+
end
|
27
|
+
|
28
|
+
def untracked
|
29
|
+
@files.select { |k, f| f.untracked }
|
30
|
+
end
|
31
|
+
|
32
|
+
def pretty
|
33
|
+
out = ''
|
34
|
+
self.each do |file|
|
35
|
+
out << file.path
|
36
|
+
out << "\n\tsha(r) " + file.sha_repo.to_s + ' ' + file.mode_repo.to_s
|
37
|
+
out << "\n\tsha(i) " + file.sha_index.to_s + ' ' + file.mode_index.to_s
|
38
|
+
out << "\n\ttype " + file.type.to_s
|
39
|
+
out << "\n\tstage " + file.stage.to_s
|
40
|
+
out << "\n\tuntrac " + file.untracked.to_s
|
41
|
+
out << "\n"
|
42
|
+
end
|
43
|
+
out << "\n"
|
44
|
+
out
|
45
|
+
end
|
46
|
+
|
47
|
+
# enumerable method
|
48
|
+
|
49
|
+
def [](file)
|
50
|
+
@files[file]
|
51
|
+
end
|
52
|
+
|
53
|
+
def each
|
54
|
+
@files.each do |k, file|
|
55
|
+
yield file
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class StatusFile
|
60
|
+
attr_accessor :path, :type, :stage, :untracked
|
61
|
+
attr_accessor :mode_index, :mode_repo
|
62
|
+
attr_accessor :sha_index, :sha_repo
|
63
|
+
|
64
|
+
@base = nil
|
65
|
+
|
66
|
+
def initialize(base, hash)
|
67
|
+
@base = base
|
68
|
+
@path = hash[:path]
|
69
|
+
@type = hash[:type]
|
70
|
+
@stage = hash[:stage]
|
71
|
+
@mode_index = hash[:mode_index]
|
72
|
+
@mode_repo = hash[:mode_repo]
|
73
|
+
@sha_index = hash[:sha_index]
|
74
|
+
@sha_repo = hash[:sha_repo]
|
75
|
+
@untracked = hash[:untracked]
|
76
|
+
end
|
77
|
+
|
78
|
+
def blob(type = :index)
|
79
|
+
if type == :repo
|
80
|
+
@base.object(@sha_repo)
|
81
|
+
else
|
82
|
+
@base.object(@sha_index) rescue @base.object(@sha_repo)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def construct_status
|
91
|
+
@files = ls_files
|
92
|
+
|
93
|
+
Dir.chdir(@base.working_dir) do
|
94
|
+
# find untracked in working dir
|
95
|
+
Dir.glob('**/*') do |file|
|
96
|
+
if !@files[file]
|
97
|
+
@files[file] = {:path => file, :untracked => true} if !File.directory?(file)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# find modified in tree
|
102
|
+
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
|
+
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
|
+
end
|
116
|
+
|
117
|
+
# compares the index and the working directory
|
118
|
+
def diff_files
|
119
|
+
hsh = {}
|
120
|
+
@base.git.diff_files.split("\n").each do |line|
|
121
|
+
(info, file) = line.split("\t")
|
122
|
+
(mode_src, mode_dest, sha_src, sha_dest, type) = info.split
|
123
|
+
hsh[file] = {:path => file, :mode_file => mode_src.to_s[1, 7], :mode_index => mode_dest,
|
124
|
+
:sha_file => sha_src, :sha_index => sha_dest, :type => type}
|
125
|
+
end
|
126
|
+
hsh
|
127
|
+
end
|
128
|
+
|
129
|
+
# compares the index and the repository
|
130
|
+
def diff_index(treeish)
|
131
|
+
hsh = {}
|
132
|
+
@base.git.diff_index({}, treeish).split("\n").each do |line|
|
133
|
+
(info, file) = line.split("\t")
|
134
|
+
(mode_src, mode_dest, sha_src, sha_dest, type) = info.split
|
135
|
+
hsh[file] = {:path => file, :mode_repo => mode_src.to_s[1, 7], :mode_index => mode_dest,
|
136
|
+
:sha_repo => sha_src, :sha_index => sha_dest, :type => type}
|
137
|
+
end
|
138
|
+
hsh
|
139
|
+
end
|
140
|
+
|
141
|
+
def ls_files
|
142
|
+
hsh = {}
|
143
|
+
lines = @base.git.ls_files({:stage => true})
|
144
|
+
lines.split("\n").each do |line|
|
145
|
+
(info, file) = line.split("\t")
|
146
|
+
(mode, sha, stage) = info.split
|
147
|
+
hsh[file] = {:path => file, :mode_index => mode, :sha_index => sha, :stage => stage}
|
148
|
+
end
|
149
|
+
hsh
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Grit
|
2
|
+
|
3
|
+
class Submodule
|
4
|
+
attr_reader :id
|
5
|
+
attr_reader :mode
|
6
|
+
attr_reader :name
|
7
|
+
|
8
|
+
# Create a Submodule containing just the specified attributes
|
9
|
+
# +repo+ is the Repo
|
10
|
+
# +atts+ is a Hash of instance variable data
|
11
|
+
#
|
12
|
+
# Returns Grit::Submodule (unbaked)
|
13
|
+
def self.create(repo, atts)
|
14
|
+
self.allocate.create_initialize(repo, atts)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Initializer for Submodule.create
|
18
|
+
# +repo+ is the Repo
|
19
|
+
# +atts+ is a Hash of instance variable data
|
20
|
+
#
|
21
|
+
# Returns Grit::Submodule
|
22
|
+
def create_initialize(repo, atts)
|
23
|
+
@repo = repo
|
24
|
+
atts.each do |k, v|
|
25
|
+
instance_variable_set("@#{k}".to_sym, v)
|
26
|
+
end
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
# The url of this submodule
|
31
|
+
# +ref+ is the committish that should be used to look up the url
|
32
|
+
#
|
33
|
+
# Returns String
|
34
|
+
def url(ref)
|
35
|
+
config = self.class.config(@repo, ref)
|
36
|
+
|
37
|
+
lookup = config.keys.inject({}) do |acc, key|
|
38
|
+
id = config[key]['id']
|
39
|
+
acc[id] = config[key]['url']
|
40
|
+
acc
|
41
|
+
end
|
42
|
+
|
43
|
+
lookup[@id]
|
44
|
+
end
|
45
|
+
|
46
|
+
# The configuration information for the given +repo+
|
47
|
+
# +repo+ is the Repo
|
48
|
+
# +ref+ is the committish (defaults to 'master')
|
49
|
+
#
|
50
|
+
# Returns a Hash of { <path:String> => { 'url' => <url:String>, 'id' => <id:String> } }
|
51
|
+
# Returns {} if no .gitmodules file was found
|
52
|
+
def self.config(repo, ref = "master")
|
53
|
+
commit = repo.commit(ref)
|
54
|
+
blob = commit.tree/'.gitmodules'
|
55
|
+
return {} unless blob
|
56
|
+
|
57
|
+
lines = blob.data.gsub(/\r\n?/, "\n" ).split("\n")
|
58
|
+
|
59
|
+
config = {}
|
60
|
+
current = nil
|
61
|
+
|
62
|
+
lines.each do |line|
|
63
|
+
if line =~ /^\[submodule "(.+)"\]$/
|
64
|
+
current = $1
|
65
|
+
config[current] = {}
|
66
|
+
config[current]['id'] = (commit.tree/current).id
|
67
|
+
elsif line =~ /^\t(\w+) = (.+)$/
|
68
|
+
config[current][$1] = $2
|
69
|
+
config[current]['id'] = (commit.tree/$2).id if $1 == 'path'
|
70
|
+
else
|
71
|
+
# ignore
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
config
|
76
|
+
end
|
77
|
+
|
78
|
+
def basename
|
79
|
+
File.basename(name)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Pretty object inspection
|
83
|
+
def inspect
|
84
|
+
%Q{#<Grit::Submodule "#{@id}">}
|
85
|
+
end
|
86
|
+
end # Submodule
|
87
|
+
|
88
|
+
end # Grit
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module Grit
|
2
|
+
|
3
|
+
class Tag < Ref
|
4
|
+
extend Lazy
|
5
|
+
|
6
|
+
lazy_reader :message
|
7
|
+
lazy_reader :tagger
|
8
|
+
lazy_reader :tag_date
|
9
|
+
|
10
|
+
def self.find_all(repo, options = {})
|
11
|
+
refs = repo.git.refs(options, prefix)
|
12
|
+
refs.split("\n").map do |ref|
|
13
|
+
name, id = *ref.split(' ')
|
14
|
+
sha = repo.git.commit_from_sha(id)
|
15
|
+
raise "Unknown object type." if sha == ''
|
16
|
+
commit = Commit.create(repo, :id => sha)
|
17
|
+
new(name, commit)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Writes a new tag object from a hash
|
22
|
+
# +repo+ is a Grit repo
|
23
|
+
# +hash+ is the hash of tag values
|
24
|
+
#
|
25
|
+
# Returns a hash with +sha+ and +size+ of the created object
|
26
|
+
def self.create_tag_object(repo, hash, default_actor = nil)
|
27
|
+
tagger = hash[:tagger]
|
28
|
+
if !tagger
|
29
|
+
tagger = default_actor ? default_actor : Actor.new("none", "none@none")
|
30
|
+
tagger_date = Time.now
|
31
|
+
else
|
32
|
+
tagger_date = tagger[:date] ? Time.parse(tagger[:date]) : Time.now
|
33
|
+
tagger = Actor.new(tagger[:name], tagger[:email])
|
34
|
+
end
|
35
|
+
data = []
|
36
|
+
data << "object #{hash[:object]}"
|
37
|
+
data << "type #{hash[:type]}"
|
38
|
+
data << "tag #{hash[:tag]}"
|
39
|
+
data << "tagger #{tagger.output(tagger_date)}"
|
40
|
+
data << ""
|
41
|
+
data << hash[:message]
|
42
|
+
data = data.join("\n")
|
43
|
+
sha = repo.git.put_raw_object(data, 'tag')
|
44
|
+
{ :sha => sha, :size => data.size }
|
45
|
+
end
|
46
|
+
|
47
|
+
# Parses the results from `cat-file -p`
|
48
|
+
#
|
49
|
+
# data - String tag object data. Example:
|
50
|
+
# object 7bcc0ee821cdd133d8a53e8e7173a334fef448aa
|
51
|
+
# type commit
|
52
|
+
# tag v0.7.0
|
53
|
+
# tagger USER <EMAIL> DATE
|
54
|
+
#
|
55
|
+
# v0.7.0
|
56
|
+
#
|
57
|
+
# Returns parsed Hash. Example:
|
58
|
+
# {:message => "...", :tagger => "bob", :tag_date => ...}
|
59
|
+
def self.parse_tag_data(data)
|
60
|
+
return unless data =~ /^object/
|
61
|
+
parsed = {}
|
62
|
+
lines = data.split("\n")
|
63
|
+
parsed[:object] = lines.shift.sub(/^object /, '')
|
64
|
+
parsed[:type] = lines.shift.sub(/^type /, '')
|
65
|
+
parsed[:tag] = lines.shift.sub(/^tag /, '')
|
66
|
+
author_line = lines.shift
|
67
|
+
parsed[:tagger], parsed[:tag_date] = Commit.actor(author_line)
|
68
|
+
if !parsed[:tagger] || !parsed[:tagger].name
|
69
|
+
parsed[:tag_date] ||= Time.utc(1970)
|
70
|
+
parsed[:tagger] = Actor.from_string(author_line.sub(/^tagger /, ''))
|
71
|
+
end
|
72
|
+
lines.shift # blank line
|
73
|
+
parsed[:message] = []
|
74
|
+
while lines.first && lines.first !~ /-----BEGIN PGP SIGNATURE-----/
|
75
|
+
parsed[:message] << lines.shift
|
76
|
+
end
|
77
|
+
parsed[:message] = parsed[:message] * "\n"
|
78
|
+
parsed[:pgp] = []
|
79
|
+
while lines.first
|
80
|
+
parsed[:pgp] << lines.shift
|
81
|
+
end
|
82
|
+
parsed[:pgp] = parsed[:pgp] * "\n"
|
83
|
+
parsed
|
84
|
+
end
|
85
|
+
|
86
|
+
def lazy_source
|
87
|
+
data = commit.repo.git.cat_ref({:p => true}, name)
|
88
|
+
@message = commit.short_message
|
89
|
+
@tagger = commit.author
|
90
|
+
@tag_date = commit.authored_date
|
91
|
+
return self if data.empty?
|
92
|
+
|
93
|
+
if parsed = self.class.parse_tag_data(data)
|
94
|
+
@message = parsed[:message]
|
95
|
+
@tagger = parsed[:tagger]
|
96
|
+
@tag_date = parsed[:tag_date]
|
97
|
+
end
|
98
|
+
self
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module Grit
|
2
|
+
|
3
|
+
class Tree
|
4
|
+
extend Lazy
|
5
|
+
|
6
|
+
lazy_reader :contents
|
7
|
+
attr_reader :id
|
8
|
+
attr_reader :mode
|
9
|
+
attr_reader :name
|
10
|
+
|
11
|
+
# Construct the contents of the tree
|
12
|
+
# +repo+ is the Repo
|
13
|
+
# +treeish+ is the reference
|
14
|
+
# +paths+ is an optional Array of directory paths to restrict the tree
|
15
|
+
#
|
16
|
+
# Returns Grit::Tree (baked)
|
17
|
+
def self.construct(repo, treeish, paths = [])
|
18
|
+
output = repo.git.ls_tree({:raise => true}, treeish, *paths)
|
19
|
+
self.allocate.construct_initialize(repo, treeish, output)
|
20
|
+
end
|
21
|
+
|
22
|
+
def construct_initialize(repo, id, text)
|
23
|
+
@repo = repo
|
24
|
+
@id = id
|
25
|
+
@contents = []
|
26
|
+
|
27
|
+
text.split("\n").each do |line|
|
28
|
+
@contents << content_from_string(repo, line)
|
29
|
+
end
|
30
|
+
@contents.compact!
|
31
|
+
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def lazy_source
|
36
|
+
Tree.construct(@repo, @id, [])
|
37
|
+
end
|
38
|
+
|
39
|
+
# Create an unbaked Tree containing just the specified attributes
|
40
|
+
# +repo+ is the Repo
|
41
|
+
# +atts+ is a Hash of instance variable data
|
42
|
+
#
|
43
|
+
# Returns Grit::Tree (unbaked)
|
44
|
+
def self.create(repo, atts)
|
45
|
+
self.allocate.create_initialize(repo, atts)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Initializer for Tree.create
|
49
|
+
# +repo+ is the Repo
|
50
|
+
# +atts+ is a Hash of instance variable data
|
51
|
+
#
|
52
|
+
# Returns Grit::Tree (unbaked)
|
53
|
+
def create_initialize(repo, atts)
|
54
|
+
@repo = repo
|
55
|
+
|
56
|
+
atts.each do |k, v|
|
57
|
+
instance_variable_set("@#{k}", v)
|
58
|
+
end
|
59
|
+
self
|
60
|
+
end
|
61
|
+
|
62
|
+
# Parse a content item and create the appropriate object
|
63
|
+
# +repo+ is the Repo
|
64
|
+
# +text+ is the single line containing the items data in `git ls-tree` format
|
65
|
+
#
|
66
|
+
# Returns Grit::Blob or Grit::Tree
|
67
|
+
def content_from_string(repo, text)
|
68
|
+
mode, type, id, name = text.split(/ |\t/, 4)
|
69
|
+
case type
|
70
|
+
when "tree"
|
71
|
+
Tree.create(repo, :id => id, :mode => mode, :name => name)
|
72
|
+
when "blob"
|
73
|
+
Blob.create(repo, :id => id, :mode => mode, :name => name)
|
74
|
+
when "link"
|
75
|
+
Blob.create(repo, :id => id, :mode => mode, :name => name)
|
76
|
+
when "commit"
|
77
|
+
Submodule.create(repo, :id => id, :mode => mode, :name => name)
|
78
|
+
else
|
79
|
+
raise Grit::InvalidObjectType, type
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Find the named object in this tree's contents
|
84
|
+
#
|
85
|
+
# Examples
|
86
|
+
# Repo.new('/path/to/grit').tree/'lib'
|
87
|
+
# # => #<Grit::Tree "6cc23ee138be09ff8c28b07162720018b244e95e">
|
88
|
+
# Repo.new('/path/to/grit').tree/'README.txt'
|
89
|
+
# # => #<Grit::Blob "8b1e02c0fb554eed2ce2ef737a68bb369d7527df">
|
90
|
+
#
|
91
|
+
# Returns Grit::Blob or Grit::Tree or nil if not found
|
92
|
+
def /(file)
|
93
|
+
if file =~ /\//
|
94
|
+
file.split("/").inject(self) { |acc, x| acc/x } rescue nil
|
95
|
+
else
|
96
|
+
self.contents.find { |c| c.name == file }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def basename
|
101
|
+
File.basename(name)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Pretty object inspection
|
105
|
+
def inspect
|
106
|
+
%Q{#<Grit::Tree "#{@id}">}
|
107
|
+
end
|
108
|
+
|
109
|
+
# Find only Tree objects from contents
|
110
|
+
def trees
|
111
|
+
contents.select {|v| v.kind_of? Tree}
|
112
|
+
end
|
113
|
+
|
114
|
+
# Find only Blob objects from contents
|
115
|
+
def blobs
|
116
|
+
contents.select {|v| v.kind_of? Blob}
|
117
|
+
end
|
118
|
+
|
119
|
+
# Compares trees by name
|
120
|
+
def <=>(other)
|
121
|
+
name <=> other.name
|
122
|
+
end
|
123
|
+
end # Tree
|
124
|
+
|
125
|
+
end # Grit
|