Commit 76a4cbe464a4472e82065c670d1190552db67cc6
Exists in
master
and in
4 other branches
Merge branch 'refactor/gitlab_git'
Showing
72 changed files
with
918 additions
and
836 deletions
Show diff stats
app/contexts/commit_load_context.rb
app/controllers/blame_controller.rb
... | ... | @@ -8,7 +8,6 @@ class BlameController < ProjectResourceController |
8 | 8 | before_filter :require_non_empty_project |
9 | 9 | |
10 | 10 | def show |
11 | - @repo = @project.repo | |
12 | - @blame = Grit::Blob.blame(@repo, @commit.id, @path) | |
11 | + @blame = Gitlab::Git::Blame.new(project.repository, @commit.id, @path) | |
13 | 12 | end |
14 | 13 | end | ... | ... |
app/controllers/commits_controller.rb
... | ... | @@ -13,7 +13,6 @@ class CommitsController < ProjectResourceController |
13 | 13 | @limit, @offset = (params[:limit] || 40), (params[:offset] || 0) |
14 | 14 | |
15 | 15 | @commits = @repo.commits(@ref, @path, @limit, @offset) |
16 | - @commits = CommitDecorator.decorate_collection(@commits) | |
17 | 16 | |
18 | 17 | respond_to do |format| |
19 | 18 | format.html # index.html.erb | ... | ... |
app/controllers/compare_controller.rb
... | ... | @@ -8,15 +8,13 @@ class CompareController < ProjectResourceController |
8 | 8 | end |
9 | 9 | |
10 | 10 | def show |
11 | - result = Commit.compare(project, params[:from], params[:to]) | |
11 | + compare = Gitlab::Git::Compare.new(project.repository, params[:from], params[:to]) | |
12 | 12 | |
13 | - @commits = result[:commits] | |
14 | - @commit = result[:commit] | |
15 | - @diffs = result[:diffs] | |
16 | - @refs_are_same = result[:same] | |
13 | + @commits = compare.commits | |
14 | + @commit = compare.commit | |
15 | + @diffs = compare.diffs | |
16 | + @refs_are_same = compare.same | |
17 | 17 | @line_notes = [] |
18 | - | |
19 | - @commits = CommitDecorator.decorate_collection(@commits) | |
20 | 18 | end |
21 | 19 | |
22 | 20 | def create | ... | ... |
app/controllers/merge_requests_controller.rb
... | ... | @@ -94,12 +94,10 @@ class MergeRequestsController < ProjectResourceController |
94 | 94 | |
95 | 95 | def branch_from |
96 | 96 | @commit = @repository.commit(params[:ref]) |
97 | - @commit = CommitDecorator.decorate(@commit) | |
98 | 97 | end |
99 | 98 | |
100 | 99 | def branch_to |
101 | 100 | @commit = @repository.commit(params[:ref]) |
102 | - @commit = CommitDecorator.decorate(@commit) | |
103 | 101 | end |
104 | 102 | |
105 | 103 | def ci_status |
... | ... | @@ -143,7 +141,6 @@ class MergeRequestsController < ProjectResourceController |
143 | 141 | # Get commits from repository |
144 | 142 | # or from cache if already merged |
145 | 143 | @commits = @merge_request.commits |
146 | - @commits = CommitDecorator.decorate_collection(@commits) | |
147 | 144 | |
148 | 145 | @allowed_to_merge = allowed_to_merge? |
149 | 146 | @show_merge_controls = @merge_request.opened? && @commits.any? && @allowed_to_merge | ... | ... |
app/controllers/refs_controller.rb
... | ... | @@ -34,7 +34,6 @@ class RefsController < ProjectResourceController |
34 | 34 | @logs = contents.map do |content| |
35 | 35 | file = params[:path] ? File.join(params[:path], content.name) : content.name |
36 | 36 | last_commit = @repo.commits(@commit.id, file, 1).last |
37 | - last_commit = CommitDecorator.decorate(last_commit) | |
38 | 37 | { |
39 | 38 | file_name: content.name, |
40 | 39 | commit: last_commit |
... | ... | @@ -49,9 +48,7 @@ class RefsController < ProjectResourceController |
49 | 48 | |
50 | 49 | @repo = project.repository |
51 | 50 | @commit = @repo.commit(@ref) |
52 | - @commit = CommitDecorator.decorate(@commit) | |
53 | 51 | @tree = Tree.new(@commit.tree, @ref, params[:path]) |
54 | - @tree = TreeDecorator.new(@tree) | |
55 | 52 | @hex_path = Digest::SHA1.hexdigest(params[:path] || "") |
56 | 53 | |
57 | 54 | if params[:path] | ... | ... |
app/decorators/commit_decorator.rb
... | ... | @@ -1,93 +0,0 @@ |
1 | -class CommitDecorator < ApplicationDecorator | |
2 | - decorates :commit | |
3 | - | |
4 | - # Returns a string describing the commit for use in a link title | |
5 | - # | |
6 | - # Example | |
7 | - # | |
8 | - # "Commit: Alex Denisov - Project git clone panel" | |
9 | - def link_title | |
10 | - "Commit: #{author_name} - #{title}" | |
11 | - end | |
12 | - | |
13 | - # Returns the commits title. | |
14 | - # | |
15 | - # Usually, the commit title is the first line of the commit message. | |
16 | - # In case this first line is longer than 80 characters, it is cut off | |
17 | - # after 70 characters and ellipses (`&hellp;`) are appended. | |
18 | - def title | |
19 | - title = safe_message | |
20 | - | |
21 | - return no_commit_message if title.blank? | |
22 | - | |
23 | - title_end = title.index(/\n/) | |
24 | - if (!title_end && title.length > 80) || (title_end && title_end > 80) | |
25 | - title[0..69] << "…".html_safe | |
26 | - else | |
27 | - title.split(/\n/, 2).first | |
28 | - end | |
29 | - end | |
30 | - | |
31 | - # Returns the commits description | |
32 | - # | |
33 | - # cut off, ellipses (`&hellp;`) are prepended to the commit message. | |
34 | - def description | |
35 | - description = safe_message | |
36 | - | |
37 | - title_end = description.index(/\n/) | |
38 | - if (!title_end && description.length > 80) || (title_end && title_end > 80) | |
39 | - "…".html_safe << description[70..-1] | |
40 | - else | |
41 | - description.split(/\n/, 2)[1].try(:chomp) | |
42 | - end | |
43 | - end | |
44 | - | |
45 | - # Returns a link to the commit author. If the author has a matching user and | |
46 | - # is a member of the current @project it will link to the team member page. | |
47 | - # Otherwise it will link to the author email as specified in the commit. | |
48 | - # | |
49 | - # options: | |
50 | - # avatar: true will prepend the avatar image | |
51 | - # size: size of the avatar image in px | |
52 | - def author_link(options = {}) | |
53 | - person_link(options.merge source: :author) | |
54 | - end | |
55 | - | |
56 | - # Just like #author_link but for the committer. | |
57 | - def committer_link(options = {}) | |
58 | - person_link(options.merge source: :committer) | |
59 | - end | |
60 | - | |
61 | - protected | |
62 | - | |
63 | - def no_commit_message | |
64 | - "--no commit message" | |
65 | - end | |
66 | - | |
67 | - # Private: Returns a link to a person. If the person has a matching user and | |
68 | - # is a member of the current @project it will link to the team member page. | |
69 | - # Otherwise it will link to the person email as specified in the commit. | |
70 | - # | |
71 | - # options: | |
72 | - # source: one of :author or :committer | |
73 | - # avatar: true will prepend the avatar image | |
74 | - # size: size of the avatar image in px | |
75 | - def person_link(options = {}) | |
76 | - source_name = send "#{options[:source]}_name".to_sym | |
77 | - source_email = send "#{options[:source]}_email".to_sym | |
78 | - text = if options[:avatar] | |
79 | - avatar = h.image_tag h.gravatar_icon(source_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "" | |
80 | - %Q{#{avatar} <span class="commit-#{options[:source]}-name">#{source_name}</span>} | |
81 | - else | |
82 | - source_name | |
83 | - end | |
84 | - | |
85 | - user = User.where('name like ? or email like ?', source_name, source_email).first | |
86 | - | |
87 | - if user.nil? | |
88 | - h.mail_to(source_email, text.html_safe, class: "commit-#{options[:source]}-link") | |
89 | - else | |
90 | - h.link_to(text.html_safe, h.user_path(user), class: "commit-#{options[:source]}-link") | |
91 | - end | |
92 | - end | |
93 | -end |
app/decorators/tree_decorator.rb
... | ... | @@ -1,33 +0,0 @@ |
1 | -class TreeDecorator < ApplicationDecorator | |
2 | - decorates :tree | |
3 | - | |
4 | - def breadcrumbs(max_links = 2) | |
5 | - if path | |
6 | - part_path = "" | |
7 | - parts = path.split("\/") | |
8 | - | |
9 | - yield('..', nil) if parts.count > max_links | |
10 | - | |
11 | - parts.each do |part| | |
12 | - part_path = File.join(part_path, part) unless part_path.empty? | |
13 | - part_path = part if part_path.empty? | |
14 | - | |
15 | - next unless parts.last(2).include?(part) if parts.count > max_links | |
16 | - yield(part, h.tree_join(ref, part_path)) | |
17 | - end | |
18 | - end | |
19 | - end | |
20 | - | |
21 | - def up_dir? | |
22 | - path.present? | |
23 | - end | |
24 | - | |
25 | - def up_dir_path | |
26 | - file = File.join(path, "..") | |
27 | - h.tree_join(ref, file) | |
28 | - end | |
29 | - | |
30 | - def readme | |
31 | - @readme ||= contents.find { |c| c.is_a?(Grit::Blob) and c.name =~ /^readme/i } | |
32 | - end | |
33 | -end |
app/helpers/application_helper.rb
... | ... | @@ -96,7 +96,7 @@ module ApplicationHelper |
96 | 96 | ] |
97 | 97 | |
98 | 98 | project_nav = [] |
99 | - if @project && @project.repository && @project.repository.root_ref | |
99 | + if @project && @project.repository.exists? && @project.repository.root_ref | |
100 | 100 | project_nav = [ |
101 | 101 | { label: "#{simple_sanitize(@project.name_with_namespace)} - Issues", url: project_issues_path(@project) }, |
102 | 102 | { label: "#{simple_sanitize(@project.name_with_namespace)} - Commits", url: project_commits_path(@project, @ref || @project.repository.root_ref) }, | ... | ... |
app/helpers/commits_helper.rb
1 | 1 | module CommitsHelper |
2 | + # Returns a link to the commit author. If the author has a matching user and | |
3 | + # is a member of the current @project it will link to the team member page. | |
4 | + # Otherwise it will link to the author email as specified in the commit. | |
5 | + # | |
6 | + # options: | |
7 | + # avatar: true will prepend the avatar image | |
8 | + # size: size of the avatar image in px | |
9 | + def commit_author_link(commit, options = {}) | |
10 | + commit_person_link(commit, options.merge(source: :author)) | |
11 | + end | |
12 | + | |
13 | + # Just like #author_link but for the committer. | |
14 | + def commit_committer_link(commit, options = {}) | |
15 | + commit_person_link(commit, options.merge(source: :committer)) | |
16 | + end | |
17 | + | |
2 | 18 | def identification_type(line) |
3 | 19 | if line[0] == "+" |
4 | 20 | "new" |
... | ... | @@ -93,9 +109,7 @@ module CommitsHelper |
93 | 109 | end |
94 | 110 | |
95 | 111 | def commit_to_html commit |
96 | - if commit.model | |
97 | - escape_javascript(render 'commits/commit', commit: commit) | |
98 | - end | |
112 | + escape_javascript(render 'commits/commit', commit: commit) | |
99 | 113 | end |
100 | 114 | |
101 | 115 | def diff_line_content(line) |
... | ... | @@ -105,4 +119,58 @@ module CommitsHelper |
105 | 119 | line |
106 | 120 | end |
107 | 121 | end |
122 | + | |
123 | + # Breadcrumb links for a Project and, if applicable, a tree path | |
124 | + def commits_breadcrumbs | |
125 | + return unless @project && @ref | |
126 | + | |
127 | + # Add the root project link and the arrow icon | |
128 | + crumbs = content_tag(:li) do | |
129 | + content_tag(:span, nil, class: 'arrow') + | |
130 | + link_to(@project.name, project_commits_path(@project, @ref)) | |
131 | + end | |
132 | + | |
133 | + if @path | |
134 | + parts = @path.split('/') | |
135 | + | |
136 | + parts.each_with_index do |part, i| | |
137 | + crumbs += content_tag(:span, '/', class: 'divider') | |
138 | + crumbs += content_tag(:li) do | |
139 | + # The text is just the individual part, but the link needs all the parts before it | |
140 | + link_to part, project_commits_path(@project, tree_join(@ref, parts[0..i].join('/'))) | |
141 | + end | |
142 | + end | |
143 | + end | |
144 | + | |
145 | + crumbs.html_safe | |
146 | + end | |
147 | + | |
148 | + protected | |
149 | + | |
150 | + # Private: Returns a link to a person. If the person has a matching user and | |
151 | + # is a member of the current @project it will link to the team member page. | |
152 | + # Otherwise it will link to the person email as specified in the commit. | |
153 | + # | |
154 | + # options: | |
155 | + # source: one of :author or :committer | |
156 | + # avatar: true will prepend the avatar image | |
157 | + # size: size of the avatar image in px | |
158 | + def commit_person_link(commit, options = {}) | |
159 | + source_name = commit.send "#{options[:source]}_name".to_sym | |
160 | + source_email = commit.send "#{options[:source]}_email".to_sym | |
161 | + text = if options[:avatar] | |
162 | + avatar = image_tag(gravatar_icon(source_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "") | |
163 | + %Q{#{avatar} <span class="commit-#{options[:source]}-name">#{source_name}</span>} | |
164 | + else | |
165 | + source_name | |
166 | + end | |
167 | + | |
168 | + user = User.where('name like ? or email like ?', source_name, source_email).first | |
169 | + | |
170 | + if user.nil? | |
171 | + mail_to(source_email, text.html_safe, class: "commit-#{options[:source]}-link") | |
172 | + else | |
173 | + link_to(text.html_safe, user_path(user), class: "commit-#{options[:source]}-link") | |
174 | + end | |
175 | + end | |
108 | 176 | end | ... | ... |
app/helpers/tree_helper.rb
... | ... | @@ -70,28 +70,26 @@ module TreeHelper |
70 | 70 | end |
71 | 71 | end |
72 | 72 | |
73 | - # Breadcrumb links for a Project and, if applicable, a tree path | |
74 | - def breadcrumbs | |
75 | - return unless @project && @ref | |
76 | - | |
77 | - # Add the root project link and the arrow icon | |
78 | - crumbs = content_tag(:li) do | |
79 | - content_tag(:span, nil, class: 'arrow') + | |
80 | - link_to(@project.name, project_commits_path(@project, @ref)) | |
81 | - end | |
73 | + def tree_breadcrumbs(tree, max_links = 2) | |
74 | + if tree.path | |
75 | + part_path = "" | |
76 | + parts = tree.path.split("\/") | |
77 | + | |
78 | + yield('..', nil) if parts.count > max_links | |
82 | 79 | |
83 | - if @path | |
84 | - parts = @path.split('/') | |
80 | + parts.each do |part| | |
81 | + part_path = File.join(part_path, part) unless part_path.empty? | |
82 | + part_path = part if part_path.empty? | |
85 | 83 | |
86 | - parts.each_with_index do |part, i| | |
87 | - crumbs += content_tag(:span, '/', class: 'divider') | |
88 | - crumbs += content_tag(:li) do | |
89 | - # The text is just the individual part, but the link needs all the parts before it | |
90 | - link_to part, project_commits_path(@project, tree_join(@ref, parts[0..i].join('/'))) | |
91 | - end | |
84 | + next unless parts.last(2).include?(part) if parts.count > max_links | |
85 | + yield(part, tree_join(tree.ref, part_path)) | |
92 | 86 | end |
93 | 87 | end |
88 | + end | |
94 | 89 | |
95 | - crumbs.html_safe | |
90 | + def up_dir_path tree | |
91 | + file = File.join(tree.path, "..") | |
92 | + tree_join(tree.ref, file) | |
96 | 93 | end |
94 | + | |
97 | 95 | end | ... | ... |
app/mailers/emails/notes.rb
... | ... | @@ -3,7 +3,6 @@ module Emails |
3 | 3 | def note_commit_email(recipient_id, note_id) |
4 | 4 | @note = Note.find(note_id) |
5 | 5 | @commit = @note.noteable |
6 | - @commit = CommitDecorator.decorate(@commit) | |
7 | 6 | @project = @note.project |
8 | 7 | mail(to: recipient(recipient_id), subject: subject("note for commit #{@commit.short_id}", @commit.title)) |
9 | 8 | end | ... | ... |
app/models/commit.rb
... | ... | @@ -8,174 +8,70 @@ class Commit |
8 | 8 | # |
9 | 9 | DIFF_SAFE_SIZE = 100 |
10 | 10 | |
11 | - attr_accessor :commit, :head, :refs | |
12 | - | |
13 | - delegate :message, :authored_date, :committed_date, :parents, :sha, | |
14 | - :date, :committer, :author, :diffs, :tree, :id, :stats, | |
15 | - :to_patch, to: :commit | |
16 | - | |
17 | - class << self | |
18 | - def find_or_first(repo, commit_id = nil, root_ref) | |
19 | - commit = if commit_id | |
20 | - repo.commit(commit_id) | |
21 | - else | |
22 | - repo.commits(root_ref).first | |
23 | - end | |
24 | - | |
25 | - Commit.new(commit) if commit | |
26 | - end | |
27 | - | |
28 | - def fresh_commits(repo, n = 10) | |
29 | - commits = repo.heads.map do |h| | |
30 | - repo.commits(h.name, n).map { |c| Commit.new(c, h) } | |
31 | - end.flatten.uniq { |c| c.id } | |
32 | - | |
33 | - commits.sort! do |x, y| | |
34 | - y.committed_date <=> x.committed_date | |
35 | - end | |
36 | - | |
37 | - commits[0...n] | |
38 | - end | |
39 | - | |
40 | - def commits_with_refs(repo, n = 20) | |
41 | - commits = repo.branches.map { |ref| Commit.new(ref.commit, ref) } | |
42 | - | |
43 | - commits.sort! do |x, y| | |
44 | - y.committed_date <=> x.committed_date | |
45 | - end | |
46 | - | |
47 | - commits[0..n] | |
48 | - end | |
49 | - | |
50 | - def commits_since(repo, date) | |
51 | - commits = repo.heads.map do |h| | |
52 | - repo.log(h.name, nil, since: date).each { |c| Commit.new(c, h) } | |
53 | - end.flatten.uniq { |c| c.id } | |
54 | - | |
55 | - commits.sort! do |x, y| | |
56 | - y.committed_date <=> x.committed_date | |
57 | - end | |
58 | - | |
59 | - commits | |
60 | - end | |
61 | - | |
62 | - def commits(repo, ref, path = nil, limit = nil, offset = nil) | |
63 | - if path | |
64 | - repo.log(ref, path, max_count: limit, skip: offset) | |
65 | - elsif limit && offset | |
66 | - repo.commits(ref, limit, offset) | |
67 | - else | |
68 | - repo.commits(ref) | |
69 | - end.map{ |c| Commit.new(c) } | |
70 | - end | |
71 | - | |
72 | - def commits_between(repo, from, to) | |
73 | - repo.commits_between(from, to).map { |c| Commit.new(c) } | |
74 | - end | |
75 | - | |
76 | - def compare(project, from, to) | |
77 | - result = { | |
78 | - commits: [], | |
79 | - diffs: [], | |
80 | - commit: nil, | |
81 | - same: false | |
82 | - } | |
83 | - | |
84 | - return result unless from && to | |
85 | - | |
86 | - first = project.repository.commit(to.try(:strip)) | |
87 | - last = project.repository.commit(from.try(:strip)) | |
88 | - | |
89 | - if first && last | |
90 | - result[:same] = (first.id == last.id) | |
91 | - result[:commits] = project.repo.commits_between(last.id, first.id).map {|c| Commit.new(c)} | |
92 | - | |
93 | - # Dont load diff for 100+ commits | |
94 | - result[:diffs] = if result[:commits].size > 100 | |
95 | - [] | |
96 | - else | |
97 | - project.repo.diff(last.id, first.id) rescue [] | |
98 | - end | |
99 | - | |
100 | - result[:commit] = Commit.new(first) | |
101 | - end | |
102 | - | |
103 | - result | |
104 | - end | |
105 | - end | |
106 | - | |
107 | - def initialize(raw_commit, head = nil) | |
108 | - raise "Nil as raw commit passed" unless raw_commit | |
109 | - | |
110 | - @commit = raw_commit | |
111 | - @head = head | |
112 | - end | |
113 | - | |
114 | - def short_id(length = 10) | |
115 | - id.to_s[0..length] | |
11 | + def self.decorate(commits) | |
12 | + commits.map { |c| self.new(c) } | |
116 | 13 | end |
117 | 14 | |
118 | - def safe_message | |
119 | - @safe_message ||= message | |
120 | - end | |
121 | - | |
122 | - def created_at | |
123 | - committed_date | |
124 | - end | |
15 | + attr_accessor :raw | |
125 | 16 | |
126 | - def author_email | |
127 | - author.email | |
128 | - end | |
17 | + def initialize(raw_commit) | |
18 | + raise "Nil as raw commit passed" unless raw_commit | |
129 | 19 | |
130 | - def author_name | |
131 | - author.name | |
20 | + @raw = raw_commit | |
132 | 21 | end |
133 | 22 | |
134 | - # Was this commit committed by a different person than the original author? | |
135 | - def different_committer? | |
136 | - author_name != committer_name || author_email != committer_email | |
23 | + def id | |
24 | + @raw.id | |
137 | 25 | end |
138 | 26 | |
139 | - def committer_name | |
140 | - committer.name | |
27 | + # Returns a string describing the commit for use in a link title | |
28 | + # | |
29 | + # Example | |
30 | + # | |
31 | + # "Commit: Alex Denisov - Project git clone panel" | |
32 | + def link_title | |
33 | + "Commit: #{author_name} - #{title}" | |
141 | 34 | end |
142 | 35 | |
143 | - def committer_email | |
144 | - committer.email | |
36 | + # Returns the commits title. | |
37 | + # | |
38 | + # Usually, the commit title is the first line of the commit message. | |
39 | + # In case this first line is longer than 80 characters, it is cut off | |
40 | + # after 70 characters and ellipses (`&hellp;`) are appended. | |
41 | + def title | |
42 | + title = safe_message | |
43 | + | |
44 | + return no_commit_message if title.blank? | |
45 | + | |
46 | + title_end = title.index(/\n/) | |
47 | + if (!title_end && title.length > 80) || (title_end && title_end > 80) | |
48 | + title[0..69] << "…".html_safe | |
49 | + else | |
50 | + title.split(/\n/, 2).first | |
51 | + end | |
145 | 52 | end |
146 | 53 | |
147 | - def prev_commit | |
148 | - @prev_commit ||= if parents.present? | |
149 | - Commit.new(parents.first) | |
150 | - else | |
151 | - nil | |
152 | - end | |
54 | + # Returns the commits description | |
55 | + # | |
56 | + # cut off, ellipses (`&hellp;`) are prepended to the commit message. | |
57 | + def description | |
58 | + description = safe_message | |
59 | + | |
60 | + title_end = description.index(/\n/) | |
61 | + if (!title_end && description.length > 80) || (title_end && title_end > 80) | |
62 | + "…".html_safe << description[70..-1] | |
63 | + else | |
64 | + description.split(/\n/, 2)[1].try(:chomp) | |
65 | + end | |
153 | 66 | end |
154 | 67 | |
155 | - def prev_commit_id | |
156 | - prev_commit.try :id | |
68 | + def method_missing(m, *args, &block) | |
69 | + @raw.send(m, *args, &block) | |
157 | 70 | end |
158 | 71 | |
159 | - # Shows the diff between the commit's parent and the commit. | |
160 | - # | |
161 | - # Cuts out the header and stats from #to_patch and returns only the diff. | |
162 | - def to_diff | |
163 | - # see Grit::Commit#show | |
164 | - patch = to_patch | |
165 | - | |
166 | - # discard lines before the diff | |
167 | - lines = patch.split("\n") | |
168 | - while !lines.first.start_with?("diff --git") do | |
169 | - lines.shift | |
170 | - end | |
171 | - lines.pop if lines.last =~ /^[\d.]+$/ # Git version | |
172 | - lines.pop if lines.last == "-- " # end of diff | |
173 | - lines.join("\n") | |
174 | - end | |
72 | + def respond_to?(method) | |
73 | + return true if @raw.respond_to?(method) | |
175 | 74 | |
176 | - def has_zero_stats? | |
177 | - stats.total.zero? | |
178 | - rescue | |
179 | - true | |
75 | + super | |
180 | 76 | end |
181 | 77 | end | ... | ... |
app/models/gollum_wiki.rb
... | ... | @@ -50,7 +50,7 @@ class GollumWiki |
50 | 50 | # Returns the last 30 Commit objects across the entire |
51 | 51 | # repository. |
52 | 52 | def recent_history |
53 | - Commit.fresh_commits(wiki.repo, 30) | |
53 | + Gitlab::Git::Commit.fresh_commits(wiki.repo, 30) | |
54 | 54 | end |
55 | 55 | |
56 | 56 | # Finds a page within the repository based on a tile |
... | ... | @@ -90,13 +90,17 @@ class GollumWiki |
90 | 90 | private |
91 | 91 | |
92 | 92 | def create_repo! |
93 | - if gitlab_shell.add_repository(path_with_namespace) | |
93 | + if init_repo(path_with_namespace) | |
94 | 94 | Gollum::Wiki.new(path_to_repo) |
95 | 95 | else |
96 | 96 | raise CouldNotCreateWikiError |
97 | 97 | end |
98 | 98 | end |
99 | 99 | |
100 | + def init_repo(path_with_namespace) | |
101 | + gitlab_shell.add_repository(path_with_namespace) | |
102 | + end | |
103 | + | |
100 | 104 | def commit_details(action, message = nil, title = nil) |
101 | 105 | commit_message = message || default_message(action, title) |
102 | 106 | |
... | ... | @@ -114,5 +118,4 @@ class GollumWiki |
114 | 118 | def path_to_repo |
115 | 119 | @path_to_repo ||= File.join(Gitlab.config.gitlab_shell.repos_path, "#{path_with_namespace}.git") |
116 | 120 | end |
117 | - | |
118 | 121 | end | ... | ... |
app/models/merge_request.rb
... | ... | @@ -152,7 +152,17 @@ class MergeRequest < ActiveRecord::Base |
152 | 152 | end |
153 | 153 | |
154 | 154 | def commits |
155 | - st_commits || [] | |
155 | + if st_commits.present? | |
156 | + # check if merge request commits are valid | |
157 | + if st_commits.first.respond_to?(:short_id) | |
158 | + st_commits | |
159 | + else | |
160 | + # if commits are invalid - simply reload it from repo | |
161 | + reloaded_commits | |
162 | + end | |
163 | + else | |
164 | + [] | |
165 | + end | |
156 | 166 | end |
157 | 167 | |
158 | 168 | def probably_merged? |
... | ... | @@ -169,9 +179,8 @@ class MergeRequest < ActiveRecord::Base |
169 | 179 | end |
170 | 180 | |
171 | 181 | def unmerged_commits |
172 | - self.project.repo. | |
182 | + self.project.repository. | |
173 | 183 | commits_between(self.target_branch, self.source_branch). |
174 | - map {|c| Commit.new(c)}. | |
175 | 184 | sort_by(&:created_at). |
176 | 185 | reverse |
177 | 186 | end | ... | ... |
app/models/network/commit.rb
app/models/project.rb
... | ... | @@ -141,13 +141,7 @@ class Project < ActiveRecord::Base |
141 | 141 | end |
142 | 142 | |
143 | 143 | def repository |
144 | - if path | |
145 | - @repository ||= Repository.new(path_with_namespace, default_branch) | |
146 | - else | |
147 | - nil | |
148 | - end | |
149 | - rescue Grit::NoSuchPathError | |
150 | - nil | |
144 | + @repository ||= Repository.new(path_with_namespace, default_branch) | |
151 | 145 | end |
152 | 146 | |
153 | 147 | def saved? |
... | ... | @@ -332,14 +326,14 @@ class Project < ActiveRecord::Base |
332 | 326 | end |
333 | 327 | |
334 | 328 | def valid_repo? |
335 | - repo | |
329 | + repository.exists? | |
336 | 330 | rescue |
337 | 331 | errors.add(:path, "Invalid repository path") |
338 | 332 | false |
339 | 333 | end |
340 | 334 | |
341 | 335 | def empty_repo? |
342 | - !repository || repository.empty? | |
336 | + !repository.exists? || repository.empty? | |
343 | 337 | end |
344 | 338 | |
345 | 339 | def ensure_satellite_exists |
... | ... | @@ -363,7 +357,7 @@ class Project < ActiveRecord::Base |
363 | 357 | end |
364 | 358 | |
365 | 359 | def repo_exists? |
366 | - @repo_exists ||= (repository && repository.branches.present?) | |
360 | + @repo_exists ||= repository.exists? | |
367 | 361 | rescue |
368 | 362 | @repo_exists = false |
369 | 363 | end | ... | ... |
app/models/repository.rb
1 | 1 | class Repository |
2 | - include Gitlab::Popen | |
2 | + attr_accessor :raw_repository | |
3 | 3 | |
4 | - # Repository directory name with namespace direcotry | |
5 | - # Examples: | |
6 | - # gitlab/gitolite | |
7 | - # diaspora | |
8 | - # | |
9 | - attr_accessor :path_with_namespace | |
10 | - | |
11 | - # Grit repo object | |
12 | - attr_accessor :repo | |
13 | - | |
14 | - # Default branch in the repository | |
15 | - attr_accessor :root_ref | |
16 | - | |
17 | - def initialize(path_with_namespace, root_ref = 'master') | |
18 | - @root_ref = root_ref || "master" | |
19 | - @path_with_namespace = path_with_namespace | |
20 | - | |
21 | - # Init grit repo object | |
22 | - repo | |
23 | - end | |
24 | - | |
25 | - def raw | |
26 | - repo | |
27 | - end | |
28 | - | |
29 | - def path_to_repo | |
30 | - @path_to_repo ||= File.join(Gitlab.config.gitlab_shell.repos_path, "#{path_with_namespace}.git") | |
31 | - end | |
32 | - | |
33 | - def repo | |
34 | - @repo ||= Grit::Repo.new(path_to_repo) | |
35 | - end | |
36 | - | |
37 | - def commit(commit_id = nil) | |
38 | - Commit.find_or_first(repo, commit_id, root_ref) | |
4 | + def initialize(path_with_namespace, default_branch) | |
5 | + @raw_repository = Gitlab::Git::Repository.new(path_with_namespace, default_branch) | |
6 | + rescue Gitlab::Git::Repository::NoRepository | |
7 | + nil | |
39 | 8 | end |
40 | 9 | |
41 | - def fresh_commits(n = 10) | |
42 | - Commit.fresh_commits(repo, n) | |
10 | + def exists? | |
11 | + raw_repository | |
43 | 12 | end |
44 | 13 | |
45 | - def commits_with_refs(n = 20) | |
46 | - Commit.commits_with_refs(repo, n) | |
14 | + def empty? | |
15 | + raw_repository.empty? | |
47 | 16 | end |
48 | 17 | |
49 | - def commits_since(date) | |
50 | - Commit.commits_since(repo, date) | |
18 | + def commit(id = nil) | |
19 | + commit = raw_repository.commit(id) | |
20 | + commit = Commit.new(commit) if commit | |
21 | + commit | |
51 | 22 | end |
52 | 23 | |
53 | 24 | def commits(ref, path = nil, limit = nil, offset = nil) |
54 | - Commit.commits(repo, ref, path, limit, offset) | |
55 | - end | |
56 | - | |
57 | - def last_commit_for(ref, path = nil) | |
58 | - commits(ref, path, 1).first | |
59 | - end | |
60 | - | |
61 | - def commits_between(from, to) | |
62 | - Commit.commits_between(repo, from, to) | |
25 | + commits = raw_repository.commits(ref, path, limit, offset) | |
26 | + commits = Commit.decorate(commits) if commits.present? | |
27 | + commits | |
63 | 28 | end |
64 | 29 | |
65 | - # Returns an Array of branch names | |
66 | - # sorted by name ASC | |
67 | - def branch_names | |
68 | - branches.map(&:name) | |
30 | + def commits_between(target, source) | |
31 | + commits = raw_repository.commits_between(target, source) | |
32 | + commits = Commit.decorate(commits) if commits.present? | |
33 | + commits | |
69 | 34 | end |
70 | 35 | |
71 | - # Returns an Array of Branches | |
72 | - def branches | |
73 | - repo.branches.sort_by(&:name) | |
36 | + def method_missing(m, *args, &block) | |
37 | + raw_repository.send(m, *args, &block) | |
74 | 38 | end |
75 | 39 | |
76 | - # Returns an Array of tag names | |
77 | - def tag_names | |
78 | - repo.tags.collect(&:name).sort.reverse | |
79 | - end | |
80 | - | |
81 | - # Returns an Array of Tags | |
82 | - def tags | |
83 | - repo.tags.sort_by(&:name).reverse | |
84 | - end | |
85 | - | |
86 | - # Returns an Array of branch and tag names | |
87 | - def ref_names | |
88 | - [branch_names + tag_names].flatten | |
89 | - end | |
90 | - | |
91 | - def heads | |
92 | - @heads ||= repo.heads | |
93 | - end | |
94 | - | |
95 | - def tree(fcommit, path = nil) | |
96 | - fcommit = commit if fcommit == :head | |
97 | - tree = fcommit.tree | |
98 | - path ? (tree / path) : tree | |
99 | - end | |
100 | - | |
101 | - def has_commits? | |
102 | - !!commit | |
103 | - rescue Grit::NoSuchPathError | |
104 | - false | |
105 | - end | |
106 | - | |
107 | - def empty? | |
108 | - !has_commits? | |
109 | - end | |
110 | - | |
111 | - # Discovers the default branch based on the repository's available branches | |
112 | - # | |
113 | - # - If no branches are present, returns nil | |
114 | - # - If one branch is present, returns its name | |
115 | - # - If two or more branches are present, returns the one that has a name | |
116 | - # matching root_ref (default_branch or 'master' if default_branch is nil) | |
117 | - def discover_default_branch | |
118 | - if branch_names.length == 0 | |
119 | - nil | |
120 | - elsif branch_names.length == 1 | |
121 | - branch_names.first | |
122 | - else | |
123 | - branch_names.select { |v| v == root_ref }.first | |
124 | - end | |
125 | - end | |
126 | - | |
127 | - # Archive Project to .tar.gz | |
128 | - # | |
129 | - # Already packed repo archives stored at | |
130 | - # app_root/tmp/repositories/project_name/project_name-commit-id.tag.gz | |
131 | - # | |
132 | - def archive_repo(ref) | |
133 | - ref = ref || self.root_ref | |
134 | - commit = self.commit(ref) | |
135 | - return nil unless commit | |
136 | - | |
137 | - # Build file path | |
138 | - file_name = self.path_with_namespace.gsub("/","_") + "-" + commit.id.to_s + ".tar.gz" | |
139 | - storage_path = Rails.root.join("tmp", "repositories") | |
140 | - file_path = File.join(storage_path, self.path_with_namespace, file_name) | |
141 | - | |
142 | - # Put files into a directory before archiving | |
143 | - prefix = File.basename(self.path_with_namespace) + "/" | |
144 | - | |
145 | - # Create file if not exists | |
146 | - unless File.exists?(file_path) | |
147 | - FileUtils.mkdir_p File.dirname(file_path) | |
148 | - file = self.repo.archive_to_file(ref, prefix, file_path) | |
149 | - end | |
150 | - | |
151 | - file_path | |
152 | - end | |
153 | - | |
154 | - # Return repo size in megabytes | |
155 | - # Cached in redis | |
156 | - def size | |
157 | - Rails.cache.fetch(cache_key(:size)) do | |
158 | - size = popen('du -s', path_to_repo).first.strip.to_i | |
159 | - (size.to_f / 1024).round(2) | |
160 | - end | |
161 | - end | |
162 | - | |
163 | - def expire_cache | |
164 | - Rails.cache.delete(cache_key(:size)) | |
165 | - end | |
40 | + def respond_to?(method) | |
41 | + return true if raw_repository.respond_to?(method) | |
166 | 42 | |
167 | - def cache_key(type) | |
168 | - "#{type}:#{path_with_namespace}" | |
43 | + super | |
169 | 44 | end |
170 | 45 | end | ... | ... |
app/models/tree.rb
app/models/wiki_page.rb
... | ... | @@ -79,14 +79,14 @@ class WikiPage |
79 | 79 | def version |
80 | 80 | return nil unless persisted? |
81 | 81 | |
82 | - @version ||= Commit.new(@page.version) | |
82 | + @version ||= Commit.new(Gitlab::Git::Commit.new(@page.version)) | |
83 | 83 | end |
84 | 84 | |
85 | 85 | # Returns an array of Gitlab Commit instances. |
86 | 86 | def versions |
87 | 87 | return [] unless persisted? |
88 | 88 | |
89 | - @page.versions.map { |v| Commit.new(v) } | |
89 | + @page.versions.map { |v| Commit.new(Gitlab::Git::Commit.new(v)) } | |
90 | 90 | end |
91 | 91 | |
92 | 92 | # Returns the Date that this latest version was | ... | ... |
app/views/admin/projects/show.html.haml
... | ... | @@ -46,18 +46,21 @@ |
46 | 46 | %span.light ssh: |
47 | 47 | %strong |
48 | 48 | = link_to @project.ssh_url_to_repo |
49 | - %li | |
50 | - %span.light fs: | |
51 | - %strong | |
52 | - = @repository.path_to_repo | |
49 | + - if @project.repository.exists? | |
50 | + %li | |
51 | + %span.light fs: | |
52 | + %strong | |
53 | + = @repository.path_to_repo | |
53 | 54 | |
54 | - %li | |
55 | - %span.light last commit: | |
56 | - %strong | |
57 | - - if @repository | |
55 | + %li | |
56 | + %span.light last commit: | |
57 | + %strong | |
58 | 58 | = last_commit(@project) |
59 | - - else | |
60 | - never | |
59 | + - else | |
60 | + %li | |
61 | + %span.light repository: | |
62 | + %strong.cred | |
63 | + does not exist | |
61 | 64 | |
62 | 65 | %li |
63 | 66 | %span.light access: | ... | ... |
app/views/blame/show.html.haml
... | ... | @@ -6,7 +6,7 @@ |
6 | 6 | %i.icon-angle-right |
7 | 7 | = link_to project_tree_path(@project, @ref) do |
8 | 8 | = @project.name |
9 | - - @tree.breadcrumbs(6) do |link| | |
9 | + - tree_breadcrumbs(@tree, 6) do |link| | |
10 | 10 | \/ |
11 | 11 | %li= link |
12 | 12 | .clear |
... | ... | @@ -22,13 +22,13 @@ |
22 | 22 | %table |
23 | 23 | - current_line = 1 |
24 | 24 | - @blame.each do |commit, lines| |
25 | - - commit = CommitDecorator.decorate(Commit.new(commit)) | |
25 | + - commit = Commit.new(commit) | |
26 | 26 | %tr |
27 | 27 | %td.blame-commit |
28 | 28 | %span.commit |
29 | 29 | = link_to commit.short_id(8), project_commit_path(@project, commit), class: "commit_short_id" |
30 | 30 | |
31 | - = commit.author_link avatar: true, size: 16 | |
31 | + = commit_author_link(commit, avatar: true, size: 16) | |
32 | 32 | |
33 | 33 | = link_to_gfm truncate(commit.title, length: 20), project_commit_path(@project, commit.id), class: "row_title" |
34 | 34 | %td.lines.blame-numbers | ... | ... |
app/views/commit/_commit_box.html.haml
... | ... | @@ -24,14 +24,14 @@ |
24 | 24 | .row |
25 | 25 | .span5 |
26 | 26 | .author |
27 | - = @commit.author_link avatar: true, size: 32 | |
27 | + = commit_author_link(@commit, avatar: true, size: 32) | |
28 | 28 | authored |
29 | 29 | %time{title: @commit.authored_date.stamp("Aug 21, 2011 9:23pm")} |
30 | 30 | #{time_ago_in_words(@commit.authored_date)} ago |
31 | 31 | - if @commit.different_committer? |
32 | 32 | .committer |
33 | 33 | → |
34 | - = @commit.committer_link | |
34 | + = commit_committer_link(@commit) | |
35 | 35 | committed |
36 | 36 | %time{title: @commit.committed_date.stamp("Aug 21, 2011 9:23pm")} |
37 | 37 | #{time_ago_in_words(@commit.committed_date)} ago | ... | ... |
app/views/commits/_commit.html.haml
... | ... | @@ -4,7 +4,7 @@ |
4 | 4 | %strong= link_to "Browse Code »", project_tree_path(@project, commit), class: "right" |
5 | 5 | %p |
6 | 6 | = link_to commit.short_id(8), project_commit_path(@project, commit), class: "commit_short_id" |
7 | - = commit.author_link avatar: true, size: 24 | |
7 | + = commit_author_link(commit, avatar: true, size: 24) | |
8 | 8 | |
9 | 9 | = link_to_gfm truncate(commit.title, length: 70), project_commit_path(@project, commit.id), class: "row_title" |
10 | 10 | ... | ... |
app/views/commits/show.html.haml
app/views/compare/show.html.haml
app/views/events/_commit.html.haml
app/views/projects/_clone_panel.html.haml
... | ... | @@ -4,7 +4,7 @@ |
4 | 4 | .form-horizontal= render "shared/clone_panel" |
5 | 5 | .span4.pull-right |
6 | 6 | .pull-right |
7 | - - unless @project.empty_repo? | |
7 | + - if @project.empty_repo? | |
8 | 8 | - if can? current_user, :download_code, @project |
9 | 9 | = link_to archive_project_repository_path(@project), class: "btn-small btn grouped" do |
10 | 10 | %i.icon-download-alt | ... | ... |
app/views/repositories/_branch.html.haml
app/views/repositories/_feed.html.haml
app/views/repositories/tags.html.haml
app/views/tree/_tree.html.haml
... | ... | @@ -3,7 +3,7 @@ |
3 | 3 | %i.icon-angle-right |
4 | 4 | = link_to project_tree_path(@project, @ref) do |
5 | 5 | = @project.path |
6 | - - tree.breadcrumbs(6) do |title, path| | |
6 | + - tree_breadcrumbs(tree, 6) do |title, path| | |
7 | 7 | \/ |
8 | 8 | %li |
9 | 9 | - if path |
... | ... | @@ -27,7 +27,7 @@ |
27 | 27 | %tr.tree-item |
28 | 28 | %td.tree-item-file-name |
29 | 29 | = image_tag "file_empty.png", size: '16x16' |
30 | - = link_to "..", project_tree_path(@project, tree.up_dir_path) | |
30 | + = link_to "..", project_tree_path(@project, up_dir_path(tree)) | |
31 | 31 | %td |
32 | 32 | %td |
33 | 33 | %td | ... | ... |
app/views/tree/_tree_commit_column.html.haml
app/views/wikis/history.html.haml
... | ... | @@ -14,12 +14,13 @@ |
14 | 14 | %th Format |
15 | 15 | %tbody |
16 | 16 | - @wiki.versions.each do |version| |
17 | - - commit = CommitDecorator.new(version) | |
17 | + - commit = version | |
18 | 18 | %tr |
19 | 19 | %td |
20 | 20 | = link_to project_wiki_path(@project, @wiki, version_id: commit.id) do |
21 | 21 | = commit.short_id |
22 | - %td= commit.author_link avatar: true, size: 24 | |
22 | + %td | |
23 | + = commit_author_link(commit, avatar: true, size: 24) | |
23 | 24 | %td |
24 | 25 | = commit.title |
25 | 26 | %td | ... | ... |
app/views/wikis/pages.html.haml
... | ... | @@ -21,5 +21,5 @@ |
21 | 21 | = wiki_page.created_at.to_s(:short) do |
22 | 22 | (#{time_ago_in_words(wiki_page.created_at)} |
23 | 23 | ago) |
24 | - - commit = CommitDecorator.decorate(wiki_page.version) | |
25 | - %td= commit.author_link avatar: true, size: 24 | |
24 | + %td | |
25 | + = commit_author_link(wiki_page.version, avatar: true, size: 24) | ... | ... |
app/views/wikis/show.html.haml
... | ... | @@ -13,5 +13,4 @@ |
13 | 13 | = preserve do |
14 | 14 | = render_wiki_content(@wiki) |
15 | 15 | |
16 | -- commit = CommitDecorator.new(@wiki.version) | |
17 | -%p.time Last edited by #{commit.author_link(avatar: true, size: 16)} #{time_ago_in_words @wiki.created_at} ago | |
16 | +%p.time Last edited by #{commit_author_link(@wiki.version, avatar: true, size: 16)} #{time_ago_in_words @wiki.created_at} ago | ... | ... |
features/steps/project/project_browse_commits.rb
... | ... | @@ -15,7 +15,7 @@ class ProjectBrowseCommits < Spinach::FeatureSteps |
15 | 15 | end |
16 | 16 | |
17 | 17 | Then 'I see commits atom feed' do |
18 | - commit = CommitDecorator.decorate(@project.repository.commit) | |
18 | + commit = @project.repository.commit | |
19 | 19 | page.response_headers['Content-Type'].should have_content("application/atom+xml") |
20 | 20 | page.body.should have_selector("title", :text => "Recent commits to #{@project.name}") |
21 | 21 | page.body.should have_selector("author email", :text => commit.author_email) | ... | ... |
features/steps/shared/project.rb
... | ... | @@ -3,14 +3,14 @@ module SharedProject |
3 | 3 | |
4 | 4 | # Create a project without caring about what it's called |
5 | 5 | And "I own a project" do |
6 | - @project = create(:project) | |
6 | + @project = create(:project_with_code) | |
7 | 7 | @project.team << [@user, :master] |
8 | 8 | end |
9 | 9 | |
10 | 10 | # Create a specific project called "Shop" |
11 | 11 | And 'I own project "Shop"' do |
12 | 12 | @project = Project.find_by_name "Shop" |
13 | - @project ||= create(:project, name: "Shop") | |
13 | + @project ||= create(:project_with_code, name: "Shop") | |
14 | 14 | @project.team << [@user, :master] |
15 | 15 | end |
16 | 16 | ... | ... |
features/steps/userteams/userteams.rb
... | ... | @@ -132,7 +132,7 @@ class Userteams < Spinach::FeatureSteps |
132 | 132 | team = UserTeam.last |
133 | 133 | team.projects.each do |project| |
134 | 134 | team.members.each do |member| |
135 | - 3.times { project.merge_requests << create(:merge_request, assignee: member) } | |
135 | + 3.times { create(:merge_request, assignee: member, project: project) } | |
136 | 136 | end |
137 | 137 | end |
138 | 138 | end |
... | ... | @@ -157,7 +157,7 @@ class Userteams < Spinach::FeatureSteps |
157 | 157 | team = UserTeam.last |
158 | 158 | team.projects.each do |project| |
159 | 159 | team.members.each do |member| |
160 | - 3.times { project.merge_requests << create(:merge_request, assignee: member) } | |
160 | + 3.times { create(:merge_request, assignee: member, project: project) } | |
161 | 161 | end |
162 | 162 | end |
163 | 163 | end | ... | ... |
features/support/env.rb
... | ... | @@ -14,7 +14,7 @@ require 'spinach/capybara' |
14 | 14 | require 'sidekiq/testing/inline' |
15 | 15 | |
16 | 16 | |
17 | -%w(stubbed_repository valid_commit select2_helper).each do |f| | |
17 | +%w(valid_commit select2_helper test_env).each do |f| | |
18 | 18 | require Rails.root.join('spec', 'support', f) |
19 | 19 | end |
20 | 20 | |
... | ... | @@ -35,13 +35,8 @@ Capybara.default_wait_time = 10 |
35 | 35 | DatabaseCleaner.strategy = :truncation |
36 | 36 | |
37 | 37 | Spinach.hooks.before_scenario do |
38 | - # Use tmp dir for FS manipulations | |
39 | - Gitlab.config.gitlab_shell.stub(repos_path: Rails.root.join('tmp', 'test-git-base-path')) | |
40 | - Gitlab::Shell.any_instance.stub(:add_repository) do |path| | |
41 | - create_temp_repo("#{Rails.root}/tmp/test-git-base-path/#{path}.git") | |
42 | - end | |
43 | - FileUtils.rm_rf Gitlab.config.gitlab_shell.repos_path | |
44 | - FileUtils.mkdir_p Gitlab.config.gitlab_shell.repos_path | |
38 | + TestEnv.init | |
39 | + | |
45 | 40 | DatabaseCleaner.start |
46 | 41 | end |
47 | 42 | |
... | ... | @@ -54,9 +49,3 @@ Spinach.hooks.before_run do |
54 | 49 | |
55 | 50 | include FactoryGirl::Syntax::Methods |
56 | 51 | end |
57 | - | |
58 | -def create_temp_repo(path) | |
59 | - FileUtils.mkdir_p path | |
60 | - command = "git init --quiet --bare #{path};" | |
61 | - system(command) | |
62 | -end | ... | ... |
lib/api/projects.rb
... | ... | @@ -372,7 +372,7 @@ module Gitlab |
372 | 372 | ref = params[:ref_name] || user_project.try(:default_branch) || 'master' |
373 | 373 | |
374 | 374 | commits = user_project.repository.commits(ref, nil, per_page, page * per_page) |
375 | - present CommitDecorator.decorate(commits), with: Entities::RepoCommit | |
375 | + present commits, with: Entities::RepoCommit | |
376 | 376 | end |
377 | 377 | |
378 | 378 | # Get a project snippets | ... | ... |
lib/extracts_path.rb
... | ... | @@ -85,8 +85,8 @@ module ExtractsPath |
85 | 85 | # - @id - A string representing the joined ref and path |
86 | 86 | # - @ref - A string representing the ref (e.g., the branch, tag, or commit SHA) |
87 | 87 | # - @path - A string representing the filesystem path |
88 | - # - @commit - A CommitDecorator representing the commit from the given ref | |
89 | - # - @tree - A TreeDecorator representing the tree at the given ref/path | |
88 | + # - @commit - A Commit representing the commit from the given ref | |
89 | + # - @tree - A Tree representing the tree at the given ref/path | |
90 | 90 | # |
91 | 91 | # If the :id parameter appears to be requesting a specific response format, |
92 | 92 | # that will be handled as well. |
... | ... | @@ -100,11 +100,9 @@ module ExtractsPath |
100 | 100 | |
101 | 101 | # It is used "@project.repository.commits(@ref, @path, 1, 0)", |
102 | 102 | # because "@project.repository.commit(@ref)" returns wrong commit when @ref is tag name. |
103 | - commits = @project.repository.commits(@ref, @path, 1, 0) | |
104 | - @commit = CommitDecorator.decorate(commits.first) | |
103 | + @commit = @project.repository.commits(@ref, @path, 1, 0).first | |
105 | 104 | |
106 | 105 | @tree = Tree.new(@commit.tree, @ref, @path) |
107 | - @tree = TreeDecorator.new(@tree) | |
108 | 106 | |
109 | 107 | raise InvalidPathError if @tree.invalid? |
110 | 108 | rescue RuntimeError, NoMethodError, InvalidPathError | ... | ... |
... | ... | @@ -0,0 +1,22 @@ |
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 | + | |
10 | + end | |
11 | + | |
12 | + def each | |
13 | + raw_blame = Grit::Blob.blame(repository.repo, sha, path) | |
14 | + | |
15 | + raw_blame.each do |commit, lines| | |
16 | + commit = Gitlab::Git::Commit.new(commit) | |
17 | + yield(commit, lines) | |
18 | + end | |
19 | + end | |
20 | + end | |
21 | + end | |
22 | +end | ... | ... |
... | ... | @@ -0,0 +1,153 @@ |
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 | + | |
9 | + delegate :message, :authored_date, :committed_date, :parents, :sha, | |
10 | + :date, :committer, :author, :diffs, :tree, :id, :stats, :to_patch, | |
11 | + to: :raw_commit | |
12 | + | |
13 | + class << self | |
14 | + def find_or_first(repo, commit_id = nil, root_ref) | |
15 | + commit = if commit_id | |
16 | + repo.commit(commit_id) | |
17 | + else | |
18 | + repo.commits(root_ref).first | |
19 | + end | |
20 | + | |
21 | + Commit.new(commit) if commit | |
22 | + end | |
23 | + | |
24 | + def fresh_commits(repo, n = 10) | |
25 | + commits = repo.heads.map do |h| | |
26 | + repo.commits(h.name, n).map { |c| Commit.new(c, h) } | |
27 | + end.flatten.uniq { |c| c.id } | |
28 | + | |
29 | + commits.sort! do |x, y| | |
30 | + y.committed_date <=> x.committed_date | |
31 | + end | |
32 | + | |
33 | + commits[0...n] | |
34 | + end | |
35 | + | |
36 | + def commits_with_refs(repo, n = 20) | |
37 | + commits = repo.branches.map { |ref| Commit.new(ref.commit, ref) } | |
38 | + | |
39 | + commits.sort! do |x, y| | |
40 | + y.committed_date <=> x.committed_date | |
41 | + end | |
42 | + | |
43 | + commits[0..n] | |
44 | + end | |
45 | + | |
46 | + def commits_since(repo, date) | |
47 | + commits = repo.heads.map do |h| | |
48 | + repo.log(h.name, nil, since: date).each { |c| Commit.new(c, h) } | |
49 | + end.flatten.uniq { |c| c.id } | |
50 | + | |
51 | + commits.sort! do |x, y| | |
52 | + y.committed_date <=> x.committed_date | |
53 | + end | |
54 | + | |
55 | + commits | |
56 | + end | |
57 | + | |
58 | + def commits(repo, ref, path = nil, limit = nil, offset = nil) | |
59 | + if path | |
60 | + repo.log(ref, path, max_count: limit, skip: offset) | |
61 | + elsif limit && offset | |
62 | + repo.commits(ref, limit, offset) | |
63 | + else | |
64 | + repo.commits(ref) | |
65 | + end.map{ |c| Commit.new(c) } | |
66 | + end | |
67 | + | |
68 | + def commits_between(repo, from, to) | |
69 | + repo.commits_between(from, to).map { |c| Commit.new(c) } | |
70 | + end | |
71 | + end | |
72 | + | |
73 | + def initialize(raw_commit, head = nil) | |
74 | + raise "Nil as raw commit passed" unless raw_commit | |
75 | + | |
76 | + @raw_commit = raw_commit | |
77 | + @head = head | |
78 | + end | |
79 | + | |
80 | + def short_id(length = 10) | |
81 | + id.to_s[0..length] | |
82 | + end | |
83 | + | |
84 | + def safe_message | |
85 | + @safe_message ||= message | |
86 | + end | |
87 | + | |
88 | + def created_at | |
89 | + committed_date | |
90 | + end | |
91 | + | |
92 | + def author_email | |
93 | + author.email | |
94 | + end | |
95 | + | |
96 | + def author_name | |
97 | + author.name | |
98 | + end | |
99 | + | |
100 | + # Was this commit committed by a different person than the original author? | |
101 | + def different_committer? | |
102 | + author_name != committer_name || author_email != committer_email | |
103 | + end | |
104 | + | |
105 | + def committer_name | |
106 | + committer.name | |
107 | + end | |
108 | + | |
109 | + def committer_email | |
110 | + committer.email | |
111 | + end | |
112 | + | |
113 | + def prev_commit | |
114 | + @prev_commit ||= if parents.present? | |
115 | + Commit.new(parents.first) | |
116 | + else | |
117 | + nil | |
118 | + end | |
119 | + end | |
120 | + | |
121 | + def prev_commit_id | |
122 | + prev_commit.try :id | |
123 | + end | |
124 | + | |
125 | + # Shows the diff between the commit's parent and the commit. | |
126 | + # | |
127 | + # Cuts out the header and stats from #to_patch and returns only the diff. | |
128 | + def to_diff | |
129 | + # see Grit::Commit#show | |
130 | + patch = to_patch | |
131 | + | |
132 | + # discard lines before the diff | |
133 | + lines = patch.split("\n") | |
134 | + while !lines.first.start_with?("diff --git") do | |
135 | + lines.shift | |
136 | + end | |
137 | + lines.pop if lines.last =~ /^[\d.]+$/ # Git version | |
138 | + lines.pop if lines.last == "-- " # end of diff | |
139 | + lines.join("\n") | |
140 | + end | |
141 | + | |
142 | + def has_zero_stats? | |
143 | + stats.total.zero? | |
144 | + rescue | |
145 | + true | |
146 | + end | |
147 | + | |
148 | + def no_commit_message | |
149 | + "--no commit message" | |
150 | + end | |
151 | + end | |
152 | + end | |
153 | +end | ... | ... |
... | ... | @@ -0,0 +1,37 @@ |
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 = Commit.new(first) | |
24 | + | |
25 | + @commits = repository.commits_between(last.id, first.id) | |
26 | + @commits = @commits.map { |c| Commit.new(c) } | |
27 | + | |
28 | + @diffs = if @commits.size > 100 | |
29 | + [] | |
30 | + else | |
31 | + repository.repo.diff(last.id, first.id) rescue [] | |
32 | + end | |
33 | + end | |
34 | + end | |
35 | + end | |
36 | +end | |
37 | + | ... | ... |
... | ... | @@ -0,0 +1,185 @@ |
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 | + Gitlab::Git::Commit.find_or_first(repo, commit_id, root_ref) | |
52 | + end | |
53 | + | |
54 | + def fresh_commits(n = 10) | |
55 | + Gitlab::Git::Commit.fresh_commits(repo, n) | |
56 | + end | |
57 | + | |
58 | + def commits_with_refs(n = 20) | |
59 | + Gitlab::Git::Commit.commits_with_refs(repo, n) | |
60 | + end | |
61 | + | |
62 | + def commits_since(date) | |
63 | + Gitlab::Git::Commit.commits_since(repo, date) | |
64 | + end | |
65 | + | |
66 | + def commits(ref, path = nil, limit = nil, offset = nil) | |
67 | + Gitlab::Git::Commit.commits(repo, ref, path, limit, offset) | |
68 | + end | |
69 | + | |
70 | + def last_commit_for(ref, path = nil) | |
71 | + commits(ref, path, 1).first | |
72 | + end | |
73 | + | |
74 | + def commits_between(from, to) | |
75 | + Gitlab::Git::Commit.commits_between(repo, from, to) | |
76 | + end | |
77 | + | |
78 | + # Returns an Array of branch names | |
79 | + # sorted by name ASC | |
80 | + def branch_names | |
81 | + branches.map(&:name) | |
82 | + end | |
83 | + | |
84 | + # Returns an Array of Branches | |
85 | + def branches | |
86 | + repo.branches.sort_by(&:name) | |
87 | + end | |
88 | + | |
89 | + # Returns an Array of tag names | |
90 | + def tag_names | |
91 | + repo.tags.collect(&:name).sort.reverse | |
92 | + end | |
93 | + | |
94 | + # Returns an Array of Tags | |
95 | + def tags | |
96 | + repo.tags.sort_by(&:name).reverse | |
97 | + end | |
98 | + | |
99 | + # Returns an Array of branch and tag names | |
100 | + def ref_names | |
101 | + [branch_names + tag_names].flatten | |
102 | + end | |
103 | + | |
104 | + def heads | |
105 | + @heads ||= repo.heads | |
106 | + end | |
107 | + | |
108 | + def tree(fcommit, path = nil) | |
109 | + fcommit = commit if fcommit == :head | |
110 | + tree = fcommit.tree | |
111 | + path ? (tree / path) : tree | |
112 | + end | |
113 | + | |
114 | + def has_commits? | |
115 | + !!commit | |
116 | + rescue Grit::NoSuchPathError | |
117 | + false | |
118 | + end | |
119 | + | |
120 | + def empty? | |
121 | + !has_commits? | |
122 | + end | |
123 | + | |
124 | + # Discovers the default branch based on the repository's available branches | |
125 | + # | |
126 | + # - If no branches are present, returns nil | |
127 | + # - If one branch is present, returns its name | |
128 | + # - If two or more branches are present, returns the one that has a name | |
129 | + # matching root_ref (default_branch or 'master' if default_branch is nil) | |
130 | + def discover_default_branch | |
131 | + if branch_names.length == 0 | |
132 | + nil | |
133 | + elsif branch_names.length == 1 | |
134 | + branch_names.first | |
135 | + else | |
136 | + branch_names.select { |v| v == root_ref }.first | |
137 | + end | |
138 | + end | |
139 | + | |
140 | + # Archive Project to .tar.gz | |
141 | + # | |
142 | + # Already packed repo archives stored at | |
143 | + # app_root/tmp/repositories/project_name/project_name-commit-id.tag.gz | |
144 | + # | |
145 | + def archive_repo(ref) | |
146 | + ref = ref || self.root_ref | |
147 | + commit = self.commit(ref) | |
148 | + return nil unless commit | |
149 | + | |
150 | + # Build file path | |
151 | + file_name = self.path_with_namespace.gsub("/","_") + "-" + commit.id.to_s + ".tar.gz" | |
152 | + storage_path = Rails.root.join("tmp", "repositories") | |
153 | + file_path = File.join(storage_path, self.path_with_namespace, file_name) | |
154 | + | |
155 | + # Put files into a directory before archiving | |
156 | + prefix = File.basename(self.path_with_namespace) + "/" | |
157 | + | |
158 | + # Create file if not exists | |
159 | + unless File.exists?(file_path) | |
160 | + FileUtils.mkdir_p File.dirname(file_path) | |
161 | + file = self.repo.archive_to_file(ref, prefix, file_path) | |
162 | + end | |
163 | + | |
164 | + file_path | |
165 | + end | |
166 | + | |
167 | + # Return repo size in megabytes | |
168 | + # Cached in redis | |
169 | + def size | |
170 | + Rails.cache.fetch(cache_key(:size)) do | |
171 | + size = popen('du -s', path_to_repo).first.strip.to_i | |
172 | + (size.to_f / 1024).round(2) | |
173 | + end | |
174 | + end | |
175 | + | |
176 | + def expire_cache | |
177 | + Rails.cache.delete(cache_key(:size)) | |
178 | + end | |
179 | + | |
180 | + def cache_key(type) | |
181 | + "#{type}:#{path_with_namespace}" | |
182 | + end | |
183 | + end | |
184 | + end | |
185 | +end | ... | ... |
lib/gitlab/markdown.rb
... | ... | @@ -187,7 +187,7 @@ module Gitlab |
187 | 187 | |
188 | 188 | def reference_commit(identifier) |
189 | 189 | if @project.valid_repo? && commit = @project.repository.commit(identifier) |
190 | - link_to(identifier, project_commit_url(@project, commit), html_options.merge(title: CommitDecorator.new(commit).link_title, class: "gfm gfm-commit #{html_options[:class]}")) | |
190 | + link_to(identifier, project_commit_url(@project, commit), html_options.merge(title: commit.link_title, class: "gfm gfm-commit #{html_options[:class]}")) | |
191 | 191 | end |
192 | 192 | end |
193 | 193 | end | ... | ... |
spec/controllers/commit_controller_spec.rb
spec/controllers/commits_controller_spec.rb
spec/controllers/merge_requests_controller_spec.rb
1 | 1 | require 'spec_helper' |
2 | 2 | |
3 | 3 | describe MergeRequestsController do |
4 | - let(:project) { create(:project) } | |
4 | + let(:project) { create(:project_with_code) } | |
5 | 5 | let(:user) { create(:user) } |
6 | 6 | let(:merge_request) { create(:merge_request_with_diffs, project: project, target_branch: "bcf03b5d~3", source_branch: "bcf03b5d") } |
7 | 7 | ... | ... |
spec/controllers/tree_controller_spec.rb
spec/factories.rb
... | ... | @@ -34,6 +34,10 @@ FactoryGirl.define do |
34 | 34 | issues_tracker_id { "project_name_in_redmine" } |
35 | 35 | end |
36 | 36 | |
37 | + factory :project_with_code, parent: :project do | |
38 | + path { 'gitlabhq' } | |
39 | + end | |
40 | + | |
37 | 41 | factory :group do |
38 | 42 | sequence(:name) { |n| "group#{n}" } |
39 | 43 | path { name.downcase.gsub(/\s/, '_') } |
... | ... | @@ -73,7 +77,7 @@ FactoryGirl.define do |
73 | 77 | factory :merge_request do |
74 | 78 | title |
75 | 79 | author |
76 | - project | |
80 | + project factory: :project_with_code | |
77 | 81 | source_branch "master" |
78 | 82 | target_branch "stable" |
79 | 83 | |
... | ... | @@ -82,9 +86,9 @@ FactoryGirl.define do |
82 | 86 | target_branch "master" # pretend bcf03b5d~3 |
83 | 87 | source_branch "stable" # pretend bcf03b5d |
84 | 88 | st_commits do |
85 | - [Commit.new(project.repo.commit('bcf03b5d')), | |
86 | - Commit.new(project.repo.commit('bcf03b5d~1')), | |
87 | - Commit.new(project.repo.commit('bcf03b5d~2'))] | |
89 | + [Commit.new(project.repository.commit('bcf03b5d')), | |
90 | + Commit.new(project.repository.commit('bcf03b5d~1')), | |
91 | + Commit.new(project.repository.commit('bcf03b5d~2'))] | |
88 | 92 | end |
89 | 93 | st_diffs do |
90 | 94 | project.repo.diff("bcf03b5d~3", "bcf03b5d") |
... | ... | @@ -116,6 +120,7 @@ FactoryGirl.define do |
116 | 120 | factory :note_on_merge_request_diff, traits: [:on_merge_request, :on_diff] |
117 | 121 | |
118 | 122 | trait :on_commit do |
123 | + project factory: :project_with_code | |
119 | 124 | commit_id "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a" |
120 | 125 | noteable_type "Commit" |
121 | 126 | end |
... | ... | @@ -125,6 +130,7 @@ FactoryGirl.define do |
125 | 130 | end |
126 | 131 | |
127 | 132 | trait :on_merge_request do |
133 | + project factory: :project_with_code | |
128 | 134 | noteable_id 1 |
129 | 135 | noteable_type "MergeRequest" |
130 | 136 | end | ... | ... |
spec/features/gitlab_flavored_markdown_spec.rb
1 | 1 | require 'spec_helper' |
2 | 2 | |
3 | 3 | describe "Gitlab Flavored Markdown" do |
4 | - let(:project) { create(:project) } | |
4 | + let(:project) { create(:project_with_code) } | |
5 | 5 | let(:issue) { create(:issue, project: project) } |
6 | 6 | let(:merge_request) { create(:merge_request, project: project) } |
7 | 7 | let(:fred) do | ... | ... |
spec/features/notes_on_merge_requests_spec.rb
1 | 1 | require 'spec_helper' |
2 | 2 | |
3 | 3 | describe "On a merge request", js: true do |
4 | - let!(:project) { create(:project) } | |
4 | + let!(:project) { create(:project_with_code) } | |
5 | 5 | let!(:merge_request) { create(:merge_request, project: project) } |
6 | 6 | |
7 | 7 | before do |
... | ... | @@ -83,7 +83,7 @@ end |
83 | 83 | |
84 | 84 | |
85 | 85 | describe "On a merge request diff", js: true, focus: true do |
86 | - let!(:project) { create(:project) } | |
86 | + let!(:project) { create(:project_with_code) } | |
87 | 87 | let!(:merge_request) { create(:merge_request_with_diffs, project: project) } |
88 | 88 | |
89 | 89 | before do | ... | ... |
spec/features/profile_spec.rb
... | ... | @@ -12,8 +12,9 @@ describe "Profile account page" do |
12 | 12 | Gitlab.config.gitlab.stub(:signup_enabled).and_return(true) |
13 | 13 | visit account_profile_path |
14 | 14 | end |
15 | + | |
15 | 16 | it { page.should have_content("Remove account") } |
16 | - | |
17 | + | |
17 | 18 | it "should delete the account", js: true do |
18 | 19 | expect { click_link "Delete account" }.to change {User.count}.by(-1) |
19 | 20 | current_path.should == new_user_session_path |
... | ... | @@ -45,4 +46,4 @@ describe "Profile account page" do |
45 | 46 | current_path.should == account_profile_path |
46 | 47 | end |
47 | 48 | end |
48 | -end | |
49 | 49 | \ No newline at end of file |
50 | +end | ... | ... |
spec/features/security/project_access_spec.rb
spec/helpers/gitlab_markdown_helper_spec.rb
... | ... | @@ -4,10 +4,10 @@ describe GitlabMarkdownHelper do |
4 | 4 | include ApplicationHelper |
5 | 5 | include IssuesHelper |
6 | 6 | |
7 | - let!(:project) { create(:project) } | |
7 | + let!(:project) { create(:project_with_code) } | |
8 | 8 | |
9 | 9 | let(:user) { create(:user, username: 'gfm') } |
10 | - let(:commit) { CommitDecorator.decorate(project.repository.commit) } | |
10 | + let(:commit) { project.repository.commit } | |
11 | 11 | let(:issue) { create(:issue, project: project) } |
12 | 12 | let(:merge_request) { create(:merge_request, project: project) } |
13 | 13 | let(:snippet) { create(:snippet, project: project) } | ... | ... |
... | ... | @@ -0,0 +1,49 @@ |
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 | + message: 'Refactoring specs' | |
24 | + ) | |
25 | + | |
26 | + @commit = Gitlab::Git::Commit.new(@raw_commit) | |
27 | + end | |
28 | + | |
29 | + it { @commit.short_id.should == "bcf03b5de6a" } | |
30 | + it { @commit.safe_message.should == @raw_commit.message } | |
31 | + it { @commit.created_at.should == @raw_commit.committed_date } | |
32 | + it { @commit.author_email.should == @author.email } | |
33 | + it { @commit.author_name.should == @author.name } | |
34 | + it { @commit.committer_name.should == @committer.name } | |
35 | + it { @commit.committer_email.should == @committer.email } | |
36 | + it { @commit.different_committer?.should be_true } | |
37 | + end | |
38 | + | |
39 | + describe "Class methods" do | |
40 | + subject { Gitlab::Git::Commit } | |
41 | + | |
42 | + it { should respond_to(:find_or_first) } | |
43 | + it { should respond_to(:fresh_commits) } | |
44 | + it { should respond_to(:commits_with_refs) } | |
45 | + it { should respond_to(:commits_since) } | |
46 | + it { should respond_to(:commits_between) } | |
47 | + it { should respond_to(:commits) } | |
48 | + end | |
49 | +end | ... | ... |
... | ... | @@ -0,0 +1,104 @@ |
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 | + it { should respond_to(:commits_since) } | |
18 | + it { should respond_to(:commits_between) } | |
19 | + end | |
20 | + | |
21 | + | |
22 | + describe "#discover_default_branch" do | |
23 | + let(:master) { 'master' } | |
24 | + let(:stable) { 'stable' } | |
25 | + | |
26 | + it "returns 'master' when master exists" do | |
27 | + repository.should_receive(:branch_names).at_least(:once).and_return([stable, master]) | |
28 | + repository.discover_default_branch.should == 'master' | |
29 | + end | |
30 | + | |
31 | + it "returns non-master when master exists but default branch is set to something else" do | |
32 | + repository.root_ref = 'stable' | |
33 | + repository.should_receive(:branch_names).at_least(:once).and_return([stable, master]) | |
34 | + repository.discover_default_branch.should == 'stable' | |
35 | + end | |
36 | + | |
37 | + it "returns a non-master branch when only one exists" do | |
38 | + repository.should_receive(:branch_names).at_least(:once).and_return([stable]) | |
39 | + repository.discover_default_branch.should == 'stable' | |
40 | + end | |
41 | + | |
42 | + it "returns nil when no branch exists" do | |
43 | + repository.should_receive(:branch_names).at_least(:once).and_return([]) | |
44 | + repository.discover_default_branch.should be_nil | |
45 | + end | |
46 | + end | |
47 | + | |
48 | + describe :commit do | |
49 | + it "should return first head commit if without params" do | |
50 | + repository.commit.id.should == repository.repo.commits.first.id | |
51 | + end | |
52 | + | |
53 | + it "should return valid commit" do | |
54 | + repository.commit(ValidCommit::ID).should be_valid_commit | |
55 | + end | |
56 | + | |
57 | + it "should return nil" do | |
58 | + repository.commit("+123_4532530XYZ").should be_nil | |
59 | + end | |
60 | + end | |
61 | + | |
62 | + describe :tree do | |
63 | + before do | |
64 | + @commit = repository.commit(ValidCommit::ID) | |
65 | + end | |
66 | + | |
67 | + it "should raise error w/o arguments" do | |
68 | + lambda { repository.tree }.should raise_error | |
69 | + end | |
70 | + | |
71 | + it "should return root tree for commit" do | |
72 | + tree = repository.tree(@commit) | |
73 | + tree.contents.size.should == ValidCommit::FILES_COUNT | |
74 | + tree.contents.map(&:name).should == ValidCommit::FILES | |
75 | + end | |
76 | + | |
77 | + it "should return root tree for commit with correct path" do | |
78 | + tree = repository.tree(@commit, ValidCommit::C_FILE_PATH) | |
79 | + tree.contents.map(&:name).should == ValidCommit::C_FILES | |
80 | + end | |
81 | + | |
82 | + it "should return root tree for commit with incorrect path" do | |
83 | + repository.tree(@commit, "invalid_path").should be_nil | |
84 | + end | |
85 | + end | |
86 | + | |
87 | + describe "fresh commits" do | |
88 | + it { repository.fresh_commits(3).count.should == 3 } | |
89 | + it { repository.fresh_commits.first.id.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a" } | |
90 | + it { repository.fresh_commits.last.id.should == "f403da73f5e62794a0447aca879360494b08f678" } | |
91 | + end | |
92 | + | |
93 | + describe "commits_between" do | |
94 | + subject do | |
95 | + commits = repository.commits_between("3a4b4fb4cde7809f033822a171b9feae19d41fff", | |
96 | + "8470d70da67355c9c009e4401746b1d5410af2e3") | |
97 | + commits.map { |c| c.id } | |
98 | + end | |
99 | + | |
100 | + it { should have(3).elements } | |
101 | + it { should include("f0f14c8eaba69ebddd766498a9d0b0e79becd633") } | |
102 | + it { should_not include("bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a") } | |
103 | + end | |
104 | +end | ... | ... |
spec/mailers/notify_spec.rb
... | ... | @@ -5,7 +5,7 @@ describe Notify do |
5 | 5 | include EmailSpec::Matchers |
6 | 6 | |
7 | 7 | let(:recipient) { create(:user, email: 'recipient@example.com') } |
8 | - let(:project) { create(:project) } | |
8 | + let(:project) { create(:project_with_code) } | |
9 | 9 | |
10 | 10 | shared_examples 'a multiple recipients email' do |
11 | 11 | it 'is sent to the given recipient' do |
... | ... | @@ -277,14 +277,7 @@ describe Notify do |
277 | 277 | end |
278 | 278 | |
279 | 279 | describe 'on a commit' do |
280 | - let(:commit) do | |
281 | - mock(:commit).tap do |commit| | |
282 | - commit.stub(:id).and_return('fauxsha1') | |
283 | - commit.stub(:project).and_return(project) | |
284 | - commit.stub(:short_id).and_return('fauxsha1') | |
285 | - commit.stub(:safe_message).and_return('some message') | |
286 | - end | |
287 | - end | |
280 | + let(:commit) { project.repository.commit } | |
288 | 281 | |
289 | 282 | before(:each) { note.stub(:noteable).and_return(commit) } |
290 | 283 | |
... | ... | @@ -297,7 +290,7 @@ describe Notify do |
297 | 290 | end |
298 | 291 | |
299 | 292 | it 'contains a link to the commit' do |
300 | - should have_body_text /fauxsha1/ | |
293 | + should have_body_text commit.short_id | |
301 | 294 | end |
302 | 295 | end |
303 | 296 | ... | ... |
spec/models/commit_spec.rb
1 | 1 | require 'spec_helper' |
2 | 2 | |
3 | 3 | describe Commit do |
4 | - let(:commit) { create(:project).repository.commit } | |
4 | + let(:commit) { create(:project_with_code).repository.commit } | |
5 | 5 | |
6 | - describe CommitDecorator do | |
7 | - let(:decorator) { CommitDecorator.new(commit) } | |
8 | 6 | |
9 | - describe '#title' do | |
10 | - it "returns no_commit_message when safe_message is blank" do | |
11 | - decorator.stub(:safe_message).and_return('') | |
12 | - decorator.title.should == "--no commit message" | |
13 | - end | |
14 | - | |
15 | - it "truncates a message without a newline at 70 characters" do | |
16 | - message = commit.safe_message * 10 | |
17 | - | |
18 | - decorator.stub(:safe_message).and_return(message) | |
19 | - decorator.title.should == "#{message[0..69]}…" | |
20 | - end | |
21 | - | |
22 | - it "truncates a message with a newline before 80 characters at the newline" do | |
23 | - message = commit.safe_message.split(" ").first | |
24 | - | |
25 | - decorator.stub(:safe_message).and_return(message + "\n" + message) | |
26 | - decorator.title.should == message | |
27 | - end | |
28 | - | |
29 | - it "truncates a message with a newline after 80 characters at 70 characters" do | |
30 | - message = (commit.safe_message * 10) + "\n" | |
31 | - | |
32 | - decorator.stub(:safe_message).and_return(message) | |
33 | - decorator.title.should == "#{message[0..69]}…" | |
34 | - end | |
7 | + describe '#title' do | |
8 | + it "returns no_commit_message when safe_message is blank" do | |
9 | + commit.stub(:safe_message).and_return('') | |
10 | + commit.title.should == "--no commit message" | |
35 | 11 | end |
36 | - end | |
37 | 12 | |
38 | - describe "Commit info" do | |
39 | - before do | |
40 | - @committer = double( | |
41 | - email: 'mike@smith.com', | |
42 | - name: 'Mike Smith' | |
43 | - ) | |
13 | + it "truncates a message without a newline at 70 characters" do | |
14 | + message = commit.safe_message * 10 | |
44 | 15 | |
45 | - @author = double( | |
46 | - email: 'john@smith.com', | |
47 | - name: 'John Smith' | |
48 | - ) | |
16 | + commit.stub(:safe_message).and_return(message) | |
17 | + commit.title.should == "#{message[0..69]}…" | |
18 | + end | |
49 | 19 | |
50 | - @raw_commit = double( | |
51 | - id: "bcf03b5de6abcf03b5de6c", | |
52 | - author: @author, | |
53 | - committer: @committer, | |
54 | - committed_date: Date.yesterday, | |
55 | - message: 'Refactoring specs' | |
56 | - ) | |
20 | + it "truncates a message with a newline before 80 characters at the newline" do | |
21 | + message = commit.safe_message.split(" ").first | |
57 | 22 | |
58 | - @commit = Commit.new(@raw_commit) | |
23 | + commit.stub(:safe_message).and_return(message + "\n" + message) | |
24 | + commit.title.should == message | |
59 | 25 | end |
60 | 26 | |
61 | - it { @commit.short_id.should == "bcf03b5de6a" } | |
62 | - it { @commit.safe_message.should == @raw_commit.message } | |
63 | - it { @commit.created_at.should == @raw_commit.committed_date } | |
64 | - it { @commit.author_email.should == @author.email } | |
65 | - it { @commit.author_name.should == @author.name } | |
66 | - it { @commit.committer_name.should == @committer.name } | |
67 | - it { @commit.committer_email.should == @committer.email } | |
68 | - it { @commit.different_committer?.should be_true } | |
69 | - end | |
27 | + it "truncates a message with a newline after 80 characters at 70 characters" do | |
28 | + message = (commit.safe_message * 10) + "\n" | |
70 | 29 | |
71 | - describe "Class methods" do | |
72 | - subject { Commit } | |
73 | - | |
74 | - it { should respond_to(:find_or_first) } | |
75 | - it { should respond_to(:fresh_commits) } | |
76 | - it { should respond_to(:commits_with_refs) } | |
77 | - it { should respond_to(:commits_since) } | |
78 | - it { should respond_to(:commits_between) } | |
79 | - it { should respond_to(:commits) } | |
80 | - it { should respond_to(:compare) } | |
30 | + commit.stub(:safe_message).and_return(message) | |
31 | + commit.title.should == "#{message[0..69]}…" | |
32 | + end | |
81 | 33 | end |
82 | 34 | |
83 | 35 | describe "delegation" do | ... | ... |
spec/models/gollum_wiki_spec.rb
... | ... | @@ -81,7 +81,7 @@ describe GollumWiki do |
81 | 81 | end |
82 | 82 | |
83 | 83 | it "raises CouldNotCreateWikiError if it can't create the wiki repository" do |
84 | - Gitlab::Shell.any_instance.stub(:add_repository).and_return(false) | |
84 | + GollumWiki.any_instance.stub(:init_repo).and_return(false) | |
85 | 85 | expect { GollumWiki.new(project, user).wiki }.to raise_exception(GollumWiki::CouldNotCreateWikiError) |
86 | 86 | end |
87 | 87 | end | ... | ... |
spec/models/project_spec.rb
... | ... | @@ -119,7 +119,7 @@ describe Project do |
119 | 119 | end |
120 | 120 | |
121 | 121 | describe :update_merge_requests do |
122 | - let(:project) { create(:project) } | |
122 | + let(:project) { create(:project_with_code) } | |
123 | 123 | |
124 | 124 | before do |
125 | 125 | @merge_request = create(:merge_request, project: project) |
... | ... | @@ -189,10 +189,6 @@ describe Project do |
189 | 189 | it "should return valid repo" do |
190 | 190 | project.repository.should be_kind_of(Repository) |
191 | 191 | end |
192 | - | |
193 | - it "should return nil" do | |
194 | - Project.new(path: "empty").repository.should be_nil | |
195 | - end | |
196 | 192 | end |
197 | 193 | |
198 | 194 | describe :issue_exists? do |
... | ... | @@ -249,7 +245,7 @@ describe Project do |
249 | 245 | end |
250 | 246 | |
251 | 247 | describe :open_branches do |
252 | - let(:project) { create(:project) } | |
248 | + let(:project) { create(:project_with_code) } | |
253 | 249 | |
254 | 250 | before do |
255 | 251 | project.protected_branches.create(name: 'master') | ... | ... |
spec/models/repository_spec.rb
... | ... | @@ -1,105 +0,0 @@ |
1 | -require "spec_helper" | |
2 | - | |
3 | -describe Repository do | |
4 | - let(:project) { create(:project) } | |
5 | - let(:repository) { project.repository } | |
6 | - | |
7 | - describe "Respond to" do | |
8 | - subject { repository } | |
9 | - | |
10 | - it { should respond_to(:repo) } | |
11 | - it { should respond_to(:tree) } | |
12 | - it { should respond_to(:root_ref) } | |
13 | - it { should respond_to(:tags) } | |
14 | - it { should respond_to(:commit) } | |
15 | - it { should respond_to(:commits) } | |
16 | - it { should respond_to(:commits_between) } | |
17 | - it { should respond_to(:commits_with_refs) } | |
18 | - it { should respond_to(:commits_since) } | |
19 | - it { should respond_to(:commits_between) } | |
20 | - end | |
21 | - | |
22 | - | |
23 | - describe "#discover_default_branch" do | |
24 | - let(:master) { 'master' } | |
25 | - let(:stable) { 'stable' } | |
26 | - | |
27 | - it "returns 'master' when master exists" do | |
28 | - repository.should_receive(:branch_names).at_least(:once).and_return([stable, master]) | |
29 | - repository.discover_default_branch.should == 'master' | |
30 | - end | |
31 | - | |
32 | - it "returns non-master when master exists but default branch is set to something else" do | |
33 | - repository.root_ref = 'stable' | |
34 | - repository.should_receive(:branch_names).at_least(:once).and_return([stable, master]) | |
35 | - repository.discover_default_branch.should == 'stable' | |
36 | - end | |
37 | - | |
38 | - it "returns a non-master branch when only one exists" do | |
39 | - repository.should_receive(:branch_names).at_least(:once).and_return([stable]) | |
40 | - repository.discover_default_branch.should == 'stable' | |
41 | - end | |
42 | - | |
43 | - it "returns nil when no branch exists" do | |
44 | - repository.should_receive(:branch_names).at_least(:once).and_return([]) | |
45 | - repository.discover_default_branch.should be_nil | |
46 | - end | |
47 | - end | |
48 | - | |
49 | - describe :commit do | |
50 | - it "should return first head commit if without params" do | |
51 | - repository.commit.id.should == repository.repo.commits.first.id | |
52 | - end | |
53 | - | |
54 | - it "should return valid commit" do | |
55 | - repository.commit(ValidCommit::ID).should be_valid_commit | |
56 | - end | |
57 | - | |
58 | - it "should return nil" do | |
59 | - repository.commit("+123_4532530XYZ").should be_nil | |
60 | - end | |
61 | - end | |
62 | - | |
63 | - describe :tree do | |
64 | - before do | |
65 | - @commit = repository.commit(ValidCommit::ID) | |
66 | - end | |
67 | - | |
68 | - it "should raise error w/o arguments" do | |
69 | - lambda { repository.tree }.should raise_error | |
70 | - end | |
71 | - | |
72 | - it "should return root tree for commit" do | |
73 | - tree = repository.tree(@commit) | |
74 | - tree.contents.size.should == ValidCommit::FILES_COUNT | |
75 | - tree.contents.map(&:name).should == ValidCommit::FILES | |
76 | - end | |
77 | - | |
78 | - it "should return root tree for commit with correct path" do | |
79 | - tree = repository.tree(@commit, ValidCommit::C_FILE_PATH) | |
80 | - tree.contents.map(&:name).should == ValidCommit::C_FILES | |
81 | - end | |
82 | - | |
83 | - it "should return root tree for commit with incorrect path" do | |
84 | - repository.tree(@commit, "invalid_path").should be_nil | |
85 | - end | |
86 | - end | |
87 | - | |
88 | - describe "fresh commits" do | |
89 | - it { repository.fresh_commits(3).count.should == 3 } | |
90 | - it { repository.fresh_commits.first.id.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a" } | |
91 | - it { repository.fresh_commits.last.id.should == "f403da73f5e62794a0447aca879360494b08f678" } | |
92 | - end | |
93 | - | |
94 | - describe "commits_between" do | |
95 | - subject do | |
96 | - commits = repository.commits_between("3a4b4fb4cde7809f033822a171b9feae19d41fff", | |
97 | - "8470d70da67355c9c009e4401746b1d5410af2e3") | |
98 | - commits.map { |c| c.id } | |
99 | - end | |
100 | - | |
101 | - it { should have(3).elements } | |
102 | - it { should include("f0f14c8eaba69ebddd766498a9d0b0e79becd633") } | |
103 | - it { should_not include("bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a") } | |
104 | - end | |
105 | -end |
spec/requests/api/merge_requests_spec.rb
... | ... | @@ -4,7 +4,7 @@ describe Gitlab::API do |
4 | 4 | include ApiHelpers |
5 | 5 | |
6 | 6 | let(:user) { create(:user ) } |
7 | - let!(:project) { create(:project, namespace: user.namespace ) } | |
7 | + let!(:project) { create(:project_with_code, creator_id: user.id) } | |
8 | 8 | let!(:merge_request) { create(:merge_request, author: user, assignee: user, project: project, title: "Test") } |
9 | 9 | before { project.team << [user, :reporters] } |
10 | 10 | ... | ... |
spec/requests/api/projects_spec.rb
... | ... | @@ -7,7 +7,7 @@ describe Gitlab::API do |
7 | 7 | let(:user2) { create(:user) } |
8 | 8 | let(:user3) { create(:user) } |
9 | 9 | let(:admin) { create(:admin) } |
10 | - let!(:project) { create(:project, namespace: user.namespace ) } | |
10 | + let!(:project) { create(:project_with_code, creator_id: user.id) } | |
11 | 11 | let!(:hook) { create(:project_hook, project: project, url: "http://example.com") } |
12 | 12 | let!(:snippet) { create(:snippet, author: user, project: project, title: 'example') } |
13 | 13 | let!(:users_project) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) } | ... | ... |
spec/services/git_push_service_spec.rb
spec/spec_helper.rb
... | ... | @@ -47,11 +47,7 @@ Spork.prefork do |
47 | 47 | config.use_transactional_fixtures = false |
48 | 48 | |
49 | 49 | config.before do |
50 | - # Use tmp dir for FS manipulations | |
51 | - temp_repos_path = Rails.root.join('tmp', 'test-git-base-path') | |
52 | - Gitlab.config.gitlab_shell.stub(repos_path: temp_repos_path) | |
53 | - FileUtils.rm_rf temp_repos_path | |
54 | - FileUtils.mkdir_p temp_repos_path | |
50 | + TestEnv.init | |
55 | 51 | end |
56 | 52 | end |
57 | 53 | end | ... | ... |
spec/support/stubbed_repository.rb
... | ... | @@ -1,75 +0,0 @@ |
1 | -require "repository" | |
2 | -require "project" | |
3 | -require "merge_request" | |
4 | -require "shell" | |
5 | - | |
6 | -# Stubs out all Git repository access done by models so that specs can run | |
7 | -# against fake repositories without Grit complaining that they don't exist. | |
8 | -class Project | |
9 | - def repository | |
10 | - if path == "empty" || !path | |
11 | - nil | |
12 | - else | |
13 | - GitLabTestRepo.new(path_with_namespace) | |
14 | - end | |
15 | - end | |
16 | - | |
17 | - def satellite | |
18 | - FakeSatellite.new | |
19 | - end | |
20 | - | |
21 | - class FakeSatellite | |
22 | - def exists? | |
23 | - true | |
24 | - end | |
25 | - | |
26 | - def destroy | |
27 | - true | |
28 | - end | |
29 | - | |
30 | - def create | |
31 | - true | |
32 | - end | |
33 | - end | |
34 | -end | |
35 | - | |
36 | -class MergeRequest | |
37 | - def check_if_can_be_merged | |
38 | - true | |
39 | - end | |
40 | -end | |
41 | - | |
42 | -class GitLabTestRepo < Repository | |
43 | - def repo | |
44 | - @repo ||= Grit::Repo.new(Rails.root.join('tmp', 'repositories', 'gitlabhq')) | |
45 | - end | |
46 | - | |
47 | - # patch repo size (in mb) | |
48 | - def size | |
49 | - 12.45 | |
50 | - end | |
51 | -end | |
52 | - | |
53 | -module Gitlab | |
54 | - class Shell | |
55 | - def add_repository name | |
56 | - true | |
57 | - end | |
58 | - | |
59 | - def mv_repository name, new_name | |
60 | - true | |
61 | - end | |
62 | - | |
63 | - def remove_repository name | |
64 | - true | |
65 | - end | |
66 | - | |
67 | - def add_key id, key | |
68 | - true | |
69 | - end | |
70 | - | |
71 | - def remove_key id, key | |
72 | - true | |
73 | - end | |
74 | - end | |
75 | -end |
... | ... | @@ -0,0 +1,63 @@ |
1 | +module TestEnv | |
2 | + extend self | |
3 | + | |
4 | + # Test environment | |
5 | + # | |
6 | + # all repositories and namespaces stored at | |
7 | + # RAILS_APP/tmp/test-git-base-path | |
8 | + # | |
9 | + # Next shell methods are stubbed and return true | |
10 | + # - mv_repository | |
11 | + # - remove_repository | |
12 | + # - add_key | |
13 | + # - remove_key | |
14 | + # | |
15 | + def init | |
16 | + # Use tmp dir for FS manipulations | |
17 | + repos_path = Rails.root.join('tmp', 'test-git-base-path') | |
18 | + Gitlab.config.gitlab_shell.stub(repos_path: repos_path) | |
19 | + | |
20 | + GollumWiki.any_instance.stub(:init_repo) do |path| | |
21 | + create_temp_repo(File.join(repos_path, "#{path}.git")) | |
22 | + end | |
23 | + | |
24 | + Gitlab::Shell.any_instance.stub( | |
25 | + add_repository: true, | |
26 | + mv_repository: true, | |
27 | + remove_repository: true, | |
28 | + add_key: true, | |
29 | + remove_key: true | |
30 | + ) | |
31 | + | |
32 | + Gitlab::Satellite::Satellite.any_instance.stub( | |
33 | + exists?: true, | |
34 | + destroy: true, | |
35 | + create: true | |
36 | + ) | |
37 | + | |
38 | + MergeRequest.any_instance.stub( | |
39 | + check_if_can_be_merged: true | |
40 | + ) | |
41 | + | |
42 | + Repository.any_instance.stub( | |
43 | + size: 12.45 | |
44 | + ) | |
45 | + | |
46 | + # Remove tmp/test-git-base-path | |
47 | + FileUtils.rm_rf Gitlab.config.gitlab_shell.repos_path | |
48 | + | |
49 | + # Recreate tmp/test-git-base-path | |
50 | + FileUtils.mkdir_p Gitlab.config.gitlab_shell.repos_path | |
51 | + | |
52 | + # Symlink tmp/repositories/gitlabhq to tmp/test-git-base-path/gitlabhq | |
53 | + seed_repo = Rails.root.join('tmp', 'repositories', 'gitlabhq') | |
54 | + target_repo = File.join(repos_path, 'gitlabhq.git') | |
55 | + system("ln -s #{seed_repo} #{target_repo}") | |
56 | + end | |
57 | + | |
58 | + def create_temp_repo(path) | |
59 | + FileUtils.mkdir_p path | |
60 | + command = "git init --quiet --bare #{path};" | |
61 | + system(command) | |
62 | + end | |
63 | +end | ... | ... |
spec/workers/post_receive_spec.rb