From 96a584211bf7bfa87b172b72015d7729b32150cf Mon Sep 17 00:00:00 2001 From: Sato Hiroyuki Date: Tue, 19 Mar 2013 18:08:27 +0900 Subject: [PATCH 001/152] Refactor: Clean up code. --- app/assets/javascripts/branch-graph.js.coffee | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/assets/javascripts/branch-graph.js.coffee b/app/assets/javascripts/branch-graph.js.coffee index 6e4d6931..38735463 100644 --- a/app/assets/javascripts/branch-graph.js.coffee +++ b/app/assets/javascripts/branch-graph.js.coffee @@ -212,10 +212,6 @@ class BranchGraph top.push anchor Raphael::commitTooltip = (x, y, commit) -> - icon = undefined - nameText = undefined - idText = undefined - messageText = undefined boxWidth = 300 boxHeight = 200 icon = @image(commit.author.icon, x, y, 20, 20) From 351c952192da7cdd088fe693289e96d945dcafe3 Mon Sep 17 00:00:00 2001 From: Sato Hiroyuki Date: Tue, 19 Mar 2013 18:42:46 +0900 Subject: [PATCH 002/152] Refactor: extract method. --- app/assets/javascripts/branch-graph.js.coffee | 116 ++++++++++-------- 1 file changed, 63 insertions(+), 53 deletions(-) diff --git a/app/assets/javascripts/branch-graph.js.coffee b/app/assets/javascripts/branch-graph.js.coffee index 38735463..4a270c49 100644 --- a/app/assets/javascripts/branch-graph.js.coffee +++ b/app/assets/javascripts/branch-graph.js.coffee @@ -53,10 +53,10 @@ class BranchGraph top = r.set() cuday = 0 cumonth = "" - offsetX = 20 - offsetY = 60 + @offsetX = 20 + @offsetY = 60 barWidth = Math.max(graphWidth, @days.length * 20 + 320) - scrollLeft = cw + @scrollLeft = cw @raphael = r r.rect(0, 0, barWidth, 20).attr fill: "#222" r.rect(0, 20, barWidth, 20).attr fill: "#444" @@ -64,7 +64,7 @@ class BranchGraph for day, mm in @days if cuday isnt day[0] # Dates - r.text(offsetX + mm * 20, 31, day[0]) + r.text(@offsetX + mm * 20, 31, day[0]) .attr( font: "12px Monaco, monospace" fill: "#DDD" @@ -73,7 +73,7 @@ class BranchGraph if cumonth isnt day[1] # Months - r.text(offsetX + mm * 20, 11, day[1]) + r.text(@offsetX + mm * 20, 11, day[1]) .attr( font: "12px Monaco, monospace" fill: "#EEE" @@ -81,61 +81,21 @@ class BranchGraph cumonth = day[1] for commit in @commits - x = offsetX + 20 * commit.time - y = offsetY + 10 * commit.space - # Draw dot - r.circle(x, y, 3).attr( - fill: @colors[commit.space] - stroke: "none" - ) + x = @offsetX + 20 * commit.time + y = @offsetY + 10 * commit.space - # Draw lines - for parent in commit.parents - parentCommit = @preparedCommits[parent[0]] - parentX = offsetX + 20 * parentCommit.time - parentY1 = offsetY + 10 * parentCommit.space - parentY2 = offsetY + 10 * parent[1] - if parentCommit.space is commit.space and parentCommit.space is parent[1] - r.path(["M", x, y, "L", parentX, parentY1]).attr( - stroke: @colors[parentCommit.space] - "stroke-width": 2 - ) + @drawDot(x, y, commit) - else if parentCommit.space < commit.space - if y is parentY2 - r.path(["M", x - 5, y, "l-5,-2,0,4,5,-2", "L", x - 10, y, "L", x - 15, parentY2, "L", parentX + 5, parentY2, "L", parentX, parentY1]).attr( - stroke: @colors[commit.space] - "stroke-width": 2 - ) + @drawLines(x, y, commit) - else - r.path(["M", x - 3, y - 6, "l-4,-3,4,-2,0,5", "L", x - 5, y - 10, "L", x - 10, parentY2, "L", parentX + 5, parentY2, "L", parentX, parentY1]).attr( - stroke: @colors[commit.space] - "stroke-width": 2 - ) + @appendLabel(x, y, commit.refs) if commit.refs - else - r.path(["M", x - 3, y + 6, "l-4,3,4,2,0,-5", "L", x - 5, y + 10, "L", x - 10, parentY2, "L", parentX + 5, parentY2, "L", parentX, parentY1]).attr( - stroke: @colors[parentCommit.space] - "stroke-width": 2 - ) + @appendAnchor(top, commit, x, y) - @appendLabel x, y, commit.refs if commit.refs - - # Mark commit and displayed in the center - if commit.id is @options.commit_id - r.path(["M", x, y - 5, "L", x + 4, y - 15, "L", x - 4, y - 15, "Z"]).attr( - fill: "#000" - "fill-opacity": .7 - stroke: "none" - ) - - scrollLeft = x - graphWidth / 2 - - @appendAnchor top, commit, x, y + @markCommit(x, y, commit, graphWidth) top.toFront() - @element.scrollLeft scrollLeft + @element.scrollLeft @scrollLeft @bindEvents() bindEvents: -> @@ -211,6 +171,56 @@ class BranchGraph ) top.push anchor + drawDot: (x, y, commit) -> + r = @raphael + r.circle(x, y, 3).attr( + fill: @colors[commit.space] + stroke: "none" + ) + + drawLines: (x, y, commit) -> + r = @raphael + for parent in commit.parents + parentCommit = @preparedCommits[parent[0]] + parentX = @offsetX + 20 * parentCommit.time + parentY1 = @offsetY + 10 * parentCommit.space + parentY2 = @offsetY + 10 * parent[1] + if parentCommit.space is commit.space and parentCommit.space is parent[1] + r.path(["M", x, y, "L", parentX, parentY1]).attr( + stroke: @colors[parentCommit.space] + "stroke-width": 2 + ) + + else if parentCommit.space < commit.space + if y is parentY2 + r.path(["M", x - 5, y, "l-5,-2,0,4,5,-2", "L", x - 10, y, "L", x - 15, parentY2, "L", parentX + 5, parentY2, "L", parentX, parentY1]).attr( + stroke: @colors[commit.space] + "stroke-width": 2 + ) + + else + r.path(["M", x - 3, y - 6, "l-4,-3,4,-2,0,5", "L", x - 5, y - 10, "L", x - 10, parentY2, "L", parentX + 5, parentY2, "L", parentX, parentY1]).attr( + stroke: @colors[commit.space] + "stroke-width": 2 + ) + + else + r.path(["M", x - 3, y + 6, "l-4,3,4,2,0,-5", "L", x - 5, y + 10, "L", x - 10, parentY2, "L", parentX + 5, parentY2, "L", parentX, parentY1]).attr( + stroke: @colors[parentCommit.space] + "stroke-width": 2 + ) + + markCommit: (x, y, commit, graphWidth) -> + if commit.id is @options.commit_id + r = @raphael + r.path(["M", x, y - 5, "L", x + 4, y - 15, "L", x - 4, y - 15, "Z"]).attr( + fill: "#000" + "fill-opacity": .7 + stroke: "none" + ) + # Displayed in the center + @scrollLeft = x - graphWidth / 2 + Raphael::commitTooltip = (x, y, commit) -> boxWidth = 300 boxHeight = 200 From 175e09f16742cbc8d5535e548cef880768ec3397 Mon Sep 17 00:00:00 2001 From: Sato Hiroyuki Date: Tue, 19 Mar 2013 19:27:15 +0900 Subject: [PATCH 003/152] Change graph element size. --- app/assets/javascripts/branch-graph.js.coffee | 8 ++++---- app/assets/stylesheets/sections/graph.scss | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/branch-graph.js.coffee b/app/assets/javascripts/branch-graph.js.coffee index 4a270c49..79ea62af 100644 --- a/app/assets/javascripts/branch-graph.js.coffee +++ b/app/assets/javascripts/branch-graph.js.coffee @@ -47,14 +47,14 @@ class BranchGraph buildGraph: -> graphWidth = $(@element).width() - ch = @mspace * 20 + 100 + ch = @mspace * 10 + 100 cw = Math.max(graphWidth, @mtime * 20 + 260) r = Raphael(@element.get(0), cw, ch) top = r.set() cuday = 0 cumonth = "" @offsetX = 20 - @offsetY = 60 + @offsetY = 50 barWidth = Math.max(graphWidth, @days.length * 20 + 320) @scrollLeft = cw @raphael = r @@ -64,7 +64,7 @@ class BranchGraph for day, mm in @days if cuday isnt day[0] # Dates - r.text(@offsetX + mm * 20, 31, day[0]) + r.text(@offsetX + mm * 20, 30, day[0]) .attr( font: "12px Monaco, monospace" fill: "#DDD" @@ -73,7 +73,7 @@ class BranchGraph if cumonth isnt day[1] # Months - r.text(@offsetX + mm * 20, 11, day[1]) + r.text(@offsetX + mm * 20, 10, day[1]) .attr( font: "12px Monaco, monospace" fill: "#EEE" diff --git a/app/assets/stylesheets/sections/graph.scss b/app/assets/stylesheets/sections/graph.scss index 5800098a..7da00719 100644 --- a/app/assets/stylesheets/sections/graph.scss +++ b/app/assets/stylesheets/sections/graph.scss @@ -12,7 +12,7 @@ .graph { background: #f1f1f1; cursor: move; - height: 70%; + height: 500px; overflow: hidden; } } From 1f6b6b6c629592e3ecc08e9dac6514a4b1a831a0 Mon Sep 17 00:00:00 2001 From: Sato Hiroyuki Date: Wed, 20 Mar 2013 09:17:12 +0000 Subject: [PATCH 004/152] Rotating graph orientation. --- app/assets/javascripts/branch-graph.js.coffee | 113 +++++++++++------- app/models/network/graph.rb | 39 +++--- 2 files changed, 82 insertions(+), 70 deletions(-) diff --git a/app/assets/javascripts/branch-graph.js.coffee b/app/assets/javascripts/branch-graph.js.coffee index 79ea62af..a3223172 100644 --- a/app/assets/javascripts/branch-graph.js.coffee +++ b/app/assets/javascripts/branch-graph.js.coffee @@ -20,8 +20,6 @@ class BranchGraph prepareData: (@days, @commits) -> @collectParents() - @mtime += 4 - @mspace += 10 for c in @commits c.isParent = true if c.id of @parents @@ -35,6 +33,7 @@ class BranchGraph @mspace = Math.max(@mspace, c.space) for p in c.parents @parents[p[0]] = true + @mspace = Math.max(@mspace, p[1]) collectColors: -> k = 0 @@ -46,25 +45,26 @@ class BranchGraph k++ buildGraph: -> + graphHeight = $(@element).height() graphWidth = $(@element).width() - ch = @mspace * 10 + 100 - cw = Math.max(graphWidth, @mtime * 20 + 260) + ch = Math.max(graphHeight, @mtime * 20 + 100) + cw = Math.max(graphWidth, @mspace * 10 + 260) r = Raphael(@element.get(0), cw, ch) top = r.set() cuday = 0 cumonth = "" - @offsetX = 20 - @offsetY = 50 - barWidth = Math.max(graphWidth, @days.length * 20 + 320) + @offsetX = 120 + @offsetY = 20 + barHeight = Math.max(graphHeight, @days.length * 20 + 320) @scrollLeft = cw @raphael = r - r.rect(0, 0, barWidth, 20).attr fill: "#222" - r.rect(0, 20, barWidth, 20).attr fill: "#444" + r.rect(0, 0, 20, barHeight).attr fill: "#222" + r.rect(20, 0, 20, barHeight).attr fill: "#444" for day, mm in @days if cuday isnt day[0] # Dates - r.text(@offsetX + mm * 20, 30, day[0]) + r.text(30, @offsetY + mm * 20, day[0]) .attr( font: "12px Monaco, monospace" fill: "#DDD" @@ -73,7 +73,7 @@ class BranchGraph if cumonth isnt day[1] # Months - r.text(@offsetX + mm * 20, 10, day[1]) + r.text(10, @offsetY + mm * 20, day[1]) .attr( font: "12px Monaco, monospace" fill: "#EEE" @@ -81,8 +81,8 @@ class BranchGraph cumonth = day[1] for commit in @commits - x = @offsetX + 20 * commit.time - y = @offsetY + 10 * commit.space + x = @offsetX + 10 * (@mspace - commit.space) + y = @offsetY + 20 * commit.time @drawDot(x, y, commit) @@ -92,10 +92,9 @@ class BranchGraph @appendAnchor(top, commit, x, y) - @markCommit(x, y, commit, graphWidth) + @markCommit(x, y, commit, graphHeight) top.toFront() - @element.scrollLeft @scrollLeft @bindEvents() bindEvents: -> @@ -131,26 +130,28 @@ class BranchGraph shortrefs = refs # Truncate if longer than 15 chars shortrefs = shortrefs.substr(0, 15) + "…" if shortrefs.length > 17 - text = r.text(x + 5, y + 8 + 10, shortrefs).attr( + text = r.text(x + 8, y, shortrefs).attr( + "text-anchor": "start" font: "10px Monaco, monospace" fill: "#FFF" title: refs ) textbox = text.getBBox() - text.transform ["t", textbox.height / -4, textbox.width / 2 + 5, "r90"] # Create rectangle based on the size of the textbox - rect = r.rect(x, y, textbox.width + 15, textbox.height + 5, 4).attr( + rect = r.rect(x, y - 7, textbox.width + 15, textbox.height + 5, 4).attr( fill: "#000" - "fill-opacity": .7 + "fill-opacity": .5 stroke: "none" ) - triangle = r.path(["M", x, y + 5, "L", x + 4, y + 15, "L", x - 4, y + 15, "Z"]).attr( + triangle = r.path(["M", x - 5, y, "L", x - 15, y - 4, "L", x - 15, y + 4, "Z"]).attr( fill: "#000" - "fill-opacity": .7 + "fill-opacity": .5 stroke: "none" ) - # Rotate and reposition rectangle over text - rect.transform ["r", 90, x, y, "t", 15, -9] + + label = r.set(rect, text) + label.transform(["t", -rect.getBBox().width - 15, 0]) + # Set text to front text.toFront() @@ -164,7 +165,7 @@ class BranchGraph ).click(-> window.open options.commit_url.replace("%s", commit.id), "_blank" ).hover(-> - @tooltip = r.commitTooltip(x, y + 5, commit) + @tooltip = r.commitTooltip(x + 5, y, commit) top.push @tooltip.insertBefore(this) , -> @tooltip and @tooltip.remove() and delete @tooltip @@ -182,44 +183,66 @@ class BranchGraph r = @raphael for parent in commit.parents parentCommit = @preparedCommits[parent[0]] - parentX = @offsetX + 20 * parentCommit.time - parentY1 = @offsetY + 10 * parentCommit.space - parentY2 = @offsetY + 10 * parent[1] + parentY = @offsetY + 20 * parentCommit.time + parentX1 = @offsetX + 10 * (@mspace - parentCommit.space) + parentX2 = @offsetX + 10 * (@mspace - parent[1]) + if parentCommit.space is commit.space and parentCommit.space is parent[1] - r.path(["M", x, y, "L", parentX, parentY1]).attr( + r.path(["M", x, y, "L", parentX1, parentY]).attr( stroke: @colors[parentCommit.space] "stroke-width": 2 ) else if parentCommit.space < commit.space - if y is parentY2 - r.path(["M", x - 5, y, "l-5,-2,0,4,5,-2", "L", x - 10, y, "L", x - 15, parentY2, "L", parentX + 5, parentY2, "L", parentX, parentY1]).attr( - stroke: @colors[commit.space] - "stroke-width": 2 - ) + if x is parentX2 + r + .path([ + "M", x, y + 5, + "l-2,5,4,0,-2,-5", + "L", x, y + 10, + "L", parentX2, y + 10, + "L", parentX2, parentY - 5, + "L", parentX1, parentY]) + .attr( + stroke: @colors[commit.space] + "stroke-width": 2) else - r.path(["M", x - 3, y - 6, "l-4,-3,4,-2,0,5", "L", x - 5, y - 10, "L", x - 10, parentY2, "L", parentX + 5, parentY2, "L", parentX, parentY1]).attr( - stroke: @colors[commit.space] - "stroke-width": 2 - ) + r + .path([ + "M", x + 3, y + 3, + "l5,0,-2,4,-3,-4", + "L", x + 7, y + 5, + "L", parentX2, y + 10, + "L", parentX2, parentY - 5, + "L", parentX1, parentY]) + .attr( + stroke: @colors[commit.space] + "stroke-width": 2) else - r.path(["M", x - 3, y + 6, "l-4,3,4,2,0,-5", "L", x - 5, y + 10, "L", x - 10, parentY2, "L", parentX + 5, parentY2, "L", parentX, parentY1]).attr( - stroke: @colors[parentCommit.space] - "stroke-width": 2 - ) + r + .path([ + "M", x - 3, y + 3, + "l-5,0,2,4,3,-4", + "L", x - 7, y + 5, + "L", parentX2, y + 10, + "L", parentX2, parentY - 5, + "L", parentX1, parentY]) + .attr( + stroke: @colors[parentCommit.space] + "stroke-width": 2) - markCommit: (x, y, commit, graphWidth) -> + markCommit: (x, y, commit, graphHeight) -> if commit.id is @options.commit_id r = @raphael - r.path(["M", x, y - 5, "L", x + 4, y - 15, "L", x - 4, y - 15, "Z"]).attr( + r.path(["M", x + 5, y, "L", x + 15, y + 4, "L", x + 15, y - 4, "Z"]).attr( fill: "#000" - "fill-opacity": .7 + "fill-opacity": .5 stroke: "none" ) # Displayed in the center - @scrollLeft = x - graphWidth / 2 + @element.scrollTop(y - graphHeight / 2) Raphael::commitTooltip = (x, y, commit) -> boxWidth = 300 diff --git a/app/models/network/graph.rb b/app/models/network/graph.rb index 4b1abf52..2957adbf 100644 --- a/app/models/network/graph.rb +++ b/app/models/network/graph.rb @@ -40,15 +40,12 @@ module Network def index_commits days = [] @map = {} + @reserved = {} - @commits.reverse.each_with_index do |c,i| + @commits.each_with_index do |c,i| c.time = i days[i] = c.committed_date @map[c.id] = c - end - - @reserved = {} - days.each_index do |i| @reserved[i] = [] end @@ -135,11 +132,7 @@ module Network spaces = [] commit.parents(@map).each do |parent| - range = if commit.time < parent.time then - commit.time..parent.time - else - parent.time..commit.time - end + range = commit.time..parent.time space = if commit.space >= parent.space then find_free_parent_space(range, parent.space, -1, commit.space) @@ -166,7 +159,7 @@ module Network range.each do |i| if i != range.first && i != range.last && - @commits[reversed_index(i)].spaces.include?(overlap_space) then + @commits[i].spaces.include?(overlap_space) then return true; end @@ -184,7 +177,7 @@ module Network return end - time_range = leaves.last.time..leaves.first.time + time_range = leaves.first.time..leaves.last.time space_base = get_space_base(leaves) space = find_free_space(time_range, 2, space_base) leaves.each do |l| @@ -198,17 +191,17 @@ module Network end # and mark it as reserved - min_time = leaves.last.time - leaves.last.parents(@map).each do |parent| - if parent.time < min_time - min_time = parent.time - end + if parent_time.nil? + min_time = leaves.first.time + else + min_time = parent_time + 1 end - if parent_time.nil? - max_time = leaves.first.time - else - max_time = parent_time - 1 + max_time = leaves.last.time + leaves.last.parents(@map).each do |parent| + if max_time < parent.time + max_time = parent.time + end end mark_reserved(min_time..max_time, space) @@ -289,9 +282,5 @@ module Network end refs_cache end - - def reversed_index(index) - -index - 1 - end end end From 916c61fc64292bf4ae2fd84cbbbc86a5afa943bf Mon Sep 17 00:00:00 2001 From: Sato Hiroyuki Date: Thu, 21 Mar 2013 12:34:15 +0000 Subject: [PATCH 005/152] Refactor: clean up code. --- app/assets/javascripts/branch-graph.js.coffee | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/app/assets/javascripts/branch-graph.js.coffee b/app/assets/javascripts/branch-graph.js.coffee index a3223172..a5cf67c9 100644 --- a/app/assets/javascripts/branch-graph.js.coffee +++ b/app/assets/javascripts/branch-graph.js.coffee @@ -5,6 +5,10 @@ class BranchGraph @mspace = 0 @parents = {} @colors = ["#000"] + @offsetX = 120 + @offsetY = 20 + @unitTime = 20 + @unitSpace = 10 @load() load: -> @@ -47,24 +51,21 @@ class BranchGraph buildGraph: -> graphHeight = $(@element).height() graphWidth = $(@element).width() - ch = Math.max(graphHeight, @mtime * 20 + 100) - cw = Math.max(graphWidth, @mspace * 10 + 260) - r = Raphael(@element.get(0), cw, ch) + ch = Math.max(graphHeight, @unitTime * @mtime + 100) + cw = Math.max(graphWidth, @unitSpace * @mspace + 260) + @r = r = Raphael(@element.get(0), cw, ch) top = r.set() cuday = 0 cumonth = "" - @offsetX = 120 - @offsetY = 20 - barHeight = Math.max(graphHeight, @days.length * 20 + 320) - @scrollLeft = cw - @raphael = r + barHeight = Math.max(graphHeight, @unitTime * @days.length + 320) + r.rect(0, 0, 20, barHeight).attr fill: "#222" r.rect(20, 0, 20, barHeight).attr fill: "#444" for day, mm in @days if cuday isnt day[0] # Dates - r.text(30, @offsetY + mm * 20, day[0]) + r.text(30, @offsetY + @unitTime * mm, day[0]) .attr( font: "12px Monaco, monospace" fill: "#DDD" @@ -73,7 +74,7 @@ class BranchGraph if cumonth isnt day[1] # Months - r.text(10, @offsetY + mm * 20, day[1]) + r.text(10, @offsetY + @unitTime * mm, day[1]) .attr( font: "12px Monaco, monospace" fill: "#EEE" @@ -81,8 +82,8 @@ class BranchGraph cumonth = day[1] for commit in @commits - x = @offsetX + 10 * (@mspace - commit.space) - y = @offsetY + 20 * commit.time + x = @offsetX + @unitSpace * (@mspace - commit.space) + y = @offsetY + @unitTime * commit.time @drawDot(x, y, commit) @@ -126,7 +127,7 @@ class BranchGraph element.scrollTop element.scrollTop() + 50 if event.keyCode is 40 appendLabel: (x, y, refs) -> - r = @raphael + r = @r shortrefs = refs # Truncate if longer than 15 chars shortrefs = shortrefs.substr(0, 15) + "…" if shortrefs.length > 17 @@ -156,7 +157,7 @@ class BranchGraph text.toFront() appendAnchor: (top, commit, x, y) -> - r = @raphael + r = @r options = @options anchor = r.circle(x, y, 10).attr( fill: "#000" @@ -173,19 +174,19 @@ class BranchGraph top.push anchor drawDot: (x, y, commit) -> - r = @raphael + r = @r r.circle(x, y, 3).attr( fill: @colors[commit.space] stroke: "none" ) drawLines: (x, y, commit) -> - r = @raphael + r = @r for parent in commit.parents parentCommit = @preparedCommits[parent[0]] - parentY = @offsetY + 20 * parentCommit.time - parentX1 = @offsetX + 10 * (@mspace - parentCommit.space) - parentX2 = @offsetX + 10 * (@mspace - parent[1]) + parentY = @offsetY + @unitTime * parentCommit.time + parentX1 = @offsetX + @unitSpace * (@mspace - parentCommit.space) + parentX2 = @offsetX + @unitSpace * (@mspace - parent[1]) if parentCommit.space is commit.space and parentCommit.space is parent[1] r.path(["M", x, y, "L", parentX1, parentY]).attr( @@ -235,7 +236,7 @@ class BranchGraph markCommit: (x, y, commit, graphHeight) -> if commit.id is @options.commit_id - r = @raphael + r = @r r.path(["M", x + 5, y, "L", x + 15, y + 4, "L", x + 15, y - 4, "Z"]).attr( fill: "#000" "fill-opacity": .5 From a19e3d898d6bb52867f1356f3410f52fa0d76e98 Mon Sep 17 00:00:00 2001 From: Sato Hiroyuki Date: Wed, 20 Mar 2013 09:19:01 +0000 Subject: [PATCH 006/152] Display icon and commit message on network graph. --- app/assets/javascripts/branch-graph.js.coffee | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/branch-graph.js.coffee b/app/assets/javascripts/branch-graph.js.coffee index a5cf67c9..b6ce8ce9 100644 --- a/app/assets/javascripts/branch-graph.js.coffee +++ b/app/assets/javascripts/branch-graph.js.coffee @@ -7,7 +7,7 @@ class BranchGraph @colors = ["#000"] @offsetX = 120 @offsetY = 20 - @unitTime = 20 + @unitTime = 30 @unitSpace = 10 @load() @@ -179,6 +179,15 @@ class BranchGraph fill: @colors[commit.space] stroke: "none" ) + r.rect(@offsetX + @unitSpace * @mspace + 10, y - 10, 20, 20).attr( + fill: "url(#{commit.author.icon})" + stroke: @colors[commit.space] + "stroke-width": 2 + ) + r.text(@offsetX + @unitSpace * @mspace + 35, y, commit.message.split("\n")[0]).attr( + "text-anchor": "start" + font: "14px Monaco, monospace" + ) drawLines: (x, y, commit) -> r = @r From 02f70851e4f029e5de877e2ed2851af269e6045b Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 21 Mar 2013 16:29:53 +0200 Subject: [PATCH 007/152] Update readme to match 5-0-stable --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b04d7eb9..6c063fe5 100644 --- a/README.md +++ b/README.md @@ -51,9 +51,9 @@ Follow the installation guide for production server. -* [Installation guide for latest stable release (4.2)](https://github.com/gitlabhq/gitlabhq/blob/4-2-stable/doc/install/installation.md) - **Recommended** +* [Installation guide for latest stable release (5.0)](https://github.com/gitlabhq/gitlabhq/blob/5-0-stable/doc/install/installation.md) - **Recommended** -* [Installation guide for the current master branch (5.0)](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md) +* [Installation guide for the current master branch (5.1)](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md) #### For development From a1fe375e44987d89b9f9fbacb784eed83de233b2 Mon Sep 17 00:00:00 2001 From: Sato Hiroyuki Date: Thu, 21 Mar 2013 14:41:16 +0000 Subject: [PATCH 008/152] Fix 404 error while displaying json files. It uses params[:id] instead of request.fullpath. It should fix #3132. --- app/controllers/blame_controller.rb | 2 -- app/controllers/blob_controller.rb | 2 -- app/controllers/tree_controller.rb | 1 - lib/extracts_path.rb | 25 +++++------------ spec/lib/extracts_path_spec.rb | 42 ----------------------------- 5 files changed, 6 insertions(+), 66 deletions(-) diff --git a/app/controllers/blame_controller.rb b/app/controllers/blame_controller.rb index 37d7245c..76caa4a6 100644 --- a/app/controllers/blame_controller.rb +++ b/app/controllers/blame_controller.rb @@ -7,8 +7,6 @@ class BlameController < ProjectResourceController before_filter :authorize_code_access! before_filter :require_non_empty_project - before_filter :assign_ref_vars - def show @repo = @project.repo @blame = Grit::Blob.blame(@repo, @commit.id, @path) diff --git a/app/controllers/blob_controller.rb b/app/controllers/blob_controller.rb index d4a45d95..530b72fe 100644 --- a/app/controllers/blob_controller.rb +++ b/app/controllers/blob_controller.rb @@ -7,8 +7,6 @@ class BlobController < ProjectResourceController before_filter :authorize_code_access! before_filter :require_non_empty_project - before_filter :assign_ref_vars - def show if @tree.is_blob? send_data( diff --git a/app/controllers/tree_controller.rb b/app/controllers/tree_controller.rb index 2151bd7c..093fd5e5 100644 --- a/app/controllers/tree_controller.rb +++ b/app/controllers/tree_controller.rb @@ -7,7 +7,6 @@ class TreeController < ProjectResourceController before_filter :authorize_code_access! before_filter :require_non_empty_project - before_filter :assign_ref_vars before_filter :edit_requirements, only: [:edit, :update] def show diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb index 66b2f450..351fc2f2 100644 --- a/lib/extracts_path.rb +++ b/lib/extracts_path.rb @@ -8,7 +8,7 @@ module ExtractsPath included do if respond_to?(:before_filter) - before_filter :assign_ref_vars, only: [:show] + before_filter :assign_ref_vars end end @@ -33,7 +33,7 @@ module ExtractsPath # extract_ref("v2.0.0/README.md") # # => ['v2.0.0', 'README.md'] # - # extract_ref('/gitlab/vagrant/tree/master/app/models/project.rb') + # extract_ref('master/app/models/project.rb') # # => ['master', 'app/models/project.rb'] # # extract_ref('issues/1234/app/models/project.rb') @@ -45,22 +45,12 @@ module ExtractsPath # # Returns an Array where the first value is the tree-ish and the second is the # path - def extract_ref(input) + def extract_ref(id) pair = ['', ''] return pair unless @project - # Remove relative_url_root from path - input.gsub!(/^#{Gitlab.config.gitlab.relative_url_root}/, "") - # Remove project, actions and all other staff from path - input.gsub!(/^\/#{Regexp.escape(@project.path_with_namespace)}/, "") - input.gsub!(/^\/(tree|commits|blame|blob|refs|graph)\//, "") # remove actions - input.gsub!(/\?.*$/, "") # remove stamps suffix - input.gsub!(/.atom$/, "") # remove rss feed - input.gsub!(/.json$/, "") # remove json suffix - input.gsub!(/\/edit$/, "") # remove edit route part - - if input.match(/^([[:alnum:]]{40})(.+)/) + if id.match(/^([[:alnum:]]{40})(.+)/) # If the ref appears to be a SHA, we're done, just split the string pair = $~.captures else @@ -68,7 +58,6 @@ module ExtractsPath # branches and tags # Append a trailing slash if we only get a ref and no file path - id = input id += '/' unless id.ends_with?('/') valid_refs = @project.repository.ref_names @@ -105,11 +94,9 @@ module ExtractsPath # Automatically renders `not_found!` if a valid tree path could not be # resolved (e.g., when a user inserts an invalid path or ref). def assign_ref_vars - path = CGI::unescape(request.fullpath.dup) + @id = params[:id] - @ref, @path = extract_ref(path) - - @id = File.join(@ref, @path) + @ref, @path = extract_ref(@id) # It is used "@project.repository.commits(@ref, @path, 1, 0)", # because "@project.repository.commit(@ref)" returns wrong commit when @ref is tag name. diff --git a/spec/lib/extracts_path_spec.rb b/spec/lib/extracts_path_spec.rb index ee20ae79..aac72c63 100644 --- a/spec/lib/extracts_path_spec.rb +++ b/spec/lib/extracts_path_spec.rb @@ -54,47 +54,5 @@ describe ExtractsPath do extract_ref('stable/CHANGELOG').should == ['stable', 'CHANGELOG'] end end - - context "with a fullpath" do - it "extracts a valid branch" do - extract_ref('/gitlab/gitlab-ci/tree/foo/bar/baz/CHANGELOG').should == ['foo/bar/baz', 'CHANGELOG'] - end - - it "extracts a valid tag" do - extract_ref('/gitlab/gitlab-ci/tree/v2.0.0/CHANGELOG').should == ['v2.0.0', 'CHANGELOG'] - end - - it "extracts a valid commit SHA" do - extract_ref('/gitlab/gitlab-ci/tree/f4b14494ef6abf3d144c28e4af0c20143383e062/CHANGELOG').should == - ['f4b14494ef6abf3d144c28e4af0c20143383e062', 'CHANGELOG'] - end - - it "extracts a timestamp" do - extract_ref('/gitlab/gitlab-ci/tree/v2.0.0/CHANGELOG?_=12354435').should == ['v2.0.0', 'CHANGELOG'] - end - end - - context "with a fullpath and a relative_url_root" do - before do - Gitlab.config.gitlab.stub(relative_url_root: '/relative') - end - - it "extracts a valid branch with relative_url_root" do - extract_ref('/relative/gitlab/gitlab-ci/tree/foo/bar/baz/CHANGELOG').should == ['foo/bar/baz', 'CHANGELOG'] - end - - it "extracts a valid tag" do - extract_ref('/relative/gitlab/gitlab-ci/tree/v2.0.0/CHANGELOG').should == ['v2.0.0', 'CHANGELOG'] - end - - it "extracts a valid commit SHA" do - extract_ref('/relative/gitlab/gitlab-ci/tree/f4b14494ef6abf3d144c28e4af0c20143383e062/CHANGELOG').should == - ['f4b14494ef6abf3d144c28e4af0c20143383e062', 'CHANGELOG'] - end - - it "extracts a timestamp" do - extract_ref('/relative/gitlab/gitlab-ci/tree/v2.0.0/CHANGELOG?_=12354435').should == ['v2.0.0', 'CHANGELOG'] - end - end end end From 06c5389780cf5625f68a0efa3d8ef21b496966a7 Mon Sep 17 00:00:00 2001 From: Sato Hiroyuki Date: Thu, 21 Mar 2013 15:24:06 +0000 Subject: [PATCH 009/152] Fix travis failure randomly, because Capybara.default_wait_time is too short. --- spec/spec_helper.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 30518cc2..0f593de8 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -16,6 +16,7 @@ require 'email_spec' require 'sidekiq/testing/inline' require 'capybara/poltergeist' Capybara.javascript_driver = :poltergeist +Capybara.default_wait_time = 10 # Requires supporting ruby files with custom matchers and macros, etc, # in spec/support/ and its subdirectories. From 0103363191d63d9a81bfeba61abf443532f47183 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 21 Mar 2013 21:01:14 +0200 Subject: [PATCH 010/152] replace Gitolited mixin with Gitlab::ShellAdapter --- app/models/project.rb | 2 +- app/models/protected_branch.rb | 2 +- app/models/users_project.rb | 2 +- app/observers/key_observer.rb | 2 +- app/services/project_transfer_service.rb | 2 +- app/workers/gitlab_shell_worker.rb | 2 +- config/initializers/5_backend.rb | 3 +++ lib/gitlab/backend/shell_adapter.rb | 12 ++++++++++++ lib/gitolited.rb | 11 ----------- 9 files changed, 21 insertions(+), 17 deletions(-) create mode 100644 lib/gitlab/backend/shell_adapter.rb delete mode 100644 lib/gitolited.rb diff --git a/app/models/project.rb b/app/models/project.rb index b13b2918..23eb7f90 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -23,7 +23,7 @@ require "grit" class Project < ActiveRecord::Base - include Gitolited + include Gitlab::ShellAdapter extend Enumerize class TransferError < StandardError; end diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb index 57229d50..16379720 100644 --- a/app/models/protected_branch.rb +++ b/app/models/protected_branch.rb @@ -10,7 +10,7 @@ # class ProtectedBranch < ActiveRecord::Base - include Gitolited + include Gitlab::ShellAdapter attr_accessible :name diff --git a/app/models/users_project.rb b/app/models/users_project.rb index 486aaa69..8051c060 100644 --- a/app/models/users_project.rb +++ b/app/models/users_project.rb @@ -11,7 +11,7 @@ # class UsersProject < ActiveRecord::Base - include Gitolited + include Gitlab::ShellAdapter GUEST = 10 REPORTER = 20 diff --git a/app/observers/key_observer.rb b/app/observers/key_observer.rb index 9d02cbc1..0bc71a66 100644 --- a/app/observers/key_observer.rb +++ b/app/observers/key_observer.rb @@ -1,5 +1,5 @@ class KeyObserver < ActiveRecord::Observer - include Gitolited + include Gitlab::ShellAdapter def after_save(key) GitlabShellWorker.perform_async( diff --git a/app/services/project_transfer_service.rb b/app/services/project_transfer_service.rb index 2ff1aa91..719e0d3d 100644 --- a/app/services/project_transfer_service.rb +++ b/app/services/project_transfer_service.rb @@ -3,7 +3,7 @@ # Used for transfer project to another namespace # class ProjectTransferService - include Gitolited + include Gitlab::ShellAdapter attr_accessor :project diff --git a/app/workers/gitlab_shell_worker.rb b/app/workers/gitlab_shell_worker.rb index 0a921b1b..cfeda88b 100644 --- a/app/workers/gitlab_shell_worker.rb +++ b/app/workers/gitlab_shell_worker.rb @@ -1,6 +1,6 @@ class GitlabShellWorker include Sidekiq::Worker - include Gitolited + include Gitlab::ShellAdapter sidekiq_options queue: :gitlab_shell diff --git a/config/initializers/5_backend.rb b/config/initializers/5_backend.rb index 73436608..7c2e7f39 100644 --- a/config/initializers/5_backend.rb +++ b/config/initializers/5_backend.rb @@ -3,3 +3,6 @@ require Rails.root.join("lib", "gitlab", "backend", "grack_auth") # GIT over SSH require Rails.root.join("lib", "gitlab", "backend", "shell") + +# GitLab shell adapter +require Rails.root.join("lib", "gitlab", "backend", "shell_adapter") diff --git a/lib/gitlab/backend/shell_adapter.rb b/lib/gitlab/backend/shell_adapter.rb new file mode 100644 index 00000000..f247f459 --- /dev/null +++ b/lib/gitlab/backend/shell_adapter.rb @@ -0,0 +1,12 @@ +# == GitLab Shell mixin +# +# Provide a shortcut to Gitlab::Shell instance by gitlab_shell +# +module Gitlab + module ShellAdapter + def gitlab_shell + Gitlab::Shell.new + end + end +end + diff --git a/lib/gitolited.rb b/lib/gitolited.rb deleted file mode 100644 index a7fc4148..00000000 --- a/lib/gitolited.rb +++ /dev/null @@ -1,11 +0,0 @@ -# == Gitolited mixin -# -# Provide a shortcut to Gitlab::Shell instance by gitlab_shell -# -# Used by Project, UsersProject, etc -# -module Gitolited - def gitlab_shell - Gitlab::Shell.new - end -end From c4299bb45a97314fd51962b91346c65ba564d388 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 21 Mar 2013 22:11:08 +0200 Subject: [PATCH 011/152] Move directory logic out of model. Use Gitlab:Shell class to interact with file system --- app/models/namespace.rb | 64 ++++++++++++++--------------------- lib/gitlab/backend/shell.rb | 59 ++++++++++++++++++++++++++++++++ spec/models/namespace_spec.rb | 2 +- 3 files changed, 86 insertions(+), 39 deletions(-) diff --git a/app/models/namespace.rb b/app/models/namespace.rb index e8b7d0c3..cb7164ea 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -13,6 +13,8 @@ # class Namespace < ActiveRecord::Base + include Gitlab::ShellAdapter + attr_accessible :name, :description, :path has_many :projects, dependent: :destroy @@ -31,7 +33,7 @@ class Namespace < ActiveRecord::Base delegate :name, to: :owner, allow_nil: true, prefix: true after_create :ensure_dir_exist - after_update :move_dir + after_update :move_dir, if: :path_changed? after_destroy :rm_dir scope :root, -> { where('type IS NULL') } @@ -53,46 +55,32 @@ class Namespace < ActiveRecord::Base end def ensure_dir_exist - unless dir_exists? - FileUtils.mkdir( namespace_full_path, mode: 0770 ) - end - end - - def dir_exists? - File.exists?(namespace_full_path) - end - - def namespace_full_path - @namespace_full_path ||= File.join(Gitlab.config.gitlab_shell.repos_path, path) - end - - def move_dir - if path_changed? - old_path = File.join(Gitlab.config.gitlab_shell.repos_path, path_was) - new_path = File.join(Gitlab.config.gitlab_shell.repos_path, path) - if File.exists?(new_path) - raise "Already exists" - end - - - begin - # Remove satellite when moving repo - if path_was.present? - satellites_path = File.join(Gitlab.config.satellites.path, path_was) - FileUtils.rm_r( satellites_path, force: true ) - end - - FileUtils.mv( old_path, new_path ) - send_update_instructions - rescue Exception => e - raise "Namespace move error #{old_path} #{new_path}" - end - end + gitlab_shell.add_namespace(path) end def rm_dir - dir_path = File.join(Gitlab.config.gitlab_shell.repos_path, path) - FileUtils.rm_r( dir_path, force: true ) + gitlab_shell.rm_namespace(path) + end + + def move_dir + if gitlab_shell.mv_namespace(path_was, path) + # If repositories moved successfully we need to remove old satellites + # and send update instructions to users. + # However we cannot allow rollback since we moved namespace dir + # So we basically we mute exceptions in next actions + begin + gitlab_shell.rm_satellites(path_was) + send_update_instructions + rescue + # Returning false does not rolback after_* transaction but gives + # us information about failing some of tasks + false + end + else + # if we cannot move namespace directory we should rollback + # db changes in order to prevent out of sync between db and fs + raise Exception.new('namespace directory cannot be moved') + end end def send_update_instructions diff --git a/lib/gitlab/backend/shell.rb b/lib/gitlab/backend/shell.rb index a230886b..bae87977 100644 --- a/lib/gitlab/backend/shell.rb +++ b/lib/gitlab/backend/shell.rb @@ -65,13 +65,72 @@ module Gitlab system("#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-keys rm-key #{key_id} \"#{key_content}\"") end + # Add empty directory for storing repositories + # + # Ex. + # add_namespace("gitlab") + # + def add_namespace(name) + FileUtils.mkdir(full_path(name), mode: 0770) unless exists?(name) + end + + # Remove directory from repositories storage + # Every repository inside this directory will be removed too + # + # Ex. + # rm_namespace("gitlab") + # + def rm_namespace(name) + FileUtils.rm_r(full_path(name), force: true) + end + + # Move namespace directory inside repositories storage + # + # Ex. + # mv_namespace("gitlab", "gitlabhq") + # + def mv_namespace(old_name, new_name) + return false if exists?(new_name) || !exists?(old_name) + + FileUtils.mv(full_path(old_name), full_path(new_name)) + end + + # Remove GitLab Satellites for provided path (namespace or repo dir) + # + # Ex. + # rm_satellites("gitlab") + # + # rm_satellites("gitlab/gitlab-ci.git") + # + def rm_satellites(path) + raise ArgumentError.new("Path can't be blank") if path.blank? + + satellites_path = File.join(Gitlab.config.satellites.path, path) + FileUtils.rm_r(satellites_path, force: true) + end + def url_to_repo path Gitlab.config.gitlab_shell.ssh_path_prefix + "#{path}.git" end + protected + def gitlab_shell_user_home File.expand_path("~#{Gitlab.config.gitlab_shell.ssh_user}") end + def repos_path + Gitlab.config.gitlab_shell.repos_path + end + + def full_path(dir_name) + raise ArgumentError.new("Directory name can't be blank") if dir_name.blank? + + File.join(repos_path, dir_name) + end + + def exists?(dir_name) + File.exists?(full_path(dir_name)) + end end end diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb index 412e42aa..b40a0795 100644 --- a/spec/models/namespace_spec.rb +++ b/spec/models/namespace_spec.rb @@ -60,7 +60,7 @@ describe Namespace do end it "should raise error when dirtory exists" do - expect { @namespace.move_dir }.to raise_error("Already exists") + expect { @namespace.move_dir }.to raise_error("namespace directory cannot be moved") end it "should move dir if path changed" do From fec283889bdc02893bd2fc78a0638b9a4ad2ac1a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 21 Mar 2013 22:22:21 +0200 Subject: [PATCH 012/152] fix commit-description css on commit.show --- app/assets/stylesheets/sections/commits.scss | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss index 0df39298..1e564188 100644 --- a/app/assets/stylesheets/sections/commits.scss +++ b/app/assets/stylesheets/sections/commits.scss @@ -413,3 +413,9 @@ padding: 4px; background-color: #EEE; } + +.commit-description { + background: none; + border: none; + margin: 0; +} From ad5ea14210cc6dcb674c421e296b67ed2d0e6dbc Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 21 Mar 2013 22:22:54 +0200 Subject: [PATCH 013/152] Move commit.show partial from commits/ to commit/ --- app/views/{commits => commit}/_commit_box.html.haml | 0 app/views/commit/show.html.haml | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename app/views/{commits => commit}/_commit_box.html.haml (100%) diff --git a/app/views/commits/_commit_box.html.haml b/app/views/commit/_commit_box.html.haml similarity index 100% rename from app/views/commits/_commit_box.html.haml rename to app/views/commit/_commit_box.html.haml diff --git a/app/views/commit/show.html.haml b/app/views/commit/show.html.haml index 485f2d1e..6a723ee8 100644 --- a/app/views/commit/show.html.haml +++ b/app/views/commit/show.html.haml @@ -1,4 +1,4 @@ -= render "commits/commit_box" += render "commit_box" %p.pull-right.cgray This commit has From 5f9d654939d388c7aeb8e84f6bb5b0d65319c535 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 21 Mar 2013 22:50:18 +0200 Subject: [PATCH 014/152] Dont show '0 additions and 0 deletions' message for commit --- app/models/commit.rb | 6 ++++++ app/views/commit/show.html.haml | 11 ++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/app/models/commit.rb b/app/models/commit.rb index daba5414..4d0c57b3 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -172,4 +172,10 @@ class Commit lines.pop if lines.last == "-- " # end of diff lines.join("\n") end + + def has_zero_stats? + stats.total.zero? + rescue + true + end end diff --git a/app/views/commit/show.html.haml b/app/views/commit/show.html.haml index 6a723ee8..48fb44a9 100644 --- a/app/views/commit/show.html.haml +++ b/app/views/commit/show.html.haml @@ -1,10 +1,11 @@ = render "commit_box" -%p.pull-right.cgray - This commit has - %span.cgreen #{@commit.stats.additions} additions - and - %span.cred #{@commit.stats.deletions} deletions +- unless @commit.has_zero_stats? + %p.pull-right.cgray + This commit has + %span.cgreen #{@commit.stats.additions} additions + and + %span.cred #{@commit.stats.deletions} deletions = render "commits/diffs", diffs: @commit.diffs = render "notes/notes_with_form" From 26606aa2ec5f518f2b310a0e1855e0f3f43c9bbd Mon Sep 17 00:00:00 2001 From: Sato Hiroyuki Date: Fri, 22 Mar 2013 10:07:11 +0900 Subject: [PATCH 015/152] Fix style of network graph. refs #3258 --- app/assets/javascripts/branch-graph.js.coffee | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/branch-graph.js.coffee b/app/assets/javascripts/branch-graph.js.coffee index b6ce8ce9..c2fa4f24 100644 --- a/app/assets/javascripts/branch-graph.js.coffee +++ b/app/assets/javascripts/branch-graph.js.coffee @@ -51,21 +51,21 @@ class BranchGraph buildGraph: -> graphHeight = $(@element).height() graphWidth = $(@element).width() - ch = Math.max(graphHeight, @unitTime * @mtime + 100) - cw = Math.max(graphWidth, @unitSpace * @mspace + 260) + ch = Math.max(graphHeight, @offsetY + @unitTime * @mtime + 150) + cw = Math.max(graphWidth, @offsetX + @unitSpace * @mspace + 300) @r = r = Raphael(@element.get(0), cw, ch) top = r.set() cuday = 0 cumonth = "" barHeight = Math.max(graphHeight, @unitTime * @days.length + 320) - r.rect(0, 0, 20, barHeight).attr fill: "#222" - r.rect(20, 0, 20, barHeight).attr fill: "#444" + r.rect(0, 0, 26, barHeight).attr fill: "#222" + r.rect(26, 0, 20, barHeight).attr fill: "#444" for day, mm in @days if cuday isnt day[0] # Dates - r.text(30, @offsetY + @unitTime * mm, day[0]) + r.text(36, @offsetY + @unitTime * mm, day[0]) .attr( font: "12px Monaco, monospace" fill: "#DDD" @@ -74,7 +74,7 @@ class BranchGraph if cumonth isnt day[1] # Months - r.text(10, @offsetY + @unitTime * mm, day[1]) + r.text(13, @offsetY + @unitTime * mm, day[1]) .attr( font: "12px Monaco, monospace" fill: "#EEE" From f5e001bd8cc76fb104a2e7c6e1ac4f6d0c2e8bf0 Mon Sep 17 00:00:00 2001 From: Sato Hiroyuki Date: Fri, 22 Mar 2013 11:59:36 +0900 Subject: [PATCH 016/152] Using arrowed line only if it connects to not first parent. It is easy to see which branch is merged. --- app/assets/javascripts/branch-graph.js.coffee | 89 ++++++++++--------- 1 file changed, 45 insertions(+), 44 deletions(-) diff --git a/app/assets/javascripts/branch-graph.js.coffee b/app/assets/javascripts/branch-graph.js.coffee index c2fa4f24..796bebe2 100644 --- a/app/assets/javascripts/branch-graph.js.coffee +++ b/app/assets/javascripts/branch-graph.js.coffee @@ -191,57 +191,58 @@ class BranchGraph drawLines: (x, y, commit) -> r = @r - for parent in commit.parents + for parent, i in commit.parents parentCommit = @preparedCommits[parent[0]] parentY = @offsetY + @unitTime * parentCommit.time parentX1 = @offsetX + @unitSpace * (@mspace - parentCommit.space) parentX2 = @offsetX + @unitSpace * (@mspace - parent[1]) - if parentCommit.space is commit.space and parentCommit.space is parent[1] - r.path(["M", x, y, "L", parentX1, parentY]).attr( - stroke: @colors[parentCommit.space] - "stroke-width": 2 - ) - - else if parentCommit.space < commit.space - if x is parentX2 - r - .path([ - "M", x, y + 5, - "l-2,5,4,0,-2,-5", - "L", x, y + 10, - "L", parentX2, y + 10, - "L", parentX2, parentY - 5, - "L", parentX1, parentY]) - .attr( - stroke: @colors[commit.space] - "stroke-width": 2) - - else - r - .path([ - "M", x + 3, y + 3, - "l5,0,-2,4,-3,-4", - "L", x + 7, y + 5, - "L", parentX2, y + 10, - "L", parentX2, parentY - 5, - "L", parentX1, parentY]) - .attr( - stroke: @colors[commit.space] - "stroke-width": 2) + # Set line color + if parentCommit.space <= commit.space + color = @colors[commit.space] else - r - .path([ - "M", x - 3, y + 3, - "l-5,0,2,4,3,-4", - "L", x - 7, y + 5, - "L", parentX2, y + 10, - "L", parentX2, parentY - 5, - "L", parentX1, parentY]) - .attr( - stroke: @colors[parentCommit.space] - "stroke-width": 2) + color = @colors[parentCommit.space] + + # Build line shape + if parent[1] is commit.space + d1 = [0, 5] + d2 = [0, 10] + arrow = "l-2,5,4,0,-2,-5" + + else if parent[1] < commit.space + d1 = [3, 3] + d2 = [7, 5] + arrow = "l5,0,-2,4,-3,-4" + + else + d1 = [-3, 3] + d2 = [-7, 5] + arrow = "l-5,0,2,4,3,-4" + + # Start point + route = ["M", x + d1[0], y + d1[1]] + + # Add arrow if not first parent + if i > 0 + route.push(arrow) + + # Circumvent if overlap + if commit.space isnt parentCommit.space or commit.space isnt parent[1] + route.push( + "L", x + d2[0], y + d2[1], + "L", parentX2, y + 10, + "L", parentX2, parentY - 5, + ) + + # End point + route.push("L", parentX1, parentY) + + r + .path(route) + .attr( + stroke: color + "stroke-width": 2) markCommit: (x, y, commit, graphHeight) -> if commit.id is @options.commit_id From ef968fd0c8a61d63283e9f7aba4a07809d87bc16 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 21 Mar 2013 22:22:21 +0200 Subject: [PATCH 017/152] fix commit-description css on commit.show --- app/assets/stylesheets/sections/commits.scss | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss index 0df39298..1e564188 100644 --- a/app/assets/stylesheets/sections/commits.scss +++ b/app/assets/stylesheets/sections/commits.scss @@ -413,3 +413,9 @@ padding: 4px; background-color: #EEE; } + +.commit-description { + background: none; + border: none; + margin: 0; +} From 84043e8e44337353169a7c1ec8ccca2ce823b995 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 22 Mar 2013 15:08:02 +0200 Subject: [PATCH 018/152] Fix lines and line numbers being squashed in File -> blame --- app/views/blame/show.html.haml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/views/blame/show.html.haml b/app/views/blame/show.html.haml index 36d81e6a..62516266 100644 --- a/app/views/blame/show.html.haml +++ b/app/views/blame/show.html.haml @@ -38,9 +38,11 @@ - current_line += 1 - else - lines.each do |line| - = current_line + :preserve + #{current_line} - current_line += 1 %td.lines %pre - lines.each do |line| - = line + :preserve + #{line} From de2c189ec10448787e41e4f2283de7c120fb16df Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 22 Mar 2013 15:11:16 +0200 Subject: [PATCH 019/152] fix blame view head nav --- app/views/blame/_head.html.haml | 9 ++------- app/views/blame/show.html.haml | 2 +- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/app/views/blame/_head.html.haml b/app/views/blame/_head.html.haml index ef9e6c9c..3a883829 100644 --- a/app/views/blame/_head.html.haml +++ b/app/views/blame/_head.html.haml @@ -1,7 +1,2 @@ -%ul.nav.nav-tabs - %li - = render partial: 'shared/ref_switcher', locals: {destination: 'tree', path: params[:path]} - = nav_link(controller: :refs) do - = link_to 'Source', project_tree_path(@project, @ref) - %li.pull-right - = render "shared/clone_panel" +%div.tree-ref-holder + = render 'shared/ref_switcher', destination: 'tree', path: params[:path] diff --git a/app/views/blame/show.html.haml b/app/views/blame/show.html.haml index 62516266..f85dde6d 100644 --- a/app/views/blame/show.html.haml +++ b/app/views/blame/show.html.haml @@ -3,7 +3,7 @@ #tree-holder.tree-holder %ul.breadcrumb %li - %span.arrow + %i.icon-angle-right = link_to project_tree_path(@project, @ref) do = @project.name - @tree.breadcrumbs(6) do |link| From 0e4b2395a9612d67255f5101452a2e79334c4352 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 22 Mar 2013 15:08:02 +0200 Subject: [PATCH 020/152] Fix lines and line numbers being squashed in File -> blame --- app/views/blame/show.html.haml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/views/blame/show.html.haml b/app/views/blame/show.html.haml index 36d81e6a..62516266 100644 --- a/app/views/blame/show.html.haml +++ b/app/views/blame/show.html.haml @@ -38,9 +38,11 @@ - current_line += 1 - else - lines.each do |line| - = current_line + :preserve + #{current_line} - current_line += 1 %td.lines %pre - lines.each do |line| - = line + :preserve + #{line} From 5c49cf6ca170aba7646f53d02130c79c0c4470a6 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 22 Mar 2013 15:11:16 +0200 Subject: [PATCH 021/152] fix blame view head nav --- app/views/blame/_head.html.haml | 9 ++------- app/views/blame/show.html.haml | 2 +- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/app/views/blame/_head.html.haml b/app/views/blame/_head.html.haml index ef9e6c9c..3a883829 100644 --- a/app/views/blame/_head.html.haml +++ b/app/views/blame/_head.html.haml @@ -1,7 +1,2 @@ -%ul.nav.nav-tabs - %li - = render partial: 'shared/ref_switcher', locals: {destination: 'tree', path: params[:path]} - = nav_link(controller: :refs) do - = link_to 'Source', project_tree_path(@project, @ref) - %li.pull-right - = render "shared/clone_panel" +%div.tree-ref-holder + = render 'shared/ref_switcher', destination: 'tree', path: params[:path] diff --git a/app/views/blame/show.html.haml b/app/views/blame/show.html.haml index 62516266..f85dde6d 100644 --- a/app/views/blame/show.html.haml +++ b/app/views/blame/show.html.haml @@ -3,7 +3,7 @@ #tree-holder.tree-holder %ul.breadcrumb %li - %span.arrow + %i.icon-angle-right = link_to project_tree_path(@project, @ref) do = @project.name - @tree.breadcrumbs(6) do |link| From 693dcce6bc2cb7db515972c250fd5f598143eb1d Mon Sep 17 00:00:00 2001 From: Austin Robertson Date: Fri, 22 Mar 2013 10:31:19 -0500 Subject: [PATCH 022/152] Change gollum repo to use https:// instead of git:// A lot of people might have firewalls blocking the git:// protocol. Using https:// makes this easier and matches the other git repositories in the Gemfile. --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 7f92cb75..d0280732 100644 --- a/Gemfile +++ b/Gemfile @@ -104,7 +104,7 @@ gem 'settingslogic' # github-linquist needs pygments 0.4.2 but Gollum 2.4.11 # requires pygments 0.3.2. The latest master Gollum has been updated # to use pygments 0.4.2. Change this after next Gollum release. -gem "gollum", "~> 2.4.0", git: "git://github.com/gollum/gollum.git", ref: "5dcd3c8c8f" +gem "gollum", "~> 2.4.0", git: "https://github.com/gollum/gollum.git", ref: "5dcd3c8c8f" # Misc gem "foreman" From ba1dbd39fb20a004eb54a8653d548628e1186587 Mon Sep 17 00:00:00 2001 From: Austin Robertson Date: Fri, 22 Mar 2013 10:38:27 -0500 Subject: [PATCH 023/152] Change Gemfile.lock repo to use https:// --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 4de5c893..f2800771 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,5 +1,5 @@ GIT - remote: git://github.com/gollum/gollum.git + remote: https://github.com/gollum/gollum.git revision: 5dcd3c8c8f68158e43ff79861279088ee56d0ebe ref: 5dcd3c8c8f specs: From ccc880675818406e4ac33cfa69d95993696d6f96 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Fri, 22 Mar 2013 17:39:22 +0100 Subject: [PATCH 024/152] Attribution as mentioned in https://news.ycombinator.com/item?id=5423635 --- CHANGELOG | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 62792fcf..a80113c2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -14,7 +14,7 @@ v 5.0.0 - Add validations for Group and Team names - Restyle team page for project - Update capybara, rspec-rails, poltergeist to recent versions - - Wiki on git using Gollum + - Wiki on git using Gollum - Added Solarized Dark theme for code review - Dont show user emails in autocomplete lists, profile pages - Added settings tab for group, team, project @@ -24,7 +24,7 @@ v 5.0.0 - Fixed search field on projects page - Added teams to search autocomplete - Move groups and teams on dashboard sidebar to sub-tabs - - API: improved return codes and docs. + - API: improved return codes and docs. @Xylakant - Redesign wall to be more like chat - Snippets, Wall features are disabled by default for new projects @@ -56,7 +56,7 @@ v 4.1.0 - cleanup rake tasks - fix backup/restore - scss cleanup - - show preview for note images + - show preview for note images - improved network-graph - get rid of app/roles/ - added new classes Team, Repository @@ -70,7 +70,7 @@ v 4.1.0 v 4.0.0 - Remove project code and path from API. Use id instead - Return valid clonable url to repo for web hook - - Fixed backup issue + - Fixed backup issue - Reorganized settings - Fixed commits compare - Refactored scss From 3869cfecc164fb15a9092f55ad20e5d60ec400b6 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Fri, 22 Mar 2013 17:42:31 +0100 Subject: [PATCH 025/152] Use real name. --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index a80113c2..ff9a8058 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -24,7 +24,7 @@ v 5.0.0 - Fixed search field on projects page - Added teams to search autocomplete - Move groups and teams on dashboard sidebar to sub-tabs - - API: improved return codes and docs. @Xylakant + - API: improved return codes and docs. (Felix Gilcher) - Redesign wall to be more like chat - Snippets, Wall features are disabled by default for new projects From c0da61c6d88dd6ea08bd6ace3149652178d2e26d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 22 Mar 2013 18:52:25 +0200 Subject: [PATCH 026/152] fix xss issue in blame --- app/views/blame/show.html.haml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/views/blame/show.html.haml b/app/views/blame/show.html.haml index f85dde6d..b2a45ef5 100644 --- a/app/views/blame/show.html.haml +++ b/app/views/blame/show.html.haml @@ -38,11 +38,11 @@ - current_line += 1 - else - lines.each do |line| - :preserve - #{current_line} + = current_line + \ - current_line += 1 %td.lines %pre - lines.each do |line| - :preserve - #{line} + = line + \ From 0c7f426037db668fbd9ad11376b4db0007baafce Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 22 Mar 2013 18:52:25 +0200 Subject: [PATCH 027/152] fix xss issue in blame --- app/views/blame/show.html.haml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/views/blame/show.html.haml b/app/views/blame/show.html.haml index f85dde6d..b2a45ef5 100644 --- a/app/views/blame/show.html.haml +++ b/app/views/blame/show.html.haml @@ -38,11 +38,11 @@ - current_line += 1 - else - lines.each do |line| - :preserve - #{current_line} + = current_line + \ - current_line += 1 %td.lines %pre - lines.each do |line| - :preserve - #{line} + = line + \ From 78dd9a148196dcd51666f678c2601281b9568ea0 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Fri, 22 Mar 2013 17:54:42 +0100 Subject: [PATCH 028/152] All involved are mentioned. https://news.ycombinator.com/item?id=5424050 --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index ff9a8058..2641875d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -24,7 +24,7 @@ v 5.0.0 - Fixed search field on projects page - Added teams to search autocomplete - Move groups and teams on dashboard sidebar to sub-tabs - - API: improved return codes and docs. (Felix Gilcher) + - API: improved return codes and docs. (Felix Gilcher, Sebastian Ziebell) - Redesign wall to be more like chat - Snippets, Wall features are disabled by default for new projects From 5cc5b74e8e42e23f6ffa45609de540e5b6209b60 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Fri, 22 Mar 2013 18:34:59 +0100 Subject: [PATCH 029/152] Update ruby to latest version. --- .travis.yml | 2 +- doc/install/installation.md | 4 ++-- doc/raketasks/maintenance.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index befa0c32..609f2967 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ branches: only: - 'master' rvm: - - 1.9.3-p327 + - 1.9.3-p392 services: - mysql - postgresql diff --git a/doc/install/installation.md b/doc/install/installation.md index 69d3b186..df95b083 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -74,8 +74,8 @@ Make sure you have the right version of Python installed. Download and compile it: mkdir /tmp/ruby && cd /tmp/ruby - curl --progress http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-p327.tar.gz | tar xz - cd ruby-1.9.3-p327 + curl --progress http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-p392.tar.gz | tar xz + cd ruby-1.9.3-p392 ./configure make sudo make install diff --git a/doc/raketasks/maintenance.md b/doc/raketasks/maintenance.md index 726cc083..b5514705 100644 --- a/doc/raketasks/maintenance.md +++ b/doc/raketasks/maintenance.md @@ -15,7 +15,7 @@ System: Debian 6.0.6 Current User: gitlab Using RVM: yes RVM Version: 1.17.2 -Ruby Version: ruby-1.9.3-p327 +Ruby Version: ruby-1.9.3-p392 Gem Version: 1.8.24 Bundler Version:1.2.3 Rake Version: 10.0.1 From de3b181a690db5acd17453fca1b348d95227950a Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Sat, 23 Mar 2013 21:05:42 +0100 Subject: [PATCH 030/152] 5.0 should no longer be on the roadmap --- ROADMAP.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index bf4fe695..eaee47b1 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,7 +1,5 @@ ## GitLab Roadmap -### v5.0 March 22 +### v5.1 Apil 22 -* Replace gitolite with gitlab-shell -* Usability improvements -* Notification improvements \ No newline at end of file +* Not decided yet. From c4f8d34b7d16751432c30904b60314430617ccfd Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Sat, 23 Mar 2013 21:06:00 +0100 Subject: [PATCH 031/152] spelling error --- ROADMAP.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ROADMAP.md b/ROADMAP.md index eaee47b1..9c4bd2db 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,5 +1,5 @@ ## GitLab Roadmap -### v5.1 Apil 22 +### v5.1 April 22 * Not decided yet. From 0d56b1b07f8ec05725b9c8f4ed45f10c76325d43 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Sat, 23 Mar 2013 21:20:09 +0100 Subject: [PATCH 032/152] Updated links to gitlab.com and added the last doc files. --- README.md | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 6c063fe5..a524f790 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ * GitLab.org community site: [Homepage](http://gitlab.org) [Screenshots](http://gitlab.org/screenshots/) [Blog](http://blog.gitlab.org/) [Demo](http://demo.gitlabhq.com/users/sign_in) -* GitLab.com commercial services: [Homepage](http://blog.gitlab.com/) [GitLab Cloud](http://blog.gitlab.com/cloud/) [Subscription](http://blog.gitlab.com/subscription/) [Consultancy](http://blog.gitlab.com/consultancy/) [Blog](http://blog.gitlab.com/blog/) +* GitLab.com commercial services: [Homepage](http://www.gitlab.com/) [GitLab Cloud](http://www.gitlab.com/cloud/) [Subscription](http://www.gitlab.com/subscription/) [Consultancy](http://www.gitlab.com/consultancy/) [Blog](http://blog.gitlab.com/) * GitLab CI: [Readme](https://github.com/gitlabhq/gitlab-ci/blob/master/README.md) of the GitLab open-source continuous integration server @@ -55,13 +55,20 @@ Follow the installation guide for production server. * [Installation guide for the current master branch (5.1)](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md) - #### For development If you want to contribute, please first read our [Contributing Guidelines](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) and then we suggest you to use the Vagrant virtual machine project to get an environment working sandboxed and with all dependencies. * [Vagrant virtual machine](https://github.com/gitlabhq/gitlab-vagrant-vm) +#### Unsupported installation methods + +* [GitLab recipes](https://github.com/gitlabhq/gitlab-recipes) for setup on different platforms + +* [Unofficial installation guides](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Unofficial-Installation-Guides) + + + ### Starting 1. The Installation guide contains instructions to download an init script and run that on boot. With the init script you can also start GitLab @@ -108,25 +115,29 @@ If you want to contribute, please first read our [Contributing Guidelines](https * [Feedback and suggestions forum](http://gitlab.uservoice.com/forums/176466-general) -* [Support subscription](http://blog.gitlab.com/subscription/) +* [Support subscription](http://www.gitlab.com/subscription/) -* [Consultancy](http://blog.gitlab.com/consultancy/) +* [Consultancy](http://www.gitlab.com/consultancy/) -### New versions and the API +### New versions and upgrading Each month on the 22th a new version is released together with an upgrade guide. * [Upgrade guides](https://github.com/gitlabhq/gitlabhq/wiki) +* [Changelog](https://github.com/gitlabhq/gitlabhq/blob/master/CHANGELOG) + * [Roadmap](https://github.com/gitlabhq/gitlabhq/blob/master/ROADMAP.md) -### Other documentation +### GitLab interfaces * [GitLab API](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/README.md) * [Rake tasks](https://github.com/gitlabhq/gitlabhq/tree/master/doc/raketasks) -* [GitLab recipes](https://github.com/gitlabhq/gitlab-recipes) +* [Directory structure](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/structure.md) + +* [Databases](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/databases.md) ### Getting in touch From 979dcdba958cb6063c2676532a25ac407b601645 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 24 Mar 2013 11:24:26 +0200 Subject: [PATCH 033/152] security update of crack gem --- Gemfile.lock | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index f2800771..51d121b9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,3 +1,17 @@ +GIT + remote: https://github.com/ctran/annotate_models.git + revision: be4e26825b521f0b2d86b181e2dff89901aa9b1e + specs: + annotate (2.6.0.beta1) + activerecord (>= 2.3.0) + rake (>= 0.8.7) + +GIT + remote: https://github.com/gitlabhq/raphael-rails.git + revision: cb2c92a040b9b941a5f1aa1ea866cc26e944fe58 + specs: + raphael-rails (2.1.0) + GIT remote: https://github.com/gollum/gollum.git revision: 5dcd3c8c8f68158e43ff79861279088ee56d0ebe @@ -15,20 +29,6 @@ GIT stringex (~> 1.5.1) useragent (~> 0.4.16) -GIT - remote: https://github.com/ctran/annotate_models.git - revision: be4e26825b521f0b2d86b181e2dff89901aa9b1e - specs: - annotate (2.6.0.beta1) - activerecord (>= 2.3.0) - rake (>= 0.8.7) - -GIT - remote: https://github.com/gitlabhq/raphael-rails.git - revision: cb2c92a040b9b941a5f1aa1ea866cc26e944fe58 - specs: - raphael-rails (2.1.0) - GEM remote: https://rubygems.org/ specs: @@ -112,7 +112,7 @@ GEM rest-client simplecov (>= 0.7) thor - crack (0.3.1) + crack (0.3.2) daemons (1.1.9) database_cleaner (0.9.1) debug_inspector (0.0.2) From 159cd0d742df2ed3b234f47cb19d99b68434c9fe Mon Sep 17 00:00:00 2001 From: Andrew Kumanyaev Date: Sun, 24 Mar 2013 13:48:23 +0400 Subject: [PATCH 034/152] Update databases.md --- doc/install/databases.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/install/databases.md b/doc/install/databases.md index 2c4fb9db..fade5d4f 100644 --- a/doc/install/databases.md +++ b/doc/install/databases.md @@ -38,10 +38,10 @@ GitLab supports the following databases: sudo -u postgres psql -d template1 # Create a user for GitLab. (change $password to a real password) - template1=# CREATE USER gitlab WITH PASSWORD '$password'; + template1=# CREATE USER git WITH PASSWORD '$password'; # Create the GitLab production database & grant all privileges on database - template1=# CREATE DATABASE gitlabhq_production OWNER gitlab; + template1=# CREATE DATABASE gitlabhq_production OWNER git; # Quit the database session template1=# \q From 29b0ac489b7dea0bab97b25cf34a3b2d44fcd069 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 24 Mar 2013 11:57:44 +0200 Subject: [PATCH 035/152] move edit to separate controller. This fixes #3265 --- app/controllers/edit_tree_controller.rb | 47 +++++++++++++++++++ app/controllers/tree_controller.rb | 38 --------------- .../show.html.haml} | 2 +- app/views/tree/_blob_actions.html.haml | 2 +- config/routes.rb | 3 +- 5 files changed, 51 insertions(+), 41 deletions(-) create mode 100644 app/controllers/edit_tree_controller.rb rename app/views/{tree/edit.html.haml => edit_tree/show.html.haml} (93%) diff --git a/app/controllers/edit_tree_controller.rb b/app/controllers/edit_tree_controller.rb new file mode 100644 index 00000000..aae983aa --- /dev/null +++ b/app/controllers/edit_tree_controller.rb @@ -0,0 +1,47 @@ +# Controller for edit a repository's file +class EditTreeController < ProjectResourceController + include ExtractsPath + + # Authorize + before_filter :authorize_read_project! + before_filter :authorize_code_access! + before_filter :require_non_empty_project + + before_filter :edit_requirements, only: [:edit, :update] + + def show + @last_commit = @project.repository.last_commit_for(@ref, @path).sha + end + + def update + edit_file_action = Gitlab::Satellite::EditFileAction.new(current_user, @project, @ref, @path) + updated_successfully = edit_file_action.commit!( + params[:content], + params[:commit_message], + params[:last_commit] + ) + + if updated_successfully + redirect_to project_tree_path(@project, @id), notice: "Your changes have been successfully commited" + else + flash[:notice] = "Your changes could not be commited, because the file has been changed" + render :edit + end + end + + private + + def edit_requirements + unless @tree.is_blob? && @tree.text? + redirect_to project_tree_path(@project, @id), notice: "You can only edit text files" + end + + allowed = if project.protected_branch? @ref + can?(current_user, :push_code_to_protected_branches, project) + else + can?(current_user, :push_code, project) + end + + return access_denied! unless allowed + end +end diff --git a/app/controllers/tree_controller.rb b/app/controllers/tree_controller.rb index 093fd5e5..a03ea3ff 100644 --- a/app/controllers/tree_controller.rb +++ b/app/controllers/tree_controller.rb @@ -7,8 +7,6 @@ class TreeController < ProjectResourceController before_filter :authorize_code_access! before_filter :require_non_empty_project - before_filter :edit_requirements, only: [:edit, :update] - def show @hex_path = Digest::SHA1.hexdigest(@path) @logs_path = logs_file_project_ref_path(@project, @ref, @path) @@ -19,40 +17,4 @@ class TreeController < ProjectResourceController format.js { no_cache_headers } end end - - def edit - @last_commit = @project.repository.last_commit_for(@ref, @path).sha - end - - def update - edit_file_action = Gitlab::Satellite::EditFileAction.new(current_user, @project, @ref, @path) - updated_successfully = edit_file_action.commit!( - params[:content], - params[:commit_message], - params[:last_commit] - ) - - if updated_successfully - redirect_to project_tree_path(@project, @id), notice: "Your changes have been successfully commited" - else - flash[:notice] = "Your changes could not be commited, because the file has been changed" - render :edit - end - end - - private - - def edit_requirements - unless @tree.is_blob? && @tree.text? - redirect_to project_tree_path(@project, @id), notice: "You can only edit text files" - end - - allowed = if project.protected_branch? @ref - can?(current_user, :push_code_to_protected_branches, project) - else - can?(current_user, :push_code, project) - end - - return access_denied! unless allowed - end end diff --git a/app/views/tree/edit.html.haml b/app/views/edit_tree/show.html.haml similarity index 93% rename from app/views/tree/edit.html.haml rename to app/views/edit_tree/show.html.haml index 81918e50..211396ba 100644 --- a/app/views/tree/edit.html.haml +++ b/app/views/edit_tree/show.html.haml @@ -1,5 +1,5 @@ .file-editor - = form_tag(project_tree_path(@project, @id), method: :put, class: "form-horizontal") do + = form_tag(project_edit_tree_path(@project, @id), method: :put, class: "form-horizontal") do .file_holder .file_title %i.icon-file diff --git a/app/views/tree/_blob_actions.html.haml b/app/views/tree/_blob_actions.html.haml index 0bde968d..1d55a4ff 100644 --- a/app/views/tree/_blob_actions.html.haml +++ b/app/views/tree/_blob_actions.html.haml @@ -1,7 +1,7 @@ .btn-group.tree-btn-group -# only show edit link for text files - if @tree.text? - = link_to "edit", edit_project_tree_path(@project, @id), class: "btn btn-tiny", disabled: !allowed_tree_edit? + = link_to "edit", project_edit_tree_path(@project, @id), class: "btn btn-tiny", disabled: !allowed_tree_edit? = link_to "raw", project_blob_path(@project, @id), class: "btn btn-tiny", target: "_blank" -# only show normal/blame view links for text files - if @tree.text? diff --git a/config/routes.rb b/config/routes.rb index 0028baf8..fafaef84 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -168,7 +168,8 @@ Gitlab::Application.routes.draw do # resources :projects, constraints: { id: /(?:[a-zA-Z.0-9_\-]+\/)?[a-zA-Z.0-9_\-]+/ }, except: [:new, :create, :index], path: "/" do resources :blob, only: [:show], constraints: {id: /.+/} - resources :tree, only: [:show, :edit, :update], constraints: {id: /.+/} + resources :tree, only: [:show], constraints: {id: /.+/, format: /(html|js)/ } + resources :edit_tree, only: [:show, :update], constraints: {id: /.+/}, path: 'edit' resources :commit, only: [:show], constraints: {id: /[[:alnum:]]{6,40}/} resources :commits, only: [:show], constraints: {id: /(?:[^.]|\.(?!atom$))+/, format: /atom/} resources :compare, only: [:index, :create] From 4cc27fd9e1cd1a2073737f94b62a19a169aac32e Mon Sep 17 00:00:00 2001 From: Andrew Kumanyaev Date: Sun, 24 Mar 2013 14:10:32 +0400 Subject: [PATCH 036/152] Update database.yml.postgresql --- config/database.yml.postgresql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/database.yml.postgresql b/config/database.yml.postgresql index 2bc0884f..4a4aa346 100644 --- a/config/database.yml.postgresql +++ b/config/database.yml.postgresql @@ -6,7 +6,7 @@ production: encoding: unicode database: gitlabhq_production pool: 5 - username: gitlab + username: git password: # host: localhost # port: 5432 From df46903dbe551f80c1eb36389efd73b529dc1e31 Mon Sep 17 00:00:00 2001 From: Vinod Chandru Date: Sun, 24 Mar 2013 20:23:02 -0700 Subject: [PATCH 037/152] Fixing a minor typo in the installation docs --- doc/install/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index df95b083..fc73b366 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -1,6 +1,6 @@ This installation guide was created for Debian/Ubuntu and tested on it. Please read [`doc/install/requirements.md`](./requirements.md) for hardware and platform requirements. -This installation guide is recommended to set up a production server. If you want a development environment please use the [Vargrant virtual machine](https://github.com/gitlabhq/gitlab-vagrant-vm) since it makes it much easier to set up all the dependencies for integration testing. +This installation guide is recommended to set up a production server. If you want a development environment please use the [Vagrant virtual machine](https://github.com/gitlabhq/gitlab-vagrant-vm) since it makes it much easier to set up all the dependencies for integration testing. **Important Note:** The following steps have been known to work. From 850881a2ef2d89b7eb045f408bf9c8803094e6cf Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 25 Mar 2013 10:46:57 +0200 Subject: [PATCH 038/152] add admin ability to edit project settings from project area --- app/models/ability.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/ability.rb b/app/models/ability.rb index 41f71274..5b49104d 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -41,7 +41,7 @@ class Ability rules << project_guest_rules end - if project.owner == user + if project.owner == user || user.admin? rules << project_admin_rules end From 1fb99264a99e5fbe03b9ccef42ac8c4f07575d8c Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 25 Mar 2013 10:47:22 +0200 Subject: [PATCH 039/152] Use TransferContext for project --- app/contexts/projects/transfer_context.rb | 27 +++++++++++++++++++++++ app/views/projects/transfer.js.haml | 7 ++++++ 2 files changed, 34 insertions(+) create mode 100644 app/contexts/projects/transfer_context.rb create mode 100644 app/views/projects/transfer.js.haml diff --git a/app/contexts/projects/transfer_context.rb b/app/contexts/projects/transfer_context.rb new file mode 100644 index 00000000..aed396a5 --- /dev/null +++ b/app/contexts/projects/transfer_context.rb @@ -0,0 +1,27 @@ +module Projects + class TransferContext < BaseContext + def execute(role = :default) + namespace_id = params[:project].delete(:namespace_id) + allowed_transfer = can?(current_user, :change_namespace, project) || role == :admin + + if allowed_transfer && namespace_id.present? + if namespace_id == Namespace.global_id + if project.namespace.present? + # Transfer to global namespace from anyone + project.transfer(nil) + end + elsif namespace_id.to_i != project.namespace_id + # Transfer to someone namespace + namespace = Namespace.find(namespace_id) + project.transfer(namespace) + end + end + + rescue ProjectTransferService::TransferError => ex + project.reload + project.errors.add(:namespace_id, ex.message) + false + end + end +end + diff --git a/app/views/projects/transfer.js.haml b/app/views/projects/transfer.js.haml new file mode 100644 index 00000000..10b0de98 --- /dev/null +++ b/app/views/projects/transfer.js.haml @@ -0,0 +1,7 @@ +- if @project.errors[:namespace_id].present? + :plain + $("#tab-transfer .errors-holder").replaceWith(errorMessage('#{escape_javascript(@project.errors[:namespace_id].first)}')); + $("#tab-transfer .form-actions input").removeAttr('disabled').removeClass('disabled'); +- else + :plain + location.href = "#{edit_project_path(@project)}"; From ff35b37fd2df3b4bdcb9f1b7448d98df07237d08 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 25 Mar 2013 10:47:47 +0200 Subject: [PATCH 040/152] transfer also wiki repository when transfer a project --- app/services/project_transfer_service.rb | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/app/services/project_transfer_service.rb b/app/services/project_transfer_service.rb index 719e0d3d..88688af2 100644 --- a/app/services/project_transfer_service.rb +++ b/app/services/project_transfer_service.rb @@ -5,6 +5,8 @@ class ProjectTransferService include Gitlab::ShellAdapter + class TransferError < StandardError; end + attr_accessor :project def transfer(project, new_namespace) @@ -19,14 +21,18 @@ class ProjectTransferService project.namespace = new_namespace project.save! + # Move main repository unless gitlab_shell.mv_repository(old_path, new_path) raise TransferError.new('Cannot move project') end + # Move wiki repo also if present + if project.wikis.any? + gitlab_shell.mv_repository("#{old_path}.wiki", "#{new_path}.wiki") + end + true end - rescue => ex - raise Project::TransferError.new(ex.message) end end From e292d7c17b48182f7f8df20d93b92e8ba9e98ce6 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 25 Mar 2013 10:48:30 +0200 Subject: [PATCH 041/152] Make transfer action in project controller --- app/contexts/projects/update_context.rb | 18 +----------------- app/controllers/projects_controller.rb | 8 ++++---- app/models/project.rb | 2 -- app/views/projects/_form.html.haml | 3 ++- app/views/projects/update_failed.js.haml | 2 -- config/routes.rb | 4 ++++ 6 files changed, 11 insertions(+), 26 deletions(-) delete mode 100644 app/views/projects/update_failed.js.haml diff --git a/app/contexts/projects/update_context.rb b/app/contexts/projects/update_context.rb index e5d09b7d..40385fa6 100644 --- a/app/contexts/projects/update_context.rb +++ b/app/contexts/projects/update_context.rb @@ -1,24 +1,8 @@ module Projects class UpdateContext < BaseContext def execute(role = :default) - namespace_id = params[:project].delete(:namespace_id) + params[:project].delete(:namespace_id) params[:project].delete(:public) unless can?(current_user, :change_public_mode, project) - - allowed_transfer = can?(current_user, :change_namespace, project) || role == :admin - - if allowed_transfer && namespace_id.present? - if namespace_id == Namespace.global_id - if project.namespace.present? - # Transfer to global namespace from anyone - project.transfer(nil) - end - elsif namespace_id.to_i != project.namespace_id - # Transfer to someone namespace - namespace = Namespace.find(namespace_id) - project.transfer(namespace) - end - end - project.update_attributes(params[:project], as: role) end end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index f2718344..5b17e1ab 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -4,7 +4,7 @@ class ProjectsController < ProjectResourceController # Authorize before_filter :authorize_read_project!, except: [:index, :new, :create] - before_filter :authorize_admin_project!, only: [:edit, :update, :destroy] + before_filter :authorize_admin_project!, only: [:edit, :update, :destroy, :transfer] before_filter :require_non_empty_project, only: [:blob, :tree, :graph] layout 'application', only: [:new, :create] @@ -45,10 +45,10 @@ class ProjectsController < ProjectResourceController format.js end end + end - rescue Project::TransferError => ex - @error = ex - render :update_failed + def transfer + ::Projects::TransferContext.new(project, current_user, params).execute end def show diff --git a/app/models/project.rb b/app/models/project.rb index 23eb7f90..0bb1003a 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -26,8 +26,6 @@ class Project < ActiveRecord::Base include Gitlab::ShellAdapter extend Enumerize - class TransferError < StandardError; end - attr_accessible :name, :path, :description, :default_branch, :issues_tracker, :issues_enabled, :wall_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id, :wiki_enabled, :public, :import_url, as: [:default, :admin] diff --git a/app/views/projects/_form.html.haml b/app/views/projects/_form.html.haml index 6d547c94..01fb6a67 100644 --- a/app/views/projects/_form.html.haml +++ b/app/views/projects/_form.html.haml @@ -107,8 +107,9 @@ - if can?(current_user, :change_namespace, @project) .ui-box.ui-box-danger %h5.title Transfer project + .errors-holder .form-holder - = form_for(@project, remote: true, html: { class: 'transfer-project' }) do |f| + = form_for(@project, url: transfer_project_path(@project), remote: true, html: { class: 'transfer-project' }) do |f| .control-group = f.label :namespace_id do %span Namespace diff --git a/app/views/projects/update_failed.js.haml b/app/views/projects/update_failed.js.haml deleted file mode 100644 index a3ac5f40..00000000 --- a/app/views/projects/update_failed.js.haml +++ /dev/null @@ -1,2 +0,0 @@ -:plain - $(".save-project-loader").replaceWith(errorMessage('#{escape_javascript(@error.message)}')); diff --git a/config/routes.rb b/config/routes.rb index fafaef84..505538fc 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -167,6 +167,10 @@ Gitlab::Application.routes.draw do # Project Area # resources :projects, constraints: { id: /(?:[a-zA-Z.0-9_\-]+\/)?[a-zA-Z.0-9_\-]+/ }, except: [:new, :create, :index], path: "/" do + member do + put :transfer + end + resources :blob, only: [:show], constraints: {id: /.+/} resources :tree, only: [:show], constraints: {id: /.+/, format: /(html|js)/ } resources :edit_tree, only: [:show, :update], constraints: {id: /.+/}, path: 'edit' From d0df8a6ff80a25dc36157e8f412ed9d56afda4e5 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 25 Mar 2013 11:07:11 +0200 Subject: [PATCH 042/152] remove project edit from admin area. Redesigned project page in admin area --- app/controllers/admin/projects_controller.rb | 28 --- app/views/admin/projects/index.html.haml | 4 +- app/views/admin/projects/show.html.haml | 198 ++++++++----------- config/routes.rb | 6 +- 4 files changed, 81 insertions(+), 155 deletions(-) diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb index 8ae0bba9..bbb80cbb 100644 --- a/app/controllers/admin/projects_controller.rb +++ b/app/controllers/admin/projects_controller.rb @@ -19,34 +19,6 @@ class Admin::ProjectsController < Admin::ApplicationController @users = @users.all end - def edit - end - - def team_update - @project.team.add_users_ids(params[:user_ids], params[:project_access]) - - redirect_to [:admin, @project], notice: 'Project was successfully updated.' - end - - def update - project.creator = current_user unless project.creator - - status = ::Projects::UpdateContext.new(project, current_user, params).execute(:admin) - - if status - redirect_to [:admin, @project], notice: 'Project was successfully updated.' - else - render action: "edit" - end - end - - def destroy - @project.team.truncate - @project.destroy - - redirect_to admin_projects_path, notice: 'Project was successfully deleted.' - end - protected def project diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml index 15b27782..82d5fdcd 100644 --- a/app/views/admin/projects/index.html.haml +++ b/app/views/admin/projects/index.html.haml @@ -52,8 +52,8 @@ %i.icon-lock.cgreen = link_to project.name_with_namespace, [:admin, project] .pull-right - = link_to 'Edit', edit_admin_project_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small" - = link_to 'Destroy', [:admin, project], confirm: "REMOVE #{project.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove" + = link_to 'Edit', edit_project_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small" + = link_to 'Destroy', [project], confirm: "REMOVE #{project.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove" - if @projects.blank? %p.nothing_here_message 0 projects matches - else diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml index 65b92117..55247041 100644 --- a/app/views/admin/projects/show.html.haml +++ b/app/views/admin/projects/show.html.haml @@ -1,129 +1,87 @@ %h3.page_title Project: #{@project.name_with_namespace} - = link_to edit_admin_project_path(@project), class: "btn pull-right" do + = link_to edit_project_path(@project), class: "btn pull-right" do %i.icon-edit Edit +%hr +.row + .span6 + .ui-box + %h5.title + Project info: + %ul.well-list + %li + %span.light Name: + %strong= @project.name + %li + %span.light Namespace: + %strong + - if @project.namespace + = link_to @project.namespace.human_name, [:admin, @project.group || @project.owner] + - else + Global + %li + %span.light Owned by: + %strong + - if @project.owner + = link_to @project.owner_name, admin_user_path(@project.owner) + - else + (deleted) + %li + %span.light Created by: + %strong + = @project.creator.try(:name) || '(deleted)' -%br -%table.zebra-striped - %thead - %tr - %th Project - %th - %tr - %td - %b - Name: - %td - = @project.name - %tr - %td - %b - Namespace: - %td - - if @project.namespace - = @project.namespace.human_name - - else - Global - %tr - %td - %b - Owned by: - %td - - if @project.owner - = link_to @project.owner_name, admin_user_path(@project.owner) - - else - (deleted) - %tr - %td - %b - Created by: - %td - = @project.creator.try(:name) || '(deleted)' - %tr - %td - %b - Created at: - %td - = @project.created_at.stamp("March 1, 1999") - %tr - %td - %b - Smart HTTP: - %td - = link_to @project.http_url_to_repo - %tr - %td - %b - SSH: - %td - = link_to @project.ssh_url_to_repo - - if @project.public - %tr.bgred - %td - %b - Public Read-Only Code access: - %td - = check_box_tag 'public', nil, @project.public + %li + %span.light Created at: + %strong + = @project.created_at.stamp("March 1, 1999") -- if @repository - %table.zebra-striped - %thead - %tr - %th Repository - %th - %tr - %td - %b - FS Path: - %td - %code= @repository.path_to_repo - %tr - %td - %b - Last commit at: - %td - = last_commit(@project) + %li + %span.light http: + %strong + = link_to @project.http_url_to_repo + %li + %span.light ssh: + %strong + = link_to @project.ssh_url_to_repo + %li + %span.light fs: + %strong + = @repository.path_to_repo -%br -%h5 - Team - %small - (#{@project.users.count}) -%br -%table.zebra-striped.team_members - %thead - %tr - %th Name - %th Project Access - %th Repository Access - %th + %li + %span.light last commit: + %strong + - if @repository + = last_commit(@project) + - else + never - - @project.users.each do |tm| - %tr - %td - = link_to tm.name, admin_user_path(tm) - %td= @project.project_access_human(tm) - %td= link_to 'Edit Access', edit_admin_project_member_path(@project, tm), class: "btn btn-small" - %td= link_to 'Remove from team', admin_project_member_path(@project, tm), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove small" - -%br -%h5 Add new team member -%br -= form_tag team_update_admin_project_path(@project), class: "bulk_import", method: :put do - %table.zebra-striped - %thead - %tr - %th Users - %th Project Access: - - %tr - %td= select_tag :user_ids, options_from_collection_for_select(@users , :id, :name), multiple: true, data: {placeholder: 'Select users'}, class: 'chosen span5' - %td= select_tag :project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3"} - - %tr - %td= submit_tag 'Add', class: "btn btn-primary" - %td - Read more about project permissions - %strong= link_to "here", help_permissions_path, class: "vlink" + %li + %span.light access: + %strong + - if @project.public + %span.cblue + %i.icon-share + Public + - else + %span.cgreen + %i.icon-lock + Private + .span6 + .ui-box + %h5.title + Team + %small + (#{@project.users.count}) + = link_to project_team_index_path(@project), class: "btn btn-tiny" do + %i.icon-edit + Edit Team + %ul.well-list + - @project.users.each do |tm| + %li + %strong + = link_to tm.name, admin_user_path(tm) + %span.pull-right.light= @project.project_access_human(tm) diff --git a/config/routes.rb b/config/routes.rb index 505538fc..25eb75a1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -85,11 +85,7 @@ Gitlab::Application.routes.draw do resource :logs, only: [:show] resource :resque, controller: 'resque', only: [:show] - resources :projects, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ }, except: [:new, :create] do - member do - get :team - put :team_update - end + resources :projects, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ }, only: [:index, :show] do scope module: :projects, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ } do resources :members, only: [:edit, :update, :destroy] end From 017c19bbe4e9098e161b8cc0e866d644e7d3ae95 Mon Sep 17 00:00:00 2001 From: Koen Punt Date: Mon, 25 Mar 2013 12:00:57 +0100 Subject: [PATCH 043/152] Fixed type --- doc/install/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index 69d3b186..a0ff9a26 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -1,6 +1,6 @@ This installation guide was created for Debian/Ubuntu and tested on it. Please read [`doc/install/requirements.md`](./requirements.md) for hardware and platform requirements. -This installation guide is recommended to set up a production server. If you want a development environment please use the [Vargrant virtual machine](https://github.com/gitlabhq/gitlab-vagrant-vm) since it makes it much easier to set up all the dependencies for integration testing. +This installation guide is recommended to set up a production server. If you want a development environment please use the [Vagrant virtual machine](https://github.com/gitlabhq/gitlab-vagrant-vm) since it makes it much easier to set up all the dependencies for integration testing. **Important Note:** The following steps have been known to work. From c610347cc19e615d0fe87950f7e3d6887317ac55 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 25 Mar 2013 13:36:08 +0200 Subject: [PATCH 044/152] Removed not relevant tests for admin.projects --- app/views/admin/projects/show.html.haml | 2 +- features/steps/admin/admin_projects.rb | 2 -- spec/features/admin/admin_projects_spec.rb | 42 ---------------------- 3 files changed, 1 insertion(+), 45 deletions(-) diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml index 55247041..27c687bb 100644 --- a/app/views/admin/projects/show.html.haml +++ b/app/views/admin/projects/show.html.haml @@ -79,7 +79,7 @@ = link_to project_team_index_path(@project), class: "btn btn-tiny" do %i.icon-edit Edit Team - %ul.well-list + %ul.well-list.team_members - @project.users.each do |tm| %li %strong diff --git a/features/steps/admin/admin_projects.rb b/features/steps/admin/admin_projects.rb index dd6b4e98..b410b238 100644 --- a/features/steps/admin/admin_projects.rb +++ b/features/steps/admin/admin_projects.rb @@ -16,9 +16,7 @@ class AdminProjects < Spinach::FeatureSteps Then 'I should see project details' do project = Project.first current_path.should == admin_project_path(project) - page.should have_content(project.name_with_namespace) page.should have_content(project.creator.name) - page.should have_content('Add new team member') end end diff --git a/spec/features/admin/admin_projects_spec.rb b/spec/features/admin/admin_projects_spec.rb index c9ddf1f4..23370891 100644 --- a/spec/features/admin/admin_projects_spec.rb +++ b/spec/features/admin/admin_projects_spec.rb @@ -31,46 +31,4 @@ describe "Admin::Projects" do page.should have_content(@project.name) end end - - describe "GET /admin/projects/:id/edit" do - before do - visit admin_projects_path - click_link "edit_project_#{@project.id}" - end - - it "should have project edit page" do - page.should have_content("Edit project") - page.should have_button("Save Project") - end - - describe "Update project" do - before do - fill_in "project_name", with: "Big Bang" - click_button "Save Project" - @project.reload - end - - it "should show page with new data" do - page.should have_content("Big Bang") - end - - it "should change project entry" do - @project.name.should == "Big Bang" - end - end - end - - describe "Add new team member" do - before do - @new_user = create(:user) - visit admin_project_path(@project) - end - - it "should create new user" do - select @new_user.name, from: "user_ids" - expect { click_button "Add" }.to change { UsersProject.count }.by(1) - page.should have_content @new_user.name - current_path.should == admin_project_path(@project) - end - end end From 98bea4b1ff6e7f5fdc07d6712cc6e1fd2d1e53ea Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 25 Mar 2013 13:40:08 +0200 Subject: [PATCH 045/152] Updatev security tests since admin is a superuser now. Has access to any project --- spec/features/security/project_access_spec.rb | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/spec/features/security/project_access_spec.rb b/spec/features/security/project_access_spec.rb index b8984401..179ebffc 100644 --- a/spec/features/security/project_access_spec.rb +++ b/spec/features/security/project_access_spec.rb @@ -33,7 +33,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -44,7 +44,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -55,7 +55,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -66,7 +66,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -77,7 +77,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -88,7 +88,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -99,7 +99,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -114,7 +114,7 @@ describe "Application access" do it { @blob_path.should be_allowed_for master } it { @blob_path.should be_allowed_for reporter } - it { @blob_path.should be_denied_for :admin } + it { @blob_path.should be_allowed_for :admin } it { @blob_path.should be_denied_for guest } it { @blob_path.should be_denied_for :user } it { @blob_path.should be_denied_for :visitor } @@ -125,7 +125,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_denied_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -136,7 +136,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_denied_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -147,7 +147,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -158,7 +158,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -169,7 +169,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -180,7 +180,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -196,7 +196,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -212,7 +212,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } @@ -223,7 +223,7 @@ describe "Application access" do it { should be_allowed_for master } it { should be_allowed_for reporter } - it { should be_denied_for :admin } + it { should be_allowed_for :admin } it { should be_denied_for guest } it { should be_denied_for :user } it { should be_denied_for :visitor } From d6ac38133c57336fa555532c1e85d7ad99499def Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 25 Mar 2013 14:58:43 +0200 Subject: [PATCH 046/152] Admin.projects: remove views and route specs --- app/views/admin/projects/_form.html.haml | 86 ------------------------ app/views/admin/projects/edit.html.haml | 3 - app/views/admin/projects/team.html.haml | 0 spec/routing/admin_routing_spec.rb | 20 ------ 4 files changed, 109 deletions(-) delete mode 100644 app/views/admin/projects/_form.html.haml delete mode 100644 app/views/admin/projects/edit.html.haml delete mode 100644 app/views/admin/projects/team.html.haml diff --git a/app/views/admin/projects/_form.html.haml b/app/views/admin/projects/_form.html.haml deleted file mode 100644 index 29b90bdd..00000000 --- a/app/views/admin/projects/_form.html.haml +++ /dev/null @@ -1,86 +0,0 @@ -= form_for [:admin, project] do |f| - -if project.errors.any? - .alert.alert-error - %ul - - project.errors.full_messages.each do |msg| - %li= msg - - .clearfix.project_name_holder - = f.label :name do - Project name is - .input - = f.text_field :name, placeholder: "Example Project", class: "xxlarge" - - - if project.repo_exists? - %fieldset.adv_settings - %legend Advanced settings: - .clearfix - = f.label :path do - Path - .input - = text_field_tag :ppath, @project.repository.path_to_repo, class: "xlarge", disabled: true - - .clearfix - = f.label :default_branch, "Default Branch" - .input= f.select(:default_branch, @project.repository.heads.map(&:name), {}, style: "width:210px;") - - %fieldset.adv_settings - %legend Features: - - .clearfix - = f.label :issues_enabled, "Issues" - .input= f.check_box :issues_enabled - - - if Project.issues_tracker.values.count > 1 - .clearfix - = f.label :issues_tracker, "Issues tracker", class: 'control-label' - .input= f.select(:issues_tracker, Project.issues_tracker.values, {}, { disabled: !@project.issues_enabled }) - - .clearfix - = f.label :issues_tracker_id, "Project name or id in issues tracker", class: 'control-label' - .input= f.text_field :issues_tracker_id, class: "xxlarge", disabled: !@project.can_have_issues_tracker_id? - - .clearfix - = f.label :merge_requests_enabled, "Merge Requests" - .input= f.check_box :merge_requests_enabled - - .clearfix - = f.label :wall_enabled, "Wall" - .input= f.check_box :wall_enabled - - .clearfix - = f.label :wiki_enabled, "Wiki" - .input= f.check_box :wiki_enabled - - %fieldset.features - %legend Public mode: - .clearfix - = f.label :public do - %span Allow public http clone - .input= f.check_box :public - - %fieldset.features - %legend Transfer: - .control-group - = f.label :namespace_id do - %span Namespace - .controls - = f.select :namespace_id, namespaces_options(@project.namespace_id, :all), {}, {class: 'chosen'} - %br - %ul.prepend-top-10.cred - %li Be careful. Changing project namespace can have unintended side effects - %li You can transfer project only to namespaces you can manage - %li You will need to update your local repositories to point to the new location. - - - .actions - = f.submit 'Save Project', class: "btn btn-save" - = link_to 'Cancel', admin_projects_path, class: "btn btn-cancel" - - - -:javascript - $(function(){ - new Projects(); - }) - diff --git a/app/views/admin/projects/edit.html.haml b/app/views/admin/projects/edit.html.haml deleted file mode 100644 index 7b59a0cc..00000000 --- a/app/views/admin/projects/edit.html.haml +++ /dev/null @@ -1,3 +0,0 @@ -%h3.page_title #{@project.name} → Edit project -%hr -= render 'form', project: @project diff --git a/app/views/admin/projects/team.html.haml b/app/views/admin/projects/team.html.haml deleted file mode 100644 index e69de29b..00000000 diff --git a/spec/routing/admin_routing_spec.rb b/spec/routing/admin_routing_spec.rb index 3e0e4bb3..b6509fcb 100644 --- a/spec/routing/admin_routing_spec.rb +++ b/spec/routing/admin_routing_spec.rb @@ -66,33 +66,13 @@ end # PUT /admin/projects/:id(.:format) admin/projects#update {:id=>/[^\/]+/} # DELETE /admin/projects/:id(.:format) admin/projects#destroy {:id=>/[^\/]+/} describe Admin::ProjectsController, "routing" do - it "to #team" do - get("/admin/projects/gitlab/team").should route_to('admin/projects#team', id: 'gitlab') - end - - it "to #team_update" do - put("/admin/projects/gitlab/team_update").should route_to('admin/projects#team_update', id: 'gitlab') - end - it "to #index" do get("/admin/projects").should route_to('admin/projects#index') end - it "to #edit" do - get("/admin/projects/gitlab/edit").should route_to('admin/projects#edit', id: 'gitlab') - end - it "to #show" do get("/admin/projects/gitlab").should route_to('admin/projects#show', id: 'gitlab') end - - it "to #update" do - put("/admin/projects/gitlab").should route_to('admin/projects#update', id: 'gitlab') - end - - it "to #destroy" do - delete("/admin/projects/gitlab").should route_to('admin/projects#destroy', id: 'gitlab') - end end # edit_admin_project_member GET /admin/projects/:project_id/members/:id/edit(.:format) admin/projects/members#edit {:id=>/[^\/]+/, :project_id=>/[^\/]+/} From 53e54ddf8a107f02fe870159663d9763c48a3c54 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 25 Mar 2013 15:19:06 +0200 Subject: [PATCH 047/152] require gitlab-shell v1.2.0 now --- lib/tasks/gitlab/check.rake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index 855227fb..ea97d181 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -637,8 +637,8 @@ namespace :gitlab do def check_gitlab_shell print "GitLab Shell version? ... " - if gitlab_shell_version.strip == '1.1.0' - puts 'OK (1.1.0)'.green + if gitlab_shell_version.strip == '1.2.0' + puts 'OK (1.2.0)'.green else puts 'FAIL. Please update gitlab-shell to v1.1.0'.red end From 6752968bb5d4a3c09fdf15996ad0055d1b1fa8b0 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 25 Mar 2013 15:27:09 +0200 Subject: [PATCH 048/152] Updated changelog with transfer & security changes --- CHANGELOG | 6 ++++++ VERSION | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 2641875d..1b099474 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,9 @@ +v 5.1.0 + - Corrected project transfer rollback when repository cannot be moved + - Move both repo and wiki when project transfer requrested + - Admin area: project editing was removed from admin namespace + - Access: admin user has now access to any project. + v 5.0.0 - Replaced gitolite with gitlab-shell - Removed gitolite-related libraries diff --git a/VERSION b/VERSION index 0062ac97..52df2a23 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -5.0.0 +5.1.0pre From 1496c01521b46265660de72209fd81b585639bcf Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 25 Mar 2013 15:52:54 +0200 Subject: [PATCH 049/152] try to move wiki if it does not exist --- app/services/project_transfer_service.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/services/project_transfer_service.rb b/app/services/project_transfer_service.rb index 88688af2..3b8c4847 100644 --- a/app/services/project_transfer_service.rb +++ b/app/services/project_transfer_service.rb @@ -27,9 +27,7 @@ class ProjectTransferService end # Move wiki repo also if present - if project.wikis.any? - gitlab_shell.mv_repository("#{old_path}.wiki", "#{new_path}.wiki") - end + gitlab_shell.mv_repository("#{old_path}.wiki", "#{new_path}.wiki") true end From 9d92433a7c83432657faf4c02839bba1ba6f22ac Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 25 Mar 2013 16:10:14 +0200 Subject: [PATCH 050/152] login with both email or username --- app/models/user.rb | 17 +++++++++++++++++ app/views/devise/sessions/new.html.haml | 16 ++++++++-------- config/initializers/devise.rb | 2 +- spec/support/login_helpers.rb | 2 +- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/app/models/user.rb b/app/models/user.rb index c73353bf..16d91675 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -46,6 +46,13 @@ class User < ActiveRecord::Base attr_accessor :force_random_password + # Virtual attribute for authenticating by either username or email + attr_accessor :login + + # Add login to attr_accessible + attr_accessible :login + + # # Relations # @@ -140,6 +147,16 @@ class User < ActiveRecord::Base # Class methods # class << self + # Devise method overriden to allow sing in with email or username + def find_for_database_authentication(warden_conditions) + conditions = warden_conditions.dup + if login = conditions.delete(:login) + where(conditions).where(["lower(username) = :value OR lower(email) = :value", { value: login.downcase }]).first + else + where(conditions).first + end + end + def filter filter_name case filter_name when "admins"; self.admins diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml index d904e701..5e93ab18 100644 --- a/app/views/devise/sessions/new.html.haml +++ b/app/views/devise/sessions/new.html.haml @@ -1,19 +1,19 @@ - if ldap_enable? - = render :partial => 'devise/sessions/new_ldap' + = render partial: 'devise/sessions/new_ldap' - else - = form_for(resource, :as => resource_name, :url => session_path(resource_name), :html => { :class => "login-box" }) do |f| - = image_tag "login-logo.png", :width => "304", :height => "66", :class => "login-logo", :alt => "Login Logo" - = f.email_field :email, :class => "text top", :placeholder => "Email", :autofocus => "autofocus" - = f.password_field :password, :class => "text bottom", :placeholder => "Password" + = form_for(resource, as: resource_name, url: session_path(resource_name), html: { class: "login-box" }) do |f| + = image_tag "login-logo.png", width: "304", height: "66", class: "login-logo", alt: "Login Logo" + = f.text_field :login, class: "text top", placeholder: "Username or Email", autofocus: "autofocus" + = f.password_field :password, class: "text bottom", placeholder: "Password" - if devise_mapping.rememberable? .clearfix.inputs-list - %label.checkbox.remember_me{:for => "user_remember_me"} + %label.checkbox.remember_me{for: "user_remember_me"} = f.check_box :remember_me %span Remember me %br/ - = f.submit "Sign in", :class => "btn-create btn" + = f.submit "Sign in", class: "btn-create btn" .pull-right - = link_to "Forgot your password?", new_password_path(resource_name), :class => "btn" + = link_to "Forgot your password?", new_password_path(resource_name), class: "btn" %br/ - if Gitlab.config.gitlab.signup_enabled %hr/ diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 9c397633..5714407f 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -23,7 +23,7 @@ Devise.setup do |config| # session. If you need permissions, you should implement that in a before filter. # You can also supply a hash where the value is a boolean determining whether # or not authentication should be aborted when the value is not present. - # config.authentication_keys = [ :email ] + config.authentication_keys = [ :login ] # Configure parameters from the request object used for authentication. Each entry # given should be a request method and it will automatically be passed to the diff --git a/spec/support/login_helpers.rb b/spec/support/login_helpers.rb index 4579c971..d423ccf8 100644 --- a/spec/support/login_helpers.rb +++ b/spec/support/login_helpers.rb @@ -12,7 +12,7 @@ module LoginHelpers # user - User instance to login with def login_with(user) visit new_user_session_path - fill_in "user_email", with: user.email + fill_in "user_login", with: user.email fill_in "user_password", with: "123456" click_button "Sign in" end From 8c9123943f1fbee5b72d97031a5e30ec7dd96db6 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 25 Mar 2013 16:12:12 +0200 Subject: [PATCH 051/152] Update changelog --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 1b099474..872661d4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,5 @@ v 5.1.0 + - You can login with email or username now - Corrected project transfer rollback when repository cannot be moved - Move both repo and wiki when project transfer requrested - Admin area: project editing was removed from admin namespace From 7a4f70d79b9d78d3417b16bdaf0dc67d9dcdd4e9 Mon Sep 17 00:00:00 2001 From: Saito Date: Tue, 26 Mar 2013 01:12:29 +0800 Subject: [PATCH 052/152] bump version of grit_ext --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index d0280732..fdc6a41f 100644 --- a/Gemfile +++ b/Gemfile @@ -23,7 +23,7 @@ gem 'omniauth-github' # Extracting information from a git repository gem "gitlab-grit", '~> 1.0.0', require: 'grit' -gem 'grit_ext', '~> 0.6.2' +gem 'grit_ext', '~> 0.8.1' # Ruby/Rack Git Smart-HTTP Server Handler gem 'gitlab-grack', '~> 1.0.0', require: 'grack' diff --git a/Gemfile.lock b/Gemfile.lock index 51d121b9..4e86bbcc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -198,7 +198,7 @@ GEM diff-lcs (~> 1.1) mime-types (~> 1.15) posix-spawn (~> 0.3.6) - grit_ext (0.6.2) + grit_ext (0.8.1) charlock_holmes (~> 0.6.9) growl (1.0.3) guard (1.5.4) @@ -530,7 +530,7 @@ DEPENDENCIES gon grape (~> 0.3.1) grape-entity (~> 0.2.0) - grit_ext (~> 0.6.2) + grit_ext (~> 0.8.1) growl guard-rspec guard-spinach From 62ef763a80271b58e0c0f6e51891828f22689daa Mon Sep 17 00:00:00 2001 From: Sato Hiroyuki Date: Tue, 26 Mar 2013 09:46:10 +0900 Subject: [PATCH 053/152] Refector: clean up code. --- app/assets/javascripts/branch-graph.js.coffee | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/app/assets/javascripts/branch-graph.js.coffee b/app/assets/javascripts/branch-graph.js.coffee index 796bebe2..2a668de2 100644 --- a/app/assets/javascripts/branch-graph.js.coffee +++ b/app/assets/javascripts/branch-graph.js.coffee @@ -131,7 +131,7 @@ class BranchGraph shortrefs = refs # Truncate if longer than 15 chars shortrefs = shortrefs.substr(0, 15) + "…" if shortrefs.length > 17 - text = r.text(x + 8, y, shortrefs).attr( + text = r.text(x + 4, y, shortrefs).attr( "text-anchor": "start" font: "10px Monaco, monospace" fill: "#FFF" @@ -139,7 +139,7 @@ class BranchGraph ) textbox = text.getBBox() # Create rectangle based on the size of the textbox - rect = r.rect(x, y - 7, textbox.width + 15, textbox.height + 5, 4).attr( + rect = r.rect(x, y - 7, textbox.width + 5, textbox.height + 5, 4).attr( fill: "#000" "fill-opacity": .5 stroke: "none" @@ -206,22 +206,19 @@ class BranchGraph # Build line shape if parent[1] is commit.space - d1 = [0, 5] - d2 = [0, 10] - arrow = "l-2,5,4,0,-2,-5" + offset = [0, 5] + arrow = "l-2,5,4,0,-2,-5,0,5" else if parent[1] < commit.space - d1 = [3, 3] - d2 = [7, 5] - arrow = "l5,0,-2,4,-3,-4" + offset = [3, 3] + arrow = "l5,0,-2,4,-3,-4,4,2" else - d1 = [-3, 3] - d2 = [-7, 5] - arrow = "l-5,0,2,4,3,-4" + offset = [-3, 3] + arrow = "l-5,0,2,4,3,-4,-4,2" # Start point - route = ["M", x + d1[0], y + d1[1]] + route = ["M", x + offset[0], y + offset[1]] # Add arrow if not first parent if i > 0 @@ -230,7 +227,6 @@ class BranchGraph # Circumvent if overlap if commit.space isnt parentCommit.space or commit.space isnt parent[1] route.push( - "L", x + d2[0], y + d2[1], "L", parentX2, y + 10, "L", parentX2, parentY - 5, ) From b49c1cb161e4d97c4ee33ae45a48e948f1097e60 Mon Sep 17 00:00:00 2001 From: Sato Hiroyuki Date: Tue, 26 Mar 2013 09:51:39 +0900 Subject: [PATCH 054/152] Display note count on network graph. --- app/helpers/graph_helper.rb | 11 +++++++++-- app/views/graph/show.json.erb | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/app/helpers/graph_helper.rb b/app/helpers/graph_helper.rb index 36933015..ca7d823a 100644 --- a/app/helpers/graph_helper.rb +++ b/app/helpers/graph_helper.rb @@ -1,6 +1,13 @@ module GraphHelper - def join_with_space(ary) - ary.collect{|r|r.name}.join(" ") unless ary.nil? + def get_refs(commit) + refs = "" + refs += commit.refs.collect{|r|r.name}.join(" ") if commit.refs + + # append note count + notes = @project.notes.for_commit_id(commit.id) + refs += "[#{notes.count}]" if notes.any? + + refs end def parents_zip_spaces(parents, parent_spaces) diff --git a/app/views/graph/show.json.erb b/app/views/graph/show.json.erb index d0a0709a..529d5849 100644 --- a/app/views/graph/show.json.erb +++ b/app/views/graph/show.json.erb @@ -13,7 +13,7 @@ }, time: c.time, space: c.spaces.first, - refs: join_with_space(c.refs), + refs: get_refs(c), id: c.sha, date: c.date, message: c.message, From 33e236c63124e5c59dba5979d641ba174f4a1479 Mon Sep 17 00:00:00 2001 From: Sato Hiroyuki Date: Tue, 26 Mar 2013 14:42:08 +0900 Subject: [PATCH 055/152] Fix RoutingError when changing username to non ascii char. --- app/controllers/admin/users_controller.rb | 2 ++ features/admin/users.feature | 8 ++++++++ features/steps/admin/admin_users.rb | 23 +++++++++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 43e6f099..20cb13e7 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -84,6 +84,8 @@ class Admin::UsersController < Admin::ApplicationController format.html { redirect_to [:admin, admin_user], notice: 'User was successfully updated.' } format.json { head :ok } else + # restore username to keep form action url. + admin_user.username = params[:id] format.html { render action: "edit" } format.json { render json: admin_user.errors, status: :unprocessable_entity } end diff --git a/features/admin/users.feature b/features/admin/users.feature index 03ac86a3..4c951df9 100644 --- a/features/admin/users.feature +++ b/features/admin/users.feature @@ -6,3 +6,11 @@ Feature: Admin Users Scenario: On Admin Users Given I visit admin users page Then I should see all users + + Scenario: Edit user and change username to non ascii char + When I visit admin users page + And Click edit + And Input non ascii char in username + And Click save + Then See username error message + And Not chenged form action url diff --git a/features/steps/admin/admin_users.rb b/features/steps/admin/admin_users.rb index 1828ae70..61b3ed91 100644 --- a/features/steps/admin/admin_users.rb +++ b/features/steps/admin/admin_users.rb @@ -8,4 +8,27 @@ class AdminUsers < Spinach::FeatureSteps page.should have_content user.name end end + + And 'Click edit' do + @user = User.first + find("#edit_user_#{@user.id}").click + end + + And 'Input non ascii char in username' do + fill_in 'user_username', with: "\u3042\u3044" + end + + And 'Click save' do + click_button("Save") + end + + Then 'See username error message' do + within "#error_explanation" do + page.should have_content "Username" + end + end + + And 'Not chenged form action url' do + page.should have_selector %(form[action="/admin/users/#{@user.username}"]) + end end From 242f6aa218da6385b08d28705eb42297d899c089 Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Tue, 26 Mar 2013 12:27:34 +0400 Subject: [PATCH 056/152] New issue button was not follows to external tracker if it is selected. fixed #3386 --- app/helpers/issues_helper.rb | 12 ++++++++++ app/views/projects/_clone_panel.html.haml | 2 +- config/gitlab.yml.example | 8 +++++++ spec/helpers/issues_helper_spec.rb | 27 +++++++++++++++++++++++ 4 files changed, 48 insertions(+), 1 deletion(-) diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index 54385117..afd08bd5 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -54,6 +54,18 @@ module IssuesHelper end end + def url_for_new_issue + return "" if @project.nil? + + if @project.used_default_issues_tracker? + url = new_project_issue_path project_id: @project + else + url = Settings[:issues_tracker][@project.issues_tracker]["new_issue_url"] + url.gsub(':project_id', @project.id.to_s) + .gsub(':issues_tracker_id', @project.issues_tracker_id.to_s) + end + end + def url_for_issue(issue_id) return "" if @project.nil? diff --git a/app/views/projects/_clone_panel.html.haml b/app/views/projects/_clone_panel.html.haml index e52df19b..9a2be429 100644 --- a/app/views/projects/_clone_panel.html.haml +++ b/app/views/projects/_clone_panel.html.haml @@ -13,5 +13,5 @@ = link_to new_project_merge_request_path(@project), title: "New Merge Request", class: "btn-small btn grouped" do Merge Request - if @project.issues_enabled && can?(current_user, :write_issue, @project) - = link_to new_project_issue_path(@project), title: "New Issue", class: "btn-small btn grouped" do + = link_to url_for_new_issue, title: "New Issue", class: "btn-small btn grouped" do Issue diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index a8704719..90d04b39 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -46,12 +46,19 @@ production: &base # ## :project_id - GitLab project identifier # ## :issues_tracker_id - Project Name or Id in external issue tracker # project_url: "http://redmine.sample/projects/:issues_tracker_id" + # # ## If not nil, links from /#\d/ entities from commit messages will replaced with this # ## Use placeholders: # ## :project_id - GitLab project identifier # ## :issues_tracker_id - Project Name or Id in external issue tracker # ## :id - Issue id (from commit messages) # issues_url: "http://redmine.sample/issues/:id" + # + # ## If not nil, linkis to creating new issues will be replaced with this + # ## Use placeholders: + # ## :project_id - GitLab project identifier + # ## :issues_tracker_id - Project Name or Id in external issue tracker + # new_issue_url: "http://redmine.sample/projects/:issues_tracker_id/issues/new" ## Gravatar gravatar: @@ -152,6 +159,7 @@ test: redmine: project_url: "http://redmine/projects/:issues_tracker_id" issues_url: "http://redmine/:project_id/:issues_tracker_id/:id" + new_issue_url: "http://redmine/projects/:issues_tracker_id/insues/new" staging: <<: *base diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb index c9eb6591..a1f23073 100644 --- a/spec/helpers/issues_helper_spec.rb +++ b/spec/helpers/issues_helper_spec.rb @@ -76,4 +76,31 @@ describe IssuesHelper do url_for_issue(issue.id).should eq "" end end + + describe :url_for_new_issue do + let(:issues_url) { Gitlab.config.issues_tracker.redmine.new_issue_url} + let(:ext_expected) do + issues_url.gsub(':project_id', ext_project.id.to_s) + .gsub(':issues_tracker_id', ext_project.issues_tracker_id.to_s) + end + let(:int_expected) { new_project_issue_path(project) } + + it "should return internal path if used internal tracker" do + @project = project + url_for_new_issue.should match(int_expected) + end + + it "should return path to external tracker" do + @project = ext_project + + url_for_new_issue.should match(ext_expected) + end + + it "should return empty string if project nil" do + @project = nil + + url_for_new_issue.should eq "" + end + end + end From ec1a37875d2be29835d0ac165db22a19ca269e38 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Sat, 23 Mar 2013 15:56:29 +0100 Subject: [PATCH 057/152] Added memory requirements based on https://news.ycombinator.com/item?id=5423851 --- doc/install/requirements.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/install/requirements.md b/doc/install/requirements.md index ec5b013c..d71b8f54 100644 --- a/doc/install/requirements.md +++ b/doc/install/requirements.md @@ -54,3 +54,9 @@ some work on your part. If you have troubles installing GitLab following the official installation guide or want to share your experience installing GitLab on a not officially supported platform, please follow the the contribution guide (see CONTRIBUTING.md). + + + +# Memory requirements + +To run GitLab without any changes you need 1GB of memory. You can use it with 512MB of memory but you need to setup unicorn to use only 1 worker and you need at least 200MB of swap. On a server with 1.5GB of memory you are able to support 1000+ users. From 77c802a4fe2ff598d6ce30bc6c042c5640d6922f Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Sat, 23 Mar 2013 21:34:45 +0100 Subject: [PATCH 058/152] Combine it with the memory requirements that where already there. --- doc/install/requirements.md | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/doc/install/requirements.md b/doc/install/requirements.md index d71b8f54..34475f20 100644 --- a/doc/install/requirements.md +++ b/doc/install/requirements.md @@ -1,11 +1,13 @@ -# Hardware +# Memory -We recommend you to run GitLab on a server with at least 1GB RAM. +We recommend you to run GitLab on a server with at least 1GB of RAM memory. You can use it with 512MB of memory but you need to setup unicorn to use only 1 worker and you need at least 200MB of swap. On a server with 1.5GB of memory you are able to support 1000+ users. + + +# Hard disk capacity The necessary hard disk space largely depends on the size of the repos you want -to use GitLab with. But as a *rule of thumb* you should have at least as much -free space as your all repos combined take up. - +to store in GitLab. But as a *rule of thumb* you should have at least twice as much +free space as your all repos combined take up. Apart from a local hard drive you can also mount a volume that supports the network file system (NFS) protocol. This volume mich be located on a file server, a network attached storage (NAS) device, a storage area network (SAN) or on an Amazon Web Services (AWS) Elastic Block Store (EBS) volume. # Operating Systems @@ -54,9 +56,3 @@ some work on your part. If you have troubles installing GitLab following the official installation guide or want to share your experience installing GitLab on a not officially supported platform, please follow the the contribution guide (see CONTRIBUTING.md). - - - -# Memory requirements - -To run GitLab without any changes you need 1GB of memory. You can use it with 512MB of memory but you need to setup unicorn to use only 1 worker and you need at least 200MB of swap. On a server with 1.5GB of memory you are able to support 1000+ users. From 7e93aaa6e69dc89aacc1b55618c22344928c1be7 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Sat, 23 Mar 2013 21:38:51 +0100 Subject: [PATCH 059/152] Corrected mistake, added hint for windows users. --- doc/install/requirements.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/install/requirements.md b/doc/install/requirements.md index 34475f20..1628a443 100644 --- a/doc/install/requirements.md +++ b/doc/install/requirements.md @@ -7,7 +7,7 @@ We recommend you to run GitLab on a server with at least 1GB of RAM memory. You The necessary hard disk space largely depends on the size of the repos you want to store in GitLab. But as a *rule of thumb* you should have at least twice as much -free space as your all repos combined take up. Apart from a local hard drive you can also mount a volume that supports the network file system (NFS) protocol. This volume mich be located on a file server, a network attached storage (NAS) device, a storage area network (SAN) or on an Amazon Web Services (AWS) Elastic Block Store (EBS) volume. +free space as your all repos combined take up. Apart from a local hard drive you can also mount a volume that supports the network file system (NFS) protocol. This volume might be located on a file server, a network attached storage (NAS) device, a storage area network (SAN) or on an Amazon Web Services (AWS) Elastic Block Store (EBS) volume. # Operating Systems @@ -38,7 +38,7 @@ systems. This means you may get it to work on systems running FreeBSD or OS X. ## Windows GitLab does **not** run on Windows and we have no plans of supporting it in the -near future. +near future. Please consider using a virtual machine to run GitLab. From 83d3f7e052a93a90366127211e0c700582018584 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Sun, 24 Mar 2013 11:02:39 +0100 Subject: [PATCH 060/152] Better header and detail why you need two times the storage. Also moving memory and storage to the bottom, OS is more important. --- doc/install/requirements.md | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/doc/install/requirements.md b/doc/install/requirements.md index 1628a443..d1431c7e 100644 --- a/doc/install/requirements.md +++ b/doc/install/requirements.md @@ -1,15 +1,3 @@ -# Memory - -We recommend you to run GitLab on a server with at least 1GB of RAM memory. You can use it with 512MB of memory but you need to setup unicorn to use only 1 worker and you need at least 200MB of swap. On a server with 1.5GB of memory you are able to support 1000+ users. - - -# Hard disk capacity - -The necessary hard disk space largely depends on the size of the repos you want -to store in GitLab. But as a *rule of thumb* you should have at least twice as much -free space as your all repos combined take up. Apart from a local hard drive you can also mount a volume that supports the network file system (NFS) protocol. This volume might be located on a file server, a network attached storage (NAS) device, a storage area network (SAN) or on an Amazon Web Services (AWS) Elastic Block Store (EBS) volume. - - # Operating Systems ## Linux @@ -41,7 +29,6 @@ GitLab does **not** run on Windows and we have no plans of supporting it in the near future. Please consider using a virtual machine to run GitLab. - # Rubies GitLab requires Ruby (MRI) 1.9.3 and several Gems with native components. @@ -50,6 +37,17 @@ While it is generally possible to use other Rubies (like some work on your part. +# Memory + +We recommend you to run GitLab on a server with at least 1GB of RAM memory. You can use it with 512MB of memory but you need to setup unicorn to use only 1 worker and you need at least 200MB of swap. On a server with 1.5GB of memory you are able to support 1000+ users. + + +# Storage + +The necessary hard disk space largely depends on the size of the repos you want +to store in GitLab. But as a *rule of thumb* you should have at least twice as much +free space as your all repos combined take up. You need twice the storage because [GitLab satellites](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/structure.md) contain an extra copy of each repo. Apart from a local hard drive you can also mount a volume that supports the network file system (NFS) protocol. This volume might be located on a file server, a network attached storage (NAS) device, a storage area network (SAN) or on an Amazon Web Services (AWS) Elastic Block Store (EBS) volume. + # Installation troubles and reporting success or failure From f7e630c4528d0561466ede42d5e4820aa8b4d267 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Sun, 24 Mar 2013 22:23:28 +0100 Subject: [PATCH 061/152] Updating based on Dmitriy his comments. --- doc/install/requirements.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/doc/install/requirements.md b/doc/install/requirements.md index d1431c7e..9209fad5 100644 --- a/doc/install/requirements.md +++ b/doc/install/requirements.md @@ -37,17 +37,24 @@ While it is generally possible to use other Rubies (like some work on your part. -# Memory +# Hardware requirements -We recommend you to run GitLab on a server with at least 1GB of RAM memory. You can use it with 512MB of memory but you need to setup unicorn to use only 1 worker and you need at least 200MB of swap. On a server with 1.5GB of memory you are able to support 1000+ users. +## CPU +We recommend a processor with **4 cores**. At a minimum you need a processor with 2 cores to responsively run an unmodified installation. -# Storage +## Memory -The necessary hard disk space largely depends on the size of the repos you want +We recommend you to run GitLab on a server with at least **1GB of RAM** memory. You can use it with 512MB of memory but you need to setup unicorn to use only 1 worker and you need at least 200MB of swap. The minimal requirement for an unmodified installation is 768MB. With 1.5GB of memory you should be able to support 1000+ users. + +## Storage + +The necessary hard drive space largely depends on the size of the repos you want to store in GitLab. But as a *rule of thumb* you should have at least twice as much free space as your all repos combined take up. You need twice the storage because [GitLab satellites](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/structure.md) contain an extra copy of each repo. Apart from a local hard drive you can also mount a volume that supports the network file system (NFS) protocol. This volume might be located on a file server, a network attached storage (NAS) device, a storage area network (SAN) or on an Amazon Web Services (AWS) Elastic Block Store (EBS) volume. +If you have enough RAM memory and a recent CPU the speed of GitLab is mainly limited by hard drive seek times. Having a fast drive (7200 RPM and up) or a solid state drive (SSD) will improve the responsiveness of GitLab. + # Installation troubles and reporting success or failure From 448152ab944aa1c74d01d0717f10267a978c1c7c Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 26 Mar 2013 09:47:40 +0200 Subject: [PATCH 062/152] Use NotificationService for observers pt1 --- app/observers/issue_observer.rb | 24 ++++++++---------------- app/observers/key_observer.rb | 2 +- app/observers/note_observer.rb | 4 ++++ 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/app/observers/issue_observer.rb b/app/observers/issue_observer.rb index 29e24040..7e8e9ccd 100644 --- a/app/observers/issue_observer.rb +++ b/app/observers/issue_observer.rb @@ -2,41 +2,33 @@ class IssueObserver < ActiveRecord::Observer cattr_accessor :current_user def after_create(issue) - if issue.assignee && issue.assignee != current_user - Notify.delay.new_issue_email(issue.id) - end + notification.new_issue(issue, current_user) end def after_close(issue, transition) - send_reassigned_email(issue) if issue.is_being_reassigned? + notification.close_issue(issue, current_user) create_note(issue) end def after_reopen(issue, transition) - send_reassigned_email(issue) if issue.is_being_reassigned? - create_note(issue) end def after_update(issue) - send_reassigned_email(issue) if issue.is_being_reassigned? + if issue.is_being_reassigned? + notification.reassigned_issue(issue, current_user) + end end protected + # Create issue note with service comment like 'Status changed to closed' def create_note(issue) Note.create_status_change_note(issue, current_user, issue.state) - [issue.author, issue.assignee].compact.uniq.each do |recipient| - Notify.delay.issue_status_changed_email(recipient.id, issue.id, issue.state, current_user.id) - end end - def send_reassigned_email(issue) - recipient_ids = [issue.assignee_id, issue.assignee_id_was].keep_if {|id| id && id != current_user.id } - - recipient_ids.each do |recipient_id| - Notify.delay.reassigned_issue_email(recipient_id, issue.id, issue.assignee_id_was) - end + def notification + NotificationService.new end end diff --git a/app/observers/key_observer.rb b/app/observers/key_observer.rb index 0bc71a66..2a69b876 100644 --- a/app/observers/key_observer.rb +++ b/app/observers/key_observer.rb @@ -9,7 +9,7 @@ class KeyObserver < ActiveRecord::Observer ) # Notify about ssh key being added - Notify.delay.new_ssh_key_email(key.id) if key.user + NotificationService.new.new_key(key) end def after_destroy(key) diff --git a/app/observers/note_observer.rb b/app/observers/note_observer.rb index 0f820a26..1c3c1ad3 100644 --- a/app/observers/note_observer.rb +++ b/app/observers/note_observer.rb @@ -35,4 +35,8 @@ class NoteObserver < ActiveRecord::Observer def team_without_note_author(note) note.project.users.reject { |u| u.id == note.author.id } end + + def notification + NotificationService.new + end end From cf6d4dc10c8d6488153c73a3586d2d3477d735fc Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 26 Mar 2013 09:48:13 +0200 Subject: [PATCH 063/152] NotificationService for resolving email notification logic --- app/services/notification_service.rb | 51 ++++++++++++++++++++++ spec/services/notification_service_spec.rb | 47 ++++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 app/services/notification_service.rb create mode 100644 spec/services/notification_service_spec.rb diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb new file mode 100644 index 00000000..f20f3a44 --- /dev/null +++ b/app/services/notification_service.rb @@ -0,0 +1,51 @@ +# NotificationService class +# +# Used for notifing users with emails about different events +# +# Ex. +# NotificationService.new.new_issue(issue, current_user) +# +class NotificationService + # Always notify user about ssh key added + # only if ssh key is not deploy key + def new_key(key) + if key.user + Notify.delay.new_ssh_key_email(key.id) + end + end + + # TODO: When we close an issue we should send next emails: + # + # * issue author if his notification level is not Disabled + # * issue assignee if his notification level is not Disabled + # * project team members with notification level higher then Participating + # + def close_issue(issue, current_user) + [issue.author, issue.assignee].compact.uniq.each do |recipient| + Notify.delay.issue_status_changed_email(recipient.id, issue.id, issue.state, current_user.id) + end + end + + # When we reassign an issue we should send next emails: + # + # * issue author if his notification level is not Disabled + # * issue assignee if his notification level is not Disabled + # + def reassigned_issue(issue, current_user) + recipient_ids = [issue.assignee_id, issue.assignee_id_was].keep_if {|id| id && id != current_user.id } + + recipient_ids.each do |recipient_id| + Notify.delay.reassigned_issue_email(recipient_id, issue.id, issue.assignee_id_was) + end + end + + # When we reassign an issue we should send next emails: + # + # * issue assignee if his notification level is not Disabled + # + def new_issue(issue, current_user) + if issue.assignee && issue.assignee != current_user + Notify.delay.new_issue_email(issue.id) + end + end +end diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb new file mode 100644 index 00000000..3869db71 --- /dev/null +++ b/spec/services/notification_service_spec.rb @@ -0,0 +1,47 @@ +require 'spec_helper' + +describe NotificationService do + # Disable observers to prevent factory trigger notification service + before { ActiveRecord::Base.observers.disable :all } + + let(:notification) { NotificationService.new } + + describe 'Keys' do + describe :new_key do + let(:key) { create(:personal_key) } + + it { notification.new_key(key).should be_true } + + it 'should sent email to key owner' do + Notify.should_receive(:new_ssh_key_email).with(key.id) + notification.new_key(key) + end + end + end + + describe 'Issues' do + let(:issue) { create :issue, assignee: create(:user) } + + describe :new_issue do + it 'should sent email to issue assignee' do + Notify.should_receive(:new_issue_email).with(issue.id) + notification.new_issue(issue, nil) + end + end + + describe :reassigned_issue do + it 'should sent email to issue old assignee and new issue assignee' do + Notify.should_receive(:reassigned_issue_email).twice + notification.reassigned_issue(issue, issue.author) + end + end + + describe :close_issue do + it 'should sent email to issue assignee and issue author' do + Notify.should_receive(:issue_status_changed_email).twice + notification.close_issue(issue, issue.author) + end + end + end +end + From 4b3950456d666bc92fcf123532e73ae82c3c5e12 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 26 Mar 2013 10:16:49 +0200 Subject: [PATCH 064/152] notification level for user --- app/models/user.rb | 7 +++++++ .../20130325173941_add_notification_level_to_user.rb | 5 +++++ db/schema.rb | 3 ++- 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20130325173941_add_notification_level_to_user.rb diff --git a/app/models/user.rb b/app/models/user.rb index 16d91675..30bd8f47 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -53,6 +53,13 @@ class User < ActiveRecord::Base attr_accessible :login + # + # Notification levels + # + N_DISABLED = 0 + N_PARTICIPATING = 1 + N_WATCH = 2 + # # Relations # diff --git a/db/migrate/20130325173941_add_notification_level_to_user.rb b/db/migrate/20130325173941_add_notification_level_to_user.rb new file mode 100644 index 00000000..9f466e38 --- /dev/null +++ b/db/migrate/20130325173941_add_notification_level_to_user.rb @@ -0,0 +1,5 @@ +class AddNotificationLevelToUser < ActiveRecord::Migration + def change + add_column :users, :notification_level, :integer, null: false, default: 1 + end +end diff --git a/db/schema.rb b/db/schema.rb index e4349ac4..3c8b9eae 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20130318212250) do +ActiveRecord::Schema.define(:version => 20130325173941) do create_table "events", :force => true do |t| t.string "target_type" @@ -270,6 +270,7 @@ ActiveRecord::Schema.define(:version => 20130318212250) do t.boolean "can_create_team", :default => true, :null => false t.string "state" t.integer "color_scheme_id", :default => 1, :null => false + t.integer "notification_level", :default => 1, :null => false end add_index "users", ["admin"], :name => "index_users_on_admin" From bfebf108508fa011294c36ad59a4943173c309b2 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 26 Mar 2013 11:06:24 +0200 Subject: [PATCH 065/152] reject current_user from close issue emails --- app/services/notification_service.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index f20f3a44..804b33e0 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -21,7 +21,12 @@ class NotificationService # * project team members with notification level higher then Participating # def close_issue(issue, current_user) - [issue.author, issue.assignee].compact.uniq.each do |recipient| + recipients = [issue.author, issue.assignee].compact.uniq + + # Dont send email to me when I close an issue + recipients.reject! { |u| u == current_user } + + recipients.each do |recipient| Notify.delay.issue_status_changed_email(recipient.id, issue.id, issue.state, current_user.id) end end @@ -32,7 +37,10 @@ class NotificationService # * issue assignee if his notification level is not Disabled # def reassigned_issue(issue, current_user) - recipient_ids = [issue.assignee_id, issue.assignee_id_was].keep_if {|id| id && id != current_user.id } + recipient_ids = [issue.assignee_id, issue.assignee_id_was].compact.uniq + + # Reject me from recipients if I reassign an issue + recipient_ids.reject! { |id| id == current_user.id } recipient_ids.each do |recipient_id| Notify.delay.reassigned_issue_email(recipient_id, issue.id, issue.assignee_id_was) From e3e8b9fcb9299b6772c0936e8202137cc372fc53 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 26 Mar 2013 11:17:49 +0200 Subject: [PATCH 066/152] fixed tests --- spec/services/notification_service_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index 3869db71..eea2a2df 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -31,14 +31,14 @@ describe NotificationService do describe :reassigned_issue do it 'should sent email to issue old assignee and new issue assignee' do - Notify.should_receive(:reassigned_issue_email).twice + Notify.should_receive(:reassigned_issue_email) notification.reassigned_issue(issue, issue.author) end end describe :close_issue do it 'should sent email to issue assignee and issue author' do - Notify.should_receive(:issue_status_changed_email).twice + Notify.should_receive(:issue_status_changed_email) notification.close_issue(issue, issue.author) end end From 5949e302431167ecd61dec198e26f6587dbe0955 Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Tue, 26 Mar 2013 13:13:30 +0400 Subject: [PATCH 067/152] Spork support added --- .rspec | 2 +- Gemfile | 2 + Gemfile.lock | 2 + spec/spec_helper.rb | 89 ++++++++++++++++++++++++++------------------- 4 files changed, 57 insertions(+), 38 deletions(-) diff --git a/.rspec b/.rspec index 53607ea5..5902dd3a 100644 --- a/.rspec +++ b/.rspec @@ -1 +1 @@ ---colour +--colour --drb diff --git a/Gemfile b/Gemfile index fdc6a41f..efa4be7c 100644 --- a/Gemfile +++ b/Gemfile @@ -173,6 +173,8 @@ group :development, :test do # PhantomJS driver for Capybara gem 'poltergeist', '1.1.0' + + gem 'spork', '~> 1.0rc' end group :test do diff --git a/Gemfile.lock b/Gemfile.lock index 4e86bbcc..a81404b9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -447,6 +447,7 @@ GEM capybara (~> 2.0.0) railties (>= 3) spinach (>= 0.4) + spork (1.0.0rc3) sprockets (2.2.2) hike (~> 1.2) multi_json (~> 1.0) @@ -574,6 +575,7 @@ DEPENDENCIES six slim spinach-rails (= 0.2.0) + spork (~> 1.0rc) stamp state_machine test_after_commit diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 0f593de8..03c586f8 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,47 +1,62 @@ -require 'simplecov' unless ENV['CI'] +require 'rubygems' +require 'spork' -if ENV['TRAVIS'] - require 'coveralls' - Coveralls.wear! -end +Spork.prefork do + require 'simplecov' unless ENV['CI'] -# This file is copied to spec/ when you run 'rails generate rspec:install' -ENV["RAILS_ENV"] ||= 'test' -require File.expand_path("../../config/environment", __FILE__) -require 'rspec/rails' -require 'capybara/rails' -require 'capybara/rspec' -require 'webmock/rspec' -require 'email_spec' -require 'sidekiq/testing/inline' -require 'capybara/poltergeist' -Capybara.javascript_driver = :poltergeist -Capybara.default_wait_time = 10 + if ENV['TRAVIS'] + require 'coveralls' + Coveralls.wear! + end -# Requires supporting ruby files with custom matchers and macros, etc, -# in spec/support/ and its subdirectories. -Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} + # This file is copied to spec/ when you run 'rails generate rspec:install' + ENV["RAILS_ENV"] ||= 'test' + require File.expand_path("../../config/environment", __FILE__) + require 'rspec/rails' + require 'capybara/rails' + require 'capybara/rspec' + require 'webmock/rspec' + require 'email_spec' + require 'sidekiq/testing/inline' + require 'capybara/poltergeist' -WebMock.disable_net_connect!(allow_localhost: true) + # Loading more in this block will cause your tests to run faster. However, -RSpec.configure do |config| - config.mock_with :rspec + # if you change any configuration or code from libraries loaded here, you'll + # need to restart spork for it take effect. + Capybara.javascript_driver = :poltergeist + Capybara.default_wait_time = 10 - config.include LoginHelpers, type: :feature - config.include LoginHelpers, type: :request - config.include FactoryGirl::Syntax::Methods - config.include Devise::TestHelpers, type: :controller + # Requires supporting ruby files with custom matchers and macros, etc, + # in spec/support/ and its subdirectories. + Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} - # If you're not using ActiveRecord, or you'd prefer not to run each of your - # examples within a transaction, remove the following line or assign false - # instead of true. - config.use_transactional_fixtures = false + WebMock.disable_net_connect!(allow_localhost: true) - config.before do - # Use tmp dir for FS manipulations - temp_repos_path = Rails.root.join('tmp', 'test-git-base-path') - Gitlab.config.gitlab_shell.stub(repos_path: temp_repos_path) - FileUtils.rm_rf temp_repos_path - FileUtils.mkdir_p temp_repos_path + RSpec.configure do |config| + config.mock_with :rspec + + config.include LoginHelpers, type: :feature + config.include LoginHelpers, type: :request + config.include FactoryGirl::Syntax::Methods + config.include Devise::TestHelpers, type: :controller + + # If you're not using ActiveRecord, or you'd prefer not to run each of your + # examples within a transaction, remove the following line or assign false + # instead of true. + config.use_transactional_fixtures = false + + config.before do + # Use tmp dir for FS manipulations + temp_repos_path = Rails.root.join('tmp', 'test-git-base-path') + Gitlab.config.gitlab_shell.stub(repos_path: temp_repos_path) + FileUtils.rm_rf temp_repos_path + FileUtils.mkdir_p temp_repos_path + end end end + +Spork.each_run do + # This code will be run each time you run your specs. + +end From c7bd99b04053421726012d77f85919b1d6fc0387 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 26 Mar 2013 14:41:57 +0200 Subject: [PATCH 068/152] refactor issue observer spec --- spec/observers/issue_observer_spec.rb | 81 +++++----------------- spec/services/notification_service_spec.rb | 1 - 2 files changed, 16 insertions(+), 66 deletions(-) diff --git a/spec/observers/issue_observer_spec.rb b/spec/observers/issue_observer_spec.rb index e4e66917..539c6550 100644 --- a/spec/observers/issue_observer_spec.rb +++ b/spec/observers/issue_observer_spec.rb @@ -11,7 +11,9 @@ describe IssueObserver do let(:closed_unassigned_issue) { create(:closed_issue, author: author) } - before(:each) { subject.stub(:current_user).and_return(some_user) } + before { subject.stub(:current_user).and_return(some_user) } + before { subject.stub(notification: mock('NotificationService').as_null_object) } + subject { IssueObserver.instance } @@ -25,15 +27,8 @@ describe IssueObserver do end end - it 'sends an email to the assignee' do - Notify.should_receive(:new_issue_email).with(mock_issue.id) - - subject.after_create(mock_issue) - end - - it 'does not send an email to the assignee if assignee created the issue' do - subject.stub(:current_user).and_return(assignee) - Notify.should_not_receive(:new_issue_email) + it 'trigger notification to send emails' do + subject.should_receive(:notification) subject.after_create(mock_issue) end @@ -47,16 +42,14 @@ describe IssueObserver do assigned_issue.close end - it 'notification is delivered if the issue being closed' do - Notify.should_receive(:issue_status_changed_email).twice + it 'trigger notification to send emails' do + subject.should_receive(:notification) assigned_issue.close end - it 'notification is delivered only to author if the issue being closed' do - Notify.should_receive(:issue_status_changed_email).once + it 'creates a note' do Note.should_receive(:create_status_change_note).with(unassigned_issue, some_user, 'closed') - unassigned_issue.close end end @@ -68,14 +61,13 @@ describe IssueObserver do closed_assigned_issue.reopen end - it 'notification is delivered if the issue being reopened' do - Notify.should_receive(:issue_status_changed_email).twice + it 'trigger notification to send emails' do + subject.should_receive(:notification) closed_assigned_issue.reopen end - it 'notification is delivered only to author if the issue being reopened' do - Notify.should_receive(:issue_status_changed_email).once + it 'create a note' do Note.should_receive(:create_status_change_note).with(closed_unassigned_issue, some_user, 'reopened') closed_unassigned_issue.reopen @@ -98,61 +90,20 @@ describe IssueObserver do end end - context 'a reassigned email' do - it 'is sent if the issue is being reassigned' do + context 'notification' do + it 'triggered if the issue is being reassigned' do mock_issue.should_receive(:is_being_reassigned?).and_return(true) - subject.should_receive(:send_reassigned_email).with(mock_issue) + subject.should_receive(:notification) subject.after_update(mock_issue) end - it 'is not sent if the issue is not being reassigned' do + it 'is not triggered if the issue is not being reassigned' do mock_issue.should_receive(:is_being_reassigned?).and_return(false) - subject.should_not_receive(:send_reassigned_email) + subject.should_not_receive(:notification) subject.after_update(mock_issue) end end end - - describe '#send_reassigned_email' do - let(:previous_assignee) { double(:user, id: 3) } - - before(:each) do - mock_issue.stub(:assignee_id).and_return(assignee.id) - mock_issue.stub(:assignee_id_was).and_return(previous_assignee.id) - end - - def it_sends_a_reassigned_email_to(recipient) - Notify.should_receive(:reassigned_issue_email).with(recipient, mock_issue.id, previous_assignee.id) - end - - def it_does_not_send_a_reassigned_email_to(recipient) - Notify.should_not_receive(:reassigned_issue_email).with(recipient, mock_issue.id, previous_assignee.id) - end - - it 'sends a reassigned email to the previous and current assignees' do - it_sends_a_reassigned_email_to assignee.id - it_sends_a_reassigned_email_to previous_assignee.id - - subject.send(:send_reassigned_email, mock_issue) - end - - context 'does not send an email to the user who made the reassignment' do - it 'if the user is the assignee' do - subject.stub(:current_user).and_return(assignee) - it_sends_a_reassigned_email_to previous_assignee.id - it_does_not_send_a_reassigned_email_to assignee.id - - subject.send(:send_reassigned_email, mock_issue) - end - it 'if the user is the previous assignee' do - subject.stub(:current_user).and_return(previous_assignee) - it_sends_a_reassigned_email_to assignee.id - it_does_not_send_a_reassigned_email_to previous_assignee.id - - subject.send(:send_reassigned_email, mock_issue) - end - end - end end diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index eea2a2df..a802d50f 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -44,4 +44,3 @@ describe NotificationService do end end end - From da1cf5b9e70dc16113f441e17ad33c4e53bc1ca5 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 26 Mar 2013 15:16:06 +0200 Subject: [PATCH 069/152] enable callbacks for specs after notification --- spec/services/notification_service_spec.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index a802d50f..0edfb216 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -2,7 +2,8 @@ require 'spec_helper' describe NotificationService do # Disable observers to prevent factory trigger notification service - before { ActiveRecord::Base.observers.disable :all } + before(:all) { ActiveRecord::Base.observers.disable :all } + after(:all) { ActiveRecord::Base.observers.enable :all } let(:notification) { NotificationService.new } From 7ed0dc0185e93a0af9bf67888c5b24a49baf48a3 Mon Sep 17 00:00:00 2001 From: Nihad Abbasov Date: Tue, 26 Mar 2013 07:14:57 -0700 Subject: [PATCH 070/152] use convenient method to check for empty project repo --- app/controllers/projects_controller.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 5b17e1ab..8e55aa01 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -57,11 +57,11 @@ class ProjectsController < ProjectResourceController respond_to do |format| format.html do - if @project.repository && !@project.repository.empty? + if @project.empty_repo? + render "projects/empty" + else @last_push = current_user.recent_push(@project.id) render :show - else - render "projects/empty" end end format.js From b8502cbaeeb843f579221664289f3ff93be3df67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Ho=CC=88ltje?= Date: Tue, 26 Mar 2013 10:19:55 -0400 Subject: [PATCH 071/152] Fixed UsersProject.in_projects I discovered while trying to use UserTeam#remove_member() that UsersProject.in_projects was broken. So I wrote test cases to test what I was trying to do and fixed the underlying problem. --- app/models/users_project.rb | 2 +- spec/models/user_team_spec.rb | 21 ++++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/app/models/users_project.rb b/app/models/users_project.rb index 8051c060..c32edf38 100644 --- a/app/models/users_project.rb +++ b/app/models/users_project.rb @@ -38,7 +38,7 @@ class UsersProject < ActiveRecord::Base scope :masters, -> { where(project_access: MASTER) } scope :in_project, ->(project) { where(project_id: project.id) } - scope :in_projects, ->(projects) { where(project_id: project_ids) } + scope :in_projects, ->(projects) { where(project_id: projects.map { |p| p.id }) } scope :with_user, ->(user) { where(user_id: user.id) } class << self diff --git a/spec/models/user_team_spec.rb b/spec/models/user_team_spec.rb index 6cc2003e..d330bbf3 100644 --- a/spec/models/user_team_spec.rb +++ b/spec/models/user_team_spec.rb @@ -14,5 +14,24 @@ require 'spec_helper' describe UserTeam do - pending "add some examples to (or delete) #{__FILE__}" + let(:team) { FactoryGirl.create :user_team } + + context ".add_member" do + let(:user) { FactoryGirl.create :user } + + it "should work" do + team.add_member(user, UsersProject::DEVELOPER, false) + team.members.should include(user) + end + end + + context ".remove_member" do + let(:user) { FactoryGirl.create :user } + before { team.add_member(user, UsersProject::DEVELOPER, false) } + + it "should work" do + team.remove_member(user) + team.members.should_not include(user) + end + end end From 38ffb8220c8d8ae030b762f7b2d244eabe8cc0bf Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 26 Mar 2013 17:16:06 +0200 Subject: [PATCH 072/152] use NotificationService for handle notify logic when MR created --- app/observers/merge_request_observer.rb | 4 +--- app/services/notification_service.rb | 12 +++++++++++- spec/observers/merge_request_observer_spec.rb | 19 +++++-------------- spec/services/notification_service_spec.rb | 16 ++++++++++++++++ 4 files changed, 33 insertions(+), 18 deletions(-) diff --git a/app/observers/merge_request_observer.rb b/app/observers/merge_request_observer.rb index d89e7734..355f7848 100644 --- a/app/observers/merge_request_observer.rb +++ b/app/observers/merge_request_observer.rb @@ -2,9 +2,7 @@ class MergeRequestObserver < ActiveRecord::Observer cattr_accessor :current_user def after_create(merge_request) - if merge_request.assignee && merge_request.assignee != current_user - Notify.delay.new_merge_request_email(merge_request.id) - end + notification.new_merge_request(merge_request, current_user) end def after_close(merge_request, transition) diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 804b33e0..7e7a36f3 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -47,7 +47,7 @@ class NotificationService end end - # When we reassign an issue we should send next emails: + # When create an issue we should send next emails: # # * issue assignee if his notification level is not Disabled # @@ -56,4 +56,14 @@ class NotificationService Notify.delay.new_issue_email(issue.id) end end + + # When create a merge request we should send next emails: + # + # * mr assignee if his notification level is not Disabled + # + def new_merge_request(merge_request, current_user) + if merge_request.assignee && merge_request.assignee != current_user + Notify.delay.new_merge_request_email(merge_request.id) + end + end end diff --git a/spec/observers/merge_request_observer_spec.rb b/spec/observers/merge_request_observer_spec.rb index 9d702107..991f2d40 100644 --- a/spec/observers/merge_request_observer_spec.rb +++ b/spec/observers/merge_request_observer_spec.rb @@ -10,7 +10,8 @@ describe MergeRequestObserver do let(:closed_assigned_mr) { create(:closed_merge_request, assignee: assignee, author: author) } let(:closed_unassigned_mr) { create(:closed_merge_request, author: author) } - before(:each) { subject.stub(:current_user).and_return(some_user) } + before { subject.stub(:current_user).and_return(some_user) } + before { subject.stub(notification: mock('NotificationService').as_null_object) } subject { MergeRequestObserver.instance } @@ -18,21 +19,11 @@ describe MergeRequestObserver do it 'is called when a merge request is created' do subject.should_receive(:after_create) - - MergeRequest.observers.enable :merge_request_observer do - create(:merge_request, project: create(:project)) - end + create(:merge_request, project: create(:project)) end - it 'sends an email to the assignee' do - Notify.should_receive(:new_merge_request_email).with(mr_mock.id) - subject.after_create(mr_mock) - end - - it 'does not send an email to the assignee if assignee created the merge request' do - subject.stub(:current_user).and_return(assignee) - Notify.should_not_receive(:new_merge_request_email) - + it 'trigger notification service' do + subject.should_receive(:notification) subject.after_create(mr_mock) end end diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index 0edfb216..e9e4770d 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -44,4 +44,20 @@ describe NotificationService do end end end + + describe 'Merge Requests' do + let(:merge_request) { create :merge_request, assignee: create(:user) } + + describe :new_merge_request do + it 'should send email to merge_request assignee' do + Notify.should_receive(:new_merge_request_email).with(merge_request.id) + notification.new_merge_request(merge_request, merge_request.author) + end + + it 'should not send email to merge_request assignee if he is current_user' do + Notify.should_not_receive(:new_merge_request_email).with(merge_request.id) + notification.new_merge_request(merge_request, merge_request.assignee) + end + end + end end From f93c4dc0d83dd40452d40447a62cd68a08e24b09 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 26 Mar 2013 17:23:28 +0200 Subject: [PATCH 073/152] Use notificationService for MR reassigned --- app/observers/merge_request_observer.rb | 15 +++------------ app/services/notification_service.rb | 18 ++++++++++++++++-- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/app/observers/merge_request_observer.rb b/app/observers/merge_request_observer.rb index 355f7848..64585570 100644 --- a/app/observers/merge_request_observer.rb +++ b/app/observers/merge_request_observer.rb @@ -6,29 +6,20 @@ class MergeRequestObserver < ActiveRecord::Observer end def after_close(merge_request, transition) - send_reassigned_email(merge_request) if merge_request.is_being_reassigned? - Note.create_status_change_note(merge_request, current_user, merge_request.state) end def after_reopen(merge_request, transition) - send_reassigned_email(merge_request) if merge_request.is_being_reassigned? - Note.create_status_change_note(merge_request, current_user, merge_request.state) end def after_update(merge_request) - send_reassigned_email(merge_request) if merge_request.is_being_reassigned? + notification.reassigned_merge_request(merge_request) if merge_request.is_being_reassigned? end protected - def send_reassigned_email(merge_request) - recipients_ids = merge_request.assignee_id_was, merge_request.assignee_id - recipients_ids.delete current_user.id - - recipients_ids.each do |recipient_id| - Notify.delay.reassigned_merge_request_email(recipient_id, merge_request.id, merge_request.assignee_id_was) - end + def notification + NotificationService.new end end diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 7e7a36f3..873fc297 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -33,8 +33,8 @@ class NotificationService # When we reassign an issue we should send next emails: # - # * issue author if his notification level is not Disabled - # * issue assignee if his notification level is not Disabled + # * issue old assignee if his notification level is not Disabled + # * issue new assignee if his notification level is not Disabled # def reassigned_issue(issue, current_user) recipient_ids = [issue.assignee_id, issue.assignee_id_was].compact.uniq @@ -66,4 +66,18 @@ class NotificationService Notify.delay.new_merge_request_email(merge_request.id) end end + + # When we reassign a merge_request we should send next emails: + # + # * merge_request old assignee if his notification level is not Disabled + # * merge_request assignee if his notification level is not Disabled + # + def reassigned_merge_request(merge_request, current_user) + recipients_ids = merge_request.assignee_id_was, merge_request.assignee_id + recipients_ids.delete current_user.id + + recipients_ids.each do |recipient_id| + Notify.delay.reassigned_merge_request_email(recipient_id, merge_request.id, merge_request.assignee_id_was) + end + end end From 6abf58466fc47a7efd86a03c5b0b3878edfbce36 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 26 Mar 2013 17:51:06 +0200 Subject: [PATCH 074/152] Move new_note email logic to NotificationService --- app/observers/note_observer.rb | 33 +--------------------------- app/observers/user_observer.rb | 7 ++++-- app/services/notification_service.rb | 28 +++++++++++++++++++++++ 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/app/observers/note_observer.rb b/app/observers/note_observer.rb index 1c3c1ad3..944c6839 100644 --- a/app/observers/note_observer.rb +++ b/app/observers/note_observer.rb @@ -1,41 +1,10 @@ class NoteObserver < ActiveRecord::Observer def after_create(note) - send_notify_mails(note) + notification.new_note(note) end protected - def send_notify_mails(note) - if note.notify - notify_team(note) - elsif note.notify_author - # Notify only author of resource - if note.commit_author - Notify.delay.note_commit_email(note.commit_author.id, note.id) - end - else - # Otherwise ignore it - nil - end - end - - # Notifies the whole team except the author of note - def notify_team(note) - # Note: wall posts are not "attached" to anything, so fall back to "Wall" - noteable_type = note.noteable_type.presence || "Wall" - notify_method = "note_#{noteable_type.underscore}_email".to_sym - - if Notify.respond_to? notify_method - team_without_note_author(note).map do |u| - Notify.delay.send(notify_method, u.id, note.id) - end - end - end - - def team_without_note_author(note) - note.project.users.reject { |u| u.id == note.author.id } - end - def notification NotificationService.new end diff --git a/app/observers/user_observer.rb b/app/observers/user_observer.rb index 6c461e07..7ce3be0c 100644 --- a/app/observers/user_observer.rb +++ b/app/observers/user_observer.rb @@ -2,8 +2,7 @@ class UserObserver < ActiveRecord::Observer def after_create(user) log_info("User \"#{user.name}\" (#{user.email}) was created") - # Dont email omniauth created users - Notify.delay.new_user_email(user.id, user.password) unless user.extern_uid? + notification.new_user(user) end def after_destroy user @@ -25,4 +24,8 @@ class UserObserver < ActiveRecord::Observer def log_info message Gitlab::AppLogger.info message end + + def notification + NotificationService.new + end end diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 873fc297..05a6730f 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -80,4 +80,32 @@ class NotificationService Notify.delay.reassigned_merge_request_email(recipient_id, merge_request.id, merge_request.assignee_id_was) end end + + # Notify new user with email after creation + def new_user(user) + # Dont email omniauth created users + Notify.delay.new_user_email(user.id, user.password) unless user.extern_uid? + end + + # Notify users on new note in system + # + # TODO: split on methods and refactor + # + def new_note(note) + if note.notify + users = note.project.users.reject { |u| u.id == note.author.id } + + # Note: wall posts are not "attached" to anything, so fall back to "Wall" + noteable_type = note.noteable_type.presence || "Wall" + notify_method = "note_#{noteable_type.underscore}_email".to_sym + + if Notify.respond_to? notify_method + team_without_note_author(note).map do |u| + Notify.delay.send(notify_method, u.id, note.id) + end + end + elsif note.notify_author && note.commit_author + Notify.delay.note_commit_email(note.commit_author.id, note.id) + end + end end From ce0945efcd36cc89d1b633500e4bdecf373fc304 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 26 Mar 2013 18:11:38 +0200 Subject: [PATCH 075/152] refactor observers. Added BaseObserver with helper methods --- app/observers/base_observer.rb | 11 +++++++++++ app/observers/issue_observer.rb | 6 +----- app/observers/key_observer.rb | 7 ++----- app/observers/merge_request_observer.rb | 8 +------- app/observers/note_observer.rb | 8 +------- app/observers/project_observer.rb | 8 +------- app/observers/system_hook_observer.rb | 2 +- app/observers/user_observer.rb | 12 +----------- app/observers/users_project_observer.rb | 9 +++++++-- 9 files changed, 26 insertions(+), 45 deletions(-) create mode 100644 app/observers/base_observer.rb diff --git a/app/observers/base_observer.rb b/app/observers/base_observer.rb new file mode 100644 index 00000000..b4641bf8 --- /dev/null +++ b/app/observers/base_observer.rb @@ -0,0 +1,11 @@ +class BaseObserver < ActiveRecord::Observer + protected + + def notification + NotificationService.new + end + + def log_info message + Gitlab::AppLogger.info message + end +end diff --git a/app/observers/issue_observer.rb b/app/observers/issue_observer.rb index 7e8e9ccd..03ce4b95 100644 --- a/app/observers/issue_observer.rb +++ b/app/observers/issue_observer.rb @@ -1,4 +1,4 @@ -class IssueObserver < ActiveRecord::Observer +class IssueObserver < BaseObserver cattr_accessor :current_user def after_create(issue) @@ -27,8 +27,4 @@ class IssueObserver < ActiveRecord::Observer def create_note(issue) Note.create_status_change_note(issue, current_user, issue.state) end - - def notification - NotificationService.new - end end diff --git a/app/observers/key_observer.rb b/app/observers/key_observer.rb index 2a69b876..28fef55a 100644 --- a/app/observers/key_observer.rb +++ b/app/observers/key_observer.rb @@ -1,6 +1,4 @@ -class KeyObserver < ActiveRecord::Observer - include Gitlab::ShellAdapter - +class KeyObserver < BaseObserver def after_save(key) GitlabShellWorker.perform_async( :add_key, @@ -8,8 +6,7 @@ class KeyObserver < ActiveRecord::Observer key.key ) - # Notify about ssh key being added - NotificationService.new.new_key(key) + notification.new_key(key) end def after_destroy(key) diff --git a/app/observers/merge_request_observer.rb b/app/observers/merge_request_observer.rb index 64585570..15214016 100644 --- a/app/observers/merge_request_observer.rb +++ b/app/observers/merge_request_observer.rb @@ -1,4 +1,4 @@ -class MergeRequestObserver < ActiveRecord::Observer +class MergeRequestObserver < BaseObserver cattr_accessor :current_user def after_create(merge_request) @@ -16,10 +16,4 @@ class MergeRequestObserver < ActiveRecord::Observer def after_update(merge_request) notification.reassigned_merge_request(merge_request) if merge_request.is_being_reassigned? end - - protected - - def notification - NotificationService.new - end end diff --git a/app/observers/note_observer.rb b/app/observers/note_observer.rb index 944c6839..7b79161c 100644 --- a/app/observers/note_observer.rb +++ b/app/observers/note_observer.rb @@ -1,11 +1,5 @@ -class NoteObserver < ActiveRecord::Observer +class NoteObserver < BaseObserver def after_create(note) notification.new_note(note) end - - protected - - def notification - NotificationService.new - end end diff --git a/app/observers/project_observer.rb b/app/observers/project_observer.rb index 89dc97ac..7d7ecdd3 100644 --- a/app/observers/project_observer.rb +++ b/app/observers/project_observer.rb @@ -1,4 +1,4 @@ -class ProjectObserver < ActiveRecord::Observer +class ProjectObserver < BaseObserver def after_create(project) GitlabShellWorker.perform_async( :add_repository, @@ -27,10 +27,4 @@ class ProjectObserver < ActiveRecord::Observer log_info("Project \"#{project.name}\" was removed") end - - protected - - def log_info message - Gitlab::AppLogger.info message - end end diff --git a/app/observers/system_hook_observer.rb b/app/observers/system_hook_observer.rb index be2594b4..3a649fd5 100644 --- a/app/observers/system_hook_observer.rb +++ b/app/observers/system_hook_observer.rb @@ -1,4 +1,4 @@ -class SystemHookObserver < ActiveRecord::Observer +class SystemHookObserver < BaseObserver observe :user, :project, :users_project def after_create(model) diff --git a/app/observers/user_observer.rb b/app/observers/user_observer.rb index 7ce3be0c..6bb3c471 100644 --- a/app/observers/user_observer.rb +++ b/app/observers/user_observer.rb @@ -1,4 +1,4 @@ -class UserObserver < ActiveRecord::Observer +class UserObserver < BaseObserver def after_create(user) log_info("User \"#{user.name}\" (#{user.email}) was created") @@ -18,14 +18,4 @@ class UserObserver < ActiveRecord::Observer end end end - - protected - - def log_info message - Gitlab::AppLogger.info message - end - - def notification - NotificationService.new - end end diff --git a/app/observers/users_project_observer.rb b/app/observers/users_project_observer.rb index 66b42175..ca9649c7 100644 --- a/app/observers/users_project_observer.rb +++ b/app/observers/users_project_observer.rb @@ -1,7 +1,6 @@ -class UsersProjectObserver < ActiveRecord::Observer +class UsersProjectObserver < BaseObserver def after_commit(users_project) return if users_project.destroyed? - Notify.delay.project_access_granted_email(users_project.id) end def after_create(users_project) @@ -10,6 +9,12 @@ class UsersProjectObserver < ActiveRecord::Observer action: Event::JOINED, author_id: users_project.user.id ) + + notification.new_team_member(users_project) + end + + def after_update(users_project) + notification.update_team_member(users_project) end def after_destroy(users_project) From 3728c4904e61e47d23b6454754451bd716f4f422 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 26 Mar 2013 19:00:54 +0200 Subject: [PATCH 076/152] refactor observers test since email logic moved to service --- app/observers/activity_observer.rb | 2 +- app/observers/base_observer.rb | 2 - app/services/notification_service.rb | 8 ++ spec/observers/merge_request_observer_spec.rb | 48 +------- spec/observers/note_observer_spec.rb | 110 +----------------- spec/observers/user_observer_spec.rb | 8 +- spec/observers/users_project_observer_spec.rb | 5 +- 7 files changed, 19 insertions(+), 164 deletions(-) diff --git a/app/observers/activity_observer.rb b/app/observers/activity_observer.rb index c040c4c5..ee3e4629 100644 --- a/app/observers/activity_observer.rb +++ b/app/observers/activity_observer.rb @@ -1,4 +1,4 @@ -class ActivityObserver < ActiveRecord::Observer +class ActivityObserver < BaseObserver observe :issue, :merge_request, :note, :milestone def after_create(record) diff --git a/app/observers/base_observer.rb b/app/observers/base_observer.rb index b4641bf8..182d3b7b 100644 --- a/app/observers/base_observer.rb +++ b/app/observers/base_observer.rb @@ -1,6 +1,4 @@ class BaseObserver < ActiveRecord::Observer - protected - def notification NotificationService.new end diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 05a6730f..37c8345e 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -108,4 +108,12 @@ class NotificationService Notify.delay.note_commit_email(note.commit_author.id, note.id) end end + + def new_team_member(users_project) + Notify.delay.project_access_granted_email(users_project.id) + end + + def update_team_member(users_project) + Notify.delay.project_access_granted_email(users_project.id) + end end diff --git a/spec/observers/merge_request_observer_spec.rb b/spec/observers/merge_request_observer_spec.rb index 991f2d40..2593da72 100644 --- a/spec/observers/merge_request_observer_spec.rb +++ b/spec/observers/merge_request_observer_spec.rb @@ -43,22 +43,21 @@ describe MergeRequestObserver do end end - context 'a reassigned email' do + context 'a notification' do it 'is sent if the merge request is being reassigned' do mr_mock.should_receive(:is_being_reassigned?).and_return(true) - subject.should_receive(:send_reassigned_email).with(mr_mock) + subject.should_receive(:notification) subject.after_update(mr_mock) end it 'is not sent if the merge request is not being reassigned' do mr_mock.should_receive(:is_being_reassigned?).and_return(false) - subject.should_not_receive(:send_reassigned_email) + subject.should_not_receive(:notification) subject.after_update(mr_mock) end end - end context '#after_close' do @@ -92,45 +91,4 @@ describe MergeRequestObserver do end end end - - describe '#send_reassigned_email' do - let(:previous_assignee) { double(:user, id: 3) } - - before(:each) do - mr_mock.stub(:assignee_id).and_return(assignee.id) - mr_mock.stub(:assignee_id_was).and_return(previous_assignee.id) - end - - def it_sends_a_reassigned_email_to(recipient) - Notify.should_receive(:reassigned_merge_request_email).with(recipient, mr_mock.id, previous_assignee.id) - end - - def it_does_not_send_a_reassigned_email_to(recipient) - Notify.should_not_receive(:reassigned_merge_request_email).with(recipient, mr_mock.id, previous_assignee.id) - end - - it 'sends a reassigned email to the previous and current assignees' do - it_sends_a_reassigned_email_to assignee.id - it_sends_a_reassigned_email_to previous_assignee.id - - subject.send(:send_reassigned_email, mr_mock) - end - - context 'does not send an email to the user who made the reassignment' do - it 'if the user is the assignee' do - subject.stub(:current_user).and_return(assignee) - it_sends_a_reassigned_email_to previous_assignee.id - it_does_not_send_a_reassigned_email_to assignee.id - - subject.send(:send_reassigned_email, mr_mock) - end - it 'if the user is the previous assignee' do - subject.stub(:current_user).and_return(previous_assignee) - it_sends_a_reassigned_email_to assignee.id - it_does_not_send_a_reassigned_email_to previous_assignee.id - - subject.send(:send_reassigned_email, mr_mock) - end - end - end end diff --git a/spec/observers/note_observer_spec.rb b/spec/observers/note_observer_spec.rb index 8ad42c21..9ada9270 100644 --- a/spec/observers/note_observer_spec.rb +++ b/spec/observers/note_observer_spec.rb @@ -2,6 +2,7 @@ require 'spec_helper' describe NoteObserver do subject { NoteObserver.instance } + before { subject.stub(notification: mock('NotificationService').as_null_object) } let(:team_without_author) { (1..2).map { |n| double :user, id: n } } @@ -17,116 +18,9 @@ describe NoteObserver do end it 'sends out notifications' do - subject.should_receive(:send_notify_mails).with(note) + subject.should_receive(:notification) subject.after_create(note) end end - - describe "#send_notify_mails" do - let(:note) { double :note, notify: false, notify_author: false } - - it 'notifies team of new note when flagged to notify' do - note.stub(:notify).and_return(true) - subject.should_receive(:notify_team).with(note) - - subject.after_create(note) - end - - it 'does not notify team of new note when not flagged to notify' do - subject.should_not_receive(:notify_team).with(note) - - subject.after_create(note) - end - - it 'notifies the author of a commit when flagged to notify the author' do - note.stub(:notify_author).and_return(true) - note.stub(:noteable).and_return(double(author_email: 'test@test.com')) - note.stub(:id).and_return(42) - author = double :user, id: 1, email: 'test@test.com' - note.stub(:commit_author).and_return(author) - Notify.should_receive(:note_commit_email) - - subject.after_create(note) - end - - it 'does not notify the author of a commit when not flagged to notify the author' do - notify.should_not_receive(:note_commit_email) - - subject.after_create(note) - end - - it 'does nothing if no notify flags are set' do - subject.after_create(note).should be_nil - end - end - - describe '#notify_team' do - let(:note) { double :note, id: 1 } - - before :each do - subject.stub(:team_without_note_author).with(note).and_return(team_without_author) - end - - context 'notifies team of a new note on' do - it 'a commit' do - note.stub(:noteable_type).and_return('Commit') - notify.should_receive(:note_commit_email).twice - - subject.send(:notify_team, note) - end - - it 'an issue' do - note.stub(:noteable_type).and_return('Issue') - notify.should_receive(:note_issue_email).twice - - subject.send(:notify_team, note) - end - - it 'a wiki page' do - note.stub(:noteable_type).and_return('Wiki') - notify.should_receive(:note_wiki_email).twice - - subject.send(:notify_team, note) - end - - it 'a merge request' do - note.stub(:noteable_type).and_return('MergeRequest') - notify.should_receive(:note_merge_request_email).twice - - subject.send(:notify_team, note) - end - - it 'a wall' do - # Note: wall posts have #noteable_type of nil - note.stub(:noteable_type).and_return(nil) - notify.should_receive(:note_wall_email).twice - - subject.send(:notify_team, note) - end - end - - it 'does nothing for a new note on a snippet' do - note.stub(:noteable_type).and_return('Snippet') - - subject.send(:notify_team, note).should be_nil - end - end - - - describe '#team_without_note_author' do - let(:author) { double :user, id: 4 } - - let(:users) { team_without_author + [author] } - let(:project) { double :project, users: users } - let(:note) { double :note, project: project, author: author } - - it 'returns the projects user without the note author included' do - subject.send(:team_without_note_author, note).should == team_without_author - end - end - - def notify - Notify - end end diff --git a/spec/observers/user_observer_spec.rb b/spec/observers/user_observer_spec.rb index b58c5647..5b735a8f 100644 --- a/spec/observers/user_observer_spec.rb +++ b/spec/observers/user_observer_spec.rb @@ -2,6 +2,7 @@ require 'spec_helper' describe UserObserver do subject { UserObserver.instance } + before { subject.stub(notification: mock('NotificationService').as_null_object) } it 'calls #after_create when new users are created' do new_user = build(:user) @@ -11,15 +12,10 @@ describe UserObserver do context 'when a new user is created' do it 'sends an email' do - Notify.should_receive(:new_user_email) + subject.should_receive(:notification) create(:user) end - it 'no email for external' do - Notify.should_not_receive(:new_user_email) - create(:user, extern_uid: '32442eEfsafada') - end - it 'trigger logger' do user = double(:user, id: 42, password: 'P@ssword!', name: 'John', email: 'u@mail.local', extern_uid?: false) Gitlab::AppLogger.should_receive(:info) diff --git a/spec/observers/users_project_observer_spec.rb b/spec/observers/users_project_observer_spec.rb index 068688b0..c034501e 100644 --- a/spec/observers/users_project_observer_spec.rb +++ b/spec/observers/users_project_observer_spec.rb @@ -4,6 +4,7 @@ describe UsersProjectObserver do let(:user) { create(:user) } let(:project) { create(:project) } subject { UsersProjectObserver.instance } + before { subject.stub(notification: mock('NotificationService').as_null_object) } describe "#after_commit" do it "should called when UsersProject created" do @@ -12,7 +13,7 @@ describe UsersProjectObserver do end it "should send email to user" do - Notify.should_receive(:project_access_granted_email).and_return(double(deliver: true)) + subject.should_receive(:notification) Event.stub(:create => true) create(:users_project) @@ -36,7 +37,7 @@ describe UsersProjectObserver do end it "should send email to user" do - Notify.should_receive(:project_access_granted_email) + subject.should_receive(:notification) @users_project.update_attribute(:project_access, UsersProject::MASTER) end From 5e6f45b07f0c5b35f3c5ae0b9a49e14b79460d8d Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Tue, 26 Mar 2013 21:04:00 +0400 Subject: [PATCH 077/152] Settings replaced by Gitlab.config --- app/helpers/issues_helper.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index afd08bd5..70ebbdd3 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -48,7 +48,7 @@ module IssuesHelper if @project.used_default_issues_tracker? project_issues_filter_path(@project) else - url = Settings[:issues_tracker][@project.issues_tracker]["project_url"] + url = Gitlab.config.issues_tracker[@project.issues_tracker]["project_url"] url.gsub(':project_id', @project.id.to_s) .gsub(':issues_tracker_id', @project.issues_tracker_id.to_s) end @@ -60,7 +60,7 @@ module IssuesHelper if @project.used_default_issues_tracker? url = new_project_issue_path project_id: @project else - url = Settings[:issues_tracker][@project.issues_tracker]["new_issue_url"] + url = Gitlab.config.issues_tracker[@project.issues_tracker]["new_issue_url"] url.gsub(':project_id', @project.id.to_s) .gsub(':issues_tracker_id', @project.issues_tracker_id.to_s) end @@ -72,7 +72,7 @@ module IssuesHelper if @project.used_default_issues_tracker? url = project_issue_url project_id: @project, id: issue_id else - url = Settings[:issues_tracker][@project.issues_tracker]["issues_url"] + url = Gitlab.config.issues_tracker[@project.issues_tracker]["issues_url"] url.gsub(':id', issue_id.to_s) .gsub(':project_id', @project.id.to_s) .gsub(':issues_tracker_id', @project.issues_tracker_id.to_s) From e3f116424877864424250971f824b5a2552aec9a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 26 Mar 2013 19:27:39 +0200 Subject: [PATCH 078/152] stub notification in event model --- spec/models/event_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb index cc789939..85bdf08a 100644 --- a/spec/models/event_spec.rb +++ b/spec/models/event_spec.rb @@ -72,6 +72,7 @@ describe Event do before { Event.should_receive :create + observer.stub(notification: stub.as_null_object) } describe "Joined project team" do From 3392f6c1f0d7810e25a12cefd3a6676ebb227d0e Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Wed, 27 Mar 2013 10:15:12 +0100 Subject: [PATCH 079/152] Link to accepting issues on feedback forum. --- CONTRIBUTING.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d3ccbee9..632cf930 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -19,7 +19,7 @@ Please visit our [Support Forum](https://groups.google.com/forum/#!forum/gitlabh **Search** for similar issues before posting your own, there's a good chance somebody else had the same issue you have now and had it resolved. -## Paid support +## Support options Community support in the [Support Forum](https://groups.google.com/forum/#!forum/gitlabhq) is done by volunteers. A support subscription is available from [GitLab.com](http://blog.gitlab.com/subscription/) @@ -29,6 +29,8 @@ Feature suggestions don't belong in issues but can go to [Feedback forum](http:/ ## Pull requests +You can submit a pull request if you have made an improvement to GitLab. The issues we would really like a pull request for are listed with the [status 'accepting merge/pull requests' on our feedback forum](http://feedback.gitlab.com/forums/176466-general/status/796455). + Code speaks louder than words. If you can please submit a pull request with the fix including tests. The workflow to make a pull request is as follows: 1. Fork the project on GitHub From 5f14a6bcf8ca5ec4325bae401069c3a03a617bd0 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 27 Mar 2013 18:26:37 +0200 Subject: [PATCH 080/152] annotated --- app/models/project.rb | 1 + app/models/user.rb | 1 + spec/models/project_spec.rb | 1 + spec/models/user_spec.rb | 1 + 4 files changed, 4 insertions(+) diff --git a/app/models/project.rb b/app/models/project.rb index 0bb1003a..0da35b5d 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -18,6 +18,7 @@ # public :boolean default(FALSE), not null # issues_tracker :string(255) default("gitlab"), not null # issues_tracker_id :string(255) +# snippets_enabled :boolean default(TRUE), not null # require "grit" diff --git a/app/models/user.rb b/app/models/user.rb index 30bd8f47..4718e24d 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -33,6 +33,7 @@ # can_create_team :boolean default(TRUE), not null # state :string(255) # color_scheme_id :integer default(1), not null +# notification_level :integer default(1), not null # class User < ActiveRecord::Base diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 9423c7de..e6585f78 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -18,6 +18,7 @@ # public :boolean default(FALSE), not null # issues_tracker :string(255) default("gitlab"), not null # issues_tracker_id :string(255) +# snippets_enabled :boolean default(TRUE), not null # require 'spec_helper' diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 7d061bf2..4e276dea 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -33,6 +33,7 @@ # can_create_team :boolean default(TRUE), not null # state :string(255) # color_scheme_id :integer default(1), not null +# notification_level :integer default(1), not null # require 'spec_helper' From d55ade16861d0700e302f50945560e8570eddcd7 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 27 Mar 2013 19:04:29 +0200 Subject: [PATCH 081/152] notification scaffold --- app/controllers/notifications_controller.rb | 11 ++++++++ app/helpers/notifications_helper.rb | 2 ++ app/models/notification.rb | 30 +++++++++++++++++++++ app/models/user.rb | 14 +++++----- app/views/layouts/profile.html.haml | 2 ++ app/views/notifications/show.html.haml | 26 ++++++++++++++++++ config/routes.rb | 2 ++ spec/helpers/notifications_helper_spec.rb | 15 +++++++++++ spec/requests/notifications_spec.rb | 11 ++++++++ spec/routing/notifications_routing_spec.rb | 13 +++++++++ 10 files changed, 119 insertions(+), 7 deletions(-) create mode 100644 app/controllers/notifications_controller.rb create mode 100644 app/helpers/notifications_helper.rb create mode 100644 app/models/notification.rb create mode 100644 app/views/notifications/show.html.haml create mode 100644 spec/helpers/notifications_helper_spec.rb create mode 100644 spec/requests/notifications_spec.rb create mode 100644 spec/routing/notifications_routing_spec.rb diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb new file mode 100644 index 00000000..d2edb6a6 --- /dev/null +++ b/app/controllers/notifications_controller.rb @@ -0,0 +1,11 @@ +class NotificationsController < ApplicationController + layout 'profile' + + def show + @notification = current_user.notification + end + + def update + @notification = current_user.notification + end +end diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb new file mode 100644 index 00000000..7342393a --- /dev/null +++ b/app/helpers/notifications_helper.rb @@ -0,0 +1,2 @@ +module NotificationsHelper +end diff --git a/app/models/notification.rb b/app/models/notification.rb new file mode 100644 index 00000000..bfd1e2cf --- /dev/null +++ b/app/models/notification.rb @@ -0,0 +1,30 @@ +class Notification + # + # Notification levels + # + N_DISABLED = 0 + N_PARTICIPATING = 1 + N_WATCH = 2 + + attr_accessor :user + + def self.notification_levels + [N_DISABLED, N_PARTICIPATING, N_WATCH] + end + + def initialize(user) + @user = user + end + + def disabled? + user.notification_level == N_DISABLED + end + + def participating? + user.notification_level == N_PARTICIPATING + end + + def watch? + user.notification_level == N_WATCH + end +end diff --git a/app/models/user.rb b/app/models/user.rb index 4718e24d..dcbf5812 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -54,13 +54,6 @@ class User < ActiveRecord::Base attr_accessible :login - # - # Notification levels - # - N_DISABLED = 0 - N_PARTICIPATING = 1 - N_WATCH = 2 - # # Relations # @@ -116,6 +109,9 @@ class User < ActiveRecord::Base format: { with: Gitlab::Regex.username_regex, message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" } + validates :notification_level, + inclusion: { in: Notification.notification_levels }, + presence: true validate :namespace_uniq, if: ->(user) { user.username_changed? } @@ -216,6 +212,10 @@ class User < ActiveRecord::Base username end + def notification + @notification ||= Notification.new(self) + end + def generate_password if self.force_random_password self.password = self.password_confirmation = Devise.friendly_token.first(8) diff --git a/app/views/layouts/profile.html.haml b/app/views/layouts/profile.html.haml index 611063e8..a7225baa 100644 --- a/app/views/layouts/profile.html.haml +++ b/app/views/layouts/profile.html.haml @@ -11,6 +11,8 @@ %i.icon-home = nav_link(path: 'profiles#account') do = link_to "Account", account_profile_path + = nav_link(controller: :notifications) do + = link_to "Notifications", profile_notifications_path = nav_link(controller: :keys) do = link_to keys_path do SSH Keys diff --git a/app/views/notifications/show.html.haml b/app/views/notifications/show.html.haml new file mode 100644 index 00000000..7ceb1926 --- /dev/null +++ b/app/views/notifications/show.html.haml @@ -0,0 +1,26 @@ +%h3.page_title Setup your notification level +%hr + + += form_tag profile_notifications_path do + + %ul.unstyled + %li + .row + .span3 + %h5 Global + .span9 + = label_tag do + = radio_button_tag :notification_level, Notification::N_DISABLED, @notification.disabled? + %span Disabled + + = label_tag do + = radio_button_tag :notification_level, Notification::N_PARTICIPATING, @notification.participating? + %span Participating + + = label_tag do + = radio_button_tag :notification_level, Notification::N_WATCH, @notification.watch? + %span Watch + + .form-actions + = submit_tag 'Save', class: 'btn btn-save' diff --git a/config/routes.rb b/config/routes.rb index 25eb75a1..61a604b9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -110,6 +110,8 @@ Gitlab::Application.routes.draw do put :reset_private_token put :update_username end + + resource :notifications end resources :keys diff --git a/spec/helpers/notifications_helper_spec.rb b/spec/helpers/notifications_helper_spec.rb new file mode 100644 index 00000000..f97959ee --- /dev/null +++ b/spec/helpers/notifications_helper_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +# Specs in this file have access to a helper object that includes +# the NotificationsHelper. For example: +# +# describe NotificationsHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# helper.concat_strings("this","that").should == "this that" +# end +# end +# end +describe NotificationsHelper do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/requests/notifications_spec.rb b/spec/requests/notifications_spec.rb new file mode 100644 index 00000000..07db7c05 --- /dev/null +++ b/spec/requests/notifications_spec.rb @@ -0,0 +1,11 @@ +require 'spec_helper' + +describe "Notifications" do + describe "GET /notifications" do + it "works! (now write some real specs)" do + # Run the generator again with the --webrat flag if you want to use webrat methods/matchers + get notifications_path + response.status.should be(200) + end + end +end diff --git a/spec/routing/notifications_routing_spec.rb b/spec/routing/notifications_routing_spec.rb new file mode 100644 index 00000000..6880d281 --- /dev/null +++ b/spec/routing/notifications_routing_spec.rb @@ -0,0 +1,13 @@ +require "spec_helper" + +describe NotificationsController do + describe "routing" do + it "routes to #show" do + get("/profile/notifications").should route_to("notifications#show") + end + + it "routes to #update" do + put("/profile/notifications").should route_to("notifications#update") + end + end +end From ba59912072efb1e648e94d4c2cc2c2d0625f74db Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 27 Mar 2013 20:07:52 +0200 Subject: [PATCH 082/152] Prepare UI for notification settings --- .../behaviors/toggler_behavior.coffee | 8 +++ .../javascripts/extensions/jquery.js.coffee | 9 ++++ app/assets/javascripts/main.js.coffee | 2 + app/assets/javascripts/profile.js.coffee | 6 ++- app/controllers/notifications_controller.rb | 4 +- app/views/notifications/show.html.haml | 54 ++++++++++++++++--- app/views/notifications/update.js.haml | 7 +++ spec/requests/notifications_spec.rb | 11 ---- 8 files changed, 81 insertions(+), 20 deletions(-) create mode 100644 app/assets/javascripts/extensions/jquery.js.coffee create mode 100644 app/views/notifications/update.js.haml delete mode 100644 spec/requests/notifications_spec.rb diff --git a/app/assets/javascripts/behaviors/toggler_behavior.coffee b/app/assets/javascripts/behaviors/toggler_behavior.coffee index 3fefbf8e..d2181e7b 100644 --- a/app/assets/javascripts/behaviors/toggler_behavior.coffee +++ b/app/assets/javascripts/behaviors/toggler_behavior.coffee @@ -3,3 +3,11 @@ $ -> container = $(@).closest(".js-toggler-container") container.toggleClass("on") + + $("body").on "click", ".js-toggle-visibility-link", (e) -> + $(@).find('i'). + toggleClass('icon-chevron-down'). + toggleClass('icon-chevron-up') + container = $(".js-toggle-visibility-container") + container.toggleClass("hide") + e.preventDefault() diff --git a/app/assets/javascripts/extensions/jquery.js.coffee b/app/assets/javascripts/extensions/jquery.js.coffee new file mode 100644 index 00000000..8a997fe3 --- /dev/null +++ b/app/assets/javascripts/extensions/jquery.js.coffee @@ -0,0 +1,9 @@ +$.fn.showAndHide = -> + $(@).show(). + delay(3000). + fadeOut() + +$.fn.enableButton = -> + $(@).removeAttr('disabled'). + removeClass('disabled') + diff --git a/app/assets/javascripts/main.js.coffee b/app/assets/javascripts/main.js.coffee index b61df846..39ec86e6 100644 --- a/app/assets/javascripts/main.js.coffee +++ b/app/assets/javascripts/main.js.coffee @@ -7,6 +7,8 @@ window.slugify = (text) -> window.ajaxGet = (url) -> $.ajax({type: "GET", url: url, dataType: "script"}) +window.showAndHide = (selector) -> + window.errorMessage = (message) -> ehtml = $("

") ehtml.addClass("error_message") diff --git a/app/assets/javascripts/profile.js.coffee b/app/assets/javascripts/profile.js.coffee index 42207a39..213133bc 100644 --- a/app/assets/javascripts/profile.js.coffee +++ b/app/assets/javascripts/profile.js.coffee @@ -15,6 +15,8 @@ $ -> $(this).find('.update-failed').hide() $('.update-username form').on 'ajax:complete', -> - $(this).find('.save-btn').removeAttr('disabled') - $(this).find('.save-btn').removeClass('disabled') + $(this).find('.btn-save').enableButton() $(this).find('.loading-gif').hide() + + $('.update-notifications').on 'ajax:complete', -> + $(this).find('.btn-save').enableButton() diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb index d2edb6a6..e44e0aa8 100644 --- a/app/controllers/notifications_controller.rb +++ b/app/controllers/notifications_controller.rb @@ -3,9 +3,11 @@ class NotificationsController < ApplicationController def show @notification = current_user.notification + @projects = current_user.authorized_projects end def update - @notification = current_user.notification + current_user.notification_level = params[:notification_level] + @saved = current_user.save end end diff --git a/app/views/notifications/show.html.haml b/app/views/notifications/show.html.haml index 7ceb1926..d8ab93b8 100644 --- a/app/views/notifications/show.html.haml +++ b/app/views/notifications/show.html.haml @@ -1,15 +1,25 @@ %h3.page_title Setup your notification level + +%br + +%p.light + %strong Disabled + – You will not get any notifications via email +%p.light + %strong Participating + – You will receive only notifications from related resources(ex. from assigned issue or your commit) +%p.light + %strong Watch + – You will receive all notifications from projects in which you participate %hr - -= form_tag profile_notifications_path do - - %ul.unstyled += form_tag profile_notifications_path, method: :put, remote: true, class: 'update-notifications' do + %ul.well-list %li .row - .span3 + .span4 %h5 Global - .span9 + .span7 = label_tag do = radio_button_tag :notification_level, Notification::N_DISABLED, @notification.disabled? %span Disabled @@ -22,5 +32,37 @@ = radio_button_tag :notification_level, Notification::N_WATCH, @notification.watch? %span Watch + + = link_to '#', class: 'js-toggle-visibility-link' do + %h6.btn.btn-tiny + %i.icon-chevron-down + %span Per project notifications settings + %ul.well-list.js-toggle-visibility-container.hide + - @projects.each do |project| + %li + .row + .span4 + %span + = project.name_with_namespace + .span7 + = label_tag do + = radio_button_tag :"notification_level[#{project.id}]", Notification::N_DISABLED, @notification.disabled?, disabled: true + %span Disabled + + = label_tag do + = radio_button_tag :"notification_level[#{project.id}]", Notification::N_PARTICIPATING, @notification.participating?, disabled: true + %span Participating + + = label_tag do + = radio_button_tag :"notification_level[#{project.id}]", Notification::N_WATCH, @notification.watch?, disabled: true + %span Watch + + .form-actions = submit_tag 'Save', class: 'btn btn-save' + %span.update-success.cgreen.hide + %i.icon-ok + Saved + %span.update-failed.cred.hide + %i.icon-remove + Failed diff --git a/app/views/notifications/update.js.haml b/app/views/notifications/update.js.haml new file mode 100644 index 00000000..4468004a --- /dev/null +++ b/app/views/notifications/update.js.haml @@ -0,0 +1,7 @@ +- if @saved + :plain + $('.update-notifications .update-success').showAndHide(); +- else + :plain + $('.update-notifications .update-failed').showAndHide(); + diff --git a/spec/requests/notifications_spec.rb b/spec/requests/notifications_spec.rb deleted file mode 100644 index 07db7c05..00000000 --- a/spec/requests/notifications_spec.rb +++ /dev/null @@ -1,11 +0,0 @@ -require 'spec_helper' - -describe "Notifications" do - describe "GET /notifications" do - it "works! (now write some real specs)" do - # Run the generator again with the --webrat flag if you want to use webrat methods/matchers - get notifications_path - response.status.should be(200) - end - end -end From 0a044c7318ada48999bcf61cc95ab65b0d1435ca Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 27 Mar 2013 20:28:00 +0200 Subject: [PATCH 083/152] NotificationService respects disabled notifications now --- app/services/notification_service.rb | 62 +++++++++++++++++++--------- 1 file changed, 43 insertions(+), 19 deletions(-) diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 37c8345e..4c543cc4 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -8,6 +8,9 @@ class NotificationService # Always notify user about ssh key added # only if ssh key is not deploy key + # + # This is security email so it will be sent + # even if user disabled notifications def new_key(key) if key.user Notify.delay.new_ssh_key_email(key.id) @@ -21,10 +24,10 @@ class NotificationService # * project team members with notification level higher then Participating # def close_issue(issue, current_user) - recipients = [issue.author, issue.assignee].compact.uniq + recipients = reject_muted_users([issue.author, issue.assignee]) # Dont send email to me when I close an issue - recipients.reject! { |u| u == current_user } + recipients.delete(current_user) recipients.each do |recipient| Notify.delay.issue_status_changed_email(recipient.id, issue.id, issue.state, current_user.id) @@ -37,14 +40,7 @@ class NotificationService # * issue new assignee if his notification level is not Disabled # def reassigned_issue(issue, current_user) - recipient_ids = [issue.assignee_id, issue.assignee_id_was].compact.uniq - - # Reject me from recipients if I reassign an issue - recipient_ids.reject! { |id| id == current_user.id } - - recipient_ids.each do |recipient_id| - Notify.delay.reassigned_issue_email(recipient_id, issue.id, issue.assignee_id_was) - end + reassign_email(merge_request, current_user, 'reassigned_issue_email') end # When create an issue we should send next emails: @@ -52,7 +48,11 @@ class NotificationService # * issue assignee if his notification level is not Disabled # def new_issue(issue, current_user) + if issue.assignee && issue.assignee != current_user + # skip if assignee notification disabled + return true if issue.assignee.notification.disabled? + Notify.delay.new_issue_email(issue.id) end end @@ -63,6 +63,9 @@ class NotificationService # def new_merge_request(merge_request, current_user) if merge_request.assignee && merge_request.assignee != current_user + # skip if assignee notification disabled + return true if merge_request.assignee.notification.disabled? + Notify.delay.new_merge_request_email(merge_request.id) end end @@ -73,12 +76,7 @@ class NotificationService # * merge_request assignee if his notification level is not Disabled # def reassigned_merge_request(merge_request, current_user) - recipients_ids = merge_request.assignee_id_was, merge_request.assignee_id - recipients_ids.delete current_user.id - - recipients_ids.each do |recipient_id| - Notify.delay.reassigned_merge_request_email(recipient_id, merge_request.id, merge_request.assignee_id_was) - end + reassign_email(merge_request, current_user, 'reassigned_merge_request_email') end # Notify new user with email after creation @@ -93,15 +91,17 @@ class NotificationService # def new_note(note) if note.notify - users = note.project.users.reject { |u| u.id == note.author.id } + users = note.project.users + users = reject_muted_users(users) + users.delete(note.author) # Note: wall posts are not "attached" to anything, so fall back to "Wall" noteable_type = note.noteable_type.presence || "Wall" notify_method = "note_#{noteable_type.underscore}_email".to_sym if Notify.respond_to? notify_method - team_without_note_author(note).map do |u| - Notify.delay.send(notify_method, u.id, note.id) + users.each do |user| + Notify.delay.send(notify_method, user.id, note.id) end end elsif note.notify_author && note.commit_author @@ -116,4 +116,28 @@ class NotificationService def update_team_member(users_project) Notify.delay.project_access_granted_email(users_project.id) end + + protected + + # Remove users with disabled notifications from array + # Also remove duplications and nil recipients + def reject_muted_users(users) + users.compact.uniq.reject do |user| + user.notification.disabled? + end + end + + def reassign_email(target, current_user, entity_sym) + recipients = User.where(id: [target.assignee_id, target.assignee_id_was]) + + # reject users with disabled notifications + recipients = reject_muted_users(recipients) + + # Reject me from recipients if I reassign an item + recipients.delete(current_user) + + recipients.each do |recipient_id| + Notify.delay.send(method, recipient.id, target.id, target.assignee_id_was) + end + end end From f230fe3ddab86130af57671b325ff83984d62117 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 27 Mar 2013 21:42:01 +0200 Subject: [PATCH 084/152] Fix NotificationService NameError for new issue --- app/services/notification_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 4c543cc4..cb302efa 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -40,7 +40,7 @@ class NotificationService # * issue new assignee if his notification level is not Disabled # def reassigned_issue(issue, current_user) - reassign_email(merge_request, current_user, 'reassigned_issue_email') + reassign_email(issue, current_user, 'reassigned_issue_email') end # When create an issue we should send next emails: From ed7a2136dd311829196db8631d28720ca756dc19 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 27 Mar 2013 21:51:40 +0200 Subject: [PATCH 085/152] update sidekiq --- Gemfile.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index a81404b9..d872cd96 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -137,7 +137,7 @@ GEM eventmachine (1.0.0) execjs (1.4.0) multi_json (~> 1.0) - facter (1.6.17) + facter (1.6.18) factory_girl (4.1.0) activesupport (>= 3.0.0) factory_girl_rails (4.1.0) @@ -257,7 +257,7 @@ GEM mime-types (1.21) modernizr (2.6.2) sprockets (~> 2.0) - multi_json (1.7.1) + multi_json (1.7.2) multi_xml (0.5.3) multipart-post (1.1.5) mustache (0.99.4) @@ -357,7 +357,7 @@ GEM rdoc (3.12.2) json (~> 1.4) redcarpet (2.2.2) - redis (3.0.2) + redis (3.0.3) redis-actionpack (3.2.3) actionpack (~> 3.2.3) redis-rack (~> 1.4.0) @@ -421,7 +421,7 @@ GEM sexp_processor (4.1.3) shoulda-matchers (1.3.0) activesupport (>= 3.0.0) - sidekiq (2.7.5) + sidekiq (2.8.0) celluloid (~> 0.12.0) connection_pool (~> 1.0) multi_json (~> 1) From 9e24929f162249ad2b2bfb8905be416d7148b40d Mon Sep 17 00:00:00 2001 From: Colin Dean Date: Wed, 27 Mar 2013 15:55:10 -0400 Subject: [PATCH 086/152] fix typo: shure -> sure --- app/views/team_members/_assigned_team.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/team_members/_assigned_team.html.haml b/app/views/team_members/_assigned_team.html.haml index 1d512c44..51a31a64 100644 --- a/app/views/team_members/_assigned_team.html.haml +++ b/app/views/team_members/_assigned_team.html.haml @@ -1,7 +1,7 @@ %li{id: dom_id(team), class: "user_team_row team_#{team.id}"} .pull-right - if can?(current_user, :admin_team_member, @project) - = link_to resign_project_team_path(@project, team), method: :delete, confirm: "Are you shure?", class: "btn btn-remove btn-tiny" do + = link_to resign_project_team_path(@project, team), method: :delete, confirm: "Are you sure?", class: "btn btn-remove btn-tiny" do %i.icon-minus.icon-white %strong= link_to team.name, team_path(team), title: team.name, class: "dark" From 2b2d43ed2a91b9a82608d26a6ece70929009b5ed Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 27 Mar 2013 22:21:32 +0200 Subject: [PATCH 087/152] Update develoment dependencies --- Gemfile | 6 ++--- Gemfile.lock | 68 +++++++++++++++++++++++++++------------------------- 2 files changed, 38 insertions(+), 36 deletions(-) diff --git a/Gemfile b/Gemfile index efa4be7c..035942fa 100644 --- a/Gemfile +++ b/Gemfile @@ -153,9 +153,9 @@ end group :development, :test do gem 'coveralls', require: false gem 'rails-dev-tweaks' - gem 'spinach-rails', '0.2.0' - gem "rspec-rails", '2.12.2' - gem "capybara", '2.0.2' + gem 'spinach-rails' + gem "rspec-rails" + gem "capybara" gem "pry" gem "awesome_print" gem "database_cleaner" diff --git a/Gemfile.lock b/Gemfile.lock index d872cd96..fca92716 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -95,7 +95,7 @@ GEM thor (~> 0.14) code_analyzer (0.3.1) sexp_processor - coderay (1.0.8) + coderay (1.0.9) coffee-rails (3.2.2) coffee-script (>= 2.2.0) railties (~> 3.2.0) @@ -122,7 +122,7 @@ GEM orm_adapter (~> 0.1) railties (~> 3.1) warden (~> 1.2.1) - diff-lcs (1.1.3) + diff-lcs (1.2.1) draper (1.1.0) actionpack (>= 3.0) activesupport (>= 3.0) @@ -201,12 +201,13 @@ GEM grit_ext (0.8.1) charlock_holmes (~> 0.6.9) growl (1.0.3) - guard (1.5.4) - listen (>= 0.4.2) + guard (1.6.2) + listen (>= 0.6.0) lumberjack (>= 1.0.2) pry (>= 0.9.10) + terminal-table (>= 1.4.3) thor (>= 0.14.6) - guard-rspec (2.1.2) + guard-rspec (2.5.1) guard (>= 1.1) rspec (~> 2.11) guard-spinach (0.0.2) @@ -247,8 +248,8 @@ GEM letter_opener (1.0.0) launchy (>= 2.0.4) libv8 (3.3.10.4) - listen (0.5.3) - lumberjack (1.0.2) + listen (0.7.3) + lumberjack (1.0.3) mail (2.5.3) i18n (>= 0.4.0) mime-types (~> 1.16) @@ -297,11 +298,10 @@ GEM http_parser.rb (~> 0.5.3) polyglot (0.3.3) posix-spawn (0.3.6) - progressbar (0.12.0) - pry (0.9.10) + pry (0.9.12) coderay (~> 1.0.5) method_source (~> 0.8) - slop (~> 3.3.1) + slop (~> 3.4) pygments.rb (0.4.2) posix-spawn (~> 0.3.6) yajl-ruby (~> 1.1.0) @@ -334,14 +334,14 @@ GEM rails-dev-tweaks (0.6.1) actionpack (~> 3.1) railties (~> 3.1) - rails_best_practices (1.13.2) + rails_best_practices (1.13.4) activesupport awesome_print code_analyzer colored erubis i18n - progressbar + ruby-progressbar railties (3.2.13) actionpack (= 3.2.13) activesupport (= 3.2.13) @@ -350,7 +350,7 @@ GEM rdoc (~> 3.4) thor (>= 0.14.6, < 2.0) raindrops (0.10.0) - rake (10.0.3) + rake (10.0.4) rb-fsevent (0.9.2) rb-inotify (0.8.8) ffi (>= 0.5.0) @@ -379,27 +379,28 @@ GEM request_store (1.0.5) rest-client (1.6.7) mime-types (>= 1.16) - rspec (2.12.0) - rspec-core (~> 2.12.0) - rspec-expectations (~> 2.12.0) - rspec-mocks (~> 2.12.0) - rspec-core (2.12.0) - rspec-expectations (2.12.0) - diff-lcs (~> 1.1.3) - rspec-mocks (2.12.0) - rspec-rails (2.12.2) + rspec (2.13.0) + rspec-core (~> 2.13.0) + rspec-expectations (~> 2.13.0) + rspec-mocks (~> 2.13.0) + rspec-core (2.13.1) + rspec-expectations (2.13.0) + diff-lcs (>= 1.1.3, < 2.0) + rspec-mocks (2.13.0) + rspec-rails (2.13.0) actionpack (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) - rspec-core (~> 2.12.0) - rspec-expectations (~> 2.12.0) - rspec-mocks (~> 2.12.0) + rspec-core (~> 2.13.0) + rspec-expectations (~> 2.13.0) + rspec-mocks (~> 2.13.0) + ruby-progressbar (1.0.2) rubyntlm (0.1.1) rubyzip (0.9.9) sanitize (2.0.3) nokogiri (>= 1.4.4, < 1.6) - sass (3.2.5) - sass-rails (3.2.5) + sass (3.2.7) + sass-rails (3.2.6) railties (~> 3.2.0) sass (>= 3.1.10) tilt (~> 1.3) @@ -418,7 +419,7 @@ GEM rubyzip websocket (~> 1.0.4) settingslogic (2.0.9) - sexp_processor (4.1.3) + sexp_processor (4.2.0) shoulda-matchers (1.3.0) activesupport (>= 3.0.0) sidekiq (2.8.0) @@ -439,7 +440,7 @@ GEM slim (1.3.6) temple (~> 0.5.5) tilt (~> 1.3.3) - slop (3.3.3) + slop (3.4.4) spinach (0.7.0) colorize gherkin-ruby (~> 0.2.0) @@ -457,6 +458,7 @@ GEM state_machine (1.1.2) stringex (1.5.1) temple (0.5.5) + terminal-table (1.4.5) test_after_commit (0.0.1) therubyracer (0.10.2) libv8 (~> 3.3.10) @@ -464,7 +466,7 @@ GEM daemons (>= 1.0.9) eventmachine (>= 0.12.6) rack (>= 1.0.0) - thor (0.17.0) + thor (0.18.0) tilt (1.3.6) timers (1.1.0) treetop (1.4.12) @@ -502,7 +504,7 @@ DEPENDENCIES better_errors binding_of_caller bootstrap-sass (= 2.2.1.1) - capybara (= 2.0.2) + capybara carrierwave chosen-rails (= 0.9.8) coffee-rails (~> 3.2.2) @@ -562,7 +564,7 @@ DEPENDENCIES rb-inotify redcarpet (~> 2.2.2) redis-rails - rspec-rails (= 2.12.2) + rspec-rails sass-rails (~> 3.2.5) sdoc seed-fu @@ -574,7 +576,7 @@ DEPENDENCIES sinatra six slim - spinach-rails (= 0.2.0) + spinach-rails spork (~> 1.0rc) stamp state_machine From 11d52a15533cf0cbaa4a3a61186f8942d90ce374 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 27 Mar 2013 22:33:59 +0200 Subject: [PATCH 088/152] Fix NotificationService reassign_email method --- app/services/notification_service.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index cb302efa..47d535fe 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -127,7 +127,7 @@ class NotificationService end end - def reassign_email(target, current_user, entity_sym) + def reassign_email(target, current_user, method) recipients = User.where(id: [target.assignee_id, target.assignee_id_was]) # reject users with disabled notifications @@ -136,7 +136,7 @@ class NotificationService # Reject me from recipients if I reassign an item recipients.delete(current_user) - recipients.each do |recipient_id| + recipients.each do |recipient| Notify.delay.send(method, recipient.id, target.id, target.assignee_id_was) end end From 26bd6acadb27275b28ac017faf9c4fc6166274a5 Mon Sep 17 00:00:00 2001 From: Tyler Funk Date: Wed, 27 Mar 2013 22:03:54 -0500 Subject: [PATCH 089/152] Changed the word 'authentification' to 'authentication' --- app/views/projects/_form.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/_form.html.haml b/app/views/projects/_form.html.haml index 01fb6a67..b25cfda2 100644 --- a/app/views/projects/_form.html.haml +++ b/app/views/projects/_form.html.haml @@ -54,7 +54,7 @@ %span.descr If checked, this project can be cloned %em without any - authentification. + authentication. It will also be listed on the #{link_to "public access directory", public_root_path}. %fieldset.features From 9e616459e068f2ba65f90016a09387a192fe4cfc Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Mar 2013 11:59:06 +0200 Subject: [PATCH 090/152] add watchers to email recipients list. Add emails for close/merge MR --- app/observers/merge_request_observer.rb | 6 + app/services/notification_service.rb | 78 ++++++++--- .../closed_merge_request_email.html.haml | 9 ++ .../merged_merge_request_email.html.haml | 9 ++ spec/services/notification_service_spec.rb | 123 ++++++++++++++++-- 5 files changed, 197 insertions(+), 28 deletions(-) create mode 100644 app/views/notify/closed_merge_request_email.html.haml create mode 100644 app/views/notify/merged_merge_request_email.html.haml diff --git a/app/observers/merge_request_observer.rb b/app/observers/merge_request_observer.rb index 15214016..10f30155 100644 --- a/app/observers/merge_request_observer.rb +++ b/app/observers/merge_request_observer.rb @@ -7,6 +7,12 @@ class MergeRequestObserver < BaseObserver def after_close(merge_request, transition) Note.create_status_change_note(merge_request, current_user, merge_request.state) + + notification.close_mr(merge_request, current_user) + end + + def after_merge(merge_request, transition) + notification.merge_mr(merge_request, current_user) end def after_reopen(merge_request, transition) diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 47d535fe..82ecd25e 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -17,7 +17,21 @@ class NotificationService end end - # TODO: When we close an issue we should send next emails: + # When create an issue we should send next emails: + # + # * issue assignee if his notification level is not Disabled + # * project team members with notification level higher then Participating + # + def new_issue(issue, current_user) + recipients = reject_muted_users([issue.assignee]) + recipients = recipients.concat(project_watchers(issue.project)).uniq + + recipients.each do |recipient| + Notify.delay.new_issue_email(recipient.id, issue.id) + end + end + + # When we close an issue we should send next emails: # # * issue author if his notification level is not Disabled # * issue assignee if his notification level is not Disabled @@ -26,6 +40,9 @@ class NotificationService def close_issue(issue, current_user) recipients = reject_muted_users([issue.author, issue.assignee]) + # Add watchers to email list + recipients = recipients.concat(project_watchers(issue.project)).uniq + # Dont send email to me when I close an issue recipients.delete(current_user) @@ -43,30 +60,17 @@ class NotificationService reassign_email(issue, current_user, 'reassigned_issue_email') end - # When create an issue we should send next emails: - # - # * issue assignee if his notification level is not Disabled - # - def new_issue(issue, current_user) - - if issue.assignee && issue.assignee != current_user - # skip if assignee notification disabled - return true if issue.assignee.notification.disabled? - - Notify.delay.new_issue_email(issue.id) - end - end # When create a merge request we should send next emails: # # * mr assignee if his notification level is not Disabled # def new_merge_request(merge_request, current_user) - if merge_request.assignee && merge_request.assignee != current_user - # skip if assignee notification disabled - return true if merge_request.assignee.notification.disabled? + recipients = reject_muted_users([merge_request.assignee]) + recipients = recipients.concat(project_watchers(merge_request.project)).uniq - Notify.delay.new_merge_request_email(merge_request.id) + recipients.each do |recipient| + Notify.delay.new_merge_request_email(recipient.id, merge_request.id) end end @@ -79,6 +83,36 @@ class NotificationService reassign_email(merge_request, current_user, 'reassigned_merge_request_email') end + # When we close a merge request we should send next emails: + # + # * merge_request author if his notification level is not Disabled + # * merge_request assignee if his notification level is not Disabled + # * project team members with notification level higher then Participating + # + def close_mr(merge_request) + recipients = reject_muted_users([merge_request.author, merge_request.assignee]) + recipients = recipients.concat(project_watchers(merge_request.project)).uniq + + recipients.each do |recipient| + Notify.delay.closed_merge_request_email(recipient.id, merge_request.id) + end + end + + # When we merge a merge request we should send next emails: + # + # * merge_request author if his notification level is not Disabled + # * merge_request assignee if his notification level is not Disabled + # * project team members with notification level higher then Participating + # + def merge_mr(merge_request) + recipients = reject_muted_users([merge_request.author, merge_request.assignee]) + recipients = recipients.concat(project_watchers(merge_request.project)).uniq + + recipients.each do |recipient| + Notify.delay.merged_merge_request_email(recipient.id, merge_request.id) + end + end + # Notify new user with email after creation def new_user(user) # Dont email omniauth created users @@ -119,6 +153,11 @@ class NotificationService protected + # Get project users with WATCH notification level + def project_watchers(project) + project.users.where(notification_level: Notification::N_WATCH) + end + # Remove users with disabled notifications from array # Also remove duplications and nil recipients def reject_muted_users(users) @@ -130,6 +169,9 @@ class NotificationService def reassign_email(target, current_user, method) recipients = User.where(id: [target.assignee_id, target.assignee_id_was]) + # Add watchers to email list + recipients = recipients.concat(project_watchers(target.project)) + # reject users with disabled notifications recipients = reject_muted_users(recipients) diff --git a/app/views/notify/closed_merge_request_email.html.haml b/app/views/notify/closed_merge_request_email.html.haml new file mode 100644 index 00000000..c0b08fcc --- /dev/null +++ b/app/views/notify/closed_merge_request_email.html.haml @@ -0,0 +1,9 @@ +%p + = "Merge Request #{@merge_request.id} was closed" +%p + = link_to_gfm truncate(@merge_request.title, length: 40), project_merge_request_url(@merge_request.project, @merge_request) +%p + Branches: #{@merge_request.source_branch} → #{@merge_request.target_branch} +%p + Assignee: #{@merge_request.author_name} → #{@merge_request.assignee_name} + diff --git a/app/views/notify/merged_merge_request_email.html.haml b/app/views/notify/merged_merge_request_email.html.haml new file mode 100644 index 00000000..2b8cc030 --- /dev/null +++ b/app/views/notify/merged_merge_request_email.html.haml @@ -0,0 +1,9 @@ +%p + = "Merge Request #{@merge_request.id} was merged" +%p + = link_to_gfm truncate(@merge_request.title, length: 40), project_merge_request_url(@merge_request.project, @merge_request) +%p + Branches: #{@merge_request.source_branch} → #{@merge_request.target_branch} +%p + Assignee: #{@merge_request.author_name} → #{@merge_request.assignee_name} + diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index e9e4770d..6fe18bb7 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -23,6 +23,10 @@ describe NotificationService do describe 'Issues' do let(:issue) { create :issue, assignee: create(:user) } + before do + build_team(issue.project) + end + describe :new_issue do it 'should sent email to issue assignee' do Notify.should_receive(:new_issue_email).with(issue.id) @@ -31,16 +35,41 @@ describe NotificationService do end describe :reassigned_issue do - it 'should sent email to issue old assignee and new issue assignee' do - Notify.should_receive(:reassigned_issue_email) - notification.reassigned_issue(issue, issue.author) + it 'should email new assignee' do + should_email(issue.assignee_id) + should_email(@u_watcher.id) + should_not_email(@u_participating.id) + should_not_email(@u_disabled.id) + + notification.reassigned_issue(issue, @u_disabled) + end + + def should_email(user_id) + Notify.should_receive(:reassigned_issue_email).with(user_id, issue.id, issue.assignee_id) + end + + def should_not_email(user_id) + Notify.should_not_receive(:reassigned_issue_email).with(user_id, issue.id, issue.assignee_id) end end describe :close_issue do it 'should sent email to issue assignee and issue author' do - Notify.should_receive(:issue_status_changed_email) - notification.close_issue(issue, issue.author) + should_email(issue.assignee_id) + should_email(issue.author_id) + should_email(@u_watcher.id) + should_not_email(@u_participating.id) + should_not_email(@u_disabled.id) + + notification.close_issue(issue, @u_disabled) + end + + def should_email(user_id) + Notify.should_receive(:issue_status_changed_email).with(user_id, issue.id, issue.assignee_id) + end + + def should_not_email(user_id) + Notify.should_not_receive(:issue_status_changed_email).with(user_id, issue.id, issue.assignee_id) end end end @@ -48,16 +77,90 @@ describe NotificationService do describe 'Merge Requests' do let(:merge_request) { create :merge_request, assignee: create(:user) } + before do + build_team(merge_request.project) + end + describe :new_merge_request do - it 'should send email to merge_request assignee' do - Notify.should_receive(:new_merge_request_email).with(merge_request.id) - notification.new_merge_request(merge_request, merge_request.author) + it do + should_email(merge_request.assignee_id) + should_email(@u_watcher.id) + should_not_email(@u_participating.id) + should_not_email(@u_disabled.id) + notification.new_merge_request(merge_request, @u_disabled) end - it 'should not send email to merge_request assignee if he is current_user' do + def should_email(user_id) + Notify.should_receive(:new_merge_request_email).with(merge_request.id) + end + + def should_not_email(user_id) Notify.should_not_receive(:new_merge_request_email).with(merge_request.id) - notification.new_merge_request(merge_request, merge_request.assignee) + end + end + + describe :reassigned_merge_request do + it do + should_email(merge_request.assignee_id) + should_email(@u_watcher.id) + should_not_email(@u_participating.id) + should_not_email(@u_disabled.id) + notification.reassigned_merge_request(merge_request, merge_request.author) + end + + def should_email(user_id) + Notify.should_receive(:reassigned_merge_request_email).with(user_id, merge_request.id, merge_request.assignee_id) + end + + def should_not_email(user_id) + Notify.should_not_receive(:reassigned_merge_request_email).with(user_id, merge_request.id, merge_request.assignee_id) + end + end + + describe :closed_merge_request do + it do + should_email(merge_request.assignee_id) + should_email(@u_watcher.id) + should_not_email(@u_participating.id) + should_not_email(@u_disabled.id) + notification.close_mr(merge_request) + end + + def should_email(user_id) + Notify.should_receive(:closed_merge_request_email).with(user_id, merge_request.id) + end + + def should_not_email(user_id) + Notify.should_not_receive(:closed_merge_request_email).with(user_id, merge_request.id) + end + end + + describe :merged_merge_request do + it do + should_email(merge_request.assignee_id) + should_email(@u_watcher.id) + should_not_email(@u_participating.id) + should_not_email(@u_disabled.id) + notification.merge_mr(merge_request) + end + + def should_email(user_id) + Notify.should_receive(:merged_merge_request_email).with(user_id, merge_request.id) + end + + def should_not_email(user_id) + Notify.should_not_receive(:merged_merge_request_email).with(user_id, merge_request.id) end end end + + def build_team(project) + @u_watcher = create(:user, notification_level: Notification::N_WATCH) + @u_participating = create(:user, notification_level: Notification::N_PARTICIPATING) + @u_disabled = create(:user, notification_level: Notification::N_DISABLED) + + project.team << [@u_watcher, :master] + project.team << [@u_participating, :master] + project.team << [@u_disabled, :master] + end end From f49a2ac0df978eaf897a8c8b28a202ae9a01165f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Mar 2013 12:14:53 +0200 Subject: [PATCH 091/152] Add close issue/mr methods to Notify. Refactored Notificationservice --- app/mailers/emails/issues.rb | 8 +++ app/mailers/emails/merge_requests.rb | 13 ++++ app/observers/merge_request_observer.rb | 2 +- app/services/notification_service.rb | 61 +++++++++---------- app/views/notify/closed_issue_email.html.haml | 5 ++ .../closed_merge_request_email.html.haml | 2 +- spec/services/notification_service_spec.rb | 6 +- 7 files changed, 59 insertions(+), 38 deletions(-) create mode 100644 app/views/notify/closed_issue_email.html.haml diff --git a/app/mailers/emails/issues.rb b/app/mailers/emails/issues.rb index 5b69886f..dc0381f5 100644 --- a/app/mailers/emails/issues.rb +++ b/app/mailers/emails/issues.rb @@ -13,6 +13,14 @@ module Emails mail(to: recipient(recipient_id), subject: subject("changed issue ##{@issue.id}", @issue.title)) end + def close_issue_email(recipient_id, issue_id, updated_by_user_id) + @issue = Issue.find issue_id + @project = @issue.project + @updated_by = User.find updated_by_user_id + mail(to: recipient(recipient_id), + subject: subject("Closed issue ##{@issue.id}", @issue.title)) + end + def issue_status_changed_email(recipient_id, issue_id, status, updated_by_user_id) @issue = Issue.find issue_id @issue_status = status diff --git a/app/mailers/emails/merge_requests.rb b/app/mailers/emails/merge_requests.rb index 35890460..76a0ae55 100644 --- a/app/mailers/emails/merge_requests.rb +++ b/app/mailers/emails/merge_requests.rb @@ -12,5 +12,18 @@ module Emails @project = @merge_request.project mail(to: recipient(recipient_id), subject: subject("changed merge request !#{@merge_request.id}", @merge_request.title)) end + + def closed_merge_request_email(recipient_id, merge_request_id, updated_by_user_id) + @merge_request = MergeRequest.find(merge_request_id) + @project = @merge_request.project + @updated_by = User.find updated_by_user_id + mail(to: recipient(recipient_id), subject: subject("Closed merge request !#{@merge_request.id}", @merge_request.title)) + end + + def merged_merge_request_email(recipient_id, merge_request_id) + @merge_request = MergeRequest.find(merge_request_id) + @project = @merge_request.project + mail(to: recipient(recipient_id), subject: subject("Accepted merge request !#{@merge_request.id}", @merge_request.title)) + end end end diff --git a/app/observers/merge_request_observer.rb b/app/observers/merge_request_observer.rb index 10f30155..e10e5049 100644 --- a/app/observers/merge_request_observer.rb +++ b/app/observers/merge_request_observer.rb @@ -12,7 +12,7 @@ class MergeRequestObserver < BaseObserver end def after_merge(merge_request, transition) - notification.merge_mr(merge_request, current_user) + notification.merge_mr(merge_request) end def after_reopen(merge_request, transition) diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 82ecd25e..c53a6cc5 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -23,12 +23,7 @@ class NotificationService # * project team members with notification level higher then Participating # def new_issue(issue, current_user) - recipients = reject_muted_users([issue.assignee]) - recipients = recipients.concat(project_watchers(issue.project)).uniq - - recipients.each do |recipient| - Notify.delay.new_issue_email(recipient.id, issue.id) - end + new_resource_email(issue, 'new_issue_email') end # When we close an issue we should send next emails: @@ -38,17 +33,7 @@ class NotificationService # * project team members with notification level higher then Participating # def close_issue(issue, current_user) - recipients = reject_muted_users([issue.author, issue.assignee]) - - # Add watchers to email list - recipients = recipients.concat(project_watchers(issue.project)).uniq - - # Dont send email to me when I close an issue - recipients.delete(current_user) - - recipients.each do |recipient| - Notify.delay.issue_status_changed_email(recipient.id, issue.id, issue.state, current_user.id) - end + close_resource_email(issue, current_user, 'close_issue_email') end # When we reassign an issue we should send next emails: @@ -57,7 +42,7 @@ class NotificationService # * issue new assignee if his notification level is not Disabled # def reassigned_issue(issue, current_user) - reassign_email(issue, current_user, 'reassigned_issue_email') + reassign_resource_email(issue, current_user, 'reassigned_issue_email') end @@ -66,12 +51,7 @@ class NotificationService # * mr assignee if his notification level is not Disabled # def new_merge_request(merge_request, current_user) - recipients = reject_muted_users([merge_request.assignee]) - recipients = recipients.concat(project_watchers(merge_request.project)).uniq - - recipients.each do |recipient| - Notify.delay.new_merge_request_email(recipient.id, merge_request.id) - end + new_resource_email(merge_request, 'new_merge_request_email') end # When we reassign a merge_request we should send next emails: @@ -80,7 +60,7 @@ class NotificationService # * merge_request assignee if his notification level is not Disabled # def reassigned_merge_request(merge_request, current_user) - reassign_email(merge_request, current_user, 'reassigned_merge_request_email') + reassign_resource_email(merge_request, current_user, 'reassigned_merge_request_email') end # When we close a merge request we should send next emails: @@ -89,13 +69,8 @@ class NotificationService # * merge_request assignee if his notification level is not Disabled # * project team members with notification level higher then Participating # - def close_mr(merge_request) - recipients = reject_muted_users([merge_request.author, merge_request.assignee]) - recipients = recipients.concat(project_watchers(merge_request.project)).uniq - - recipients.each do |recipient| - Notify.delay.closed_merge_request_email(recipient.id, merge_request.id) - end + def close_mr(merge_request, current_user) + close_resource_email(merge_request, current_user, 'closed_merge_request_email') end # When we merge a merge request we should send next emails: @@ -166,7 +141,27 @@ class NotificationService end end - def reassign_email(target, current_user, method) + def new_resource_email(target, method) + recipients = reject_muted_users([target.assignee]) + recipients = recipients.concat(project_watchers(target.project)).uniq + recipients.delete(target.author) + + recipients.each do |recipient| + Notify.delay.send(method, recipient.id, target.id) + end + end + + def close_resource_email(target, current_user, method) + recipients = reject_muted_users([target.author, target.assignee]) + recipients = recipients.concat(project_watchers(target.project)).uniq + recipients.delete(current_user) + + recipients.each do |recipient| + Notify.delay.send(method, recipient.id, target.id, current_user.id) + end + end + + def reassign_resource_email(target, current_user, method) recipients = User.where(id: [target.assignee_id, target.assignee_id_was]) # Add watchers to email list diff --git a/app/views/notify/closed_issue_email.html.haml b/app/views/notify/closed_issue_email.html.haml new file mode 100644 index 00000000..23ccc453 --- /dev/null +++ b/app/views/notify/closed_issue_email.html.haml @@ -0,0 +1,5 @@ +%p + = "Issue was closed by #{@updated_by.name}" +%p + = "Issue ##{@issue.id}" + = link_to_gfm truncate(@issue.title, length: 45), project_issue_url(@issue.project, @issue), title: @issue.title diff --git a/app/views/notify/closed_merge_request_email.html.haml b/app/views/notify/closed_merge_request_email.html.haml index c0b08fcc..0c6c79e0 100644 --- a/app/views/notify/closed_merge_request_email.html.haml +++ b/app/views/notify/closed_merge_request_email.html.haml @@ -1,5 +1,5 @@ %p - = "Merge Request #{@merge_request.id} was closed" + = "Merge Request #{@merge_request.id} was closed by #{@updated_by.name}" %p = link_to_gfm truncate(@merge_request.title, length: 40), project_merge_request_url(@merge_request.project, @merge_request) %p diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index 6fe18bb7..0c6c0144 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -65,11 +65,11 @@ describe NotificationService do end def should_email(user_id) - Notify.should_receive(:issue_status_changed_email).with(user_id, issue.id, issue.assignee_id) + Notify.should_receive(:closed_issue_email).with(user_id, issue.id, issue.assignee_id) end def should_not_email(user_id) - Notify.should_not_receive(:issue_status_changed_email).with(user_id, issue.id, issue.assignee_id) + Notify.should_not_receive(:closed_issue_email).with(user_id, issue.id, issue.assignee_id) end end end @@ -123,7 +123,7 @@ describe NotificationService do should_email(@u_watcher.id) should_not_email(@u_participating.id) should_not_email(@u_disabled.id) - notification.close_mr(merge_request) + notification.close_mr(merge_request, @u_disabled) end def should_email(user_id) From c04120c1c512bd515fceccc70d0c7cf0a6bf4cb7 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Mar 2013 12:24:04 +0200 Subject: [PATCH 092/152] Improve notification service tests --- app/mailers/emails/issues.rb | 2 +- app/services/notification_service.rb | 2 +- spec/services/notification_service_spec.rb | 29 +++++++++++++++------- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/app/mailers/emails/issues.rb b/app/mailers/emails/issues.rb index dc0381f5..74114ffd 100644 --- a/app/mailers/emails/issues.rb +++ b/app/mailers/emails/issues.rb @@ -13,7 +13,7 @@ module Emails mail(to: recipient(recipient_id), subject: subject("changed issue ##{@issue.id}", @issue.title)) end - def close_issue_email(recipient_id, issue_id, updated_by_user_id) + def closed_issue_email(recipient_id, issue_id, updated_by_user_id) @issue = Issue.find issue_id @project = @issue.project @updated_by = User.find updated_by_user_id diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index c53a6cc5..a9978a95 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -33,7 +33,7 @@ class NotificationService # * project team members with notification level higher then Participating # def close_issue(issue, current_user) - close_resource_email(issue, current_user, 'close_issue_email') + close_resource_email(issue, current_user, 'closed_issue_email') end # When we reassign an issue we should send next emails: diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index 0c6c0144..e818277d 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -28,9 +28,20 @@ describe NotificationService do end describe :new_issue do - it 'should sent email to issue assignee' do - Notify.should_receive(:new_issue_email).with(issue.id) - notification.new_issue(issue, nil) + it do + should_email(issue.assignee_id) + should_email(@u_watcher.id) + should_not_email(@u_participating.id) + should_not_email(@u_disabled.id) + notification.new_issue(issue, @u_disabled) + end + + def should_email(user_id) + Notify.should_receive(:new_issue_email).with(user_id, issue.id) + end + + def should_not_email(user_id) + Notify.should_not_receive(:new_issue_email).with(user_id, issue.id) end end @@ -65,11 +76,11 @@ describe NotificationService do end def should_email(user_id) - Notify.should_receive(:closed_issue_email).with(user_id, issue.id, issue.assignee_id) + Notify.should_receive(:closed_issue_email).with(user_id, issue.id, @u_disabled.id) end def should_not_email(user_id) - Notify.should_not_receive(:closed_issue_email).with(user_id, issue.id, issue.assignee_id) + Notify.should_not_receive(:closed_issue_email).with(user_id, issue.id, @u_disabled.id) end end end @@ -91,11 +102,11 @@ describe NotificationService do end def should_email(user_id) - Notify.should_receive(:new_merge_request_email).with(merge_request.id) + Notify.should_receive(:new_merge_request_email).with(user_id, merge_request.id) end def should_not_email(user_id) - Notify.should_not_receive(:new_merge_request_email).with(merge_request.id) + Notify.should_not_receive(:new_merge_request_email).with(user_id, merge_request.id) end end @@ -127,11 +138,11 @@ describe NotificationService do end def should_email(user_id) - Notify.should_receive(:closed_merge_request_email).with(user_id, merge_request.id) + Notify.should_receive(:closed_merge_request_email).with(user_id, merge_request.id, @u_disabled.id) end def should_not_email(user_id) - Notify.should_not_receive(:closed_merge_request_email).with(user_id, merge_request.id) + Notify.should_not_receive(:closed_merge_request_email).with(user_id, merge_request.id, @u_disabled.id) end end From ecf3b2e4710276aa1e12a931960bda2aff6ec95c Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Mar 2013 12:33:54 +0200 Subject: [PATCH 093/152] add text templates to new emails --- app/views/notify/closed_issue_email.text.haml | 3 +++ app/views/notify/closed_merge_request_email.text.haml | 8 ++++++++ app/views/notify/merged_merge_request_email.text.haml | 8 ++++++++ 3 files changed, 19 insertions(+) create mode 100644 app/views/notify/closed_issue_email.text.haml create mode 100644 app/views/notify/closed_merge_request_email.text.haml create mode 100644 app/views/notify/merged_merge_request_email.text.haml diff --git a/app/views/notify/closed_issue_email.text.haml b/app/views/notify/closed_issue_email.text.haml new file mode 100644 index 00000000..0cca3215 --- /dev/null +++ b/app/views/notify/closed_issue_email.text.haml @@ -0,0 +1,3 @@ += "Issue was closed by #{@updated_by.name}" + +Issue ##{@issue.id}: #{project_issue_url(@issue.project, @issue)} diff --git a/app/views/notify/closed_merge_request_email.text.haml b/app/views/notify/closed_merge_request_email.text.haml new file mode 100644 index 00000000..ee4648e3 --- /dev/null +++ b/app/views/notify/closed_merge_request_email.text.haml @@ -0,0 +1,8 @@ += "Merge Request #{@merge_request.id} was closed by #{@updated_by.name}" + +Merge Request url: #{project_merge_request_url(@merge_request.project, @merge_request)} + +Branches: #{@merge_request.source_branch} - #{@merge_request.target_branch} + +Author: #{@merge_request.author_name} +Assignee: #{@merge_request.assignee_name} diff --git a/app/views/notify/merged_merge_request_email.text.haml b/app/views/notify/merged_merge_request_email.text.haml new file mode 100644 index 00000000..91c23360 --- /dev/null +++ b/app/views/notify/merged_merge_request_email.text.haml @@ -0,0 +1,8 @@ += "Merge Request #{@merge_request.id} was merged" + +Merge Request Url: #{project_merge_request_url(@merge_request.project, @merge_request)} + +Branches: #{@merge_request.source_branch} - #{@merge_request.target_branch} + +Author: #{@merge_request.author_name} +Assignee: #{@merge_request.assignee_name} From 2f585840dbf4910d3a4b40c1771ff1dd4525625d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Mar 2013 12:52:44 +0200 Subject: [PATCH 094/152] Fixed new mr/issue emails --- app/mailers/emails/issues.rb | 4 ++-- app/mailers/emails/merge_requests.rb | 4 ++-- app/views/notify/new_issue_email.html.haml | 6 +++++- app/views/notify/new_issue_email.text.erb | 5 +++-- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/app/mailers/emails/issues.rb b/app/mailers/emails/issues.rb index 74114ffd..79731b60 100644 --- a/app/mailers/emails/issues.rb +++ b/app/mailers/emails/issues.rb @@ -1,9 +1,9 @@ module Emails module Issues - def new_issue_email(issue_id) + def new_issue_email(recipient_id, issue_id) @issue = Issue.find(issue_id) @project = @issue.project - mail(to: @issue.assignee_email, subject: subject("new issue ##{@issue.id}", @issue.title)) + mail(to: recipient(recipient_id), subject: subject("new issue ##{@issue.id}", @issue.title)) end def reassigned_issue_email(recipient_id, issue_id, previous_assignee_id) diff --git a/app/mailers/emails/merge_requests.rb b/app/mailers/emails/merge_requests.rb index 76a0ae55..806f1b01 100644 --- a/app/mailers/emails/merge_requests.rb +++ b/app/mailers/emails/merge_requests.rb @@ -1,9 +1,9 @@ module Emails module MergeRequests - def new_merge_request_email(merge_request_id) + def new_merge_request_email(recipient_id, merge_request_id) @merge_request = MergeRequest.find(merge_request_id) @project = @merge_request.project - mail(to: @merge_request.assignee_email, subject: subject("new merge request !#{@merge_request.id}", @merge_request.title)) + mail(to: recipient(recipient_id), subject: subject("new merge request !#{@merge_request.id}", @merge_request.title)) end def reassigned_merge_request_email(recipient_id, merge_request_id, previous_assignee_id) diff --git a/app/views/notify/new_issue_email.html.haml b/app/views/notify/new_issue_email.html.haml index 0c891748..f11c8506 100644 --- a/app/views/notify/new_issue_email.html.haml +++ b/app/views/notify/new_issue_email.html.haml @@ -1,5 +1,9 @@ %p - New Issue was created and assigned to you. + New Issue was created. %p = "Issue ##{@issue.id}" = link_to_gfm truncate(@issue.title, length: 45), project_issue_url(@issue.project, @issue), title: @issue.title +%p + Author: #{@issue.author_name} +%p + Assignee: #{@issue.assignee_name} diff --git a/app/views/notify/new_issue_email.text.erb b/app/views/notify/new_issue_email.text.erb index 5ed55c35..9907ca83 100644 --- a/app/views/notify/new_issue_email.text.erb +++ b/app/views/notify/new_issue_email.text.erb @@ -1,4 +1,5 @@ -New Issue was created and assigned to you. +New Issue was created. - Issue <%= @issue.id %>: <%= url_for(project_issue_url(@issue.project, @issue)) %> +Author: <%= @issue.author_name %> +Asignee: <%= @issue.assignee_name %> From 63e6f055f12a5f955ae3bb7f27b562f89efbd8bb Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Mar 2013 13:24:01 +0200 Subject: [PATCH 095/152] Fix notify specs. Fix merge request close via api --- lib/api/merge_requests.rb | 2 ++ spec/mailers/notify_spec.rb | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb index 234a005a..d5595d5f 100644 --- a/lib/api/merge_requests.rb +++ b/lib/api/merge_requests.rb @@ -94,6 +94,8 @@ module Gitlab authorize! :modify_merge_request, merge_request + MergeRequestObserver.current_user = current_user + if merge_request.update_attributes attrs merge_request.reload_code merge_request.mark_as_unchecked diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index 7867c4dd..472458e8 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -107,7 +107,7 @@ describe Notify do let(:issue) { create(:issue, assignee: assignee, project: project ) } describe 'that are new' do - subject { Notify.new_issue_email(issue.id) } + subject { Notify.new_issue_email(issue.assignee_id, issue.id) } it_behaves_like 'an assignee email' @@ -172,7 +172,7 @@ describe Notify do let(:merge_request) { create(:merge_request, assignee: assignee, project: project) } describe 'that are new' do - subject { Notify.new_merge_request_email(merge_request.id) } + subject { Notify.new_merge_request_email(merge_request.assignee_id, merge_request.id) } it_behaves_like 'an assignee email' From 618249734b1bcb8886b9d96714d278119037261c Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Mar 2013 14:39:59 +0200 Subject: [PATCH 096/152] rebuild notification on notes logic --- app/services/notification_service.rb | 40 ++++++++++++++-------- spec/services/notification_service_spec.rb | 39 +++++++++++++++++++++ 2 files changed, 65 insertions(+), 14 deletions(-) diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index a9978a95..112a0ff0 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -99,22 +99,34 @@ class NotificationService # TODO: split on methods and refactor # def new_note(note) - if note.notify - users = note.project.users - users = reject_muted_users(users) - users.delete(note.author) + # ignore wall messages + return true unless note.noteable_type.present? - # Note: wall posts are not "attached" to anything, so fall back to "Wall" - noteable_type = note.noteable_type.presence || "Wall" - notify_method = "note_#{noteable_type.underscore}_email".to_sym + opts = { noteable_type: note.noteable_type, project_id: note.project_id } - if Notify.respond_to? notify_method - users.each do |user| - Notify.delay.send(notify_method, user.id, note.id) - end - end - elsif note.notify_author && note.commit_author - Notify.delay.note_commit_email(note.commit_author.id, note.id) + if note.commit_id + opts.merge!(commit_id: note.commit_id) + else + opts.merge!(noteable_id: note.noteable_id) + end + + # Get users who left comment in thread + recipients = User.where(id: Note.where(opts).pluck(:author_id)) + + # Merge project watchers + recipients = recipients.concat(project_watchers(note.project)).compact.uniq + + # Reject mutes users + recipients = reject_muted_users(recipients) + + # Reject author + recipients.delete(note.author) + + # build notify method like 'note_commit_email' + notify_method = "note_#{note.noteable_type.underscore}_email".to_sym + + recipients.each do |recipient| + Notify.delay.send(notify_method, recipient.id, note.id) end end diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index e818277d..c82b89d6 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -20,6 +20,45 @@ describe NotificationService do end end + describe 'Notes' do + let(:note) { create :note_on_commit } + + before do + build_team(note.project) + end + + describe :new_note do + it do + should_email(@u_watcher.id) + should_not_email(note.author_id) + should_not_email(@u_participating.id) + should_not_email(@u_disabled.id) + notification.new_note(note) + end + + it do + create(:note_on_commit, + author: @u_participating, + project_id: note.project_id, + commit_id: note.commit_id) + + should_email(@u_watcher.id) + should_email(@u_participating.id) + should_not_email(note.author_id) + should_not_email(@u_disabled.id) + notification.new_note(note) + end + + def should_email(user_id) + Notify.should_receive(:note_commit_email).with(user_id, note.id) + end + + def should_not_email(user_id) + Notify.should_not_receive(:note_commit_email).with(user_id, note.id) + end + end + end + describe 'Issues' do let(:issue) { create :issue, assignee: create(:user) } From 70947fedda4f955f69d928ad0309b3f042056582 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Mar 2013 14:51:25 +0200 Subject: [PATCH 097/152] inslude author & assignee to note notification recipients --- app/services/notification_service.rb | 4 +- spec/services/notification_service_spec.rb | 83 +++++++++++++++------- 2 files changed, 60 insertions(+), 27 deletions(-) diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 112a0ff0..3c3ee39c 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -106,12 +106,14 @@ class NotificationService if note.commit_id opts.merge!(commit_id: note.commit_id) + recipients = [note.commit_author] else opts.merge!(noteable_id: note.noteable_id) + recipients = [note.noteable.try(:author), note.noteable.try(:assignee)] end # Get users who left comment in thread - recipients = User.where(id: Note.where(opts).pluck(:author_id)) + recipients = recipients.concat(User.where(id: Note.where(opts).pluck(:author_id))) # Merge project watchers recipients = recipients.concat(project_watchers(note.project)).compact.uniq diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index c82b89d6..fa47a635 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -21,40 +21,71 @@ describe NotificationService do end describe 'Notes' do - let(:note) { create :note_on_commit } + context 'issue note' do + let(:issue) { create(:issue, assignee: create(:user)) } + let(:note) { create(:note_on_issue, noteable: issue, project_id: issue.project_id) } - before do - build_team(note.project) + before do + build_team(note.project) + end + + describe :new_note do + it do + should_email(@u_watcher.id) + should_email(note.noteable.author_id) + should_email(note.noteable.assignee_id) + should_not_email(note.author_id) + should_not_email(@u_participating.id) + should_not_email(@u_disabled.id) + notification.new_note(note) + end + + def should_email(user_id) + Notify.should_receive(:note_issue_email).with(user_id, note.id) + end + + def should_not_email(user_id) + Notify.should_not_receive(:note_issue_email).with(user_id, note.id) + end + end end - describe :new_note do - it do - should_email(@u_watcher.id) - should_not_email(note.author_id) - should_not_email(@u_participating.id) - should_not_email(@u_disabled.id) - notification.new_note(note) + context 'commit note' do + let(:note) { create :note_on_commit } + + before do + build_team(note.project) end - it do - create(:note_on_commit, - author: @u_participating, - project_id: note.project_id, - commit_id: note.commit_id) + describe :new_note do + it do + should_email(@u_watcher.id) + should_not_email(note.author_id) + should_not_email(@u_participating.id) + should_not_email(@u_disabled.id) + notification.new_note(note) + end - should_email(@u_watcher.id) - should_email(@u_participating.id) - should_not_email(note.author_id) - should_not_email(@u_disabled.id) - notification.new_note(note) - end + it do + create(:note_on_commit, + author: @u_participating, + project_id: note.project_id, + commit_id: note.commit_id) - def should_email(user_id) - Notify.should_receive(:note_commit_email).with(user_id, note.id) - end + should_email(@u_watcher.id) + should_email(@u_participating.id) + should_not_email(note.author_id) + should_not_email(@u_disabled.id) + notification.new_note(note) + end - def should_not_email(user_id) - Notify.should_not_receive(:note_commit_email).with(user_id, note.id) + def should_email(user_id) + Notify.should_receive(:note_commit_email).with(user_id, note.id) + end + + def should_not_email(user_id) + Notify.should_not_receive(:note_commit_email).with(user_id, note.id) + end end end end From 5ad4be295f68310bbd031585bbf6e203084f325e Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Mar 2013 15:39:18 +0200 Subject: [PATCH 098/152] remove notify checkboxes from note forms --- app/assets/stylesheets/sections/notes.scss | 13 +++++++++++-- app/contexts/notes/create_context.rb | 2 -- app/models/note.rb | 11 ----------- app/views/notes/_form.html.haml | 11 +---------- app/views/walls/show.html.haml | 5 ----- 5 files changed, 12 insertions(+), 30 deletions(-) diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss index ae2e1b25..a8628fc5 100644 --- a/app/assets/stylesheets/sections/notes.scss +++ b/app/assets/stylesheets/sections/notes.scss @@ -274,6 +274,15 @@ ul.notes { } +.common-note-form { + margin: 0; + height: 140px; + background: #F9F9F9; + padding: 3px; + padding-bottom: 25px; + border: 1px solid #DDD; +} + .note-form-actions { background: #F9F9F9; @@ -281,8 +290,8 @@ ul.notes { padding: 0 5px; .note-form-option { - margin-top: 8px; - margin-left: 15px; + margin-top: 10px; + margin-left: 30px; @extend .pull-left; } diff --git a/app/contexts/notes/create_context.rb b/app/contexts/notes/create_context.rb index 1367dff4..36ea76ff 100644 --- a/app/contexts/notes/create_context.rb +++ b/app/contexts/notes/create_context.rb @@ -3,8 +3,6 @@ module Notes def execute note = project.notes.new(params[:note]) note.author = current_user - note.notify = params[:notify].present? - note.notify_author = params[:notify_author].present? note.save note end diff --git a/app/models/note.rb b/app/models/note.rb index f56f999f..f26420ca 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -22,9 +22,6 @@ class Note < ActiveRecord::Base attr_accessible :note, :noteable, :noteable_id, :noteable_type, :project_id, :attachment, :line_code, :commit_id - attr_accessor :notify - attr_accessor :notify_author - belongs_to :project belongs_to :noteable, polymorphic: true belongs_to :author, class_name: "User" @@ -143,14 +140,6 @@ class Note < ActiveRecord::Base nil end - def notify - @notify ||= false - end - - def notify_author - @notify_author ||= false - end - # Returns true if this is an upvote note, # otherwise false is returned def upvote? diff --git a/app/views/notes/_form.html.haml b/app/views/notes/_form.html.haml index c2bdeafb..7add2921 100644 --- a/app/views/notes/_form.html.haml +++ b/app/views/notes/_form.html.haml @@ -1,4 +1,4 @@ -= form_for [@project, @note], remote: true, html: { multipart: true, id: nil, class: "new_note js-new-note-form" } do |f| += form_for [@project, @note], remote: true, html: { multipart: true, id: nil, class: "new_note js-new-note-form common-note-form" } do |f| = note_target_fields = f.hidden_field :commit_id @@ -26,15 +26,6 @@ %a.btn.grouped.js-close-discussion-note-form Cancel - .note-form-option - = label_tag :notify do - = check_box_tag :notify, 1, false - %span.light Notify team via email - - .js-notify-commit-author - = label_tag :notify_author do - = check_box_tag :notify_author, 1 , false - %span.light Notify commit author .note-form-option %a.choose-btn.btn.btn-small.js-choose-note-attachment-button %i.icon-paper-clip diff --git a/app/views/walls/show.html.haml b/app/views/walls/show.html.haml index 0cd29486..78693b99 100644 --- a/app/views/walls/show.html.haml +++ b/app/views/walls/show.html.haml @@ -11,11 +11,6 @@ .buttons = f.submit 'Add Comment', class: "btn comment-btn grouped js-comment-button" - .note-form-option - = label_tag :notify do - = check_box_tag :notify, 1, false - %span.light Notify team via email - .note-form-option %a.choose-btn.btn.btn-small.js-choose-note-attachment-button %i.icon-paper-clip From 583bfac5f57d3d5c599c8d5d1c422e1bf7b9f265 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Mar 2013 16:00:19 +0200 Subject: [PATCH 099/152] Fix Note notification for entities without assignee --- app/services/notification_service.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 3c3ee39c..486aef1d 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -109,7 +109,10 @@ class NotificationService recipients = [note.commit_author] else opts.merge!(noteable_id: note.noteable_id) - recipients = [note.noteable.try(:author), note.noteable.try(:assignee)] + target = note.noteable + recipients = [] + recipients << target.assignee if target.respond_to?(:assignee) + recipients << target.author if target.respond_to?(:author) end # Get users who left comment in thread From 21191318ae616a88376977d2438f1f4d7826283e Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Mar 2013 16:41:29 +0200 Subject: [PATCH 100/152] refactor wall.js. style wall page a bit --- app/assets/javascripts/wall.js.coffee | 28 +++++++++++++------ app/assets/stylesheets/sections/wall.scss | 22 +++++++++++++-- app/views/walls/show.html.haml | 2 +- spec/features/notes_on_merge_requests_spec.rb | 8 ------ 4 files changed, 40 insertions(+), 20 deletions(-) diff --git a/app/assets/javascripts/wall.js.coffee b/app/assets/javascripts/wall.js.coffee index a35c8c60..e2fca3dd 100644 --- a/app/assets/javascripts/wall.js.coffee +++ b/app/assets/javascripts/wall.js.coffee @@ -58,14 +58,26 @@ form.show() renderNote: (note) -> - author = '' + note.author.name + '' - body = '' + linkify(sanitize(note.body)) + '' - file = '' - time = '' + note.created_at + '' + template = Wall.noteTemplate() + template = template.replace('{{author_name}}', note.author.name) + template = template.replace('{{created_at}}', note.created_at) + template = template.replace('{{text}}', linkify(sanitize(note.body))) if note.attachment - file = '' + note.attachment + '' - - html = '

  • ' + author + body + file + time + '
  • ' + file = '' + note.attachment + '' + else + file = '' + template = template.replace('{{file}}', file) - $('ul.notes').append(html) + + $('ul.notes').append(template) + + noteTemplate: -> + return '
  • + {{author_name}} + + {{text}} + {{file}} + + {{created_at}} +
  • ' diff --git a/app/assets/stylesheets/sections/wall.scss b/app/assets/stylesheets/sections/wall.scss index 598d9df8..8d3b4734 100644 --- a/app/assets/stylesheets/sections/wall.scss +++ b/app/assets/stylesheets/sections/wall.scss @@ -14,12 +14,28 @@ .notes { margin-bottom: 160px; + background: #FFE; + border: 1px solid #EED; + + > li { + @extend .clearfix; + border-bottom: 1px solid #EED; + padding: 10px; + } .wall-author { color: #666; - margin-right: 10px; - border-right: 1px solid #CCC; - padding-right: 5px + float: left; + width: 100px; + text-overflow: ellipsis; + } + + .wall-text { + border-left: 1px solid #CCC; + margin-left: 10px; + padding-left: 10px; + float: left; + width: 80%; } .wall-file { diff --git a/app/views/walls/show.html.haml b/app/views/walls/show.html.haml index 78693b99..139e66f5 100644 --- a/app/views/walls/show.html.haml +++ b/app/views/walls/show.html.haml @@ -1,5 +1,5 @@ %div.wall-page - %ul.well-list.notes + %ul.notes - if can? current_user, :write_note, @project .note-form-holder diff --git a/spec/features/notes_on_merge_requests_spec.rb b/spec/features/notes_on_merge_requests_spec.rb index 670762e8..d48dffc0 100644 --- a/spec/features/notes_on_merge_requests_spec.rb +++ b/spec/features/notes_on_merge_requests_spec.rb @@ -21,11 +21,6 @@ describe "On a merge request", js: true do it { find(".js-main-target-form input[type=submit]").value.should == "Add Comment" } it { within(".js-main-target-form") { should_not have_link("Cancel") } } - # notifiactions - it { within(".js-main-target-form") { should have_unchecked_field("Notify team via email") } } - it { within(".js-main-target-form") { should_not have_checked_field("Notify commit author") } } - it { within(".js-main-target-form") { should_not have_unchecked_field("Notify commit author") } } - describe "without text" do it { within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: false) } } end @@ -126,9 +121,6 @@ describe "On a merge request diff", js: true, focus: true do it { should have_button("Add Comment") } it { should have_css(".js-close-discussion-note-form", text: "Cancel") } - # notification options - it { should have_unchecked_field("Notify team via email") } - it "shouldn't add a second form for same row" do find("#4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185.line_holder .js-add-diff-note-button").trigger("click") From f1b369b57ddaa4c308c0f1debcc9548f14f86b24 Mon Sep 17 00:00:00 2001 From: Evan Wondrasek Date: Thu, 28 Mar 2013 11:03:00 -0500 Subject: [PATCH 101/152] Fixed: gitlab-shell version check error message --- lib/tasks/gitlab/check.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index ea97d181..c8d8d531 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -640,7 +640,7 @@ namespace :gitlab do if gitlab_shell_version.strip == '1.2.0' puts 'OK (1.2.0)'.green else - puts 'FAIL. Please update gitlab-shell to v1.1.0'.red + puts 'FAIL. Please update gitlab-shell to v1.2.0'.red end end end From 6a09b21df677e5115f46d3e52ffaf553f4276f85 Mon Sep 17 00:00:00 2001 From: Oluf Lorenzen Date: Thu, 28 Mar 2013 18:53:26 +0100 Subject: [PATCH 102/152] switch gitlab-shell to correct version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit a gitlab:check does say that you need v1.1.0 of gitlab-shell... --- doc/install/installation.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/install/installation.md b/doc/install/installation.md index a0ff9a26..853a6e78 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -106,6 +106,11 @@ GitLab Shell is a ssh access and repository management software developed specia git clone https://github.com/gitlabhq/gitlab-shell.git cd gitlab-shell + + # switch to right version for v5.0 + git checkout v1.1.0 + git checkout -b v1.1.0 + cp config.yml.example config.yml # Edit config and replace gitlab_url From 4524ba20b804dacccbaca3c37e781adc82c5e0d3 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Mar 2013 21:57:38 +0200 Subject: [PATCH 103/152] First step with rugged --- Gemfile | 1 + Gemfile.lock | 2 ++ app/models/repository.rb | 10 +++++++--- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 035942fa..f8aa096d 100644 --- a/Gemfile +++ b/Gemfile @@ -22,6 +22,7 @@ gem 'omniauth-twitter' gem 'omniauth-github' # Extracting information from a git repository +gem 'rugged', '~> 0.17.0.b7' gem "gitlab-grit", '~> 1.0.0', require: 'grit' gem 'grit_ext', '~> 0.8.1' diff --git a/Gemfile.lock b/Gemfile.lock index fca92716..0c96c35c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -397,6 +397,7 @@ GEM ruby-progressbar (1.0.2) rubyntlm (0.1.1) rubyzip (0.9.9) + rugged (0.17.0.b7) sanitize (2.0.3) nokogiri (>= 1.4.4, < 1.6) sass (3.2.7) @@ -565,6 +566,7 @@ DEPENDENCIES redcarpet (~> 2.2.2) redis-rails rspec-rails + rugged (~> 0.17.0.b7) sass-rails (~> 3.2.5) sdoc seed-fu diff --git a/app/models/repository.rb b/app/models/repository.rb index 934c1a6e..93ead9e5 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -34,6 +34,10 @@ class Repository @repo ||= Grit::Repo.new(path_to_repo) end + def rugged + @rugged ||= Rugged::Repository.new(path_to_repo) + end + def commit(commit_id = nil) Commit.find_or_first(repo, commit_id, root_ref) end @@ -64,17 +68,17 @@ class Repository # Returns an Array of branch names def branch_names - repo.branches.collect(&:name).sort + branches.map(&:name).sort end # Returns an Array of Branches def branches - repo.branches.sort_by(&:name) + rugged.branches.sort_by(&:name) end # Returns an Array of tag names def tag_names - repo.tags.collect(&:name).sort.reverse + rugged.tags.sort.reverse end # Returns an Array of Tags From a18ce409431dfad00af137bf3983bb0f456d2485 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Mar 2013 23:01:42 +0200 Subject: [PATCH 104/152] Revert "First step with rugged" This reverts commit 4524ba20b804dacccbaca3c37e781adc82c5e0d3. --- Gemfile | 1 - Gemfile.lock | 2 -- app/models/repository.rb | 10 +++------- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/Gemfile b/Gemfile index f8aa096d..035942fa 100644 --- a/Gemfile +++ b/Gemfile @@ -22,7 +22,6 @@ gem 'omniauth-twitter' gem 'omniauth-github' # Extracting information from a git repository -gem 'rugged', '~> 0.17.0.b7' gem "gitlab-grit", '~> 1.0.0', require: 'grit' gem 'grit_ext', '~> 0.8.1' diff --git a/Gemfile.lock b/Gemfile.lock index 0c96c35c..fca92716 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -397,7 +397,6 @@ GEM ruby-progressbar (1.0.2) rubyntlm (0.1.1) rubyzip (0.9.9) - rugged (0.17.0.b7) sanitize (2.0.3) nokogiri (>= 1.4.4, < 1.6) sass (3.2.7) @@ -566,7 +565,6 @@ DEPENDENCIES redcarpet (~> 2.2.2) redis-rails rspec-rails - rugged (~> 0.17.0.b7) sass-rails (~> 3.2.5) sdoc seed-fu diff --git a/app/models/repository.rb b/app/models/repository.rb index 93ead9e5..934c1a6e 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -34,10 +34,6 @@ class Repository @repo ||= Grit::Repo.new(path_to_repo) end - def rugged - @rugged ||= Rugged::Repository.new(path_to_repo) - end - def commit(commit_id = nil) Commit.find_or_first(repo, commit_id, root_ref) end @@ -68,17 +64,17 @@ class Repository # Returns an Array of branch names def branch_names - branches.map(&:name).sort + repo.branches.collect(&:name).sort end # Returns an Array of Branches def branches - rugged.branches.sort_by(&:name) + repo.branches.sort_by(&:name) end # Returns an Array of tag names def tag_names - rugged.tags.sort.reverse + repo.tags.collect(&:name).sort.reverse end # Returns an Array of Tags From 49f14f057d6deb0903ae4e9b876c89f717f85f10 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 29 Mar 2013 08:47:14 +0200 Subject: [PATCH 105/152] Prevent gollum to overrride gitlab-grit gem. Use grit as instead so gollum uses it too. Fixes things with gpg singatured commits, etc. --- Gemfile | 3 ++- Gemfile.lock | 20 +++++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Gemfile b/Gemfile index 035942fa..a69a5c08 100644 --- a/Gemfile +++ b/Gemfile @@ -22,7 +22,8 @@ gem 'omniauth-twitter' gem 'omniauth-github' # Extracting information from a git repository -gem "gitlab-grit", '~> 1.0.0', require: 'grit' +# Since gollum requires grit we cannot use gitlab-grit gem name any more. Use grit instead +gem "grit", '~> 2.5.0', git: 'https://github.com/gitlabhq/grit.git', ref: 'c40a32432616a07fa7fc3c32c24ab73ad6a9718f' gem 'grit_ext', '~> 0.8.1' # Ruby/Rack Git Smart-HTTP Server Handler diff --git a/Gemfile.lock b/Gemfile.lock index fca92716..44fe59a9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,6 +6,16 @@ GIT activerecord (>= 2.3.0) rake (>= 0.8.7) +GIT + remote: https://github.com/gitlabhq/grit.git + revision: c40a32432616a07fa7fc3c32c24ab73ad6a9718f + ref: c40a32432616a07fa7fc3c32c24ab73ad6a9718f + specs: + grit (2.5.0) + diff-lcs (~> 1.1) + mime-types (~> 1.15) + posix-spawn (~> 0.3.6) + GIT remote: https://github.com/gitlabhq/raphael-rails.git revision: cb2c92a040b9b941a5f1aa1ea866cc26e944fe58 @@ -166,10 +176,6 @@ GEM github-markup (0.7.5) gitlab-grack (1.0.0) rack (~> 1.4.1) - gitlab-grit (1.0.0) - diff-lcs (~> 1.1) - mime-types (~> 1.15) - posix-spawn (~> 0.3.6) gitlab-pygments.rb (0.3.2) posix-spawn (~> 0.3.6) yajl-ruby (~> 1.1.0) @@ -194,10 +200,6 @@ GEM grape-entity (0.2.0) activesupport multi_json (>= 1.3.2) - grit (2.5.0) - diff-lcs (~> 1.1) - mime-types (~> 1.15) - posix-spawn (~> 0.3.6) grit_ext (0.8.1) charlock_holmes (~> 0.6.9) growl (1.0.3) @@ -524,7 +526,6 @@ DEPENDENCIES github-linguist (~> 2.3.4) github-markup (~> 0.7.4) gitlab-grack (~> 1.0.0) - gitlab-grit (~> 1.0.0) gitlab-pygments.rb (~> 0.3.2) gitlab_meta (= 5.0) gitlab_omniauth-ldap (= 1.0.2) @@ -533,6 +534,7 @@ DEPENDENCIES gon grape (~> 0.3.1) grape-entity (~> 0.2.0) + grit (~> 2.5.0)! grit_ext (~> 0.8.1) growl guard-rspec From d8eefdccfc58fdbc4918941a21d699e644c7443a Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Sat, 30 Mar 2013 11:35:35 +0100 Subject: [PATCH 106/152] Removing duplication by putting everything in the readme. Allow us to close issues that deviate from the guidelines. --- CONTRIBUTING.md | 57 +++++++++--------------------- README.md | 69 +++++++++++++++++++++---------------- doc/install/installation.md | 19 +++------- 3 files changed, 59 insertions(+), 86 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 632cf930..f9263aa6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,37 +1,18 @@ # Contribute to GitLab -If you have a question or want to contribute to GitLab this guide show you the appropriate channel to use. +This guide details how to use pull requests and the issues to improve GitLab. -## Ruling out common errors +## Closing deviating issues -Some errors are common and it may so happen, that you are not the only one who stumbled over a particular issue. We have [collected several of those and documented quick solutions](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Trouble-Shooting-Guide) for them. - -## Support forum - -Please visit our [Support Forum](https://groups.google.com/forum/#!forum/gitlabhq) for any kind of question regarding the usage or adiministration/configuration of GitLab. - -### Use the support forum if ... - -* You get permission denied errors -* You can't see your repos -* You have issues cloning, pulling or pushing -* You have issues with web_hooks not firing - -**Search** for similar issues before posting your own, there's a good chance somebody else had the same issue you have now and had it resolved. - -## Support options - -Community support in the [Support Forum](https://groups.google.com/forum/#!forum/gitlabhq) is done by volunteers. A support subscription is available from [GitLab.com](http://blog.gitlab.com/subscription/) - -## Feature suggestions - -Feature suggestions don't belong in issues but can go to [Feedback forum](http://gitlab.uservoice.com/forums/176466-general) where they can be voted on. +Pull requests and issues not in line with the guidelines listed in this document will be closed with just a link to this paragraph. GitLab is popular open source project and the capacity to deal with issues and pull requests is limited. To get support for your problems please use other channels as detailed in [the getting help section of the readme](https://github.com/gitlabhq/gitlabhq#getting-help). [Support subscriptions](http://www.gitlab.com/subscription/) and [consulting services](http://www.gitlab.com/consultancy/) are available from GitLab.com. ## Pull requests -You can submit a pull request if you have made an improvement to GitLab. The issues we would really like a pull request for are listed with the [status 'accepting merge/pull requests' on our feedback forum](http://feedback.gitlab.com/forums/176466-general/status/796455). +We welcome pull request with improvements to GitLab code and/or documentation. The issues we would really like a pull request for are listed with the [status 'accepting merge/pull requests' on our feedback forum](http://feedback.gitlab.com/forums/176466-general/status/796455) but other improvements are also welcome. -Code speaks louder than words. If you can please submit a pull request with the fix including tests. The workflow to make a pull request is as follows: +## Pull request guidelines + + If you can please submit a pull request with the fix including tests. The workflow to make a pull request is as follows: 1. Fork the project on GitHub 1. Create a feature branch @@ -53,26 +34,20 @@ We will accept pull requests if: For examples of feedback on pull requests please look at already [closed pull requests](https://github.com/gitlabhq/gitlabhq/pulls?direction=desc&page=1&sort=created&state=closed). -## Submitting via GitHub's issue tracker +## Issue tracker -* For obvious bugs or misbehavior in GitLab in the master branch. Please include the revision id and a reproducible test case. -* For problematic or insufficient documentation. Please give a suggestion on how to improve it. +The [issue tracker](https://github.com/gitlabhq/gitlabhq/issues) is only for obvious bugs or misbehavior in the master branch of GitLab. When submitting an issue please conform to the issue submission guidelines listed below. -If you're unsure where to post, post it to the [Support Forum](https://groups.google.com/forum/#!forum/gitlabhq) first. -There are a lot of helpful GitLab users there who may be able to help you quickly. -If your particular issue turns out to be a bug, it will find its way from there to the [issue tracker on GitHub](https://github.com/gitlabhq/gitlabhq/issues). +Please send a pull request with a tested solution or a pull request with a failing test instead of opening an issue if you can. If you're unsure where to post, post to the [Support Forum](https://groups.google.com/forum/#!forum/gitlabhq) first. There are a lot of helpful GitLab users there who may be able to help you quickly. If your particular issue turns out to be a bug, it will find its way from there. -### When submitting an issue +### Issue tracker guidelines **Search** for similar entries before submitting your own, there's a good chance somebody else had the same issue or idea. Show your support with `:+1:` and/or join the discussion. -Please consider the following points when submitting an **issue**: - -* Summarize your issue in one sentence (what happened wrong, when you did/expected something else) -* Describe your issue in detail (including steps to reproduce) +* Summarize your issue in one sentence (what goes wrong, what did you expect to happen) +* Describe your issue in detail +* How can we reproduce the issue on the [GitLab Vagrant virtual machine](https://github.com/gitlabhq/gitlab-vagrant-vm) (start with: vagrant destroy && vagrant up && vagrant ssh) +* Add the last commit sha1 of the GitLab version you used to replicate the issue * Add logs or screen shots when possible +* Link to the line of code that might be responsible for the problem * Describe your setup (use relevant parts from `sudo -u gitlab -H bundle exec rake gitlab:env:info`) - -## Thank you! - -By taking the time to use the right channel, you help the development team to organize and prioritize issues and suggestions in order to make GitLab a better product for us all. diff --git a/README.md b/README.md index a524f790..3ab4c051 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ * powered by Ruby on Rails * completely free and open source (MIT license) -* used by 10.000 organizations to keep their code secure +* used by more than 10.000 organizations to keep their code secure ### Code status @@ -30,7 +30,7 @@ * GitLab.org community site: [Homepage](http://gitlab.org) [Screenshots](http://gitlab.org/screenshots/) [Blog](http://blog.gitlab.org/) [Demo](http://demo.gitlabhq.com/users/sign_in) -* GitLab.com commercial services: [Homepage](http://www.gitlab.com/) [GitLab Cloud](http://www.gitlab.com/cloud/) [Subscription](http://www.gitlab.com/subscription/) [Consultancy](http://www.gitlab.com/consultancy/) [Blog](http://blog.gitlab.com/) +* GitLab.com commercial services: [Homepage](http://www.gitlab.com/) [Subscription](http://www.gitlab.com/subscription/) [Consultancy](http://www.gitlab.com/consultancy/) [GitLab Cloud](http://www.gitlab.com/cloud/) [Blog](http://blog.gitlab.com/) * GitLab CI: [Readme](https://github.com/gitlabhq/gitlab-ci/blob/master/README.md) of the GitLab open-source continuous integration server @@ -47,7 +47,7 @@ ### Installation -#### For production +#### Official production installation Follow the installation guide for production server. @@ -55,21 +55,37 @@ Follow the installation guide for production server. * [Installation guide for the current master branch (5.1)](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md) -#### For development -If you want to contribute, please first read our [Contributing Guidelines](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) and then we suggest you to use the Vagrant virtual machine project to get an environment working sandboxed and with all dependencies. +#### Official development installation + +If you want to contribute, please first read our [Contributing Guidelines](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) and then we suggest you to use the Vagrant virtual machine project to get an environment working with all dependencies. * [Vagrant virtual machine](https://github.com/gitlabhq/gitlab-vagrant-vm) -#### Unsupported installation methods + +#### Unsupported production installation * [GitLab recipes](https://github.com/gitlabhq/gitlab-recipes) for setup on different platforms * [Unofficial installation guides](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Unofficial-Installation-Guides) +* [BitNami one-click installers](http://bitnami.com/stack/gitlab) + +* [TurnKey Linux virtual appliance](http://www.turnkeylinux.org/gitlab) -### Starting +### New versions and upgrading + +Each month on the 22th a new version is released together with an upgrade guide. + +* [Upgrade guides](https://github.com/gitlabhq/gitlabhq/wiki) + +* [Changelog](https://github.com/gitlabhq/gitlabhq/blob/master/CHANGELOG) + +* [Roadmap](https://github.com/gitlabhq/gitlabhq/blob/master/ROADMAP.md) + + +### Getting started 1. The Installation guide contains instructions to download an init script and run that on boot. With the init script you can also start GitLab @@ -107,27 +123,6 @@ If you want to contribute, please first read our [Contributing Guidelines](https bundle exec rake spinach -### Getting help - -* [Troubleshooting guide](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Trouble-Shooting-Guide) - -* [Support forum](https://groups.google.com/forum/#!forum/gitlabhq) - -* [Feedback and suggestions forum](http://gitlab.uservoice.com/forums/176466-general) - -* [Support subscription](http://www.gitlab.com/subscription/) - -* [Consultancy](http://www.gitlab.com/consultancy/) - -### New versions and upgrading - -Each month on the 22th a new version is released together with an upgrade guide. - -* [Upgrade guides](https://github.com/gitlabhq/gitlabhq/wiki) - -* [Changelog](https://github.com/gitlabhq/gitlabhq/blob/master/CHANGELOG) - -* [Roadmap](https://github.com/gitlabhq/gitlabhq/blob/master/ROADMAP.md) ### GitLab interfaces @@ -139,9 +134,23 @@ Each month on the 22th a new version is released together with an upgrade guide. * [Databases](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/databases.md) -### Getting in touch -* [Contributing guide](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) +### Getting help + +* [Troubleshooting guide](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Trouble-Shooting-Guide) contains solutions to common problems. + +* [Support forum](https://groups.google.com/forum/#!forum/gitlabhq) is the best place to ask questions. For example you can use it if you have questions about: permission denied errors, invisible repos, can't clone/pull/push or with web hooks that don't fire. Please search for similar issues before posting your own, there's a good chance somebody else had the same issue you have now and had it resolved. There are a lot of helpful GitLab users there who may be able to help you quickly. If your particular issue turns out to be a bug, it will find its way from there to a fix. + +* [Feedback and suggestions forum](http://gitlab.uservoice.com/forums/176466-general) is the place to propose and discuss new features for GitLab. + +* [Support subscription](http://www.gitlab.com/subscription/) connect you to the knowledge of GitLab experts that will resolve your issues and answer your questions. + +* [Consultancy](http://www.gitlab.com/consultancy/) allows you hire GitLab exports for installations, upgrades and customizations. + +* [Contributing guide](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) describes how to submit pull requests and issues. Pull requests and issues not in line with the guidelines in this document will be closed without comment. + + +### Getting in touch * [Core team](https://github.com/gitlabhq?tab=members) diff --git a/doc/install/installation.md b/doc/install/installation.md index fc73b366..39df86ad 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -1,19 +1,13 @@ This installation guide was created for Debian/Ubuntu and tested on it. Please read [`doc/install/requirements.md`](./requirements.md) for hardware and platform requirements. -This installation guide is recommended to set up a production server. If you want a development environment please use the [Vagrant virtual machine](https://github.com/gitlabhq/gitlab-vagrant-vm) since it makes it much easier to set up all the dependencies for integration testing. +**Important Note:** +This is the official installation guide to set up a production server. To set up a development installation or for many other installation options please consult [the installation section in the readme](https://github.com/gitlabhq/gitlabhq#installation). **Important Note:** -The following steps have been known to work. -If you deviate from this guide, do it with caution and make sure you don't -violate any assumptions GitLab makes about its environment. -For things like AWS installation scripts, init scripts or config files for -alternative web server have a look at the [`Advanced Setup -Tips`](./installation.md#advanced-setup-tips) section. - +The following steps have been known to work. If you deviate from this guide, do it with caution and make sure you don't violate any assumptions GitLab makes about its environment. **Important Note:** -If you find a bug/error in this guide please submit an issue or pull request -following the [`contribution guide`](../../CONTRIBUTING.md). +If you find a bug/error in this guide please submit a pull request following the [`contributing guide`](../../CONTRIBUTING.md). - - - @@ -299,8 +293,3 @@ If you are running SSH on a non-standard port, you must change the gitlab user's hostname 127.0.0.1; # Your server name or IP You also need to change the corresponding options (e.g. ssh_user, ssh_host, admin_uri) in the `config\gitlab.yml` file. - -## User-contributed Configurations - -You can find things like AWS installation scripts, init scripts or config files -for alternative web server in our [recipes collection](https://github.com/gitlabhq/gitlab-recipes/). From 66a1b88393cea26b9626087c0a2d5bec69cbf863 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 30 Mar 2013 12:50:44 +0200 Subject: [PATCH 107/152] Update a grit to newer version --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index a69a5c08..e3c8ef2c 100644 --- a/Gemfile +++ b/Gemfile @@ -23,7 +23,7 @@ gem 'omniauth-github' # Extracting information from a git repository # Since gollum requires grit we cannot use gitlab-grit gem name any more. Use grit instead -gem "grit", '~> 2.5.0', git: 'https://github.com/gitlabhq/grit.git', ref: 'c40a32432616a07fa7fc3c32c24ab73ad6a9718f' +gem "grit", '~> 2.5.0', git: 'https://github.com/gitlabhq/grit.git', ref: 'c15e2758ec75f99230cd0fbcc9110bf932c0bf05' gem 'grit_ext', '~> 0.8.1' # Ruby/Rack Git Smart-HTTP Server Handler diff --git a/Gemfile.lock b/Gemfile.lock index 44fe59a9..a4a3085f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -8,8 +8,8 @@ GIT GIT remote: https://github.com/gitlabhq/grit.git - revision: c40a32432616a07fa7fc3c32c24ab73ad6a9718f - ref: c40a32432616a07fa7fc3c32c24ab73ad6a9718f + revision: c15e2758ec75f99230cd0fbcc9110bf932c0bf05 + ref: c15e2758ec75f99230cd0fbcc9110bf932c0bf05 specs: grit (2.5.0) diff-lcs (~> 1.1) From 34136d381fe733e7465700a043c7a3a27c8c0ec6 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 30 Mar 2013 13:14:19 +0200 Subject: [PATCH 108/152] Use latest gitlab-grit fork to prevent gollum override gitlab-grit. Fixes issues related to gpg signed commits and other fixes from gitlab/grit fork --- Gemfile | 3 ++- Gemfile.lock | 20 +++++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Gemfile b/Gemfile index 7f92cb75..494f331e 100644 --- a/Gemfile +++ b/Gemfile @@ -22,7 +22,8 @@ gem 'omniauth-twitter' gem 'omniauth-github' # Extracting information from a git repository -gem "gitlab-grit", '~> 1.0.0', require: 'grit' +# Since gollum requires grit we cannot use gitlab-grit gem name any more. Use grit instead +gem "grit", '~> 2.5.0', git: 'https://github.com/gitlabhq/grit.git', ref: 'c15e2758ec75f99230cd0fbcc9110bf932c0bf05' gem 'grit_ext', '~> 0.6.2' # Ruby/Rack Git Smart-HTTP Server Handler diff --git a/Gemfile.lock b/Gemfile.lock index 4de5c893..7b779dbc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -23,6 +23,16 @@ GIT activerecord (>= 2.3.0) rake (>= 0.8.7) +GIT + remote: https://github.com/gitlabhq/grit.git + revision: c15e2758ec75f99230cd0fbcc9110bf932c0bf05 + ref: c15e2758ec75f99230cd0fbcc9110bf932c0bf05 + specs: + grit (2.5.0) + diff-lcs (~> 1.1) + mime-types (~> 1.15) + posix-spawn (~> 0.3.6) + GIT remote: https://github.com/gitlabhq/raphael-rails.git revision: cb2c92a040b9b941a5f1aa1ea866cc26e944fe58 @@ -166,10 +176,6 @@ GEM github-markup (0.7.5) gitlab-grack (1.0.0) rack (~> 1.4.1) - gitlab-grit (1.0.0) - diff-lcs (~> 1.1) - mime-types (~> 1.15) - posix-spawn (~> 0.3.6) gitlab-pygments.rb (0.3.2) posix-spawn (~> 0.3.6) yajl-ruby (~> 1.1.0) @@ -194,10 +200,6 @@ GEM grape-entity (0.2.0) activesupport multi_json (>= 1.3.2) - grit (2.5.0) - diff-lcs (~> 1.1) - mime-types (~> 1.15) - posix-spawn (~> 0.3.6) grit_ext (0.6.2) charlock_holmes (~> 0.6.9) growl (1.0.3) @@ -521,7 +523,6 @@ DEPENDENCIES github-linguist (~> 2.3.4) github-markup (~> 0.7.4) gitlab-grack (~> 1.0.0) - gitlab-grit (~> 1.0.0) gitlab-pygments.rb (~> 0.3.2) gitlab_meta (= 5.0) gitlab_omniauth-ldap (= 1.0.2) @@ -530,6 +531,7 @@ DEPENDENCIES gon grape (~> 0.3.1) grape-entity (~> 0.2.0) + grit (~> 2.5.0)! grit_ext (~> 0.6.2) growl guard-rspec From e29c9b79329511ebfc335c87039118bd3fdcadb6 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 30 Mar 2013 13:23:58 +0200 Subject: [PATCH 109/152] slower animation for tree browsing --- app/assets/javascripts/tree.js.coffee | 2 +- app/views/tree/show.js.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/tree.js.coffee b/app/assets/javascripts/tree.js.coffee index 2603b9a9..10d0df70 100644 --- a/app/assets/javascripts/tree.js.coffee +++ b/app/assets/javascripts/tree.js.coffee @@ -6,7 +6,7 @@ $ -> $('span.log_loading:first').removeClass('hide') $('#tree-slider .tree-item-file-name a, .breadcrumb li > a').live "click", -> - $("#tree-content-holder").hide("slide", { direction: "left" }, 150) + $("#tree-content-holder").hide("slide", { direction: "left" }, 400) # Make the entire tree-item row clickable, but not if clicking another link (like a commit message) $("#tree-slider .tree-item").live 'click', (e) -> diff --git a/app/views/tree/show.js.haml b/app/views/tree/show.js.haml index fadd5e22..a01d4917 100644 --- a/app/views/tree/show.js.haml +++ b/app/views/tree/show.js.haml @@ -1,7 +1,7 @@ :plain // Load Files list $("#tree-holder").html("#{escape_javascript(render(partial: "tree", locals: {tree: @tree}))}"); - $("#tree-content-holder").show("slide", { direction: "right" }, 150); + $("#tree-content-holder").show("slide", { direction: "right" }, 400); $('.project-refs-form #path').val("#{@path}"); // Load last commit log for each file in tree From e998257dcf3a0e4a46305a8c6019e74fcce2887f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 30 Mar 2013 16:33:26 +0200 Subject: [PATCH 110/152] use rollbacked version of grit to make gollum works --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index e3c8ef2c..01e3b0f2 100644 --- a/Gemfile +++ b/Gemfile @@ -23,7 +23,7 @@ gem 'omniauth-github' # Extracting information from a git repository # Since gollum requires grit we cannot use gitlab-grit gem name any more. Use grit instead -gem "grit", '~> 2.5.0', git: 'https://github.com/gitlabhq/grit.git', ref: 'c15e2758ec75f99230cd0fbcc9110bf932c0bf05' +gem "grit", '~> 2.5.0', git: 'https://github.com/gitlabhq/grit.git', ref: '42297cdcee16284d2e4eff23d41377f52fc28b9d' gem 'grit_ext', '~> 0.8.1' # Ruby/Rack Git Smart-HTTP Server Handler diff --git a/Gemfile.lock b/Gemfile.lock index a4a3085f..82a13e08 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -8,8 +8,8 @@ GIT GIT remote: https://github.com/gitlabhq/grit.git - revision: c15e2758ec75f99230cd0fbcc9110bf932c0bf05 - ref: c15e2758ec75f99230cd0fbcc9110bf932c0bf05 + revision: 42297cdcee16284d2e4eff23d41377f52fc28b9d + ref: 42297cdcee16284d2e4eff23d41377f52fc28b9d specs: grit (2.5.0) diff-lcs (~> 1.1) From 8b761574bd629cf5a6ddb0e169fff019d55ad415 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 30 Mar 2013 16:37:41 +0200 Subject: [PATCH 111/152] fix gollum --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 494f331e..e1e5bba2 100644 --- a/Gemfile +++ b/Gemfile @@ -23,7 +23,7 @@ gem 'omniauth-github' # Extracting information from a git repository # Since gollum requires grit we cannot use gitlab-grit gem name any more. Use grit instead -gem "grit", '~> 2.5.0', git: 'https://github.com/gitlabhq/grit.git', ref: 'c15e2758ec75f99230cd0fbcc9110bf932c0bf05' +gem "grit", '~> 2.5.0', git: 'https://github.com/gitlabhq/grit.git', ref: 'c40a32432616a07fa7fc3c32c24ab73ad6a9718f' gem 'grit_ext', '~> 0.6.2' # Ruby/Rack Git Smart-HTTP Server Handler diff --git a/Gemfile.lock b/Gemfile.lock index 7b779dbc..9614a07c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -25,8 +25,8 @@ GIT GIT remote: https://github.com/gitlabhq/grit.git - revision: c15e2758ec75f99230cd0fbcc9110bf932c0bf05 - ref: c15e2758ec75f99230cd0fbcc9110bf932c0bf05 + revision: c40a32432616a07fa7fc3c32c24ab73ad6a9718f + ref: c40a32432616a07fa7fc3c32c24ab73ad6a9718f specs: grit (2.5.0) diff-lcs (~> 1.1) From 52ae054447980f2efb775e43adbe5ad4bcf575e6 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 30 Mar 2013 16:46:56 +0200 Subject: [PATCH 112/152] prevent exception when trying to edit empty project --- app/views/projects/_form.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/projects/_form.html.haml b/app/views/projects/_form.html.haml index 01fb6a67..2bc86d0b 100644 --- a/app/views/projects/_form.html.haml +++ b/app/views/projects/_form.html.haml @@ -36,10 +36,10 @@ .input = f.text_area :description, placeholder: "awesome project", class: "span5", rows: 3, maxlength: 250 - - unless @repository.heads.empty? + - unless @project.empty_repo? .clearfix = f.label :default_branch, "Default Branch" - .input= f.select(:default_branch, @repository.heads.map(&:name), {}, style: "width:210px;") + .input= f.select(:default_branch, @repository.branch_names, {}) - if can?(current_user, :change_public_mode, @project) From abc47852a97317d7ba155c14feb4154094e48220 Mon Sep 17 00:00:00 2001 From: Douglas Huff Date: Sat, 30 Mar 2013 18:54:12 -0700 Subject: [PATCH 113/152] Update deps for therubyracer and libv8 to resolve build issues on FreeBSD. Resolves Iussue#3446 . --- Gemfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 82a13e08..3292d62e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -249,7 +249,7 @@ GEM addressable (~> 2.3) letter_opener (1.0.0) launchy (>= 2.0.4) - libv8 (3.3.10.4) + libv8 (3.11.8.17) listen (0.7.3) lumberjack (1.0.3) mail (2.5.3) @@ -462,8 +462,8 @@ GEM temple (0.5.5) terminal-table (1.4.5) test_after_commit (0.0.1) - therubyracer (0.10.2) - libv8 (~> 3.3.10) + therubyracer (0.11.4) + libv8 (>= 3.11.8.17) thin (1.5.0) daemons (>= 1.0.9) eventmachine (>= 0.12.6) From 15143a3b7b1c36d03da5ae462e0cf3e8bcdd97f1 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Sun, 31 Mar 2013 13:48:49 +0200 Subject: [PATCH 114/152] Improve header and wording. --- CONTRIBUTING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f9263aa6..f322a81c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,15 +2,15 @@ This guide details how to use pull requests and the issues to improve GitLab. -## Closing deviating issues +## Closing policy for pull requests and issues -Pull requests and issues not in line with the guidelines listed in this document will be closed with just a link to this paragraph. GitLab is popular open source project and the capacity to deal with issues and pull requests is limited. To get support for your problems please use other channels as detailed in [the getting help section of the readme](https://github.com/gitlabhq/gitlabhq#getting-help). [Support subscriptions](http://www.gitlab.com/subscription/) and [consulting services](http://www.gitlab.com/consultancy/) are available from GitLab.com. +Pull requests and issues not in line with the guidelines listed in this document will be closed with just a link to this paragraph. GitLab is a popular open source project and the capacity to deal with issues and pull requests is limited. To get support for your problems please use other channels as detailed in [the getting help section of the readme](https://github.com/gitlabhq/gitlabhq#getting-help). Professional [support subscriptions](http://www.gitlab.com/subscription/) and [consulting services](http://www.gitlab.com/consultancy/) are available from [GitLab.com](http://www.gitlab.com/). ## Pull requests We welcome pull request with improvements to GitLab code and/or documentation. The issues we would really like a pull request for are listed with the [status 'accepting merge/pull requests' on our feedback forum](http://feedback.gitlab.com/forums/176466-general/status/796455) but other improvements are also welcome. -## Pull request guidelines +### Pull request guidelines If you can please submit a pull request with the fix including tests. The workflow to make a pull request is as follows: From 8fcdbaea71460c5a67ae91aa6539773655a785bd Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Sun, 31 Mar 2013 13:54:46 +0200 Subject: [PATCH 115/152] Section for important notes. --- doc/install/installation.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index 39df86ad..8cacc413 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -1,13 +1,12 @@ -This installation guide was created for Debian/Ubuntu and tested on it. Please read [`doc/install/requirements.md`](./requirements.md) for hardware and platform requirements. +# Important notes -**Important Note:** -This is the official installation guide to set up a production server. To set up a development installation or for many other installation options please consult [the installation section in the readme](https://github.com/gitlabhq/gitlabhq#installation). +This installation guide was created for and tested on **Debian/Ubuntu** operating systems. Please read [`doc/install/requirements.md`](./requirements.md) for hardware and operating system requirements. -**Important Note:** -The following steps have been known to work. If you deviate from this guide, do it with caution and make sure you don't violate any assumptions GitLab makes about its environment. +This is the official installation guide to set up a production server. To set up a **development installation** or for many other installation options please consult [the installation section in the readme](https://github.com/gitlabhq/gitlabhq#installation). -**Important Note:** -If you find a bug/error in this guide please submit a pull request following the [`contributing guide`](../../CONTRIBUTING.md). +The following steps have been known to work. Please **use caution when you deviate** from this guide. Make sure you don't violate any assumptions GitLab makes about its environment. + +If you find a bug/error in this guide please **submit a pull request** following the [`contributing guide`](../../CONTRIBUTING.md). - - - From ddaedaef1ae90ccfa1146b816000a28b6503ace9 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 31 Mar 2013 15:04:08 +0300 Subject: [PATCH 116/152] Fix therubyracer dependencies --- Gemfile.lock | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 3292d62e..586b7bda 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -378,6 +378,7 @@ GEM redis-store (~> 1.1.0) redis-store (1.1.3) redis (>= 2.2.0) + ref (1.0.4) request_store (1.0.5) rest-client (1.6.7) mime-types (>= 1.16) @@ -463,7 +464,8 @@ GEM terminal-table (1.4.5) test_after_commit (0.0.1) therubyracer (0.11.4) - libv8 (>= 3.11.8.17) + libv8 (~> 3.11.8.12) + ref thin (1.5.0) daemons (>= 1.0.9) eventmachine (>= 0.12.6) From 71b0f8ea0b7d4460fdbb70ca9b61789d37ed4885 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 31 Mar 2013 17:08:10 +0300 Subject: [PATCH 117/152] Use existing methods for branch names: Ex use @repository.branch_names instead of @repository.heads.map(&:name) --- app/controllers/merge_requests_controller.rb | 4 ++-- app/models/project.rb | 21 +++++++++++++------- app/models/repository.rb | 3 ++- app/views/merge_requests/_form.html.haml | 4 ++-- spec/models/project_spec.rb | 13 +++++++++++- 5 files changed, 32 insertions(+), 13 deletions(-) diff --git a/app/controllers/merge_requests_controller.rb b/app/controllers/merge_requests_controller.rb index 88e0df16..e2185361 100644 --- a/app/controllers/merge_requests_controller.rb +++ b/app/controllers/merge_requests_controller.rb @@ -129,11 +129,11 @@ class MergeRequestsController < ProjectResourceController def validates_merge_request # Show git not found page if target branch doesn't exist - return invalid_mr unless @project.repo.heads.map(&:name).include?(@merge_request.target_branch) + return invalid_mr unless @project.repository.branch_names.include?(@merge_request.target_branch) # Show git not found page if source branch doesn't exist # and there is no saved commits between source & target branch - return invalid_mr if !@project.repo.heads.map(&:name).include?(@merge_request.source_branch) && @merge_request.commits.blank? + return invalid_mr if !@project.repository.branch_names.include?(@merge_request.source_branch) && @merge_request.commits.blank? end def define_show_vars diff --git a/app/models/project.rb b/app/models/project.rb index 0da35b5d..6871afca 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -369,12 +369,19 @@ class Project < ActiveRecord::Base end def open_branches - if protected_branches.empty? - self.repo.heads - else - pnames = protected_branches.map(&:name) - self.repo.heads.reject { |h| pnames.include?(h.name) } - end.sort_by(&:name) + all_branches = repository.branches + + if protected_branches.present? + all_branches.reject! do |branch| + protected_branches_names.include?(branch.name) + end + end + + all_branches + end + + def protected_branches_names + @protected_branches_names ||= protected_branches.map(&:name) end def root_ref?(branch) @@ -396,6 +403,6 @@ class Project < ActiveRecord::Base # Check if current branch name is marked as protected in the system def protected_branch? branch_name - protected_branches.map(&:name).include?(branch_name) + protected_branches_names.include?(branch_name) end end diff --git a/app/models/repository.rb b/app/models/repository.rb index 934c1a6e..7f56047b 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -63,8 +63,9 @@ class Repository end # Returns an Array of branch names + # sorted by name ASC def branch_names - repo.branches.collect(&:name).sort + branches.map(&:name) end # Returns an Array of Branches diff --git a/app/views/merge_requests/_form.html.haml b/app/views/merge_requests/_form.html.haml index 816c852d..6d64988c 100644 --- a/app/views/merge_requests/_form.html.haml +++ b/app/views/merge_requests/_form.html.haml @@ -13,7 +13,7 @@ .mr_branch_box %h5.cgray From (Head Branch) .body - .padded= f.select(:source_branch, @repository.heads.map(&:name), { include_blank: "Select branch" }, {class: 'chosen span4'}) + .padded= f.select(:source_branch, @repository.branch_names, { include_blank: "Select branch" }, {class: 'chosen span4'}) .mr_source_commit .span2 @@ -22,7 +22,7 @@ .mr_branch_box %h5.cgray To (Base Branch) .body - .padded= f.select(:target_branch, @repository.heads.map(&:name), { include_blank: "Select branch" }, {class: 'chosen span4'}) + .padded= f.select(:target_branch, @repository.branch_names, { include_blank: "Select branch" }, {class: 'chosen span4'}) .mr_target_commit %fieldset diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index e6585f78..53388b93 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -233,7 +233,7 @@ describe Project do it "should be true for projects with external issues tracker if issues enabled" do ext_project.can_have_issues_tracker_id?.should be_true - end + end it "should be false for projects with internal issue tracker if issues enabled" do project.can_have_issues_tracker_id?.should be_false @@ -247,4 +247,15 @@ describe Project do ext_project.can_have_issues_tracker_id?.should be_false end end + + describe :open_branches do + let(:project) { create(:project) } + + before do + project.protected_branches.create(name: 'master') + end + + it { project.open_branches.map(&:name).should include('bootstrap') } + it { project.open_branches.map(&:name).should_not include('master') } + end end From 676bce2ab941fcc50ef5796ff77229e238eb9b35 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 31 Mar 2013 18:49:06 +0300 Subject: [PATCH 118/152] Move Commit and Repository logic to lib/gitlab/git --- lib/gitlab/git/commit.rb | 179 ++++++++++++++++++++++++++++++++++ lib/gitlab/git/repository.rb | 181 +++++++++++++++++++++++++++++++++++ 2 files changed, 360 insertions(+) create mode 100644 lib/gitlab/git/commit.rb create mode 100644 lib/gitlab/git/repository.rb diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb new file mode 100644 index 00000000..86e0dfbb --- /dev/null +++ b/lib/gitlab/git/commit.rb @@ -0,0 +1,179 @@ +# Gitlab::Git::Gitlab::Git::Commit is a wrapper around native Grit::Commit object +# We dont want to use grit objects inside app/ +# It helps us easily migrate to rugged in future +module Gitlab + module Git + class Gitlab::Git::Commit + attr_accessor :raw_commit, :head, :refs + + delegate :message, :authored_date, :committed_date, :parents, :sha, + :date, :committer, :author, :diffs, :tree, :id, :stats, + :to_patch, to: :raw_commit + + class << self + def find_or_first(repo, commit_id = nil, root_ref) + commit = if commit_id + repo.commit(commit_id) + else + repo.commits(root_ref).first + end + + Gitlab::Git::Commit.new(commit) if commit + end + + def fresh_commits(repo, n = 10) + commits = repo.heads.map do |h| + repo.commits(h.name, n).map { |c| Gitlab::Git::Commit.new(c, h) } + end.flatten.uniq { |c| c.id } + + commits.sort! do |x, y| + y.committed_date <=> x.committed_date + end + + commits[0...n] + end + + def commits_with_refs(repo, n = 20) + commits = repo.branches.map { |ref| Gitlab::Git::Commit.new(ref.commit, ref) } + + commits.sort! do |x, y| + y.committed_date <=> x.committed_date + end + + commits[0..n] + end + + def commits_since(repo, date) + commits = repo.heads.map do |h| + repo.log(h.name, nil, since: date).each { |c| Gitlab::Git::Commit.new(c, h) } + end.flatten.uniq { |c| c.id } + + commits.sort! do |x, y| + y.committed_date <=> x.committed_date + end + + commits + end + + def commits(repo, ref, path = nil, limit = nil, offset = nil) + if path + repo.log(ref, path, max_count: limit, skip: offset) + elsif limit && offset + repo.commits(ref, limit, offset) + else + repo.commits(ref) + end.map{ |c| Gitlab::Git::Commit.new(c) } + end + + def commits_between(repo, from, to) + repo.commits_between(from, to).map { |c| Gitlab::Git::Commit.new(c) } + end + + def compare(project, from, to) + result = { + commits: [], + diffs: [], + commit: nil, + same: false + } + + return result unless from && to + + first = project.repository.commit(to.try(:strip)) + last = project.repository.commit(from.try(:strip)) + + if first && last + result[:same] = (first.id == last.id) + result[:commits] = project.repo.commits_between(last.id, first.id).map {|c| Gitlab::Git::Commit.new(c)} + + # Dont load diff for 100+ commits + result[:diffs] = if result[:commits].size > 100 + [] + else + project.repo.diff(last.id, first.id) rescue [] + end + + result[:commit] = Gitlab::Git::Commit.new(first) + end + + result + end + end + + def initialize(raw_commit, head = nil) + raise "Nil as raw commit passed" unless raw_commit + + @raw_commit = raw_commit + @head = head + end + + def short_id(length = 10) + id.to_s[0..length] + end + + def safe_message + @safe_message ||= message + end + + def created_at + committed_date + end + + def author_email + author.email + end + + def author_name + author.name + end + + # Was this commit committed by a different person than the original author? + def different_committer? + author_name != committer_name || author_email != committer_email + end + + def committer_name + committer.name + end + + def committer_email + committer.email + end + + def prev_commit + @prev_commit ||= if parents.present? + Gitlab::Git::Commit.new(parents.first) + else + nil + end + end + + def prev_commit_id + prev_commit.try :id + end + + # Shows the diff between the commit's parent and the commit. + # + # Cuts out the header and stats from #to_patch and returns only the diff. + def to_diff + # see Grit::Gitlab::Git::Commit#show + patch = to_patch + + # discard lines before the diff + lines = patch.split("\n") + while !lines.first.start_with?("diff --git") do + lines.shift + end + lines.pop if lines.last =~ /^[\d.]+$/ # Git version + lines.pop if lines.last == "-- " # end of diff + lines.join("\n") + end + + def has_zero_stats? + stats.total.zero? + rescue + true + end + end + end +end diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb new file mode 100644 index 00000000..53d9c735 --- /dev/null +++ b/lib/gitlab/git/repository.rb @@ -0,0 +1,181 @@ +# Gitlab::Git::Gitlab::Git::Commit is a wrapper around native Grit::Repository object +# We dont want to use grit objects inside app/ +# It helps us easily migrate to rugged in future +module Gitlab + module Git + class Repository + include Gitlab::Popen + + class NoRepository < StandardError; end + + # Repository directory name with namespace direcotry + # Examples: + # gitlab/gitolite + # diaspora + # + attr_accessor :path_with_namespace + + # Grit repo object + attr_accessor :repo + + # Default branch in the repository + attr_accessor :root_ref + + def initialize(path_with_namespace, root_ref = 'master') + @root_ref = root_ref || "master" + @path_with_namespace = path_with_namespace + + # Init grit repo object + repo + end + + def raw + repo + end + + def path_to_repo + @path_to_repo ||= File.join(Gitlab.config.gitlab_shell.repos_path, "#{path_with_namespace}.git") + end + + def repo + @repo ||= Grit::Repo.new(path_to_repo) + rescue Grit::NoSuchPathError + raise NoRepository.new('no repository for such path') + end + + def commit(commit_id = nil) + Gitlab::Git::Commit.find_or_first(repo, commit_id, root_ref) + end + + def fresh_commits(n = 10) + Gitlab::Git::Commit.fresh_commits(repo, n) + end + + def commits_with_refs(n = 20) + Gitlab::Git::Commit.commits_with_refs(repo, n) + end + + def commits_since(date) + Gitlab::Git::Commit.commits_since(repo, date) + end + + def commits(ref, path = nil, limit = nil, offset = nil) + Gitlab::Git::Commit.commits(repo, ref, path, limit, offset) + end + + def last_commit_for(ref, path = nil) + commits(ref, path, 1).first + end + + def commits_between(from, to) + Gitlab::Git::Commit.commits_between(repo, from, to) + end + + # Returns an Array of branch names + # sorted by name ASC + def branch_names + branches.map(&:name) + end + + # Returns an Array of Branches + def branches + repo.branches.sort_by(&:name) + end + + # Returns an Array of tag names + def tag_names + repo.tags.collect(&:name).sort.reverse + end + + # Returns an Array of Tags + def tags + repo.tags.sort_by(&:name).reverse + end + + # Returns an Array of branch and tag names + def ref_names + [branch_names + tag_names].flatten + end + + def heads + @heads ||= repo.heads + end + + def tree(fcommit, path = nil) + fcommit = commit if fcommit == :head + tree = fcommit.tree + path ? (tree / path) : tree + end + + def has_commits? + !!commit + rescue Grit::NoSuchPathError + false + end + + def empty? + !has_commits? + end + + # Discovers the default branch based on the repository's available branches + # + # - If no branches are present, returns nil + # - If one branch is present, returns its name + # - If two or more branches are present, returns the one that has a name + # matching root_ref (default_branch or 'master' if default_branch is nil) + def discover_default_branch + if branch_names.length == 0 + nil + elsif branch_names.length == 1 + branch_names.first + else + branch_names.select { |v| v == root_ref }.first + end + end + + # Archive Project to .tar.gz + # + # Already packed repo archives stored at + # app_root/tmp/repositories/project_name/project_name-commit-id.tag.gz + # + def archive_repo(ref) + ref = ref || self.root_ref + commit = self.commit(ref) + return nil unless commit + + # Build file path + file_name = self.path_with_namespace.gsub("/","_") + "-" + commit.id.to_s + ".tar.gz" + storage_path = Rails.root.join("tmp", "repositories") + file_path = File.join(storage_path, self.path_with_namespace, file_name) + + # Put files into a directory before archiving + prefix = File.basename(self.path_with_namespace) + "/" + + # Create file if not exists + unless File.exists?(file_path) + FileUtils.mkdir_p File.dirname(file_path) + file = self.repo.archive_to_file(ref, prefix, file_path) + end + + file_path + end + + # Return repo size in megabytes + # Cached in redis + def size + Rails.cache.fetch(cache_key(:size)) do + size = popen('du -s', path_to_repo).first.strip.to_i + (size.to_f / 1024).round(2) + end + end + + def expire_cache + Rails.cache.delete(cache_key(:size)) + end + + def cache_key(type) + "#{type}:#{path_with_namespace}" + end + end + end +end From d444a23ad6d9c2455a0159435d0c63342aca5edb Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 31 Mar 2013 18:49:31 +0300 Subject: [PATCH 119/152] specs for Gitlab::Git::Repository and Gitlab::Git::Commit --- spec/lib/git/commit_spec.rb | 50 +++++++++++++++ spec/lib/git/repository_spec.rb | 105 ++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 spec/lib/git/commit_spec.rb create mode 100644 spec/lib/git/repository_spec.rb diff --git a/spec/lib/git/commit_spec.rb b/spec/lib/git/commit_spec.rb new file mode 100644 index 00000000..93f579d3 --- /dev/null +++ b/spec/lib/git/commit_spec.rb @@ -0,0 +1,50 @@ +require "spec_helper" + +describe Gitlab::Git::Commit do + let(:commit) { create(:project).repository.commit } + + describe "Commit info" do + before do + @committer = double( + email: 'mike@smith.com', + name: 'Mike Smith' + ) + + @author = double( + email: 'john@smith.com', + name: 'John Smith' + ) + + @raw_commit = double( + id: "bcf03b5de6abcf03b5de6c", + author: @author, + committer: @committer, + committed_date: Date.yesterday, + message: 'Refactoring specs' + ) + + @commit = Gitlab::Git::Commit.new(@raw_commit) + end + + it { @commit.short_id.should == "bcf03b5de6a" } + it { @commit.safe_message.should == @raw_commit.message } + it { @commit.created_at.should == @raw_commit.committed_date } + it { @commit.author_email.should == @author.email } + it { @commit.author_name.should == @author.name } + it { @commit.committer_name.should == @committer.name } + it { @commit.committer_email.should == @committer.email } + it { @commit.different_committer?.should be_true } + end + + describe "Class methods" do + subject { Gitlab::Git::Commit } + + it { should respond_to(:find_or_first) } + it { should respond_to(:fresh_commits) } + it { should respond_to(:commits_with_refs) } + it { should respond_to(:commits_since) } + it { should respond_to(:commits_between) } + it { should respond_to(:commits) } + it { should respond_to(:compare) } + end +end diff --git a/spec/lib/git/repository_spec.rb b/spec/lib/git/repository_spec.rb new file mode 100644 index 00000000..e0ff93ea --- /dev/null +++ b/spec/lib/git/repository_spec.rb @@ -0,0 +1,105 @@ +require "spec_helper" + +describe Gitlab::Git::Repository do + let(:project) { create(:project) } + let(:repository) { project.repository } + + describe "Respond to" do + subject { repository } + + it { should respond_to(:repo) } + it { should respond_to(:tree) } + it { should respond_to(:root_ref) } + it { should respond_to(:tags) } + it { should respond_to(:commit) } + it { should respond_to(:commits) } + it { should respond_to(:commits_between) } + it { should respond_to(:commits_with_refs) } + it { should respond_to(:commits_since) } + it { should respond_to(:commits_between) } + end + + + describe "#discover_default_branch" do + let(:master) { 'master' } + let(:stable) { 'stable' } + + it "returns 'master' when master exists" do + repository.should_receive(:branch_names).at_least(:once).and_return([stable, master]) + repository.discover_default_branch.should == 'master' + end + + it "returns non-master when master exists but default branch is set to something else" do + repository.root_ref = 'stable' + repository.should_receive(:branch_names).at_least(:once).and_return([stable, master]) + repository.discover_default_branch.should == 'stable' + end + + it "returns a non-master branch when only one exists" do + repository.should_receive(:branch_names).at_least(:once).and_return([stable]) + repository.discover_default_branch.should == 'stable' + end + + it "returns nil when no branch exists" do + repository.should_receive(:branch_names).at_least(:once).and_return([]) + repository.discover_default_branch.should be_nil + end + end + + describe :commit do + it "should return first head commit if without params" do + repository.commit.id.should == repository.repo.commits.first.id + end + + it "should return valid commit" do + repository.commit(ValidCommit::ID).should be_valid_commit + end + + it "should return nil" do + repository.commit("+123_4532530XYZ").should be_nil + end + end + + describe :tree do + before do + @commit = repository.commit(ValidCommit::ID) + end + + it "should raise error w/o arguments" do + lambda { repository.tree }.should raise_error + end + + it "should return root tree for commit" do + tree = repository.tree(@commit) + tree.contents.size.should == ValidCommit::FILES_COUNT + tree.contents.map(&:name).should == ValidCommit::FILES + end + + it "should return root tree for commit with correct path" do + tree = repository.tree(@commit, ValidCommit::C_FILE_PATH) + tree.contents.map(&:name).should == ValidCommit::C_FILES + end + + it "should return root tree for commit with incorrect path" do + repository.tree(@commit, "invalid_path").should be_nil + end + end + + describe "fresh commits" do + it { repository.fresh_commits(3).count.should == 3 } + it { repository.fresh_commits.first.id.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a" } + it { repository.fresh_commits.last.id.should == "f403da73f5e62794a0447aca879360494b08f678" } + end + + describe "commits_between" do + subject do + commits = repository.commits_between("3a4b4fb4cde7809f033822a171b9feae19d41fff", + "8470d70da67355c9c009e4401746b1d5410af2e3") + commits.map { |c| c.id } + end + + it { should have(3).elements } + it { should include("f0f14c8eaba69ebddd766498a9d0b0e79becd633") } + it { should_not include("bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a") } + end +end From 154e54b46e01615bc13f5e3ac2d0f07f7a27464d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 31 Mar 2013 18:49:58 +0300 Subject: [PATCH 120/152] Remove grit logic from app/ --- app/models/commit.rb | 169 ++--------------------------------- app/models/gollum_wiki.rb | 2 +- app/models/merge_request.rb | 2 +- app/models/network/commit.rb | 2 +- app/models/note.rb | 2 +- app/models/project.rb | 4 +- 6 files changed, 11 insertions(+), 170 deletions(-) diff --git a/app/models/commit.rb b/app/models/commit.rb index 4d0c57b3..0164ae66 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -8,174 +8,15 @@ class Commit # DIFF_SAFE_SIZE = 100 - attr_accessor :commit, :head, :refs + attr_accessor :raw - delegate :message, :authored_date, :committed_date, :parents, :sha, - :date, :committer, :author, :diffs, :tree, :id, :stats, - :to_patch, to: :commit - - class << self - def find_or_first(repo, commit_id = nil, root_ref) - commit = if commit_id - repo.commit(commit_id) - else - repo.commits(root_ref).first - end - - Commit.new(commit) if commit - end - - def fresh_commits(repo, n = 10) - commits = repo.heads.map do |h| - repo.commits(h.name, n).map { |c| Commit.new(c, h) } - end.flatten.uniq { |c| c.id } - - commits.sort! do |x, y| - y.committed_date <=> x.committed_date - end - - commits[0...n] - end - - def commits_with_refs(repo, n = 20) - commits = repo.branches.map { |ref| Commit.new(ref.commit, ref) } - - commits.sort! do |x, y| - y.committed_date <=> x.committed_date - end - - commits[0..n] - end - - def commits_since(repo, date) - commits = repo.heads.map do |h| - repo.log(h.name, nil, since: date).each { |c| Commit.new(c, h) } - end.flatten.uniq { |c| c.id } - - commits.sort! do |x, y| - y.committed_date <=> x.committed_date - end - - commits - end - - def commits(repo, ref, path = nil, limit = nil, offset = nil) - if path - repo.log(ref, path, max_count: limit, skip: offset) - elsif limit && offset - repo.commits(ref, limit, offset) - else - repo.commits(ref) - end.map{ |c| Commit.new(c) } - end - - def commits_between(repo, from, to) - repo.commits_between(from, to).map { |c| Commit.new(c) } - end - - def compare(project, from, to) - result = { - commits: [], - diffs: [], - commit: nil, - same: false - } - - return result unless from && to - - first = project.repository.commit(to.try(:strip)) - last = project.repository.commit(from.try(:strip)) - - if first && last - result[:same] = (first.id == last.id) - result[:commits] = project.repo.commits_between(last.id, first.id).map {|c| Commit.new(c)} - - # Dont load diff for 100+ commits - result[:diffs] = if result[:commits].size > 100 - [] - else - project.repo.diff(last.id, first.id) rescue [] - end - - result[:commit] = Commit.new(first) - end - - result - end - end - - def initialize(raw_commit, head = nil) + def initialize(raw_commit) raise "Nil as raw commit passed" unless raw_commit - @commit = raw_commit - @head = head + @raw = raw_commit end - def short_id(length = 10) - id.to_s[0..length] - end - - def safe_message - @safe_message ||= message - end - - def created_at - committed_date - end - - def author_email - author.email - end - - def author_name - author.name - end - - # Was this commit committed by a different person than the original author? - def different_committer? - author_name != committer_name || author_email != committer_email - end - - def committer_name - committer.name - end - - def committer_email - committer.email - end - - def prev_commit - @prev_commit ||= if parents.present? - Commit.new(parents.first) - else - nil - end - end - - def prev_commit_id - prev_commit.try :id - end - - # Shows the diff between the commit's parent and the commit. - # - # Cuts out the header and stats from #to_patch and returns only the diff. - def to_diff - # see Grit::Commit#show - patch = to_patch - - # discard lines before the diff - lines = patch.split("\n") - while !lines.first.start_with?("diff --git") do - lines.shift - end - lines.pop if lines.last =~ /^[\d.]+$/ # Git version - lines.pop if lines.last == "-- " # end of diff - lines.join("\n") - end - - def has_zero_stats? - stats.total.zero? - rescue - true + def method_missing(m, *args, &block) + @raw.send(m, *args, &block) end end diff --git a/app/models/gollum_wiki.rb b/app/models/gollum_wiki.rb index a1ee3a08..cdfcd567 100644 --- a/app/models/gollum_wiki.rb +++ b/app/models/gollum_wiki.rb @@ -50,7 +50,7 @@ class GollumWiki # Returns the last 30 Commit objects across the entire # repository. def recent_history - Commit.fresh_commits(wiki.repo, 30) + Gitlab::Git::Commit.fresh_commits(wiki.repo, 30) end # Finds a page within the repository based on a tile diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 9d42b1e1..505f6637 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -169,7 +169,7 @@ class MergeRequest < ActiveRecord::Base end def unmerged_commits - self.project.repo. + self.project.repository. commits_between(self.target_branch, self.source_branch). map {|c| Commit.new(c)}. sort_by(&:created_at). diff --git a/app/models/network/commit.rb b/app/models/network/commit.rb index d0bc61c3..3cd0c015 100644 --- a/app/models/network/commit.rb +++ b/app/models/network/commit.rb @@ -8,7 +8,7 @@ module Network attr_accessor :time, :spaces, :parent_spaces def initialize(raw_commit, refs) - @commit = ::Commit.new(raw_commit) + @commit = Gitlab::Git::Commit.new(raw_commit) @time = -1 @spaces = [] @parent_spaces = [] diff --git a/app/models/note.rb b/app/models/note.rb index f26420ca..17ceb541 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -130,7 +130,7 @@ class Note < ActiveRecord::Base # override to return commits, which are not active record def noteable if for_commit? - project.repository.commit(commit_id) + Commit.new(project.repository.commit(commit_id)) else super end diff --git a/app/models/project.rb b/app/models/project.rb index 6871afca..54abbc3e 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -142,11 +142,11 @@ class Project < ActiveRecord::Base def repository if path - @repository ||= Repository.new(path_with_namespace, default_branch) + @repository ||= Gitlab::Git::Repository.new(path_with_namespace, default_branch) else nil end - rescue Grit::NoSuchPathError + rescue Gitlab::Git::NoRepository nil end From 9dc644635f99dffa26555eeb1c92f988221ccb6a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 31 Mar 2013 18:50:17 +0300 Subject: [PATCH 121/152] Fix tests and remove app/models/repository.rb --- app/models/repository.rb | 170 ----------------------------- lib/extracts_path.rb | 4 +- spec/models/commit_spec.rb | 45 -------- spec/models/project_spec.rb | 2 +- spec/models/repository_spec.rb | 105 ------------------ spec/support/stubbed_repository.rb | 4 +- 6 files changed, 5 insertions(+), 325 deletions(-) delete mode 100644 app/models/repository.rb delete mode 100644 spec/models/repository_spec.rb diff --git a/app/models/repository.rb b/app/models/repository.rb deleted file mode 100644 index 7f56047b..00000000 --- a/app/models/repository.rb +++ /dev/null @@ -1,170 +0,0 @@ -class Repository - include Gitlab::Popen - - # Repository directory name with namespace direcotry - # Examples: - # gitlab/gitolite - # diaspora - # - attr_accessor :path_with_namespace - - # Grit repo object - attr_accessor :repo - - # Default branch in the repository - attr_accessor :root_ref - - def initialize(path_with_namespace, root_ref = 'master') - @root_ref = root_ref || "master" - @path_with_namespace = path_with_namespace - - # Init grit repo object - repo - end - - def raw - repo - end - - def path_to_repo - @path_to_repo ||= File.join(Gitlab.config.gitlab_shell.repos_path, "#{path_with_namespace}.git") - end - - def repo - @repo ||= Grit::Repo.new(path_to_repo) - end - - def commit(commit_id = nil) - Commit.find_or_first(repo, commit_id, root_ref) - end - - def fresh_commits(n = 10) - Commit.fresh_commits(repo, n) - end - - def commits_with_refs(n = 20) - Commit.commits_with_refs(repo, n) - end - - def commits_since(date) - Commit.commits_since(repo, date) - end - - def commits(ref, path = nil, limit = nil, offset = nil) - Commit.commits(repo, ref, path, limit, offset) - end - - def last_commit_for(ref, path = nil) - commits(ref, path, 1).first - end - - def commits_between(from, to) - Commit.commits_between(repo, from, to) - end - - # Returns an Array of branch names - # sorted by name ASC - def branch_names - branches.map(&:name) - end - - # Returns an Array of Branches - def branches - repo.branches.sort_by(&:name) - end - - # Returns an Array of tag names - def tag_names - repo.tags.collect(&:name).sort.reverse - end - - # Returns an Array of Tags - def tags - repo.tags.sort_by(&:name).reverse - end - - # Returns an Array of branch and tag names - def ref_names - [branch_names + tag_names].flatten - end - - def heads - @heads ||= repo.heads - end - - def tree(fcommit, path = nil) - fcommit = commit if fcommit == :head - tree = fcommit.tree - path ? (tree / path) : tree - end - - def has_commits? - !!commit - rescue Grit::NoSuchPathError - false - end - - def empty? - !has_commits? - end - - # Discovers the default branch based on the repository's available branches - # - # - If no branches are present, returns nil - # - If one branch is present, returns its name - # - If two or more branches are present, returns the one that has a name - # matching root_ref (default_branch or 'master' if default_branch is nil) - def discover_default_branch - if branch_names.length == 0 - nil - elsif branch_names.length == 1 - branch_names.first - else - branch_names.select { |v| v == root_ref }.first - end - end - - # Archive Project to .tar.gz - # - # Already packed repo archives stored at - # app_root/tmp/repositories/project_name/project_name-commit-id.tag.gz - # - def archive_repo(ref) - ref = ref || self.root_ref - commit = self.commit(ref) - return nil unless commit - - # Build file path - file_name = self.path_with_namespace.gsub("/","_") + "-" + commit.id.to_s + ".tar.gz" - storage_path = Rails.root.join("tmp", "repositories") - file_path = File.join(storage_path, self.path_with_namespace, file_name) - - # Put files into a directory before archiving - prefix = File.basename(self.path_with_namespace) + "/" - - # Create file if not exists - unless File.exists?(file_path) - FileUtils.mkdir_p File.dirname(file_path) - file = self.repo.archive_to_file(ref, prefix, file_path) - end - - file_path - end - - # Return repo size in megabytes - # Cached in redis - def size - Rails.cache.fetch(cache_key(:size)) do - size = popen('du -s', path_to_repo).first.strip.to_i - (size.to_f / 1024).round(2) - end - end - - def expire_cache - Rails.cache.delete(cache_key(:size)) - end - - def cache_key(type) - "#{type}:#{path_with_namespace}" - end -end diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb index 351fc2f2..4ad485c5 100644 --- a/lib/extracts_path.rb +++ b/lib/extracts_path.rb @@ -100,8 +100,8 @@ module ExtractsPath # It is used "@project.repository.commits(@ref, @path, 1, 0)", # because "@project.repository.commit(@ref)" returns wrong commit when @ref is tag name. - commits = @project.repository.commits(@ref, @path, 1, 0) - @commit = CommitDecorator.decorate(commits.first) + @commit = @project.repository.commits(@ref, @path, 1, 0).first + @commit = CommitDecorator.decorate(@commit) @tree = Tree.new(@commit.tree, @ref, @path) @tree = TreeDecorator.new(@tree) diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb index 91301029..7b063d2a 100644 --- a/spec/models/commit_spec.rb +++ b/spec/models/commit_spec.rb @@ -35,51 +35,6 @@ describe Commit do end end - describe "Commit info" do - before do - @committer = double( - email: 'mike@smith.com', - name: 'Mike Smith' - ) - - @author = double( - email: 'john@smith.com', - name: 'John Smith' - ) - - @raw_commit = double( - id: "bcf03b5de6abcf03b5de6c", - author: @author, - committer: @committer, - committed_date: Date.yesterday, - message: 'Refactoring specs' - ) - - @commit = Commit.new(@raw_commit) - end - - it { @commit.short_id.should == "bcf03b5de6a" } - it { @commit.safe_message.should == @raw_commit.message } - it { @commit.created_at.should == @raw_commit.committed_date } - it { @commit.author_email.should == @author.email } - it { @commit.author_name.should == @author.name } - it { @commit.committer_name.should == @committer.name } - it { @commit.committer_email.should == @committer.email } - it { @commit.different_committer?.should be_true } - end - - describe "Class methods" do - subject { Commit } - - it { should respond_to(:find_or_first) } - it { should respond_to(:fresh_commits) } - it { should respond_to(:commits_with_refs) } - it { should respond_to(:commits_since) } - it { should respond_to(:commits_between) } - it { should respond_to(:commits) } - it { should respond_to(:compare) } - end - describe "delegation" do subject { commit } diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 53388b93..90b5e08e 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -187,7 +187,7 @@ describe Project do let(:project) { create(:project) } it "should return valid repo" do - project.repository.should be_kind_of(Repository) + project.repository.should be_kind_of(Gitlab::Git::Repository) end it "should return nil" do diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb deleted file mode 100644 index 71f9b964..00000000 --- a/spec/models/repository_spec.rb +++ /dev/null @@ -1,105 +0,0 @@ -require "spec_helper" - -describe Repository do - let(:project) { create(:project) } - let(:repository) { project.repository } - - describe "Respond to" do - subject { repository } - - it { should respond_to(:repo) } - it { should respond_to(:tree) } - it { should respond_to(:root_ref) } - it { should respond_to(:tags) } - it { should respond_to(:commit) } - it { should respond_to(:commits) } - it { should respond_to(:commits_between) } - it { should respond_to(:commits_with_refs) } - it { should respond_to(:commits_since) } - it { should respond_to(:commits_between) } - end - - - describe "#discover_default_branch" do - let(:master) { 'master' } - let(:stable) { 'stable' } - - it "returns 'master' when master exists" do - repository.should_receive(:branch_names).at_least(:once).and_return([stable, master]) - repository.discover_default_branch.should == 'master' - end - - it "returns non-master when master exists but default branch is set to something else" do - repository.root_ref = 'stable' - repository.should_receive(:branch_names).at_least(:once).and_return([stable, master]) - repository.discover_default_branch.should == 'stable' - end - - it "returns a non-master branch when only one exists" do - repository.should_receive(:branch_names).at_least(:once).and_return([stable]) - repository.discover_default_branch.should == 'stable' - end - - it "returns nil when no branch exists" do - repository.should_receive(:branch_names).at_least(:once).and_return([]) - repository.discover_default_branch.should be_nil - end - end - - describe :commit do - it "should return first head commit if without params" do - repository.commit.id.should == repository.repo.commits.first.id - end - - it "should return valid commit" do - repository.commit(ValidCommit::ID).should be_valid_commit - end - - it "should return nil" do - repository.commit("+123_4532530XYZ").should be_nil - end - end - - describe :tree do - before do - @commit = repository.commit(ValidCommit::ID) - end - - it "should raise error w/o arguments" do - lambda { repository.tree }.should raise_error - end - - it "should return root tree for commit" do - tree = repository.tree(@commit) - tree.contents.size.should == ValidCommit::FILES_COUNT - tree.contents.map(&:name).should == ValidCommit::FILES - end - - it "should return root tree for commit with correct path" do - tree = repository.tree(@commit, ValidCommit::C_FILE_PATH) - tree.contents.map(&:name).should == ValidCommit::C_FILES - end - - it "should return root tree for commit with incorrect path" do - repository.tree(@commit, "invalid_path").should be_nil - end - end - - describe "fresh commits" do - it { repository.fresh_commits(3).count.should == 3 } - it { repository.fresh_commits.first.id.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a" } - it { repository.fresh_commits.last.id.should == "f403da73f5e62794a0447aca879360494b08f678" } - end - - describe "commits_between" do - subject do - commits = repository.commits_between("3a4b4fb4cde7809f033822a171b9feae19d41fff", - "8470d70da67355c9c009e4401746b1d5410af2e3") - commits.map { |c| c.id } - end - - it { should have(3).elements } - it { should include("f0f14c8eaba69ebddd766498a9d0b0e79becd633") } - it { should_not include("bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a") } - end -end diff --git a/spec/support/stubbed_repository.rb b/spec/support/stubbed_repository.rb index 6376c8d5..68c380e6 100644 --- a/spec/support/stubbed_repository.rb +++ b/spec/support/stubbed_repository.rb @@ -1,4 +1,4 @@ -require "repository" +require "gitlab/git/repository" require "project" require "merge_request" require "shell" @@ -39,7 +39,7 @@ class MergeRequest end end -class GitLabTestRepo < Repository +class GitLabTestRepo < Gitlab::Git::Repository def repo @repo ||= Grit::Repo.new(Rails.root.join('tmp', 'repositories', 'gitlabhq')) end From 26323046fda07b2353ee427afcd0253cea935047 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 31 Mar 2013 19:00:45 +0300 Subject: [PATCH 122/152] Decorate Gitlab::Git::Commit with Commit --- app/contexts/commit_load_context.rb | 1 + app/controllers/commits_controller.rb | 1 + app/models/commit.rb | 8 ++++++++ lib/gitlab/git/commit.rb | 4 ++-- spec/helpers/gitlab_markdown_helper_spec.rb | 2 +- 5 files changed, 13 insertions(+), 3 deletions(-) diff --git a/app/contexts/commit_load_context.rb b/app/contexts/commit_load_context.rb index 1f23f633..c8d77d9b 100644 --- a/app/contexts/commit_load_context.rb +++ b/app/contexts/commit_load_context.rb @@ -12,6 +12,7 @@ class CommitLoadContext < BaseContext commit = project.repository.commit(params[:id]) if commit + commit = Commit.new(commit) commit = CommitDecorator.decorate(commit) line_notes = project.notes.for_commit_id(commit.id).inline diff --git a/app/controllers/commits_controller.rb b/app/controllers/commits_controller.rb index 9dc0d968..fded5f0a 100644 --- a/app/controllers/commits_controller.rb +++ b/app/controllers/commits_controller.rb @@ -13,6 +13,7 @@ class CommitsController < ProjectResourceController @limit, @offset = (params[:limit] || 40), (params[:offset] || 0) @commits = @repo.commits(@ref, @path, @limit, @offset) + @commits = Commit.decorate(@commits) @commits = CommitDecorator.decorate_collection(@commits) respond_to do |format| diff --git a/app/models/commit.rb b/app/models/commit.rb index 0164ae66..ea5b451b 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -10,12 +10,20 @@ class Commit attr_accessor :raw + def self.decorate(commits) + commits.map { |c| Commit.new(c) } + end + def initialize(raw_commit) raise "Nil as raw commit passed" unless raw_commit @raw = raw_commit end + def id + @raw.id + end + def method_missing(m, *args, &block) @raw.send(m, *args, &block) end diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb index 86e0dfbb..023672f9 100644 --- a/lib/gitlab/git/commit.rb +++ b/lib/gitlab/git/commit.rb @@ -7,8 +7,8 @@ module Gitlab attr_accessor :raw_commit, :head, :refs delegate :message, :authored_date, :committed_date, :parents, :sha, - :date, :committer, :author, :diffs, :tree, :id, :stats, - :to_patch, to: :raw_commit + :date, :committer, :author, :diffs, :tree, :id, :stats, :to_patch, + to: :raw_commit class << self def find_or_first(repo, commit_id = nil, root_ref) diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb index b9025026..3abeaeef 100644 --- a/spec/helpers/gitlab_markdown_helper_spec.rb +++ b/spec/helpers/gitlab_markdown_helper_spec.rb @@ -7,7 +7,7 @@ describe GitlabMarkdownHelper do let!(:project) { create(:project) } let(:user) { create(:user, username: 'gfm') } - let(:commit) { CommitDecorator.decorate(project.repository.commit) } + let(:commit) { CommitDecorator.decorate(Commit.new(project.repository.commit)) } let(:issue) { create(:issue, project: project) } let(:merge_request) { create(:merge_request, project: project) } let(:snippet) { create(:snippet, project: project) } From 1ea385625b481e405fbbffc2b2465553b20d90de Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 31 Mar 2013 23:44:59 +0300 Subject: [PATCH 123/152] Remove Commit & Tree decorators --- app/decorators/commit_decorator.rb | 93 ------------------------------ app/decorators/tree_decorator.rb | 33 ----------- 2 files changed, 126 deletions(-) delete mode 100644 app/decorators/commit_decorator.rb delete mode 100644 app/decorators/tree_decorator.rb diff --git a/app/decorators/commit_decorator.rb b/app/decorators/commit_decorator.rb deleted file mode 100644 index 0337d8d4..00000000 --- a/app/decorators/commit_decorator.rb +++ /dev/null @@ -1,93 +0,0 @@ -class CommitDecorator < ApplicationDecorator - decorates :commit - - # Returns a string describing the commit for use in a link title - # - # Example - # - # "Commit: Alex Denisov - Project git clone panel" - def link_title - "Commit: #{author_name} - #{title}" - end - - # Returns the commits title. - # - # Usually, the commit title is the first line of the commit message. - # In case this first line is longer than 80 characters, it is cut off - # after 70 characters and ellipses (`&hellp;`) are appended. - def title - title = safe_message - - return no_commit_message if title.blank? - - title_end = title.index(/\n/) - if (!title_end && title.length > 80) || (title_end && title_end > 80) - title[0..69] << "…".html_safe - else - title.split(/\n/, 2).first - end - end - - # Returns the commits description - # - # cut off, ellipses (`&hellp;`) are prepended to the commit message. - def description - description = safe_message - - title_end = description.index(/\n/) - if (!title_end && description.length > 80) || (title_end && title_end > 80) - "…".html_safe << description[70..-1] - else - description.split(/\n/, 2)[1].try(:chomp) - end - end - - # Returns a link to the commit author. If the author has a matching user and - # is a member of the current @project it will link to the team member page. - # Otherwise it will link to the author email as specified in the commit. - # - # options: - # avatar: true will prepend the avatar image - # size: size of the avatar image in px - def author_link(options = {}) - person_link(options.merge source: :author) - end - - # Just like #author_link but for the committer. - def committer_link(options = {}) - person_link(options.merge source: :committer) - end - - protected - - def no_commit_message - "--no commit message" - end - - # Private: Returns a link to a person. If the person has a matching user and - # is a member of the current @project it will link to the team member page. - # Otherwise it will link to the person email as specified in the commit. - # - # options: - # source: one of :author or :committer - # avatar: true will prepend the avatar image - # size: size of the avatar image in px - def person_link(options = {}) - source_name = send "#{options[:source]}_name".to_sym - source_email = send "#{options[:source]}_email".to_sym - text = if options[:avatar] - avatar = h.image_tag h.gravatar_icon(source_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "" - %Q{#{avatar} #{source_name}} - else - source_name - end - - user = User.where('name like ? or email like ?', source_name, source_email).first - - if user.nil? - h.mail_to(source_email, text.html_safe, class: "commit-#{options[:source]}-link") - else - h.link_to(text.html_safe, h.user_path(user), class: "commit-#{options[:source]}-link") - end - end -end diff --git a/app/decorators/tree_decorator.rb b/app/decorators/tree_decorator.rb deleted file mode 100644 index 0e760f97..00000000 --- a/app/decorators/tree_decorator.rb +++ /dev/null @@ -1,33 +0,0 @@ -class TreeDecorator < ApplicationDecorator - decorates :tree - - def breadcrumbs(max_links = 2) - if path - part_path = "" - parts = path.split("\/") - - yield('..', nil) if parts.count > max_links - - parts.each do |part| - part_path = File.join(part_path, part) unless part_path.empty? - part_path = part if part_path.empty? - - next unless parts.last(2).include?(part) if parts.count > max_links - yield(part, h.tree_join(ref, part_path)) - end - end - end - - def up_dir? - path.present? - end - - def up_dir_path - file = File.join(path, "..") - h.tree_join(ref, file) - end - - def readme - @readme ||= contents.find { |c| c.is_a?(Grit::Blob) and c.name =~ /^readme/i } - end -end From a0bca5b71d11454b51f890f4dd36bbf948f1edf5 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 31 Mar 2013 23:45:38 +0300 Subject: [PATCH 124/152] Add Repository model to proxy request to Gitlab::Git::Repositoty and decorate commits with Commit model --- app/models/repository.rb | 41 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 app/models/repository.rb diff --git a/app/models/repository.rb b/app/models/repository.rb new file mode 100644 index 00000000..048795b2 --- /dev/null +++ b/app/models/repository.rb @@ -0,0 +1,41 @@ +class Repository + attr_accessor :raw_repository + + def initialize(path_with_namespace, default_branch) + @raw_repository = Gitlab::Git::Repository.new(path_with_namespace, default_branch) + end + + def commit(id = nil) + commit = raw_repository.commit(id) + commit = Commit.new(commit) if commit + commit + end + + def commits(ref, path = nil, limit = nil, offset = nil) + commits = raw_repository.commits(ref, path, limit, offset) + commits = decorate_commits(commits) if commits.present? + commits + end + + def commits_between(target, source) + commits = raw_repository.commits_between(target, source) + commits = decorate_commits(commits) if commits.present? + commits + end + + def method_missing(m, *args, &block) + @raw_repository.send(m, *args, &block) + end + + def respond_to?(method) + return true if @raw_repository.respond_to?(method) + + super + end + + protected + + def decorate_commits(commits) + commits.map { |c| Commit.new(c) } + end +end From 2a6b4f965e97867dbec9c3c5091b61c4ec27bb5d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 31 Mar 2013 23:45:58 +0300 Subject: [PATCH 125/152] rake task to clear redis cache --- lib/tasks/cache.rake | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 lib/tasks/cache.rake diff --git a/lib/tasks/cache.rake b/lib/tasks/cache.rake new file mode 100644 index 00000000..8320b9b2 --- /dev/null +++ b/lib/tasks/cache.rake @@ -0,0 +1,6 @@ +namespace :cache do + desc "GITLAB | Clear redis cache" + task :clear => :environment do + Rails.cache.clear + end +end From 685681e28af2cae7c5ba208130ad5b6b4e5c4ed9 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 31 Mar 2013 23:46:25 +0300 Subject: [PATCH 126/152] remove Tree/Commit decorator usage from controllers --- app/controllers/commits_controller.rb | 2 -- app/controllers/compare_controller.rb | 2 -- app/controllers/merge_requests_controller.rb | 3 --- app/controllers/refs_controller.rb | 3 --- 4 files changed, 10 deletions(-) diff --git a/app/controllers/commits_controller.rb b/app/controllers/commits_controller.rb index fded5f0a..cde1f459 100644 --- a/app/controllers/commits_controller.rb +++ b/app/controllers/commits_controller.rb @@ -13,8 +13,6 @@ class CommitsController < ProjectResourceController @limit, @offset = (params[:limit] || 40), (params[:offset] || 0) @commits = @repo.commits(@ref, @path, @limit, @offset) - @commits = Commit.decorate(@commits) - @commits = CommitDecorator.decorate_collection(@commits) respond_to do |format| format.html # index.html.erb diff --git a/app/controllers/compare_controller.rb b/app/controllers/compare_controller.rb index bd3f1115..b72da783 100644 --- a/app/controllers/compare_controller.rb +++ b/app/controllers/compare_controller.rb @@ -15,8 +15,6 @@ class CompareController < ProjectResourceController @diffs = result[:diffs] @refs_are_same = result[:same] @line_notes = [] - - @commits = CommitDecorator.decorate_collection(@commits) end def create diff --git a/app/controllers/merge_requests_controller.rb b/app/controllers/merge_requests_controller.rb index e2185361..1950ebb2 100644 --- a/app/controllers/merge_requests_controller.rb +++ b/app/controllers/merge_requests_controller.rb @@ -94,12 +94,10 @@ class MergeRequestsController < ProjectResourceController def branch_from @commit = @repository.commit(params[:ref]) - @commit = CommitDecorator.decorate(@commit) end def branch_to @commit = @repository.commit(params[:ref]) - @commit = CommitDecorator.decorate(@commit) end def ci_status @@ -143,7 +141,6 @@ class MergeRequestsController < ProjectResourceController # Get commits from repository # or from cache if already merged @commits = @merge_request.commits - @commits = CommitDecorator.decorate_collection(@commits) @allowed_to_merge = allowed_to_merge? @show_merge_controls = @merge_request.opened? && @commits.any? && @allowed_to_merge diff --git a/app/controllers/refs_controller.rb b/app/controllers/refs_controller.rb index 0e4dba3d..eb8d1e19 100644 --- a/app/controllers/refs_controller.rb +++ b/app/controllers/refs_controller.rb @@ -34,7 +34,6 @@ class RefsController < ProjectResourceController @logs = contents.map do |content| file = params[:path] ? File.join(params[:path], content.name) : content.name last_commit = @repo.commits(@commit.id, file, 1).last - last_commit = CommitDecorator.decorate(last_commit) { file_name: content.name, commit: last_commit @@ -49,9 +48,7 @@ class RefsController < ProjectResourceController @repo = project.repository @commit = @repo.commit(@ref) - @commit = CommitDecorator.decorate(@commit) @tree = Tree.new(@commit.tree, @ref, params[:path]) - @tree = TreeDecorator.new(@tree) @hex_path = Digest::SHA1.hexdigest(params[:path] || "") if params[:path] From da5b0c91dc79136be4315cf61e5520692e19be8a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 31 Mar 2013 23:46:54 +0300 Subject: [PATCH 127/152] Move some decorator logic to helpers --- app/helpers/commits_helper.rb | 74 +++++++++++++++++++++++++++++++++++ app/helpers/tree_helper.rb | 34 ++++++++-------- 2 files changed, 90 insertions(+), 18 deletions(-) diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index acdd48e0..da209e06 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -1,4 +1,20 @@ module CommitsHelper + # Returns a link to the commit author. If the author has a matching user and + # is a member of the current @project it will link to the team member page. + # Otherwise it will link to the author email as specified in the commit. + # + # options: + # avatar: true will prepend the avatar image + # size: size of the avatar image in px + def commit_author_link(commit, options = {}) + commit_person_link(commit, options.merge(source: :author)) + end + + # Just like #author_link but for the committer. + def commit_committer_link(commit, options = {}) + commit_person_link(commit, options.merge(source: :committer)) + end + def identification_type(line) if line[0] == "+" "new" @@ -105,4 +121,62 @@ module CommitsHelper line end end + + # Breadcrumb links for a Project and, if applicable, a tree path + def commits_breadcrumbs + return unless @project && @ref + + # Add the root project link and the arrow icon + crumbs = content_tag(:li) do + content_tag(:span, nil, class: 'arrow') + + link_to(@project.name, project_commits_path(@project, @ref)) + end + + if @path + parts = @path.split('/') + + parts.each_with_index do |part, i| + crumbs += content_tag(:span, '/', class: 'divider') + crumbs += content_tag(:li) do + # The text is just the individual part, but the link needs all the parts before it + link_to part, project_commits_path(@project, tree_join(@ref, parts[0..i].join('/'))) + end + end + end + + crumbs.html_safe + end + + protected + + def no_commit_message + "--no commit message" + end + + # Private: Returns a link to a person. If the person has a matching user and + # is a member of the current @project it will link to the team member page. + # Otherwise it will link to the person email as specified in the commit. + # + # options: + # source: one of :author or :committer + # avatar: true will prepend the avatar image + # size: size of the avatar image in px + def commit_person_link(commit, options = {}) + source_name = commit.send "#{options[:source]}_name".to_sym + source_email = commit.send "#{options[:source]}_email".to_sym + text = if options[:avatar] + avatar = image_tag(gravatar_icon(source_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "") + %Q{#{avatar} #{source_name}} + else + source_name + end + + user = User.where('name like ? or email like ?', source_name, source_email).first + + if user.nil? + mail_to(source_email, text.html_safe, class: "commit-#{options[:source]}-link") + else + link_to(text.html_safe, user_path(user), class: "commit-#{options[:source]}-link") + end + end end diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb index fab0085b..1cba9476 100644 --- a/app/helpers/tree_helper.rb +++ b/app/helpers/tree_helper.rb @@ -70,28 +70,26 @@ module TreeHelper end end - # Breadcrumb links for a Project and, if applicable, a tree path - def breadcrumbs - return unless @project && @ref + def tree_breadcrumbs(tree, max_links = 2) + if tree.path + part_path = "" + parts = tree.path.split("\/") - # Add the root project link and the arrow icon - crumbs = content_tag(:li) do - content_tag(:span, nil, class: 'arrow') + - link_to(@project.name, project_commits_path(@project, @ref)) - end + yield('..', nil) if parts.count > max_links - if @path - parts = @path.split('/') + parts.each do |part| + part_path = File.join(part_path, part) unless part_path.empty? + part_path = part if part_path.empty? - parts.each_with_index do |part, i| - crumbs += content_tag(:span, '/', class: 'divider') - crumbs += content_tag(:li) do - # The text is just the individual part, but the link needs all the parts before it - link_to part, project_commits_path(@project, tree_join(@ref, parts[0..i].join('/'))) - end + next unless parts.last(2).include?(part) if parts.count > max_links + yield(part, tree_join(tree.ref, part_path)) end end - - crumbs.html_safe end + + def up_dir_path tree + file = File.join(tree.path, "..") + tree_join(tree.ref, file) + end + end From b53557aca64fbf55f9bbd59849d83daa10b7361f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 31 Mar 2013 23:47:26 +0300 Subject: [PATCH 128/152] Remove decorator calls and methods from views. Repalace with helper calls when needed --- app/views/blame/show.html.haml | 4 ++-- app/views/commit/_commit_box.html.haml | 4 ++-- app/views/commits/_commit.html.haml | 2 +- app/views/commits/show.html.haml | 2 +- app/views/events/_commit.html.haml | 1 - app/views/repositories/_branch.html.haml | 3 +-- app/views/repositories/_feed.html.haml | 1 - app/views/repositories/tags.html.haml | 3 +-- app/views/tree/_tree.html.haml | 4 ++-- app/views/tree/_tree_commit_column.html.haml | 2 +- app/views/wikis/history.html.haml | 5 +++-- app/views/wikis/pages.html.haml | 4 ++-- app/views/wikis/show.html.haml | 4 ++-- 13 files changed, 18 insertions(+), 21 deletions(-) diff --git a/app/views/blame/show.html.haml b/app/views/blame/show.html.haml index b2a45ef5..b07a514f 100644 --- a/app/views/blame/show.html.haml +++ b/app/views/blame/show.html.haml @@ -22,13 +22,13 @@ %table - current_line = 1 - @blame.each do |commit, lines| - - commit = CommitDecorator.decorate(Commit.new(commit)) + - commit = Commit.new(commit) %tr %td.blame-commit %span.commit = link_to commit.short_id(8), project_commit_path(@project, commit), class: "commit_short_id"   - = commit.author_link avatar: true, size: 16 + = commit_author_link(commit, avatar: true, size: 16)   = link_to_gfm truncate(commit.title, length: 20), project_commit_path(@project, commit.id), class: "row_title" %td.lines.blame-numbers diff --git a/app/views/commit/_commit_box.html.haml b/app/views/commit/_commit_box.html.haml index 4c80c13c..64679177 100644 --- a/app/views/commit/_commit_box.html.haml +++ b/app/views/commit/_commit_box.html.haml @@ -24,14 +24,14 @@ .row .span5 .author - = @commit.author_link avatar: true, size: 32 + = commit_author_link(@commit, avatar: true, size: 32) authored %time{title: @commit.authored_date.stamp("Aug 21, 2011 9:23pm")} #{time_ago_in_words(@commit.authored_date)} ago - if @commit.different_committer? .committer → - = @commit.committer_link + = commit_committer_link(@commit) committed %time{title: @commit.committed_date.stamp("Aug 21, 2011 9:23pm")} #{time_ago_in_words(@commit.committed_date)} ago diff --git a/app/views/commits/_commit.html.haml b/app/views/commits/_commit.html.haml index 2f5ff130..65d92030 100644 --- a/app/views/commits/_commit.html.haml +++ b/app/views/commits/_commit.html.haml @@ -4,7 +4,7 @@ %strong= link_to "Browse Code »", project_tree_path(@project, commit), class: "right" %p = link_to commit.short_id(8), project_commit_path(@project, commit), class: "commit_short_id" - = commit.author_link avatar: true, size: 24 + = commit_author_link(commit, avatar: true, size: 24)   = link_to_gfm truncate(commit.title, length: 70), project_commit_path(@project, commit.id), class: "row_title" diff --git a/app/views/commits/show.html.haml b/app/views/commits/show.html.haml index d180b8ec..586b21df 100644 --- a/app/views/commits/show.html.haml +++ b/app/views/commits/show.html.haml @@ -2,7 +2,7 @@ - if @path.present? %ul.breadcrumb - = breadcrumbs + = commits_breadcrumbs %div{id: dom_id(@project)} #commits-list= render "commits" diff --git a/app/views/events/_commit.html.haml b/app/views/events/_commit.html.haml index ea417aa9..f2f2d47e 100644 --- a/app/views/events/_commit.html.haml +++ b/app/views/events/_commit.html.haml @@ -1,4 +1,3 @@ -- commit = CommitDecorator.decorate(commit) %li.commit %p = link_to commit.short_id(8), project_commit_path(project, commit), class: "commit_short_id" diff --git a/app/views/repositories/_branch.html.haml b/app/views/repositories/_branch.html.haml index a6faa5fd..dd91e14b 100644 --- a/app/views/repositories/_branch.html.haml +++ b/app/views/repositories/_branch.html.haml @@ -1,5 +1,4 @@ -- commit = Commit.new(branch.commit) -- commit = CommitDecorator.decorate(commit) +- commit = Commit.new(Gitlab::Git::Commit.new(branch.commit)) %tr %td = link_to project_commits_path(@project, branch.name) do diff --git a/app/views/repositories/_feed.html.haml b/app/views/repositories/_feed.html.haml index eaf15ca7..6bb75265 100644 --- a/app/views/repositories/_feed.html.haml +++ b/app/views/repositories/_feed.html.haml @@ -1,5 +1,4 @@ - commit = update -- commit = CommitDecorator.new(commit) %tr %td = link_to project_commits_path(@project, commit.head.name) do diff --git a/app/views/repositories/tags.html.haml b/app/views/repositories/tags.html.haml index d4b8bbe1..2d311124 100644 --- a/app/views/repositories/tags.html.haml +++ b/app/views/repositories/tags.html.haml @@ -7,8 +7,7 @@ %th Last commit %th - @tags.each do |tag| - - commit = Commit.new(tag.commit) - - commit = CommitDecorator.decorate(commit) + - commit = Commit.new(Gitlab::Git::Commit.new(tag.commit)) %tr %td %strong diff --git a/app/views/tree/_tree.html.haml b/app/views/tree/_tree.html.haml index 24a57ae7..caab6e45 100644 --- a/app/views/tree/_tree.html.haml +++ b/app/views/tree/_tree.html.haml @@ -3,7 +3,7 @@ %i.icon-angle-right = link_to project_tree_path(@project, @ref) do = @project.path - - tree.breadcrumbs(6) do |title, path| + - tree_breadcrumbs(tree, 6) do |title, path| \/ %li - if path @@ -27,7 +27,7 @@ %tr.tree-item %td.tree-item-file-name = image_tag "file_empty.png", size: '16x16' - = link_to "..", project_tree_path(@project, tree.up_dir_path) + = link_to "..", project_tree_path(@project, up_dir_path(tree)) %td %td %td diff --git a/app/views/tree/_tree_commit_column.html.haml b/app/views/tree/_tree_commit_column.html.haml index 9d02132b..7ae2582c 100644 --- a/app/views/tree/_tree_commit_column.html.haml +++ b/app/views/tree/_tree_commit_column.html.haml @@ -1,2 +1,2 @@ -%span.tree_author= commit.author_link avatar: true +%span.tree_author= commit_author_link(commit, avatar: true) = link_to_gfm truncate(commit.title, length: 80), project_commit_path(@project, commit.id), class: "tree-commit-link" diff --git a/app/views/wikis/history.html.haml b/app/views/wikis/history.html.haml index 599e9cf6..f4946ed0 100644 --- a/app/views/wikis/history.html.haml +++ b/app/views/wikis/history.html.haml @@ -14,12 +14,13 @@ %th Format %tbody - @wiki.versions.each do |version| - - commit = CommitDecorator.new(version) + - commit = version %tr %td = link_to project_wiki_path(@project, @wiki, version_id: commit.id) do = commit.short_id - %td= commit.author_link avatar: true, size: 24 + %td + = commit_author_link(commit, avatar: true, size: 24) %td = commit.title %td diff --git a/app/views/wikis/pages.html.haml b/app/views/wikis/pages.html.haml index eb65599d..95d5eef1 100644 --- a/app/views/wikis/pages.html.haml +++ b/app/views/wikis/pages.html.haml @@ -21,5 +21,5 @@ = wiki_page.created_at.to_s(:short) do (#{time_ago_in_words(wiki_page.created_at)} ago) - - commit = CommitDecorator.decorate(wiki_page.version) - %td= commit.author_link avatar: true, size: 24 + %td + = commit_author_link(wiki_page.version, avatar: true, size: 24) diff --git a/app/views/wikis/show.html.haml b/app/views/wikis/show.html.haml index b660a15e..4102182e 100644 --- a/app/views/wikis/show.html.haml +++ b/app/views/wikis/show.html.haml @@ -13,5 +13,5 @@ = preserve do = render_wiki_content(@wiki) -- commit = CommitDecorator.new(@wiki.version) -%p.time Last edited by #{commit.author_link(avatar: true, size: 16)} #{time_ago_in_words @wiki.created_at} ago +- commit = Commit.new(@wiki.version) +%p.time Last edited by #{commit_author_link(commit, avatar: true, size: 16)} #{time_ago_in_words @wiki.created_at} ago From bbfbff3add4c78ce1256ac3bbe787cc6eb9fe1b9 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 31 Mar 2013 23:48:12 +0300 Subject: [PATCH 129/152] Extend models functionality with old decorator methods. Use Repository model --- app/contexts/commit_load_context.rb | 1 - app/mailers/emails/notes.rb | 1 - app/models/commit.rb | 51 ++++++++++++++++++++++++++--- app/models/merge_request.rb | 13 ++++++-- app/models/project.rb | 2 +- app/models/tree.rb | 8 +++++ lib/extracts_path.rb | 2 -- 7 files changed, 67 insertions(+), 11 deletions(-) diff --git a/app/contexts/commit_load_context.rb b/app/contexts/commit_load_context.rb index c8d77d9b..a0652377 100644 --- a/app/contexts/commit_load_context.rb +++ b/app/contexts/commit_load_context.rb @@ -13,7 +13,6 @@ class CommitLoadContext < BaseContext if commit commit = Commit.new(commit) - commit = CommitDecorator.decorate(commit) line_notes = project.notes.for_commit_id(commit.id).inline result[:commit] = commit diff --git a/app/mailers/emails/notes.rb b/app/mailers/emails/notes.rb index de51debf..769b6e0b 100644 --- a/app/mailers/emails/notes.rb +++ b/app/mailers/emails/notes.rb @@ -3,7 +3,6 @@ module Emails def note_commit_email(recipient_id, note_id) @note = Note.find(note_id) @commit = @note.noteable - @commit = CommitDecorator.decorate(@commit) @project = @note.project mail(to: recipient(recipient_id), subject: subject("note for commit #{@commit.short_id}", @commit.title)) end diff --git a/app/models/commit.rb b/app/models/commit.rb index ea5b451b..96c8577f 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -10,10 +10,6 @@ class Commit attr_accessor :raw - def self.decorate(commits) - commits.map { |c| Commit.new(c) } - end - def initialize(raw_commit) raise "Nil as raw commit passed" unless raw_commit @@ -24,7 +20,54 @@ class Commit @raw.id end + # Returns a string describing the commit for use in a link title + # + # Example + # + # "Commit: Alex Denisov - Project git clone panel" + def link_title + "Commit: #{author_name} - #{title}" + end + + # Returns the commits title. + # + # Usually, the commit title is the first line of the commit message. + # In case this first line is longer than 80 characters, it is cut off + # after 70 characters and ellipses (`&hellp;`) are appended. + def title + title = safe_message + + return no_commit_message if title.blank? + + title_end = title.index(/\n/) + if (!title_end && title.length > 80) || (title_end && title_end > 80) + title[0..69] << "…".html_safe + else + title.split(/\n/, 2).first + end + end + + # Returns the commits description + # + # cut off, ellipses (`&hellp;`) are prepended to the commit message. + def description + description = safe_message + + title_end = description.index(/\n/) + if (!title_end && description.length > 80) || (title_end && title_end > 80) + "…".html_safe << description[70..-1] + else + description.split(/\n/, 2)[1].try(:chomp) + end + end + def method_missing(m, *args, &block) @raw.send(m, *args, &block) end + + def respond_to?(method) + return true if @raw.respond_to?(method) + + super + end end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 505f6637..8d378053 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -152,7 +152,17 @@ class MergeRequest < ActiveRecord::Base end def commits - st_commits || [] + if st_commits.present? + # check if merge request commits are valid + if st_commits.first.respond_to?(:short_id) + st_commits + else + # if commits are invalid - simply reload it from repo + reloaded_commits + end + else + [] + end end def probably_merged? @@ -171,7 +181,6 @@ class MergeRequest < ActiveRecord::Base def unmerged_commits self.project.repository. commits_between(self.target_branch, self.source_branch). - map {|c| Commit.new(c)}. sort_by(&:created_at). reverse end diff --git a/app/models/project.rb b/app/models/project.rb index 54abbc3e..934dd6b2 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -142,7 +142,7 @@ class Project < ActiveRecord::Base def repository if path - @repository ||= Gitlab::Git::Repository.new(path_with_namespace, default_branch) + @repository ||= Repository.new(path_with_namespace, default_branch) else nil end diff --git a/app/models/tree.rb b/app/models/tree.rb index 96395a42..4b6c5b13 100644 --- a/app/models/tree.rb +++ b/app/models/tree.rb @@ -26,4 +26,12 @@ class Tree def empty? data.blank? end + + def up_dir? + path.present? + end + + def readme + @readme ||= contents.find { |c| c.is_a?(Grit::Blob) and c.name =~ /^readme/i } + end end diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb index 4ad485c5..d4871a49 100644 --- a/lib/extracts_path.rb +++ b/lib/extracts_path.rb @@ -101,10 +101,8 @@ module ExtractsPath # It is used "@project.repository.commits(@ref, @path, 1, 0)", # because "@project.repository.commit(@ref)" returns wrong commit when @ref is tag name. @commit = @project.repository.commits(@ref, @path, 1, 0).first - @commit = CommitDecorator.decorate(@commit) @tree = Tree.new(@commit.tree, @ref, @path) - @tree = TreeDecorator.new(@tree) raise InvalidPathError if @tree.invalid? rescue RuntimeError, NoMethodError, InvalidPathError From 458631c5ba8c830021bd7c219affdb0afe6f0efe Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 31 Mar 2013 23:58:17 +0300 Subject: [PATCH 130/152] remove unnecessary Commit.new --- app/contexts/commit_load_context.rb | 1 - app/helpers/commits_helper.rb | 4 +--- app/models/note.rb | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/app/contexts/commit_load_context.rb b/app/contexts/commit_load_context.rb index a0652377..2cf5420d 100644 --- a/app/contexts/commit_load_context.rb +++ b/app/contexts/commit_load_context.rb @@ -12,7 +12,6 @@ class CommitLoadContext < BaseContext commit = project.repository.commit(params[:id]) if commit - commit = Commit.new(commit) line_notes = project.notes.for_commit_id(commit.id).inline result[:commit] = commit diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index da209e06..66603c97 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -109,9 +109,7 @@ module CommitsHelper end def commit_to_html commit - if commit.model - escape_javascript(render 'commits/commit', commit: commit) - end + escape_javascript(render 'commits/commit', commit: commit) end def diff_line_content(line) diff --git a/app/models/note.rb b/app/models/note.rb index 17ceb541..f26420ca 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -130,7 +130,7 @@ class Note < ActiveRecord::Base # override to return commits, which are not active record def noteable if for_commit? - Commit.new(project.repository.commit(commit_id)) + project.repository.commit(commit_id) else super end From 7bb71bb088e17578482e7f934147b0fd11c7ad0e Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 1 Apr 2013 09:21:31 +0300 Subject: [PATCH 131/152] Fix stubbed repo --- app/models/repository.rb | 4 ++-- spec/support/stubbed_repository.rb | 8 ++------ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/app/models/repository.rb b/app/models/repository.rb index 048795b2..be6502eb 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -24,11 +24,11 @@ class Repository end def method_missing(m, *args, &block) - @raw_repository.send(m, *args, &block) + raw_repository.send(m, *args, &block) end def respond_to?(method) - return true if @raw_repository.respond_to?(method) + return true if raw_repository.respond_to?(method) super end diff --git a/spec/support/stubbed_repository.rb b/spec/support/stubbed_repository.rb index 68c380e6..3dfdb353 100644 --- a/spec/support/stubbed_repository.rb +++ b/spec/support/stubbed_repository.rb @@ -10,7 +10,7 @@ class Project if path == "empty" || !path nil else - GitLabTestRepo.new(path_with_namespace) + GitLabTestRepo.new(Rails.root.join('tmp', 'repositories', 'gitlabhq'), 'master') end end @@ -39,11 +39,7 @@ class MergeRequest end end -class GitLabTestRepo < Gitlab::Git::Repository - def repo - @repo ||= Grit::Repo.new(Rails.root.join('tmp', 'repositories', 'gitlabhq')) - end - +class GitLabTestRepo < Repository # patch repo size (in mb) def size 12.45 From 45c4804c8e6bdc35bf5ad69ee4e84aea88d86a3c Mon Sep 17 00:00:00 2001 From: tsl0922 Date: Mon, 1 Apr 2013 17:25:31 +0800 Subject: [PATCH 132/152] fix: wrong argument number --- app/observers/merge_request_observer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/observers/merge_request_observer.rb b/app/observers/merge_request_observer.rb index e10e5049..d0dfad88 100644 --- a/app/observers/merge_request_observer.rb +++ b/app/observers/merge_request_observer.rb @@ -20,6 +20,6 @@ class MergeRequestObserver < BaseObserver end def after_update(merge_request) - notification.reassigned_merge_request(merge_request) if merge_request.is_being_reassigned? + notification.reassigned_merge_request(merge_request, current_user) if merge_request.is_being_reassigned? end end From 22817398e6c1cf9a479fecd99c55369fd81717cb Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 1 Apr 2013 14:39:19 +0300 Subject: [PATCH 133/152] define TestEnv and keep all global stubs in one place --- features/support/env.rb | 17 ++----- lib/gitlab/git/repository.rb | 6 ++- spec/factories.rb | 2 +- spec/support/stubbed_repository.rb | 71 ------------------------------ spec/support/test_env.rb | 63 ++++++++++++++++++++++++++ 5 files changed, 72 insertions(+), 87 deletions(-) delete mode 100644 spec/support/stubbed_repository.rb create mode 100644 spec/support/test_env.rb diff --git a/features/support/env.rb b/features/support/env.rb index 90a61dd1..08b627f5 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -14,7 +14,7 @@ require 'spinach/capybara' require 'sidekiq/testing/inline' -%w(stubbed_repository valid_commit select2_helper).each do |f| +%w(valid_commit select2_helper test_env).each do |f| require Rails.root.join('spec', 'support', f) end @@ -35,13 +35,8 @@ Capybara.default_wait_time = 10 DatabaseCleaner.strategy = :truncation Spinach.hooks.before_scenario do - # Use tmp dir for FS manipulations - Gitlab.config.gitlab_shell.stub(repos_path: Rails.root.join('tmp', 'test-git-base-path')) - Gitlab::Shell.any_instance.stub(:add_repository) do |path| - create_temp_repo("#{Rails.root}/tmp/test-git-base-path/#{path}.git") - end - FileUtils.rm_rf Gitlab.config.gitlab_shell.repos_path - FileUtils.mkdir_p Gitlab.config.gitlab_shell.repos_path + TestEnv.init + DatabaseCleaner.start end @@ -54,9 +49,3 @@ Spinach.hooks.before_run do include FactoryGirl::Syntax::Methods end - -def create_temp_repo(path) - FileUtils.mkdir_p path - command = "git init --quiet --bare #{path};" - system(command) -end diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index 53d9c735..30344a3d 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -34,7 +34,11 @@ module Gitlab end def path_to_repo - @path_to_repo ||= File.join(Gitlab.config.gitlab_shell.repos_path, "#{path_with_namespace}.git") + @path_to_repo ||= File.join(repos_path, "#{path_with_namespace}.git") + end + + def repos_path + Gitlab.config.gitlab_shell.repos_path end def repo diff --git a/spec/factories.rb b/spec/factories.rb index 41766859..8f620cd7 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -25,7 +25,7 @@ FactoryGirl.define do factory :project do sequence(:name) { |n| "project#{n}" } - path { name.downcase.gsub(/\s/, '_') } + path { 'gitlabhq' } creator end diff --git a/spec/support/stubbed_repository.rb b/spec/support/stubbed_repository.rb deleted file mode 100644 index 3dfdb353..00000000 --- a/spec/support/stubbed_repository.rb +++ /dev/null @@ -1,71 +0,0 @@ -require "gitlab/git/repository" -require "project" -require "merge_request" -require "shell" - -# Stubs out all Git repository access done by models so that specs can run -# against fake repositories without Grit complaining that they don't exist. -class Project - def repository - if path == "empty" || !path - nil - else - GitLabTestRepo.new(Rails.root.join('tmp', 'repositories', 'gitlabhq'), 'master') - end - end - - def satellite - FakeSatellite.new - end - - class FakeSatellite - def exists? - true - end - - def destroy - true - end - - def create - true - end - end -end - -class MergeRequest - def check_if_can_be_merged - true - end -end - -class GitLabTestRepo < Repository - # patch repo size (in mb) - def size - 12.45 - end -end - -module Gitlab - class Shell - def add_repository name - true - end - - def mv_repository name, new_name - true - end - - def remove_repository name - true - end - - def add_key id, key - true - end - - def remove_key id, key - true - end - end -end diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb new file mode 100644 index 00000000..769405b6 --- /dev/null +++ b/spec/support/test_env.rb @@ -0,0 +1,63 @@ +module TestEnv + extend self + + # Test environment + # + # all repositories and namespaces stored at + # RAILS_APP/tmp/test-git-base-path + # + # Next shell methods are stubbed and return true + # - mv_repository + # - remove_repository + # - add_key + # - remove_key + # + def init + # Use tmp dir for FS manipulations + repos_path = Rails.root.join('tmp', 'test-git-base-path') + Gitlab.config.gitlab_shell.stub(repos_path: repos_path) + + Gitlab::Shell.any_instance.stub( + add_repository: ->(path) { create_temp_repo(File.join(repos_path, "#{path}.git")) }, + mv_repository: true, + remove_repository: true, + add_key: true, + remove_key: true + ) + + fake_satellite = double( + exists?: true, + destroy: true, + create: true + ) + + Project.any_instance.stub( + satellite: fake_satellite + ) + + MergeRequest.any_instance.stub( + check_if_can_be_merged: true + ) + + Repository.any_instance.stub( + size: 12.45 + ) + + # Remove tmp/test-git-base-path + FileUtils.rm_rf Gitlab.config.gitlab_shell.repos_path + + # Recreate tmp/test-git-base-path + FileUtils.mkdir_p Gitlab.config.gitlab_shell.repos_path + + # Symlink tmp/repositories/gitlabhq to tmp/test-git-base-path/gitlabhq + seed_repo = Rails.root.join('tmp', 'repositories', 'gitlabhq') + target_repo = File.join(repos_path, 'gitlabhq.git') + system("ln -s #{seed_repo} #{target_repo}") + end + + def create_temp_repo(path) + FileUtils.mkdir_p path + command = "git init --quiet --bare #{path};" + system(command) + end +end From 51c167554cf492be98cecad182a6870cd6febb82 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 1 Apr 2013 16:02:54 +0300 Subject: [PATCH 134/152] added Gitlab::Git::Blame for git blame feature --- lib/gitlab/git/blame.rb | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 lib/gitlab/git/blame.rb diff --git a/lib/gitlab/git/blame.rb b/lib/gitlab/git/blame.rb new file mode 100644 index 00000000..d6e988b6 --- /dev/null +++ b/lib/gitlab/git/blame.rb @@ -0,0 +1,22 @@ +module Gitlab + module Git + class Blame + + attr_accessor :repository, :sha, :path + + def initialize(repository, sha, path) + @repository, @sha, @path = repository, sha, path + + end + + def each + raw_blame = Grit::Blob.blame(repository.repo, sha, path) + + raw_blame.each do |commit, lines| + commit = Gitlab::Git::Commit.new(commit) + yield(commit, lines) + end + end + end + end +end From bb06e905efb1722502d71059c21add8cfde851aa Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 1 Apr 2013 16:03:11 +0300 Subject: [PATCH 135/152] added Gitlab::Git::Compare for git compare feature --- lib/gitlab/git/compare.rb | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 lib/gitlab/git/compare.rb diff --git a/lib/gitlab/git/compare.rb b/lib/gitlab/git/compare.rb new file mode 100644 index 00000000..1fa43062 --- /dev/null +++ b/lib/gitlab/git/compare.rb @@ -0,0 +1,37 @@ +module Gitlab + module Git + class Compare + attr_accessor :commits, :commit, :diffs, :same + + def initialize(repository, from, to) + @commits, @diffs = [], [] + @commit = nil + @same = false + + return unless from && to + + first = repository.commit(to.try(:strip)) + last = repository.commit(from.try(:strip)) + + return unless first && last + + if first.id == last.id + @same = true + return + end + + @commit = Commit.new(first) + + @commits = repository.commits_between(last.id, first.id) + @commits = @commits.map { |c| Commit.new(c) } + + @diffs = if @commits.size > 100 + [] + else + repository.repo.diff(last.id, first.id) rescue [] + end + end + end + end +end + From 49b024f5f5b88d406b895f050943db1e75adfa2a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 1 Apr 2013 16:04:35 +0300 Subject: [PATCH 136/152] Use Gitlab::Git:: for git features across application --- app/controllers/blame_controller.rb | 3 +- app/controllers/compare_controller.rb | 10 +++--- app/models/commit.rb | 4 +++ app/models/gollum_wiki.rb | 1 - app/models/repository.rb | 10 ++---- app/models/wiki_page.rb | 4 +-- app/views/blame/show.html.haml | 2 +- app/views/compare/show.html.haml | 2 +- app/views/wikis/show.html.haml | 3 +- lib/gitlab/git/commit.rb | 50 ++++++--------------------- spec/support/test_env.rb | 7 ++-- 11 files changed, 32 insertions(+), 64 deletions(-) diff --git a/app/controllers/blame_controller.rb b/app/controllers/blame_controller.rb index 76caa4a6..310b567c 100644 --- a/app/controllers/blame_controller.rb +++ b/app/controllers/blame_controller.rb @@ -8,7 +8,6 @@ class BlameController < ProjectResourceController before_filter :require_non_empty_project def show - @repo = @project.repo - @blame = Grit::Blob.blame(@repo, @commit.id, @path) + @blame = Gitlab::Git::Blame.new(project.repository, @commit.id, @path) end end diff --git a/app/controllers/compare_controller.rb b/app/controllers/compare_controller.rb index b72da783..750e9c23 100644 --- a/app/controllers/compare_controller.rb +++ b/app/controllers/compare_controller.rb @@ -8,12 +8,12 @@ class CompareController < ProjectResourceController end def show - result = Commit.compare(project, params[:from], params[:to]) + compare = Gitlab::Git::Compare.new(project.repository, params[:from], params[:to]) - @commits = result[:commits] - @commit = result[:commit] - @diffs = result[:diffs] - @refs_are_same = result[:same] + @commits = compare.commits + @commit = compare.commit + @diffs = compare.diffs + @refs_are_same = compare.same @line_notes = [] end diff --git a/app/models/commit.rb b/app/models/commit.rb index 96c8577f..e3363350 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -8,6 +8,10 @@ class Commit # DIFF_SAFE_SIZE = 100 + def self.decorate(commits) + commits.map { |c| self.new(c) } + end + attr_accessor :raw def initialize(raw_commit) diff --git a/app/models/gollum_wiki.rb b/app/models/gollum_wiki.rb index cdfcd567..647058e8 100644 --- a/app/models/gollum_wiki.rb +++ b/app/models/gollum_wiki.rb @@ -114,5 +114,4 @@ class GollumWiki def path_to_repo @path_to_repo ||= File.join(Gitlab.config.gitlab_shell.repos_path, "#{path_with_namespace}.git") end - end diff --git a/app/models/repository.rb b/app/models/repository.rb index be6502eb..0a4431f1 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -13,13 +13,13 @@ class Repository def commits(ref, path = nil, limit = nil, offset = nil) commits = raw_repository.commits(ref, path, limit, offset) - commits = decorate_commits(commits) if commits.present? + commits = Commit.decorate(commits) if commits.present? commits end def commits_between(target, source) commits = raw_repository.commits_between(target, source) - commits = decorate_commits(commits) if commits.present? + commits = Commit.decorate(commits) if commits.present? commits end @@ -32,10 +32,4 @@ class Repository super end - - protected - - def decorate_commits(commits) - commits.map { |c| Commit.new(c) } - end end diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb index adc77b22..497d69e8 100644 --- a/app/models/wiki_page.rb +++ b/app/models/wiki_page.rb @@ -79,14 +79,14 @@ class WikiPage def version return nil unless persisted? - @version ||= Commit.new(@page.version) + @version ||= Commit.new(Gitlab::Git::Commit.new(@page.version)) end # Returns an array of Gitlab Commit instances. def versions return [] unless persisted? - @page.versions.map { |v| Commit.new(v) } + @page.versions.map { |v| Commit.new(Gitlab::Git::Commit.new(v)) } end # Returns the Date that this latest version was diff --git a/app/views/blame/show.html.haml b/app/views/blame/show.html.haml index b07a514f..96d153e6 100644 --- a/app/views/blame/show.html.haml +++ b/app/views/blame/show.html.haml @@ -6,7 +6,7 @@ %i.icon-angle-right = link_to project_tree_path(@project, @ref) do = @project.name - - @tree.breadcrumbs(6) do |link| + - tree_breadcrumbs(@tree, 6) do |link| \/ %li= link .clear diff --git a/app/views/compare/show.html.haml b/app/views/compare/show.html.haml index 476be255..56c4a113 100644 --- a/app/views/compare/show.html.haml +++ b/app/views/compare/show.html.haml @@ -16,7 +16,7 @@ %div.ui-box %h5.title Commits (#{@commits.count}) - %ul.well-list= render @commits + %ul.well-list= render Commit.decorate(@commits) - unless @diffs.empty? %h4 Diff diff --git a/app/views/wikis/show.html.haml b/app/views/wikis/show.html.haml index 4102182e..b237bc52 100644 --- a/app/views/wikis/show.html.haml +++ b/app/views/wikis/show.html.haml @@ -13,5 +13,4 @@ = preserve do = render_wiki_content(@wiki) -- commit = Commit.new(@wiki.version) -%p.time Last edited by #{commit_author_link(commit, avatar: true, size: 16)} #{time_ago_in_words @wiki.created_at} ago +%p.time Last edited by #{commit_author_link(@wiki.version, avatar: true, size: 16)} #{time_ago_in_words @wiki.created_at} ago diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb index 023672f9..d7e1a5ca 100644 --- a/lib/gitlab/git/commit.rb +++ b/lib/gitlab/git/commit.rb @@ -1,9 +1,9 @@ -# Gitlab::Git::Gitlab::Git::Commit is a wrapper around native Grit::Commit object +# Gitlab::Git::Commit is a wrapper around native Grit::Commit object # We dont want to use grit objects inside app/ # It helps us easily migrate to rugged in future module Gitlab module Git - class Gitlab::Git::Commit + class Commit attr_accessor :raw_commit, :head, :refs delegate :message, :authored_date, :committed_date, :parents, :sha, @@ -18,12 +18,12 @@ module Gitlab repo.commits(root_ref).first end - Gitlab::Git::Commit.new(commit) if commit + Commit.new(commit) if commit end def fresh_commits(repo, n = 10) commits = repo.heads.map do |h| - repo.commits(h.name, n).map { |c| Gitlab::Git::Commit.new(c, h) } + repo.commits(h.name, n).map { |c| Commit.new(c, h) } end.flatten.uniq { |c| c.id } commits.sort! do |x, y| @@ -34,7 +34,7 @@ module Gitlab end def commits_with_refs(repo, n = 20) - commits = repo.branches.map { |ref| Gitlab::Git::Commit.new(ref.commit, ref) } + commits = repo.branches.map { |ref| Commit.new(ref.commit, ref) } commits.sort! do |x, y| y.committed_date <=> x.committed_date @@ -45,7 +45,7 @@ module Gitlab def commits_since(repo, date) commits = repo.heads.map do |h| - repo.log(h.name, nil, since: date).each { |c| Gitlab::Git::Commit.new(c, h) } + repo.log(h.name, nil, since: date).each { |c| Commit.new(c, h) } end.flatten.uniq { |c| c.id } commits.sort! do |x, y| @@ -62,41 +62,11 @@ module Gitlab repo.commits(ref, limit, offset) else repo.commits(ref) - end.map{ |c| Gitlab::Git::Commit.new(c) } + end.map{ |c| Commit.new(c) } end def commits_between(repo, from, to) - repo.commits_between(from, to).map { |c| Gitlab::Git::Commit.new(c) } - end - - def compare(project, from, to) - result = { - commits: [], - diffs: [], - commit: nil, - same: false - } - - return result unless from && to - - first = project.repository.commit(to.try(:strip)) - last = project.repository.commit(from.try(:strip)) - - if first && last - result[:same] = (first.id == last.id) - result[:commits] = project.repo.commits_between(last.id, first.id).map {|c| Gitlab::Git::Commit.new(c)} - - # Dont load diff for 100+ commits - result[:diffs] = if result[:commits].size > 100 - [] - else - project.repo.diff(last.id, first.id) rescue [] - end - - result[:commit] = Gitlab::Git::Commit.new(first) - end - - result + repo.commits_between(from, to).map { |c| Commit.new(c) } end end @@ -142,7 +112,7 @@ module Gitlab def prev_commit @prev_commit ||= if parents.present? - Gitlab::Git::Commit.new(parents.first) + Commit.new(parents.first) else nil end @@ -156,7 +126,7 @@ module Gitlab # # Cuts out the header and stats from #to_patch and returns only the diff. def to_diff - # see Grit::Gitlab::Git::Commit#show + # see Grit::Commit#show patch = to_patch # discard lines before the diff diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index 769405b6..0f81347d 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -17,15 +17,18 @@ module TestEnv repos_path = Rails.root.join('tmp', 'test-git-base-path') Gitlab.config.gitlab_shell.stub(repos_path: repos_path) + Gitlab::Shell.any_instance.stub(:add_repository) do |path| + create_temp_repo(File.join(repos_path, "#{path}.git")) + end + Gitlab::Shell.any_instance.stub( - add_repository: ->(path) { create_temp_repo(File.join(repos_path, "#{path}.git")) }, mv_repository: true, remove_repository: true, add_key: true, remove_key: true ) - fake_satellite = double( + fake_satellite = stub( exists?: true, destroy: true, create: true From 541d89941014137762dff696c83b3357eba8efeb Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 1 Apr 2013 16:56:25 +0300 Subject: [PATCH 137/152] Project.repository should never be nil so you can call repository.exists? or repository.empty? Also specify separate project factory for project with filled repo --- app/helpers/application_helper.rb | 2 +- app/models/project.rb | 14 ++----- app/models/repository.rb | 10 +++++ app/views/projects/_clone_panel.html.haml | 2 +- features/steps/shared/project.rb | 4 +- lib/api/projects.rb | 2 +- lib/extracts_path.rb | 4 +- lib/gitlab/markdown.rb | 2 +- spec/factories.rb | 6 ++- spec/helpers/gitlab_markdown_helper_spec.rb | 2 +- spec/models/commit_spec.rb | 41 ++++++++++----------- spec/models/project_spec.rb | 10 ++--- spec/spec_helper.rb | 6 +-- 13 files changed, 51 insertions(+), 54 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index f03039e4..cb9cb1a3 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -96,7 +96,7 @@ module ApplicationHelper ] project_nav = [] - if @project && @project.repository && @project.repository.root_ref + if @project && @project.repository.exists? && @project.repository.root_ref project_nav = [ { label: "#{simple_sanitize(@project.name_with_namespace)} - Issues", url: project_issues_path(@project) }, { label: "#{simple_sanitize(@project.name_with_namespace)} - Commits", url: project_commits_path(@project, @ref || @project.repository.root_ref) }, diff --git a/app/models/project.rb b/app/models/project.rb index 934dd6b2..0263ffef 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -141,13 +141,7 @@ class Project < ActiveRecord::Base end def repository - if path - @repository ||= Repository.new(path_with_namespace, default_branch) - else - nil - end - rescue Gitlab::Git::NoRepository - nil + @repository ||= Repository.new(path_with_namespace, default_branch) end def saved? @@ -332,14 +326,14 @@ class Project < ActiveRecord::Base end def valid_repo? - repo + repository.exists? rescue errors.add(:path, "Invalid repository path") false end def empty_repo? - !repository || repository.empty? + !repository.exists? || repository.empty? end def ensure_satellite_exists @@ -363,7 +357,7 @@ class Project < ActiveRecord::Base end def repo_exists? - @repo_exists ||= (repository && repository.branches.present?) + @repo_exists ||= repository.exists? rescue @repo_exists = false end diff --git a/app/models/repository.rb b/app/models/repository.rb index 0a4431f1..ed600e29 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -3,6 +3,16 @@ class Repository def initialize(path_with_namespace, default_branch) @raw_repository = Gitlab::Git::Repository.new(path_with_namespace, default_branch) + rescue Gitlab::Git::Repository::NoRepository + nil + end + + def exists? + raw_repository + end + + def empty? + raw_repository.empty? end def commit(id = nil) diff --git a/app/views/projects/_clone_panel.html.haml b/app/views/projects/_clone_panel.html.haml index 9a2be429..91353147 100644 --- a/app/views/projects/_clone_panel.html.haml +++ b/app/views/projects/_clone_panel.html.haml @@ -4,7 +4,7 @@ .form-horizontal= render "shared/clone_panel" .span4.pull-right .pull-right - - unless @project.empty_repo? + - if @project.empty_repo? - if can? current_user, :download_code, @project = link_to archive_project_repository_path(@project), class: "btn-small btn grouped" do %i.icon-download-alt diff --git a/features/steps/shared/project.rb b/features/steps/shared/project.rb index 81863a54..b16032a8 100644 --- a/features/steps/shared/project.rb +++ b/features/steps/shared/project.rb @@ -3,14 +3,14 @@ module SharedProject # Create a project without caring about what it's called And "I own a project" do - @project = create(:project) + @project = create(:project_with_code) @project.team << [@user, :master] end # Create a specific project called "Shop" And 'I own project "Shop"' do @project = Project.find_by_name "Shop" - @project ||= create(:project, name: "Shop") + @project ||= create(:project_with_code, name: "Shop") @project.team << [@user, :master] end diff --git a/lib/api/projects.rb b/lib/api/projects.rb index d4f50fda..ce94c34b 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -372,7 +372,7 @@ module Gitlab ref = params[:ref_name] || user_project.try(:default_branch) || 'master' commits = user_project.repository.commits(ref, nil, per_page, page * per_page) - present CommitDecorator.decorate(commits), with: Entities::RepoCommit + present commits, with: Entities::RepoCommit end # Get a project snippets diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb index d4871a49..2e3ab1b2 100644 --- a/lib/extracts_path.rb +++ b/lib/extracts_path.rb @@ -85,8 +85,8 @@ module ExtractsPath # - @id - A string representing the joined ref and path # - @ref - A string representing the ref (e.g., the branch, tag, or commit SHA) # - @path - A string representing the filesystem path - # - @commit - A CommitDecorator representing the commit from the given ref - # - @tree - A TreeDecorator representing the tree at the given ref/path + # - @commit - A Commit representing the commit from the given ref + # - @tree - A Tree representing the tree at the given ref/path # # If the :id parameter appears to be requesting a specific response format, # that will be handled as well. diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb index 762eb372..ad6ba3e8 100644 --- a/lib/gitlab/markdown.rb +++ b/lib/gitlab/markdown.rb @@ -187,7 +187,7 @@ module Gitlab def reference_commit(identifier) if @project.valid_repo? && commit = @project.repository.commit(identifier) - link_to(identifier, project_commit_url(@project, commit), html_options.merge(title: CommitDecorator.new(commit).link_title, class: "gfm gfm-commit #{html_options[:class]}")) + link_to(identifier, project_commit_url(@project, commit), html_options.merge(title: commit.link_title, class: "gfm gfm-commit #{html_options[:class]}")) end end end diff --git a/spec/factories.rb b/spec/factories.rb index 8f620cd7..d904e337 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -25,7 +25,7 @@ FactoryGirl.define do factory :project do sequence(:name) { |n| "project#{n}" } - path { 'gitlabhq' } + path { name.downcase.gsub(/\s/, '_') } creator end @@ -34,6 +34,10 @@ FactoryGirl.define do issues_tracker_id { "project_name_in_redmine" } end + factory :project_with_code, parent: :project do + path { 'gitlabhq' } + end + factory :group do sequence(:name) { |n| "group#{n}" } path { name.downcase.gsub(/\s/, '_') } diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb index 3abeaeef..234608c1 100644 --- a/spec/helpers/gitlab_markdown_helper_spec.rb +++ b/spec/helpers/gitlab_markdown_helper_spec.rb @@ -7,7 +7,7 @@ describe GitlabMarkdownHelper do let!(:project) { create(:project) } let(:user) { create(:user, username: 'gfm') } - let(:commit) { CommitDecorator.decorate(Commit.new(project.repository.commit)) } + let(:commit) { project.repository.commit) } let(:issue) { create(:issue, project: project) } let(:merge_request) { create(:merge_request, project: project) } let(:snippet) { create(:snippet, project: project) } diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb index 7b063d2a..7713a33d 100644 --- a/spec/models/commit_spec.rb +++ b/spec/models/commit_spec.rb @@ -3,35 +3,32 @@ require 'spec_helper' describe Commit do let(:commit) { create(:project).repository.commit } - describe CommitDecorator do - let(:decorator) { CommitDecorator.new(commit) } - describe '#title' do - it "returns no_commit_message when safe_message is blank" do - decorator.stub(:safe_message).and_return('') - decorator.title.should == "--no commit message" - end + describe '#title' do + it "returns no_commit_message when safe_message is blank" do + commit.stub(:safe_message).and_return('') + commit.title.should == "--no commit message" + end - it "truncates a message without a newline at 70 characters" do - message = commit.safe_message * 10 + it "truncates a message without a newline at 70 characters" do + message = commit.safe_message * 10 - decorator.stub(:safe_message).and_return(message) - decorator.title.should == "#{message[0..69]}…" - end + commit.stub(:safe_message).and_return(message) + commit.title.should == "#{message[0..69]}…" + end - it "truncates a message with a newline before 80 characters at the newline" do - message = commit.safe_message.split(" ").first + it "truncates a message with a newline before 80 characters at the newline" do + message = commit.safe_message.split(" ").first - decorator.stub(:safe_message).and_return(message + "\n" + message) - decorator.title.should == message - end + commit.stub(:safe_message).and_return(message + "\n" + message) + commit.title.should == message + end - it "truncates a message with a newline after 80 characters at 70 characters" do - message = (commit.safe_message * 10) + "\n" + it "truncates a message with a newline after 80 characters at 70 characters" do + message = (commit.safe_message * 10) + "\n" - decorator.stub(:safe_message).and_return(message) - decorator.title.should == "#{message[0..69]}…" - end + commit.stub(:safe_message).and_return(message) + commit.title.should == "#{message[0..69]}…" end end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 90b5e08e..cbc7f278 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -119,7 +119,7 @@ describe Project do end describe :update_merge_requests do - let(:project) { create(:project) } + let(:project) { create(:project_with_code) } before do @merge_request = create(:merge_request, project: project) @@ -187,11 +187,7 @@ describe Project do let(:project) { create(:project) } it "should return valid repo" do - project.repository.should be_kind_of(Gitlab::Git::Repository) - end - - it "should return nil" do - Project.new(path: "empty").repository.should be_nil + project.repository.should be_kind_of(Repository) end end @@ -249,7 +245,7 @@ describe Project do end describe :open_branches do - let(:project) { create(:project) } + let(:project) { create(:project_with_code) } before do project.protected_branches.create(name: 'master') diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 03c586f8..8a01c930 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -47,11 +47,7 @@ Spork.prefork do config.use_transactional_fixtures = false config.before do - # Use tmp dir for FS manipulations - temp_repos_path = Rails.root.join('tmp', 'test-git-base-path') - Gitlab.config.gitlab_shell.stub(repos_path: temp_repos_path) - FileUtils.rm_rf temp_repos_path - FileUtils.mkdir_p temp_repos_path + TestEnv.init end end end From 9a26e9a0d634c8bb796f0b08f6397d1e343bd4be Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 1 Apr 2013 17:27:44 +0300 Subject: [PATCH 138/152] Dont init repo on every create(:repo) --- app/helpers/commits_helper.rb | 4 ---- app/models/gollum_wiki.rb | 6 +++++- lib/gitlab/git/commit.rb | 4 ++++ spec/factories.rb | 8 +++++--- spec/models/commit_spec.rb | 2 +- spec/models/gollum_wiki_spec.rb | 2 +- spec/support/test_env.rb | 3 ++- 7 files changed, 18 insertions(+), 11 deletions(-) diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index 66603c97..95ca294c 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -147,10 +147,6 @@ module CommitsHelper protected - def no_commit_message - "--no commit message" - end - # Private: Returns a link to a person. If the person has a matching user and # is a member of the current @project it will link to the team member page. # Otherwise it will link to the person email as specified in the commit. diff --git a/app/models/gollum_wiki.rb b/app/models/gollum_wiki.rb index 647058e8..16e801c1 100644 --- a/app/models/gollum_wiki.rb +++ b/app/models/gollum_wiki.rb @@ -90,13 +90,17 @@ class GollumWiki private def create_repo! - if gitlab_shell.add_repository(path_with_namespace) + if init_repo(path_with_namespace) Gollum::Wiki.new(path_to_repo) else raise CouldNotCreateWikiError end end + def init_repo(path_with_namespace) + gitlab_shell.add_repository(path_with_namespace) + end + def commit_details(action, message = nil, title = nil) commit_message = message || default_message(action, title) diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb index d7e1a5ca..35991a38 100644 --- a/lib/gitlab/git/commit.rb +++ b/lib/gitlab/git/commit.rb @@ -144,6 +144,10 @@ module Gitlab rescue true end + + def no_commit_message + "--no commit message" + end end end end diff --git a/spec/factories.rb b/spec/factories.rb index d904e337..76bd3ebb 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -86,9 +86,9 @@ FactoryGirl.define do target_branch "master" # pretend bcf03b5d~3 source_branch "stable" # pretend bcf03b5d st_commits do - [Commit.new(project.repo.commit('bcf03b5d')), - Commit.new(project.repo.commit('bcf03b5d~1')), - Commit.new(project.repo.commit('bcf03b5d~2'))] + [Commit.new(project.repository.commit('bcf03b5d')), + Commit.new(project.repository.commit('bcf03b5d~1')), + Commit.new(project.repository.commit('bcf03b5d~2'))] end st_diffs do project.repo.diff("bcf03b5d~3", "bcf03b5d") @@ -120,6 +120,7 @@ FactoryGirl.define do factory :note_on_merge_request_diff, traits: [:on_merge_request, :on_diff] trait :on_commit do + project factory: :project_with_code commit_id "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a" noteable_type "Commit" end @@ -129,6 +130,7 @@ FactoryGirl.define do end trait :on_merge_request do + project factory: :project_with_code noteable_id 1 noteable_type "MergeRequest" end diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb index 7713a33d..6cf777be 100644 --- a/spec/models/commit_spec.rb +++ b/spec/models/commit_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe Commit do - let(:commit) { create(:project).repository.commit } + let(:commit) { create(:project_with_code).repository.commit } describe '#title' do diff --git a/spec/models/gollum_wiki_spec.rb b/spec/models/gollum_wiki_spec.rb index 87601683..aa850dfd 100644 --- a/spec/models/gollum_wiki_spec.rb +++ b/spec/models/gollum_wiki_spec.rb @@ -81,7 +81,7 @@ describe GollumWiki do end it "raises CouldNotCreateWikiError if it can't create the wiki repository" do - Gitlab::Shell.any_instance.stub(:add_repository).and_return(false) + GollumWiki.any_instance.stub(:init_repo).and_return(false) expect { GollumWiki.new(project, user).wiki }.to raise_exception(GollumWiki::CouldNotCreateWikiError) end end diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index 0f81347d..19be8029 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -17,11 +17,12 @@ module TestEnv repos_path = Rails.root.join('tmp', 'test-git-base-path') Gitlab.config.gitlab_shell.stub(repos_path: repos_path) - Gitlab::Shell.any_instance.stub(:add_repository) do |path| + GollumWiki.any_instance.stub(:init_repo) do |path| create_temp_repo(File.join(repos_path, "#{path}.git")) end Gitlab::Shell.any_instance.stub( + add_repository: true, mv_repository: true, remove_repository: true, add_key: true, From f5dec306fda53a6b2e90f64c0407077ab0022e8f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 1 Apr 2013 18:16:08 +0300 Subject: [PATCH 139/152] Use project_with_code factory where necessary --- app/views/admin/projects/show.html.haml | 23 +++++++++++-------- .../steps/project/project_browse_commits.rb | 2 +- spec/controllers/commit_controller_spec.rb | 2 +- spec/controllers/commits_controller_spec.rb | 2 +- .../merge_requests_controller_spec.rb | 2 +- spec/controllers/tree_controller_spec.rb | 2 +- .../features/gitlab_flavored_markdown_spec.rb | 2 +- spec/helpers/gitlab_markdown_helper_spec.rb | 2 +- 8 files changed, 20 insertions(+), 17 deletions(-) diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml index 27c687bb..92b89601 100644 --- a/app/views/admin/projects/show.html.haml +++ b/app/views/admin/projects/show.html.haml @@ -46,18 +46,21 @@ %span.light ssh: %strong = link_to @project.ssh_url_to_repo - %li - %span.light fs: - %strong - = @repository.path_to_repo + - if @project.repository.exists? + %li + %span.light fs: + %strong + = @repository.path_to_repo - %li - %span.light last commit: - %strong - - if @repository + %li + %span.light last commit: + %strong = last_commit(@project) - - else - never + - else + %li + %span.light repository: + %strong.cred + does not exist %li %span.light access: diff --git a/features/steps/project/project_browse_commits.rb b/features/steps/project/project_browse_commits.rb index 3433c2ba..b4c595fa 100644 --- a/features/steps/project/project_browse_commits.rb +++ b/features/steps/project/project_browse_commits.rb @@ -15,7 +15,7 @@ class ProjectBrowseCommits < Spinach::FeatureSteps end Then 'I see commits atom feed' do - commit = CommitDecorator.decorate(@project.repository.commit) + commit = @project.repository.commit page.response_headers['Content-Type'].should have_content("application/atom+xml") page.body.should have_selector("title", :text => "Recent commits to #{@project.name}") page.body.should have_selector("author email", :text => commit.author_email) diff --git a/spec/controllers/commit_controller_spec.rb b/spec/controllers/commit_controller_spec.rb index 7bf13822..5fffbf0e 100644 --- a/spec/controllers/commit_controller_spec.rb +++ b/spec/controllers/commit_controller_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe CommitController do - let(:project) { create(:project) } + let(:project) { create(:project_with_code) } let(:user) { create(:user) } let(:commit) { project.repository.last_commit_for("master") } diff --git a/spec/controllers/commits_controller_spec.rb b/spec/controllers/commits_controller_spec.rb index 99cbcd13..ce402917 100644 --- a/spec/controllers/commits_controller_spec.rb +++ b/spec/controllers/commits_controller_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe CommitsController do - let(:project) { create(:project) } + let(:project) { create(:project_with_code) } let(:user) { create(:user) } before do diff --git a/spec/controllers/merge_requests_controller_spec.rb b/spec/controllers/merge_requests_controller_spec.rb index 37e36efc..e8dd9bf9 100644 --- a/spec/controllers/merge_requests_controller_spec.rb +++ b/spec/controllers/merge_requests_controller_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe MergeRequestsController do - let(:project) { create(:project) } + let(:project) { create(:project_with_code) } let(:user) { create(:user) } let(:merge_request) { create(:merge_request_with_diffs, project: project, target_branch: "bcf03b5d~3", source_branch: "bcf03b5d") } diff --git a/spec/controllers/tree_controller_spec.rb b/spec/controllers/tree_controller_spec.rb index 81c7656d..8232f147 100644 --- a/spec/controllers/tree_controller_spec.rb +++ b/spec/controllers/tree_controller_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe TreeController do - let(:project) { create(:project) } + let(:project) { create(:project_with_code) } let(:user) { create(:user) } before do diff --git a/spec/features/gitlab_flavored_markdown_spec.rb b/spec/features/gitlab_flavored_markdown_spec.rb index a57e34ac..653ff865 100644 --- a/spec/features/gitlab_flavored_markdown_spec.rb +++ b/spec/features/gitlab_flavored_markdown_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe "Gitlab Flavored Markdown" do - let(:project) { create(:project) } + let(:project) { create(:project_with_code) } let(:issue) { create(:issue, project: project) } let(:merge_request) { create(:merge_request, project: project) } let(:fred) do diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb index 234608c1..e67e211c 100644 --- a/spec/helpers/gitlab_markdown_helper_spec.rb +++ b/spec/helpers/gitlab_markdown_helper_spec.rb @@ -7,7 +7,7 @@ describe GitlabMarkdownHelper do let!(:project) { create(:project) } let(:user) { create(:user, username: 'gfm') } - let(:commit) { project.repository.commit) } + let(:commit) { project.repository.commit } let(:issue) { create(:issue, project: project) } let(:merge_request) { create(:merge_request, project: project) } let(:snippet) { create(:snippet, project: project) } From adccf3b49912df4ea630eb6e96e34204ddf932e6 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 1 Apr 2013 18:24:05 +0300 Subject: [PATCH 140/152] fix facotries --- spec/factories.rb | 2 +- spec/features/notes_on_merge_requests_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/factories.rb b/spec/factories.rb index 76bd3ebb..3205cabd 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -77,7 +77,7 @@ FactoryGirl.define do factory :merge_request do title author - project + project factory: :project_with_code source_branch "master" target_branch "stable" diff --git a/spec/features/notes_on_merge_requests_spec.rb b/spec/features/notes_on_merge_requests_spec.rb index d48dffc0..82f44279 100644 --- a/spec/features/notes_on_merge_requests_spec.rb +++ b/spec/features/notes_on_merge_requests_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe "On a merge request", js: true do - let!(:project) { create(:project) } + let!(:project) { create(:project_with_code) } let!(:merge_request) { create(:merge_request, project: project) } before do @@ -83,7 +83,7 @@ end describe "On a merge request diff", js: true, focus: true do - let!(:project) { create(:project) } + let!(:project) { create(:project_with_code) } let!(:merge_request) { create(:merge_request_with_diffs, project: project) } before do From 3b88636d3c3a85d8dea83149b1f401d505d84d60 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 1 Apr 2013 18:35:29 +0300 Subject: [PATCH 141/152] fix tests --- spec/features/profile_spec.rb | 5 +++-- spec/features/security/project_access_spec.rb | 2 +- spec/support/test_env.rb | 6 +----- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb index c18d8f92..51b95c25 100644 --- a/spec/features/profile_spec.rb +++ b/spec/features/profile_spec.rb @@ -12,8 +12,9 @@ describe "Profile account page" do Gitlab.config.gitlab.stub(:signup_enabled).and_return(true) visit account_profile_path end + it { page.should have_content("Remove account") } - + it "should delete the account", js: true do expect { click_link "Delete account" }.to change {User.count}.by(-1) current_path.should == new_user_session_path @@ -45,4 +46,4 @@ describe "Profile account page" do current_path.should == account_profile_path end end -end \ No newline at end of file +end diff --git a/spec/features/security/project_access_spec.rb b/spec/features/security/project_access_spec.rb index 179ebffc..cfbb8f13 100644 --- a/spec/features/security/project_access_spec.rb +++ b/spec/features/security/project_access_spec.rb @@ -14,7 +14,7 @@ describe "Application access" do end describe "Project" do - let(:project) { create(:project) } + let(:project) { create(:project_with_code) } let(:master) { create(:user) } let(:guest) { create(:user) } diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index 19be8029..370094d3 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -29,16 +29,12 @@ module TestEnv remove_key: true ) - fake_satellite = stub( + Gitlab::Satellite::Satellite.any_instance.stub( exists?: true, destroy: true, create: true ) - Project.any_instance.stub( - satellite: fake_satellite - ) - MergeRequest.any_instance.stub( check_if_can_be_merged: true ) From f536c133550b74b3083c66adaebf0ae6d425f81b Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 1 Apr 2013 19:06:47 +0300 Subject: [PATCH 142/152] fixed test using repo with commits but old factory --- spec/helpers/gitlab_markdown_helper_spec.rb | 2 +- spec/lib/git/commit_spec.rb | 3 +-- spec/lib/git/repository_spec.rb | 3 +-- spec/mailers/notify_spec.rb | 13 +++---------- spec/requests/api/merge_requests_spec.rb | 2 +- spec/requests/api/projects_spec.rb | 2 +- spec/services/git_push_service_spec.rb | 2 +- spec/workers/post_receive_spec.rb | 2 +- 8 files changed, 10 insertions(+), 19 deletions(-) diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb index e67e211c..4140ba48 100644 --- a/spec/helpers/gitlab_markdown_helper_spec.rb +++ b/spec/helpers/gitlab_markdown_helper_spec.rb @@ -4,7 +4,7 @@ describe GitlabMarkdownHelper do include ApplicationHelper include IssuesHelper - let!(:project) { create(:project) } + let!(:project) { create(:project_with_code) } let(:user) { create(:user, username: 'gfm') } let(:commit) { project.repository.commit } diff --git a/spec/lib/git/commit_spec.rb b/spec/lib/git/commit_spec.rb index 93f579d3..475bc359 100644 --- a/spec/lib/git/commit_spec.rb +++ b/spec/lib/git/commit_spec.rb @@ -1,7 +1,7 @@ require "spec_helper" describe Gitlab::Git::Commit do - let(:commit) { create(:project).repository.commit } + let(:commit) { create(:project_with_code).repository.commit } describe "Commit info" do before do @@ -45,6 +45,5 @@ describe Gitlab::Git::Commit do it { should respond_to(:commits_since) } it { should respond_to(:commits_between) } it { should respond_to(:commits) } - it { should respond_to(:compare) } end end diff --git a/spec/lib/git/repository_spec.rb b/spec/lib/git/repository_spec.rb index e0ff93ea..b2b6f196 100644 --- a/spec/lib/git/repository_spec.rb +++ b/spec/lib/git/repository_spec.rb @@ -1,8 +1,7 @@ require "spec_helper" describe Gitlab::Git::Repository do - let(:project) { create(:project) } - let(:repository) { project.repository } + let(:repository) { Gitlab::Git::Repository.new('gitlabhq', 'master') } describe "Respond to" do subject { repository } diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index 472458e8..84ce7e86 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -5,7 +5,7 @@ describe Notify do include EmailSpec::Matchers let(:recipient) { create(:user, email: 'recipient@example.com') } - let(:project) { create(:project) } + let(:project) { create(:project_with_code) } shared_examples 'a multiple recipients email' do it 'is sent to the given recipient' do @@ -277,14 +277,7 @@ describe Notify do end describe 'on a commit' do - let(:commit) do - mock(:commit).tap do |commit| - commit.stub(:id).and_return('fauxsha1') - commit.stub(:project).and_return(project) - commit.stub(:short_id).and_return('fauxsha1') - commit.stub(:safe_message).and_return('some message') - end - end + let(:commit) { project.repository.commit } before(:each) { note.stub(:noteable).and_return(commit) } @@ -297,7 +290,7 @@ describe Notify do end it 'contains a link to the commit' do - should have_body_text /fauxsha1/ + should have_body_text commit.short_id end end diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index e7af056a..25bbd986 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -4,7 +4,7 @@ describe Gitlab::API do include ApiHelpers let(:user) { create(:user ) } - let!(:project) { create(:project, namespace: user.namespace ) } + let!(:project) { create(:project_with_code, creator_id: user.id) } let!(:merge_request) { create(:merge_request, author: user, assignee: user, project: project, title: "Test") } before { project.team << [user, :reporters] } diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index cddb7264..aca3919a 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -7,7 +7,7 @@ describe Gitlab::API do let(:user2) { create(:user) } let(:user3) { create(:user) } let(:admin) { create(:admin) } - let!(:project) { create(:project, namespace: user.namespace ) } + let!(:project) { create(:project_with_code, creator_id: user.id) } let!(:hook) { create(:project_hook, project: project, url: "http://example.com") } let!(:snippet) { create(:snippet, author: user, project: project, title: 'example') } let!(:users_project) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) } diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index 9fc5fd62..286a8cda 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe GitPushService do let (:user) { create :user } - let (:project) { create :project } + let (:project) { create :project_with_code } let (:service) { GitPushService.new } before do diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb index a4751bd0..46e86dbe 100644 --- a/spec/workers/post_receive_spec.rb +++ b/spec/workers/post_receive_spec.rb @@ -9,7 +9,7 @@ describe PostReceive do end context "web hook" do - let(:project) { create(:project) } + let(:project) { create(:project_with_code) } let(:key) { create(:key, user: project.owner) } let(:key_id) { key.shell_id } From 8a6bf09ad0f95a859406c86c3a925f824dfbd633 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 1 Apr 2013 20:35:41 +0300 Subject: [PATCH 143/152] Pass project into factory for teams tests --- features/steps/userteams/userteams.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/steps/userteams/userteams.rb b/features/steps/userteams/userteams.rb index 70ad3cca..9a86572e 100644 --- a/features/steps/userteams/userteams.rb +++ b/features/steps/userteams/userteams.rb @@ -132,7 +132,7 @@ class Userteams < Spinach::FeatureSteps team = UserTeam.last team.projects.each do |project| team.members.each do |member| - 3.times { project.merge_requests << create(:merge_request, assignee: member) } + 3.times { create(:merge_request, assignee: member, project: project) } end end end @@ -157,7 +157,7 @@ class Userteams < Spinach::FeatureSteps team = UserTeam.last team.projects.each do |project| team.members.each do |member| - 3.times { project.merge_requests << create(:merge_request, assignee: member) } + 3.times { create(:merge_request, assignee: member, project: project) } end end end From 65d9f8c16c35dd716955c420223aa22720628b6e Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 1 Apr 2013 21:16:52 +0300 Subject: [PATCH 144/152] Fix notification issue --- app/services/notification_service.rb | 2 +- app/views/layouts/project_resource.html.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 486aef1d..f8779fd5 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -104,7 +104,7 @@ class NotificationService opts = { noteable_type: note.noteable_type, project_id: note.project_id } - if note.commit_id + if note.commit_id.present? opts.merge!(commit_id: note.commit_id) recipients = [note.commit_author] else diff --git a/app/views/layouts/project_resource.html.haml b/app/views/layouts/project_resource.html.haml index ca2f6e9a..0ca06837 100644 --- a/app/views/layouts/project_resource.html.haml +++ b/app/views/layouts/project_resource.html.haml @@ -13,7 +13,7 @@ = link_to project_path(@project), title: "Project" do %i.icon-home - - if @project.repo_exists? + - unless @project.empty_repo? - if can? current_user, :download_code, @project = nav_link(controller: %w(tree blob blame)) do = link_to 'Files', project_tree_path(@project, @ref || @repository.root_ref) From 0e9080e3dda595d91c563439e7d07f4ecf822403 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 1 Apr 2013 21:25:50 +0300 Subject: [PATCH 145/152] Fixed bug with non-displayed download button --- app/views/projects/_clone_panel.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/_clone_panel.html.haml b/app/views/projects/_clone_panel.html.haml index 91353147..9a2be429 100644 --- a/app/views/projects/_clone_panel.html.haml +++ b/app/views/projects/_clone_panel.html.haml @@ -4,7 +4,7 @@ .form-horizontal= render "shared/clone_panel" .span4.pull-right .pull-right - - if @project.empty_repo? + - unless @project.empty_repo? - if can? current_user, :download_code, @project = link_to archive_project_repository_path(@project), class: "btn-small btn grouped" do %i.icon-download-alt From 19ab03f4612a2e622098bc199538380b011754c1 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 1 Apr 2013 21:37:39 +0300 Subject: [PATCH 146/152] minor design improvements --- app/assets/stylesheets/gitlab_bootstrap/blocks.scss | 5 +++-- app/views/dashboard/_groups.html.haml | 4 ++-- app/views/dashboard/_projects.html.haml | 4 ++-- app/views/dashboard/_teams.html.haml | 4 ++-- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/app/assets/stylesheets/gitlab_bootstrap/blocks.scss b/app/assets/stylesheets/gitlab_bootstrap/blocks.scss index cb055a1c..842e7a08 100644 --- a/app/assets/stylesheets/gitlab_bootstrap/blocks.scss +++ b/app/assets/stylesheets/gitlab_bootstrap/blocks.scss @@ -100,8 +100,9 @@ margin-top: 0; } - .btn-tiny { - @include box-shadow(0 0px 0px 1px #f1f1f1); + .btn { + position: relative; + top: -2px; } .nav-pills { diff --git a/app/views/dashboard/_groups.html.haml b/app/views/dashboard/_groups.html.haml index 3124d76a..2fedf87a 100644 --- a/app/views/dashboard/_groups.html.haml +++ b/app/views/dashboard/_groups.html.haml @@ -1,11 +1,11 @@ .ui-box %h5.title Groups - %small + %span.light (#{groups.count}) - if current_user.can_create_group? %span.pull-right - = link_to new_group_path, class: "btn btn-tiny info" do + = link_to new_group_path, class: "btn btn-small" do %i.icon-plus New Group %ul.well-list diff --git a/app/views/dashboard/_projects.html.haml b/app/views/dashboard/_projects.html.haml index 105e23fe..a106e83e 100644 --- a/app/views/dashboard/_projects.html.haml +++ b/app/views/dashboard/_projects.html.haml @@ -1,11 +1,11 @@ .ui-box %h5.title Projects - %small + %span.light (#{@projects_count}) - if current_user.can_create_project? %span.pull-right - = link_to new_project_path, class: "btn btn-tiny info" do + = link_to new_project_path, class: "btn btn-small" do %i.icon-plus New Project diff --git a/app/views/dashboard/_teams.html.haml b/app/views/dashboard/_teams.html.haml index 5c28f964..95d87f50 100644 --- a/app/views/dashboard/_teams.html.haml +++ b/app/views/dashboard/_teams.html.haml @@ -1,10 +1,10 @@ .ui-box.teams-box %h5.title Teams - %small + %span.light (#{teams.count}) %span.pull-right - = link_to new_team_path, class: "btn btn-tiny info" do + = link_to new_team_path, class: "btn btn-small" do %i.icon-plus New Team %ul.well-list From 8cadeb67502d9f674dc69c0b05341269c2baeb8f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 1 Apr 2013 22:30:48 +0300 Subject: [PATCH 147/152] nav views refactoring --- app/assets/stylesheets/sections/nav.scss | 116 +++++++++---------- app/views/layouts/admin.html.haml | 22 +--- app/views/layouts/application.html.haml | 23 +--- app/views/layouts/group.html.haml | 23 +--- app/views/layouts/nav/_admin.html.haml | 19 +++ app/views/layouts/nav/_dashboard.html.haml | 20 ++++ app/views/layouts/nav/_group.html.haml | 20 ++++ app/views/layouts/nav/_profile.html.haml | 17 +++ app/views/layouts/nav/_project.html.haml | 43 +++++++ app/views/layouts/nav/_team.html.haml | 25 ++++ app/views/layouts/profile.html.haml | 20 +--- app/views/layouts/project_resource.html.haml | 47 +------- app/views/layouts/user_team.html.haml | 28 +---- 13 files changed, 218 insertions(+), 205 deletions(-) create mode 100644 app/views/layouts/nav/_admin.html.haml create mode 100644 app/views/layouts/nav/_dashboard.html.haml create mode 100644 app/views/layouts/nav/_group.html.haml create mode 100644 app/views/layouts/nav/_profile.html.haml create mode 100644 app/views/layouts/nav/_project.html.haml create mode 100644 app/views/layouts/nav/_team.html.haml diff --git a/app/assets/stylesheets/sections/nav.scss b/app/assets/stylesheets/sections/nav.scss index 50091cd7..514b0b7c 100644 --- a/app/assets/stylesheets/sections/nav.scss +++ b/app/assets/stylesheets/sections/nav.scss @@ -1,68 +1,64 @@ -/* - * Main Menu of Application - * - */ -ul.main_menu { - margin: auto; +.main-nav { margin: 30px 0; margin-top: 10px; - height: 38px; - position: relative; - overflow: hidden; - .count { - position: relative; - top: -1px; - display: inline-block; - height: 15px; - margin: 0 0 0 5px; - padding: 0 8px 1px 8px; - height: auto; - font-size: 0.82em; - line-height: 14px; - text-align: center; - color: #777; - } - .label { - background: $hover; - text-shadow: none; - color: $style_color; - } - li { - list-style-type: none; - margin: 0; - display: table-cell; - width: 1%; - border-bottom: 2px solid #EEE; - &.active { - border-bottom: 2px solid #474D57; - a { - color: $style_color; - } - } + border-bottom: 1px solid #E1E1E1; - &.home { - a { - i { - font-size: 20px; - position: relative; - top: 4px; + ul { + margin: auto; + height: 39px; + position: relative; + top: 3px; + overflow: hidden; + .count { + position: relative; + top: -1px; + display: inline-block; + height: 15px; + margin: 0 0 0 5px; + padding: 0 8px 1px 8px; + height: auto; + font-size: 0.82em; + line-height: 14px; + text-align: center; + color: #777; + } + .label { + background: $hover; + text-shadow: none; + color: $style_color; + } + li { + list-style-type: none; + margin: 0; + display: table-cell; + width: 1%; + &.active { + border-bottom: 3px solid #777; + a { + color: $style_color; + font-weight: bolder; + } + } + + &.home { + a { + i { + font-size: 20px; + position: relative; + top: 4px; + } } } } - } - a { - display: block; - text-align: center; - font-weight: normal; - height: 36px; - line-height: 36px; - color: #777; - text-shadow: 0 1px 1px white; - padding: 0 10px; + a { + display: block; + text-align: center; + font-weight: normal; + height: 36px; + line-height: 34px; + color: #777; + text-shadow: 0 1px 1px white; + padding: 0 10px; + } } } -/* - * End of Main Menu - * - */ - diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml index 00a08e61..abe3f2ea 100644 --- a/app/views/layouts/admin.html.haml +++ b/app/views/layouts/admin.html.haml @@ -4,24 +4,8 @@ %body{class: "#{app_theme} admin"} = render "layouts/head_panel", title: "Admin area" = render "layouts/flash" - .container - %ul.main_menu - = nav_link(controller: :dashboard, html_options: {class: 'home'}) do - = link_to admin_root_path, title: "Stats" do - %i.icon-home - = nav_link(controller: :projects) do - = link_to "Projects", admin_projects_path - = nav_link(controller: :teams) do - = link_to "Teams", admin_teams_path - = nav_link(controller: :groups) do - = link_to "Groups", admin_groups_path - = nav_link(controller: :users) do - = link_to "Users", admin_users_path - = nav_link(controller: :logs) do - = link_to "Logs", admin_logs_path - = nav_link(controller: :hooks) do - = link_to "Hooks", admin_hooks_path - = nav_link(controller: :resque) do - = link_to "Background Jobs", admin_resque_path + %nav.main-nav + .container= render 'layouts/nav/admin' + .container .content= yield diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 90c26534..4e683140 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -4,25 +4,8 @@ %body{class: "#{app_theme} application"} = render "layouts/head_panel", title: "Dashboard" = render "layouts/flash" - .container - %ul.main_menu - = nav_link(path: 'dashboard#show', html_options: {class: 'home'}) do - = link_to root_path, title: "Home" do - %i.icon-home - = nav_link(path: 'dashboard#projects') do - = link_to projects_dashboard_path do - Projects - = nav_link(path: 'dashboard#issues') do - = link_to issues_dashboard_path do - Issues - %span.count= current_user.assigned_issues.opened.count - = nav_link(path: 'dashboard#merge_requests') do - = link_to merge_requests_dashboard_path do - Merge Requests - %span.count= current_user.cared_merge_requests.opened.count - = nav_link(path: 'search#show') do - = link_to "Search", search_path - = nav_link(controller: :help) do - = link_to "Help", help_path + %nav.main-nav + .container= render 'layouts/nav/dashboard' + .container .content= yield diff --git a/app/views/layouts/group.html.haml b/app/views/layouts/group.html.haml index 45528281..8296b8ae 100644 --- a/app/views/layouts/group.html.haml +++ b/app/views/layouts/group.html.haml @@ -4,25 +4,8 @@ %body{class: "#{app_theme} application"} = render "layouts/head_panel", title: "group: #{@group.name}" = render "layouts/flash" + %nav.main-nav + .container= render 'layouts/nav/group' + .container - %ul.main_menu - = nav_link(path: 'groups#show', html_options: {class: 'home'}) do - = link_to group_path(@group), title: "Home" do - %i.icon-home - = nav_link(path: 'groups#issues') do - = link_to issues_group_path(@group) do - Issues - %span.count= current_user.assigned_issues.opened.of_group(@group).count - = nav_link(path: 'groups#merge_requests') do - = link_to merge_requests_group_path(@group) do - Merge Requests - %span.count= current_user.cared_merge_requests.opened.of_group(@group).count - = nav_link(path: 'groups#people') do - = link_to "People", people_group_path(@group) - - - if can?(current_user, :manage_group, @group) - = nav_link(path: 'groups#edit') do - = link_to edit_group_path(@group), class: "tab " do - Settings - .content= yield diff --git a/app/views/layouts/nav/_admin.html.haml b/app/views/layouts/nav/_admin.html.haml new file mode 100644 index 00000000..ca77c26e --- /dev/null +++ b/app/views/layouts/nav/_admin.html.haml @@ -0,0 +1,19 @@ +%ul + = nav_link(controller: :dashboard, html_options: {class: 'home'}) do + = link_to admin_root_path, title: "Stats" do + %i.icon-home + = nav_link(controller: :projects) do + = link_to "Projects", admin_projects_path + = nav_link(controller: :teams) do + = link_to "Teams", admin_teams_path + = nav_link(controller: :groups) do + = link_to "Groups", admin_groups_path + = nav_link(controller: :users) do + = link_to "Users", admin_users_path + = nav_link(controller: :logs) do + = link_to "Logs", admin_logs_path + = nav_link(controller: :hooks) do + = link_to "Hooks", admin_hooks_path + = nav_link(controller: :resque) do + = link_to "Background Jobs", admin_resque_path + diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml new file mode 100644 index 00000000..2ac35050 --- /dev/null +++ b/app/views/layouts/nav/_dashboard.html.haml @@ -0,0 +1,20 @@ +%ul + = nav_link(path: 'dashboard#show', html_options: {class: 'home'}) do + = link_to root_path, title: "Home" do + %i.icon-home + = nav_link(path: 'dashboard#projects') do + = link_to projects_dashboard_path do + Projects + = nav_link(path: 'dashboard#issues') do + = link_to issues_dashboard_path do + Issues + %span.count= current_user.assigned_issues.opened.count + = nav_link(path: 'dashboard#merge_requests') do + = link_to merge_requests_dashboard_path do + Merge Requests + %span.count= current_user.cared_merge_requests.opened.count + = nav_link(path: 'search#show') do + = link_to "Search", search_path + = nav_link(controller: :help) do + = link_to "Help", help_path + diff --git a/app/views/layouts/nav/_group.html.haml b/app/views/layouts/nav/_group.html.haml new file mode 100644 index 00000000..f3cdb5ac --- /dev/null +++ b/app/views/layouts/nav/_group.html.haml @@ -0,0 +1,20 @@ +%ul + = nav_link(path: 'groups#show', html_options: {class: 'home'}) do + = link_to group_path(@group), title: "Home" do + %i.icon-home + = nav_link(path: 'groups#issues') do + = link_to issues_group_path(@group) do + Issues + %span.count= current_user.assigned_issues.opened.of_group(@group).count + = nav_link(path: 'groups#merge_requests') do + = link_to merge_requests_group_path(@group) do + Merge Requests + %span.count= current_user.cared_merge_requests.opened.of_group(@group).count + = nav_link(path: 'groups#people') do + = link_to "People", people_group_path(@group) + + - if can?(current_user, :manage_group, @group) + = nav_link(path: 'groups#edit') do + = link_to edit_group_path(@group), class: "tab " do + Settings + diff --git a/app/views/layouts/nav/_profile.html.haml b/app/views/layouts/nav/_profile.html.haml new file mode 100644 index 00000000..e5e4b27c --- /dev/null +++ b/app/views/layouts/nav/_profile.html.haml @@ -0,0 +1,17 @@ +%ul + = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do + = link_to profile_path, title: "Profile" do + %i.icon-home + = nav_link(path: 'profiles#account') do + = link_to "Account", account_profile_path + = nav_link(controller: :notifications) do + = link_to "Notifications", profile_notifications_path + = nav_link(controller: :keys) do + = link_to keys_path do + SSH Keys + %span.count= current_user.keys.count + = nav_link(path: 'profiles#design') do + = link_to "Design", design_profile_path + = nav_link(path: 'profiles#history') do + = link_to "History", history_profile_path + diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml new file mode 100644 index 00000000..ec3da964 --- /dev/null +++ b/app/views/layouts/nav/_project.html.haml @@ -0,0 +1,43 @@ +%ul + = nav_link(path: 'projects#show', html_options: {class: "home"}) do + = link_to project_path(@project), title: "Project" do + %i.icon-home + + - unless @project.empty_repo? + - if can? current_user, :download_code, @project + = nav_link(controller: %w(tree blob blame)) do + = link_to 'Files', project_tree_path(@project, @ref || @repository.root_ref) + = nav_link(controller: %w(commit commits compare repositories protected_branches)) do + = link_to "Commits", project_commits_path(@project, @ref || @repository.root_ref) + = nav_link(controller: %w(graph)) do + = link_to "Network", project_graph_path(@project, @ref || @repository.root_ref) + + - if @project.issues_enabled + = nav_link(controller: %w(issues milestones labels)) do + = link_to url_for_project_issues do + Issues + - if @project.used_default_issues_tracker? + %span.count.issue_counter= @project.issues.opened.count + + - if @project.repo_exists? && @project.merge_requests_enabled + = nav_link(controller: :merge_requests) do + = link_to project_merge_requests_path(@project) do + Merge Requests + %span.count.merge_counter= @project.merge_requests.opened.count + + - if @project.wiki_enabled + = nav_link(controller: :wikis) do + = link_to 'Wiki', project_wiki_path(@project, :home) + + - if @project.wall_enabled + = nav_link(controller: :walls) do + = link_to 'Wall', project_wall_path(@project) + + - if @project.snippets_enabled + = nav_link(controller: :snippets) do + = link_to 'Snippets', project_snippets_path(@project) + + - if can? current_user, :admin_project, @project + = nav_link(html_options: {class: "#{project_tab_class}"}) do + = link_to edit_project_path(@project), class: "stat-tab tab " do + Settings diff --git a/app/views/layouts/nav/_team.html.haml b/app/views/layouts/nav/_team.html.haml new file mode 100644 index 00000000..415e4510 --- /dev/null +++ b/app/views/layouts/nav/_team.html.haml @@ -0,0 +1,25 @@ +%ul + = nav_link(path: 'teams#show', html_options: {class: 'home'}) do + = link_to team_path(@team), title: "Home" do + %i.icon-home + + = nav_link(path: 'teams#issues') do + = link_to issues_team_path(@team) do + Issues + %span.count= Issue.opened.of_user_team(@team).count + + = nav_link(path: 'teams#merge_requests') do + = link_to merge_requests_team_path(@team) do + Merge Requests + %span.count= MergeRequest.opened.of_user_team(@team).count + + = nav_link(controller: [:members]) do + = link_to team_members_path(@team), class: "team-tab tab" do + Members + %span.count= @team.members.count + + - if can? current_user, :admin_user_team, @team + = nav_link(path: 'teams#edit') do + = link_to edit_team_path(@team), class: "stat-tab tab " do + Settings + diff --git a/app/views/layouts/profile.html.haml b/app/views/layouts/profile.html.haml index a7225baa..535f94c4 100644 --- a/app/views/layouts/profile.html.haml +++ b/app/views/layouts/profile.html.haml @@ -4,22 +4,8 @@ %body{class: "#{app_theme} profile"} = render "layouts/head_panel", title: "Profile" = render "layouts/flash" - .container - %ul.main_menu - = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do - = link_to profile_path, title: "Profile" do - %i.icon-home - = nav_link(path: 'profiles#account') do - = link_to "Account", account_profile_path - = nav_link(controller: :notifications) do - = link_to "Notifications", profile_notifications_path - = nav_link(controller: :keys) do - = link_to keys_path do - SSH Keys - %span.count= current_user.keys.count - = nav_link(path: 'profiles#design') do - = link_to "Design", design_profile_path - = nav_link(path: 'profiles#history') do - = link_to "History", history_profile_path + %nav.main-nav + .container= render 'layouts/nav/profile' + .container .content= yield diff --git a/app/views/layouts/project_resource.html.haml b/app/views/layouts/project_resource.html.haml index 0ca06837..7b0d4789 100644 --- a/app/views/layouts/project_resource.html.haml +++ b/app/views/layouts/project_resource.html.haml @@ -7,49 +7,8 @@ - if can?(current_user, :download_code, @project) = render 'shared/no_ssh' + %nav.main-nav + .container= render 'layouts/nav/project' + .container - %ul.main_menu - = nav_link(path: 'projects#show', html_options: {class: "home"}) do - = link_to project_path(@project), title: "Project" do - %i.icon-home - - - unless @project.empty_repo? - - if can? current_user, :download_code, @project - = nav_link(controller: %w(tree blob blame)) do - = link_to 'Files', project_tree_path(@project, @ref || @repository.root_ref) - = nav_link(controller: %w(commit commits compare repositories protected_branches)) do - = link_to "Commits", project_commits_path(@project, @ref || @repository.root_ref) - = nav_link(controller: %w(graph)) do - = link_to "Network", project_graph_path(@project, @ref || @repository.root_ref) - - - if @project.issues_enabled - = nav_link(controller: %w(issues milestones labels)) do - = link_to url_for_project_issues do - Issues - - if @project.used_default_issues_tracker? - %span.count.issue_counter= @project.issues.opened.count - - - if @project.repo_exists? && @project.merge_requests_enabled - = nav_link(controller: :merge_requests) do - = link_to project_merge_requests_path(@project) do - Merge Requests - %span.count.merge_counter= @project.merge_requests.opened.count - - - if @project.wiki_enabled - = nav_link(controller: :wikis) do - = link_to 'Wiki', project_wiki_path(@project, :home) - - - if @project.wall_enabled - = nav_link(controller: :walls) do - = link_to 'Wall', project_wall_path(@project) - - - if @project.snippets_enabled - = nav_link(controller: :snippets) do - = link_to 'Snippets', project_snippets_path(@project) - - - if can? current_user, :admin_project, @project - = nav_link(html_options: {class: "#{project_tab_class}"}) do - = link_to edit_project_path(@project), class: "stat-tab tab " do - Settings - .content= yield diff --git a/app/views/layouts/user_team.html.haml b/app/views/layouts/user_team.html.haml index 483bfad6..f2ead9d2 100644 --- a/app/views/layouts/user_team.html.haml +++ b/app/views/layouts/user_team.html.haml @@ -4,30 +4,8 @@ %body{class: "#{app_theme} application"} = render "layouts/head_panel", title: "team: #{@team.name}" = render "layouts/flash" + %nav.main-nav + .container= render 'layouts/nav/team' + .container - %ul.main_menu - = nav_link(path: 'teams#show', html_options: {class: 'home'}) do - = link_to team_path(@team), title: "Home" do - %i.icon-home - - = nav_link(path: 'teams#issues') do - = link_to issues_team_path(@team) do - Issues - %span.count= Issue.opened.of_user_team(@team).count - - = nav_link(path: 'teams#merge_requests') do - = link_to merge_requests_team_path(@team) do - Merge Requests - %span.count= MergeRequest.opened.of_user_team(@team).count - - = nav_link(controller: [:members]) do - = link_to team_members_path(@team), class: "team-tab tab" do - Members - %span.count= @team.members.count - - - if can? current_user, :admin_user_team, @team - = nav_link(path: 'teams#edit') do - = link_to edit_team_path(@team), class: "stat-tab tab " do - Settings - .content= yield From 8465238899ef2e7569df2c2a1780a4e331ed612c Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 1 Apr 2013 22:53:07 +0300 Subject: [PATCH 148/152] fix long names on wall --- app/assets/stylesheets/sections/wall.scss | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/sections/wall.scss b/app/assets/stylesheets/sections/wall.scss index 8d3b4734..d6ac08fc 100644 --- a/app/assets/stylesheets/sections/wall.scss +++ b/app/assets/stylesheets/sections/wall.scss @@ -26,8 +26,11 @@ .wall-author { color: #666; float: left; - width: 100px; + font-size: 12px; + width: 120px; text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; } .wall-text { @@ -35,7 +38,7 @@ margin-left: 10px; padding-left: 10px; float: left; - width: 80%; + width: 75%; } .wall-file { From 08c6f5f604e88a47a8dde8e2052883285c4e6c1c Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Tue, 2 Apr 2013 07:52:47 +0200 Subject: [PATCH 149/152] Adding special cases to the advanced setup notes. --- doc/install/installation.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/doc/install/installation.md b/doc/install/installation.md index 8cacc413..a9ae4b1e 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -292,3 +292,27 @@ If you are running SSH on a non-standard port, you must change the gitlab user's hostname 127.0.0.1; # Your server name or IP You also need to change the corresponding options (e.g. ssh_user, ssh_host, admin_uri) in the `config\gitlab.yml` file. + +## LDAP authentication + +You can configure LDAP authentication in config/gitlab.yml. Please restart GitLab after editing this file. + +## Using Custom Omniauth Providers + +GitLab uses [Omniauth](http://www.omniauth.org/) for authentication and already ships with a few providers preinstalled (e.g. LDAP, GitHub, Twitter). But sometimes that is not enough and you need to integrate with other authentication solutions. For these cases you can use the Omniauth provider. + +### Steps + +These steps are fairly general and you will need to figure out the exact details from the Omniauth provider's documentation. + +* Add `gem "omniauth-your-auth-provider"` to the [Gemfile](https://github.com/gitlabhq/gitlabhq/blob/master/Gemfile#L18) +* Run `sudo -u gitlab -H bundle install` to install the new gem(s) +* Add provider specific configuration options to your `config/gitlab.yml` (you can use the [auth providers section of the example config](https://github.com/gitlabhq/gitlabhq/blob/master/config/gitlab.yml.example#L53) as a reference) +* Add icons for the new provider into the [vendor/assets/images/authbuttons](https://github.com/gitlabhq/gitlabhq/tree/master/vendor/assets/images/authbuttons) directory (you can find some more popular ones over at https://github.com/intridea/authbuttons) +* Restart GitLab + +### Examples + +If you have successfully set up a provider that is not shipped with GitLab itself, please let us know. +You can help others by reporting successful configurations and probably share a few insights or provide warnings for common errors or pitfalls by sharing your experience [in the public Wiki](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Working-Custom-Omniauth-Provider-Configurations). +While we can't officially support every possible auth mechanism out there, we'd like to at least help those with special needs. From d3559e2556e70947787d841bc6ee98110059f2b3 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 2 Apr 2013 11:23:06 +0300 Subject: [PATCH 150/152] fix tabs features --- features/steps/shared/active_tab.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/features/steps/shared/active_tab.rb b/features/steps/shared/active_tab.rb index 446e3b9a..617a077b 100644 --- a/features/steps/shared/active_tab.rb +++ b/features/steps/shared/active_tab.rb @@ -3,9 +3,9 @@ module SharedActiveTab def ensure_active_main_tab(content) if content == "Home" - page.find('ul.main_menu li.active').should have_css('i.icon-home') + page.find('.main-nav li.active').should have_css('i.icon-home') else - page.find('ul.main_menu li.active').should have_content(content) + page.find('.main-nav li.active').should have_content(content) end end @@ -14,7 +14,7 @@ module SharedActiveTab end And 'no other main tabs should be active' do - page.should have_selector('ul.main_menu li.active', count: 1) + page.should have_selector('.main-nav li.active', count: 1) end And 'no other sub tabs should be active' do From af657b0509476db56e88014062ccf0a7a6b9d8b7 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 2 Apr 2013 11:32:41 +0300 Subject: [PATCH 151/152] reset st_commits before setting new value to prevent error when old st_commits is broken --- app/models/merge_request.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 8d378053..6ce94417 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -172,6 +172,12 @@ class MergeRequest < ActiveRecord::Base def reloaded_commits if opened? && unmerged_commits.any? + # we need to reset st_commits field first + # in order to prevent internal rails comparison + self.st_commits = [] + save + + # Then we can safely write unmerged commits self.st_commits = unmerged_commits save end From b641cdd183cc40fe25ee67ece41e883146a6207f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 2 Apr 2013 14:30:32 +0300 Subject: [PATCH 152/152] fix test --- spec/features/admin/admin_hooks_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/features/admin/admin_hooks_spec.rb b/spec/features/admin/admin_hooks_spec.rb index bc0586b2..102a1b92 100644 --- a/spec/features/admin/admin_hooks_spec.rb +++ b/spec/features/admin/admin_hooks_spec.rb @@ -12,7 +12,7 @@ describe "Admin::Hooks" do describe "GET /admin/hooks" do it "should be ok" do visit admin_root_path - within ".main_menu" do + within ".main-nav" do click_on "Hooks" end current_path.should == admin_hooks_path