Merge branch 'master' into fixes/api
Conflicts: spec/requests/api/projects_spec.rb
This commit is contained in:
commit
eefb27f5ae
134 changed files with 1116 additions and 859 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -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
|
||||
|
|
3
Gemfile
3
Gemfile
|
@ -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
|
||||
|
|
13
app/controllers/files_controller.rb
Normal file
13
app/controllers/files_controller.rb
Normal file
|
@ -0,0 +1,13 @@
|
|||
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
|
||||
|
|
|
@ -1,12 +1,4 @@
|
|||
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)
|
||||
scope :merged, -> { with_state(:merged) }
|
||||
|
||||
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 self.find_all_by_milestone(milestone)
|
||||
where("milestone_id = :milestone_id", milestone_id: milestone)
|
||||
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
|
||||
|
||||
= 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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
%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
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
.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.
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
- 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
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
%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 @@
|
|||
← 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}
|
||||
–
|
||||
|
@ -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}
|
||||
–
|
||||
|
|
|
@ -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
|
||||
|
||||
%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
|
||||
|
||||
%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"
|
||||
= 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
|
||||
|
|
10
app/views/team_members/_assigned_team.html.haml
Normal file
10
app/views/team_members/_assigned_team.html.haml
Normal file
|
@ -0,0 +1,10 @@
|
|||
%li{id: dom_id(team), class: "user_team_row team_#{team.id}"}
|
||||
.pull-right
|
||||
- if can?(current_user, :admin_team_member, @project)
|
||||
= link_to resign_project_team_path(@project, team), method: :delete, confirm: "Are you shure?", class: "btn btn-remove btn-tiny" do
|
||||
%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}
|
4
app/views/team_members/_assigned_teams.html.haml
Normal file
4
app/views/team_members/_assigned_teams.html.haml
Normal file
|
@ -0,0 +1,4 @@
|
|||
.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
|
|
@ -1,15 +0,0 @@
|
|||
- 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}
|
||||
|
||||
.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
|
|
@ -1,16 +1,8 @@
|
|||
- 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
|
|
@ -1,16 +0,0 @@
|
|||
- 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}
|
||||
|
|
|
@ -1,20 +1,29 @@
|
|||
%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
|
||||
# ==========================
|
||||
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
|
||||
## 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
|
||||
# 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 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
|
||||
# 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.
|
||||
## 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
|
||||
## 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
|
||||
# ==========================
|
||||
#
|
||||
# 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'
|
||||
## 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
|
||||
## 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
|
||||
# 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
|
||||
|
||||
## 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' }
|
||||
development:
|
||||
<<: *base
|
||||
|
||||
test:
|
||||
<<: *base
|
||||
|
||||
|
||||
#
|
||||
# 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
|
||||
staging:
|
||||
<<: *base
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
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
|
||||
|
|
|
@ -46,6 +46,11 @@ Gitlab::Application.routes.draw do
|
|||
root to: "projects#index"
|
||||
end
|
||||
|
||||
#
|
||||
# Attachments serving
|
||||
#
|
||||
get 'files/:type/:id/:filename' => 'files#download', constraints: { id: /\d+/, type: /[a-z]+/, filename: /[a-zA-Z.0-9_\-\+]+/ }
|
||||
|
||||
#
|
||||
# Admin Area
|
||||
#
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
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)
|
||||
}])
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
class RenameStateToMergeStatusInMilestone < ActiveRecord::Migration
|
||||
def change
|
||||
rename_column :merge_requests, :state, :merge_status
|
||||
end
|
||||
end
|
5
db/migrate/20130218140952_add_state_to_issue.rb
Normal file
5
db/migrate/20130218140952_add_state_to_issue.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
class AddStateToIssue < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :issues, :state, :string
|
||||
end
|
||||
end
|
5
db/migrate/20130218141038_add_state_to_merge_request.rb
Normal file
5
db/migrate/20130218141038_add_state_to_merge_request.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
class AddStateToMergeRequest < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :merge_requests, :state, :string
|
||||
end
|
||||
end
|
5
db/migrate/20130218141117_add_state_to_milestone.rb
Normal file
5
db/migrate/20130218141117_add_state_to_milestone.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
class AddStateToMilestone < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :milestones, :state, :string
|
||||
end
|
||||
end
|
|
@ -0,0 +1,14 @@
|
|||
class ConvertClosedToStateInIssue < ActiveRecord::Migration
|
||||
def up
|
||||
Issue.transaction do
|
||||
Issue.where(closed: true).update_all("state = 'closed'")
|
||||
Issue.where(closed: false).update_all("state = 'opened'")
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
Issue.transaction do
|
||||
Issue.where(state: :closed).update_all("closed = 1")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,16 @@
|
|||
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
|
|
@ -0,0 +1,14 @@
|
|||
class ConvertClosedToStateInMilestone < ActiveRecord::Migration
|
||||
def up
|
||||
Milestone.transaction do
|
||||
Milestone.where(closed: false).update_all("state = 'opened'")
|
||||
Milestone.where(closed: false).update_all("state = 'active'")
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
Milestone.transaction do
|
||||
Milestone.where(state: :closed).update_all("closed = 1")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
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
|
9
db/migrate/20130218141507_remove_closed_from_issue.rb
Normal file
9
db/migrate/20130218141507_remove_closed_from_issue.rb
Normal file
|
@ -0,0 +1,9 @@
|
|||
class RemoveClosedFromIssue < ActiveRecord::Migration
|
||||
def up
|
||||
remove_column :issues, :closed
|
||||
end
|
||||
|
||||
def down
|
||||
add_column :issues, :closed, :boolean
|
||||
end
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
class RemoveClosedFromMergeRequest < ActiveRecord::Migration
|
||||
def up
|
||||
remove_column :merge_requests, :closed
|
||||
end
|
||||
|
||||
def down
|
||||
add_column :merge_requests, :closed, :boolean
|
||||
end
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
class RemoveClosedFromMilestone < ActiveRecord::Migration
|
||||
def up
|
||||
remove_column :milestones, :closed
|
||||
end
|
||||
|
||||
def down
|
||||
add_column :milestones, :closed, :boolean
|
||||
end
|
||||
end
|
35
db/schema.rb
35
db/schema.rb
|
@ -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
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
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
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue