gitlab_git 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/gitlab_git/blame.rb +23 -0
- data/lib/gitlab_git/blob.rb +44 -0
- data/lib/gitlab_git/commit.rb +140 -0
- data/lib/gitlab_git/compare.rb +35 -0
- data/lib/gitlab_git/diff.rb +63 -0
- data/lib/gitlab_git/popen.rb +20 -0
- data/lib/gitlab_git/repository.rb +225 -0
- data/lib/gitlab_git/stats.rb +75 -0
- data/lib/gitlab_git/tree.rb +52 -0
- metadata +10 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c8f85ff5ac6e3846697e0a4e5c479cd608bffdd
|
4
|
+
data.tar.gz: 29c128efbfffb375d443274f6c49b3641443321e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ab12c3ab17f22500f9483f4cabbd01aa94f098b11990373399df73676e9756c809f1af6ce957e8608d5e0286bf2d69c6ef3db613d5b92698215e997bd40a3376
|
7
|
+
data.tar.gz: 5bb1ab43d66022fce5d2c20eda9b17270a0f0d0ddea1f600771c583054c78b1a05258d140edcb36515597f9b8e82c03e766ef8e3c22fa53bff91c168ea5d66b0
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Gitlab
|
2
|
+
module Git
|
3
|
+
class Blame
|
4
|
+
|
5
|
+
attr_accessor :repository, :sha, :path
|
6
|
+
|
7
|
+
def initialize(repository, sha, path)
|
8
|
+
@repository, @sha, @path = repository, sha, path
|
9
|
+
end
|
10
|
+
|
11
|
+
def each
|
12
|
+
raw_blame = Grit::Blob.blame(repository.repo, sha, path)
|
13
|
+
|
14
|
+
raw_blame.each do |commit, lines|
|
15
|
+
next unless commit
|
16
|
+
|
17
|
+
commit = Gitlab::Git::Commit.new(commit)
|
18
|
+
yield(commit, lines)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Gitlab
|
2
|
+
module Git
|
3
|
+
class Blob
|
4
|
+
include Linguist::BlobHelper
|
5
|
+
|
6
|
+
attr_accessor :raw_blob
|
7
|
+
|
8
|
+
def initialize(repository, sha, ref, path)
|
9
|
+
@repository, @sha, @ref = repository, sha, ref
|
10
|
+
|
11
|
+
@commit = @repository.commit(sha)
|
12
|
+
@raw_blob = @repository.tree(@commit, path)
|
13
|
+
end
|
14
|
+
|
15
|
+
def data
|
16
|
+
if raw_blob
|
17
|
+
raw_blob.data
|
18
|
+
else
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def name
|
24
|
+
raw_blob.name
|
25
|
+
end
|
26
|
+
|
27
|
+
def exists?
|
28
|
+
raw_blob
|
29
|
+
end
|
30
|
+
|
31
|
+
def empty?
|
32
|
+
!data || data == ''
|
33
|
+
end
|
34
|
+
|
35
|
+
def mode
|
36
|
+
raw_blob.mode
|
37
|
+
end
|
38
|
+
|
39
|
+
def size
|
40
|
+
raw_blob.size
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
# Gitlab::Git::Commit is a wrapper around native Grit::Commit object
|
2
|
+
# We dont want to use grit objects inside app/
|
3
|
+
# It helps us easily migrate to rugged in future
|
4
|
+
module Gitlab
|
5
|
+
module Git
|
6
|
+
class Commit
|
7
|
+
attr_accessor :raw_commit, :head, :refs,
|
8
|
+
:id, :authored_date, :committed_date, :message,
|
9
|
+
:author_name, :author_email, :parent_ids,
|
10
|
+
:committer_name, :committer_email
|
11
|
+
|
12
|
+
def initialize(raw_commit, head = nil)
|
13
|
+
raise "Nil as raw commit passed" unless raw_commit
|
14
|
+
|
15
|
+
if raw_commit.is_a?(Hash)
|
16
|
+
init_from_hash(raw_commit)
|
17
|
+
else
|
18
|
+
init_from_grit(raw_commit)
|
19
|
+
end
|
20
|
+
|
21
|
+
@head = head
|
22
|
+
end
|
23
|
+
|
24
|
+
def serialize_keys
|
25
|
+
@serialize_keys ||= %w(id authored_date committed_date author_name author_email committer_name committer_email message parent_ids).map(&:to_sym)
|
26
|
+
end
|
27
|
+
|
28
|
+
def sha
|
29
|
+
id
|
30
|
+
end
|
31
|
+
|
32
|
+
def short_id(length = 10)
|
33
|
+
id.to_s[0..length]
|
34
|
+
end
|
35
|
+
|
36
|
+
def safe_message
|
37
|
+
@safe_message ||= message
|
38
|
+
end
|
39
|
+
|
40
|
+
def created_at
|
41
|
+
committed_date
|
42
|
+
end
|
43
|
+
|
44
|
+
# Was this commit committed by a different person than the original author?
|
45
|
+
def different_committer?
|
46
|
+
author_name != committer_name || author_email != committer_email
|
47
|
+
end
|
48
|
+
|
49
|
+
def parent_id
|
50
|
+
parent_ids.first
|
51
|
+
end
|
52
|
+
|
53
|
+
# Shows the diff between the commit's parent and the commit.
|
54
|
+
#
|
55
|
+
# Cuts out the header and stats from #to_patch and returns only the diff.
|
56
|
+
def to_diff
|
57
|
+
# see Grit::Commit#show
|
58
|
+
patch = to_patch
|
59
|
+
|
60
|
+
# discard lines before the diff
|
61
|
+
lines = patch.split("\n")
|
62
|
+
while !lines.first.start_with?("diff --git") do
|
63
|
+
lines.shift
|
64
|
+
end
|
65
|
+
lines.pop if lines.last =~ /^[\d.]+$/ # Git version
|
66
|
+
lines.pop if lines.last == "-- " # end of diff
|
67
|
+
lines.join("\n")
|
68
|
+
end
|
69
|
+
|
70
|
+
def has_zero_stats?
|
71
|
+
stats.total.zero?
|
72
|
+
rescue
|
73
|
+
true
|
74
|
+
end
|
75
|
+
|
76
|
+
def no_commit_message
|
77
|
+
"--no commit message"
|
78
|
+
end
|
79
|
+
|
80
|
+
def to_hash
|
81
|
+
hash = {}
|
82
|
+
|
83
|
+
keys = serialize_keys
|
84
|
+
|
85
|
+
keys.each do |key|
|
86
|
+
hash[key] = send(key)
|
87
|
+
end
|
88
|
+
|
89
|
+
hash
|
90
|
+
end
|
91
|
+
|
92
|
+
def date
|
93
|
+
committed_date
|
94
|
+
end
|
95
|
+
|
96
|
+
def diffs
|
97
|
+
raw_commit.diffs.map { |diff| Gitlab::Git::Diff.new(diff) }
|
98
|
+
end
|
99
|
+
|
100
|
+
def parents
|
101
|
+
raw_commit.parents
|
102
|
+
end
|
103
|
+
|
104
|
+
def tree
|
105
|
+
raw_commit.tree
|
106
|
+
end
|
107
|
+
|
108
|
+
def stats
|
109
|
+
raw_commit.tree
|
110
|
+
end
|
111
|
+
|
112
|
+
def to_patch
|
113
|
+
raw_commit.to_patch
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def init_from_grit(grit)
|
119
|
+
@raw_commit = grit
|
120
|
+
@id = grit.id
|
121
|
+
@message = grit.message
|
122
|
+
@authored_date = grit.authored_date
|
123
|
+
@committed_date = grit.committed_date
|
124
|
+
@author_name = grit.author.name
|
125
|
+
@author_email = grit.author.email
|
126
|
+
@committer_name = grit.committer.name
|
127
|
+
@committer_email = grit.committer.email
|
128
|
+
@parent_ids = grit.parents.map(&:id)
|
129
|
+
end
|
130
|
+
|
131
|
+
def init_from_hash(hash)
|
132
|
+
raw_commit = hash.symbolize_keys
|
133
|
+
|
134
|
+
serialize_keys.each do |key|
|
135
|
+
send(:"#{key}=", raw_commit[key.to_sym])
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Gitlab
|
2
|
+
module Git
|
3
|
+
class Compare
|
4
|
+
attr_accessor :commits, :commit, :diffs, :same
|
5
|
+
|
6
|
+
def initialize(repository, from, to)
|
7
|
+
@commits, @diffs = [], []
|
8
|
+
@commit = nil
|
9
|
+
@same = false
|
10
|
+
|
11
|
+
return unless from && to
|
12
|
+
|
13
|
+
first = repository.commit(to.try(:strip))
|
14
|
+
last = repository.commit(from.try(:strip))
|
15
|
+
|
16
|
+
return unless first && last
|
17
|
+
|
18
|
+
if first.id == last.id
|
19
|
+
@same = true
|
20
|
+
return
|
21
|
+
end
|
22
|
+
|
23
|
+
@commit = first
|
24
|
+
@commits = repository.commits_between(last.id, first.id)
|
25
|
+
|
26
|
+
@diffs = if @commits.size > 100
|
27
|
+
[]
|
28
|
+
else
|
29
|
+
repository.repo.diff(last.id, first.id) rescue []
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# Gitlab::Git::Diff is a wrapper around native Grit::Diff object
|
2
|
+
# We dont want to use grit objects inside app/
|
3
|
+
# It helps us easily migrate to rugged in future
|
4
|
+
module Gitlab
|
5
|
+
module Git
|
6
|
+
class Diff
|
7
|
+
BROKEN_DIFF = "--broken-diff"
|
8
|
+
|
9
|
+
attr_accessor :raw_diff
|
10
|
+
|
11
|
+
# Diff properties
|
12
|
+
attr_accessor :old_path, :new_path, :a_mode, :b_mode, :diff
|
13
|
+
|
14
|
+
# Stats properties
|
15
|
+
attr_accessor :new_file, :renamed_file, :deleted_file
|
16
|
+
|
17
|
+
def initialize(raw_diff)
|
18
|
+
raise "Nil as raw diff passed" unless raw_diff
|
19
|
+
|
20
|
+
if raw_diff.is_a?(Hash)
|
21
|
+
init_from_hash(raw_diff)
|
22
|
+
else
|
23
|
+
init_from_grit(raw_diff)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def serialize_keys
|
28
|
+
@serialize_keys ||= %w(diff new_path old_path a_mode b_mode new_file renamed_file deleted_file).map(&:to_sym)
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_hash
|
32
|
+
hash = {}
|
33
|
+
|
34
|
+
keys = serialize_keys
|
35
|
+
|
36
|
+
keys.each do |key|
|
37
|
+
hash[key] = send(key)
|
38
|
+
end
|
39
|
+
|
40
|
+
hash
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def init_from_grit(grit)
|
46
|
+
@raw_diff = grit
|
47
|
+
|
48
|
+
serialize_keys.each do |key|
|
49
|
+
send(:"#{key}=", grit.send(key))
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def init_from_hash(hash)
|
54
|
+
raw_diff = hash.symbolize_keys
|
55
|
+
|
56
|
+
serialize_keys.each do |key|
|
57
|
+
send(:"#{key}=", raw_diff[key.to_sym])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Gitlab
|
2
|
+
module Git
|
3
|
+
module Popen
|
4
|
+
def popen(cmd, path)
|
5
|
+
vars = { "PWD" => path }
|
6
|
+
options = { :chdir => path }
|
7
|
+
|
8
|
+
@cmd_output = ""
|
9
|
+
@cmd_status = 0
|
10
|
+
Open3.popen3(vars, cmd, options) do |stdin, stdout, stderr, wait_thr|
|
11
|
+
@cmd_status = wait_thr.value.exitstatus
|
12
|
+
@cmd_output << stdout.read
|
13
|
+
@cmd_output << stderr.read
|
14
|
+
end
|
15
|
+
|
16
|
+
return @cmd_output, @cmd_status
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,225 @@
|
|
1
|
+
# Gitlab::Git::Gitlab::Git::Commit is a wrapper around native Grit::Repository object
|
2
|
+
# We dont want to use grit objects inside app/
|
3
|
+
# It helps us easily migrate to rugged in future
|
4
|
+
module Gitlab
|
5
|
+
module Git
|
6
|
+
class Repository
|
7
|
+
include Gitlab::Git::Popen
|
8
|
+
|
9
|
+
class NoRepository < StandardError; end
|
10
|
+
|
11
|
+
class << self
|
12
|
+
attr_accessor :repos_path
|
13
|
+
end
|
14
|
+
|
15
|
+
# Repository directory name with namespace direcotry
|
16
|
+
# Examples:
|
17
|
+
# gitlab/gitolite
|
18
|
+
# diaspora
|
19
|
+
#
|
20
|
+
attr_accessor :path_with_namespace
|
21
|
+
|
22
|
+
# Grit repo object
|
23
|
+
attr_accessor :repo
|
24
|
+
|
25
|
+
# Default branch in the repository
|
26
|
+
attr_accessor :root_ref
|
27
|
+
|
28
|
+
def initialize(path_with_namespace, root_ref = 'master')
|
29
|
+
@root_ref = root_ref || "master"
|
30
|
+
@path_with_namespace = path_with_namespace
|
31
|
+
|
32
|
+
# Init grit repo object
|
33
|
+
repo
|
34
|
+
end
|
35
|
+
|
36
|
+
def raw
|
37
|
+
repo
|
38
|
+
end
|
39
|
+
|
40
|
+
def path_to_repo
|
41
|
+
@path_to_repo ||= File.join(repos_path, "#{path_with_namespace}.git")
|
42
|
+
end
|
43
|
+
|
44
|
+
def repos_path
|
45
|
+
self.class.repos_path
|
46
|
+
end
|
47
|
+
|
48
|
+
def repo
|
49
|
+
@repo ||= Grit::Repo.new(path_to_repo)
|
50
|
+
rescue Grit::NoSuchPathError
|
51
|
+
raise NoRepository.new('no repository for such path')
|
52
|
+
end
|
53
|
+
|
54
|
+
def commit(commit_id = nil)
|
55
|
+
commit = if commit_id
|
56
|
+
# Find repo.refs first,
|
57
|
+
# because if commit_id is "tag name",
|
58
|
+
# repo.commit(commit_id) returns wrong commit sha
|
59
|
+
# that is git tag object sha.
|
60
|
+
ref = repo.refs.find {|r| r.name == commit_id}
|
61
|
+
if ref
|
62
|
+
ref.commit
|
63
|
+
else
|
64
|
+
repo.commit(commit_id)
|
65
|
+
end
|
66
|
+
else
|
67
|
+
repo.commits(root_ref).first
|
68
|
+
end
|
69
|
+
|
70
|
+
decorate_commit(commit) if commit
|
71
|
+
end
|
72
|
+
|
73
|
+
def commits_with_refs(n = 20)
|
74
|
+
commits = repo.branches.map { |ref| decorate_commit(ref.commit, ref) }
|
75
|
+
|
76
|
+
commits.sort! do |x, y|
|
77
|
+
y.committed_date <=> x.committed_date
|
78
|
+
end
|
79
|
+
|
80
|
+
commits[0..n]
|
81
|
+
end
|
82
|
+
|
83
|
+
def commits(ref, path = nil, limit = nil, offset = nil)
|
84
|
+
if path && path != ''
|
85
|
+
repo.log(ref, path, max_count: limit, skip: offset, follow: true)
|
86
|
+
elsif limit && offset
|
87
|
+
repo.commits(ref, limit.to_i, offset.to_i)
|
88
|
+
else
|
89
|
+
repo.commits(ref)
|
90
|
+
end.map{ |c| decorate_commit(c) }
|
91
|
+
end
|
92
|
+
|
93
|
+
def commits_between(from, to)
|
94
|
+
repo.commits_between(from, to).map { |c| decorate_commit(c) }
|
95
|
+
end
|
96
|
+
|
97
|
+
def last_commit_for(ref, path = nil)
|
98
|
+
commits(ref, path, 1).first
|
99
|
+
end
|
100
|
+
|
101
|
+
# Returns an Array of branch names
|
102
|
+
# sorted by name ASC
|
103
|
+
def branch_names
|
104
|
+
branches.map(&:name)
|
105
|
+
end
|
106
|
+
|
107
|
+
# Returns an Array of Branches
|
108
|
+
def branches
|
109
|
+
repo.branches.sort_by(&:name)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Returns an Array of tag names
|
113
|
+
def tag_names
|
114
|
+
repo.tags.collect(&:name).sort.reverse
|
115
|
+
end
|
116
|
+
|
117
|
+
# Returns an Array of Tags
|
118
|
+
def tags
|
119
|
+
repo.tags.sort_by(&:name).reverse
|
120
|
+
end
|
121
|
+
|
122
|
+
# Returns an Array of branch and tag names
|
123
|
+
def ref_names
|
124
|
+
[branch_names + tag_names].flatten
|
125
|
+
end
|
126
|
+
|
127
|
+
def heads
|
128
|
+
@heads ||= repo.heads
|
129
|
+
end
|
130
|
+
|
131
|
+
def tree(fcommit, path = nil)
|
132
|
+
fcommit = commit if fcommit == :head
|
133
|
+
tree = fcommit.tree
|
134
|
+
path ? (tree / path) : tree
|
135
|
+
end
|
136
|
+
|
137
|
+
def has_commits?
|
138
|
+
!!commit
|
139
|
+
rescue Grit::NoSuchPathError
|
140
|
+
false
|
141
|
+
end
|
142
|
+
|
143
|
+
def empty?
|
144
|
+
!has_commits?
|
145
|
+
end
|
146
|
+
|
147
|
+
# Discovers the default branch based on the repository's available branches
|
148
|
+
#
|
149
|
+
# - If no branches are present, returns nil
|
150
|
+
# - If one branch is present, returns its name
|
151
|
+
# - If two or more branches are present, returns the one that has a name
|
152
|
+
# matching root_ref (default_branch or 'master' if default_branch is nil)
|
153
|
+
def discover_default_branch
|
154
|
+
if branch_names.length == 0
|
155
|
+
nil
|
156
|
+
elsif branch_names.length == 1
|
157
|
+
branch_names.first
|
158
|
+
else
|
159
|
+
branch_names.select { |v| v == root_ref }.first
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
# Archive Project to .tar.gz
|
164
|
+
#
|
165
|
+
# Already packed repo archives stored at
|
166
|
+
# app_root/tmp/repositories/project_name/project_name-commit-id.tag.gz
|
167
|
+
#
|
168
|
+
def archive_repo(ref)
|
169
|
+
ref = ref || self.root_ref
|
170
|
+
commit = self.commit(ref)
|
171
|
+
return nil unless commit
|
172
|
+
|
173
|
+
# Build file path
|
174
|
+
file_name = self.path_with_namespace.gsub("/","_") + "-" + commit.id.to_s + ".tar.gz"
|
175
|
+
storage_path = Rails.root.join("tmp", "repositories")
|
176
|
+
file_path = File.join(storage_path, self.path_with_namespace, file_name)
|
177
|
+
|
178
|
+
# Put files into a directory before archiving
|
179
|
+
prefix = File.basename(self.path_with_namespace) + "/"
|
180
|
+
|
181
|
+
# Create file if not exists
|
182
|
+
unless File.exists?(file_path)
|
183
|
+
FileUtils.mkdir_p File.dirname(file_path)
|
184
|
+
file = self.repo.archive_to_file(ref, prefix, file_path)
|
185
|
+
end
|
186
|
+
|
187
|
+
file_path
|
188
|
+
end
|
189
|
+
|
190
|
+
# Return repo size in megabytes
|
191
|
+
# Cached in redis
|
192
|
+
def size
|
193
|
+
Rails.cache.fetch(cache_key(:size)) do
|
194
|
+
size = popen('du -s', path_to_repo).first.strip.to_i
|
195
|
+
(size.to_f / 1024).round(2)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def expire_cache
|
200
|
+
Rails.cache.delete(cache_key(:size))
|
201
|
+
end
|
202
|
+
|
203
|
+
def cache_key(type)
|
204
|
+
"#{type}:#{path_with_namespace}"
|
205
|
+
end
|
206
|
+
|
207
|
+
def diffs_between(source_branch, target_branch)
|
208
|
+
# Only show what is new in the source branch compared to the target branch, not the other way around.
|
209
|
+
# The linex below with merge_base is equivalent to diff with three dots (git diff branch1...branch2)
|
210
|
+
# From the git documentation: "git diff A...B" is equivalent to "git diff $(git-merge-base A B) B"
|
211
|
+
common_commit = repo.git.native(:merge_base, {}, [target_branch, source_branch]).strip
|
212
|
+
repo.diff(common_commit, source_branch).map { |diff| Gitlab::Git::Diff.new(diff) }
|
213
|
+
|
214
|
+
rescue Grit::Git::GitTimeout
|
215
|
+
[Gitlab::Git::Diff::BROKEN_DIFF]
|
216
|
+
end
|
217
|
+
|
218
|
+
protected
|
219
|
+
|
220
|
+
def decorate_commit(commit, ref = nil)
|
221
|
+
Gitlab::Git::Commit.new(commit, ref)
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Gitlab
|
2
|
+
module Git
|
3
|
+
class Stats
|
4
|
+
attr_accessor :repo, :ref
|
5
|
+
|
6
|
+
def initialize repo, ref
|
7
|
+
@repo, @ref = repo, ref
|
8
|
+
end
|
9
|
+
|
10
|
+
def authors
|
11
|
+
@authors ||= collect_authors
|
12
|
+
end
|
13
|
+
|
14
|
+
def commits_count
|
15
|
+
@commits_count ||= repo.commit_count(ref)
|
16
|
+
end
|
17
|
+
|
18
|
+
def files_count
|
19
|
+
args = [ref, '-r', '--name-only' ]
|
20
|
+
repo.git.run(nil, 'ls-tree', nil, {}, args).split("\n").count
|
21
|
+
end
|
22
|
+
|
23
|
+
def authors_count
|
24
|
+
authors.size
|
25
|
+
end
|
26
|
+
|
27
|
+
def graph
|
28
|
+
@graph ||= build_graph
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
def collect_authors
|
34
|
+
shortlog = repo.git.shortlog({e: true, s: true }, ref)
|
35
|
+
|
36
|
+
authors = []
|
37
|
+
|
38
|
+
lines = shortlog.split("\n")
|
39
|
+
|
40
|
+
lines.each do |line|
|
41
|
+
data = line.split("\t")
|
42
|
+
commits = data.first
|
43
|
+
author = Grit::Actor.from_string(data.last)
|
44
|
+
|
45
|
+
authors << OpenStruct.new(
|
46
|
+
name: author.name,
|
47
|
+
email: author.email,
|
48
|
+
commits: commits.to_i
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
authors.sort_by(&:commits).reverse
|
53
|
+
end
|
54
|
+
|
55
|
+
def build_graph n = 4
|
56
|
+
from, to = (Date.today.prev_day(n*7)), Date.today
|
57
|
+
args = ['--all', "--since=#{from.to_s}", '--format=%ad' ]
|
58
|
+
rev_list = repo.git.run(nil, 'rev-list', nil, {}, args).split("\n")
|
59
|
+
|
60
|
+
commits_dates = rev_list.values_at(* rev_list.each_index.select {|i| i.odd?})
|
61
|
+
commits_dates = commits_dates.map { |date_str| Time.parse(date_str).to_date.to_s(:date) }
|
62
|
+
|
63
|
+
commits_per_day = from.upto(to).map do |day|
|
64
|
+
commits_dates.count(day.to_date.to_s)
|
65
|
+
end
|
66
|
+
|
67
|
+
OpenStruct.new(
|
68
|
+
labels: from.upto(to).map { |day| day.strftime('%b %d') },
|
69
|
+
commits: commits_per_day,
|
70
|
+
weeks: n
|
71
|
+
)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Gitlab
|
2
|
+
module Git
|
3
|
+
class Tree
|
4
|
+
attr_accessor :repository, :sha, :path, :ref, :raw_tree, :id
|
5
|
+
|
6
|
+
def initialize(repository, sha, ref = nil, path = nil)
|
7
|
+
@repository, @sha, @ref, @path = repository, sha, ref, path
|
8
|
+
|
9
|
+
@path = nil if !@path || @path == ''
|
10
|
+
|
11
|
+
# Load tree from repository
|
12
|
+
@commit = @repository.commit(@sha)
|
13
|
+
@raw_tree = @repository.tree(@commit, @path)
|
14
|
+
end
|
15
|
+
|
16
|
+
def exists?
|
17
|
+
raw_tree
|
18
|
+
end
|
19
|
+
|
20
|
+
def empty?
|
21
|
+
trees.empty? && blobs.empty?
|
22
|
+
end
|
23
|
+
|
24
|
+
def trees
|
25
|
+
entries.select { |t| t.is_a?(Grit::Tree) }
|
26
|
+
end
|
27
|
+
|
28
|
+
def blobs
|
29
|
+
entries.select { |t| t.is_a?(Grit::Blob) }
|
30
|
+
end
|
31
|
+
|
32
|
+
def is_blob?
|
33
|
+
raw_tree.is_a?(Grit::Blob)
|
34
|
+
end
|
35
|
+
|
36
|
+
def up_dir?
|
37
|
+
path && path != ''
|
38
|
+
end
|
39
|
+
|
40
|
+
def readme
|
41
|
+
@readme ||= blobs.find { |c| c.name =~ /^readme/i }
|
42
|
+
end
|
43
|
+
|
44
|
+
protected
|
45
|
+
|
46
|
+
def entries
|
47
|
+
raw_tree.contents
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gitlab_git
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dmitriy Zaporozhets
|
@@ -73,6 +73,15 @@ extensions: []
|
|
73
73
|
extra_rdoc_files: []
|
74
74
|
files:
|
75
75
|
- lib/gitlab_git.rb
|
76
|
+
- lib/gitlab_git/blame.rb
|
77
|
+
- lib/gitlab_git/blob.rb
|
78
|
+
- lib/gitlab_git/commit.rb
|
79
|
+
- lib/gitlab_git/compare.rb
|
80
|
+
- lib/gitlab_git/diff.rb
|
81
|
+
- lib/gitlab_git/popen.rb
|
82
|
+
- lib/gitlab_git/repository.rb
|
83
|
+
- lib/gitlab_git/stats.rb
|
84
|
+
- lib/gitlab_git/tree.rb
|
76
85
|
homepage: http://rubygems.org/gems/gitlab_git
|
77
86
|
licenses: []
|
78
87
|
metadata: {}
|