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,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
|