From cb2be3ce0ab27ac9aa25f0c3eb59047ad5a0153a Mon Sep 17 00:00:00 2001 From: Gabor Liptak Date: Wed, 19 Sep 2012 13:36:00 -0500 Subject: [PATCH 001/113] Don't email omniauth created users --- app/observers/user_observer.rb | 5 +++-- spec/observers/user_observer_spec.rb | 12 ++++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/app/observers/user_observer.rb b/app/observers/user_observer.rb index 654621f7e1..aed320f6c0 100644 --- a/app/observers/user_observer.rb +++ b/app/observers/user_observer.rb @@ -1,8 +1,9 @@ class UserObserver < ActiveRecord::Observer def after_create(user) log_info("User \"#{user.name}\" (#{user.email}) was created") - - Notify.new_user_email(user.id, user.password).deliver + unless user.extern_uid? + Notify.new_user_email(user.id, user.password).deliver + end end def after_destroy user diff --git a/spec/observers/user_observer_spec.rb b/spec/observers/user_observer_spec.rb index 0420a250c8..8ce0b577ec 100644 --- a/spec/observers/user_observer_spec.rb +++ b/spec/observers/user_observer_spec.rb @@ -13,17 +13,25 @@ describe UserObserver do end context 'when a new user is created' do - let(:user) { double(:user, id: 42, password: 'P@ssword!', name: 'John', email: 'u@mail.local') } let(:notification) { double :notification } - it 'sends an email' do + it 'sends an email unless external' do + user = double(:user, id: 42, password: 'P@ssword!', name: 'John', email: 'u@mail.local', extern_uid?: false) notification.should_receive(:deliver) Notify.should_receive(:new_user_email).with(user.id, user.password).and_return(notification) subject.after_create(user) end + it 'no email for external' do + user = double(:user, id: 42, password: 'P@ssword!', name: 'John', email: 'u@mail.local', extern_uid?: true) + Notify.should_not_receive(:new_user_email) + + subject.after_create(user) + 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) subject.after_create(user) end From 333f7372c505583ddafa9f22bd93205f7ad3dbc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vanja=20Radovanovi=C4=87?= Date: Mon, 19 Nov 2012 11:44:28 +0100 Subject: [PATCH 002/113] fix: grouping by date desc doesn't sort it too --- app/views/commits/_commits.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/commits/_commits.html.haml b/app/views/commits/_commits.html.haml index c3c7d49ce7..9887b825fe 100644 --- a/app/views/commits/_commits.html.haml +++ b/app/views/commits/_commits.html.haml @@ -1,4 +1,4 @@ -- @commits.group_by { |c| c.committed_date.to_date }.each do |day, commits| +- @commits.group_by { |c| c.committed_date.to_date }.sort.reverse.each do |day, commits| %div.ui-box %h5.small %i.icon-calendar From 4d19a4fbebab7c240834fea73087a61725596932 Mon Sep 17 00:00:00 2001 From: Cyril Date: Mon, 10 Dec 2012 16:56:12 +0100 Subject: [PATCH 003/113] fix build failure (https://travis-ci.org/gitlabhq/gitlabhq/builds/3593153) --- features/steps/group/group.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/steps/group/group.rb b/features/steps/group/group.rb index 04d8c874b3..03d4ccae61 100644 --- a/features/steps/group/group.rb +++ b/features/steps/group/group.rb @@ -28,7 +28,7 @@ class Groups < Spinach::FeatureSteps Then 'I should see merge requests from this group assigned to me' do assigned_to_me(:merge_requests).each do |issue| - page.should have_content issue.title + page.should have_content issue.title[0..80] end end From 7225c06934993e1c1deccf3adfc2ed770f69e0db Mon Sep 17 00:00:00 2001 From: Mike Wyatt Date: Thu, 31 Jan 2013 18:28:03 -0330 Subject: [PATCH 004/113] default gitlab.relative_url_root to ENV['RAILS_RELATIVE_URL_ROOT'] --- config/initializers/1_settings.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index a1afa5b22c..119ae8e383 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -46,7 +46,7 @@ Settings.gitlab['default_projects_limit'] ||= 10 Settings.gitlab['host'] ||= 'localhost' Settings.gitlab['https'] = false if Settings.gitlab['https'].nil? Settings.gitlab['port'] ||= Settings.gitlab.https ? 443 : 80 -Settings.gitlab['relative_url_root'] ||= '' +Settings.gitlab['relative_url_root'] ||= ENV['RAILS_RELATIVE_URL_ROOT'] || '' Settings.gitlab['protocol'] ||= Settings.gitlab.https ? "https" : "http" Settings.gitlab['email_from'] ||= "gitlab@#{Settings.gitlab.host}" Settings.gitlab['support_email'] ||= Settings.gitlab.email_from From f6957f76586a5bba510f29a7ed965a606945c868 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Cabe=C3=A7a?= Date: Mon, 11 Feb 2013 12:22:06 +0000 Subject: [PATCH 005/113] Fix image url for emoji. --- app/helpers/application_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 196105f011..f5ad8330c6 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -160,7 +160,7 @@ module ApplicationHelper end def image_url(source) - root_url + path_to_image(source) + root_url.sub(/#{root_path}$/,'') + path_to_image(source) end alias_method :url_to_image, :image_url end From 157b03866124d562b78583fbcb38b3db8ac84d4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Cabe=C3=A7a?= Date: Sun, 17 Feb 2013 13:02:22 +0000 Subject: [PATCH 006/113] Include Riyad Preukschas suggestions. --- app/helpers/application_helper.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index f5ad8330c6..f640d5647f 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -160,7 +160,8 @@ module ApplicationHelper end def image_url(source) - root_url.sub(/#{root_path}$/,'') + path_to_image(source) + # prevent relative_root_path being added twice (it's part of root_url and path_to_image) + root_url.sub(/#{root_path}$/, path_to_image(source)) end alias_method :url_to_image, :image_url end From e975ed836d10214c4891d7d6e2052c7485d40c72 Mon Sep 17 00:00:00 2001 From: Dmitrii Pakhtinov Date: Mon, 25 Feb 2013 12:21:38 +0400 Subject: [PATCH 007/113] Distorted lines in `diff` Distorted lines in `diff` when viewing files `windows-style-line-separator: \r\n` --- app/assets/stylesheets/sections/commits.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss index a389a9baa8..0df39298c8 100644 --- a/app/assets/stylesheets/sections/commits.scss +++ b/app/assets/stylesheets/sections/commits.scss @@ -100,8 +100,9 @@ } } .line_content { + display: block; white-space: pre; - height: 14px; + height: 18px; margin: 0px; padding: 0px; border: none; From d8a40d8c933da8e89013e989940f8b60d0f2e247 Mon Sep 17 00:00:00 2001 From: Sato Hiroyuki Date: Tue, 26 Feb 2013 13:28:11 +0900 Subject: [PATCH 008/113] Move graph module from lib or vendor directory to app directory. Because not autoloading lib directory at development mode. --- .../assets/javascripts/branch-graph.js | 0 app/controllers/graph_controller.rb | 2 +- app/controllers/projects_controller.rb | 2 - app/models/graph/commit.rb | 50 ++++ app/models/graph/json_builder.rb | 266 +++++++++++++++++ lib/gitlab/graph/commit.rb | 52 ---- lib/gitlab/graph/json_builder.rb | 268 ------------------ 7 files changed, 317 insertions(+), 323 deletions(-) rename {vendor => app}/assets/javascripts/branch-graph.js (100%) create mode 100644 app/models/graph/commit.rb create mode 100644 app/models/graph/json_builder.rb delete mode 100644 lib/gitlab/graph/commit.rb delete mode 100644 lib/gitlab/graph/json_builder.rb diff --git a/vendor/assets/javascripts/branch-graph.js b/app/assets/javascripts/branch-graph.js similarity index 100% rename from vendor/assets/javascripts/branch-graph.js rename to app/assets/javascripts/branch-graph.js diff --git a/app/controllers/graph_controller.rb b/app/controllers/graph_controller.rb index c370433e50..8aadcfef8c 100644 --- a/app/controllers/graph_controller.rb +++ b/app/controllers/graph_controller.rb @@ -20,7 +20,7 @@ class GraphController < ProjectResourceController respond_to do |format| format.html format.json do - graph = Gitlab::Graph::JsonBuilder.new(project, @ref, @commit) + graph = Graph::JsonBuilder.new(project, @ref, @commit) render :json => graph.to_json end end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 5da3fbf591..f703cf6bc1 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -1,5 +1,3 @@ -require Rails.root.join('lib', 'gitlab', 'graph', 'json_builder') - class ProjectsController < ProjectResourceController skip_before_filter :project, only: [:new, :create] skip_before_filter :repository, only: [:new, :create] diff --git a/app/models/graph/commit.rb b/app/models/graph/commit.rb new file mode 100644 index 0000000000..2b09d53902 --- /dev/null +++ b/app/models/graph/commit.rb @@ -0,0 +1,50 @@ +require "grit" + +module Graph + class Commit + include ActionView::Helpers::TagHelper + + attr_accessor :time, :space, :refs, :parent_spaces + + def initialize(commit) + @_commit = commit + @time = -1 + @space = 0 + @parent_spaces = [] + end + + def method_missing(m, *args, &block) + @_commit.send(m, *args, &block) + end + + def to_graph_hash + h = {} + h[:parents] = self.parents.collect do |p| + [p.id,0,0] + end + h[:author] = { + name: author.name, + email: author.email + } + h[:time] = time + h[:space] = space + h[:parent_spaces] = parent_spaces + h[:refs] = refs.collect{|r|r.name}.join(" ") unless refs.nil? + h[:id] = sha + h[:date] = date + h[:message] = message + h + end + + def add_refs(ref_cache, repo) + if ref_cache.empty? + repo.refs.each do |ref| + ref_cache[ref.commit.id] ||= [] + ref_cache[ref.commit.id] << ref + end + end + @refs = ref_cache[@_commit.id] if ref_cache.include?(@_commit.id) + @refs ||= [] + end + end +end diff --git a/app/models/graph/json_builder.rb b/app/models/graph/json_builder.rb new file mode 100644 index 0000000000..8440b5d5cd --- /dev/null +++ b/app/models/graph/json_builder.rb @@ -0,0 +1,266 @@ +require "grit" + +module Graph + class JsonBuilder + attr_accessor :days, :commits, :ref_cache, :repo + + def self.max_count + @max_count ||= 650 + end + + def initialize project, ref, commit + @project = project + @ref = ref + @commit = commit + @repo = project.repo + @ref_cache = {} + + @commits = collect_commits + @days = index_commits + end + + def to_json(*args) + { + days: @days.compact.map { |d| [d.day, d.strftime("%b")] }, + commits: @commits.map(&:to_graph_hash) + }.to_json(*args) + end + + protected + + # Get commits from repository + # + def collect_commits + + @commits = Grit::Commit.find_all(repo, nil, {topo_order: true, max_count: self.class.max_count, skip: to_commit}).dup + + # Decorate with app/models/commit.rb + @commits.map! { |commit| Commit.new(commit) } + + # Decorate with lib/gitlab/graph/commit.rb + @commits.map! { |commit| Graph::Commit.new(commit) } + + # add refs to each commit + @commits.each { |commit| commit.add_refs(ref_cache, repo) } + + @commits + end + + # Method is adding time and space on the + # list of commits. As well as returns date list + # corelated with time set on commits. + # + # @param [Array] commits to index + # + # @return [Array] list of commit dates corelated with time on commits + def index_commits + days, times = [], [] + map = {} + + commits.reverse.each_with_index do |c,i| + c.time = i + days[i] = c.committed_date + map[c.id] = c + times[i] = c + end + + @_reserved = {} + days.each_index do |i| + @_reserved[i] = [] + end + + commits_sort_by_ref.each do |commit| + if map.include? commit.id then + place_chain(map[commit.id], map) + end + end + + # find parent spaces for not overlap lines + times.each do |c| + c.parent_spaces.concat(find_free_parent_spaces(c, map, times)) + end + + days + end + + # Skip count that the target commit is displayed in center. + def to_commit + commits = Grit::Commit.find_all(repo, nil, {topo_order: true}) + commit_index = commits.index do |c| + c.id == @commit.id + end + + if commit_index && (self.class.max_count / 2 < commit_index) then + # get max index that commit is displayed in the center. + commit_index - self.class.max_count / 2 + else + 0 + end + end + + def commits_sort_by_ref + commits.sort do |a,b| + if include_ref?(a) + -1 + elsif include_ref?(b) + 1 + else + b.committed_date <=> a.committed_date + end + end + end + + def include_ref?(commit) + heads = commit.refs.select do |ref| + ref.is_a?(Grit::Head) or ref.is_a?(Grit::Remote) or ref.is_a?(Grit::Tag) + end + + heads.map! do |head| + head.name + end + + heads.include?(@ref) + end + + def find_free_parent_spaces(commit, map, times) + spaces = [] + + commit.parents.each do |p| + if map.include?(p.id) then + parent = map[p.id] + + range = if commit.time < parent.time then + commit.time..parent.time + else + parent.time..commit.time + end + + space = if commit.space >= parent.space then + find_free_parent_space(range, parent.space, 1, commit.space, times) + else + find_free_parent_space(range, parent.space, -1, parent.space, times) + end + + mark_reserved(range, space) + spaces << space + end + end + + spaces + end + + def find_free_parent_space(range, space_base, space_step, space_default, times) + if is_overlap?(range, times, space_default) then + find_free_space(range, space_base, space_step) + else + space_default + end + end + + def is_overlap?(range, times, overlap_space) + range.each do |i| + if i != range.first && + i != range.last && + times[i].space == overlap_space then + + return true; + end + end + + false + end + + # Add space mark on commit and its parents + # + # @param [Graph::Commit] the commit object. + # @param [Hash] map of commits + def place_chain(commit, map, parent_time = nil) + leaves = take_left_leaves(commit, map) + if leaves.empty? + return + end + # and mark it as reserved + min_time = leaves.last.time + max_space = 1 + parents = leaves.last.parents.collect + parents.each do |p| + if map.include? p.id + parent = map[p.id] + if parent.time < min_time + min_time = parent.time + end + if max_space < parent.space then + max_space = parent.space + end + end + end + if parent_time.nil? + max_time = leaves.first.time + else + max_time = parent_time - 1 + end + + time_range = leaves.last.time..leaves.first.time + space = find_free_space(time_range, max_space, 2) + leaves.each{|l| l.space = space} + + mark_reserved(min_time..max_time, space) + + # Visit branching chains + leaves.each do |l| + parents = l.parents.collect.select{|p| map.include? p.id and map[p.id].space.zero?} + for p in parents + place_chain(map[p.id], map, l.time) + end + end + end + + def mark_reserved(time_range, space) + for day in time_range + @_reserved[day].push(space) + end + end + + def find_free_space(time_range, space_base, space_step) + reserved = [] + for day in time_range + reserved += @_reserved[day] + end + reserved.uniq! + + space = space_base + while reserved.include?(space) do + space += space_step + if space <= 0 then + space_step *= -1 + space = space_base + space_step + end + end + + space + end + + # Takes most left subtree branch of commits + # which don't have space mark yet. + # + # @param [Graph::Commit] the commit object. + # @param [Hash] map of commits + # + # @return [Array] list of branch commits + def take_left_leaves(commit, map) + leaves = [] + leaves.push(commit) if commit.space.zero? + + while true + return leaves if commit.parents.count.zero? + return leaves unless map.include? commit.parents.first.id + + commit = map[commit.parents.first.id] + + return leaves unless commit.space.zero? + + leaves.push(commit) + end + end + end +end diff --git a/lib/gitlab/graph/commit.rb b/lib/gitlab/graph/commit.rb deleted file mode 100644 index 13c8ebc995..0000000000 --- a/lib/gitlab/graph/commit.rb +++ /dev/null @@ -1,52 +0,0 @@ -require "grit" - -module Gitlab - module Graph - class Commit - include ActionView::Helpers::TagHelper - - attr_accessor :time, :space, :refs, :parent_spaces - - def initialize(commit) - @_commit = commit - @time = -1 - @space = 0 - @parent_spaces = [] - end - - def method_missing(m, *args, &block) - @_commit.send(m, *args, &block) - end - - def to_graph_hash - h = {} - h[:parents] = self.parents.collect do |p| - [p.id,0,0] - end - h[:author] = { - name: author.name, - email: author.email - } - h[:time] = time - h[:space] = space - h[:parent_spaces] = parent_spaces - h[:refs] = refs.collect{|r|r.name}.join(" ") unless refs.nil? - h[:id] = sha - h[:date] = date - h[:message] = message - h - end - - def add_refs(ref_cache, repo) - if ref_cache.empty? - repo.refs.each do |ref| - ref_cache[ref.commit.id] ||= [] - ref_cache[ref.commit.id] << ref - end - end - @refs = ref_cache[@_commit.id] if ref_cache.include?(@_commit.id) - @refs ||= [] - end - end - end -end diff --git a/lib/gitlab/graph/json_builder.rb b/lib/gitlab/graph/json_builder.rb deleted file mode 100644 index cc971a245a..0000000000 --- a/lib/gitlab/graph/json_builder.rb +++ /dev/null @@ -1,268 +0,0 @@ -require "grit" - -module Gitlab - module Graph - class JsonBuilder - attr_accessor :days, :commits, :ref_cache, :repo - - def self.max_count - @max_count ||= 650 - end - - def initialize project, ref, commit - @project = project - @ref = ref - @commit = commit - @repo = project.repo - @ref_cache = {} - - @commits = collect_commits - @days = index_commits - end - - def to_json(*args) - { - days: @days.compact.map { |d| [d.day, d.strftime("%b")] }, - commits: @commits.map(&:to_graph_hash) - }.to_json(*args) - end - - protected - - # Get commits from repository - # - def collect_commits - - @commits = Grit::Commit.find_all(repo, nil, {topo_order: true, max_count: self.class.max_count, skip: to_commit}).dup - - # Decorate with app/models/commit.rb - @commits.map! { |commit| ::Commit.new(commit) } - - # Decorate with lib/gitlab/graph/commit.rb - @commits.map! { |commit| Gitlab::Graph::Commit.new(commit) } - - # add refs to each commit - @commits.each { |commit| commit.add_refs(ref_cache, repo) } - - @commits - end - - # Method is adding time and space on the - # list of commits. As well as returns date list - # corelated with time set on commits. - # - # @param [Array] commits to index - # - # @return [Array] list of commit dates corelated with time on commits - def index_commits - days, times = [], [] - map = {} - - commits.reverse.each_with_index do |c,i| - c.time = i - days[i] = c.committed_date - map[c.id] = c - times[i] = c - end - - @_reserved = {} - days.each_index do |i| - @_reserved[i] = [] - end - - commits_sort_by_ref.each do |commit| - if map.include? commit.id then - place_chain(map[commit.id], map) - end - end - - # find parent spaces for not overlap lines - times.each do |c| - c.parent_spaces.concat(find_free_parent_spaces(c, map, times)) - end - - days - end - - # Skip count that the target commit is displayed in center. - def to_commit - commits = Grit::Commit.find_all(repo, nil, {topo_order: true}) - commit_index = commits.index do |c| - c.id == @commit.id - end - - if commit_index && (self.class.max_count / 2 < commit_index) then - # get max index that commit is displayed in the center. - commit_index - self.class.max_count / 2 - else - 0 - end - end - - def commits_sort_by_ref - commits.sort do |a,b| - if include_ref?(a) - -1 - elsif include_ref?(b) - 1 - else - b.committed_date <=> a.committed_date - end - end - end - - def include_ref?(commit) - heads = commit.refs.select do |ref| - ref.is_a?(Grit::Head) or ref.is_a?(Grit::Remote) or ref.is_a?(Grit::Tag) - end - - heads.map! do |head| - head.name - end - - heads.include?(@ref) - end - - def find_free_parent_spaces(commit, map, times) - spaces = [] - - commit.parents.each do |p| - if map.include?(p.id) then - parent = map[p.id] - - range = if commit.time < parent.time then - commit.time..parent.time - else - parent.time..commit.time - end - - space = if commit.space >= parent.space then - find_free_parent_space(range, parent.space, 1, commit.space, times) - else - find_free_parent_space(range, parent.space, -1, parent.space, times) - end - - mark_reserved(range, space) - spaces << space - end - end - - spaces - end - - def find_free_parent_space(range, space_base, space_step, space_default, times) - if is_overlap?(range, times, space_default) then - find_free_space(range, space_base, space_step) - else - space_default - end - end - - def is_overlap?(range, times, overlap_space) - range.each do |i| - if i != range.first && - i != range.last && - times[i].space == overlap_space then - - return true; - end - end - - false - end - - # Add space mark on commit and its parents - # - # @param [Graph::Commit] the commit object. - # @param [Hash] map of commits - def place_chain(commit, map, parent_time = nil) - leaves = take_left_leaves(commit, map) - if leaves.empty? - return - end - # and mark it as reserved - min_time = leaves.last.time - max_space = 1 - parents = leaves.last.parents.collect - parents.each do |p| - if map.include? p.id - parent = map[p.id] - if parent.time < min_time - min_time = parent.time - end - if max_space < parent.space then - max_space = parent.space - end - end - end - if parent_time.nil? - max_time = leaves.first.time - else - max_time = parent_time - 1 - end - - time_range = leaves.last.time..leaves.first.time - space = find_free_space(time_range, max_space, 2) - leaves.each{|l| l.space = space} - - mark_reserved(min_time..max_time, space) - - # Visit branching chains - leaves.each do |l| - parents = l.parents.collect.select{|p| map.include? p.id and map[p.id].space.zero?} - for p in parents - place_chain(map[p.id], map, l.time) - end - end - end - - def mark_reserved(time_range, space) - for day in time_range - @_reserved[day].push(space) - end - end - - def find_free_space(time_range, space_base, space_step) - reserved = [] - for day in time_range - reserved += @_reserved[day] - end - reserved.uniq! - - space = space_base - while reserved.include?(space) do - space += space_step - if space <= 0 then - space_step *= -1 - space = space_base + space_step - end - end - - space - end - - # Takes most left subtree branch of commits - # which don't have space mark yet. - # - # @param [Graph::Commit] the commit object. - # @param [Hash] map of commits - # - # @return [Array] list of branch commits - def take_left_leaves(commit, map) - leaves = [] - leaves.push(commit) if commit.space.zero? - - while true - return leaves if commit.parents.count.zero? - return leaves unless map.include? commit.parents.first.id - - commit = map[commit.parents.first.id] - - return leaves unless commit.space.zero? - - leaves.push(commit) - end - end - end - end -end From aa36f07a02b524c843374968af6a6c122d980bd7 Mon Sep 17 00:00:00 2001 From: Sato Hiroyuki Date: Tue, 26 Feb 2013 21:20:14 +0900 Subject: [PATCH 009/113] Fix the commits are not ordered commiter date. It is fixed that the date label of network graph is broken. --- app/models/graph/json_builder.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/graph/json_builder.rb b/app/models/graph/json_builder.rb index 8440b5d5cd..06805fd4a0 100644 --- a/app/models/graph/json_builder.rb +++ b/app/models/graph/json_builder.rb @@ -32,7 +32,7 @@ module Graph # def collect_commits - @commits = Grit::Commit.find_all(repo, nil, {topo_order: true, max_count: self.class.max_count, skip: to_commit}).dup + @commits = Grit::Commit.find_all(repo, nil, {date_order: true, max_count: self.class.max_count, skip: to_commit}).dup # Decorate with app/models/commit.rb @commits.map! { |commit| Commit.new(commit) } @@ -85,7 +85,7 @@ module Graph # Skip count that the target commit is displayed in center. def to_commit - commits = Grit::Commit.find_all(repo, nil, {topo_order: true}) + commits = Grit::Commit.find_all(repo, nil, {date_order: true}) commit_index = commits.index do |c| c.id == @commit.id end From 4a55c6987703717fd63b7884f2c9695ccac8c010 Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Wed, 27 Feb 2013 12:53:36 +0400 Subject: [PATCH 010/113] Data converting migrations was wrong. Fixed --- .../20130218141258_convert_closed_to_state_in_issue.rb | 6 +++--- ...130218141327_convert_closed_to_state_in_merge_request.rb | 6 +++--- .../20130218141344_convert_closed_to_state_in_milestone.rb | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/db/migrate/20130218141258_convert_closed_to_state_in_issue.rb b/db/migrate/20130218141258_convert_closed_to_state_in_issue.rb index 0614a5c006..9fa96203ff 100644 --- a/db/migrate/20130218141258_convert_closed_to_state_in_issue.rb +++ b/db/migrate/20130218141258_convert_closed_to_state_in_issue.rb @@ -1,14 +1,14 @@ class ConvertClosedToStateInIssue < ActiveRecord::Migration def up Issue.transaction do - Issue.where(closed: true).update_all("state = 'closed'") - Issue.where(closed: false).update_all("state = 'opened'") + Issue.where(closed: true).update_all(state: :closed) + Issue.where(closed: false).update_all(state: :opened) end end def down Issue.transaction do - Issue.where(state: :closed).update_all("closed = 1") + Issue.where(state: :closed).update_all(closed: true) end end end diff --git a/db/migrate/20130218141327_convert_closed_to_state_in_merge_request.rb b/db/migrate/20130218141327_convert_closed_to_state_in_merge_request.rb index 5e7477d84e..ebb7ae585e 100644 --- a/db/migrate/20130218141327_convert_closed_to_state_in_merge_request.rb +++ b/db/migrate/20130218141327_convert_closed_to_state_in_merge_request.rb @@ -1,9 +1,9 @@ class ConvertClosedToStateInMergeRequest < ActiveRecord::Migration def up MergeRequest.transaction do - MergeRequest.where(closed: true, merged: true).update_all("state = 'merged'") - MergeRequest.where(closed: true, merged: true).update_all("state = 'closed'") - MergeRequest.where(closed: false).update_all("state = 'opened'") + MergeRequest.where(closed: true, merged: true).update_all(state: :merged) + MergeRequest.where(closed: true, merged: false).update_all(state: :closed) + MergeRequest.where(closed: false).update_all(state: :opened) end end diff --git a/db/migrate/20130218141344_convert_closed_to_state_in_milestone.rb b/db/migrate/20130218141344_convert_closed_to_state_in_milestone.rb index 7809666639..1978ea8915 100644 --- a/db/migrate/20130218141344_convert_closed_to_state_in_milestone.rb +++ b/db/migrate/20130218141344_convert_closed_to_state_in_milestone.rb @@ -1,14 +1,14 @@ class ConvertClosedToStateInMilestone < ActiveRecord::Migration def up Milestone.transaction do - Milestone.where(closed: false).update_all("state = 'opened'") - Milestone.where(closed: false).update_all("state = 'active'") + Milestone.where(closed: true).update_all(state: :closed) + Milestone.where(closed: false).update_all(state: :active) end end def down Milestone.transaction do - Milestone.where(state: :closed).update_all("closed = 1") + Milestone.where(state: :closed).update_all(closed: true) end end end From df63ab78a8bac8fd7cd2ea2edc7d2c274210602a Mon Sep 17 00:00:00 2001 From: tsl0922 Date: Wed, 27 Feb 2013 18:27:10 +0800 Subject: [PATCH 011/113] Fix project transfer error --- app/services/project_transfer_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/project_transfer_service.rb b/app/services/project_transfer_service.rb index f91a3cd199..35d9517ad2 100644 --- a/app/services/project_transfer_service.rb +++ b/app/services/project_transfer_service.rb @@ -25,7 +25,7 @@ class ProjectTransferService Gitlab::ProjectMover.new(project, old_dir, new_dir).execute - save! + project.save! end rescue Gitlab::ProjectMover::ProjectMoveError => ex raise Project::TransferError.new(ex.message) From f11e855bdb7f4026a4ec4c553ce7308b9bf71a0a Mon Sep 17 00:00:00 2001 From: Sato Hiroyuki Date: Wed, 27 Feb 2013 21:49:53 +0900 Subject: [PATCH 012/113] Finding free space from the way near commit which is downward --- app/models/graph/json_builder.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/models/graph/json_builder.rb b/app/models/graph/json_builder.rb index 06805fd4a0..2ba05405e2 100644 --- a/app/models/graph/json_builder.rb +++ b/app/models/graph/json_builder.rb @@ -136,9 +136,9 @@ module Graph end space = if commit.space >= parent.space then - find_free_parent_space(range, parent.space, 1, commit.space, times) + find_free_parent_space(range, parent.space, -1, commit.space, times) else - find_free_parent_space(range, parent.space, -1, parent.space, times) + find_free_parent_space(range, commit.space, -1, parent.space, times) end mark_reserved(range, space) @@ -151,7 +151,7 @@ module Graph def find_free_parent_space(range, space_base, space_step, space_default, times) if is_overlap?(range, times, space_default) then - find_free_space(range, space_base, space_step) + find_free_space(range, space_base, space_step, space_default) else space_default end @@ -221,17 +221,17 @@ module Graph end end - def find_free_space(time_range, space_base, space_step) + def find_free_space(time_range, space_base, space_step, space_default = 1) reserved = [] for day in time_range reserved += @_reserved[day] end reserved.uniq! - space = space_base + space = space_default while reserved.include?(space) do space += space_step - if space <= 0 then + if space < space_base then space_step *= -1 space = space_base + space_step end From 92039dd67763fc6503f74c96cb3c16724e04e18f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 27 Feb 2013 20:20:31 +0200 Subject: [PATCH 013/113] Developers can merge MR if target branch is not protected --- app/controllers/merge_requests_controller.rb | 16 +++++++++++++++- app/models/ability.rb | 1 - app/services/git_push_service.rb | 4 ++-- .../merge_requests/show/_mr_accept.html.haml | 6 +++--- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/app/controllers/merge_requests_controller.rb b/app/controllers/merge_requests_controller.rb index 67f9617833..c8fe2e6bfe 100644 --- a/app/controllers/merge_requests_controller.rb +++ b/app/controllers/merge_requests_controller.rb @@ -81,7 +81,8 @@ class MergeRequestsController < ProjectResourceController end def automerge - return access_denied! unless can?(current_user, :accept_mr, @project) + return access_denied! unless allowed_to_merge? + if @merge_request.opened? && @merge_request.can_be_merged? @merge_request.should_remove_source_branch = params[:should_remove_source_branch] @merge_request.automerge!(current_user) @@ -143,5 +144,18 @@ class MergeRequestsController < ProjectResourceController # or from cache if already merged @commits = @merge_request.commits @commits = CommitDecorator.decorate(@commits) + + @allowed_to_merge = allowed_to_merge? + @show_merge_controls = @merge_request.opened? && @commits.any? && @allowed_to_merge + end + + def allowed_to_merge? + action = if project.protected_branch?(@merge_request.target_branch) + :push_code_to_protected_branches + else + :push_code + end + + can?(current_user, action, @project) end end diff --git a/app/models/ability.rb b/app/models/ability.rb index 6fda2e52c7..41f7127403 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -91,7 +91,6 @@ class Ability :admin_team_member, :admin_merge_request, :admin_note, - :accept_mr, :admin_wiki, :admin_project ] diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index 40d57c6757..208ccf699d 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -19,6 +19,8 @@ class GitPushService # Collect data for this git push @push_data = post_receive_data(oldrev, newrev, ref) + create_push_event + project.ensure_satellite_exists project.discover_default_branch @@ -27,8 +29,6 @@ class GitPushService project.execute_hooks(@push_data.dup) project.execute_services(@push_data.dup) end - - create_push_event end # This method provide a sample data diff --git a/app/views/merge_requests/show/_mr_accept.html.haml b/app/views/merge_requests/show/_mr_accept.html.haml index 64f25a5118..d4271c5551 100644 --- a/app/views/merge_requests/show/_mr_accept.html.haml +++ b/app/views/merge_requests/show/_mr_accept.html.haml @@ -1,9 +1,9 @@ -- unless can?(current_user, :accept_mr, @project) +- unless @allowed_to_merge .alert - %strong Only masters can accept MR + %strong You don't have enough permissions to merge this MR -- if @merge_request.opened? && @commits.any? && can?(current_user, :accept_mr, @project) +- if @show_merge_controls .automerge_widget.can_be_merged{style: "display:none"} .alert.alert-success %span From aceb747bb87319c4118ce60fe9c221e54068ba31 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 27 Feb 2013 20:40:01 +0200 Subject: [PATCH 014/113] use system call to start sidekiq --- lib/tasks/sidekiq.rake | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/tasks/sidekiq.rake b/lib/tasks/sidekiq.rake index cf99951e02..d0e9dfe46a 100644 --- a/lib/tasks/sidekiq.rake +++ b/lib/tasks/sidekiq.rake @@ -1,19 +1,19 @@ namespace :sidekiq do desc "GITLAB | Stop sidekiq" task :stop do - run "bundle exec sidekiqctl stop #{pidfile}" + system "bundle exec sidekiqctl stop #{pidfile}" end desc "GITLAB | Start sidekiq" task :start do - run "nohup bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,gitlab_shell,common,default -e #{Rails.env} -P #{pidfile} >> #{Rails.root.join("log", "sidekiq.log")} 2>&1 &" + system "nohup bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,gitlab_shell,common,default -e #{Rails.env} -P #{pidfile} >> #{Rails.root.join("log", "sidekiq.log")} 2>&1 &" end - + desc "GITLAB | Start sidekiq with launchd on Mac OS X" task :launchd do - run "bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,gitlab_shell,common,default -e #{Rails.env} -P #{pidfile} >> #{Rails.root.join("log", "sidekiq.log")} 2>&1" + system "bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,gitlab_shell,common,default -e #{Rails.env} -P #{pidfile} >> #{Rails.root.join("log", "sidekiq.log")} 2>&1" end - + def pidfile Rails.root.join("tmp", "pids", "sidekiq.pid") end From 2c71c2e1df1bec9ded0a62feb6f68f60fbdfb154 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 27 Feb 2013 21:05:57 +0200 Subject: [PATCH 015/113] trying new readme --- README.md | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index e910dc958c..2b8b8dfc18 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,34 @@ -# Welcome to GitLab! Self hosted Git management software +## GitLab is a self hosted Git management software. +Check out [gitlab.org](http://gitlab.org) -## Badges: +![logo](https://raw.github.com/gitlabhq/gitlabhq/master/public/gitlab_logo.png) + +With GitLab you can: + * create projects and repositories + * manage repositories access + * do code review + +- - - + +### Code status: + +* master: travis-ci.org + [![build status](https://secure.travis-ci.org/gitlabhq/gitlabhq.png)](https://travis-ci.org/gitlabhq/gitlabhq) + +* master: ci.gitlab.org + [![CI](http://ci.gitlab.org/projects/1/status?ref=master)](http://ci.gitlab.org/projects/1?ref=master) -* master: travis-ci.org [![build status](https://secure.travis-ci.org/gitlabhq/gitlabhq.png)](https://travis-ci.org/gitlabhq/gitlabhq)a -* master: ci.gitlab.org [![CI](http://ci.gitlab.org/projects/1/status?ref=master)](http://ci.gitlab.org/projects/1?ref=master) * [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/gitlabhq/gitlabhq) * [![Dependency Status](https://gemnasium.com/gitlabhq/gitlabhq.png)](https://gemnasium.com/gitlabhq/gitlabhq) -GitLab is a free project and repository management application - - -## Application details +### Application details * powered by Ruby on Rails * its completely free and open source * distributed under the MIT License -## Requirements +### Requirements * Ubuntu/Debian * ruby 1.9.3+ @@ -26,16 +37,14 @@ GitLab is a free project and repository management application * gitlab-shell * redis -## Install +### Install Checkout [wiki](https://github.com/gitlabhq/gitlabhq/wiki) pages for installation information, migration, etc. -## [Community](http://gitlab.org/community/) +### [Community](http://gitlab.org/community/) -## [Contact](http://gitlab.org/contact/) +### [Contact](http://gitlab.org/contact/) -## Contribute +### [Issue Submission Guide](https://github.com/gitlabhq/gitlabhq/wiki/Issue-Submission-Guide) -[Developer Guide](https://github.com/gitlabhq/gitlabhq/wiki/Developer-Guide) -Want to help - send a pull request. -We'll accept good pull requests. +### [Developer Guide](https://github.com/gitlabhq/gitlabhq/wiki/Developer-Guide) From 863d297ede6989f00ab0a5af28efdf99a51f805a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 27 Feb 2013 21:10:23 +0200 Subject: [PATCH 016/113] reduce fonts size for wiki render --- app/assets/stylesheets/gitlab_bootstrap/typography.scss | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/gitlab_bootstrap/typography.scss b/app/assets/stylesheets/gitlab_bootstrap/typography.scss index 781577c214..2f7b1d25a4 100644 --- a/app/assets/stylesheets/gitlab_bootstrap/typography.scss +++ b/app/assets/stylesheets/gitlab_bootstrap/typography.scss @@ -88,13 +88,14 @@ a:focus { */ .wiki { font-size: 13px; + line-height: 20px; code { padding: 0 4px; } p { font-size: 13px; } - h1 { font-size: 32px; line-height: 40px; margin: 10px 0;} - h2 { font-size: 26px; line-height: 40px; margin: 10px 0;} - h3 { font-size: 22px; line-height: 40px; margin: 10px 0;} - h4 { font-size: 18px; line-height: 20px; margin: 10px 0;} + h1 { font-size: 26px; line-height: 40px; margin: 10px 0;} + h2 { font-size: 22px; line-height: 40px; margin: 10px 0;} + h3 { font-size: 18px; line-height: 40px; margin: 10px 0;} + h4 { font-size: 16px; line-height: 20px; margin: 10px 0;} h5 { font-size: 14px; line-height: 20px; margin: 10px 0;} h6 { font-size: 12px; line-height: 20px; margin: 10px 0;} .white .highlight pre { background: #f5f5f5; } From 70e1b3b1cb7dbfaceec702f929ca13536772ac2b Mon Sep 17 00:00:00 2001 From: Ezekiel Templin Date: Wed, 27 Feb 2013 14:28:36 -0500 Subject: [PATCH 017/113] Update `binding_of_caller` version Updating this dependency fixed my Ruby 2.0 installation issues. --- Gemfile.lock | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 93abf857cb..7a7153fcd2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -94,7 +94,8 @@ GEM better_errors (0.3.2) coderay (>= 1.0.0) erubis (>= 2.7.0) - binding_of_caller (0.6.8) + binding_of_caller (0.7.1) + debug_inspector (>= 0.0.1) bootstrap-sass (2.2.1.1) sass (~> 3.2) builder (3.0.4) @@ -132,6 +133,7 @@ GEM connection_pool (1.0.0) crack (0.3.1) daemons (1.1.9) + debug_inspector (0.0.2) devise (2.1.2) bcrypt-ruby (~> 3.0) orm_adapter (~> 0.1) From 5f9bc743f5fbd7170bb3040ab8e5d8fbafb3b903 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Wed, 27 Feb 2013 21:51:46 +0100 Subject: [PATCH 018/113] Update contributing file with latest insights. --- CONTRIBUTING.md | 60 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 15 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 00304dd3d6..005837f2ca 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,26 +1,56 @@ -# Contact & support - -If you want quick help, head over to our [Support Forum](https://groups.google.com/forum/#!forum/gitlabhq). -Otherwise you can follow our [Issue Submission Guide](https://github.com/gitlabhq/gitlabhq/wiki/Issue-Submission-Guide) for a more systematic and thorough guide to solving your issues. - - - # Contribute to GitLab -## Recipes +If you have a question or want to contribute to GitLab this guide show you the appropriate channel to use. -We collect user submitted installation scripts and config file templates for platforms we don't support officially. -We believe there is merit in allowing a certain amount of diversity. -You can get and submit your solution to running/configuring GitLab with your favorite OS/distro, database, web server, cloud hoster, configuration management tool, etc. +## Ruling out common errors -Help us improve the collection of [GitLab Recipes](https://github.com/gitlabhq/gitlab-recipes/) +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. + +## Paid support + +Community support in the [Support Forum](https://groups.google.com/forum/#!forum/gitlabhq) is done by volunteers. Paid support is available from [GitLab.com](http://blog.gitlab.com/services/) ## Feature suggestions -Follow the [Issue Submission Guide](https://github.com/gitlabhq/gitlabhq/wiki/Issue-Submission-Guide) and support other peoples ideas or propose your own. +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 -## Code +Code speaks louder than words. If you can please submit a pull request with the fix including tests. Starting point would be the [Developer Guide](https://github.com/gitlabhq/gitlabhq/wiki/Developer-Guide) -Follow our [Developer Guide](https://github.com/gitlabhq/gitlabhq/wiki/Developer-Guide) to set you up for hacking on GitLab. +## Submitting via GitHub's 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 include a suggestion to improve it. + +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). + +### When submitting an issue + +**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) +* Add logs or screen shots when possible +* 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. From 46bbeabcde4a2b7cdfcec29da4bde51ceb45a97a Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Wed, 27 Feb 2013 22:17:46 +0100 Subject: [PATCH 019/113] Link to new contributing file and the requirements doc. --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2b8b8dfc18..b8ae9d3845 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## GitLab is a self hosted Git management software. +## GitLab is a self hosted Git management software. Check out [gitlab.org](http://gitlab.org) @@ -13,10 +13,10 @@ With GitLab you can: ### Code status: -* master: travis-ci.org +* master: travis-ci.org [![build status](https://secure.travis-ci.org/gitlabhq/gitlabhq.png)](https://travis-ci.org/gitlabhq/gitlabhq) -* master: ci.gitlab.org +* master: ci.gitlab.org [![CI](http://ci.gitlab.org/projects/1/status?ref=master)](http://ci.gitlab.org/projects/1?ref=master) * [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/gitlabhq/gitlabhq) @@ -37,6 +37,8 @@ With GitLab you can: * gitlab-shell * redis +More details are in the [requirements doc](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/requirements.md) + ### Install Checkout [wiki](https://github.com/gitlabhq/gitlabhq/wiki) pages for installation information, migration, etc. @@ -45,6 +47,6 @@ Checkout [wiki](https://github.com/gitlabhq/gitlabhq/wiki) pages for installatio ### [Contact](http://gitlab.org/contact/) -### [Issue Submission Guide](https://github.com/gitlabhq/gitlabhq/wiki/Issue-Submission-Guide) +### [Contributing Guide](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) ### [Developer Guide](https://github.com/gitlabhq/gitlabhq/wiki/Developer-Guide) From c13f9adab8199d35b6f04e87be767655002a7725 Mon Sep 17 00:00:00 2001 From: David Date: Wed, 27 Feb 2013 17:09:14 -0500 Subject: [PATCH 020/113] Update doc/install/databases.md Remove prompt $ from code line for uniformity --- doc/install/databases.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/install/databases.md b/doc/install/databases.md index 61882602bb..2c4fb9dbff 100644 --- a/doc/install/databases.md +++ b/doc/install/databases.md @@ -12,7 +12,7 @@ GitLab supports the following databases: sudo apt-get install -y mysql-server mysql-client libmysqlclient-dev # Login to MySQL - $ mysql -u root -p + mysql -u root -p # Create a user for GitLab. (change $password to a real password) mysql> CREATE USER 'gitlab'@'localhost' IDENTIFIED BY '$password'; From 38fce3deb03904fdfcf2fe512b094d49e22fe61c Mon Sep 17 00:00:00 2001 From: Sato Hiroyuki Date: Wed, 27 Feb 2013 22:37:38 +0900 Subject: [PATCH 021/113] It improves detecting an overlap of a line --- app/models/graph/commit.rb | 14 +++++++++++--- app/models/graph/json_builder.rb | 32 ++++++++++++++++++++------------ 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/app/models/graph/commit.rb b/app/models/graph/commit.rb index 2b09d53902..742a73b38b 100644 --- a/app/models/graph/commit.rb +++ b/app/models/graph/commit.rb @@ -4,12 +4,12 @@ module Graph class Commit include ActionView::Helpers::TagHelper - attr_accessor :time, :space, :refs, :parent_spaces + attr_accessor :time, :spaces, :refs, :parent_spaces def initialize(commit) @_commit = commit @time = -1 - @space = 0 + @spaces = [] @parent_spaces = [] end @@ -27,7 +27,7 @@ module Graph email: author.email } h[:time] = time - h[:space] = space + h[:space] = spaces.first h[:parent_spaces] = parent_spaces h[:refs] = refs.collect{|r|r.name}.join(" ") unless refs.nil? h[:id] = sha @@ -46,5 +46,13 @@ module Graph @refs = ref_cache[@_commit.id] if ref_cache.include?(@_commit.id) @refs ||= [] end + + def space + if @spaces.size > 0 + @spaces.first + else + 0 + end + end end end diff --git a/app/models/graph/json_builder.rb b/app/models/graph/json_builder.rb index 2ba05405e2..5237ccfe08 100644 --- a/app/models/graph/json_builder.rb +++ b/app/models/graph/json_builder.rb @@ -151,7 +151,7 @@ module Graph def find_free_parent_space(range, space_base, space_step, space_default, times) if is_overlap?(range, times, space_default) then - find_free_space(range, space_base, space_step, space_default) + find_free_space(range, space_step, space_base, space_default) else space_default end @@ -161,7 +161,7 @@ module Graph range.each do |i| if i != range.first && i != range.last && - times[i].space == overlap_space then + times[i].spaces.include?(overlap_space) then return true; end @@ -179,9 +179,24 @@ module Graph if leaves.empty? return end + + time_range = leaves.last.time..leaves.first.time + space = find_free_space(time_range, 2) + leaves.each do |l| + l.spaces << space + # Also add space to parent + l.parents.each do |p| + if map.include?(p.id) + parent = map[p.id] + if parent.space > 0 + parent.spaces << space + end + end + end + end + # and mark it as reserved min_time = leaves.last.time - max_space = 1 parents = leaves.last.parents.collect parents.each do |p| if map.include? p.id @@ -189,21 +204,14 @@ module Graph if parent.time < min_time min_time = parent.time end - if max_space < parent.space then - max_space = parent.space - end end end + if parent_time.nil? max_time = leaves.first.time else max_time = parent_time - 1 end - - time_range = leaves.last.time..leaves.first.time - space = find_free_space(time_range, max_space, 2) - leaves.each{|l| l.space = space} - mark_reserved(min_time..max_time, space) # Visit branching chains @@ -221,7 +229,7 @@ module Graph end end - def find_free_space(time_range, space_base, space_step, space_default = 1) + def find_free_space(time_range, space_step, space_base = 1, space_default = 1) reserved = [] for day in time_range reserved += @_reserved[day] From 14c2a37da218ca5ca23918d4787113644e1fd1cc Mon Sep 17 00:00:00 2001 From: Sato Hiroyuki Date: Wed, 27 Feb 2013 22:55:37 +0900 Subject: [PATCH 022/113] A tip is made slanting. --- app/assets/javascripts/branch-graph.js | 36 ++++++++++++++++++-------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/app/assets/javascripts/branch-graph.js b/app/assets/javascripts/branch-graph.js index fb22953acd..231b1cc674 100644 --- a/app/assets/javascripts/branch-graph.js +++ b/app/assets/javascripts/branch-graph.js @@ -132,17 +132,31 @@ }); } else if (c.space < this.commits[i].space) { - r.path([ - "M", x - 5, y, - "l-5-2,0,4,5,-2", - "L", x - 10, y, - "L", x - 15, psy, - "L", cx + 5, psy, - "L", cx, cy]) - .attr({ - stroke: this.colors[this.commits[i].space], - "stroke-width": 2 - }); + if (y == psy) { + r.path([ + "M", x - 5, y, + "l-5,-2,0,4,5,-2", + "L", x - 10, y, + "L", x - 15, psy, + "L", cx + 5, psy, + "L", cx, cy]) + .attr({ + stroke: this.colors[this.commits[i].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, psy, + "L", cx + 5, psy, + "L", cx, cy]) + .attr({ + stroke: this.colors[this.commits[i].space], + "stroke-width": 2 + }); + } } else { r.path([ "M", x - 3, y + 6, From 00d0e57e859454c62084893a74fad71c26d5c50c Mon Sep 17 00:00:00 2001 From: Sato Hiroyuki Date: Wed, 27 Feb 2013 23:43:33 +0900 Subject: [PATCH 023/113] Commits are arranged below their first parent. --- app/models/graph/json_builder.rb | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/app/models/graph/json_builder.rb b/app/models/graph/json_builder.rb index 5237ccfe08..013d15fb75 100644 --- a/app/models/graph/json_builder.rb +++ b/app/models/graph/json_builder.rb @@ -181,7 +181,8 @@ module Graph end time_range = leaves.last.time..leaves.first.time - space = find_free_space(time_range, 2) + space_base = get_space_base(leaves, map) + space = find_free_space(time_range, 2, space_base) leaves.each do |l| l.spaces << space # Also add space to parent @@ -223,13 +224,29 @@ module Graph end end + def get_space_base(leaves, map) + space_base = 1 + if leaves.last.parents.size > 0 + first_parent = leaves.last.parents.first + if map.include?(first_parent.id) + first_p = map[first_parent.id] + if first_p.space > 0 + space_base = first_p.space + end + end + end + space_base + end + def mark_reserved(time_range, space) for day in time_range @_reserved[day].push(space) end end - def find_free_space(time_range, space_step, space_base = 1, space_default = 1) + def find_free_space(time_range, space_step, space_base = 1, space_default = nil) + space_default ||= space_base + reserved = [] for day in time_range reserved += @_reserved[day] From 2a687dd5625c29e48b7b64a388a828c358d45215 Mon Sep 17 00:00:00 2001 From: Sato Hiroyuki Date: Thu, 28 Feb 2013 14:56:27 +0900 Subject: [PATCH 024/113] Show gravatar icon on tooltip. --- app/assets/javascripts/branch-graph.js | 7 ++++--- app/controllers/graph_controller.rb | 4 ++++ app/models/graph/commit.rb | 7 ++++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/branch-graph.js b/app/assets/javascripts/branch-graph.js index 231b1cc674..137e87de37 100644 --- a/app/assets/javascripts/branch-graph.js +++ b/app/assets/javascripts/branch-graph.js @@ -320,15 +320,16 @@ }(this); Raphael.fn.commitTooltip = function(x, y, commit){ - var nameText, idText, messageText + var icon, nameText, idText, messageText , boxWidth = 300 , boxHeight = 200; - nameText = this.text(x, y + 10, commit.author.name); + icon = this.image(commit.author.icon, x, y, 20, 20); + nameText = this.text(x + 25, y + 10, commit.author.name); idText = this.text(x, y + 35, commit.id); messageText = this.text(x, y + 50, commit.message); - textSet = this.set(nameText, idText, messageText).attr({ + textSet = this.set(icon, nameText, idText, messageText).attr({ "text-anchor": "start", "font": "12px Monaco, monospace" }); diff --git a/app/controllers/graph_controller.rb b/app/controllers/graph_controller.rb index 8aadcfef8c..33cb2d2dcb 100644 --- a/app/controllers/graph_controller.rb +++ b/app/controllers/graph_controller.rb @@ -1,5 +1,6 @@ class GraphController < ProjectResourceController include ExtractsPath + include ApplicationHelper # Authorize before_filter :authorize_read_project! @@ -21,6 +22,9 @@ class GraphController < ProjectResourceController format.html format.json do graph = Graph::JsonBuilder.new(project, @ref, @commit) + graph.commits.each do |c| + c.icon = gravatar_icon(c.author.email) + end render :json => graph.to_json end end diff --git a/app/models/graph/commit.rb b/app/models/graph/commit.rb index 742a73b38b..8ed61f4b5a 100644 --- a/app/models/graph/commit.rb +++ b/app/models/graph/commit.rb @@ -4,7 +4,7 @@ module Graph class Commit include ActionView::Helpers::TagHelper - attr_accessor :time, :spaces, :refs, :parent_spaces + attr_accessor :time, :spaces, :refs, :parent_spaces, :icon def initialize(commit) @_commit = commit @@ -23,8 +23,9 @@ module Graph [p.id,0,0] end h[:author] = { - name: author.name, - email: author.email + name: author.name, + email: author.email, + icon: icon } h[:time] = time h[:space] = spaces.first From 51b547f842538234eb97ddfcee5c13a6e85f9287 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Feb 2013 09:25:23 +0200 Subject: [PATCH 025/113] Commenting a failing test --- features/project/merge_requests.feature | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/features/project/merge_requests.feature b/features/project/merge_requests.feature index 5b8becbb6c..b1f95efbb6 100644 --- a/features/project/merge_requests.feature +++ b/features/project/merge_requests.feature @@ -34,11 +34,11 @@ Feature: Project Merge Requests And I submit new merge request "Wiki Feature" Then I should see merge request "Wiki Feature" - @javascript - Scenario: I comment on a merge request - Given I visit merge request page "Bug NS-04" - And I leave a comment like "XML attached" - Then I should see comment "XML attached" + #@javascript + #Scenario: I comment on a merge request + #Given I visit merge request page "Bug NS-04" + #And I leave a comment like "XML attached" + #Then I should see comment "XML attached" @javascript Scenario: I comment on a merge request diff From e6b5f4ade9d7dc5aae1bcb41be4fc74cf751fb92 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Feb 2013 09:43:48 +0200 Subject: [PATCH 026/113] refactor finders in spianch:merge_request.feature --- features/project/merge_requests.feature | 10 +++--- .../steps/project/project_merge_requests.rb | 34 +++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/features/project/merge_requests.feature b/features/project/merge_requests.feature index b1f95efbb6..5b8becbb6c 100644 --- a/features/project/merge_requests.feature +++ b/features/project/merge_requests.feature @@ -34,11 +34,11 @@ Feature: Project Merge Requests And I submit new merge request "Wiki Feature" Then I should see merge request "Wiki Feature" - #@javascript - #Scenario: I comment on a merge request - #Given I visit merge request page "Bug NS-04" - #And I leave a comment like "XML attached" - #Then I should see comment "XML attached" + @javascript + Scenario: I comment on a merge request + Given I visit merge request page "Bug NS-04" + And I leave a comment like "XML attached" + Then I should see comment "XML attached" @javascript Scenario: I comment on a merge request diff diff --git a/features/steps/project/project_merge_requests.rb b/features/steps/project/project_merge_requests.rb index ff95a47d4c..09ce6b720d 100644 --- a/features/steps/project/project_merge_requests.rb +++ b/features/steps/project/project_merge_requests.rb @@ -25,8 +25,8 @@ class ProjectMergeRequests < Spinach::FeatureSteps end Then 'I should see closed merge request "Bug NS-04"' do - mr = MergeRequest.find_by_title("Bug NS-04") - mr.closed?.should be_true + merge_request = MergeRequest.find_by_title!("Bug NS-04") + merge_request.closed?.should be_true page.should have_content "Closed by" end @@ -63,7 +63,6 @@ class ProjectMergeRequests < Spinach::FeatureSteps end And 'project "Shop" have "Bug NS-04" open merge request' do - project = Project.find_by_name("Shop") create(:merge_request, title: "Bug NS-04", project: project, @@ -71,7 +70,6 @@ class ProjectMergeRequests < Spinach::FeatureSteps end And 'project "Shop" have "Bug NS-05" open merge request with diffs inside' do - project = Project.find_by_name("Shop") create(:merge_request_with_diffs, title: "Bug NS-05", project: project, @@ -79,7 +77,6 @@ class ProjectMergeRequests < Spinach::FeatureSteps end And 'project "Shop" have "Feature NS-03" closed merge request' do - project = Project.find_by_name("Shop") create(:closed_merge_request, title: "Feature NS-03", project: project, @@ -87,18 +84,16 @@ class ProjectMergeRequests < Spinach::FeatureSteps end And 'I switch to the diff tab' do - mr = MergeRequest.find_by_title("Bug NS-05") - visit diffs_project_merge_request_path(mr.project, mr) + visit diffs_project_merge_request_path(merge_request.project, merge_request) end And 'I switch to the merge request\'s comments tab' do - mr = MergeRequest.find_by_title("Bug NS-05") - visit project_merge_request_path(mr.project, mr) + visit project_merge_request_path(merge_request.project, merge_request) end And 'I click on the first commit in the merge request' do - mr = MergeRequest.find_by_title("Bug NS-05") - click_link mr.commits.first.short_id(8) + + click_link merge_request.commits.first.short_id(8) end And 'I leave a comment on the diff page' do @@ -121,8 +116,7 @@ class ProjectMergeRequests < Spinach::FeatureSteps end Then 'I should see a discussion has started on line 185' do - mr = MergeRequest.find_by_title("Bug NS-05") - first_commit = mr.commits.first + first_commit = merge_request.commits.first first_diff = first_commit.diffs.first page.should have_content "#{current_user.name} started a discussion on this merge request diff" page.should have_content "#{first_diff.b_path}:L185" @@ -130,8 +124,7 @@ class ProjectMergeRequests < Spinach::FeatureSteps end Then 'I should see a discussion has started on commit bcf03b5de6c:L185' do - mr = MergeRequest.find_by_title("Bug NS-05") - first_commit = mr.commits.first + first_commit = merge_request.commits.first first_diff = first_commit.diffs.first page.should have_content "#{current_user.name} started a discussion on commit" page.should have_content first_commit.short_id(8) @@ -140,12 +133,19 @@ class ProjectMergeRequests < Spinach::FeatureSteps end Then 'I should see a discussion has started on commit bcf03b5de6c' do - mr = MergeRequest.find_by_title("Bug NS-05") - first_commit = mr.st_commits.first + first_commit = merge_request.st_commits.first first_diff = first_commit.diffs.first page.should have_content "#{current_user.name} started a discussion on commit bcf03b5de6c" page.should have_content first_commit.short_id(8) page.should have_content "One comment to rule them all" page.should have_content "#{first_diff.b_path}:L185" end + + def project + @project ||= Project.find_by_name!("Shop") + end + + def merge_request + @merge_request ||= MergeRequest.find_by_title!("Bug NS-05") + end end From 54d95f5897235009f670a8de262333fe528875cf Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Feb 2013 11:06:52 +0200 Subject: [PATCH 027/113] Restyle flash message. Not it does not overflow head panel --- app/assets/javascripts/main.js.coffee | 8 +++--- app/assets/stylesheets/common.scss | 28 +++++++------------- app/assets/stylesheets/sections/login.scss | 4 +-- app/views/layouts/_flash.html.haml | 11 +++++--- app/views/layouts/admin.html.haml | 2 +- app/views/layouts/application.html.haml | 2 +- app/views/layouts/devise.html.haml | 5 +++- app/views/layouts/errors.html.haml | 2 +- app/views/layouts/group.html.haml | 2 +- app/views/layouts/profile.html.haml | 2 +- app/views/layouts/project_resource.html.haml | 2 +- app/views/layouts/user_team.html.haml | 2 +- 12 files changed, 34 insertions(+), 36 deletions(-) diff --git a/app/assets/javascripts/main.js.coffee b/app/assets/javascripts/main.js.coffee index d789f54a4e..d707657d4b 100644 --- a/app/assets/javascripts/main.js.coffee +++ b/app/assets/javascripts/main.js.coffee @@ -54,10 +54,10 @@ $ -> $(@).parents('form').submit() # Flash - if (flash = $("#flash-container")).length > 0 - flash.click -> $(@).slideUp("slow") - flash.slideDown "slow" - setTimeout (-> flash.slideUp("slow")), 3000 + if (flash = $(".flash-container")).length > 0 + flash.click -> $(@).fadeOut() + flash.show() + setTimeout (-> flash.fadeOut()), 3000 # Disable form buttons while a form is submitting $('body').on 'ajax:complete, ajax:beforeSend, submit', 'form', (e) -> diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss index 7ac8c2dd91..ead27922cc 100644 --- a/app/assets/stylesheets/common.scss +++ b/app/assets/stylesheets/common.scss @@ -67,27 +67,17 @@ table a code { } /** FLASH message **/ -#flash-container { - height: 50px; - position: fixed; - z-index: 10001; - top: 0px; - width: 100%; - margin-bottom: 15px; - overflow: hidden; - background: white; - cursor: pointer; - border-bottom: 1px solid #ccc; - text-align: center; +.flash-container { display: none; + .alert { + cursor: pointer; + margin: 0; + text-align: center; + border-radius: 0; - h4 { - color: #666; - font-size: 18px; - line-height: 38px; - padding-top: 5px; - margin: 2px; - font-weight: normal; + span { + font-size: 14px; + } } } diff --git a/app/assets/stylesheets/sections/login.scss b/app/assets/stylesheets/sections/login.scss index 89b8f1c005..e3fe0b436c 100644 --- a/app/assets/stylesheets/sections/login.scss +++ b/app/assets/stylesheets/sections/login.scss @@ -1,7 +1,7 @@ /* Login Page */ body.login-page{ - padding-top: 7%; - background: #666; + background: #EEE; + .container .content { padding-top: 5%; } } .login-box{ diff --git a/app/views/layouts/_flash.html.haml b/app/views/layouts/_flash.html.haml index 9961ce8dd3..a3bed593e1 100644 --- a/app/views/layouts/_flash.html.haml +++ b/app/views/layouts/_flash.html.haml @@ -1,3 +1,8 @@ -- if text = alert || notice - #flash-container - %h4= text +.flash-container + - if alert + .alert + %span= alert + + - elsif notice + .alert.alert-info + %span= notice diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml index a01886cdab..00a08e6131 100644 --- a/app/views/layouts/admin.html.haml +++ b/app/views/layouts/admin.html.haml @@ -2,8 +2,8 @@ %html{ lang: "en"} = render "layouts/head", title: "Admin area" %body{class: "#{app_theme} admin"} - = render "layouts/flash" = render "layouts/head_panel", title: "Admin area" + = render "layouts/flash" .container %ul.main_menu = nav_link(controller: :dashboard, html_options: {class: 'home'}) do diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 7ee44238d1..90c2653438 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -2,8 +2,8 @@ %html{ lang: "en"} = render "layouts/head", title: "Dashboard" %body{class: "#{app_theme} application"} - = render "layouts/flash" = render "layouts/head_panel", title: "Dashboard" + = render "layouts/flash" .container %ul.main_menu = nav_link(path: 'dashboard#show', html_options: {class: 'home'}) do diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml index 36c6b4c6c3..e790b22c9d 100644 --- a/app/views/layouts/devise.html.haml +++ b/app/views/layouts/devise.html.haml @@ -3,4 +3,7 @@ = render "layouts/head" %body.ui_basic.login-page = render "layouts/flash" - .container= yield + .container + .content + %center + = yield diff --git a/app/views/layouts/errors.html.haml b/app/views/layouts/errors.html.haml index 3554d88f10..b9395873c3 100644 --- a/app/views/layouts/errors.html.haml +++ b/app/views/layouts/errors.html.haml @@ -2,8 +2,8 @@ %html{ lang: "en"} = render "layouts/head", title: "Error" %body{class: "#{app_theme} application"} - = render "layouts/flash" = render "layouts/head_panel", title: "" + = render "layouts/flash" .container .content %center.padded.prepend-top-20 diff --git a/app/views/layouts/group.html.haml b/app/views/layouts/group.html.haml index 9057ad50ce..2c144de49b 100644 --- a/app/views/layouts/group.html.haml +++ b/app/views/layouts/group.html.haml @@ -2,8 +2,8 @@ %html{ lang: "en"} = render "layouts/head", title: "#{@group.name}" %body{class: "#{app_theme} application"} - = render "layouts/flash" = render "layouts/head_panel", title: "group: #{@group.name}" + = render "layouts/flash" .container %ul.main_menu = nav_link(path: 'groups#show', html_options: {class: 'home'}) do diff --git a/app/views/layouts/profile.html.haml b/app/views/layouts/profile.html.haml index 57f250c775..611063e8c9 100644 --- a/app/views/layouts/profile.html.haml +++ b/app/views/layouts/profile.html.haml @@ -2,8 +2,8 @@ %html{ lang: "en"} = render "layouts/head", title: "Profile" %body{class: "#{app_theme} profile"} - = render "layouts/flash" = render "layouts/head_panel", title: "Profile" + = render "layouts/flash" .container %ul.main_menu = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do diff --git a/app/views/layouts/project_resource.html.haml b/app/views/layouts/project_resource.html.haml index 13fb8637bf..3b68921587 100644 --- a/app/views/layouts/project_resource.html.haml +++ b/app/views/layouts/project_resource.html.haml @@ -2,8 +2,8 @@ %html{ lang: "en"} = render "layouts/head", title: @project.name_with_namespace %body{class: "#{app_theme} project"} - = render "layouts/flash" = render "layouts/head_panel", title: project_title(@project) + = render "layouts/flash" - if can?(current_user, :download_code, @project) = render 'shared/no_ssh' diff --git a/app/views/layouts/user_team.html.haml b/app/views/layouts/user_team.html.haml index 19bbc373f4..e5e08aab13 100644 --- a/app/views/layouts/user_team.html.haml +++ b/app/views/layouts/user_team.html.haml @@ -2,8 +2,8 @@ %html{ lang: "en"} = render "layouts/head", title: "#{@team.name}" %body{class: "#{app_theme} application"} - = render "layouts/flash" = render "layouts/head_panel", title: "team: #{@team.name}" + = render "layouts/flash" .container %ul.main_menu = nav_link(path: 'teams#show', html_options: {class: 'home'}) do From fa6bf2c0f5d8a87b0fa0cd32daaa4a55d1d0178c Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Feb 2013 12:08:25 +0200 Subject: [PATCH 028/113] remove unnecessary center tag in devise layout --- app/views/layouts/devise.html.haml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml index e790b22c9d..a9758f19d3 100644 --- a/app/views/layouts/devise.html.haml +++ b/app/views/layouts/devise.html.haml @@ -5,5 +5,4 @@ = render "layouts/flash" .container .content - %center - = yield + = yield From 8f621c9e064afe1465728143d71f0658053d55ad Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Fri, 8 Feb 2013 16:47:24 +0400 Subject: [PATCH 029/113] Enumerize gem added --- Gemfile | 3 +++ Gemfile.lock | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Gemfile b/Gemfile index 0eba7eb2f6..46ad7e8059 100644 --- a/Gemfile +++ b/Gemfile @@ -45,6 +45,9 @@ gem "grape", "~> 0.2.1" # based on human-friendly examples gem "stamp" +# Enumeration fields +gem 'enumerize' + # Pagination gem "kaminari", "~> 0.14.1" diff --git a/Gemfile.lock b/Gemfile.lock index 3ca39aeae2..311e757cd7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -144,6 +144,8 @@ GEM email_spec (1.4.0) launchy (~> 2.1) mail (~> 2.2) + enumerize (0.5.1) + activesupport (>= 3.2) erubis (2.7.0) escape_utils (0.2.4) eventmachine (1.0.0) @@ -469,6 +471,7 @@ DEPENDENCIES devise (~> 2.1.0) draper (~> 0.18.0) email_spec + enumerize factory_girl_rails ffaker font-awesome-sass-rails (~> 3.0.0) From e6d2e5696186cc81b7d9a12af25e00528ca2cc30 Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Wed, 23 Jan 2013 18:13:28 +0400 Subject: [PATCH 030/113] Issue tracker field added to projects --- app/helpers/issues_helper.rb | 27 ++ app/models/project.rb | 6 +- app/views/projects/_form.html.haml | 4 + config/gitlab.yml.example | 6 + ...123114545_add_issues_tracker_to_project.rb | 5 + db/schema.rb | 312 ------------------ lib/gitlab/markdown.rb | 7 +- spec/helpers/gitlab_markdown_helper_spec.rb | 1 + spec/lib/issues_tracker_spec.rb | 16 + 9 files changed, 69 insertions(+), 315 deletions(-) create mode 100644 db/migrate/20130123114545_add_issues_tracker_to_project.rb delete mode 100644 db/schema.rb create mode 100644 spec/lib/issues_tracker_spec.rb diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index ed7e3e869c..030f9af369 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -40,4 +40,31 @@ module IssuesHelper def issues_active_milestones @project.milestones.active.order("id desc").all end + + def url_for_issue(issue_id) + if @project.issues_tracker == Project.issues_tracker.default_value + url = project_issue_url project_id: @project, id: issue_id + else + url = Settings[:issues_tracker][@project.issues_tracker]["issues_url"] + url.gsub(':id', issue_id.to_s).gsub(':project_id', @project.id.to_s) + end + end + + def title_for_issue(issue_id) + if issue = @project.issues.where(id: issue_id).first + issue.title + else + "" + end + end + + def issue_exists?(issue_id) + return false if @project.nil? + + if @project.issues_tracker == Project.issues_tracker.default_value + @project.issues.where(id: issue_id).first.present? + else + true + end + end end diff --git a/app/models/project.rb b/app/models/project.rb index 6ff2a3698d..9ba3080cb1 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -11,6 +11,7 @@ # creator_id :integer # default_branch :string(255) # issues_enabled :boolean default(TRUE), not null +# issues_tracker :string not null # wall_enabled :boolean default(TRUE), not null # merge_requests_enabled :boolean default(TRUE), not null # wiki_enabled :boolean default(TRUE), not null @@ -22,10 +23,11 @@ require "grit" class Project < ActiveRecord::Base include Gitolited + extend Enumerize class TransferError < StandardError; end - attr_accessible :name, :path, :description, :default_branch, + attr_accessible :name, :path, :description, :default_branch, :issues_tracker, :issues_enabled, :wall_enabled, :merge_requests_enabled, :wiki_enabled, :public, :import_url, as: [:default, :admin] @@ -93,6 +95,8 @@ class Project < ActiveRecord::Base scope :joined, ->(user) { where("namespace_id != ?", user.namespace_id) } scope :public_only, -> { where(public: true) } + enumerize :issues_tracker, :in => (Settings[:issues_tracker].keys).append(:gitlab), :default => :gitlab + class << self def abandoned project_ids = Event.select('max(created_at) as latest_date, project_id'). diff --git a/app/views/projects/_form.html.haml b/app/views/projects/_form.html.haml index 0336654dc6..7072d78d3e 100644 --- a/app/views/projects/_form.html.haml +++ b/app/views/projects/_form.html.haml @@ -24,6 +24,10 @@ = f.check_box :issues_enabled %span.descr Lightweight issue tracking system for this project + .control-group + = f.label :issues_tracker, "Issues tracker", class: 'control-label' + .input= f.select(:issues_tracker, Project.issues_tracker.values, {}, { disabled: !@project.issues_enabled }) + .control-group = f.label :merge_requests_enabled, "Merge Requests", class: 'control-label' .controls diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index 62761c80cb..0d1d5818b2 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -7,6 +7,7 @@ # 2. Replace gitlab -> host with your domain # 3. Replace gitlab -> email_from +<<<<<<< HEAD production: &base # # 1. GitLab app settings @@ -37,6 +38,11 @@ production: &base # signup_enabled: true # default: false - Account passwords are not sent via the email if signup is enabled. # username_changing_enabled: false # default: true - User can change her username/namespace + ## Available issues trackers + issues_tracker: + redmine: + issues_url: "http://redmine.sample/issues/:id" + ## Gravatar gravatar: enabled: true # Use user avatar images from Gravatar.com (default: true) diff --git a/db/migrate/20130123114545_add_issues_tracker_to_project.rb b/db/migrate/20130123114545_add_issues_tracker_to_project.rb new file mode 100644 index 0000000000..288d0f07c9 --- /dev/null +++ b/db/migrate/20130123114545_add_issues_tracker_to_project.rb @@ -0,0 +1,5 @@ +class AddIssuesTrackerToProject < ActiveRecord::Migration + def change + add_column :projects, :issues_tracker, :string, default: :gitlab, null: false + end +end diff --git a/db/schema.rb b/db/schema.rb deleted file mode 100644 index 74d5f9a360..0000000000 --- a/db/schema.rb +++ /dev/null @@ -1,312 +0,0 @@ -# encoding: UTF-8 -# This file is auto-generated from the current state of the database. Instead -# of editing this file, please use the migrations feature of Active Record to -# incrementally modify your database, and then regenerate this schema definition. -# -# Note that this schema.rb definition is the authoritative source for your -# database schema. If you need to create the application database on another -# system, you should be using db:schema:load, not running all the migrations -# from scratch. The latter is a flawed and unsustainable approach (the more migrations -# you'll amass, the slower it'll run and the greater likelihood for issues). -# -# It's strongly recommended to check this file into your version control system. - -ActiveRecord::Schema.define(:version => 20130220133245) do - - create_table "events", :force => true do |t| - t.string "target_type" - t.integer "target_id" - t.string "title" - t.text "data" - t.integer "project_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "action" - t.integer "author_id" - end - - add_index "events", ["action"], :name => "index_events_on_action" - add_index "events", ["author_id"], :name => "index_events_on_author_id" - add_index "events", ["created_at"], :name => "index_events_on_created_at" - add_index "events", ["project_id"], :name => "index_events_on_project_id" - add_index "events", ["target_id"], :name => "index_events_on_target_id" - add_index "events", ["target_type"], :name => "index_events_on_target_type" - - create_table "issues", :force => true do |t| - t.string "title" - t.integer "assignee_id" - t.integer "author_id" - t.integer "project_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "position", :default => 0 - t.string "branch_name" - t.text "description" - t.integer "milestone_id" - t.string "state" - end - - add_index "issues", ["assignee_id"], :name => "index_issues_on_assignee_id" - add_index "issues", ["author_id"], :name => "index_issues_on_author_id" - add_index "issues", ["created_at"], :name => "index_issues_on_created_at" - add_index "issues", ["milestone_id"], :name => "index_issues_on_milestone_id" - add_index "issues", ["project_id"], :name => "index_issues_on_project_id" - add_index "issues", ["title"], :name => "index_issues_on_title" - - create_table "keys", :force => true do |t| - t.integer "user_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.text "key" - t.string "title" - t.string "identifier" - t.integer "project_id" - end - - add_index "keys", ["identifier"], :name => "index_keys_on_identifier" - add_index "keys", ["project_id"], :name => "index_keys_on_project_id" - add_index "keys", ["user_id"], :name => "index_keys_on_user_id" - - create_table "merge_requests", :force => true do |t| - t.string "target_branch", :null => false - t.string "source_branch", :null => false - t.integer "project_id", :null => false - t.integer "author_id" - t.integer "assignee_id" - t.string "title" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.text "st_commits", :limit => 2147483647 - t.text "st_diffs", :limit => 2147483647 - t.integer "milestone_id" - t.string "state" - t.string "merge_status" - end - - add_index "merge_requests", ["assignee_id"], :name => "index_merge_requests_on_assignee_id" - add_index "merge_requests", ["author_id"], :name => "index_merge_requests_on_author_id" - add_index "merge_requests", ["created_at"], :name => "index_merge_requests_on_created_at" - add_index "merge_requests", ["milestone_id"], :name => "index_merge_requests_on_milestone_id" - add_index "merge_requests", ["project_id"], :name => "index_merge_requests_on_project_id" - add_index "merge_requests", ["source_branch"], :name => "index_merge_requests_on_source_branch" - add_index "merge_requests", ["target_branch"], :name => "index_merge_requests_on_target_branch" - add_index "merge_requests", ["title"], :name => "index_merge_requests_on_title" - - create_table "milestones", :force => true do |t| - t.string "title", :null => false - t.integer "project_id", :null => false - t.text "description" - t.date "due_date" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "state" - end - - add_index "milestones", ["due_date"], :name => "index_milestones_on_due_date" - add_index "milestones", ["project_id"], :name => "index_milestones_on_project_id" - - create_table "namespaces", :force => true do |t| - t.string "name", :null => false - t.string "path", :null => false - t.integer "owner_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "type" - end - - add_index "namespaces", ["name"], :name => "index_namespaces_on_name" - add_index "namespaces", ["owner_id"], :name => "index_namespaces_on_owner_id" - add_index "namespaces", ["path"], :name => "index_namespaces_on_path" - add_index "namespaces", ["type"], :name => "index_namespaces_on_type" - - create_table "notes", :force => true do |t| - t.text "note" - t.string "noteable_type" - t.integer "author_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "project_id" - t.string "attachment" - t.string "line_code" - t.string "commit_id" - t.integer "noteable_id" - end - - add_index "notes", ["commit_id"], :name => "index_notes_on_commit_id" - add_index "notes", ["created_at"], :name => "index_notes_on_created_at" - add_index "notes", ["noteable_type"], :name => "index_notes_on_noteable_type" - add_index "notes", ["project_id", "noteable_type"], :name => "index_notes_on_project_id_and_noteable_type" - add_index "notes", ["project_id"], :name => "index_notes_on_project_id" - - create_table "projects", :force => true do |t| - t.string "name" - t.string "path" - t.text "description" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "creator_id" - t.string "default_branch" - t.boolean "issues_enabled", :default => true, :null => false - t.boolean "wall_enabled", :default => true, :null => false - t.boolean "merge_requests_enabled", :default => true, :null => false - t.boolean "wiki_enabled", :default => true, :null => false - t.integer "namespace_id" - t.boolean "public", :default => false, :null => false - end - - add_index "projects", ["creator_id"], :name => "index_projects_on_owner_id" - add_index "projects", ["namespace_id"], :name => "index_projects_on_namespace_id" - - create_table "protected_branches", :force => true do |t| - t.integer "project_id", :null => false - t.string "name", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "services", :force => true do |t| - t.string "type" - t.string "title" - t.string "token" - t.integer "project_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.boolean "active", :default => false, :null => false - t.string "project_url" - end - - add_index "services", ["project_id"], :name => "index_services_on_project_id" - - create_table "snippets", :force => true do |t| - t.string "title" - t.text "content" - t.integer "author_id", :null => false - t.integer "project_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "file_name" - t.datetime "expires_at" - end - - add_index "snippets", ["created_at"], :name => "index_snippets_on_created_at" - add_index "snippets", ["expires_at"], :name => "index_snippets_on_expires_at" - add_index "snippets", ["project_id"], :name => "index_snippets_on_project_id" - - create_table "taggings", :force => true do |t| - t.integer "tag_id" - t.integer "taggable_id" - t.string "taggable_type" - t.integer "tagger_id" - t.string "tagger_type" - t.string "context" - t.datetime "created_at" - end - - add_index "taggings", ["tag_id"], :name => "index_taggings_on_tag_id" - add_index "taggings", ["taggable_id", "taggable_type", "context"], :name => "index_taggings_on_taggable_id_and_taggable_type_and_context" - - create_table "tags", :force => true do |t| - t.string "name" - end - - create_table "user_team_project_relationships", :force => true do |t| - t.integer "project_id" - t.integer "user_team_id" - t.integer "greatest_access" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "user_team_user_relationships", :force => true do |t| - t.integer "user_id" - t.integer "user_team_id" - t.boolean "group_admin" - t.integer "permission" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "user_teams", :force => true do |t| - t.string "name" - t.string "path" - t.integer "owner_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "users", :force => true do |t| - t.string "email", :default => "", :null => false - t.string "encrypted_password", :default => "", :null => false - t.string "reset_password_token" - t.datetime "reset_password_sent_at" - t.datetime "remember_created_at" - t.integer "sign_in_count", :default => 0 - t.datetime "current_sign_in_at" - t.datetime "last_sign_in_at" - t.string "current_sign_in_ip" - t.string "last_sign_in_ip" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "name" - t.boolean "admin", :default => false, :null => false - t.integer "projects_limit", :default => 10 - t.string "skype", :default => "", :null => false - t.string "linkedin", :default => "", :null => false - t.string "twitter", :default => "", :null => false - t.string "authentication_token" - t.boolean "dark_scheme", :default => false, :null => false - t.integer "theme_id", :default => 1, :null => false - t.string "bio" - t.boolean "blocked", :default => false, :null => false - t.integer "failed_attempts", :default => 0 - t.datetime "locked_at" - t.string "extern_uid" - t.string "provider" - t.string "username" - t.boolean "can_create_group", :default => true, :null => false - t.boolean "can_create_team", :default => true, :null => false - end - - add_index "users", ["admin"], :name => "index_users_on_admin" - add_index "users", ["blocked"], :name => "index_users_on_blocked" - add_index "users", ["email"], :name => "index_users_on_email", :unique => true - add_index "users", ["extern_uid", "provider"], :name => "index_users_on_extern_uid_and_provider", :unique => true - add_index "users", ["name"], :name => "index_users_on_name" - add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true - add_index "users", ["username"], :name => "index_users_on_username" - - create_table "users_projects", :force => true do |t| - t.integer "user_id", :null => false - t.integer "project_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "project_access", :default => 0, :null => false - end - - add_index "users_projects", ["project_access"], :name => "index_users_projects_on_project_access" - add_index "users_projects", ["project_id"], :name => "index_users_projects_on_project_id" - add_index "users_projects", ["user_id"], :name => "index_users_projects_on_user_id" - - create_table "web_hooks", :force => true do |t| - t.string "url" - t.integer "project_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "type", :default => "ProjectHook" - t.integer "service_id" - end - - create_table "wikis", :force => true do |t| - t.string "title" - t.text "content" - t.integer "project_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "slug" - t.integer "user_id" - end - - add_index "wikis", ["project_id"], :name => "index_wikis_on_project_id" - add_index "wikis", ["slug"], :name => "index_wikis_on_slug" - -end diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb index e7d6e3e6bd..befac46270 100644 --- a/lib/gitlab/markdown.rb +++ b/lib/gitlab/markdown.rb @@ -163,8 +163,11 @@ module Gitlab end def reference_issue(identifier) - if issue = @project.issues.where(id: identifier).first - link_to("##{identifier}", project_issue_url(@project, issue), html_options.merge(title: "Issue: #{issue.title}", class: "gfm gfm-issue #{html_options[:class]}")) + if issue_exists? identifier + url = url_for_issue(identifier) + title = title_for_issue(identifier) + + link_to("##{identifier}", url, html_options.merge(title: "Issue: #{title}", class: "gfm gfm-issue #{html_options[:class]}")) end end diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb index 1b067972c8..1f5fabfbb8 100644 --- a/spec/helpers/gitlab_markdown_helper_spec.rb +++ b/spec/helpers/gitlab_markdown_helper_spec.rb @@ -2,6 +2,7 @@ require "spec_helper" describe GitlabMarkdownHelper do include ApplicationHelper + include IssuesHelper let!(:project) { create(:project) } diff --git a/spec/lib/issues_tracker_spec.rb b/spec/lib/issues_tracker_spec.rb new file mode 100644 index 0000000000..f0bbd8839a --- /dev/null +++ b/spec/lib/issues_tracker_spec.rb @@ -0,0 +1,16 @@ +require 'spec_helper' + +describe IssuesTracker do + let(:project) { double('project') } + + before do + @project = project + project.stub(repository: stub(ref_names: ['master', 'foo/bar/baz', 'v1.0.0', 'v2.0.0'])) + project.stub(path_with_namespace: 'gitlab/gitlab-ci') + end + + it 'returns url for issue' do + ololo + end +end + From 999fc2391b012a9de66ad089a3c3eafe8c8b02d8 Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Fri, 8 Feb 2013 17:55:02 +0400 Subject: [PATCH 031/113] Issue tracker added to edit project form in admin area --- app/views/admin/projects/_form.html.haml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/views/admin/projects/_form.html.haml b/app/views/admin/projects/_form.html.haml index ebf69924a2..657a66f98e 100644 --- a/app/views/admin/projects/_form.html.haml +++ b/app/views/admin/projects/_form.html.haml @@ -31,6 +31,10 @@ = f.label :issues_enabled, "Issues" .input= f.check_box :issues_enabled + .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 :merge_requests_enabled, "Merge Requests" .input= f.check_box :merge_requests_enabled From 68a7ecdaaf0959d5087d08ef3c94bb201e6dd166 Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Mon, 11 Feb 2013 15:41:12 +0400 Subject: [PATCH 032/113] Project issue tracker functions refactored --- app/helpers/issues_helper.rb | 14 ++------------ app/models/project.rb | 12 ++++++++++++ lib/gitlab/markdown.rb | 2 +- spec/factories.rb | 4 ++++ spec/lib/issues_tracker_spec.rb | 16 ---------------- spec/models/project_spec.rb | 33 +++++++++++++++++++++++++++++++++ 6 files changed, 52 insertions(+), 29 deletions(-) delete mode 100644 spec/lib/issues_tracker_spec.rb diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index 030f9af369..0d1301d062 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -42,7 +42,7 @@ module IssuesHelper end def url_for_issue(issue_id) - if @project.issues_tracker == Project.issues_tracker.default_value + 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"] @@ -51,20 +51,10 @@ module IssuesHelper end def title_for_issue(issue_id) - if issue = @project.issues.where(id: issue_id).first + if @project.used_default_issues_tracker? && issue = @project.issues.where(id: issue_id).first issue.title else "" end end - - def issue_exists?(issue_id) - return false if @project.nil? - - if @project.issues_tracker == Project.issues_tracker.default_value - @project.issues.where(id: issue_id).first.present? - else - true - end - end end diff --git a/app/models/project.rb b/app/models/project.rb index 9ba3080cb1..612a318c96 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -205,6 +205,18 @@ class Project < ActiveRecord::Base issues.tag_counts_on(:labels) end + def issue_exists?(issue_id) + if used_default_issues_tracker? + self.issues.where(id: issue_id).first.present? + else + true + end + end + + def used_default_issues_tracker? + self.issues_tracker == Project.issues_tracker.default_value + end + def services [gitlab_ci_service].compact end diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb index befac46270..4e78d88118 100644 --- a/lib/gitlab/markdown.rb +++ b/lib/gitlab/markdown.rb @@ -163,7 +163,7 @@ module Gitlab end def reference_issue(identifier) - if issue_exists? identifier + if @project.issue_exists? identifier url = url_for_issue(identifier) title = title_for_issue(identifier) diff --git a/spec/factories.rb b/spec/factories.rb index b81984b5d5..b846f0a432 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -29,6 +29,10 @@ FactoryGirl.define do creator end + factory :redmine_project, parent: :project do + issues_tracker { "redmine" } + end + factory :group do sequence(:name) { |n| "group#{n}" } path { name.downcase.gsub(/\s/, '_') } diff --git a/spec/lib/issues_tracker_spec.rb b/spec/lib/issues_tracker_spec.rb deleted file mode 100644 index f0bbd8839a..0000000000 --- a/spec/lib/issues_tracker_spec.rb +++ /dev/null @@ -1,16 +0,0 @@ -require 'spec_helper' - -describe IssuesTracker do - let(:project) { double('project') } - - before do - @project = project - project.stub(repository: stub(ref_names: ['master', 'foo/bar/baz', 'v1.0.0', 'v2.0.0'])) - project.stub(path_with_namespace: 'gitlab/gitlab-ci') - end - - it 'returns url for issue' do - ololo - end -end - diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 48432eac14..c5603f52f6 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -190,4 +190,37 @@ describe Project do Project.new(path: "empty").repository.should be_nil end end + + describe :issue_exists? do + let(:project) { create(:project) } + let(:existed_issue) { create(:issue, project: project) } + let(:not_existed_issue) { create(:issue) } + let(:ext_project) { create(:redmine_project) } + + it "should be true or if used internal tracker and issue exists" do + project.issue_exists?(existed_issue.id).should be_true + end + + it "should be false or if used internal tracker and issue not exists" do + project.issue_exists?(not_existed_issue.id).should be_false + end + + it "should always be true if used other tracker" do + ext_project.issue_exists?(rand(100)).should be_true + end + end + + describe :used_default_issues_tracker? do + let(:project) { create(:project) } + let(:ext_project) { create(:redmine_project) } + + it "should be true if used internal tracker" do + project.used_default_issues_tracker?.should be_true + end + + it "should be false if used other tracker" do + ext_project.used_default_issues_tracker?.should be_false + end + end + end From 62de22c142d0ad9d956e7f6dae2eef4559d38436 Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Mon, 11 Feb 2013 17:15:10 +0400 Subject: [PATCH 033/113] External issue tracker params added to config --- config/gitlab.yml.example | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index 0d1d5818b2..93824e8685 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -7,6 +7,7 @@ # 2. Replace gitlab -> host with your domain # 3. Replace gitlab -> email_from +<<<<<<< HEAD <<<<<<< HEAD production: &base # @@ -38,9 +39,17 @@ production: &base # signup_enabled: true # default: false - Account passwords are not sent via the email if signup is enabled. # username_changing_enabled: false # default: true - User can change her username/namespace - ## Available issues trackers + + ## External issues trackers issues_tracker: redmine: + ## If not nil Issues link in project page will be replaced to this + url: "http://redmine.sample" + ## If not nil links from /#\d/ entities from commit messages will replaced to 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" ## Gravatar From 0afdf39dbcc50eb5889be08e5b1aaefe162e456c Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Mon, 11 Feb 2013 18:17:43 +0400 Subject: [PATCH 034/113] New field added --- app/models/project.rb | 7 ++++++- app/views/admin/projects/_form.html.haml | 4 ++++ app/views/projects/_form.html.haml | 4 ++++ config/gitlab.yml.example | 6 +----- spec/factories.rb | 1 + spec/models/project_spec.rb | 21 +++++++++++++++++++++ 6 files changed, 37 insertions(+), 6 deletions(-) diff --git a/app/models/project.rb b/app/models/project.rb index 612a318c96..e47e2a094f 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -28,7 +28,7 @@ class Project < ActiveRecord::Base class TransferError < StandardError; end attr_accessible :name, :path, :description, :default_branch, :issues_tracker, - :issues_enabled, :wall_enabled, :merge_requests_enabled, + :issues_enabled, :wall_enabled, :merge_requests_enabled, :issues_tracker_id, :wiki_enabled, :public, :import_url, as: [:default, :admin] attr_accessible :namespace_id, :creator_id, as: :admin @@ -74,6 +74,7 @@ class Project < ActiveRecord::Base message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" } validates :issues_enabled, :wall_enabled, :merge_requests_enabled, :wiki_enabled, inclusion: { in: [true, false] } + validates :issues_tracker_id, length: { within: 0..255 } validates_uniqueness_of :name, scope: :namespace_id validates_uniqueness_of :path, scope: :namespace_id @@ -217,6 +218,10 @@ class Project < ActiveRecord::Base self.issues_tracker == Project.issues_tracker.default_value end + def can_have_issues_tracker_id? + self.issues_enabled && !self.used_default_issues_tracker? + end + def services [gitlab_ci_service].compact end diff --git a/app/views/admin/projects/_form.html.haml b/app/views/admin/projects/_form.html.haml index 657a66f98e..9049dcd679 100644 --- a/app/views/admin/projects/_form.html.haml +++ b/app/views/admin/projects/_form.html.haml @@ -35,6 +35,10 @@ = 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 diff --git a/app/views/projects/_form.html.haml b/app/views/projects/_form.html.haml index 7072d78d3e..c9d623182e 100644 --- a/app/views/projects/_form.html.haml +++ b/app/views/projects/_form.html.haml @@ -28,6 +28,10 @@ = 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? + .control-group = f.label :merge_requests_enabled, "Merge Requests", class: 'control-label' .controls diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index 93824e8685..cc38b3a45c 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -7,8 +7,6 @@ # 2. Replace gitlab -> host with your domain # 3. Replace gitlab -> email_from -<<<<<<< HEAD -<<<<<<< HEAD production: &base # # 1. GitLab app settings @@ -43,9 +41,7 @@ production: &base ## External issues trackers issues_tracker: redmine: - ## If not nil Issues link in project page will be replaced to this - url: "http://redmine.sample" - ## If not nil links from /#\d/ entities from commit messages will replaced to this + ## If not nil, links from /#\d/ entities from commit messages will replaced to this ## Use placeholders: ## :project_id - Gitlab project identifier ## :issues_tracker_id - Project Name or Id in external issue tracker diff --git a/spec/factories.rb b/spec/factories.rb index b846f0a432..4176685946 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -31,6 +31,7 @@ FactoryGirl.define do factory :redmine_project, parent: :project do issues_tracker { "redmine" } + issues_tracker_id { "project_name_in_redmine" } end factory :group do diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index c5603f52f6..44f4cd4a73 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -60,6 +60,7 @@ describe Project do it { should ensure_inclusion_of(:wall_enabled).in_array([true, false]) } it { should ensure_inclusion_of(:merge_requests_enabled).in_array([true, false]) } it { should ensure_inclusion_of(:wiki_enabled).in_array([true, false]) } + it { should ensure_length_of(:issues_tracker_id).is_within(0..255) } it "should not allow new projects beyond user limits" do project.stub(:creator).and_return(double(can_create_project?: false, projects_limit: 1)) @@ -223,4 +224,24 @@ describe Project do end end + describe :can_have_issues_tracker_id? do + let(:project) { create(:project) } + let(:ext_project) { create(:redmine_project) } + + 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 + + it "should be false for projects with internal issue tracker if issues enabled" do + project.can_have_issues_tracker_id?.should be_false + end + + it "should be always false if issues disbled" do + project.issues_enabled = false + ext_project.issues_enabled = false + + project.can_have_issues_tracker_id?.should be_false + ext_project.can_have_issues_tracker_id?.should be_false + end + end end From f13600845d2ccec816337234eb5f1dccd40777f7 Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Mon, 11 Feb 2013 18:21:04 +0400 Subject: [PATCH 035/113] Migration added --- .../20130211085435_add_issues_tracker_id_to_project.rb | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 db/migrate/20130211085435_add_issues_tracker_id_to_project.rb diff --git a/db/migrate/20130211085435_add_issues_tracker_id_to_project.rb b/db/migrate/20130211085435_add_issues_tracker_id_to_project.rb new file mode 100644 index 0000000000..71763d18ae --- /dev/null +++ b/db/migrate/20130211085435_add_issues_tracker_id_to_project.rb @@ -0,0 +1,5 @@ +class AddIssuesTrackerIdToProject < ActiveRecord::Migration + def change + add_column :projects, :issues_tracker_id, :string + end +end From 16c720fd966ccb70a7642c59b81b23f74f00c122 Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Mon, 11 Feb 2013 17:32:29 +0400 Subject: [PATCH 036/113] Issues helper improved --- app/helpers/issues_helper.rb | 8 ++++- spec/helpers/issues_helper_spec.rb | 54 ++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 spec/helpers/issues_helper_spec.rb diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index 0d1301d062..3f80272756 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -42,15 +42,21 @@ module IssuesHelper end def url_for_issue(issue_id) + return "" if @project.nil? + 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.gsub(':id', issue_id.to_s).gsub(':project_id', @project.id.to_s) + url.gsub(':id', issue_id.to_s) + .gsub(':project_id', @project.id.to_s) + .gsub(':issues_tracker_id', @project.issues_tracker_id.to_s) end end def title_for_issue(issue_id) + return "" if @project.nil? + if @project.used_default_issues_tracker? && issue = @project.issues.where(id: issue_id).first issue.title else diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb new file mode 100644 index 0000000000..7d2ac8c7d8 --- /dev/null +++ b/spec/helpers/issues_helper_spec.rb @@ -0,0 +1,54 @@ +require "spec_helper" + +describe IssuesHelper do + let(:project) { create(:project) } + let(:issue) { create(:issue, project: project) } + let(:ext_project) { create(:redmine_project) } + + describe :title_for_issue do + it "should return issue title if used internal tracker" do + @project = project + title_for_issue(issue.id).should eq issue.title + end + + it "should always return empty string if used external tracker" do + @project = ext_project + title_for_issue(rand(100)).should eq "" + end + + it "should always return empty string if project nil" do + @project = nil + + title_for_issue(rand(100)).should eq "" + end + end + + describe :url_for_issue do + let(:issue_id) { 3 } + let(:issues_url) { "http://redmine/:project_id/:issues_tracker_id/:id" } + let(:ext_expected) do + issues_url.gsub(':id', issue_id.to_s) + .gsub(':project_id', ext_project.id.to_s) + .gsub(':issues_tracker_id', ext_project.issues_tracker_id.to_s) + end + let(:int_expected) { polymorphic_path([project, issue]) } + + it "should return internal path if used internal tracker" do + @project = project + url_for_issue(issue.id).should match(int_expected) + end + + it "should return path to external tracker" do + @project = ext_project + Settings[:issues_tracker][ext_project.issues_tracker]["issues_url"] = issues_url + + url_for_issue(issue_id).should match(ext_expected) + end + + it "should return empty string if project nil" do + @project = nil + + url_for_issue(issue.id).should eq "" + end + end +end From 9e8a818696f3b3538b93a306d6e8d3ce5973ece0 Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Tue, 12 Feb 2013 15:37:33 +0400 Subject: [PATCH 037/113] Issues helper included to markdown helper --- lib/gitlab/markdown.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb index 4e78d88118..280f9f9730 100644 --- a/lib/gitlab/markdown.rb +++ b/lib/gitlab/markdown.rb @@ -25,6 +25,8 @@ module Gitlab # >> gfm(":trollface:") # => "\":trollface:\" module Markdown + include IssuesHelper + attr_reader :html_options # Public: Parse the provided text with GitLab-Flavored Markdown From 9b606ede000666bc5f5330f43fa0ea0c7ff9815c Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Thu, 14 Feb 2013 18:25:56 +0400 Subject: [PATCH 038/113] Wrong default section in config. Fixed. --- config/gitlab.yml.example | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index cc38b3a45c..c7bb66ae6e 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -140,10 +140,10 @@ production: &base timeout: 10 development: - <<: *base + <<: *defaults test: <<: *base staging: - <<: *base + <<: *defaults From c643b50dbd726b6a3396ea459d14378e1c52b48b Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Thu, 14 Feb 2013 18:26:50 +0400 Subject: [PATCH 039/113] Default value for issues_tracker setting added --- app/models/project.rb | 2 +- config/gitlab.yml.example | 5 ++++- config/initializers/1_settings.rb | 2 ++ spec/helpers/issues_helper_spec.rb | 3 +-- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/models/project.rb b/app/models/project.rb index e47e2a094f..12f7e45496 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -96,7 +96,7 @@ class Project < ActiveRecord::Base scope :joined, ->(user) { where("namespace_id != ?", user.namespace_id) } scope :public_only, -> { where(public: true) } - enumerize :issues_tracker, :in => (Settings[:issues_tracker].keys).append(:gitlab), :default => :gitlab + enumerize :issues_tracker, :in => (Gitlab.config.issues_tracker.keys).append(:gitlab), :default => :gitlab class << self def abandoned diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index c7bb66ae6e..895ae797b6 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -143,7 +143,10 @@ development: <<: *defaults test: - <<: *base + <<: *defaults + issues_tracker: + redmine: + issues_url: "http://redmine/:project_id/:issues_tracker_id/:id" staging: <<: *defaults diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index f7d18e6714..a656b02171 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -42,6 +42,8 @@ Settings['omniauth'] ||= Settingslogic.new({}) Settings.omniauth['enabled'] = false if Settings.omniauth['enabled'].nil? Settings.omniauth['providers'] ||= [] +Settings['issues_tracker'] ||= {} + # # GitLab # diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb index 7d2ac8c7d8..013dab71d6 100644 --- a/spec/helpers/issues_helper_spec.rb +++ b/spec/helpers/issues_helper_spec.rb @@ -25,7 +25,7 @@ describe IssuesHelper do describe :url_for_issue do let(:issue_id) { 3 } - let(:issues_url) { "http://redmine/:project_id/:issues_tracker_id/:id" } + let(:issues_url) { Gitlab.config.issues_tracker.redmine.issues_url} let(:ext_expected) do issues_url.gsub(':id', issue_id.to_s) .gsub(':project_id', ext_project.id.to_s) @@ -40,7 +40,6 @@ describe IssuesHelper do it "should return path to external tracker" do @project = ext_project - Settings[:issues_tracker][ext_project.issues_tracker]["issues_url"] = issues_url url_for_issue(issue_id).should match(ext_expected) end From c6385e41355a622ef1be2d72d0fd20eef2897707 Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Thu, 14 Feb 2013 18:43:06 +0400 Subject: [PATCH 040/113] Section name returned back to base --- config/gitlab.yml.example | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index 895ae797b6..b7b2296fee 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -140,13 +140,13 @@ production: &base timeout: 10 development: - <<: *defaults + <<: *base test: - <<: *defaults + <<: *base issues_tracker: redmine: issues_url: "http://redmine/:project_id/:issues_tracker_id/:id" staging: - <<: *defaults + <<: *base From cf3cf3750e53439cfaa8df786fd71308e4ef4867 Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Tue, 19 Feb 2013 16:30:37 +0400 Subject: [PATCH 041/113] Gem gon added. It produces server-side variable values in javascript --- Gemfile | 1 + Gemfile.lock | 4 ++++ app/views/layouts/_head.html.haml | 1 + 3 files changed, 6 insertions(+) diff --git a/Gemfile b/Gemfile index 46ad7e8059..9c8467b173 100644 --- a/Gemfile +++ b/Gemfile @@ -115,6 +115,7 @@ group :assets do gem 'bootstrap-sass', "2.2.1.1" gem "font-awesome-sass-rails", "~> 3.0.0" gem "gemoji", "~> 1.2.1", require: 'emoji/railtie' + gem "gon" end group :development do diff --git a/Gemfile.lock b/Gemfile.lock index 311e757cd7..65fd6f363f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -184,6 +184,9 @@ GEM pyu-ruby-sasl (~> 0.0.3.1) rubyntlm (~> 0.1.1) gitlab_yaml_db (1.0.0) + gon (4.0.2) + actionpack (>= 2.3.0) + json grape (0.2.2) activesupport hashie (~> 1.2) @@ -483,6 +486,7 @@ DEPENDENCIES gitlab_meta (= 5.0) gitlab_omniauth-ldap (= 1.0.2) gitlab_yaml_db (= 1.0.0) + gon grack! grape (~> 0.2.1) grit! diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml index 4b4f5da332..eb83fd2fd4 100644 --- a/app/views/layouts/_head.html.haml +++ b/app/views/layouts/_head.html.haml @@ -7,6 +7,7 @@ = stylesheet_link_tag "application" = javascript_include_tag "application" = csrf_meta_tags + = include_gon -# Atom feed - if current_user From bca72eac747acbec42e4b93fecb4f6100e3ba257 Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Tue, 19 Feb 2013 16:37:43 +0400 Subject: [PATCH 042/113] Default issue tracker name added to gon variables --- app/controllers/application_controller.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 1f211bac9c..5b886227bc 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -5,6 +5,7 @@ class ApplicationController < ActionController::Base before_filter :add_abilities before_filter :dev_tools if Rails.env == 'development' before_filter :default_headers + before_filter :add_gon_variables protect_from_forgery @@ -148,4 +149,8 @@ class ApplicationController < ActionController::Base headers['X-Frame-Options'] = 'DENY' headers['X-XSS-Protection'] = '1; mode=block' end + + def add_gon_variables + gon.default_issues_tracker = Project.issues_tracker.default_value + end end From ab98db73a35172d723adf474d9dc50b5d613a9bf Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Tue, 19 Feb 2013 16:43:24 +0400 Subject: [PATCH 043/113] Issues tracker settings enableds/disableds without page reloading now --- app/assets/javascripts/projects.js.coffee | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/app/assets/javascripts/projects.js.coffee b/app/assets/javascripts/projects.js.coffee index d03a487c45..24106c61b7 100644 --- a/app/assets/javascripts/projects.js.coffee +++ b/app/assets/javascripts/projects.js.coffee @@ -18,3 +18,18 @@ $ -> # Ref switcher $('.project-refs-select').on 'change', -> $(@).parents('form').submit() + + $('#project_issues_enabled').change -> + if ($(this).is(':checked') == true) + $('#project_issues_tracker').removeAttr('disabled') + else + $('#project_issues_tracker').attr('disabled', 'disabled') + + $('#project_issues_tracker').change() + + $('#project_issues_tracker').change -> + if ($(this).val() == gon.default_issues_tracker || $(this).is(':disabled')) + $('#project_issues_tracker_id').attr('disabled', 'disabled') + else + $('#project_issues_tracker_id').removeAttr('disabled') + From b6d0f2852d1f2518ca8987667beb7df2b8223611 Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Tue, 19 Feb 2013 17:06:40 +0400 Subject: [PATCH 044/113] Issues link from project page follows on remote bug tracker if it selected now --- app/helpers/issues_helper.rb | 12 ++++++++++++ app/views/layouts/project_resource.html.haml | 7 ++++--- config/gitlab.yml.example | 6 ++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index 3f80272756..8321518049 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -41,6 +41,18 @@ module IssuesHelper @project.milestones.active.order("id desc").all end + def url_for_project_issues + return "" if @project.nil? + + if @project.used_default_issues_tracker? + project_issues_filter_path(@project) + else + url = Settings[: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 + end + def url_for_issue(issue_id) return "" if @project.nil? diff --git a/app/views/layouts/project_resource.html.haml b/app/views/layouts/project_resource.html.haml index 13fb8637bf..55abe8ab5f 100644 --- a/app/views/layouts/project_resource.html.haml +++ b/app/views/layouts/project_resource.html.haml @@ -22,11 +22,12 @@ = nav_link(controller: %w(graph)) do = link_to "Network", project_graph_path(@project, @ref || @repository.root_ref) - - if @project.issues_enabled + - if @project.issues_enabled = nav_link(controller: %w(issues milestones labels)) do - = link_to project_issues_filter_path(@project) do + = link_to url_for_project_issues do Issues - %span.count.issue_counter= @project.issues.opened.count + - 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 diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index b7b2296fee..07e97ae541 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -41,6 +41,11 @@ production: &base ## External issues trackers issues_tracker: redmine: + ## If not nil, link 'Issues' on project page will be replaced tp this + ## Use placeholders: + ## :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 to this ## Use placeholders: ## :project_id - Gitlab project identifier @@ -146,6 +151,7 @@ test: <<: *base issues_tracker: redmine: + project_url: "http://redmine/projects/:issues_tracker_id" issues_url: "http://redmine/:project_id/:issues_tracker_id/:id" staging: From 8caccae45457940b54174a3516a1a56915016c22 Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Tue, 19 Feb 2013 17:21:59 +0400 Subject: [PATCH 045/113] Issue helper tests improved --- spec/helpers/issues_helper_spec.rb | 32 +++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb index 013dab71d6..c9eb659156 100644 --- a/spec/helpers/issues_helper_spec.rb +++ b/spec/helpers/issues_helper_spec.rb @@ -1,9 +1,9 @@ require "spec_helper" describe IssuesHelper do - let(:project) { create(:project) } - let(:issue) { create(:issue, project: project) } - let(:ext_project) { create(:redmine_project) } + let(:project) { create :project } + let(:issue) { create :issue, project: project } + let(:ext_project) { create :redmine_project } describe :title_for_issue do it "should return issue title if used internal tracker" do @@ -23,6 +23,32 @@ describe IssuesHelper do end end + describe :url_for_project_issues do + let(:project_url) { Gitlab.config.issues_tracker.redmine.project_url} + let(:ext_expected) do + project_url.gsub(':project_id', ext_project.id.to_s) + .gsub(':issues_tracker_id', ext_project.issues_tracker_id.to_s) + end + let(:int_expected) { polymorphic_path([project]) } + + it "should return internal path if used internal tracker" do + @project = project + url_for_project_issues.should match(int_expected) + end + + it "should return path to external tracker" do + @project = ext_project + + url_for_project_issues.should match(ext_expected) + end + + it "should return empty string if project nil" do + @project = nil + + url_for_project_issues.should eq "" + end + end + describe :url_for_issue do let(:issue_id) { 3 } let(:issues_url) { Gitlab.config.issues_tracker.redmine.issues_url} From cff845784eb76aeaff7b4242e0aaa2469a530a59 Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Tue, 19 Feb 2013 17:31:45 +0400 Subject: [PATCH 046/113] Show Issues tracker select only if one or more remote issue trackers available --- app/views/admin/projects/_form.html.haml | 13 +++++++------ app/views/projects/_form.html.haml | 13 +++++++------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/app/views/admin/projects/_form.html.haml b/app/views/admin/projects/_form.html.haml index 9049dcd679..29b90bdd4c 100644 --- a/app/views/admin/projects/_form.html.haml +++ b/app/views/admin/projects/_form.html.haml @@ -31,13 +31,14 @@ = f.label :issues_enabled, "Issues" .input= f.check_box :issues_enabled - .clearfix - = f.label :issues_tracker, "Issues tracker", class: 'control-label' - .input= f.select(:issues_tracker, Project.issues_tracker.values, {}, { disabled: !@project.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 :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" diff --git a/app/views/projects/_form.html.haml b/app/views/projects/_form.html.haml index c9d623182e..b78c70be18 100644 --- a/app/views/projects/_form.html.haml +++ b/app/views/projects/_form.html.haml @@ -24,13 +24,14 @@ = f.check_box :issues_enabled %span.descr Lightweight issue tracking system for this project - .control-group - = f.label :issues_tracker, "Issues tracker", class: 'control-label' - .input= f.select(:issues_tracker, Project.issues_tracker.values, {}, { disabled: !@project.issues_enabled }) + - if Project.issues_tracker.values.count > 1 + .control-group + = 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 :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? .control-group = f.label :merge_requests_enabled, "Merge Requests", class: 'control-label' From 1dab19d0d7b25cb5af27b8d10c8b615b2d38c2cf Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Thu, 28 Feb 2013 16:30:47 +0400 Subject: [PATCH 047/113] DB schema updated --- db/schema.rb | 314 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 314 insertions(+) create mode 100644 db/schema.rb diff --git a/db/schema.rb b/db/schema.rb new file mode 100644 index 0000000000..e9d428e5ef --- /dev/null +++ b/db/schema.rb @@ -0,0 +1,314 @@ +# encoding: UTF-8 +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# Note that this schema.rb definition is the authoritative source for your +# database schema. If you need to create the application database on another +# system, you should be using db:schema:load, not running all the migrations +# from scratch. The latter is a flawed and unsustainable approach (the more migrations +# you'll amass, the slower it'll run and the greater likelihood for issues). +# +# It's strongly recommended to check this file into your version control system. + +ActiveRecord::Schema.define(:version => 20130220133245) do + + create_table "events", :force => true do |t| + t.string "target_type" + t.integer "target_id" + t.string "title" + t.text "data" + t.integer "project_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.integer "action" + t.integer "author_id" + end + + add_index "events", ["action"], :name => "index_events_on_action" + add_index "events", ["author_id"], :name => "index_events_on_author_id" + add_index "events", ["created_at"], :name => "index_events_on_created_at" + add_index "events", ["project_id"], :name => "index_events_on_project_id" + add_index "events", ["target_id"], :name => "index_events_on_target_id" + add_index "events", ["target_type"], :name => "index_events_on_target_type" + + create_table "issues", :force => true do |t| + t.string "title" + t.integer "assignee_id" + t.integer "author_id" + t.integer "project_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.integer "position", :default => 0 + t.string "branch_name" + t.text "description" + t.integer "milestone_id" + t.string "state" + end + + add_index "issues", ["assignee_id"], :name => "index_issues_on_assignee_id" + add_index "issues", ["author_id"], :name => "index_issues_on_author_id" + add_index "issues", ["created_at"], :name => "index_issues_on_created_at" + add_index "issues", ["milestone_id"], :name => "index_issues_on_milestone_id" + add_index "issues", ["project_id"], :name => "index_issues_on_project_id" + add_index "issues", ["title"], :name => "index_issues_on_title" + + create_table "keys", :force => true do |t| + t.integer "user_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.text "key" + t.string "title" + t.string "identifier" + t.integer "project_id" + end + + add_index "keys", ["identifier"], :name => "index_keys_on_identifier" + add_index "keys", ["project_id"], :name => "index_keys_on_project_id" + add_index "keys", ["user_id"], :name => "index_keys_on_user_id" + + create_table "merge_requests", :force => true do |t| + t.string "target_branch", :null => false + t.string "source_branch", :null => false + t.integer "project_id", :null => false + t.integer "author_id" + t.integer "assignee_id" + t.string "title" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.text "st_commits", :limit => 2147483647 + t.text "st_diffs", :limit => 2147483647 + t.integer "milestone_id" + t.string "state" + t.string "merge_status" + end + + add_index "merge_requests", ["assignee_id"], :name => "index_merge_requests_on_assignee_id" + add_index "merge_requests", ["author_id"], :name => "index_merge_requests_on_author_id" + add_index "merge_requests", ["created_at"], :name => "index_merge_requests_on_created_at" + add_index "merge_requests", ["milestone_id"], :name => "index_merge_requests_on_milestone_id" + add_index "merge_requests", ["project_id"], :name => "index_merge_requests_on_project_id" + add_index "merge_requests", ["source_branch"], :name => "index_merge_requests_on_source_branch" + add_index "merge_requests", ["target_branch"], :name => "index_merge_requests_on_target_branch" + add_index "merge_requests", ["title"], :name => "index_merge_requests_on_title" + + create_table "milestones", :force => true do |t| + t.string "title", :null => false + t.integer "project_id", :null => false + t.text "description" + t.date "due_date" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "state" + end + + add_index "milestones", ["due_date"], :name => "index_milestones_on_due_date" + add_index "milestones", ["project_id"], :name => "index_milestones_on_project_id" + + create_table "namespaces", :force => true do |t| + t.string "name", :null => false + t.string "path", :null => false + t.integer "owner_id", :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "type" + end + + add_index "namespaces", ["name"], :name => "index_namespaces_on_name" + add_index "namespaces", ["owner_id"], :name => "index_namespaces_on_owner_id" + add_index "namespaces", ["path"], :name => "index_namespaces_on_path" + add_index "namespaces", ["type"], :name => "index_namespaces_on_type" + + create_table "notes", :force => true do |t| + t.text "note" + t.string "noteable_type" + t.integer "author_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.integer "project_id" + t.string "attachment" + t.string "line_code" + t.string "commit_id" + t.integer "noteable_id" + end + + add_index "notes", ["commit_id"], :name => "index_notes_on_commit_id" + add_index "notes", ["created_at"], :name => "index_notes_on_created_at" + add_index "notes", ["noteable_type"], :name => "index_notes_on_noteable_type" + add_index "notes", ["project_id", "noteable_type"], :name => "index_notes_on_project_id_and_noteable_type" + add_index "notes", ["project_id"], :name => "index_notes_on_project_id" + + create_table "projects", :force => true do |t| + t.string "name" + t.string "path" + t.text "description" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.integer "creator_id" + t.string "default_branch" + t.boolean "issues_enabled", :default => true, :null => false + t.boolean "wall_enabled", :default => true, :null => false + t.boolean "merge_requests_enabled", :default => true, :null => false + t.boolean "wiki_enabled", :default => true, :null => false + t.integer "namespace_id" + t.boolean "public", :default => false, :null => false + t.string "issues_tracker", :default => "gitlab", :null => false + t.string "issues_tracker_id" + end + + add_index "projects", ["creator_id"], :name => "index_projects_on_owner_id" + add_index "projects", ["namespace_id"], :name => "index_projects_on_namespace_id" + + create_table "protected_branches", :force => true do |t| + t.integer "project_id", :null => false + t.string "name", :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "services", :force => true do |t| + t.string "type" + t.string "title" + t.string "token" + t.integer "project_id", :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.boolean "active", :default => false, :null => false + t.string "project_url" + end + + add_index "services", ["project_id"], :name => "index_services_on_project_id" + + create_table "snippets", :force => true do |t| + t.string "title" + t.text "content" + t.integer "author_id", :null => false + t.integer "project_id", :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "file_name" + t.datetime "expires_at" + end + + add_index "snippets", ["created_at"], :name => "index_snippets_on_created_at" + add_index "snippets", ["expires_at"], :name => "index_snippets_on_expires_at" + add_index "snippets", ["project_id"], :name => "index_snippets_on_project_id" + + create_table "taggings", :force => true do |t| + t.integer "tag_id" + t.integer "taggable_id" + t.string "taggable_type" + t.integer "tagger_id" + t.string "tagger_type" + t.string "context" + t.datetime "created_at" + end + + add_index "taggings", ["tag_id"], :name => "index_taggings_on_tag_id" + add_index "taggings", ["taggable_id", "taggable_type", "context"], :name => "index_taggings_on_taggable_id_and_taggable_type_and_context" + + create_table "tags", :force => true do |t| + t.string "name" + end + + create_table "user_team_project_relationships", :force => true do |t| + t.integer "project_id" + t.integer "user_team_id" + t.integer "greatest_access" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "user_team_user_relationships", :force => true do |t| + t.integer "user_id" + t.integer "user_team_id" + t.boolean "group_admin" + t.integer "permission" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "user_teams", :force => true do |t| + t.string "name" + t.string "path" + t.integer "owner_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "users", :force => true do |t| + t.string "email", :default => "", :null => false + t.string "encrypted_password", :default => "", :null => false + t.string "reset_password_token" + t.datetime "reset_password_sent_at" + t.datetime "remember_created_at" + t.integer "sign_in_count", :default => 0 + t.datetime "current_sign_in_at" + t.datetime "last_sign_in_at" + t.string "current_sign_in_ip" + t.string "last_sign_in_ip" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "name" + t.boolean "admin", :default => false, :null => false + t.integer "projects_limit", :default => 10 + t.string "skype", :default => "", :null => false + t.string "linkedin", :default => "", :null => false + t.string "twitter", :default => "", :null => false + t.string "authentication_token" + t.boolean "dark_scheme", :default => false, :null => false + t.integer "theme_id", :default => 1, :null => false + t.string "bio" + t.boolean "blocked", :default => false, :null => false + t.integer "failed_attempts", :default => 0 + t.datetime "locked_at" + t.string "extern_uid" + t.string "provider" + t.string "username" + t.boolean "can_create_group", :default => true, :null => false + t.boolean "can_create_team", :default => true, :null => false + end + + add_index "users", ["admin"], :name => "index_users_on_admin" + add_index "users", ["blocked"], :name => "index_users_on_blocked" + add_index "users", ["email"], :name => "index_users_on_email", :unique => true + add_index "users", ["extern_uid", "provider"], :name => "index_users_on_extern_uid_and_provider", :unique => true + add_index "users", ["name"], :name => "index_users_on_name" + add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true + add_index "users", ["username"], :name => "index_users_on_username" + + create_table "users_projects", :force => true do |t| + t.integer "user_id", :null => false + t.integer "project_id", :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.integer "project_access", :default => 0, :null => false + end + + add_index "users_projects", ["project_access"], :name => "index_users_projects_on_project_access" + add_index "users_projects", ["project_id"], :name => "index_users_projects_on_project_id" + add_index "users_projects", ["user_id"], :name => "index_users_projects_on_user_id" + + create_table "web_hooks", :force => true do |t| + t.string "url" + t.integer "project_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "type", :default => "ProjectHook" + t.integer "service_id" + end + + create_table "wikis", :force => true do |t| + t.string "title" + t.text "content" + t.integer "project_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "slug" + t.integer "user_id" + end + + add_index "wikis", ["project_id"], :name => "index_wikis_on_project_id" + add_index "wikis", ["slug"], :name => "index_wikis_on_slug" + +end From 9f45e01e8426b9d678a210bb5237628676f99894 Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Thu, 7 Feb 2013 14:42:52 +0400 Subject: [PATCH 048/113] Description to groups added --- app/assets/stylesheets/application.scss | 1 + app/assets/stylesheets/sections/groups.scss | 31 +++++++++++++++++++ app/models/group.rb | 15 ++++----- app/models/namespace.rb | 5 +-- app/views/admin/groups/edit.html.haml | 9 ++++-- app/views/admin/groups/index.html.haml | 4 ++- app/views/admin/groups/new.html.haml | 10 ++++-- app/views/admin/groups/show.html.haml | 8 ++++- app/views/dashboard/_groups.html.haml | 10 +++--- ...206084024_add_description_to_namsespace.rb | 5 +++ db/schema.rb | 7 +++-- 11 files changed, 83 insertions(+), 22 deletions(-) create mode 100644 app/assets/stylesheets/sections/groups.scss create mode 100644 db/migrate/20130206084024_add_description_to_namsespace.rb diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 6b500b8882..8afda88af4 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -20,6 +20,7 @@ @import "sections/nav.scss"; @import "sections/commits.scss"; @import "sections/issues.scss"; +@import "sections/groups.scss"; @import "sections/projects.scss"; @import "sections/snippets.scss"; @import "sections/votes.scss"; diff --git a/app/assets/stylesheets/sections/groups.scss b/app/assets/stylesheets/sections/groups.scss new file mode 100644 index 0000000000..9f5dc15a73 --- /dev/null +++ b/app/assets/stylesheets/sections/groups.scss @@ -0,0 +1,31 @@ +.projects { + @extend .row; + .activities { + } + + .side { + @extend .right; + + .groups_box { + > .title { + padding: 2px 15px; + } + .well-list { + li { padding: 15px; } + .edit { + float: right; + margin: 0; + } + .description { + padding-top: 5px; + display: block; + span, strong { + font-size: 12px; + color: #666; + } + } + } + @extend .ui-box; + } + } +} diff --git a/app/models/group.rb b/app/models/group.rb index 8ba92980a9..7651ce23cb 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -2,13 +2,14 @@ # # Table name: namespaces # -# id :integer not null, primary key -# name :string(255) not null -# path :string(255) not null -# owner_id :integer not null -# created_at :datetime not null -# updated_at :datetime not null -# type :string(255) +# id :integer not null, primary key +# name :string(255) not null +# description :string(255) not null +# path :string(255) not null +# owner_id :integer not null +# created_at :datetime not null +# updated_at :datetime not null +# type :string(255) # class Group < Namespace diff --git a/app/models/namespace.rb b/app/models/namespace.rb index 385fa291b4..992ead4fda 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -4,6 +4,7 @@ # # id :integer not null, primary key # name :string(255) not null +# description :string(255) not null # path :string(255) not null # owner_id :integer not null # created_at :datetime not null @@ -12,7 +13,7 @@ # class Namespace < ActiveRecord::Base - attr_accessible :name, :path + attr_accessible :name, :description, :path has_many :projects, dependent: :destroy belongs_to :owner, class_name: "User" @@ -22,7 +23,7 @@ class Namespace < ActiveRecord::Base length: { within: 0..255 }, format: { with: Gitlab::Regex.name_regex, message: "only letters, digits, spaces & '_' '-' '.' allowed." } - + validates :description, length: { within: 0..255 } validates :path, uniqueness: true, presence: true, length: { within: 1..255 }, format: { with: Gitlab::Regex.path_regex, message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" } diff --git a/app/views/admin/groups/edit.html.haml b/app/views/admin/groups/edit.html.haml index dce044956c..f34ed83fb8 100644 --- a/app/views/admin/groups/edit.html.haml +++ b/app/views/admin/groups/edit.html.haml @@ -1,4 +1,4 @@ -%h3.page_title Rename Group +%h3.page_title Edit Group %hr = form_for [:admin, @group] do |f| - if @group.errors.any? @@ -10,7 +10,10 @@ .input = f.text_field :name, placeholder: "Example Group", class: "xxlarge" - + .clearfix.group_description_holder + = f.label :description, "Details" + .input + = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4 .clearfix.group_name_holder = f.label :path do @@ -24,5 +27,5 @@ %li It will change the git path to repositories under this group. .form-actions - = f.submit 'Rename group', class: "btn btn-remove" + = f.submit 'Edit group', class: "btn btn-remove" = link_to 'Cancel', admin_groups_path, class: "btn btn-cancel" diff --git a/app/views/admin/groups/index.html.haml b/app/views/admin/groups/index.html.haml index 6d5a293ef7..1b4ffcb6e0 100644 --- a/app/views/admin/groups/index.html.haml +++ b/app/views/admin/groups/index.html.haml @@ -17,6 +17,7 @@ Name %i.icon-sort-down %th Path + %th Description %th Projects %th Owner %th.cred Danger Zone! @@ -25,11 +26,12 @@ %tr %td %strong= link_to group.name, [:admin, group] + %td= group.description %td= group.path %td= group.projects.count %td = link_to group.owner_name, admin_user_path(group.owner) %td.bgred - = link_to 'Rename', edit_admin_group_path(group), id: "edit_#{dom_id(group)}", class: "btn btn-small" + = link_to 'Edit', edit_admin_group_path(group), id: "edit_#{dom_id(group)}", class: "btn btn-small" = link_to 'Destroy', [:admin, group], confirm: "REMOVE #{group.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove" = paginate @groups, theme: "admin" diff --git a/app/views/admin/groups/new.html.haml b/app/views/admin/groups/new.html.haml index 60c6fa5ad0..29bbcc55c9 100644 --- a/app/views/admin/groups/new.html.haml +++ b/app/views/admin/groups/new.html.haml @@ -9,8 +9,14 @@ Group name is .input = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left" -   - = f.submit 'Create group', class: "btn btn-primary" + .clearfix.group_description_holder + = f.label :description, "Details" + .input + = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4 + + .form-actions + = f.submit 'Create group', class: "btn btn-primary" + %hr .padded %ul diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml index 90f8fc0f81..63ea78fdd9 100644 --- a/app/views/admin/groups/show.html.haml +++ b/app/views/admin/groups/show.html.haml @@ -16,7 +16,13 @@   = link_to edit_admin_group_path(@group), class: "btn btn-small pull-right" do %i.icon-edit - Rename + Edit + %tr + %td + %b + Description: + %td + = @group.description %tr %td %b diff --git a/app/views/dashboard/_groups.html.haml b/app/views/dashboard/_groups.html.haml index ba8d3029ea..8c1dfc1232 100644 --- a/app/views/dashboard/_groups.html.haml +++ b/app/views/dashboard/_groups.html.haml @@ -1,4 +1,4 @@ -.ui-box +.groups_box %h5.title Groups %small @@ -13,6 +13,8 @@ %li = link_to group_path(id: group.path), class: dom_class(group) do %strong.well-title= truncate(group.name, length: 35) - %span.pull-right.light - - if group.owner == current_user - %i.icon-wrench + %span.edit.light + - if group.owner == current_user + %i.icon-wrench + %span.description + %strong= group.description diff --git a/db/migrate/20130206084024_add_description_to_namsespace.rb b/db/migrate/20130206084024_add_description_to_namsespace.rb new file mode 100644 index 0000000000..ef02e489d0 --- /dev/null +++ b/db/migrate/20130206084024_add_description_to_namsespace.rb @@ -0,0 +1,5 @@ +class AddDescriptionToNamsespace < ActiveRecord::Migration + def change + add_column :namespaces, :description, :string, default: '', null: false + end +end diff --git a/db/schema.rb b/db/schema.rb index 74d5f9a360..63f498e4a6 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -112,6 +112,7 @@ ActiveRecord::Schema.define(:version => 20130220133245) do t.datetime "created_at", :null => false t.datetime "updated_at", :null => false t.string "type" + t.string "description", :default => "", :null => false end add_index "namespaces", ["name"], :name => "index_namespaces_on_name" @@ -152,6 +153,8 @@ ActiveRecord::Schema.define(:version => 20130220133245) do t.boolean "wiki_enabled", :default => true, :null => false t.integer "namespace_id" t.boolean "public", :default => false, :null => false + t.string "issues_tracker", :default => "gitlab", :null => false + t.string "issues_tracker_id" end add_index "projects", ["creator_id"], :name => "index_projects_on_owner_id" @@ -230,8 +233,8 @@ ActiveRecord::Schema.define(:version => 20130220133245) do t.string "name" t.string "path" t.integer "owner_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false end create_table "users", :force => true do |t| From 5f657203a1c19b3eca38b3961dfe24e3a06af910 Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Thu, 7 Feb 2013 15:10:14 +0400 Subject: [PATCH 049/113] Description added to temas --- app/assets/stylesheets/application.scss | 1 + app/assets/stylesheets/sections/teams.scss | 31 +++++++++++++++++++ app/models/user_team.rb | 3 +- app/views/admin/teams/edit.html.haml | 9 ++++-- app/views/admin/teams/index.html.haml | 4 ++- app/views/admin/teams/new.html.haml | 11 +++++-- app/views/admin/teams/show.html.haml | 8 ++++- app/views/dashboard/_teams.html.haml | 16 +++++----- ...20130207104426_add_description_to_teams.rb | 5 +++ 9 files changed, 74 insertions(+), 14 deletions(-) create mode 100644 app/assets/stylesheets/sections/teams.scss create mode 100644 db/migrate/20130207104426_add_description_to_teams.rb diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 8afda88af4..25cef4324c 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -21,6 +21,7 @@ @import "sections/commits.scss"; @import "sections/issues.scss"; @import "sections/groups.scss"; +@import "sections/teams.scss"; @import "sections/projects.scss"; @import "sections/snippets.scss"; @import "sections/votes.scss"; diff --git a/app/assets/stylesheets/sections/teams.scss b/app/assets/stylesheets/sections/teams.scss new file mode 100644 index 0000000000..b5c546ca5f --- /dev/null +++ b/app/assets/stylesheets/sections/teams.scss @@ -0,0 +1,31 @@ +.projects { + @extend .row; + .activities { + } + + .side { + @extend .right; + + .teams_box { + > .title { + padding: 2px 15px; + } + .well-list { + li { padding: 15px; } + .edit { + float: right; + margin: 0; + } + .description { + padding-top: 5px; + display: block; + span, strong { + font-size: 12px; + color: #666; + } + } + } + @extend .ui-box; + } + } +} diff --git a/app/models/user_team.rb b/app/models/user_team.rb index 2f3091c235..0cb84edd66 100644 --- a/app/models/user_team.rb +++ b/app/models/user_team.rb @@ -11,7 +11,7 @@ # class UserTeam < ActiveRecord::Base - attr_accessible :name, :owner_id, :path + attr_accessible :name, :description, :owner_id, :path belongs_to :owner, class_name: User @@ -26,6 +26,7 @@ class UserTeam < ActiveRecord::Base length: { within: 0..255 }, format: { with: Gitlab::Regex.name_regex, message: "only letters, digits, spaces & '_' '-' '.' allowed." } + validates :description, length: { within: 0..255 } validates :path, uniqueness: true, presence: true, length: { within: 1..255 }, format: { with: Gitlab::Regex.path_regex, message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" } diff --git a/app/views/admin/teams/edit.html.haml b/app/views/admin/teams/edit.html.haml index 9282398ce5..a48a369b3b 100644 --- a/app/views/admin/teams/edit.html.haml +++ b/app/views/admin/teams/edit.html.haml @@ -1,4 +1,4 @@ -%h3.page_title Rename Team +%h3.page_title Edit Team %hr = form_for @team, url: admin_team_path(@team), method: :put do |f| - if @team.errors.any? @@ -10,6 +10,11 @@ .input = f.text_field :name, placeholder: "Example Team", class: "xxlarge" + .clearfix.team_description_holder + = f.label :description, "Details" + .input + = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4 + .clearfix.team_name_holder = f.label :path do %span.cred Team path is @@ -19,5 +24,5 @@ %li It will change web url for access team and team projects. .form-actions - = f.submit 'Rename team', class: "btn btn-remove" + = f.submit 'Edit team', class: "btn btn-remove" = link_to 'Cancel', admin_teams_path, class: "btn btn-cancel" diff --git a/app/views/admin/teams/index.html.haml b/app/views/admin/teams/index.html.haml index bb0487d43e..62af4b5093 100644 --- a/app/views/admin/teams/index.html.haml +++ b/app/views/admin/teams/index.html.haml @@ -16,6 +16,7 @@ %th Name %i.icon-sort-down + %th Description %th Path %th Projects %th Members @@ -26,13 +27,14 @@ %tr %td %strong= link_to team.name, admin_team_path(team) + %td= team.description %td= team.path %td= team.projects.count %td= team.members.count %td = link_to team.owner.name, admin_user_path(team.owner) %td.bgred - = link_to 'Rename', edit_admin_team_path(team), id: "edit_#{dom_id(team)}", class: "btn btn-small" + = link_to 'Edit', edit_admin_team_path(team), id: "edit_#{dom_id(team)}", class: "btn btn-small" = link_to 'Destroy', admin_team_path(team), confirm: "REMOVE #{team.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove" = paginate @teams, theme: "admin" diff --git a/app/views/admin/teams/new.html.haml b/app/views/admin/teams/new.html.haml index 5d55a7975e..a852b4cbbf 100644 --- a/app/views/admin/teams/new.html.haml +++ b/app/views/admin/teams/new.html.haml @@ -9,8 +9,15 @@ Team name is .input = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left" -   - = f.submit 'Create team', class: "btn btn-primary" + + .clearfix.team_description_holder + = f.label :description, "Details" + .input + = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4 + + .form-actions + = f.submit 'Create team', class: "btn btn-primary" + %hr .padded %ul diff --git a/app/views/admin/teams/show.html.haml b/app/views/admin/teams/show.html.haml index e5d079981c..abdfada8c5 100644 --- a/app/views/admin/teams/show.html.haml +++ b/app/views/admin/teams/show.html.haml @@ -16,7 +16,13 @@   = link_to edit_admin_team_path(@team), class: "btn btn-small pull-right" do %i.icon-edit - Rename + Edit + %tr + %td + %b + Description: + %td + = @team.description %tr %td %b diff --git a/app/views/dashboard/_teams.html.haml b/app/views/dashboard/_teams.html.haml index f56115856a..76e9785ee2 100644 --- a/app/views/dashboard/_teams.html.haml +++ b/app/views/dashboard/_teams.html.haml @@ -1,4 +1,4 @@ -.ui-box.teams-box +.ui-box.teams_box %h5.title Teams %small @@ -12,9 +12,11 @@ %li = link_to team_path(id: team.path), class: dom_class(team) do %strong.well-title= truncate(team.name, length: 35) - %span.pull-right.light - - if team.owner == current_user - %i.icon-wrench - - tm = current_user.user_team_user_relationships.find_by_user_team_id(team.id) - - if tm - = tm.access_human + %span.edit.light + - if team.owner == current_user + %i.icon-wrench + - tm = current_user.user_team_user_relationships.find_by_user_team_id(team.id) + - if tm + = tm.access_human + %span.description + %strong= team.description diff --git a/db/migrate/20130207104426_add_description_to_teams.rb b/db/migrate/20130207104426_add_description_to_teams.rb new file mode 100644 index 0000000000..6d03777901 --- /dev/null +++ b/db/migrate/20130207104426_add_description_to_teams.rb @@ -0,0 +1,5 @@ +class AddDescriptionToTeams < ActiveRecord::Migration + def change + add_column :user_teams, :description, :string, default: '', null: false + end +end From b4648c3b521f2160bd4d7f47267dfaf204456825 Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Thu, 7 Feb 2013 17:11:31 +0400 Subject: [PATCH 050/113] Spinach tests fixed --- 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 1abb0f4912..ef432824ea 100644 --- a/features/steps/userteams/userteams.rb +++ b/features/steps/userteams/userteams.rb @@ -8,7 +8,7 @@ class Userteams < Spinach::FeatureSteps end Then 'I should see dashboard page without teams info block' do - page.has_no_css?(".teams-box").must_equal true + page.has_no_css?(".teams_box").must_equal true end When 'I have teams with my membership' do @@ -17,7 +17,7 @@ class Userteams < Spinach::FeatureSteps end Then 'I should see dashboard page with teams information block' do - page.should have_css(".teams-box") + page.should have_css(".teams_box") end When 'exist user teams' do From ba5373805a1e3396434df3dc023b8b573374b5a1 Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Fri, 8 Feb 2013 12:16:08 +0400 Subject: [PATCH 051/113] Description added to user temas factory --- spec/factories/user_teams.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/factories/user_teams.rb b/spec/factories/user_teams.rb index 1a9ae8e885..8d1ee11ee7 100644 --- a/spec/factories/user_teams.rb +++ b/spec/factories/user_teams.rb @@ -15,6 +15,7 @@ FactoryGirl.define do factory :user_team do sequence(:name) { |n| "team#{n}" } + sequence(:description) { |n| "team_description#{n}" } path { name.downcase.gsub(/\s/, '_') } owner end From 3d4e32457b66f5fa49bc35d938ec27ab24b7f15b Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Fri, 8 Feb 2013 15:42:14 +0400 Subject: [PATCH 052/113] Table description indentation fixed --- app/models/namespace.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/models/namespace.rb b/app/models/namespace.rb index 992ead4fda..c6b3e94d05 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -2,14 +2,14 @@ # # Table name: namespaces # -# id :integer not null, primary key -# name :string(255) not null +# id :integer not null, primary key +# name :string(255) not null # description :string(255) not null -# path :string(255) not null -# owner_id :integer not null -# created_at :datetime not null -# updated_at :datetime not null -# type :string(255) +# path :string(255) not null +# owner_id :integer not null +# created_at :datetime not null +# updated_at :datetime not null +# type :string(255) # class Namespace < ActiveRecord::Base From 9959669f1cb533e14e5df8d240c7560a2f258f84 Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Thu, 14 Feb 2013 12:14:34 +0400 Subject: [PATCH 053/113] Desctiptions removed from dashboard --- app/assets/stylesheets/application.scss | 2 -- app/assets/stylesheets/sections/groups.scss | 31 --------------------- app/assets/stylesheets/sections/teams.scss | 31 --------------------- app/views/dashboard/_groups.html.haml | 10 +++---- app/views/dashboard/_teams.html.haml | 16 +++++------ features/steps/userteams/userteams.rb | 4 +-- 6 files changed, 13 insertions(+), 81 deletions(-) delete mode 100644 app/assets/stylesheets/sections/groups.scss delete mode 100644 app/assets/stylesheets/sections/teams.scss diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 25cef4324c..6b500b8882 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -20,8 +20,6 @@ @import "sections/nav.scss"; @import "sections/commits.scss"; @import "sections/issues.scss"; -@import "sections/groups.scss"; -@import "sections/teams.scss"; @import "sections/projects.scss"; @import "sections/snippets.scss"; @import "sections/votes.scss"; diff --git a/app/assets/stylesheets/sections/groups.scss b/app/assets/stylesheets/sections/groups.scss deleted file mode 100644 index 9f5dc15a73..0000000000 --- a/app/assets/stylesheets/sections/groups.scss +++ /dev/null @@ -1,31 +0,0 @@ -.projects { - @extend .row; - .activities { - } - - .side { - @extend .right; - - .groups_box { - > .title { - padding: 2px 15px; - } - .well-list { - li { padding: 15px; } - .edit { - float: right; - margin: 0; - } - .description { - padding-top: 5px; - display: block; - span, strong { - font-size: 12px; - color: #666; - } - } - } - @extend .ui-box; - } - } -} diff --git a/app/assets/stylesheets/sections/teams.scss b/app/assets/stylesheets/sections/teams.scss deleted file mode 100644 index b5c546ca5f..0000000000 --- a/app/assets/stylesheets/sections/teams.scss +++ /dev/null @@ -1,31 +0,0 @@ -.projects { - @extend .row; - .activities { - } - - .side { - @extend .right; - - .teams_box { - > .title { - padding: 2px 15px; - } - .well-list { - li { padding: 15px; } - .edit { - float: right; - margin: 0; - } - .description { - padding-top: 5px; - display: block; - span, strong { - font-size: 12px; - color: #666; - } - } - } - @extend .ui-box; - } - } -} diff --git a/app/views/dashboard/_groups.html.haml b/app/views/dashboard/_groups.html.haml index 8c1dfc1232..ba8d3029ea 100644 --- a/app/views/dashboard/_groups.html.haml +++ b/app/views/dashboard/_groups.html.haml @@ -1,4 +1,4 @@ -.groups_box +.ui-box %h5.title Groups %small @@ -13,8 +13,6 @@ %li = link_to group_path(id: group.path), class: dom_class(group) do %strong.well-title= truncate(group.name, length: 35) - %span.edit.light - - if group.owner == current_user - %i.icon-wrench - %span.description - %strong= group.description + %span.pull-right.light + - if group.owner == current_user + %i.icon-wrench diff --git a/app/views/dashboard/_teams.html.haml b/app/views/dashboard/_teams.html.haml index 76e9785ee2..f56115856a 100644 --- a/app/views/dashboard/_teams.html.haml +++ b/app/views/dashboard/_teams.html.haml @@ -1,4 +1,4 @@ -.ui-box.teams_box +.ui-box.teams-box %h5.title Teams %small @@ -12,11 +12,9 @@ %li = link_to team_path(id: team.path), class: dom_class(team) do %strong.well-title= truncate(team.name, length: 35) - %span.edit.light - - if team.owner == current_user - %i.icon-wrench - - tm = current_user.user_team_user_relationships.find_by_user_team_id(team.id) - - if tm - = tm.access_human - %span.description - %strong= team.description + %span.pull-right.light + - if team.owner == current_user + %i.icon-wrench + - tm = current_user.user_team_user_relationships.find_by_user_team_id(team.id) + - if tm + = tm.access_human diff --git a/features/steps/userteams/userteams.rb b/features/steps/userteams/userteams.rb index ef432824ea..1abb0f4912 100644 --- a/features/steps/userteams/userteams.rb +++ b/features/steps/userteams/userteams.rb @@ -8,7 +8,7 @@ class Userteams < Spinach::FeatureSteps end Then 'I should see dashboard page without teams info block' do - page.has_no_css?(".teams_box").must_equal true + page.has_no_css?(".teams-box").must_equal true end When 'I have teams with my membership' do @@ -17,7 +17,7 @@ class Userteams < Spinach::FeatureSteps end Then 'I should see dashboard page with teams information block' do - page.should have_css(".teams_box") + page.should have_css(".teams-box") end When 'exist user teams' do From cf6d9a222213e37c9490bd30ae3a9971ac1baff5 Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Tue, 19 Feb 2013 23:01:57 +0400 Subject: [PATCH 054/113] Tests for team and group descriptions added --- features/steps/admin/admin_groups.rb | 2 ++ features/steps/admin/admin_teams.rb | 2 ++ features/steps/group/group.rb | 2 ++ features/steps/userteams/userteams.rb | 7 +++++++ features/teams/team.feature | 1 + 5 files changed, 14 insertions(+) diff --git a/features/steps/admin/admin_groups.rb b/features/steps/admin/admin_groups.rb index cbca2daa70..167763b691 100644 --- a/features/steps/admin/admin_groups.rb +++ b/features/steps/admin/admin_groups.rb @@ -25,11 +25,13 @@ class AdminGroups < Spinach::FeatureSteps And 'submit form with new group info' do fill_in 'group_name', :with => 'gitlab' + fill_in 'group_description', :with => 'Group description' click_button "Create group" end Then 'I should see newly created group' do page.should have_content "Group: gitlab" + page.should have_content "Group description" end Then 'I should be redirected to group page' do diff --git a/features/steps/admin/admin_teams.rb b/features/steps/admin/admin_teams.rb index 637fc4e58f..6423f3dfd9 100644 --- a/features/steps/admin/admin_teams.rb +++ b/features/steps/admin/admin_teams.rb @@ -18,6 +18,7 @@ class AdminTeams < Spinach::FeatureSteps And 'submit form with new team info' do fill_in 'user_team_name', with: 'gitlab' + fill_in 'user_team_description', with: 'description' click_button 'Create team' end @@ -27,6 +28,7 @@ class AdminTeams < Spinach::FeatureSteps And 'I should see newly created team' do page.should have_content "Team: gitlab" + page.should have_content "description" end When 'I visit admin teams page' do diff --git a/features/steps/group/group.rb b/features/steps/group/group.rb index 5cfa4756ac..3438ad8dda 100644 --- a/features/steps/group/group.rb +++ b/features/steps/group/group.rb @@ -70,11 +70,13 @@ class Groups < Spinach::FeatureSteps And 'submit form with new group info' do fill_in 'group_name', :with => 'Samurai' + fill_in 'group_description', :with => 'Tokugawa Shogunate' click_button "Create group" end Then 'I should see newly created group' do page.should have_content "Samurai" + page.should have_content "Tokugawa Shogunate" page.should have_content "You will only see events from projects in this group" end diff --git a/features/steps/userteams/userteams.rb b/features/steps/userteams/userteams.rb index 1abb0f4912..862259dcb4 100644 --- a/features/steps/userteams/userteams.rb +++ b/features/steps/userteams/userteams.rb @@ -44,9 +44,16 @@ class Userteams < Spinach::FeatureSteps And 'I submit form with new team info' do fill_in 'name', with: 'gitlab' + + fill_in 'user_team_description', with: 'team description' click_button 'Create team' end + And 'I should see newly created team' do + page.should have_content "gitlab" + page.should have_content "team description" + end + Then 'I should be redirected to new team page' do team = UserTeam.last current_path.should == team_path(team) diff --git a/features/teams/team.feature b/features/teams/team.feature index 9255e0daad..f7774597dc 100644 --- a/features/teams/team.feature +++ b/features/teams/team.feature @@ -20,6 +20,7 @@ Feature: UserTeams When I click to "New team" link And I submit form with new team info Then I should be redirected to new team page + Then I should see newly created team Scenario: I should see team dashboard list When I have teams with projects and members From 9c747fbb95ed795b7159db79cea76ab8e4bd3da0 Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Tue, 19 Feb 2013 23:02:25 +0400 Subject: [PATCH 055/113] Missing descriptions added --- app/views/admin/teams/edit.html.haml | 2 +- app/views/admin/teams/new.html.haml | 2 +- app/views/groups/edit.html.haml | 11 +++++++++-- app/views/groups/new.html.haml | 12 ++++++++++-- app/views/groups/show.html.haml | 5 +++++ app/views/teams/edit.html.haml | 10 ++++++++-- app/views/teams/new.html.haml | 11 +++++++++-- app/views/teams/show.html.haml | 5 +++++ 8 files changed, 48 insertions(+), 10 deletions(-) diff --git a/app/views/admin/teams/edit.html.haml b/app/views/admin/teams/edit.html.haml index a48a369b3b..0a3d993b13 100644 --- a/app/views/admin/teams/edit.html.haml +++ b/app/views/admin/teams/edit.html.haml @@ -10,7 +10,7 @@ .input = f.text_field :name, placeholder: "Example Team", class: "xxlarge" - .clearfix.team_description_holder + .clearfix.team-description-holder = f.label :description, "Details" .input = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4 diff --git a/app/views/admin/teams/new.html.haml b/app/views/admin/teams/new.html.haml index a852b4cbbf..1c90cb20c1 100644 --- a/app/views/admin/teams/new.html.haml +++ b/app/views/admin/teams/new.html.haml @@ -10,7 +10,7 @@ .input = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left" - .clearfix.team_description_holder + .clearfix.team-description-holder = f.label :description, "Details" .input = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4 diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml index 41ebf60698..828a9b430c 100644 --- a/app/views/groups/edit.html.haml +++ b/app/views/groups/edit.html.haml @@ -9,8 +9,15 @@ Group name is .input = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left" -   - = f.submit 'Save group', class: "btn btn-save" + + .clearfix.group_description_holder + = f.label :description, "Details" + .input + = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4 + + .form-actions + = f.submit 'Save group', class: "btn btn-save" + %hr diff --git a/app/views/groups/new.html.haml b/app/views/groups/new.html.haml index 73be474e27..9308e9a674 100644 --- a/app/views/groups/new.html.haml +++ b/app/views/groups/new.html.haml @@ -9,8 +9,16 @@ Group name is .input = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left" -   - = f.submit 'Create group', class: "btn btn-create" + + .clearfix.group_description_holder + = f.label :description, "Details" + .input + = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4 + + .form-actions + = f.submit 'Create group', class: "btn btn-primary" + + %hr .padded %ul diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml index a140b401b9..fe08e0b551 100644 --- a/app/views/groups/show.html.haml +++ b/app/views/groups/show.html.haml @@ -1,3 +1,8 @@ +- if @group.description.present? + .description + = @group.description + %hr + .projects .activities.span8 = render "events/event_last_push", event: @last_push diff --git a/app/views/teams/edit.html.haml b/app/views/teams/edit.html.haml index 751fe94c65..5491993d5f 100644 --- a/app/views/teams/edit.html.haml +++ b/app/views/teams/edit.html.haml @@ -12,13 +12,20 @@ .input = f.text_field :name, placeholder: "Ex. OpenSource", class: "xlarge left" + .clearfix.team-description-holder + = f.label :description, "Details" + .input + = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4 + .clearfix = f.label :path do Team path is .input = f.text_field :path, placeholder: "opensource", class: "xlarge left" + .form-actions - = f.submit 'Save team changes', class: "btn btn-save" + = f.submit 'Save team changes', class: "btn btn-primary" + = link_to 'Delete team', team_path(@team), method: :delete, confirm: "You are shure?", class: "btn btn-remove pull-right" .span5 .ui-box %h5.title Remove team @@ -26,4 +33,3 @@ %p Removed team can not be restored! = link_to 'Remove team', team_path(@team), method: :delete, confirm: "You are sure?", class: "btn btn-remove btn-small" - diff --git a/app/views/teams/new.html.haml b/app/views/teams/new.html.haml index 7089f79155..332a6a558d 100644 --- a/app/views/teams/new.html.haml +++ b/app/views/teams/new.html.haml @@ -9,8 +9,15 @@ Team name is .input = f.text_field :name, placeholder: "Ex. Ruby Developers", class: "xxlarge left" -   - = f.submit 'Create team', class: "btn btn-create" + + .clearfix.team-description-holder + = f.label :description, "Details" + .input + = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4 + + .form-actions + = f.submit 'Create team', class: "btn btn-create" + %hr .padded %ul diff --git a/app/views/teams/show.html.haml b/app/views/teams/show.html.haml index d6e80e2a51..eef13cbe76 100644 --- a/app/views/teams/show.html.haml +++ b/app/views/teams/show.html.haml @@ -1,3 +1,8 @@ +- if @group.description.present? + .description + = @group.description + %hr + .projects .activities.span8 = link_to dashboard_path, class: 'btn btn-tiny' do From dec15a41420733b9ce75c1939d871f6406142975 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Feb 2013 16:13:24 +0200 Subject: [PATCH 056/113] Add instruction to edit gitlab-shell config --- doc/install/installation.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index 4d2ab63b2e..42114235ca 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -103,9 +103,14 @@ Create a `git` user for Gitlab: # Clone gitlab shell git clone https://github.com/gitlabhq/gitlab-shell.git - # Setup cd gitlab-shell cp config.yml.example config.yml + + # Edit config and replace gitlab_url + # with something like 'http://domain.com/' + vim config.yml + + # Do setup ./bin/install From 6393ed6a418a628cfe37688558fe1a58a489a4ab Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Feb 2013 16:21:58 +0200 Subject: [PATCH 057/113] add description what is gitlab-shell --- doc/install/installation.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/install/installation.md b/doc/install/installation.md index 42114235ca..2de6bab97c 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -92,8 +92,11 @@ Create a `git` user for Gitlab: sudo adduser --disabled-login --gecos 'GitLab' git + # 4. GitLab shell +GitLab Shell is a ssh access and repository management software developed specially for GitLab. + # Login as git sudo su git From d3f042a6f2bab3553dd4202637dfb916d8243cd6 Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Thu, 28 Feb 2013 18:35:27 +0400 Subject: [PATCH 058/113] Css classes improved --- app/views/admin/groups/edit.html.haml | 2 +- app/views/admin/groups/new.html.haml | 2 +- app/views/groups/edit.html.haml | 2 +- app/views/groups/new.html.haml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/views/admin/groups/edit.html.haml b/app/views/admin/groups/edit.html.haml index f34ed83fb8..bb1398f66c 100644 --- a/app/views/admin/groups/edit.html.haml +++ b/app/views/admin/groups/edit.html.haml @@ -10,7 +10,7 @@ .input = f.text_field :name, placeholder: "Example Group", class: "xxlarge" - .clearfix.group_description_holder + .clearfix.group-description-holder = f.label :description, "Details" .input = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4 diff --git a/app/views/admin/groups/new.html.haml b/app/views/admin/groups/new.html.haml index 29bbcc55c9..3fa63e1ba2 100644 --- a/app/views/admin/groups/new.html.haml +++ b/app/views/admin/groups/new.html.haml @@ -9,7 +9,7 @@ Group name is .input = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left" - .clearfix.group_description_holder + .clearfix.group-description-holder = f.label :description, "Details" .input = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4 diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml index 828a9b430c..bf16b70c7f 100644 --- a/app/views/groups/edit.html.haml +++ b/app/views/groups/edit.html.haml @@ -10,7 +10,7 @@ .input = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left" - .clearfix.group_description_holder + .clearfix.group-description-holder = f.label :description, "Details" .input = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4 diff --git a/app/views/groups/new.html.haml b/app/views/groups/new.html.haml index 9308e9a674..2104db8684 100644 --- a/app/views/groups/new.html.haml +++ b/app/views/groups/new.html.haml @@ -10,7 +10,7 @@ .input = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left" - .clearfix.group_description_holder + .clearfix.group-description-holder = f.label :description, "Details" .input = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4 From 7ed08786542ebb62ca9d1f7943d148c0290032a7 Mon Sep 17 00:00:00 2001 From: Thomas Berger Date: Fri, 11 Jan 2013 17:53:30 +0100 Subject: [PATCH 059/113] added text-templates for mail notification --- app/views/notify/issue_status_changed_email.text.erb | 4 ++++ app/views/notify/new_issue_email.text.erb | 4 ++++ app/views/notify/new_merge_request_email.text.erb | 9 +++++++++ app/views/notify/new_user_email.text.erb | 8 ++++++++ app/views/notify/note_commit_email.text.erb | 9 +++++++++ app/views/notify/note_issue_email.text.erb | 9 +++++++++ app/views/notify/note_merge_request_email.text.erb | 9 +++++++++ app/views/notify/note_wall_email.text.erb | 9 +++++++++ app/views/notify/project_access_granted_email.text.erb | 4 ++++ app/views/notify/project_was_moved_email.text.erb | 8 ++++++++ app/views/notify/reassigned_issue_email.text.erb | 7 +++++++ app/views/notify/reassigned_merge_request_email.text.erb | 7 +++++++ 12 files changed, 87 insertions(+) create mode 100644 app/views/notify/issue_status_changed_email.text.erb create mode 100644 app/views/notify/new_issue_email.text.erb create mode 100644 app/views/notify/new_merge_request_email.text.erb create mode 100644 app/views/notify/new_user_email.text.erb create mode 100644 app/views/notify/note_commit_email.text.erb create mode 100644 app/views/notify/note_issue_email.text.erb create mode 100644 app/views/notify/note_merge_request_email.text.erb create mode 100644 app/views/notify/note_wall_email.text.erb create mode 100644 app/views/notify/project_access_granted_email.text.erb create mode 100644 app/views/notify/project_was_moved_email.text.erb create mode 100644 app/views/notify/reassigned_issue_email.text.erb create mode 100644 app/views/notify/reassigned_merge_request_email.text.erb diff --git a/app/views/notify/issue_status_changed_email.text.erb b/app/views/notify/issue_status_changed_email.text.erb new file mode 100644 index 0000000000..bbca3474d5 --- /dev/null +++ b/app/views/notify/issue_status_changed_email.text.erb @@ -0,0 +1,4 @@ +Issue was <%= @issue_status %> by <%= @updated_by.name %> + +Issue <%= @issue.id %>: <%= url_for(project_issue_url(@issue.project, @issue)) %> + diff --git a/app/views/notify/new_issue_email.text.erb b/app/views/notify/new_issue_email.text.erb new file mode 100644 index 0000000000..5ed55c35b2 --- /dev/null +++ b/app/views/notify/new_issue_email.text.erb @@ -0,0 +1,4 @@ +New Issue was created and assigned to you. + + +Issue <%= @issue.id %>: <%= url_for(project_issue_url(@issue.project, @issue)) %> diff --git a/app/views/notify/new_merge_request_email.text.erb b/app/views/notify/new_merge_request_email.text.erb new file mode 100644 index 0000000000..3393d8384f --- /dev/null +++ b/app/views/notify/new_merge_request_email.text.erb @@ -0,0 +1,9 @@ +New Merge Request <%= @merge_request.id %> + +<%= url_for(project_merge_request_url(@merge_request.project, @merge_request)) %> + + +Branches: <%= @merge_request.source_branch %> to <%= @merge_request.target_branch %> +Author: <%= @merge_request.author_name %> +Asignee: <%= @merge_request.assignee_name %> + diff --git a/app/views/notify/new_user_email.text.erb b/app/views/notify/new_user_email.text.erb new file mode 100644 index 0000000000..794d5a2c3e --- /dev/null +++ b/app/views/notify/new_user_email.text.erb @@ -0,0 +1,8 @@ +Hi <%= @user.name %>! + +Administrator created account for you. Now you are a member of company GitLab application. + +login.................. <%= @user.email %> +password............... <%= @password %> + +Click here to login: <%= url_for(root_url) %> diff --git a/app/views/notify/note_commit_email.text.erb b/app/views/notify/note_commit_email.text.erb new file mode 100644 index 0000000000..aab8e5cfb6 --- /dev/null +++ b/app/views/notify/note_commit_email.text.erb @@ -0,0 +1,9 @@ +New comment for Commit <%= @commit.short_id %> + +<%= url_for(project_commit_url(@note.project, id: @commit.id, anchor: "note_#{@note.id}")) %> + + +Author: <%= @note.author_name %> + +<%= @note.note %> + diff --git a/app/views/notify/note_issue_email.text.erb b/app/views/notify/note_issue_email.text.erb new file mode 100644 index 0000000000..a476b286ae --- /dev/null +++ b/app/views/notify/note_issue_email.text.erb @@ -0,0 +1,9 @@ +New comment for Issue <%= @issue.id %> + +<%= url_for(project_issue_url(@issue.project, @issue, anchor: "note_#{@note.id}")) %> + + +Author: <%= @note.author_name %> + +<%= @note.note %> + diff --git a/app/views/notify/note_merge_request_email.text.erb b/app/views/notify/note_merge_request_email.text.erb new file mode 100644 index 0000000000..26c73bdaa3 --- /dev/null +++ b/app/views/notify/note_merge_request_email.text.erb @@ -0,0 +1,9 @@ +New comment for Merge Request <%= @merge_request.id %> + +<%= url_for(project_merge_request_url(@merge_request.project, @merge_request, anchor: "note_#{@note.id}")) %> + + +<%= @note.author_name %> + +<%= @note.note %> + diff --git a/app/views/notify/note_wall_email.text.erb b/app/views/notify/note_wall_email.text.erb new file mode 100644 index 0000000000..ea1b7efbe8 --- /dev/null +++ b/app/views/notify/note_wall_email.text.erb @@ -0,0 +1,9 @@ +New message on the project wall <%= @note.project %> + +<%= url_for(wall_project_url(@note.project, anchor: "note_#{@note.id}")) %> + + +<%= @note.author_name %> + +<%= @note.note %> + diff --git a/app/views/notify/project_access_granted_email.text.erb b/app/views/notify/project_access_granted_email.text.erb new file mode 100644 index 0000000000..077c3b8a7d --- /dev/null +++ b/app/views/notify/project_access_granted_email.text.erb @@ -0,0 +1,4 @@ + +You have been granted <%= @users_project.project_access_human %> access to project <%= @project.name_with_namespace %> + +<%= url_for(project_url(@project)) %> diff --git a/app/views/notify/project_was_moved_email.text.erb b/app/views/notify/project_was_moved_email.text.erb new file mode 100644 index 0000000000..da123c2f89 --- /dev/null +++ b/app/views/notify/project_was_moved_email.text.erb @@ -0,0 +1,8 @@ +Project was moved to another location + +The project is now located under +<%= url_for(link_to project_url(@project)) %> + + +To update the remote url in your local repository run: + git remote set-url origin <%= @project.ssh_url_to_repo %> diff --git a/app/views/notify/reassigned_issue_email.text.erb b/app/views/notify/reassigned_issue_email.text.erb new file mode 100644 index 0000000000..497044184d --- /dev/null +++ b/app/views/notify/reassigned_issue_email.text.erb @@ -0,0 +1,7 @@ +Reassigned Issue <%= @issue.id %> + +<%= url_for(project_issue_url(@issue.project, @issue)) %> + + +Assignee changed from <%= @previous_assignee.name %> to <%= @issue.assignee_name %> + diff --git a/app/views/notify/reassigned_merge_request_email.text.erb b/app/views/notify/reassigned_merge_request_email.text.erb new file mode 100644 index 0000000000..1af4ab559f --- /dev/null +++ b/app/views/notify/reassigned_merge_request_email.text.erb @@ -0,0 +1,7 @@ +Reassigned Merge Request <%= @merge_request.id %> + +<%= url_for(project_merge_request_url(@merge_request.project, @merge_request)) %> + + +Assignee changed from <%= @previous_assignee.name %> to <%= @merge_request.assignee_name %> + From 2f1f05d431d1df062e46365930b98b358554a07d Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Thu, 28 Feb 2013 18:55:35 +0400 Subject: [PATCH 060/113] Fixed notes from randx --- app/views/teams/show.html.haml | 4 ++-- db/schema.rb | 21 ++++++++++----------- features/steps/group/group.rb | 4 ++-- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/app/views/teams/show.html.haml b/app/views/teams/show.html.haml index eef13cbe76..34be769241 100644 --- a/app/views/teams/show.html.haml +++ b/app/views/teams/show.html.haml @@ -1,6 +1,6 @@ -- if @group.description.present? +- if @team.description.present? .description - = @group.description + = @team.description %hr .projects diff --git a/db/schema.rb b/db/schema.rb index 63f498e4a6..e0ad8294e7 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -143,18 +143,16 @@ ActiveRecord::Schema.define(:version => 20130220133245) do t.string "name" t.string "path" t.text "description" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false t.integer "creator_id" t.string "default_branch" - t.boolean "issues_enabled", :default => true, :null => false - t.boolean "wall_enabled", :default => true, :null => false - t.boolean "merge_requests_enabled", :default => true, :null => false - t.boolean "wiki_enabled", :default => true, :null => false + t.boolean "issues_enabled", :default => true, :null => false + t.boolean "wall_enabled", :default => true, :null => false + t.boolean "merge_requests_enabled", :default => true, :null => false + t.boolean "wiki_enabled", :default => true, :null => false t.integer "namespace_id" - t.boolean "public", :default => false, :null => false - t.string "issues_tracker", :default => "gitlab", :null => false - t.string "issues_tracker_id" + t.boolean "public", :default => false, :null => false end add_index "projects", ["creator_id"], :name => "index_projects_on_owner_id" @@ -233,8 +231,9 @@ ActiveRecord::Schema.define(:version => 20130220133245) do t.string "name" t.string "path" t.integer "owner_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "description", :default => "", :null => false end create_table "users", :force => true do |t| diff --git a/features/steps/group/group.rb b/features/steps/group/group.rb index 3438ad8dda..75db9fef14 100644 --- a/features/steps/group/group.rb +++ b/features/steps/group/group.rb @@ -69,8 +69,8 @@ class Groups < Spinach::FeatureSteps end And 'submit form with new group info' do - fill_in 'group_name', :with => 'Samurai' - fill_in 'group_description', :with => 'Tokugawa Shogunate' + fill_in 'group_name', with: 'Samurai' + fill_in 'group_description', with: 'Tokugawa Shogunate' click_button "Create group" end From 115454f3ed35d136c2edd77296ffff97570a6822 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Feb 2013 17:46:28 +0200 Subject: [PATCH 061/113] created-by-me filter for issues inside project. Fixed global project.issues order --- app/contexts/issues_list_context.rb | 5 +++-- app/helpers/issues_helper.rb | 3 ++- app/models/issue.rb | 4 ++++ app/models/project.rb | 2 +- app/views/issues/_filter.html.haml | 5 ++++- 5 files changed, 14 insertions(+), 5 deletions(-) diff --git a/app/contexts/issues_list_context.rb b/app/contexts/issues_list_context.rb index 0cc73f9953..0765b30c35 100644 --- a/app/contexts/issues_list_context.rb +++ b/app/contexts/issues_list_context.rb @@ -7,12 +7,13 @@ class IssuesListContext < BaseContext @issues = case params[:status] when issues_filter[:all] then @project.issues when issues_filter[:closed] then @project.issues.closed - when issues_filter[:to_me] then @project.issues.opened.assigned(current_user) + when issues_filter[:to_me] then @project.issues.assigned(current_user) + when issues_filter[:by_me] then @project.issues.authored(current_user) else @project.issues.opened end @issues = @issues.tagged_with(params[:label_name]) if params[:label_name].present? - @issues = @issues.includes(:author, :project).order("updated_at") + @issues = @issues.includes(:author, :project) # Filter by specific assignee_id (or lack thereof)? if params[:assignee_id].present? diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index 8321518049..54385117c2 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -27,6 +27,7 @@ module IssuesHelper all: "all", closed: "closed", to_me: "assigned-to-me", + by_me: "created-by-me", open: "open" } end @@ -45,7 +46,7 @@ module IssuesHelper return "" if @project.nil? if @project.used_default_issues_tracker? - project_issues_filter_path(@project) + project_issues_filter_path(@project) else url = Settings[:issues_tracker][@project.issues_tracker]["project_url"] url.gsub(':project_id', @project.id.to_s) diff --git a/app/models/issue.rb b/app/models/issue.rb index 112f43c469..f01cad0a45 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -30,6 +30,10 @@ class Issue < ActiveRecord::Base where('assignee_id = :user', user: user.id) end + def authored(user) + where('author_id = :user', user: user.id) + end + def open_for(user) opened.assigned(user) end diff --git a/app/models/project.rb b/app/models/project.rb index 12f7e45496..02f1df13f9 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -45,7 +45,7 @@ class Project < ActiveRecord::Base has_many :events, dependent: :destroy has_many :merge_requests, dependent: :destroy - has_many :issues, dependent: :destroy, order: "state, created_at DESC" + has_many :issues, dependent: :destroy, order: "state DESC, created_at DESC" has_many :milestones, dependent: :destroy has_many :users_projects, dependent: :destroy has_many :notes, dependent: :destroy diff --git a/app/views/issues/_filter.html.haml b/app/views/issues/_filter.html.haml index 21efaa5357..b621f11bc5 100644 --- a/app/views/issues/_filter.html.haml +++ b/app/views/issues/_filter.html.haml @@ -6,7 +6,10 @@ Open %li{class: ("active" if params[:status] == 'assigned-to-me')} = link_to project_issues_path(@project, status: 'assigned-to-me') do - Assigned To Me + Assigned to me + %li{class: ("active" if params[:status] == 'created-by-me')} + = link_to project_issues_path(@project, status: 'created-by-me') do + Created by me %li{class: ("active" if params[:status] == 'closed')} = link_to project_issues_path(@project, status: 'closed') do Closed From b1f58fcaeab2320b549522c8ae792d57535224a6 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Feb 2013 19:29:21 +0200 Subject: [PATCH 062/113] allow any attachment filenames --- config/routes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/routes.rb b/config/routes.rb index 7537a11de9..57eefe23ab 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -48,7 +48,7 @@ Gitlab::Application.routes.draw do # # Attachments serving # - get 'files/:type/:id/:filename' => 'files#download', constraints: { id: /\d+/, type: /[a-z]+/, filename: /[a-zA-Z.0-9_\-\+]+/ } + get 'files/:type/:id/:filename' => 'files#download', constraints: { id: /\d+/, type: /[a-z]+/, filename: /.+/ } # # Admin Area From 9c40002625b34588435456e5487d2b174566b9f5 Mon Sep 17 00:00:00 2001 From: Un1matr1x Date: Thu, 28 Feb 2013 18:30:07 +0100 Subject: [PATCH 063/113] docs improvement --- README.md | 2 +- ROADMAP.md | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index b8ae9d3845..267f42360b 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ With GitLab you can: * master: ci.gitlab.org [![CI](http://ci.gitlab.org/projects/1/status?ref=master)](http://ci.gitlab.org/projects/1?ref=master) -* [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/gitlabhq/gitlabhq) +* [![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.png)](https://codeclimate.com/github/gitlabhq/gitlabhq) * [![Dependency Status](https://gemnasium.com/gitlabhq/gitlabhq.png)](https://gemnasium.com/gitlabhq/gitlabhq) ### Application details diff --git a/ROADMAP.md b/ROADMAP.md index d148b518b0..bf4fe69543 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -4,9 +4,4 @@ * Replace gitolite with gitlab-shell * Usability improvements -* Notification improvements - -### v4.2 February 22 - -* Teams - +* Notification improvements \ No newline at end of file From 1c517153a889f77f0a2c321ce4e013f4504253e9 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Feb 2013 19:56:16 +0200 Subject: [PATCH 064/113] fix admin users tests --- app/views/notify/new_user_email.text.erb | 4 +++- spec/features/admin/admin_users_spec.rb | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app/views/notify/new_user_email.text.erb b/app/views/notify/new_user_email.text.erb index 794d5a2c3e..94072d7fe5 100644 --- a/app/views/notify/new_user_email.text.erb +++ b/app/views/notify/new_user_email.text.erb @@ -3,6 +3,8 @@ Hi <%= @user.name %>! Administrator created account for you. Now you are a member of company GitLab application. login.................. <%= @user.email %> -password............... <%= @password %> +<% unless Gitlab.config.gitlab.signup_enabled %> + password............... <%= @password %> +<% end %> Click here to login: <%= url_for(root_url) %> diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb index 77d6e9e379..22d1ee9148 100644 --- a/spec/features/admin/admin_users_spec.rb +++ b/spec/features/admin/admin_users_spec.rb @@ -55,8 +55,8 @@ describe "Admin::Users" do user = User.last email = ActionMailer::Base.deliveries.last email.subject.should have_content("Account was created") - email.body.should have_content(user.email) - email.body.should have_content(@password) + email.text_part.body.should have_content(user.email) + email.text_part.body.should have_content(@password) end end @@ -67,8 +67,8 @@ describe "Admin::Users" do user = User.last email = ActionMailer::Base.deliveries.last email.subject.should have_content("Account was created") - email.body.should have_content(user.email) - email.body.should_not have_content(@password) + email.text_part.body.should have_content(user.email) + email.text_part.body.should_not have_content(@password) end end end From 00ae65b10808289252b1115eb86b90fcddc17d59 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Feb 2013 21:02:41 +0200 Subject: [PATCH 065/113] try to use stable version for database cleaner --- Gemfile | 2 +- Gemfile.lock | 10 ++-------- features/steps/project/project_merge_requests.rb | 4 ++-- features/support/env.rb | 1 + 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/Gemfile b/Gemfile index 723cfd8b05..e6dfec9f49 100644 --- a/Gemfile +++ b/Gemfile @@ -144,7 +144,7 @@ group :development, :test do gem "capybara", '2.0.2' gem "pry" gem "awesome_print" - gem "database_cleaner", ref: "9f898fc50d87a5d51760f9dcf374bf5ffda21baf", git: "https://github.com/bmabey/database_cleaner.git" + gem "database_cleaner" gem "launchy" gem 'factory_girl_rails' diff --git a/Gemfile.lock b/Gemfile.lock index 9ee413d473..76f1c214c5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,10 +1,3 @@ -GIT - remote: https://github.com/bmabey/database_cleaner.git - revision: 9f898fc50d87a5d51760f9dcf374bf5ffda21baf - ref: 9f898fc50d87a5d51760f9dcf374bf5ffda21baf - specs: - database_cleaner (0.9.1) - GIT remote: https://github.com/ctran/annotate_models.git revision: be4e26825b521f0b2d86b181e2dff89901aa9b1e @@ -133,6 +126,7 @@ GEM connection_pool (1.0.0) crack (0.3.1) daemons (1.1.9) + database_cleaner (0.9.1) debug_inspector (0.0.2) devise (2.1.2) bcrypt-ruby (~> 3.0) @@ -474,7 +468,7 @@ DEPENDENCIES chosen-rails (= 0.9.8) coffee-rails (~> 3.2.2) colored - database_cleaner! + database_cleaner devise (~> 2.1.0) draper (~> 0.18.0) email_spec diff --git a/features/steps/project/project_merge_requests.rb b/features/steps/project/project_merge_requests.rb index 09ce6b720d..4c22119b07 100644 --- a/features/steps/project/project_merge_requests.rb +++ b/features/steps/project/project_merge_requests.rb @@ -84,11 +84,11 @@ class ProjectMergeRequests < Spinach::FeatureSteps end And 'I switch to the diff tab' do - visit diffs_project_merge_request_path(merge_request.project, merge_request) + visit diffs_project_merge_request_path(project, merge_request) end And 'I switch to the merge request\'s comments tab' do - visit project_merge_request_path(merge_request.project, merge_request) + visit project_merge_request_path(project, merge_request) end And 'I click on the first commit in the merge request' do diff --git a/features/support/env.rb b/features/support/env.rb index da40b38b79..2fd7ffdb81 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -34,6 +34,7 @@ Spinach.hooks.before_scenario do Gitlab.config.gitlab_shell.stub(repos_path: Rails.root.join('tmp', 'test-git-base-path')) FileUtils.rm_rf Gitlab.config.gitlab_shell.repos_path FileUtils.mkdir_p Gitlab.config.gitlab_shell.repos_path + DatabaseCleaner.start end Spinach.hooks.after_scenario do From ed9543ff5d84b2087febc539b84f091a8ddea4c0 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Feb 2013 21:06:16 +0200 Subject: [PATCH 066/113] update devise gem --- Gemfile.lock | 8 ++++---- config/initializers/devise.rb | 2 +- config/locales/devise.en.yml | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 76f1c214c5..91f3790b83 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -128,7 +128,7 @@ GEM daemons (1.1.9) database_cleaner (0.9.1) debug_inspector (0.0.2) - devise (2.1.2) + devise (2.1.3) bcrypt-ruby (~> 3.0) orm_adapter (~> 0.1) railties (~> 3.1) @@ -219,7 +219,7 @@ GEM multi_json (~> 1.0) multi_xml httpauth (0.2.0) - i18n (0.6.1) + i18n (0.6.4) journey (1.0.4) jquery-atwho-rails (0.1.7) jquery-rails (2.1.3) @@ -343,7 +343,7 @@ GEM rb-fsevent (0.9.2) rb-inotify (0.8.8) ffi (>= 0.5.0) - rdoc (3.12.1) + rdoc (3.12.2) json (~> 1.4) redcarpet (2.2.2) redis (3.0.2) @@ -428,7 +428,7 @@ GEM eventmachine (>= 0.12.6) rack (>= 1.0.0) thor (0.17.0) - tilt (1.3.3) + tilt (1.3.4) timers (1.1.0) treetop (1.4.12) polyglot diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 97946c54b4..9c3976335f 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -99,7 +99,7 @@ Devise.setup do |config| # ==> Configuration for :validatable # Range for password length. Default is 6..128. - # config.password_length = 6..128 + config.password_length = 6..128 # Email regex used to validate email formats. It simply asserts that # an one (and only one) @ exists in the given string. This is mainly diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml index 3b763cf410..275273a0b1 100644 --- a/config/locales/devise.en.yml +++ b/config/locales/devise.en.yml @@ -17,6 +17,7 @@ en: unauthenticated: 'You need to sign in before continuing.' unconfirmed: 'You have to confirm your account before continuing.' locked: 'Your account is locked.' + not_found_in_database: 'Invalid email or password.' invalid: 'Invalid email or password.' invalid_token: 'Invalid authentication token.' timeout: 'Your session expired, please sign in again to continue.' From 547ae558d7bd21805d0c4b0d2665b84f5a4e6e59 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Feb 2013 21:11:12 +0200 Subject: [PATCH 067/113] update httparty --- Gemfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 91f3790b83..011b4adf9b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -215,9 +215,9 @@ GEM hashie (1.2.0) hike (1.2.1) http_parser.rb (0.5.3) - httparty (0.9.0) + httparty (0.10.2) multi_json (~> 1.0) - multi_xml + multi_xml (>= 0.5.2) httpauth (0.2.0) i18n (0.6.4) journey (1.0.4) @@ -251,7 +251,7 @@ GEM modernizr (2.6.2) sprockets (~> 2.0) multi_json (1.6.1) - multi_xml (0.5.1) + multi_xml (0.5.3) multipart-post (1.1.5) mysql2 (0.3.11) net-ldap (0.2.2) From 7a0af60b51c2e8e46f2cd35e7ab33199d1bb2651 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Feb 2013 21:14:00 +0200 Subject: [PATCH 068/113] update stamp --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 011b4adf9b..f9b13c5589 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -417,7 +417,7 @@ GEM multi_json (~> 1.0) rack (~> 1.0) tilt (~> 1.1, != 1.3.0) - stamp (0.3.0) + stamp (0.5.0) state_machine (1.1.2) temple (0.5.5) test_after_commit (0.0.1) From 0b52c461da6e22c68e2e124cd7e833a74021d0f6 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 1 Mar 2013 09:23:18 +0200 Subject: [PATCH 069/113] use grit_ext 0.6.2 --- Gemfile | 2 +- Gemfile.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gemfile b/Gemfile index e6dfec9f49..16b50680a9 100644 --- a/Gemfile +++ b/Gemfile @@ -24,7 +24,7 @@ gem 'omniauth-github' # GITLAB patched libs gem "grit", git: "https://github.com/gitlabhq/grit.git", ref: '9e98418ce2d654485b967003726aa2706a10060b' gem 'grack', git: "https://github.com/gitlabhq/grack.git", ref: 'ba46f3b0845c6a09d488ae6abdce6ede37e227e8' -gem 'grit_ext', git: "https://github.com/gitlabhq/grit_ext.git", ref: '8e6afc2da821354774aa4d1ee8a1aa2082f84a3e' +gem 'grit_ext', git: "https://github.com/gitlabhq/grit_ext.git", ref: '2d1b2f13cabc02520405985fccb2a0abfcba9907' # LDAP Auth gem 'gitlab_omniauth-ldap', '1.0.2', require: "omniauth-ldap" diff --git a/Gemfile.lock b/Gemfile.lock index f9b13c5589..1c60567ac4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -26,10 +26,10 @@ GIT GIT remote: https://github.com/gitlabhq/grit_ext.git - revision: 8e6afc2da821354774aa4d1ee8a1aa2082f84a3e - ref: 8e6afc2da821354774aa4d1ee8a1aa2082f84a3e + revision: 2d1b2f13cabc02520405985fccb2a0abfcba9907 + ref: 2d1b2f13cabc02520405985fccb2a0abfcba9907 specs: - grit_ext (0.6.1) + grit_ext (0.6.2) charlock_holmes (~> 0.6.9) GIT From f8009a4858fba2db871d8aecf9480021489da37c Mon Sep 17 00:00:00 2001 From: Sato Hiroyuki Date: Fri, 1 Mar 2013 17:28:29 +0900 Subject: [PATCH 070/113] Fix spinach errors. --- features/steps/project/project_network_graph.rb | 2 +- features/steps/shared/paths.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/features/steps/project/project_network_graph.rb b/features/steps/project/project_network_graph.rb index f26deff936..b66aadfeae 100644 --- a/features/steps/project/project_network_graph.rb +++ b/features/steps/project/project_network_graph.rb @@ -11,7 +11,7 @@ class ProjectNetworkGraph < Spinach::FeatureSteps And 'I visit project "Shop" network page' do # Stub Graph::JsonBuilder max_size to speed up test (10 commits vs. 650) - Gitlab::Graph::JsonBuilder.stub(max_count: 10) + Graph::JsonBuilder.stub(max_count: 10) project = Project.find_by_name("Shop") visit project_graph_path(project, "master") diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb index 40786f6e6d..431d5299d8 100644 --- a/features/steps/shared/paths.rb +++ b/features/steps/shared/paths.rb @@ -143,7 +143,7 @@ module SharedPaths Given "I visit my project's network page" do # Stub Graph::JsonBuilder max_size to speed up test (10 commits vs. 650) - Gitlab::Graph::JsonBuilder.stub(max_count: 10) + Graph::JsonBuilder.stub(max_count: 10) visit project_graph_path(@project, root_ref) end From 5da7424f8dc68a877aafcf8df6d67af28b8b945d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 1 Mar 2013 14:36:12 +0200 Subject: [PATCH 071/113] Gem updated: devise, grape, sidekiq, settingslogic --- Gemfile | 4 ++-- Gemfile.lock | 28 +++++++++++++++------------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/Gemfile b/Gemfile index 16b50680a9..5f5e081179 100644 --- a/Gemfile +++ b/Gemfile @@ -15,7 +15,7 @@ gem "mysql2", group: :mysql gem "pg", group: :postgres # Auth -gem "devise", "~> 2.1.0" +gem "devise" gem 'omniauth', "~> 1.1.1" gem 'omniauth-google-oauth2' gem 'omniauth-twitter' @@ -86,7 +86,7 @@ gem "draper", "~> 0.18.0" # Background jobs gem 'slim' gem 'sinatra', require: nil -gem 'sidekiq', '2.7.3' +gem 'sidekiq' # HTTP requests gem "httparty" diff --git a/Gemfile.lock b/Gemfile.lock index 1c60567ac4..0f89037e7d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -82,7 +82,7 @@ GEM addressable (2.3.2) arel (3.0.2) awesome_print (1.1.0) - backports (2.6.5) + backports (2.6.7) bcrypt-ruby (3.0.1) better_errors (0.3.2) coderay (>= 1.0.0) @@ -128,7 +128,8 @@ GEM daemons (1.1.9) database_cleaner (0.9.1) debug_inspector (0.0.2) - devise (2.1.3) + descendants_tracker (0.0.1) + devise (2.2.3) bcrypt-ruby (~> 3.0) orm_adapter (~> 0.1) railties (~> 3.1) @@ -181,19 +182,19 @@ GEM rubyntlm (~> 0.1.1) gitlab_yaml_db (1.0.0) gon (4.0.2) - grape (0.3.1) - actionpack (>= 2.3.0) + grape (0.3.2) activesupport - grape-entity (~> 0.2.0) - hashie (~> 1.2) - json + builder + hashie (>= 1.2.0) multi_json (>= 1.3.2) - multi_xml + multi_xml (>= 0.5.2) rack rack-accept rack-mount virtus grape-entity (0.2.0) + activesupport + multi_json (>= 1.3.2) growl (1.0.3) guard (1.5.4) listen (>= 0.4.2) @@ -382,11 +383,11 @@ GEM multi_json (~> 1.0) rubyzip websocket (~> 1.0.4) - settingslogic (2.0.8) + settingslogic (2.0.9) sexp_processor (4.1.3) shoulda-matchers (1.3.0) activesupport (>= 3.0.0) - sidekiq (2.7.3) + sidekiq (2.7.5) celluloid (~> 0.12.0) connection_pool (~> 1.0) multi_json (~> 1) @@ -441,8 +442,9 @@ GEM kgio (~> 2.6) rack raindrops (~> 0.7) - virtus (0.5.2) + virtus (0.5.4) backports (~> 2.6.1) + descendants_tracker (~> 0.0.1) warden (1.2.1) rack (>= 1.0) webmock (1.9.0) @@ -469,7 +471,7 @@ DEPENDENCIES coffee-rails (~> 3.2.2) colored database_cleaner - devise (~> 2.1.0) + devise draper (~> 0.18.0) email_spec enumerize @@ -526,7 +528,7 @@ DEPENDENCIES seed-fu settingslogic shoulda-matchers (= 1.3.0) - sidekiq (= 2.7.3) + sidekiq simplecov sinatra six From 153a4c142df90f769df68b333f533c639f923148 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 1 Mar 2013 15:09:11 +0200 Subject: [PATCH 072/113] updated gems: haml-rails, carrierwave --- Gemfile | 4 ++-- Gemfile.lock | 13 +++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Gemfile b/Gemfile index 5f5e081179..cf9117a886 100644 --- a/Gemfile +++ b/Gemfile @@ -53,10 +53,10 @@ gem 'enumerize' gem "kaminari", "~> 0.14.1" # HAML -gem "haml-rails", "~> 0.3.5" +gem "haml-rails" # Files attachments -gem "carrierwave", "~> 0.7.1" +gem "carrierwave" # Authorization gem "six" diff --git a/Gemfile.lock b/Gemfile.lock index 0f89037e7d..a375fdd830 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -99,7 +99,7 @@ GEM rack-test (>= 0.5.4) selenium-webdriver (~> 2.0) xpath (~> 1.0.0) - carrierwave (0.7.1) + carrierwave (0.8.0) activemodel (>= 3.2.0) activesupport (>= 3.2.0) celluloid (0.12.4) @@ -207,11 +207,12 @@ GEM guard-spinach (0.0.2) guard (>= 1.1) spinach - haml (3.1.7) - haml-rails (0.3.5) + haml (4.0.0) + tilt + haml-rails (0.4) actionpack (>= 3.1, < 4.1) activesupport (>= 3.1, < 4.1) - haml (~> 3.1) + haml (>= 3.1, < 4.1) railties (>= 3.1, < 4.1) hashie (1.2.0) hike (1.2.1) @@ -466,7 +467,7 @@ DEPENDENCIES binding_of_caller bootstrap-sass (= 2.2.1.1) capybara (= 2.0.2) - carrierwave (~> 0.7.1) + carrierwave chosen-rails (= 0.9.8) coffee-rails (~> 3.2.2) colored @@ -495,7 +496,7 @@ DEPENDENCIES growl guard-rspec guard-spinach - haml-rails (~> 0.3.5) + haml-rails httparty jquery-atwho-rails (= 0.1.7) jquery-rails (= 2.1.3) From 520f02259c7076ca44f298dd401ef9df2ac8c0d3 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 1 Mar 2013 15:15:29 +0200 Subject: [PATCH 073/113] gems updated: unicorn, draper, github-markup --- Gemfile | 4 ++-- Gemfile.lock | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Gemfile b/Gemfile index cf9117a886..5622c1a213 100644 --- a/Gemfile +++ b/Gemfile @@ -72,7 +72,7 @@ gem "redcarpet", "~> 2.2.2" gem "github-markup", "~> 0.7.4", require: 'github/markup' # Servers -gem "unicorn", "~> 4.4.0" +gem "unicorn" # State machine gem "state_machine" @@ -81,7 +81,7 @@ gem "state_machine" gem "acts-as-taggable-on", "2.3.3" # Decorators -gem "draper", "~> 0.18.0" +gem "draper" # Background jobs gem 'slim' diff --git a/Gemfile.lock b/Gemfile.lock index a375fdd830..f70c873527 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -135,9 +135,10 @@ GEM railties (~> 3.1) warden (~> 1.2.1) diff-lcs (1.1.3) - draper (0.18.0) - actionpack (~> 3.2) - activesupport (~> 3.2) + draper (1.1.0) + actionpack (>= 3.0) + activesupport (>= 3.0) + request_store (~> 1.0.3) email_spec (1.4.0) launchy (~> 2.1) mail (~> 2.2) @@ -173,7 +174,7 @@ GEM escape_utils (~> 0.2.3) mime-types (~> 1.19) pygments.rb (>= 0.2.13) - github-markup (0.7.4) + github-markup (0.7.5) gitlab_meta (5.0) gitlab_omniauth-ldap (1.0.2) net-ldap (~> 0.2.2) @@ -236,7 +237,7 @@ GEM kaminari (0.14.1) actionpack (>= 3.0.0) activesupport (>= 3.0.0) - kgio (2.7.4) + kgio (2.8.0) launchy (2.1.2) addressable (~> 2.3) letter_opener (1.0.0) @@ -351,6 +352,7 @@ GEM redis (3.0.2) redis-namespace (1.2.1) redis (~> 3.0.0) + request_store (1.0.5) rspec (2.12.0) rspec-core (~> 2.12.0) rspec-expectations (~> 2.12.0) @@ -439,7 +441,7 @@ GEM uglifier (1.3.0) execjs (>= 0.3.0) multi_json (~> 1.0, >= 1.0.2) - unicorn (4.4.0) + unicorn (4.6.2) kgio (~> 2.6) rack raindrops (~> 0.7) @@ -473,7 +475,7 @@ DEPENDENCIES colored database_cleaner devise - draper (~> 0.18.0) + draper email_spec enumerize factory_girl_rails @@ -541,5 +543,5 @@ DEPENDENCIES therubyracer thin uglifier (~> 1.3.0) - unicorn (~> 4.4.0) + unicorn webmock From 6aead7991f93c63e23fd96677a1c499ebca2155f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 1 Mar 2013 15:24:59 +0200 Subject: [PATCH 074/113] fix decorate calls on collections after draper update --- app/controllers/admin/teams/members_controller.rb | 2 +- app/controllers/commits_controller.rb | 2 +- app/controllers/compare_controller.rb | 2 +- app/controllers/merge_requests_controller.rb | 6 +++--- app/controllers/teams/members_controller.rb | 2 +- app/decorators/application_decorator.rb | 15 ++++++++------- 6 files changed, 15 insertions(+), 14 deletions(-) diff --git a/app/controllers/admin/teams/members_controller.rb b/app/controllers/admin/teams/members_controller.rb index e7dbcad568..e646987441 100644 --- a/app/controllers/admin/teams/members_controller.rb +++ b/app/controllers/admin/teams/members_controller.rb @@ -1,7 +1,7 @@ class Admin::Teams::MembersController < Admin::Teams::ApplicationController def new @users = User.potential_team_members(user_team) - @users = UserDecorator.decorate @users + @users = UserDecorator.decorate_collection @users end def create diff --git a/app/controllers/commits_controller.rb b/app/controllers/commits_controller.rb index 534ae1edd3..9dc0d96883 100644 --- a/app/controllers/commits_controller.rb +++ b/app/controllers/commits_controller.rb @@ -13,7 +13,7 @@ class CommitsController < ProjectResourceController @limit, @offset = (params[:limit] || 40), (params[:offset] || 0) @commits = @repo.commits(@ref, @path, @limit, @offset) - @commits = CommitDecorator.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 ae20f9c0ba..bd3f111517 100644 --- a/app/controllers/compare_controller.rb +++ b/app/controllers/compare_controller.rb @@ -16,7 +16,7 @@ class CompareController < ProjectResourceController @refs_are_same = result[:same] @line_notes = [] - @commits = CommitDecorator.decorate(@commits) + @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 c8fe2e6bfe..9992e9b81e 100644 --- a/app/controllers/merge_requests_controller.rb +++ b/app/controllers/merge_requests_controller.rb @@ -94,12 +94,12 @@ class MergeRequestsController < ProjectResourceController def branch_from @commit = @repository.commit(params[:ref]) - @commit = CommitDecorator.decorate(@commit) + @commit = CommitDecorator.decorate_collection(@commit) end def branch_to @commit = @repository.commit(params[:ref]) - @commit = CommitDecorator.decorate(@commit) + @commit = CommitDecorator.decorate_collection(@commit) end def ci_status @@ -143,7 +143,7 @@ class MergeRequestsController < ProjectResourceController # Get commits from repository # or from cache if already merged @commits = @merge_request.commits - @commits = CommitDecorator.decorate(@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/teams/members_controller.rb b/app/controllers/teams/members_controller.rb index ead62e13af..4bd70fd724 100644 --- a/app/controllers/teams/members_controller.rb +++ b/app/controllers/teams/members_controller.rb @@ -8,7 +8,7 @@ class Teams::MembersController < Teams::ApplicationController def new @users = User.potential_team_members(user_team) - @users = UserDecorator.decorate @users + @users = UserDecorator.decorate_collection @users end def create diff --git a/app/decorators/application_decorator.rb b/app/decorators/application_decorator.rb index 3023699e70..b805b3479b 100644 --- a/app/decorators/application_decorator.rb +++ b/app/decorators/application_decorator.rb @@ -1,27 +1,28 @@ -class ApplicationDecorator < Draper::Base +class ApplicationDecorator < Draper::Decorator + delegate_all # Lazy Helpers # PRO: Call Rails helpers without the h. proxy # ex: number_to_currency(model.price) # CON: Add a bazillion methods into your decorator's namespace # and probably sacrifice performance/memory - # + # # Enable them by uncommenting this line: # lazy_helpers # Shared Decorations # Consider defining shared methods common to all your models. - # + # # Example: standardize the formatting of timestamps # # def formatted_timestamp(time) - # h.content_tag :span, time.strftime("%a %m/%d/%y"), - # class: 'timestamp' + # h.content_tag :span, time.strftime("%a %m/%d/%y"), + # class: 'timestamp' # end - # + # # def created_at # formatted_timestamp(model.created_at) # end - # + # # def updated_at # formatted_timestamp(model.updated_at) # end From dbcf4144ee4da9670efa26f2297d11291823d949 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 1 Mar 2013 15:35:22 +0200 Subject: [PATCH 075/113] use simple decorate on single commits --- app/controllers/merge_requests_controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/merge_requests_controller.rb b/app/controllers/merge_requests_controller.rb index 9992e9b81e..788f2c3a5c 100644 --- a/app/controllers/merge_requests_controller.rb +++ b/app/controllers/merge_requests_controller.rb @@ -94,12 +94,12 @@ class MergeRequestsController < ProjectResourceController def branch_from @commit = @repository.commit(params[:ref]) - @commit = CommitDecorator.decorate_collection(@commit) + @commit = CommitDecorator.decorate(@commit) end def branch_to @commit = @repository.commit(params[:ref]) - @commit = CommitDecorator.decorate_collection(@commit) + @commit = CommitDecorator.decorate(@commit) end def ci_status From a73e58f70b264b36b3291bba9a8a2789235ccadb Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 1 Mar 2013 15:59:43 +0200 Subject: [PATCH 076/113] draper raise now RuntimeError instead of NoMethodError --- lib/extracts_path.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb index fb595e18b2..fd0050cfd5 100644 --- a/lib/extracts_path.rb +++ b/lib/extracts_path.rb @@ -126,7 +126,7 @@ module ExtractsPath @tree = TreeDecorator.new(@tree) raise InvalidPathError if @tree.invalid? - rescue NoMethodError, InvalidPathError + rescue RuntimeError, NoMethodError, InvalidPathError not_found! end end From 87f555e1ef26205633ff6458623054c6a95b983b Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 1 Mar 2013 16:07:55 +0200 Subject: [PATCH 077/113] fixed db/schema --- db/schema.rb | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index 3eb3a7dcee..04ed798461 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -106,11 +106,11 @@ ActiveRecord::Schema.define(:version => 20130220133245) do add_index "milestones", ["project_id"], :name => "index_milestones_on_project_id" create_table "namespaces", :force => true do |t| - t.string "name", :null => false - t.string "path", :null => false - t.integer "owner_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.string "name", :null => false + t.string "path", :null => false + t.integer "owner_id", :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false t.string "type" t.string "description", :default => "", :null => false end @@ -143,14 +143,14 @@ ActiveRecord::Schema.define(:version => 20130220133245) do t.string "name" t.string "path" t.text "description" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false t.integer "creator_id" t.string "default_branch" - t.boolean "issues_enabled", :default => true, :null => false - t.boolean "wall_enabled", :default => true, :null => false - t.boolean "merge_requests_enabled", :default => true, :null => false - t.boolean "wiki_enabled", :default => true, :null => false + t.boolean "issues_enabled", :default => true, :null => false + t.boolean "wall_enabled", :default => true, :null => false + t.boolean "merge_requests_enabled", :default => true, :null => false + t.boolean "wiki_enabled", :default => true, :null => false t.integer "namespace_id" t.boolean "public", :default => false, :null => false t.string "issues_tracker", :default => "gitlab", :null => false @@ -233,14 +233,9 @@ ActiveRecord::Schema.define(:version => 20130220133245) do t.string "name" t.string "path" t.integer "owner_id" -<<<<<<< HEAD - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false -======= t.datetime "created_at", :null => false t.datetime "updated_at", :null => false t.string "description", :default => "", :null => false ->>>>>>> 2f1f05d431d1df062e46365930b98b358554a07d end create_table "users", :force => true do |t| From c280c3ce6d1c19f1acb470862338c0c17e16bdab Mon Sep 17 00:00:00 2001 From: Sven Pachnit Date: Thu, 17 Jan 2013 01:05:44 +0100 Subject: [PATCH 078/113] Do not send issue status mail twice if author = assignee --- app/observers/issue_observer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/observers/issue_observer.rb b/app/observers/issue_observer.rb index 592e2950f3..29e2404037 100644 --- a/app/observers/issue_observer.rb +++ b/app/observers/issue_observer.rb @@ -27,7 +27,7 @@ class IssueObserver < ActiveRecord::Observer def create_note(issue) Note.create_status_change_note(issue, current_user, issue.state) - [issue.author, issue.assignee].compact.each do |recipient| + [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 From ef646928e4f89586d7057c91aee2678c3f89f363 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 1 Mar 2013 16:26:26 +0200 Subject: [PATCH 079/113] better presenting for group description --- app/assets/stylesheets/gitlab_bootstrap/common.scss | 2 ++ app/views/groups/new.html.haml | 3 +-- app/views/groups/show.html.haml | 8 +++----- app/views/teams/new.html.haml | 1 - app/views/teams/show.html.haml | 8 +++----- 5 files changed, 9 insertions(+), 13 deletions(-) diff --git a/app/assets/stylesheets/gitlab_bootstrap/common.scss b/app/assets/stylesheets/gitlab_bootstrap/common.scss index dcfd610e2c..9e015eb2b6 100644 --- a/app/assets/stylesheets/gitlab_bootstrap/common.scss +++ b/app/assets/stylesheets/gitlab_bootstrap/common.scss @@ -30,6 +30,8 @@ border-color: #DDD; } +.well { padding: 15px; } + /** HELPERS **/ .nothing_here_message { text-align: center; diff --git a/app/views/groups/new.html.haml b/app/views/groups/new.html.haml index 2104db8684..36ee492273 100644 --- a/app/views/groups/new.html.haml +++ b/app/views/groups/new.html.haml @@ -16,10 +16,9 @@ = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4 .form-actions - = f.submit 'Create group', class: "btn btn-primary" + = f.submit 'Create group', class: "btn btn-create" - %hr .padded %ul %li Group is kind of directory for several projects diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml index fe08e0b551..81694b88cc 100644 --- a/app/views/groups/show.html.haml +++ b/app/views/groups/show.html.haml @@ -1,8 +1,3 @@ -- if @group.description.present? - .description - = @group.description - %hr - .projects .activities.span8 = render "events/event_last_push", event: @last_push @@ -17,6 +12,9 @@ %p.nothing_here_message Project activity will be displayed here .loading.hide .side.span4 + - if @group.description.present? + .description.well.light + = @group.description = render "projects", projects: @projects %div %span.rss-icon diff --git a/app/views/teams/new.html.haml b/app/views/teams/new.html.haml index 332a6a558d..99d308217e 100644 --- a/app/views/teams/new.html.haml +++ b/app/views/teams/new.html.haml @@ -18,7 +18,6 @@ .form-actions = f.submit 'Create team', class: "btn btn-create" - %hr .padded %ul %li All created teams are public (users can view who enter into team and which project are assigned for this team) diff --git a/app/views/teams/show.html.haml b/app/views/teams/show.html.haml index 34be769241..43cc026a5c 100644 --- a/app/views/teams/show.html.haml +++ b/app/views/teams/show.html.haml @@ -1,8 +1,3 @@ -- if @team.description.present? - .description - = @team.description - %hr - .projects .activities.span8 = link_to dashboard_path, class: 'btn btn-tiny' do @@ -16,6 +11,9 @@ %p.nothing_here_message Projects activity will be displayed here .loading.hide .side.span4 + - if @team.description.present? + .description.well.light + = @team.description = render "projects", projects: @projects %div %span.rss-icon From dd653f62f3bf07e1ea2260b06cd44ab1aaba028b Mon Sep 17 00:00:00 2001 From: Matt Humphrey Date: Fri, 1 Mar 2013 16:34:11 +0000 Subject: [PATCH 080/113] Added namespace_id to project creation via API This allows you to set the namespace ID for projects via the the API. By default it is created for the current user. You can assign it to the global namespace by passing `GLN` which translates to 'Global Namespace'. --- lib/api/projects.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/api/projects.rb b/lib/api/projects.rb index c4d9cd9696..851e54c59b 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -42,7 +42,8 @@ module Gitlab :issues_enabled, :wall_enabled, :merge_requests_enabled, - :wiki_enabled] + :wiki_enabled + :namespace_id] @project = ::Projects::CreateContext.new(current_user, attrs).execute if @project.saved? present @project, with: Entities::Project From 1c0c7bd6e3ca2a0cbcb7af6a4b6c8067e10b3880 Mon Sep 17 00:00:00 2001 From: Matt Humphrey Date: Fri, 1 Mar 2013 16:36:19 +0000 Subject: [PATCH 081/113] Missed comma. --- lib/api/projects.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 851e54c59b..8f57e5ac79 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -42,7 +42,7 @@ module Gitlab :issues_enabled, :wall_enabled, :merge_requests_enabled, - :wiki_enabled + :wiki_enabled, :namespace_id] @project = ::Projects::CreateContext.new(current_user, attrs).execute if @project.saved? From 1c8c5c76b6a0cd1b55feb11b26c25b8e3c08173f Mon Sep 17 00:00:00 2001 From: wtw Date: Fri, 1 Mar 2013 23:53:37 +0100 Subject: [PATCH 082/113] Corrected some typos in gitlab.yml.example comments --- config/gitlab.yml.example | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index 07e97ae541..3fb173862c 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -1,5 +1,5 @@ # # # # # # # # # # # # # # # # # # -# Gitlab application config file # +# GitLab application config file # # # # # # # # # # # # # # # # # # # # # How to use: @@ -41,21 +41,21 @@ production: &base ## External issues trackers issues_tracker: redmine: - ## If not nil, link 'Issues' on project page will be replaced tp this + ## If not nil, link 'Issues' on project page will be replaced with this ## Use placeholders: - ## :project_id - Gitlab project identifier + ## :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 to this + ## If not nil, links from /#\d/ entities from commit messages will replaced with this ## Use placeholders: - ## :project_id - Gitlab project identifier + ## :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" ## Gravatar gravatar: - enabled: true # Use user avatar images from Gravatar.com (default: true) + enabled: true # Use user avatar image from Gravatar.com (default: true) # plain_url: "http://..." # default: http://www.gravatar.com/avatar/%{hash}?s=%{size}&d=mm # ssl_url: "https://..." # default: https://secure.gravatar.com/avatar/%{hash}?s=%{size}&d=mm @@ -76,22 +76,21 @@ production: &base bind_dn: '_the_full_dn_of_the_user_you_will_bind_with' password: '_the_password_of_the_bind_user' - ## Omniauth settings + ## OmniAuth settings omniauth: - # Enable ability for users - # Allow logging in via Twitter, Google, etc. using Omniauth providers + # Allow login via Twitter, Google, etc. using OmniAuth providers enabled: false # CAUTION! - # This allows users to login without having a user account first (default: false) + # This allows users to login without having a user account first (default: false). # User accounts will be created automatically when authentication was successful. allow_single_sign_on: false - # Locks down those users until they have been cleared by the admin (default: true) + # Locks down those users until they have been cleared by the admin (default: true). block_auto_created_users: true ## Auth providers - # Uncomment the lines and fill in the data of the auth provider you want to use - # If your favorite auth provider is not listed you can user others: + # Uncomment the following lines and fill in the data of the auth provider you want to use + # If your favorite auth provider is not listed you can use others: # see https://github.com/gitlabhq/gitlabhq/wiki/Using-Custom-Omniauth-Providers # The 'app_id' and 'app_secret' parameters are always passed as the first two # arguments, followed by optional 'args' which can be either a hash or an array. @@ -130,7 +129,7 @@ production: &base upload_pack: true receive_pack: true - # If you use non-standart ssh port you need to specify it + # If you use non-standard ssh port you need to specify it # ssh_port: 22 ## Git settings @@ -138,10 +137,10 @@ production: &base # Use the default values unless you really know what you are doing git: bin_path: /usr/bin/git - # Max size of git object like commit, in bytes - # This value can be increased if you have a very large commits + # Max size of a git object (e.g. a commit), in bytes + # This value can be increased if you have very large commits max_size: 5242880 # 5.megabytes - # Git timeout to read commit, in seconds + # Git timeout to read a commit, in seconds timeout: 10 development: From 86da625f1dc99ef57e554f1c39cb0db20f45a5b6 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 2 Mar 2013 12:58:47 +0200 Subject: [PATCH 083/113] Updated gems: omniauth, sinatra, foreman --- Gemfile | 2 +- Gemfile.lock | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Gemfile b/Gemfile index 5622c1a213..41d8619db0 100644 --- a/Gemfile +++ b/Gemfile @@ -16,7 +16,7 @@ gem "pg", group: :postgres # Auth gem "devise" -gem 'omniauth', "~> 1.1.1" +gem 'omniauth', "~> 1.1.3" gem 'omniauth-google-oauth2' gem 'omniauth-twitter' gem 'omniauth-github' diff --git a/Gemfile.lock b/Gemfile.lock index f70c873527..466a373ad0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -155,7 +155,7 @@ GEM factory_girl_rails (4.1.0) factory_girl (~> 4.1.0) railties (>= 3.0.0) - faraday (0.8.4) + faraday (0.8.6) multipart-post (~> 1.1) faye-websocket (0.4.7) eventmachine (>= 0.12.0) @@ -164,7 +164,7 @@ GEM font-awesome-sass-rails (3.0.0.1) railties (>= 3.1.1) sass-rails (>= 3.1.1) - foreman (0.60.2) + foreman (0.61.0) thor (>= 0.13.6) gemoji (1.2.1) gherkin-ruby (0.2.1) @@ -255,21 +255,21 @@ GEM sprockets (~> 2.0) multi_json (1.6.1) multi_xml (0.5.3) - multipart-post (1.1.5) + multipart-post (1.2.0) mysql2 (0.3.11) net-ldap (0.2.2) nokogiri (1.5.6) oauth (0.4.7) - oauth2 (0.8.0) + oauth2 (0.8.1) faraday (~> 0.8) httpauth (~> 0.1) jwt (~> 0.1.4) multi_json (~> 1.0) rack (~> 1.2) - omniauth (1.1.1) + omniauth (1.1.3) hashie (~> 1.2) rack - omniauth-github (1.0.3) + omniauth-github (1.1.0) omniauth (~> 1.0) omniauth-oauth2 (~> 1.1) omniauth-google-oauth2 (0.1.13) @@ -309,7 +309,7 @@ GEM rack (>= 1.1.3) rack-mount (0.8.3) rack (>= 1.0.0) - rack-protection (1.3.2) + rack-protection (1.4.0) rack rack-ssl (1.3.3) rack @@ -400,9 +400,9 @@ GEM multi_json (~> 1.0) simplecov-html (~> 0.7.1) simplecov-html (0.7.1) - sinatra (1.3.3) - rack (~> 1.3, >= 1.3.6) - rack-protection (~> 1.2) + sinatra (1.3.5) + rack (~> 1.4) + rack-protection (~> 1.3) tilt (~> 1.3, >= 1.3.3) six (0.2.0) slim (1.3.6) @@ -508,7 +508,7 @@ DEPENDENCIES letter_opener modernizr (= 2.6.2) mysql2 - omniauth (~> 1.1.1) + omniauth (~> 1.1.3) omniauth-github omniauth-google-oauth2 omniauth-twitter From 907c334fe0ef1be349668cb7bd9639780a098344 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 2 Mar 2013 13:23:30 +0200 Subject: [PATCH 084/113] fix decorate call for milestone users --- app/controllers/milestones_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/milestones_controller.rb b/app/controllers/milestones_controller.rb index 57f1e9e6bb..cdac28c1bd 100644 --- a/app/controllers/milestones_controller.rb +++ b/app/controllers/milestones_controller.rb @@ -32,7 +32,7 @@ class MilestonesController < ProjectResourceController def show @issues = @milestone.issues - @users = UserDecorator.decorate(@milestone.participants) + @users = UserDecorator.decorate_collection(@milestone.participants) @merge_requests = @milestone.merge_requests respond_to do |format| From 737a449795c9057fab1f326f28c8e24972d0bd71 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Sat, 2 Mar 2013 12:53:27 +0100 Subject: [PATCH 085/113] Cleaned up and enhanced readme. Finishing touches. Make the layout more consistent. --- README.md | 94 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 63 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 267f42360b..4a5ea2db3d 100644 --- a/README.md +++ b/README.md @@ -1,52 +1,84 @@ -## GitLab is a self hosted Git management software. - -Check out [gitlab.org](http://gitlab.org) +## GitLab: self hosted Git management software ![logo](https://raw.github.com/gitlabhq/gitlabhq/master/public/gitlab_logo.png) -With GitLab you can: - * create projects and repositories - * manage repositories access - * do code review +### GitLab allows you to + * keep your code secure on your own server + * manage repositories, users and access permissions + * communicate though issues, line-comments and wiki's + * perform code reviews with merge requests -- - - - -### Code status: - -* master: travis-ci.org - [![build status](https://secure.travis-ci.org/gitlabhq/gitlabhq.png)](https://travis-ci.org/gitlabhq/gitlabhq) - -* master: ci.gitlab.org - [![CI](http://ci.gitlab.org/projects/1/status?ref=master)](http://ci.gitlab.org/projects/1?ref=master) - -* [![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.png)](https://codeclimate.com/github/gitlabhq/gitlabhq) -* [![Dependency Status](https://gemnasium.com/gitlabhq/gitlabhq.png)](https://gemnasium.com/gitlabhq/gitlabhq) - -### Application details +### GitLab is * powered by Ruby on Rails -* its completely free and open source -* distributed under the MIT License +* completely free and open source (MIT license) +* used by 10.000 organization to keep their code secure + +### Code status + +* [![build status](http://ci.gitlab.org/projects/1/status?ref=master)](http://ci.gitlab.org/projects/1?ref=master) ci.gitlab.org (master branch) + +* [![build status](https://secure.travis-ci.org/gitlabhq/gitlabhq.png)](https://travis-ci.org/gitlabhq/gitlabhq) travis-ci.org (master branch) + +* [![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.png)](https://codeclimate.com/github/gitlabhq/gitlabhq) + +* [![Dependency Status](https://gemnasium.com/gitlabhq/gitlabhq.png)](https://gemnasium.com/gitlabhq/gitlabhq) + +### Resources + +* 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: [Homepage](http://blog.gitlab.com/) [Hosted pricing](http://blog.gitlab.com/pricing/) [Services](http://blog.gitlab.com/services/) [Blog](http://blog.gitlab.com/blog/) + +* GitLab CI: [Readme](https://github.com/gitlabhq/gitlab-ci/blob/master/README.md) of the GitLab open-source continuous integration server ### Requirements -* Ubuntu/Debian +* Ubuntu/Debian* * ruby 1.9.3+ * MySQL * git * gitlab-shell * redis -More details are in the [requirements doc](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/requirements.md) +* More details are in the [requirements doc](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/requirements.md) -### Install +### Getting started -Checkout [wiki](https://github.com/gitlabhq/gitlabhq/wiki) pages for installation information, migration, etc. +* [Installation guide for latest stable release](https://github.com/gitlabhq/gitlabhq/blob/4-2-stable/doc/install/installation.md) -### [Community](http://gitlab.org/community/) +* [Installation guide for the current master branch](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md) -### [Contact](http://gitlab.org/contact/) +* [Vagrant virtual machine](https://github.com/gitlabhq/gitlab-vagrant-vm) -### [Contributing Guide](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) +* [Developer guide](https://github.com/gitlabhq/gitlabhq/wiki/Developer-Guide) -### [Developer Guide](https://github.com/gitlabhq/gitlabhq/wiki/Developer-Guide) +* [Upgrade guides](https://github.com/gitlabhq/gitlabhq/wiki) + +* [Roadmap](https://github.com/gitlabhq/gitlabhq/blob/master/ROADMAP.md) + +* [GitLab API](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/README.md) + +### 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) + +* [Paid support](http://blog.gitlab.com/support/) + +* [Paid services](http://blog.gitlab.com/services/) + +### Getting in touch + +* [Contributing guide](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) + +* [Core team](https://github.com/gitlabhq?tab=members) + +* [Contributors](https://github.com/gitlabhq/gitlabhq/graphs/contributors) + +* [Leader](https://github.com/randx) + +* [Contact page](http://gitlab.org/contact/) From 56d1cc5be50939089c011325b18dee3a295edf4c Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Sat, 2 Mar 2013 23:27:52 +0100 Subject: [PATCH 086/113] Replacing the development guide. --- CONTRIBUTING.md | 24 ++++++++++++++++++++++-- README.md | 49 ++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 66 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 005837f2ca..1ca89dbbe2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -29,12 +29,32 @@ Feature suggestions don't belong in issues but can go to [Feedback forum](http:/ ## Pull requests -Code speaks louder than words. If you can please submit a pull request with the fix including tests. Starting point would be the [Developer Guide](https://github.com/gitlabhq/gitlabhq/wiki/Developer-Guide) +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 a follows: + +1. Fork the project on GitHub +1. Create a feature branch +1. Write tests and code +1. If you have multiple commits please combine them into one commit by [squashing them](http://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits) +1. Push the commit to your fork +1. Submit a pull request + +We will accept pull requests if: + +* The code has proper tests and all tests pass +* It can be merged without problems (if not please use: git rebase master to fix this) +* It won't break any existing functionality +* It's quality code that conforms to the [Rails style guide](https://github.com/bbatsov/rails-style-guide) and best practices +* You describe your PR properly please give a motive for your change and the method you used to achieve it +* It keeps the GitLab code base clean and well structured +* We think other users need the same functionality +* If it makes changes to the UI it should have screen shots + +For examples of feedback on pull requests please look at our already [closed pull requests](https://github.com/gitlabhq/gitlabhq/pulls?direction=desc&page=1&sort=created&state=closed). ## Submitting via GitHub's 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 include a suggestion to improve it. +* For problematic or insufficient documentation. Please give a suggestion on how to improve it. 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. diff --git a/README.md b/README.md index 4a5ea2db3d..327d495ab7 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,9 @@ * More details are in the [requirements doc](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/requirements.md) -### Getting started +### Installation + +You can either follow the "ordinary" Installation guide to install it on a machine or use the Vagrant virtual machine. The Installation guide is recommended to set up a production server. The Vargrant virtual machine is recommended for development since it makes it much easier to set up all the dependencies for integration testing. * [Installation guide for latest stable release](https://github.com/gitlabhq/gitlabhq/blob/4-2-stable/doc/install/installation.md) @@ -51,13 +53,40 @@ * [Vagrant virtual machine](https://github.com/gitlabhq/gitlab-vagrant-vm) -* [Developer guide](https://github.com/gitlabhq/gitlabhq/wiki/Developer-Guide) +### Starting -* [Upgrade guides](https://github.com/gitlabhq/gitlabhq/wiki) +1. The Installation guide contains instructions to download an init script and run that on boot. After configuring the init script you can run -* [Roadmap](https://github.com/gitlabhq/gitlabhq/blob/master/ROADMAP.md) +sudo service gitlab start -* [GitLab API](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/README.md) +or + +sudo /etc/init.d/gitlab restart + +2. With [foreman](https://github.com/ddollar/foreman) + +bundle exec foreman start -p 3000 + +3. Start it manually + +bundle exec rails s +bundle exec rake environment resque:work QUEUE=* VVERBOSE=1 + +### Running the tests + +* Seed the database with + +bundle exec rake db:setup RAILS_ENV=test +bundle exec rake db:seed_fu RAILS_ENV=test + +* Run all tests +bundle exec rake gitlab:test + +* Rspec unit and functional tests +bundle exec rake spec + +* Spinach integration tests +bundle exec rake spinach ### Getting help @@ -71,6 +100,16 @@ * [Paid services](http://blog.gitlab.com/services/) +### New versions and the API + +Each month on the 22th a new version is released together with an upgrade guide. + +* [Upgrade guides](https://github.com/gitlabhq/gitlabhq/wiki) + +* [Roadmap](https://github.com/gitlabhq/gitlabhq/blob/master/ROADMAP.md) + +* [GitLab API](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/README.md) + ### Getting in touch * [Contributing guide](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) From 5421f6b239fcf2742e6190ee6ffdaa6144ab800a Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Sat, 2 Mar 2013 23:38:48 +0100 Subject: [PATCH 087/113] Small fixes and better quoting. --- CONTRIBUTING.md | 14 +++++++------- README.md | 29 +++++++++++++++++++---------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1ca89dbbe2..cff5e939f1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -29,7 +29,7 @@ Feature suggestions don't belong in issues but can go to [Feedback forum](http:/ ## Pull requests -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 a follows: +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 1. Create a feature branch @@ -41,15 +41,15 @@ Code speaks louder than words. If you can please submit a pull request with the We will accept pull requests if: * The code has proper tests and all tests pass -* It can be merged without problems (if not please use: git rebase master to fix this) -* It won't break any existing functionality +* It can be merged without problems (if not please use: git rebase master) +* It doesn't break any existing functionality * It's quality code that conforms to the [Rails style guide](https://github.com/bbatsov/rails-style-guide) and best practices -* You describe your PR properly please give a motive for your change and the method you used to achieve it +* The description includes a motive for your change and the method you used to achieve it * It keeps the GitLab code base clean and well structured -* We think other users need the same functionality -* If it makes changes to the UI it should have screen shots +* We think other users will need the same functionality +* If it makes changes to the UI the pull request should include screenshots -For examples of feedback on pull requests please look at our already [closed pull requests](https://github.com/gitlabhq/gitlabhq/pulls?direction=desc&page=1&sort=created&state=closed). +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 diff --git a/README.md b/README.md index 327d495ab7..e6cb3e4b24 100644 --- a/README.md +++ b/README.md @@ -57,36 +57,39 @@ You can either follow the "ordinary" Installation guide to install it on a machi 1. The Installation guide contains instructions to download an init script and run that on boot. After configuring the init script you can run -sudo service gitlab start +> sudo service gitlab start or -sudo /etc/init.d/gitlab restart +> sudo /etc/init.d/gitlab restart -2. With [foreman](https://github.com/ddollar/foreman) +2. Start it with [Foreman](https://github.com/ddollar/foreman) bundle exec foreman start -p 3000 3. Start it manually -bundle exec rails s -bundle exec rake environment resque:work QUEUE=* VVERBOSE=1 +> bundle exec rails s +> bundle exec rake environment resque:work QUEUE=* VVERBOSE=1 ### Running the tests * Seed the database with -bundle exec rake db:setup RAILS_ENV=test -bundle exec rake db:seed_fu RAILS_ENV=test +> bundle exec rake db:setup RAILS_ENV=test +> bundle exec rake db:seed_fu RAILS_ENV=test * Run all tests -bundle exec rake gitlab:test + +> bundle exec rake gitlab:test * Rspec unit and functional tests -bundle exec rake spec + +> bundle exec rake spec * Spinach integration tests -bundle exec rake spinach + +> bundle exec rake spinach ### Getting help @@ -108,8 +111,14 @@ Each month on the 22th a new version is released together with an upgrade guide. * [Roadmap](https://github.com/gitlabhq/gitlabhq/blob/master/ROADMAP.md) +### Other documentation + * [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) + ### Getting in touch * [Contributing guide](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) From 6e908f1a36e702a5c829981f0ed48924ad837b16 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Sun, 3 Mar 2013 12:29:57 +0100 Subject: [PATCH 088/113] Sidekiq replaced resque. --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e6cb3e4b24..236f5b9cff 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ You can either follow the "ordinary" Installation guide to install it on a machi ### Starting -1. The Installation guide contains instructions to download an init script and run that on boot. After configuring the init script you can run +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 with: > sudo service gitlab start @@ -63,14 +63,14 @@ or > sudo /etc/init.d/gitlab restart -2. Start it with [Foreman](https://github.com/ddollar/foreman) +2. Start it with [Foreman](https://github.com/ddollar/foreman) in development model bundle exec foreman start -p 3000 -3. Start it manually +3. Start it manually in development mode > bundle exec rails s -> bundle exec rake environment resque:work QUEUE=* VVERBOSE=1 +> bundle exec rake sidekiq:start ### Running the tests From 50620b7df8218df835763e6665da2ab58d50fbdb Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Sun, 3 Mar 2013 12:38:01 +0100 Subject: [PATCH 089/113] Refer to virtual machine from the installation document. --- doc/install/installation.md | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index 2de6bab97c..d0f586af6b 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -1,7 +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 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. **Important Note:** The following steps have been known to work. @@ -97,10 +96,10 @@ Create a `git` user for Gitlab: GitLab Shell is a ssh access and repository management software developed specially for GitLab. - # Login as git + # Login as git sudo su git - # Go to home directory + # Go to home directory cd /home/git # Clone gitlab shell @@ -109,12 +108,12 @@ GitLab Shell is a ssh access and repository management software developed specia cd gitlab-shell cp config.yml.example config.yml - # Edit config and replace gitlab_url + # Edit config and replace gitlab_url # with something like 'http://domain.com/' vim config.yml # Do setup - ./bin/install + ./bin/install # 5. Database @@ -132,9 +131,9 @@ To setup the MySQL/PostgreSQL database and dependencies please see [`doc/install # Clone GitLab repository sudo -u git -H git clone https://github.com/gitlabhq/gitlabhq.git gitlab - # Go to gitlab dir + # Go to gitlab dir cd /home/git/gitlab - + # Checkout to stable release sudo -u git -H git checkout 5-0-stable @@ -165,7 +164,7 @@ do so with caution! # Create directory for pids and make sure GitLab can write to it sudo -u git -H mkdir tmp/pids/ sudo chmod -R u+rwX tmp/pids/ - + # Copy the example Unicorn config sudo -u git -H cp config/unicorn.rb.example config/unicorn.rb @@ -196,7 +195,7 @@ Make sure to update username/password in config/database.yml. ## Initialise Database and Activate Advanced Features - + sudo -u git -H bundle exec rake db:setup RAILS_ENV=production sudo -u git -H bundle exec rake db:seed_fu RAILS_ENV=production sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production @@ -294,7 +293,7 @@ a different host, you can configure its connection string via the ## Custom SSH Connection If you are running SSH on a non-standard port, you must change the gitlab user's SSH config. - + # Add to /home/git/.ssh/config host localhost # Give your setup a name (here: override localhost) user git # Your remote git user From bb7490771e0e19ed28cef7d20ed6f70650d3a78b Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 3 Mar 2013 17:51:24 +0200 Subject: [PATCH 090/113] Use proper markdown syntax for code in README.md --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 236f5b9cff..847bccb057 100644 --- a/README.md +++ b/README.md @@ -57,39 +57,39 @@ You can either follow the "ordinary" Installation guide to install it on a machi 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 with: -> sudo service gitlab start + sudo service gitlab start or -> sudo /etc/init.d/gitlab restart + sudo /etc/init.d/gitlab restart 2. Start it with [Foreman](https://github.com/ddollar/foreman) in development model -bundle exec foreman start -p 3000 + bundle exec foreman start -p 3000 3. Start it manually in development mode -> bundle exec rails s -> bundle exec rake sidekiq:start + bundle exec rails s + bundle exec rake sidekiq:start ### Running the tests * Seed the database with -> bundle exec rake db:setup RAILS_ENV=test -> bundle exec rake db:seed_fu RAILS_ENV=test + bundle exec rake db:setup RAILS_ENV=test + bundle exec rake db:seed_fu RAILS_ENV=test * Run all tests -> bundle exec rake gitlab:test + bundle exec rake gitlab:test * Rspec unit and functional tests -> bundle exec rake spec + bundle exec rake spec * Spinach integration tests -> bundle exec rake spinach + bundle exec rake spinach ### Getting help From 06807885cf6095517f8d128f0d870f1f81837784 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 3 Mar 2013 18:21:36 +0200 Subject: [PATCH 091/113] fix readme code nesting --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 847bccb057..f2a45ac7d6 100644 --- a/README.md +++ b/README.md @@ -57,20 +57,20 @@ You can either follow the "ordinary" Installation guide to install it on a machi 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 with: - sudo service gitlab start + sudo service gitlab start -or + or - sudo /etc/init.d/gitlab restart + sudo /etc/init.d/gitlab restart 2. Start it with [Foreman](https://github.com/ddollar/foreman) in development model - bundle exec foreman start -p 3000 + bundle exec foreman start -p 3000 3. Start it manually in development mode - bundle exec rails s - bundle exec rake sidekiq:start + bundle exec rails s + bundle exec rake sidekiq:start ### Running the tests From 891dc550e0c5cef88b250a98d9546a25da0912ba Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 3 Mar 2013 18:22:56 +0200 Subject: [PATCH 092/113] README code in lists --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f2a45ac7d6..02b4722f4b 100644 --- a/README.md +++ b/README.md @@ -76,20 +76,20 @@ You can either follow the "ordinary" Installation guide to install it on a machi * Seed the database with - bundle exec rake db:setup RAILS_ENV=test - bundle exec rake db:seed_fu RAILS_ENV=test + bundle exec rake db:setup RAILS_ENV=test + bundle exec rake db:seed_fu RAILS_ENV=test * Run all tests - bundle exec rake gitlab:test + bundle exec rake gitlab:test * Rspec unit and functional tests - bundle exec rake spec + bundle exec rake spec * Spinach integration tests - bundle exec rake spinach + bundle exec rake spinach ### Getting help From 512ab1b61a10dd0d4fc9307d222db6b7fd7488f5 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 3 Mar 2013 22:01:20 +0200 Subject: [PATCH 093/113] Use gem for gitlab grit --- Gemfile | 2 +- Gemfile.lock | 16 +++++----------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/Gemfile b/Gemfile index 41d8619db0..03afef29d7 100644 --- a/Gemfile +++ b/Gemfile @@ -22,7 +22,7 @@ gem 'omniauth-twitter' gem 'omniauth-github' # GITLAB patched libs -gem "grit", git: "https://github.com/gitlabhq/grit.git", ref: '9e98418ce2d654485b967003726aa2706a10060b' +gem "gitlab-grit", '~> 1.0.0', require: 'grit' gem 'grack', git: "https://github.com/gitlabhq/grack.git", ref: 'ba46f3b0845c6a09d488ae6abdce6ede37e227e8' gem 'grit_ext', git: "https://github.com/gitlabhq/grit_ext.git", ref: '2d1b2f13cabc02520405985fccb2a0abfcba9907' diff --git a/Gemfile.lock b/Gemfile.lock index 466a373ad0..47cb5a4640 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -14,16 +14,6 @@ GIT grack (1.0.0) rack (~> 1.4.1) -GIT - remote: https://github.com/gitlabhq/grit.git - revision: 9e98418ce2d654485b967003726aa2706a10060b - ref: 9e98418ce2d654485b967003726aa2706a10060b - specs: - grit (2.5.0) - diff-lcs (~> 1.1) - mime-types (~> 1.15) - posix-spawn (~> 0.3.6) - GIT remote: https://github.com/gitlabhq/grit_ext.git revision: 2d1b2f13cabc02520405985fccb2a0abfcba9907 @@ -175,6 +165,10 @@ GEM mime-types (~> 1.19) pygments.rb (>= 0.2.13) github-markup (0.7.5) + gitlab-grit (1.0.0) + diff-lcs (~> 1.1) + mime-types (~> 1.15) + posix-spawn (~> 0.3.6) gitlab_meta (5.0) gitlab_omniauth-ldap (1.0.2) net-ldap (~> 0.2.2) @@ -486,6 +480,7 @@ DEPENDENCIES git github-linguist (~> 2.3.4) github-markup (~> 0.7.4) + gitlab-grit (~> 1.0.0) gitlab_meta (= 5.0) gitlab_omniauth-ldap (= 1.0.2) gitlab_yaml_db (= 1.0.0) @@ -493,7 +488,6 @@ DEPENDENCIES grack! grape (~> 0.3.1) grape-entity (~> 0.2.0) - grit! grit_ext! growl guard-rspec From 282b804556b5727873527551da6cad3534144251 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 3 Mar 2013 22:08:04 +0200 Subject: [PATCH 094/113] use gitlab-grack gem --- Gemfile | 7 +++++-- Gemfile.lock | 12 +++--------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/Gemfile b/Gemfile index 03afef29d7..51332d75c5 100644 --- a/Gemfile +++ b/Gemfile @@ -21,9 +21,12 @@ gem 'omniauth-google-oauth2' gem 'omniauth-twitter' gem 'omniauth-github' -# GITLAB patched libs +# Extracting information from a git repository gem "gitlab-grit", '~> 1.0.0', require: 'grit' -gem 'grack', git: "https://github.com/gitlabhq/grack.git", ref: 'ba46f3b0845c6a09d488ae6abdce6ede37e227e8' + +# Ruby/Rack Git Smart-HTTP Server Handler +gem 'gitlab-grack', '~> 1.0.0', require: 'grack' + gem 'grit_ext', git: "https://github.com/gitlabhq/grit_ext.git", ref: '2d1b2f13cabc02520405985fccb2a0abfcba9907' # LDAP Auth diff --git a/Gemfile.lock b/Gemfile.lock index 47cb5a4640..b47d0721fb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,14 +6,6 @@ GIT activerecord (>= 2.3.0) rake (>= 0.8.7) -GIT - remote: https://github.com/gitlabhq/grack.git - revision: ba46f3b0845c6a09d488ae6abdce6ede37e227e8 - ref: ba46f3b0845c6a09d488ae6abdce6ede37e227e8 - specs: - grack (1.0.0) - rack (~> 1.4.1) - GIT remote: https://github.com/gitlabhq/grit_ext.git revision: 2d1b2f13cabc02520405985fccb2a0abfcba9907 @@ -165,6 +157,8 @@ GEM mime-types (~> 1.19) pygments.rb (>= 0.2.13) 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) @@ -480,12 +474,12 @@ DEPENDENCIES git github-linguist (~> 2.3.4) github-markup (~> 0.7.4) + gitlab-grack (~> 1.0.0) gitlab-grit (~> 1.0.0) gitlab_meta (= 5.0) gitlab_omniauth-ldap (= 1.0.2) gitlab_yaml_db (= 1.0.0) gon - grack! grape (~> 0.3.1) grape-entity (~> 0.2.0) grit_ext! From d199de044425ad73caa031627c714b7010d76e3f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 4 Mar 2013 08:54:00 +0200 Subject: [PATCH 095/113] Use gitlab-pygments gem --- Gemfile | 2 +- Gemfile.lock | 17 +++++++---------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/Gemfile b/Gemfile index 51332d75c5..70a6c0761a 100644 --- a/Gemfile +++ b/Gemfile @@ -36,7 +36,7 @@ gem 'gitlab_omniauth-ldap', '1.0.2', require: "omniauth-ldap" gem 'gitlab_yaml_db', '1.0.0', require: "yaml_db" # Syntax highlighter -gem "pygments.rb", git: "https://github.com/gitlabhq/pygments.rb.git", branch: "master" +gem "gitlab-pygments.rb", '~> 0.3.2', require: 'pygments.rb' # Language detection gem "github-linguist", "~> 2.3.4" , require: "linguist" diff --git a/Gemfile.lock b/Gemfile.lock index b47d0721fb..51940606cd 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -14,15 +14,6 @@ GIT grit_ext (0.6.2) charlock_holmes (~> 0.6.9) -GIT - remote: https://github.com/gitlabhq/pygments.rb.git - revision: db1da0343adf86b49bdc3add04d02d2e80438d38 - branch: master - specs: - pygments.rb (0.3.2) - posix-spawn (~> 0.3.6) - yajl-ruby (~> 1.1.0) - GIT remote: https://github.com/gitlabhq/raphael-rails.git revision: cb2c92a040b9b941a5f1aa1ea866cc26e944fe58 @@ -163,6 +154,9 @@ GEM 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) gitlab_meta (5.0) gitlab_omniauth-ldap (1.0.2) net-ldap (~> 0.2.2) @@ -285,6 +279,9 @@ GEM coderay (~> 1.0.5) method_source (~> 0.8) slop (~> 3.3.1) + pygments.rb (0.4.2) + posix-spawn (~> 0.3.6) + yajl-ruby (~> 1.1.0) pyu-ruby-sasl (0.0.3.3) quiet_assets (1.0.1) railties (~> 3.1) @@ -476,6 +473,7 @@ DEPENDENCIES 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) gitlab_yaml_db (= 1.0.0) @@ -503,7 +501,6 @@ DEPENDENCIES pg poltergeist (= 1.1.0) pry - pygments.rb! quiet_assets (~> 1.0.1) rack-mini-profiler rails (= 3.2.12) From 152c6018b3ace729095e7b58f5be3963b81050fb Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 4 Mar 2013 08:56:54 +0200 Subject: [PATCH 096/113] use grit_ext gem instead of fork --- Gemfile | 3 +-- Gemfile.lock | 12 +++--------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/Gemfile b/Gemfile index 70a6c0761a..cf1617c316 100644 --- a/Gemfile +++ b/Gemfile @@ -23,12 +23,11 @@ gem 'omniauth-github' # Extracting information from a git repository gem "gitlab-grit", '~> 1.0.0', require: 'grit' +gem 'grit_ext', '~> 0.6.2' # Ruby/Rack Git Smart-HTTP Server Handler gem 'gitlab-grack', '~> 1.0.0', require: 'grack' -gem 'grit_ext', git: "https://github.com/gitlabhq/grit_ext.git", ref: '2d1b2f13cabc02520405985fccb2a0abfcba9907' - # LDAP Auth gem 'gitlab_omniauth-ldap', '1.0.2', require: "omniauth-ldap" diff --git a/Gemfile.lock b/Gemfile.lock index 51940606cd..89882492b3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,14 +6,6 @@ GIT activerecord (>= 2.3.0) rake (>= 0.8.7) -GIT - remote: https://github.com/gitlabhq/grit_ext.git - revision: 2d1b2f13cabc02520405985fccb2a0abfcba9907 - ref: 2d1b2f13cabc02520405985fccb2a0abfcba9907 - specs: - grit_ext (0.6.2) - charlock_holmes (~> 0.6.9) - GIT remote: https://github.com/gitlabhq/raphael-rails.git revision: cb2c92a040b9b941a5f1aa1ea866cc26e944fe58 @@ -178,6 +170,8 @@ GEM grape-entity (0.2.0) activesupport multi_json (>= 1.3.2) + grit_ext (0.6.2) + charlock_holmes (~> 0.6.9) growl (1.0.3) guard (1.5.4) listen (>= 0.4.2) @@ -480,7 +474,7 @@ DEPENDENCIES gon grape (~> 0.3.1) grape-entity (~> 0.2.0) - grit_ext! + grit_ext (~> 0.6.2) growl guard-rspec guard-spinach From 95b826071f09f3bb63d663f2210e654609aace52 Mon Sep 17 00:00:00 2001 From: Sato Hiroyuki Date: Mon, 4 Mar 2013 17:50:42 +0900 Subject: [PATCH 097/113] Add some tests for network graph --- features/project/network.feature | 16 +++++++ .../steps/project/project_network_graph.rb | 43 +++++++++++++++++-- 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/features/project/network.feature b/features/project/network.feature index 31ce5ad327..a6cbd2c478 100644 --- a/features/project/network.feature +++ b/features/project/network.feature @@ -7,3 +7,19 @@ Feature: Project Network Graph @javascript Scenario: I should see project network Then page should have network graph + And page should select "master" in select box + And page should have "master" on graph + + @javascript + Scenario: I should switch ref to "stable" + When I switch ref to "stable" + Then page should have network graph + And page should select "stable" in select box + And page should have "stable" on graph + + @javascript + Scenario: I should looking for a commit by SHA of "v2.1.0" + When I looking for a commit by SHA of "v2.1.0" + Then page should have network graph + And page should select "master" in select box + And page should have "v2.1.0" on graph diff --git a/features/steps/project/project_network_graph.rb b/features/steps/project/project_network_graph.rb index b66aadfeae..2ca629883a 100644 --- a/features/steps/project/project_network_graph.rb +++ b/features/steps/project/project_network_graph.rb @@ -4,16 +4,51 @@ class ProjectNetworkGraph < Spinach::FeatureSteps Then 'page should have network graph' do page.should have_content "Project Network Graph" - within ".graph" do - page.should have_content "master" - end + page.should have_selector ".graph" end - And 'I visit project "Shop" network page' do + When 'I visit project "Shop" network page' do # Stub Graph::JsonBuilder max_size to speed up test (10 commits vs. 650) Graph::JsonBuilder.stub(max_count: 10) project = Project.find_by_name("Shop") visit project_graph_path(project, "master") end + + And 'page should select "master" in select box' do + page.should have_selector '#ref_chzn span', :text => "master" + end + + And 'page should have "master" on graph' do + within '.graph' do + page.should have_content 'master' + end + end + + And 'I switch ref to "stable"' do + page.select 'stable', :from => 'ref' + end + + And 'page should select "stable" in select box' do + page.should have_selector '#ref_chzn span', :text => "stable" + end + + And 'page should have "stable" on graph' do + within '.graph' do + page.should have_content 'stable' + end + end + + And 'I looking for a commit by SHA of "v2.1.0"' do + within ".content .search" do + fill_in 'q', :with => '98d6492' + find('button').click + end + end + + And 'page should have "v2.1.0" on graph' do + within '.graph' do + page.should have_content 'v2.1.0' + end + end end From 9a06dd4aa1ab008b6e12205ec3f8d00a50f79aa1 Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Mon, 4 Mar 2013 18:51:00 +0400 Subject: [PATCH 098/113] Migrations added --- db/migrate/20130304104623_add_state_to_user.rb | 5 +++++ .../20130304104740_convert_blocked_to_state.rb | 14 ++++++++++++++ .../20130304105317_remove_blocked_from_user.rb | 9 +++++++++ 3 files changed, 28 insertions(+) create mode 100644 db/migrate/20130304104623_add_state_to_user.rb create mode 100644 db/migrate/20130304104740_convert_blocked_to_state.rb create mode 100644 db/migrate/20130304105317_remove_blocked_from_user.rb diff --git a/db/migrate/20130304104623_add_state_to_user.rb b/db/migrate/20130304104623_add_state_to_user.rb new file mode 100644 index 0000000000..8154c21065 --- /dev/null +++ b/db/migrate/20130304104623_add_state_to_user.rb @@ -0,0 +1,5 @@ +class AddStateToUser < ActiveRecord::Migration + def change + add_column :users, :state, :string + end +end diff --git a/db/migrate/20130304104740_convert_blocked_to_state.rb b/db/migrate/20130304104740_convert_blocked_to_state.rb new file mode 100644 index 0000000000..91c65d4fd3 --- /dev/null +++ b/db/migrate/20130304104740_convert_blocked_to_state.rb @@ -0,0 +1,14 @@ +class ConvertBlockedToState < ActiveRecord::Migration + def up + User.transaction do + User.where(blocked: true).update_all(state: :blocked) + User.where(blocked: false).update_all(state: :active) + end + end + + def down + User.transaction do + User.where(satate: :blocked).update_all(blocked: :true) + end + end +end diff --git a/db/migrate/20130304105317_remove_blocked_from_user.rb b/db/migrate/20130304105317_remove_blocked_from_user.rb new file mode 100644 index 0000000000..e010474538 --- /dev/null +++ b/db/migrate/20130304105317_remove_blocked_from_user.rb @@ -0,0 +1,9 @@ +class RemoveBlockedFromUser < ActiveRecord::Migration + def up + remove_column :users, :blocked + end + + def down + add_column :users, :blocked, :boolean + end +end From 0d9a6fe7b16e52cc4d5595d6b26552c39911cf07 Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Mon, 4 Mar 2013 18:52:30 +0400 Subject: [PATCH 099/113] User's blocked field refactored to use state machine --- app/controllers/admin/users_controller.rb | 2 +- app/controllers/application_controller.rb | 4 +-- app/models/user.rb | 34 +++++++++++-------- app/views/admin/users/_form.html.haml | 2 +- app/views/admin/users/index.html.haml | 2 +- app/views/admin/users/show.html.haml | 2 +- app/views/team_members/_team_member.html.haml | 2 +- app/views/teams/members/_show.html.haml | 2 +- db/schema.rb | 5 ++- lib/api/entities.rb | 4 +-- lib/gitlab/auth.rb | 8 +++-- spec/models/user_spec.rb | 6 ++-- 12 files changed, 40 insertions(+), 33 deletions(-) diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 2e7114e10a..43e6f09904 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -45,7 +45,7 @@ class Admin::UsersController < Admin::ApplicationController end def unblock - if admin_user.update_attribute(:blocked, false) + if admin_user.activate redirect_to :back, alert: "Successfully unblocked" else redirect_to :back, alert: "Error occured. User was not unblocked" diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 5b886227bc..6b72f32520 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -30,7 +30,7 @@ class ApplicationController < ActionController::Base end def reject_blocked! - if current_user && current_user.blocked + if current_user && current_user.blocked? sign_out current_user flash[:alert] = "Your account is blocked. Retry when an admin unblock it." redirect_to new_user_session_path @@ -38,7 +38,7 @@ class ApplicationController < ActionController::Base end def after_sign_in_path_for resource - if resource.is_a?(User) && resource.respond_to?(:blocked) && resource.blocked + if resource.is_a?(User) && resource.respond_to?(:blocked?) && resource.blocked? sign_out resource flash[:alert] = "Your account is blocked. Retry when an admin unblock it." new_user_session_path diff --git a/app/models/user.rb b/app/models/user.rb index cd0754d781..9f5a68d50f 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -25,7 +25,7 @@ # dark_scheme :boolean default(FALSE), not null # theme_id :integer default(1), not null # bio :string(255) -# blocked :boolean default(FALSE), not null +# state :string(255) # failed_attempts :integer default(0) # locked_at :datetime # extern_uid :string(255) @@ -87,10 +87,27 @@ class User < ActiveRecord::Base delegate :path, to: :namespace, allow_nil: true, prefix: true + state_machine :state, initial: :active do + after_transition any => :blocked do |user, transition| + # Remove user from all projects and + user.users_projects.find_each do |membership| + return false unless membership.destroy + end + end + + event :block do + transition active: :blocked + end + + event :activate do + transition blocked: :active + end + end + # Scopes scope :admins, -> { where(admin: true) } - scope :blocked, -> { where(blocked: true) } - scope :active, -> { where(blocked: false) } + scope :blocked, -> { with_state(:blocked) } + scope :active, -> { with_state(:active) } scope :alphabetically, -> { order('name ASC') } scope :in_team, ->(team){ where(id: team.member_ids) } scope :not_in_team, ->(team){ where('users.id NOT IN (:ids)', ids: team.member_ids) } @@ -260,17 +277,6 @@ class User < ActiveRecord::Base MergeRequest.cared(self) end - # Remove user from all projects and - # set blocked attribute to true - def block - users_projects.find_each do |membership| - return false unless membership.destroy - end - - self.blocked = true - save - end - def projects_limit_percent return 100 if projects_limit.zero? (personal_projects.count.to_f / projects_limit) * 100 diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml index 48876338a2..1d1fe341c5 100644 --- a/app/views/admin/users/_form.html.haml +++ b/app/views/admin/users/_form.html.haml @@ -61,7 +61,7 @@ .span4 - unless @admin_user.new_record? .alert.alert-error - - if @admin_user.blocked + - if @admin_user.blocked? %p This user is blocked and is not able to login to GitLab = link_to 'Unblock User', unblock_admin_user_path(@admin_user), method: :put, class: "btn btn-small" - else diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml index f5bb8b0681..9da2871e99 100644 --- a/app/views/admin/users/index.html.haml +++ b/app/views/admin/users/index.html.haml @@ -53,7 +53,7 @@   = link_to 'Edit', edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: "btn btn-small" - unless user == current_user - - if user.blocked + - if user.blocked? = link_to 'Unblock', unblock_admin_user_path(user), method: :put, class: "btn btn-small success" - else = link_to 'Block', block_admin_user_path(user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn btn-small btn-remove" diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml index c5d6019482..2129ceec55 100644 --- a/app/views/admin/users/show.html.haml +++ b/app/views/admin/users/show.html.haml @@ -3,7 +3,7 @@ %h3.page_title = image_tag gravatar_icon(@admin_user.email, 90), class: "avatar s90" = @admin_user.name - - if @admin_user.blocked + - if @admin_user.blocked? %span.cred (Blocked) - if @admin_user.admin %span.cred (Admin) diff --git a/app/views/team_members/_team_member.html.haml b/app/views/team_members/_team_member.html.haml index e7cba0b349..e0485f408b 100644 --- a/app/views/team_members/_team_member.html.haml +++ b/app/views/team_members/_team_member.html.haml @@ -20,7 +20,7 @@ %span.label This is you! - if @project.namespace_owner == user %span.label Owner - - elsif user.blocked + - elsif user.blocked? %span.label Blocked - elsif allow_admin = link_to project_team_member_path(@project, user), confirm: remove_from_project_team_message(@project, user), method: :delete, class: "btn-tiny btn btn-remove" do diff --git a/app/views/teams/members/_show.html.haml b/app/views/teams/members/_show.html.haml index 3aa2db866a..5975810903 100644 --- a/app/views/teams/members/_show.html.haml +++ b/app/views/teams/members/_show.html.haml @@ -23,7 +23,7 @@ %span.btn.disabled This is you! - if @team.owner == user %span.btn.disabled Owner - - elsif user.blocked + - elsif user.blocked? %span.btn.disabled.blocked Blocked - elsif allow_admin = link_to team_member_path(@team, user), confirm: remove_from_user_team_message(@team, user), method: :delete, class: "btn-tiny btn btn-remove", title: "Remove from team" do diff --git a/db/schema.rb b/db/schema.rb index 04ed798461..2250f418bd 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 => 20130220133245) do +ActiveRecord::Schema.define(:version => 20130304105317) do create_table "events", :force => true do |t| t.string "target_type" @@ -261,7 +261,6 @@ ActiveRecord::Schema.define(:version => 20130220133245) do t.boolean "dark_scheme", :default => false, :null => false t.integer "theme_id", :default => 1, :null => false t.string "bio" - t.boolean "blocked", :default => false, :null => false t.integer "failed_attempts", :default => 0 t.datetime "locked_at" t.string "extern_uid" @@ -269,10 +268,10 @@ ActiveRecord::Schema.define(:version => 20130220133245) do t.string "username" t.boolean "can_create_group", :default => true, :null => false t.boolean "can_create_team", :default => true, :null => false + t.string "state" end add_index "users", ["admin"], :name => "index_users_on_admin" - add_index "users", ["blocked"], :name => "index_users_on_blocked" add_index "users", ["email"], :name => "index_users_on_email", :unique => true add_index "users", ["extern_uid", "provider"], :name => "index_users_on_extern_uid_and_provider", :unique => true add_index "users", ["name"], :name => "index_users_on_name" diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 1cae1d337f..088c995980 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -2,11 +2,11 @@ module Gitlab module Entities class User < Grape::Entity expose :id, :username, :email, :name, :bio, :skype, :linkedin, :twitter, - :dark_scheme, :theme_id, :blocked, :created_at, :extern_uid, :provider + :dark_scheme, :theme_id, :state, :created_at, :extern_uid, :provider end class UserBasic < Grape::Entity - expose :id, :username, :email, :name, :blocked, :created_at + expose :id, :username, :email, :name, :state, :created_at end class UserLogin < UserBasic diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb index d0e792befb..0fee33dbeb 100644 --- a/lib/gitlab/auth.rb +++ b/lib/gitlab/auth.rb @@ -41,10 +41,12 @@ module Gitlab password_confirmation: password, projects_limit: Gitlab.config.gitlab.default_projects_limit, }, as: :admin) - if Gitlab.config.omniauth['block_auto_created_users'] && !ldap - @user.blocked = true - end @user.save! + + if Gitlab.config.omniauth['block_auto_created_users'] && !ldap + @user.block + end + @user end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 40047b351d..cb39b6fc63 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -25,7 +25,7 @@ # dark_scheme :boolean default(FALSE), not null # theme_id :integer default(1), not null # bio :string(255) -# blocked :boolean default(FALSE), not null +# state :string(255) default(FALSE), not null # failed_attempts :integer default(0) # locked_at :datetime # extern_uid :string(255) @@ -140,7 +140,7 @@ describe User do it "should block user" do user.block - user.blocked.should be_true + user.blocked?.should be_true end end @@ -149,7 +149,7 @@ describe User do User.delete_all @user = create :user @admin = create :user, admin: true - @blocked = create :user, blocked: true + @blocked = create :user, state: :blocked end it { User.filter("admins").should == [@admin] } From c2082f4d780a44ca0b29c60939dd1ea919d706c1 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 4 Mar 2013 19:47:20 +0200 Subject: [PATCH 100/113] Fix edit team page --- app/views/teams/edit.html.haml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/views/teams/edit.html.haml b/app/views/teams/edit.html.haml index 5491993d5f..95c91b5044 100644 --- a/app/views/teams/edit.html.haml +++ b/app/views/teams/edit.html.haml @@ -15,7 +15,7 @@ .clearfix.team-description-holder = f.label :description, "Details" .input - = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4 + = f.text_area :description, maxlength: 250, class: "xlarge js-gfm-input", rows: 4 .clearfix = f.label :path do @@ -25,7 +25,6 @@ .form-actions = f.submit 'Save team changes', class: "btn btn-primary" - = link_to 'Delete team', team_path(@team), method: :delete, confirm: "You are shure?", class: "btn btn-remove pull-right" .span5 .ui-box %h5.title Remove team From 24cc0faf2cecc5148082e6f36363c57a0bdf1a09 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 4 Mar 2013 20:11:23 +0200 Subject: [PATCH 101/113] add link ti public area --- app/views/layouts/_head_panel.html.haml | 3 +++ app/views/public/projects/index.html.haml | 2 ++ 2 files changed, 5 insertions(+) diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml index 8f4f3d7815..1f3ce2f40e 100644 --- a/app/views/layouts/_head_panel.html.haml +++ b/app/views/layouts/_head_panel.html.haml @@ -8,6 +8,9 @@ %span.separator %h1.project_name= title %ul.nav + %li + = link_to public_root_path, title: "Public area", class: 'has_bottom_tooltip', 'data-original-title' => 'Public area' do + %i.icon-globe - if current_user.is_admin? %li = link_to admin_root_path, title: "Admin area", class: 'has_bottom_tooltip', 'data-original-title' => 'Admin area' do diff --git a/app/views/public/projects/index.html.haml b/app/views/public/projects/index.html.haml index 21e9d2e602..52e01c3d56 100644 --- a/app/views/public/projects/index.html.haml +++ b/app/views/public/projects/index.html.haml @@ -12,5 +12,7 @@ .pull-right %pre.dark.tiny git clone #{project.http_url_to_repo} + - unless @projects.present? + %h3.nothing_here_message No public projects = paginate @projects, theme: "admin" From 533693ab41cdabb15078aa038082c2c8ccf7d5b3 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 4 Mar 2013 21:11:03 +0200 Subject: [PATCH 102/113] Fix dark color bg for wiki --- app/assets/stylesheets/highlight/dark.scss | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/assets/stylesheets/highlight/dark.scss b/app/assets/stylesheets/highlight/dark.scss index 6018ff7074..4196ea7ad2 100644 --- a/app/assets/stylesheets/highlight/dark.scss +++ b/app/assets/stylesheets/highlight/dark.scss @@ -1,8 +1,7 @@ .black .highlight { - background-color: #333; pre { + background-color: #333; color: #eee; - background: inherit; } .hll { display: block; background-color: darken($hover, 65%) } From dc7507cfe7a677f4436f30a2414b09ff7a1998e8 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 4 Mar 2013 21:12:36 +0200 Subject: [PATCH 103/113] = preserve do was ignored for empty project page so was replaced with filter --- app/views/projects/empty.html.haml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml index 22aaaf0f2b..07132e6787 100644 --- a/app/views/projects/empty.html.haml +++ b/app/views/projects/empty.html.haml @@ -5,14 +5,14 @@ %fieldset %legend Git global setup: %pre.dark - = preserve do + :preserve git config --global user.name "#{current_user.name}" git config --global user.email "#{current_user.email}" %fieldset %legend Create Repository %pre.dark - = preserve do + :preserve mkdir #{@project.path} cd #{@project.path} git init @@ -25,7 +25,7 @@ %fieldset %legend Existing Git Repo? %pre.dark - = preserve do + :preserve cd existing_git_repo git remote add origin #{@project.url_to_repo} git push -u origin master From d54845a16a8c6c646ecf1d29ca385644f7b2660d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 4 Mar 2013 21:34:26 +0200 Subject: [PATCH 104/113] use md-typography for note content --- app/assets/stylesheets/gitlab_bootstrap/mixins.scss | 11 +++++++++++ .../stylesheets/gitlab_bootstrap/typography.scss | 10 ++-------- app/assets/stylesheets/sections/notes.scss | 1 + 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/app/assets/stylesheets/gitlab_bootstrap/mixins.scss b/app/assets/stylesheets/gitlab_bootstrap/mixins.scss index f416be95de..0a27a8350b 100644 --- a/app/assets/stylesheets/gitlab_bootstrap/mixins.scss +++ b/app/assets/stylesheets/gitlab_bootstrap/mixins.scss @@ -75,3 +75,14 @@ line-height: 36px; font-weight: normal; } + +@mixin md-typography { + code { padding: 0 4px; } + p { font-size: 13px; } + h1 { font-size: 26px; line-height: 40px; margin: 10px 0;} + h2 { font-size: 22px; line-height: 40px; margin: 10px 0;} + h3 { font-size: 18px; line-height: 40px; margin: 10px 0;} + h4 { font-size: 16px; line-height: 20px; margin: 10px 0;} + h5 { font-size: 14px; line-height: 20px; margin: 10px 0;} + h6 { font-size: 12px; line-height: 20px; margin: 10px 0;} +} diff --git a/app/assets/stylesheets/gitlab_bootstrap/typography.scss b/app/assets/stylesheets/gitlab_bootstrap/typography.scss index 2f7b1d25a4..a7d71d53c2 100644 --- a/app/assets/stylesheets/gitlab_bootstrap/typography.scss +++ b/app/assets/stylesheets/gitlab_bootstrap/typography.scss @@ -87,17 +87,11 @@ a:focus { * */ .wiki { + @include md-typography; + font-size: 13px; line-height: 20px; - code { padding: 0 4px; } - p { font-size: 13px; } - h1 { font-size: 26px; line-height: 40px; margin: 10px 0;} - h2 { font-size: 22px; line-height: 40px; margin: 10px 0;} - h3 { font-size: 18px; line-height: 40px; margin: 10px 0;} - h4 { font-size: 16px; line-height: 20px; margin: 10px 0;} - h5 { font-size: 14px; line-height: 20px; margin: 10px 0;} - h6 { font-size: 12px; line-height: 20px; margin: 10px 0;} .white .highlight pre { background: #f5f5f5; } ul { margin: 0 0 9px 25px !important; } } diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss index 1f92a3a835..1b4280f497 100644 --- a/app/assets/stylesheets/sections/notes.scss +++ b/app/assets/stylesheets/sections/notes.scss @@ -83,6 +83,7 @@ ul.notes { margin-top: -20px; } .note-body { + @include md-typography; margin-left: 45px; } .note-header { From 730e79e78785857fd706b73252547a5c7f6431d9 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 4 Mar 2013 22:00:51 +0200 Subject: [PATCH 105/113] better event-notes typography --- .../stylesheets/gitlab_bootstrap/typography.scss | 4 ++++ app/assets/stylesheets/sections/events.scss | 12 +++++------- app/views/events/event/_note.html.haml | 7 ++++--- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/app/assets/stylesheets/gitlab_bootstrap/typography.scss b/app/assets/stylesheets/gitlab_bootstrap/typography.scss index a7d71d53c2..1f0c480231 100644 --- a/app/assets/stylesheets/gitlab_bootstrap/typography.scss +++ b/app/assets/stylesheets/gitlab_bootstrap/typography.scss @@ -95,3 +95,7 @@ a:focus { .white .highlight pre { background: #f5f5f5; } ul { margin: 0 0 9px 25px !important; } } + +.md { + @include md-typography; +} diff --git a/app/assets/stylesheets/sections/events.scss b/app/assets/stylesheets/sections/events.scss index df8fd8d645..94e1d0b609 100644 --- a/app/assets/stylesheets/sections/events.scss +++ b/app/assets/stylesheets/sections/events.scss @@ -48,15 +48,13 @@ color: #666; } .event-note { - padding-top: 5px; - padding-left: 5px; - display: inline-block; color: #555; + margin-top: 5px; + margin-left: 40px; .note-file-attach { - margin-left: -25px; - float: left; .note-image-attach { + margin-top: 4px; margin-left: 0px; max-width: 200px; } @@ -66,8 +64,8 @@ color: #777; float: left; font-size: 16px; - line-height: 18px; - margin: 5px; + line-height: 16px; + margin-right: 5px; } } .avatar { diff --git a/app/views/events/event/_note.html.haml b/app/views/events/event/_note.html.haml index 19665ce0ae..199785e63f 100644 --- a/app/views/events/event/_note.html.haml +++ b/app/views/events/event/_note.html.haml @@ -21,9 +21,10 @@ = event.project_name .event-body - %i.icon-comment-alt.event-note-icon - %span.event-note - = markdown truncate(event.target.note, length: 70) + .event-note + .md + %i.icon-comment-alt.event-note-icon + = sanitize(markdown(truncate(event.target.note, length: 150)), tags: %w(a img b pre p)) - note = event.target - if note.attachment.url = link_to note.attachment.secure_url, target: "_blank", class: 'note-file-attach' do From bf06b3196dfd303665058455529e344d54867e25 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 4 Mar 2013 22:18:53 +0200 Subject: [PATCH 106/113] Make clone widget read-only --- app/assets/stylesheets/common.scss | 4 ---- app/assets/stylesheets/sections/projects.scss | 1 + app/views/shared/_clone_panel.html.haml | 3 +-- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss index ead27922cc..c967c2d1c1 100644 --- a/app/assets/stylesheets/common.scss +++ b/app/assets/stylesheets/common.scss @@ -193,10 +193,6 @@ input[type=text] { } } -input.git_clone_url { - width: 325px; -} - .merge-request-form-holder { select { width: 300px; diff --git a/app/assets/stylesheets/sections/projects.scss b/app/assets/stylesheets/sections/projects.scss index b37830b138..ada0780eec 100644 --- a/app/assets/stylesheets/sections/projects.scss +++ b/app/assets/stylesheets/sections/projects.scss @@ -80,6 +80,7 @@ border: 1px solid #BBB; box-shadow: none; margin-left: -1px; + background: #FFF; } } diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml index 7b5de4a627..bd9ca72935 100644 --- a/app/views/shared/_clone_panel.html.haml +++ b/app/views/shared/_clone_panel.html.haml @@ -1,5 +1,4 @@ .input-prepend.project_clone_holder %button{class: "btn active", :"data-clone" => @project.ssh_url_to_repo} SSH %button{class: "btn", :"data-clone" => @project.http_url_to_repo}= Gitlab.config.gitlab.protocol.upcase - - = text_field_tag :project_clone, @project.url_to_repo, class: "one_click_select input-xxlarge" + = text_field_tag :project_clone, @project.url_to_repo, class: "one_click_select input-xxlarge", readonly: true From 9bb35e7e59c79031544b4b52516723a13d3bd452 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 5 Mar 2013 09:27:06 +0200 Subject: [PATCH 107/113] Prevent app crash if team owner removed --- app/models/user.rb | 49 +++++++++++++++++++------- app/views/admin/groups/index.html.haml | 2 +- app/views/admin/teams/index.html.haml | 7 ++-- 3 files changed, 42 insertions(+), 16 deletions(-) diff --git a/app/models/user.rb b/app/models/user.rb index cd0754d781..babf00e805 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -46,10 +46,35 @@ class User < ActiveRecord::Base attr_accessor :force_random_password - # Namespace for personal projects - has_one :namespace, dependent: :destroy, foreign_key: :owner_id, class_name: "Namespace", conditions: 'type IS NULL' + # + # Relations + # - has_many :keys, dependent: :destroy + # Namespace for personal projects + has_one :namespace, + dependent: :destroy, + foreign_key: :owner_id, + class_name: "Namespace", + conditions: 'type IS NULL' + + # Profile + has_many :keys, dependent: :destroy + + # Groups + has_many :groups, class_name: "Group", foreign_key: :owner_id + + # Teams + has_many :own_teams, + class_name: "UserTeam", + foreign_key: :owner_id, + dependent: :destroy + + has_many :user_team_user_relationships, dependent: :destroy + has_many :user_teams, through: :user_team_user_relationships + has_many :user_team_project_relationships, through: :user_teams + has_many :team_projects, through: :user_team_project_relationships + + # Projects has_many :users_projects, dependent: :destroy has_many :issues, dependent: :destroy, foreign_key: :author_id has_many :notes, dependent: :destroy, foreign_key: :author_id @@ -57,18 +82,16 @@ class User < ActiveRecord::Base has_many :events, dependent: :destroy, foreign_key: :author_id, class_name: "Event" has_many :assigned_issues, dependent: :destroy, foreign_key: :assignee_id, class_name: "Issue" has_many :assigned_merge_requests, dependent: :destroy, foreign_key: :assignee_id, class_name: "MergeRequest" + has_many :projects, through: :users_projects - has_many :groups, class_name: "Group", foreign_key: :owner_id - has_many :recent_events, class_name: "Event", foreign_key: :author_id, order: "id DESC" - - has_many :projects, through: :users_projects - - has_many :user_team_user_relationships, dependent: :destroy - - has_many :user_teams, through: :user_team_user_relationships - has_many :user_team_project_relationships, through: :user_teams - has_many :team_projects, through: :user_team_project_relationships + has_many :recent_events, + class_name: "Event", + foreign_key: :author_id, + order: "id DESC" + # + # Validations + # validates :name, presence: true validates :email, presence: true, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/ } validates :bio, length: { within: 0..255 } diff --git a/app/views/admin/groups/index.html.haml b/app/views/admin/groups/index.html.haml index 1b4ffcb6e0..b10a7394bd 100644 --- a/app/views/admin/groups/index.html.haml +++ b/app/views/admin/groups/index.html.haml @@ -26,7 +26,7 @@ %tr %td %strong= link_to group.name, [:admin, group] - %td= group.description + %td= truncate group.description %td= group.path %td= group.projects.count %td diff --git a/app/views/admin/teams/index.html.haml b/app/views/admin/teams/index.html.haml index 62af4b5093..3690d6d9eb 100644 --- a/app/views/admin/teams/index.html.haml +++ b/app/views/admin/teams/index.html.haml @@ -27,12 +27,15 @@ %tr %td %strong= link_to team.name, admin_team_path(team) - %td= team.description + %td= truncate team.description %td= team.path %td= team.projects.count %td= team.members.count %td - = link_to team.owner.name, admin_user_path(team.owner) + - if team.owner + = link_to team.owner.name, admin_user_path(team.owner) + - else + (deleted) %td.bgred = link_to 'Edit', edit_admin_team_path(team), id: "edit_#{dom_id(team)}", class: "btn btn-small" = link_to 'Destroy', admin_team_path(team), confirm: "REMOVE #{team.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove" From c6d6bd6ab48c999c46e3944bd037f6b34f55fa93 Mon Sep 17 00:00:00 2001 From: Andrew8xx8 Date: Tue, 5 Mar 2013 14:29:44 +0400 Subject: [PATCH 108/113] Typo fixed --- db/migrate/20130304104740_convert_blocked_to_state.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/migrate/20130304104740_convert_blocked_to_state.rb b/db/migrate/20130304104740_convert_blocked_to_state.rb index 91c65d4fd3..e8d5257ac9 100644 --- a/db/migrate/20130304104740_convert_blocked_to_state.rb +++ b/db/migrate/20130304104740_convert_blocked_to_state.rb @@ -8,7 +8,7 @@ class ConvertBlockedToState < ActiveRecord::Migration def down User.transaction do - User.where(satate: :blocked).update_all(blocked: :true) + User.where(state: :blocked).update_all(blocked: :true) end end end From f9200e118c3afb6384bc858792133060cf6655fe Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 5 Mar 2013 13:16:56 +0200 Subject: [PATCH 109/113] remove custom font --- app/assets/fonts/OFL.txt | 92 ------------------ app/assets/fonts/YanoneKaffeesatz-Light.ttf | Bin 77296 -> 0 bytes .../stylesheets/gitlab_bootstrap/fonts.scss | 5 - .../stylesheets/gitlab_bootstrap/mixins.scss | 5 +- 4 files changed, 2 insertions(+), 100 deletions(-) delete mode 100644 app/assets/fonts/OFL.txt delete mode 100644 app/assets/fonts/YanoneKaffeesatz-Light.ttf diff --git a/app/assets/fonts/OFL.txt b/app/assets/fonts/OFL.txt deleted file mode 100644 index 3ce219f012..0000000000 --- a/app/assets/fonts/OFL.txt +++ /dev/null @@ -1,92 +0,0 @@ -Copyright (c) 2010, Jan Gerner (post@yanone.de) -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/app/assets/fonts/YanoneKaffeesatz-Light.ttf b/app/assets/fonts/YanoneKaffeesatz-Light.ttf deleted file mode 100644 index 5026d3bdbe2684ac46d7a651b340364157db2db1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77296 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�Q%A<$5%gF<=m_50B^!2v{W5FE!H5`5? z`64lAYVXMHFApSxMXvQu=*fNOZ4D#>NVE^;M#4O!cXREa7m=G2^g_vZ(92Q0tjrU= z&^*!0L#yVAUX1TQO!!~H|FX4G;d>v>CYg?U{kZ} z5j!|njfyG9&Q+swJ+j52h^SHF-xf70RJ;3I=^%PlO7OW~Og^_&)b65B)s6QQ38iPF zBM#+t)E}6}XWD$PNe@CUn&yZ|_n8CJ6I{r07%!%$hr&eUj43EA>flV5?`&m6T5PrJ z$Av>q^=MS>;gKZxe?JRvtT$%+LS!h`rcjJ%vHo0mg7)_x1U!^<;v8~)AbH{&+b#3)7fn=Id9+fc-?*rAS|=O@^7T0&=(E#3G8Pt zT^OJ<(iXPL<9PN+d$Fah!V?DX0w(Ab+^cnVEp~QwwYu28i4RdCVh#$>I0e&A6P_jp z3tL6|GP;8(hcisYSM%%fZk9sl2J5V-bhC^THk(<~R}#wn>@t%A>FzUiorQxt8yf=d zY^f~tcDKT_9Npe9w05MDPdds6iWBAV^J-G~%Te~J%ihM&uqgXPjY__r$aIx7Rez4n zWF1+Dp`vZRRCMQA)hk+XVBdYt^6nWb1|^*go)EoK@_Rw!O~72iNzHqNeJtu1q;F$> z59V#`BSic7zF{|$J#E;{hjE$^+0!~0<63bY;tslw5eE@DHE|tcLR@DCFW{j;2i z_Gro%!g&oIv|4zqy;W4WAl53KVjHjzJN{dcC=o>PA`6sY#4|pRgt{2%UHxIb9ztA+ zNmK0O(tnBk3(mmt(rG(@Gpcyc%Dk8dGXdbuzP?JMR_?Ecbv>?!qA}^dMzz%HuN9km zG!jpQKm^8Gw)3R)aYU@53DG9HM$SjF2s$bs)*kU&o(+ z79weLoP|i|`g9LNgMDfUIGlNqbr|8s1&WgarEiz7lT#2#MDT?BHLhcwM z24s!^bD0i0T7A8r!?=i@b-m@gajN^J=eVAkM?>v380TEq8#k6WkhR;Blj2ZGiDADu zxt8{eY#P;sAz)GL=6^+i*r*JHpG)VhWEMLaNMP&$buHY@r-+f}AQ5L<2?2oz z&OXXo|092Qk2r(+gDYoHe`WP?)oV_&{)6$!=IPAJ8P^SGuqRM%{BGOEmD8^S_!~On z+W5p_98djeaXhs&dHiJ??&GV^vR-q@_4!8+;`HlbI{kVJKIjprU-!7CcD%qm$+-kD z{!Ni{`+v(${~u(Ze{YQ!`oe?jL~1#jDFyo5!;}}(MQV9!Fx*$9rUmE-JpWj%>HlvQ zu>HI&-`XtTkGn~{)mgp>vV2H!BZ(Iaxv|zF);iTq;-!%XZ@2pcrA*XF;;qAK3vtHr zt75<9+u=pW z;L3%FjQAPaugKZJ(c^d{+PEl+)?B2MI`C#}5r^9ujAquqqkoeU=21E%p?gkJ%?Nd( ztq^}0)yRqtioZqpZ3kVs&}iSw>c^uvAf+CXUJ*| zIMS1Yv0$<0i3LZdvyQOG7IZ3ppVQNSU`s6MsTE_vjeGk%u#d9%{i5$9?=}Dk-MY|{ z5M^4ZNmMWr7F7f>%Dz$2cTE)9^a3`}il|E(HcFEOHcSB|%3jTZs4_MO;}A3B=0FG_ z8ldVMhiFo3<_G~z)EU5K*I^>UEoh zZwWYEUXRNeu)I=Im%gS-*ISd>yerbMoNv8wt38`f*N!1y{V| z1#GHr)TC>FNze;SDx)WD2=M+I(t4-|rMe6o)tJq5Y8w*S6PqYQAA~fgR$Rgc8j!;lmrW)5RXpB5Z^7K zWsaJ|M8fhO9K=)JPCatj#&9q-9E`1tpKtT$gTXTTU3GpYE zw%}kdqjPTS==!wk_vr4N%e$s`PJE-WF5L_`oz_sTL~=obj%WNN@L&h!-$lG{H7cQ- zT1Q)?gWag54!w}MZukH>r%nSP$H_1Rr!_SIq6*LibPf>AnS(WeHsy)9z)FEII*qBq z9T_p)Z2)Y5L)TEwN|86~8b}fl1)Kmwm}n*l`FV6`gq~UY1p1mLdYa?O#;{Tz3IS&O zskd+w0gc*)C=}BWJ%*E;^7eoaK7jI=yPuAiftW;UK~N{z z1{#3k$8VHSd&GQ?L7Mn|4=lbcIwtzML@D-d0%1*wi74_jEs>Q*1OjOpfGeAynE43Q z`k`R0(`~pcpj}`Qv_~%A>V`|i&;&Vk327~W90D%2!BBQgCs=rr9#1wIyp(`*zGP7< z-OkI&O*y;QeR?w>Aw7h%q$2};v#Vhv;}^K#O@d~I!Mi)y|AM^+p9sGaQp58M<@f2N zBS_0>QF#Rx27f?onw+`@C?dOWLTDOWpEd_OFxX)ZDi~BupqLRHK|m`>8iL)LqVg^H zn=Qn{eol2@UD)}>;kRgvXCgyX5)6z2F{myu_5^ScStb;t=N`Jd*%X9<~B^ z_=R2CMTpflksTNke7qsu7?S0)iSj)J{BQcTLd=y-h2L|U4t~(nXK{1DhlZ2q5o(w3 zPpvB&JiUD>+NE&fZNgI-6Bh!m=3otHuSt%Yod^O;D=nRbB_SFJF(cx*VQ@b6alr;jEz++5fwV_VOT?~q zHZFD$bu`7n3W!(pzKMc!h+O3LAwSMwMrw1EuG-@vUoPQ0BNzk@wwt(04hHqnSY<@x zeCdCD8l)^CM)Vr~C1PpeMrHFVjyPNR`f$9o-_GAURq7&z{37(rNH?KhrifpRBR}XM zuL${D!#Ney2bYH?JWj?0TI&t>dboS$4xL{_A_l!bH8Tb*O6N@!2oJ~1nw^m=M(s0> zKIjE-jbpmuww$S`hbaMDVs%E+2bgw?0?h2?XC`J)G0^Py6*FPaWGU4ugmR->3O%EK z{2a>;6)EQaVnmDO{OKX@lRbXbr@H)Vq>|m~ONH7;w(PrdDiYLA|E4@z@JY9+UVrm~ z&12iDzHE+cQa7Fy$k_7p`_g;QB|rs5nY%84yH{emLf;cboue2-%yJ=qGYYkp=m)x9>cFSJ8o!y4kPrY|xLj1@ZjvsBoY^G0svu#Y zA0czrFLo{$4)u9m2SXUeggxjY{OLA+0sd%Qc;I9W3vI8Ub%K7r0(KN$1w_O?bOs`GY()N7>Q3Ps$(YMsnVC~w~J|iZ!Rjw$D_%lVz)>={=Pt1 zkM`&l4X1N?J(?%&LEW<_4ex<$=-zrH7j~?h8op`3pX$|Py~&^r;b*HaKb$X4RKkJk zre?5`4a-(l@@*LK)%R{dJX4k;$=ELB!(_{)Y2ODQTR)M3R*-Bzo^ z=G2_osTNl$61rh7r)XioTR{Vx8cziMgGaW_UA3j)%8b_RJ*jRCc5wM-{x#`oIl4XE>g&ji=fyBZNA?WEm`o@%84VwkpX6e3^%J{ zp-+j3r+5o!!cinBClppMWC?;IqJDQsBuqsiwW5&7hSNt!48e6FIyP|tY=yh+iHNqh zuU{3$Ke#(uPWez+kNEyri*J==+pCi!eeq~>u92=p@nb6fQhxomT0YcFyb}iSMLL@Q zx`BSlw|~9E?ZwXn**qTq=#~*HdbnIqT6A;(H}+0s?QXBl5mwyV1v>_ZU8>9>pnJuStzmv!+HeN`t-_+gs7nb(WPnYm+tL9liKy#iI{fTb3 ziKSnVO+x{6I(s^V4zt5#ZHMdP?CG*e(LT_%CcKtJSBD7wX!_h{fh+u~yg1i^u8e%!>| ziTFg6UjvQeTp)!s9#~6Jd`3JV=K~YAarhqc6sJzAvg1WxghG3!tV)hDc}@IHnRr;v zE`6s&?$2g-JZy3EK5=?2mbQEv-0@MI(GX%oSRWnhX{^slb>fWjXILT`b|UadRsaEm1rHBkkq~lGf&?^a_uzkDi}+QXZ$=T7%}T&utLAL7%W|=- zIG27aE3WILYaLq9hEws-Ww3OQ$LVpq(H_AE#Ts;e3~Lx=;|m#z4H;`Nk9@!Y~^eW+)D;Dp~p4U z-nciK_D}Y?TG>sreuv`myFK2%QX>EVwRa|fQC3&OerF~#naq-PvL`SENC<=^5Ej{G z5jR|MZ$E2*Bt$|IlK`S^U8>f)*Q&+ZTC^x&`?W|&5QRcOD`;94EtX2dqF^uq5&{t< zVgBdbciv`{c~HOMW@e*I?zl@nuKM8!`1_4DwYv6Ff-wt;;$EmIi-pQu^@k1d;;wd~5QWm9Do z5}2xma;^-2a|r!Z$^$%yb}Qo4&>w@iE|VWs)4-^*jWMZuiD22*Yaw2hi)G`&-yETf z@odE-N>%78tjrQcde_}KW!-Ignidd|F1r9_I7{(szuOx=&)aDOd46|&T<-$gp9(Orp`4=$G(27mdOs~@)%9sPJa!?ja2$6}t z;ZT~IaokrdOmM{^Q-nRpX+Pq8734OQul&^|Ji znSMZA0{q||C<=bVr4@?%rze;`?5UjS&5yw-vu+nal?8q0t zMwZ9Wi#$i7=j_N5nlZ!`5+3bN^twV5QsXVrS564+l^DeK7@@(TtRZ2p508vAoBIq( z{m$rwzVYE!N7}%#cVwjWi?*9XgOkTxKID#3=_yv1JH~Evd%W=@W@PuuNRmw(P0aDR zQ~MGc#y|th`9lLWDNR9I{OQo3Pwwp{vvn#nWX`JeHVS@f+LYj@w+_X^rYUpl@2-~p zf|YosVF-1h<|M1tJurZfG`avBjw>ew*@Ai{TFhZiKQ%89T+*qzV{}5F_;6cDzky@F zGcYAB+HSEqtnTo!mn94uJhTTCvGPH*!yw5!Fi}W?CYQF0_1G?-*aDn0W&+Y<6wMdoN`NLPm})V<4U0XG5Xw zb~_m5{2HFHawUutRbGvgF56nG_L10E{6tysPo^%*Qo@7TwA7XcZBi-_i_9)TW(Xu$ z?SsSoi($iJ-!@0Pqa4V`zS!-y1%KaZvaVtp=zT7eZLHbDNNa1TImT{Y>UO&;*$p=+ zC_2=CZ6LR!Tw%Oqvlffksdz0z7E+8Q{cHb^d)d zLs^v(w^twdLmM5uacR|DDZN|T-xk9s$<>GcczVUS(&J*|l44^M63tJ@;Gcn+!Jgg; z30zB#i9_zPw%~2%srU?6U?IhKh1q)F4el#3a!yk*m0}(hhhZJ#ZDrf2G>M4#R}7HH zsF8_;L<6Q5fWj)>W34Oqpv9#6Bo=P9^p};?(l)M%2}k<%siep)5Yd> zj5@qYD_M54)XZ>m5d!VM}>tkdqi$0 zdF6J`gp2&QPu&yI*W>6P5zC65eLW!qB4T@?rxxNw?WQjn`{7Z$Ip(t#rL57WN2L3x z5gwFS)hDep@a)qZyF{Ih;Gfd5{y2K7qkxvInqMq?_u$hRkxo(gScBV`qnKgC^`S|6 zB^+zYi*SZJB8J3x$7CfJ{ug@@54WczjGr9SXJBktX80<9RqPBStQPdA5PS5{TQB+X zQ=zUt){uGSBd=g_(h$c%+0DxQGnbRWlVTg=uupTDXWNVME(%HI8W`5a=#i{URuMv@ zUAoN1(yD4JVj8Eh%Ee8jXkb<#NADx||5vt0b*ZZk_P4UFp-~Y7^DT~|%*7VRZw3X0 zg+*r-S)8Q5Z78zZYL@z?tG8*FgmgR#~r0-(Y;?WB)da9cn zOrx%?Vs}_MiGYF;2EvG1RVYvCcUmgvLtH(Eq$Q>Ij17q%HE6`7i$^#jLwXO5h#fni zS2mkkjI)P_1V_g8i0qS@91|LmkZ`IYL`IosdQ47qHZqxc{_%s;6T;(rh4&eD+2qSF zBP?MK9@M+{a5k~I#*r8n(JLW5GdpDfTaTHd$4B&v4;$Ji$UBHpl}atk;@o&k#DRFw^h#o~{8Dz9dBHKC9B^&;x z*H~v*nOcJm)m}Ax?ZEyJ7IBr15Px(BpNbKY)Z1ci3G*mdFjiba-4e@C)g70ldv2I) zjd8j|?)a9w?pGvB*! zM?zNY~6jFIZtF{PvXhEX80=qzPSEk+m12D+*y zkQMHwecF5EuU<8Uu_sN)vL~M2Xo>p0>Bpu6L9{}nPF;FxvCGA9E0dPOoU0eeD_JX+ z@tACbC4(tg*G%utcNiQqf))xN73MXBt-`#G&n{JK5X$*cQ(rI_uhFC+Krf*ptPV*1jYMl(wwoEd99d1{oE7XNo zp=fC{y+AxR30fF$;2#)*Q4HHcL`>E=*V)-+QcRbSwGrJ^R2nfdb)vdA#f@X}rjCfG zFiHFmotCtSvyu|(I*k(3+Edp#LxS`l8fa@f36b^UN1JNRduWID*7tzZ(N+^V;4Kcn z_)RQ_?O$tLtfk=-&_^ZRa=LaZCxCvtk7V)W0R!0gTCJTdXBh(+39AngF<&%#QZIXy zE1dBk*4XU+?f*T7bC1&=&SJ{e*ep68*%y{rPcpF->35tc{f<}@JDNfp1c62<2NL&& zT2wZ+RV-6hKw>D&HpS4zs7@>&bLthv(zedVj5nAb9qc(%pLMtVWO6@e_)T%Ht z7X)kJ_mEXThVCNcG5EKGOtJN!GPWlb(Bug{vU)`_rjkuwvK*e|sQ!aYM@nZzWnVXL zR(?e0b)&P#^mbo$lkC)ax!^`0A^%<)EGQx+DKe}_W>4>+UJ>C5DG@(0o9)i=?&P@e+oxxb?-v=7knFzRY;ic_ zulV+zBW@_Wv`5m!(y1e6-*Hu()opV`Mvc0@VC?T+?sM(;ZkaIa`jO#Qcd#>Dc+pFn zMT{XGIVI|zAW|X10&y}ogSZtz7drpNq6{6X2N&7E#*{}FS=gyoi`f}s$}S0Vgv`aR zIK$so{2h)BT!RgaWlWROTqA<1PP)Wplo=HJCY#!bz=tazB{nL`PkL|vf{DYeks%>& z^ELU;3*|Q!o1;S=?%==Cp=Cd{!@}l8At4cMA4ND>%~|1Kl=;CLF-NoX8+lZ7n3&^0 ze;uu&`9`Ismb@@dl-Ux?;8kUeEv>{vG1LeYg+HiAjBch*w+u#K&1oitkw8e%ahjoc z)Z)0et0nm*EvEIS`kZDjOm#^yle*fJOO)G)9btU8=|R(d%D3&M5w9TljX{$EH#9*V zbf@4*c8;s*5(J3Bxszfg?Kxb+;4U|f2!V||VFU#F#>RUSd&I`~lTB_dL7~Ib6H}6t zqUkb-u-U`Rw&>)(F)Dmy@iHV-%G>0qJG`=H%V7EF#!=rkK(X;C! zfDnFHNHiNwvI~V9M_ED(;gR9V&JZ9g zVoe;#5*3ve96P*mBcCUpc-(55&Nh?3`0A_HR^IJP`%2;lI8iR~3Gfuno7AkMb&{EZ;HBO9nSLJBcD8S94^(CEZ zqh;V1TaGNFJurR?9n;FF#^OGv$=)sJ3!4y88AfD9HF)vVf>nS;#aG^o4U3L&o;{v2 z#_S1=By4zEsO9@^lg(7k)<$dH!8TLnIRh=1()sh-fG`Zfmke{1n@CiUN0tB~_B4q3 z3?^)O6mh3~lgE%>m$ttOCMo&pO&Cx8v(F(0Fg)BP8z1cRQCCtF>ScevE?q*bl;+vTFT64AtdJ01=0I3h^MdS--QgVVaECO2eFu2>P1O5eDm zBci7;bSMLk6>55LLgm!$^9JH-NV6WukjlpN;`I;To|AL?!`J(Nzm?ECK6RicDl;{q zPeM$J)7iV4NG_d4R=dN2#dkTJE~g`c=%tLNpwhQF9n4K;z;X!J?Lq9`#Fppc=r}^{ zE_N}ddwH@n<7_T_h&zbQj-7Uooo=Nl)+}MM%_v(6le9vd4zb=L9tZ1&S%O#z&TO?< zBU$n!)Zqxj^=IwiV6$x`FIcR>!PtL>RWtXM)i&%FM%lA?u9NISB3RXpZq*pjVSnxj zhuLcWLjZA#$RG6Tk&v3wH$J{^N@_xnUU42zT$&}Mlzl?U#l>o~_6SqQxx->{*lkWz zD{}`}eU^Bk!(pCwzb%M-oKA}+%I+{ZQk=sX8{!HIk~7ooDU3sjvN0Lb8Eki0?0vpv zF|oL(%@h=JR|p&N1j`*;BsFzzXu2mh-sw(^n9J03J~F4UfNqbUW9gVvXp?9JWfi{w zJ4XA1f#wnzcYba)d&~t?w{&@hsy2sao}?W$Z=rQeT%Z0~t2BgpRa*4~tA`Ck?z%Zg z>OF(PqLV#Q2_CmKh^|$W&C?@2DKVpGM3{Mtt7ifumlNqa3l0sAO7nUWdiQm?WSE#X z#5`PUG#{Z4I$HG|;4}rR9t66^BgLjDV=MZIwID(w|5DQySe!OK4p$7@$T?Uz4n+zx zn?JW%Ew+g8AKPs#@yQ5ip`HC4?jv@cOms>acGak$4%Rnr7(NW+0}-kmFp@}m6r?N? zmb}er4`#Q4q!@Q(OjsDJGAdiRe=@P?x#NFg@a8y*vbma#d7J#|3LfZnq9S`L{O zo7P~d0qlXau`4*bqR+$Q%`gW46qLfV?T=-R}oL$Q6_W})ambc{`GJh z8|#Fttp&oxdDI!8Tmz%pRX(J_fR6TghZ2crDxNS>=xQ zC;yFoN{v>hqQhA2n&scv2^|~7+MN<5^=_ewryL7rz;sYWcfJh6R)cn^CnE+Aju}jS z7akokE^A`{D1Faa)<9N!&U(GHXxOPa~&txph1G4$7>D0&4 zC!FIusfmvzYa{0{N=yctg!#vMbgYf6f(wQ>W%PRJ3nLp-IK_HM_lq9X329BFh_>6lRU-)i-5i|G1>cD3>!VtVc$&sl~reMQ`(E+7?EIc+kyT zMK@_eqnmm;4MIXvD*dAg8E+-QVVc+a;$|GEaTQ#7v#*p}1{#K|6zDCXT}RiiOgj^S zAs*IHRehUy5;39X*fXw7F*&SZvJJJx5*{ATP!*f)t}`#0FE<6H4H@oH)0#XJ#$}sN zJIBiRGCeDnUVV1+Uq3csgLnIn&8&CO>_4_>Uai%C9HhmXV*JNeqQL|G$2Kj7wNmwT zg0*p`YyHP|t)J;>|8WR&%~$%59hN!ReEoT+mSi35KXwHiyR{VS)&A?DT7tFIe;lcB zU~hn+5Kv!deT?>k924^kzQTWO)*Qh_{$q=FaqwLKagdf7TB zaj^D%dw>72UAxx4#D5&3x$MXN#}3<oAS!a3rmWh$> zEiB5NR+Q(RS6DIAo6Axj*Lia*Mtc32mQOD$EUhTdEH5m|EGa9(fo=1`mDm@0&jUpUheJGJFoDc5_4%@*=!zwxbm3;=aFEUw_yJ4@(k~! zIn#0ry|Z&EuBBvAfDVb4TF(*IYTZ*W13q)9QeR^(w9t;!X;LR;7fxU_|1w|#(gd0i+M+lF~^5&J4 z&4LxP=S-hzFwoFDl~iGcx1i)S4VDryb!JH^D9WKKAX5sbmF1Sr4=^gl5LKKzJI_0L zG8~$lo9VsP&o`t@jwP5QU3bU>rG#I3cUNGVL;-TkDhj8gxzpx*Z=IW0?!7h-9+nGh zMZ_xCJWSlVtm65N+Sx4?vsFr1KXblTrWI-h+Dxs2y04!$ox0!4IzidQQL`Cc=GAUx zwT5DzE!OhX6Y^vQZ;oW&k}Tfuyqn2d7kON(;A$yHa#pTVFXn1Gu{1Be;YEDC0lAi| zGkG$Pt8>+Rnast!0h|iC>Sdiy$zAZ9%27T?^T@S~C%yhBiuj$*d9g}m2G{3sEcusl zTtQ0m>{RV?RxE6RLhGcKmu2%U3%CfsR1_rz%co}*S_@0-Y2hPmP8}Md#oXbX=a=PH$T`Gb3 zUr3(1eh5b^;7zWQ_-ua5*rmv;bmesY?UeYnJXOLQbKrIboDwOEhF;B4MHfs1_2k@d zd69rfN%T8UNj_I;WM-H2E`&1CaMAsIFe~Fow7(QwMW2Lf(P+{0LZzD`r)kqamWtMwK#`Ptk)PO%67*Z-SjxTm%KFUXNVH#nMlZ+mgkGkN(yenrcrSKB za+*duh2U7w<;?<>w&YgAGo?yOlD}?ULQ7h%V^V3+DtET{jF~OyioaQhIw9%RKU#27Y3}<(XWSlh7gcgi+$=^WGfJ zr>iT5#h0hb`JT;c8u~AM@v?5a)L25ZoavGijt*2cp5!hXUx0jPlcwZ8i9DzAd?Cm3 zo?g3(W(yT1DrW=3t9gGO&)vqaJZW6N3Y;hLY_YmJgJ_N5D}2{W!g%iJ9F_7c+AmVo z%dL)g*K%#7E9FrvtVnha)X3YVq${N=7b>LGO35;w7tV=o&^1i>U7+|N_FVGRu`qO| zKuJNgK-Uf7m~ID0aAa5tp;#>PES?h@W|Piz?w+oJMrkzcT_;u|b>X?x3g@!HM$Iyn z)Wx&XxoBK9e)TdX)=8+6avE4F4cbI&L{cIVu}D$_P3FJUnc`ar#kVS+bn2T}VUd~8 zC=~0O+G%%mI&@1Z9QX3X-AbdyYcec=U?t^aI^2~MrYRh6Rb@%E;##iidMIbQ^bM>H z8YlCNa61!D{C&RSKf_b&n)ikIRH`GNeu0nCq;5VYSsBwzM9{)2m%*ByJ`)E~K^LR2 zL+KR{C#n=ljL<`WMGPYm;)wDl&_j|$w7&=3N?{CaAJ(l)MK}845BFzmSO#S~6Q54} z?ZJ3RLl_}4jF}D>QEQH*FLyLE2F9|+`o+|`6Dg&apa+*Su6HAv+; z))<(I&wL|(>&@(ka4V(!TkLW7U#!vjEA1ie1??&Aan_K2OnZ{utLs=r_f_q`wN2Xl z+HaBZbnO}B^&wK*sC}Sq)@rpsYJZ|Eexz+-9?kF2{wCIa->!YE{TZ1yXg|{KL`Pz#LiFG+RhyQh%@yd%JT&VbH0NIS2Kuh{mi7w$EZ^7e*B;OswYRlTh-1E~eXi}( z-qH4JUzmclzi4~3o!Z}6gKoK2sa0z$wRg1@T9x*m_CxL0+8?yvvm?Z6xc`K9*ksez zX*H%`lid_za+sVZm&wiAM`5OL?SQsd`;1s#i+02mp&iwZ5zDJ*ERc-Byp4sWcs$sdFiOJrrMYp=0lb~V}^|# zX&G$!i}exfLTj~kqqWZ3WNo$CZNIgx7&xrYM#r~pe+c#j_YXeW>stGRDHB4bI3_#3 z&Gl)H)y`-8zU8{#o$uZfIx@60?DyeqkqMEFlT?3vQDvBxd)-&@`5+LQ@=clO@aXCvP~_1WF$NZ+^mzLh#MZA!n}(@WFm_OBQ) zl0rRf;OK$H0~Ze5mKl^eEOTb&@+^B+|EwulbF&s^Ezf#4t1jz!c4YRFL1PDfJm}-W zcMfhF+?ErX(=TU2&e0)n3|TgG`LN4|#|*#dqT&%VMw&;i8@X=O*imCgKd1j6Gi=Px zF<*`yGIr$H1>>$5cgwi^i~C(X?BYpqIuZ%VdUu)F5*g<=1}ifTYmtMsxCKjc8#ZAI zrQvq0#vOdGrQClH>v2EjU>4=z4a&zd%HQ*7|J#&_)qH03`Je;@0xNZE$hP4v(s z+snw!qd9#In#;GIF^@;JY+oa5dB2C{>WS?dp%vMf<6*PFvvnOnZ^^Uh?hHe(pP@ z{etIT=GregUWjhLg3bPw?-Om2@6Xy&(p|=TZ~Bg7pFCJ7kM<7vtYIIV-}}~RHN3l? zv^M~oNbdty-LIw3=#Lz`;mTGmnv}2cwL<-7sNW3ro1uO))Nh9R%~1ac6x3@=$np2S z{ZevCdpS@Eq*JrF;cUG&%J(qoG{UJmIJ6TE?Sw-+;m}Svv=a{P)V}X))9wTA2Oa<( z^sOfC7C(0y;Z7smX@nb%aHA1!G{TKWxX}nF_W3!n4^HgU7Wy`5uK>Ry-9_AAOjHG)@J%+>{hZ9fuK0x0-f}?+eqaUMhgV49* z)GQu!ZU8zbT&{)7o8j_Sxco=ByjlC1?|t;H3U1fJ?ak=jcDVg1+&-?o>e~dj8{qc) z+H1aJ+Us0jOj%ljUM>a4Wn6y~oR`DrO6=?k-!q_c|Ocffx&@Bf}O*MVyd>8%HJ zz5E!x+=*V+p_gC7Q9HSg;%qdSjDdU0Ij;n)+My#_8>x%wJcU&CVC!73atXF0!> zfIL^n6$fwc=V~2S>(q0*c>6Q1?BdEU>WeYp%lo`Bh9{QuTM3}m(9#q6kMT`Jes~$c zOrQ|B6PN{*0(Sv(f%(8az`elzzyrWT$m3z)5#Wcwqkt}>Pms@6wP(5a z6W}@Er@#W>Mc`%Nm%uB)Yoz%)zf1UC%CBHwuc$h}(GjRR096ODPssM+12@kVgX=+(4PHMoU}K(pI?81Q(j%LK9qQLL>L1k^AAm zemJln4(#_^z(a82kZu97cCP@sChmtLt(5(0wC~So-=D#70bE#s#x-hd;ZhBGt_L;% z?*i`u8-ZHx{}Jd7CC9M~!ox4&+Htsc9IhRQYscZ*akzGzvid2UJFd#jfER&jOxIs4q4WLQ5_i7fl(b8)qznR80|+3+tI>yw6Gm5Y)1>* z(ZY6Q&<@|*;d?vU*N*nJqkZjQ-wO7vVBZ4vEnwdQ@7v*hI~252`dgu*4!*ZT$$luQ zgOYYA`4mb%g_2L8k3!jMC|eC>tD$T)l&yxc)ljw?%2q>F6I3-pRTES-K~)n}H9=JqGB}84?MJir zL*afX+z*9KP}l^8qGfxaa1RvjfxW(`m*_HGXpuZH3# zs9g=UhtalOXxlDIiGxz&fa>{BJs+)WqQr>hd64>TAymHtEasSb7hH{jBYV`*7c{q792Ad!S?4=-f5bjG{%exi$|CyBnAf+ymST zd=Gfgw+u~bKvNpflm;}V0ZpNe2s{Qn4*#B@K6ny%3V0fLmg_$Oo&%l-gBO6G0t{LW zZpJ5d`|hQ@Y@@6&AK#Y)m38x&?F}TnI7h2##3tVV{3oUS=1unF}g)iVjJzS`V3-xfJ9xk-Ng%-Hb za+dP46FIja=N71M@t2V*C~txCV`%11sBeM#51{@7wDexI^j@gnNu6THhPZuyqXiHO zWzA653}www)(mCMP}U4(Qdc!YSu>Q0H`EMe%}~}1WzA653}yQizZdhng!AR3TM4Wn z?NvYm{A(qpH_(!kXh}O-(oRb4q|{DI?Py86;?EO2_ayKX@HFr|`u+m&Q(yt`BCya; z>#ulc5$8hZGBof_z)k71Be7%Tww)(;!j+v^2Rj;WN8Wpp_g>_^7kTeR-g}YvUZNs) zwAx9!Zr@Vmz6lMl!spzC{I{azq65qEEq@CgKSkRY!L7A$Yc1Sb3%A6VTno3vmn810 ztj1b6wib@9h2H(pyB~V@L+^g*-4DI{;oe%fw-%jPgib6%Cl;X-i_nQh=)@v)Vi7vA z7@c?(p1cZAUWF&G;zN3MAJVrD-B^ciEP_u9;nPC+v=BZmgii~xrB6{xUd9%@jE)ew z02caQf+H{CLvE&|?1z5~k=$DJgiL;TYd5aB&Y@`~WU~1{Z7K zVhvmrkGuvhibq}p7oUWS_2^vOTT0++%)58R{vK#w9wUFz#>%FP(xD!3=D#E;-!J>08>d$n+{7Vg!;y;`_e3-=bn zy#sKs7Vg!;z1jfoNn54~?lt+jR}1%Q&%?bsxVIbb?S^~1;ofd^a6Fvbf&T44|AcdO zaIOyhlXi0*`d5ek)xx>`aBe@G+YjgV!#Umm(z#X#*J|O~PPq0tT>Ap9?S*T5;hNrt zUI8Cg0q?-k)$m|A+##MyNsWL5J+T1UyeaM7BDfW)KQ1JpG@T?5oLKwSfro!$=qkdpNw z`fvz+Xn-p5ERRFcdMH{CMY@Ob4qnmO?9f$y*?)lSS3==dC_Jtx6fg8j-|wOHcgTJV zvad$=(w418_SML~8rfI-OHDO$uSV|GaN{7{I0!eY;YKywsD>K{DK*u|y&A5pfh%j^ z$_BWyfl{*pu55rSYv9UyxUv$itb{8o;mS%%%?V1)3AnQc?yP}38{p1*xU(Matbsdg z;LaMjvl_XtM(%5n`x@lF8SZSx?wo)_2jS3qWWO0Mtw#3MaOy)iwFXYD36T8<$o>Ol zUyJNF!?k)!Og$y0o)S|}iK(Z=)Ds`K%iJb(;u^F|O2$LfK@S6u06zpC1%3oP20V^z z&h#~!p{5yXnxUpUkE$MO>Y=6{YU-h82h@n4A>LFo*f)c{-@gEtN27L?}^etr2uaH6SLI&}q z4Ehu@=vm01MK+Mg(df(Wg4`l90?1bn6p(aqPa|ApPS=pEw`Kl|YT}E2R7t zQvM1le}$C4LdsuJ7q*hFom$b2WW%xIW6+tUlz`=2s{~eXeH9Qy?hb5fFma(^6^q1+ zA>JZaPxpwHbG;Jq@Wg(e2m`Y=w7QKak5g8UQ&x{tR>f)^rd%GTTpp%e9;RF##wOFA zg7#N{MVv2%(&eO63D8@GuN)4&3&H#qU^(ZNKrJ{+yD3iPTFp^>K(1}%+D5Kz z;OhzadIG+lP?46`c%vsz>XD~Dq_L7(LA+Tw4Nu149X!PO!@wiJ4}nL49|02eF#OAB zIsOUo9Pm?M0q`R5GVn{lz+9pmOVNVmuLfY`puN-z zR_}w=*;@claqnp$(ChEo{?|SIg-GrdK)ig3_$?=|N}v;~Hn3^~t2VG|1FJT$YEzu6 zfj{BAQNtTG$kC2HbBo;J+!)^r$h8q0dct2Peu-?qgj-*N*O%Se#+PUZiXB{rKEDYp zC%sBw1!=AV-r>Gz^Cl&ig{1rnungbkO<+0KD}h9w*hyKp@KikIuwCKtI5a*1JPAAn zJPqg(`Xfl|2+}%&w2n~Qv|*pykXjp3YXhGn{_*RO@Db4lxQto{?!I8Opk0Z#*glIy-EISi(U!Spbg ziWH^ICbfv@m$cLNf%QJH{s63{z4k}A_(!llps-#G*4x3l9gIbv-UZ{sV0<(H&Sg!@^ z?O?qftQ&}TOB7kGibz$k)-g6}>m%^^Bp9CrMl)=OAd9X63_oPlrSEKmhu0qJs7Fj zI0u^L#?rM?@{V8^+Ag5|7QB&0e+?TA zhMy~2oQ*ZpdyBuOt=N5>>fCjp^ctVuat@4H8usG=_W1zz`2e<~fjY2(Ieb+VSe7$z(mdD>i#ZlyO6nS*jD7|M-d=rT!OB?-6&AQOu zJ%j3$|5a2=o5>?yH(rn&E$6oqkSk&-ZATRZpDiByp;GYVvye1`gsywPGVq zVjt?!$Ai@D^??Kn%pM2rOZOk@Sn73o9vorKH@6*)cFXb{b~Kx?pzp ze)Ml5gJXD4M-_Ft9CQkok+&|3u9RM=Oit%W%YQg>nvS&pujh#P-g_7W7+7|sRV?L2 zTEy4TqPiA6JXg8tT4v5)njfMBKMXtq{1A8)_!00J@HnlrC&=$fpfetSkXGM8T73tx zX$P@s2eD}fv1uo;X(u{b)C+k>Mhh60LRx!DzHmyO)M+?9x6UVZ-0)wKWH@7|jd640(WdKH_^kvO zJxbI}p6Pg-^GZPO3_b16Q0@$sJ9wHB+3$FV^GZOXS!YK0B?kA;kMbXestb?u*9JuS z^?rwc9agpQqLwJ1-fMKOzK2c!My&J*{)J$*<===EJEqXOIUiPi(5nMyVD(SYDWVn9 z)1gQ9rH@7*72JUl{cY<3S(o!&;5}d?AZ4qDG7!xhdLNCH3Mu2!0i{AO+j2*G2?Ouw zy@N))`nS}e|2N00e@o5wTWsAIs&_*o?EkYE>vrcWEV9uj(_NIk6Kkn+W10CR?RjbQ zo*w=C<{onk?cWyKzb$99f6pEFk-n&ZP9#x0XQ5x(*?R0pZ;5sn|5*Xe((cynv)=pa zP;G{Dm7&w?mv7b!d*Svu2f0X(V%G?{j1Cl!SVjn*FV^;twe0oLhk6_>z_+KKdlN8X znw>5A?nfsYBjf{nQNO~rNHosy8FU*Q=r_yQvH$qZ7veV)o1|wloW3R*L)5k1q>m>$ zpO*Z)#v64;WSjgE*?@6J&`=3^fq;`~KB> zVh5*>8!%?^ZJ~7DhfjJR9>m93xR06X7zb|~nCF;Bn_>?=4}0i&*hA059(o@3(DSf| zo`;W^`+YV3>nO(Q<-^|sU?xxq+zHGAiWtXNO7GBJz+7NHa1U@Va6j+>@Sqwqr;jpw zjge)GIbXuNOVxOzI&!Zg_d0T~BlkLTuOs)rGUjL}^SfPA6ERX*#xq5790gB2_#)A? zB4Zi7DKqMNU=@4f=Vqe;qli0S$-QfQkHgF5%$nQFjJaPx!IMz%BosUe1y4f3lTh#^ z6l7sJw?aibRLG3EzRZ|&K+RV~a=V+A*$8DVP}ah%IS)Sjr^J4KL+ocSv7dTkKU<0Y z{E67lGUWF&Qt%duLZJgMwvHV9c(36>PhoT`BFae`F5mzXwa{`(J@?y8>&q zg1N|Nn|E-&IR`SoL*^PRLzXg9Kw_A0ZGY`Mh#&%E5zskl6Mfz;%f6UGbJu)j*Z}Z66cFwj# z-S!SE_~?JE;6Kp{nwTjhYeJZ#ZeWzGtovZ6h7Qsk)Qn!DN9oKh8qKkZwL0XvLQ|<} zzp2f9wMDaJT1H#0u-szFw^Uf(u)JkiZ`m0X8gyCE^+9(BJ!rkmI?ej1^#$wCt;?++ zcYbYG*q*Vq+FFAz;=4R}b?~;}di&LU7sxlHN612l%~9ky<+M99oi{k|asJ%7-nrZ5 za7}ULyPj}WyLP);-5&Q~_bu+Z?iKDMq1mCup}z^O3q2a<2 zNR4gYd2Z;5V&<~V3(`FYA#H0=vn z#U+ICs|j39;_ISr?J1U+Zy0N7jNv(1o5#cY3Rm*RHGE^#+AFd65_jR*lrv&El{FT= z$0{$f%0f1)EWE<%Ex%%X?sZtW6|Bp!id7c=i&aj3&l)8)L=L8@by#MowH69ki6E02 zCL72Bh65uQ12Ud^YXUG4xP-d)D(t{K?%fT{2Rd7t-PKOU{L{`+u`j6}SQ)X{s=ZIW z&k7%`<1iYi!lS76?Jx!L>tVOCIxUq}RwlJp4t4nu{H&owV}^mlMT}}3Pu>Pzlc>!u zBldR{I9`tiO=Sef4ftC(a{XrF9xrh{1K)zZfLJpi5ih|@jh{k3sf=MsCq|OVxRo3@ zK9rn?@jD#ME`qBgh$@W3+ZoR@6Y#kvGD~_A_b$P6ycEynGRC7#p@zST5oTB8fm}xn z^m=^Lsib`a&)tX@c@vi8X6pT0pyWHuS(w2+nalM9bo>>rzrk-6va1GGGQa+PUk$5X zq@oGw#CvkUbSPL1-vt69+k~3sbty#&F^{0`>0XXylGuJ+VOTPn$pOfzaBy<2yd;%BN!G*1G z;4OT;b@*|=Qz;%G#RH^x0Nu{PXS@vSX(NUAN#O`jy-z*~dn zI9$94Ze7OOLpM<$%j|2JSskbmpR2<$N-pW>!X9+sU36eKI{ zNVnQ|gnLI+1WRPzsMgZBjP;p{IIf~>RQopZ#3pQvgDauT?N5RGsYo)D-yBNSP|_X- zr!JyLVl>ZO46fsW3D|&%NO=;^T}AKabzHk1J)Fw*8+iUkD83oH@Ez{I#QiGP3#bOx zk;nVKCURZCdRd{+I1Vn1C&vk-CMjNm=846aieD z@uc!=w8sMOUxWK0WikqWTCrdb^fZ)GaN#taKvNGw*CBtYIz|~drcH)RSCiIt!1cgX;6|?N zSR6xJj|K7oO+BXg5P!}x{7vZXO6xJ?cFa%bF-o1m;qENO-=E7NayjJB<&f3~POgEI ztEu}wrSAI_EvY7Fc9cOo(y^wQaBeW18b>)EPc1%yYZI~VlX&J5YJ^MS+GQM1p?qJ( z{i|smT}OJ?Vc{6L#rle3V=86pF~>C7!Lq>!=1+5Xp4!V(d(WBHR-W3*Q(MK3 zla7&AXKqRhmF%S^?R=suPTNRl8&7ScZFnXwA9D9Y?n+;=1G_yMIQ=QHz*WR{s(ruV zN!7a!A40M8!jJKkQ{65$!)Z8z)w~gY-3+|Mc@^BP2G;SsUIT2#DjE1rqy$&N_i7&- zfblDooFLs3NK7SfZNATT}SNrf9}ZdP@u z?pIYI%WB_ot{#VH4q!Ae8M-b9s_-eQwRE&1U0n_4YH+6x;K5XD8QjefS~}jP2Zgf^ z+2Pq%YeRWzC{H-3heoR!&%mmY{2R$13(4KjC9_B!xcx)(wel(gJI)CTgyx|M8lu zC-}bD!KLmvG!FgNYwiXt`R8ckXIPnCXrx$l(Ma(|#OfSCBkTQs=wIMgBi!2I=a#fA z+R@NJM?(zjD{ilq+4zDoVosV9fXlJ^e!!#n0MFy&{Th$)&-i$s<1wzmV_ZX|U>iAZf{r@yt^?=KN%;#>eqG^w z3-#Cx?#s$~g5&WEO!4>yrPxyo!5?vuvX{P<6zcF)a7g$401a&#86tvO+{b8b~GTK)*i4BpHJ4d zk(Exjz#COpQR241pLf+$Cwb}%o;t}>`mA7oq>HCm#~Cd(M?E94Vb5i;4%V{HW_{rX zU$gHIz8YVxkJbZcpYXrd_pxt_uhrM&JL+5D+Xb-liaKwg?)%0cayU*-faC`>`HoFGYls=XJ`iK1M;NizyZK2hoVP!A)gRJ?W z9pJ`S_}_@^ccEcwJJ_xXVSVN43&7uaPblE|MyNRqJqLaJ;fg3|TJA5BO`62jkqrS57UzZKqD<4Xj|8qVn;BlRArEi&UE%2Fdvu`K--|72+GIoIT z-M(Vq^FT3iUP*TcHX`67dKYkdmP7J53ARdlosVEc_{e`ap^gP_a<3>o+9>F*G zNSO?L98T5C72@4|)RC0(y}l~ny}qZQw3+@W^i6*UTixwPI0^1wgW0i8E1|6(1m+dY)B3h;C@U->DL~*0&TtLc^vm<^Lkz>%P~BUueF!d25014Rqpo zCnw;s(mct5w7=%N19^Wz`Q6I-C-j8Z;+?p43#7PNL&^Pbp8kwlLNscR?|tGz*gj=b z>o{uav}Nc)XZqYz&tX%!UI!+1j9vK@kH>>oCii%jTz63)OM1KbzXM!8LwcWczQgxd z$tmyy{+;&ubF^b0-_3CCLo~4g?RL<@k|=>*J9Ip2q|wOGR}QMxAHSjrXge7yQ>ho%Qee z(lXxY`s=SXP8nAfCuB_||3^`$FehJ~g7emo9q$ScRNaanV@AuGp+{uBnXl-IXirBi zVZ8Otes!veH1Sck4Y~T>#sBetbez@QZ=92^sR~2(a|QcD*q-|+MfdUlpk`Ipql`P$ z?kWf4*UvBRi2mC2yJ!B_vG!lLpnL6r)XDohb-44b4o-EKUQx&0&KLffN8`?&7?!ya z+~rIB3#c}pH|)J}-u3sJV@;o|hJEC}{t-R$A6>9s8gGzNtCUZv4-Gw`O`%~Y`0q~@ zPtLFR_>yw%o8SyT{PnG22b5)hRsQQAB5E^3Bt@Tb&B4KB60 zSiO2$$M~TD{y9CAeDK@UFGn4I(7C14k&(RZ=dN!P<#&^$u75hY(RpOtJKwL=#E40Rh~*b-IF&zJVu?$e^vs1f+Df9Os4yFbb{wsc6gnYy5n zI%FT9d>~0!*||UJS+I7LqDQycN;B~4&z`+%8+E2%uhL&j{koR8f&Zi06x3Fv+^A}; zqi|8R$&__Hclv_wVd1c9C!L@Lun&)A3E)qWI~_Hwt}E2+9T;&}l^+9_(|=FHzfs}8 z0oiUK0_y)L{FOG5uIOwtzZZ(Xc!LTX{ zvv1mqL?dO)|_y%JeWq+wV8S}V`xaK>Id@R@2@tvdgmzt|~mbx4NevWE2rxSM! zVTOQ2sB##2=Telo!61}xfAA0ESXLO-6m5gR+{xf?z83mp`Vg7y%hw9^ zsc=Dd;nU!P^xpR8D?4WmAUD~QPj=9fU8rS`Yo{9RsllT`6p*y-=P9Lq>o2fO_}z_I8-B)Trz{t&wcdf0#PF{pc- zZw$NnJ2;MlINh}d2}V2{rG;ym6!M?voGH-!FeItlgf^TuX0`XmkVMavPHZr zyUe-SukUqeT+BC;)qt14^QC;#(6u+<;jh`hP($b5M8d3KigZ~u0ST|*n@NnkO7+uM zbA{e=uDr!pQ`$Lzc|lSyzr#06?Sz)CtznLkru4PHR>RJO8e024dbE*moVLkiVaq(( z8!a6U-K8`*LTRw*l8jXA)Zj#=!I4UX69Y6j6{>rZu9t6u(qm2Ou?ea5<+|vuIY4)l zpv%zLIHj+e($_epubR?VuhLhG($_4duR%&*tx8{$mA=}PzV=o6ni-(4@d5hUOX+Kj z($`R>ufa-R!<4?-mA>{?`r2RV>j0&%8A@OK2k2{>(${dMulPMr8L#1 zG<6`F`WSo{9Sv1F8m4rV{k-_5DIEQy?Lu5{F< zbhNM1(G;bl0|Rt4Qt4=v(ov7n(Vj|2qv**|BazV2o&h?V7@(ukN=N$y=x8K5S_2=} zGZWp;OmstEW3`PPni|1<6W~C$t2MKij~1$Sh)kfI@nQE!6ZX?M4pGmWIk#d%{kx#% z<`z|GV`mf<7HE@a7M53NQ#j1ku9rP8wOeG%OYL^q=~A1){~_9){2!{7@_(3;idm&8 zcu;=$ub)efCUTMgHuXPP{kNFB)-BrSoC{5|U#0AcXrpw# z53g(4sUL?H0~VXlUpC(dxeJ zlIbFMGn&7F|5tET$3U=uP`!0YmunBHYm)-5d3ZnYtqtml;Ero%a Date: Tue, 5 Mar 2013 16:50:37 +0200 Subject: [PATCH 110/113] fixed omniauth email spec --- spec/observers/user_observer_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/observers/user_observer_spec.rb b/spec/observers/user_observer_spec.rb index dd7d88fafc..b58c5647ca 100644 --- a/spec/observers/user_observer_spec.rb +++ b/spec/observers/user_observer_spec.rb @@ -16,7 +16,7 @@ describe UserObserver do end it 'no email for external' do - Notify.should_receive(:new_user_email) + Notify.should_not_receive(:new_user_email) create(:user, extern_uid: '32442eEfsafada') end From 9ba21dd0c4255692594f5d4e9a6efb7b9646c465 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 5 Mar 2013 17:06:22 +0200 Subject: [PATCH 111/113] better solution for #3027 --- app/models/repository.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/repository.rb b/app/models/repository.rb index a5ca5533e0..3feb318034 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -137,7 +137,7 @@ class Repository file_path = File.join(storage_path, self.path_with_namespace, file_name) # Put files into a directory before archiving - prefix = self.path_with_namespace + "/" + prefix = File.basename(self.path_with_namespace) + "/" # Create file if not exists unless File.exists?(file_path) From a99ad3d355f22907b38fad0a5b276e176c3901a7 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 5 Mar 2013 17:15:20 +0200 Subject: [PATCH 112/113] tree_heleper: concat html only if present. Avoid nil exception --- app/helpers/tree_helper.rb | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb index 0f2b695e0a..fab0085ba7 100644 --- a/app/helpers/tree_helper.rb +++ b/app/helpers/tree_helper.rb @@ -13,13 +13,15 @@ module TreeHelper tree += render partial: 'tree/tree_item', collection: folders, locals: {type: 'folder'} if folders.present? files.each do |f| - if f.respond_to?(:url) - # Object is a Submodule - tree += render partial: 'tree/submodule_item', object: f - else - # Object is a Blob - tree += render partial: 'tree/tree_item', object: f, locals: {type: 'file'} - end + html = if f.respond_to?(:url) + # Object is a Submodule + render partial: 'tree/submodule_item', object: f + else + # Object is a Blob + render partial: 'tree/tree_item', object: f, locals: {type: 'file'} + end + + tree += html if html.present? end tree.html_safe From 6beae84ea37e03e68affd2b69fba25f45a4e5386 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 5 Mar 2013 17:28:13 +0200 Subject: [PATCH 113/113] reduce letter-spacing for top nav --- app/assets/stylesheets/gitlab_bootstrap/mixins.scss | 1 + app/assets/stylesheets/sections/header.scss | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/gitlab_bootstrap/mixins.scss b/app/assets/stylesheets/gitlab_bootstrap/mixins.scss index e1fd2c2ab8..1e5fff68bf 100644 --- a/app/assets/stylesheets/gitlab_bootstrap/mixins.scss +++ b/app/assets/stylesheets/gitlab_bootstrap/mixins.scss @@ -73,6 +73,7 @@ font-size: 18px; line-height: 42px; font-weight: normal; + letter-spacing: -1px; } @mixin md-typography { diff --git a/app/assets/stylesheets/sections/header.scss b/app/assets/stylesheets/sections/header.scss index 99c8275b5c..645604731c 100644 --- a/app/assets/stylesheets/sections/header.scss +++ b/app/assets/stylesheets/sections/header.scss @@ -67,7 +67,7 @@ header { position: relative; float: left; margin: 0; - margin-left: 15px; + margin-left: 10px; @include header-font; }