Commit 4f2d2c90f7c32a9113ccce440411ec80374ee385
1 parent
df96c079
Exists in
master
and in
4 other branches
Move Gitlab::Git out of gitlab core
Showing
16 changed files
with
15 additions
and
863 deletions
Show diff stats
Gemfile
@@ -26,6 +26,8 @@ gem 'omniauth-github' | @@ -26,6 +26,8 @@ gem 'omniauth-github' | ||
26 | gem "grit", '~> 2.5.0', git: 'https://github.com/gitlabhq/grit.git', ref: '42297cdcee16284d2e4eff23d41377f52fc28b9d' | 26 | gem "grit", '~> 2.5.0', git: 'https://github.com/gitlabhq/grit.git', ref: '42297cdcee16284d2e4eff23d41377f52fc28b9d' |
27 | gem 'grit_ext', '~> 0.8.1' | 27 | gem 'grit_ext', '~> 0.8.1' |
28 | 28 | ||
29 | +gem 'gitlab_git', path: '../gitlab_git' | ||
30 | + | ||
29 | # Ruby/Rack Git Smart-HTTP Server Handler | 31 | # Ruby/Rack Git Smart-HTTP Server Handler |
30 | gem 'gitlab-grack', '~> 1.0.0', require: 'grack' | 32 | gem 'gitlab-grack', '~> 1.0.0', require: 'grack' |
31 | 33 |
Gemfile.lock
@@ -32,6 +32,14 @@ GIT | @@ -32,6 +32,14 @@ GIT | ||
32 | faye-websocket (~> 0.4, >= 0.4.4) | 32 | faye-websocket (~> 0.4, >= 0.4.4) |
33 | http_parser.rb (~> 0.5.3) | 33 | http_parser.rb (~> 0.5.3) |
34 | 34 | ||
35 | +PATH | ||
36 | + remote: ../gitlab_git | ||
37 | + specs: | ||
38 | + gitlab_git (1.0.0) | ||
39 | + activesupport (~> 3.2.13) | ||
40 | + github-linguist (~> 2.3.4) | ||
41 | + grit (~> 2.5.0) | ||
42 | + | ||
35 | GEM | 43 | GEM |
36 | remote: https://rubygems.org/ | 44 | remote: https://rubygems.org/ |
37 | specs: | 45 | specs: |
@@ -501,6 +509,7 @@ DEPENDENCIES | @@ -501,6 +509,7 @@ DEPENDENCIES | ||
501 | github-markup (~> 0.7.4) | 509 | github-markup (~> 0.7.4) |
502 | gitlab-grack (~> 1.0.0) | 510 | gitlab-grack (~> 1.0.0) |
503 | gitlab-pygments.rb (~> 0.3.2) | 511 | gitlab-pygments.rb (~> 0.3.2) |
512 | + gitlab_git! | ||
504 | gitlab_meta (= 5.0) | 513 | gitlab_meta (= 5.0) |
505 | gitlab_omniauth-ldap (= 1.0.2) | 514 | gitlab_omniauth-ldap (= 1.0.2) |
506 | gollum-lib (~> 1.0.0) | 515 | gollum-lib (~> 1.0.0) |
config/initializers/5_backend.rb
@@ -6,3 +6,6 @@ require Rails.root.join("lib", "gitlab", "backend", "shell") | @@ -6,3 +6,6 @@ require Rails.root.join("lib", "gitlab", "backend", "shell") | ||
6 | 6 | ||
7 | # GitLab shell adapter | 7 | # GitLab shell adapter |
8 | require Rails.root.join("lib", "gitlab", "backend", "shell_adapter") | 8 | require Rails.root.join("lib", "gitlab", "backend", "shell_adapter") |
9 | + | ||
10 | +# Gitlab Git repos path | ||
11 | +Gitlab::Git::Repository.repos_path = Gitlab.config.gitlab_shell.repos_path |
lib/gitlab/git/blame.rb
@@ -1,23 +0,0 @@ | @@ -1,23 +0,0 @@ | ||
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 |
lib/gitlab/git/blob.rb
@@ -1,42 +0,0 @@ | @@ -1,42 +0,0 @@ | ||
1 | -module Gitlab | ||
2 | - module Git | ||
3 | - class Blob | ||
4 | - include Linguist::BlobHelper | ||
5 | - | ||
6 | - attr_accessor :raw_blob | ||
7 | - | ||
8 | - delegate :name, to: :raw_blob | ||
9 | - | ||
10 | - def initialize(repository, sha, ref, path) | ||
11 | - @repository, @sha, @ref = repository, sha, ref | ||
12 | - | ||
13 | - @commit = @repository.commit(sha) | ||
14 | - @raw_blob = @repository.tree(@commit, path) | ||
15 | - end | ||
16 | - | ||
17 | - def data | ||
18 | - if raw_blob | ||
19 | - raw_blob.data | ||
20 | - else | ||
21 | - nil | ||
22 | - end | ||
23 | - end | ||
24 | - | ||
25 | - def exists? | ||
26 | - raw_blob | ||
27 | - end | ||
28 | - | ||
29 | - def empty? | ||
30 | - data.blank? | ||
31 | - end | ||
32 | - | ||
33 | - def mode | ||
34 | - raw_blob.mode | ||
35 | - end | ||
36 | - | ||
37 | - def size | ||
38 | - raw_blob.size | ||
39 | - end | ||
40 | - end | ||
41 | - end | ||
42 | -end |
lib/gitlab/git/commit.rb
@@ -1,127 +0,0 @@ | @@ -1,127 +0,0 @@ | ||
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 | - delegate :parents, :tree, :stats, :to_patch, | ||
13 | - to: :raw_commit | ||
14 | - | ||
15 | - def initialize(raw_commit, head = nil) | ||
16 | - raise "Nil as raw commit passed" unless raw_commit | ||
17 | - | ||
18 | - if raw_commit.is_a?(Hash) | ||
19 | - init_from_hash(raw_commit) | ||
20 | - else | ||
21 | - init_from_grit(raw_commit) | ||
22 | - end | ||
23 | - | ||
24 | - @head = head | ||
25 | - end | ||
26 | - | ||
27 | - def serialize_keys | ||
28 | - @serialize_keys ||= %w(id authored_date committed_date author_name author_email committer_name committer_email message parent_ids).map(&:to_sym) | ||
29 | - end | ||
30 | - | ||
31 | - def sha | ||
32 | - id | ||
33 | - end | ||
34 | - | ||
35 | - def short_id(length = 10) | ||
36 | - id.to_s[0..length] | ||
37 | - end | ||
38 | - | ||
39 | - def safe_message | ||
40 | - @safe_message ||= message | ||
41 | - end | ||
42 | - | ||
43 | - def created_at | ||
44 | - committed_date | ||
45 | - end | ||
46 | - | ||
47 | - # Was this commit committed by a different person than the original author? | ||
48 | - def different_committer? | ||
49 | - author_name != committer_name || author_email != committer_email | ||
50 | - end | ||
51 | - | ||
52 | - def parent_id | ||
53 | - parent_ids.first | ||
54 | - end | ||
55 | - | ||
56 | - # Shows the diff between the commit's parent and the commit. | ||
57 | - # | ||
58 | - # Cuts out the header and stats from #to_patch and returns only the diff. | ||
59 | - def to_diff | ||
60 | - # see Grit::Commit#show | ||
61 | - patch = to_patch | ||
62 | - | ||
63 | - # discard lines before the diff | ||
64 | - lines = patch.split("\n") | ||
65 | - while !lines.first.start_with?("diff --git") do | ||
66 | - lines.shift | ||
67 | - end | ||
68 | - lines.pop if lines.last =~ /^[\d.]+$/ # Git version | ||
69 | - lines.pop if lines.last == "-- " # end of diff | ||
70 | - lines.join("\n") | ||
71 | - end | ||
72 | - | ||
73 | - def has_zero_stats? | ||
74 | - stats.total.zero? | ||
75 | - rescue | ||
76 | - true | ||
77 | - end | ||
78 | - | ||
79 | - def no_commit_message | ||
80 | - "--no commit message" | ||
81 | - end | ||
82 | - | ||
83 | - def to_hash | ||
84 | - hash = {} | ||
85 | - | ||
86 | - keys = serialize_keys | ||
87 | - | ||
88 | - keys.each do |key| | ||
89 | - hash[key] = send(key) | ||
90 | - end | ||
91 | - | ||
92 | - hash | ||
93 | - end | ||
94 | - | ||
95 | - def date | ||
96 | - committed_date | ||
97 | - end | ||
98 | - | ||
99 | - def diffs | ||
100 | - raw_commit.diffs.map { |diff| Gitlab::Git::Diff.new(diff) } | ||
101 | - end | ||
102 | - | ||
103 | - private | ||
104 | - | ||
105 | - def init_from_grit(grit) | ||
106 | - @raw_commit = grit | ||
107 | - @id = grit.id | ||
108 | - @message = grit.message | ||
109 | - @authored_date = grit.authored_date | ||
110 | - @committed_date = grit.committed_date | ||
111 | - @author_name = grit.author.name | ||
112 | - @author_email = grit.author.email | ||
113 | - @committer_name = grit.committer.name | ||
114 | - @committer_email = grit.committer.email | ||
115 | - @parent_ids = grit.parents.map(&:id) | ||
116 | - end | ||
117 | - | ||
118 | - def init_from_hash(hash) | ||
119 | - raw_commit = hash.symbolize_keys | ||
120 | - | ||
121 | - serialize_keys.each do |key| | ||
122 | - send(:"#{key}=", raw_commit[key.to_sym]) | ||
123 | - end | ||
124 | - end | ||
125 | - end | ||
126 | - end | ||
127 | -end |
lib/gitlab/git/compare.rb
@@ -1,35 +0,0 @@ | @@ -1,35 +0,0 @@ | ||
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 | - |
lib/gitlab/git/diff.rb
@@ -1,63 +0,0 @@ | @@ -1,63 +0,0 @@ | ||
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 | - |
lib/gitlab/git/repository.rb
@@ -1,221 +0,0 @@ | @@ -1,221 +0,0 @@ | ||
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::Popen | ||
8 | - | ||
9 | - class NoRepository < StandardError; end | ||
10 | - | ||
11 | - # Repository directory name with namespace direcotry | ||
12 | - # Examples: | ||
13 | - # gitlab/gitolite | ||
14 | - # diaspora | ||
15 | - # | ||
16 | - attr_accessor :path_with_namespace | ||
17 | - | ||
18 | - # Grit repo object | ||
19 | - attr_accessor :repo | ||
20 | - | ||
21 | - # Default branch in the repository | ||
22 | - attr_accessor :root_ref | ||
23 | - | ||
24 | - def initialize(path_with_namespace, root_ref = 'master') | ||
25 | - @root_ref = root_ref || "master" | ||
26 | - @path_with_namespace = path_with_namespace | ||
27 | - | ||
28 | - # Init grit repo object | ||
29 | - repo | ||
30 | - end | ||
31 | - | ||
32 | - def raw | ||
33 | - repo | ||
34 | - end | ||
35 | - | ||
36 | - def path_to_repo | ||
37 | - @path_to_repo ||= File.join(repos_path, "#{path_with_namespace}.git") | ||
38 | - end | ||
39 | - | ||
40 | - def repos_path | ||
41 | - Gitlab.config.gitlab_shell.repos_path | ||
42 | - end | ||
43 | - | ||
44 | - def repo | ||
45 | - @repo ||= Grit::Repo.new(path_to_repo) | ||
46 | - rescue Grit::NoSuchPathError | ||
47 | - raise NoRepository.new('no repository for such path') | ||
48 | - end | ||
49 | - | ||
50 | - def commit(commit_id = nil) | ||
51 | - commit = if commit_id | ||
52 | - # Find repo.refs first, | ||
53 | - # because if commit_id is "tag name", | ||
54 | - # repo.commit(commit_id) returns wrong commit sha | ||
55 | - # that is git tag object sha. | ||
56 | - ref = repo.refs.find {|r| r.name == commit_id} | ||
57 | - if ref | ||
58 | - ref.commit | ||
59 | - else | ||
60 | - repo.commit(commit_id) | ||
61 | - end | ||
62 | - else | ||
63 | - repo.commits(root_ref).first | ||
64 | - end | ||
65 | - | ||
66 | - decorate_commit(commit) if commit | ||
67 | - end | ||
68 | - | ||
69 | - def commits_with_refs(n = 20) | ||
70 | - commits = repo.branches.map { |ref| decorate_commit(ref.commit, ref) } | ||
71 | - | ||
72 | - commits.sort! do |x, y| | ||
73 | - y.committed_date <=> x.committed_date | ||
74 | - end | ||
75 | - | ||
76 | - commits[0..n] | ||
77 | - end | ||
78 | - | ||
79 | - def commits(ref, path = nil, limit = nil, offset = nil) | ||
80 | - if path.present? | ||
81 | - repo.log(ref, path, max_count: limit, skip: offset, follow: true) | ||
82 | - elsif limit && offset | ||
83 | - repo.commits(ref, limit.to_i, offset.to_i) | ||
84 | - else | ||
85 | - repo.commits(ref) | ||
86 | - end.map{ |c| decorate_commit(c) } | ||
87 | - end | ||
88 | - | ||
89 | - def commits_between(from, to) | ||
90 | - repo.commits_between(from, to).map { |c| decorate_commit(c) } | ||
91 | - end | ||
92 | - | ||
93 | - def last_commit_for(ref, path = nil) | ||
94 | - commits(ref, path, 1).first | ||
95 | - end | ||
96 | - | ||
97 | - # Returns an Array of branch names | ||
98 | - # sorted by name ASC | ||
99 | - def branch_names | ||
100 | - branches.map(&:name) | ||
101 | - end | ||
102 | - | ||
103 | - # Returns an Array of Branches | ||
104 | - def branches | ||
105 | - repo.branches.sort_by(&:name) | ||
106 | - end | ||
107 | - | ||
108 | - # Returns an Array of tag names | ||
109 | - def tag_names | ||
110 | - repo.tags.collect(&:name).sort.reverse | ||
111 | - end | ||
112 | - | ||
113 | - # Returns an Array of Tags | ||
114 | - def tags | ||
115 | - repo.tags.sort_by(&:name).reverse | ||
116 | - end | ||
117 | - | ||
118 | - # Returns an Array of branch and tag names | ||
119 | - def ref_names | ||
120 | - [branch_names + tag_names].flatten | ||
121 | - end | ||
122 | - | ||
123 | - def heads | ||
124 | - @heads ||= repo.heads | ||
125 | - end | ||
126 | - | ||
127 | - def tree(fcommit, path = nil) | ||
128 | - fcommit = commit if fcommit == :head | ||
129 | - tree = fcommit.tree | ||
130 | - path ? (tree / path) : tree | ||
131 | - end | ||
132 | - | ||
133 | - def has_commits? | ||
134 | - !!commit | ||
135 | - rescue Grit::NoSuchPathError | ||
136 | - false | ||
137 | - end | ||
138 | - | ||
139 | - def empty? | ||
140 | - !has_commits? | ||
141 | - end | ||
142 | - | ||
143 | - # Discovers the default branch based on the repository's available branches | ||
144 | - # | ||
145 | - # - If no branches are present, returns nil | ||
146 | - # - If one branch is present, returns its name | ||
147 | - # - If two or more branches are present, returns the one that has a name | ||
148 | - # matching root_ref (default_branch or 'master' if default_branch is nil) | ||
149 | - def discover_default_branch | ||
150 | - if branch_names.length == 0 | ||
151 | - nil | ||
152 | - elsif branch_names.length == 1 | ||
153 | - branch_names.first | ||
154 | - else | ||
155 | - branch_names.select { |v| v == root_ref }.first | ||
156 | - end | ||
157 | - end | ||
158 | - | ||
159 | - # Archive Project to .tar.gz | ||
160 | - # | ||
161 | - # Already packed repo archives stored at | ||
162 | - # app_root/tmp/repositories/project_name/project_name-commit-id.tag.gz | ||
163 | - # | ||
164 | - def archive_repo(ref) | ||
165 | - ref = ref || self.root_ref | ||
166 | - commit = self.commit(ref) | ||
167 | - return nil unless commit | ||
168 | - | ||
169 | - # Build file path | ||
170 | - file_name = self.path_with_namespace.gsub("/","_") + "-" + commit.id.to_s + ".tar.gz" | ||
171 | - storage_path = Rails.root.join("tmp", "repositories") | ||
172 | - file_path = File.join(storage_path, self.path_with_namespace, file_name) | ||
173 | - | ||
174 | - # Put files into a directory before archiving | ||
175 | - prefix = File.basename(self.path_with_namespace) + "/" | ||
176 | - | ||
177 | - # Create file if not exists | ||
178 | - unless File.exists?(file_path) | ||
179 | - FileUtils.mkdir_p File.dirname(file_path) | ||
180 | - file = self.repo.archive_to_file(ref, prefix, file_path) | ||
181 | - end | ||
182 | - | ||
183 | - file_path | ||
184 | - end | ||
185 | - | ||
186 | - # Return repo size in megabytes | ||
187 | - # Cached in redis | ||
188 | - def size | ||
189 | - Rails.cache.fetch(cache_key(:size)) do | ||
190 | - size = popen('du -s', path_to_repo).first.strip.to_i | ||
191 | - (size.to_f / 1024).round(2) | ||
192 | - end | ||
193 | - end | ||
194 | - | ||
195 | - def expire_cache | ||
196 | - Rails.cache.delete(cache_key(:size)) | ||
197 | - end | ||
198 | - | ||
199 | - def cache_key(type) | ||
200 | - "#{type}:#{path_with_namespace}" | ||
201 | - end | ||
202 | - | ||
203 | - def diffs_between(source_branch, target_branch) | ||
204 | - # Only show what is new in the source branch compared to the target branch, not the other way around. | ||
205 | - # The linex below with merge_base is equivalent to diff with three dots (git diff branch1...branch2) | ||
206 | - # From the git documentation: "git diff A...B" is equivalent to "git diff $(git-merge-base A B) B" | ||
207 | - common_commit = repo.git.native(:merge_base, {}, [target_branch, source_branch]).strip | ||
208 | - repo.diff(common_commit, source_branch).map { |diff| Gitlab::Git::Diff.new(diff) } | ||
209 | - | ||
210 | - rescue Grit::Git::GitTimeout | ||
211 | - [Gitlab::Git::Diff::BROKEN_DIFF] | ||
212 | - end | ||
213 | - | ||
214 | - protected | ||
215 | - | ||
216 | - def decorate_commit(commit, ref = nil) | ||
217 | - Gitlab::Git::Commit.new(commit, ref) | ||
218 | - end | ||
219 | - end | ||
220 | - end | ||
221 | -end |
lib/gitlab/git/stats.rb
@@ -1,75 +0,0 @@ | @@ -1,75 +0,0 @@ | ||
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 - n.weeks), Date.today | ||
57 | - args = ['--all', "--since=#{from.to_s(:date)}", '--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(:date)) | ||
65 | - end | ||
66 | - | ||
67 | - OpenStruct.new( | ||
68 | - labels: from.upto(to).map { |day| day.stamp('Aug 23') }, | ||
69 | - commits: commits_per_day, | ||
70 | - weeks: n | ||
71 | - ) | ||
72 | - end | ||
73 | - end | ||
74 | - end | ||
75 | -end |
lib/gitlab/git/tree.rb
@@ -1,52 +0,0 @@ | @@ -1,52 +0,0 @@ | ||
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.blank? | ||
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 | - data.blank? | ||
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.present? | ||
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 | - |
spec/lib/gitlab/git/commit_spec.rb
@@ -1,40 +0,0 @@ | @@ -1,40 +0,0 @@ | ||
1 | -require "spec_helper" | ||
2 | - | ||
3 | -describe Gitlab::Git::Commit do | ||
4 | - let(:commit) { create(:project_with_code).repository.commit } | ||
5 | - | ||
6 | - describe "Commit info" do | ||
7 | - before do | ||
8 | - @committer = double( | ||
9 | - email: 'mike@smith.com', | ||
10 | - name: 'Mike Smith' | ||
11 | - ) | ||
12 | - | ||
13 | - @author = double( | ||
14 | - email: 'john@smith.com', | ||
15 | - name: 'John Smith' | ||
16 | - ) | ||
17 | - | ||
18 | - @raw_commit = double( | ||
19 | - id: "bcf03b5de6abcf03b5de6c", | ||
20 | - author: @author, | ||
21 | - committer: @committer, | ||
22 | - committed_date: Date.yesterday, | ||
23 | - authored_date: Date.yesterday, | ||
24 | - parents: [], | ||
25 | - message: 'Refactoring specs' | ||
26 | - ) | ||
27 | - | ||
28 | - @commit = Gitlab::Git::Commit.new(@raw_commit) | ||
29 | - end | ||
30 | - | ||
31 | - it { @commit.short_id.should == "bcf03b5de6a" } | ||
32 | - it { @commit.safe_message.should == @raw_commit.message } | ||
33 | - it { @commit.created_at.should == @raw_commit.committed_date } | ||
34 | - it { @commit.author_email.should == @author.email } | ||
35 | - it { @commit.author_name.should == @author.name } | ||
36 | - it { @commit.committer_name.should == @committer.name } | ||
37 | - it { @commit.committer_email.should == @committer.email } | ||
38 | - it { @commit.different_committer?.should be_true } | ||
39 | - end | ||
40 | -end |
spec/lib/gitlab/git/diff_spec.rb
@@ -1,34 +0,0 @@ | @@ -1,34 +0,0 @@ | ||
1 | -require "spec_helper" | ||
2 | - | ||
3 | -describe Gitlab::Git::Diff do | ||
4 | - before do | ||
5 | - @raw_diff_hash = { | ||
6 | - diff: 'Hello world', | ||
7 | - new_path: 'temp.rb', | ||
8 | - old_path: 'test.rb', | ||
9 | - a_mode: '100644', | ||
10 | - b_mode: '100644', | ||
11 | - new_file: false, | ||
12 | - renamed_file: true, | ||
13 | - deleted_file: false, | ||
14 | - } | ||
15 | - | ||
16 | - @grit_diff = double('Grit::Diff', @raw_diff_hash) | ||
17 | - end | ||
18 | - | ||
19 | - context 'init from grit' do | ||
20 | - before do | ||
21 | - @diff = Gitlab::Git::Diff.new(@raw_diff_hash) | ||
22 | - end | ||
23 | - | ||
24 | - it { @diff.to_hash.should == @raw_diff_hash } | ||
25 | - end | ||
26 | - | ||
27 | - context 'init from hash' do | ||
28 | - before do | ||
29 | - @diff = Gitlab::Git::Diff.new(@grit_diff) | ||
30 | - end | ||
31 | - | ||
32 | - it { @diff.to_hash.should == @raw_diff_hash } | ||
33 | - end | ||
34 | -end |
spec/lib/gitlab/git/repository_spec.rb
@@ -1,123 +0,0 @@ | @@ -1,123 +0,0 @@ | ||
1 | -require "spec_helper" | ||
2 | - | ||
3 | -describe Gitlab::Git::Repository do | ||
4 | - let(:repository) { Gitlab::Git::Repository.new('gitlabhq', 'master') } | ||
5 | - | ||
6 | - describe "Respond to" do | ||
7 | - subject { repository } | ||
8 | - | ||
9 | - it { should respond_to(:repo) } | ||
10 | - it { should respond_to(:tree) } | ||
11 | - it { should respond_to(:root_ref) } | ||
12 | - it { should respond_to(:tags) } | ||
13 | - it { should respond_to(:commit) } | ||
14 | - it { should respond_to(:commits) } | ||
15 | - it { should respond_to(:commits_between) } | ||
16 | - it { should respond_to(:commits_with_refs) } | ||
17 | - end | ||
18 | - | ||
19 | - | ||
20 | - describe "#discover_default_branch" do | ||
21 | - let(:master) { 'master' } | ||
22 | - let(:stable) { 'stable' } | ||
23 | - | ||
24 | - it "returns 'master' when master exists" do | ||
25 | - repository.should_receive(:branch_names).at_least(:once).and_return([stable, master]) | ||
26 | - repository.discover_default_branch.should == 'master' | ||
27 | - end | ||
28 | - | ||
29 | - it "returns non-master when master exists but default branch is set to something else" do | ||
30 | - repository.root_ref = 'stable' | ||
31 | - repository.should_receive(:branch_names).at_least(:once).and_return([stable, master]) | ||
32 | - repository.discover_default_branch.should == 'stable' | ||
33 | - end | ||
34 | - | ||
35 | - it "returns a non-master branch when only one exists" do | ||
36 | - repository.should_receive(:branch_names).at_least(:once).and_return([stable]) | ||
37 | - repository.discover_default_branch.should == 'stable' | ||
38 | - end | ||
39 | - | ||
40 | - it "returns nil when no branch exists" do | ||
41 | - repository.should_receive(:branch_names).at_least(:once).and_return([]) | ||
42 | - repository.discover_default_branch.should be_nil | ||
43 | - end | ||
44 | - end | ||
45 | - | ||
46 | - describe :commit do | ||
47 | - it "should return first head commit if without params" do | ||
48 | - repository.commit.id.should == repository.repo.commits.first.id | ||
49 | - end | ||
50 | - | ||
51 | - it "should return valid commit" do | ||
52 | - repository.commit(ValidCommit::ID).should be_valid_commit | ||
53 | - end | ||
54 | - | ||
55 | - it "should return nil" do | ||
56 | - repository.commit("+123_4532530XYZ").should be_nil | ||
57 | - end | ||
58 | - end | ||
59 | - | ||
60 | - describe :tree do | ||
61 | - before do | ||
62 | - @commit = repository.commit(ValidCommit::ID) | ||
63 | - end | ||
64 | - | ||
65 | - it "should raise error w/o arguments" do | ||
66 | - lambda { repository.tree }.should raise_error | ||
67 | - end | ||
68 | - | ||
69 | - it "should return root tree for commit" do | ||
70 | - tree = repository.tree(@commit) | ||
71 | - tree.contents.size.should == ValidCommit::FILES_COUNT | ||
72 | - tree.contents.map(&:name).should == ValidCommit::FILES | ||
73 | - end | ||
74 | - | ||
75 | - it "should return root tree for commit with correct path" do | ||
76 | - tree = repository.tree(@commit, ValidCommit::C_FILE_PATH) | ||
77 | - tree.contents.map(&:name).should == ValidCommit::C_FILES | ||
78 | - end | ||
79 | - | ||
80 | - it "should return root tree for commit with incorrect path" do | ||
81 | - repository.tree(@commit, "invalid_path").should be_nil | ||
82 | - end | ||
83 | - end | ||
84 | - | ||
85 | - describe "commits" do | ||
86 | - subject do | ||
87 | - commits = repository.commits('master', 'app', 3, 1) | ||
88 | - commits.map { |c| c.id } | ||
89 | - end | ||
90 | - | ||
91 | - it { should have(3).elements } | ||
92 | - it { should include("8716fc78f3c65bbf7bcf7b574febd583bc5d2812") } | ||
93 | - it { should_not include("bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a") } | ||
94 | - end | ||
95 | - | ||
96 | - describe "commits_between" do | ||
97 | - subject do | ||
98 | - commits = repository.commits_between("3a4b4fb4cde7809f033822a171b9feae19d41fff", | ||
99 | - "8470d70da67355c9c009e4401746b1d5410af2e3") | ||
100 | - commits.map { |c| c.id } | ||
101 | - end | ||
102 | - | ||
103 | - it { should have(3).elements } | ||
104 | - it { should include("f0f14c8eaba69ebddd766498a9d0b0e79becd633") } | ||
105 | - it { should_not include("bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a") } | ||
106 | - end | ||
107 | - | ||
108 | - describe "branch names" do | ||
109 | - subject { repository.branch_names } | ||
110 | - | ||
111 | - it { should have(32).elements } | ||
112 | - it { should include("master") } | ||
113 | - it { should_not include("branch-from-space") } | ||
114 | - end | ||
115 | - | ||
116 | - describe "tag names" do | ||
117 | - subject { repository.tag_names } | ||
118 | - | ||
119 | - it { should have(16).elements } | ||
120 | - it { should include("v1.2.0") } | ||
121 | - it { should_not include("v5.0.0") } | ||
122 | - end | ||
123 | -end |
spec/lib/gitlab/git/stats_spec.rb
@@ -1,28 +0,0 @@ | @@ -1,28 +0,0 @@ | ||
1 | -require "spec_helper" | ||
2 | - | ||
3 | -describe Gitlab::Git::Stats do | ||
4 | - let(:repository) { Gitlab::Git::Repository.new('gitlabhq', 'master') } | ||
5 | - | ||
6 | - before do | ||
7 | - @stats = Gitlab::Git::Stats.new(repository.raw, 'master') | ||
8 | - end | ||
9 | - | ||
10 | - describe :authors do | ||
11 | - let(:author) { @stats.authors.first } | ||
12 | - | ||
13 | - it { author.name.should == 'Dmitriy Zaporozhets' } | ||
14 | - it { author.email.should == 'dmitriy.zaporozhets@gmail.com' } | ||
15 | - it { author.commits.should == 254 } | ||
16 | - end | ||
17 | - | ||
18 | - describe :graph do | ||
19 | - let(:graph) { @stats.graph } | ||
20 | - | ||
21 | - it { graph.labels.should include Date.today.stamp('Aug 23') } | ||
22 | - it { graph.commits.should be_kind_of(Array) } | ||
23 | - it { graph.weeks.should == 4 } | ||
24 | - end | ||
25 | - | ||
26 | - it { @stats.commits_count.should == 918 } | ||
27 | - it { @stats.files_count.should == 550 } | ||
28 | -end |
spec/support/test_env.rb
@@ -32,6 +32,7 @@ module TestEnv | @@ -32,6 +32,7 @@ module TestEnv | ||
32 | # Use tmp dir for FS manipulations | 32 | # Use tmp dir for FS manipulations |
33 | repos_path = Rails.root.join('tmp', 'test-git-base-path') | 33 | repos_path = Rails.root.join('tmp', 'test-git-base-path') |
34 | Gitlab.config.gitlab_shell.stub(repos_path: repos_path) | 34 | Gitlab.config.gitlab_shell.stub(repos_path: repos_path) |
35 | + Gitlab::Git::Repository.stub(repos_path: repos_path) | ||
35 | 36 | ||
36 | GollumWiki.any_instance.stub(:init_repo) do |path| | 37 | GollumWiki.any_instance.stub(:init_repo) do |path| |
37 | create_temp_repo(File.join(repos_path, "#{path}.git")) | 38 | create_temp_repo(File.join(repos_path, "#{path}.git")) |