From 125c07fa0aa31e6c83c8fcc90df623c2ef85832f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 19 Aug 2013 22:10:21 +0300 Subject: [PATCH 001/175] Add iid field to issues and MR --- .../20130819182730_add_internal_ids_to_issues_and_mr.rb | 6 ++++++ db/schema.rb | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20130819182730_add_internal_ids_to_issues_and_mr.rb diff --git a/db/migrate/20130819182730_add_internal_ids_to_issues_and_mr.rb b/db/migrate/20130819182730_add_internal_ids_to_issues_and_mr.rb new file mode 100644 index 00000000000..e55ae38f144 --- /dev/null +++ b/db/migrate/20130819182730_add_internal_ids_to_issues_and_mr.rb @@ -0,0 +1,6 @@ +class AddInternalIdsToIssuesAndMr < ActiveRecord::Migration + def change + add_column :issues, :iid, :integer + add_column :merge_requests, :iid, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index e0e7d47b92e..c2ba5b65fc3 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 => 20130812143708) do +ActiveRecord::Schema.define(:version => 20130819182730) do create_table "deploy_keys_projects", :force => true do |t| t.integer "deploy_key_id", :null => false @@ -62,6 +62,7 @@ ActiveRecord::Schema.define(:version => 20130812143708) do t.text "description" t.integer "milestone_id" t.string "state" + t.integer "iid" end add_index "issues", ["assignee_id"], :name => "index_issues_on_assignee_id" @@ -98,6 +99,7 @@ ActiveRecord::Schema.define(:version => 20130812143708) do t.string "state" t.string "merge_status" t.integer "target_project_id", :null => false + t.integer "iid" end add_index "merge_requests", ["assignee_id"], :name => "index_merge_requests_on_assignee_id" -- GitLab From 7047a44a26f0f75ab23c58c47d096060c01256ed Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 19 Aug 2013 22:10:56 +0300 Subject: [PATCH 002/175] Sett iid on create. Use iid as value to_param --- app/models/concerns/issuable.rb | 12 ++++++++++++ app/models/merge_request.rb | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index 91fb323825d..158c226480f 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -16,6 +16,7 @@ module Issuable validates :author, presence: true validates :title, presence: true, length: { within: 0..255 } + validates :iid, presence: true, numericality: true scope :authored, ->(user) { where(author_id: user) } scope :assigned_to, ->(u) { where(assignee_id: u.id)} @@ -24,6 +25,8 @@ module Issuable scope :unassigned, -> { where("assignee_id IS NULL") } scope :of_projects, ->(ids) { where(project_id: ids) } + validate :set_iid, on: :create + delegate :name, :email, to: :author, @@ -44,6 +47,15 @@ module Issuable end end + def set_iid + max_iid = project.send(self.class.name.tableize).maximum(:iid) + self.iid = max_iid.to_i + 1 + end + + def to_param + iid.to_s + end + def today? Date.today == created_at.to_date end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index b7df2e40a16..d525ad17537 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -250,6 +250,10 @@ class MergeRequest < ActiveRecord::Base (source_project.root_ref? source_branch) || for_fork? end + def project + target_project + end + private def dump_commits(commits) -- GitLab From 2e5481b74663deddeda66ccd74eb7e38649cccb7 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 19 Aug 2013 22:11:18 +0300 Subject: [PATCH 003/175] Create task to create iid for existing issues/mr --- lib/tasks/migrate/migrate_iids.rake | 31 +++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 lib/tasks/migrate/migrate_iids.rake diff --git a/lib/tasks/migrate/migrate_iids.rake b/lib/tasks/migrate/migrate_iids.rake new file mode 100644 index 00000000000..4d2d49dd6d8 --- /dev/null +++ b/lib/tasks/migrate/migrate_iids.rake @@ -0,0 +1,31 @@ +desc "GITLAB | Build internal ids for issues and merge requests" +task migrate_iids: :environment do + puts 'Issues'.yellow + Issue.where(iid: nil).find_each(batch_size: 100) do |issue| + begin + issue.set_iid + if issue.save + print '.' + else + print 'F' + end + rescue + print 'F' + end + end + + puts 'done' + puts 'Merge Requests'.yellow + MergeRequest.where(iid: nil).find_each(batch_size: 100) do |mr| + begin + mr.set_iid + if mr.save + print '.' + else + print 'F' + end + rescue => ex + print 'F' + end + end +end -- GitLab From c1583c6d74e7a7088cf6d22957851261de965f23 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 19 Aug 2013 22:12:04 +0300 Subject: [PATCH 004/175] Find issues and Mr by iid in controller --- app/controllers/projects/issues_controller.rb | 2 +- app/controllers/projects/merge_requests_controller.rb | 2 +- app/controllers/projects_controller.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index a7f515ac851..4b6e22e3607 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -91,7 +91,7 @@ class Projects::IssuesController < Projects::ApplicationController protected def issue - @issue ||= @project.issues.find(params[:id]) + @issue ||= @project.issues.find_by_iid!(params[:id]) end def authorize_modify_issue! diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index d135cf05b9e..235247f3e52 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -132,7 +132,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController end def merge_request - @merge_request ||= @project.merge_requests.find(params[:id]) + @merge_request ||= @project.merge_requests.find_by_iid!(params[:id]) end def authorize_modify_merge_request! diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 9e88d0b4757..9b4fe5a9b5b 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -104,7 +104,7 @@ class ProjectsController < Projects::ApplicationController def autocomplete_sources @suggestions = { emojis: Emoji.names, - issues: @project.issues.select([:id, :title, :description]), + issues: @project.issues.select([:iid, :title, :description]), members: @project.team.members.sort_by(&:username).map { |user| { username: user.username, name: user.name } } } -- GitLab From 608f3286539fbcdb4727cb77623261fa506381ff Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 19 Aug 2013 22:12:40 +0300 Subject: [PATCH 005/175] Show iid as default id for issues, mr --- app/views/projects/issues/_issue.html.haml | 2 +- app/views/projects/issues/show.html.haml | 2 +- app/views/projects/merge_requests/_merge_request.html.haml | 2 +- app/views/projects/merge_requests/show/_mr_title.html.haml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/views/projects/issues/_issue.html.haml b/app/views/projects/issues/_issue.html.haml index 0f3c4f752eb..b9a2c18efdc 100644 --- a/app/views/projects/issues/_issue.html.haml +++ b/app/views/projects/issues/_issue.html.haml @@ -4,7 +4,7 @@ = check_box_tag dom_id(issue,"selected"), nil, false, 'data-id' => issue.id, class: "selected_issue", disabled: !can?(current_user, :modify_issue, issue) .issue-title - %span.light= "##{issue.id}" + %span.light= "##{issue.iid}" = link_to_gfm truncate(issue.title, length: 100), project_issue_path(issue.project, issue), class: "row_title" .issue-info diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index fc6faa9c19d..d36a831432d 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -1,5 +1,5 @@ %h3.page-title - Issue ##{@issue.id} + Issue ##{@issue.iid} %small created at diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml index 276436a9c8e..933d78bcbfb 100644 --- a/app/views/projects/merge_requests/_merge_request.html.haml +++ b/app/views/projects/merge_requests/_merge_request.html.haml @@ -1,6 +1,6 @@ %li{ class: mr_css_classes(merge_request) } .merge-request-title - %span.light= "##{merge_request.id}" + %span.light= "##{merge_request.iid}" = link_to_gfm truncate(merge_request.title, length: 80), project_merge_request_path(merge_request.target_project, merge_request), class: "row_title" - if merge_request.merged? %small.pull-right diff --git a/app/views/projects/merge_requests/show/_mr_title.html.haml b/app/views/projects/merge_requests/show/_mr_title.html.haml index 7dfc995121f..096a9167645 100644 --- a/app/views/projects/merge_requests/show/_mr_title.html.haml +++ b/app/views/projects/merge_requests/show/_mr_title.html.haml @@ -1,5 +1,5 @@ %h3.page-title - = "Merge Request ##{@merge_request.id}:" + = "Merge Request ##{@merge_request.iid}:"   -if @merge_request.for_fork? %span.label-branch -- GitLab From 20397091f10f4c00db7cfab7b8598b9a6b7fdec1 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 19 Aug 2013 22:12:59 +0300 Subject: [PATCH 006/175] Show iid in event feed and uatocomplete as default id for issues, mr --- app/assets/javascripts/gfm_auto_complete.js.coffee | 2 +- app/models/event.rb | 4 ++++ app/views/events/event/_common.html.haml | 2 +- config/routes.rb | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/gfm_auto_complete.js.coffee b/app/assets/javascripts/gfm_auto_complete.js.coffee index e22761e57a4..77091da8f61 100644 --- a/app/assets/javascripts/gfm_auto_complete.js.coffee +++ b/app/assets/javascripts/gfm_auto_complete.js.coffee @@ -44,7 +44,7 @@ GitLab.GfmAutoComplete = tpl: @Issues.template callbacks: before_save: (issues) -> - $.map issues, (i) -> id: i.id, title: sanitize(i.title), search: "#{i.id} #{i.title}" + $.map issues, (i) -> id: i.iid, title: sanitize(i.title), search: "#{i.iid} #{i.title}" input.one "focus", => $.getJSON(@dataSource).done (data) -> diff --git a/app/models/event.rb b/app/models/event.rb index 759e84bb55a..5839a834e78 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -256,6 +256,10 @@ class Event < ActiveRecord::Base target.commit_id end + def target_iid + target.respond_to?(:iid) ? target.iid : target_id + end + def note_short_commit_id note_commit_id[0..8] end diff --git a/app/views/events/event/_common.html.haml b/app/views/events/event/_common.html.haml index 6989f862f47..a9d3adf41df 100644 --- a/app/views/events/event/_common.html.haml +++ b/app/views/events/event/_common.html.haml @@ -2,7 +2,7 @@ %span.author_name= link_to_author event %span.event_label{class: event.action_name}= event_action_name(event) - if event.target - %strong= link_to "##{event.target_id}", [event.project, event.target] + %strong= link_to "##{event.target_iid}", [event.project, event.target] - else %strong= gfm event.target_title at diff --git a/config/routes.rb b/config/routes.rb index ff84bc15270..5cf47f9ac5e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -281,7 +281,7 @@ Gitlab::Application.routes.draw do end end - resources :issues, except: [:destroy] do + resources :issues, constraints: {id: /\d+/}, except: [:destroy] do collection do post :bulk_update end -- GitLab From 434c034159f584348b56a322dbcda8dc65b812f2 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 19 Aug 2013 22:53:11 +0300 Subject: [PATCH 007/175] Iid improvemets * call set_iid before validation * make rake task pass event if objects are invalid * show iid in comment event at dashboard --- app/helpers/events_helper.rb | 2 +- app/models/concerns/issuable.rb | 2 +- app/models/event.rb | 8 ++++++++ app/views/search/_result.html.haml | 4 ++-- lib/tasks/migrate/migrate_iids.rake | 6 ++++-- 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb index b93b1502b34..a35fd1ea808 100644 --- a/app/helpers/events_helper.rb +++ b/app/helpers/events_helper.rb @@ -109,7 +109,7 @@ module EventsHelper else link_to event_note_target_path(event) do content_tag :strong do - "#{event.note_target_type} ##{truncate event.note_target_id}" + "#{event.note_target_type} ##{truncate event.note_target_iid}" end end end diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index 158c226480f..fb08a5aa750 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -16,6 +16,7 @@ module Issuable validates :author, presence: true validates :title, presence: true, length: { within: 0..255 } + validate :set_iid, on: :create validates :iid, presence: true, numericality: true scope :authored, ->(user) { where(author_id: user) } @@ -25,7 +26,6 @@ module Issuable scope :unassigned, -> { where("assignee_id IS NULL") } scope :of_projects, ->(ids) { where(project_id: ids) } - validate :set_iid, on: :create delegate :name, :email, diff --git a/app/models/event.rb b/app/models/event.rb index 5839a834e78..702891f13dc 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -284,6 +284,14 @@ class Event < ActiveRecord::Base end end + def note_target_iid + if note_target.respond_to?(:iid) + note_target.iid + else + note_target_id + end.to_s + end + def wall_note? target.noteable_type.blank? end diff --git a/app/views/search/_result.html.haml b/app/views/search/_result.html.haml index fac5fdfd0b1..5f7540d1b16 100644 --- a/app/views/search/_result.html.haml +++ b/app/views/search/_result.html.haml @@ -23,7 +23,7 @@ %li merge request: = link_to [merge_request.target_project, merge_request] do - %span ##{merge_request.id} + %span ##{merge_request.iid} %strong.term = truncate merge_request.title, length: 50 - if merge_request.for_fork? @@ -37,7 +37,7 @@ %li issue: = link_to [issue.project, issue] do - %span ##{issue.id} + %span ##{issue.iid} %strong.term = truncate issue.title, length: 50 %span.light (#{issue.project.name_with_namespace}) diff --git a/lib/tasks/migrate/migrate_iids.rake b/lib/tasks/migrate/migrate_iids.rake index 4d2d49dd6d8..aef2b319df9 100644 --- a/lib/tasks/migrate/migrate_iids.rake +++ b/lib/tasks/migrate/migrate_iids.rake @@ -4,7 +4,7 @@ task migrate_iids: :environment do Issue.where(iid: nil).find_each(batch_size: 100) do |issue| begin issue.set_iid - if issue.save + if issue.update_attribute(:iid, mr.iid) print '.' else print 'F' @@ -19,7 +19,7 @@ task migrate_iids: :environment do MergeRequest.where(iid: nil).find_each(batch_size: 100) do |mr| begin mr.set_iid - if mr.save + if mr.update_attribute(:iid, mr.iid) print '.' else print 'F' @@ -28,4 +28,6 @@ task migrate_iids: :environment do print 'F' end end + + puts 'done' end -- GitLab From fd0afcc996d687232c1181263b17793b2827d44e Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Tue, 20 Aug 2013 12:05:23 +0900 Subject: [PATCH 008/175] Remove the dependancy of grit from class Network::Graph --- app/helpers/graph_helper.rb | 4 +-- app/models/network/commit.rb | 6 ++--- app/models/network/graph.rb | 34 +++++------------------- app/views/projects/network/show.json.erb | 2 +- 4 files changed, 11 insertions(+), 35 deletions(-) diff --git a/app/helpers/graph_helper.rb b/app/helpers/graph_helper.rb index 71a07d6cad1..7cb1b6f8d1a 100644 --- a/app/helpers/graph_helper.rb +++ b/app/helpers/graph_helper.rb @@ -1,7 +1,7 @@ module GraphHelper - def get_refs(commit) + def get_refs(repo, commit) refs = "" - refs += commit.refs.collect{|r|r.name}.join(" ") if commit.refs + refs += commit.ref_names(repo).join(" ") # append note count refs += "[#{@graph.notes[commit.id]}]" if @graph.notes[commit.id] > 0 diff --git a/app/models/network/commit.rb b/app/models/network/commit.rb index 3cd0c015fa0..e31adcebbe7 100644 --- a/app/models/network/commit.rb +++ b/app/models/network/commit.rb @@ -4,15 +4,13 @@ module Network class Commit include ActionView::Helpers::TagHelper - attr_reader :refs attr_accessor :time, :spaces, :parent_spaces - def initialize(raw_commit, refs) - @commit = Gitlab::Git::Commit.new(raw_commit) + def initialize(raw_commit) + @commit = raw_commit @time = -1 @spaces = [] @parent_spaces = [] - @refs = refs || [] end def method_missing(m, *args, &block) diff --git a/app/models/network/graph.rb b/app/models/network/graph.rb index 1d21e96369a..424819f3501 100644 --- a/app/models/network/graph.rb +++ b/app/models/network/graph.rb @@ -1,8 +1,6 @@ -require "grit" - module Network class Graph - attr_reader :days, :commits, :map, :notes + attr_reader :days, :commits, :map, :notes, :repo def self.max_count @max_count ||= 650 @@ -13,7 +11,7 @@ module Network @ref = ref @commit = commit @filter_ref = filter_ref - @repo = project.repo + @repo = project.repository @commits = collect_commits @days = index_commits @@ -33,11 +31,9 @@ module Network # Get commits from repository # def collect_commits - refs_cache = build_refs_cache - find_commits(count_to_display_commit_in_center).map do |commit| # Decorate with app/model/network/commit.rb - Network::Commit.new(commit, refs_cache[commit.id]) + Network::Commit.new(commit) end end @@ -103,14 +99,13 @@ module Network def find_commits(skip = 0) opts = { - date_order: true, max_count: self.class.max_count, skip: skip } - ref = @ref if @filter_ref + opts[:ref] = @commit.id if @filter_ref - Grit::Commit.find_all(@repo, ref, opts) + @repo.find_commits(opts) end def commits_sort_by_ref @@ -126,15 +121,7 @@ module Network 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) + commit.ref_names(@repo).include?(@ref) end def find_free_parent_spaces(commit) @@ -282,14 +269,5 @@ module Network leaves.push(commit) end end - - def build_refs_cache - refs_cache = {} - @repo.refs.each do |ref| - refs_cache[ref.commit.id] = [] unless refs_cache.include?(ref.commit.id) - refs_cache[ref.commit.id] << ref - end - refs_cache - end end end diff --git a/app/views/projects/network/show.json.erb b/app/views/projects/network/show.json.erb index 9a62cdb3dc9..f0bedcf2d35 100644 --- a/app/views/projects/network/show.json.erb +++ b/app/views/projects/network/show.json.erb @@ -13,7 +13,7 @@ }, time: c.time, space: c.spaces.first, - refs: get_refs(c), + refs: get_refs(@graph.repo, c), id: c.sha, date: c.date, message: c.message, -- GitLab From 90af8aa6fe3bcbb5c5e7a477b1e42f05f0a7102b Mon Sep 17 00:00:00 2001 From: MegaDiablo Date: Tue, 20 Aug 2013 14:35:49 +0300 Subject: [PATCH 009/175] add link on realisation api for java client --- doc/api/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/api/README.md b/doc/api/README.md index 8e4eb296b40..7668df07af1 100644 --- a/doc/api/README.md +++ b/doc/api/README.md @@ -88,3 +88,4 @@ When listing resources you can pass the following parameters: + [php-gitlab-api](https://github.com/m4tthumphrey/php-gitlab-api) - PHP + [Ruby Wrapper](https://github.com/NARKOZ/gitlab) - Ruby + [python-gitlab](https://github.com/Itxaka/python-gitlab) - Python ++ [java-gitlab-api](https://github.com/timols/java-gitlab-api) - Java -- GitLab From a442ad2b141e078fcc2899ece6068b82b5338bb8 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 20 Aug 2013 15:59:26 +0300 Subject: [PATCH 010/175] Added Gitlab::Access module --- lib/gitlab/access.rb | 48 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 lib/gitlab/access.rb diff --git a/lib/gitlab/access.rb b/lib/gitlab/access.rb new file mode 100644 index 00000000000..fa273f3f50a --- /dev/null +++ b/lib/gitlab/access.rb @@ -0,0 +1,48 @@ +# Gitlab::Access module +# +# Define allowed roles that can be used +# in GitLab code to determine authorization level +# +module Gitlab + module Access + GUEST = 10 + REPORTER = 20 + DEVELOPER = 30 + MASTER = 40 + OWNER = 50 + + class << self + def values + options.values + end + + def options + { + "Guest" => GUEST, + "Reporter" => REPORTER, + "Developer" => DEVELOPER, + "Master" => MASTER, + } + end + + def options_with_owner + options.merge( + "Owner" => OWNER + ) + end + + def sym_options + { + guest: GUEST, + reporter: REPORTER, + developer: DEVELOPER, + master: MASTER, + } + end + end + + def human_access + Gitlab::Access.options_with_owner.key(access_field) + end + end +end -- GitLab From 7a26a4b69ddf42c60aa406d10589a976ced0f6f3 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 20 Aug 2013 15:59:45 +0300 Subject: [PATCH 011/175] Refactor access roles methods --- app/models/project.rb | 9 ------ app/models/users_group.rb | 19 +++---------- app/models/users_project.rb | 28 ++++--------------- app/services/system_hooks_service.rb | 2 +- app/views/admin/projects/show.html.haml | 5 ++-- .../project_access_granted_email.html.haml | 2 +- .../project_access_granted_email.text.erb | 2 +- .../projects/team_members/_form.html.haml | 2 +- spec/mailers/notify_spec.rb | 2 +- 9 files changed, 18 insertions(+), 53 deletions(-) diff --git a/app/models/project.rb b/app/models/project.rb index de77bf1c666..d8e3bb6cad2 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -133,10 +133,6 @@ class Project < ActiveRecord::Base where(path: id, namespace_id: nil).last end end - - def access_options - UsersProject.access_roles - end end def team @@ -399,11 +395,6 @@ class Project < ActiveRecord::Base http_url = [Gitlab.config.gitlab.url, "/", path_with_namespace, ".git"].join('') end - def project_access_human(member) - project_user_relation = self.users_projects.find_by_user_id(member.id) - self.class.access_options.key(project_user_relation.project_access) - end - # Check if current branch name is marked as protected in the system def protected_branch? branch_name protected_branches_names.include?(branch_name) diff --git a/app/models/users_group.rb b/app/models/users_group.rb index b334066b8c8..3686551830d 100644 --- a/app/models/users_group.rb +++ b/app/models/users_group.rb @@ -12,21 +12,10 @@ class UsersGroup < ActiveRecord::Base include Notifiable - - GUEST = 10 - REPORTER = 20 - DEVELOPER = 30 - MASTER = 40 - OWNER = 50 + include Gitlab::Access def self.group_access_roles - { - "Guest" => GUEST, - "Reporter" => REPORTER, - "Developer" => DEVELOPER, - "Master" => MASTER, - "Owner" => OWNER - } + Gitlab::Access.options_with_owner end attr_accessible :group_access, :user_id @@ -50,7 +39,7 @@ class UsersGroup < ActiveRecord::Base delegate :name, :username, :email, to: :user, prefix: true - def human_access - UsersGroup.group_access_roles.key(self.group_access) + def access_field + group_access end end diff --git a/app/models/users_project.rb b/app/models/users_project.rb index 45e9305cafb..76f5685e047 100644 --- a/app/models/users_project.rb +++ b/app/models/users_project.rb @@ -14,11 +14,7 @@ class UsersProject < ActiveRecord::Base include Gitlab::ShellAdapter include Notifiable - - GUEST = 10 - REPORTER = 20 - DEVELOPER = 30 - MASTER = 40 + include Gitlab::Access attr_accessible :user, :user_id, :project_access @@ -27,7 +23,7 @@ class UsersProject < ActiveRecord::Base validates :user, presence: true validates :user_id, uniqueness: { scope: [:project_id], message: "already exists in project" } - validates :project_access, inclusion: { in: [GUEST, REPORTER, DEVELOPER, MASTER] }, presence: true + validates :project_access, inclusion: { in: Gitlab::Access.values }, presence: true validates :project, presence: true delegate :name, :username, :email, to: :user, prefix: true @@ -103,27 +99,15 @@ class UsersProject < ActiveRecord::Base end def roles_hash - { - guest: GUEST, - reporter: REPORTER, - developer: DEVELOPER, - master: MASTER - } + Gitlab::Access.sym_options end def access_roles - { - "Guest" => GUEST, - "Reporter" => REPORTER, - "Developer" => DEVELOPER, - "Master" => MASTER - } + Gitlab::Access.options end end - def project_access_human - Project.access_options.key(self.project_access) + def access_field + project_access end - - alias_method :human_access, :project_access_human end diff --git a/app/services/system_hooks_service.rb b/app/services/system_hooks_service.rb index 01ddf99e97b..c872b27ba39 100644 --- a/app/services/system_hooks_service.rb +++ b/app/services/system_hooks_service.rb @@ -43,7 +43,7 @@ class SystemHooksService project_id: model.project_id, user_name: model.user.name, user_email: model.user.email, - project_access: model.project_access_human + project_access: model.human_access }) end end diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml index 70f0c193c01..800f91d2a86 100644 --- a/app/views/admin/projects/show.html.haml +++ b/app/views/admin/projects/show.html.haml @@ -96,11 +96,12 @@ %i.icon-edit Manage Access %ul.well-list.team_members - - @project.users.each do |user| + - @project.users_projects.each do |users_project| + - user = users_project.user %li %strong = link_to user.name, admin_user_path(user) .pull-right - %span.light= @project.project_access_human(user) + %span.light= users_project.human_access = link_to admin_project_member_path(@project, user), confirm: remove_from_project_team_message(@project, user), method: :delete, class: "btn btn-small btn-remove" do %i.icon-remove diff --git a/app/views/notify/project_access_granted_email.html.haml b/app/views/notify/project_access_granted_email.html.haml index b4b44eafe2c..ce34f825358 100644 --- a/app/views/notify/project_access_granted_email.html.haml +++ b/app/views/notify/project_access_granted_email.html.haml @@ -1,5 +1,5 @@ %p - = "You have been granted #{@users_project.project_access_human} access to project" + = "You have been granted #{@users_project.human_access} access to project" %p = link_to project_url(@project) do = @project.name_with_namespace diff --git a/app/views/notify/project_access_granted_email.text.erb b/app/views/notify/project_access_granted_email.text.erb index 077c3b8a7de..66c57def375 100644 --- a/app/views/notify/project_access_granted_email.text.erb +++ b/app/views/notify/project_access_granted_email.text.erb @@ -1,4 +1,4 @@ -You have been granted <%= @users_project.project_access_human %> access to project <%= @project.name_with_namespace %> +You have been granted <%= @users_project.human_access %> access to project <%= @project.name_with_namespace %> <%= url_for(project_url(@project)) %> diff --git a/app/views/projects/team_members/_form.html.haml b/app/views/projects/team_members/_form.html.haml index 8dd2faa219b..f96fa217fa3 100644 --- a/app/views/projects/team_members/_form.html.haml +++ b/app/views/projects/team_members/_form.html.haml @@ -17,7 +17,7 @@ %h6 2. Set access level for them .control-group = f.label :project_access, "Project Access" - .controls= select_tag :project_access, options_for_select(Project.access_options, @user_project_relation.project_access), class: "project-access-select chosen" + .controls= select_tag :project_access, options_for_select(Gitlab::Access.options, @user_project_relation.project_access), class: "project-access-select chosen" .form-actions = f.submit 'Add users', class: "btn btn-create" diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index d89029276d8..a91bc9d75ad 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -250,7 +250,7 @@ describe Notify do should have_body_text /#{project.name}/ end it 'contains new user role' do - should have_body_text /#{users_project.project_access_human}/ + should have_body_text /#{users_project.human_access}/ end end -- GitLab From a73e068c06532480137b8b9861ed88f42578bb12 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 20 Aug 2013 16:56:05 +0300 Subject: [PATCH 012/175] Fixing tests after adding iid for issues/mr --- app/helpers/issues_helper.rb | 10 ++--- .../merge_requests_controller_spec.rb | 27 ++++--------- spec/helpers/gitlab_markdown_helper_spec.rb | 38 +++++++++---------- spec/helpers/issues_helper_spec.rb | 6 +-- spec/models/concerns/issuable_spec.rb | 2 + 5 files changed, 37 insertions(+), 46 deletions(-) diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index 4f433f3c60d..5977c9cbae2 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -37,23 +37,23 @@ module IssuesHelper end end - def url_for_issue(issue_id) + def url_for_issue(issue_iid) return "" if @project.nil? if @project.used_default_issues_tracker? - url = project_issue_url project_id: @project, id: issue_id + url = project_issue_url project_id: @project, id: issue_iid else url = Gitlab.config.issues_tracker[@project.issues_tracker]["issues_url"] - url.gsub(':id', issue_id.to_s) + url.gsub(':id', issue_iid.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) + def title_for_issue(issue_iid) return "" if @project.nil? - if @project.used_default_issues_tracker? && issue = @project.issues.where(id: issue_id).first + if @project.used_default_issues_tracker? && issue = @project.issues.where(iid: issue_iid).first issue.title else "" diff --git a/spec/controllers/merge_requests_controller_spec.rb b/spec/controllers/merge_requests_controller_spec.rb index d344e3eb14c..3c1a9cb7268 100644 --- a/spec/controllers/merge_requests_controller_spec.rb +++ b/spec/controllers/merge_requests_controller_spec.rb @@ -8,13 +8,13 @@ describe Projects::MergeRequestsController do before do sign_in(user) project.team << [user, :master] - Projects::MergeRequestsController.any_instance.stub(validates_merge_request: true) + Projects::MergeRequestsController.any_instance.stub(validates_merge_request: true, ) end describe "#show" do shared_examples "export merge as" do |format| it "should generally work" do - get :show, project_id: project.code, id: merge_request.id, format: format + get :show, project_id: project.code, id: merge_request.iid, format: format expect(response).to be_success end @@ -22,11 +22,11 @@ describe Projects::MergeRequestsController do it "should generate it" do MergeRequest.any_instance.should_receive(:"to_#{format}") - get :show, project_id: project.code, id: merge_request.id, format: format + get :show, project_id: project.code, id: merge_request.iid, format: format end it "should render it" do - get :show, project_id: project.code, id: merge_request.id, format: format + get :show, project_id: project.code, id: merge_request.iid, format: format expect(response.body).to eq((merge_request.send(:"to_#{format}",user)).to_s) end @@ -34,7 +34,7 @@ describe Projects::MergeRequestsController do it "should not escape Html" do MergeRequest.any_instance.stub(:"to_#{format}").and_return('HTML entities &<>" ') - get :show, project_id: project.code, id: merge_request.id, format: format + get :show, project_id: project.code, id: merge_request.iid, format: format expect(response.body).to_not include('&') expect(response.body).to_not include('>') @@ -48,7 +48,7 @@ describe Projects::MergeRequestsController do let(:format) { :diff } it "should really only be a git diff" do - get :show, project_id: project.code, id: merge_request.id, format: format + get :show, project_id: project.code, id: merge_request.iid, format: format expect(response.body).to start_with("diff --git") end @@ -59,24 +59,13 @@ describe Projects::MergeRequestsController do let(:format) { :patch } it "should really be a git email patch with commit" do - get :show, project_id: project.code, id: merge_request.id, format: format + get :show, project_id: project.code, id: merge_request.iid, format: format expect(response.body[0..100]).to start_with("From #{merge_request.commits.last.id}") end - # TODO: fix or remove - #it "should contain as many patches as there are commits" do - #get :show, project_id: project.code, id: merge_request.id, format: format - - #patch_count = merge_request.commits.count - #merge_request.commits.each_with_index do |commit, patch_num| - #expect(response.body).to match(/^From #{commit.id}/) - #expect(response.body).to match(/^Subject: \[PATCH #{patch_num}\/#{patch_count}\]/) - #end - #end - it "should contain git diffs" do - get :show, project_id: project.code, id: merge_request.id, format: format + get :show, project_id: project.code, id: merge_request.iid, format: format expect(response.body).to match(/^diff --git/) end diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb index 2dcc61e9560..a4db8b4ff7e 100644 --- a/spec/helpers/gitlab_markdown_helper_spec.rb +++ b/spec/helpers/gitlab_markdown_helper_spec.rb @@ -20,7 +20,7 @@ describe GitlabMarkdownHelper do describe "#gfm" do it "should return unaltered text if project is nil" do - actual = "Testing references: ##{issue.id}" + actual = "Testing references: ##{issue.iid}" gfm(actual).should_not == actual @@ -175,14 +175,14 @@ describe GitlabMarkdownHelper do describe "referencing an issue" do let(:object) { issue } - let(:reference) { "##{issue.id}" } + let(:reference) { "##{issue.iid}" } include_examples 'referenced object' end describe "referencing a merge request" do let(:object) { merge_request } - let(:reference) { "!#{merge_request.id}" } + let(:reference) { "!#{merge_request.iid}" } include_examples 'referenced object' end @@ -230,7 +230,7 @@ describe GitlabMarkdownHelper do end describe "referencing multiple objects" do - let(:actual) { "!#{merge_request.id} -> #{commit.id} -> ##{issue.id}" } + let(:actual) { "!#{merge_request.iid} -> #{commit.id} -> ##{issue.iid}" } it "should link to the merge request" do expected = project_merge_request_path(project, merge_request) @@ -299,7 +299,7 @@ describe GitlabMarkdownHelper do let(:issues) { create_list(:issue, 2, project: project) } it "should handle references nested in links with all the text" do - actual = link_to_gfm("This should finally fix ##{issues[0].id} and ##{issues[1].id} for real", commit_path) + actual = link_to_gfm("This should finally fix ##{issues[0].iid} and ##{issues[1].iid} for real", commit_path) # Break the result into groups of links with their content, without # closing tags @@ -311,7 +311,7 @@ describe GitlabMarkdownHelper do # First issue link groups[1].should match(/href="#{project_issue_url(project, issues[0])}"/) - groups[1].should match(/##{issues[0].id}$/) + groups[1].should match(/##{issues[0].iid}$/) # Internal commit link groups[2].should match(/href="#{commit_path}"/) @@ -319,7 +319,7 @@ describe GitlabMarkdownHelper do # Second issue link groups[3].should match(/href="#{project_issue_url(project, issues[1])}"/) - groups[3].should match(/##{issues[1].id}$/) + groups[3].should match(/##{issues[1].iid}$/) # Trailing commit link groups[4].should match(/href="#{commit_path}"/) @@ -332,7 +332,7 @@ describe GitlabMarkdownHelper do end it "escapes HTML passed in as the body" do - actual = "This is a

test

- see ##{issues[0].id}" + actual = "This is a

test

- see ##{issues[0].iid}" link_to_gfm(actual, commit_path).should match('<h1>test</h1>') end end @@ -345,25 +345,25 @@ describe GitlabMarkdownHelper do end it "should handle references in headers" do - actual = "\n# Working around ##{issue.id}\n## Apply !#{merge_request.id}" + actual = "\n# Working around ##{issue.iid}\n## Apply !#{merge_request.iid}" - markdown(actual).should match(%r{Working around ##{issue.id}}) - markdown(actual).should match(%r{Apply !#{merge_request.id}}) + markdown(actual).should match(%r{Working around ##{issue.iid}}) + markdown(actual).should match(%r{Apply !#{merge_request.iid}}) end it "should handle references in lists" do project.team << [user, :master] - actual = "\n* dark: ##{issue.id}\n* light by @#{member.user.username}" + actual = "\n* dark: ##{issue.iid}\n* light by @#{member.user.username}" - markdown(actual).should match(%r{
  • dark: ##{issue.id}
  • }) + markdown(actual).should match(%r{
  • dark: ##{issue.iid}
  • }) markdown(actual).should match(%r{
  • light by @#{member.user.username}
  • }) end it "should handle references in " do - actual = "Apply _!#{merge_request.id}_ ASAP" + actual = "Apply _!#{merge_request.iid}_ ASAP" - markdown(actual).should match(%r{Apply !#{merge_request.id}}) + markdown(actual).should match(%r{Apply !#{merge_request.iid}}) end it "should leave code blocks untouched" do @@ -379,19 +379,19 @@ describe GitlabMarkdownHelper do end it "should leave ref-like autolinks untouched" do - markdown("look at http://example.tld/#!#{merge_request.id}").should == "

    look at http://example.tld/#!#{merge_request.id}

    \n" + markdown("look at http://example.tld/#!#{merge_request.iid}").should == "

    look at http://example.tld/#!#{merge_request.iid}

    \n" end it "should leave ref-like href of 'manual' links untouched" do - markdown("why not [inspect !#{merge_request.id}](http://example.tld/#!#{merge_request.id})").should == "

    why not inspect !#{merge_request.id}

    \n" + markdown("why not [inspect !#{merge_request.iid}](http://example.tld/#!#{merge_request.iid})").should == "

    why not inspect !#{merge_request.iid}

    \n" end it "should leave ref-like src of images untouched" do - markdown("screen shot: ![some image](http://example.tld/#!#{merge_request.id})").should == "

    screen shot: \"some

    \n" + markdown("screen shot: ![some image](http://example.tld/#!#{merge_request.iid})").should == "

    screen shot: \"some

    \n" end it "should generate absolute urls for refs" do - markdown("##{issue.id}").should include(project_issue_url(project, issue)) + markdown("##{issue.iid}").should include(project_issue_url(project, issue)) end it "should generate absolute urls for emoji" do diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb index a1f23073582..3595af32431 100644 --- a/spec/helpers/issues_helper_spec.rb +++ b/spec/helpers/issues_helper_spec.rb @@ -8,7 +8,7 @@ describe IssuesHelper do 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 + title_for_issue(issue.iid).should eq issue.title end it "should always return empty string if used external tracker" do @@ -61,7 +61,7 @@ describe IssuesHelper do it "should return internal path if used internal tracker" do @project = project - url_for_issue(issue.id).should match(int_expected) + url_for_issue(issue.iid).should match(int_expected) end it "should return path to external tracker" do @@ -73,7 +73,7 @@ describe IssuesHelper do it "should return empty string if project nil" do @project = nil - url_for_issue(issue.id).should eq "" + url_for_issue(issue.iid).should eq "" end end diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb index 551e1753be0..852146ebaec 100644 --- a/spec/models/concerns/issuable_spec.rb +++ b/spec/models/concerns/issuable_spec.rb @@ -11,7 +11,9 @@ describe Issue, "Issuable" do end describe "Validation" do + before { subject.stub(set_iid: false) } it { should validate_presence_of(:project) } + it { should validate_presence_of(:iid) } it { should validate_presence_of(:author) } it { should validate_presence_of(:title) } it { should ensure_length_of(:title).is_at_least(0).is_at_most(255) } -- GitLab From 9acaec7a26d7cb140e4d0215c9f3cef4e42c5087 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 20 Aug 2013 17:31:26 +0300 Subject: [PATCH 013/175] Searching for issue/mr by iid in markdown --- app/models/project.rb | 2 +- lib/gitlab/markdown.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/project.rb b/app/models/project.rb index de77bf1c666..47916610a75 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -201,7 +201,7 @@ class Project < ActiveRecord::Base def issue_exists?(issue_id) if used_default_issues_tracker? - self.issues.where(id: issue_id).first.present? + self.issues.where(iid: issue_id).first.present? else true end diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb index 95bb22cfc27..61c622a448a 100644 --- a/lib/gitlab/markdown.rb +++ b/lib/gitlab/markdown.rb @@ -181,7 +181,7 @@ module Gitlab end def reference_merge_request(identifier) - if merge_request = @project.merge_requests.where(id: identifier).first + if merge_request = @project.merge_requests.where(iid: identifier).first link_to("!#{identifier}", project_merge_request_url(@project, merge_request), html_options.merge(title: "Merge Request: #{merge_request.title}", class: "gfm gfm-merge_request #{html_options[:class]}")) end end -- GitLab From e9f1c39e7e258e58fa79a8646c3ad224119a0ae5 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 20 Aug 2013 21:41:14 +0300 Subject: [PATCH 014/175] Fix tests --- .../features/gitlab_flavored_markdown_spec.rb | 26 +++++++++---------- spec/models/project_spec.rb | 4 +-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/spec/features/gitlab_flavored_markdown_spec.rb b/spec/features/gitlab_flavored_markdown_spec.rb index 349d68399fc..2ea569a6208 100644 --- a/spec/features/gitlab_flavored_markdown_spec.rb +++ b/spec/features/gitlab_flavored_markdown_spec.rb @@ -11,7 +11,7 @@ describe "GitLab Flavored Markdown" do end before do - Commit.any_instance.stub(title: "fix ##{issue.id}\n\nask @#{fred.username} for details") + Commit.any_instance.stub(title: "fix ##{issue.iid}\n\nask @#{fred.username} for details") end let(:commit) { project.repository.commit } @@ -25,13 +25,13 @@ describe "GitLab Flavored Markdown" do it "should render title in commits#index" do visit project_commits_path(project, 'master', limit: 1) - page.should have_link("##{issue.id}") + page.should have_link("##{issue.iid}") end it "should render title in commits#show" do visit project_commit_path(project, commit) - page.should have_link("##{issue.id}") + page.should have_link("##{issue.iid}") end it "should render description in commits#show" do @@ -43,7 +43,7 @@ describe "GitLab Flavored Markdown" do it "should render title in repositories#branches" do visit project_branches_path(project) - page.should have_link("##{issue.id}") + page.should have_link("##{issue.iid}") end end @@ -57,20 +57,20 @@ describe "GitLab Flavored Markdown" do author: @user, assignee: @user, project: project, - title: "fix ##{@other_issue.id}", + title: "fix ##{@other_issue.iid}", description: "ask @#{fred.username} for details") end it "should render subject in issues#index" do visit project_issues_path(project) - page.should have_link("##{@other_issue.id}") + page.should have_link("##{@other_issue.iid}") end it "should render subject in issues#show" do visit project_issue_path(project, @issue) - page.should have_link("##{@other_issue.id}") + page.should have_link("##{@other_issue.iid}") end it "should render details in issues#show" do @@ -83,19 +83,19 @@ describe "GitLab Flavored Markdown" do describe "for merge requests" do before do - @merge_request = create(:merge_request, source_project: project, target_project: project, title: "fix ##{issue.id}") + @merge_request = create(:merge_request, source_project: project, target_project: project, title: "fix ##{issue.iid}") end it "should render title in merge_requests#index" do visit project_merge_requests_path(project) - page.should have_link("##{issue.id}") + page.should have_link("##{issue.iid}") end it "should render title in merge_requests#show" do visit project_merge_request_path(project, @merge_request) - page.should have_link("##{issue.id}") + page.should have_link("##{issue.iid}") end end @@ -104,20 +104,20 @@ describe "GitLab Flavored Markdown" do before do @milestone = create(:milestone, project: project, - title: "fix ##{issue.id}", + title: "fix ##{issue.iid}", description: "ask @#{fred.username} for details") end it "should render title in milestones#index" do visit project_milestones_path(project) - page.should have_link("##{issue.id}") + page.should have_link("##{issue.iid}") end it "should render title in milestones#show" do visit project_milestone_path(project, @milestone) - page.should have_link("##{issue.id}") + page.should have_link("##{issue.iid}") end it "should render description in milestones#show" do diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 05a54f760f1..bca2ad74249 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -201,11 +201,11 @@ describe Project do 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 + project.issue_exists?(existed_issue.iid).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 + project.issue_exists?(not_existed_issue.iid).should be_false end it "should always be true if used other tracker" do -- GitLab From 5a664b3ca4cb1114bf5607332f325f5a6f77add2 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 20 Aug 2013 22:12:42 +0300 Subject: [PATCH 015/175] Fix bug in installation doc with non-install unicorn --- doc/install/installation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index 8ec0998e5bd..cbaeeda0437 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -232,10 +232,10 @@ Make sure to edit both `gitlab.yml` and `unicorn.rb` to match your setup. sudo gem install charlock_holmes --version '0.6.9.4' # For MySQL (note, the option says "without ... postgres") - sudo -u git -H bundle install --deployment --without development test postgres unicorn aws + sudo -u git -H bundle install --deployment --without development test postgres aws # Or for PostgreSQL (note, the option says "without ... mysql") - sudo -u git -H bundle install --deployment --without development test mysql unicorn aws + sudo -u git -H bundle install --deployment --without development test mysql aws ## Initialize Database and Activate Advanced Features -- GitLab From df7d426d2f4b7194e13841213474ee983b999c9a Mon Sep 17 00:00:00 2001 From: Chris Roemmich Date: Tue, 20 Aug 2013 14:13:49 -0500 Subject: [PATCH 016/175] Update to gitlab-shell 1.7.0 during 5.4-6.0 update --- doc/update/5.4-to-6.0.md | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/doc/update/5.4-to-6.0.md b/doc/update/5.4-to-6.0.md index 94799852549..eb8ffb26845 100644 --- a/doc/update/5.4-to-6.0.md +++ b/doc/update/5.4-to-6.0.md @@ -39,14 +39,22 @@ sudo -u git -H git fetch sudo -u git -H git checkout 6-0-dev ``` -### 3. Install additional packages +### 3. Update gitlab-shell + +```bash +cd /home/git/gitlab-shell +sudo -u git -H git fetch +sudo -u git -H git checkout v1.7.0 +``` + +### 4. Install additional packages ```bash # For reStructuredText markup language support install required package: sudo apt-get install python-docutils ``` -### 4. Install libs, migrations, etc. +### 5. Install libs, migrations, etc. ```bash cd /home/git/gitlab @@ -65,14 +73,14 @@ sudo -u git -H bundle exec rake migrate_inline_notes RAILS_ENV=production ``` -### 5. Update config files +### 6. Update config files Note: We switched from Puma in GitLab 5.4 to unicorn in GitLab 6.0. * Make `/home/git/gitlab/config/gitlab.yml` the same as https://github.com/gitlabhq/gitlabhq/blob/master/config/gitlab.yml.example but with your settings. * Make `/home/git/gitlab/config/unicorn.rb` the same as https://github.com/gitlabhq/gitlabhq/blob/master/config/unicorn.rb.example but with your settings. -### 6. Update Init script +### 7. Update Init script ```bash sudo rm /etc/init.d/gitlab @@ -80,12 +88,12 @@ sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlabhq/m sudo chmod +x /etc/init.d/gitlab ``` -### 7. Start application +### 8. Start application sudo service gitlab start sudo service nginx restart -### 8. Check application status +### 9. Check application status Check if GitLab and its environment are configured correctly: -- GitLab From 6ad88561d22c4ee1138ba229aeb5a7fc91284204 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 20 Aug 2013 22:14:22 +0300 Subject: [PATCH 017/175] Fix wrong branch in install docs --- doc/install/installation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index cbaeeda0437..6523961d4d5 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -153,10 +153,10 @@ To setup the MySQL/PostgreSQL database and dependencies please see [`doc/install cd /home/git/gitlab # Checkout to stable release - sudo -u git -H git checkout 5-4-stable + sudo -u git -H git checkout 6-0-stable **Note:** -You can change `5-4-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server! +You can change `6-0-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server! ## Configure it -- GitLab From 97b58d14848807e6bb9ccb703ef641a99dfa8603 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 20 Aug 2013 22:30:45 +0300 Subject: [PATCH 018/175] 6.1.0pre --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 09b254e90c6..ce3de583065 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -6.0.0 +6.1.0.pre -- GitLab From 1f7d485d33b38acf77d26295945a9392708b5ff0 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 20 Aug 2013 22:34:14 +0300 Subject: [PATCH 019/175] Prepare doc for update from 6.0 to 6.1 --- doc/update/6.0-to-6.1.md | 91 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 doc/update/6.0-to-6.1.md diff --git a/doc/update/6.0-to-6.1.md b/doc/update/6.0-to-6.1.md new file mode 100644 index 00000000000..5fc3ccfd7b2 --- /dev/null +++ b/doc/update/6.0-to-6.1.md @@ -0,0 +1,91 @@ +# From 6.0 to 6.1 + +### 0. Backup + +It's useful to make a backup just in case things go south: +(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version) + +```bash +cd /home/git/gitlab +sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:create +``` + +### 1. Stop server + + sudo service gitlab stop + +### 2. Get latest code + +```bash +cd /home/git/gitlab +sudo -u git -H git fetch +sudo -u git -H git checkout 6-1-stable +``` + +### 3. Update gitlab-shell + +```bash +cd /home/git/gitlab-shell +sudo -u git -H git fetch +sudo -u git -H git checkout v1.7.0 +``` + +### 4. Install libs, migrations, etc. + +```bash +cd /home/git/gitlab + +# MySQL +sudo -u git -H bundle install --without development test postgres --deployment + +#PostgreSQL +sudo -u git -H bundle install --without development test mysql --deployment + + +sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production +sudo -u git -H bundle exec rake migrate_iids RAILS_ENV=production +sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production +``` + +### 5. Update config files + +* Make `/home/git/gitlab/config/gitlab.yml` same as https://github.com/gitlabhq/gitlabhq/blob/5-4-stable/config/gitlab.yml.example but with your settings. +* Make `/home/git/gitlab/config/unicorn.rb` same as https://github.com/gitlabhq/gitlabhq/blob/5-4-stable/config/unicorn.rb.example but with your settings. + +### 6. Update Init script + +```bash +sudo rm /etc/init.d/gitlab +sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlabhq/6-1-stable/lib/support/init.d/gitlab +sudo chmod +x /etc/init.d/gitlab +``` + +### 7. Start application + + sudo service gitlab start + sudo service nginx restart + +### 8. Check application status + +Check if GitLab and its environment are configured correctly: + + sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production + +To make sure you didn't miss anything run a more thorough check with: + + sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production + +If all items are green, then congratulations upgrade complete! + +## Things went south? Revert to previous version (6.0) + +### 1. Revert the code to the previous version +Follow the [`upgrade guide from 5.4 to 6.0`](5.4-to-6.0.md), except for the database migration +(The backup is already migrated to the previous version) + +### 2. Restore from the backup: + +```bash +cd /home/git/gitlab +sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:restore +``` -- GitLab From 0a44ecf3a0eb7be66b2dbbb6e8404e3242a4b016 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 20 Aug 2013 22:41:05 +0300 Subject: [PATCH 020/175] Fix migrate_iids for issues --- lib/tasks/migrate/migrate_iids.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tasks/migrate/migrate_iids.rake b/lib/tasks/migrate/migrate_iids.rake index aef2b319df9..bc612cd69a7 100644 --- a/lib/tasks/migrate/migrate_iids.rake +++ b/lib/tasks/migrate/migrate_iids.rake @@ -4,7 +4,7 @@ task migrate_iids: :environment do Issue.where(iid: nil).find_each(batch_size: 100) do |issue| begin issue.set_iid - if issue.update_attribute(:iid, mr.iid) + if issue.update_attribute(:iid, issue.iid) print '.' else print 'F' -- GitLab From f70c5fcab242c6c0ec444c6acd6a565d53ad75fe Mon Sep 17 00:00:00 2001 From: lurdan Date: Wed, 21 Aug 2013 11:25:46 +0900 Subject: [PATCH 021/175] fix checkout tag name --- doc/update/5.4-to-6.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/update/5.4-to-6.0.md b/doc/update/5.4-to-6.0.md index eb8ffb26845..23993d05535 100644 --- a/doc/update/5.4-to-6.0.md +++ b/doc/update/5.4-to-6.0.md @@ -36,7 +36,7 @@ sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:create ```bash cd /home/git/gitlab sudo -u git -H git fetch -sudo -u git -H git checkout 6-0-dev +sudo -u git -H git checkout 6-0-stable ``` ### 3. Update gitlab-shell -- GitLab From a38c6550db410a5264a8056044f562fac7ab4b92 Mon Sep 17 00:00:00 2001 From: Hassan Amouhzi Date: Wed, 21 Aug 2013 09:13:50 +0200 Subject: [PATCH 022/175] Fix bug in ace-src-noconflict with Relative url. If we doesn't use a relative url we have this:
    gon.relative_url_root=""
    Else
    gon.relative_url_root="/gitlab"
    Gitlab::Application.config.assets.prefix contains:
    /assets
    --- app/views/projects/edit_tree/show.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/edit_tree/show.html.haml b/app/views/projects/edit_tree/show.html.haml index 06396ba992b..b1fb4f8637d 100644 --- a/app/views/projects/edit_tree/show.html.haml +++ b/app/views/projects/edit_tree/show.html.haml @@ -31,7 +31,7 @@ = link_to "Cancel", project_blob_path(@project, @id), class: "btn btn-cancel", confirm: leave_edit_message :javascript - ace.config.set("modePath", "#{Gitlab::Application.config.assets.prefix}/ace-src-noconflict") + ace.config.set("modePath", gon.relative_url_root + "#{Gitlab::Application.config.assets.prefix}/ace-src-noconflict") var ace_mode = "#{@blob.language.try(:ace_mode)}"; var editor = ace.edit("editor"); if (ace_mode) { -- GitLab From 5f24bdb7d067df9204e08e126f43c071116089b0 Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Wed, 21 Aug 2013 16:55:18 +0900 Subject: [PATCH 023/175] Render not found when failing to look for a commit --- app/controllers/projects/network_controller.rb | 4 ---- features/project/network.feature | 4 ++++ features/steps/project/project_network_graph.rb | 7 +++++++ features/steps/shared/project.rb | 4 ++++ lib/extracts_path.rb | 16 ++++++++++------ 5 files changed, 25 insertions(+), 10 deletions(-) diff --git a/app/controllers/projects/network_controller.rb b/app/controllers/projects/network_controller.rb index e4a84f80787..9832495c64f 100644 --- a/app/controllers/projects/network_controller.rb +++ b/app/controllers/projects/network_controller.rb @@ -8,10 +8,6 @@ class Projects::NetworkController < Projects::ApplicationController before_filter :require_non_empty_project def show - if @options[:q] - @commit = @project.repository.commit(@options[:q]) || @commit - end - respond_to do |format| format.html diff --git a/features/project/network.feature b/features/project/network.feature index f98e19b60d3..ceae08c1074 100644 --- a/features/project/network.feature +++ b/features/project/network.feature @@ -34,3 +34,7 @@ Feature: Project Network Graph Then page should not have content not cotaining "v2.1.0" When click "Show only selected branch" checkbox Then page should have content not cotaining "v2.1.0" + + Scenario: I should fail to look for a commit + When I look for a commit by ";" + Then page status code should be 404 diff --git a/features/steps/project/project_network_graph.rb b/features/steps/project/project_network_graph.rb index c883479ffd3..b3be2a48ecc 100644 --- a/features/steps/project/project_network_graph.rb +++ b/features/steps/project/project_network_graph.rb @@ -87,4 +87,11 @@ class ProjectNetworkGraph < Spinach::FeatureSteps page.should have_content 'v2.1.0' end end + + When 'I look for a commit by ";"' do + within ".content .search" do + fill_in 'q', with: ';' + find('button').click + end + end end diff --git a/features/steps/shared/project.rb b/features/steps/shared/project.rb index 66553e1e089..c5d8b62bfe7 100644 --- a/features/steps/shared/project.rb +++ b/features/steps/shared/project.rb @@ -51,6 +51,10 @@ module SharedProject page.should have_content("Features:") end + Then 'page status code should be 404' do + page.status_code.should == 404 + end + def current_project @project ||= Project.first end diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb index d1035240cb6..f9843d503b4 100644 --- a/lib/extracts_path.rb +++ b/lib/extracts_path.rb @@ -94,19 +94,23 @@ module ExtractsPath # Automatically renders `not_found!` if a valid tree path could not be # resolved (e.g., when a user inserts an invalid path or ref). def assign_ref_vars + # assign allowed options + allowed_options = ["filter_ref", "q"] + @options = params.select {|key, value| allowed_options.include?(key) && !value.blank? } + @options = HashWithIndifferentAccess.new(@options) + @id = get_id @ref, @path = extract_ref(@id) @repo = @project.repository - @commit = @repo.commit(@ref) + if @options[:q].blank? + @commit = @repo.commit(@ref) + else + @commit = @repo.commit(@options[:q]) + end @tree = Tree.new(@repo, @commit.id, @ref, @path) @hex_path = Digest::SHA1.hexdigest(@path) @logs_path = logs_file_project_ref_path(@project, @ref, @path) - # assign allowed options - allowed_options = ["filter_ref", "q"] - @options = params.select {|key, value| allowed_options.include?(key) && !value.blank? } - @options = HashWithIndifferentAccess.new(@options) - raise InvalidPathError unless @tree.exists? rescue RuntimeError, NoMethodError, InvalidPathError not_found! -- GitLab From ed3d31d5b2a3b4384273689f92dd39b10244dd37 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 21 Aug 2013 12:04:33 +0300 Subject: [PATCH 024/175] Warn about update to 6.1 --- doc/update/6.0-to-6.1.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/update/6.0-to-6.1.md b/doc/update/6.0-to-6.1.md index 5fc3ccfd7b2..0ee92252b2c 100644 --- a/doc/update/6.0-to-6.1.md +++ b/doc/update/6.0-to-6.1.md @@ -1,5 +1,8 @@ # From 6.0 to 6.1 +# In 6.1 we removed a lot of deprecated stuff. +# So you should update to 6.0 before continue + ### 0. Backup It's useful to make a backup just in case things go south: -- GitLab From 3b0d7a30718a26b019a14a9e5c0b61f3c3fee58d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 21 Aug 2013 12:08:10 +0300 Subject: [PATCH 025/175] Drop deprecated tables --- ...20130821090530_remove_deprecated_tables.rb | 11 ++++++++ db/schema.rb | 28 +------------------ 2 files changed, 12 insertions(+), 27 deletions(-) create mode 100644 db/migrate/20130821090530_remove_deprecated_tables.rb diff --git a/db/migrate/20130821090530_remove_deprecated_tables.rb b/db/migrate/20130821090530_remove_deprecated_tables.rb new file mode 100644 index 00000000000..539c0617eeb --- /dev/null +++ b/db/migrate/20130821090530_remove_deprecated_tables.rb @@ -0,0 +1,11 @@ +class RemoveDeprecatedTables < ActiveRecord::Migration + def up + drop_table :user_teams + drop_table :user_team_project_relationships + drop_table :user_team_user_relationships + end + + def down + raise 'No rollback for this migration' + end +end diff --git a/db/schema.rb b/db/schema.rb index c2ba5b65fc3..b8e7d3dd6f2 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 => 20130819182730) do +ActiveRecord::Schema.define(:version => 20130821090530) do create_table "deploy_keys_projects", :force => true do |t| t.integer "deploy_key_id", :null => false @@ -246,32 +246,6 @@ ActiveRecord::Schema.define(:version => 20130819182730) do 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 - t.string "description", :default => "", :null => false - end - create_table "users", :force => true do |t| t.string "email", :default => "", :null => false t.string "encrypted_password", :default => "", :null => false -- GitLab From 5d8ca6e60b8cbbb08222e4e5b93ed8c4592d051a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 21 Aug 2013 12:08:32 +0300 Subject: [PATCH 026/175] Remove deprecated models --- app/models/deprecated/user_team.rb | 118 ------------------ .../user_team_project_relationship.rb | 46 ------- .../deprecated/user_team_user_relationship.rb | 34 ----- 3 files changed, 198 deletions(-) delete mode 100644 app/models/deprecated/user_team.rb delete mode 100644 app/models/deprecated/user_team_project_relationship.rb delete mode 100644 app/models/deprecated/user_team_user_relationship.rb diff --git a/app/models/deprecated/user_team.rb b/app/models/deprecated/user_team.rb deleted file mode 100644 index 822884297d4..00000000000 --- a/app/models/deprecated/user_team.rb +++ /dev/null @@ -1,118 +0,0 @@ -# Will be removed in 6.1 with tables -# -# == Schema Information -# -# Table name: user_teams -# -# id :integer not null, primary key -# name :string(255) -# path :string(255) -# owner_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# description :string(255) default(""), not null -# - -class UserTeam < ActiveRecord::Base - attr_accessible :name, :description, :owner_id, :path - - belongs_to :owner, class_name: User - - has_many :user_team_project_relationships, dependent: :destroy - has_many :user_team_user_relationships, dependent: :destroy - - has_many :projects, through: :user_team_project_relationships - has_many :members, through: :user_team_user_relationships, source: :user - - validates :owner, presence: true - validates :name, presence: true, uniqueness: true, - 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" } - - scope :with_member, ->(user){ joins(:user_team_user_relationships).where(user_team_user_relationships: {user_id: user.id}) } - scope :with_project, ->(project){ joins(:user_team_project_relationships).where(user_team_project_relationships: {project_id: project})} - scope :without_project, ->(project){ where("user_teams.id NOT IN (:ids)", ids: (a = with_project(project); a.blank? ? 0 : a))} - scope :created_by, ->(user){ where(owner_id: user) } - - class << self - def search query - where("name LIKE :query OR path LIKE :query", query: "%#{query}%") - end - - def global_id - 'GLN' - end - - def access_roles - UsersProject.access_roles - end - end - - def to_param - path - end - - def assign_to_projects(projects, access) - projects.each do |project| - assign_to_project(project, access) - end - end - - def assign_to_project(project, access) - Gitlab::UserTeamManager.assign(self, project, access) - end - - def resign_from_project(project) - Gitlab::UserTeamManager.resign(self, project) - end - - def add_members(users, access, group_admin) - # reject existing users - users.reject! { |id| member_ids.include?(id.to_i) } - - users.each do |user| - add_member(user, access, group_admin) - end - end - - def add_member(user, access, group_admin) - Gitlab::UserTeamManager.add_member_into_team(self, user, access, group_admin) - end - - def remove_member(user) - Gitlab::UserTeamManager.remove_member_from_team(self, user) - end - - def update_membership(user, options) - Gitlab::UserTeamManager.update_team_user_membership(self, user, options) - end - - def update_project_access(project, permission) - Gitlab::UserTeamManager.update_project_greates_access(self, project, permission) - end - - def max_project_access(project) - user_team_project_relationships.find_by_project_id(project).greatest_access - end - - def human_max_project_access(project) - self.class.access_roles.invert[max_project_access(project)] - end - - def default_projects_access(member) - user_team_user_relationships.find_by_user_id(member).permission - end - - def human_default_projects_access(member) - self.class.access_roles.invert[default_projects_access(member)] - end - - def admin?(member) - user_team_user_relationships.with_user(member).first.try(:group_admin?) - end -end diff --git a/app/models/deprecated/user_team_project_relationship.rb b/app/models/deprecated/user_team_project_relationship.rb deleted file mode 100644 index e93223f3e24..00000000000 --- a/app/models/deprecated/user_team_project_relationship.rb +++ /dev/null @@ -1,46 +0,0 @@ -# Will be removed in 6.1 with tables -# -# == Schema Information -# -# Table name: user_team_project_relationships -# -# id :integer not null, primary key -# project_id :integer -# user_team_id :integer -# greatest_access :integer -# created_at :datetime not null -# updated_at :datetime not null -# - -class UserTeamProjectRelationship < ActiveRecord::Base - attr_accessible :greatest_access, :project_id, :user_team_id - - belongs_to :user_team - belongs_to :project - - validates :project, presence: true - validates :user_team, presence: true - validate :check_greatest_access - - scope :with_project, ->(project){ where(project_id: project.id) } - - def team_name - user_team.name - end - - def human_max_access - UserTeam.access_roles.key(greatest_access) - end - - private - - def check_greatest_access - errors.add(:base, :incorrect_access_code) unless correct_access? - end - - def correct_access? - return false if greatest_access.blank? - return true if UsersProject.access_roles.has_value?(greatest_access) - false - end -end diff --git a/app/models/deprecated/user_team_user_relationship.rb b/app/models/deprecated/user_team_user_relationship.rb deleted file mode 100644 index ae4c789994a..00000000000 --- a/app/models/deprecated/user_team_user_relationship.rb +++ /dev/null @@ -1,34 +0,0 @@ -# Will be removed in 6.1 with tables -# -# == Schema Information -# -# Table name: user_team_user_relationships -# -# id :integer not null, primary key -# user_id :integer -# user_team_id :integer -# group_admin :boolean -# permission :integer -# created_at :datetime not null -# updated_at :datetime not null -# - -class UserTeamUserRelationship < ActiveRecord::Base - attr_accessible :group_admin, :permission, :user_id, :user_team_id - - belongs_to :user_team - belongs_to :user - - validates :user_team, presence: true - validates :user, presence: true - - scope :with_user, ->(user) { where(user_id: user.id) } - - def user_name - user.name - end - - def access_human - UsersProject.access_roles.invert[permission] - end -end -- GitLab From 625fb2f29d99ab21de2497a36512be69c80e39be Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 21 Aug 2013 12:16:26 +0300 Subject: [PATCH 027/175] Add iids to milestones. Moved iids logic to separate concern --- app/models/concerns/internal_id.rb | 17 +++++++++++++++++ app/models/concerns/issuable.rb | 11 ----------- app/models/issue.rb | 2 +- app/models/merge_request.rb | 2 +- app/models/milestone.rb | 2 ++ ...0821090531_add_internal_ids_to_milestones.rb | 5 +++++ db/schema.rb | 3 ++- lib/tasks/migrate/migrate_iids.rake | 15 +++++++++++++++ 8 files changed, 43 insertions(+), 14 deletions(-) create mode 100644 app/models/concerns/internal_id.rb create mode 100644 db/migrate/20130821090531_add_internal_ids_to_milestones.rb diff --git a/app/models/concerns/internal_id.rb b/app/models/concerns/internal_id.rb new file mode 100644 index 00000000000..821ed54fb98 --- /dev/null +++ b/app/models/concerns/internal_id.rb @@ -0,0 +1,17 @@ +module InternalId + extend ActiveSupport::Concern + + included do + validate :set_iid, on: :create + validates :iid, presence: true, numericality: true + end + + def set_iid + max_iid = project.send(self.class.name.tableize).maximum(:iid) + self.iid = max_iid.to_i + 1 + end + + def to_param + iid.to_s + end +end diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index fb08a5aa750..a05dba7f6b6 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -16,8 +16,6 @@ module Issuable validates :author, presence: true validates :title, presence: true, length: { within: 0..255 } - validate :set_iid, on: :create - validates :iid, presence: true, numericality: true scope :authored, ->(user) { where(author_id: user) } scope :assigned_to, ->(u) { where(assignee_id: u.id)} @@ -47,15 +45,6 @@ module Issuable end end - def set_iid - max_iid = project.send(self.class.name.tableize).maximum(:iid) - self.iid = max_iid.to_i + 1 - end - - def to_param - iid.to_s - end - def today? Date.today == created_at.to_date end diff --git a/app/models/issue.rb b/app/models/issue.rb index ecb881ab597..35b487dc3cf 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -17,8 +17,8 @@ # class Issue < ActiveRecord::Base - include Issuable + include InternalId belongs_to :project validates :project, presence: true diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index d525ad17537..190f6ab15f4 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -23,8 +23,8 @@ require Rails.root.join("app/models/commit") require Rails.root.join("lib/static_model") class MergeRequest < ActiveRecord::Base - include Issuable + include InternalId belongs_to :target_project, foreign_key: :target_project_id, class_name: "Project" belongs_to :source_project, foreign_key: :source_project_id, class_name: "Project" diff --git a/app/models/milestone.rb b/app/models/milestone.rb index 023b8ddf04d..cfa47f30bde 100644 --- a/app/models/milestone.rb +++ b/app/models/milestone.rb @@ -13,6 +13,8 @@ # class Milestone < ActiveRecord::Base + include InternalId + attr_accessible :title, :description, :due_date, :state_event, :author_id_of_changes attr_accessor :author_id_of_changes diff --git a/db/migrate/20130821090531_add_internal_ids_to_milestones.rb b/db/migrate/20130821090531_add_internal_ids_to_milestones.rb new file mode 100644 index 00000000000..33e5bae5805 --- /dev/null +++ b/db/migrate/20130821090531_add_internal_ids_to_milestones.rb @@ -0,0 +1,5 @@ +class AddInternalIdsToMilestones < ActiveRecord::Migration + def change + add_column :milestones, :iid, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index b8e7d3dd6f2..429551a2bf4 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 => 20130821090530) do +ActiveRecord::Schema.define(:version => 20130821090531) do create_table "deploy_keys_projects", :force => true do |t| t.integer "deploy_key_id", :null => false @@ -119,6 +119,7 @@ ActiveRecord::Schema.define(:version => 20130821090530) do t.datetime "created_at", :null => false t.datetime "updated_at", :null => false t.string "state" + t.integer "iid" end add_index "milestones", ["due_date"], :name => "index_milestones_on_due_date" diff --git a/lib/tasks/migrate/migrate_iids.rake b/lib/tasks/migrate/migrate_iids.rake index bc612cd69a7..33271e1a2bb 100644 --- a/lib/tasks/migrate/migrate_iids.rake +++ b/lib/tasks/migrate/migrate_iids.rake @@ -29,5 +29,20 @@ task migrate_iids: :environment do end end + puts 'done' + puts 'Milestones'.yellow + Milestone.where(iid: nil).find_each(batch_size: 100) do |m| + begin + m.set_iid + if m.update_attribute(:iid, m.iid) + print '.' + else + print 'F' + end + rescue + print 'F' + end + end + puts 'done' end -- GitLab From 606701ada4076b963439983a5633535108d81f0f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 21 Aug 2013 12:22:18 +0300 Subject: [PATCH 028/175] Look for milestone by iid in milestone controller --- app/controllers/projects/milestones_controller.rb | 2 +- spec/models/milestone_spec.rb | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb index f4ee7427d29..39cd579cce5 100644 --- a/app/controllers/projects/milestones_controller.rb +++ b/app/controllers/projects/milestones_controller.rb @@ -81,7 +81,7 @@ class Projects::MilestonesController < Projects::ApplicationController protected def milestone - @milestone ||= @project.milestones.find(params[:id]) + @milestone ||= @project.milestones.find_by_iid!(params[:id]) end def authorize_admin_milestone! diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb index dfda1c87379..23b8a4aeae5 100644 --- a/spec/models/milestone_spec.rb +++ b/spec/models/milestone_spec.rb @@ -25,6 +25,7 @@ describe Milestone do end describe "Validation" do + before { subject.stub(set_iid: false) } it { should validate_presence_of(:title) } it { should validate_presence_of(:project) } end -- GitLab From fd1661468f8132800dec17ad9317d419b1440f5a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 21 Aug 2013 12:31:47 +0300 Subject: [PATCH 029/175] Remove can_create_team code from user --- app/controllers/application_controller.rb | 5 ----- app/models/user.rb | 3 +-- app/views/admin/users/_form.html.haml | 4 ---- config/gitlab.yml.example | 1 - config/initializers/1_settings.rb | 1 - 5 files changed, 1 insertion(+), 13 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 9a43381f405..2ce87e47f44 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,4 +1,3 @@ -class ApplicationController < ActionController::Base before_filter :authenticate_user! before_filter :reject_blocked! before_filter :check_password_expiration @@ -95,10 +94,6 @@ class ApplicationController < ActionController::Base return access_denied! unless can?(current_user, :push_code, project) end - def authorize_create_team! - return access_denied! unless can?(current_user, :create_team, nil) - end - def access_denied! render "errors/access_denied", layout: "errors", status: 404 end diff --git a/app/models/user.rb b/app/models/user.rb index a149b3a0322..a0637b522d0 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -47,7 +47,7 @@ class User < ActiveRecord::Base :extern_uid, :provider, :password_expires_at, as: [:default, :admin] - attr_accessible :projects_limit, :can_create_team, :can_create_group, + attr_accessible :projects_limit, :can_create_group, as: :admin attr_accessor :force_random_password @@ -208,7 +208,6 @@ class User < ActiveRecord::Base tap do |u| u.projects_limit = Gitlab.config.gitlab.default_projects_limit u.can_create_group = Gitlab.config.gitlab.default_can_create_group - u.can_create_team = Gitlab.config.gitlab.default_can_create_team u.theme_id = Gitlab::Theme::MARS end end diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml index 1365404edad..3f930c45fa6 100644 --- a/app/views/admin/users/_form.html.haml +++ b/app/views/admin/users/_form.html.haml @@ -56,10 +56,6 @@ = f.label :can_create_group .controls= f.check_box :can_create_group - .control-group - = f.label :can_create_team - .controls= f.check_box :can_create_team - .control-group = f.label :admin do %strong.cred Administrator diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index 59a4d1fd41b..a3661821271 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -41,7 +41,6 @@ production: &base ## User settings default_projects_limit: 10 # default_can_create_group: false # default: true - # default_can_create_team: false # default: true # username_changing_enabled: false # default: true - User can change her username/namespace ## Users management diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index e0207c6f0fc..92d4a29b7c1 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -52,7 +52,6 @@ Settings['issues_tracker'] ||= {} Settings['gitlab'] ||= Settingslogic.new({}) Settings.gitlab['default_projects_limit'] ||= 10 Settings.gitlab['default_can_create_group'] = true if Settings.gitlab['default_can_create_group'].nil? -Settings.gitlab['default_can_create_team'] = true if Settings.gitlab['default_can_create_team'].nil? Settings.gitlab['host'] ||= 'localhost' Settings.gitlab['https'] = false if Settings.gitlab['https'].nil? Settings.gitlab['port'] ||= Settings.gitlab.https ? 443 : 80 -- GitLab From fb492386c5323c4996d05a63ba8d93db6ed07f93 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 21 Aug 2013 12:33:12 +0300 Subject: [PATCH 030/175] Fix accidentally removed class name --- app/controllers/application_controller.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 2ce87e47f44..724122d4b93 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,3 +1,4 @@ +class ApplicationController < ActionController::Base before_filter :authenticate_user! before_filter :reject_blocked! before_filter :check_password_expiration -- GitLab From 8dd37afe3489ef46e14b33c66d9b80e913540f62 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 21 Aug 2013 12:34:02 +0300 Subject: [PATCH 031/175] Reannotate --- app/models/deploy_key.rb | 16 +++++++-------- app/models/issue.rb | 5 +++-- app/models/key.rb | 16 +++++++-------- app/models/merge_request.rb | 31 +++++++++++++++-------------- app/models/milestone.rb | 1 + app/models/note.rb | 5 +++-- app/models/personal_snippet.rb | 6 +++--- app/models/project.rb | 5 +++-- app/models/project_hook.rb | 4 ++-- app/models/project_snippet.rb | 6 +++--- app/models/service_hook.rb | 4 ++-- app/models/snippet.rb | 6 +++--- app/models/system_hook.rb | 4 ++-- app/models/user.rb | 6 +++--- app/models/users_group.rb | 13 ++++++------ app/models/users_project.rb | 4 ++-- app/models/web_hook.rb | 4 ++-- spec/factories/users_groups.rb | 13 ++++++------ spec/models/deploy_key_spec.rb | 16 +++++++-------- spec/models/issue_spec.rb | 5 +++-- spec/models/key_spec.rb | 16 +++++++-------- spec/models/merge_request_spec.rb | 30 +++++++++++++++------------- spec/models/milestone_spec.rb | 1 + spec/models/note_spec.rb | 5 +++-- spec/models/project_snippet_spec.rb | 6 +++--- spec/models/project_spec.rb | 5 +++-- spec/models/service_hook_spec.rb | 4 ++-- spec/models/snippet_spec.rb | 6 +++--- spec/models/system_hook_spec.rb | 4 ++-- spec/models/user_spec.rb | 6 +++--- spec/models/users_group_spec.rb | 13 ++++++------ spec/models/users_project_spec.rb | 4 ++-- spec/models/web_hook_spec.rb | 4 ++-- 33 files changed, 144 insertions(+), 130 deletions(-) diff --git a/app/models/deploy_key.rb b/app/models/deploy_key.rb index f983198085c..47aeb93a419 100644 --- a/app/models/deploy_key.rb +++ b/app/models/deploy_key.rb @@ -2,14 +2,14 @@ # # Table name: keys # -# id :integer not null, primary key -# user_id :integer -# created_at :datetime -# updated_at :datetime -# key :text -# title :string(255) -# identifier :string(255) -# type :string(255) +# id :integer not null, primary key +# user_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# key :text +# title :string(255) +# type :string(255) +# fingerprint :string(255) # class DeployKey < Key diff --git a/app/models/issue.rb b/app/models/issue.rb index 35b487dc3cf..03c1c166137 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -7,13 +7,14 @@ # assignee_id :integer # author_id :integer # project_id :integer -# created_at :datetime -# updated_at :datetime +# created_at :datetime not null +# updated_at :datetime not null # position :integer default(0) # branch_name :string(255) # description :text # milestone_id :integer # state :string(255) +# iid :integer # class Issue < ActiveRecord::Base diff --git a/app/models/key.rb b/app/models/key.rb index 902a7c59116..79f7bbd2590 100644 --- a/app/models/key.rb +++ b/app/models/key.rb @@ -2,14 +2,14 @@ # # Table name: keys # -# id :integer not null, primary key -# user_id :integer -# created_at :datetime -# updated_at :datetime -# key :text -# title :string(255) -# identifier :string(255) -# type :string(255) +# id :integer not null, primary key +# user_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# key :text +# title :string(255) +# type :string(255) +# fingerprint :string(255) # require 'digest/md5' diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 190f6ab15f4..0bb4b231f62 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -2,21 +2,22 @@ # # Table name: merge_requests # -# id :integer not null, primary key -# target_project_id :integer not null -# target_branch :string(255) not null -# source_project_id :integer not null -# source_branch :string(255) not null -# author_id :integer -# assignee_id :integer -# title :string(255) -# created_at :datetime -# updated_at :datetime -# st_commits :text(2147483647) -# st_diffs :text(2147483647) -# milestone_id :integer -# state :string(255) -# merge_status :string(255) +# id :integer not null, primary key +# target_branch :string(255) not null +# source_branch :string(255) not null +# source_project_id :integer not null +# author_id :integer +# assignee_id :integer +# title :string(255) +# created_at :datetime not null +# updated_at :datetime not null +# st_commits :text(2147483647) +# st_diffs :text(2147483647) +# milestone_id :integer +# state :string(255) +# merge_status :string(255) +# target_project_id :integer not null +# iid :integer # require Rails.root.join("app/models/commit") diff --git a/app/models/milestone.rb b/app/models/milestone.rb index cfa47f30bde..1a73fa71e48 100644 --- a/app/models/milestone.rb +++ b/app/models/milestone.rb @@ -10,6 +10,7 @@ # created_at :datetime not null # updated_at :datetime not null # state :string(255) +# iid :integer # class Milestone < ActiveRecord::Base diff --git a/app/models/note.rb b/app/models/note.rb index c0bf79237c1..7598978ad4d 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -6,13 +6,14 @@ # note :text # noteable_type :string(255) # author_id :integer -# created_at :datetime -# updated_at :datetime +# created_at :datetime not null +# updated_at :datetime not null # project_id :integer # attachment :string(255) # line_code :string(255) # commit_id :string(255) # noteable_id :integer +# st_diff :text # require 'carrierwave/orm/activerecord' diff --git a/app/models/personal_snippet.rb b/app/models/personal_snippet.rb index a3c0d201ee5..ef2000ad05e 100644 --- a/app/models/personal_snippet.rb +++ b/app/models/personal_snippet.rb @@ -4,11 +4,11 @@ # # id :integer not null, primary key # title :string(255) -# content :text +# content :text(2147483647) # author_id :integer not null # project_id :integer -# created_at :datetime -# updated_at :datetime +# created_at :datetime not null +# updated_at :datetime not null # file_name :string(255) # expires_at :datetime # private :boolean default(TRUE), not null diff --git a/app/models/project.rb b/app/models/project.rb index a40cea2ad39..b1b7634233c 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -6,8 +6,8 @@ # name :string(255) # path :string(255) # description :text -# created_at :datetime -# updated_at :datetime +# created_at :datetime not null +# updated_at :datetime not null # creator_id :integer # default_branch :string(255) # issues_enabled :boolean default(TRUE), not null @@ -21,6 +21,7 @@ # snippets_enabled :boolean default(TRUE), not null # last_activity_at :datetime # imported :boolean default(FALSE), not null +# import_url :string(255) # require "grit" diff --git a/app/models/project_hook.rb b/app/models/project_hook.rb index b82e1ffd4ab..2576fc979d4 100644 --- a/app/models/project_hook.rb +++ b/app/models/project_hook.rb @@ -5,8 +5,8 @@ # id :integer not null, primary key # url :string(255) # project_id :integer -# created_at :datetime -# updated_at :datetime +# created_at :datetime not null +# updated_at :datetime not null # type :string(255) default("ProjectHook") # service_id :integer # diff --git a/app/models/project_snippet.rb b/app/models/project_snippet.rb index 14c88046423..f38aa07059c 100644 --- a/app/models/project_snippet.rb +++ b/app/models/project_snippet.rb @@ -4,11 +4,11 @@ # # id :integer not null, primary key # title :string(255) -# content :text +# content :text(2147483647) # author_id :integer not null # project_id :integer -# created_at :datetime -# updated_at :datetime +# created_at :datetime not null +# updated_at :datetime not null # file_name :string(255) # expires_at :datetime # private :boolean default(TRUE), not null diff --git a/app/models/service_hook.rb b/app/models/service_hook.rb index 433e8059788..4cd2b272eec 100644 --- a/app/models/service_hook.rb +++ b/app/models/service_hook.rb @@ -5,8 +5,8 @@ # id :integer not null, primary key # url :string(255) # project_id :integer -# created_at :datetime -# updated_at :datetime +# created_at :datetime not null +# updated_at :datetime not null # type :string(255) default("ProjectHook") # service_id :integer # diff --git a/app/models/snippet.rb b/app/models/snippet.rb index 3a2fc17e59c..edc179b20fd 100644 --- a/app/models/snippet.rb +++ b/app/models/snippet.rb @@ -4,11 +4,11 @@ # # id :integer not null, primary key # title :string(255) -# content :text +# content :text(2147483647) # author_id :integer not null # project_id :integer -# created_at :datetime -# updated_at :datetime +# created_at :datetime not null +# updated_at :datetime not null # file_name :string(255) # expires_at :datetime # private :boolean default(TRUE), not null diff --git a/app/models/system_hook.rb b/app/models/system_hook.rb index 2d28f4cd452..5cdf046644f 100644 --- a/app/models/system_hook.rb +++ b/app/models/system_hook.rb @@ -5,8 +5,8 @@ # id :integer not null, primary key # url :string(255) # project_id :integer -# created_at :datetime -# updated_at :datetime +# created_at :datetime not null +# updated_at :datetime not null # type :string(255) default("ProjectHook") # service_id :integer # diff --git a/app/models/user.rb b/app/models/user.rb index a0637b522d0..071f6f30f5a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -4,7 +4,7 @@ # # id :integer not null, primary key # email :string(255) default(""), not null -# encrypted_password :string(128) default(""), not null +# encrypted_password :string(255) default(""), not null # reset_password_token :string(255) # reset_password_sent_at :datetime # remember_created_at :datetime @@ -13,8 +13,8 @@ # last_sign_in_at :datetime # current_sign_in_ip :string(255) # last_sign_in_ip :string(255) -# created_at :datetime -# updated_at :datetime +# created_at :datetime not null +# updated_at :datetime not null # name :string(255) # admin :boolean default(FALSE), not null # projects_limit :integer default(10) diff --git a/app/models/users_group.rb b/app/models/users_group.rb index 3686551830d..181bf322283 100644 --- a/app/models/users_group.rb +++ b/app/models/users_group.rb @@ -2,12 +2,13 @@ # # Table name: users_groups # -# id :integer not null, primary key -# group_access :integer not null -# group_id :integer not null -# user_id :integer not null -# created_at :datetime not null -# updated_at :datetime not null +# id :integer not null, primary key +# group_access :integer not null +# group_id :integer not null +# user_id :integer not null +# created_at :datetime not null +# updated_at :datetime not null +# notification_level :integer default(3), not null # class UsersGroup < ActiveRecord::Base diff --git a/app/models/users_project.rb b/app/models/users_project.rb index 76f5685e047..c435df2b442 100644 --- a/app/models/users_project.rb +++ b/app/models/users_project.rb @@ -5,8 +5,8 @@ # id :integer not null, primary key # user_id :integer not null # project_id :integer not null -# created_at :datetime -# updated_at :datetime +# created_at :datetime not null +# updated_at :datetime not null # project_access :integer default(0), not null # notification_level :integer default(3), not null # diff --git a/app/models/web_hook.rb b/app/models/web_hook.rb index 1e6ea885ea9..3f22b1082fb 100644 --- a/app/models/web_hook.rb +++ b/app/models/web_hook.rb @@ -5,8 +5,8 @@ # id :integer not null, primary key # url :string(255) # project_id :integer -# created_at :datetime -# updated_at :datetime +# created_at :datetime not null +# updated_at :datetime not null # type :string(255) default("ProjectHook") # service_id :integer # diff --git a/spec/factories/users_groups.rb b/spec/factories/users_groups.rb index 654bb2caee8..34bc0c51468 100644 --- a/spec/factories/users_groups.rb +++ b/spec/factories/users_groups.rb @@ -2,12 +2,13 @@ # # Table name: users_groups # -# id :integer not null, primary key -# group_access :integer not null -# group_id :integer not null -# user_id :integer not null -# created_at :datetime not null -# updated_at :datetime not null +# id :integer not null, primary key +# group_access :integer not null +# group_id :integer not null +# user_id :integer not null +# created_at :datetime not null +# updated_at :datetime not null +# notification_level :integer default(3), not null # FactoryGirl.define do diff --git a/spec/models/deploy_key_spec.rb b/spec/models/deploy_key_spec.rb index ec1f5d2c4e2..b76ca660411 100644 --- a/spec/models/deploy_key_spec.rb +++ b/spec/models/deploy_key_spec.rb @@ -2,14 +2,14 @@ # # Table name: keys # -# id :integer not null, primary key -# user_id :integer -# created_at :datetime -# updated_at :datetime -# key :text -# title :string(255) -# identifier :string(255) -# type :string(255) +# id :integer not null, primary key +# user_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# key :text +# title :string(255) +# type :string(255) +# fingerprint :string(255) # require 'spec_helper' diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb index fbdf4eb52eb..c10891331b1 100644 --- a/spec/models/issue_spec.rb +++ b/spec/models/issue_spec.rb @@ -7,13 +7,14 @@ # assignee_id :integer # author_id :integer # project_id :integer -# created_at :datetime -# updated_at :datetime +# created_at :datetime not null +# updated_at :datetime not null # position :integer default(0) # branch_name :string(255) # description :text # milestone_id :integer # state :string(255) +# iid :integer # require 'spec_helper' diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb index f4dd726331a..9c872c02a53 100644 --- a/spec/models/key_spec.rb +++ b/spec/models/key_spec.rb @@ -2,14 +2,14 @@ # # Table name: keys # -# id :integer not null, primary key -# user_id :integer -# created_at :datetime -# updated_at :datetime -# key :text -# title :string(255) -# identifier :string(255) -# type :string(255) +# id :integer not null, primary key +# user_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# key :text +# title :string(255) +# type :string(255) +# fingerprint :string(255) # require 'spec_helper' diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 68f3f920e06..40931513af6 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -2,20 +2,22 @@ # # Table name: merge_requests # -# id :integer not null, primary key -# target_branch :string(255) not null -# source_branch :string(255) not null -# project_id :integer not null -# author_id :integer -# assignee_id :integer -# title :string(255) -# created_at :datetime -# updated_at :datetime -# st_commits :text(2147483647) -# st_diffs :text(2147483647) -# milestone_id :integer -# state :string(255) -# merge_status :string(255) +# id :integer not null, primary key +# target_branch :string(255) not null +# source_branch :string(255) not null +# source_project_id :integer not null +# author_id :integer +# assignee_id :integer +# title :string(255) +# created_at :datetime not null +# updated_at :datetime not null +# st_commits :text(2147483647) +# st_diffs :text(2147483647) +# milestone_id :integer +# state :string(255) +# merge_status :string(255) +# target_project_id :integer not null +# iid :integer # require 'spec_helper' diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb index 23b8a4aeae5..b41012a3b8c 100644 --- a/spec/models/milestone_spec.rb +++ b/spec/models/milestone_spec.rb @@ -10,6 +10,7 @@ # created_at :datetime not null # updated_at :datetime not null # state :string(255) +# iid :integer # require 'spec_helper' diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb index 0f3af588457..646255543a0 100644 --- a/spec/models/note_spec.rb +++ b/spec/models/note_spec.rb @@ -6,13 +6,14 @@ # note :text # noteable_type :string(255) # author_id :integer -# created_at :datetime -# updated_at :datetime +# created_at :datetime not null +# updated_at :datetime not null # project_id :integer # attachment :string(255) # line_code :string(255) # commit_id :string(255) # noteable_id :integer +# st_diff :text # require 'spec_helper' diff --git a/spec/models/project_snippet_spec.rb b/spec/models/project_snippet_spec.rb index 42147179387..d3a46ebbb84 100644 --- a/spec/models/project_snippet_spec.rb +++ b/spec/models/project_snippet_spec.rb @@ -4,11 +4,11 @@ # # id :integer not null, primary key # title :string(255) -# content :text +# content :text(2147483647) # author_id :integer not null # project_id :integer -# created_at :datetime -# updated_at :datetime +# created_at :datetime not null +# updated_at :datetime not null # file_name :string(255) # expires_at :datetime # private :boolean default(TRUE), not null diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index bca2ad74249..172adb5fc7a 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -6,8 +6,8 @@ # name :string(255) # path :string(255) # description :text -# created_at :datetime -# updated_at :datetime +# created_at :datetime not null +# updated_at :datetime not null # creator_id :integer # default_branch :string(255) # issues_enabled :boolean default(TRUE), not null @@ -21,6 +21,7 @@ # snippets_enabled :boolean default(TRUE), not null # last_activity_at :datetime # imported :boolean default(FALSE), not null +# import_url :string(255) # require 'spec_helper' diff --git a/spec/models/service_hook_spec.rb b/spec/models/service_hook_spec.rb index e5ba59c0d65..0b0262c97f1 100644 --- a/spec/models/service_hook_spec.rb +++ b/spec/models/service_hook_spec.rb @@ -5,8 +5,8 @@ # id :integer not null, primary key # url :string(255) # project_id :integer -# created_at :datetime -# updated_at :datetime +# created_at :datetime not null +# updated_at :datetime not null # type :string(255) default("ProjectHook") # service_id :integer # diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb index a77c594aaf1..5fa397207c7 100644 --- a/spec/models/snippet_spec.rb +++ b/spec/models/snippet_spec.rb @@ -4,11 +4,11 @@ # # id :integer not null, primary key # title :string(255) -# content :text +# content :text(2147483647) # author_id :integer not null # project_id :integer -# created_at :datetime -# updated_at :datetime +# created_at :datetime not null +# updated_at :datetime not null # file_name :string(255) # expires_at :datetime # private :boolean default(TRUE), not null diff --git a/spec/models/system_hook_spec.rb b/spec/models/system_hook_spec.rb index 7f11f9ec247..a9ed6a5fa7c 100644 --- a/spec/models/system_hook_spec.rb +++ b/spec/models/system_hook_spec.rb @@ -5,8 +5,8 @@ # id :integer not null, primary key # url :string(255) # project_id :integer -# created_at :datetime -# updated_at :datetime +# created_at :datetime not null +# updated_at :datetime not null # type :string(255) default("ProjectHook") # service_id :integer # diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index eb8ffa5aafe..6743f2d803f 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -4,7 +4,7 @@ # # id :integer not null, primary key # email :string(255) default(""), not null -# encrypted_password :string(128) default(""), not null +# encrypted_password :string(255) default(""), not null # reset_password_token :string(255) # reset_password_sent_at :datetime # remember_created_at :datetime @@ -13,8 +13,8 @@ # last_sign_in_at :datetime # current_sign_in_ip :string(255) # last_sign_in_ip :string(255) -# created_at :datetime -# updated_at :datetime +# created_at :datetime not null +# updated_at :datetime not null # name :string(255) # admin :boolean default(FALSE), not null # projects_limit :integer default(10) diff --git a/spec/models/users_group_spec.rb b/spec/models/users_group_spec.rb index 4da31a55fcb..9264f2bc034 100644 --- a/spec/models/users_group_spec.rb +++ b/spec/models/users_group_spec.rb @@ -2,12 +2,13 @@ # # Table name: users_groups # -# id :integer not null, primary key -# group_access :integer not null -# group_id :integer not null -# user_id :integer not null -# created_at :datetime not null -# updated_at :datetime not null +# id :integer not null, primary key +# group_access :integer not null +# group_id :integer not null +# user_id :integer not null +# created_at :datetime not null +# updated_at :datetime not null +# notification_level :integer default(3), not null # require 'spec_helper' diff --git a/spec/models/users_project_spec.rb b/spec/models/users_project_spec.rb index aa4b8cb449b..e289a592b03 100644 --- a/spec/models/users_project_spec.rb +++ b/spec/models/users_project_spec.rb @@ -5,8 +5,8 @@ # id :integer not null, primary key # user_id :integer not null # project_id :integer not null -# created_at :datetime -# updated_at :datetime +# created_at :datetime not null +# updated_at :datetime not null # project_access :integer default(0), not null # notification_level :integer default(3), not null # diff --git a/spec/models/web_hook_spec.rb b/spec/models/web_hook_spec.rb index 4f88ed849e0..2d9301732dd 100644 --- a/spec/models/web_hook_spec.rb +++ b/spec/models/web_hook_spec.rb @@ -5,8 +5,8 @@ # id :integer not null, primary key # url :string(255) # project_id :integer -# created_at :datetime -# updated_at :datetime +# created_at :datetime not null +# updated_at :datetime not null # type :string(255) default("ProjectHook") # service_id :integer # -- GitLab From fede36f08995790d0aed89fdc3eeaacd94e98dc5 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 21 Aug 2013 12:40:02 +0300 Subject: [PATCH 032/175] Add z-index to flash message --- app/assets/stylesheets/common.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss index d9669b5e79d..66cc2ffc92d 100644 --- a/app/assets/stylesheets/common.scss +++ b/app/assets/stylesheets/common.scss @@ -55,6 +55,7 @@ table a code { bottom: 0; width: 100%; opacity: 0.8; + z-index: 100; .flash-notice { background: #49C; -- GitLab From 1101ceb3f4dfb8983f5876215378331a2d9bcc88 Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Wed, 21 Aug 2013 19:20:29 +0900 Subject: [PATCH 033/175] A little improvement 1. Replace params key 'q' with 'extended_sha1'. A extended SHA1 syntax is explained in 'man gitrevisions'. 2. Change the placeholder of looking for commit. 3. Change the label of ref filter. --- app/views/projects/network/_head.html.haml | 6 +++--- features/steps/project/project_network_graph.rb | 4 ++-- lib/extracts_path.rb | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/views/projects/network/_head.html.haml b/app/views/projects/network/_head.html.haml index ed9fcaace25..2790ed6f594 100644 --- a/app/views/projects/network/_head.html.haml +++ b/app/views/projects/network/_head.html.haml @@ -4,7 +4,7 @@ .pull-left = form_tag project_network_path(@project, @id), method: :get do |f| .control-group - = label_tag :filter_ref, "Show only selected ref", class: 'control-label light' + = label_tag :filter_ref, "Begin with the selected commit", class: 'control-label light' .controls = check_box_tag :filter_ref, 1, @options[:filter_ref] - @options.each do |key, value| @@ -15,9 +15,9 @@ .control-group = label_tag :search , "Looking for commit:", class: 'control-label light' .controls - = text_field_tag :q, @options[:q], placeholder: "Input SHA", class: "search-input input-xlarge" + = text_field_tag :extended_sha1, @options[:extended_sha1], placeholder: "Input an extended SHA1 syntax", class: "search-input input-xlarge" = button_tag type: 'submit', class: 'btn vtop' do %i.icon-search - @options.each do |key, value| - = hidden_field_tag(key, value, id: nil) unless key == "q" + = hidden_field_tag(key, value, id: nil) unless key == "extended_sha1" diff --git a/features/steps/project/project_network_graph.rb b/features/steps/project/project_network_graph.rb index b3be2a48ecc..57015f76626 100644 --- a/features/steps/project/project_network_graph.rb +++ b/features/steps/project/project_network_graph.rb @@ -76,7 +76,7 @@ class ProjectNetworkGraph < Spinach::FeatureSteps When 'I looking for a commit by SHA of "v2.1.0"' do within ".content .search" do - fill_in 'q', with: '98d6492' + fill_in 'extended_sha1', with: '98d6492' find('button').click end sleep 2 @@ -90,7 +90,7 @@ class ProjectNetworkGraph < Spinach::FeatureSteps When 'I look for a commit by ";"' do within ".content .search" do - fill_in 'q', with: ';' + fill_in 'extended_sha1', with: ';' find('button').click end end diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb index f9843d503b4..53bc079296a 100644 --- a/lib/extracts_path.rb +++ b/lib/extracts_path.rb @@ -95,17 +95,17 @@ module ExtractsPath # resolved (e.g., when a user inserts an invalid path or ref). def assign_ref_vars # assign allowed options - allowed_options = ["filter_ref", "q"] + allowed_options = ["filter_ref", "extended_sha1"] @options = params.select {|key, value| allowed_options.include?(key) && !value.blank? } @options = HashWithIndifferentAccess.new(@options) @id = get_id @ref, @path = extract_ref(@id) @repo = @project.repository - if @options[:q].blank? + if @options[:extended_sha1].blank? @commit = @repo.commit(@ref) else - @commit = @repo.commit(@options[:q]) + @commit = @repo.commit(@options[:extended_sha1]) end @tree = Tree.new(@repo, @commit.id, @ref, @path) @hex_path = Digest::SHA1.hexdigest(@path) -- GitLab From 668358439e5f4c92c96fc1ae72b0cf06df8dbd90 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 21 Aug 2013 15:07:09 +0300 Subject: [PATCH 034/175] Fix tests after can_create_team was removed --- spec/features/admin/admin_users_spec.rb | 1 - spec/lib/auth_spec.rb | 1 - spec/models/user_spec.rb | 2 -- 3 files changed, 4 deletions(-) diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb index 2aaa4e97340..8d69b595aee 100644 --- a/spec/features/admin/admin_users_spec.rb +++ b/spec/features/admin/admin_users_spec.rb @@ -35,7 +35,6 @@ describe "Admin::Users" do user = User.last user.projects_limit.should == Gitlab.config.gitlab.default_projects_limit user.can_create_group.should == Gitlab.config.gitlab.default_can_create_group - user.can_create_team.should == Gitlab.config.gitlab.default_can_create_team end it "should create user with valid data" do diff --git a/spec/lib/auth_spec.rb b/spec/lib/auth_spec.rb index 903d27686d3..2784d4e2fbe 100644 --- a/spec/lib/auth_spec.rb +++ b/spec/lib/auth_spec.rb @@ -99,7 +99,6 @@ describe Gitlab::Auth do user.should be_valid user.projects_limit.should == Gitlab.config.gitlab.default_projects_limit user.can_create_group.should == Gitlab.config.gitlab.default_can_create_group - user.can_create_team.should == Gitlab.config.gitlab.default_can_create_team end end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 6743f2d803f..695f0ae6846 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -198,7 +198,6 @@ describe User do it "should not apply defaults to user" do user.projects_limit.should == 10 user.can_create_group.should == true - user.can_create_team.should == true end end @@ -207,7 +206,6 @@ describe User do it "should apply defaults to user" do user.projects_limit.should == 42 user.can_create_group.should == false - user.can_create_team.should == false end end end -- GitLab From c7713cafce69f0419af0923665b3365662377b73 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Wed, 21 Aug 2013 17:38:59 +0200 Subject: [PATCH 035/175] Increase estimated number of GitLab installations --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d4c7c2740e4..19e7cbaad68 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ * powered by Ruby on Rails * completely free and open source (MIT license) -* used by more than 10.000 organizations to keep their code secure +* used by more than 25.000 organizations to keep their code secure ### Code status -- GitLab From c69637df9a7397133198853e093fd5cfabf10ae2 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Thu, 22 Aug 2013 08:18:50 +0200 Subject: [PATCH 036/175] Add 'hooks' to path blacklist. --- lib/gitlab/blacklist.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gitlab/blacklist.rb b/lib/gitlab/blacklist.rb index d00214a62cb..26f987b200c 100644 --- a/lib/gitlab/blacklist.rb +++ b/lib/gitlab/blacklist.rb @@ -3,7 +3,7 @@ module Gitlab extend self def path - %w(admin dashboard groups help profile projects search public assets u s teams merge_requests issues users snippets services repository) + %w(admin dashboard groups help profile projects search public assets u s teams merge_requests issues users snippets services repository hooks) end end end -- GitLab From b3e07ec334b8c80c8e745722db4bf620bf2e8e9f Mon Sep 17 00:00:00 2001 From: Michael Moll Date: Thu, 22 Aug 2013 13:17:58 +0200 Subject: [PATCH 037/175] bind unicorn listener to 127.0.0.1 otherwise it will listen on 0.0.0.0 --- config/unicorn.rb.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/unicorn.rb.example b/config/unicorn.rb.example index e010de6d6a9..7f2097071cc 100644 --- a/config/unicorn.rb.example +++ b/config/unicorn.rb.example @@ -26,7 +26,7 @@ working_directory "/home/git/gitlab" # available in 0.94.0+ # listen on both a Unix domain socket and a TCP port, # we use a shorter backlog for quicker failover when busy listen "/home/git/gitlab/tmp/sockets/gitlab.socket", :backlog => 64 -listen 8080, :tcp_nopush => true +listen "127.0.0.1:8080", :tcp_nopush => true # nuke workers after 30 seconds instead of 60 seconds (the default) timeout 30 -- GitLab From d2aa48c0d5e49309b14baa5f2f792af945e74bb3 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 22 Aug 2013 14:49:57 +0300 Subject: [PATCH 038/175] Recreate project satellite on rename or transfer --- app/models/project.rb | 1 + app/services/project_transfer_service.rb | 3 +++ 2 files changed, 4 insertions(+) diff --git a/app/models/project.rb b/app/models/project.rb index b1b7634233c..b505ffb58cf 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -421,6 +421,7 @@ class Project < ActiveRecord::Base begin gitlab_shell.mv_repository("#{old_path_with_namespace}.wiki", "#{new_path_with_namespace}.wiki") gitlab_shell.rm_satellites(old_path_with_namespace) + ensure_satellite_exists send_move_instructions rescue # Returning false does not rollback after_* transaction but gives diff --git a/app/services/project_transfer_service.rb b/app/services/project_transfer_service.rb index 3b8c4847f20..8fbf92ff20a 100644 --- a/app/services/project_transfer_service.rb +++ b/app/services/project_transfer_service.rb @@ -29,6 +29,9 @@ class ProjectTransferService # Move wiki repo also if present gitlab_shell.mv_repository("#{old_path}.wiki", "#{new_path}.wiki") + # create satellite repo + project.ensure_satellite_exists + true end end -- GitLab From 0fcd89e3ac810bb137240edf86fac5b80d52faed Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 22 Aug 2013 15:40:48 +0300 Subject: [PATCH 039/175] Show iids for issues/mr in email subject --- app/mailers/emails/issues.rb | 8 ++++---- app/mailers/emails/merge_requests.rb | 8 ++++---- spec/mailers/notify_spec.rb | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/app/mailers/emails/issues.rb b/app/mailers/emails/issues.rb index c1112a98f92..6eda88c7921 100644 --- a/app/mailers/emails/issues.rb +++ b/app/mailers/emails/issues.rb @@ -3,14 +3,14 @@ module Emails def new_issue_email(recipient_id, issue_id) @issue = Issue.find(issue_id) @project = @issue.project - mail(to: recipient(recipient_id), subject: subject("new issue ##{@issue.id}", @issue.title)) + mail(to: recipient(recipient_id), subject: subject("new issue ##{@issue.iid}", @issue.title)) end def reassigned_issue_email(recipient_id, issue_id, previous_assignee_id) @issue = Issue.find(issue_id) @previous_assignee = User.find_by_id(previous_assignee_id) if previous_assignee_id @project = @issue.project - mail(to: recipient(recipient_id), subject: subject("changed issue ##{@issue.id}", @issue.title)) + mail(to: recipient(recipient_id), subject: subject("changed issue ##{@issue.iid}", @issue.title)) end def closed_issue_email(recipient_id, issue_id, updated_by_user_id) @@ -18,7 +18,7 @@ module Emails @project = @issue.project @updated_by = User.find updated_by_user_id mail(to: recipient(recipient_id), - subject: subject("Closed issue ##{@issue.id}", @issue.title)) + subject: subject("Closed issue ##{@issue.iid}", @issue.title)) end def issue_status_changed_email(recipient_id, issue_id, status, updated_by_user_id) @@ -27,7 +27,7 @@ module Emails @project = @issue.project @updated_by = User.find updated_by_user_id mail(to: recipient(recipient_id), - subject: subject("changed issue ##{@issue.id}", @issue.title)) + subject: subject("changed issue ##{@issue.iid}", @issue.title)) end end end diff --git a/app/mailers/emails/merge_requests.rb b/app/mailers/emails/merge_requests.rb index cf6950966e1..57c1925fa47 100644 --- a/app/mailers/emails/merge_requests.rb +++ b/app/mailers/emails/merge_requests.rb @@ -2,24 +2,24 @@ module Emails module MergeRequests def new_merge_request_email(recipient_id, merge_request_id) @merge_request = MergeRequest.find(merge_request_id) - mail(to: recipient(recipient_id), subject: subject("new merge request !#{@merge_request.id}", @merge_request.title)) + mail(to: recipient(recipient_id), subject: subject("new merge request !#{@merge_request.iid}", @merge_request.title)) end def reassigned_merge_request_email(recipient_id, merge_request_id, previous_assignee_id) @merge_request = MergeRequest.find(merge_request_id) @previous_assignee = User.find_by_id(previous_assignee_id) if previous_assignee_id - mail(to: recipient(recipient_id), subject: subject("changed merge request !#{@merge_request.id}", @merge_request.title)) + mail(to: recipient(recipient_id), subject: subject("changed merge request !#{@merge_request.iid}", @merge_request.title)) end def closed_merge_request_email(recipient_id, merge_request_id, updated_by_user_id) @merge_request = MergeRequest.find(merge_request_id) @updated_by = User.find updated_by_user_id - mail(to: recipient(recipient_id), subject: subject("Closed merge request !#{@merge_request.id}", @merge_request.title)) + mail(to: recipient(recipient_id), subject: subject("Closed merge request !#{@merge_request.iid}", @merge_request.title)) end def merged_merge_request_email(recipient_id, merge_request_id) @merge_request = MergeRequest.find(merge_request_id) - mail(to: recipient(recipient_id), subject: subject("Accepted merge request !#{@merge_request.id}", @merge_request.title)) + mail(to: recipient(recipient_id), subject: subject("Accepted merge request !#{@merge_request.iid}", @merge_request.title)) end end diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index a91bc9d75ad..7d6647e0983 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -110,7 +110,7 @@ describe Notify do it_behaves_like 'an assignee email' it 'has the correct subject' do - should have_subject /#{project.name} \| new issue ##{issue.id} \| #{issue.title}/ + should have_subject /#{project.name} \| new issue ##{issue.iid} \| #{issue.title}/ end it 'contains a link to the new issue' do @@ -126,7 +126,7 @@ describe Notify do it_behaves_like 'a multiple recipients email' it 'has the correct subject' do - should have_subject /changed issue ##{issue.id} \| #{issue.title}/ + should have_subject /changed issue ##{issue.iid} \| #{issue.title}/ end it 'contains the name of the previous assignee' do @@ -148,7 +148,7 @@ describe Notify do subject { Notify.issue_status_changed_email(recipient.id, issue.id, status, current_user) } it 'has the correct subject' do - should have_subject /changed issue ##{issue.id} \| #{issue.title}/i + should have_subject /changed issue ##{issue.iid} \| #{issue.title}/i end it 'contains the new status' do @@ -175,7 +175,7 @@ describe Notify do it_behaves_like 'an assignee email' it 'has the correct subject' do - should have_subject /new merge request !#{merge_request.id}/ + should have_subject /new merge request !#{merge_request.iid}/ end it 'contains a link to the new merge request' do @@ -199,7 +199,7 @@ describe Notify do it_behaves_like 'a multiple recipients email' it 'has the correct subject' do - should have_subject /changed merge request !#{merge_request.id}/ + should have_subject /changed merge request !#{merge_request.iid}/ end it 'contains the name of the previous assignee' do -- GitLab From 9a00bbda89ab22f533db725e751ad46ff68c2cbe Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 22 Aug 2013 15:45:36 +0300 Subject: [PATCH 040/175] Show reopen milestone button if milestone was closed --- app/views/projects/milestones/show.html.haml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml index 8a5c2a938b1..b755a813419 100644 --- a/app/views/projects/milestones/show.html.haml +++ b/app/views/projects/milestones/show.html.haml @@ -8,7 +8,10 @@ = link_to edit_project_milestone_path(@project, @milestone), class: "btn grouped" do %i.icon-edit Edit - = link_to 'Close Milestone', project_milestone_path(@project, @milestone, milestone: {state_event: :close }), method: :put, class: "btn btn-remove" + - if @milestone.active? + = link_to 'Close Milestone', project_milestone_path(@project, @milestone, milestone: {state_event: :close }), method: :put, class: "btn btn-remove" + - else + = link_to 'Reopen Milestone', project_milestone_path(@project, @milestone, milestone: {state_event: :activate }), method: :put, class: "btn" - if @milestone.issues.any? && @milestone.can_be_closed? .alert.alert-success -- GitLab From b30909c269816ee14f2d6403b6001690226a7cda Mon Sep 17 00:00:00 2001 From: Alex Bouma Date: Thu, 22 Aug 2013 16:00:42 +0200 Subject: [PATCH 041/175] Added assets:precompile in upgrade guide 5.4 -> 6.0 --- doc/update/5.4-to-6.0.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/update/5.4-to-6.0.md b/doc/update/5.4-to-6.0.md index 23993d05535..7fe57a8ff3f 100644 --- a/doc/update/5.4-to-6.0.md +++ b/doc/update/5.4-to-6.0.md @@ -71,6 +71,8 @@ sudo -u git -H bundle exec rake migrate_global_projects RAILS_ENV=production sudo -u git -H bundle exec rake migrate_keys RAILS_ENV=production sudo -u git -H bundle exec rake migrate_inline_notes RAILS_ENV=production +sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production + ``` ### 6. Update config files -- GitLab From b74a50451c1e80ae59ffad7e8b7316f86476c43e Mon Sep 17 00:00:00 2001 From: Austin Robertson Date: Thu, 22 Aug 2013 13:10:18 -0500 Subject: [PATCH 042/175] Fix GitLab Shell version check --- lib/tasks/gitlab/info.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tasks/gitlab/info.rake b/lib/tasks/gitlab/info.rake index 091de6ee6d5..ea83efcd887 100644 --- a/lib/tasks/gitlab/info.rake +++ b/lib/tasks/gitlab/info.rake @@ -54,7 +54,7 @@ namespace :gitlab do # check Gitolite version - gitlab_shell_version_file = "#{Gitlab.config.gitlab_shell.repos_path}/../gitlab-shell/VERSION" + gitlab_shell_version_file = "#{Gitlab.config.gitlab_shell.hooks_path}/../VERSION" if File.readable?(gitlab_shell_version_file) gitlab_shell_version = File.read(gitlab_shell_version_file) end -- GitLab From 2b9d48ccd020a4ff62741118be94ab8d8f3b08b9 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 23 Aug 2013 10:28:07 +0200 Subject: [PATCH 043/175] Fix the `service gitlab restart` command This commit addresses two related issues: - Sidekiq should shut down completely before we restart it; - If we restart unicorn with USR2 we need to kill the old master and worker processes. --- config/unicorn.rb.example | 26 +++++++++++++------------- lib/support/init.d/gitlab | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/config/unicorn.rb.example b/config/unicorn.rb.example index e010de6d6a9..294d521b66e 100644 --- a/config/unicorn.rb.example +++ b/config/unicorn.rb.example @@ -64,19 +64,19 @@ before_fork do |server, worker| # installations. It is not needed if your system can house # twice as many worker_processes as you have configured. # - # # This allows a new master process to incrementally - # # phase out the old master process with SIGTTOU to avoid a - # # thundering herd (especially in the "preload_app false" case) - # # when doing a transparent upgrade. The last worker spawned - # # will then kill off the old master process with a SIGQUIT. - # old_pid = "#{server.config[:pid]}.oldbin" - # if old_pid != server.pid - # begin - # sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU - # Process.kill(sig, File.read(old_pid).to_i) - # rescue Errno::ENOENT, Errno::ESRCH - # end - # end + # This allows a new master process to incrementally + # phase out the old master process with SIGTTOU to avoid a + # thundering herd (especially in the "preload_app false" case) + # when doing a transparent upgrade. The last worker spawned + # will then kill off the old master process with a SIGQUIT. + old_pid = "#{server.config[:pid]}.oldbin" + if old_pid != server.pid + begin + sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU + Process.kill(sig, File.read(old_pid).to_i) + rescue Errno::ENOENT, Errno::ESRCH + end + end # # Throttle the master from forking too quickly by sleeping. Due # to the implementation of standard Unix signal handlers, this diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab index 29c9d98965d..6f97643f9e0 100644 --- a/lib/support/init.d/gitlab +++ b/lib/support/init.d/gitlab @@ -81,7 +81,7 @@ restart() { if [ "$PID" -ne 0 -a "$STATUS" -ne 0 ]; then echo "Restarting $DESC..." kill -USR2 `cat $WEB_SERVER_PID` - execute "mkdir -p $PID_PATH && $STOP_SIDEKIQ > /dev/null 2>&1 &" + execute "mkdir -p $PID_PATH && $STOP_SIDEKIQ > /dev/null 2>&1" if [ `whoami` = root ]; then execute "mkdir -p $PID_PATH && $START_SIDEKIQ > /dev/null 2>&1 &" fi -- GitLab From dc3e1d63921f4209f3823981d698fe29a6ce624e Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Fri, 23 Aug 2013 15:52:49 +0200 Subject: [PATCH 044/175] People like Karen and myself are confused by the placeholder, it seems like you don't have to change the master value. Also the to and from should be more prominent. --- app/views/projects/compare/_form.html.haml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/views/projects/compare/_form.html.haml b/app/views/projects/compare/_form.html.haml index ee733f80954..c96a2ae4cb7 100644 --- a/app/views/projects/compare/_form.html.haml +++ b/app/views/projects/compare/_form.html.haml @@ -5,7 +5,8 @@ %code.label-branch 4eedf23 or branch/tag name like %code.label-branch master - and press compare button for commits list, code diff. + and press compare button for the commits list and a code diff. + Changes are shown from the version in the first field to the version in the second field. %br @@ -14,9 +15,9 @@ .pull-left - if params[:to] && params[:from] = link_to 'switch', {from: params[:to], to: params[:from]}, {class: 'commits-compare-switch has_tooltip', title: 'Switch base of comparison'} - = text_field_tag :from, params[:from], placeholder: "master", class: "input-xlarge input-xpadding" + = text_field_tag :from, params[:from], class: "input-xlarge input-xpadding" = "..." - = text_field_tag :to, params[:to], placeholder: "aa8b4ef", class: "input-xlarge input-xpadding" + = text_field_tag :to, params[:to], class: "input-xlarge input-xpadding" .pull-left   = submit_tag "Compare", class: "btn btn-create commits-compare-btn" -- GitLab From 6f70d6977aa60ed7166726b0cb19035b77ca955d Mon Sep 17 00:00:00 2001 From: Steven Mok Date: Sat, 24 Aug 2013 11:27:08 +0800 Subject: [PATCH 045/175] Select files with diff filter for graph log --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index d950f43b205..c80705af316 100644 --- a/Gemfile +++ b/Gemfile @@ -23,7 +23,7 @@ gem 'omniauth-github' # Extracting information from a git repository # Provide access to Gitlab::Git library -gem "gitlab_git", '2.1.0' +gem "gitlab_git", '2.1.1' # Ruby/Rack Git Smart-HTTP Server Handler gem 'gitlab-grack', '~> 1.0.1', require: 'grack' diff --git a/Gemfile.lock b/Gemfile.lock index abec9243bce..e345c40f445 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -186,7 +186,7 @@ GEM gitlab-pygments.rb (0.3.2) posix-spawn (~> 0.3.6) yajl-ruby (~> 1.1.0) - gitlab_git (2.1.0) + gitlab_git (2.1.1) activesupport (~> 3.2.13) github-linguist (~> 2.3.4) gitlab-grit (~> 2.6.0) @@ -576,7 +576,7 @@ DEPENDENCIES gitlab-gollum-lib (~> 1.0.1) gitlab-grack (~> 1.0.1) gitlab-pygments.rb (~> 0.3.2) - gitlab_git (= 2.1.0) + gitlab_git (= 2.1.1) gitlab_meta (= 6.0) gitlab_omniauth-ldap (= 1.0.3) gon -- GitLab From 5a3d4cb6349c430ec1be6842f9b37204e0386cd7 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 24 Aug 2013 22:42:52 +0300 Subject: [PATCH 046/175] Fixed 500 error when try to remove group --- app/controllers/groups_controller.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 1190dd40b73..60fc3f6b551 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -87,7 +87,6 @@ class GroupsController < ApplicationController end def destroy - @group.truncate_teams @group.destroy redirect_to root_path, notice: 'Group was removed.' -- GitLab From b1358639c8943a1e3a4e46e08a429a0f4a29ecf1 Mon Sep 17 00:00:00 2001 From: dsekretov Date: Fri, 23 Aug 2013 13:34:08 +0400 Subject: [PATCH 047/175] Update 20130419190306_allow_merges_for_forks.rb Postgress db migrate fails.(5.4=>6.0) --- db/migrate/20130419190306_allow_merges_for_forks.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/db/migrate/20130419190306_allow_merges_for_forks.rb b/db/migrate/20130419190306_allow_merges_for_forks.rb index 691293a1c3e..56ce58a846d 100644 --- a/db/migrate/20130419190306_allow_merges_for_forks.rb +++ b/db/migrate/20130419190306_allow_merges_for_forks.rb @@ -1,7 +1,8 @@ class AllowMergesForForks < ActiveRecord::Migration def self.up - add_column :merge_requests, :target_project_id, :integer, :null => false + add_column :merge_requests, :target_project_id, :integer, :null => true MergeRequest.update_all("target_project_id = project_id") + change_column :merge_requests, :target_project_id, :integer, :null => false rename_column :merge_requests, :project_id, :source_project_id end -- GitLab From d139cc6b3283cef8f14660738d423ea63317203c Mon Sep 17 00:00:00 2001 From: Gabor Nagy Date: Sun, 25 Aug 2013 23:21:00 +0200 Subject: [PATCH 048/175] Adds feature: get a diff via API. --- doc/api/repositories.md | 28 ++++++++++++++++++++++++++ lib/api/repositories.rb | 14 +++++++++++++ spec/requests/api/repositories_spec.rb | 22 ++++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/doc/api/repositories.md b/doc/api/repositories.md index 7a9f766ba1d..229d4409ea6 100644 --- a/doc/api/repositories.md +++ b/doc/api/repositories.md @@ -239,6 +239,34 @@ Parameters: ] ``` +## Get the diff of a commit + +Get the diff of a commit in a project. + +``` +GET /projects/:id/repository/commit/:sha +``` + +Parameters: + ++ `id` (required) - The ID of a project ++ `sha` (required) - The name of a repository branch or tag or if not given the default branch + +```json +[ + { + "diff": "--- a/doc/update/5.4-to-6.0.md\n+++ b/doc/update/5.4-to-6.0.md\n@@ -71,6 +71,8 @@\n sudo -u git -H bundle exec rake migrate_keys RAILS_ENV=production\n sudo -u git -H bundle exec rake migrate_inline_notes RAILS_ENV=production\n \n+sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production\n+\n ```\n \n ### 6. Update config files", + "new_path": "doc/update/5.4-to-6.0.md", + "old_path": "doc/update/5.4-to-6.0.md", + "a_mode": null, + "b_mode": "100644", + "new_file": false, + "renamed_file": false, + "deleted_file": false + } +] +``` + ## List repository tree Get a list of repository files and directories in a project. diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb index 5db17b7e414..7e806546d02 100644 --- a/lib/api/repositories.rb +++ b/lib/api/repositories.rb @@ -102,6 +102,20 @@ module API present commits, with: Entities::RepoCommit end + # Get a specific commit of a project + # + # Parameters: + # id (required) - The ID of a project + # sha (required) - The commit or branch name + # Example Request: + # GET /projects/:id/repository/commit/:sha + get ":id/repository/commit/:sha" do + authorize! :download_code, user_project + sha = params[:sha] + result = CommitLoadContext.new(user_project, current_user, {id: sha}).execute + result[:commit].diffs + end + # Get a project repository tree # # Parameters: diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb index afa67d1ecbe..44892876ccb 100644 --- a/spec/requests/api/repositories_spec.rb +++ b/spec/requests/api/repositories_spec.rb @@ -112,6 +112,28 @@ describe API::API do end end + describe "GET /projects:id/repository/commit/:sha" do + context "authorized user" do + before { project.team << [user2, :reporter] } + + it "should return the diff of the selected commit" do + get api("/projects/#{project.id}/repository/commit/#{project.repository.commit.id}", user) + response.status.should == 200 + + json_response.should be_an Array + json_response.length.should >= 1 + json_response.first.keys.should include "diff" + end + end + + context "unauthorized user" do + it "should not return the diff of the selected commit" do + get api("/projects/#{project.id}/repository/commit/#{project.repository.commit.id}") + response.status.should == 401 + end + end + end + describe "GET /projects/:id/repository/tree" do context "authorized user" do before { project.team << [user2, :reporter] } -- GitLab From c8a115c0e3a9c8242c2a422572d47a49e0cb2874 Mon Sep 17 00:00:00 2001 From: ash wilson Date: Thu, 30 May 2013 23:16:49 +0000 Subject: [PATCH 049/175] Link issues from comments and automatically close them Any mention of Issues, MergeRequests, or Commits via GitLab-flavored markdown references in descriptions, titles, or attached Notes creates a back-reference Note that links to the original referencer. Furthermore, pushing commits with commit messages that match a (configurable) regexp to a project's default branch will close any issues mentioned by GFM in the matched closing phrase. If accepting a merge request would close any Issues in this way, a banner is appended to the merge request's main panel to indicate this. --- CHANGELOG | 6 +- .../projects/merge_requests_controller.rb | 5 + app/models/commit.rb | 26 +++++ app/models/concerns/mentionable.rb | 78 +++++++++++-- app/models/issue.rb | 7 ++ app/models/merge_request.rb | 16 ++- app/models/note.rb | 36 +++++- app/models/repository.rb | 1 + app/observers/activity_observer.rb | 4 +- app/observers/base_observer.rb | 4 + app/observers/issue_observer.rb | 6 +- app/observers/merge_request_observer.rb | 8 +- app/observers/note_observer.rb | 12 ++ app/services/git_push_service.rb | 88 +++++++++++--- .../merge_requests/show/_mr_box.html.haml | 8 +- config/gitlab.yml.example | 5 + config/initializers/1_settings.rb | 1 + .../20130528184641_add_system_to_notes.rb | 16 +++ db/schema.rb | 1 + lib/gitlab/reference_extractor.rb | 59 ++++++++++ spec/lib/gitlab/reference_extractor_spec.rb | 95 +++++++++++++++ spec/models/commit_spec.rb | 22 +++- spec/models/issue_spec.rb | 6 + spec/models/merge_request_spec.rb | 31 ++++- spec/models/note_spec.rb | 108 +++++++++++++++++- spec/observers/activity_observer_spec.rb | 24 ++++ spec/observers/issue_observer_spec.rb | 34 +++++- spec/observers/merge_request_observer_spec.rb | 36 ++++-- spec/observers/note_observer_spec.rb | 32 +++++- spec/services/git_push_service_spec.rb | 105 ++++++++++++++++- spec/support/login_helpers.rb | 1 + spec/support/mentionable_shared_examples.rb | 94 +++++++++++++++ 32 files changed, 925 insertions(+), 50 deletions(-) create mode 100644 db/migrate/20130528184641_add_system_to_notes.rb create mode 100644 lib/gitlab/reference_extractor.rb create mode 100644 spec/lib/gitlab/reference_extractor_spec.rb create mode 100644 spec/support/mentionable_shared_examples.rb diff --git a/CHANGELOG b/CHANGELOG index 0bd68762563..7c3d7ba3502 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,7 @@ +v 6.1.0 + - Link issues, merge requests, and commits when they reference each other with GFM + - Close issues automatically when pushing commits with a special message + v 6.0.0 - Feature: Replace teams with group membership We introduce group membership in 6.0 as a replacement for teams. @@ -54,7 +58,7 @@ v 5.4.0 - Notify mentioned users with email v 5.3.0 - - Refactored services + - Refactored services - Campfire service added - HipChat service added - Fixed bug with LDAP + git over http diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 235247f3e52..55d2c3f04fc 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -3,6 +3,7 @@ require 'gitlab/satellite/satellite' class Projects::MergeRequestsController < Projects::ApplicationController before_filter :module_enabled before_filter :merge_request, only: [:edit, :update, :show, :commits, :diffs, :automerge, :automerge_check, :ci_status] + before_filter :closes_issues, only: [:edit, :update, :show, :commits, :diffs] before_filter :validates_merge_request, only: [:show, :diffs] before_filter :define_show_vars, only: [:show, :diffs] @@ -135,6 +136,10 @@ class Projects::MergeRequestsController < Projects::ApplicationController @merge_request ||= @project.merge_requests.find_by_iid!(params[:id]) end + def closes_issues + @closes_issues ||= @merge_request.closes_issues + end + def authorize_modify_merge_request! return render_404 unless can?(current_user, :modify_merge_request, @merge_request) end diff --git a/app/models/commit.rb b/app/models/commit.rb index da80c2940ff..f8ca6a5fe82 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -2,6 +2,9 @@ class Commit include ActiveModel::Conversion include StaticModel extend ActiveModel::Naming + include Mentionable + + attr_mentionable :safe_message # Safe amount of files with diffs in one commit to render # Used to prevent 500 error on huge commits by suppressing diff @@ -65,6 +68,29 @@ class Commit end end + # Regular expression that identifies commit message clauses that trigger issue closing. + def issue_closing_regex + @issue_closing_regex ||= Regexp.new(Gitlab.config.gitlab.issue_closing_pattern) + end + + # Discover issues should be closed when this commit is pushed to a project's + # default branch. + def closes_issues project + md = issue_closing_regex.match(safe_message) + if md + extractor = Gitlab::ReferenceExtractor.new + extractor.analyze(md[0]) + extractor.issues_for(project) + else + [] + end + end + + # Mentionable override. + def gfm_reference + "commit #{sha[0..5]}" + end + def method_missing(m, *args, &block) @raw.send(m, *args, &block) end diff --git a/app/models/concerns/mentionable.rb b/app/models/concerns/mentionable.rb index f22070f8504..27e39339ae8 100644 --- a/app/models/concerns/mentionable.rb +++ b/app/models/concerns/mentionable.rb @@ -1,12 +1,47 @@ # == Mentionable concern # -# Contains common functionality shared between Issues and Notes +# Contains functionality related to objects that can mention Users, Issues, MergeRequests, or Commits by +# GFM references. # -# Used by Issue, Note +# Used by Issue, Note, MergeRequest, and Commit. # module Mentionable extend ActiveSupport::Concern + module ClassMethods + # Indicate which attributes of the Mentionable to search for GFM references. + def attr_mentionable *attrs + mentionable_attrs.concat(attrs.map(&:to_s)) + end + + # Accessor for attributes marked mentionable. + def mentionable_attrs + @mentionable_attrs ||= [] + end + end + + # Generate a GFM back-reference that will construct a link back to this Mentionable when rendered. Must + # be overridden if this model object can be referenced directly by GFM notation. + def gfm_reference + raise NotImplementedError.new("#{self.class} does not implement #gfm_reference") + end + + # Construct a String that contains possible GFM references. + def mentionable_text + self.class.mentionable_attrs.map { |attr| send(attr) || '' }.join + end + + # The GFM reference to this Mentionable, which shouldn't be included in its #references. + def local_reference + self + end + + # Determine whether or not a cross-reference Note has already been created between this Mentionable and + # the specified target. + def has_mentioned? target + Note.cross_reference_exists?(target, local_reference) + end + def mentioned_users users = [] return users if mentionable_text.blank? @@ -24,14 +59,39 @@ module Mentionable users.uniq end - def mentionable_text - if self.class == Issue - description - elsif self.class == Note - note - else - nil + # Extract GFM references to other Mentionables from this Mentionable. Always excludes its #local_reference. + def references p = project, text = mentionable_text + return [] if text.blank? + ext = Gitlab::ReferenceExtractor.new + ext.analyze(text) + (ext.issues_for(p) + ext.merge_requests_for(p) + ext.commits_for(p)).uniq - [local_reference] + end + + # Create a cross-reference Note for each GFM reference to another Mentionable found in +mentionable_text+. + def create_cross_references! p = project, a = author, without = [] + refs = references(p) - without + refs.each do |ref| + Note.create_cross_reference_note(ref, local_reference, a, p) end end + # If the mentionable_text field is about to change, locate any *added* references and create cross references for + # them. Invoke from an observer's #before_save implementation. + def notice_added_references p = project, a = author + ch = changed_attributes + original, mentionable_changed = "", false + self.class.mentionable_attrs.each do |attr| + if ch[attr] + original << ch[attr] + mentionable_changed = true + end + end + + # Only proceed if the saved changes actually include a chance to an attr_mentionable field. + return unless mentionable_changed + + preexisting = references(p, original) + create_cross_references!(p, a, preexisting) + end + end diff --git a/app/models/issue.rb b/app/models/issue.rb index 03c1c166137..ffe9681fc83 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -32,6 +32,7 @@ class Issue < ActiveRecord::Base attr_accessible :title, :assignee_id, :position, :description, :milestone_id, :label_list, :author_id_of_changes, :state_event + attr_mentionable :title, :description acts_as_taggable_on :labels @@ -56,4 +57,10 @@ class Issue < ActiveRecord::Base # Both open and reopened issues should be listed as opened scope :opened, -> { with_state(:opened, :reopened) } + + # Mentionable overrides. + + def gfm_reference + "issue ##{iid}" + end end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 0bb4b231f62..514fc79f7c5 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -31,7 +31,7 @@ class MergeRequest < ActiveRecord::Base belongs_to :source_project, foreign_key: :source_project_id, class_name: "Project" attr_accessible :title, :assignee_id, :source_project_id, :source_branch, :target_project_id, :target_branch, :milestone_id, :author_id_of_changes, :state_event - + attr_mentionable :title attr_accessor :should_remove_source_branch @@ -255,6 +255,20 @@ class MergeRequest < ActiveRecord::Base target_project end + # Return the set of issues that will be closed if this merge request is accepted. + def closes_issues + if target_branch == project.default_branch + unmerged_commits.map { |c| c.closes_issues(project) }.flatten.uniq.sort_by(&:id) + else + [] + end + end + + # Mentionable override. + def gfm_reference + "merge request !#{iid}" + end + private def dump_commits(commits) diff --git a/app/models/note.rb b/app/models/note.rb index 7598978ad4d..e819a5516b5 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -24,6 +24,7 @@ class Note < ActiveRecord::Base attr_accessible :note, :noteable, :noteable_id, :noteable_type, :project_id, :attachment, :line_code, :commit_id + attr_mentionable :note belongs_to :project belongs_to :noteable, polymorphic: true @@ -54,15 +55,36 @@ class Note < ActiveRecord::Base serialize :st_diff before_create :set_diff, if: ->(n) { n.line_code.present? } - def self.create_status_change_note(noteable, project, author, status) + def self.create_status_change_note(noteable, project, author, status, source) + body = "_Status changed to #{status}#{' by ' + source.gfm_reference if source}_" + + create({ + noteable: noteable, + project: project, + author: author, + note: body, + system: true + }, without_protection: true) + end + + # +noteable+ was referenced from +mentioner+, by including GFM in either +mentioner+'s description or an associated Note. + # Create a system Note associated with +noteable+ with a GFM back-reference to +mentioner+. + def self.create_cross_reference_note(noteable, mentioner, author, project) create({ noteable: noteable, + commit_id: (noteable.sha if noteable.respond_to? :sha), project: project, author: author, - note: "_Status changed to #{status}_" + note: "_mentioned in #{mentioner.gfm_reference}_", + system: true }, without_protection: true) end + # Determine whether or not a cross-reference note already exists. + def self.cross_reference_exists?(noteable, mentioner) + where(noteable_id: noteable.id, system: true, note: "_mentioned in #{mentioner.gfm_reference}_").any? + end + def commit_author @commit_author ||= project.users.find_by_email(noteable.author_email) || @@ -191,6 +213,16 @@ class Note < ActiveRecord::Base for_issue? || (for_merge_request? && !for_diff_line?) end + # Mentionable override. + def gfm_reference + noteable.gfm_reference + end + + # Mentionable override. + def local_reference + noteable + end + def noteable_type_name if noteable_type.present? noteable_type.downcase diff --git a/app/models/repository.rb b/app/models/repository.rb index 3d649519d8f..aeec48ee5cc 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -18,6 +18,7 @@ class Repository end def commit(id = nil) + return nil unless raw_repository commit = Gitlab::Git::Commit.find(raw_repository, id) commit = Commit.new(commit) if commit commit diff --git a/app/observers/activity_observer.rb b/app/observers/activity_observer.rb index 477ebd78aeb..d754ac8185a 100644 --- a/app/observers/activity_observer.rb +++ b/app/observers/activity_observer.rb @@ -5,8 +5,8 @@ class ActivityObserver < BaseObserver event_author_id = record.author_id if record.kind_of?(Note) - # Skip system status notes like 'status changed to close' - return true if record.note.include?("_Status changed to ") + # Skip system notes, like status changes and cross-references. + return true if record.system? # Skip wall notes to prevent spamming of dashboard return true if record.noteable_type.blank? diff --git a/app/observers/base_observer.rb b/app/observers/base_observer.rb index 92b73981d27..f9a0242ce77 100644 --- a/app/observers/base_observer.rb +++ b/app/observers/base_observer.rb @@ -10,4 +10,8 @@ class BaseObserver < ActiveRecord::Observer def current_user Thread.current[:current_user] end + + def current_commit + Thread.current[:current_commit] + end end diff --git a/app/observers/issue_observer.rb b/app/observers/issue_observer.rb index 50538419776..886d8b776fb 100644 --- a/app/observers/issue_observer.rb +++ b/app/observers/issue_observer.rb @@ -1,6 +1,8 @@ class IssueObserver < BaseObserver def after_create(issue) notification.new_issue(issue, current_user) + + issue.create_cross_references!(issue.project, current_user) end def after_close(issue, transition) @@ -17,12 +19,14 @@ class IssueObserver < BaseObserver if issue.is_being_reassigned? notification.reassigned_issue(issue, current_user) end + + issue.notice_added_references(issue.project, current_user) end protected # Create issue note with service comment like 'Status changed to closed' def create_note(issue) - Note.create_status_change_note(issue, issue.project, current_user, issue.state) + Note.create_status_change_note(issue, issue.project, current_user, issue.state, current_commit) end end diff --git a/app/observers/merge_request_observer.rb b/app/observers/merge_request_observer.rb index 689a25ff4b7..d70da514cd2 100644 --- a/app/observers/merge_request_observer.rb +++ b/app/observers/merge_request_observer.rb @@ -7,11 +7,13 @@ class MergeRequestObserver < ActivityObserver end notification.new_merge_request(merge_request, current_user) + + merge_request.create_cross_references!(merge_request.project, current_user) end def after_close(merge_request, transition) create_event(merge_request, Event::CLOSED) - Note.create_status_change_note(merge_request, merge_request.target_project, current_user, merge_request.state) + Note.create_status_change_note(merge_request, merge_request.target_project, current_user, merge_request.state, nil) notification.close_mr(merge_request, current_user) end @@ -33,11 +35,13 @@ class MergeRequestObserver < ActivityObserver def after_reopen(merge_request, transition) create_event(merge_request, Event::REOPENED) - Note.create_status_change_note(merge_request, merge_request.target_project, current_user, merge_request.state) + Note.create_status_change_note(merge_request, merge_request.target_project, current_user, merge_request.state, nil) end def after_update(merge_request) notification.reassigned_merge_request(merge_request, current_user) if merge_request.is_being_reassigned? + + merge_request.notice_added_references(merge_request.project, current_user) end def create_event(record, status) diff --git a/app/observers/note_observer.rb b/app/observers/note_observer.rb index 7b79161cce4..d31b6e8d7ce 100644 --- a/app/observers/note_observer.rb +++ b/app/observers/note_observer.rb @@ -1,5 +1,17 @@ class NoteObserver < BaseObserver def after_create(note) notification.new_note(note) + + unless note.system? + # Create a cross-reference note if this Note contains GFM that names an + # issue, merge request, or commit. + note.references.each do |mentioned| + Note.create_cross_reference_note(mentioned, note.noteable, note.author, note.project) + end + end + end + + def after_update(note) + note.notice_added_references(note.project, current_user) end end diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index e8b32f52ce1..e774b2276e8 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -1,22 +1,24 @@ class GitPushService - attr_accessor :project, :user, :push_data + attr_accessor :project, :user, :push_data, :push_commits # This method will be called after each git update # and only if the provided user and project is present in GitLab. # # All callbacks for post receive action should be placed here. # - # Now this method do next: - # 1. Ensure project satellite exists - # 2. Update merge requests - # 3. Execute project web hooks - # 4. Execute project services - # 5. Create Push Event + # Next, this method: + # 1. Creates the push event + # 2. Ensures that the project satellite exists + # 3. Updates merge requests + # 4. Recognizes cross-references from commit messages + # 5. Executes the project's web hooks + # 6. Executes the project's services # def execute(project, user, oldrev, newrev, ref) @project, @user = project, user # Collect data for this git push + @push_commits = project.repository.commits_between(oldrev, newrev) @push_data = post_receive_data(oldrev, newrev, ref) create_push_event @@ -25,11 +27,27 @@ class GitPushService project.discover_default_branch project.repository.expire_cache - if push_to_branch?(ref, oldrev) + if push_to_existing_branch?(ref, oldrev) project.update_merge_requests(oldrev, newrev, ref, @user) + process_commit_messages(ref) project.execute_hooks(@push_data.dup) project.execute_services(@push_data.dup) end + + if push_to_new_branch?(ref, oldrev) + # Re-find the pushed commits. + if is_default_branch?(ref) + # Initial push to the default branch. Take the full history of that branch as "newly pushed". + @push_commits = project.repository.commits(newrev) + else + # Use the pushed commits that aren't reachable by the default branch + # as a heuristic. This may include more commits than are actually pushed, but + # that shouldn't matter because we check for existing cross-references later. + @push_commits = project.repository.commits_between(project.default_branch, newrev) + end + + process_commit_messages(ref) + end end # This method provide a sample data @@ -45,7 +63,7 @@ class GitPushService protected def create_push_event - Event.create( + Event.create!( project: project, action: Event::PUSHED, data: push_data, @@ -53,6 +71,36 @@ class GitPushService ) end + # Extract any GFM references from the pushed commit messages. If the configured issue-closing regex is matched, + # close the referenced Issue. Create cross-reference Notes corresponding to any other referenced Mentionables. + def process_commit_messages ref + is_default_branch = is_default_branch?(ref) + + @push_commits.each do |commit| + # Close issues if these commits were pushed to the project's default branch and the commit message matches the + # closing regex. Exclude any mentioned Issues from cross-referencing even if the commits are being pushed to + # a different branch. + issues_to_close = commit.closes_issues(project) + author = commit_user(commit) + + if !issues_to_close.empty? && is_default_branch + Thread.current[:current_user] = author + Thread.current[:current_commit] = commit + + issues_to_close.each { |i| i.close && i.save } + end + + # Create cross-reference notes for any other references. Omit any issues that were referenced in an + # issue-closing phrase, or have already been mentioned from this commit (probably from this commit + # being pushed to a different branch). + refs = commit.references(project) - issues_to_close + refs.reject! { |r| commit.has_mentioned?(r) } + refs.each do |r| + Note.create_cross_reference_note(r, commit, author, project) + end + end + end + # Produce a hash of post-receive data # # data = { @@ -72,8 +120,6 @@ class GitPushService # } # def post_receive_data(oldrev, newrev, ref) - push_commits = project.repository.commits_between(oldrev, newrev) - # Total commits count push_commits_count = push_commits.size @@ -116,10 +162,26 @@ class GitPushService data end - def push_to_branch? ref, oldrev + def push_to_existing_branch? ref, oldrev ref_parts = ref.split('/') # Return if this is not a push to a branch (e.g. new commits) - !(ref_parts[1] !~ /heads/ || oldrev == "00000000000000000000000000000000") + ref_parts[1] =~ /heads/ && oldrev != "0000000000000000000000000000000000000000" + end + + def push_to_new_branch? ref, oldrev + ref_parts = ref.split('/') + + ref_parts[1] =~ /heads/ && oldrev == "0000000000000000000000000000000000000000" + end + + def is_default_branch? ref + ref == "refs/heads/#{project.default_branch}" + end + + def commit_user commit + User.where(email: commit.author_email).first || + User.where(name: commit.author_name).first || + user end end diff --git a/app/views/projects/merge_requests/show/_mr_box.html.haml b/app/views/projects/merge_requests/show/_mr_box.html.haml index 594f4061c23..c4b614b51da 100644 --- a/app/views/projects/merge_requests/show/_mr_box.html.haml +++ b/app/views/projects/merge_requests/show/_mr_box.html.haml @@ -33,4 +33,10 @@ %i.icon-ok Merged by #{link_to_member(@project, @merge_request.merge_event.author)} #{time_ago_in_words(@merge_request.merge_event.created_at)} ago. - + - if !@closes_issues.empty? && @merge_request.opened? + .ui-box-bottom.alert-info + %span + %i.icon-ok + Accepting this merge request will close #{@closes_issues.size == 1 ? 'issue' : 'issues'} + = succeed '.' do + != gfm(@closes_issues.map { |i| "##{i.iid}" }.to_sentence) diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index a3661821271..389dba59c9d 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -46,6 +46,11 @@ production: &base ## Users management # signup_enabled: true # default: false - Account passwords are not sent via the email if signup is enabled. + ## Automatic issue closing + # If a commit message matches this regular express, all issues referenced from the matched text will be closed + # if it's pushed to a project's default branch. + # issue_closing_pattern: "^([Cc]loses|[Ff]ixes) +#\d+" + ## Default project features settings default_projects_features: issues: true diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index 92d4a29b7c1..b3a19783b14 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -68,6 +68,7 @@ rescue ArgumentError # no user configured end Settings.gitlab['signup_enabled'] ||= false Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil? +Settings.gitlab['issue_closing_pattern'] = '^([Cc]loses|[Ff]ixes) #(\d+)' if Settings.gitlab['issue_closing_pattern'].nil? Settings.gitlab['default_projects_features'] ||= {} Settings.gitlab.default_projects_features['issues'] = true if Settings.gitlab.default_projects_features['issues'].nil? Settings.gitlab.default_projects_features['merge_requests'] = true if Settings.gitlab.default_projects_features['merge_requests'].nil? diff --git a/db/migrate/20130528184641_add_system_to_notes.rb b/db/migrate/20130528184641_add_system_to_notes.rb new file mode 100644 index 00000000000..1b22a4934f9 --- /dev/null +++ b/db/migrate/20130528184641_add_system_to_notes.rb @@ -0,0 +1,16 @@ +class AddSystemToNotes < ActiveRecord::Migration + class Note < ActiveRecord::Base + end + + def up + add_column :notes, :system, :boolean, default: false, null: false + + Note.reset_column_information + Note.update_all(system: false) + Note.where("note like '_status changed to%'").update_all(system: true) + end + + def down + remove_column :notes, :system + end +end diff --git a/db/schema.rb b/db/schema.rb index 429551a2bf4..5020230d831 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -152,6 +152,7 @@ ActiveRecord::Schema.define(:version => 20130821090531) do t.string "commit_id" t.integer "noteable_id" t.text "st_diff" + t.boolean "system", :default => false, :null => false end add_index "notes", ["author_id"], :name => "index_notes_on_author_id" diff --git a/lib/gitlab/reference_extractor.rb b/lib/gitlab/reference_extractor.rb new file mode 100644 index 00000000000..94b01e808d9 --- /dev/null +++ b/lib/gitlab/reference_extractor.rb @@ -0,0 +1,59 @@ +module Gitlab + # Extract possible GFM references from an arbitrary String for further processing. + class ReferenceExtractor + attr_accessor :users, :issues, :merge_requests, :snippets, :commits + + include Markdown + + def initialize + @users, @issues, @merge_requests, @snippets, @commits = [], [], [], [], [] + end + + def analyze string + parse_references(string.dup) + end + + # Given a valid project, resolve the extracted identifiers of the requested type to + # model objects. + + def users_for project + users.map do |identifier| + project.users.where(username: identifier).first + end.reject(&:nil?) + end + + def issues_for project + issues.map do |identifier| + project.issues.where(iid: identifier).first + end.reject(&:nil?) + end + + def merge_requests_for project + merge_requests.map do |identifier| + project.merge_requests.where(iid: identifier).first + end.reject(&:nil?) + end + + def snippets_for project + snippets.map do |identifier| + project.snippets.where(id: identifier).first + end.reject(&:nil?) + end + + def commits_for project + repo = project.repository + return [] if repo.nil? + + commits.map do |identifier| + repo.commit(identifier) + end.reject(&:nil?) + end + + private + + def reference_link type, identifier + # Append identifier to the appropriate collection. + send("#{type}s") << identifier + end + end +end diff --git a/spec/lib/gitlab/reference_extractor_spec.rb b/spec/lib/gitlab/reference_extractor_spec.rb new file mode 100644 index 00000000000..7d805f8c72a --- /dev/null +++ b/spec/lib/gitlab/reference_extractor_spec.rb @@ -0,0 +1,95 @@ +require 'spec_helper' + +describe Gitlab::ReferenceExtractor do + it 'extracts username references' do + subject.analyze "this contains a @user reference" + subject.users.should == ["user"] + end + + it 'extracts issue references' do + subject.analyze "this one talks about issue #1234" + subject.issues.should == ["1234"] + end + + it 'extracts merge request references' do + subject.analyze "and here's !43, a merge request" + subject.merge_requests.should == ["43"] + end + + it 'extracts snippet ids' do + subject.analyze "snippets like $12 get extracted as well" + subject.snippets.should == ["12"] + end + + it 'extracts commit shas' do + subject.analyze "commit shas 98cf0ae3 are pulled out as Strings" + subject.commits.should == ["98cf0ae3"] + end + + it 'extracts multiple references and preserves their order' do + subject.analyze "@me and @you both care about this" + subject.users.should == ["me", "you"] + end + + it 'leaves the original note unmodified' do + text = "issue #123 is just the worst, @user" + subject.analyze text + text.should == "issue #123 is just the worst, @user" + end + + it 'handles all possible kinds of references' do + accessors = Gitlab::Markdown::TYPES.map { |t| "#{t}s".to_sym } + subject.should respond_to(*accessors) + end + + context 'with a project' do + let(:project) { create(:project_with_code) } + + it 'accesses valid user objects on the project team' do + @u_foo = create(:user, username: 'foo') + @u_bar = create(:user, username: 'bar') + create(:user, username: 'offteam') + + project.team << [@u_foo, :reporter] + project.team << [@u_bar, :guest] + + subject.analyze "@foo, @baduser, @bar, and @offteam" + subject.users_for(project).should == [@u_foo, @u_bar] + end + + it 'accesses valid issue objects' do + @i0 = create(:issue, project: project) + @i1 = create(:issue, project: project) + + subject.analyze "##{@i0.iid}, ##{@i1.iid}, and #999." + subject.issues_for(project).should == [@i0, @i1] + end + + it 'accesses valid merge requests' do + @m0 = create(:merge_request, source_project: project, target_project: project, source_branch: 'aaa') + @m1 = create(:merge_request, source_project: project, target_project: project, source_branch: 'bbb') + + subject.analyze "!999, !#{@m1.iid}, and !#{@m0.iid}." + subject.merge_requests_for(project).should == [@m1, @m0] + end + + it 'accesses valid snippets' do + @s0 = create(:project_snippet, project: project) + @s1 = create(:project_snippet, project: project) + @s2 = create(:project_snippet) + + subject.analyze "$#{@s0.id}, $999, $#{@s2.id}, $#{@s1.id}" + subject.snippets_for(project).should == [@s0, @s1] + end + + it 'accesses valid commits' do + commit = project.repository.commit("master") + + subject.analyze "this references commits #{commit.sha[0..6]} and 012345" + extracted = subject.commits_for(project) + extracted.should have(1).item + extracted[0].sha.should == commit.sha + extracted[0].message.should == commit.message + end + end +end diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb index 73418efd3f2..fa556f94a1d 100644 --- a/spec/models/commit_spec.rb +++ b/spec/models/commit_spec.rb @@ -1,7 +1,8 @@ require 'spec_helper' describe Commit do - let(:commit) { create(:project_with_code).repository.commit } + let(:project) { create :project_with_code } + let(:commit) { project.repository.commit } describe '#title' do it "returns no_commit_message when safe_message is blank" do @@ -46,4 +47,23 @@ describe Commit do it { should respond_to(:id) } it { should respond_to(:to_patch) } end + + describe '#closes_issues' do + let(:issue) { create :issue, project: project } + + it 'detects issues that this commit is marked as closing' do + commit.stub(issue_closing_regex: /^([Cc]loses|[Ff]ixes) #\d+/, safe_message: "Fixes ##{issue.iid}") + commit.closes_issues(project).should == [issue] + end + end + + it_behaves_like 'a mentionable' do + let(:subject) { commit } + let(:mauthor) { create :user, email: commit.author_email } + let(:backref_text) { "commit #{subject.sha[0..5]}" } + let(:set_mentionable_text) { ->(txt){ subject.stub(safe_message: txt) } } + + # Include the subject in the repository stub. + let(:extra_commits) { [subject] } + end end diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb index c10891331b1..75155d5dc1d 100644 --- a/spec/models/issue_spec.rb +++ b/spec/models/issue_spec.rb @@ -56,4 +56,10 @@ describe Issue do Issue.open_for(user).count.should eq 2 end end + + it_behaves_like 'an editable mentionable' do + let(:subject) { create :issue, project: mproject } + let(:backref_text) { "issue ##{subject.iid}" } + let(:set_mentionable_text) { ->(txt){ subject.description = txt } } + end end diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 40931513af6..18c32d4fb74 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -43,7 +43,6 @@ describe MergeRequest do it { should include_module(Issuable) } end - describe "#mr_and_commit_notes" do let!(:merge_request) { create(:merge_request) } @@ -104,4 +103,34 @@ describe MergeRequest do end end + describe 'detection of issues to be closed' do + let(:issue0) { create :issue, project: subject.project } + let(:issue1) { create :issue, project: subject.project } + let(:commit0) { mock('commit0', closes_issues: [issue0]) } + let(:commit1) { mock('commit1', closes_issues: [issue0]) } + let(:commit2) { mock('commit2', closes_issues: [issue1]) } + + before do + subject.stub(unmerged_commits: [commit0, commit1, commit2]) + end + + it 'accesses the set of issues that will be closed on acceptance' do + subject.project.default_branch = subject.target_branch + + subject.closes_issues.should == [issue0, issue1].sort_by(&:id) + end + + it 'only lists issues as to be closed if it targets the default branch' do + subject.project.default_branch = 'master' + subject.target_branch = 'something-else' + + subject.closes_issues.should be_empty + end + end + + it_behaves_like 'an editable mentionable' do + let(:subject) { create :merge_request, source_project: mproject, target_project: mproject } + let(:backref_text) { "merge request !#{subject.iid}" } + let(:set_mentionable_text) { ->(txt){ subject.title = txt } } + end end diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb index 646255543a0..ef143debcc1 100644 --- a/spec/models/note_spec.rb +++ b/spec/models/note_spec.rb @@ -72,7 +72,6 @@ describe Note do end let(:project) { create(:project) } - let(:commit) { project.repository.commit } describe "Commit notes" do let!(:note) { create(:note_on_commit, note: "+1 from me") } @@ -131,7 +130,7 @@ describe Note do describe "Merge request notes" do let!(:note) { create(:note_on_merge_request, note: "+1 from me") } - it "should not be votable" do + it "should be votable" do note.should be_votable end end @@ -150,7 +149,7 @@ describe Note do let(:author) { create(:user) } let(:status) { 'new_status' } - subject { Note.create_status_change_note(thing, project, author, status) } + subject { Note.create_status_change_note(thing, project, author, status, nil) } it 'creates and saves a Note' do should be_a Note @@ -161,6 +160,102 @@ describe Note do its(:project) { should == thing.project } its(:author) { should == author } its(:note) { should =~ /Status changed to #{status}/ } + + it 'appends a back-reference if a closing mentionable is supplied' do + commit = double('commit', gfm_reference: 'commit 123456') + n = Note.create_status_change_note(thing, project, author, status, commit) + + n.note.should =~ /Status changed to #{status} by commit 123456/ + end + end + + describe '#create_cross_reference_note' do + let(:project) { create(:project_with_code) } + let(:author) { create(:user) } + let(:issue) { create(:issue, project: project) } + let(:mergereq) { create(:merge_request, target_project: project) } + let(:commit) { project.repository.commit } + + # Test all of {issue, merge request, commit} in both the referenced and referencing + # roles, to ensure that the correct information can be inferred from any argument. + + context 'issue from a merge request' do + subject { Note.create_cross_reference_note(issue, mergereq, author, project) } + + it { should be_valid } + its(:noteable) { should == issue } + its(:project) { should == issue.project } + its(:author) { should == author } + its(:note) { should == "_mentioned in merge request !#{mergereq.iid}_" } + end + + context 'issue from a commit' do + subject { Note.create_cross_reference_note(issue, commit, author, project) } + + it { should be_valid } + its(:noteable) { should == issue } + its(:note) { should == "_mentioned in commit #{commit.sha[0..5]}_" } + end + + context 'merge request from an issue' do + subject { Note.create_cross_reference_note(mergereq, issue, author, project) } + + it { should be_valid } + its(:noteable) { should == mergereq } + its(:project) { should == mergereq.project } + its(:note) { should == "_mentioned in issue ##{issue.iid}_" } + end + + context 'commit from a merge request' do + subject { Note.create_cross_reference_note(commit, mergereq, author, project) } + + it { should be_valid } + its(:noteable) { should == commit } + its(:project) { should == project } + its(:note) { should == "_mentioned in merge request !#{mergereq.iid}_" } + end + end + + describe '#cross_reference_exists?' do + let(:project) { create :project } + let(:author) { create :user } + let(:issue) { create :issue } + let(:commit0) { double 'commit0', gfm_reference: 'commit 123456' } + let(:commit1) { double 'commit1', gfm_reference: 'commit 654321' } + + before do + Note.create_cross_reference_note(issue, commit0, author, project) + end + + it 'detects if a mentionable has already been mentioned' do + Note.cross_reference_exists?(issue, commit0).should be_true + end + + it 'detects if a mentionable has not already been mentioned' do + Note.cross_reference_exists?(issue, commit1).should be_false + end + end + + describe '#system?' do + let(:project) { create(:project) } + let(:issue) { create(:issue, project: project) } + let(:other) { create(:issue, project: project) } + let(:author) { create(:user) } + + it 'should recognize user-supplied notes as non-system' do + @note = create(:note_on_issue) + @note.should_not be_system + end + + it 'should identify status-change notes as system notes' do + @note = Note.create_status_change_note(issue, project, author, 'closed', nil) + @note.should be_system + end + + it 'should identify cross-reference notes as system notes' do + @note = Note.create_cross_reference_note(issue, other, author, project) + @note.should be_system + end end describe :authorization do @@ -208,4 +303,11 @@ describe Note do it { @abilities.allowed?(@u3, :admin_note, @p1).should be_false } end end + + it_behaves_like 'an editable mentionable' do + let(:issue) { create :issue, project: project } + let(:subject) { create :note, noteable: issue, project: project } + let(:backref_text) { issue.gfm_reference } + let(:set_mentionable_text) { ->(txt) { subject.note = txt } } + end end diff --git a/spec/observers/activity_observer_spec.rb b/spec/observers/activity_observer_spec.rb index 78837552438..dc14ab86b6d 100644 --- a/spec/observers/activity_observer_spec.rb +++ b/spec/observers/activity_observer_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' describe ActivityObserver do let(:project) { create(:project) } + before { Thread.current[:current_user] = create(:user) } + def self.it_should_be_valid_event it { @event.should_not be_nil } it { @event.project.should == project } @@ -34,4 +36,26 @@ describe ActivityObserver do it { @event.action.should == Event::COMMENTED } it { @event.target.should == @note } end + + describe "Ignore system notes" do + let(:author) { create(:user) } + let!(:issue) { create(:issue, project: project) } + let!(:other) { create(:issue) } + + it "should not create events for status change notes" do + expect do + Note.observers.enable :activity_observer do + Note.create_status_change_note(issue, project, author, 'reopened', nil) + end + end.to_not change { Event.count } + end + + it "should not create events for cross-reference notes" do + expect do + Note.observers.enable :activity_observer do + Note.create_cross_reference_note(issue, other, author, issue.project) + end + end.to_not change { Event.count } + end + end end diff --git a/spec/observers/issue_observer_spec.rb b/spec/observers/issue_observer_spec.rb index c9e88aee1a5..4155ff31193 100644 --- a/spec/observers/issue_observer_spec.rb +++ b/spec/observers/issue_observer_spec.rb @@ -8,8 +8,9 @@ describe IssueObserver do before { subject.stub(:current_user).and_return(some_user) } + before { subject.stub(:current_commit).and_return(nil) } before { subject.stub(notification: mock('NotificationService').as_null_object) } - + before { mock_issue.project.stub_chain(:repository, :commit).and_return(nil) } subject { IssueObserver.instance } @@ -19,6 +20,15 @@ describe IssueObserver do subject.after_create(mock_issue) end + + it 'should create cross-reference notes' do + other_issue = create(:issue) + mock_issue.stub(references: [other_issue]) + + Note.should_receive(:create_cross_reference_note).with(other_issue, mock_issue, + some_user, mock_issue.project) + subject.after_create(mock_issue) + end end context '#after_close' do @@ -26,7 +36,7 @@ describe IssueObserver do before { mock_issue.stub(state: 'closed') } it 'note is created if the issue is being closed' do - Note.should_receive(:create_status_change_note).with(mock_issue, mock_issue.project, some_user, 'closed') + Note.should_receive(:create_status_change_note).with(mock_issue, mock_issue.project, some_user, 'closed', nil) subject.after_close(mock_issue, nil) end @@ -35,13 +45,23 @@ describe IssueObserver do subject.notification.should_receive(:close_issue).with(mock_issue, some_user) subject.after_close(mock_issue, nil) end + + it 'appends a mention to the closing commit if one is present' do + commit = double('commit', gfm_reference: 'commit 123456') + subject.stub(current_commit: commit) + + Note.should_receive(:create_status_change_note).with(mock_issue, mock_issue.project, some_user, 'closed', commit) + + subject.after_close(mock_issue, nil) + end end context 'a status "reopened"' do before { mock_issue.stub(state: 'reopened') } it 'note is created if the issue is being reopened' do - Note.should_receive(:create_status_change_note).with(mock_issue, mock_issue.project, some_user, 'reopened') + Note.should_receive(:create_status_change_note).with(mock_issue, mock_issue.project, some_user, 'reopened', nil) + subject.after_reopen(mock_issue, nil) end end @@ -67,5 +87,13 @@ describe IssueObserver do subject.after_update(mock_issue) end end + + context 'cross-references' do + it 'notices added references' do + mock_issue.should_receive(:notice_added_references) + + subject.after_update(mock_issue) + end + end end end diff --git a/spec/observers/merge_request_observer_spec.rb b/spec/observers/merge_request_observer_spec.rb index 3d6fff9c24e..3f5250a0040 100644 --- a/spec/observers/merge_request_observer_spec.rb +++ b/spec/observers/merge_request_observer_spec.rb @@ -5,15 +5,20 @@ describe MergeRequestObserver do let(:assignee) { create :user } let(:author) { create :user } let(:mr_mock) { double(:merge_request, id: 42, assignee: assignee, author: author) } - let(:assigned_mr) { create(:merge_request, assignee: assignee, author: author) } - let(:unassigned_mr) { create(:merge_request, author: author) } - let(:closed_assigned_mr) { create(:closed_merge_request, assignee: assignee, author: author) } - let(:closed_unassigned_mr) { create(:closed_merge_request, author: author) } + let(:assigned_mr) { create(:merge_request, assignee: assignee, author: author, target_project: create(:project)) } + let(:unassigned_mr) { create(:merge_request, author: author, target_project: create(:project)) } + let(:closed_assigned_mr) { create(:closed_merge_request, assignee: assignee, author: author, target_project: create(:project)) } + let(:closed_unassigned_mr) { create(:closed_merge_request, author: author, target_project: create(:project)) } before { subject.stub(:current_user).and_return(some_user) } before { subject.stub(notification: mock('NotificationService').as_null_object) } before { mr_mock.stub(:author_id) } before { mr_mock.stub(:target_project) } + before { mr_mock.stub(:source_project) } + before { mr_mock.stub(:project) } + before { mr_mock.stub(:create_cross_references!).and_return(true) } + before { Repository.any_instance.stub(commit: nil) } + before(:each) { enable_observers } after(:each) { disable_observers } @@ -24,11 +29,20 @@ describe MergeRequestObserver do subject.should_receive(:notification) subject.after_create(mr_mock) end + + it 'creates cross-reference notes' do + project = create :project + mr_mock.stub(title: "this mr references !#{assigned_mr.id}", project: project) + mr_mock.should_receive(:create_cross_references!).with(project, some_user) + + subject.after_create(mr_mock) + end end context '#after_update' do before(:each) do mr_mock.stub(:is_being_reassigned?).and_return(false) + mr_mock.stub(:notice_added_references) end it 'is called when a merge request is changed' do @@ -41,6 +55,12 @@ describe MergeRequestObserver do end end + it 'checks for new references' do + mr_mock.should_receive(:notice_added_references) + + subject.after_update(mr_mock) + end + context 'a notification' do it 'is sent if the merge request is being reassigned' do mr_mock.should_receive(:is_being_reassigned?).and_return(true) @@ -61,13 +81,13 @@ describe MergeRequestObserver do context '#after_close' do context 'a status "closed"' do it 'note is created if the merge request is being closed' do - Note.should_receive(:create_status_change_note).with(assigned_mr, assigned_mr.target_project, some_user, 'closed') + Note.should_receive(:create_status_change_note).with(assigned_mr, assigned_mr.target_project, some_user, 'closed', nil) assigned_mr.close end it 'notification is delivered only to author if the merge request is being closed' do - Note.should_receive(:create_status_change_note).with(unassigned_mr, unassigned_mr.target_project, some_user, 'closed') + Note.should_receive(:create_status_change_note).with(unassigned_mr, unassigned_mr.target_project, some_user, 'closed', nil) unassigned_mr.close end @@ -77,13 +97,13 @@ describe MergeRequestObserver do context '#after_reopen' do context 'a status "reopened"' do it 'note is created if the merge request is being reopened' do - Note.should_receive(:create_status_change_note).with(closed_assigned_mr, closed_assigned_mr.target_project, some_user, 'reopened') + Note.should_receive(:create_status_change_note).with(closed_assigned_mr, closed_assigned_mr.target_project, some_user, 'reopened', nil) closed_assigned_mr.reopen end it 'notification is delivered only to author if the merge request is being reopened' do - Note.should_receive(:create_status_change_note).with(closed_unassigned_mr, closed_unassigned_mr.target_project, some_user, 'reopened') + Note.should_receive(:create_status_change_note).with(closed_unassigned_mr, closed_unassigned_mr.target_project, some_user, 'reopened', nil) closed_unassigned_mr.reopen end diff --git a/spec/observers/note_observer_spec.rb b/spec/observers/note_observer_spec.rb index 9ada92704b6..f9b96c255c1 100644 --- a/spec/observers/note_observer_spec.rb +++ b/spec/observers/note_observer_spec.rb @@ -5,9 +5,9 @@ describe NoteObserver do before { subject.stub(notification: mock('NotificationService').as_null_object) } let(:team_without_author) { (1..2).map { |n| double :user, id: n } } + let(:note) { double(:note).as_null_object } describe '#after_create' do - let(:note) { double :note } it 'is called after a note is created' do subject.should_receive :after_create @@ -22,5 +22,35 @@ describe NoteObserver do subject.after_create(note) end + + it 'creates cross-reference notes as appropriate' do + @p = create(:project) + @referenced = create(:issue, project: @p) + @referencer = create(:issue, project: @p) + @author = create(:user) + + Note.should_receive(:create_cross_reference_note).with(@referenced, @referencer, @author, @p) + + Note.observers.enable :note_observer do + create(:note, project: @p, author: @author, noteable: @referencer, + note: "Duplicate of ##{@referenced.iid}") + end + end + + it "doesn't cross-reference system notes" do + Note.should_receive(:create_cross_reference_note).once + + Note.observers.enable :note_observer do + Note.create_cross_reference_note(create(:issue), create(:issue)) + end + end + end + + describe '#after_update' do + it 'checks for new cross-references' do + note.should_receive(:notice_added_references) + + subject.after_update(note) + end end end diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index 286a8cdaa22..ffd80f33fc8 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -6,6 +6,7 @@ describe GitPushService do let (:service) { GitPushService.new } before do + @blankrev = '0000000000000000000000000000000000000000' @oldrev = 'b98a310def241a6fd9c9a9a3e7934c48e498fe81' @newrev = 'b19a04f53caeebf4fe5ec2327cb83e9253dc91bb' @ref = 'refs/heads/master' @@ -98,7 +99,7 @@ describe GitPushService do it "when pushing a branch for the first time" do @project_hook.should_not_receive(:execute) - service.execute(project, user, '00000000000000000000000000000000', 'newrev', 'refs/heads/master') + service.execute(project, user, @blankrev, 'newrev', 'refs/heads/master') end it "when pushing tags" do @@ -107,5 +108,107 @@ describe GitPushService do end end end + + describe "cross-reference notes" do + let(:issue) { create :issue, project: project } + let(:commit_author) { create :user } + let(:commit) { project.repository.commit } + + before do + commit.stub({ + safe_message: "this commit \n mentions ##{issue.id}", + references: [issue], + author_name: commit_author.name, + author_email: commit_author.email + }) + project.repository.stub(commits_between: [commit]) + end + + it "creates a note if a pushed commit mentions an issue" do + Note.should_receive(:create_cross_reference_note).with(issue, commit, commit_author, project) + + service.execute(project, user, @oldrev, @newrev, @ref) + end + + it "only creates a cross-reference note if one doesn't already exist" do + Note.create_cross_reference_note(issue, commit, user, project) + + Note.should_not_receive(:create_cross_reference_note).with(issue, commit, commit_author, project) + + service.execute(project, user, @oldrev, @newrev, @ref) + end + + it "defaults to the pushing user if the commit's author is not known" do + commit.stub(author_name: 'unknown name', author_email: 'unknown@email.com') + Note.should_receive(:create_cross_reference_note).with(issue, commit, user, project) + + service.execute(project, user, @oldrev, @newrev, @ref) + end + + it "finds references in the first push to a non-default branch" do + project.repository.stub(:commits_between).with(@blankrev, @newrev).and_return([]) + project.repository.stub(:commits_between).with("master", @newrev).and_return([commit]) + + Note.should_receive(:create_cross_reference_note).with(issue, commit, commit_author, project) + + service.execute(project, user, @blankrev, @newrev, 'refs/heads/other') + end + + it "finds references in the first push to a default branch" do + project.repository.stub(:commits_between).with(@blankrev, @newrev).and_return([]) + project.repository.stub(:commits).with(@newrev).and_return([commit]) + + Note.should_receive(:create_cross_reference_note).with(issue, commit, commit_author, project) + + service.execute(project, user, @blankrev, @newrev, 'refs/heads/master') + end + end + + describe "closing issues from pushed commits" do + let(:issue) { create :issue, project: project } + let(:other_issue) { create :issue, project: project } + let(:commit_author) { create :user } + let(:closing_commit) { project.repository.commit } + + before do + closing_commit.stub({ + issue_closing_regex: /^([Cc]loses|[Ff]ixes) #\d+/, + safe_message: "this is some work.\n\ncloses ##{issue.iid}", + author_name: commit_author.name, + author_email: commit_author.email + }) + + project.repository.stub(commits_between: [closing_commit]) + end + + it "closes issues with commit messages" do + service.execute(project, user, @oldrev, @newrev, @ref) + + Issue.find(issue.id).should be_closed + end + + it "passes the closing commit as a thread-local" do + service.execute(project, user, @oldrev, @newrev, @ref) + + Thread.current[:current_commit].should == closing_commit + end + + it "doesn't create cross-reference notes for a closing reference" do + expect { + service.execute(project, user, @oldrev, @newrev, @ref) + }.not_to change { Note.where(project_id: project.id, system: true).count } + end + + it "doesn't close issues when pushed to non-default branches" do + project.stub(default_branch: 'durf') + + # The push still shouldn't create cross-reference notes. + expect { + service.execute(project, user, @oldrev, @newrev, 'refs/heads/hurf') + }.not_to change { Note.where(project_id: project.id, system: true).count } + + Issue.find(issue.id).should be_opened + end + end end diff --git a/spec/support/login_helpers.rb b/spec/support/login_helpers.rb index 46794f48384..025534a900d 100644 --- a/spec/support/login_helpers.rb +++ b/spec/support/login_helpers.rb @@ -18,6 +18,7 @@ module LoginHelpers fill_in "user_login", with: user.email fill_in "user_password", with: "123456" click_button "Sign in" + Thread.current[:current_user] = user end def logout diff --git a/spec/support/mentionable_shared_examples.rb b/spec/support/mentionable_shared_examples.rb new file mode 100644 index 00000000000..a7f189777c8 --- /dev/null +++ b/spec/support/mentionable_shared_examples.rb @@ -0,0 +1,94 @@ +# Specifications for behavior common to all Mentionable implementations. +# Requires a shared context containing: +# - let(:subject) { "the mentionable implementation" } +# - let(:backref_text) { "the way that +subject+ should refer to itself in backreferences " } +# - let(:set_mentionable_text) { lambda { |txt| "block that assigns txt to the subject's mentionable_text" } } + +def common_mentionable_setup + # Avoid name collisions with let(:project) or let(:author) in the surrounding scope. + let(:mproject) { create :project } + let(:mauthor) { subject.author } + + let(:mentioned_issue) { create :issue, project: mproject } + let(:other_issue) { create :issue, project: mproject } + let(:mentioned_mr) { create :merge_request, target_project: mproject, source_branch: 'different' } + let(:mentioned_commit) { mock('commit', sha: '1234567890abcdef').as_null_object } + + # Override to add known commits to the repository stub. + let(:extra_commits) { [] } + + # A string that mentions each of the +mentioned_.*+ objects above. Mentionables should add a self-reference + # to this string and place it in their +mentionable_text+. + let(:ref_string) do + "mentions ##{mentioned_issue.iid} twice ##{mentioned_issue.iid}, !#{mentioned_mr.iid}, " + + "#{mentioned_commit.sha[0..5]} and itself as #{backref_text}" + end + + before do + # Wire the project's repository to return the mentioned commit, and +nil+ for any + # unrecognized commits. + commitmap = { '123456' => mentioned_commit } + extra_commits.each { |c| commitmap[c.sha[0..5]] = c } + + repo = mock('repository') + repo.stub(:commit) { |sha| commitmap[sha] } + mproject.stub(repository: repo) + + set_mentionable_text.call(ref_string) + end +end + +shared_examples 'a mentionable' do + common_mentionable_setup + + it 'generates a descriptive back-reference' do + subject.gfm_reference.should == backref_text + end + + it "extracts references from its reference property" do + # De-duplicate and omit itself + refs = subject.references(mproject) + + refs.should have(3).items + refs.should include(mentioned_issue) + refs.should include(mentioned_mr) + refs.should include(mentioned_commit) + end + + it 'creates cross-reference notes' do + [mentioned_issue, mentioned_mr, mentioned_commit].each do |referenced| + Note.should_receive(:create_cross_reference_note).with(referenced, subject.local_reference, mauthor, mproject) + end + + subject.create_cross_references!(mproject, mauthor) + end + + it 'detects existing cross-references' do + Note.create_cross_reference_note(mentioned_issue, subject.local_reference, mauthor, mproject) + + subject.has_mentioned?(mentioned_issue).should be_true + subject.has_mentioned?(mentioned_mr).should be_false + end +end + +shared_examples 'an editable mentionable' do + common_mentionable_setup + + it_behaves_like 'a mentionable' + + it 'creates new cross-reference notes when the mentionable text is edited' do + new_text = "this text still mentions ##{mentioned_issue.iid} and #{mentioned_commit.sha[0..5]}, " + + "but now it mentions ##{other_issue.iid}, too." + + [mentioned_issue, mentioned_commit].each do |oldref| + Note.should_not_receive(:create_cross_reference_note).with(oldref, subject.local_reference, + mauthor, mproject) + end + + Note.should_receive(:create_cross_reference_note).with(other_issue, subject.local_reference, mauthor, mproject) + + subject.save + set_mentionable_text.call(new_text) + subject.notice_added_references(mproject, mauthor) + end +end -- GitLab From 48ce80a60c4d80afa555ce511e98102ff5291a31 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Aug 2013 12:54:57 +0300 Subject: [PATCH 050/175] Fix issue when developers are able to push to protected branch When that branch contain a '/' in the branch name. Fix for git over HTTP --- lib/gitlab/backend/grack_auth.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/gitlab/backend/grack_auth.rb b/lib/gitlab/backend/grack_auth.rb index ddf370fbab8..be5c58bb5a6 100644 --- a/lib/gitlab/backend/grack_auth.rb +++ b/lib/gitlab/backend/grack_auth.rb @@ -15,7 +15,7 @@ module Grack @auth = Request.new(env) # Need this patch due to the rails mount - + # Need this if under RELATIVE_URL_ROOT unless Gitlab.config.gitlab.relative_url_root.empty? # If website is mounted using relative_url_root need to remove it first @@ -23,7 +23,7 @@ module Grack else @env['PATH_INFO'] = @request.path end - + @env['SCRIPT_NAME'] = "" auth! @@ -110,7 +110,7 @@ module Grack # Need to reset seek point @request.body.rewind - /refs\/heads\/([\w\.-]+)/n.match(input.force_encoding('ascii-8bit')).to_a.last + /refs\/heads\/([\/\w\.-]+)/n.match(input.force_encoding('ascii-8bit')).to_a.last end end end -- GitLab From b5593683af9c8d182c954e04fbde9934404c5058 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Aug 2013 13:06:41 +0300 Subject: [PATCH 051/175] Mars theme for generated admin account --- db/fixtures/development/01_admin.rb | 1 + db/fixtures/production/001_admin.rb | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/db/fixtures/development/01_admin.rb b/db/fixtures/development/01_admin.rb index 948a3459283..ecea8211393 100644 --- a/db/fixtures/development/01_admin.rb +++ b/db/fixtures/development/01_admin.rb @@ -8,5 +8,6 @@ User.seed(:id, [ password_confirmation: "5iveL!fe", admin: true, projects_limit: 100, + theme_id: Gitlab::Theme::MARS } ]) diff --git a/db/fixtures/production/001_admin.rb b/db/fixtures/production/001_admin.rb index 632f6107b33..1b77d94905d 100644 --- a/db/fixtures/production/001_admin.rb +++ b/db/fixtures/production/001_admin.rb @@ -4,7 +4,9 @@ admin = User.create( username: 'root', password: "5iveL!fe", password_confirmation: "5iveL!fe", - password_expires_at: Time.now + password_expires_at: Time.now, + theme_id: Gitlab::Theme::MARS + ) admin.projects_limit = 10000 -- GitLab From cc4b638c343d49c205fa510380b65043229e5a9e Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Aug 2013 13:20:45 +0300 Subject: [PATCH 052/175] Set iid in fixtures. Add rake dev:setup for development --- db/fixtures/development/07_milestones.rb | 5 +++++ db/fixtures/development/09_issues.rb | 5 +++++ db/fixtures/development/10_merge_requests.rb | 5 +++++ lib/tasks/dev.rake | 10 ++++++++++ 4 files changed, 25 insertions(+) create mode 100644 lib/tasks/dev.rake diff --git a/db/fixtures/development/07_milestones.rb b/db/fixtures/development/07_milestones.rb index 3135bf3a4f4..6fe7e246770 100644 --- a/db/fixtures/development/07_milestones.rb +++ b/db/fixtures/development/07_milestones.rb @@ -11,3 +11,8 @@ Milestone.seed(:id, [ { id: 9, project_id: 3, title: 'v' + Faker::Address.zip_code }, { id: 11, project_id: 3, title: 'v' + Faker::Address.zip_code }, ]) + +Milestone.all.map do |ml| + ml.set_iid + ml.save +end diff --git a/db/fixtures/development/09_issues.rb b/db/fixtures/development/09_issues.rb index 627579721d0..31ba77254a3 100644 --- a/db/fixtures/development/09_issues.rb +++ b/db/fixtures/development/09_issues.rb @@ -24,4 +24,9 @@ Gitlab::Seeder.quiet do }]) print('.') end + + Issue.all.map do |issue| + issue.set_iid + issue.save + end end diff --git a/db/fixtures/development/10_merge_requests.rb b/db/fixtures/development/10_merge_requests.rb index bf247adb416..1e61ea28636 100644 --- a/db/fixtures/development/10_merge_requests.rb +++ b/db/fixtures/development/10_merge_requests.rb @@ -34,6 +34,11 @@ Gitlab::Seeder.quiet do end end +MergeRequest.all.map do |mr| + mr.set_iid + mr.save +end + puts 'Load diffs for Merge Requests (it will take some time)...' MergeRequest.all.each do |mr| mr.reload_code diff --git a/lib/tasks/dev.rake b/lib/tasks/dev.rake new file mode 100644 index 00000000000..7d3602211c1 --- /dev/null +++ b/lib/tasks/dev.rake @@ -0,0 +1,10 @@ +namespace :dev do + desc "GITLAB | Setup developer environment (db, fixtures)" + task :setup => :environment do + ENV['force'] = 'yes' + Rake::Task["db:setup"].invoke + Rake::Task["db:seed_fu"].invoke + Rake::Task["gitlab:shell:setup"].invoke + end +end + -- GitLab From bda409c4c8e938c4cee254b04dd954978f770d8c Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Aug 2013 10:37:58 +0000 Subject: [PATCH 053/175] Add placeholders from and to --- app/views/projects/compare/_form.html.haml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/projects/compare/_form.html.haml b/app/views/projects/compare/_form.html.haml index c96a2ae4cb7..6fb7b1fd3dd 100644 --- a/app/views/projects/compare/_form.html.haml +++ b/app/views/projects/compare/_form.html.haml @@ -15,9 +15,9 @@ .pull-left - if params[:to] && params[:from] = link_to 'switch', {from: params[:to], to: params[:from]}, {class: 'commits-compare-switch has_tooltip', title: 'Switch base of comparison'} - = text_field_tag :from, params[:from], class: "input-xlarge input-xpadding" + = text_field_tag :from, params[:from], placeholder: "from", class: "input-xlarge input-xpadding" = "..." - = text_field_tag :to, params[:to], class: "input-xlarge input-xpadding" + = text_field_tag :to, params[:to], placeholder: "to", class: "input-xlarge input-xpadding" .pull-left   = submit_tag "Compare", class: "btn btn-create commits-compare-btn" @@ -35,4 +35,4 @@ minLength: 1 }); - disableButtonIfEmptyField('#to', '.commits-compare-btn'); + disableButtonIfEmptyField('#to', '.commits-compare-btn'); \ No newline at end of file -- GitLab From 45c39250209aa4bcfc41c82445cf4ae68a45b880 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Aug 2013 13:50:13 +0300 Subject: [PATCH 054/175] Better style for blockquote text in comments --- app/assets/stylesheets/gitlab_bootstrap/mixins.scss | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/assets/stylesheets/gitlab_bootstrap/mixins.scss b/app/assets/stylesheets/gitlab_bootstrap/mixins.scss index 8676cc624ce..e7daf8f43b4 100644 --- a/app/assets/stylesheets/gitlab_bootstrap/mixins.scss +++ b/app/assets/stylesheets/gitlab_bootstrap/mixins.scss @@ -89,6 +89,12 @@ h2 { margin-top: 25px;} h3 { margin-top: 20px;} h4 { margin-top: 15px;} + + blockquote p { + color: #888; + font-size: 14px; + line-height: 1.5; + } } @mixin page-title { -- GitLab From dc016fef3983a956bb3f98a70b8db6490e949605 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Aug 2013 14:15:21 +0300 Subject: [PATCH 055/175] Add redirect from Issue#id to Issue#iid --- app/controllers/projects/issues_controller.rb | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 4b6e22e3607..e8f845b2d17 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -91,7 +91,11 @@ class Projects::IssuesController < Projects::ApplicationController protected def issue - @issue ||= @project.issues.find_by_iid!(params[:id]) + @issue ||= begin + @project.issues.find_by_iid!(params[:id]) + rescue ActiveRecord::RecordNotFound + redirect_old + end end def authorize_modify_issue! @@ -109,4 +113,20 @@ class Projects::IssuesController < Projects::ApplicationController def issues_filtered @issues = Issues::ListContext.new(project, current_user, params).execute end + + # Since iids are implemented only in 6.1 + # user may navigate to issue page using old global ids. + # + # To prevent 404 errors we provide a redirect to correct iids until 7.0 release + # + def redirect_old + issue = @project.issues.find_by_id(params[:id]) + + if issue + redirect_to project_issue_path(@project, issue) + return + else + raise ActiveRecord::RecordNotFound.new + end + end end -- GitLab From 6b206c9d965c664053ff0139736357ea096f4766 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Aug 2013 14:27:19 +0300 Subject: [PATCH 056/175] Allow markdown tables --- lib/gitlab/markdown.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb index 61c622a448a..dc9c0e0ab2c 100644 --- a/lib/gitlab/markdown.rb +++ b/lib/gitlab/markdown.rb @@ -63,7 +63,7 @@ module Gitlab insert_piece($1) end - sanitize text.html_safe, attributes: ActionView::Base.sanitized_allowed_attributes + %w(id class) + sanitize text.html_safe, attributes: ActionView::Base.sanitized_allowed_attributes + %w(id class), tags: ActionView::Base.sanitized_allowed_tags + %w(table tr td th) end private -- GitLab From 3cc26654d576ed6a0f6eb33980c41f1b66b5f1eb Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Aug 2013 14:53:36 +0300 Subject: [PATCH 057/175] Remove old migration tasks You should update to 6.0 before proceed with update to higher version. So its no reason to keep old tasks any more. It should be still available in 6-0-stable but not in master --- .../migrate/migrate_global_projects.rake | 23 ------------------- lib/tasks/migrate/migrate_groups.rake | 16 ------------- lib/tasks/migrate/migrate_inline_notes.rake | 16 ------------- lib/tasks/migrate/migrate_keys.rake | 20 ---------------- lib/tasks/migrate/migrate_milestones.rake | 4 ---- lib/tasks/migrate/migrate_mr.rake | 18 --------------- lib/tasks/migrate/migrate_note_linecode.rake | 13 ----------- 7 files changed, 110 deletions(-) delete mode 100644 lib/tasks/migrate/migrate_global_projects.rake delete mode 100644 lib/tasks/migrate/migrate_groups.rake delete mode 100644 lib/tasks/migrate/migrate_inline_notes.rake delete mode 100644 lib/tasks/migrate/migrate_keys.rake delete mode 100644 lib/tasks/migrate/migrate_milestones.rake delete mode 100644 lib/tasks/migrate/migrate_mr.rake delete mode 100644 lib/tasks/migrate/migrate_note_linecode.rake diff --git a/lib/tasks/migrate/migrate_global_projects.rake b/lib/tasks/migrate/migrate_global_projects.rake deleted file mode 100644 index 7a61bc82d20..00000000000 --- a/lib/tasks/migrate/migrate_global_projects.rake +++ /dev/null @@ -1,23 +0,0 @@ -desc "GITLAB | Migrate Global Projects to Namespaces" -task migrate_global_projects: :environment do - found = Project.where(namespace_id: nil).count - if found > 0 - puts "Global namespace is deprecated. We found #{found} projects stored in global namespace".yellow - puts "You may abort this task and move them to group/user namespaces manually." - puts "If you want us to move this projects under owner namespaces then continue" - ask_to_continue - else - puts "No global projects found. Proceed with update.".green - end - - Project.where(namespace_id: nil).find_each(batch_size: 20) do |project| - begin - project.transfer(project.owner.namespace) - print '.' - rescue => ex - puts ex.message - print 'F' - end - end -end - diff --git a/lib/tasks/migrate/migrate_groups.rake b/lib/tasks/migrate/migrate_groups.rake deleted file mode 100644 index 49c930a4893..00000000000 --- a/lib/tasks/migrate/migrate_groups.rake +++ /dev/null @@ -1,16 +0,0 @@ -desc "GITLAB | Migrate Groups to match v6.0" -task migrate_groups: :environment do - puts "This will add group owners to group membership" - ask_to_continue - - Group.find_each(batch_size: 20) do |group| - begin - group.send :add_owner - print '.' - rescue => ex - puts ex.message - print 'F' - end - end -end - diff --git a/lib/tasks/migrate/migrate_inline_notes.rake b/lib/tasks/migrate/migrate_inline_notes.rake deleted file mode 100644 index e21fa0e8ce8..00000000000 --- a/lib/tasks/migrate/migrate_inline_notes.rake +++ /dev/null @@ -1,16 +0,0 @@ -desc "GITLAB | Migrate inline notes" -task migrate_inline_notes: :environment do - Note.where('line_code IS NOT NULL').find_each(batch_size: 100) do |note| - begin - note.set_diff - if note.save - print '.' - else - print 'F' - end - rescue - print 'F' - end - end -end - diff --git a/lib/tasks/migrate/migrate_keys.rake b/lib/tasks/migrate/migrate_keys.rake deleted file mode 100644 index 969ba6dc15e..00000000000 --- a/lib/tasks/migrate/migrate_keys.rake +++ /dev/null @@ -1,20 +0,0 @@ -desc "GITLAB | Migrate SSH Keys" -task migrate_keys: :environment do - puts "This will add fingerprint to ssh keys in db" - puts "If you have duplicate keys https://github.com/gitlabhq/gitlabhq/issues/4453 all but the first will be deleted".yellow - ask_to_continue - - Key.find_each(batch_size: 20) do |key| - if key.valid? && key.save - print '.' - elsif key.fingerprint.present? - puts "\nDeleting #{key.inspect}".yellow - key.destroy - else - print 'F' - end - end - print "\n" -end - - diff --git a/lib/tasks/migrate/migrate_milestones.rake b/lib/tasks/migrate/migrate_milestones.rake deleted file mode 100644 index 14c70a3d1c7..00000000000 --- a/lib/tasks/migrate/migrate_milestones.rake +++ /dev/null @@ -1,4 +0,0 @@ -desc "GITLAB | Migrate Milestones" -task migrate_milestones: :environment do - Milestone.where(state: nil).update_all(state: 'active') -end diff --git a/lib/tasks/migrate/migrate_mr.rake b/lib/tasks/migrate/migrate_mr.rake deleted file mode 100644 index 74b1db03442..00000000000 --- a/lib/tasks/migrate/migrate_mr.rake +++ /dev/null @@ -1,18 +0,0 @@ -# This taks will reload commits/diff for all merge requests -desc "GITLAB | Migrate Merge Requests" -task migrate_merge_requests: :environment do - puts "Since 5.1 old merge request serialization logic was replaced with a better one." - puts "It makes old merge request diff invalid for GitLab 5.1+" - puts "* * *" - puts "This will rebuild commits/diffs info for existing merge requests." - puts "You will lose merge request diff if its already merged." - ask_to_continue - - MergeRequest.find_each(batch_size: 20) do |mr| - mr.st_commits = [] - mr.save - mr.reload_code - print '.' - end -end - diff --git a/lib/tasks/migrate/migrate_note_linecode.rake b/lib/tasks/migrate/migrate_note_linecode.rake deleted file mode 100644 index 71be1f12d1b..00000000000 --- a/lib/tasks/migrate/migrate_note_linecode.rake +++ /dev/null @@ -1,13 +0,0 @@ -desc "GITLAB | Migrate Note LineCode" -task migrate_note_linecode: :environment do - Note.inline.each do |note| - index = note.diff_file_index - if index =~ /^\d{1,10}$/ # is number. not hash. - hash = Digest::SHA1.hexdigest(note.noteable.diffs[index.to_i].new_path) - new_line_code = note.line_code.sub(index, hash) - note.update_column :line_code, new_line_code - print '.' - end - end -end - -- GitLab From 0093554ad6055a0843b0537557e8ca44d6ff2429 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Aug 2013 15:07:07 +0300 Subject: [PATCH 058/175] Add test and docs for markdown tables --- doc/markdown/markdown.md | 23 ++++++++++++++++++++- spec/helpers/gitlab_markdown_helper_spec.rb | 9 ++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/doc/markdown/markdown.md b/doc/markdown/markdown.md index ccf44652b5b..b23e0f3e265 100644 --- a/doc/markdown/markdown.md +++ b/doc/markdown/markdown.md @@ -27,8 +27,9 @@ Table of Contents [Inline HTML](#toc_25) [Horizontal Rule](#toc_26) [Line Breaks](#toc_27) +[Tables](#toc_28) -[References](#toc_28) +[References](#toc_29) --------------------- ---------------------------------------------- @@ -440,6 +441,26 @@ This line is separated from the one above by two newlines, so it will be a *sepa This line is also begins a separate paragraph, but... This line is only separated by a single newline, so it's a separate line in the *same paragraph*. + +## Tables + +Tables aren't part of the core Markdown spec, but they are part of GFM and Markdown Here supports them. + +``` +| header 1 | header 2 | +| -------- | -------- | +| cell 1 | cell 2 | +| cell 3 | cell 4 | +``` + +Code above produces next output: + +| header 1 | header 2 | +| -------- | -------- | +| cell 1 | cell 2 | +| cell 3 | cell 4 | + + ------------ diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb index a4db8b4ff7e..d49247accc2 100644 --- a/spec/helpers/gitlab_markdown_helper_spec.rb +++ b/spec/helpers/gitlab_markdown_helper_spec.rb @@ -366,6 +366,15 @@ describe GitlabMarkdownHelper do markdown(actual).should match(%r{Apply !#{merge_request.iid}}) end + it "should handle tables" do + actual = %Q{| header 1 | header 2 | +| -------- | -------- | +| cell 1 | cell 2 | +| cell 3 | cell 4 |} + + markdown(actual).should match(/\A Date: Mon, 26 Aug 2013 15:09:33 +0300 Subject: [PATCH 059/175] Fix md help table header --- doc/markdown/markdown.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/markdown/markdown.md b/doc/markdown/markdown.md index b23e0f3e265..a84222f9fc2 100644 --- a/doc/markdown/markdown.md +++ b/doc/markdown/markdown.md @@ -442,6 +442,7 @@ This line is also begins a separate paragraph, but... This line is only separated by a single newline, so it's a separate line in the *same paragraph*. + ## Tables Tables aren't part of the core Markdown spec, but they are part of GFM and Markdown Here supports them. -- GitLab From 4675ff46e8b1d354d86cdf80ac3bd4f60814dbe3 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Aug 2013 15:49:11 +0300 Subject: [PATCH 060/175] Remove bottom margin for text in event note --- app/assets/stylesheets/sections/events.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/assets/stylesheets/sections/events.scss b/app/assets/stylesheets/sections/events.scss index d94d97c8d9a..80ee6b6323c 100644 --- a/app/assets/stylesheets/sections/events.scss +++ b/app/assets/stylesheets/sections/events.scss @@ -80,6 +80,10 @@ margin-left: 0px; max-width: 200px; } + + p:last-child { + margin-bottom: 0; + } } .event-note-icon { color: #777; -- GitLab From 3d8f38c683283f1e9eb5c1243b0ea9cc2ca5f6b1 Mon Sep 17 00:00:00 2001 From: Romain Date: Mon, 26 Aug 2013 14:54:07 +0200 Subject: [PATCH 061/175] [#4821] - Fix some missing iids --- app/mailers/emails/notes.rb | 4 ++-- app/views/projects/milestones/_issues.html.haml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/mailers/emails/notes.rb b/app/mailers/emails/notes.rb index 769b6e0b861..761b4c8161f 100644 --- a/app/mailers/emails/notes.rb +++ b/app/mailers/emails/notes.rb @@ -11,14 +11,14 @@ module Emails @note = Note.find(note_id) @issue = @note.noteable @project = @note.project - mail(to: recipient(recipient_id), subject: subject("note for issue ##{@issue.id}")) + mail(to: recipient(recipient_id), subject: subject("note for issue ##{@issue.iid}")) end def note_merge_request_email(recipient_id, note_id) @note = Note.find(note_id) @merge_request = @note.noteable @project = @note.project - mail(to: recipient(recipient_id), subject: subject("note for merge request !#{@merge_request.id}")) + mail(to: recipient(recipient_id), subject: subject("note for merge request !#{@merge_request.iid}")) end def note_wall_email(recipient_id, note_id) diff --git a/app/views/projects/milestones/_issues.html.haml b/app/views/projects/milestones/_issues.html.haml index 983692399ca..bf81cfda45f 100644 --- a/app/views/projects/milestones/_issues.html.haml +++ b/app/views/projects/milestones/_issues.html.haml @@ -4,7 +4,7 @@ - issues.each do |issue| %li = link_to [@project, issue] do - %span.badge{class: issue.closed? ? 'badge-important' : 'badge-info'} ##{issue.id} + %span.badge{class: issue.closed? ? 'badge-important' : 'badge-info'} ##{issue.iid} = link_to_gfm truncate(issue.title, length: 40), [@project, issue] - if issue.assignee .pull-right -- GitLab From 17af835387c996f82b46f3bade67d513b4e40cc5 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Aug 2013 16:30:03 +0300 Subject: [PATCH 062/175] Add event filter for group and project show pages --- app/assets/javascripts/activities.js.coffee | 31 +++++++++++++++++++++ app/assets/javascripts/dashboard.js.coffee | 27 ------------------ app/assets/javascripts/dispatcher.js.coffee | 3 +- app/controllers/application_controller.rb | 5 ++++ app/controllers/dashboard_controller.rb | 5 ---- app/controllers/groups_controller.rb | 4 ++- app/controllers/projects_controller.rb | 5 +++- app/helpers/events_helper.rb | 2 +- app/views/dashboard/_activities.html.haml | 7 +---- app/views/groups/show.html.haml | 1 + app/views/projects/show.html.haml | 1 + app/views/shared/_event_filter.html.haml | 5 ++++ 12 files changed, 54 insertions(+), 42 deletions(-) create mode 100644 app/assets/javascripts/activities.js.coffee create mode 100644 app/views/shared/_event_filter.html.haml diff --git a/app/assets/javascripts/activities.js.coffee b/app/assets/javascripts/activities.js.coffee new file mode 100644 index 00000000000..fdefbfb92bd --- /dev/null +++ b/app/assets/javascripts/activities.js.coffee @@ -0,0 +1,31 @@ +class Activities + constructor: -> + Pager.init 20, true + $(".event_filter_link").bind "click", (event) => + event.preventDefault() + @toggleFilter($(event.currentTarget)) + @reloadActivities() + + reloadActivities: -> + $(".content_list").html '' + Pager.init 20, true + + + toggleFilter: (sender) -> + sender.parent().toggleClass "inactive" + event_filters = $.cookie("event_filter") + filter = sender.attr("id").split("_")[0] + if event_filters + event_filters = event_filters.split(",") + else + event_filters = new Array() + + index = event_filters.indexOf(filter) + if index is -1 + event_filters.push filter + else + event_filters.splice index, 1 + + $.cookie "event_filter", event_filters.join(","), { path: '/' } + +@Activities = Activities diff --git a/app/assets/javascripts/dashboard.js.coffee b/app/assets/javascripts/dashboard.js.coffee index 4871936d5b2..d2bd9e7362b 100644 --- a/app/assets/javascripts/dashboard.js.coffee +++ b/app/assets/javascripts/dashboard.js.coffee @@ -1,13 +1,7 @@ class Dashboard constructor: -> - Pager.init 20, true @initSidebarTab() - $(".event_filter_link").bind "click", (event) => - event.preventDefault() - @toggleFilter($(event.currentTarget)) - @reloadActivities() - $(".dash-filter").keyup -> terms = $(this).val() uiBox = $(this).parents('.ui-box').first() @@ -24,27 +18,6 @@ class Dashboard - reloadActivities: -> - $(".content_list").html '' - Pager.init 20, true - - toggleFilter: (sender) -> - sender.parent().toggleClass "inactive" - event_filters = $.cookie("event_filter") - filter = sender.attr("id").split("_")[0] - if event_filters - event_filters = event_filters.split(",") - else - event_filters = new Array() - - index = event_filters.indexOf(filter) - if index is -1 - event_filters.push filter - else - event_filters.splice index, 1 - - $.cookie "event_filter", event_filters.join(","), { path: '/' } - initSidebarTab: -> key = "dashboard_sidebar_filter" diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee index b0b947dd476..c8ddbed5097 100644 --- a/app/assets/javascripts/dispatcher.js.coffee +++ b/app/assets/javascripts/dispatcher.js.coffee @@ -20,10 +20,11 @@ class Dispatcher Issues.init() when 'dashboard:show' new Dashboard() + new Activities() when 'projects:commit:show' new Commit() when 'groups:show', 'projects:show' - Pager.init(20, true) + new Activities() when 'projects:new', 'projects:edit' new Project() when 'projects:walls:show' diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 724122d4b93..b93bf0f98eb 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -155,4 +155,9 @@ class ApplicationController < ActionController::Base redirect_to new_profile_password_path and return end end + + def event_filter + filters = cookies['event_filter'].split(',') if cookies['event_filter'].present? + @event_filter ||= EventFilter.new(filters) + end end diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index f6620b25818..23da2c274dc 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -66,9 +66,4 @@ class DashboardController < ApplicationController def load_projects @projects = current_user.authorized_projects.sorted_by_activity end - - def event_filter - filters = cookies['event_filter'].split(',') if cookies['event_filter'].present? - @event_filter ||= EventFilter.new(filters) - end end diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 60fc3f6b551..3378675692a 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -31,7 +31,9 @@ class GroupsController < ApplicationController end def show - @events = Event.in_projects(project_ids).limit(20).offset(params[:offset] || 0) + @events = Event.in_projects(project_ids) + @events = event_filter.apply_filter(@events) + @events = @events.limit(20).offset(params[:offset] || 0) @last_push = current_user.recent_push respond_to do |format| diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 9b4fe5a9b5b..23b54ec44a8 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -55,7 +55,10 @@ class ProjectsController < Projects::ApplicationController def show limit = (params[:limit] || 20).to_i - @events = @project.events.recent.limit(limit).offset(params[:offset] || 0) + + @events = @project.events.recent + @events = event_filter.apply_filter(@events) + @events = @events.limit(limit).offset(params[:offset] || 0) # Ensure project default branch is set if it possible # Normally it defined on push or during creation diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb index 3db010966c5..3c637404c4f 100644 --- a/app/helpers/events_helper.rb +++ b/app/helpers/events_helper.rb @@ -28,7 +28,7 @@ module EventsHelper end content_tag :div, class: "filter_icon #{inactive}" do - link_to dashboard_path, class: 'has_tooltip event_filter_link', id: "#{key}_event_filter", 'data-original-title' => tooltip do + link_to request.path, class: 'has_tooltip event_filter_link', id: "#{key}_event_filter", 'data-original-title' => tooltip do content_tag :i, nil, class: icon_for_event[key] end end diff --git a/app/views/dashboard/_activities.html.haml b/app/views/dashboard/_activities.html.haml index 2b7d23c225d..89117726317 100644 --- a/app/views/dashboard/_activities.html.haml +++ b/app/views/dashboard/_activities.html.haml @@ -1,10 +1,5 @@ = render "events/event_last_push", event: @last_push - -.event_filter - = event_filter_link EventFilter.push, 'Push events' - = event_filter_link EventFilter.merged, 'Merge events' - = event_filter_link EventFilter.comments, 'Comments' - = event_filter_link EventFilter.team, 'Team' += render 'shared/event_filter' - if @events.any? .content_list diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml index 8afc4ab4a12..e613ed3eaa3 100644 --- a/app/views/groups/show.html.haml +++ b/app/views/groups/show.html.haml @@ -6,6 +6,7 @@   %span.cgray You will only see events from projects in this group %hr + = render 'shared/event_filter' - if @events.any? .content_list - else diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index 8a3427f3980..06ca5169dff 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -3,6 +3,7 @@ .row .span9 = render "events/event_last_push", event: @last_push + = render 'shared/event_filter' .content_list .loading.hide .span3 diff --git a/app/views/shared/_event_filter.html.haml b/app/views/shared/_event_filter.html.haml new file mode 100644 index 00000000000..ee0b57fbe5a --- /dev/null +++ b/app/views/shared/_event_filter.html.haml @@ -0,0 +1,5 @@ +.event_filter + = event_filter_link EventFilter.push, 'Push events' + = event_filter_link EventFilter.merged, 'Merge events' + = event_filter_link EventFilter.comments, 'Comments' + = event_filter_link EventFilter.team, 'Team' -- GitLab From 01c8aae8f25555788049fd3537cb3251bcb5801a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Aug 2013 16:46:03 +0300 Subject: [PATCH 063/175] Add br for new sentense in Compare view --- app/views/projects/compare/_form.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/projects/compare/_form.html.haml b/app/views/projects/compare/_form.html.haml index 6fb7b1fd3dd..503b39c0663 100644 --- a/app/views/projects/compare/_form.html.haml +++ b/app/views/projects/compare/_form.html.haml @@ -6,9 +6,9 @@ or branch/tag name like %code.label-branch master and press compare button for the commits list and a code diff. + %br Changes are shown from the version in the first field to the version in the second field. - %br = form_tag project_compare_index_path(@project), method: :post do .clearfix @@ -35,4 +35,4 @@ minLength: 1 }); - disableButtonIfEmptyField('#to', '.commits-compare-btn'); \ No newline at end of file + disableButtonIfEmptyField('#to', '.commits-compare-btn'); -- GitLab From c4bf88f96f31b0ff73939702b137f79383d28d1d Mon Sep 17 00:00:00 2001 From: Axilleas Pipinellis Date: Mon, 26 Aug 2013 10:09:53 +0300 Subject: [PATCH 064/175] Clear redis cache and precompile assets during update to 6.0. Fix #4874 #4840 As a consequence on the namespaces change from 5.4 to 6.0, after upgrade lots of links on the dashboard were not working (pointing to projects without the group part on the url). Also, after upgrading to 6.0-stable, the network (branch history) function does not work. The progress bar rotates forever, but the network graph cannot be generated. Clearing redis cache fixes those issues. --- doc/update/5.4-to-6.0.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/doc/update/5.4-to-6.0.md b/doc/update/5.4-to-6.0.md index 7fe57a8ff3f..0869dd833f9 100644 --- a/doc/update/5.4-to-6.0.md +++ b/doc/update/5.4-to-6.0.md @@ -4,7 +4,7 @@ #### Global projects -We deprecated root(global) namespace for projects. +We deprecated root(global) namespace for projects. So you need to move all your global projects under group/users manually before update or they will be automatically moved to the owner namespace during the update. #### Teams @@ -62,7 +62,7 @@ cd /home/git/gitlab # MySQL sudo -u git -H bundle install --without development test postgres --deployment -#PostgreSQL +# PostgreSQL sudo -u git -H bundle install --without development test mysql --deployment sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production @@ -71,8 +71,12 @@ sudo -u git -H bundle exec rake migrate_global_projects RAILS_ENV=production sudo -u git -H bundle exec rake migrate_keys RAILS_ENV=production sudo -u git -H bundle exec rake migrate_inline_notes RAILS_ENV=production -sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production +# Clear redis cache +sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production +# Clear and precompile assets +sudo -u git -H bundle exec rake assets:clean RAILS_ENV=production +sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production ``` ### 6. Update config files -- GitLab From a7bd18f9f2d684a2b37208e3ebd26d763bbc1ef3 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Aug 2013 20:58:34 +0300 Subject: [PATCH 065/175] Fix mailer tests --- spec/mailers/notify_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index 7d6647e0983..2f0475e5f02 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -320,7 +320,7 @@ describe Notify do it_behaves_like 'a note email' it 'has the correct subject' do - should have_subject /note for merge request !#{merge_request.id}/ + should have_subject /note for merge request !#{merge_request.iid}/ end it 'contains a link to the merge request note' do @@ -338,7 +338,7 @@ describe Notify do it_behaves_like 'a note email' it 'has the correct subject' do - should have_subject /note for issue ##{issue.id}/ + should have_subject /note for issue ##{issue.iid}/ end it 'contains a link to the issue note' do -- GitLab From 0787726ae7b1692e019ca9d209f5a99ba6e9f294 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Aug 2013 21:13:54 +0300 Subject: [PATCH 066/175] Set correct header border-bottom color for themes --- app/assets/stylesheets/themes/ui_color.scss | 1 + app/assets/stylesheets/themes/ui_gray.scss | 1 + app/assets/stylesheets/themes/ui_modern.scss | 1 + 3 files changed, 3 insertions(+) diff --git a/app/assets/stylesheets/themes/ui_color.scss b/app/assets/stylesheets/themes/ui_color.scss index 07e854b73d8..1fd54ff18a6 100644 --- a/app/assets/stylesheets/themes/ui_color.scss +++ b/app/assets/stylesheets/themes/ui_color.scss @@ -17,6 +17,7 @@ &.navbar-gitlab { .navbar-inner { background: #547; + border-bottom: 1px solid #435; .app_logo { &:hover { background-color: #435; diff --git a/app/assets/stylesheets/themes/ui_gray.scss b/app/assets/stylesheets/themes/ui_gray.scss index 4f88c631e4d..41c08c840e2 100644 --- a/app/assets/stylesheets/themes/ui_gray.scss +++ b/app/assets/stylesheets/themes/ui_gray.scss @@ -17,6 +17,7 @@ &.navbar-gitlab { .navbar-inner { background: #373737; + border-bottom: 1px solid #272727; .app_logo { &:hover { background-color: #272727; diff --git a/app/assets/stylesheets/themes/ui_modern.scss b/app/assets/stylesheets/themes/ui_modern.scss index 68318f93016..6173757082e 100644 --- a/app/assets/stylesheets/themes/ui_modern.scss +++ b/app/assets/stylesheets/themes/ui_modern.scss @@ -17,6 +17,7 @@ &.navbar-gitlab { .navbar-inner { background: #345; + border-bottom: 1px solid #234; .app_logo { &:hover { background-color: #234; -- GitLab From bb01b4f131a273e0d1da78bd1fd1936ff151458b Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Mon, 26 Aug 2013 20:59:15 +0200 Subject: [PATCH 067/175] Warning about issue numbers. --- doc/update/6.0-to-6.1.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/doc/update/6.0-to-6.1.md b/doc/update/6.0-to-6.1.md index 0ee92252b2c..c9a3a31fd27 100644 --- a/doc/update/6.0-to-6.1.md +++ b/doc/update/6.0-to-6.1.md @@ -1,7 +1,13 @@ # From 6.0 to 6.1 -# In 6.1 we removed a lot of deprecated stuff. -# So you should update to 6.0 before continue +# In 6.1 we remove a lot of deprecated code. +# You should update to 6.0 before installing 6.1 so all the necessary conversions are run. + +### Deprecations + +#### Global issue numbers + +In 6.1 issue numbers are project specific. This means all issues are renumbered and get a new number in their url. If you use an old issue number url and the issue number does not exist yet you are redirected to the new one. This conversion does not trigger if the old number already exists for this project, this is unlikely but will happen with old issues and large projects. ### 0. Backup -- GitLab From 45280499b8d0135ad7a2d088e24bae1eddd7eb74 Mon Sep 17 00:00:00 2001 From: Andrew Austin Date: Tue, 27 Aug 2013 01:54:09 +0000 Subject: [PATCH 068/175] Fix project_id field in MergeRequest API --- lib/api/entities.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/api/entities.rb b/lib/api/entities.rb index c8531e80af1..f15ca35e954 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -107,7 +107,8 @@ module API end class MergeRequest < Grape::Entity - expose :id, :target_branch, :source_branch, :project_id, :title, :state + expose :id, :target_branch, :source_branch, :title, :state + expose :target_project_id, as: :project_id expose :author, :assignee, using: Entities::UserBasic end -- GitLab From 65455278535f9af769b6faa1ec9085737c2ff352 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 Aug 2013 12:01:45 +0300 Subject: [PATCH 069/175] Improve user block logic When block user - remove it from joined groups Dont remove user from own resources (groups, users) --- app/models/user.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/models/user.rb b/app/models/user.rb index 071f6f30f5a..e2c1580ffcf 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -126,6 +126,17 @@ class User < ActiveRecord::Base after_transition any => :blocked do |user, transition| # Remove user from all projects and user.users_projects.find_each do |membership| + # skip owned resources + next if membership.project.owner == user + + return false unless membership.destroy + end + + # Remove user from all groups + user.users_groups.find_each do |membership| + # skip owned resources + next if membership.group.owner == user + return false unless membership.destroy end end -- GitLab From a2a7c8093b7fb2966a40c6c6be45c4dd52683ab4 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 Aug 2013 12:18:53 +0300 Subject: [PATCH 070/175] Use flash message for notification across app --- app/assets/javascripts/flash.js.coffee | 15 +++++++++++++++ app/assets/javascripts/profile.js.coffee | 8 ++------ app/assets/stylesheets/sections/profile.scss | 6 ------ app/assets/stylesheets/sections/themes.scss | 7 ------- app/views/profiles/design.html.haml | 6 ------ app/views/profiles/notifications/show.html.haml | 9 --------- app/views/profiles/notifications/update.js.haml | 4 ++-- 7 files changed, 19 insertions(+), 36 deletions(-) create mode 100644 app/assets/javascripts/flash.js.coffee diff --git a/app/assets/javascripts/flash.js.coffee b/app/assets/javascripts/flash.js.coffee new file mode 100644 index 00000000000..f8b7789884f --- /dev/null +++ b/app/assets/javascripts/flash.js.coffee @@ -0,0 +1,15 @@ +class Flash + constructor: (message, type)-> + flash = $(".flash-container") + flash.html("") + + $('
    ', + class: "flash-#{type}", + text: message + ).appendTo(".flash-container") + + flash.click -> $(@).fadeOut() + flash.show() + setTimeout (-> flash.fadeOut()), 5000 + +@Flash = Flash diff --git a/app/assets/javascripts/profile.js.coffee b/app/assets/javascripts/profile.js.coffee index 213133bc965..e7974611cbe 100644 --- a/app/assets/javascripts/profile.js.coffee +++ b/app/assets/javascripts/profile.js.coffee @@ -1,13 +1,9 @@ $ -> $('.edit_user .application-theme input, .edit_user .code-preview-theme input').click -> - # Hide any previous submission feedback - $('.edit_user .update-feedback').hide() - # Submit the form $('.edit_user').submit() - # Go up the hierarchy and show the corresponding submission feedback element - $(@).closest('fieldset').find('.update-feedback').show('highlight', {color: '#DFF0D8'}, 500) + new Flash("Appearance settings saved", "notice") $('.update-username form').on 'ajax:before', -> $('.loading-gif').show() @@ -17,6 +13,6 @@ $ -> $('.update-username form').on 'ajax:complete', -> $(this).find('.btn-save').enableButton() $(this).find('.loading-gif').hide() - + $('.update-notifications').on 'ajax:complete', -> $(this).find('.btn-save').enableButton() diff --git a/app/assets/stylesheets/sections/profile.scss b/app/assets/stylesheets/sections/profile.scss index 06a4046f916..5c7516ce6f9 100644 --- a/app/assets/stylesheets/sections/profile.scss +++ b/app/assets/stylesheets/sections/profile.scss @@ -1,9 +1,3 @@ -.save-status-fixed { - position: fixed; - left: 20px; - bottom: 50px; -} - .update-notifications { margin-bottom: 0; label { diff --git a/app/assets/stylesheets/sections/themes.scss b/app/assets/stylesheets/sections/themes.scss index c5487f9f40c..cd1aa2b011a 100644 --- a/app/assets/stylesheets/sections/themes.scss +++ b/app/assets/stylesheets/sections/themes.scss @@ -1,10 +1,3 @@ -.application-theme, .code-preview-theme { - .update-feedback { - color: #468847; - float: right; - } -} - .themes_opts { padding-left: 20px; diff --git a/app/views/profiles/design.html.haml b/app/views/profiles/design.html.haml index 75f00ab10a2..0d8075b7d43 100644 --- a/app/views/profiles/design.html.haml +++ b/app/views/profiles/design.html.haml @@ -8,9 +8,6 @@ %fieldset.application-theme %legend Application theme - .update-feedback.hide - %i.icon-ok - Saved .themes_opts = label_tag do .prev.default @@ -42,9 +39,6 @@ %fieldset.code-preview-theme %legend Code preview theme - .update-feedback.hide - %i.icon-ok - Saved .code_highlight_opts - color_schemes.each do |color_scheme_id, color_scheme| = label_tag do diff --git a/app/views/profiles/notifications/show.html.haml b/app/views/profiles/notifications/show.html.haml index 356d5499f07..8353b2f5f23 100644 --- a/app/views/profiles/notifications/show.html.haml +++ b/app/views/profiles/notifications/show.html.haml @@ -56,12 +56,3 @@ - @users_projects.each do |users_project| - notification = Notification.new(users_project) = render 'settings', type: 'project', membership: users_project, notification: notification - - -.save-status-fixed - %span.update-success.cgreen.hide - %i.icon-ok - Saved - %span.update-failed.cred.hide - %i.icon-remove - Failed diff --git a/app/views/profiles/notifications/update.js.haml b/app/views/profiles/notifications/update.js.haml index 88e74d50671..84c6ab25599 100644 --- a/app/views/profiles/notifications/update.js.haml +++ b/app/views/profiles/notifications/update.js.haml @@ -1,6 +1,6 @@ - if @saved :plain - $('.save-status-fixed .update-success').showAndHide(); + new Flash("Notification settings saved", "notice") - else :plain - $('.save-status-fixed .update-failed').showAndHide(); + new Flash("Failed to save new settings", "alert") -- GitLab From dd19ce962828255579b107f81e0fb54ba067575f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 Aug 2013 12:34:54 +0300 Subject: [PATCH 071/175] Show amount of users and projects in Profile#groups --- app/views/profiles/groups/index.html.haml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/views/profiles/groups/index.html.haml b/app/views/profiles/groups/index.html.haml index d3ff233bf12..6fc27be5db4 100644 --- a/app/views/profiles/groups/index.html.haml +++ b/app/views/profiles/groups/index.html.haml @@ -29,7 +29,10 @@ = link_to group, class: 'group-name' do %strong= group.name - as #{user_group.human_access} + as + %strong #{user_group.human_access} + %div.light + #{pluralize(group.projects.count, "project")}, #{pluralize(group.users.count, "user")} = paginate @user_groups -- GitLab From 9fbbd6a68ec603de8fd32681d90f47aa98cbd289 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 Aug 2013 12:41:49 +0300 Subject: [PATCH 072/175] Return empty abilities if user is blocked --- app/models/ability.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/ability.rb b/app/models/ability.rb index 0b77564adc6..74f92fe7438 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -2,6 +2,7 @@ class Ability class << self def allowed(user, subject) return [] unless user.kind_of?(User) + return [] if user.blocked? case subject.class.name when "Project" then project_abilities(user, subject) -- GitLab From bbc916baeecfd848eba86dd71c83623a79512a68 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 Aug 2013 12:47:28 +0300 Subject: [PATCH 073/175] If user is owner of project it cant be removed from this project --- app/models/users_project.rb | 4 ++++ app/views/admin/projects/show.html.haml | 9 ++++++--- app/views/admin/users/show.html.haml | 9 ++++++--- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/app/models/users_project.rb b/app/models/users_project.rb index c435df2b442..6f147859a5c 100644 --- a/app/models/users_project.rb +++ b/app/models/users_project.rb @@ -110,4 +110,8 @@ class UsersProject < ActiveRecord::Base def access_field project_access end + + def owner? + project.owner == user + end end diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml index 800f91d2a86..72317bb8efe 100644 --- a/app/views/admin/projects/show.html.haml +++ b/app/views/admin/projects/show.html.haml @@ -102,6 +102,9 @@ %strong = link_to user.name, admin_user_path(user) .pull-right - %span.light= users_project.human_access - = link_to admin_project_member_path(@project, user), confirm: remove_from_project_team_message(@project, user), method: :delete, class: "btn btn-small btn-remove" do - %i.icon-remove + - if users_project.owner? + %span.light Owner + - else + %span.light= users_project.human_access + = link_to admin_project_member_path(@project, user), confirm: remove_from_project_team_message(@project, user), method: :delete, class: "btn btn-small btn-remove" do + %i.icon-remove diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml index d48660f0a9e..9b1718dc53d 100644 --- a/app/views/admin/users/show.html.haml +++ b/app/views/admin/users/show.html.haml @@ -90,6 +90,9 @@ - if tm .pull-right - %span.light= tm.human_access - = link_to admin_project_member_path(project, tm.user), confirm: remove_from_project_team_message(project, @user), method: :delete, class: "btn btn-small btn-remove" do - %i.icon-remove + - if tm.owner? + %span.light Owner + - else + %span.light= tm.human_access + = link_to admin_project_member_path(project, tm.user), confirm: remove_from_project_team_message(project, @user), method: :delete, class: "btn btn-small btn-remove" do + %i.icon-remove -- GitLab From 61d98601583b30928076eb7180d444854f0b4f0a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 Aug 2013 12:59:44 +0300 Subject: [PATCH 074/175] Remove team mentions --- app/views/groups/edit.html.haml | 2 +- app/views/projects/_clone_panel.html.haml | 4 ++-- app/views/projects/team_members/_form.html.haml | 6 +++--- app/views/projects/team_members/index.html.haml | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml index fe66f89626f..8aefdf7f513 100644 --- a/app/views/groups/edit.html.haml +++ b/app/views/groups/edit.html.haml @@ -59,7 +59,7 @@ = private_icon = link_to project.name_with_namespace, project .pull-right - = link_to 'Team', project_team_index_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small" + = link_to 'Members', project_team_index_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small" = link_to 'Edit', edit_project_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small" = link_to 'Remove', project, confirm: remove_project_message(project), method: :delete, class: "btn btn-small btn-remove" - if @group.projects.blank? diff --git a/app/views/projects/_clone_panel.html.haml b/app/views/projects/_clone_panel.html.haml index 4aee2b16bdb..f7889b8eb05 100644 --- a/app/views/projects/_clone_panel.html.haml +++ b/app/views/projects/_clone_panel.html.haml @@ -40,5 +40,5 @@ - if can?(current_user, :admin_team_member, @project) %li.divider %li - = link_to new_project_team_member_path(@project), title: "New Team member" do - Team member + = link_to new_project_team_member_path(@project), title: "New project member" do + Project member diff --git a/app/views/projects/team_members/_form.html.haml b/app/views/projects/team_members/_form.html.haml index f96fa217fa3..5214a54e909 100644 --- a/app/views/projects/team_members/_form.html.haml +++ b/app/views/projects/team_members/_form.html.haml @@ -1,5 +1,5 @@ %h3.page-title - = "New Team member(s)" + = "New project member(s)" = form_for @user_project_relation, as: :team_member, url: project_team_members_path(@project) do |f| -if @user_project_relation.errors.any? @@ -8,13 +8,13 @@ - @user_project_relation.errors.full_messages.each do |msg| %li= msg - %h6 1. Choose people you want in the team + %p 1. Choose people you want in the project .control-group = f.label :user_ids, "People" .controls = users_select_tag(:user_ids, multiple: true) - %h6 2. Set access level for them + %p 2. Set access level for them .control-group = f.label :project_access, "Project Access" .controls= select_tag :project_access, options_for_select(Gitlab::Access.options, @user_project_relation.project_access), class: "project-access-select chosen" diff --git a/app/views/projects/team_members/index.html.haml b/app/views/projects/team_members/index.html.haml index 88325587f44..acbe82919f1 100644 --- a/app/views/projects/team_members/index.html.haml +++ b/app/views/projects/team_members/index.html.haml @@ -3,9 +3,9 @@ - if can? current_user, :admin_team_member, @project %span.pull-right - = link_to new_project_team_member_path(@project), class: "btn btn-new grouped", title: "New Team Member" do - New Team Member - = link_to import_project_team_members_path(@project), class: "btn grouped", title: "Import team from another project" do + = link_to new_project_team_member_path(@project), class: "btn btn-new grouped", title: "New project member" do + New project member + = link_to import_project_team_members_path(@project), class: "btn grouped", title: "Import members from another project" do Import members %p.light -- GitLab From 449edae5aba573943fa048a45d1a78cda9fb13f8 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 Aug 2013 13:11:05 +0300 Subject: [PATCH 075/175] Minor UI improvements --- app/views/dashboard/_groups.html.haml | 4 ++-- app/views/dashboard/_projects.html.haml | 4 ++-- app/views/layouts/_head_panel.html.haml | 4 ++-- app/views/users/show.html.haml | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/views/dashboard/_groups.html.haml b/app/views/dashboard/_groups.html.haml index 9aca7b353f3..8b32c5642bb 100644 --- a/app/views/dashboard/_groups.html.haml +++ b/app/views/dashboard/_groups.html.haml @@ -3,9 +3,9 @@ = search_field_tag :filter_group, nil, placeholder: 'Filter by name', class: 'dash-filter' - if current_user.can_create_group? %span.pull-right - = link_to new_group_path, class: "btn" do + = link_to new_group_path, class: "btn btn-new" do %i.icon-plus - New Group + New group %ul.well-list.dash-list - groups.each do |group| %li.group-row diff --git a/app/views/dashboard/_projects.html.haml b/app/views/dashboard/_projects.html.haml index 305b83771a1..90b843de016 100644 --- a/app/views/dashboard/_projects.html.haml +++ b/app/views/dashboard/_projects.html.haml @@ -3,9 +3,9 @@ = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'dash-filter' - if current_user.can_create_project? %span.pull-right - = link_to new_project_path, class: "btn" do + = link_to new_project_path, class: "btn btn-new" do %i.icon-plus - New Project + New project %ul.well-list.dash-list - projects.each do |project| diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml index 5644c89016b..6492c122ba0 100644 --- a/app/views/layouts/_head_panel.html.haml +++ b/app/views/layouts/_head_panel.html.haml @@ -27,10 +27,10 @@ %i.icon-cogs - if current_user.can_create_project? %li - = link_to new_project_path, title: "Create New Project", class: 'has_bottom_tooltip', 'data-original-title' => 'New project' do + = link_to new_project_path, title: "New project", class: 'has_bottom_tooltip', 'data-original-title' => 'New project' do %i.icon-plus %li - = link_to profile_path, title: "My Profile", class: 'has_bottom_tooltip', 'data-original-title' => 'Your profile' do + = link_to profile_path, title: "My profile", class: 'has_bottom_tooltip', 'data-original-title' => 'My profile' do %i.icon-user %li = link_to destroy_user_session_path, class: "logout", method: :delete, title: "Logout", class: 'has_bottom_tooltip', 'data-original-title' => 'Logout' do diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index 284098b9b19..743ab0949a1 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -5,7 +5,7 @@ = @user.name - if @user == current_user .pull-right - = link_to profile_path, class: 'btn btn-small' do + = link_to profile_path, class: 'btn' do %i.icon-edit Edit Profile %br @@ -14,7 +14,7 @@ %small member since #{@user.created_at.stamp("Nov 12, 2031")} .clearfix %hr - %h5 User Activity: + %h4 User Activity: = render @events .span4 = render 'profile', user: @user -- GitLab From 95f032c4facf893879470328649892aea800fed4 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 Aug 2013 13:14:55 +0300 Subject: [PATCH 076/175] Fix spinach tests --- features/steps/profile/profile.rb | 2 +- features/steps/project/project_team_management.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/features/steps/profile/profile.rb b/features/steps/profile/profile.rb index 9cd4e470250..23eeac447b0 100644 --- a/features/steps/profile/profile.rb +++ b/features/steps/profile/profile.rb @@ -84,7 +84,7 @@ class Profile < Spinach::FeatureSteps end step "I should receive feedback that the changes were saved" do - page.should have_content("Saved") + page.should have_content("saved") end step 'my password is expired' do diff --git a/features/steps/project/project_team_management.rb b/features/steps/project/project_team_management.rb index 93ba1086f6e..efebba1be24 100644 --- a/features/steps/project/project_team_management.rb +++ b/features/steps/project/project_team_management.rb @@ -16,7 +16,7 @@ class ProjectTeamManagement < Spinach::FeatureSteps end Given 'I click link "New Team Member"' do - click_link "New Team Member" + click_link "New project member" end And 'I select "Mike" as "Reporter"' do @@ -90,7 +90,7 @@ class ProjectTeamManagement < Spinach::FeatureSteps end And 'I click link "Import team from another project"' do - click_link "Import team from another project" + click_link "Import members from another project" end When 'I submit "Website" project for import team' do -- GitLab From 8457415eb92f80bf485d40c41fafa02cd9377904 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 Aug 2013 13:20:36 +0300 Subject: [PATCH 077/175] Add links to create branch/tag from project home page --- app/views/projects/_clone_panel.html.haml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/views/projects/_clone_panel.html.haml b/app/views/projects/_clone_panel.html.haml index f7889b8eb05..7228c760d27 100644 --- a/app/views/projects/_clone_panel.html.haml +++ b/app/views/projects/_clone_panel.html.haml @@ -37,6 +37,17 @@ %li = link_to new_project_snippet_path(@project), title: "New Snippet" do Snippet + - if can? current_user, :push_code, @project + %li.divider + %li + = link_to new_project_branch_path(@project) do + %i.icon-code-fork + Git branch + %li + = link_to new_project_tag_path(@project) do + %i.icon-tag + Git tag + - if can?(current_user, :admin_team_member, @project) %li.divider %li -- GitLab From c2f104000615f1f68ca9be61825add098265053f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 Aug 2013 13:49:29 +0300 Subject: [PATCH 078/175] Few fixes to spinach tests --- app/views/groups/_projects.html.haml | 4 ++-- features/steps/dashboard/dashboard.rb | 2 +- features/steps/group/group.rb | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/views/groups/_projects.html.haml b/app/views/groups/_projects.html.haml index cbad2e3e522..16a3c60f660 100644 --- a/app/views/groups/_projects.html.haml +++ b/app/views/groups/_projects.html.haml @@ -3,9 +3,9 @@ Projects (#{projects.count}) - if can? current_user, :manage_group, @group %span.pull-right - = link_to new_project_path(namespace_id: @group.id), class: "btn" do + = link_to new_project_path(namespace_id: @group.id), class: "btn btn-new" do %i.icon-plus - New Project + New project %ul.well-list - if projects.blank? %p.nothing_here_message This groups has no projects yet diff --git a/features/steps/dashboard/dashboard.rb b/features/steps/dashboard/dashboard.rb index 596b5a78170..5baf4e757ac 100644 --- a/features/steps/dashboard/dashboard.rb +++ b/features/steps/dashboard/dashboard.rb @@ -4,7 +4,7 @@ class Dashboard < Spinach::FeatureSteps include SharedProject Then 'I should see "New Project" link' do - page.should have_link "New Project" + page.should have_link "New project" end Then 'I should see "Shop" project link' do diff --git a/features/steps/group/group.rb b/features/steps/group/group.rb index 6f18f6185f5..45dda6ff55e 100644 --- a/features/steps/group/group.rb +++ b/features/steps/group/group.rb @@ -67,7 +67,7 @@ class Groups < Spinach::FeatureSteps end When 'I click new group link' do - click_link "New Group" + click_link "New group" end And 'submit form with new group info' do -- GitLab From 79f0858a18081d37669883f1b5a32d033197561d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 Aug 2013 13:56:04 +0300 Subject: [PATCH 079/175] Services and hooks MUST BE executed on branch push! --- app/services/git_push_service.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index e774b2276e8..9584f420ab3 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -30,6 +30,9 @@ class GitPushService if push_to_existing_branch?(ref, oldrev) project.update_merge_requests(oldrev, newrev, ref, @user) process_commit_messages(ref) + end + + if push_to_branch?(ref) project.execute_hooks(@push_data.dup) project.execute_services(@push_data.dup) end @@ -175,6 +178,10 @@ class GitPushService ref_parts[1] =~ /heads/ && oldrev == "0000000000000000000000000000000000000000" end + def push_to_branch? ref + ref =~ /refs\/heads/ + end + def is_default_branch? ref ref == "refs/heads/#{project.default_branch}" end -- GitLab From df9e1db9040db43eecb9f2a449055a28adfc5707 Mon Sep 17 00:00:00 2001 From: Rovanion Date: Tue, 27 Aug 2013 13:30:06 +0200 Subject: [PATCH 080/175] Rewrote init script. --- CHANGELOG | 1 + lib/support/init.d/gitlab | 252 ++++++++++++++++++++++++++------------ 2 files changed, 175 insertions(+), 78 deletions(-) mode change 100644 => 100755 lib/support/init.d/gitlab diff --git a/CHANGELOG b/CHANGELOG index 7c3d7ba3502..33dee49f85d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,5 @@ v 6.1.0 + - Rewrite: Init script now less prone to errors and keeps better track of the service. - Link issues, merge requests, and commits when they reference each other with GFM - Close issues automatically when pushing commits with a special message diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab old mode 100644 new mode 100755 index 6f97643f9e0..bf405c18cf9 --- a/lib/support/init.d/gitlab +++ b/lib/support/init.d/gitlab @@ -1,7 +1,8 @@ -#! /bin/bash +#! /bin/sh # GITLAB # Maintainer: @randx +# Authors: rovanion.luckey@gmail.com, @randx # App Version: 6.0 ### BEGIN INIT INFO @@ -14,102 +15,198 @@ # Description: GitLab git repository management ### END INIT INFO +### Environment variables +RAILS_ENV="production" -APP_ROOT="/home/git/gitlab" -APP_USER="git" -DAEMON_OPTS="-c $APP_ROOT/config/unicorn.rb -E production" -PID_PATH="$APP_ROOT/tmp/pids" -SOCKET_PATH="$APP_ROOT/tmp/sockets" -WEB_SERVER_PID="$PID_PATH/unicorn.pid" -SIDEKIQ_PID="$PID_PATH/sidekiq.pid" -STOP_SIDEKIQ="RAILS_ENV=production bundle exec rake sidekiq:stop" -START_SIDEKIQ="RAILS_ENV=production bundle exec rake sidekiq:start" -NAME="gitlab" -DESC="GitLab service" - -check_pid(){ - if [ -f $WEB_SERVER_PID ]; then - PID=`cat $WEB_SERVER_PID` - SPID=`cat $SIDEKIQ_PID` - STATUS=`ps aux | grep $PID | grep -v grep | wc -l` +# Script variable names should be lower-case not to conflict with internal +# /bin/sh variables such as PATH, EDITOR or SHELL. +app_root="/home/gitlab/gitlab" +app_user="gitlab" +unicorn_conf="$app_root/config/unicorn.rb" +pid_path="$app_root/tmp/pids" +socket_path="$app_root/tmp/sockets" +web_server_pid_path="$pid_path/unicorn.pid" +sidekiq_pid_path="$pid_path/sidekiq.pid" + + + +### Here ends user configuration ### + + +# Switch to the app_user if it is not he/she who is running the script. +if [ "$USER" != "$app_user" ]; then + sudo -u "$app_user" -H /etc/init.d/gitlab "$@"; exit; +fi + +# Switch to the gitlab path, if it fails exit with an error. +if ! cd "$app_root" ; then + echo "Failed to cd into $app_root, exiting!"; exit 1 +fi + +### Init Script functions + +check_pids(){ + if ! mkdir -p "$pid_path"; then + echo "Could not create the path $pid_path needed to store the pids." + exit 1 + fi + # If there exists a file which should hold the value of the Unicorn pid: read it. + if [ -f "$web_server_pid_path" ]; then + wpid=$(cat "$web_server_pid_path") + else + wpid=0 + fi + if [ -f "$sidekiq_pid_path" ]; then + spid=$(cat "$sidekiq_pid_path") else - STATUS=0 - PID=0 + spid=0 fi } -execute() { - sudo -u $APP_USER -H bash -l -c "$1" +# We use the pids in so many parts of the script it makes sense to always check them. +# Only after start() is run should the pids change. Sidekiq sets it's own pid. +check_pids + + +# Checks wether the different parts of the server is already running or not. +check_status(){ + check_pids + # If the web server is running kill -0 $wpid returns true, or rather 0. + # Checks of *_status should only check for == 0 or != 0, never anything else. + if [ $wpid -ne 0 ]; then + kill -0 "$wpid" 2>/dev/null + web_status="$?" + fi + if [ $spid -ne 0 ]; then + kill -0 "$spid" 2>/dev/null + sidekiq_status="$?" + fi } +# Check for stale pids and remove them if necessary +check_stale_pids(){ + check_status + # If there is a pid it is something else than 0, the service is running if + # *_status is == 0. + if [ "$wpid" != "0" -a "$web_status" != "0" ]; then + echo "Found stale Unicorn web server pid, removing. This is most likely caused by the web server crashing the last time it ran." + rm "$web_server_pid_path" + fi + if [ "$spid" != "0" -a "$sidekiq_status" != "0" ]; then + echo "Found stale Sidekiq web server pid, removing. This is most likely caused by the Sidekiq crashing the last time it ran." + rm "$sidekiq_pid_path" + fi +} + +# If no parts of the service is running, bail out. +check_not_running(){ + check_stale_pids + if [ "$web_status" != "0" -a "$sidekiq_status" != "0" ]; then + echo "GitLab is not running." + exit + fi +} + +# Starts Unicorn and Sidekiq. start() { - cd $APP_ROOT - check_pid - if [ "$PID" -ne 0 -a "$STATUS" -ne 0 ]; then - # Program is running, exit with error code 1. - echo "Error! $DESC $NAME is currently running!" - exit 1 + check_stale_pids + + # Then check if the service is running. If it is: don't start again. + if [ "$web_status" = "0" ]; then + echo "The Unicorn web server already running with pid $wpid, not restarting." else - if [ `whoami` = root ]; then - execute "rm -f $SOCKET_PATH/gitlab.socket" - execute "RAILS_ENV=production bundle exec unicorn_rails $DAEMON_OPTS > /dev/null 2>&1 &" - execute "mkdir -p $PID_PATH && $START_SIDEKIQ > /dev/null 2>&1 &" - echo "$DESC started" - fi + echo "Starting the GitLab Unicorn web server..." + # Remove old socket if it exists + rm -f "$socket_path"/gitlab.socket + # Start the webserver + bundle exec unicorn_rails -D -c "$unicorn_conf" -E "$RAILS_ENV" fi -} -stop() { - cd $APP_ROOT - check_pid - if [ "$PID" -ne 0 -a "$STATUS" -ne 0 ]; then - ## Program is running, stop it. - kill -QUIT `cat $WEB_SERVER_PID` - execute "mkdir -p $PID_PATH && $STOP_SIDEKIQ > /dev/null 2>&1 &" - rm "$WEB_SERVER_PID" >> /dev/null - echo "$DESC stopped" + # If sidekiq is already running, don't start it again. + if [ "$sidekiq_status" = "0" ]; then + echo "The Sidekiq job dispatcher is already running with pid $spid, not restarting" else - ## Program is not running, exit with error. - echo "Error! $DESC not started!" - exit 1 + echo "Starting the GitLab Sidekiq event dispatcher..." + RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:start + # We are sleeping a bit here because sidekiq is slow at writing it's pid + sleep 2 fi + + # Finally check the status to tell wether or not GitLab is running + status } -restart() { - cd $APP_ROOT - check_pid - if [ "$PID" -ne 0 -a "$STATUS" -ne 0 ]; then - echo "Restarting $DESC..." - kill -USR2 `cat $WEB_SERVER_PID` - execute "mkdir -p $PID_PATH && $STOP_SIDEKIQ > /dev/null 2>&1" - if [ `whoami` = root ]; then - execute "mkdir -p $PID_PATH && $START_SIDEKIQ > /dev/null 2>&1 &" - fi - echo "$DESC restarted." +# Asks the Unicorn and the Sidekiq if they would be so kind as to stop, if not kills them. +stop() { + check_not_running + # If the Unicorn web server is running, tell it to stop; + if [ "$web_status" = "0" ]; then + kill -QUIT "$wpid" & + echo "Stopping the GitLab Unicorn web server..." + stopping=true else - echo "Error, $NAME not running!" - exit 1 + echo "The Unicorn web was not running, doing nothing." + fi + # And do the same thing for the Sidekiq. + if [ "$sidekiq_status" = "0" ]; then + printf "Stopping Sidekiq job dispatcher." + RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:stop & + stopping=true + else + echo "The Sidekiq was not running, must have run out of breath." fi + + + # If something needs to be stopped, lets wait for it to stop. Never use SIGKILL in a script. + while [ "$stopping" = "true" ]; do + sleep 1 + check_status + if [ "$web_status" = "0" -o "$sidekiq_status" = "0" ]; then + printf "." + else + printf "\n" + break + fi + done + sleep 1 + # Cleaning up unused pids + rm "$web_server_pid_path" 2>/dev/null + # rm "$sidekiq_pid_path" # Sidekiq seems to be cleaning up it's own pid. + + status } +# Returns the status of GitLab and it's components status() { - cd $APP_ROOT - check_pid - if [ "$PID" -ne 0 -a "$STATUS" -ne 0 ]; then - echo "$DESC / Unicorn with PID $PID is running." - echo "$DESC / Sidekiq with PID $SPID is running." + check_not_running + if [ "$web_status" = "0" ]; then + echo "The GitLab Unicorn webserver with pid $wpid is running." else - echo "$DESC is not running." - exit 1 + printf "The GitLab Unicorn webserver is \033[31mnot running\033[0m.\n" + fi + if [ "$sidekiq_status" = "0" ]; then + echo "The GitLab Sidekiq job dispatcher with pid $spid is running." + else + printf "The GitLab Sidekiq job dispatcher is \033[31mnot running\033[0m.\n" + fi + if [ "$web_status" = "0" -a "$sidekiq_status" = "0" ]; then + printf "GitLab and all it's components are \033[32mup and running\033[0m.\n" fi } -## Check to see if we are running as root first. -## Found at http://www.cyberciti.biz/tips/shell-root-user-check-script.html -if [ "$(id -u)" != "0" ]; then - echo "This script must be run as root" +reload(){ + check_not_running + if [ "$wpid" = "0" ];then + echo "The GitLab Unicorn Web server is not running thus it's configuration can't be reloaded." exit 1 -fi + fi + printf "Reloading GitLab configuration... " + kill -HUP "$wpid" + echo "Done." +} + + +## Finally the input handling. case "$1" in start) @@ -119,20 +216,19 @@ case "$1" in stop ;; restart) - restart + stop + start ;; reload|force-reload) - echo -n "Reloading $NAME configuration: " - kill -HUP `cat $PID` - echo "done." + reload ;; status) status ;; *) - echo "Usage: sudo service gitlab {start|stop|restart|reload}" >&2 + echo "Usage: service gitlab {start|stop|restart|reload|status}" exit 1 ;; esac -exit 0 +exit \ No newline at end of file -- GitLab From 7c38f4e23784b3c141db254059b88cb1044bd946 Mon Sep 17 00:00:00 2001 From: Rovanion Date: Tue, 27 Aug 2013 15:04:20 +0200 Subject: [PATCH 081/175] Changes recommended by @axilleas --- lib/support/init.d/gitlab | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab index bf405c18cf9..65e036fe984 100755 --- a/lib/support/init.d/gitlab +++ b/lib/support/init.d/gitlab @@ -20,8 +20,8 @@ RAILS_ENV="production" # Script variable names should be lower-case not to conflict with internal # /bin/sh variables such as PATH, EDITOR or SHELL. -app_root="/home/gitlab/gitlab" -app_user="gitlab" +app_root="/home/git/gitlab" +app_user="git" unicorn_conf="$app_root/config/unicorn.rb" pid_path="$app_root/tmp/pids" socket_path="$app_root/tmp/sockets" @@ -68,7 +68,7 @@ check_pids(){ check_pids -# Checks wether the different parts of the server is already running or not. +# Checks whether the different parts of the service are already running or not. check_status(){ check_pids # If the web server is running kill -0 $wpid returns true, or rather 0. @@ -117,7 +117,7 @@ start() { else echo "Starting the GitLab Unicorn web server..." # Remove old socket if it exists - rm -f "$socket_path"/gitlab.socket + rm -f "$socket_path"/gitlab.socket 2>/dev/null # Start the webserver bundle exec unicorn_rails -D -c "$unicorn_conf" -E "$RAILS_ENV" fi @@ -231,4 +231,4 @@ case "$1" in ;; esac -exit \ No newline at end of file +exit -- GitLab From afdfbd1e8a5865ebb2494c7d55220248a4981b77 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 Aug 2013 13:44:58 +0300 Subject: [PATCH 082/175] Add description to user removal block. Transfer owned groups to admin before remove --- app/controllers/admin/users_controller.rb | 9 +++++++-- app/views/admin/users/show.html.haml | 21 ++++++++++++++++----- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 7703ae8b249..eeedc764078 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -83,9 +83,14 @@ class Admin::UsersController < Admin::ApplicationController end def destroy - if user.personal_projects.count > 0 - redirect_to admin_users_path, alert: "User is a project owner and can't be removed." and return + # 1. Move all user groups to admin + user.own_groups.each do |group| + group.owner_id = User.admins.first + group.save end + + # 2. Remove user with all authored contenst + # including personal projects user.destroy respond_to do |format| diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml index 9b1718dc53d..d1b882072e8 100644 --- a/app/views/admin/users/show.html.haml +++ b/app/views/admin/users/show.html.haml @@ -7,15 +7,14 @@ %span.cred (Admin) .pull-right - = link_to edit_admin_user_path(@user), class: "btn grouped btn-small" do + = link_to edit_admin_user_path(@user), class: "btn grouped" do %i.icon-edit Edit - unless @user == current_user - if @user.blocked? - = link_to 'Unblock', unblock_admin_user_path(@user), method: :put, class: "btn grouped btn-small success" + = link_to 'Unblock', unblock_admin_user_path(@user), method: :put, class: "btn grouped success" - else - = link_to 'Block', block_admin_user_path(@user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn grouped btn-small btn-remove" - = link_to 'Destroy', [:admin, @user], confirm: "USER #{@user.name} WILL BE REMOVED! Are you sure?", method: :delete, class: "btn grouped btn-small btn-remove" + = link_to 'Block', block_admin_user_path(@user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn grouped btn-remove" %hr .row @@ -63,6 +62,17 @@ %strong = link_to @user.created_by.name, [:admin, @user.created_by] + .alert.alert-error + %h4 Remove user + %br + %p Deleting a user has the following effects: + %ul + %li All user content like authored issues, snippets, comments will be removed + %li User personal projects will be removed and cannot be restored + %li Owned groups will be transfered to first admin + = link_to 'Remove user', [:admin, @user], confirm: "USER #{@user.name} WILL BE REMOVED! Are you sure?", method: :delete, class: "btn btn-remove" + + .span6 - if @user.users_groups.present? .ui-box .title Groups: @@ -74,7 +84,6 @@ .pull-right %span.light= user_group.human_access - .span6 .ui-box .title Projects (#{@projects.count}) %ul.well-list @@ -96,3 +105,5 @@ %span.light= tm.human_access = link_to admin_project_member_path(project, tm.user), confirm: remove_from_project_team_message(project, @user), method: :delete, class: "btn btn-small btn-remove" do %i.icon-remove + + -- GitLab From 24e26d8b7a4a2487600f273f7b1a6236691d2664 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 Aug 2013 20:40:42 +0300 Subject: [PATCH 083/175] Improve user block/removal from admin area Provide UI with explanation what happens when you block or remove user When remove user - remove all groups where user is an only owner --- app/controllers/admin/users_controller.rb | 10 ++---- app/models/group.rb | 2 +- app/models/user.rb | 8 ++++- app/views/admin/users/show.html.haml | 44 +++++++++++++++-------- 4 files changed, 41 insertions(+), 23 deletions(-) diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index eeedc764078..7809a157dbc 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -83,14 +83,10 @@ class Admin::UsersController < Admin::ApplicationController end def destroy - # 1. Move all user groups to admin - user.own_groups.each do |group| - group.owner_id = User.admins.first - group.save - end + # 1. Remove groups where user is the only owner + user.solo_owned_groups.map(&:destroy) - # 2. Remove user with all authored contenst - # including personal projects + # 2. Remove user with all authored content including personal projects user.destroy respond_to do |format| diff --git a/app/models/group.rb b/app/models/group.rb index 1c8eb98e0f2..fce8d71217b 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -23,7 +23,7 @@ class Group < Namespace end def owners - @owners ||= (users_groups.owners.map(&:user) << owner) + @owners ||= (users_groups.owners.map(&:user) << owner).uniq end def add_users(user_ids, group_access) diff --git a/app/models/user.rb b/app/models/user.rb index e2c1580ffcf..b44c063c32f 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -135,7 +135,7 @@ class User < ActiveRecord::Base # Remove user from all groups user.users_groups.find_each do |membership| # skip owned resources - next if membership.group.owner == user + next if membership.group.owners.include?(user) return false unless membership.destroy end @@ -376,4 +376,10 @@ class User < ActiveRecord::Base self.send("#{attr}=", Sanitize.clean(value)) if value.present? end end + + def solo_owned_groups + @solo_owned_groups ||= owned_groups.select do |group| + group.owners == [self] + end + end end diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml index d1b882072e8..bf41508d27b 100644 --- a/app/views/admin/users/show.html.haml +++ b/app/views/admin/users/show.html.haml @@ -10,11 +10,8 @@ = link_to edit_admin_user_path(@user), class: "btn grouped" do %i.icon-edit Edit - - unless @user == current_user - - if @user.blocked? - = link_to 'Unblock', unblock_admin_user_path(@user), method: :put, class: "btn grouped success" - - else - = link_to 'Block', block_admin_user_path(@user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn grouped btn-remove" + - if @user.blocked? + = link_to 'Unblock', unblock_admin_user_path(@user), method: :put, class: "btn grouped success" %hr .row @@ -62,15 +59,34 @@ %strong = link_to @user.created_by.name, [:admin, @user.created_by] - .alert.alert-error - %h4 Remove user - %br - %p Deleting a user has the following effects: - %ul - %li All user content like authored issues, snippets, comments will be removed - %li User personal projects will be removed and cannot be restored - %li Owned groups will be transfered to first admin - = link_to 'Remove user', [:admin, @user], confirm: "USER #{@user.name} WILL BE REMOVED! Are you sure?", method: :delete, class: "btn btn-remove" + - unless @user == current_user + .alert + %h4 Block user + %br + %p Blocking user has the following effects: + %ul + %li User will not be able to login + %li User will not be able to access git repositories + %li User will be removed from joined projects and groups + %li Personal projects will be left + %li Owned groups will be left + = link_to 'Block user', block_admin_user_path(@user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn btn-remove" + + .alert.alert-error + %h4 + Remove user + %br + %p Deleting a user has the following effects: + %ul + %li All user content like authored issues, snippets, comments will be removed + - rp = @user.personal_projects.count + - unless rp.zero? + %li #{pluralize rp, 'personal project'} will be removed and cannot be restored + - if @user.solo_owned_groups.present? + %li + Next groups with all content will be removed: + %strong #{@user.solo_owned_groups.map(&:name).join(', ')} + = link_to 'Remove user', [:admin, @user], confirm: "USER #{@user.name} WILL BE REMOVED! Are you sure?", method: :delete, class: "btn btn-remove" .span6 - if @user.users_groups.present? -- GitLab From 643a6e5824cc8ffb6b58288b7822f42d13476c8f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 Aug 2013 21:35:41 +0300 Subject: [PATCH 084/175] Improve admin user show page Show permissions for all project. Add ability to remove user from group if not an owner Remove unnecessary admin controller --- app/assets/javascripts/admin.js.coffee | 8 +++++++- app/controllers/admin/members_controller.rb | 9 --------- app/models/project_team.rb | 10 +++++++++- app/views/admin/users/show.html.haml | 13 +++++++++---- config/routes.rb | 6 +----- lib/gitlab/access.rb | 4 ++++ 6 files changed, 30 insertions(+), 20 deletions(-) delete mode 100644 app/controllers/admin/members_controller.rb diff --git a/app/assets/javascripts/admin.js.coffee b/app/assets/javascripts/admin.js.coffee index f75008e2b60..6230fe7f93f 100644 --- a/app/assets/javascripts/admin.js.coffee +++ b/app/assets/javascripts/admin.js.coffee @@ -23,10 +23,16 @@ class Admin e.preventDefault() $(this).hide() modal.show() - + $('.change-owner-cancel-link').bind "click", (e) -> e.preventDefault() modal.hide() $('.change-owner-link').show() + $('li.users_project').bind 'ajax:success', -> + Turbolinks.visit(location.href) + + $('li.users_group').bind 'ajax:success', -> + Turbolinks.visit(location.href) + @Admin = Admin diff --git a/app/controllers/admin/members_controller.rb b/app/controllers/admin/members_controller.rb deleted file mode 100644 index d9201930501..00000000000 --- a/app/controllers/admin/members_controller.rb +++ /dev/null @@ -1,9 +0,0 @@ -class Admin::MembersController < Admin::ApplicationController - def destroy - user = User.find_by_username(params[:id]) - project = Project.find_with_namespace(params[:project_id]) - project.users_projects.where(user_id: user).first.destroy - - redirect_to :back - end -end diff --git a/app/models/project_team.rb b/app/models/project_team.rb index c797c36882f..bc35c4041ba 100644 --- a/app/models/project_team.rb +++ b/app/models/project_team.rb @@ -32,7 +32,15 @@ class ProjectTeam end def find_tm(user_id) - project.users_projects.find_by_user_id(user_id) + tm = project.users_projects.find_by_user_id(user_id) + + # If user is not in project members + # we should check for group membership + if group && !tm + tm = group.users_groups.find_by_user_id(user_id) + end + + tm end def add_user(user, access) diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml index bf41508d27b..95257a4594e 100644 --- a/app/views/admin/users/show.html.haml +++ b/app/views/admin/users/show.html.haml @@ -95,17 +95,20 @@ %ul.well-list - @user.users_groups.each do |user_group| - group = user_group.group - %li + %li.users_group %strong= link_to group.name, admin_group_path(group) .pull-right %span.light= user_group.human_access + - unless user_group.owner? + = link_to group_users_group_path(group, user_group), confirm: remove_user_from_group_message(group, @user), method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do + %i.icon-remove.icon-white .ui-box .title Projects (#{@projects.count}) %ul.well-list - @projects.sort_by(&:name_with_namespace).each do |project| - tm = project.team.find_tm(@user.id) - %li + %li.users_project = link_to admin_project_path(project), class: dom_class(project) do - if project.namespace = project.namespace.human_name @@ -119,7 +122,9 @@ %span.light Owner - else %span.light= tm.human_access - = link_to admin_project_member_path(project, tm.user), confirm: remove_from_project_team_message(project, @user), method: :delete, class: "btn btn-small btn-remove" do - %i.icon-remove + + - if tm.respond_to? :project + = link_to project_team_member_path(project, @user), confirm: remove_from_project_team_message(project, @user), remote: true, method: :delete, class: "btn-tiny btn btn-remove", title: 'Remove user from project' do + %i.icon-remove diff --git a/config/routes.rb b/config/routes.rb index 5cf47f9ac5e..d0e29a5ab96 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -89,11 +89,7 @@ Gitlab::Application.routes.draw do resource :logs, only: [:show] resource :background_jobs, controller: 'background_jobs', only: [:show] - - resources :projects, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ }, only: [:index, :show] do - resources :members, only: [:destroy] - end - + resources :projects, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ }, only: [:index, :show] root to: "dashboard#index" end diff --git a/lib/gitlab/access.rb b/lib/gitlab/access.rb index fa273f3f50a..87f9cfab608 100644 --- a/lib/gitlab/access.rb +++ b/lib/gitlab/access.rb @@ -44,5 +44,9 @@ module Gitlab def human_access Gitlab::Access.options_with_owner.key(access_field) end + + def owner? + access_field == OWNER + end end end -- GitLab From eb4272e2f57683c4be6a064c8e1675513e4a908a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 Aug 2013 22:00:41 +0300 Subject: [PATCH 085/175] Remove old specs --- spec/routing/admin_routing_spec.rb | 7 ------- 1 file changed, 7 deletions(-) diff --git a/spec/routing/admin_routing_spec.rb b/spec/routing/admin_routing_spec.rb index bd76148043c..7fe18ff47c3 100644 --- a/spec/routing/admin_routing_spec.rb +++ b/spec/routing/admin_routing_spec.rb @@ -75,13 +75,6 @@ describe Admin::ProjectsController, "routing" do end end -# DELETE /admin/projects/:project_id/members/:id(.:format) admin/projects/members#destroy {id: /[^\/]+/, project_id: /[^\/]+/} -describe Admin::MembersController, "routing" do - it "to #destroy" do - delete("/admin/projects/test/members/1").should route_to('admin/members#destroy', project_id: 'test', id: '1') - end -end - # admin_hook_test GET /admin/hooks/:hook_id/test(.:format) admin/hooks#test # admin_hooks GET /admin/hooks(.:format) admin/hooks#index # POST /admin/hooks(.:format) admin/hooks#create -- GitLab From 777456b29ccf69774048061bb0aac91e4406fef8 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 28 Aug 2013 00:04:04 +0300 Subject: [PATCH 086/175] fix tests --- spec/services/git_push_service_spec.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index ffd80f33fc8..1f6ee818a42 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -91,19 +91,20 @@ describe GitPushService do end end - context "does not execute web hooks" do + context "execute web hooks" do before do @project_hook = create(:project_hook) project.hooks << [@project_hook] + stub_request(:post, @project_hook.url) end it "when pushing a branch for the first time" do - @project_hook.should_not_receive(:execute) + @project_hook.should_receive(:async_execute) service.execute(project, user, @blankrev, 'newrev', 'refs/heads/master') end it "when pushing tags" do - @project_hook.should_not_receive(:execute) + @project_hook.should_not_receive(:async_execute) service.execute(project, user, 'newrev', 'newrev', 'refs/tags/v1.0.0') end end -- GitLab From 4994ebbb11d701a5831edce2ca450d0c1011c99e Mon Sep 17 00:00:00 2001 From: James Newton Date: Tue, 27 Aug 2013 16:15:32 -0500 Subject: [PATCH 087/175] update gitlab:check to look for update hook, not post-receive --- lib/tasks/gitlab/check.rake | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index be679dcd97e..74b3e7787e6 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -374,8 +374,8 @@ namespace :gitlab do check_repo_base_is_not_symlink check_repo_base_user_and_group check_repo_base_permissions - check_post_receive_hook_is_up_to_date - check_repos_post_receive_hooks_is_link + check_update_hook_is_up_to_date + check_repos_update_hooks_is_link finished_checking "GitLab Shell" end @@ -385,10 +385,10 @@ namespace :gitlab do ######################## - def check_post_receive_hook_is_up_to_date - print "post-receive hook up-to-date? ... " + def check_update_hook_is_up_to_date + print "update hook up-to-date? ... " - hook_file = "post-receive" + hook_file = "update" gitlab_shell_hooks_path = Gitlab.config.gitlab_shell.hooks_path gitlab_shell_hook_file = File.join(gitlab_shell_hooks_path, hook_file) gitlab_shell_ssh_user = Gitlab.config.gitlab_shell.ssh_user @@ -494,10 +494,10 @@ namespace :gitlab do end end - def check_repos_post_receive_hooks_is_link - print "post-receive hooks in repos are links: ... " + def check_repos_update_hooks_is_link + print "update hooks in repos are links: ... " - hook_file = "post-receive" + hook_file = "update" gitlab_shell_hooks_path = Gitlab.config.gitlab_shell.hooks_path gitlab_shell_hook_file = File.join(gitlab_shell_hooks_path, hook_file) gitlab_shell_ssh_user = Gitlab.config.gitlab_shell.ssh_user -- GitLab From 59f428dca20228984e9f50c33b12f54eb15638e5 Mon Sep 17 00:00:00 2001 From: Alex Van't Hof Date: Tue, 27 Aug 2013 21:22:42 -0400 Subject: [PATCH 088/175] Standardize commit diff api url, change blob api url, add get single commit Use "/commits/:sha/diff" as opposed to "/commit/:sha", keeping in line with existing api urls (e.g. "/projects/:id", etc.) Fix 500 error resulting from a diff api call with an invalid commit hash Move "/commits/:sha/blob" to "/blobs/:sha", leaving the old path for backwards compatibility. Add ability to get a single commit via "/commits/:sha" --- doc/api/repositories.md | 29 +++++++++++++- lib/api/repositories.rb | 24 ++++++++++-- spec/requests/api/repositories_spec.rb | 52 ++++++++++++++++++++++---- 3 files changed, 91 insertions(+), 14 deletions(-) diff --git a/doc/api/repositories.md b/doc/api/repositories.md index 229d4409ea6..cb0626972e5 100644 --- a/doc/api/repositories.md +++ b/doc/api/repositories.md @@ -239,12 +239,37 @@ Parameters: ] ``` +## Get a single commit + +Get a specific commit identified by the commit hash or name of a branch or tag. + +``` +GET /projects/:id/repository/commits/:sha +``` + +Parameters: + ++ `id` (required) - The ID of a project ++ `sha` (required) - The commit hash or name of a repository branch or tag + +```json +{ + "id": "6104942438c14ec7bd21c6cd5bd995272b3faff6", + "short_id": "6104942438c", + "title": "Sanitize for network graph", + "author_name": "randx", + "author_email": "dmitriy.zaporozhets@gmail.com", + "created_at": "2012-09-20T09:06:12+03:00" +} +``` + + ## Get the diff of a commit Get the diff of a commit in a project. ``` -GET /projects/:id/repository/commit/:sha +GET /projects/:id/repository/commits/:sha/diff ``` Parameters: @@ -323,7 +348,7 @@ Parameters: Get the raw file contents for a file. ``` -GET /projects/:id/repository/commits/:sha/blob +GET /projects/:id/repository/blobs/:sha ``` Parameters: diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb index 7e806546d02..fef32d3a2fe 100644 --- a/lib/api/repositories.rb +++ b/lib/api/repositories.rb @@ -106,13 +106,29 @@ module API # # Parameters: # id (required) - The ID of a project + # sha (required) - The commit hash or name of a repository branch or tag + # Example Request: + # GET /projects/:id/repository/commits/:sha + get ":id/repository/commits/:sha" do + authorize! :download_code, user_project + sha = params[:sha] + commit = user_project.repository.commit(sha) + not_found! "Commit" unless commit + present commit, with: Entities::RepoCommit + end + + # Get the diff for a specific commit of a project + # + # Parameters: + # id (required) - The ID of a project # sha (required) - The commit or branch name # Example Request: - # GET /projects/:id/repository/commit/:sha - get ":id/repository/commit/:sha" do + # GET /projects/:id/repository/commits/:sha/diff + get ":id/repository/commits/:sha/diff" do authorize! :download_code, user_project sha = params[:sha] result = CommitLoadContext.new(user_project, current_user, {id: sha}).execute + not_found! "Commit" unless result[:commit] result[:commit].diffs end @@ -148,8 +164,8 @@ module API # sha (required) - The commit or branch name # filepath (required) - The path to the file to display # Example Request: - # GET /projects/:id/repository/commits/:sha/blob - get ":id/repository/commits/:sha/blob" do + # GET /projects/:id/repository/blobs/:sha + get [ ":id/repository/blobs/:sha", ":id/repository/commits/:sha/blob" ] do authorize! :download_code, user_project required_attributes! [:filepath] diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb index 44892876ccb..f15abdd3581 100644 --- a/spec/requests/api/repositories_spec.rb +++ b/spec/requests/api/repositories_spec.rb @@ -112,23 +112,51 @@ describe API::API do end end - describe "GET /projects:id/repository/commit/:sha" do + describe "GET /projects:id/repository/commits/:sha" do + context "authorized user" do + it "should return a commit by sha" do + get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}", user) + response.status.should == 200 + json_response['id'].should == project.repository.commit.id + json_response['title'].should == project.repository.commit.title + end + + it "should return a 404 error if not found" do + get api("/projects/#{project.id}/repository/commits/invalid_sha", user) + response.status.should == 404 + end + end + + context "unauthorized user" do + it "should not return the selected commit" do + get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}") + response.status.should == 401 + end + end + end + + describe "GET /projects:id/repository/commits/:sha/diff" do context "authorized user" do before { project.team << [user2, :reporter] } it "should return the diff of the selected commit" do - get api("/projects/#{project.id}/repository/commit/#{project.repository.commit.id}", user) + get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/diff", user) response.status.should == 200 json_response.should be_an Array json_response.length.should >= 1 json_response.first.keys.should include "diff" end + + it "should return a 404 error if invalid commit" do + get api("/projects/#{project.id}/repository/commits/invalid_sha/diff", user) + response.status.should == 404 + end end context "unauthorized user" do it "should not return the diff of the selected commit" do - get api("/projects/#{project.id}/repository/commit/#{project.repository.commit.id}") + get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/diff") response.status.should == 401 end end @@ -157,25 +185,33 @@ describe API::API do end end - describe "GET /projects/:id/repository/commits/:sha/blob" do + describe "GET /projects/:id/repository/blobs/:sha" do it "should get the raw file contents" do - get api("/projects/#{project.id}/repository/commits/master/blob?filepath=README.md", user) + get api("/projects/#{project.id}/repository/blobs/master?filepath=README.md", user) response.status.should == 200 end it "should return 404 for invalid branch_name" do - get api("/projects/#{project.id}/repository/commits/invalid_branch_name/blob?filepath=README.md", user) + get api("/projects/#{project.id}/repository/blobs/invalid_branch_name?filepath=README.md", user) response.status.should == 404 end it "should return 404 for invalid file" do - get api("/projects/#{project.id}/repository/commits/master/blob?filepath=README.invalid", user) + get api("/projects/#{project.id}/repository/blobs/master?filepath=README.invalid", user) response.status.should == 404 end it "should return a 400 error if filepath is missing" do - get api("/projects/#{project.id}/repository/commits/master/blob", user) + get api("/projects/#{project.id}/repository/blobs/master", user) response.status.should == 400 end end + + describe "GET /projects/:id/repository/commits/:sha/blob" do + it "should get the raw file contents" do + get api("/projects/#{project.id}/repository/commits/master/blob?filepath=README.md", user) + response.status.should == 200 + end + end + end -- GitLab From f57944cc6170e1c06e7fe18e52a08c90ccb10ddb Mon Sep 17 00:00:00 2001 From: Rovanion Date: Wed, 28 Aug 2013 12:38:41 +0200 Subject: [PATCH 089/175] Corrections suggested by jacobvosmaer --- lib/support/init.d/gitlab | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab index 65e036fe984..eb9f5125c32 100755 --- a/lib/support/init.d/gitlab +++ b/lib/support/init.d/gitlab @@ -20,8 +20,8 @@ RAILS_ENV="production" # Script variable names should be lower-case not to conflict with internal # /bin/sh variables such as PATH, EDITOR or SHELL. -app_root="/home/git/gitlab" -app_user="git" +app_root="/home/gitlab/gitlab" +app_user="gitlab" unicorn_conf="$app_root/config/unicorn.rb" pid_path="$app_root/tmp/pids" socket_path="$app_root/tmp/sockets" @@ -99,7 +99,7 @@ check_stale_pids(){ } # If no parts of the service is running, bail out. -check_not_running(){ +exit_if_not_running(){ check_stale_pids if [ "$web_status" != "0" -a "$sidekiq_status" != "0" ]; then echo "GitLab is not running." @@ -138,7 +138,7 @@ start() { # Asks the Unicorn and the Sidekiq if they would be so kind as to stop, if not kills them. stop() { - check_not_running + exit_if_not_running # If the Unicorn web server is running, tell it to stop; if [ "$web_status" = "0" ]; then kill -QUIT "$wpid" & @@ -178,7 +178,7 @@ stop() { # Returns the status of GitLab and it's components status() { - check_not_running + exit_if_not_running if [ "$web_status" = "0" ]; then echo "The GitLab Unicorn webserver with pid $wpid is running." else @@ -195,14 +195,21 @@ status() { } reload(){ - check_not_running + exit_if_not_running if [ "$wpid" = "0" ];then echo "The GitLab Unicorn Web server is not running thus it's configuration can't be reloaded." exit 1 fi - printf "Reloading GitLab configuration... " - kill -HUP "$wpid" + printf "Reloading GitLab Unicorn configuration... " + kill -USR2 "$wpid" echo "Done." + echo "Restarting GitLab Sidekiq since it isn't capable of reloading it's config..." + RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:stop + echo "Starting Sidekiq..." + RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:start + # Waiting 2 seconds for sidekiq to write it. + sleep 2 + status } -- GitLab From cda4d6881aba6ebcdd71a8f1c47976e77cf9e9aa Mon Sep 17 00:00:00 2001 From: Rovanion Date: Wed, 28 Aug 2013 13:16:34 +0200 Subject: [PATCH 090/175] Fixed failure to stop and added handling of failure to remove stale pid --- lib/support/init.d/gitlab | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab index eb9f5125c32..00bd7a460c2 100755 --- a/lib/support/init.d/gitlab +++ b/lib/support/init.d/gitlab @@ -20,8 +20,8 @@ RAILS_ENV="production" # Script variable names should be lower-case not to conflict with internal # /bin/sh variables such as PATH, EDITOR or SHELL. -app_root="/home/gitlab/gitlab" -app_user="gitlab" +app_root="/home/git/gitlab" +app_user="git" unicorn_conf="$app_root/config/unicorn.rb" pid_path="$app_root/tmp/pids" socket_path="$app_root/tmp/sockets" @@ -76,10 +76,14 @@ check_status(){ if [ $wpid -ne 0 ]; then kill -0 "$wpid" 2>/dev/null web_status="$?" + else + web_status="-1" fi if [ $spid -ne 0 ]; then kill -0 "$spid" 2>/dev/null sidekiq_status="$?" + else + sidekiq_status="-1" fi } @@ -89,12 +93,18 @@ check_stale_pids(){ # If there is a pid it is something else than 0, the service is running if # *_status is == 0. if [ "$wpid" != "0" -a "$web_status" != "0" ]; then - echo "Found stale Unicorn web server pid, removing. This is most likely caused by the web server crashing the last time it ran." - rm "$web_server_pid_path" + echo "Removing stale Unicorn web server pid. This is most likely caused by the web server crashing the last time it ran." + if ! rm "$web_server_pid_path"; then + echo "Unable to remove stale pid, exiting" + exit 1 + fi fi if [ "$spid" != "0" -a "$sidekiq_status" != "0" ]; then - echo "Found stale Sidekiq web server pid, removing. This is most likely caused by the Sidekiq crashing the last time it ran." - rm "$sidekiq_pid_path" + echo "Removing stale Sidekiq web server pid. This is most likely caused by the Sidekiq crashing the last time it ran." + if ! rm "$sidekiq_pid_path"; then + echo "Unable to remove stale pid, exiting" + exit 1 + fi fi } @@ -205,7 +215,7 @@ reload(){ echo "Done." echo "Restarting GitLab Sidekiq since it isn't capable of reloading it's config..." RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:stop - echo "Starting Sidekiq..." + echo "Starting Sidekiq..." RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:start # Waiting 2 seconds for sidekiq to write it. sleep 2 -- GitLab From 7f65339fffaf6d051338ee399bfe439234ce70a0 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 28 Aug 2013 21:36:09 +0300 Subject: [PATCH 091/175] Fix s500 when press ervice test button --- app/services/git_push_service.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index 9584f420ab3..f9d43e60de6 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -59,8 +59,8 @@ class GitPushService # def sample_data(project, user) @project, @user = project, user - commits = project.repository.commits(project.default_branch, nil, 3) - post_receive_data(commits.last.id, commits.first.id, "refs/heads/#{project.default_branch}") + @push_commits = project.repository.commits(project.default_branch, nil, 3) + post_receive_data(@push_commits.last.id, @push_commits.first.id, "refs/heads/#{project.default_branch}") end protected -- GitLab From ffa46e0225bad993f8999a33905dcff7a75327e0 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 29 Aug 2013 18:59:08 +0300 Subject: [PATCH 092/175] More entries to 6.1 CHANGELOG --- CHANGELOG | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 7c3d7ba3502..a6648d950b1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,11 @@ v 6.1.0 - Link issues, merge requests, and commits when they reference each other with GFM - Close issues automatically when pushing commits with a special message + - Project internal ids for issues, mr, milestones + - Improve user removal from admin area + - Remove deprecated classes and rake tasks + - Add event filter for group and project show pages + - Add links to create branch/tag from project home page v 6.0.0 - Feature: Replace teams with group membership -- GitLab From 99eefcb54d0f467a96629ef63caaf3cceda18eb6 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 29 Aug 2013 19:12:22 +0300 Subject: [PATCH 093/175] Invalidate events cache when project was moved --- app/models/project.rb | 16 ++++++++++++++++ app/services/project_transfer_service.rb | 3 +++ 2 files changed, 19 insertions(+) diff --git a/app/models/project.rb b/app/models/project.rb index b505ffb58cf..6c4f3075e1c 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -423,6 +423,7 @@ class Project < ActiveRecord::Base gitlab_shell.rm_satellites(old_path_with_namespace) ensure_satellite_exists send_move_instructions + reset_events_cache rescue # Returning false does not rollback after_* transaction but gives # us information about failing some of tasks @@ -434,4 +435,19 @@ class Project < ActiveRecord::Base raise Exception.new('repository cannot be renamed') end end + + # Reset events cache related to this project + # + # Since we do cache @event we need to reset cache in special cases: + # * when project was moved + # * when project was renamed + # Events cache stored like events/23-20130109142513. + # The cache key includes updated_at timestamp. + # Thus it will automatically generate a new fragment + # when the event is updated because the key changes. + def reset_events_cache + Event.where(project_id: self.id). + order('id DESC').limit(100). + update_all(updated_at: Time.now) + end end diff --git a/app/services/project_transfer_service.rb b/app/services/project_transfer_service.rb index 8fbf92ff20a..7150c1c78c0 100644 --- a/app/services/project_transfer_service.rb +++ b/app/services/project_transfer_service.rb @@ -32,6 +32,9 @@ class ProjectTransferService # create satellite repo project.ensure_satellite_exists + # clear project cached events + project.reset_events_cache + true end end -- GitLab From b928d45d519f767e8206e1c2c0d1a8a84f23fe90 Mon Sep 17 00:00:00 2001 From: Jon Bringhurst Date: Thu, 29 Aug 2013 10:34:37 -0600 Subject: [PATCH 094/175] Fixed up wording on the new SSH key page. --- app/views/profiles/keys/_form.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/profiles/keys/_form.html.haml b/app/views/profiles/keys/_form.html.haml index 3a0b6cd48a1..158979c0ee5 100644 --- a/app/views/profiles/keys/_form.html.haml +++ b/app/views/profiles/keys/_form.html.haml @@ -13,7 +13,7 @@ = f.label :key .controls %p.light - Paste your public key here. Read more about how generate it #{link_to "here", help_ssh_path} + Paste your public key here. Read more about how to generate a key on #{link_to "the SSH help page", help_ssh_path}. = f.text_area :key, class: "input-xxlarge thin_area" -- GitLab From 255d6d8b215a6733f4b49229aded0152b4510891 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 29 Aug 2013 20:32:40 +0300 Subject: [PATCH 095/175] Update sidekiq and redis-rails --- Gemfile.lock | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index e345c40f445..e608afad1e7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -389,24 +389,24 @@ GEM json (~> 1.4) redcarpet (2.2.2) redis (3.0.4) - redis-actionpack (3.2.3) - actionpack (~> 3.2.3) - redis-rack (~> 1.4.0) + redis-actionpack (3.2.4) + actionpack (~> 3.2.0) + redis-rack (~> 1.4.4) + redis-store (~> 1.1.4) + redis-activesupport (3.2.4) + activesupport (~> 3.2.0) redis-store (~> 1.1.0) - redis-activesupport (3.2.3) - activesupport (~> 3.2.3) - redis-store (~> 1.1.0) - redis-namespace (1.3.0) + redis-namespace (1.3.1) redis (~> 3.0.0) - redis-rack (1.4.2) - rack (~> 1.4.1) - redis-store (~> 1.1.0) - redis-rails (3.2.3) - redis-actionpack (~> 3.2.3) - redis-activesupport (~> 3.2.3) - redis-store (~> 1.1.0) - redis-store (1.1.3) - redis (>= 2.2.0) + redis-rack (1.4.4) + rack (~> 1.4.0) + redis-store (~> 1.1.4) + redis-rails (3.2.4) + redis-actionpack (~> 3.2.4) + redis-activesupport (~> 3.2.4) + redis-store (~> 1.1.4) + redis-store (1.1.4) + redis (>= 2.2) ref (1.0.5) rest-client (1.6.7) mime-types (>= 1.16) @@ -455,11 +455,11 @@ GEM sexp_processor (4.2.1) shoulda-matchers (2.1.0) activesupport (>= 3.0.0) - sidekiq (2.12.4) + sidekiq (2.14.0) celluloid (>= 0.14.1) connection_pool (>= 1.0.0) json - redis (>= 3.0) + redis (>= 3.0.4) redis-namespace simple_oauth (0.1.9) simplecov (0.7.1) -- GitLab From 3d41e182c2051d539006107df9ece42b947100c2 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 29 Aug 2013 21:11:01 +0300 Subject: [PATCH 096/175] Minor UI fix --- app/assets/stylesheets/gitlab_bootstrap/common.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/stylesheets/gitlab_bootstrap/common.scss b/app/assets/stylesheets/gitlab_bootstrap/common.scss index 372cbe50fd0..9637be679af 100644 --- a/app/assets/stylesheets/gitlab_bootstrap/common.scss +++ b/app/assets/stylesheets/gitlab_bootstrap/common.scss @@ -28,7 +28,7 @@ .hint { font-style: italic; color: #999; } .light { color: #888 } .tiny { font-weight: normal } -.vtop { vertical-align: top; } +.vtop { vertical-align: top !important; } /** ALERT MESSAGES **/ -- GitLab From 07f156f5c2c6776079f0210f4067121d1b74048d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 29 Aug 2013 21:44:45 +0300 Subject: [PATCH 097/175] Dont update namespace if User name was changed. Use user#username for namespace name because Namespace#name validates by uniq --- app/observers/user_observer.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/observers/user_observer.rb b/app/observers/user_observer.rb index e969405a598..fba0f1006d9 100644 --- a/app/observers/user_observer.rb +++ b/app/observers/user_observer.rb @@ -13,8 +13,8 @@ class UserObserver < BaseObserver # Ensure user has namespace user.create_namespace!(path: user.username, name: user.username) unless user.namespace - if user.username_changed? || user.name_changed? - user.namespace.update_attributes(path: user.username, name: user.name) + if user.username_changed? + user.namespace.update_attributes(path: user.username, name: user.username) end end end -- GitLab From b32088414941fefd85172614ba6d615db2f07961 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 29 Aug 2013 21:45:19 +0300 Subject: [PATCH 098/175] List groups on Dashboard#projects page --- .../stylesheets/gitlab_bootstrap/common.scss | 17 ----------- .../stylesheets/gitlab_bootstrap/forms.scss | 19 ++++++++++++ .../stylesheets/gitlab_bootstrap/nav.scss | 1 + app/controllers/dashboard_controller.rb | 6 +++- app/views/dashboard/projects.html.haml | 30 ++++++++++++++----- 5 files changed, 48 insertions(+), 25 deletions(-) diff --git a/app/assets/stylesheets/gitlab_bootstrap/common.scss b/app/assets/stylesheets/gitlab_bootstrap/common.scss index 9637be679af..bc6c786da50 100644 --- a/app/assets/stylesheets/gitlab_bootstrap/common.scss +++ b/app/assets/stylesheets/gitlab_bootstrap/common.scss @@ -56,23 +56,6 @@ line-height: 24px; } -/** FORMS **/ -input[type='search'].search-text-input { - background-image: url("icon-search.png"); - background-repeat: no-repeat; - background-position: 10px; - padding-left: 25px; - @include border-radius(4px); - border: 1px solid #ccc; -} - -input[type='text'].danger { - background: #F2DEDE!important; - border-color: #D66; - text-shadow: 0 1px 1px #fff -} - -fieldset legend { font-size: 15px; } .tab-content { overflow: visible; diff --git a/app/assets/stylesheets/gitlab_bootstrap/forms.scss b/app/assets/stylesheets/gitlab_bootstrap/forms.scss index d1feb554404..020a0bf7fd5 100644 --- a/app/assets/stylesheets/gitlab_bootstrap/forms.scss +++ b/app/assets/stylesheets/gitlab_bootstrap/forms.scss @@ -31,3 +31,22 @@ input { } } +input[type='search'].search-text-input { + background-image: url("icon-search.png"); + background-repeat: no-repeat; + background-position: 10px; + padding-left: 25px; + @include border-radius(4px); + border: 1px solid #ccc; +} + +input[type='text'].danger { + background: #F2DEDE!important; + border-color: #D66; + text-shadow: 0 1px 1px #fff +} + +fieldset legend { + font-size: 16px; + margin-bottom: 10px; +} diff --git a/app/assets/stylesheets/gitlab_bootstrap/nav.scss b/app/assets/stylesheets/gitlab_bootstrap/nav.scss index 40616f7540a..aa4cb1ed5fd 100644 --- a/app/assets/stylesheets/gitlab_bootstrap/nav.scss +++ b/app/assets/stylesheets/gitlab_bootstrap/nav.scss @@ -22,6 +22,7 @@ background: #F1F1F1; color: $style_color; font-weight: bold; + text-shadow: 0 1px 1px #fff; } &.nav-stacked-menu { diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 23da2c274dc..33b2a5cd7e7 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -33,9 +33,13 @@ class DashboardController < ApplicationController current_user.owned_projects else current_user.authorized_projects - end.sorted_by_activity + end + + @projects = @projects.where(namespace_id: Group.find_by_name(params[:group])) if params[:group].present? + @projects = @projects.includes(:namespace).sorted_by_activity @labels = current_user.authorized_projects.tags_on(:labels) + @groups = current_user.authorized_groups @projects = @projects.tagged_with(params[:label]) if params[:label].present? @projects = @projects.page(params[:page]).per(30) diff --git a/app/views/dashboard/projects.html.haml b/app/views/dashboard/projects.html.haml index 3599320dfb3..0dcb1a87e9a 100644 --- a/app/views/dashboard/projects.html.haml +++ b/app/views/dashboard/projects.html.haml @@ -26,14 +26,30 @@ %span.pull-right = current_user.owned_projects.count + + - if @groups.present? + %fieldset + %legend Groups + %ul.bordered-list + - @groups.each do |group| + %li{ class: (group.name == params[:group]) ? 'active' : 'light' } + = link_to projects_dashboard_path(group: group.name) do + %i.icon-folder-close-alt + = group.name + %small.pull-right + = group.projects.count + + + - if @labels.present? - %p.light Filter by label: - %ul.bordered-list - - @labels.each do |label| - %li{ class: (label.name == params[:label]) ? 'active' : 'light' } - = link_to projects_dashboard_path(scope: params[:scope], label: label.name) do - %i.icon-tag - = label.name + %fieldset + %legend Labels + %ul.bordered-list + - @labels.each do |label| + %li{ class: (label.name == params[:label]) ? 'active' : 'light' } + = link_to projects_dashboard_path(scope: params[:scope], label: label.name) do + %i.icon-tag + = label.name .span9 %ul.bordered-list.my-projects.top-list -- GitLab From 25a723c3ae04c5818427682b2fbe97609a97f1ea Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 29 Aug 2013 21:49:13 +0300 Subject: [PATCH 099/175] Remove colon --- app/views/shared/_filter.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/shared/_filter.html.haml b/app/views/shared/_filter.html.haml index 52ca1f22d7d..2f051cea48b 100644 --- a/app/views/shared/_filter.html.haml +++ b/app/views/shared/_filter.html.haml @@ -12,7 +12,7 @@ All %fieldset - %legend Projects: + %legend Projects %ul.nav.nav-pills.nav-pills-small.nav-stacked - @projects.each do |project| - unless entities_per_project(project, entity).zero? -- GitLab From bae719df664714c20c0157944337a9857bd2d91f Mon Sep 17 00:00:00 2001 From: Snooze- Date: Thu, 29 Aug 2013 21:23:19 +0200 Subject: [PATCH 100/175] Create satellites during update to 6.0. Fix #4938 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Satellites for projects that were located in the root namespace needs to be recreated once they've been migrated to the creator’s namespace during the upgrade process. This can be achieved by running the sudo -u git -H bundle exec rake gitlab:satellites:create RAILS_ENV=production during the update process. The command has been added to the 5.4 to 6.0 update doc. --- doc/update/5.4-to-6.0.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/update/5.4-to-6.0.md b/doc/update/5.4-to-6.0.md index 0869dd833f9..907a134ed1d 100644 --- a/doc/update/5.4-to-6.0.md +++ b/doc/update/5.4-to-6.0.md @@ -70,6 +70,7 @@ sudo -u git -H bundle exec rake migrate_groups RAILS_ENV=production sudo -u git -H bundle exec rake migrate_global_projects RAILS_ENV=production sudo -u git -H bundle exec rake migrate_keys RAILS_ENV=production sudo -u git -H bundle exec rake migrate_inline_notes RAILS_ENV=production +sudo -u git -H bundle exec rake gitlab:satellites:create RAILS_ENV=production # Clear redis cache sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production -- GitLab From e602c9b0b17b2442048aa5df81fbd057bd7ab12e Mon Sep 17 00:00:00 2001 From: Austin Robertson Date: Thu, 29 Aug 2013 14:53:22 -0500 Subject: [PATCH 101/175] Add link to project page from admin view --- app/views/admin/projects/show.html.haml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml index 72317bb8efe..561d3252e22 100644 --- a/app/views/admin/projects/show.html.haml +++ b/app/views/admin/projects/show.html.haml @@ -12,7 +12,8 @@ %ul.well-list %li %span.light Name: - %strong= @project.name + %strong + = link_to @project.name, project_path(@project) %li %span.light Namespace: %strong -- GitLab From 98ea81e65956cb37fc67c03e3a88c29c6932b12c Mon Sep 17 00:00:00 2001 From: Rovanion Date: Thu, 29 Aug 2013 23:26:08 +0200 Subject: [PATCH 102/175] Restart works again, grammar mistakes corrected. --- lib/support/init.d/gitlab | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab index 00bd7a460c2..a05227ceb1b 100755 --- a/lib/support/init.d/gitlab +++ b/lib/support/init.d/gitlab @@ -188,7 +188,11 @@ stop() { # Returns the status of GitLab and it's components status() { - exit_if_not_running + check_status + if [ "$web_status" != "0" -a "$sidekiq_status" != "0" ]; then + echo "GitLab is not running." + return + fi if [ "$web_status" = "0" ]; then echo "The GitLab Unicorn webserver with pid $wpid is running." else @@ -207,13 +211,13 @@ status() { reload(){ exit_if_not_running if [ "$wpid" = "0" ];then - echo "The GitLab Unicorn Web server is not running thus it's configuration can't be reloaded." + echo "The GitLab Unicorn Web server is not running thus its configuration can't be reloaded." exit 1 fi printf "Reloading GitLab Unicorn configuration... " kill -USR2 "$wpid" echo "Done." - echo "Restarting GitLab Sidekiq since it isn't capable of reloading it's config..." + echo "Restarting GitLab Sidekiq since it isn't capable of reloading its config..." RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:stop echo "Starting Sidekiq..." RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:start @@ -222,6 +226,14 @@ reload(){ status } +restart(){ + check_status + if [ "$web_status" = "0" -o "$sidekiq_status" = "0" ]; then + stop + fi + start +} + ## Finally the input handling. @@ -233,8 +245,7 @@ case "$1" in stop ;; restart) - stop - start + restart ;; reload|force-reload) reload -- GitLab From 850b4af0fffa77d5f3440d89015543f060d9ac67 Mon Sep 17 00:00:00 2001 From: James Newton Date: Thu, 29 Aug 2013 21:26:32 -0500 Subject: [PATCH 103/175] have email views use iid --- app/views/notify/closed_issue_email.html.haml | 2 +- app/views/notify/closed_issue_email.text.haml | 2 +- app/views/notify/closed_merge_request_email.html.haml | 2 +- app/views/notify/closed_merge_request_email.text.haml | 2 +- app/views/notify/issue_status_changed_email.html.haml | 2 +- app/views/notify/issue_status_changed_email.text.erb | 2 +- app/views/notify/merged_merge_request_email.html.haml | 2 +- app/views/notify/merged_merge_request_email.text.haml | 2 +- app/views/notify/new_issue_email.html.haml | 2 +- app/views/notify/new_issue_email.text.erb | 4 ++-- app/views/notify/new_merge_request_email.html.haml | 2 +- app/views/notify/new_merge_request_email.text.erb | 2 +- app/views/notify/new_user_email.text.erb | 2 +- app/views/notify/note_issue_email.html.haml | 2 +- app/views/notify/note_issue_email.text.erb | 2 +- app/views/notify/note_merge_request_email.html.haml | 2 +- app/views/notify/note_merge_request_email.text.erb | 6 +++--- app/views/notify/note_wall_email.text.erb | 2 +- app/views/notify/project_was_moved_email.text.erb | 4 ++-- app/views/notify/reassigned_issue_email.html.haml | 2 +- app/views/notify/reassigned_issue_email.text.erb | 4 ++-- app/views/notify/reassigned_merge_request_email.html.haml | 2 +- app/views/notify/reassigned_merge_request_email.text.erb | 4 ++-- 23 files changed, 29 insertions(+), 29 deletions(-) diff --git a/app/views/notify/closed_issue_email.html.haml b/app/views/notify/closed_issue_email.html.haml index 23ccc4538de..325cd44eb4b 100644 --- a/app/views/notify/closed_issue_email.html.haml +++ b/app/views/notify/closed_issue_email.html.haml @@ -1,5 +1,5 @@ %p = "Issue was closed by #{@updated_by.name}" %p - = "Issue ##{@issue.id}" + = "Issue ##{@issue.iid}" = link_to_gfm truncate(@issue.title, length: 45), project_issue_url(@issue.project, @issue), title: @issue.title diff --git a/app/views/notify/closed_issue_email.text.haml b/app/views/notify/closed_issue_email.text.haml index 0cca321552c..49f160a0d5f 100644 --- a/app/views/notify/closed_issue_email.text.haml +++ b/app/views/notify/closed_issue_email.text.haml @@ -1,3 +1,3 @@ = "Issue was closed by #{@updated_by.name}" -Issue ##{@issue.id}: #{project_issue_url(@issue.project, @issue)} +Issue ##{@issue.iid}: #{project_issue_url(@issue.project, @issue)} diff --git a/app/views/notify/closed_merge_request_email.html.haml b/app/views/notify/closed_merge_request_email.html.haml index c6b45b1710a..45770cc85de 100644 --- a/app/views/notify/closed_merge_request_email.html.haml +++ b/app/views/notify/closed_merge_request_email.html.haml @@ -1,5 +1,5 @@ %p - = "Merge Request #{@merge_request.id} was closed by #{@updated_by.name}" + = "Merge Request #{@merge_request.iid} was closed by #{@updated_by.name}" %p = link_to_gfm truncate(@merge_request.title, length: 40), project_merge_request_url(@merge_request.target_project, @merge_request) %p diff --git a/app/views/notify/closed_merge_request_email.text.haml b/app/views/notify/closed_merge_request_email.text.haml index 9a5bce5915a..ee434ec8cb2 100644 --- a/app/views/notify/closed_merge_request_email.text.haml +++ b/app/views/notify/closed_merge_request_email.text.haml @@ -1,4 +1,4 @@ -= "Merge Request #{@merge_request.id} was closed by #{@updated_by.name}" += "Merge Request #{@merge_request.iid} was closed by #{@updated_by.name}" Merge Request url: #{project_merge_request_url(@merge_request.target_project, @merge_request)} diff --git a/app/views/notify/issue_status_changed_email.html.haml b/app/views/notify/issue_status_changed_email.html.haml index 4cdb70994ce..7706b3f7516 100644 --- a/app/views/notify/issue_status_changed_email.html.haml +++ b/app/views/notify/issue_status_changed_email.html.haml @@ -1,5 +1,5 @@ %p = "Issue was #{@issue_status} by #{@updated_by.name}" %p - = "Issue ##{@issue.id}" + = "Issue ##{@issue.iid}" = link_to_gfm truncate(@issue.title, length: 45), project_issue_url(@issue.project, @issue), title: @issue.title diff --git a/app/views/notify/issue_status_changed_email.text.erb b/app/views/notify/issue_status_changed_email.text.erb index bbca3474d50..4200881f7e8 100644 --- a/app/views/notify/issue_status_changed_email.text.erb +++ b/app/views/notify/issue_status_changed_email.text.erb @@ -1,4 +1,4 @@ Issue was <%= @issue_status %> by <%= @updated_by.name %> -Issue <%= @issue.id %>: <%= url_for(project_issue_url(@issue.project, @issue)) %> +Issue <%= @issue.iid %>: <%= url_for(project_issue_url(@issue.project, @issue)) %> diff --git a/app/views/notify/merged_merge_request_email.html.haml b/app/views/notify/merged_merge_request_email.html.haml index e3ae41819f8..e2bc9cf5c04 100644 --- a/app/views/notify/merged_merge_request_email.html.haml +++ b/app/views/notify/merged_merge_request_email.html.haml @@ -1,5 +1,5 @@ %p - = "Merge Request #{@merge_request.id} was merged" + = "Merge Request #{@merge_request.iid} was merged" %p = link_to_gfm truncate(@merge_request.title, length: 40), project_merge_request_url(@merge_request.target_project, @merge_request) %p diff --git a/app/views/notify/merged_merge_request_email.text.haml b/app/views/notify/merged_merge_request_email.text.haml index fa9ef0a4b32..550f677fed4 100644 --- a/app/views/notify/merged_merge_request_email.text.haml +++ b/app/views/notify/merged_merge_request_email.text.haml @@ -1,4 +1,4 @@ -= "Merge Request #{@merge_request.id} was merged" += "Merge Request #{@merge_request.iid} was merged" Merge Request Url: #{project_merge_request_url(@merge_request.target_project, @merge_request)} diff --git a/app/views/notify/new_issue_email.html.haml b/app/views/notify/new_issue_email.html.haml index f11c850641b..3b3c148517a 100644 --- a/app/views/notify/new_issue_email.html.haml +++ b/app/views/notify/new_issue_email.html.haml @@ -1,7 +1,7 @@ %p New Issue was created. %p - = "Issue ##{@issue.id}" + = "Issue ##{@issue.iid}" = link_to_gfm truncate(@issue.title, length: 45), project_issue_url(@issue.project, @issue), title: @issue.title %p Author: #{@issue.author_name} diff --git a/app/views/notify/new_issue_email.text.erb b/app/views/notify/new_issue_email.text.erb index 9907ca83247..d36f54eb1ca 100644 --- a/app/views/notify/new_issue_email.text.erb +++ b/app/views/notify/new_issue_email.text.erb @@ -1,5 +1,5 @@ New Issue was created. - -Issue <%= @issue.id %>: <%= url_for(project_issue_url(@issue.project, @issue)) %> + +Issue <%= @issue.iid %>: <%= url_for(project_issue_url(@issue.project, @issue)) %> Author: <%= @issue.author_name %> Asignee: <%= @issue.assignee_name %> diff --git a/app/views/notify/new_merge_request_email.html.haml b/app/views/notify/new_merge_request_email.html.haml index 3b060001e6b..6b2782ebb0b 100644 --- a/app/views/notify/new_merge_request_email.html.haml +++ b/app/views/notify/new_merge_request_email.html.haml @@ -1,5 +1,5 @@ %p - = "New Merge Request !#{@merge_request.id}" + = "New Merge Request !#{@merge_request.iid}" %p = link_to_gfm truncate(@merge_request.title, length: 40), project_merge_request_url(@merge_request.target_project, @merge_request) %p diff --git a/app/views/notify/new_merge_request_email.text.erb b/app/views/notify/new_merge_request_email.text.erb index 3f711840a51..2d27350486e 100644 --- a/app/views/notify/new_merge_request_email.text.erb +++ b/app/views/notify/new_merge_request_email.text.erb @@ -1,4 +1,4 @@ -New Merge Request <%= @merge_request.id %> +New Merge Request <%= @merge_request.iid %> <%= url_for(project_merge_request_url(@merge_request.target_project, @merge_request)) %> diff --git a/app/views/notify/new_user_email.text.erb b/app/views/notify/new_user_email.text.erb index 50ed595b38a..c21c95d3047 100644 --- a/app/views/notify/new_user_email.text.erb +++ b/app/views/notify/new_user_email.text.erb @@ -5,7 +5,7 @@ The Administrator created an account for you. Now you are a member of the compan login.................. <%= @user.email %> <% if @user.created_by_id %> password............... <%= @password %> - + You will be forced to change this password immediately after login. <% end %> diff --git a/app/views/notify/note_issue_email.html.haml b/app/views/notify/note_issue_email.html.haml index ca1331260d3..b3230953e7d 100644 --- a/app/views/notify/note_issue_email.html.haml +++ b/app/views/notify/note_issue_email.html.haml @@ -1,4 +1,4 @@ %p - = "New comment for Issue ##{@issue.id}" + = "New comment for Issue ##{@issue.iid}" = link_to_gfm truncate(@issue.title, length: 35), project_issue_url(@issue.project, @issue, anchor: "note_#{@note.id}") = render 'note_message' diff --git a/app/views/notify/note_issue_email.text.erb b/app/views/notify/note_issue_email.text.erb index a476b286ae4..8a61f54a337 100644 --- a/app/views/notify/note_issue_email.text.erb +++ b/app/views/notify/note_issue_email.text.erb @@ -1,4 +1,4 @@ -New comment for Issue <%= @issue.id %> +New comment for Issue <%= @issue.iid %> <%= url_for(project_issue_url(@issue.project, @issue, anchor: "note_#{@note.id}")) %> diff --git a/app/views/notify/note_merge_request_email.html.haml b/app/views/notify/note_merge_request_email.html.haml index 14abcca6070..d587b068486 100644 --- a/app/views/notify/note_merge_request_email.html.haml +++ b/app/views/notify/note_merge_request_email.html.haml @@ -3,6 +3,6 @@ = link_to "New comment on diff", diffs_project_merge_request_url(@merge_request.target_project, @merge_request, anchor: "note_#{@note.id}") - else = link_to "New comment", project_merge_request_url(@merge_request.target_project, @merge_request, anchor: "note_#{@note.id}") - for Merge Request ##{@merge_request.id} + for Merge Request ##{@merge_request.iid} %cite "#{truncate(@merge_request.title, length: 20)}" = render 'note_message' diff --git a/app/views/notify/note_merge_request_email.text.erb b/app/views/notify/note_merge_request_email.text.erb index 3daa091db81..79e72ca16c6 100644 --- a/app/views/notify/note_merge_request_email.text.erb +++ b/app/views/notify/note_merge_request_email.text.erb @@ -1,9 +1,9 @@ -New comment for Merge Request <%= @merge_request.id %> +New comment for Merge Request <%= @merge_request.iid %> <%= url_for(project_merge_request_url(@merge_request.target_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 index 97910d5eb79..ee0dc3db1db 100644 --- a/app/views/notify/note_wall_email.text.erb +++ b/app/views/notify/note_wall_email.text.erb @@ -1,7 +1,7 @@ New message on the project wall <%= @note.project %> <%= url_for(project_wall_url(@note.project, anchor: "note_#{@note.id}")) %> - + <%= @note.author_name %> diff --git a/app/views/notify/project_was_moved_email.text.erb b/app/views/notify/project_was_moved_email.text.erb index 9c41073fddc..7889c7b9cc4 100644 --- a/app/views/notify/project_was_moved_email.text.erb +++ b/app/views/notify/project_was_moved_email.text.erb @@ -1,8 +1,8 @@ Project was moved to another location - + The project is now located under <%= 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.html.haml b/app/views/notify/reassigned_issue_email.html.haml index 6d332af3d70..b0edff44ce6 100644 --- a/app/views/notify/reassigned_issue_email.html.haml +++ b/app/views/notify/reassigned_issue_email.html.haml @@ -1,5 +1,5 @@ %p - = "Reassigned Issue ##{@issue.id}" + = "Reassigned Issue ##{@issue.iid}" = link_to_gfm truncate(@issue.title, length: 30), project_issue_url(@issue.project, @issue) %p Assignee changed diff --git a/app/views/notify/reassigned_issue_email.text.erb b/app/views/notify/reassigned_issue_email.text.erb index 867c4d01da5..bc0d0567922 100644 --- a/app/views/notify/reassigned_issue_email.text.erb +++ b/app/views/notify/reassigned_issue_email.text.erb @@ -1,5 +1,5 @@ -Reassigned Issue <%= @issue.id %> +Reassigned Issue <%= @issue.iid %> <%= url_for(project_issue_url(@issue.project, @issue)) %> - + Assignee changed <%= "from #{@previous_assignee.name}" if @previous_assignee %> to <%= @issue.assignee_name %> diff --git a/app/views/notify/reassigned_merge_request_email.html.haml b/app/views/notify/reassigned_merge_request_email.html.haml index 314b2882672..3a615f86e69 100644 --- a/app/views/notify/reassigned_merge_request_email.html.haml +++ b/app/views/notify/reassigned_merge_request_email.html.haml @@ -1,5 +1,5 @@ %p - = "Reassigned Merge Request !#{@merge_request.id}" + = "Reassigned Merge Request !#{@merge_request.iid}" = link_to_gfm truncate(@merge_request.title, length: 30), project_merge_request_url(@merge_request.target_project, @merge_request) %p Assignee changed diff --git a/app/views/notify/reassigned_merge_request_email.text.erb b/app/views/notify/reassigned_merge_request_email.text.erb index 05a9797165d..eecf055ff6f 100644 --- a/app/views/notify/reassigned_merge_request_email.text.erb +++ b/app/views/notify/reassigned_merge_request_email.text.erb @@ -1,7 +1,7 @@ -Reassigned Merge Request <%= @merge_request.id %> +Reassigned Merge Request <%= @merge_request.iid %> <%= url_for(project_merge_request_url(@merge_request.target_project, @merge_request)) %> - + Assignee changed <%= "from #{@previous_assignee.name}" if @previous_assignee %> to <%= @merge_request.assignee_name %> -- GitLab From 30b8218ffba6c417b1742b0632e302cc1fe63c55 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 30 Aug 2013 17:10:58 +0300 Subject: [PATCH 104/175] Rename team to Project members --- app/views/admin/projects/show.html.haml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml index 72317bb8efe..efd2807b235 100644 --- a/app/views/admin/projects/show.html.haml +++ b/app/views/admin/projects/show.html.haml @@ -77,8 +77,8 @@ - if @group .ui-box .title - %strong #{@group.name} Group - members (#{@group.users_groups.count}) + %strong #{@group.name} + group members (#{@group.users_groups.count}) .pull-right = link_to admin_group_path(@group), class: 'btn btn-small' do %i.icon-edit @@ -88,7 +88,7 @@ .ui-box .title - Team + Project members %small (#{@project.users.count}) .pull-right -- GitLab From cbae8097c0af53a20873214bcaccfb3d20c0a76b Mon Sep 17 00:00:00 2001 From: Johannes Schleifenbaum Date: Fri, 30 Aug 2013 21:04:26 +0200 Subject: [PATCH 105/175] add missing comma(s) in api examples --- doc/api/deploy_keys.md | 6 +++--- doc/api/session.md | 2 +- doc/api/users.md | 16 ++++++++-------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/doc/api/deploy_keys.md b/doc/api/deploy_keys.md index 5a394094fe6..fbb1e45bccd 100644 --- a/doc/api/deploy_keys.md +++ b/doc/api/deploy_keys.md @@ -16,14 +16,14 @@ Parameters: [ { "id": 1, - "title" : "Public key" + "title" : "Public key", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4 596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4 soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", }, { "id": 3, - "title" : "Another Public key" + "title" : "Another Public key", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4 596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4 soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=" @@ -48,7 +48,7 @@ Parameters: ```json { "id": 1, - "title" : "Public key" + "title" : "Public key", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4 596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4 soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=" diff --git a/doc/api/session.md b/doc/api/session.md index 8caf5fe1862..162d4c8bf78 100644 --- a/doc/api/session.md +++ b/doc/api/session.md @@ -27,7 +27,7 @@ __You can login with both GitLab and LDAP credentials now__ "linkedin": "", "twitter": "", "dark_scheme": false, - "theme_id": 1 + "theme_id": 1, "is_admin": false, "can_create_group" : true, "can_create_team" : true, diff --git a/doc/api/users.md b/doc/api/users.md index 20664f1e740..49afbab8c6a 100644 --- a/doc/api/users.md +++ b/doc/api/users.md @@ -22,7 +22,7 @@ GET /users "twitter": "", "extern_uid": "john.smith", "provider": "provider_name", - "theme_id": 1 + "theme_id": 1, "color_scheme_id": 2 }, { @@ -38,7 +38,7 @@ GET /users "twitter": "", "extern_uid": "jack.smith", "provider": "provider_name", - "theme_id": 1 + "theme_id": 1, "color_scheme_id": 3 } ] @@ -71,7 +71,7 @@ Parameters: "twitter": "", "extern_uid": "john.smith", "provider": "provider_name", - "theme_id": 1 + "theme_id": 1, "color_scheme_id": 2 } ``` @@ -162,8 +162,8 @@ GET /user "skype": "", "linkedin": "", "twitter": "", - "theme_id": 1 - "color_scheme_id": 2 + "theme_id": 1, + "color_scheme_id": 2, "is_admin": false, "can_create_group" : true, "can_create_team" : true, @@ -184,14 +184,14 @@ GET /user/keys [ { "id": 1, - "title" : "Public key" + "title" : "Public key", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4 596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4 soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", }, { "id": 3, - "title" : "Another Public key" + "title" : "Another Public key", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4 596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4 soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=" @@ -219,7 +219,7 @@ Parameters: ```json { "id": 1, - "title" : "Public key" + "title" : "Public key", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4 596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4 soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=" -- GitLab From 84992cd0fac36846ebfde5800d52158258107ecc Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 1 Sep 2013 01:04:22 +0300 Subject: [PATCH 106/175] Use original raphael-rails v2.1.2 --- Gemfile | 2 +- Gemfile.lock | 9 ++------- db/schema.rb | 4 ++-- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/Gemfile b/Gemfile index c80705af316..5b8118457d3 100644 --- a/Gemfile +++ b/Gemfile @@ -134,7 +134,7 @@ group :assets do gem "jquery-rails", "2.1.3" gem "jquery-ui-rails", "2.0.2" gem "modernizr", "2.6.2" - gem "raphael-rails", git: "https://github.com/gitlabhq/raphael-rails.git" + gem "raphael-rails", "~> 2.1.2" gem 'bootstrap-sass' gem "font-awesome-rails" gem "gemoji", "~> 1.2.1", require: 'emoji/railtie' diff --git a/Gemfile.lock b/Gemfile.lock index e608afad1e7..d71988e13e6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,12 +6,6 @@ GIT activerecord (>= 2.3.0) rake (>= 0.8.7) -GIT - remote: https://github.com/gitlabhq/raphael-rails.git - revision: cb2c92a040b9b941a5f1aa1ea866cc26e944fe58 - specs: - raphael-rails (2.1.0) - GEM remote: https://rubygems.org/ specs: @@ -380,6 +374,7 @@ GEM thor (>= 0.14.6, < 2.0) raindrops (0.11.0) rake (10.1.0) + raphael-rails (2.1.2) rb-fsevent (0.9.3) rb-inotify (0.9.0) ffi (>= 0.5.0) @@ -611,7 +606,7 @@ DEPENDENCIES rails (= 3.2.13) rails-dev-tweaks rails_best_practices - raphael-rails! + raphael-rails (~> 2.1.2) rb-fsevent rb-inotify redcarpet (~> 2.2.2) diff --git a/db/schema.rb b/db/schema.rb index 5020230d831..654f2b1e8f7 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -144,8 +144,8 @@ ActiveRecord::Schema.define(:version => 20130821090531) do t.text "note" t.string "noteable_type" t.integer "author_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.integer "project_id" t.string "attachment" t.string "line_code" -- GitLab From a848d9dbccce3621041f8b71a3de96c660489697 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Sun, 1 Sep 2013 12:13:17 +0200 Subject: [PATCH 107/175] Refactor contributing process to make it more readable and make sure other core team members are mentioned. --- PROCESS.md | 72 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/PROCESS.md b/PROCESS.md index 17684ae5c71..a7a61c5231a 100644 --- a/PROCESS.md +++ b/PROCESS.md @@ -2,23 +2,47 @@ ## Purpose of describing the contributing process -Below we describe the contributing process for two reasons. Contributors know what to expect from maintainers (initial, response within xx days, friendly treatment, etc). And maintainers know what to expect from contributors (use latest version, confirm the issue is addressed, friendly treatment, etc). +Below we describe the contributing process to GitLab for two reasons. So that contributors know what to expect from maintainers (possible responses, friendly treatment, etc.). And so that maintainers know what to expect from contributors (use the latest version, ensure that the issue is addressed, friendly treatment, etc.). -## How we handle issues +## Common actions -The priority should be mentioning people that can help and assigning workflow labels. Workflow labels are purposely not very detailed since that would be hard to keep updated as you would need to reevaluate them after every comment. We optionally use functional labels on demand when want to group related issues to get an overview (for example all issues related to RVM, to tackle them in one go) and to add details to the issue. +### Issue team +- Looks for issues without workflow labels and triages issue +- Monitors pull requests +- Closes invalid issues and pull requests with a comment (duplicates, [feature requests](#feature-requests), [fixed in newer version](#issue-fixed-in-newer-version), [issue report for old version](#issue-report-for-old-version), not a problem in GitLab, etc.) +- Assigns appropriate [labels](#how-we-handle-issues) +- Asks for feedback from issue reporter/pull request initiator ([invalid issue reports](#improperly-formatted-issue), [format code](#code-format), etc.) +- Asks for feedback from the relevant developer(s) based on the [list of members and their specialities](http://gitlab.org/team/) +- Monitors all issues/pull requests for feedback (but especially ones commented on since automatically watching them): +- Closes issues with no feedback from the reporter for two weeks +- Closes stale pull requests -If an issue is complex and needs the attention of a specific person, assignment is a good option but assigning issues might discourage other people from contributing to that issue. We need all the contributions we can get so this should never be discouraged. Also, an assigned person might not have time for a few weeks, so others should feel free to takeover. +### Development team -Priority (from high to low): +- Responds to issues and pull requests the issue team mentions them in +- Monitors for new issues in _Awaiting developer action/feedback_ with no developer activity (once a week) +- Monitors for new pull requests (at least once a week) +- Manages their work queue by looking at issues and pull requests assigned to them +- Close fixed issues (via commit messages or manually) +- Codes [new features](http://feedback.gitlab.com/forums/176466-general/filters/top)! +- Response guidelines +- Be kind to people trying to contribute. Be aware that people can be a non-native or a native English speaker, they might not understand thing or they might be very sensitive to how your word things. Use emoji to express your feelings (hearth, star, smile, etc.). Some good tips about giving feedback to pull requests is in the [Thoughtbot code review guide](https://github.com/thoughtbot/guides/tree/master/code-review). + +## Priorities of the issue team + +1. Mentioning people (critical) +2. Workflow labels (normal) +3. Functional labels (minor) +4. Assigning issues (avoid if possible) -1. Mentioning people (very important) -2. Workflow labels -3. Functional labels (less important) -4. Assigning issues (optional) +## Mentioning people + +The most important thing is making sure valid issues receive feedback from the development team. Therefore the priority is mentioning developers that can help on those issue. Please select someone with relevant experience from [GitLab core team](http://gitlab.org/team/). If there is nobody mentioned with that expertise look in the commit history for the affected files to find someone. Avoid mentioning the lead developer, this is the person that is least likely to give a timely response. If the involvement of the lead developer is needed the other core team members will mention this person. ## Workflow labels +Workflow labels are purposely not very detailed since that would be hard to keep updated as you would need to reevaluate them after every comment. We optionally use functional labels on demand when want to group related issues to get an overview (for example all issues related to RVM, to tackle them in one go) and to add details to the issue. + - _Awaiting feedback_: Feedback pending from the reporter - _Awaiting confirmation of fix_: The issue should already be solved in **master** (generally you can avoid this workflow item and just close the issue right away) - _Attached PR_: There is a PR attached and the discussion should happen there @@ -29,6 +53,10 @@ Priority (from high to low): These labels describe what development specialities are involved such as: PostgreSQL, UX, LDAP. +## Assigning issues + +If an issue is complex and needs the attention of a specific person, assignment is a good option but assigning issues might discourage other people from contributing to that issue. We need all the contributions we can get so this should never be discouraged. Also, an assigned person might not have time for a few weeks, so others should feel free to takeover. + ## Label colors - Light orange `#fef2c0`: workflow labels for issue team members (awaiting feedback, awaiting confirmation of fix) - Bright orange `#eb6420`: workflow labels for core team members (attached PR, awaiting developer action/feedback) @@ -37,32 +65,6 @@ These labels describe what development specialities are involved such as: Postgr - Feature request (see copy & paste response: [Feature requests](#feature-requests)) - Support (see copy & paste response: [Support requests and configuration questions](#support-requests-and-configuration-questions) -## Common actions - -### Issue team -- Looks for issues without workflow labels and triages issue -- Monitors pull requests -- Closes invalid issues and pull requests with a comment (duplicates, [feature requests](#feature-requests), [fixed in newer version](#issue-fixed-in-newer-version), [issue report for old version](#issue-report-for-old-version), not a problem in GitLab, etc.) -- Assigns appropriate [labels](#how-we-handle-issues) -- Asks for feedback from issue reporter/pull request initiator ([invalid issue reports](#improperly-formatted-issue), [format code](#code-format), etc.) -- Asks for feedback from the relevant developer(s) based on the [list of members and their specialities](http://gitlab.org/team/) -- Monitors all issues/pull requests for feedback (but especially ones commented on since automatically watching them): -- Assigns issues to developers if they indicate they are fixing it -- Assigns pull requests to developers if they indicate they will take care of merge -- Closes issues with no feedback from the reporter for two weeks -- Closes stale pull requests - -### Development team - -- Responds to issues and pull requests the issue team mentions them in -- Monitors for new issues in _Awaiting developer action/feedback_ with no developer activity (once a week) -- Monitors for new pull requests (at least once a week) -- Manages their work queue by looking at issues and pull requests assigned to them -- Close fixed issues (via commit messages or manually) -- Codes [new features](http://feedback.gitlab.com/forums/176466-general/filters/top)! -- Response guidelines -- Be kind to people trying to contribute. Be aware that people can be a non-native or a native English speaker, they might not understand thing or they might be very sensitive to how your word things. Use emoji to express your feelings (hearth, star, smile, etc.). Some good tips about giving feedback to pull requests is in the [Thoughtbot code review guide](https://github.com/thoughtbot/guides/tree/master/code-review). - ## Copy & paste responses ### Improperly formatted issue -- GitLab From 1f3f874142775ba6d074460a570c69e1fb02e096 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 1 Sep 2013 22:07:02 +0300 Subject: [PATCH 108/175] Color in .rspec --- .rspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.rspec b/.rspec index 5902dd3af1f..7488cbe7792 100644 --- a/.rspec +++ b/.rspec @@ -1 +1 @@ ---colour --drb +--color --drb -- GitLab From 6bf117c601eda2ae3045644ab778d167955cd0c3 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 2 Sep 2013 23:35:40 +0300 Subject: [PATCH 109/175] Mode User+LDAP functionality from Gitlab::Auth --- .../omniauth_callbacks_controller.rb | 12 +-- app/models/user.rb | 1 + lib/gitlab/auth.rb | 17 ---- lib/gitlab/ldap/user.rb | 92 +++++++++++++++++++ 4 files changed, 99 insertions(+), 23 deletions(-) create mode 100644 lib/gitlab/ldap/user.rb diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb index c4ebf0e4889..b0765672dda 100644 --- a/app/controllers/omniauth_callbacks_controller.rb +++ b/app/controllers/omniauth_callbacks_controller.rb @@ -16,12 +16,12 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController end def ldap - # We only find ourselves here if the authentication to LDAP was successful. - @user = User.find_for_ldap_auth(request.env["omniauth.auth"], current_user) - if @user.persisted? - @user.remember_me = true - end - sign_in_and_redirect @user + # We only find ourselves here + # if the authentication to LDAP was successful. + @user = Gitlab::LDAP::User.find_or_create(request.env["omniauth.auth"]) + @user.remember_me = true if @user.persisted? + + sign_in_and_redirect(@user) end private diff --git a/app/models/user.rb b/app/models/user.rb index b44c063c32f..823e7a24a25 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -159,6 +159,7 @@ class User < ActiveRecord::Base scope :not_in_team, ->(team){ where('users.id NOT IN (:ids)', ids: team.member_ids) } scope :not_in_project, ->(project) { project.users.present? ? where("id not in (:ids)", ids: project.users.map(&:id) ) : scoped } scope :without_projects, -> { where('id NOT IN (SELECT DISTINCT(user_id) FROM users_projects)') } + scope :ldap, -> { where(provider: 'ldap') } scope :potential_team_members, ->(team) { team.members.any? ? active.not_in_team(team) : active } diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb index de70c5ce780..5f4b6c22c2c 100644 --- a/lib/gitlab/auth.rb +++ b/lib/gitlab/auth.rb @@ -13,23 +13,6 @@ module Gitlab end end - def find_for_ldap_auth(auth, signed_in_resource = nil) - uid = auth.info.uid - provider = auth.provider - email = auth.info.email.downcase unless auth.info.email.nil? - raise OmniAuth::Error, "LDAP accounts must provide an uid and email address" if uid.nil? or email.nil? - - if @user = User.find_by_extern_uid_and_provider(uid, provider) - @user - elsif @user = User.find_by_email(email) - log.info "Updating legacy LDAP user #{email} with extern_uid => #{uid}" - @user.update_attributes(extern_uid: uid, provider: provider) - @user - else - create_from_omniauth(auth, true) - end - end - def create_from_omniauth(auth, ldap = false) provider = auth.provider uid = auth.info.uid || auth.uid diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb new file mode 100644 index 00000000000..a7a11e5a640 --- /dev/null +++ b/lib/gitlab/ldap/user.rb @@ -0,0 +1,92 @@ +# LDAP extension for User model +# +# * Find or create user from omniauth.auth data +# * Links LDAP account with existing user +# +module Gitlab + module LDAP + class User + class << self + def find(uid, email) + # Look for user with ldap provider and same uid + user = model.ldap.where(extern_uid: uid).last + return user if user + + # Look for user with same emails + # + # Possible cases: + # * When user already has account and need to link his LDAP account. + # * LDAP uid changed for user with same email and we need to update his uid + # + user = model.find_by_email(email) + + if user + user.update_attributes(extern_uid: uid, provider: 'ldap') + log.info("(LDAP) Updating legacy LDAP user #{email} with extern_uid => #{uid}") + end + + user + end + + def create(uid, email, name) + password = Devise.friendly_token[0, 8].downcase + username = email.match(/^[^@]*/)[0] + + opts = { + extern_uid: uid, + provider: 'ldap', + name: name, + username: username, + email: email, + password: password, + password_confirmation: password, + } + + user = model.new(opts, as: :admin).with_defaults + user.save! + log.info "(LDAP) Creating user #{email} from login with extern_uid => #{uid}" + + user + end + + def find_or_create(auth) + uid, email, name = uid(auth), email(auth), name(auth) + + if uid.blank? || email.blank? + raise_error("Account must provide an uid and email address") + end + + user = find(uid, email) + user = create(uid, email, name) unless user + user + end + + private + + def uid(auth) + auth.info.uid + end + + def email(auth) + auth.info.email.downcase unless auth.info.email.nil? + end + + def name(auth) + auth.info.name.to_s.force_encoding("utf-8") + end + + def log + Gitlab::AppLogger + end + + def raise_error(message) + raise OmniAuth::Error, "(LDAP) " + message + end + + def model + ::User + end + end + end + end +end -- GitLab From 71abf70458ca1f6d85bc828b215931eaf3639b5d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 2 Sep 2013 23:50:45 +0300 Subject: [PATCH 110/175] Move ldap auth to LDAP::User. Removed unused code --- lib/gitlab/auth.rb | 19 ++++--------------- lib/gitlab/backend/grack_ldap.rb | 24 ------------------------ lib/gitlab/ldap/user.rb | 25 ++++++++++++++++++++++++- 3 files changed, 28 insertions(+), 40 deletions(-) delete mode 100644 lib/gitlab/backend/grack_ldap.rb diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb index 5f4b6c22c2c..34e25bc9ccb 100644 --- a/lib/gitlab/auth.rb +++ b/lib/gitlab/auth.rb @@ -66,23 +66,12 @@ module Gitlab Gitlab::AppLogger end - def ldap_auth(login, password) - # Check user against LDAP backend if user is not authenticated - # Only check with valid login and password to prevent anonymous bind results - return nil unless ldap_conf.enabled && !login.blank? && !password.blank? - - ldap = OmniAuth::LDAP::Adaptor.new(ldap_conf) - ldap_user = ldap.bind_as( - filter: Net::LDAP::Filter.eq(ldap.uid, login), - size: 1, - password: password - ) - - User.find_by_extern_uid_and_provider(ldap_user.dn, 'ldap') if ldap_user - end - def ldap_conf @ldap_conf ||= Gitlab.config.ldap end + + def ldap_auth(login, password) + Gitlab::LDAP::User.auth(login, password) + end end end diff --git a/lib/gitlab/backend/grack_ldap.rb b/lib/gitlab/backend/grack_ldap.rb deleted file mode 100644 index 45e98fbac1e..00000000000 --- a/lib/gitlab/backend/grack_ldap.rb +++ /dev/null @@ -1,24 +0,0 @@ -require 'omniauth-ldap' - -module Grack - module LDAP - def ldap_auth(login, password) - # Check user against LDAP backend if user is not authenticated - # Only check with valid login and password to prevent anonymous bind results - return nil unless ldap_conf.enabled && !login.blank? && !password.blank? - - ldap = OmniAuth::LDAP::Adaptor.new(ldap_conf) - ldap_user = ldap.bind_as( - filter: Net::LDAP::Filter.eq(ldap.uid, login), - size: 1, - password: password - ) - - User.find_by_extern_uid_and_provider(ldap_user.dn, 'ldap') if ldap_user - end - - def ldap_conf - @ldap_conf ||= Gitlab.config.ldap - end - end -end diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb index a7a11e5a640..fe4a93f3fe7 100644 --- a/lib/gitlab/ldap/user.rb +++ b/lib/gitlab/ldap/user.rb @@ -9,7 +9,7 @@ module Gitlab class << self def find(uid, email) # Look for user with ldap provider and same uid - user = model.ldap.where(extern_uid: uid).last + user = find_by_uid(uid) return user if user # Look for user with same emails @@ -61,6 +61,25 @@ module Gitlab user end + def find_by_uid(uid) + model.ldap.where(extern_uid: uid).last + end + + def auth(login, password) + # Check user against LDAP backend if user is not authenticated + # Only check with valid login and password to prevent anonymous bind results + return nil unless ldap_conf.enabled && login.present? && password.present? + + ldap = OmniAuth::LDAP::Adaptor.new(ldap_conf) + ldap_user = ldap.bind_as( + filter: Net::LDAP::Filter.eq(ldap.uid, login), + size: 1, + password: password + ) + + find_by_uid(ldap_user.dn) if ldap_user + end + private def uid(auth) @@ -86,6 +105,10 @@ module Gitlab def model ::User end + + def ldap_conf + Gitlab.config.ldap + end end end end -- GitLab From 7dfb2b6379719cd6c3ee7b919f973146e9dbc645 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 2 Sep 2013 23:52:58 +0300 Subject: [PATCH 111/175] Remove include of grack_ldap --- lib/gitlab/backend/grack_auth.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/gitlab/backend/grack_auth.rb b/lib/gitlab/backend/grack_auth.rb index be5c58bb5a6..c522e0a413b 100644 --- a/lib/gitlab/backend/grack_auth.rb +++ b/lib/gitlab/backend/grack_auth.rb @@ -1,10 +1,8 @@ require_relative 'shell_env' -require_relative 'grack_ldap' require_relative 'grack_helpers' module Grack class Auth < Rack::Auth::Basic - include LDAP include Helpers attr_accessor :user, :project, :ref, :env -- GitLab From 54faf7871ee43115e972f3cb70d93fde01f030e1 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 3 Sep 2013 00:09:20 +0300 Subject: [PATCH 112/175] Use normal font-weight for file names on tree view --- app/assets/stylesheets/sections/tree.scss | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/assets/stylesheets/sections/tree.scss b/app/assets/stylesheets/sections/tree.scss index b8b82bcf68c..850ed831dfb 100644 --- a/app/assets/stylesheets/sections/tree.scss +++ b/app/assets/stylesheets/sections/tree.scss @@ -15,6 +15,12 @@ .tree-table { @include border-radius(0); .tree-item { + td { + padding: 8px 10px; + strong { + font-weight: normal; + } + } &:hover { td { background: $hover; -- GitLab From e832c4d90d3482a58d2b50ceadfdebc75c93a765 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Tue, 3 Sep 2013 07:25:39 +0200 Subject: [PATCH 113/175] Add 'notes' to path blacklist, fixes #4967 --- lib/gitlab/blacklist.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gitlab/blacklist.rb b/lib/gitlab/blacklist.rb index 26f987b200c..2f9091e07df 100644 --- a/lib/gitlab/blacklist.rb +++ b/lib/gitlab/blacklist.rb @@ -3,7 +3,7 @@ module Gitlab extend self def path - %w(admin dashboard groups help profile projects search public assets u s teams merge_requests issues users snippets services repository hooks) + %w(admin dashboard groups help profile projects search public assets u s teams merge_requests issues users snippets services repository hooks notes) end end end -- GitLab From fe8fa9a58110a70645edfa3ce0320a292da39fce Mon Sep 17 00:00:00 2001 From: Rovanion Date: Tue, 3 Sep 2013 14:24:20 +0200 Subject: [PATCH 114/175] Made script path flexible --- lib/support/init.d/gitlab | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab index a05227ceb1b..79c56a9854b 100755 --- a/lib/support/init.d/gitlab +++ b/lib/support/init.d/gitlab @@ -35,7 +35,7 @@ sidekiq_pid_path="$pid_path/sidekiq.pid" # Switch to the app_user if it is not he/she who is running the script. if [ "$USER" != "$app_user" ]; then - sudo -u "$app_user" -H /etc/init.d/gitlab "$@"; exit; + sudo -u "$app_user" -H $0 "$@"; exit; fi # Switch to the gitlab path, if it fails exit with an error. -- GitLab From ad5228481019e1f282d3a32249e801d15f0690d4 Mon Sep 17 00:00:00 2001 From: Robert Djurasaj Date: Tue, 3 Sep 2013 09:09:12 -0600 Subject: [PATCH 115/175] Update installation docs to use v1.7.1 of gitlab-shell --- doc/install/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index 6523961d4d5..dd696f954aa 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -122,7 +122,7 @@ GitLab Shell is a ssh access and repository management software developed specia cd gitlab-shell # switch to right version - sudo -u git -H git checkout v1.7.0 + sudo -u git -H git checkout v1.7.1 sudo -u git -H cp config.yml.example config.yml -- GitLab From 38cebe03bcd49895332401e5103925754ab7db85 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 3 Sep 2013 20:55:01 +0300 Subject: [PATCH 116/175] Dont allow html render for RAW view --- app/controllers/projects/raw_controller.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb index 0d35f373e9c..0c23d411f4c 100644 --- a/app/controllers/projects/raw_controller.rb +++ b/app/controllers/projects/raw_controller.rb @@ -11,9 +11,17 @@ class Projects::RawController < Projects::ApplicationController @blob = Gitlab::Git::Blob.new(@repository, @commit.id, @ref, @path) if @blob.exists? + type = if @blob.mime_type =~ /html|javascript/ + 'text/plain; charset=utf-8' + else + @blob.mime_type + end + + headers['X-Content-Type-Options'] = 'nosniff' + send_data( @blob.data, - type: @blob.mime_type, + type: type, disposition: 'inline', filename: @blob.name ) -- GitLab From cdc4d64da6fc6fbb6c3b78c5e07cdddd91a4c900 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 3 Sep 2013 23:58:42 +0300 Subject: [PATCH 117/175] Dont show remove user button for ldap user --- app/views/profiles/account.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/profiles/account.html.haml b/app/views/profiles/account.html.haml index d711d55ec99..42214a1b46f 100644 --- a/app/views/profiles/account.html.haml +++ b/app/views/profiles/account.html.haml @@ -86,7 +86,7 @@ .controls = f.submit 'Save username', class: "btn btn-save" -- if gitlab_config.signup_enabled +- if gitlab_config.signup_enabled && !current_user.ldap_user? %fieldset.remove-account %legend Remove account -- GitLab From b45e92646e3f91c60e25197d68f72f50b1754c99 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 4 Sep 2013 00:04:27 +0300 Subject: [PATCH 118/175] Added Gitlab::OAuth::User class Authenticate or create users from OAuth providers --- lib/gitlab/oauth/user.rb | 85 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 lib/gitlab/oauth/user.rb diff --git a/lib/gitlab/oauth/user.rb b/lib/gitlab/oauth/user.rb new file mode 100644 index 00000000000..515c5b769e5 --- /dev/null +++ b/lib/gitlab/oauth/user.rb @@ -0,0 +1,85 @@ +# OAuth extension for User model +# +# * Find GitLab user based on omniauth uid and provider +# * Create new user from omniauth data +# +module Gitlab + module OAuth + class User + class << self + attr_reader :auth + + def find(auth) + @auth = auth + find_by_uid_and_provider + end + + def create(auth) + @auth = auth + password = Devise.friendly_token[0, 8].downcase + opts = { + extern_uid: uid, + provider: provider, + name: name, + username: username, + email: email, + password: password, + password_confirmation: password, + } + + user = model.new(opts, as: :admin).with_defaults + user.save! + log.info "(OAuth) Creating user #{email} from login with extern_uid => #{uid}" + + if Gitlab.config.omniauth['block_auto_created_users'] && !ldap? + user.block + end + + user + end + + private + + def find_by_uid_and_provider + model.where(provider: provider, extern_uid: uid).last + end + + def uid + auth.info.uid || auth.uid + end + + def email + auth.info.email.downcase unless auth.info.email.nil? + end + + def name + auth.info.name.to_s.force_encoding("utf-8") + end + + def username + email.match(/^[^@]*/)[0] + end + + def provider + auth.provider + end + + def log + Gitlab::AppLogger + end + + def model + ::User + end + + def raise_error(message) + raise OmniAuth::Error, "(OAuth) " + message + end + + def ldap? + provider == 'ldap' + end + end + end + end +end -- GitLab From 0df1cf7fcceee10db1e66ecf99dcd453d9e687a4 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 4 Sep 2013 00:06:13 +0300 Subject: [PATCH 119/175] Inherit Gitlab::LDAP::User from Gitlab::OAuth::User --- lib/gitlab/ldap/user.rb | 100 +++++++++++++--------------------------- 1 file changed, 33 insertions(+), 67 deletions(-) diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb index fe4a93f3fe7..c8f3a69376a 100644 --- a/lib/gitlab/ldap/user.rb +++ b/lib/gitlab/ldap/user.rb @@ -1,71 +1,49 @@ +require 'gitlab/oauth/user' + # LDAP extension for User model # # * Find or create user from omniauth.auth data # * Links LDAP account with existing user +# * Auth LDAP user with login and password # module Gitlab module LDAP - class User + class User < Gitlab::OAuth::User class << self - def find(uid, email) - # Look for user with ldap provider and same uid - user = find_by_uid(uid) - return user if user - - # Look for user with same emails - # - # Possible cases: - # * When user already has account and need to link his LDAP account. - # * LDAP uid changed for user with same email and we need to update his uid - # - user = model.find_by_email(email) - - if user - user.update_attributes(extern_uid: uid, provider: 'ldap') - log.info("(LDAP) Updating legacy LDAP user #{email} with extern_uid => #{uid}") - end - - user - end - - def create(uid, email, name) - password = Devise.friendly_token[0, 8].downcase - username = email.match(/^[^@]*/)[0] - - opts = { - extern_uid: uid, - provider: 'ldap', - name: name, - username: username, - email: email, - password: password, - password_confirmation: password, - } - - user = model.new(opts, as: :admin).with_defaults - user.save! - log.info "(LDAP) Creating user #{email} from login with extern_uid => #{uid}" - - user - end - def find_or_create(auth) - uid, email, name = uid(auth), email(auth), name(auth) + @auth = auth if uid.blank? || email.blank? raise_error("Account must provide an uid and email address") end - user = find(uid, email) - user = create(uid, email, name) unless user - user - end + user = find(auth) + + unless user + # Look for user with same emails + # + # Possible cases: + # * When user already has account and need to link his LDAP account. + # * LDAP uid changed for user with same email and we need to update his uid + # + user = model.find_by_email(email) + + if user + user.update_attributes(extern_uid: uid, provider: provider) + log.info("(LDAP) Updating legacy LDAP user #{email} with extern_uid => #{uid}") + else + # Create a new user inside GitLab database + # based on LDAP credentials + # + # + user = create(auth) + end + end - def find_by_uid(uid) - model.ldap.where(extern_uid: uid).last + user end - def auth(login, password) + def authenticate(login, password) # Check user against LDAP backend if user is not authenticated # Only check with valid login and password to prevent anonymous bind results return nil unless ldap_conf.enabled && login.present? && password.present? @@ -82,30 +60,18 @@ module Gitlab private - def uid(auth) - auth.info.uid - end - - def email(auth) - auth.info.email.downcase unless auth.info.email.nil? - end - - def name(auth) - auth.info.name.to_s.force_encoding("utf-8") + def find_by_uid(uid) + model.where(provider: provider, extern_uid: uid).last end - def log - Gitlab::AppLogger + def provider + 'ldap' end def raise_error(message) raise OmniAuth::Error, "(LDAP) " + message end - def model - ::User - end - def ldap_conf Gitlab.config.ldap end -- GitLab From 9028999c933a3db790ef4645474d7b04888a308f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 4 Sep 2013 00:06:29 +0300 Subject: [PATCH 120/175] Use new OAuth classes --- .../omniauth_callbacks_controller.rb | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb index b0765672dda..7131e0fe181 100644 --- a/app/controllers/omniauth_callbacks_controller.rb +++ b/app/controllers/omniauth_callbacks_controller.rb @@ -18,33 +18,39 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController def ldap # We only find ourselves here # if the authentication to LDAP was successful. - @user = Gitlab::LDAP::User.find_or_create(request.env["omniauth.auth"]) + @user = Gitlab::LDAP::User.find_or_create(oauth) @user.remember_me = true if @user.persisted? - sign_in_and_redirect(@user) end private def handle_omniauth - oauth = request.env['omniauth.auth'] - provider, uid = oauth['provider'], oauth['uid'] - if current_user # Change a logged-in user's authentication method: - current_user.extern_uid = uid - current_user.provider = provider + current_user.extern_uid = oauth['uid'] + current_user.provider = oauth['provider'] current_user.save redirect_to profile_path else - @user = User.find_or_new_for_omniauth(oauth) + @user = Gitlab::OAuth::User.find(oauth) + + # Create user if does not exist + # and allow_single_sign_on is true + if Gitlab.config.omniauth['allow_single_sign_on'] + @user ||= Gitlab::OAuth::User.create(oauth) + end if @user - sign_in_and_redirect @user + sign_in_and_redirect(@user) else flash[:notice] = "There's no such user!" redirect_to new_user_session_path end end end + + def oauth + @oauth ||= request.env['omniauth.auth'] + end end -- GitLab From 3707cc119b291c06703ebf31456c4b8140c324c6 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 4 Sep 2013 00:12:00 +0300 Subject: [PATCH 121/175] Refactor Gitlab::Auth --- app/models/user.rb | 16 -------------- lib/gitlab/auth.rb | 55 +--------------------------------------------- 2 files changed, 1 insertion(+), 70 deletions(-) diff --git a/app/models/user.rb b/app/models/user.rb index 823e7a24a25..b593c22fde3 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -187,22 +187,6 @@ class User < ActiveRecord::Base end end - def create_from_omniauth(auth, ldap = false) - gitlab_auth.create_from_omniauth(auth, ldap) - end - - def find_or_new_for_omniauth(auth) - gitlab_auth.find_or_new_for_omniauth(auth) - end - - def find_for_ldap_auth(auth, signed_in_resource = nil) - gitlab_auth.find_for_ldap_auth(auth, signed_in_resource) - end - - def gitlab_auth - Gitlab::Auth.new - end - def search query where("name LIKE :query OR email LIKE :query OR username LIKE :query", query: "%#{query}%") end diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb index 34e25bc9ccb..0f196297477 100644 --- a/lib/gitlab/auth.rb +++ b/lib/gitlab/auth.rb @@ -7,61 +7,12 @@ module Gitlab # Second chance - try LDAP authentication return nil unless ldap_conf.enabled - ldap_auth(login, password) + Gitlab::LDAP::User.authenticate(login, password) else user if user.valid_password?(password) end end - def create_from_omniauth(auth, ldap = false) - provider = auth.provider - uid = auth.info.uid || auth.uid - uid = uid.to_s.force_encoding("utf-8") - name = auth.info.name.to_s.force_encoding("utf-8") - email = auth.info.email.to_s.downcase unless auth.info.email.nil? - - ldap_prefix = ldap ? '(LDAP) ' : '' - raise OmniAuth::Error, "#{ldap_prefix}#{provider} does not provide an email"\ - " address" if auth.info.email.blank? - - log.info "#{ldap_prefix}Creating user from #{provider} login"\ - " {uid => #{uid}, name => #{name}, email => #{email}}" - password = Devise.friendly_token[0, 8].downcase - @user = User.new({ - extern_uid: uid, - provider: provider, - name: name, - username: email.match(/^[^@]*/)[0], - email: email, - password: password, - password_confirmation: password, - }, as: :admin).with_defaults - @user.save! - - if Gitlab.config.omniauth['block_auto_created_users'] && !ldap - @user.block - end - - @user - end - - def find_or_new_for_omniauth(auth) - provider, uid = auth.provider, auth.uid - email = auth.info.email.downcase unless auth.info.email.nil? - - if @user = User.find_by_provider_and_extern_uid(provider, uid) - @user - elsif @user = User.find_by_email(email) - @user.update_attributes(extern_uid: uid, provider: provider) - @user - else - if Gitlab.config.omniauth['allow_single_sign_on'] - @user = create_from_omniauth(auth) - @user - end - end - end - def log Gitlab::AppLogger end @@ -69,9 +20,5 @@ module Gitlab def ldap_conf @ldap_conf ||= Gitlab.config.ldap end - - def ldap_auth(login, password) - Gitlab::LDAP::User.auth(login, password) - end end end -- GitLab From 3832b2aa679d71dc857f4a6083f0038a2eeb7a9f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 4 Sep 2013 00:53:01 +0300 Subject: [PATCH 122/175] Improve Profile#account page --- app/helpers/profile_helper.rb | 12 ++ app/views/profiles/account.html.haml | 195 ++++++++++++++++----------- 2 files changed, 128 insertions(+), 79 deletions(-) diff --git a/app/helpers/profile_helper.rb b/app/helpers/profile_helper.rb index 80d67009f59..88d9f184d0e 100644 --- a/app/helpers/profile_helper.rb +++ b/app/helpers/profile_helper.rb @@ -4,4 +4,16 @@ module ProfileHelper 'active' end end + + def show_profile_username_tab? + current_user.can_change_username? + end + + def show_profile_social_tab? + Gitlab.config.omniauth.enabled && !current_user.ldap_user? + end + + def show_profile_remove_tab? + Gitlab.config.gitlab.signup_enabled && !current_user.ldap_user? + end end diff --git a/app/views/profiles/account.html.haml b/app/views/profiles/account.html.haml index 42214a1b46f..8f43db66249 100644 --- a/app/views/profiles/account.html.haml +++ b/app/views/profiles/account.html.haml @@ -5,91 +5,128 @@ - if current_user.ldap_user? Some options are unavailable for LDAP accounts %hr -- unless current_user.ldap_user? - - if Gitlab.config.omniauth.enabled - %fieldset - %legend Social Accounts - .oauth_select_holder - %p.hint Tip: Click on icon to activate signin with one of the following services - - enabled_social_providers.each do |provider| - %span{class: oauth_active_class(provider) } - = link_to authbutton(provider, 32), omniauth_authorize_path(User, provider) - %fieldset.update-password - %legend Password - = form_for @user, url: update_password_profile_path, method: :put do |f| - .padded - %p.slead After a successful password update you will be redirected to login page where you should login with your new password - -if @user.errors.any? - .alert.alert-error - %ul - - @user.errors.full_messages.each do |msg| - %li= msg +.row + .span2 + %ul.nav.nav-pills.nav-stacked.nav-stacked-menu + %li.active + = link_to '#tab-token', 'data-toggle' => 'tab' do + Private Token + %li + = link_to '#tab-password', 'data-toggle' => 'tab' do + Password - .control-group - = f.label :password - .controls= f.password_field :password, required: true - .control-group - = f.label :password_confirmation - .controls - = f.password_field :password_confirmation, required: true - .control-group - .controls - = f.submit 'Save password', class: "btn btn-save" + - if show_profile_social_tab? + %li + = link_to '#tab-social', 'data-toggle' => 'tab' do + Social Accounts + - if show_profile_username_tab? + %li + = link_to '#tab-username', 'data-toggle' => 'tab' do + Change Username + - if show_profile_remove_tab? + %li + = link_to '#tab-remove', 'data-toggle' => 'tab' do + Remove Account + .span10 + .tab-content + .tab-pane.active#tab-token + %fieldset.update-token + %legend + Private token + %span.cred.pull-right + keep it secret! + %div + = form_for @user, url: reset_private_token_profile_path, method: :put do |f| + .data + %p.slead + Your private token is used to access application resources without authentication. + %br + It can be used for atom feeds or the API. + %p.cgray + - if current_user.private_token + = text_field_tag "token", current_user.private_token, class: "input-xxlarge large_text input-xpadding" + = f.submit 'Reset', confirm: "Are you sure?", class: "btn btn-primary btn-build-token" + - else + %span You don`t have one yet. Click generate to fix it. + = f.submit 'Generate', class: "btn success btn-build-token" -%fieldset.update-token - %legend - Private token - %span.cred.pull-right - keep it secret! - .padded - = form_for @user, url: reset_private_token_profile_path, method: :put do |f| - .data - %p.slead - Your private token is used to access application resources without authentication. - %br - It can be used for atom feeds or the API. - %p.cgray - - if current_user.private_token - = text_field_tag "token", current_user.private_token, class: "input-xxlarge large_text input-xpadding" - = f.submit 'Reset', confirm: "Are you sure?", class: "btn btn-primary btn-build-token" - - else - %span You don`t have one yet. Click generate to fix it. - = f.submit 'Generate', class: "btn success btn-build-token" + .tab-pane#tab-password + %fieldset.update-password + %legend Password + = form_for @user, url: update_password_profile_path, method: :put do |f| + %div + %p.slead After a successful password update you will be redirected to login page where you should login with your new password + -if @user.errors.any? + .alert.alert-error + %ul + - @user.errors.full_messages.each do |msg| + %li= msg + .control-group + = f.label :password + .controls= f.password_field :password, required: true + .control-group + = f.label :password_confirmation + .controls + = f.password_field :password_confirmation, required: true + .control-group + .controls + = f.submit 'Save password', class: "btn btn-save" + - if show_profile_social_tab? + .tab-pane#tab-social + %fieldset + %legend Social Accounts + .oauth_select_holder + %p.hint Tip: Click on icon to activate signin with one of the following services + - enabled_social_providers.each do |provider| + %span{class: oauth_active_class(provider) } + = link_to authbutton(provider, 32), omniauth_authorize_path(User, provider) -- if current_user.can_change_username? - %fieldset.update-username - %legend - Username - %small.cred.pull-right - Changing your username can have unintended side effects! - = form_for @user, url: update_username_profile_path, method: :put, remote: true do |f| - .padded - = f.label :username - .controls - = f.text_field :username, required: true -   - %span.loading-gif.hide= image_tag "ajax_loader.gif" - %span.update-success.cgreen.hide - %i.icon-ok - Saved - %span.update-failed.cred.hide - %i.icon-remove - Failed - %ul.cred - %li This will change the web URL for personal projects. - %li This will change the git path to repositories for personal projects. - .controls - = f.submit 'Save username', class: "btn btn-save" + - if show_profile_username_tab? + .tab-pane#tab-username + %fieldset.update-username + %legend + Username + %small.cred.pull-right + Changing your username can have unintended side effects! + = form_for @user, url: update_username_profile_path, method: :put, remote: true do |f| + %div + .control-group + = f.label :username + .controls + = f.text_field :username, required: true +   + %span.loading-gif.hide= image_tag "ajax_loader.gif" + %span.update-success.cgreen.hide + %i.icon-ok + Saved + %span.update-failed.cred.hide + %i.icon-remove + Failed + %ul.cred + %li This will change the web URL for personal projects. + %li This will change the git path to repositories for personal projects. + .controls + = f.submit 'Save username', class: "btn btn-save" -- if gitlab_config.signup_enabled && !current_user.ldap_user? - %fieldset.remove-account - %legend - Remove account - %small.cred.pull-right - Before removing the account you must remove all projects! - = link_to 'Delete account', user_registration_path, confirm: "REMOVE #{current_user.name}? Are you sure?", method: :delete, class: "btn btn-remove delete-key btn-small pull-right" + - if show_profile_remove_tab? + .tab-pane#tab-remove + %fieldset.remove-account + %legend + Remove account + %div + %p Deleting an account has the following effects: + %ul + %li All user content like authored issues, snippets, comments will be removed + - rp = current_user.personal_projects.count + - unless rp.zero? + %li #{pluralize rp, 'personal project'} will be removed and cannot be restored + - if current_user.solo_owned_groups.present? + %li + Next groups will be abandoned. You should transfer or remove them: + %strong #{current_user.solo_owned_groups.map(&:name).join(', ')} + = link_to 'Delete account', user_registration_path, confirm: "REMOVE #{current_user.name}? Are you sure?", method: :delete, class: "btn btn-remove" -- GitLab From 7b8bd93e673a6ace673cab00e0cc10489d64437d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 4 Sep 2013 00:53:13 +0300 Subject: [PATCH 123/175] Rewrite OAuth specs --- spec/lib/auth_spec.rb | 100 +++++------------------------------------ spec/lib/oauth_spec.rb | 44 ++++++++++++++++++ 2 files changed, 56 insertions(+), 88 deletions(-) create mode 100644 spec/lib/oauth_spec.rb diff --git a/spec/lib/auth_spec.rb b/spec/lib/auth_spec.rb index 2784d4e2fbe..e05fde95731 100644 --- a/spec/lib/auth_spec.rb +++ b/spec/lib/auth_spec.rb @@ -3,102 +3,26 @@ require 'spec_helper' describe Gitlab::Auth do let(:gl_auth) { Gitlab::Auth.new } - before do - Gitlab.config.stub(omniauth: {}) - - @info = mock( - uid: '12djsak321', - name: 'John', - email: 'john@mail.com' - ) - end - - describe :find_for_ldap_auth do + describe :find do before do - @auth = mock( - uid: '12djsak321', - info: @info, - provider: 'ldap' + @user = create( + :user, + username: 'john', + password: '888777', + password_confirmation: '888777' ) end - it "should find by uid & provider" do - User.should_receive :find_by_extern_uid_and_provider - gl_auth.find_for_ldap_auth(@auth) - end - - it "should update credentials by email if missing uid" do - user = double('User') - User.stub find_by_extern_uid_and_provider: nil - User.stub find_by_email: user - user.should_receive :update_attributes - gl_auth.find_for_ldap_auth(@auth) - end - - - it "should create from auth if user does not exist"do - User.stub find_by_extern_uid_and_provider: nil - User.stub find_by_email: nil - gl_auth.should_receive :create_from_omniauth - gl_auth.find_for_ldap_auth(@auth) - end - end - - describe :find_or_new_for_omniauth do - before do - @auth = mock( - info: @info, - provider: 'twitter', - uid: '12djsak321', - ) + it "should find user by valid login/password" do + gl_auth.find('john', '888777').should == @user end - it "should find user"do - User.should_receive :find_by_provider_and_extern_uid - gl_auth.should_not_receive :create_from_omniauth - gl_auth.find_or_new_for_omniauth(@auth) + it "should not find user with invalid password" do + gl_auth.find('john', 'invalid').should_not == @user end - it "should not create user"do - User.stub find_by_provider_and_extern_uid: nil - gl_auth.should_not_receive :create_from_omniauth - gl_auth.find_or_new_for_omniauth(@auth) - end - - it "should create user if single_sing_on"do - Gitlab.config.omniauth['allow_single_sign_on'] = true - User.stub find_by_provider_and_extern_uid: nil - gl_auth.should_receive :create_from_omniauth - gl_auth.find_or_new_for_omniauth(@auth) - end - end - - describe :create_from_omniauth do - it "should create user from LDAP" do - @auth = mock(info: @info, provider: 'ldap') - user = gl_auth.create_from_omniauth(@auth, true) - - user.should be_valid - user.extern_uid.should == @info.uid - user.provider.should == 'ldap' - end - - it "should create user from Omniauth" do - @auth = mock(info: @info, provider: 'twitter') - user = gl_auth.create_from_omniauth(@auth, false) - - user.should be_valid - user.extern_uid.should == @info.uid - user.provider.should == 'twitter' - end - - it "should apply defaults to user" do - @auth = mock(info: @info, provider: 'ldap') - user = gl_auth.create_from_omniauth(@auth, true) - - user.should be_valid - user.projects_limit.should == Gitlab.config.gitlab.default_projects_limit - user.can_create_group.should == Gitlab.config.gitlab.default_can_create_group + it "should not find user with invalid login and password" do + gl_auth.find('jon', 'invalid').should_not == @user end end end diff --git a/spec/lib/oauth_spec.rb b/spec/lib/oauth_spec.rb new file mode 100644 index 00000000000..e21074554b6 --- /dev/null +++ b/spec/lib/oauth_spec.rb @@ -0,0 +1,44 @@ +require 'spec_helper' + +describe Gitlab::OAuth::User do + let(:gl_auth) { Gitlab::OAuth::User } + + before do + Gitlab.config.stub(omniauth: {}) + + @info = mock( + uid: '12djsak321', + name: 'John', + email: 'john@mail.com' + ) + end + + describe :create do + it "should create user from LDAP" do + @auth = mock(info: @info, provider: 'ldap') + user = gl_auth.create(@auth) + + user.should be_valid + user.extern_uid.should == @info.uid + user.provider.should == 'ldap' + end + + it "should create user from Omniauth" do + @auth = mock(info: @info, provider: 'twitter') + user = gl_auth.create(@auth) + + user.should be_valid + user.extern_uid.should == @info.uid + user.provider.should == 'twitter' + end + + it "should apply defaults to user" do + @auth = mock(info: @info, provider: 'ldap') + user = gl_auth.create(@auth) + + user.should be_valid + user.projects_limit.should == Gitlab.config.gitlab.default_projects_limit + user.can_create_group.should == Gitlab.config.gitlab.default_can_create_group + end + end +end -- GitLab From cabf9e04045c343eaa8cdf0b9c0bd6f341e5480a Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Wed, 4 Sep 2013 09:08:39 +0200 Subject: [PATCH 124/175] spelling mistake. --- PROCESS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PROCESS.md b/PROCESS.md index a7a61c5231a..668cacc870a 100644 --- a/PROCESS.md +++ b/PROCESS.md @@ -26,7 +26,7 @@ Below we describe the contributing process to GitLab for two reasons. So that co - Close fixed issues (via commit messages or manually) - Codes [new features](http://feedback.gitlab.com/forums/176466-general/filters/top)! - Response guidelines -- Be kind to people trying to contribute. Be aware that people can be a non-native or a native English speaker, they might not understand thing or they might be very sensitive to how your word things. Use emoji to express your feelings (hearth, star, smile, etc.). Some good tips about giving feedback to pull requests is in the [Thoughtbot code review guide](https://github.com/thoughtbot/guides/tree/master/code-review). +- Be kind to people trying to contribute. Be aware that people can be a non-native or a native English speaker, they might not understand thing or they might be very sensitive to how your word things. Use emoji to express your feelings (heart, star, smile, etc.). Some good tips about giving feedback to pull requests is in the [Thoughtbot code review guide](https://github.com/thoughtbot/guides/tree/master/code-review). ## Priorities of the issue team -- GitLab From 8e238f42732e5968dc46e3f08d853d0f3c9b2760 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 4 Sep 2013 16:20:40 +0300 Subject: [PATCH 125/175] Fix user remove tests. Remove user even if he has projects --- app/controllers/registrations_controller.rb | 3 --- spec/features/profile_spec.rb | 16 +--------------- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 194dfcd4122..5f18bac82ed 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -2,9 +2,6 @@ class RegistrationsController < Devise::RegistrationsController before_filter :signup_enabled? def destroy - if current_user.owned_projects.count > 0 - redirect_to account_profile_path, alert: "Remove projects and groups before removing account." and return - end current_user.destroy respond_to do |format| diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb index 7fa474d0ea1..80c9f5d7f14 100644 --- a/spec/features/profile_spec.rb +++ b/spec/features/profile_spec.rb @@ -17,26 +17,12 @@ describe "Profile account page" do it { page.should have_content("Remove account") } - it "should delete the account", js: true do + it "should delete the account" do expect { click_link "Delete account" }.to change {User.count}.by(-1) current_path.should == new_user_session_path end end - describe "when signup is enabled and user has a project" do - before do - Gitlab.config.gitlab.stub(:signup_enabled).and_return(true) - @project = create(:project, namespace: @user.namespace) - @project.team << [@user, :master] - visit account_profile_path - end - it { page.should have_content("Remove account") } - - it "should not allow user to delete the account" do - expect { click_link "Delete account" }.not_to change {User.count}.by(-1) - end - end - describe "when signup is disabled" do before do Gitlab.config.gitlab.stub(:signup_enabled).and_return(false) -- GitLab From 626359831402aeede4c4cb12cb10c7534a0dae79 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 4 Sep 2013 17:05:48 +0300 Subject: [PATCH 126/175] Respect group members in mentionable concern --- app/models/concerns/mentionable.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/concerns/mentionable.rb b/app/models/concerns/mentionable.rb index 27e39339ae8..5858fe1bb6f 100644 --- a/app/models/concerns/mentionable.rb +++ b/app/models/concerns/mentionable.rb @@ -50,7 +50,7 @@ module Mentionable matches.each do |match| identifier = match.delete "@" if has_project - id = project.users_projects.joins(:user).where(users: { username: identifier }).pluck(:user_id).first + id = project.team.members.find { |u| u.username == identifier }.try(:id) else id = User.where(username: identifier).pluck(:id).first end -- GitLab From 9109a207589c3a3d085005ee87049bba6aeecc1a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 4 Sep 2013 18:15:42 +0300 Subject: [PATCH 127/175] Improve commit diff * show highlights when replace empty line with content * show inline diff when replace line with spaces with content --- lib/gitlab/inline_diff.rb | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/inline_diff.rb b/lib/gitlab/inline_diff.rb index 44cf49b4047..89c8e0680c3 100644 --- a/lib/gitlab/inline_diff.rb +++ b/lib/gitlab/inline_diff.rb @@ -13,6 +13,9 @@ module Gitlab second_line = diff_arr[index+2] max_length = [first_line.size, second_line.size].max + # Skip inline diff if empty line was replaced with content + next if first_line == "-\n" + first_the_same_symbols = 0 (0..max_length + 1).each do |i| first_the_same_symbols = i - 1 @@ -20,10 +23,19 @@ module Gitlab break end end + first_token = first_line[0..first_the_same_symbols][1..-1] start = first_token + START - diff_arr[index+1].sub!(first_token, first_token => start) - diff_arr[index+2].sub!(first_token, first_token => start) + + if first_token.empty? + # In case if we remove string of spaces in commit + diff_arr[index+1].sub!("-", "-" => "-#{START}") + diff_arr[index+2].sub!("+", "+" => "+#{START}") + else + diff_arr[index+1].sub!(first_token, first_token => start) + diff_arr[index+2].sub!(first_token, first_token => start) + end + last_the_same_symbols = 0 (1..max_length + 1).each do |i| last_the_same_symbols = -i -- GitLab From 8248e1f2b83895f394a3fecd25dcea4a8b40303b Mon Sep 17 00:00:00 2001 From: Izaak Alpert Date: Wed, 4 Sep 2013 11:19:03 -0400 Subject: [PATCH 128/175] Add group membership api Change-Id: I5b174bba02856ede788dcb51ec9b0d598ea7d0df --- doc/api/groups.md | 62 +++++++++++++++++ lib/api/entities.rb | 6 ++ lib/api/groups.rb | 73 +++++++++++++++++-- spec/requests/api/groups_spec.rb | 116 ++++++++++++++++++++++++++++--- 4 files changed, 243 insertions(+), 14 deletions(-) diff --git a/doc/api/groups.md b/doc/api/groups.md index e9702ea2cd1..9c551fff83a 100644 --- a/doc/api/groups.md +++ b/doc/api/groups.md @@ -55,3 +55,65 @@ POST /groups/:id/projects/:project_id Parameters: + `id` (required) - The ID of a group + `project_id (required) - The ID of a project + + +## Group members + +### List group members + +Get a list of group members viewable by the authenticated user. + +``` +GET /groups/:id/members +``` + +```json +[ + { + id: 1, + username: "raymond_smith", + email: "ray@smith.org", + name: "Raymond Smith", + state: "active", + created_at: "2012-10-22T14:13:35Z", + access_level: 30 + }, + { + id: 2, + username: "john_doe", + email: "joh@doe.org", + name: "John Doe", + state: "active", + created_at: "2012-10-22T14:13:35Z", + access_level: 30 + } +] +``` + +### Add group member + +Adds a user to the list of group members. + +``` +POST /groups/:id/members +``` + +Parameters: + ++ `id` (required) - The ID of a group ++ `user_id` (required) - The ID of a user to add ++ `access_level` (required) - Project access level + + +### Remove user team member + +Removes user from user team. + +``` +DELETE /groups/:id/members/:user_id +``` + +Parameters: + ++ `id` (required) - The ID of a user group ++ `user_id` (required) - The ID of a group member diff --git a/lib/api/entities.rb b/lib/api/entities.rb index f15ca35e954..1f35e9ec5fc 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -67,6 +67,12 @@ module API expose :projects, using: Entities::Project end + class GroupMember < UserBasic + expose :group_access, as: :access_level do |user, options| + options[:group].users_groups.find_by_user_id(user.id).group_access + end + end + class RepoObject < Grape::Entity expose :name, :commit expose :protected do |repo, options| diff --git a/lib/api/groups.rb b/lib/api/groups.rb index 701f6777b77..54393740867 100644 --- a/lib/api/groups.rb +++ b/lib/api/groups.rb @@ -4,6 +4,19 @@ module API before { authenticate! } resource :groups do + helpers do + def find_group(id) + group = Group.find(id) + if current_user.admin or current_user.groups.include? group + group + else + render_api_error!("403 Forbidden - #{current_user.username} lacks sufficient access to #{group.name}", 403) + end + end + def validate_access_level?(level) + [UsersGroup::GUEST, UsersGroup::REPORTER, UsersGroup::DEVELOPER, UsersGroup::MASTER].include? level.to_i + end + end # Get a groups list # # Example Request: @@ -46,12 +59,8 @@ module API # Example Request: # GET /groups/:id get ":id" do - @group = Group.find(params[:id]) - if current_user.admin or current_user.groups.include? @group - present @group, with: Entities::GroupDetail - else - not_found! - end + group = find_group(params[:id]) + present group, with: Entities::GroupDetail end # Transfer a project to the Group namespace @@ -71,6 +80,58 @@ module API not_found! end end + + # Get a list of group members viewable by the authenticated user. + # + # Example Request: + # GET /groups/:id/members + get ":id/members" do + group = find_group(params[:id]) + members = group.users_groups + users = (paginate members).collect { | member| member.user} + present users, with: Entities::GroupMember, group: group + end + + # Add a user to the list of group members + # + # Parameters: + # id (required) - group id + # user_id (required) - the users id + # access_level (required) - Project access level + # Example Request: + # POST /groups/:id/members + post ":id/members" do + required_attributes! [:user_id, :access_level] + if not validate_access_level?(params[:access_level]) + render_api_error!("Wrong access level", 422) + end + group = find_group(params[:id]) + if group.users_groups.find_by_user_id(params[:user_id]) + render_api_error!("Already exists", 409) + end + group.add_users([params[:user_id]], params[:access_level]) + member = group.users_groups.find_by_user_id(params[:user_id]) + present member.user, with: Entities::GroupMember, group: group + end + + # Remove member. + # + # Parameters: + # id (required) - group id + # user_id (required) - the users id + # + # Example Request: + # DELETE /groups/:id/members/:user_id + delete ":id/members/:user_id" do + group = find_group(params[:id]) + member = group.users_groups.find_by_user_id(params[:user_id]) + if member.nil? + render_api_error!("404 Not Found - user_id:#{params[:user_id]} not a member of group #{group.name}",404) + else + member.destroy + end + end + end end end diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb index d2e25fb9e23..51d6384a261 100644 --- a/spec/requests/api/groups_spec.rb +++ b/spec/requests/api/groups_spec.rb @@ -3,11 +3,11 @@ require 'spec_helper' describe API::API do include ApiHelpers - let(:user1) { create(:user) } - let(:user2) { create(:user) } + let(:user1) { create(:user) } + let(:user2) { create(:user) } let(:admin) { create(:admin) } - let!(:group1) { create(:group, owner: user1) } - let!(:group2) { create(:group, owner: user2) } + let!(:group1) { create(:group, owner: user1) } + let!(:group2) { create(:group, owner: user2) } describe "GET /groups" do context "when unauthenticated" do @@ -52,7 +52,7 @@ describe API::API do it "should not return a group not attached to user1" do get api("/groups/#{group2.id}", user1) - response.status.should == 404 + response.status.should == 403 end end @@ -90,7 +90,7 @@ describe API::API do end it "should return 400 bad request error if name not given" do - post api("/groups", admin), { path: group2.path } + post api("/groups", admin), {path: group2.path} response.status.should == 400 end @@ -104,8 +104,8 @@ describe API::API do describe "POST /groups/:id/projects/:project_id" do let(:project) { create(:project) } before(:each) do - project.stub!(:transfer).and_return(true) - Project.stub(:find).and_return(project) + project.stub!(:transfer).and_return(true) + Project.stub(:find).and_return(project) end @@ -123,4 +123,104 @@ describe API::API do end end end + + describe "members" do + let(:owner) { create(:user) } + let(:reporter) { create(:user) } + let(:developer) { create(:user) } + let(:master) { create(:user) } + let(:guest) { create(:user) } + let!(:group_with_members) do + group = create(:group, owner: owner) + group.add_users([reporter.id], UsersGroup::REPORTER) + group.add_users([developer.id], UsersGroup::DEVELOPER) + group.add_users([master.id], UsersGroup::MASTER) + group.add_users([guest.id], UsersGroup::GUEST) + group + end + let!(:group_no_members) { create(:group, owner: owner) } + describe "GET /groups/:id/members" do + context "when authenticated as user that is part or the group" do + it "each user: should return an array of members groups of group3" do + [owner, master, developer, reporter, guest].each do |user| + get api("/groups/#{group_with_members.id}/members", user) + response.status.should == 200 + json_response.should be_an Array + json_response.size.should == 5 + json_response.find { |e| e['id']==owner.id }['access_level'].should == UsersGroup::OWNER + json_response.find { |e| e['id']==reporter.id }['access_level'].should == UsersGroup::REPORTER + json_response.find { |e| e['id']==developer.id }['access_level'].should == UsersGroup::DEVELOPER + json_response.find { |e| e['id']==master.id }['access_level'].should == UsersGroup::MASTER + json_response.find { |e| e['id']==guest.id }['access_level'].should == UsersGroup::GUEST + end + end + it "users not part of the group should get access error" do + get api("/groups/#{group_with_members.id}/members", user1) + response.status.should == 403 + end + end + end + + describe "POST /groups/:id/members" do + context "when not a member of the group" do + it "should not add guest as member of group_no_members when adding being done by person outside the group" do + post api("/groups/#{group_no_members.id}/members", reporter), user_id: guest.id, access_level: UsersGroup::MASTER + response.status.should == 403 + end + end + + context "when a member of the group" do + it "should return ok and add new member" do + count_before=group_no_members.users_groups.count + new_user = create(:user) + post api("/groups/#{group_no_members.id}/members", owner), user_id: new_user.id, access_level: UsersGroup::MASTER + response.status.should == 201 + json_response['name'].should == new_user.name + json_response['access_level'].should == UsersGroup::MASTER + group_no_members.users_groups.count.should == count_before + 1 + end + it "should return error if member already exists" do + post api("/groups/#{group_with_members.id}/members", owner), user_id: master.id, access_level: UsersGroup::MASTER + response.status.should == 409 + end + it "should return a 400 error when user id is not given" do + post api("/groups/#{group_no_members.id}/members", owner), access_level: UsersGroup::MASTER + response.status.should == 400 + end + it "should return a 400 error when access level is not given" do + post api("/groups/#{group_no_members.id}/members", owner), user_id: master.id + response.status.should == 400 + end + + it "should return a 422 error when access level is not known" do + post api("/groups/#{group_no_members.id}/members", owner), user_id: master.id, access_level: 1234 + response.status.should == 422 + end + + end + end + + describe "DELETE /groups/:id/members/:user_id" do + context "when not a member of the group" do + it "should not delete guest's membership of group_with_members" do + random_user = create(:user) + delete api("/groups/#{group_with_members.id}/members/#{owner.id}", random_user) + response.status.should == 403 + end + end + + context "when a member of the group" do + it "should delete guest's membership of group" do + count_before=group_with_members.users_groups.count + delete api("/groups/#{group_with_members.id}/members/#{guest.id}", owner) + response.status.should == 200 + group_with_members.users_groups.count.should == count_before - 1 + end + it "should return a 404 error when user id is not known" do + delete api("/groups/#{group_with_members.id}/members/1328", owner) + response.status.should == 404 + end + end + end + end end -- GitLab From fadcc251899095e37b97091a03b2025b1f39c7a6 Mon Sep 17 00:00:00 2001 From: Izaak Alpert Date: Thu, 5 Sep 2013 10:17:40 -0400 Subject: [PATCH 129/175] Fixes for @randx Change-Id: I3b15ae34c0957a0f4026e1886c92a9770e9d170e --- lib/api/groups.rb | 7 ++++--- spec/requests/api/groups_spec.rb | 8 ++++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/api/groups.rb b/lib/api/groups.rb index 54393740867..396554404af 100644 --- a/lib/api/groups.rb +++ b/lib/api/groups.rb @@ -14,9 +14,10 @@ module API end end def validate_access_level?(level) - [UsersGroup::GUEST, UsersGroup::REPORTER, UsersGroup::DEVELOPER, UsersGroup::MASTER].include? level.to_i + Gitlab::Access.options_with_owner.values.include? level.to_i end end + # Get a groups list # # Example Request: @@ -88,7 +89,7 @@ module API get ":id/members" do group = find_group(params[:id]) members = group.users_groups - users = (paginate members).collect { | member| member.user} + users = (paginate members).collect(&:user) present users, with: Entities::GroupMember, group: group end @@ -102,7 +103,7 @@ module API # POST /groups/:id/members post ":id/members" do required_attributes! [:user_id, :access_level] - if not validate_access_level?(params[:access_level]) + unless validate_access_level?(params[:access_level]) render_api_error!("Wrong access level", 422) end group = find_group(params[:id]) diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb index 51d6384a261..f7fd27523b0 100644 --- a/spec/requests/api/groups_spec.rb +++ b/spec/requests/api/groups_spec.rb @@ -108,7 +108,6 @@ describe API::API do Project.stub(:find).and_return(project) end - context "when authenticated as user" do it "should not transfer project to group" do post api("/groups/#{group1.id}/projects/#{project.id}", user2) @@ -139,6 +138,7 @@ describe API::API do group end let!(:group_no_members) { create(:group, owner: owner) } + describe "GET /groups/:id/members" do context "when authenticated as user that is part or the group" do it "each user: should return an array of members groups of group3" do @@ -154,6 +154,7 @@ describe API::API do json_response.find { |e| e['id']==guest.id }['access_level'].should == UsersGroup::GUEST end end + it "users not part of the group should get access error" do get api("/groups/#{group_with_members.id}/members", user1) response.status.should == 403 @@ -179,14 +180,17 @@ describe API::API do json_response['access_level'].should == UsersGroup::MASTER group_no_members.users_groups.count.should == count_before + 1 end + it "should return error if member already exists" do post api("/groups/#{group_with_members.id}/members", owner), user_id: master.id, access_level: UsersGroup::MASTER response.status.should == 409 end + it "should return a 400 error when user id is not given" do post api("/groups/#{group_no_members.id}/members", owner), access_level: UsersGroup::MASTER response.status.should == 400 end + it "should return a 400 error when access level is not given" do post api("/groups/#{group_no_members.id}/members", owner), user_id: master.id response.status.should == 400 @@ -196,7 +200,6 @@ describe API::API do post api("/groups/#{group_no_members.id}/members", owner), user_id: master.id, access_level: 1234 response.status.should == 422 end - end end @@ -216,6 +219,7 @@ describe API::API do response.status.should == 200 group_with_members.users_groups.count.should == count_before - 1 end + it "should return a 404 error when user id is not known" do delete api("/groups/#{group_with_members.id}/members/1328", owner) response.status.should == 404 -- GitLab From ca1d63c2f668059eb5da3f8b61001ee898651eb1 Mon Sep 17 00:00:00 2001 From: Jeff '2 bits' Bachtel Date: Fri, 6 Sep 2013 18:53:10 -0400 Subject: [PATCH 130/175] -i flag allows sudo to work for git users using rvm that is not being used by root user (su might be better) --- lib/support/init.d/gitlab | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab index 79c56a9854b..dbdf7db114b 100755 --- a/lib/support/init.d/gitlab +++ b/lib/support/init.d/gitlab @@ -35,7 +35,7 @@ sidekiq_pid_path="$pid_path/sidekiq.pid" # Switch to the app_user if it is not he/she who is running the script. if [ "$USER" != "$app_user" ]; then - sudo -u "$app_user" -H $0 "$@"; exit; + sudo -u "$app_user" -H -i $0 "$@"; exit; fi # Switch to the gitlab path, if it fails exit with an error. -- GitLab From a9d3e6ce573e1e108ab340141ab0f104bf27a430 Mon Sep 17 00:00:00 2001 From: "C. Walker" Date: Fri, 6 Sep 2013 16:18:09 -0700 Subject: [PATCH 131/175] Fixed description. --- lib/tasks/gitlab/import.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tasks/gitlab/import.rake b/lib/tasks/gitlab/import.rake index 668ef1d2300..f2cba162784 100644 --- a/lib/tasks/gitlab/import.rake +++ b/lib/tasks/gitlab/import.rake @@ -9,7 +9,7 @@ namespace :gitlab do # * project owner will be a first admin # * existing projects will be skipped # - desc "GITLAB | Import bare repositories from git_host -> base_path into GitLab project instance" + desc "GITLAB | Import bare repositories from gitlab_shell -> repos_path into GitLab project instance" task repos: :environment do git_base_path = Gitlab.config.gitlab_shell.repos_path -- GitLab From 0f2299a8d43c8e66d1bf764b737b8ec14266fb2a Mon Sep 17 00:00:00 2001 From: "C. Walker" Date: Fri, 6 Sep 2013 16:19:35 -0700 Subject: [PATCH 132/175] Fixed Import Bare Repositories instructions to match rake task. --- doc/raketasks/maintenance.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/raketasks/maintenance.md b/doc/raketasks/maintenance.md index 68c1a72b230..3033d8c46b4 100644 --- a/doc/raketasks/maintenance.md +++ b/doc/raketasks/maintenance.md @@ -122,7 +122,7 @@ Notes: How to use: -1. copy your bare repos under git base_path (see `config/gitlab.yml` git_host -> base_path) +1. copy your bare repos under git repos_path (see `config/gitlab.yml` gitlab_shell -> repos_path) 2. run the command below ``` -- GitLab From 24bc3e0874bd81d1cf8cc8a7104f277d5a9fa5c7 Mon Sep 17 00:00:00 2001 From: "C. Walker" Date: Fri, 6 Sep 2013 16:45:42 -0700 Subject: [PATCH 133/175] Forgot to fix the comment instructions. --- lib/tasks/gitlab/import.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tasks/gitlab/import.rake b/lib/tasks/gitlab/import.rake index f2cba162784..8fa89270854 100644 --- a/lib/tasks/gitlab/import.rake +++ b/lib/tasks/gitlab/import.rake @@ -2,7 +2,7 @@ namespace :gitlab do namespace :import do # How to use: # - # 1. copy your bare repos under git base_path + # 1. copy your bare repos under git repos_path # 2. run bundle exec rake gitlab:import:repos RAILS_ENV=production # # Notes: -- GitLab From 01ff084a4df76ba0856a513aca9bdf8f1d550365 Mon Sep 17 00:00:00 2001 From: Boyan Tabakov Date: Wed, 4 Sep 2013 10:33:09 +0300 Subject: [PATCH 134/175] Improved large commit handling. Previously, only number of changed files mattered. Now, number of lines to render in the diff are also taken into account. A hard limit is set, above which diffs are not rendered and users are not allowed to override that. This prevents high server resource usage with huge commits. Related to #1745, #2259 In addition, handle large commits for MergeRequests and Compare controllers. Also fixes a bug where diffs are loaded twice, if user goes directly to merge_requests/:id/diffs URL. --- .../javascripts/merge_requests.js.coffee | 2 +- app/contexts/commit_load_context.rb | 3 +- app/controllers/projects/commit_controller.rb | 1 + .../projects/compare_controller.rb | 4 ++ .../projects/merge_requests_controller.rb | 4 ++ app/models/commit.rb | 43 ++++++++++++++++++- app/views/projects/commits/_diffs.html.haml | 22 ++++++++-- features/project/commits/commits.feature | 8 ++++ .../steps/project/project_browse_commits.rb | 20 +++++++++ features/support/env.rb | 2 +- spec/support/big_commits.rb | 8 ++++ 11 files changed, 108 insertions(+), 9 deletions(-) create mode 100644 spec/support/big_commits.rb diff --git a/app/assets/javascripts/merge_requests.js.coffee b/app/assets/javascripts/merge_requests.js.coffee index 153198ca5c5..5400bc5c1ad 100644 --- a/app/assets/javascripts/merge_requests.js.coffee +++ b/app/assets/javascripts/merge_requests.js.coffee @@ -11,7 +11,7 @@ class MergeRequest constructor: (@opts) -> this.$el = $('.merge-request') - @diffs_loaded = false + @diffs_loaded = if @opts.action == 'diffs' then true else false @commits_loaded = false this.activateTab(@opts.action) diff --git a/app/contexts/commit_load_context.rb b/app/contexts/commit_load_context.rb index 2cf5420d62d..2930c5b1668 100644 --- a/app/contexts/commit_load_context.rb +++ b/app/contexts/commit_load_context.rb @@ -20,7 +20,8 @@ class CommitLoadContext < BaseContext result[:notes_count] = project.notes.for_commit_id(commit.id).count begin - result[:suppress_diff] = true if commit.diffs.size > Commit::DIFF_SAFE_SIZE && !params[:force_show_diff] + result[:suppress_diff] = true if commit.diff_suppress? && !params[:force_show_diff] + result[:force_suppress_diff] = commit.diff_force_suppress? rescue Grit::Git::GitTimeout result[:suppress_diff] = true result[:status] = :huge_commit diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index 6a2d2315c1d..bdc501d73bb 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -18,6 +18,7 @@ class Projects::CommitController < Projects::ApplicationController end @suppress_diff = result[:suppress_diff] + @force_suppress_diff = result[:force_suppress_diff] @note = result[:note] @line_notes = result[:line_notes] diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb index 126a2ea50c9..d7e660dac22 100644 --- a/app/controllers/projects/compare_controller.rb +++ b/app/controllers/projects/compare_controller.rb @@ -15,6 +15,10 @@ class Projects::CompareController < Projects::ApplicationController @diffs = compare.diffs @refs_are_same = compare.same @line_notes = [] + + diff_line_count = Commit::diff_line_count(@diffs) + @suppress_diff = Commit::diff_suppress?(@diffs, diff_line_count) && !params[:force_show_diff] + @force_suppress_diff = Commit::diff_force_suppress?(@diffs, diff_line_count) end def create diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 55d2c3f04fc..3bc50b0418f 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -40,6 +40,10 @@ class Projects::MergeRequestsController < Projects::ApplicationController @comments_target = {noteable_type: 'MergeRequest', noteable_id: @merge_request.id} @line_notes = @merge_request.notes.where("line_code is not null") + + diff_line_count = Commit::diff_line_count(@merge_request.diffs) + @suppress_diff = Commit::diff_suppress?(@merge_request.diffs, diff_line_count) && !params[:force_show_diff] + @force_suppress_diff = Commit::diff_force_suppress?(@merge_request.diffs, diff_line_count) end def new diff --git a/app/models/commit.rb b/app/models/commit.rb index f8ca6a5fe82..dd1f9801878 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -6,15 +6,41 @@ class Commit attr_mentionable :safe_message - # Safe amount of files with diffs in one commit to render + # Safe amount of changes (files and lines) in one commit to render # Used to prevent 500 error on huge commits by suppressing diff # - DIFF_SAFE_SIZE = 100 + # User can force display of diff above this size + DIFF_SAFE_FILES = 100 + DIFF_SAFE_LINES = 5000 + # Commits above this size will not be rendered in HTML + DIFF_HARD_LIMIT_FILES = 500 + DIFF_HARD_LIMIT_LINES = 10000 def self.decorate(commits) commits.map { |c| self.new(c) } end + # Calculate number of lines to render for diffs + def self.diff_line_count(diffs) + diffs.reduce(0){|sum, d| sum + d.diff.lines.count} + end + + def self.diff_suppress?(diffs, line_count = nil) + # optimize - check file count first + return true if diffs.size > DIFF_SAFE_FILES + + line_count ||= Commit::diff_line_count(diffs) + line_count > DIFF_SAFE_LINES + end + + def self.diff_force_suppress?(diffs, line_count = nil) + # optimize - check file count first + return true if diffs.size > DIFF_HARD_LIMIT_FILES + + line_count ||= Commit::diff_line_count(diffs) + line_count > DIFF_HARD_LIMIT_LINES + end + attr_accessor :raw def initialize(raw_commit) @@ -27,6 +53,19 @@ class Commit @raw.id end + def diff_line_count + @diff_line_count ||= Commit::diff_line_count(self.diffs) + @diff_line_count + end + + def diff_suppress? + Commit::diff_suppress?(self.diffs, diff_line_count) + end + + def diff_force_suppress? + Commit::diff_force_suppress?(self.diffs, diff_line_count) + end + # Returns a string describing the commit for use in a link title # # Example diff --git a/app/views/projects/commits/_diffs.html.haml b/app/views/projects/commits/_diffs.html.haml index 5a3a9bd16af..c51f1b6eff5 100644 --- a/app/views/projects/commits/_diffs.html.haml +++ b/app/views/projects/commits/_diffs.html.haml @@ -1,11 +1,25 @@ +- @suppress_diff ||= @suppress_diff || @force_suppress_diff - if @suppress_diff .alert.alert-block %p - %strong Warning! Large commit with more than #{Commit::DIFF_SAFE_SIZE} files changed. - %p To preserve performance the diff is not shown. + %strong Warning! This is a large diff. %p - But if you still want to see the diff - = link_to "click this link", project_commit_path(project, @commit, force_show_diff: true), class: "underlined_link" + To preserve performance the diff is not shown. + - if current_controller?(:commit) or current_controller?(:merge_requests) + Please, download the diff as + - if current_controller?(:commit) + = link_to "plain diff", project_commit_path(@project, @commit, format: :diff), class: "underlined_link" + or + = link_to "email patch", project_commit_path(@project, @commit, format: :patch), class: "underlined_link" + - else + = link_to "plain diff", project_merge_request_path(@project, @merge_request, format: :diff), class: "underlined_link" + or + = link_to "email patch", project_merge_request_path(@project, @merge_request, format: :patch), class: "underlined_link" + instead. + - unless @force_suppress_diff + %p + If you still want to see the diff + = link_to "click this link", url_for(force_show_diff: true), class: "underlined_link" %p.commit-stat-summary Showing diff --git a/features/project/commits/commits.feature b/features/project/commits/commits.feature index 56069cdc977..d962471ebdb 100644 --- a/features/project/commits/commits.feature +++ b/features/project/commits/commits.feature @@ -27,3 +27,11 @@ Feature: Project Browse commits Scenario: I browse commits stats Given I visit my project's commits stats page Then I see commits stats + + Scenario: I browse big commit + Given I visit big commit page + Then I see big commit warning + + Scenario: I browse huge commit + Given I visit huge commit page + Then I see huge commit message diff --git a/features/steps/project/project_browse_commits.rb b/features/steps/project/project_browse_commits.rb index 71f4bd79f7e..4b122b853e6 100644 --- a/features/steps/project/project_browse_commits.rb +++ b/features/steps/project/project_browse_commits.rb @@ -58,4 +58,24 @@ class ProjectBrowseCommits < Spinach::FeatureSteps page.should have_content 'Total commits' page.should have_content 'Authors' end + + Given 'I visit big commit page' do + visit project_commit_path(@project, BigCommits::BIG_COMMIT_ID) + end + + Then 'I see big commit warning' do + page.should have_content BigCommits::BIG_COMMIT_MESSAGE + page.should have_content "Warning! This is a large diff" + page.should have_content "If you still want to see the diff" + end + + Given 'I visit huge commit page' do + visit project_commit_path(@project, BigCommits::HUGE_COMMIT_ID) + end + + Then 'I see huge commit message' do + page.should have_content BigCommits::HUGE_COMMIT_MESSAGE + page.should have_content "Warning! This is a large diff" + page.should_not have_content "If you still want to see the diff" + end end diff --git a/features/support/env.rb b/features/support/env.rb index 0cc7d8d2fe9..61f8dc29670 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -14,7 +14,7 @@ require 'spinach/capybara' require 'sidekiq/testing/inline' -%w(valid_commit select2_helper chosen_helper test_env).each do |f| +%w(valid_commit big_commits select2_helper chosen_helper test_env).each do |f| require Rails.root.join('spec', 'support', f) end diff --git a/spec/support/big_commits.rb b/spec/support/big_commits.rb new file mode 100644 index 00000000000..69daa709dd9 --- /dev/null +++ b/spec/support/big_commits.rb @@ -0,0 +1,8 @@ +module BigCommits + HUGE_COMMIT_ID = "7f92534f767fa20357a11c63f973ae3b79cc5b85" + HUGE_COMMIT_MESSAGE = "pybments.rb version up. gitignore improved" + + BIG_COMMIT_ID = "d62200cad430565bd9f80befaf329297120330b5" + BIG_COMMIT_MESSAGE = "clean-up code" +end + -- GitLab From 2bfea8f4f38044ac57ac60413c82c5f1209c5a5a Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Sun, 8 Sep 2013 12:31:00 +0200 Subject: [PATCH 135/175] Consistent status. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 19e7cbaad68..a4c5c0d0534 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ Since 2011 GitLab is released on the 22nd of every month. Every new release incl * [Changelog](CHANGELOG) -* Features that will be in the next releases are listed on [the feedback and suggestions forum](http://feedback.gitlab.com/forums/176466-general) with the status ["started"](http://feedback.gitlab.com/forums/176466-general/status/796456) and [completed](http://feedback.gitlab.com/forums/176466-general/status/796457). +* Features that will be in the next releases are listed on [the feedback and suggestions forum](http://feedback.gitlab.com/forums/176466-general) with the status [started](http://feedback.gitlab.com/forums/176466-general/status/796456) and [completed](http://feedback.gitlab.com/forums/176466-general/status/796457). ### Run in production mode -- GitLab From 9e9f0551415a8c606105c6277048becff981b460 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 9 Sep 2013 16:20:43 +0300 Subject: [PATCH 136/175] Move commits dates to left --- app/assets/stylesheets/sections/commits.scss | 15 +++++++++++++++ app/views/projects/commits/_commits.html.haml | 16 +++++++++------- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss index faae0e127d9..2f4472a52e1 100644 --- a/app/assets/stylesheets/sections/commits.scss +++ b/app/assets/stylesheets/sections/commits.scss @@ -374,6 +374,15 @@ min-width: 65px; font-family: $monospace_font; } + + .row_title { + font-weight: bold; + color: #444; + &:hover { + color: #444; + text-decoration: underline; + } + } } .file-stats a { @@ -496,3 +505,9 @@ li.commit { font-weight: bold; } } + +.commits-row { + padding-bottom: 10px; + margin-bottom: 10px; + border-bottom: 1px solid #DDD; +} diff --git a/app/views/projects/commits/_commits.html.haml b/app/views/projects/commits/_commits.html.haml index fd0616f9acc..b6eeeb92287 100644 --- a/app/views/projects/commits/_commits.html.haml +++ b/app/views/projects/commits/_commits.html.haml @@ -1,8 +1,10 @@ - @commits.group_by { |c| c.committed_date.to_date }.sort.reverse.each do |day, commits| - .ui-box.small-box - .title - %i.icon-calendar - %span= day.stamp("28 Aug, 2010") - .pull-right - %small= pluralize(commits.count, 'commit') - %ul.well-list= render commits, project: @project + .row.commits-row + .span2 + %h4 + %i.icon-calendar + %span= day.stamp("28 Aug, 2010") + %p= pluralize(commits.count, 'commit') + .span10 + %ul.well-list + = render commits, project: @project -- GitLab From 76a07394547a8df1ac1553ecd52f3e6e2d20a8af Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 9 Sep 2013 16:32:43 +0300 Subject: [PATCH 137/175] Add description to MergeRequest model --- app/models/concerns/issuable.rb | 2 ++ app/models/issue.rb | 1 - app/models/merge_request.rb | 3 +-- .../20130909132950_add_description_to_merge_request.rb | 5 +++++ db/schema.rb | 3 ++- 5 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 db/migrate/20130909132950_add_description_to_merge_request.rb diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index a05dba7f6b6..7f820f950b0 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -37,6 +37,8 @@ module Issuable prefix: true attr_accessor :author_id_of_changes + + attr_mentionable :title, :description end module ClassMethods diff --git a/app/models/issue.rb b/app/models/issue.rb index ffe9681fc83..f3ec322126f 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -32,7 +32,6 @@ class Issue < ActiveRecord::Base attr_accessible :title, :assignee_id, :position, :description, :milestone_id, :label_list, :author_id_of_changes, :state_event - attr_mentionable :title, :description acts_as_taggable_on :labels diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 514fc79f7c5..7f367588b23 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -30,8 +30,7 @@ class MergeRequest < ActiveRecord::Base belongs_to :target_project, foreign_key: :target_project_id, class_name: "Project" belongs_to :source_project, foreign_key: :source_project_id, class_name: "Project" - attr_accessible :title, :assignee_id, :source_project_id, :source_branch, :target_project_id, :target_branch, :milestone_id, :author_id_of_changes, :state_event - attr_mentionable :title + attr_accessible :title, :assignee_id, :source_project_id, :source_branch, :target_project_id, :target_branch, :milestone_id, :author_id_of_changes, :state_event, :description attr_accessor :should_remove_source_branch diff --git a/db/migrate/20130909132950_add_description_to_merge_request.rb b/db/migrate/20130909132950_add_description_to_merge_request.rb new file mode 100644 index 00000000000..9bcd0c7ee06 --- /dev/null +++ b/db/migrate/20130909132950_add_description_to_merge_request.rb @@ -0,0 +1,5 @@ +class AddDescriptionToMergeRequest < ActiveRecord::Migration + def change + add_column :merge_requests, :description, :text, null: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 654f2b1e8f7..d5effe40ea1 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 => 20130821090531) do +ActiveRecord::Schema.define(:version => 20130909132950) do create_table "deploy_keys_projects", :force => true do |t| t.integer "deploy_key_id", :null => false @@ -100,6 +100,7 @@ ActiveRecord::Schema.define(:version => 20130821090531) do t.string "merge_status" t.integer "target_project_id", :null => false t.integer "iid" + t.text "description" end add_index "merge_requests", ["assignee_id"], :name => "index_merge_requests_on_assignee_id" -- GitLab From e0ca2adafda95dbb0476847499d662623ff0b6be Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 9 Sep 2013 17:11:58 +0300 Subject: [PATCH 138/175] Improve Merge Request form * added description * simplified form * enabled gfm autocomplete --- app/assets/javascripts/dispatcher.js.coffee | 2 + .../stylesheets/sections/merge_requests.scss | 2 +- .../projects/merge_requests/_form.html.haml | 57 +++++++++---------- .../merge_requests/show/_mr_box.html.haml | 6 ++ 4 files changed, 36 insertions(+), 31 deletions(-) diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee index c8ddbed5097..e264e281309 100644 --- a/app/assets/javascripts/dispatcher.js.coffee +++ b/app/assets/javascripts/dispatcher.js.coffee @@ -18,6 +18,8 @@ class Dispatcher switch page when 'projects:issues:index' Issues.init() + when 'projects:issues:new', 'projects:merge_requests:new' + GitLab.GfmAutoComplete.setup() when 'dashboard:show' new Dashboard() new Activities() diff --git a/app/assets/stylesheets/sections/merge_requests.scss b/app/assets/stylesheets/sections/merge_requests.scss index bdab306a57d..e7b464fd4aa 100644 --- a/app/assets/stylesheets/sections/merge_requests.scss +++ b/app/assets/stylesheets/sections/merge_requests.scss @@ -117,7 +117,7 @@ .merge-request-angle { text-align: center; - margin-top: 45px; + margin: 0; } .merge-request-form-info { diff --git a/app/views/projects/merge_requests/_form.html.haml b/app/views/projects/merge_requests/_form.html.haml index 5e94f1fdf18..ce72756303e 100644 --- a/app/views/projects/merge_requests/_form.html.haml +++ b/app/views/projects/merge_requests/_form.html.haml @@ -5,41 +5,32 @@ - @merge_request.errors.full_messages.each do |msg| %li= msg - %h3.page-title - Branches .merge-request-branches - .row - .span5 - .ui-box - .title From - .ui-box-head - Project: - = f.select(:source_project_id,[[@merge_request.source_project.path_with_namespace,@merge_request.source_project.id]] , {}, {class: 'source_project chosen span4'}) - .prepend-top-10 + .row + .span5 + .clearfix + .pull-left + = f.select(:source_project_id,[[@merge_request.source_project.path_with_namespace,@merge_request.source_project.id]] , {}, {class: 'source_project chosen span3'}) + .pull-left +   %i.icon-code-fork - Branch: - = f.select(:source_branch, @merge_request.source_project.repository.branch_names, { include_blank: "Select branch" }, {class: 'source_branch chosen span3'}) - .mr_source_commit.prepend-top-10 - .span2 - %h1.merge-request-angle - %i.icon-angle-right - .span5 - .ui-box - .title To - .ui-box-head - - projects = @project.forked_from_project.nil? ? [@project] : [ @project,@project.forked_from_project] - Project: - = f.select(:target_project_id, projects.map { |proj| [proj.path_with_namespace,proj.id] }, {include_blank: "Select Target Project" }, {class: 'target_project chosen span4'}) - .prepend-top-10 + = f.select(:source_branch, @merge_request.source_project.repository.branch_names, { include_blank: "Select branch" }, {class: 'source_branch chosen span2'}) + .mr_source_commit.prepend-top-10 + .span2 + %h2.merge-request-angle.light + %i.icon-long-arrow-right + .span5 + .clearfix + .pull-left + - projects = @project.forked_from_project.nil? ? [@project] : [ @project,@project.forked_from_project] + = f.select(:target_project_id, projects.map { |proj| [proj.path_with_namespace,proj.id] }, {include_blank: "Select Target Project" }, {class: 'target_project chosen span3'}) + .pull-left +   %i.icon-code-fork - Branch: - = f.select(:target_branch, @target_branches, { include_blank: "Select branch" }, {class: 'target_branch chosen span3'}) - .mr_target_commit.prepend-top-10 + = f.select(:target_branch, @target_branches, { include_blank: "Select branch" }, {class: 'target_branch chosen span2'}) + .mr_target_commit.prepend-top-10 %hr - - %h3.page-title - Details .merge-request-form-info .control-group = f.label :title do @@ -56,6 +47,12 @@ %i.icon-time Milestone .controls= f.select(:milestone_id, @project.milestones.active.all.map {|p| [ p.title, p.id ] }, { include_blank: "Select milestone" }, {class: 'chosen'}) + .control-group + = f.label :description, "Description" + .controls + = f.text_area :description, class: "input-xxlarge js-gfm-input", rows: 14 + %p.hint Description is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. + .form-actions - if @merge_request.new_record? diff --git a/app/views/projects/merge_requests/show/_mr_box.html.haml b/app/views/projects/merge_requests/show/_mr_box.html.haml index c4b614b51da..1f750e22c65 100644 --- a/app/views/projects/merge_requests/show/_mr_box.html.haml +++ b/app/views/projects/merge_requests/show/_mr_box.html.haml @@ -21,6 +21,12 @@ %strong= link_to_gfm truncate(milestone.title, length: 20), project_milestone_path(milestone.project, milestone) + - if @merge_request.description.present? + .ui-box-bottom + .wiki + = preserve do + = markdown @merge_request.description + - if @merge_request.closed? .ui-box-bottom.alert-error %span -- GitLab From e86e8818327059279247db3a451994c6a62ab161 Mon Sep 17 00:00:00 2001 From: Izaak Alpert Date: Thu, 28 Mar 2013 14:37:44 -0400 Subject: [PATCH 139/175] API: admin users can sudo commands as other users -Specifying a header of SUDO or adding a :sudo with either user id, or username of the user will set the current_user to be that user if your identifying private_token/PRIVATE_TOKEN is an administrator token --- doc/api/README.md | 36 ++++++ lib/api/helpers.rb | 44 ++++++- spec/requests/api/api_helpers_spec.rb | 159 ++++++++++++++++++++++++++ 3 files changed, 234 insertions(+), 5 deletions(-) create mode 100644 spec/requests/api/api_helpers_spec.rb diff --git a/doc/api/README.md b/doc/api/README.md index 7668df07af1..6971e08f010 100644 --- a/doc/api/README.md +++ b/doc/api/README.md @@ -58,7 +58,43 @@ Return values: * `409 Conflict` - A conflicting resource already exists, e.g. creating a project with a name that already exists * `500 Server Error` - While handling the request something went wrong on the server side +## Sudo +All API requests support performing an api call as if you were another user, if your private token is for an administration account. You need to pass `sudo` parameter by url or header with an id or username of the user you want to perform the operation as. If passed as header, the header name must be "SUDO" (capitals). +If a non administrative `private_token` is provided then an error message will be returned with status code 403: + +```json +{ + "message": "403 Forbidden: Must be admin to use sudo" +} +``` + +If the sudo user id or username cannot be found then an error message will be returned with status code 404: + +```json +{ + "message": "404 Not Found: No user id or username for: " +} +``` + +Example of a valid API with sudo request: + +``` +GET http://example.com/api/v3/projects?private_token=QVy1PB7sTxfy4pqfZM1U&sudo=username +``` +``` +GET http://example.com/api/v3/projects?private_token=QVy1PB7sTxfy4pqfZM1U&sudo=23 +``` + + +Example for a valid API request with sudo using curl and authentication via header: + +``` +curl --header "PRIVATE-TOKEN: QVy1PB7sTxfy4pqfZM1U" --header "SUDO: username" "http://example.com/api/v3/projects" +``` +``` +curl --header "PRIVATE-TOKEN: QVy1PB7sTxfy4pqfZM1U" --header "SUDO: 23" "http://example.com/api/v3/projects" +``` #### Pagination diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index f857d4133b2..996d3adb174 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -1,7 +1,41 @@ module API module APIHelpers + PRIVATE_TOKEN_HEADER = "HTTP_PRIVATE_TOKEN" + PRIVATE_TOKEN_PARAM = :private_token + SUDO_HEADER ="HTTP_SUDO" + SUDO_PARAM = :sudo + def current_user - @current_user ||= User.find_by_authentication_token(params[:private_token] || env["HTTP_PRIVATE_TOKEN"]) + @current_user ||= User.find_by_authentication_token(params[PRIVATE_TOKEN_PARAM] || env[PRIVATE_TOKEN_HEADER]) + identifier = sudo_identifier() + # If the sudo is the current user do nothing + if (identifier && !(@current_user.id == identifier || @current_user.username == identifier)) + render_api_error!('403 Forbidden: Must be admin to use sudo', 403) unless @current_user.is_admin? + begin + + if (identifier.is_a?(Integer)) + user = User.find_by_id(identifier) + else + user = User.find_by_username(identifier) + end + if user.nil? + not_found!("No user id or username for: #{identifier}") + end + @current_user = user + rescue => ex + not_found!("No user id or username for: #{identifier}") + end + end + @current_user + end + + def sudo_identifier() + identifier = params[SUDO_PARAM] == nil ? env[SUDO_HEADER] : params[SUDO_PARAM] + if (!!(identifier =~ /^[0-9]+$/)) + identifier.to_i + else + identifier + end end def user_project @@ -95,10 +129,10 @@ module API def abilities @abilities ||= begin - abilities = Six.new - abilities << Ability - abilities - end + abilities = Six.new + abilities << Ability + abilities + end end end end diff --git a/spec/requests/api/api_helpers_spec.rb b/spec/requests/api/api_helpers_spec.rb new file mode 100644 index 00000000000..de71deabb8e --- /dev/null +++ b/spec/requests/api/api_helpers_spec.rb @@ -0,0 +1,159 @@ +require 'spec_helper' + +describe Gitlab::API do + include Gitlab::APIHelpers + include ApiHelpers + let(:user) { create(:user) } + let(:admin) { create(:admin) } + let(:key) { create(:key, user: user) } + + let(:params) { {} } + let(:env) { {} } + + def set_env(token_usr, identifier) + clear_env + clear_param + env[Gitlab::APIHelpers::PRIVATE_TOKEN_HEADER] = token_usr.private_token + env[Gitlab::APIHelpers::SUDO_HEADER] = identifier + end + + + def set_param(token_usr, identifier) + clear_env + clear_param + params[Gitlab::APIHelpers::PRIVATE_TOKEN_PARAM] = token_usr.private_token + params[Gitlab::APIHelpers::SUDO_PARAM] = identifier + end + + + def clear_env + env.delete(Gitlab::APIHelpers::PRIVATE_TOKEN_HEADER) + env.delete(Gitlab::APIHelpers::SUDO_HEADER) + end + + def clear_param + params.delete(Gitlab::APIHelpers::PRIVATE_TOKEN_PARAM) + params.delete(Gitlab::APIHelpers::SUDO_PARAM) + end + + def error!(message, status) + raise Exception + end + + describe ".current_user" do + it "should leave user as is when sudo not specified" do + env[Gitlab::APIHelpers::PRIVATE_TOKEN_HEADER] = user.private_token + current_user.should == user + clear_env + params[Gitlab::APIHelpers::PRIVATE_TOKEN_PARAM] = user.private_token + current_user.should == user + end + + it "should change current user to sudo when admin" do + set_env(admin, user.id) + current_user.should == user + set_param(admin, user.id) + current_user.should == user + set_env(admin, user.username) + current_user.should == user + set_param(admin, user.username) + current_user.should == user + end + + it "should throw an error when the current user is not an admin and attempting to sudo" do + set_env(user, admin.id) + expect { current_user }.to raise_error + set_param(user, admin.id) + expect { current_user }.to raise_error + set_env(user, admin.username) + expect { current_user }.to raise_error + set_param(user, admin.username) + expect { current_user }.to raise_error + end + it "should throw an error when the user cannot be found for a given id" do + id = user.id + admin.id + user.id.should_not == id + admin.id.should_not == id + set_env(admin, id) + expect { current_user }.to raise_error + + set_param(admin, id) + expect { current_user }.to raise_error + end + it "should throw an error when the user cannot be found for a given username" do + username = "#{user.username}#{admin.username}" + user.username.should_not == username + admin.username.should_not == username + set_env(admin, username) + expect { current_user }.to raise_error + + set_param(admin, username) + expect { current_user }.to raise_error + end + it "should handle sudo's to oneself" do + set_env(admin, admin.id) + current_user.should == admin + set_param(admin, admin.id) + current_user.should == admin + set_env(admin, admin.username) + current_user.should == admin + set_param(admin, admin.username) + current_user.should == admin + end + + it "should handle multiple sudo's to oneself" do + set_env(admin, user.id) + current_user.should == user + current_user.should == user + set_env(admin, user.username) + current_user.should == user + current_user.should == user + + set_param(admin, user.id) + current_user.should == user + current_user.should == user + set_param(admin, user.username) + current_user.should == user + current_user.should == user + end + it "should handle multiple sudo's to oneself using string ids" do + set_env(admin, user.id.to_s) + current_user.should == user + current_user.should == user + + set_param(admin, user.id.to_s) + current_user.should == user + current_user.should == user + end + end + + describe '.sudo_identifier' do + it "should return integers when input is an int" do + set_env(admin, '123') + sudo_identifier.should == 123 + set_env(admin, '0001234567890') + sudo_identifier.should == 1234567890 + + set_param(admin, '123') + sudo_identifier.should == 123 + set_param(admin, '0001234567890') + sudo_identifier.should == 1234567890 + end + + it "should return string when input is an is not an int" do + set_env(admin, '12.30') + sudo_identifier.should == "12.30" + set_env(admin, 'hello') + sudo_identifier.should == 'hello' + set_env(admin, ' 123') + sudo_identifier.should == ' 123' + + set_param(admin, '12.30') + sudo_identifier.should == "12.30" + set_param(admin, 'hello') + sudo_identifier.should == 'hello' + set_param(admin, ' 123') + sudo_identifier.should == ' 123' + end + end +end \ No newline at end of file -- GitLab From 7a56075efac308a3bd08e022e56e96d41c4c05b5 Mon Sep 17 00:00:00 2001 From: Izaak Alpert Date: Fri, 28 Jun 2013 08:59:05 -0400 Subject: [PATCH 140/175] Some of the requested updates, rebase on master Change-Id: I305266fe9acbbb5136adeeb52e7e4e1d6629a30a --- app/models/user.rb | 8 ++++++++ lib/api/helpers.rb | 23 ++++++++--------------- spec/models/user_spec.rb | 10 ++++++++++ spec/requests/api/api_helpers_spec.rb | 24 ++++++++++++------------ 4 files changed, 38 insertions(+), 27 deletions(-) diff --git a/app/models/user.rb b/app/models/user.rb index b593c22fde3..c2355eaab99 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -190,6 +190,14 @@ class User < ActiveRecord::Base def search query where("name LIKE :query OR email LIKE :query OR username LIKE :query", query: "%#{query}%") end + + def by_username_or_id(name_or_id) + if (name_or_id.is_a?(Integer)) + User.find_by_id(name_or_id) + else + User.find_by_username(name_or_id) + end + end end # diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 996d3adb174..4f189f35196 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -12,25 +12,18 @@ module API if (identifier && !(@current_user.id == identifier || @current_user.username == identifier)) render_api_error!('403 Forbidden: Must be admin to use sudo', 403) unless @current_user.is_admin? begin - - if (identifier.is_a?(Integer)) - user = User.find_by_id(identifier) - else - user = User.find_by_username(identifier) - end - if user.nil? - not_found!("No user id or username for: #{identifier}") - end - @current_user = user + @current_user = User.by_username_or_id(identifier) rescue => ex not_found!("No user id or username for: #{identifier}") end + not_found!("No user id or username for: #{identifier}") if current_user.nil? end @current_user end def sudo_identifier() - identifier = params[SUDO_PARAM] == nil ? env[SUDO_HEADER] : params[SUDO_PARAM] + identifier ||= params[SUDO_PARAM] ||= env[SUDO_HEADER] + # Regex for integers if (!!(identifier =~ /^[0-9]+$/)) identifier.to_i else @@ -129,10 +122,10 @@ module API def abilities @abilities ||= begin - abilities = Six.new - abilities << Ability - abilities - end + abilities = Six.new + abilities << Ability + abilities + end end end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 695f0ae6846..de06bf71dc1 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -208,4 +208,14 @@ describe User do user.can_create_group.should == false end end + + describe 'by_username_or_id' do + let(:user1){create(:user, username: 'foo')} + it "should get the correct user" do + User.by_username_or_id(user1.id).should == user1 + User.by_username_or_id('foo').should == user1 + User.by_username_or_id(-1).should be_nil + User.by_username_or_id('bar').should be_nil + end + end end diff --git a/spec/requests/api/api_helpers_spec.rb b/spec/requests/api/api_helpers_spec.rb index de71deabb8e..a1cbfcd60e9 100644 --- a/spec/requests/api/api_helpers_spec.rb +++ b/spec/requests/api/api_helpers_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' -describe Gitlab::API do - include Gitlab::APIHelpers +describe API do + include API::APIHelpers include ApiHelpers let(:user) { create(:user) } let(:admin) { create(:admin) } @@ -13,27 +13,27 @@ describe Gitlab::API do def set_env(token_usr, identifier) clear_env clear_param - env[Gitlab::APIHelpers::PRIVATE_TOKEN_HEADER] = token_usr.private_token - env[Gitlab::APIHelpers::SUDO_HEADER] = identifier + env[API::APIHelpers::PRIVATE_TOKEN_HEADER] = token_usr.private_token + env[API::APIHelpers::SUDO_HEADER] = identifier end def set_param(token_usr, identifier) clear_env clear_param - params[Gitlab::APIHelpers::PRIVATE_TOKEN_PARAM] = token_usr.private_token - params[Gitlab::APIHelpers::SUDO_PARAM] = identifier + params[API::APIHelpers::PRIVATE_TOKEN_PARAM] = token_usr.private_token + params[API::APIHelpers::SUDO_PARAM] = identifier end def clear_env - env.delete(Gitlab::APIHelpers::PRIVATE_TOKEN_HEADER) - env.delete(Gitlab::APIHelpers::SUDO_HEADER) + env.delete(API::APIHelpers::PRIVATE_TOKEN_HEADER) + env.delete(API::APIHelpers::SUDO_HEADER) end def clear_param - params.delete(Gitlab::APIHelpers::PRIVATE_TOKEN_PARAM) - params.delete(Gitlab::APIHelpers::SUDO_PARAM) + params.delete(API::APIHelpers::PRIVATE_TOKEN_PARAM) + params.delete(API::APIHelpers::SUDO_PARAM) end def error!(message, status) @@ -42,10 +42,10 @@ describe Gitlab::API do describe ".current_user" do it "should leave user as is when sudo not specified" do - env[Gitlab::APIHelpers::PRIVATE_TOKEN_HEADER] = user.private_token + env[API::APIHelpers::PRIVATE_TOKEN_HEADER] = user.private_token current_user.should == user clear_env - params[Gitlab::APIHelpers::PRIVATE_TOKEN_PARAM] = user.private_token + params[API::APIHelpers::PRIVATE_TOKEN_PARAM] = user.private_token current_user.should == user end -- GitLab From fdc23a93e7368283f8f78b8e8627aef9ad73c617 Mon Sep 17 00:00:00 2001 From: Izaak Alpert Date: Mon, 9 Sep 2013 13:18:10 -0400 Subject: [PATCH 141/175] Style guide fixes (spacing) Change-Id: I966bfd0ccc4b05925384ecab8c6cbe3c6ba3b667 --- spec/requests/api/api_helpers_spec.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/spec/requests/api/api_helpers_spec.rb b/spec/requests/api/api_helpers_spec.rb index a1cbfcd60e9..2fc78a7e390 100644 --- a/spec/requests/api/api_helpers_spec.rb +++ b/spec/requests/api/api_helpers_spec.rb @@ -17,7 +17,6 @@ describe API do env[API::APIHelpers::SUDO_HEADER] = identifier end - def set_param(token_usr, identifier) clear_env clear_param @@ -25,7 +24,6 @@ describe API do params[API::APIHelpers::SUDO_PARAM] = identifier end - def clear_env env.delete(API::APIHelpers::PRIVATE_TOKEN_HEADER) env.delete(API::APIHelpers::SUDO_HEADER) @@ -70,6 +68,7 @@ describe API do set_param(user, admin.username) expect { current_user }.to raise_error end + it "should throw an error when the user cannot be found for a given id" do id = user.id + admin.id user.id.should_not == id @@ -80,6 +79,7 @@ describe API do set_param(admin, id) expect { current_user }.to raise_error end + it "should throw an error when the user cannot be found for a given username" do username = "#{user.username}#{admin.username}" user.username.should_not == username @@ -90,6 +90,7 @@ describe API do set_param(admin, username) expect { current_user }.to raise_error end + it "should handle sudo's to oneself" do set_env(admin, admin.id) current_user.should == admin @@ -116,6 +117,7 @@ describe API do current_user.should == user current_user.should == user end + it "should handle multiple sudo's to oneself using string ids" do set_env(admin, user.id.to_s) current_user.should == user -- GitLab From f87e2d2801fa4c9c47466e38012210348fac0710 Mon Sep 17 00:00:00 2001 From: Angus MacArthur Date: Mon, 9 Sep 2013 01:45:30 -0400 Subject: [PATCH 142/175] make public/private setting for project creation configurable --- app/contexts/projects/create_context.rb | 3 +- config/gitlab.yml.example | 1 + config/initializers/1_settings.rb | 1 + spec/contexts/projects_create_context_spec.rb | 28 +++++++++++++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/app/contexts/projects/create_context.rb b/app/contexts/projects/create_context.rb index 1ee3e459074..9fd24e0eeea 100644 --- a/app/contexts/projects/create_context.rb +++ b/app/contexts/projects/create_context.rb @@ -16,7 +16,8 @@ module Projects wiki_enabled: default_features.wiki, wall_enabled: default_features.wall, snippets_enabled: default_features.snippets, - merge_requests_enabled: default_features.merge_requests + merge_requests_enabled: default_features.merge_requests, + public: default_features.public } @project = Project.new(default_opts.merge(params)) diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index 389dba59c9d..99a23db0f1e 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -58,6 +58,7 @@ production: &base wiki: true wall: false snippets: false + public: false ## External issues trackers issues_tracker: diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index b3a19783b14..da7a83a62a4 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -75,6 +75,7 @@ Settings.gitlab.default_projects_features['merge_requests'] = true if Settings.g Settings.gitlab.default_projects_features['wiki'] = true if Settings.gitlab.default_projects_features['wiki'].nil? Settings.gitlab.default_projects_features['wall'] = false if Settings.gitlab.default_projects_features['wall'].nil? Settings.gitlab.default_projects_features['snippets'] = false if Settings.gitlab.default_projects_features['snippets'].nil? +Settings.gitlab.default_projects_features['public'] = false if Settings.gitlab.default_projects_features['public'].nil? # # Gravatar diff --git a/spec/contexts/projects_create_context_spec.rb b/spec/contexts/projects_create_context_spec.rb index dd10dd3ede8..3cabec283d7 100644 --- a/spec/contexts/projects_create_context_spec.rb +++ b/spec/contexts/projects_create_context_spec.rb @@ -30,6 +30,34 @@ describe Projects::CreateContext do it { @project.owner.should == @user } it { @project.namespace.should == @group } end + + context 'respect configured public setting' do + before(:each) do + @settings = double("settings") + @settings.stub(:issues) { true } + @settings.stub(:merge_requests) { true } + @settings.stub(:wiki) { true } + @settings.stub(:wall) { true } + @settings.stub(:snippets) { true } + stub_const("Settings", Class.new) + Settings.stub_chain(:gitlab, :default_projects_features).and_return(@settings) + end + context 'should be public when setting is public' do + before do + @settings.stub(:public) { true } + @project = create_project(@user, @opts) + end + it { @project.public.should be_true } + end + context 'should be private when setting is not public' do + before do + @settings.stub(:public) { false } + @project = create_project(@user, @opts) + end + it { @project.public.should be_false } + end + + end end def create_project(user, opts) -- GitLab From cfe13a0d9f052ab604a8d76e89b4c2fdaf64c2fd Mon Sep 17 00:00:00 2001 From: Angus MacArthur Date: Mon, 9 Sep 2013 16:26:27 -0400 Subject: [PATCH 143/175] update to project creation page to reflect default public project setting --- app/views/projects/new.html.haml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index 736da85952a..ab8efe5e3e1 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -2,8 +2,12 @@ .project-edit-errors = render 'projects/errors' .project-edit-content - %p.slead - New projects are private by default. You choose who can see the project and commit to repository. + - if Gitlab.config.gitlab.default_projects_features.public + %p.slead + New projects are public by default. Any signed in user can see your project but cannot commit to it unless granted access. + - else + %p.slead + New projects are private by default. You choose who can see the project and commit to repository. %hr = form_for @project, remote: true do |f| .control-group.project-name-holder -- GitLab From a30ce86690025a57264b2e9f619a75ee8cdf4826 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 10 Sep 2013 10:17:15 +0300 Subject: [PATCH 144/175] Improve commits list UI --- app/assets/stylesheets/sections/commits.scss | 108 ++++++++---------- app/views/projects/commits/_commit.html.haml | 24 ++-- app/views/projects/commits/_commits.html.haml | 1 + 3 files changed, 58 insertions(+), 75 deletions(-) diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss index 2f4472a52e1..f661276fcaa 100644 --- a/app/assets/stylesheets/sections/commits.scss +++ b/app/assets/stylesheets/sections/commits.scss @@ -345,46 +345,6 @@ } -/** - * COMMIT ROW - */ -.commit { - .browse_code_link_holder { - float: right; - } - - .committed_ago { - float: right; - @extend .cgray; - } - - .notes_count { - float: right; - margin-right: 10px; - } - - code { - background: #FCEEC1; - color: $style_color; - } - - .commit_short_id { - float: left; - @extend .lined; - min-width: 65px; - font-family: $monospace_font; - } - - .row_title { - font-weight: bold; - color: #444; - &:hover { - color: #444; - text-decoration: underline; - } - } -} - .file-stats a { color: $style_color; } @@ -472,24 +432,6 @@ line-height: 2; } -li.commit { - .avatar { - width: 24px; - top:-5px; - margin-right: 5px; - margin-left: 10px; - } - - code { - padding: 2px 2px 0; - margin-top: -2px; - &:hover { - color: black; - border: 1px solid #ccc; - } - } -} - .commit-breadcrumb { padding: 0; } @@ -506,8 +448,50 @@ li.commit { } } -.commits-row { - padding-bottom: 10px; - margin-bottom: 10px; - border-bottom: 1px solid #DDD; +.lists-separator { + margin: 10px 0; + border-top: 1px dashed #CCC; +} + +/** + * COMMIT ROW + */ +li.commit { + padding: 8px; + + .commit-row-title { + font-size: 14px; + margin-bottom: 2px; + + .notes_count { + float: right; + margin-right: 10px; + } + + .commit_short_id { + float: left; + min-width: 65px; + font-family: $monospace_font; + } + + .commit-row-message { + color: #555; + font-weight: bolder; + &:hover { + color: #444; + text-decoration: underline; + } + } + } + + .commit-row-info { + a { + color: #777; + } + + .committed_ago { + float: right; + @extend .cgray; + } + } } diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml index eb5bdb886e2..d70fd96accd 100644 --- a/app/views/projects/commits/_commit.html.haml +++ b/app/views/projects/commits/_commit.html.haml @@ -1,21 +1,19 @@ %li.commit - .browse_code_link_holder - %p - %strong= link_to "Browse Code »", project_tree_path(project, commit), class: "right" - %p + .commit-row-title = link_to commit.short_id(8), project_commit_path(project, commit), class: "commit_short_id" - = commit_author_link(commit, avatar: true, size: 24)   - = link_to_gfm truncate(commit.title, length: 70), project_commit_path(project, commit.id), class: "row_title" - - %time.committed_ago{ datetime: commit.committed_date, title: commit.committed_date.stamp("Aug 21, 2011 9:23pm") } - = time_ago_in_words(commit.committed_date) - ago -   - - %span.notes_count + = link_to_gfm truncate(commit.title, length: 70), project_commit_path(project, commit.id), class: "commit-row-message" + = link_to "Browse Code »", project_tree_path(project, commit), class: "pull-right" + .notes_count - notes = project.notes.for_commit_id(commit.id) - if notes.any? %span.badge.badge-info %i.icon-comment = notes.count + + .commit-row-info + = commit_author_link(commit, avatar: true, size: 16) + %time.committed_ago{ datetime: commit.committed_date, title: commit.committed_date.stamp("Aug 21, 2011 9:23pm") } + = time_ago_in_words(commit.committed_date) + ago +   diff --git a/app/views/projects/commits/_commits.html.haml b/app/views/projects/commits/_commits.html.haml index b6eeeb92287..b6404778073 100644 --- a/app/views/projects/commits/_commits.html.haml +++ b/app/views/projects/commits/_commits.html.haml @@ -8,3 +8,4 @@ .span10 %ul.well-list = render commits, project: @project + %hr.lists-separator -- GitLab From 94d364e8cc84d82d278fee3881f5fab48a149ed2 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 10 Sep 2013 13:15:49 +0300 Subject: [PATCH 145/175] UI fixes for commits lists --- app/assets/stylesheets/sections/commits.scss | 12 +++++++++++- app/assets/stylesheets/sections/events.scss | 17 ++++------------- .../stylesheets/sections/merge_requests.scss | 7 ------- app/helpers/commits_helper.rb | 5 +++-- app/views/events/_commit.html.haml | 8 +++----- .../projects/commits/_inline_commit.html.haml | 9 +++++++++ 6 files changed, 30 insertions(+), 28 deletions(-) create mode 100644 app/views/projects/commits/_inline_commit.html.haml diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss index f661276fcaa..b0cf8b16260 100644 --- a/app/assets/stylesheets/sections/commits.scss +++ b/app/assets/stylesheets/sections/commits.scss @@ -469,7 +469,6 @@ li.commit { } .commit_short_id { - float: left; min-width: 65px; font-family: $monospace_font; } @@ -494,4 +493,15 @@ li.commit { @extend .cgray; } } + + &.inline-commit { + .commit-row-title { + font-size: 13px; + } + + .committed_ago { + float: right; + @extend .cgray; + } + } } diff --git a/app/assets/stylesheets/sections/events.scss b/app/assets/stylesheets/sections/events.scss index 80ee6b6323c..fd5c80f988c 100644 --- a/app/assets/stylesheets/sections/events.scss +++ b/app/assets/stylesheets/sections/events.scss @@ -56,10 +56,6 @@ margin-left: 35px; margin-right: 100px; - .commit p { - color: #666; - padding-top: 5px; - } .event-info { color: #666; } @@ -107,13 +103,6 @@ } } - ul { - .avatar { - width: 18px; - margin: 2px 4px; - } - } - &:last-child { border:none } .event_commits { @@ -124,12 +113,14 @@ background: transparent; padding: 3px; border: none; - font-size: 12px; + color: #666; + .commit-row-title { + font-size: 12px; + } } &.commits-stat { display: block; padding: 3px; - margin-top: 3px; &:hover { background: none; diff --git a/app/assets/stylesheets/sections/merge_requests.scss b/app/assets/stylesheets/sections/merge_requests.scss index e7b464fd4aa..aa61cae4b9a 100644 --- a/app/assets/stylesheets/sections/merge_requests.scss +++ b/app/assets/stylesheets/sections/merge_requests.scss @@ -64,13 +64,6 @@ margin: 0; padding: 0; padding: 5px 0; - .avatar { position:relative } - .commit-author-name, - .dash, - .committed_ago, - .browse_code_link_holder { - display: none; - } list-style: none; &:hover { background: none; diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index e889b390968..f8f84ff8b62 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -56,8 +56,9 @@ module CommitsHelper end end - def commit_to_html commit, project - escape_javascript(render 'projects/commits/commit', commit: commit, project: project) unless commit.nil? + def commit_to_html(commit, project, inline = true) + template = inline ? "inline_commit" : "commit" + escape_javascript(render "projects/commits/#{template}", commit: commit, project: project) unless commit.nil? end def diff_line_content(line) diff --git a/app/views/events/_commit.html.haml b/app/views/events/_commit.html.haml index b50faf5a25c..4d4b24009f4 100644 --- a/app/views/events/_commit.html.haml +++ b/app/views/events/_commit.html.haml @@ -1,7 +1,5 @@ %li.commit - %p + .commit-row-title = link_to commit[:id][0..8], project_commit_path(project, commit[:id]), class: "commit_short_id", alt: '' - %span= commit[:author][:name] - – - = image_tag gravatar_icon(commit[:author][:email]), class: "avatar", width: 16 - = gfm escape_once(truncate(commit[:message], length: 50)) rescue "--broken encoding" +   + = gfm escape_once(truncate(commit[:message], length: 70)) rescue "--broken encoding" diff --git a/app/views/projects/commits/_inline_commit.html.haml b/app/views/projects/commits/_inline_commit.html.haml new file mode 100644 index 00000000000..5be8460e061 --- /dev/null +++ b/app/views/projects/commits/_inline_commit.html.haml @@ -0,0 +1,9 @@ +%li.commit.inline-commit + .commit-row-title + = link_to commit.short_id(8), project_commit_path(project, commit), class: "commit_short_id" +   + = link_to_gfm truncate(commit.title, length: 40), project_commit_path(project, commit.id), class: "commit-row-message" + %time.committed_ago{ datetime: commit.committed_date, title: commit.committed_date.stamp("Aug 21, 2011 9:23pm") } + = time_ago_in_words(commit.committed_date) + ago +   -- GitLab From eaa2781d9cc15590533038647c4901672cef7c6f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 10 Sep 2013 13:37:56 +0300 Subject: [PATCH 146/175] More entries in CHANGELOG for 6.1 --- CHANGELOG | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index e843c180cd8..5c27e93ff64 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,9 +1,15 @@ v 6.1.0 + - Description field added to Merge Request + - API: Sudo api calls (Izaak Alpert) + - API: Group membership api (Izaak Alpert) + - Improved commit diff + - Improved large commit handling (Boyan Tabakov) - Rewrite: Init script now less prone to errors and keeps better track of the service. - Link issues, merge requests, and commits when they reference each other with GFM - Close issues automatically when pushing commits with a special message - Project internal ids for issues, mr, milestones - Improve user removal from admin area + - Invalidate events cache when project was moved - Remove deprecated classes and rake tasks - Add event filter for group and project show pages - Add links to create branch/tag from project home page -- GitLab From 6cc2e6d7edd38cb81c1eabfb0b2607c256785bb3 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 10 Sep 2013 13:42:53 +0300 Subject: [PATCH 147/175] Clear cache when update to 6.1 --- doc/update/6.0-to-6.1.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/update/6.0-to-6.1.md b/doc/update/6.0-to-6.1.md index c9a3a31fd27..dcd09be72f7 100644 --- a/doc/update/6.0-to-6.1.md +++ b/doc/update/6.0-to-6.1.md @@ -54,12 +54,13 @@ sudo -u git -H bundle install --without development test mysql --deployment sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production sudo -u git -H bundle exec rake migrate_iids RAILS_ENV=production sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production +sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production ``` ### 5. Update config files -* Make `/home/git/gitlab/config/gitlab.yml` same as https://github.com/gitlabhq/gitlabhq/blob/5-4-stable/config/gitlab.yml.example but with your settings. -* Make `/home/git/gitlab/config/unicorn.rb` same as https://github.com/gitlabhq/gitlabhq/blob/5-4-stable/config/unicorn.rb.example but with your settings. +* Make `/home/git/gitlab/config/gitlab.yml` same as https://github.com/gitlabhq/gitlabhq/blob/6-1-stable/config/gitlab.yml.example but with your settings. +* Make `/home/git/gitlab/config/unicorn.rb` same as https://github.com/gitlabhq/gitlabhq/blob/6-1-stable/config/unicorn.rb.example but with your settings. ### 6. Update Init script -- GitLab From 3811e4348187ff3dbe9a257c53798e726a851b55 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 10 Sep 2013 13:43:06 +0300 Subject: [PATCH 148/175] Version up to beta1 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index ce3de583065..f5999028a39 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -6.1.0.pre +6.1.0.beta1 -- GitLab From cc1eb9657e67827e3de88d86b7f09f6aa11767a2 Mon Sep 17 00:00:00 2001 From: Angus MacArthur Date: Tue, 10 Sep 2013 10:49:23 -0400 Subject: [PATCH 149/175] style fixes --- spec/contexts/projects_create_context_spec.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/spec/contexts/projects_create_context_spec.rb b/spec/contexts/projects_create_context_spec.rb index 3cabec283d7..be492585b27 100644 --- a/spec/contexts/projects_create_context_spec.rb +++ b/spec/contexts/projects_create_context_spec.rb @@ -42,21 +42,24 @@ describe Projects::CreateContext do stub_const("Settings", Class.new) Settings.stub_chain(:gitlab, :default_projects_features).and_return(@settings) end + context 'should be public when setting is public' do before do @settings.stub(:public) { true } @project = create_project(@user, @opts) end + it { @project.public.should be_true } end + context 'should be private when setting is not public' do before do @settings.stub(:public) { false } @project = create_project(@user, @opts) end + it { @project.public.should be_false } end - end end -- GitLab From e19526c2ac3e6a8ae62934c09ac70219062c818a Mon Sep 17 00:00:00 2001 From: Stephen Holdaway Date: Thu, 12 Sep 2013 00:10:45 +1200 Subject: [PATCH 150/175] Fix several_namespaces? to work with multiple ownership of groups --- app/models/user.rb | 2 +- spec/models/user_spec.rb | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/app/models/user.rb b/app/models/user.rb index c2355eaab99..2411b270fc6 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -322,7 +322,7 @@ class User < ActiveRecord::Base end def several_namespaces? - namespaces.many? + namespaces.many? || owned_groups.any? end def namespace_id diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index de06bf71dc1..d79d2b82b6a 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -139,6 +139,19 @@ describe User do it { @user.owned_groups.should == [@group] } end + describe 'group multiple owners' do + before do + ActiveRecord::Base.observers.enable(:user_observer) + @user = create :user + @user2 = create :user + @group = create :group, owner: @user + + @group.add_users([@user2.id], UsersGroup::OWNER) + end + + it { @user2.several_namespaces?.should be_true } + end + describe 'namespaced' do before do ActiveRecord::Base.observers.enable(:user_observer) -- GitLab From 0235c2a7f3d9424cff075ea366b8f4990824e1db Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 11 Sep 2013 20:27:50 +0300 Subject: [PATCH 151/175] Fix feature test --- features/steps/project/project_forked_merge_requests.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/features/steps/project/project_forked_merge_requests.rb b/features/steps/project/project_forked_merge_requests.rb index 86f16d3bac5..f7bf085a423 100644 --- a/features/steps/project/project_forked_merge_requests.rb +++ b/features/steps/project/project_forked_merge_requests.rb @@ -175,10 +175,9 @@ class ProjectForkedMergeRequests < Spinach::FeatureSteps @project ||= Project.find_by_name!("Shop") end - #Verify a link is generated against the correct project + # Verify a link is generated against the correct project def verify_commit_link(container_div, container_project) - #This should force a wait for the javascript to execute - find(:div,container_div).should have_css ".browse_code_link_holder" + # This should force a wait for the javascript to execute find(:div,container_div).find(".commit_short_id")['href'].should have_content "#{container_project.path_with_namespace}/commit" end end -- GitLab From 694768e51870ebb24a25730188e018782d3175ca Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 11 Sep 2013 21:00:16 +0300 Subject: [PATCH 152/175] Fix 404 if Group guest visit empty group page --- app/controllers/groups_controller.rb | 2 +- app/models/ability.rb | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 3378675692a..9dc9afe9e67 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -110,7 +110,7 @@ class GroupsController < ApplicationController # Dont allow unauthorized access to group def authorize_read_group! - unless projects.present? or can?(current_user, :manage_group, @group) + unless projects.present? or can?(current_user, :read_group, @group) return render_404 end end diff --git a/app/models/ability.rb b/app/models/ability.rb index 74f92fe7438..8335829f919 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -135,6 +135,10 @@ class Ability def group_abilities user, group rules = [] + if group.users.include?(user) + rules << :read_group + end + # Only group owner and administrators can manage group if group.owners.include?(user) || user.admin? rules << [ -- GitLab From d4d4a78f834b409631b012aa555c0cb2c4e3166d Mon Sep 17 00:00:00 2001 From: Izaak Alpert Date: Thu, 8 Aug 2013 14:09:33 -0400 Subject: [PATCH 153/175] Update User api to respect default settings -API now respects default_projects_limit, default_can_create_group, and default_can_create_team Change-Id: I059d060d576df1050e5371e707381c5e8c608a7a --- app/models/user.rb | 5 +++++ lib/api/users.rb | 2 +- spec/requests/api/users_spec.rb | 11 +++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/app/models/user.rb b/app/models/user.rb index 2411b270fc6..526edb9839e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -198,6 +198,11 @@ class User < ActiveRecord::Base User.find_by_username(name_or_id) end end + + def defaults + { projects_limit: Gitlab.config.gitlab.default_projects_limit, can_create_group: Gitlab.config.gitlab.default_can_create_group, can_create_team: Gitlab.config.gitlab.default_can_create_team } + end + end # diff --git a/lib/api/users.rb b/lib/api/users.rb index 84256b51124..3b7ae9f01a1 100644 --- a/lib/api/users.rb +++ b/lib/api/users.rb @@ -46,7 +46,7 @@ module API authenticated_as_admin! required_attributes! [:email, :password, :name, :username] - attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio] + attrs = User.defaults.merge(attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio]) user = User.new attrs, as: :admin if user.save present user, with: Entities::User diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index 2f4aaae3890..c09d78993e1 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -57,6 +57,17 @@ describe API::API do response.status.should == 201 end + it "creating a user should respect default project limit" do + limit = 123456 + Gitlab.config.gitlab.stub(:default_projects_limit).and_return(limit) + attr = attributes_for(:user ) + expect { + post api("/users", admin), attr + }.to change { User.count }.by(1) + User.find_by_username(attr[:username]).projects_limit.should == limit + Gitlab.config.gitlab.unstub(:default_projects_limit) + end + it "should not create user with invalid email" do post api("/users", admin), { email: "invalid email", password: 'password' } response.status.should == 400 -- GitLab From 5dae40f579f66fdc060de633b183ede7bd8b2ce4 Mon Sep 17 00:00:00 2001 From: Izaak Alpert Date: Thu, 15 Aug 2013 17:43:46 -0400 Subject: [PATCH 154/175] Update to only provide one way to get a default user -calling build_user will now apply defaults and only override them if as: :admin is set Change-Id: Id1d938c0967752ecc14370af54f2d88128d18c44 --- app/controllers/admin/users_controller.rb | 4 +- app/models/user.rb | 27 +++++---- lib/api/users.rb | 5 +- lib/gitlab/auth.rb | 66 +++++++++++++++++++++ spec/models/user_spec.rb | 72 +++++++++++++++++------ spec/requests/api/users_spec.rb | 4 +- 6 files changed, 143 insertions(+), 35 deletions(-) diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 7809a157dbc..70bbe306562 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -13,7 +13,7 @@ class Admin::UsersController < Admin::ApplicationController end def new - @user = User.new.with_defaults + @user = User.build_user end def edit @@ -44,7 +44,7 @@ class Admin::UsersController < Admin::ApplicationController password_expires_at: Time.now } - @user = User.new(params[:user].merge(opts), as: :admin) + @user = User.build_user(params[:user].merge(opts), as: :admin) @user.admin = (admin && admin.to_i > 0) @user.created_by_id = current_user.id diff --git a/app/models/user.rb b/app/models/user.rb index 526edb9839e..fbcc004f9b0 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -199,10 +199,16 @@ class User < ActiveRecord::Base end end - def defaults - { projects_limit: Gitlab.config.gitlab.default_projects_limit, can_create_group: Gitlab.config.gitlab.default_can_create_group, can_create_team: Gitlab.config.gitlab.default_can_create_team } + def build_user(attrs = {}, options= {}) + user = User.new(defaults.merge(attrs), options) + # if not as: :admin force default settings + user.with_defaults unless options[:as] == :admin + user end + def defaults + { projects_limit: Gitlab.config.gitlab.default_projects_limit, can_create_group: Gitlab.config.gitlab.default_can_create_group, theme_id: Gitlab::Theme::BASIC } + end end # @@ -213,14 +219,6 @@ class User < ActiveRecord::Base username end - def with_defaults - tap do |u| - u.projects_limit = Gitlab.config.gitlab.default_projects_limit - u.can_create_group = Gitlab.config.gitlab.default_can_create_group - u.theme_id = Gitlab::Theme::MARS - end - end - def notification @notification ||= Notification.new(self) end @@ -380,4 +378,13 @@ class User < ActiveRecord::Base group.owners == [self] end end + + :private + + def with_defaults + User.defaults.each do |k,v| + self.send("#{k}=",v) + end + end + end diff --git a/lib/api/users.rb b/lib/api/users.rb index 3b7ae9f01a1..00dc2311ffd 100644 --- a/lib/api/users.rb +++ b/lib/api/users.rb @@ -45,9 +45,8 @@ module API post do authenticated_as_admin! required_attributes! [:email, :password, :name, :username] - - attrs = User.defaults.merge(attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio]) - user = User.new attrs, as: :admin + attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio] + user = User.build_user(attrs, as: :admin) if user.save present user, with: Entities::User else diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb index 0f196297477..b1e40defc7f 100644 --- a/lib/gitlab/auth.rb +++ b/lib/gitlab/auth.rb @@ -13,6 +13,72 @@ module Gitlab end end + def find_for_ldap_auth(auth, signed_in_resource = nil) + uid = auth.info.uid + provider = auth.provider + email = auth.info.email.downcase unless auth.info.email.nil? + raise OmniAuth::Error, "LDAP accounts must provide an uid and email address" if uid.nil? or email.nil? + + if @user = User.find_by_extern_uid_and_provider(uid, provider) + @user + elsif @user = User.find_by_email(email) + log.info "Updating legacy LDAP user #{email} with extern_uid => #{uid}" + @user.update_attributes(extern_uid: uid, provider: provider) + @user + else + create_from_omniauth(auth, true) + end + end + + def create_from_omniauth(auth, ldap = false) + provider = auth.provider + uid = auth.info.uid || auth.uid + uid = uid.to_s.force_encoding("utf-8") + name = auth.info.name.to_s.force_encoding("utf-8") + email = auth.info.email.to_s.downcase unless auth.info.email.nil? + + ldap_prefix = ldap ? '(LDAP) ' : '' + raise OmniAuth::Error, "#{ldap_prefix}#{provider} does not provide an email"\ + " address" if auth.info.email.blank? + + log.info "#{ldap_prefix}Creating user from #{provider} login"\ + " {uid => #{uid}, name => #{name}, email => #{email}}" + password = Devise.friendly_token[0, 8].downcase + @user = User.build_user({ + extern_uid: uid, + provider: provider, + name: name, + username: email.match(/^[^@]*/)[0], + email: email, + password: password, + password_confirmation: password, + }, as: :admin) + @user.save! + + if Gitlab.config.omniauth['block_auto_created_users'] && !ldap + @user.block + end + + @user + end + + def find_or_new_for_omniauth(auth) + provider, uid = auth.provider, auth.uid + email = auth.info.email.downcase unless auth.info.email.nil? + + if @user = User.find_by_provider_and_extern_uid(provider, uid) + @user + elsif @user = User.find_by_email(email) + @user.update_attributes(extern_uid: uid, provider: provider) + @user + else + if Gitlab.config.omniauth['allow_single_sign_on'] + @user = create_from_omniauth(auth) + @user + end + end + end + def log Gitlab::AppLogger end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index d79d2b82b6a..330d22cf962 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -196,29 +196,63 @@ describe User do it { User.not_in_project(@project).should include(@user, @project.owner) } end - describe 'normal user' do - let(:user) { create(:user, name: 'John Smith') } + describe 'user creation' do + describe 'normal user' do + let(:user) { create(:user, name: 'John Smith') } - it { user.is_admin?.should be_false } - it { user.require_ssh_key?.should be_true } - it { user.can_create_group?.should be_true } - it { user.can_create_project?.should be_true } - it { user.first_name.should == 'John' } - end + it { user.is_admin?.should be_false } + it { user.require_ssh_key?.should be_true } + it { user.can_create_group?.should be_true } + it { user.can_create_project?.should be_true } + it { user.first_name.should == 'John' } + end - describe 'without defaults' do - let(:user) { User.new } - it "should not apply defaults to user" do - user.projects_limit.should == 10 - user.can_create_group.should == true + describe 'without defaults' do + let(:user) { User.new } + it "should not apply defaults to user" do + user.projects_limit.should == 10 + user.can_create_group.should be_true + user.theme_id.should == Gitlab::Theme::BASIC + end end - end + context 'as admin' do + describe 'with defaults' do + let(:user) { User.build_user({}, as: :admin) } + it "should apply defaults to user" do + user.projects_limit.should == 42 + user.can_create_group.should be_false + user.theme_id.should == Gitlab::Theme::BASIC + end + end + + describe 'with default overrides' do + let(:user) { User.build_user({projects_limit: 123, can_create_group: true, can_create_team: true, theme_id: Gitlab::Theme::MARS}, as: :admin) } + it "should apply defaults to user" do + user.projects_limit.should == 123 + user.can_create_group.should be_true + user.theme_id.should == Gitlab::Theme::MARS + end + end + end + + context 'as user' do + describe 'with defaults' do + let(:user) { User.build_user } + it "should apply defaults to user" do + user.projects_limit.should == 42 + user.can_create_group.should be_false + user.theme_id.should == Gitlab::Theme::BASIC + end + end - describe 'with defaults' do - let(:user) { User.new.with_defaults } - it "should apply defaults to user" do - user.projects_limit.should == 42 - user.can_create_group.should == false + describe 'with default overrides' do + let(:user) { User.build_user(projects_limit: 123, can_create_group: true, theme_id: Gitlab::Theme::MARS) } + it "should apply defaults to user" do + user.projects_limit.should == 42 + user.can_create_group.should be_false + user.theme_id.should == Gitlab::Theme::BASIC + end + end end end diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index c09d78993e1..e42c0567ef6 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -64,7 +64,9 @@ describe API::API do expect { post api("/users", admin), attr }.to change { User.count }.by(1) - User.find_by_username(attr[:username]).projects_limit.should == limit + user = User.find_by_username(attr[:username]) + user.projects_limit.should == limit + user.theme_id.should == Gitlab::Theme::BASIC Gitlab.config.gitlab.unstub(:default_projects_limit) end -- GitLab From 810851f5740599dc8b1419dcf817bac48ee967fc Mon Sep 17 00:00:00 2001 From: Izaak Alpert Date: Wed, 11 Sep 2013 12:23:04 -0400 Subject: [PATCH 155/175] Style updates Change-Id: Ib4eb533dff5c722fe559330e4aa71b5d5baf6fb8 --- app/models/user.rb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/app/models/user.rb b/app/models/user.rb index fbcc004f9b0..e92f0847724 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -207,7 +207,11 @@ class User < ActiveRecord::Base end def defaults - { projects_limit: Gitlab.config.gitlab.default_projects_limit, can_create_group: Gitlab.config.gitlab.default_can_create_group, theme_id: Gitlab::Theme::BASIC } + { + projects_limit: Gitlab.config.gitlab.default_projects_limit, + can_create_group: Gitlab.config.gitlab.default_can_create_group, + theme_id: Gitlab::Theme::BASIC + } end end @@ -379,12 +383,11 @@ class User < ActiveRecord::Base end end - :private + private def with_defaults User.defaults.each do |k,v| self.send("#{k}=",v) end end - end -- GitLab From fc6ed495487084b051d7228fdafe814784ea3ea0 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 11 Sep 2013 21:12:33 +0300 Subject: [PATCH 156/175] Update poltergeist and database_cleaner --- Gemfile | 2 +- Gemfile.lock | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Gemfile b/Gemfile index 5b8118457d3..b201969bc36 100644 --- a/Gemfile +++ b/Gemfile @@ -187,7 +187,7 @@ group :development, :test do gem 'rb-inotify', require: linux_only('rb-inotify') # PhantomJS driver for Capybara - gem 'poltergeist', '~> 1.3.0' + gem 'poltergeist', '~> 1.4.1' gem 'spork', '~> 1.0rc' gem 'jasmine' diff --git a/Gemfile.lock b/Gemfile.lock index d71988e13e6..ddca83d38c2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -72,6 +72,7 @@ GEM railties (>= 3.0) sass-rails (>= 3.2) chunky_png (1.2.8) + cliver (0.2.1) code_analyzer (0.3.2) sexp_processor coderay (1.0.9) @@ -102,7 +103,7 @@ GEM d3_rails (3.1.10) railties (>= 3.1.0) daemons (1.1.9) - database_cleaner (1.0.1) + database_cleaner (1.1.1) debug_inspector (0.0.2) descendants_tracker (0.0.1) devise (2.2.5) @@ -132,8 +133,6 @@ GEM multipart-post (~> 1.1) faraday_middleware (0.9.0) faraday (>= 0.7.4, < 0.9) - faye-websocket (0.4.7) - eventmachine (>= 0.12.0) ffaker (1.16.1) ffi (1.9.0) fog (1.3.1) @@ -275,7 +274,7 @@ GEM mime-types (~> 1.16) treetop (~> 1.4.8) method_source (0.8.1) - mime-types (1.23) + mime-types (1.25) minitest (4.7.4) modernizr (2.6.2) sprockets (~> 2.0) @@ -315,10 +314,11 @@ GEM omniauth-oauth (~> 1.0) orm_adapter (0.4.0) pg (0.15.1) - poltergeist (1.3.0) + poltergeist (1.4.1) capybara (~> 2.1.0) - faye-websocket (>= 0.4.4, < 0.5.0) - http_parser.rb (~> 0.5.3) + cliver (~> 0.2.1) + multi_json (~> 1.0) + websocket-driver (>= 0.2.0) polyglot (0.3.3) posix-spawn (0.3.6) pry (0.9.12.2) @@ -534,6 +534,7 @@ GEM addressable (>= 2.2.7) crack (>= 0.3.2) websocket (1.0.7) + websocket-driver (0.3.0) xpath (2.0.0) nokogiri (~> 1.3) yajl-ruby (1.1.0) @@ -599,7 +600,7 @@ DEPENDENCIES omniauth-google-oauth2 omniauth-twitter pg - poltergeist (~> 1.3.0) + poltergeist (~> 1.4.1) pry quiet_assets (~> 1.0.1) rack-mini-profiler -- GitLab From 73446fe15e35c6e9d077b071bec7f06f64a1b6b9 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 11 Sep 2013 21:17:28 +0300 Subject: [PATCH 157/175] Email templates when user was added to group --- app/mailers/emails/groups.rb | 11 +++++++++++ app/mailers/emails/profile.rb | 15 +++++++++++++++ app/mailers/emails/projects.rb | 1 - app/mailers/notify.rb | 14 ++------------ .../notify/group_access_granted_email.html.haml | 5 +++++ .../notify/group_access_granted_email.text.erb | 4 ++++ 6 files changed, 37 insertions(+), 13 deletions(-) create mode 100644 app/mailers/emails/groups.rb create mode 100644 app/mailers/emails/profile.rb create mode 100644 app/views/notify/group_access_granted_email.html.haml create mode 100644 app/views/notify/group_access_granted_email.text.erb diff --git a/app/mailers/emails/groups.rb b/app/mailers/emails/groups.rb new file mode 100644 index 00000000000..2e9d28981e3 --- /dev/null +++ b/app/mailers/emails/groups.rb @@ -0,0 +1,11 @@ +module Emails + module Groups + def group_access_granted_email(user_group_id) + @membership = UsersGroup.find(user_group_id) + @group = @membership.group + + mail(to: @membership.user.email, + subject: subject("access to group was granted")) + end + end +end diff --git a/app/mailers/emails/profile.rb b/app/mailers/emails/profile.rb new file mode 100644 index 00000000000..bcd44f9476c --- /dev/null +++ b/app/mailers/emails/profile.rb @@ -0,0 +1,15 @@ +module Emails + module Profile + def new_user_email(user_id, password) + @user = User.find(user_id) + @password = password + mail(to: @user.email, subject: subject("Account was created for you")) + end + + def new_ssh_key_email(key_id) + @key = Key.find(key_id) + @user = @key.user + mail(to: @user.email, subject: subject("SSH key was added to your account")) + end + end +end diff --git a/app/mailers/emails/projects.rb b/app/mailers/emails/projects.rb index 1ad7ca588bd..4d5fe9ef614 100644 --- a/app/mailers/emails/projects.rb +++ b/app/mailers/emails/projects.rb @@ -7,7 +7,6 @@ module Emails subject: subject("access to project was granted")) end - def project_was_moved_email(project_id, user_id) @user = User.find user_id @project = Project.find project_id diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb index 7890ca7793b..2f7be00c33e 100644 --- a/app/mailers/notify.rb +++ b/app/mailers/notify.rb @@ -3,6 +3,8 @@ class Notify < ActionMailer::Base include Emails::MergeRequests include Emails::Notes include Emails::Projects + include Emails::Profile + include Emails::Groups add_template_helper ApplicationHelper add_template_helper GitlabMarkdownHelper @@ -20,18 +22,6 @@ class Notify < ActionMailer::Base delay_for(2.seconds) end - def new_user_email(user_id, password) - @user = User.find(user_id) - @password = password - mail(to: @user.email, subject: subject("Account was created for you")) - end - - def new_ssh_key_email(key_id) - @key = Key.find(key_id) - @user = @key.user - mail(to: @user.email, subject: subject("SSH key was added to your account")) - end - private # Look up a User by their ID and return their email address diff --git a/app/views/notify/group_access_granted_email.html.haml b/app/views/notify/group_access_granted_email.html.haml new file mode 100644 index 00000000000..5023ec737a5 --- /dev/null +++ b/app/views/notify/group_access_granted_email.html.haml @@ -0,0 +1,5 @@ +%p + = "You have been granted #{@membership.human_access} access to group" +%p + = link_to group_url(@group) do + = @group.name diff --git a/app/views/notify/group_access_granted_email.text.erb b/app/views/notify/group_access_granted_email.text.erb new file mode 100644 index 00000000000..331bb98d5c9 --- /dev/null +++ b/app/views/notify/group_access_granted_email.text.erb @@ -0,0 +1,4 @@ + +You have been granted <%= @membership.human_access %> access to group <%= @group.name %> + +<%= url_for(group_url(@group)) %> -- GitLab From 88d4559e62f4e49de6b3ceab2620e418c11eb7f6 Mon Sep 17 00:00:00 2001 From: Izaak Alpert Date: Wed, 11 Sep 2013 14:03:26 -0400 Subject: [PATCH 158/175] Removed private scope Change-Id: Ia723321a5cb05deb626d34c7d8d78194e049b1f0 --- app/models/user.rb | 2 -- lib/gitlab/oauth/user.rb | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/models/user.rb b/app/models/user.rb index e92f0847724..ea1b9419288 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -383,8 +383,6 @@ class User < ActiveRecord::Base end end - private - def with_defaults User.defaults.each do |k,v| self.send("#{k}=",v) diff --git a/lib/gitlab/oauth/user.rb b/lib/gitlab/oauth/user.rb index 515c5b769e5..1b32b99f4ba 100644 --- a/lib/gitlab/oauth/user.rb +++ b/lib/gitlab/oauth/user.rb @@ -27,7 +27,7 @@ module Gitlab password_confirmation: password, } - user = model.new(opts, as: :admin).with_defaults + user = model.build_user(opts, as: :admin) user.save! log.info "(OAuth) Creating user #{email} from login with extern_uid => #{uid}" -- GitLab From 4002561e1798bc1b6609c3ea852b0bf568f1e51d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 11 Sep 2013 22:20:51 +0300 Subject: [PATCH 159/175] New landing page when you have 0 projects --- app/assets/stylesheets/common.scss | 9 ++++ .../_zero_authorized_projects.html.haml | 48 ++++++++++++++----- 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss index 66cc2ffc92d..6d80b22b3aa 100644 --- a/app/assets/stylesheets/common.scss +++ b/app/assets/stylesheets/common.scss @@ -373,3 +373,12 @@ table { text-align: center; } } + +.dashboard-intro-icon { + float: left; + font-size: 32px; + color: #AAA; + padding: 5px 0; + width: 50px; + min-height: 100px; +} diff --git a/app/views/dashboard/_zero_authorized_projects.html.haml b/app/views/dashboard/_zero_authorized_projects.html.haml index ea5d8d6376f..79d5dca8845 100644 --- a/app/views/dashboard/_zero_authorized_projects.html.haml +++ b/app/views/dashboard/_zero_authorized_projects.html.haml @@ -1,12 +1,36 @@ -%h3.nothing_here_message - You don't have access to any projects. - %br - - if current_user.can_create_project? - You can create up to - = pluralize(current_user.projects_limit, "project") + "." - Click on the button below to add a new one - .link_holder - = link_to new_project_path, class: "btn btn-primary" do - New Project » - - else - If you are added to a project, it will be displayed here +%h3.page-title Welcome to GitLab! +%p.light Self Hosted Git Management application. +%hr +%div + .dashboard-intro-icon + %i.icon-bookmark-empty + %div + %p.slead + You don't have access to any projects right now. + %br + - if current_user.can_create_project? + You can create up to + %strong= pluralize(current_user.projects_limit, "project") + "." + Click on the button below to add a new one + - else + If you are added to a project, it will be displayed here + + - if current_user.can_create_project? + .link_holder + = link_to new_project_path, class: "btn btn-new" do + New project » + +- if current_user.can_create_group? + %hr + %div + .dashboard-intro-icon + %i.icon-group + %div + %p.slead + You can create a group for several dependent projects. + %br + Group is the best way to manage projects and members + .link_holder + = link_to new_group_path, class: "btn btn-new" do + New group » + -- GitLab From 13fec18ac9cbdecdef3b0e5fb7dd7480e9d7cbbf Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 11 Sep 2013 22:46:37 +0300 Subject: [PATCH 160/175] Truncate some text from dashboard events --- app/helpers/application_helper.rb | 7 +++++++ app/helpers/events_helper.rb | 4 +++- app/views/events/event/_push.html.haml | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 0a49892ca0a..4209b081bfa 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -235,4 +235,11 @@ module ApplicationHelper "Search" end end + + def first_line(str) + lines = str.split("\n") + line = lines.first + line += "..." if lines.size > 1 + line + end end diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb index 3c637404c4f..cd8761a6113 100644 --- a/app/helpers/events_helper.rb +++ b/app/helpers/events_helper.rb @@ -123,6 +123,8 @@ module EventsHelper end def event_note(text) - sanitize(markdown(truncate(text, length: 150)), tags: %w(a img b pre p)) + text = first_line(text) + text = truncate(text, length: 150) + sanitize(markdown(text), tags: %w(a img b pre p)) end end diff --git a/app/views/events/event/_push.html.haml b/app/views/events/event/_push.html.haml index f2b8dc4238c..adba9a5f619 100644 --- a/app/views/events/event/_push.html.haml +++ b/app/views/events/event/_push.html.haml @@ -5,7 +5,7 @@ %strong= event.ref_name - else = link_to project_commits_path(event.project, event.ref_name) do - %strong= event.ref_name + %strong= truncate(event.ref_name, length: 30) at %strong= link_to_project event.project -- GitLab From 7bf8d22f178d5628e9c2dc8e79ec94a016e1d69b Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 11 Sep 2013 22:50:08 +0300 Subject: [PATCH 161/175] Remove commented tests since nobody is going to fix them --- .../project/forked_merge_requests.feature | 9 ---- features/project/issues/issues.feature | 17 ------- spec/features/notes_on_merge_requests_spec.rb | 45 ------------------- 3 files changed, 71 deletions(-) diff --git a/features/project/forked_merge_requests.feature b/features/project/forked_merge_requests.feature index 2c6c1ef574c..966905645a2 100644 --- a/features/project/forked_merge_requests.feature +++ b/features/project/forked_merge_requests.feature @@ -4,15 +4,6 @@ Feature: Project Forked Merge Requests And I am a member of project "Shop" And I have a project forked off of "Shop" called "Forked Shop" - # TODO: fix - #@javascript - #Scenario: I can visit the target projects commit for a forked merge request - #Given I visit project "Forked Shop" merge requests page - #And I click link "New Merge Request" - #And I fill out a "Merge Request On Forked Project" merge request - #And I follow the target commit link - #Then I should see the commit under the forked from project - @javascript Scenario: I submit new unassigned merge request to a forked project Given I visit project "Forked Shop" merge requests page diff --git a/features/project/issues/issues.feature b/features/project/issues/issues.feature index d6ef384c9a6..022188f8250 100644 --- a/features/project/issues/issues.feature +++ b/features/project/issues/issues.feature @@ -54,20 +54,3 @@ Feature: Project Issues And I fill in issue search with "0.3" Then I should see "Release 0.3" in issues And I should not see "Release 0.4" in issues - - # Disable this two cause of random failing - # TODO: fix after v4.0 released - #@javascript - #Scenario: I create Issue with pre-selected milestone - #Given project "Shop" has milestone "v2.2" - #And project "Shop" has milestone "v3.0" - #And I visit project "Shop" issues page - #When I select milestone "v3.0" - #And I click link "New Issue" - #Then I should see selected milestone with title "v3.0" - - #@javascript - #Scenario: I create Issue with pre-selected assignee - #When I select first assignee from "Shop" project - #And I click link "New Issue" - #Then I should see first assignee from "Shop" as selected assignee diff --git a/spec/features/notes_on_merge_requests_spec.rb b/spec/features/notes_on_merge_requests_spec.rb index 16bdaf0f83c..ba580d9484d 100644 --- a/spec/features/notes_on_merge_requests_spec.rb +++ b/spec/features/notes_on_merge_requests_spec.rb @@ -206,17 +206,6 @@ describe "On a merge request diff", js: true, focus: true do find(".js-note-preview-button").trigger("click") end end - - # TODO: fix - #it 'should check if previews were rendered separately' do - #within("tr[id='4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185'] + .js-temp-notes-holder") do - #should have_css(".js-note-preview", text: "One comment on line 185") - #end - - #within("tr[id='342e16cbbd482ac2047dc679b2749d248cc1428f_18_17'] + .js-temp-notes-holder") do - #should have_css(".js-note-preview", text: "Another comment on line 17") - #end - #end end describe "posting a note" do @@ -239,42 +228,8 @@ describe "On a merge request diff", js: true, focus: true do should have_css(".notes_holder .note", count: 1) should have_link("Reply") end - - # TODO: fix - #it "should remove last note of a discussion" do - # within("tr[id='342e16cbbd482ac2047dc679b2749d248cc1428f_18_17'] + .notes-holder") do - # find(".js-note-delete").click - # end - # should_not have_css(".note_holder") - #end end end - - # TODO: fix - #describe "when replying to a note" do - #before do - ## create first note - # find('a[data-line-code="4735dfc552ad7bf15ca468adc3cad9d05b624490_184_184"]').click - - # within(".js-temp-notes-holder") do - # fill_in "note[note]", with: "One comment on line 184" - # click_button("Add Comment") - #end - - # within(".js-temp-notes-holder") do - # find(".js-discussion-reply-button").click - # fill_in "note[note]", with: "An additional comment in reply" - # click_button("Add Comment") - # end - #end - - #it 'should be inserted and form removed from reply' do - # should have_content("An additional comment in reply") - # within(".notes_holder") { should have_css(".note", count: 2) } - # within(".notes_holder") { should have_no_css("form") } - # within(".notes_holder") { should have_link("Reply") } - # end - #end end describe "On merge request discussion", js: true do -- GitLab From 0a05ab9126aa1edadea069e9e7dbe272da4b9618 Mon Sep 17 00:00:00 2001 From: Ryan Mendivil Date: Tue, 10 Sep 2013 17:36:04 -0800 Subject: [PATCH 162/175] Fix bug with rendering changing images in commits When viewing the diff for a changed image file, two bugs occur: - Both the 'before' and 'after' images link to the 'after' commit - Visiting the link for either image will cause a error The first is caused by both image links referencing '@commit.id' rather than '@commit.parent_id'. The second is caused by the use of 'project_tree_path' which is used for creating links to directories in the git file tree. 'project_blob_path' which links to files should be used instead. --- app/views/projects/commits/_image.html.haml | 4 ++-- features/project/commits/commits.feature | 4 ++++ features/steps/project/project_browse_commits.rb | 10 ++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/app/views/projects/commits/_image.html.haml b/app/views/projects/commits/_image.html.haml index db02fa333b9..73f87289d3d 100644 --- a/app/views/projects/commits/_image.html.haml +++ b/app/views/projects/commits/_image.html.haml @@ -9,7 +9,7 @@ %div.two-up.view %span.wrap .frame.deleted - %a{href: project_tree_path(@project, tree_join(@commit.id, diff.old_path))} + %a{href: project_blob_path(@project, tree_join(@commit.parent_id, diff.old_path))} %img{src: "data:#{old_file.mime_type};base64,#{Base64.encode64(old_file.data)}"} %p.image-info.hide %span.meta-filesize= "#{number_to_human_size old_file.size}" @@ -21,7 +21,7 @@ %span.meta-height %span.wrap .frame.added - %a{href: project_tree_path(@project, tree_join(@commit.id, diff.new_path))} + %a{href: project_blob_path(@project, tree_join(@commit.id, diff.new_path))} %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"} %p.image-info.hide %span.meta-filesize= "#{number_to_human_size file.size}" diff --git a/features/project/commits/commits.feature b/features/project/commits/commits.feature index d962471ebdb..fe470f5ac99 100644 --- a/features/project/commits/commits.feature +++ b/features/project/commits/commits.feature @@ -35,3 +35,7 @@ Feature: Project Browse commits Scenario: I browse huge commit Given I visit huge commit page Then I see huge commit message + + Scenario: I browse a commit with an image + Given I visit a commit with an image that changed + Then The diff links to both the previous and current image diff --git a/features/steps/project/project_browse_commits.rb b/features/steps/project/project_browse_commits.rb index 4b122b853e6..650bc3a16f7 100644 --- a/features/steps/project/project_browse_commits.rb +++ b/features/steps/project/project_browse_commits.rb @@ -78,4 +78,14 @@ class ProjectBrowseCommits < Spinach::FeatureSteps page.should have_content "Warning! This is a large diff" page.should_not have_content "If you still want to see the diff" end + + Given 'I visit a commit with an image that changed' do + visit project_commit_path(@project, 'cc1ba255d6c5ffdce87a357ba7ccc397a4f4026b') + end + + Then 'The diff links to both the previous and current image' do + links = page.all('.two-up span div a') + links[0]['href'].should =~ %r{blob/bc3735004cb45cec5e0e4fa92710897a910a5957} + links[1]['href'].should =~ %r{blob/cc1ba255d6c5ffdce87a357ba7ccc397a4f4026b} + end end -- GitLab From 5c2d3c8e50b55e04d7094f9d4a95e7f6f88894ce Mon Sep 17 00:00:00 2001 From: Joerg Bornschein Date: Thu, 12 Sep 2013 14:30:55 +0200 Subject: [PATCH 163/175] Fix typo in tests --- features/admin/users.feature | 2 +- features/steps/admin/admin_users.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/features/admin/users.feature b/features/admin/users.feature index 4c951df9fe2..7f503cf9235 100644 --- a/features/admin/users.feature +++ b/features/admin/users.feature @@ -13,4 +13,4 @@ Feature: Admin Users And Input non ascii char in username And Click save Then See username error message - And Not chenged form action url + And Not changed form action url diff --git a/features/steps/admin/admin_users.rb b/features/steps/admin/admin_users.rb index 61b3ed91beb..33c1344eaeb 100644 --- a/features/steps/admin/admin_users.rb +++ b/features/steps/admin/admin_users.rb @@ -28,7 +28,7 @@ class AdminUsers < Spinach::FeatureSteps end end - And 'Not chenged form action url' do + And 'Not changed form action url' do page.should have_selector %(form[action="/admin/users/#{@user.username}"]) end end -- GitLab From cb6d7e5192c926b61d8cbdd4f4e0d45813ed7a09 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Thu, 12 Sep 2013 15:28:46 +0200 Subject: [PATCH 164/175] Rescue an error if group doesn't exist --- lib/tasks/gitlab/check.rake | 6 ++++-- lib/tasks/gitlab/task_helpers.rake | 6 +++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index 74b3e7787e6..1e9228a3509 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -479,11 +479,13 @@ namespace :gitlab do return end - if File.stat(repo_base_path).uid == uid_for(gitlab_shell_ssh_user) && - File.stat(repo_base_path).gid == gid_for(gitlab_shell_owner_group) + uid = uid_for(gitlab_shell_ssh_user) + gid = gid_for(gitlab_shell_owner_group) + if File.stat(repo_base_path).uid == uid && File.stat(repo_base_path).gid == gid puts "yes".green else puts "no".red + puts " User id for #{gitlab_shell_ssh_user}: #{uid}. Groupd id for #{gitlab_shell_owner_group}: #{gid}".blue try_fixing_it( "sudo chown -R #{gitlab_shell_ssh_user}:#{gitlab_shell_owner_group} #{repo_base_path}" ) diff --git a/lib/tasks/gitlab/task_helpers.rake b/lib/tasks/gitlab/task_helpers.rake index f84257d15b5..ac2c4577c77 100644 --- a/lib/tasks/gitlab/task_helpers.rake +++ b/lib/tasks/gitlab/task_helpers.rake @@ -80,7 +80,11 @@ namespace :gitlab do end def gid_for(group_name) - Etc.getgrnam(group_name).gid + begin + Etc.getgrnam(group_name).gid + rescue ArgumentError # no group + "group #{group_name} doesn't exist" + end end def warn_user_is_not_gitlab -- GitLab From 8589824f005dc6d0c8291c454ff7ecdcadacf695 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 12 Sep 2013 18:59:31 +0300 Subject: [PATCH 165/175] Add UsersGroup observer Trigger notification service when new user-group relation was created --- app/observers/users_group_observer.rb | 9 +++++++ spec/observers/users_group_observer_spec.rb | 27 +++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 app/observers/users_group_observer.rb create mode 100644 spec/observers/users_group_observer_spec.rb diff --git a/app/observers/users_group_observer.rb b/app/observers/users_group_observer.rb new file mode 100644 index 00000000000..ecdbede89d9 --- /dev/null +++ b/app/observers/users_group_observer.rb @@ -0,0 +1,9 @@ +class UsersGroupObserver < BaseObserver + def after_create(membership) + notification.new_group_member(membership) + end + + def after_update(membership) + notification.update_group_member(membership) + end +end diff --git a/spec/observers/users_group_observer_spec.rb b/spec/observers/users_group_observer_spec.rb new file mode 100644 index 00000000000..3bf562edbb7 --- /dev/null +++ b/spec/observers/users_group_observer_spec.rb @@ -0,0 +1,27 @@ +require 'spec_helper' + +describe UsersGroupObserver do + before(:each) { enable_observers } + after(:each) { disable_observers } + + subject { UsersGroupObserver.instance } + before { subject.stub(notification: mock('NotificationService').as_null_object) } + + describe "#after_create" do + it "should send email to user" do + subject.should_receive(:notification) + create(:users_group) + end + end + + describe "#after_update" do + before do + @membership = create :users_group + end + + it "should send email to user" do + subject.should_receive(:notification) + @membership.update_attribute(:group_access, UsersGroup::MASTER) + end + end +end -- GitLab From c1dd31cf8bd98ec1a8d951fa6211bfa799233650 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 12 Sep 2013 19:00:32 +0300 Subject: [PATCH 166/175] Enable UsersGroup observer, Add group_member methods to NotificationService --- app/services/notification_service.rb | 8 ++++++++ config/application.rb | 1 + spec/mailers/notify_spec.rb | 20 ++++++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index c20b07e69f0..71c25dc1b70 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -148,6 +148,14 @@ class NotificationService mailer.project_access_granted_email(users_project.id) end + def new_group_member(users_group) + mailer.group_access_granted_email(users_group.id) + end + + def update_group_member(users_group) + mailer.group_access_granted_email(users_group.id) + end + protected # Get project users with WATCH notification level diff --git a/config/application.rb b/config/application.rb index f7349fa009b..8ac07ef337a 100644 --- a/config/application.rb +++ b/config/application.rb @@ -32,6 +32,7 @@ module Gitlab :project_observer, :system_hook_observer, :user_observer, + :users_group_observer, :users_project_observer # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index 2f0475e5f02..0787bdbea6f 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -347,4 +347,24 @@ describe Notify do end end end + + describe 'group access changed' do + let(:group) { create(:group) } + let(:user) { create(:user) } + let(:membership) { create(:users_group, group: group, user: user) } + + subject { Notify.group_access_granted_email(membership.id) } + + it 'has the correct subject' do + should have_subject /access to group was granted/ + end + + it 'contains name of project' do + should have_body_text /#{group.name}/ + end + + it 'contains new user role' do + should have_body_text /#{membership.human_access}/ + end + end end -- GitLab From f774949d3f7676f925c7fc858d462ec2400e43a2 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 12 Sep 2013 20:15:10 +0300 Subject: [PATCH 167/175] Compare page improved * Show new merge request button from compare page * Show message if user selected same branches * Show message if compared branches are the same * Prepend inputs with from/to labels --- .../stylesheets/gitlab_bootstrap/forms.scss | 7 ++- app/helpers/compare_helper.rb | 12 +++++ app/views/projects/compare/_form.html.haml | 45 ++++++++----------- app/views/projects/compare/index.html.haml | 10 +++++ app/views/projects/compare/show.html.haml | 13 ++++++ app/views/projects/issues/_form.html.haml | 4 +- 6 files changed, 58 insertions(+), 33 deletions(-) create mode 100644 app/helpers/compare_helper.rb diff --git a/app/assets/stylesheets/gitlab_bootstrap/forms.scss b/app/assets/stylesheets/gitlab_bootstrap/forms.scss index 020a0bf7fd5..a2612166c78 100644 --- a/app/assets/stylesheets/gitlab_bootstrap/forms.scss +++ b/app/assets/stylesheets/gitlab_bootstrap/forms.scss @@ -6,10 +6,9 @@ form { } } -input { - &.input-xpadding { - padding: 6px 10px; - } +input.input-xpadding, +.add-on.input-xpadding { + padding: 6px 10px; } .control-group { diff --git a/app/helpers/compare_helper.rb b/app/helpers/compare_helper.rb new file mode 100644 index 00000000000..55d0d6268ad --- /dev/null +++ b/app/helpers/compare_helper.rb @@ -0,0 +1,12 @@ +module CompareHelper + def compare_to_mr_button? + params[:from].present? && params[:to].present? && + @repository.branch_names.include?(params[:from]) && + @repository.branch_names.include?(params[:to]) && + !@refs_are_same + end + + def compare_mr_path + new_project_merge_request_path(@project, merge_request: {source_branch: params[:from], target_branch: params[:to]}) + end +end diff --git a/app/views/projects/compare/_form.html.haml b/app/views/projects/compare/_form.html.haml index 503b39c0663..ca1ea4073e6 100644 --- a/app/views/projects/compare/_form.html.haml +++ b/app/views/projects/compare/_form.html.haml @@ -1,30 +1,21 @@ -%div - - unless params[:to] - %p.slead - Fill input field with commit id like - %code.label-branch 4eedf23 - or branch/tag name like - %code.label-branch master - and press compare button for the commits list and a code diff. - %br - Changes are shown from the version in the first field to the version in the second field. - - - = form_tag project_compare_index_path(@project), method: :post do - .clearfix - .pull-left - - if params[:to] && params[:from] - = link_to 'switch', {from: params[:to], to: params[:from]}, {class: 'commits-compare-switch has_tooltip', title: 'Switch base of comparison'} - = text_field_tag :from, params[:from], placeholder: "from", class: "input-xlarge input-xpadding" - = "..." - = text_field_tag :to, params[:to], placeholder: "to", class: "input-xlarge input-xpadding" - .pull-left -   - = submit_tag "Compare", class: "btn btn-create commits-compare-btn" - - if @refs_are_same - .alert - %span Refs are the same - += form_tag project_compare_index_path(@project), method: :post do + .clearfix + .pull-left + - if params[:to] && params[:from] + = link_to 'switch', {from: params[:to], to: params[:from]}, {class: 'commits-compare-switch has_tooltip', title: 'Switch base of comparison'} + .input-prepend + %span.add-on.input-xpadding from + = text_field_tag :from, params[:from], class: "span3 input-xpadding" + = "..." + .input-prepend + %span.add-on.input-xpadding to + = text_field_tag :to, params[:to], class: "span3 input-xpadding" + .pull-left +   + = submit_tag "Compare", class: "btn btn-create commits-compare-btn" + - if compare_to_mr_button? + = link_to compare_mr_path, class: 'prepend-left-10' do + %strong Make a merge request :javascript diff --git a/app/views/projects/compare/index.html.haml b/app/views/projects/compare/index.html.haml index 8f108ed0b08..4745bfbeaaf 100644 --- a/app/views/projects/compare/index.html.haml +++ b/app/views/projects/compare/index.html.haml @@ -2,5 +2,15 @@ %h3.page-title Compare View +%p.slead + Compare branches, tags or commit ranges. + %br + Fill input field with commit id like + %code.label-branch 4eedf23 + or branch/tag name like + %code.label-branch master + and press compare button for the commits list and a code diff. + %br + Changes are shown from the version in the first field to the version in the second field. = render "form" diff --git a/app/views/projects/compare/show.html.haml b/app/views/projects/compare/show.html.haml index af9273f9315..4be62d36917 100644 --- a/app/views/projects/compare/show.html.haml +++ b/app/views/projects/compare/show.html.haml @@ -20,3 +20,16 @@ - unless @diffs.empty? %h4 Diff = render "projects/commits/diffs", diffs: @diffs, project: @project +- else + .light-well + %center + %h4 + There isn't anything to compare. + %p.slead + - if params[:to] == params[:from] + You'll need to use different branch names to get a valid comparison. + - else + %span.label-branch #{params[:from]} + and + %span.label-branch #{params[:to]} + are the same. diff --git a/app/views/projects/issues/_form.html.haml b/app/views/projects/issues/_form.html.haml index 957cc5a7e2d..6acad9134d1 100644 --- a/app/views/projects/issues/_form.html.haml +++ b/app/views/projects/issues/_form.html.haml @@ -67,8 +67,8 @@ event.preventDefault(); } }) - .bind( "click", function( event ) { - $( this ).autocomplete("search", ""); + .bind("click", function(event) { + $(this).autocomplete("search", ""); }) .autocomplete({ minLength: 0, -- GitLab From ed72e949f2947e26b8990aac9b8e6f3b836c85b7 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 12 Sep 2013 20:23:03 +0300 Subject: [PATCH 168/175] Right branches for mr link at Compare view --- app/helpers/compare_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/helpers/compare_helper.rb b/app/helpers/compare_helper.rb index 55d0d6268ad..e1dd89dcd3d 100644 --- a/app/helpers/compare_helper.rb +++ b/app/helpers/compare_helper.rb @@ -7,6 +7,6 @@ module CompareHelper end def compare_mr_path - new_project_merge_request_path(@project, merge_request: {source_branch: params[:from], target_branch: params[:to]}) + new_project_merge_request_path(@project, merge_request: {source_branch: params[:to], target_branch: params[:from]}) end end -- GitLab From 069a6dfa9152dc61042bc3385651e9a81c8d3392 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 12 Sep 2013 21:39:27 +0300 Subject: [PATCH 169/175] Compare link for branches --- app/helpers/compare_helper.rb | 1 + app/views/projects/branches/_branch.html.haml | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/app/helpers/compare_helper.rb b/app/helpers/compare_helper.rb index e1dd89dcd3d..ea2540bf385 100644 --- a/app/helpers/compare_helper.rb +++ b/app/helpers/compare_helper.rb @@ -3,6 +3,7 @@ module CompareHelper params[:from].present? && params[:to].present? && @repository.branch_names.include?(params[:from]) && @repository.branch_names.include?(params[:to]) && + params[:from] != params[:to] && !@refs_are_same end diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index 026948aa027..b8392525791 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -13,6 +13,10 @@ = link_to archive_project_repository_path(@project, ref: branch.name), class: 'btn grouped btn-small' do %i.icon-download-alt Download + = link_to project_compare_index_path(@project, from: branch.name, to: branch.name), class: 'btn grouped btn-small', title: "Compare" do + %i.icon-copy + Compare + - if can?(current_user, :admin_project, @project) && branch.name != @repository.root_ref = link_to project_branch_path(@project, branch.name), class: 'btn grouped btn-small remove-row', method: :delete, confirm: 'Removed branch cannot be restored. Are you sure?', remote: true do %i.icon-trash -- GitLab From e1ca9de0dabb9d1da13073110072b3327280eb55 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 12 Sep 2013 21:46:31 +0300 Subject: [PATCH 170/175] Add default values to compare page link --- app/views/projects/commits/_head.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/commits/_head.html.haml b/app/views/projects/commits/_head.html.haml index c16abac7f17..624604142b1 100644 --- a/app/views/projects/commits/_head.html.haml +++ b/app/views/projects/commits/_head.html.haml @@ -4,7 +4,7 @@ = nav_link(controller: [:commit, :commits]) do = link_to 'Commits', project_commits_path(@project, @repository.root_ref) = nav_link(controller: :compare) do - = link_to 'Compare', project_compare_index_path(@project) + = link_to 'Compare', project_compare_index_path(@project, from: @repository.root_ref, to: @ref || @repository.root_ref) = nav_link(html_options: {class: branches_tab_class}) do = link_to recent_project_branches_path(@project) do -- GitLab From 86d14441a44922e466da294f9b1147453b462d18 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Fri, 13 Sep 2013 07:44:30 +0200 Subject: [PATCH 171/175] Notice about moving projects. --- doc/update/5.4-to-6.0.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/update/5.4-to-6.0.md b/doc/update/5.4-to-6.0.md index 907a134ed1d..8ad318f44b7 100644 --- a/doc/update/5.4-to-6.0.md +++ b/doc/update/5.4-to-6.0.md @@ -4,8 +4,8 @@ #### Global projects -We deprecated root(global) namespace for projects. -So you need to move all your global projects under group/users manually before update or they will be automatically moved to the owner namespace during the update. +The root (global) namespace for projects is depreated. +So you need to move all your global projects under groups or users manually before update or they will be automatically moved to the project owner namespace during the update. When a project is moved all its members will receive an email with instructions how to update their git remote url. Please make sure you disable ssending email when you do a test of the upgrade. #### Teams -- GitLab From 1045ea6476436f961f2a9e2d65a786ba7f4907a6 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Fri, 13 Sep 2013 07:49:45 +0200 Subject: [PATCH 172/175] Typo fix. --- doc/update/5.4-to-6.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/update/5.4-to-6.0.md b/doc/update/5.4-to-6.0.md index 8ad318f44b7..3b1d9878204 100644 --- a/doc/update/5.4-to-6.0.md +++ b/doc/update/5.4-to-6.0.md @@ -4,7 +4,7 @@ #### Global projects -The root (global) namespace for projects is depreated. +The root (global) namespace for projects is deprecated. So you need to move all your global projects under groups or users manually before update or they will be automatically moved to the project owner namespace during the update. When a project is moved all its members will receive an email with instructions how to update their git remote url. Please make sure you disable ssending email when you do a test of the upgrade. #### Teams -- GitLab From 91e112ffe2a2c16b3b5e2cd4ce032cb9fa769660 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Fri, 13 Sep 2013 10:12:42 +0200 Subject: [PATCH 173/175] Replace remote url on selection. --- app/assets/javascripts/project.js.coffee | 1 + app/views/projects/empty.html.haml | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/project.js.coffee b/app/assets/javascripts/project.js.coffee index 780292daa11..83236b34814 100644 --- a/app/assets/javascripts/project.js.coffee +++ b/app/assets/javascripts/project.js.coffee @@ -35,6 +35,7 @@ $ -> $('a, button', scope).removeClass 'active' $(@).addClass 'active' $('#project_clone', scope).val $(@).data 'clone' + $(".clone").text("").append 'git remote add origin ' + $(@).data 'clone' # Ref switcher $('.project-refs-select').on 'change', -> diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml index 99e334cc6b8..001857cefda 100644 --- a/app/views/projects/empty.html.haml +++ b/app/views/projects/empty.html.haml @@ -29,7 +29,8 @@ touch README git add README git commit -m 'first commit' - git remote add origin #{@project.url_to_repo} + %span.clone= "git remote add origin #{@project.url_to_repo}" + :preserve git push -u origin master %fieldset @@ -37,7 +38,8 @@ %pre.dark :preserve cd existing_git_repo - git remote add origin #{@project.url_to_repo} + %span.clone= "git remote add origin #{@project.url_to_repo}" + :preserve git push -u origin master - if can? current_user, :remove_project, @project -- GitLab From c606df8fdf7ea4601415fb54135f1c53083f9456 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Fri, 13 Sep 2013 11:37:13 +0200 Subject: [PATCH 174/175] Test. --- features/project/create_project.feature | 11 +++++++++++ features/steps/project/create_project.rb | 22 ++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/features/project/create_project.feature b/features/project/create_project.feature index b7cdfdb818e..395a3218b2b 100644 --- a/features/project/create_project.feature +++ b/features/project/create_project.feature @@ -9,3 +9,14 @@ Feature: Create Project And fill project form with valid data Then I should see project page And I should see empty project instuctions + + @javascript + Scenario: Empty project instructions + Given I sign in as a user + When I visit new project page + And fill project form with valid data + Then I see empty project instuctions + And I click on HTTP + Then Remote url should update to http link + And If I click on SSH + Then Remote url should update to ssh link \ No newline at end of file diff --git a/features/steps/project/create_project.rb b/features/steps/project/create_project.rb index 0d9727732c7..b59345e7078 100644 --- a/features/steps/project/create_project.rb +++ b/features/steps/project/create_project.rb @@ -17,4 +17,26 @@ class CreateProject < Spinach::FeatureSteps page.should have_content "git remote" page.should have_content Project.last.url_to_repo end + + Then 'I see empty project instuctions' do + page.should have_content "git init" + page.should have_content "git remote" + page.should have_content Project.last.url_to_repo + end + + And 'I click on HTTP' do + click_button 'HTTP' + end + + Then 'Remote url should update to http link' do + page.should have_content "git remote add origin #{Project.last.http_url_to_repo}" + end + + And 'If I click on SSH' do + click_button 'SSH' + end + + Then 'Remote url should update to ssh link' do + page.should have_content "git remote add origin #{Project.last.url_to_repo}" + end end -- GitLab From 3f038a320edd59745012500469b876e2c8dad45b Mon Sep 17 00:00:00 2001 From: twistedR Date: Fri, 13 Sep 2013 14:48:40 -0400 Subject: [PATCH 175/175] fixed command to update init script The init script was being loaded from the master branch causing the rake gitlab:check to think that it was out of date. Fixed the link to the proper branch --- doc/update/5.4-to-6.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/update/5.4-to-6.0.md b/doc/update/5.4-to-6.0.md index 3b1d9878204..ab12ecc253b 100644 --- a/doc/update/5.4-to-6.0.md +++ b/doc/update/5.4-to-6.0.md @@ -91,7 +91,7 @@ Note: We switched from Puma in GitLab 5.4 to unicorn in GitLab 6.0. ```bash sudo rm /etc/init.d/gitlab -sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlabhq/master/lib/support/init.d/gitlab +sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlabhq/6-0-stable/lib/support/init.d/gitlab sudo chmod +x /etc/init.d/gitlab ``` -- GitLab