BigW Consortium Gitlab

Commit eefb27f5 by Sebastian Ziebell

Merge branch 'master' into fixes/api

Conflicts: spec/requests/api/projects_spec.rb
parents 1b97a2ee b7ac654b
......@@ -2,7 +2,7 @@
.rbx/
db/*.sqlite3
db/*.sqlite3-journal
log/*.log
log/*.log*
tmp/
.sass-cache/
coverage/*
......@@ -20,6 +20,7 @@ config/database.yml
config/initializers/omniauth.rb
config/unicorn.rb
config/resque.yml
config/aws.yml
db/data.yml
.idea
.DS_Store
......
......@@ -70,6 +70,9 @@ gem "github-markup", "~> 0.7.4", require: 'github/markup'
# Servers
gem "unicorn", "~> 4.4.0"
# State machine
gem "state_machine"
# Issue tags
gem "acts-as-taggable-on", "2.3.3"
......
......@@ -425,6 +425,7 @@ GEM
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
stamp (0.3.0)
state_machine (1.1.2)
temple (0.5.5)
test_after_commit (0.0.1)
therubyracer (0.10.2)
......@@ -536,6 +537,7 @@ DEPENDENCIES
slim
spinach-rails
stamp
state_machine
test_after_commit
therubyracer
thin
......
......@@ -49,6 +49,10 @@ $ ->
# Bottom tooltip
$('.has_bottom_tooltip').tooltip(placement: 'bottom')
# Form submitter
$('.trigger-submit').on 'change', ->
$(@).parents('form').submit()
# Flash
if (flash = $("#flash-container")).length > 0
flash.click -> $(@).slideUp("slow")
......
......@@ -27,7 +27,7 @@ class MergeRequest
this.$el.find(selector)
initMergeWidget: ->
this.showState( @opts.current_state )
this.showState( @opts.current_status )
if this.$('.automerge_widget').length and @opts.check_enable
$.get @opts.url_to_automerge_check, (data) =>
......
......@@ -63,7 +63,7 @@
color: $style_color;
text-shadow: 0 1px 1px #FFF;
font-family: 'Yanone', sans-serif;
font-size: 26px;
line-height: 42px;
font-size: 24px;
line-height: 36px;
font-weight: normal;
}
......@@ -29,7 +29,7 @@
a{
color: $style_color;
}
> span {
font-family: $monospace_font;
font-size: 14px;
......@@ -124,7 +124,7 @@
.wrap{
display: inline-block;
}
.frame {
display: inline-block;
background-color: #fff;
......@@ -149,7 +149,7 @@
.view.swipe{
position: relative;
.swipe-frame{
display: block;
margin: auto;
......@@ -228,7 +228,7 @@
bottom: 0px;
left: 50%;
margin-left: -150px;
.drag-track{
display: block;
position: absolute;
......@@ -237,7 +237,7 @@
width: 276px;
background: url('onion_skin_sprites.gif') -4px -20px repeat-x;
}
.dragger {
display: block;
position: absolute;
......@@ -248,7 +248,7 @@
background: url('onion_skin_sprites.gif') 0px -34px repeat-x;
cursor: pointer;
}
.transparent {
display: block;
position: absolute;
......@@ -258,7 +258,7 @@
width: 10px;
background: url('onion_skin_sprites.gif') -2px 0px no-repeat;
}
.opaque {
display: block;
position: absolute;
......@@ -275,19 +275,19 @@
padding: 10px;
text-align: center;
background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
ul, li{
list-style: none;
margin: 0;
padding: 0;
display: inline-block;
}
li{
color: grey;
border-left: 1px solid #c1c1c1;
......@@ -322,12 +322,12 @@
}
.commit-author, .commit-committer{
display: block;
color: #999;
font-weight: normal;
color: #999;
font-weight: normal;
font-style: italic;
}
.commit-author strong, .commit-committer strong{
font-weight: bold;
font-weight: bold;
font-style: normal;
}
......@@ -337,7 +337,6 @@
*/
.commit {
.browse_code_link_holder {
@extend .span2;
float: right;
}
......
......@@ -5,15 +5,16 @@
header {
&.navbar-gitlab {
.navbar-inner {
height: 45px;
padding: 5px;
height: 40px;
padding: 3px;
background: #F1F1F1;
filter: none;
.nav > li > a {
color: $style_color;
text-shadow: 0 1px 0 #fff;
font-size: 18px;
padding: 12px;
font-size: 16px;
padding: 10px;
}
/** NAV block with links and profile **/
......@@ -25,7 +26,6 @@ header {
}
z-index: 10;
/*height: 60px;*/
/**
*
......@@ -34,7 +34,7 @@ header {
*/
.app_logo {
float: left;
margin-right: 15px;
margin-right: 9px;
position: relative;
top: -5px;
padding-top: 5px;
......@@ -42,10 +42,10 @@ header {
a {
float: left;
padding: 0px;
margin: 0 10px;
margin: 0 6px;
h1 {
background: url('logo_dark.png') no-repeat 0px 2px;
background: url('logo_dark.png') no-repeat center 1px;
float: left;
height: 40px;
width: 40px;
......@@ -79,7 +79,6 @@ header {
.search {
margin-right: 45px;
margin-left: 10px;
margin-top: 2px;
.search-input {
@extend .span2;
......@@ -105,7 +104,7 @@ header {
.account-box {
position: absolute;
right: 0;
top: 6px;
top: 4px;
z-index: 10000;
width: 128px;
font-size: 11px;
......@@ -228,6 +227,7 @@ header {
.search-input {
background-color: #D2D5DA;
background-color: rgba(255, 255, 255, 0.5);
border: 1px solid #AAA;
&:focus {
background-color: white;
......@@ -240,13 +240,16 @@ header {
.app_logo {
a {
h1 {
background: url('logo_white.png') no-repeat center center;
background: url('logo_white.png') no-repeat center 1px;
color: #fff;
text-shadow: 0 1px 1px #111;
}
}
}
.project_name {
a {
color: #FFF;
}
color: #fff;
text-shadow: 0 1px 1px #111;
}
......@@ -261,11 +264,11 @@ header {
.separator {
float: left;
height: 60px;
height: 46px;
width: 1px;
background: white;
border-left: 1px solid #DDD;
margin-top: -10px;
margin-top: -3px;
margin-left: 10px;
margin-right: 10px;
}
......
......@@ -115,3 +115,7 @@ ul.nav.nav-projects-tabs {
}
}
}
.team_member_row form {
margin: 0px;
}
......@@ -8,66 +8,27 @@
*
*/
.ui_mars {
/*
* Application Header
*
*/
header {
@extend .header-dark;
&.navbar-gitlab {
.navbar-inner {
background: #474D57 url('bg-header.png') repeat-x bottom;
border-bottom: 1px solid #444;
.nav > li > a {
color: #eee;
text-shadow: 0 1px 0 #444;
background: #474D57;
border-bottom: 1px solid #373D47;
.app_logo {
&:hover {
background-color: #373D47;
}
}
}
}
.search {
float: right;
margin-right: 45px;
.search-input {
border: 1px solid rgba(0, 0, 0, 0.7);
background-color: #D2D5DA;
background-color: rgba(255, 255, 255, 0.5);
&:focus {
background-color: white;
}
}
}
.search-input::-webkit-input-placeholder {
color: #666;
}
.app_logo {
a {
h1 {
background: url('logo_white.png') no-repeat center center;
color: #eee;
text-shadow: 0 1px 1px #111;
}
}
&:hover {
background-color: #41464e;
}
}
.project_name {
color: #eee;
text-shadow: 0 1px 1px #111;
.separator {
background: #31363E;
border-left: 1px solid #666;
}
}
.separator {
background: #31363E;
border-left: 1px solid #666;
}
/*
* End of Application Header
*
*/
}
......@@ -14,7 +14,7 @@ class MergeRequestsLoadContext < BaseContext
end
merge_requests = merge_requests.page(params[:page]).per(20)
merge_requests = merge_requests.includes(:author, :project).order("closed, created_at desc")
merge_requests = merge_requests.includes(:author, :project).order("state, created_at desc")
# Filter by specific assignee_id (or lack thereof)?
if params[:assignee_id].present?
......
......@@ -38,6 +38,8 @@ module Projects
if @project.valid? && @project.import_url.present?
shell = Gitlab::Shell.new
if shell.import_repository(@project.path_with_namespace, @project.import_url)
# We should create satellite for imported repo
@project.satellite.create unless @project.satellite.exists?
true
else
@project.errors.add(:import_url, 'cannot clone repo')
......
......@@ -5,7 +5,7 @@ class DashboardController < ApplicationController
before_filter :event_filter, only: :show
def show
@groups = current_user.authorized_groups
@groups = current_user.authorized_groups.sort_by(&:human_name)
@has_authorized_projects = @projects.count > 0
@teams = current_user.authorized_teams
@projects_count = @projects.count
......
class FilesController < ApplicationController
def download
note = Note.find(params[:id])
if can?(current_user, :read_project, note.project)
uploader = note.attachment
send_file uploader.file.path, disposition: 'attachment'
else
not_found!
end
end
end
......@@ -73,14 +73,14 @@ class MergeRequestsController < ProjectResourceController
if @merge_request.unchecked?
@merge_request.check_if_can_be_merged
end
render json: {state: @merge_request.human_state}
render json: {merge_status: @merge_request.human_merge_status}
rescue Gitlab::SatelliteNotExistError
render json: {state: :no_satellite}
render json: {merge_status: :no_satellite}
end
def automerge
return access_denied! unless can?(current_user, :accept_mr, @project)
if @merge_request.open? && @merge_request.can_be_merged?
if @merge_request.opened? && @merge_request.can_be_merged?
@merge_request.should_remove_source_branch = params[:should_remove_source_branch]
@merge_request.automerge!(current_user)
@status = true
......
......@@ -12,7 +12,7 @@ class MilestonesController < ProjectResourceController
def index
@milestones = case params[:f]
when 'all'; @project.milestones.order("closed, due_date DESC")
when 'all'; @project.milestones.order("state, due_date DESC")
when 'closed'; @project.milestones.closed.order("due_date DESC")
else @project.milestones.active.order("due_date ASC")
end
......
......@@ -51,7 +51,9 @@ class ProfilesController < ApplicationController
end
def update_username
@user.update_attributes(username: params[:user][:username])
if @user.can_change_username?
@user.update_attributes(username: params[:user][:username])
end
respond_to do |format|
format.js
......
......@@ -4,7 +4,11 @@ class TeamMembersController < ProjectResourceController
before_filter :authorize_admin_project!, except: [:index, :show]
def index
@teams = UserTeam.scoped
@team = @project.users_projects.scoped
@team = @team.send(params[:type]) if %w(masters developers reporters guests).include?(params[:type])
@team = @team.sort_by(&:project_access).reverse.group_by(&:project_access)
@assigned_teams = @project.user_team_project_relationships
end
def show
......
......@@ -27,7 +27,13 @@ class Teams::MembersController < Teams::ApplicationController
end
def update
options = {default_projects_access: params[:default_project_access], group_admin: params[:group_admin]}
member_params = params[:team_member]
options = {
default_projects_access: member_params[:permission],
group_admin: member_params[:group_admin]
}
if user_team.update_membership(team_member, options)
redirect_to team_members_path(user_team), notice: "Membership for #{team_member.name} was successfully updated in Team of users."
else
......@@ -45,5 +51,4 @@ class Teams::MembersController < Teams::ApplicationController
def team_member
@member ||= user_team.members.find_by_username(params[:id])
end
end
......@@ -9,13 +9,11 @@ class TeamsController < ApplicationController
layout 'user_team', except: [:new, :create]
def show
user_team
projects
@events = Event.in_projects(user_team.project_ids).limit(20).offset(params[:offset] || 0)
end
def edit
user_team
end
def update
......@@ -41,6 +39,9 @@ class TeamsController < ApplicationController
@team.path = @team.name.dup.parameterize if @team.name
if @team.save
# Add current user as Master to the team
@team.add_members([current_user.id], UsersProject::MASTER, true)
redirect_to team_path(@team)
else
render action: :new
......
......@@ -73,8 +73,8 @@ module ApplicationHelper
def search_autocomplete_source
projects = current_user.authorized_projects.map { |p| { label: "project: #{p.name_with_namespace}", url: project_path(p) } }
groups = current_user.authorized_groups.map { |group| { label: "group: #{group.name}", url: group_path(group) } }
teams = current_user.authorized_teams.map { |team| { label: "team: #{team.name}", url: team_path(team) } }
groups = current_user.authorized_groups.map { |group| { label: "group: #{simple_sanitize(group.name)}", url: group_path(group) } }
teams = current_user.authorized_teams.map { |team| { label: "team: #{simple_sanitize(team.name)}", url: team_path(team) } }
default_nav = [
{ label: "My Profile", url: profile_path },
......@@ -159,8 +159,13 @@ module ApplicationHelper
alt: "Sign in with #{provider.to_s.titleize}")
end
def simple_sanitize str
sanitize(str, tags: %w(a span))
end
def image_url(source)
root_url + path_to_image(source)
end
alias_method :url_to_image, :image_url
end
......@@ -27,6 +27,6 @@ module DashboardHelper
items.opened
end
items.where(assignee_id: current_user.id).count
items.cared(current_user).count
end
end
......@@ -6,7 +6,7 @@ module IssuesHelper
def issue_css_classes issue
classes = "issue"
classes << " closed" if issue.closed
classes << " closed" if issue.closed?
classes << " today" if issue.today?
classes
end
......
......@@ -12,7 +12,7 @@ module MergeRequestsHelper
def mr_css_classes mr
classes = "merge_request"
classes << " closed" if mr.closed
classes << " closed" if mr.closed?
classes << " merged" if mr.merged?
classes
end
......
......@@ -10,8 +10,8 @@ module NamespacesHelper
global_opts = ["Global", [['/', Namespace.global_id]] ]
group_opts = ["Groups", groups.map {|g| [g.human_name, g.id]} ]
users_opts = [ "Users", users.map {|u| [u.human_name, u.id]} ]
group_opts = ["Groups", groups.sort_by(&:human_name).map {|g| [g.human_name, g.id]} ]
users_opts = [ "Users", users.sort_by(&:human_name).map {|u| [u.human_name, u.id]} ]
options = []
options << global_opts if current_user.admin
......
module ProjectsHelper
def grouper_project_members(project)
@project.users_projects.sort_by(&:project_access).reverse.group_by(&:project_access)
end
def grouper_project_teams(project)
@project.user_team_project_relationships.sort_by(&:greatest_access).reverse.group_by(&:greatest_access)
end
def remove_from_project_team_message(project, user)
"You are going to remove #{user.name} from #{project.name} project team. Are you sure?"
end
......@@ -56,7 +48,7 @@ module ProjectsHelper
def project_title project
if project.group
content_tag :span do
link_to(project.group.name, group_path(project.group)) + " / " + project.name
link_to(simple_sanitize(project.group.name), group_path(project.group)) + " / " + project.name
end
else
project.name
......
......@@ -123,7 +123,7 @@ class Ability
def user_team_abilities user, team
rules = []
# Only group owner and administrators can manage group
# Only group owner and administrators can manage team
if team.owner == user || team.admin?(user) || user.admin?
rules << [ :manage_user_team ]
end
......
......@@ -17,10 +17,9 @@ module Issuable
validates :project, presence: true
validates :author, presence: true
validates :title, presence: true, length: { within: 0..255 }
validates :closed, inclusion: { in: [true, false] }
scope :opened, -> { where(closed: false) }
scope :closed, -> { where(closed: true) }
scope :opened, -> { with_state(:opened) }
scope :closed, -> { with_state(:closed) }
scope :of_group, ->(group) { where(project_id: group.project_ids) }
scope :of_user_team, ->(team) { where(project_id: team.project_ids, assignee_id: team.member_ids) }
scope :assigned, ->(u) { where(assignee_id: u.id)}
......@@ -62,14 +61,6 @@ module Issuable
assignee_id_changed?
end
def is_being_closed?
closed_changed? && closed
end
def is_being_reopened?
closed_changed? && !closed
end
#
# Votes
#
......
......@@ -130,10 +130,6 @@ class Event < ActiveRecord::Base
target if target_type == "MergeRequest"
end
def author
@author ||= User.find(author_id)
end
def action_name
if closed?
"closed"
......
......@@ -9,7 +9,7 @@
# project_id :integer
# created_at :datetime not null
# updated_at :datetime not null
# closed :boolean default(FALSE), not null
# state :string default(FALSE), not null
# position :integer default(0)
# branch_name :string(255)
# description :text
......@@ -19,12 +19,35 @@
class Issue < ActiveRecord::Base
include Issuable
attr_accessible :title, :assignee_id, :closed, :position, :description,
:milestone_id, :label_list, :author_id_of_changes
attr_accessible :title, :assignee_id, :position, :description,
:milestone_id, :label_list, :author_id_of_changes,
:state_event
acts_as_taggable_on :labels
def self.open_for(user)
opened.assigned(user)
class << self
def cared(user)
where('assignee_id = :user', user: user.id)
end
def open_for(user)
opened.assigned(user)
end
end
state_machine :state, initial: :opened do
event :close do
transition [:reopened, :opened] => :closed
end
event :reopen do
transition closed: :reopened
end
state :opened
state :reopened
state :closed
end
end
......@@ -35,7 +35,7 @@ class Key < ActiveRecord::Base
def fingerprintable_key
return true unless key # Don't test if there is no key.
# `ssh-keygen -lf /dev/stdin <<< "#{key}"` errors with: redirection unexpected
file = Tempfile.new('key_file')
begin
file.puts key
......@@ -45,7 +45,7 @@ class Key < ActiveRecord::Base
file.close
file.unlink # deletes the temp file
end
errors.add(:key, "can't be fingerprinted") if fingerprint_output.match("failed")
errors.add(:key, "can't be fingerprinted") if $?.exitstatus != 0
end
def set_identifier
......
......@@ -9,15 +9,14 @@
# author_id :integer
# assignee_id :integer
# title :string(255)
# closed :boolean default(FALSE), not null
# state :string(255) not null
# created_at :datetime not null
# updated_at :datetime not null
# st_commits :text(2147483647)
# st_diffs :text(2147483647)
# merged :boolean default(FALSE), not null
# state :integer default(1), not null
# milestone_id :integer
# merge_status :integer default(1), not null
#
# milestone_id :integer
require Rails.root.join("app/models/commit")
require Rails.root.join("lib/static_model")
......@@ -25,11 +24,33 @@ require Rails.root.join("lib/static_model")
class MergeRequest < ActiveRecord::Base
include Issuable
attr_accessible :title, :assignee_id, :closed, :target_branch, :source_branch, :milestone_id,
:author_id_of_changes
attr_accessible :title, :assignee_id, :target_branch, :source_branch, :milestone_id,
:author_id_of_changes, :state_event
attr_accessor :should_remove_source_branch
state_machine :state, initial: :opened do
event :close do
transition [:reopened, :opened] => :closed
end
event :merge do
transition [:reopened, :opened] => :merged
end
event :reopen do
transition closed: :reopened
end
state :opened
state :reopened
state :closed
state :merged
end
BROKEN_DIFF = "--broken-diff"
UNCHECKED = 1
......@@ -43,21 +64,33 @@ class MergeRequest < ActiveRecord::Base
validates :target_branch, presence: true
validate :validate_branches
def self.find_all_by_branch(branch_name)
where("source_branch LIKE :branch OR target_branch LIKE :branch", branch: branch_name)
end
scope :merged, -> { with_state(:merged) }
def self.find_all_by_milestone(milestone)
where("milestone_id = :milestone_id", milestone_id: milestone)
class << self
def find_all_by_branch(branch_name)
where("source_branch LIKE :branch OR target_branch LIKE :branch", branch: branch_name)
end
def cared(user)
where('assignee_id = :user OR author_id = :user', user: user.id)
end
def find_all_by_branch(branch_name)
where("source_branch LIKE :branch OR target_branch LIKE :branch", branch: branch_name)
end
def find_all_by_milestone(milestone)
where("milestone_id = :milestone_id", milestone_id: milestone)
end
end
def human_state
states = {
def human_merge_status
merge_statuses = {
CAN_BE_MERGED => "can_be_merged",
CANNOT_BE_MERGED => "cannot_be_merged",
UNCHECKED => "unchecked"
}
states[self.state]
merge_statuses[self.merge_status]
end
def validate_branches
......@@ -72,20 +105,20 @@ class MergeRequest < ActiveRecord::Base
end
def unchecked?
state == UNCHECKED
merge_status == UNCHECKED
end
def mark_as_unchecked
self.state = UNCHECKED
self.merge_status = UNCHECKED
self.save
end
def can_be_merged?
state == CAN_BE_MERGED
merge_status == CAN_BE_MERGED
end
def check_if_can_be_merged
self.state = if Gitlab::Satellite::MergeAction.new(self.author, self).can_be_merged?
self.merge_status = if Gitlab::Satellite::MergeAction.new(self.author, self).can_be_merged?
CAN_BE_MERGED
else
CANNOT_BE_MERGED
......@@ -98,7 +131,7 @@ class MergeRequest < ActiveRecord::Base
end
def reloaded_diffs
if open? && unmerged_diffs.any?
if opened? && unmerged_diffs.any?
self.st_diffs = unmerged_diffs
self.save
end
......@@ -128,10 +161,6 @@ class MergeRequest < ActiveRecord::Base
commits.first
end
def merged?
merged && merge_event
end
def merge_event
self.project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::MERGED).last
end
......@@ -146,26 +175,16 @@ class MergeRequest < ActiveRecord::Base
def probably_merged?
unmerged_commits.empty? &&
commits.any? && open?
end
def open?
!closed
end
def mark_as_merged!
self.merged = true
self.closed = true
save
commits.any? && opened?
end
def mark_as_unmergable
self.state = CANNOT_BE_MERGED
self.merge_status = CANNOT_BE_MERGED
self.save
end
def reloaded_commits
if open? && unmerged_commits.any?
if opened? && unmerged_commits.any?
self.st_commits = unmerged_commits
save
end
......@@ -181,7 +200,8 @@ class MergeRequest < ActiveRecord::Base
end
def merge!(user_id)
self.mark_as_merged!
self.merge
Event.create(
project: self.project,
action: Event::MERGED,
......
......@@ -13,19 +13,32 @@
#
class Milestone < ActiveRecord::Base
attr_accessible :title, :description, :due_date, :closed, :author_id_of_changes
attr_accessible :title, :description, :due_date, :state_event, :author_id_of_changes
attr_accessor :author_id_of_changes
belongs_to :project
has_many :issues
has_many :merge_requests
scope :active, -> { where(closed: false) }
scope :closed, -> { where(closed: true) }
scope :active, -> { with_state(:active) }
scope :closed, -> { with_state(:closed) }
validates :title, presence: true
validates :project, presence: true
validates :closed, inclusion: { in: [true, false] }
state_machine :state, initial: :active do
event :close do
transition active: :closed
end
event :activate do
transition closed: :active
end
state :closed
state :active
end
def expired?
if due_date
......@@ -68,17 +81,13 @@ class Milestone < ActiveRecord::Base
end
def can_be_closed?
open? && issues.opened.count.zero?
active? && issues.opened.count.zero?
end
def is_empty?
total_items_count.zero?
end
def open?
!closed
end
def author_id
author_id_of_changes
end
......
......@@ -17,11 +17,15 @@ class Namespace < ActiveRecord::Base
has_many :projects, dependent: :destroy
belongs_to :owner, class_name: "User"
validates :name, presence: true, uniqueness: true
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 :path, uniqueness: true, presence: true, length: { within: 1..255 },
format: { with: Gitlab::Regex.path_regex,
message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" }
validates :owner, presence: true
delegate :name, to: :owner, allow_nil: true, prefix: true
......
......@@ -43,7 +43,7 @@ class Project < ActiveRecord::Base
has_many :events, dependent: :destroy
has_many :merge_requests, dependent: :destroy
has_many :issues, dependent: :destroy, order: "closed, created_at DESC"
has_many :issues, dependent: :destroy, order: "state, created_at DESC"
has_many :milestones, dependent: :destroy
has_many :users_projects, dependent: :destroy
has_many :notes, dependent: :destroy
......@@ -146,7 +146,7 @@ class Project < ActiveRecord::Base
end
def saved?
id && valid?
id && persisted?
end
def import?
......
......@@ -132,16 +132,16 @@ class Repository
return nil unless commit
# Build file path
file_name = self.path_with_namespace + "-" + commit.id.to_s + ".tar.gz"
file_name = self.path_with_namespace.gsub("/","_") + "-" + commit.id.to_s + ".tar.gz"
storage_path = Rails.root.join("tmp", "repositories")
file_path = File.join(storage_path, file_name)
file_path = File.join(storage_path, self.path_with_namespace, file_name)
# Put files into a directory before archiving
prefix = self.path_with_namespace + "/"
# Create file if not exists
unless File.exists?(file_path)
FileUtils.mkdir_p storage_path
FileUtils.mkdir_p File.dirname(file_path)
file = self.repo.archive_to_file(ref, prefix, file_path)
end
......
......@@ -234,8 +234,12 @@ class User < ActiveRecord::Base
keys.count == 0
end
def can_change_username?
Gitlab.config.gitlab.username_changing_enabled
end
def can_create_project?
projects_limit > personal_projects.count
projects_limit > owned_projects.count
end
def can_create_group?
......@@ -263,7 +267,7 @@ class User < ActiveRecord::Base
end
def cared_merge_requests
MergeRequest.where("author_id = :id or assignee_id = :id", id: self.id)
MergeRequest.cared(self)
end
# Remove user from all projects and
......
......@@ -21,8 +21,11 @@ class UserTeam < ActiveRecord::Base
has_many :projects, through: :user_team_project_relationships
has_many :members, through: :user_team_user_relationships, source: :user
validates :name, presence: true, uniqueness: true
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 :path, uniqueness: true, presence: true, length: { within: 1..255 },
format: { with: Gitlab::Regex.path_regex,
message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" }
......
......@@ -26,6 +26,10 @@ class UserTeamProjectRelationship < ActiveRecord::Base
user_team.name
end
def human_max_access
UserTeam.access_roles.key(greatest_access)
end
private
def check_greatest_access
......
......@@ -20,15 +20,23 @@ class ActivityObserver < ActiveRecord::Observer
end
end
def after_save(record)
if record.changed.include?("closed") && record.author_id_of_changes
def after_close(record, transition)
Event.create(
project: record.project,
target_id: record.id,
target_type: record.class.name,
action: (record.closed ? Event::CLOSED : Event::REOPENED),
action: Event::CLOSED,
author_id: record.author_id_of_changes
)
end
def after_reopen(record, transition)
Event.create(
project: record.project,
target_id: record.id,
target_type: record.class.name,
action: Event::REOPENED,
author_id: record.author_id_of_changes
)
end
end
end
......@@ -7,22 +7,31 @@ class IssueObserver < ActiveRecord::Observer
end
end
def after_update(issue)
def after_close(issue, transition)
send_reassigned_email(issue) if issue.is_being_reassigned?
status = nil
status = 'closed' if issue.is_being_closed?
status = 'reopened' if issue.is_being_reopened?
if status
Note.create_status_change_note(issue, current_user, status)
[issue.author, issue.assignee].compact.each do |recipient|
Notify.delay.issue_status_changed_email(recipient.id, issue.id, status, current_user.id)
end
end
create_note(issue)
end
def after_reopen(issue, transition)
send_reassigned_email(issue) if issue.is_being_reassigned?
create_note(issue)
end
def after_update(issue)
send_reassigned_email(issue) if issue.is_being_reassigned?
end
protected
def create_note(issue)
Note.create_status_change_note(issue, current_user, issue.state)
[issue.author, issue.assignee].compact.each do |recipient|
Notify.delay.issue_status_changed_email(recipient.id, issue.id, issue.state, current_user.id)
end
end
def send_reassigned_email(issue)
recipient_ids = [issue.assignee_id, issue.assignee_id_was].keep_if {|id| id && id != current_user.id }
......
......@@ -7,15 +7,20 @@ class MergeRequestObserver < ActiveRecord::Observer
end
end
def after_update(merge_request)
def after_close(merge_request, transition)
send_reassigned_email(merge_request) if merge_request.is_being_reassigned?
status = nil
status = 'closed' if merge_request.is_being_closed?
status = 'reopened' if merge_request.is_being_reopened?
if status
Note.create_status_change_note(merge_request, current_user, status)
end
Note.create_status_change_note(merge_request, current_user, merge_request.state)
end
def after_reopen(merge_request, transition)
send_reassigned_email(merge_request) if merge_request.is_being_reassigned?
Note.create_status_change_note(merge_request, current_user, merge_request.state)
end
def after_update(merge_request)
send_reassigned_email(merge_request) if merge_request.is_being_reassigned?
end
protected
......
......@@ -19,4 +19,12 @@ class AttachmentUploader < CarrierWave::Uploader::Base
rescue
false
end
def secure_url
if self.class.storage == CarrierWave::Storage::File
"/files/#{model.class.to_s.underscore}/#{model.id}/#{file.filename}"
else
url
end
end
end
......@@ -28,7 +28,7 @@
%td= group.path
%td= group.projects.count
%td
= link_to group.owner_name, admin_user_path(group.owner_id)
= link_to group.owner_name, admin_user_path(group.owner)
%td.bgred
= link_to 'Rename', edit_admin_group_path(group), id: "edit_#{dom_id(group)}", class: "btn btn-small"
= link_to 'Destroy', [:admin, group], confirm: "REMOVE #{group.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove"
......
......@@ -30,7 +30,7 @@
%td= team.projects.count
%td= team.members.count
%td
= link_to team.owner.name, admin_user_path(team.owner_id)
= link_to team.owner.name, admin_user_path(team.owner)
%td.bgred
= link_to 'Rename', edit_admin_team_path(team), id: "edit_#{dom_id(team)}", class: "btn btn-small"
= link_to 'Destroy', admin_team_path(team), confirm: "REMOVE #{team.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove"
......
......@@ -6,9 +6,9 @@
= link_to commit.short_id(8), project_commit_path(@project, commit), class: "commit_short_id"
= commit.author_link avatar: true, size: 24
&nbsp;
= link_to_gfm truncate(commit.title, length: 50), project_commit_path(@project, commit.id), class: "row_title"
= link_to_gfm truncate(commit.title, length: 70), project_commit_path(@project, commit.id), class: "row_title"
%span.committed_ago
%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
&nbsp;
......
......@@ -26,7 +26,7 @@
= markdown truncate(event.target.note, length: 70)
- note = event.target
- if note.attachment.url
= link_to note.attachment.url, target: "_blank", class: 'note-file-attach' do
= link_to note.attachment.secure_url, target: "_blank", class: 'note-file-attach' do
- if note.attachment.image?
= image_tag note.attachment.url, class: 'note-image-attach'
- else
......
......@@ -26,6 +26,8 @@
= link_to group_filter_path(entity, project_id: project.id) do
= project.name_with_namespace
%small.pull-right= entities_per_project(project, entity)
- if @projects.blank?
%p.nothing_here_message This group has no projects yet
%fieldset
%hr
......
......@@ -7,6 +7,8 @@
= link_to people_group_path(@group, project_id: project.id) do
= project.name_with_namespace
%small.pull-right= project.users.count
- if @projects.blank?
%p.nothing_here_message This group has no projects yet
%fieldset
%hr
......
......@@ -30,6 +30,8 @@
= link_to 'Team', 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.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove"
- if @group.projects.blank?
%p.nothing_here_message This group has no projects yet
.span5
.ui-box
......
%h3.page_title
GITLAB
.pull-right
%span= Gitlab::Version
%small= Gitlab::Revision
%span= Gitlab::VERSION
%small= Gitlab::REVISION
%hr
%p.lead
Self Hosted Git Management
......
......@@ -8,10 +8,10 @@
%i.icon-comment
= issue.notes.count
- if can? current_user, :modify_issue, issue
- if issue.closed
= link_to 'Reopen', project_issue_path(issue.project, issue, issue: {closed: false }, status_only: true), method: :put, class: "btn btn-small grouped reopen_issue", remote: true
- if issue.closed?
= link_to 'Reopen', project_issue_path(issue.project, issue, issue: {state_event: :reopen }, status_only: true), method: :put, class: "btn btn-small grouped reopen_issue", remote: true
- else
= link_to 'Close', project_issue_path(issue.project, issue, issue: {closed: true }, status_only: true), method: :put, class: "btn btn-small grouped close_issue", remote: true
= link_to 'Close', project_issue_path(issue.project, issue, issue: {state_event: :close }, status_only: true), method: :put, class: "btn btn-small grouped close_issue", remote: true
= link_to edit_project_issue_path(issue.project, issue), class: "btn btn-small edit-issue-link grouped" do
%i.icon-edit
Edit
......
......@@ -7,10 +7,10 @@
%span.pull-right
- if can?(current_user, :admin_project, @project) || @issue.author == current_user
- if @issue.closed
= link_to 'Reopen', project_issue_path(@project, @issue, issue: {closed: false }, status_only: true), method: :put, class: "btn grouped reopen_issue"
- if @issue.closed?
= link_to 'Reopen', project_issue_path(@project, @issue, issue: {state_event: :reopen }, status_only: true), method: :put, class: "btn grouped reopen_issue"
- else
= link_to 'Close', project_issue_path(@project, @issue, issue: {closed: true }, status_only: true), method: :put, class: "btn grouped close_issue", title: "Close Issue"
= link_to 'Close', project_issue_path(@project, @issue, issue: {state_event: :close }, status_only: true), method: :put, class: "btn grouped close_issue", title: "Close Issue"
- if can?(current_user, :admin_project, @project) || @issue.author == current_user
= link_to edit_project_issue_path(@project, @issue), class: "btn grouped" do
%i.icon-edit
......@@ -27,7 +27,7 @@
.ui-box.ui-box-show
.ui-box-head
%h4.box-title
- if @issue.closed
- if @issue.closed?
.error.status_info Closed
= gfm escape_once(@issue.title)
......
......@@ -29,10 +29,10 @@
$(function(){
merge_request = new MergeRequest({
url_to_automerge_check: "#{automerge_check_project_merge_request_path(@project, @merge_request)}",
check_enable: #{@merge_request.state == MergeRequest::UNCHECKED ? "true" : "false"},
check_enable: #{@merge_request.merge_status == MergeRequest::UNCHECKED ? "true" : "false"},
url_to_ci_check: "#{ci_status_project_merge_request_path(@project, @merge_request)}",
ci_enable: #{@project.gitlab_ci? ? "true" : "false"},
current_state: "#{@merge_request.human_state}",
current_status: "#{@merge_request.human_merge_status}",
action: "#{controller.action_name}"
});
});
......
......@@ -3,7 +3,7 @@
%strong Only masters can accept MR
- if @merge_request.open? && @commits.any? && can?(current_user, :accept_mr, @project)
- if @merge_request.opened? && @commits.any? && can?(current_user, :accept_mr, @project)
.automerge_widget.can_be_merged{style: "display:none"}
.alert.alert-success
%span
......
.ui-box.ui-box-show
.ui-box-head
%h4.box-title
- if @merge_request.merged
- if @merge_request.merged?
.error.status_info
%i.icon-ok
Merged
- elsif @merge_request.closed
- elsif @merge_request.closed?
.error.status_info Closed
= gfm escape_once(@merge_request.title)
......@@ -21,14 +21,14 @@
%strong= link_to_gfm truncate(milestone.title, length: 20), project_milestone_path(milestone.project, milestone)
- if @merge_request.closed
- if @merge_request.closed?
.ui-box-bottom
- if @merge_request.merged?
%span
Merged by #{link_to_member(@project, @merge_request.merge_event.author)}
%small #{time_ago_in_words(@merge_request.merge_event.created_at)} ago.
- elsif @merge_request.closed_event
%span
Closed by #{link_to_member(@project, @merge_request.closed_event.author)}
%small #{time_ago_in_words(@merge_request.closed_event.created_at)} ago.
%span
Closed by #{link_to_member(@project, @merge_request.closed_event.author)}
%small #{time_ago_in_words(@merge_request.closed_event.created_at)} ago.
- if @merge_request.merged?
.ui-box-bottom
%span
Merged by #{link_to_member(@project, @merge_request.merge_event.author)}
%small #{time_ago_in_words(@merge_request.merge_event.created_at)} ago.
- if @merge_request.open? && @commits.any?
- if @merge_request.opened? && @commits.any?
.ci_widget.ci-success{style: "display:none"}
.alert.alert-success
%i.icon-ok
......
......@@ -7,7 +7,7 @@
%span.pull-right
- if can?(current_user, :modify_merge_request, @merge_request)
- if @merge_request.open?
- if @merge_request.opened?
.left.btn-group
%a.btn.grouped.dropdown-toggle{ data: {toggle: :dropdown} }
%i.icon-download-alt
......@@ -17,7 +17,7 @@
%li= link_to "Email Patches", project_merge_request_path(@project, @merge_request, format: :patch)
%li= link_to "Plain Diff", project_merge_request_path(@project, @merge_request, format: :diff)
= link_to 'Close', project_merge_request_path(@project, @merge_request, merge_request: {closed: true }, status_only: true), method: :put, class: "btn grouped btn-close", title: "Close merge request"
= link_to 'Close', project_merge_request_path(@project, @merge_request, merge_request: {state_event: :close }), method: :put, class: "btn grouped btn-close", title: "Close merge request"
= link_to edit_project_merge_request_path(@project, @merge_request), class: "btn grouped" do
%i.icon-edit
......
%li{class: "milestone milestone-#{milestone.closed ? 'closed' : 'open'}", id: dom_id(milestone) }
%li{class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: dom_id(milestone) }
.pull-right
- if can?(current_user, :admin_milestone, milestone.project) and milestone.open?
- if can?(current_user, :admin_milestone, milestone.project) and milestone.active?
= link_to edit_project_milestone_path(milestone.project, milestone), class: "btn btn-small edit-milestone-link grouped" do
%i.icon-edit
Edit
%h4
= link_to_gfm truncate(milestone.title, length: 100), project_milestone_path(milestone.project, milestone)
- if milestone.expired? and not milestone.closed
- if milestone.expired? and not milestone.closed?
%span.cred (Expired)
%small
= milestone.expires_at
......
......@@ -9,7 +9,7 @@
&larr; To milestones list
.span6
.pull-right
- unless @milestone.closed
- unless @milestone.closed?
= link_to new_project_issue_path(@project, issue: { milestone_id: @milestone.id }), class: "btn btn-small grouped", title: "New Issue" do
%i.icon-plus
New Issue
......@@ -25,12 +25,12 @@
%hr
%p
%span All issues for this milestone are closed. You may close milestone now.
= link_to 'Close Milestone', project_milestone_path(@project, @milestone, milestone: {closed: true }), method: :put, class: "btn btn-small btn-remove"
= link_to 'Close Milestone', project_milestone_path(@project, @milestone, milestone: {state_event: :close }), method: :put, class: "btn btn-small btn-remove"
.ui-box.ui-box-show
.ui-box-head
%h4.box-title
- if @milestone.closed
- if @milestone.closed?
.error.status_info Closed
- elsif @milestone.expired?
.error.status_info Expired
......@@ -63,7 +63,7 @@
%li=link_to('All Issues', '#')
%ul.well-list
- @issues.each do |issue|
%li{data: {closed: issue.closed}}
%li{data: {closed: issue.closed?}}
= link_to [@project, issue] do
%span.badge.badge-info ##{issue.id}
&ndash;
......@@ -77,7 +77,7 @@
%li=link_to('All Merge Requests', '#')
%ul.well-list
- @merge_requests.each do |merge_request|
%li{data: {closed: merge_request.closed}}
%li{data: {closed: merge_request.closed?}}
= link_to [@project, merge_request] do
%span.badge.badge-info ##{merge_request.id}
&ndash;
......
......@@ -31,7 +31,7 @@
- if note.attachment.image?
= image_tag note.attachment.url, class: 'note-image-attach'
.attachment.pull-right
= link_to note.attachment.url, target: "_blank" do
= link_to note.attachment.secure_url, target: "_blank" do
%i.icon-paper-clip
= note.attachment_identifier
.clear
......@@ -53,29 +53,30 @@
%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
.input
= f.text_field :username, required: true
&nbsp;
%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 It will change web url for personal projects.
%li It will change the git path to repositories for personal projects.
.input
= f.submit 'Save username', class: "btn btn-save"
- 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
.input
= f.text_field :username, required: true
&nbsp;
%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 It will change web url for personal projects.
%li It will change the git path to repositories for personal projects.
.input
= f.submit 'Save username', class: "btn btn-save"
- if Gitlab.config.gitlab.signup_enabled
%fieldset.remove-account
......@@ -83,4 +84,4 @@
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"
\ No newline at end of file
= 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"
......@@ -77,7 +77,7 @@
%legend
Personal projects:
%small.pull-right
%span= current_user.personal_projects.count
%span= current_user.owned_projects.count
of
%span= current_user.projects_limit
.padded
......
......@@ -28,7 +28,7 @@
.input
= f.text_field :import_url, class: 'xlarge', placeholder: 'https://github.com/randx/six.git'
.light
URL should be clonable
URL must be clonable
%p.padded
New projects are private by default. You choose who can see the project and commit to repository.
......
......@@ -9,7 +9,7 @@
- @notes.each do |note|
%tr
%td
%a{href: note.attachment.url}
= link_to note.attachment.secure_url, target: "_blank" do
= image_tag gravatar_icon(note.author_email), class: "avatar s24"
= note.attachment_identifier
%td
......
- team = team_rel.user_team
- allow_admin = can? current_user, :admin_team_member, @project
%li{id: dom_id(team), class: "user_team_row team_#{team.id}"}
.row
.span6
%strong= link_to team.name, team_path(team), title: team.name, class: "dark"
%br
%small.cgray Members: #{team.members.count}
.pull-right
- if can?(current_user, :admin_team_member, @project)
= link_to resign_project_team_path(@project, team), method: :delete, confirm: "Are you shure?", class: "btn btn-remove btn-tiny" do
%i.icon-minus.icon-white
.span5.pull-right
.pull-right
- if allow_admin
.left
= link_to resign_project_team_path(@project, team), method: :delete, confirm: "Are you shure?", class: "btn btn-remove small" do
%i.icon-minus.icon-white
%strong= link_to team.name, team_path(team), title: team.name, class: "dark"
%br
%small.cgray Members: #{team.members.count}
%small.cgray Max access: #{team_relation.human_max_access}
.ui-box
%ul.well-list
- assigned_teams.sort_by(&:team_name).each do |team_relation|
= render "team_members/assigned_team", team_relation: team_relation, team: team_relation.user_team
- grouper_project_members(@project).each do |access, members|
- team.each do |access, members|
.ui-box
%h5.title
= Project.access_options.key(access).pluralize
%small= members.size
%ul.well-list
- members.sort_by(&:user_name).each do |up|
= render(partial: 'team_members/show', locals: {member: up})
:javascript
$(function(){
$('.repo-access-select, .project-access-select').live("change", function() {
$(this.form).submit();
});
})
- members.sort_by(&:user_name).each do |team_member|
= render 'team_members/team_member', member: team_member
......@@ -2,7 +2,7 @@
- allow_admin = can? current_user, :admin_project, @project
%li{id: dom_id(user), class: "team_member_row user_#{user.id}"}
.row
.span6
.span4
= link_to project_team_member_path(@project, user), title: user.name, class: "dark" do
= image_tag gravatar_icon(user.email, 40), class: "avatar s32"
= link_to project_team_member_path(@project, user), title: user.name, class: "dark" do
......@@ -10,18 +10,18 @@
%br
%small.cgray= user.email
.span5.pull-right
.span4.pull-right
- if allow_admin
.left
= form_for(member, as: :team_member, url: project_team_member_path(@project, member.user)) do |f|
= f.select :project_access, options_for_select(UsersProject.access_roles, member.project_access), {}, class: "medium project-access-select span2"
= f.select :project_access, options_for_select(UsersProject.access_roles, member.project_access), {}, class: "medium project-access-select span2 trigger-submit"
.pull-right
- if current_user == user
%span.btn.disabled This is you!
%span.label This is you!
- if @project.namespace_owner == user
%span.btn.disabled Owner
%span.label Owner
- elsif user.blocked
%span.btn.disabled.blocked Blocked
%span.label Blocked
- elsif allow_admin
= link_to project_team_member_path(@project, user), confirm: remove_from_project_team_message(@project, user), method: :delete, class: "btn-tiny btn btn-remove" do
%i.icon-minus.icon-white
......
- grouper_project_teams(@project).each do |access, teams|
.ui-box
%h5.title
= UserTeam.access_roles.key(access).pluralize
%small= teams.size
%ul.well-list
- teams.sort_by(&:team_name).each do |tofr|
= render(partial: 'team_members/show_team', locals: {team_rel: tofr})
:javascript
$(function(){
$('.repo-access-select, .project-access-select').live("change", function() {
$(this.form).submit();
});
})
......@@ -18,16 +18,39 @@
%hr
.clearfix
%div.team-table
= render partial: "team_members/team", locals: {project: @project}
.row
.span3
%ul.nav.nav-pills.nav-stacked
%li{class: ("active" if !params[:type])}
= link_to project_team_members_path(type: nil) do
All
%li{class: ("active" if params[:type] == 'masters')}
= link_to project_team_members_path(type: 'masters') do
Masters
%span.pull-right= @project.users_projects.masters.count
%li{class: ("active" if params[:type] == 'developers')}
= link_to project_team_members_path(type: 'developers') do
Developers
%span.pull-right= @project.users_projects.developers.count
%li{class: ("active" if params[:type] == 'reporters')}
= link_to project_team_members_path(type: 'reporters') do
Reporters
%span.pull-right= @project.users_projects.reporters.count
%li{class: ("active" if params[:type] == 'guests')}
= link_to project_team_members_path(type: 'guests') do
Guests
%span.pull-right= @project.users_projects.guests.count
- if @assigned_teams.present?
%h5
Assigned teams
(#{@project.user_teams.count})
%div
= render "team_members/assigned_teams", assigned_teams: @assigned_teams
.span9
%div.team-table
= render "team_members/team", team: @team
%h3.page_title
Assigned teams
(#{@project.user_teams.count})
%hr
.clearfix
%div.team-table
= render partial: "team_members/teams", locals: {project: @project}
%h3.page_title= "Edit Team #{@team.name}"
%hr
= form_for @team, url: team_path(@team) do |f|
- if @team.errors.any?
.alert.alert-error
%span= @team.errors.full_messages.first
.clearfix
= f.label :name do
Team name is
.input
= f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
.row
.span7
= form_for @team, url: team_path(@team) do |f|
- if @team.errors.any?
.alert.alert-error
%span= @team.errors.full_messages.first
.clearfix
= f.label :name do
Team name is
.input
= f.text_field :name, placeholder: "Ex. OpenSource", class: "xlarge left"
.clearfix
= f.label :path do
Team path is
.input
= f.text_field :path, placeholder: "opensource", class: "xlarge left"
.form-actions
= f.submit 'Save team changes', class: "btn btn-save"
.span5
.ui-box
%h5.title Remove team
.padded.bgred
%p
Removed team can not be restored!
= link_to 'Remove team', team_path(@team), method: :delete, confirm: "You are sure?", class: "btn btn-remove btn-small"
.clearfix
= f.label :path do
Team path is
.input
= f.text_field :path, placeholder: "opensource", class: "xxlarge left"
.form-actions
= f.submit 'Save team changes', class: "btn btn-primary"
= link_to 'Delete team', team_path(@team), method: :delete, confirm: "You are shure?", class: "btn btn-remove pull-right"
......@@ -10,22 +10,21 @@
%br
%small.cgray= user.email
.span6.pull-right
.span4
- if allow_admin
.left.span2
= form_for(member, as: :team_member, url: team_member_path(@team, user)) do |f|
= f.select :permission, options_for_select(UsersProject.access_roles, @team.default_projects_access(user)), {}, class: "medium project-access-select span2"
.left.span2
%span
= check_box_tag :group_admin, true, @team.admin?(user)
Admin access
.pull-right
- if current_user == user
%span.btn.disabled This is you!
- if @team.owner == user
%span.btn.disabled.btn-success Owner
- elsif user.blocked
%span.btn.disabled.blocked Blocked
- elsif allow_admin
= link_to team_member_path(@team, user), confirm: remove_from_user_team_message(@team, user), method: :delete, class: "btn-tiny btn btn-remove" do
%i.icon-minus.icon-white
= form_for(member, as: :team_member, url: team_member_path(@team, user)) do |f|
= f.select :permission, options_for_select(UsersProject.access_roles, @team.default_projects_access(user)), {}, class: "medium trigger-submit"
%br
= label_tag do
= f.check_box :group_admin, class: 'trigger-submit'
%span Admin access
.pull-right
- if current_user == user
%span.btn.disabled This is you!
- if @team.owner == user
%span.btn.disabled Owner
- elsif user.blocked
%span.btn.disabled.blocked Blocked
- elsif allow_admin
= link_to team_member_path(@team, user), confirm: remove_from_user_team_message(@team, user), method: :delete, class: "btn-tiny btn btn-remove" do
%i.icon-minus.icon-white
......@@ -17,3 +17,17 @@
%li All created teams are public (users can view who enter into team and which project are assigned for this team)
%li People within a team see only projects they have access to
%li You will be able to assign existing projects for team
%hr
- if current_user.can_create_group?
.clearfix
.input.light
Need a group for several dependent projects?
= link_to new_group_path, class: "btn btn-tiny" do
Create a group
- if current_user.can_create_project?
.clearfix
.input.light
Want to create a project?
= link_to new_project_path, class: "btn btn-tiny" do
Create a project
......@@ -21,14 +21,18 @@ class PostReceive
return false
end
# Ignore push from non-gitlab users
user = if identifier.nil?
raise identifier.inspect
user = if identifier.blank?
# Local push from gitlab
email = project.repository.commit(newrev).author.email rescue nil
User.find_by_email(email) if email
elsif /^[A-Z0-9._%a-z\-]+@(?:[A-Z0-9a-z\-]+\.)+[A-Za-z]{2,4}$/.match(identifier)
User.find_by_email(identifier)
elsif identifier =~ /key/
elsif identifier =~ /\Auser-\d+\Z/
# git push over http
user_id = identifier.gsub("user-", "")
User.find_by_id(user_id)
elsif identifier =~ /\Akey-\d+\Z/
# git push over ssh
key_id = identifier.gsub("key-", "")
Key.find_by_id(key_id).try(:user)
end
......
......@@ -7,121 +7,132 @@
# 2. Replace gitlab -> host with your domain
# 3. Replace gitlab -> email_from
#
# 1. GitLab app settings
# ==========================
## GitLab settings
gitlab:
## Web server settings
host: localhost
port: 80
https: false
# Uncomment and customize to run in non-root path
# Note that ENV['RAILS_RELATIVE_URL_ROOT'] in config/unicorn.rb may need to be changed
# relative_url_root: /gitlab
# Uncomment and customize if you can't use the default user to run GitLab (default: 'git')
# user: git
## Email settings
# Email address used in the "From" field in mails sent by GitLab
email_from: gitlab@localhost
# Email address of your support contact (default: same as email_from)
support_email: support@localhost
## Project settings
default_projects_limit: 10
# signup_enabled: true # default: false - Account passwords are not sent via the email if signup is enabled.
## Gravatar
gravatar:
enabled: true # Use user avatar images from Gravatar.com (default: true)
# plain_url: "http://..." # default: http://www.gravatar.com/avatar/%{hash}?s=%{size}&d=mm
# ssl_url: "https://..." # default: https://secure.gravatar.com/avatar/%{hash}?s=%{size}&d=mm
#
# 2. Auth settings
# ==========================
## LDAP settings
ldap:
enabled: false
host: '_your_ldap_server'
base: '_the_base_where_you_search_for_users'
port: 636
uid: 'sAMAccountName'
method: 'ssl' # "ssl" or "plain"
bind_dn: '_the_full_dn_of_the_user_you_will_bind_with'
password: '_the_password_of_the_bind_user'
## Omniauth settings
omniauth:
# Enable ability for users
# Allow logging in via Twitter, Google, etc. using Omniauth providers
enabled: false
production: &base
#
# 1. GitLab app settings
# ==========================
## GitLab settings
gitlab:
## Web server settings
host: localhost
port: 80
https: false
# Uncomment and customize to run in non-root path
# Note that ENV['RAILS_RELATIVE_URL_ROOT'] in config/unicorn.rb may need to be changed
# relative_url_root: /gitlab
# Uncomment and customize if you can't use the default user to run GitLab (default: 'git')
# user: git
## Email settings
# Email address used in the "From" field in mails sent by GitLab
email_from: gitlab@localhost
# Email address of your support contact (default: same as email_from)
support_email: support@localhost
## Project settings
default_projects_limit: 10
# signup_enabled: true # default: false - Account passwords are not sent via the email if signup is enabled.
# username_changing_enabled: false # default: true - User can change her username/namespace
## Gravatar
gravatar:
enabled: true # Use user avatar images from Gravatar.com (default: true)
# plain_url: "http://..." # default: http://www.gravatar.com/avatar/%{hash}?s=%{size}&d=mm
# ssl_url: "https://..." # default: https://secure.gravatar.com/avatar/%{hash}?s=%{size}&d=mm
#
# 2. Auth settings
# ==========================
## LDAP settings
ldap:
enabled: false
host: '_your_ldap_server'
base: '_the_base_where_you_search_for_users'
port: 636
uid: 'sAMAccountName'
method: 'ssl' # "ssl" or "plain"
bind_dn: '_the_full_dn_of_the_user_you_will_bind_with'
password: '_the_password_of_the_bind_user'
## Omniauth settings
omniauth:
# Enable ability for users
# Allow logging in via Twitter, Google, etc. using Omniauth providers
enabled: false
# CAUTION!
# This allows users to login without having a user account first (default: false)
# User accounts will be created automatically when authentication was successful.
allow_single_sign_on: false
# Locks down those users until they have been cleared by the admin (default: true)
block_auto_created_users: true
## Auth providers
# Uncomment the lines and fill in the data of the auth provider you want to use
# If your favorite auth provider is not listed you can user others:
# see https://github.com/gitlabhq/gitlabhq/wiki/Using-Custom-Omniauth-Providers
# The 'app_id' and 'app_secret' parameters are always passed as the first two
# arguments, followed by optional 'args' which can be either a hash or an array.
providers:
# - { name: 'google_oauth2', app_id: 'YOUR APP ID',
# app_secret: 'YOUR APP SECRET',
# args: { access_type: 'offline', approval_prompt: '' } }
# - { name: 'twitter', app_id: 'YOUR APP ID',
# app_secret: 'YOUR APP SECRET'}
# - { name: 'github', app_id: 'YOUR APP ID',
# app_secret: 'YOUR APP SECRET' }
#
# 3. Advanced settings
# ==========================
# GitLab Satellites
satellites:
# Relative paths are relative to Rails.root (default: tmp/repo_satellites/)
path: /home/git/gitlab-satellites/
## Backup settings
backup:
path: "tmp/backups" # Relative paths are relative to Rails.root (default: tmp/backups/)
# keep_time: 604800 # default: 0 (forever) (in seconds)
## GitLab Shell settings
gitlab_shell:
# REPOS_PATH MUST NOT BE A SYMLINK!!!
repos_path: /home/git/repositories/
hooks_path: /home/git/gitlab-shell/hooks/
# Git over HTTP
upload_pack: true
receive_pack: true
# If you use non-standart ssh port you need to specify it
# ssh_port: 22
## Git settings
# CAUTION!
# This allows users to login without having a user account first (default: false)
# User accounts will be created automatically when authentication was successful.
allow_single_sign_on: false
# Locks down those users until they have been cleared by the admin (default: true)
block_auto_created_users: true
## Auth providers
# Uncomment the lines and fill in the data of the auth provider you want to use
# If your favorite auth provider is not listed you can user others:
# see https://github.com/gitlabhq/gitlabhq/wiki/Using-Custom-Omniauth-Providers
# The 'app_id' and 'app_secret' parameters are always passed as the first two
# arguments, followed by optional 'args' which can be either a hash or an array.
providers:
# - { name: 'google_oauth2', app_id: 'YOUR APP ID',
# app_secret: 'YOUR APP SECRET',
# args: { access_type: 'offline', approval_prompt: '' } }
# - { name: 'twitter', app_id: 'YOUR APP ID',
# app_secret: 'YOUR APP SECRET'}
# - { name: 'github', app_id: 'YOUR APP ID',
# app_secret: 'YOUR APP SECRET' }
#
# 3. Advanced settings
# ==========================
# GitLab Satellites
satellites:
# Relative paths are relative to Rails.root (default: tmp/repo_satellites/)
path: /home/git/gitlab-satellites/
## Backup settings
backup:
path: "tmp/backups" # Relative paths are relative to Rails.root (default: tmp/backups/)
# keep_time: 604800 # default: 0 (forever) (in seconds)
## GitLab Shell settings
gitlab_shell:
# REPOS_PATH MUST NOT BE A SYMLINK!!!
repos_path: /home/git/repositories/
hooks_path: /home/git/gitlab-shell/hooks/
# Git over HTTP
upload_pack: true
receive_pack: true
# If you use non-standart ssh port you need to specify it
# ssh_port: 22
## Git settings
# CAUTION!
# Use the default values unless you really know what you are doing
git:
bin_path: /usr/bin/git
# Max size of git object like commit, in bytes
# This value can be increased if you have a very large commits
max_size: 5242880 # 5.megabytes
# Git timeout to read commit, in seconds
timeout: 10
# Use the default values unless you really know what you are doing
git:
bin_path: /usr/bin/git
# Max size of git object like commit, in bytes
# This value can be increased if you have a very large commits
max_size: 5242880 # 5.megabytes
# Git timeout to read commit, in seconds
timeout: 10
development:
<<: *base
test:
<<: *base
staging:
<<: *base
class Settings < Settingslogic
source "#{Rails.root}/config/gitlab.yml"
namespace Rails.env
class << self
def gitlab_on_non_standard_port?
......@@ -56,6 +57,7 @@ Settings.gitlab['support_email'] ||= Settings.gitlab.email_from
Settings.gitlab['url'] ||= Settings.send(:build_gitlab_url)
Settings.gitlab['user'] ||= 'git'
Settings.gitlab['signup_enabled'] ||= false
Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil?
#
# Gravatar
......
module Gitlab
Version = File.read(Rails.root.join("VERSION"))
Revision = `git log --pretty=format:'%h' -n 1`
VERSION = File.read(Rails.root.join("VERSION")).strip
REVISION = `git log --pretty=format:'%h' -n 1`
def self.config
Settings
......
......@@ -47,6 +47,11 @@ Gitlab::Application.routes.draw do
end
#
# Attachments serving
#
get 'files/:type/:id/:filename' => 'files#download', constraints: { id: /\d+/, type: /[a-z]+/, filename: /[a-zA-Z.0-9_\-\+]+/ }
#
# Admin Area
#
namespace :admin do
......
root = Gitlab.config.gitolite.repos_path
root = Gitlab.config.gitlab_shell.repos_path
projects = [
{ path: 'underscore.git', git: 'https://github.com/documentcloud/underscore.git' },
......
......@@ -16,7 +16,7 @@ Gitlab::Seeder.quiet do
project_id: project.id,
author_id: user_id,
assignee_id: user_id,
closed: [true, false].sample,
state: ['opened', 'closed'].sample,
milestone: project.milestones.sample,
title: Faker::Lorem.sentence(6)
}])
......
......@@ -17,7 +17,7 @@ Gitlab::Seeder.quiet do
project_id: project.id,
author_id: user_id,
assignee_id: user_id,
closed: [true, false].sample,
state: ['opened', 'closed'].sample,
milestone: project.milestones.sample,
title: Faker::Lorem.sentence(6)
}])
......
class RenameStateToMergeStatusInMilestone < ActiveRecord::Migration
def change
rename_column :merge_requests, :state, :merge_status
end
end
class AddStateToIssue < ActiveRecord::Migration
def change
add_column :issues, :state, :string
end
end
class AddStateToMergeRequest < ActiveRecord::Migration
def change
add_column :merge_requests, :state, :string
end
end
class AddStateToMilestone < ActiveRecord::Migration
def change
add_column :milestones, :state, :string
end
end
class ConvertClosedToStateInIssue < ActiveRecord::Migration
def up
Issue.transaction do
Issue.where(closed: true).update_all("state = 'closed'")
Issue.where(closed: false).update_all("state = 'opened'")
end
end
def down
Issue.transaction do
Issue.where(state: :closed).update_all("closed = 1")
end
end
end
class ConvertClosedToStateInMergeRequest < ActiveRecord::Migration
def up
MergeRequest.transaction do
MergeRequest.where("closed = 1 AND merged = 1").update_all("state = 'merged'")
MergeRequest.where("closed = 1 AND merged = 0").update_all("state = 'closed'")
MergeRequest.where("closed = 0").update_all("state = 'opened'")
end
end
def down
MergeRequest.transaction do
MergeRequest.where(state: :closed).update_all("closed = 1")
MergeRequest.where(state: :merged).update_all("closed = 1, merged = 1")
end
end
end
class ConvertClosedToStateInMilestone < ActiveRecord::Migration
def up
Milestone.transaction do
Milestone.where(closed: false).update_all("state = 'opened'")
Milestone.where(closed: false).update_all("state = 'active'")
end
end
def down
Milestone.transaction do
Milestone.where(state: :closed).update_all("closed = 1")
end
end
end
class RemoveMergedFromMergeRequest < ActiveRecord::Migration
def up
remove_column :merge_requests, :merged
end
def down
add_column :merge_requests, :merged, :boolean, default: true, null: false
end
end
class RemoveClosedFromIssue < ActiveRecord::Migration
def up
remove_column :issues, :closed
end
def down
add_column :issues, :closed, :boolean
end
end
class RemoveClosedFromMergeRequest < ActiveRecord::Migration
def up
remove_column :merge_requests, :closed
end
def down
add_column :merge_requests, :closed, :boolean
end
end
class RemoveClosedFromMilestone < ActiveRecord::Migration
def up
remove_column :milestones, :closed
end
def down
add_column :milestones, :closed, :boolean
end
end
......@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20130131070232) do
ActiveRecord::Schema.define(:version => 20130218141554) do
create_table "events", :force => true do |t|
t.string "target_type"
......@@ -37,18 +37,17 @@ ActiveRecord::Schema.define(:version => 20130131070232) do
t.integer "assignee_id"
t.integer "author_id"
t.integer "project_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.boolean "closed", :default => false, :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "position", :default => 0
t.string "branch_name"
t.text "description"
t.integer "milestone_id"
t.string "state"
end
add_index "issues", ["assignee_id"], :name => "index_issues_on_assignee_id"
add_index "issues", ["author_id"], :name => "index_issues_on_author_id"
add_index "issues", ["closed"], :name => "index_issues_on_closed"
add_index "issues", ["created_at"], :name => "index_issues_on_created_at"
add_index "issues", ["milestone_id"], :name => "index_issues_on_milestone_id"
add_index "issues", ["project_id"], :name => "index_issues_on_project_id"
......@@ -69,25 +68,23 @@ ActiveRecord::Schema.define(:version => 20130131070232) do
add_index "keys", ["user_id"], :name => "index_keys_on_user_id"
create_table "merge_requests", :force => true do |t|
t.string "target_branch", :null => false
t.string "source_branch", :null => false
t.integer "project_id", :null => false
t.string "target_branch", :null => false
t.string "source_branch", :null => false
t.integer "project_id", :null => false
t.integer "author_id"
t.integer "assignee_id"
t.string "title"
t.boolean "closed", :default => false, :null => false
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.text "st_commits", :limit => 2147483647
t.text "st_diffs", :limit => 2147483647
t.boolean "merged", :default => false, :null => false
t.integer "state", :default => 1, :null => false
t.integer "merge_status", :default => 1, :null => false
t.integer "milestone_id"
t.string "state"
end
add_index "merge_requests", ["assignee_id"], :name => "index_merge_requests_on_assignee_id"
add_index "merge_requests", ["author_id"], :name => "index_merge_requests_on_author_id"
add_index "merge_requests", ["closed"], :name => "index_merge_requests_on_closed"
add_index "merge_requests", ["created_at"], :name => "index_merge_requests_on_created_at"
add_index "merge_requests", ["milestone_id"], :name => "index_merge_requests_on_milestone_id"
add_index "merge_requests", ["project_id"], :name => "index_merge_requests_on_project_id"
......@@ -96,13 +93,13 @@ ActiveRecord::Schema.define(:version => 20130131070232) do
add_index "merge_requests", ["title"], :name => "index_merge_requests_on_title"
create_table "milestones", :force => true do |t|
t.string "title", :null => false
t.integer "project_id", :null => false
t.string "title", :null => false
t.integer "project_id", :null => false
t.text "description"
t.date "due_date"
t.boolean "closed", :default => false, :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "state"
end
add_index "milestones", ["due_date"], :name => "index_milestones_on_due_date"
......
......@@ -34,7 +34,6 @@ POST /projects/:id/milestones
Parameters:
+ `id` (required) - The ID of a project
+ `milestone_id` (required) - The ID of a project milestone
+ `title` (required) - The title of an milestone
+ `description` (optional) - The description of the milestone
+ `due_date` (optional) - The due date of the milestone
......
......@@ -23,7 +23,7 @@ GET /projects
"blocked": false,
"created_at": "2012-05-23T08:00:58Z"
},
"private": true,
"public": true,
"path": "rails",
"path_with_namespace": "rails/rails",
"issues_enabled": false,
......@@ -45,7 +45,7 @@ GET /projects
"blocked": false,
"created_at": "2012-05-23T08:00:58Z"
},
"private": true,
"public": true,
"path": "gitlab",
"path_with_namespace": "randx/gitlab",
"issues_enabled": true,
......@@ -89,7 +89,7 @@ Parameters:
"blocked": false,
"created_at": "2012-05-23T08:00:58Z"
},
"private": true,
"public": true,
"path": "gitlab",
"path_with_namespace": "randx/gitlab",
"issues_enabled": true,
......
......@@ -27,7 +27,7 @@ GitLab supports the following databases:
mysql> \q
# Try connecting to the new database with the new user
sudo -u gitlab -H mysql -u gitlab -p -D gitlabhq_production
sudo -u git -H mysql -u gitlab -p -D gitlabhq_production
## PostgreSQL
......@@ -47,5 +47,5 @@ GitLab supports the following databases:
template1=# \q
# Try connecting to the new database with the new user
sudo -u gitlab -H psql -d gitlabhq_production
sudo -u git -H psql -d gitlabhq_production
This installation guide was created for Debian/Ubuntu and tested on it.
Please read `doc/install/requirements.md` for hardware and platform requirements.
Please read [`doc/install/requirements.md`](./requirements.md) for hardware and platform requirements.
**Important Note:**
......@@ -8,12 +8,13 @@ The following steps have been known to work.
If you deviate from this guide, do it with caution and make sure you don't
violate any assumptions GitLab makes about its environment.
For things like AWS installation scripts, init scripts or config files for
alternative web server have a look at the "Advanced Setup Tips" section.
alternative web server have a look at the [`Advanced Setup
Tips`](./installation.md#advanced-setup-tips) section.
**Important Note:**
If you find a bug/error in this guide please submit an issue or pull request
following the contribution guide (see `CONTRIBUTING.md`).
following the [`contribution guide`](../../CONTRIBUTING.md).
- - -
......@@ -24,7 +25,7 @@ The GitLab installation consists of setting up the following components:
1. Packages / Dependencies
2. Ruby
3. System Users
4. Gitolite
4. GitLab shell
5. Database
6. GitLab
7. Nginx
......@@ -32,16 +33,13 @@ The GitLab installation consists of setting up the following components:
# 1. Packages / Dependencies
`sudo` is not installed on Debian by default. If you don't have it you'll need
to install it first.
`sudo` is not installed on Debian by default. Make sure your system is
up-to-date and install it.
# run as root
apt-get update && apt-get upgrade && apt-get install sudo
Make sure your system is up-to-date:
sudo apt-get update
sudo apt-get upgrade
apt-get update
apt-get upgrade
apt-get install sudo
**Note:**
Vim is an editor that is used here whenever there are files that need to be
......@@ -96,25 +94,24 @@ Create a `git` user for Gitlab:
# 4. GitLab shell
# login as git
# Login as git
sudo su git
# go to home directory
# Go to home directory
cd /home/git
# clone gitlab shell
# Clone gitlab shell
git clone https://github.com/gitlabhq/gitlab-shell.git
# setup
# Setup
cd gitlab-shell
cp config.yml.example config.yml
./bin/install
# 5. Database
To setup the MySQL/PostgreSQL database and dependencies please see [`doc/install/databases.md`](./databases.md) .
To setup the MySQL/PostgreSQL database and dependencies please see [`doc/install/databases.md`](./databases.md).
# 6. GitLab
......@@ -154,9 +151,13 @@ do so with caution!
sudo chmod -R u+rwX log/
sudo chmod -R u+rwX tmp/
# Make directory for satellites
# Create directory for satellites
sudo -u git -H mkdir /home/git/gitlab-satellites
# Create directory for pids and make sure GitLab can write to it
sudo -u git -H mkdir tmp/pids/
sudo chmod -R u+rwX tmp/pids/
# Copy the example Unicorn config
sudo -u git -H cp config/unicorn.rb.example config/unicorn.rb
......@@ -187,7 +188,9 @@ Make sure to update username/password in config/database.yml.
## Initialise Database and Activate Advanced Features
sudo -u git -H bundle exec rake db:setup RAILS_ENV=production
sudo -u git -H bundle exec rake db:seed_fu RAILS_ENV=production
sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production
......@@ -205,7 +208,7 @@ Make GitLab start on boot:
## Check Application Status
Check if GitLab and its environment is configured correctly:
Check if GitLab and its environment are configured correctly:
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
......@@ -227,7 +230,7 @@ However there are still a few steps left.
**Note:**
If you can't or don't want to use Nginx as your web server, have a look at the
"Advanced Setup Tips" section.
[`Advanced Setup Tips`](./installation.md#advanced-setup-tips) section.
## Installation
sudo apt-get install nginx
......@@ -244,11 +247,11 @@ Make sure to edit the config file to match your setup:
# Change **YOUR_SERVER_IP** and **YOUR_SERVER_FQDN**
# to the IP address and fully-qualified domain name
# of your host serving GitLab
sudo vim /etc/nginx/sites-enabled/gitlab
sudo vim /etc/nginx/sites-available/gitlab
## Restart
sudo /etc/init.d/nginx restart
sudo service nginx restart
# Done!
......@@ -282,7 +285,7 @@ a different host, you can configure its connection string via the
## Custom SSH Connection
If you are running SSH on a non-standard port, you must change the gitlab user'S SSH config.
If you are running SSH on a non-standard port, you must change the gitlab user's SSH config.
# Add to /home/git/.ssh/config
host localhost # Give your setup a name (here: override localhost)
......
......@@ -43,6 +43,6 @@ class ProfileSshKeys < Spinach::FeatureSteps
end
And 'I have ssh key "ssh-rsa Work"' do
create(:key, :user => @user, :title => "ssh-rsa Work", :key => "jfKLJDFKSFJSHFJssh-rsa Work")
create(:key, :user => @user, :title => "ssh-rsa Work", :key => "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+L3TbFegm3k8QjejSwemk4HhlRh+DuN679Pc5ckqE/MPhVtE/+kZQDYCTB284GiT2aIoGzmZ8ee9TkaoejAsBwlA+Wz2Q3vhz65X6sMgalRwpdJx8kSEUYV8ZPV3MZvPo8KdNg993o4jL6G36GDW4BPIyO6FPZhfsawdf6liVD0Xo5kibIK7B9VoE178cdLQtLpS2YolRwf5yy6XR6hbbBGQR+6xrGOdP16eGZDb1CE2bMvvJijjloFqPscGktWOqW+nfh5txwFfBzlfARDTBsS8WZtg3Yoj1kn33kPsWRlgHfNutFRAIynDuDdQzQq8tTtVwm+Yi75RfcPHW8y3P Work")
end
end
......@@ -122,10 +122,9 @@ class ProjectIssues < Spinach::FeatureSteps
And 'project "Shop" have "Release 0.3" closed issue' do
project = Project.find_by_name("Shop")
create(:issue,
create(:closed_issue,
:title => "Release 0.3",
:project => project,
:author => project.users.first,
:closed => true)
:author => project.users.first)
end
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment