Commit 8045a81b authored by Sebastian Ziebell's avatar Sebastian Ziebell

Merge branch 'master' into fixes/api

parents 5d8a99f1 2f0a75ab
v 5.0.0
- replaced gitolite with gitlab-shell
v 4.2.0
- User show page. Via /u/username
- Show help contents on pages for better navigation
......
......@@ -32,9 +32,6 @@ gem 'gitlab_omniauth-ldap', '1.0.2', require: "omniauth-ldap"
# Dump db to yml file. Mostly used to migrate from sqlite to mysql
gem 'gitlab_yaml_db', '1.0.0', require: "yaml_db"
# Gitolite client (for work with gitolite-admin repo)
gem "gitolite", '1.1.0'
# Syntax highlighter
gem "pygments.rb", git: "https://github.com/gitlabhq/pygments.rb.git", branch: "master"
......@@ -165,5 +162,5 @@ group :test do
end
group :production do
gem "gitlab_meta", '4.0'
gem "gitlab_meta", '5.0'
end
......@@ -107,7 +107,6 @@ GEM
coderay (>= 1.0.0)
erubis (>= 2.7.0)
binding_of_caller (0.6.8)
blankslate (3.1.2)
bootstrap-sass (2.2.1.1)
sass (~> 3.2)
builder (3.0.4)
......@@ -188,17 +187,13 @@ GEM
mime-types (~> 1.19)
pygments.rb (>= 0.2.13)
github-markup (0.7.4)
gitlab_meta (4.0)
gitlab_meta (5.0)
gitlab_omniauth-ldap (1.0.2)
net-ldap (~> 0.2.2)
omniauth (~> 1.0)
pyu-ruby-sasl (~> 0.0.3.1)
rubyntlm (~> 0.1.1)
gitlab_yaml_db (1.0.0)
gitolite (1.1.0)
gratr19 (~> 0.4.4.1)
grit (~> 2.5.0)
hashery (~> 1.5.0)
grape (0.2.2)
activesupport
hashie (~> 1.2)
......@@ -208,7 +203,6 @@ GEM
rack-accept
rack-mount
virtus
gratr19 (0.4.4.1)
growl (1.0.3)
guard (1.5.4)
listen (>= 0.4.2)
......@@ -227,8 +221,6 @@ GEM
activesupport (>= 3.1, < 4.1)
haml (~> 3.1)
railties (>= 3.1, < 4.1)
hashery (1.5.0)
blankslate
hashie (1.2.0)
hike (1.2.1)
http_parser.rb (0.5.3)
......@@ -494,10 +486,9 @@ DEPENDENCIES
git
github-linguist (~> 2.3.4)
github-markup (~> 0.7.4)
gitlab_meta (= 4.0)
gitlab_meta (= 5.0)
gitlab_omniauth-ldap (= 1.0.2)
gitlab_yaml_db (= 1.0.0)
gitolite (= 1.1.0)
grack!
grape (~> 0.2.1)
grit!
......
## GitLab Roadmap
### v4.3 March 22
### v5.0 March 22
* Jenkins CI integration service
* Replace gitolite with gitlab-shell
* Usability improvements
* Notification improvements
### v4.2 February 22
* Campfire integration service
* Teams
......@@ -20,12 +20,12 @@ var NoteList = {
if(NoteList.reversed) {
var form = $(".js-main-target-form");
form.find(".buttons, .note_options").hide();
form.find(".note-form-actions").hide();
var textarea = form.find(".js-note-text");
textarea.css("height", "40px");
textarea.on("focus", function(){
textarea.css("height", "80px");
form.find(".buttons, .note_options").show();
form.find(".note-form-actions").show();
});
}
......
......@@ -338,10 +338,6 @@ li.note {
li {
border-bottom:none !important;
}
.attachment {
padding-left: 20px;
background:url("icon-attachment.png") no-repeat left center;
}
}
}
......
......@@ -17,6 +17,8 @@ $baseLineHeight: 18px !default;
@import "gitlab_bootstrap/variables.scss";
@import "gitlab_bootstrap/fonts.scss";
@import "gitlab_bootstrap/mixins.scss";
@import "gitlab_bootstrap/avatar.scss";
@import "gitlab_bootstrap/nav.scss";
@import "gitlab_bootstrap/common.scss";
@import "gitlab_bootstrap/typography.scss";
@import "gitlab_bootstrap/buttons.scss";
......
/** AVATARS **/
img.avatar { float: left; margin-right: 12px; width: 40px; border: 1px solid #ddd; padding: 1px; }
img.avatar.s16 { width: 16px; height: 16px; margin-right: 6px; }
img.avatar.s24 { width: 24px; height: 24px; margin-right: 8px; }
img.avatar.s32 { width: 32px; height: 32px; margin-right: 10px; }
img.avatar.s90 { width: 90px; height: 90px; margin-right: 15px; }
img.lil_av { padding-left: 4px; padding-right: 3px; }
img.small { width: 80px; }
......@@ -95,7 +95,11 @@
form {
margin-bottom: 0;
margin-top: 3px;
margin-top: 0;
}
.btn-tiny {
@include box-shadow(0 0px 0px 1px #f1f1f1);
}
.nav-pills {
......
.btn {
@include linear-gradient(#f7f7f7, #d5d5d5);
@include linear-gradient(#f1f1f1, #e1e1e1);
text-shadow: 0 1px 1px #FFF;
border-color: #BBB;
&:hover {
@include bg-gray-gradient;
border-color: #bbb;
background: #f1f1f1;
@include linear-gradient(#fAfAfA, #f1f1f1);
border-color: #AAA;
color: #333;
}
&.btn-white {
background: #FFF;
}
&.primary {
&.btn-primary {
background: #2a79A3;
@include linear-gradient(#47A7b7, #2585b5);
border-color: #2A79A3;
......@@ -58,21 +57,18 @@
}
}
&.save-btn {
&.btn-create {
@extend .wide;
@extend .primary;
@extend .success;
}
&.cancel-btn {
float: right;
}
&.wide {
padding-left: 30px;
padding-right: 30px;
&.btn-save {
@extend .wide;
@extend .btn-primary;
}
&.danger {
&.btn-close,
&.btn-remove {
@extend .btn-danger;
border-color: #BD362F;
......@@ -82,8 +78,13 @@
}
}
&.danger {
@extend .btn-danger;
&.btn-cancel {
float: right;
}
&.wide {
padding-left: 20px;
padding-right: 20px;
}
&.small {
......@@ -95,7 +96,7 @@
background-color: #ccc;
}
&.very_small {
&.btn-tiny {
font-size: 11px;
padding: 2px 6px;
line-height: 16px;
......
......@@ -9,7 +9,6 @@
/** COMMON CLASSES **/
.left { float:left }
.right { float:right!important }
.append-bottom-10 { margin-bottom:10px }
.append-bottom-20 { margin-bottom:20px }
.prepend-top-10 { margin-top:10px }
......@@ -22,82 +21,13 @@
.light { color: #888 }
.tiny { font-weight: normal }
/** PILLS & TABS**/
.nav-pills {
.active a {
background: $primary_color;
}
> li > a {
@include border-radius(0);
}
&.nav-stacked {
> li > a {
border-left: 4px solid #EEE;
padding: 12px;
}
> .active > a {
border-color: #29B;
border-radius: 0;
background: #F1F1F1;
color: $style_color;
font-weight: bold;
}
}
}
.nav-pills > .active > a > i[class^="icon-"] { background: inherit; }
/**
* nav-tabs
*
*/
.nav-tabs > li > a, .nav-pills > li > a { color: $style_color; }
.nav.nav-tabs {
li {
> a {
padding: 8px 20px;
margin-right: 7px;
line-height: 20px;
border-color: #EEE;
color: #888;
border-bottom: 1px solid #ddd;
.badge {
background-color: #eee;
color: #888;
text-shadow: 0 1px 1px #fff;
}
i[class^="icon-"] {
line-height: 14px;
}
}
&.active {
> a {
border-color: #CCC;
border-bottom: 1px solid #fff;
color: #333;
}
}
}
&.nav-small-tabs > li > a { padding: 6px 9px; }
}
/** ALERT MESSAGES **/
.alert-message { @extend .alert; }
.alert-messag.success { @extend .alert-success; }
.alert-message.error { @extend .alert-error; }
/** AVATARS **/
img.avatar { float: left; margin-right: 12px; width: 40px; border: 1px solid #ddd; padding: 1px; }
img.avatar.s16 { width: 16px; height: 16px; margin-right: 6px; }
img.avatar.s24 { width: 24px; height: 24px; margin-right: 8px; }
img.avatar.s32 { width: 32px; height: 32px; margin-right: 10px; }
img.avatar.s90 { width: 90px; height: 90px; margin-right: 15px; }
img.lil_av { padding-left: 4px; padding-right: 3px; }
img.small { width: 80px; }
.alert.alert-disabled {
background: #EEE;
color: #777;
border-color: #DDD;
}
/** HELPERS **/
.nothing_here_message {
......
/**
* nav-pills
*
*/
.nav-pills {
.active a {
background: $primary_color;
}
> li > a {
@include border-radius(0);
}
&.nav-stacked {
> li > a {
border-left: 4px solid #EEE;
padding: 12px;
}
> .active > a {
border-color: #29B;
border-radius: 0;
background: #F1F1F1;
color: $style_color;
font-weight: bold;
}
}
}
.nav-pills > .active > a > i[class^="icon-"] { background: inherit; }
/**
* nav-tabs
*
*/
.nav-tabs > li > a, .nav-pills > li > a { color: $style_color; }
.nav.nav-tabs {
li {
> a {
padding: 8px 20px;
margin-right: 7px;
line-height: 20px;
border-color: #EEE;
color: #888;
border-bottom: 1px solid #ddd;
.badge {
background-color: #eee;
color: #888;
text-shadow: 0 1px 1px #fff;
}
i[class^="icon-"] {
line-height: 14px;
}
}
&.active {
> a {
border-color: #CCC;
border-bottom: 1px solid #fff;
color: #333;
}
}
}
&.nav-small-tabs > li > a { padding: 6px 9px; }
}
......@@ -127,7 +127,7 @@
.btn-new-mr {
@extend .btn-info;
@extend .small;
@extend .right;
@extend .pull-right;
margin: -3px;
}
}
......
/* Login Page */
body.login-page{
padding-top: 10%;
background: #f1f1f1;
body.login-page{
padding-top: 7%;
background: #666;
}
.login-box{
......
......@@ -6,8 +6,7 @@ ul.main_menu {
margin: auto;
margin: 30px 0;
margin-top: 10px;
border-bottom: 1px solid #DDD;
height: 37px;
height: 38px;
position: relative;
overflow: hidden;
.count {
......@@ -33,6 +32,7 @@ ul.main_menu {
margin: 0;
display: table-cell;
width: 1%;
border-bottom: 2px solid #EEE;
&.active {
border-bottom: 2px solid #474D57;
a {
......@@ -42,10 +42,8 @@ ul.main_menu {
&.home {
a {
background: url(home_icon.PNG) no-repeat center center;
text-indent:-9999px;
min-width: 20px;
img {
i {
font-size: 20px;
position: relative;
top: 4px;
}
......@@ -56,7 +54,7 @@ ul.main_menu {
display: block;
text-align: center;
font-weight: normal;
height: 35px;
height: 36px;
line-height: 36px;
color: #777;
text-shadow: 0 1px 1px white;
......
......@@ -81,14 +81,6 @@ ul.notes {
.attachment {
font-size: 14px;
margin-top: -20px;
.icon-attachment {
@extend .icon-paper-clip;
font-size: 24px;
position: relative;
text-align: right;
top: 6px;
}
}
.note-body {
margin-left: 45px;
......@@ -214,9 +206,11 @@ ul.notes {
* Note Form
*/
.comment-btn,
.comment-btn {
@extend .btn-create;
}
.reply-btn {
@extend .save-btn;
@extend .btn-primary;
}
.file .content tr.line_holder:hover > td { background: $hover !important; }
.file .content tr.line_holder:hover > td .line_note_link {
......@@ -227,11 +221,6 @@ ul.notes {
.discussion {
.new_note {
margin: 8px 5px 8px 0;
.note_options {
// because of the smaller width and the extra "cancel" button
margin-top: 8px;
}
}
}
.new_note {
......@@ -244,37 +233,6 @@ ul.notes {
.clearfix {
margin-bottom: 0;
}
.note_options {
h6 {
@extend .left;
line-height: 20px;
padding-right: 16px;
padding-bottom: 16px;
}
label {
padding: 0;
}
.attachment {
@extend .right;
position: relative;
width: 350px;
height: 50px;
margin:0 0 5px !important;
// hide the actual file field
input {
display: none;
}
.choose-btn {
float: right;
}
}
.notify_options {
@extend .right;
}
}
.note_text_and_preview {
// makes the "absolute" position for links relative to this
position: relative;
......@@ -313,3 +271,17 @@ ul.notes {
@extend .thumbnail;
margin-left: 45px;
}
.note-form-actions {
background: #F9F9F9;
height: 45px;
padding: 0 5px;
.note-form-option {
margin-top: 8px;
margin-left: 15px;
@extend .pull-left;
@extend .span4;
}
}
......@@ -4,7 +4,7 @@
}
.side {
@extend .right;
@extend .pull-right;
.projects_box {
> .title {
......
......@@ -4,16 +4,12 @@ class ApplicationController < ActionController::Base
before_filter :set_current_user_for_observers
before_filter :add_abilities
before_filter :dev_tools if Rails.env == 'development'
before_filter :default_headers
protect_from_forgery
helper_method :abilities, :can?
rescue_from Gitlab::Gitolite::AccessDenied do |exception|
log_exception(exception)
render "errors/gitolite", layout: "errors", status: 500
end
rescue_from Encoding::CompatibilityError do |exception|
log_exception(exception)
render "errors/encoding", layout: "errors", status: 500
......@@ -148,4 +144,8 @@ class ApplicationController < ActionController::Base
Rack::MiniProfiler.authorize_request
end
def default_headers
headers['X-Frame-Options'] = 'DENY'
headers['X-XSS-Protection'] = '1; mode=block'
end
end
class GraphController < ProjectResourceController
include ExtractsPath
# Authorize
before_filter :authorize_read_project!
before_filter :authorize_code_access!
before_filter :require_non_empty_project
def show
respond_to do |format|
format.html
format.json do
graph = Gitlab::Graph::JsonBuilder.new(project, @ref)
render :json => graph.to_json
end
end
end
end
......@@ -6,6 +6,7 @@ class GroupsController < ApplicationController
# Authorize
before_filter :authorize_read_group!, except: [:new, :create]
before_filter :authorize_admin_group!, only: [:edit, :update, :destroy]
before_filter :authorize_create_group!, only: [:new, :create]
# Load group projects
......@@ -84,6 +85,31 @@ class GroupsController < ApplicationController
redirect_to people_group_path(@group), notice: 'Users was successfully added.'
end
def edit
end
def update
group_params = params[:group].dup
owner_id =group_params.delete(:owner_id)
if owner_id
@group.owner = User.find(owner_id)
end
if @group.update_attributes(group_params)
redirect_to @group, notice: 'Group was successfully updated.'
else
render action: "edit"
end
end
def destroy
@group.truncate_teams
@group.destroy
redirect_to root_path, notice: 'Group was removed.'
end
protected
def group
......@@ -106,6 +132,14 @@ class GroupsController < ApplicationController
end
def authorize_create_group!
can?(current_user, :create_group, nil)
unless can?(current_user, :create_group, nil)
return render_404
end
end
def authorize_admin_group!
unless can?(current_user, :manage_group, group)
return render_404
end
end
end
......@@ -90,16 +90,6 @@ class ProjectsController < ProjectResourceController
end
end
def graph
respond_to do |format|
format.html
format.json do
graph = Gitlab::Graph::JsonBuilder.new(project)
render :json => graph.to_json
end
end
end
def destroy
return access_denied! unless can?(current_user, :remove_project, project)
......
......@@ -13,6 +13,8 @@ class RefsController < ProjectResourceController
format.html do
new_path = if params[:destination] == "tree"
project_tree_path(@project, (@ref + "/" + params[:path]))
elsif params[:destination] == "graph"
project_graph_path(@project, @ref)
else
project_commits_path(@project, @ref)
end
......
......@@ -43,7 +43,7 @@ module ProjectsHelper
tm = project.team_member_by_id(author)
if tm
link_to author_html, project_team_member_path(project, tm), class: "author_link"
link_to author_html, project_team_member_path(project, tm.user_username), class: "author_link"
else
author_html
end.html_safe
......
......@@ -10,6 +10,10 @@ class Notify < ActionMailer::Base
default from: Gitlab.config.gitlab.email_from
# Just send email with 3 seconds delay
def self.delay
delay_for(2.seconds)
end
#
......@@ -63,12 +67,12 @@ class Notify < ActionMailer::Base
# Note
#
def note_commit_email(commit_autor_email, note_id)
def note_commit_email(recipient_id, note_id)
@note = Note.find(note_id)
@commit = @note.noteable
@commit = CommitDecorator.decorate(@commit)
@project = @note.project
mail(to: commit_autor_email, subject: subject("note for commit #{@commit.short_id}", @commit.title))
mail(to: recipient(recipient_id), subject: subject("note for commit #{@commit.short_id}", @commit.title))
end
def note_issue_email(recipient_id, note_id)
......
......@@ -24,8 +24,8 @@ class Key < ActiveRecord::Base
before_save :set_identifier
validates :title, presence: true, length: { within: 0..255 }
validates :key, presence: true, length: { within: 0..5000 }, format: { :with => /ssh-.{3} / }
validate :unique_key, :fingerprintable_key
validates :key, presence: true, length: { within: 0..5000 }, format: { :with => /ssh-.{3} / }, uniqueness: true
validate :fingerprintable_key
delegate :name, :email, to: :user, prefix: true
......@@ -33,14 +33,6 @@ class Key < ActiveRecord::Base
self.key = self.key.strip unless self.key.blank?
end
def unique_key
query = Key.where(key: key)
query = query.where('(project_id IS NULL OR project_id = ?)', project_id) if project_id
if (query.count > 0)
errors.add :key, 'already exist.'
end
end
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
......@@ -65,7 +57,7 @@ class Key < ActiveRecord::Base
end
def is_deploy_key
true if project_id
!!project_id
end
# projects that has this key
......@@ -77,7 +69,7 @@ class Key < ActiveRecord::Base
end
end
def last_deploy?
Key.where(identifier: identifier).count == 0
def shell_id
"key-#{self.id}"
end
end
......@@ -27,7 +27,6 @@ class Namespace < ActiveRecord::Base
after_create :ensure_dir_exist
after_update :move_dir
after_commit :update_gitolite, on: :update, if: :require_update_gitolite
after_destroy :rm_dir
scope :root, where('type IS NULL')
......@@ -89,11 +88,6 @@ class Namespace < ActiveRecord::Base
end
end
def update_gitolite
@require_update_gitolite = false
projects.each(&:update_repository)
end
def rm_dir
dir_path = File.join(Gitlab.config.gitolite.repos_path, path)
FileUtils.rm_r( dir_path, force: true )
......
......@@ -8,7 +8,6 @@
# description :text
# created_at :datetime not null
# updated_at :datetime not null
# private_flag :boolean default(TRUE), not null
# creator_id :integer
# default_branch :string(255)
# issues_enabled :boolean default(TRUE), not null
......@@ -16,6 +15,7 @@
# merge_requests_enabled :boolean default(TRUE), not null
# wiki_enabled :boolean default(TRUE), not null
# namespace_id :integer
# public :boolean default(FALSE), not null
#
require "grit"
......@@ -262,8 +262,6 @@ class Project < ActiveRecord::Base
Gitlab::ProjectMover.new(self, old_dir, new_dir).execute
gitolite.move_repository(old_repo, self)
save!
end
rescue Gitlab::ProjectMover::ProjectMoveError => ex
......@@ -459,20 +457,6 @@ class Project < ActiveRecord::Base
namespace.try(:path) || ''
end
def update_repository
GitoliteWorker.perform_async(
:update_repository,
self.id
)
end
def destroy_repository
GitoliteWorker.perform_async(
:remove_repository,
self.path_with_namespace
)
end
def repo_exists?
@repo_exists ||= (repository && repository.branches.present?)
rescue
......
......@@ -112,7 +112,6 @@ class ProjectTeam
source_team.each do |tm|
tm.save
end
target_project.update_repository
end
true
......
......@@ -18,13 +18,6 @@ class ProtectedBranch < ActiveRecord::Base
validates :name, presence: true
validates :project, presence: true
after_save :update_repository
after_destroy :update_repository
def update_repository
project.update_repository
end
def commit
project.repository.commit(self.name)
end
......
......@@ -31,6 +31,8 @@
# extern_uid :string(255)
# provider :string(255)
# username :string(255)
# can_create_group :boolean default(TRUE), not null
# can_create_team :boolean default(TRUE), not null
#
class User < ActiveRecord::Base
......
# == Schema Information
#
# Table name: user_teams
#
# id :integer not null, primary key
# name :string(255)
# path :string(255)
# owner_id :integer
# created_at :datetime not null
# updated_at :datetime not null
#
class UserTeam < ActiveRecord::Base
attr_accessible :name, :owner_id, :path
......
# == Schema Information
#
# Table name: user_team_project_relationships
#
# id :integer not null, primary key
# project_id :integer
# user_team_id :integer
# greatest_access :integer
# created_at :datetime not null
# updated_at :datetime not null
#
class UserTeamProjectRelationship < ActiveRecord::Base
attr_accessible :greatest_access, :project_id, :user_team_id
......
# == Schema Information
#
# Table name: user_team_user_relationships
#
# id :integer not null, primary key
# user_id :integer
# user_team_id :integer
# group_admin :boolean
# permission :integer
# created_at :datetime not null
# updated_at :datetime not null
#
class UserTeamUserRelationship < ActiveRecord::Base
attr_accessible :group_admin, :permission, :user_id, :user_team_id
......
......@@ -25,15 +25,12 @@ class UsersProject < ActiveRecord::Base
attr_accessor :skip_git
after_save :update_repository, unless: :skip_git?
after_destroy :update_repository, unless: :skip_git?
validates :user, presence: true
validates :user_id, uniqueness: { scope: [:project_id], message: "already exists in project" }
validates :project_access, inclusion: { in: [GUEST, REPORTER, DEVELOPER, MASTER] }, presence: true
validates :project, presence: true
delegate :name, :email, to: :user, prefix: true
delegate :name, :username, :email, to: :user, prefix: true
scope :guests, where(project_access: GUEST)
scope :reporters, where(project_access: REPORTER)
......@@ -84,11 +81,6 @@ class UsersProject < ActiveRecord::Base
end
end
GitoliteWorker.perform_async(
:update_repositories,
project_ids
)
true
rescue
false
......@@ -103,11 +95,6 @@ class UsersProject < ActiveRecord::Base
end
end
GitoliteWorker.perform_async(
:update_repositories,
project_ids
)
true
rescue
false
......@@ -136,10 +123,6 @@ class UsersProject < ActiveRecord::Base
end
end
def update_repository
project.update_repository
end
def project_access_human
Project.access_options.key(self.project_access)
end
......
......@@ -3,20 +3,17 @@ class KeyObserver < ActiveRecord::Observer
def after_save(key)
GitoliteWorker.perform_async(
:set_key,
key.identifier,
key.key,
key.projects.map(&:id)
:add_key,
key.shell_id,
key.key
)
end
def after_destroy(key)
return if key.is_deploy_key && !key.last_deploy?
GitoliteWorker.perform_async(
:remove_key,
key.identifier,
key.projects.map(&:id)
key.shell_id,
key.key,
)
end
end
......@@ -11,7 +11,9 @@ class NoteObserver < ActiveRecord::Observer
notify_team(note)
elsif note.notify_author
# Notify only author of resource
Notify.delay.note_commit_email(note.noteable.author_email, note.id)
if note.commit_author
Notify.delay.note_commit_email(note.commit_author.id, note.id)
end
else
# Otherwise ignore it
nil
......
class ProjectObserver < ActiveRecord::Observer
def after_create(project)
project.update_repository
GitoliteWorker.perform_async(
:add_repository,
project.path_with_namespace
)
log_info("#{project.owner.name} created a new project \"#{project.name_with_namespace}\"")
end
def after_update(project)
......@@ -8,14 +13,14 @@ class ProjectObserver < ActiveRecord::Observer
end
def after_destroy(project)
log_info("Project \"#{project.name}\" was removed")
GitoliteWorker.perform_async(
:remove_repository,
project.path_with_namespace
)
project.satellite.destroy
project.destroy_repository
end
def after_create project
log_info("#{project.owner.name} created a new project \"#{project.name_with_namespace}\"")
log_info("Project \"#{project.name}\" was removed")
end
protected
......
......@@ -6,7 +6,7 @@
= link_to admin_projects_path do
%h1= Project.count
%hr
= link_to 'New Project', new_project_path, class: "btn small"
= link_to 'New Project', new_project_path, class: "btn btn-small"
.span4
.ui-box
%h5.title Groups
......@@ -14,7 +14,7 @@
= link_to admin_groups_path do
%h1= Group.count
%hr
= link_to 'New Group', new_admin_group_path, class: "btn small"
= link_to 'New Group', new_admin_group_path, class: "btn btn-small"
.span4
.ui-box
%h5.title Users
......@@ -22,7 +22,7 @@
= link_to admin_users_path do
%h1= User.count
%hr
= link_to 'New User', new_admin_user_path, class: "btn small"
= link_to 'New User', new_admin_user_path, class: "btn btn-small"
.row
.span4
......@@ -31,7 +31,7 @@
- @projects.each do |project|
%p
= link_to project.name_with_namespace, [:admin, project]
%span.light.right
%span.light.pull-right
= time_ago_in_words project.created_at
ago
......@@ -42,7 +42,7 @@
%p
= link_to [:admin, user] do
= user.name
%span.light.right
%span.light.pull-right
= time_ago_in_words user.created_at
ago
......@@ -51,25 +51,25 @@
%hr
%p
Issues
%span.light.right
%span.light.pull-right
= Issue.count
%p
Merge Requests
%span.light.right
%span.light.pull-right
= MergeRequest.count
%p
Notes
%span.light.right
%span.light.pull-right
= Note.count
%p
Snippets
%span.light.right
%span.light.pull-right
= Snippet.count
%p
SSH Keys
%span.light.right
%span.light.pull-right
= Key.count
%p
Milestones
%span.light.right
%span.light.pull-right
= Milestone.count
......@@ -2,7 +2,7 @@
%hr
= form_for [:admin, @group] do |f|
- if @group.errors.any?
.alert-message.block-message.error
.alert.alert-error
%span= @group.errors.full_messages.first
.clearfix.group_name_holder
= f.label :name do
......@@ -24,5 +24,5 @@
%li It will change the git path to repositories under this group.
.form-actions
= f.submit 'Rename group', class: "btn danger"
= link_to 'Cancel', admin_groups_path, class: "btn cancel-btn"
= f.submit 'Rename group', class: "btn btn-remove"
= link_to 'Cancel', admin_groups_path, class: "btn btn-cancel"
......@@ -4,11 +4,11 @@
allows you to keep projects organized.
Use groups for uniting related projects.
= link_to 'New Group', new_admin_group_path, class: "btn small right"
= link_to 'New Group', new_admin_group_path, class: "btn btn-small pull-right"
%br
= form_tag admin_groups_path, method: :get, class: 'form-inline' do
= text_field_tag :name, params[:name], class: "xlarge"
= submit_tag "Search", class: "btn submit primary"
= submit_tag "Search", class: "btn submit btn-primary"
%table
%thead
......@@ -30,6 +30,6 @@
%td
= link_to group.owner_name, admin_user_path(group.owner_id)
%td.bgred
= link_to 'Rename', edit_admin_group_path(group), id: "edit_#{dom_id(group)}", class: "btn small"
= link_to 'Destroy', [:admin, group], confirm: "REMOVE #{group.name}? Are you sure?", method: :delete, class: "btn small danger"
= 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"
= paginate @groups, theme: "admin"
......@@ -2,7 +2,7 @@
%hr
= form_for [:admin, @group] do |f|
- if @group.errors.any?
.alert-message.block-message.error
.alert.alert-error
%span= @group.errors.full_messages.first
.clearfix
= f.label :name do
......@@ -10,7 +10,7 @@
.input
= f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
&nbsp;
= f.submit 'Create group', class: "btn primary"
= f.submit 'Create group', class: "btn btn-primary"
%hr
.padded
%ul
......
......@@ -14,7 +14,7 @@
%td
= @group.name
&nbsp;
= link_to edit_admin_group_path(@group), class: "btn btn-small right" do
= link_to edit_admin_group_path(@group), class: "btn btn-small pull-right" do
%i.icon-edit
Rename
%tr
......@@ -29,7 +29,7 @@
Owner:
%td
= @group.owner_name
.right
.pull-right
= link_to "#", class: "btn btn-small change-owner-link" do
%i.icon-edit
Change owner
......@@ -42,7 +42,7 @@
= form_for [:admin, @group] do |f|
= f.select :owner_id, User.all.map { |user| [user.name, user.id] }, {}, {class: 'chosen'}
%div
= f.submit 'Change Owner', class: "btn danger"
= f.submit 'Change Owner', class: "btn btn-remove"
= link_to "Cancel", "#", class: "btn change-owner-cancel-link"
- if @group.projects.any?
......@@ -63,7 +63,7 @@
%span.monospace= project.path_with_namespace + ".git"
%td= project.users.count
%td.bgred
= link_to 'Transfer project to global namespace', remove_project_admin_group_path(@group, project_id: project.id), confirm: 'Remove project from group and move to global namespace. Are you sure?', method: :delete, class: "btn danger small"
= link_to 'Transfer project to global namespace', remove_project_admin_group_path(@group, project_id: project.id), confirm: 'Remove project from group and move to global namespace. Are you sure?', method: :delete, class: "btn btn-remove small"
= form_tag project_teams_update_admin_group_path(@group), id: "new_team_member", class: "bulk_import", method: :put do
%table.zebra-striped
......@@ -88,7 +88,7 @@
%td= select_tag :project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3"}
%tr
%td= submit_tag 'Add user to projects in group', class: "btn primary"
%td= submit_tag 'Add user to projects in group', class: "btn btn-primary"
%td
Read more about project permissions
%strong= link_to "here", help_permissions_path, class: "vlink"
......@@ -110,7 +110,7 @@
.input
= select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name_with_namespace), multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5'
.form-actions
= submit_tag 'Add', class: "btn primary"
= submit_tag 'Add', class: "btn btn-primary"
:javascript
$(function(){
......
......@@ -7,7 +7,7 @@
= form_for @hook, as: :hook, url: admin_hooks_path, html: { class: 'form-inline' } do |f|
-if @hook.errors.any?
.alert-message.block-message.error
.alert.alert-error
- @hook.errors.full_messages.each do |msg|
%p= msg
.clearfix
......@@ -15,7 +15,7 @@
.input
= f.text_field :url, class: "text_field xxlarge"
&nbsp;
= f.submit "Add System Hook", class: "btn primary"
= f.submit "Add System Hook", class: "btn btn-primary"
%hr
-if @hooks.any?
......@@ -33,7 +33,7 @@
%td
= link_to admin_hook_path(hook) do
%strong= hook.url
= link_to 'Test Hook', admin_hook_test_path(hook), class: "btn small right"
= link_to 'Test Hook', admin_hook_test_path(hook), class: "btn btn-small pull-right"
%td POST
%td
= link_to 'Remove', admin_hook_path(hook), confirm: 'Are you sure?', method: :delete, class: "danger btn small right"
= link_to 'Remove', admin_hook_path(hook), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove btn-small pull-right"
......@@ -15,7 +15,7 @@
.file_title
%i.icon-file
githost.log
.right
.pull-right
= link_to '#', class: 'log-bottom' do
%i.icon-arrow-down
Scroll down
......@@ -29,7 +29,7 @@
.file_title
%i.icon-file
application.log
.right
.pull-right
= link_to '#', class: 'log-bottom' do
%i.icon-arrow-down
Scroll down
......@@ -43,7 +43,7 @@
.file_title
%i.icon-file
production.log
.right
.pull-right
= link_to '#', class: 'log-bottom' do
%i.icon-arrow-down
Scroll down
......@@ -57,7 +57,7 @@
.file_title
%i.icon-file
sidekiq.log
.right
.pull-right
= link_to '#', class: 'log-bottom' do
%i.icon-arrow-down
Scroll down
......
= form_for [:admin, project] do |f|
-if project.errors.any?
.alert-message.block-message.error
.alert.alert-error
%ul
- project.errors.full_messages.each do |msg|
%li= msg
......@@ -65,8 +65,8 @@
.actions
= f.submit 'Save Project', class: "btn save-btn"
= link_to 'Cancel', admin_projects_path, class: "btn cancel-btn"
= f.submit 'Save Project', class: "btn btn-save"
= link_to 'Cancel', admin_projects_path, class: "btn btn-cancel"
......
%h3.page_title
Projects
= link_to 'New Project', new_project_path, class: "btn small right"
= link_to 'New Project', new_project_path, class: "btn btn-small pull-right"
%hr
......@@ -37,7 +37,7 @@
.form-actions
= submit_tag "Search", class: "btn submit primary"
= submit_tag "Search", class: "btn submit btn-primary"
= link_to "Reset", admin_projects_path, class: "btn"
.span8
.ui-box
......@@ -51,9 +51,9 @@
- else
%i.icon-lock.cgreen
= link_to project.name_with_namespace, [:admin, project]
.right
= link_to 'Edit', edit_admin_project_path(project), id: "edit_#{dom_id(project)}", class: "btn small"
= link_to 'Destroy', [:admin, project], confirm: "REMOVE #{project.name}? Are you sure?", method: :delete, class: "btn small danger"
.pull-right
= link_to 'Edit', edit_admin_project_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small"
= link_to 'Destroy', [:admin, project], confirm: "REMOVE #{project.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove"
- if @projects.blank?
%p.nothing_here_message 0 projects matches
- else
......
= form_for @team_member_relation, as: :team_member, url: admin_project_member_path(@project, @member) do |f|
-if @team_member_relation.errors.any?
.alert-message.block-message.error
.alert.alert-error
%ul
- @team_member_relation.errors.full_messages.each do |msg|
%li= msg
......@@ -12,5 +12,5 @@
%br
.actions
= f.submit 'Save', class: "btn primary"
= f.submit 'Save', class: "btn btn-primary"
= link_to 'Cancel', :back, class: "btn"
%h3.page_title
Project: #{@project.name_with_namespace}
= link_to edit_admin_project_path(@project), class: "btn right" do
= link_to edit_admin_project_path(@project), class: "btn pull-right" do
%i.icon-edit
Edit
......@@ -129,8 +129,8 @@
%td
= link_to tm.name, admin_user_path(tm)
%td= @project.project_access_human(tm)
%td= link_to 'Edit Access', edit_admin_project_member_path(@project, tm), class: "btn small"
%td= link_to 'Remove from team', admin_project_member_path(@project, tm), confirm: 'Are you sure?', method: :delete, class: "btn danger small"
%td= link_to 'Edit Access', edit_admin_project_member_path(@project, tm), class: "btn btn-small"
%td= link_to 'Remove from team', admin_project_member_path(@project, tm), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove small"
%br
%h5 Add new team member
......@@ -147,7 +147,7 @@
%td= select_tag :project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3"}
%tr
%td= submit_tag 'Add', class: "btn primary"
%td= submit_tag 'Add', class: "btn btn-primary"
%td
Read more about project permissions
%strong= link_to "here", help_permissions_path, class: "vlink"
......@@ -2,7 +2,7 @@
%hr
= form_for @team, url: admin_team_path(@team), method: :put do |f|
- if @team.errors.any?
.alert-message.block-message.error
.alert.alert-error
%span= @team.errors.full_messages.first
.clearfix.team_name_holder
= f.label :name do
......@@ -19,5 +19,5 @@
%li It will change web url for access team and team projects.
.form-actions
= f.submit 'Rename team', class: "btn danger"
= link_to 'Cancel', admin_teams_path, class: "btn cancel-btn"
= f.submit 'Rename team', class: "btn btn-remove"
= link_to 'Cancel', admin_teams_path, class: "btn btn-cancel"
......@@ -3,12 +3,12 @@
%small
simple Teams description
= link_to 'New Team', new_admin_team_path, class: "btn small right"
= link_to 'New Team', new_admin_team_path, class: "btn btn-small pull-right"
%br
= form_tag admin_teams_path, method: :get, class: 'form-inline' do
= text_field_tag :name, params[:name], class: "xlarge"
= submit_tag "Search", class: "btn submit primary"
= submit_tag "Search", class: "btn submit btn-primary"
%table
%thead
......@@ -32,7 +32,7 @@
%td
= link_to team.owner.name, admin_user_path(team.owner_id)
%td.bgred
= link_to 'Rename', edit_admin_team_path(team), id: "edit_#{dom_id(team)}", class: "btn small"
= link_to 'Destroy', admin_team_path(team), confirm: "REMOVE #{team.name}? Are you sure?", method: :delete, class: "btn small danger"
= 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"
= paginate @teams, theme: "admin"
= form_tag admin_team_member_path(@team, @member), method: :put do
-if @member.errors.any?
.alert-message.block-message.error
.alert.alert-error
%ul
- @member.errors.full_messages.each do |msg|
%li= msg
......@@ -16,5 +16,5 @@
%br
.actions
= submit_tag 'Save', class: "btn primary"
= submit_tag 'Save', class: "btn btn-primary"
= link_to 'Cancel', :back, class: "btn"
......@@ -26,4 +26,4 @@
%td
%span= check_box_tag :group_admin
%span Admin?
%td= submit_tag 'Add', class: "btn primary", id: :add_members_to_team
%td= submit_tag 'Add', class: "btn btn-primary", id: :add_members_to_team
......@@ -2,7 +2,7 @@
%hr
= form_for @team, url: admin_teams_path do |f|
- if @team.errors.any?
.alert-message.block-message.error
.alert.alert-error
%span= @team.errors.full_messages.first
.clearfix
= f.label :name do
......@@ -10,7 +10,7 @@
.input
= f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
&nbsp;
= f.submit 'Create team', class: "btn primary"
= f.submit 'Create team', class: "btn btn-primary"
%hr
.padded
%ul
......
= form_tag admin_team_project_path(@team, @project), method: :put do
-if @project.errors.any?
.alert-message.block-message.error
.alert.alert-error
%ul
- @project.errors.full_messages.each do |msg|
%li= msg
......@@ -12,5 +12,5 @@
%br
.actions
= submit_tag 'Save', class: "btn primary"
= submit_tag 'Save', class: "btn btn-primary"
= link_to 'Cancel', :back, class: "btn"
......@@ -20,4 +20,4 @@
%tr
%td= select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name_with_namespace), multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5'
%td= select_tag :greatest_project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3" }
%td= submit_tag 'Add', class: "btn primary", id: :assign_projects_to_team
%td= submit_tag 'Add', class: "btn btn-primary", id: :assign_projects_to_team
......@@ -14,7 +14,7 @@
%td
= @team.name
&nbsp;
= link_to edit_admin_team_path(@team), class: "btn btn-small right" do
= link_to edit_admin_team_path(@team), class: "btn btn-small pull-right" do
%i.icon-edit
Rename
%tr
......@@ -23,7 +23,7 @@
Owner:
%td
= @team.owner.name
.right
.pull-right
= link_to "#", class: "btn btn-small change-owner-link" do
%i.icon-edit
Change owner
......@@ -36,13 +36,13 @@
= form_for @team, url: admin_team_path(@team) do |f|
= f.select :owner_id, User.all.map { |user| [user.name, user.id] }, {}, {class: 'chosen'}
%div
= f.submit 'Change Owner', class: "btn danger"
= f.submit 'Change Owner', class: "btn btn-remove"
= link_to "Cancel", "#", class: "btn change-owner-cancel-link"
%fieldset
%legend
Members (#{@team.members.count})
%span= link_to 'Add members', new_admin_team_member_path(@team), class: "btn success small right", id: :add_members_to_team
%span= link_to 'Add members', new_admin_team_member_path(@team), class: "btn btn-primary btn-small pull-right", id: :add_members_to_team
- if @team.members.any?
%table#members_list
%thead
......@@ -60,14 +60,14 @@
%td= @team.human_default_projects_access(member)
%td= @team.admin?(member) ? "Admin" : "Member"
%td.bgred
= link_to 'Edit', edit_admin_team_member_path(@team, member), class: "btn small"
= link_to 'Edit', edit_admin_team_member_path(@team, member), class: "btn btn-small"
&nbsp;
= link_to 'Remove', admin_team_member_path(@team, member), confirm: 'Remove member from team. Are you sure?', method: :delete, class: "btn danger small", id: "remove_member_#{member.id}"
= link_to 'Remove', admin_team_member_path(@team, member), confirm: 'Remove member from team. Are you sure?', method: :delete, class: "btn btn-remove btn-small", id: "remove_member_#{member.id}"
%fieldset
%legend
Projects (#{@team.projects.count})
%span= link_to 'Add projects', new_admin_team_project_path(@team), class: "btn success small right", id: :assign_projects_to_team
%span= link_to 'Add projects', new_admin_team_project_path(@team), class: "btn btn-primary btn-small pull-right", id: :assign_projects_to_team
- if @team.projects.any?
%table#projects_list
%thead
......@@ -82,9 +82,9 @@
%td
%span= @team.human_max_project_access(project)
%td.bgred
= link_to 'Edit', edit_admin_team_project_path(@team, project), class: "btn small"
= link_to 'Edit', edit_admin_team_project_path(@team, project), class: "btn btn-small"
&nbsp;
= link_to 'Relegate', admin_team_project_path(@team, project), confirm: 'Remove project from team. Are you sure?', method: :delete, class: "btn danger small", id: "relegate_project_#{project.id}"
= link_to 'Relegate', admin_team_project_path(@team, project), confirm: 'Remove project from team. Are you sure?', method: :delete, class: "btn btn-remove small", id: "relegate_project_#{project.id}"
:javascript
$(function(){
......
......@@ -63,10 +63,10 @@
.alert.alert-error
- if @admin_user.blocked
%p This user is blocked and is not able to login to GitLab
= link_to 'Unblock User', unblock_admin_user_path(@admin_user), method: :put, class: "btn small"
= link_to 'Unblock User', unblock_admin_user_path(@admin_user), method: :put, class: "btn btn-small"
- else
%p Blocked users will be removed from all projects &amp; will not be able to login to GitLab.
= link_to 'Block User', block_admin_user_path(@admin_user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn small danger"
= link_to 'Block User', block_admin_user_path(@admin_user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn btn-small btn-remove"
%fieldset
%legend Profile
.clearfix
......@@ -80,8 +80,8 @@
.input= f.text_field :twitter
.actions
= f.submit 'Save', class: "btn save-btn"
= f.submit 'Save', class: "btn btn-save"
- if @admin_user.new_record?
= link_to 'Cancel', admin_users_path, class: "btn cancel-btn"
= link_to 'Cancel', admin_users_path, class: "btn btn-cancel"
- else
= link_to 'Cancel', admin_user_path(@admin_user), class: "btn cancel-btn"
= link_to 'Cancel', admin_user_path(@admin_user), class: "btn btn-cancel"
%h3.page_title
Users
= link_to 'New User', new_admin_user_path, class: "btn small right"
= link_to 'New User', new_admin_user_path, class: "btn btn-small pull-right"
%br
= form_tag admin_users_path, method: :get, class: 'form-inline' do
= text_field_tag :name, params[:name], class: "xlarge"
= submit_tag "Search", class: "btn submit primary"
= submit_tag "Search", class: "btn submit btn-primary"
%ul.nav.nav-tabs
%li{class: "#{'active' unless params[:filter]}"}
= link_to admin_users_path do
......@@ -44,15 +44,15 @@
%td= user.username
%td= user.email
%td= user.users_projects.count
%td= link_to 'Edit', edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: "btn small"
%td= link_to 'Edit', edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: "btn btn-small"
%td.bgred
- if user == current_user
%span.cred It's you!
- else
- if user.blocked
= link_to 'Unblock', unblock_admin_user_path(user), method: :put, class: "btn small success"
= link_to 'Unblock', unblock_admin_user_path(user), method: :put, class: "btn btn-small success"
- else
= link_to 'Block', block_admin_user_path(user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn small danger"
= link_to 'Destroy', [:admin, user], confirm: "USER #{user.name} WILL BE REMOVED! Are you sure?", method: :delete, class: "btn small danger"
= link_to 'Block', block_admin_user_path(user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn btn-small btn-remove"
= link_to 'Destroy', [:admin, user], confirm: "USER #{user.name} WILL BE REMOVED! Are you sure?", method: :delete, class: "btn btn-small btn-remove"
= paginate @admin_users, theme: "admin"
......@@ -4,7 +4,7 @@
%small Blocked
- if @admin_user.admin
%small Administrator
= link_to edit_admin_user_path(@admin_user), class: "btn right" do
= link_to edit_admin_user_path(@admin_user), class: "btn pull-right" do
%i.icon-edit
Edit
......@@ -86,7 +86,7 @@
%td= select_tag :project_access, options_for_select(Project.access_options), class: "project-access-select chosen span3"
%tr
%td= submit_tag 'Add', class: "btn primary"
%td= submit_tag 'Add', class: "btn btn-primary"
%td
Read more about project permissions
%strong= link_to "here", help_permissions_path, class: "vlink"
......@@ -123,5 +123,5 @@
%tr
%td= link_to project.name_with_namespace, admin_project_path(project)
%td= tm.project_access_human
%td= link_to 'Edit Access', edit_admin_project_member_path(project, tm.user), class: "btn small"
%td= link_to 'Remove from team', admin_project_member_path(project, tm.user), confirm: 'Are you sure?', method: :delete, class: "btn small danger"
%td= link_to 'Edit Access', edit_admin_project_member_path(project, tm.user), class: "btn btn-small"
%td= link_to 'Remove from team', admin_project_member_path(project, tm.user), confirm: 'Are you sure?', method: :delete, class: "btn btn-small btn-remove"
......@@ -3,5 +3,5 @@
= render partial: 'shared/ref_switcher', locals: {destination: 'tree', path: params[:path]}
= nav_link(controller: :refs) do
= link_to 'Source', project_tree_path(@project, @ref)
%li.right
%li.pull-right
= render "shared/clone_panel"
= render "commits/commit_box"
.alert-message.block-message.error
.alert.alert-error
%h4 Commit diffs are too big to be displayed
= render "commits/commit_box"
%p.right.cgray
%p.pull-right.cgray
This commit has
%span.cgreen #{@commit.stats.additions} additions
and
......
.ui-box.ui-box-show
.ui-box-head
.right
.pull-right
- if @notes_count > 0
%span.btn.disabled.grouped
%i.icon-comment
......@@ -13,7 +13,7 @@
%ul.dropdown-menu
%li= link_to "Email Patches", project_commit_path(@project, @commit, format: :patch)
%li= link_to "Plain Diff", project_commit_path(@project, @commit, format: :diff)
= link_to project_tree_path(@project, @commit), class: "btn primary grouped" do
= link_to project_tree_path(@project, @commit), class: "btn btn-primary grouped" do
%span Browse Code »
%h3.commit-title.page_title
= gfm escape_once(@commit.title)
......
- if @suppress_diff
.alert-message.block-message
.alert.alert-block
%p
%strong Warning! Large commit with more then #{Commit::DIFF_SAFE_SIZE} files changed.
%strong Warning! Large commit with more than #{Commit::DIFF_SAFE_SIZE} files changed.
%p To prevent performance issue we rejected diff information.
%p
But if you still want to see diff
......@@ -25,7 +25,7 @@
%span= diff.old_path
- if @commit.prev_commit
= link_to project_tree_path(@project, tree_join(@commit.prev_commit_id, diff.new_path)), {:class => 'btn right view-file'} do
= link_to project_tree_path(@project, tree_join(@commit.prev_commit_id, diff.new_path)), {:class => 'btn pull-right view-file'} do
View file @
%span.commit-short-id= @commit.short_id(6)
- else
......@@ -33,7 +33,7 @@
- if diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode
%span.file-mode= "#{diff.a_mode}#{diff.b_mode}"
= link_to project_tree_path(@project, tree_join(@commit.id, diff.new_path)), {:class => 'btn very_small right view-file'} do
= link_to project_tree_path(@project, tree_join(@commit.id, diff.new_path)), {:class => 'btn btn-tiny pull-right view-file'} do
View file @
%span.commit-short-id= @commit.short_id(6)
......
......@@ -22,7 +22,7 @@
- if current_controller?(:commits) && current_user.private_token
%li.right
%li.pull-right
%span.rss-icon
= link_to project_commits_path(@project, @ref, {format: :atom, private_token: current_user.private_token}), title: "Feed" do
= image_tag "rss_ui.png", title: "feed"
......@@ -19,7 +19,7 @@
= text_field_tag :to, params[:to], placeholder: "aa8b4ef", class: "xlarge"
.pull-left
&nbsp;
= submit_tag "Compare", class: "btn primary wide commits-compare-btn"
= submit_tag "Compare", class: "btn btn-primary wide commits-compare-btn"
- if @refs_are_same
.alert
%span Refs are the same
......
......@@ -25,9 +25,9 @@
%li{class: ("active" if params[:project_id] == project.id.to_s)}
= link_to dashboard_filter_path(entity, project_id: project.id) do
= project.name_with_namespace
%small.right= entities_per_project(project, entity)
%small.pull-right= entities_per_project(project, entity)
%fieldset
%hr
= link_to "Reset", dashboard_filter_path(entity), class: 'btn right'
= link_to "Reset", dashboard_filter_path(entity), class: 'btn pull-right'
......@@ -4,8 +4,8 @@
%small
(#{groups.count})
- if current_user.can_create_group?
%span.right
= link_to new_group_path, class: "btn very_small info" do
%span.pull-right
= link_to new_group_path, class: "btn btn-tiny info" do
%i.icon-plus
New Group
%ul.well-list
......@@ -13,6 +13,6 @@
%li
= link_to group_path(id: group.path), class: dom_class(group) do
%strong.well-title= truncate(group.name, length: 35)
%span.right.light
%span.pull-right.light
- if group.owner == current_user
%i.icon-wrench
......@@ -4,8 +4,8 @@
%small
(#{@projects_count})
- if current_user.can_create_project?
%span.right
= link_to new_project_path, class: "btn very_small info" do
%span.pull-right
= link_to new_project_path, class: "btn btn-tiny info" do
%i.icon-plus
New Project
......
......@@ -3,8 +3,8 @@
Teams
%small
(#{@teams.count})
%span.right
= link_to new_team_path, class: "btn very_small info" do
%span.pull-right
= link_to new_team_path, class: "btn btn-tiny info" do
%i.icon-plus
New Team
%ul.well-list
......@@ -12,7 +12,7 @@
%li
= link_to team_path(id: team.path), class: dom_class(team) do
%strong.well-title= truncate(team.name, length: 35)
%span.right.light
%span.pull-right.light
- if team.owner == current_user
%i.icon-wrench
- tm = current_user.user_team_user_relationships.find_by_user_team_id(team.id)
......
......@@ -6,7 +6,7 @@
= current_user.projects_limit
projects. Click on button below to add a new one
.link_holder
= link_to new_project_path, class: "btn primary" do
= link_to new_project_path, class: "btn btn-primary" do
New Project »
- else
If you will be added to project - it will be displayed here
%h3.page_title
Issues
%small (assigned to you)
%small.right #{@issues.total_count} issues
%small.pull-right #{@issues.total_count} issues
%hr
......
%h3.page_title
Merge Requests
%small (authored by or assigned to you)
%small.right #{@merge_requests.total_count} merge requests
%small.pull-right #{@merge_requests.total_count} merge requests
%hr
.row
......
......@@ -3,8 +3,8 @@
%span
(#{@projects.total_count})
- if current_user.can_create_project?
%span.right
= link_to new_project_path, class: "btn very_small info" do
%span.pull-right
= link_to new_project_path, class: "btn btn-tiny info" do
%i.icon-plus
New Project
......@@ -42,7 +42,7 @@
%small.light
%strong Last activity:
%span= project_last_activity(project)
.right.light
.pull-right.light
- if project.owner == current_user
%i.icon-wrench
- tm = project.team.get_tm(current_user.id)
......
%div
= form_for [@project, @key], url: project_deploy_keys_path do |f|
-if @key.errors.any?
.alert-message.block-message.error
.alert.alert-error
%ul
- @key.errors.full_messages.each do |msg|
%li= msg
......@@ -18,6 +18,6 @@
= link_to "here", help_ssh_path
.actions
= f.submit 'Save', class: "save-btn btn"
= link_to "Cancel", project_deploy_keys_path(@project), class: "btn cancel-btn"
= f.submit 'Save', class: "btn-save btn"
= link_to "Cancel", project_deploy_keys_path(@project), class: "btn btn-cancel"
......@@ -8,5 +8,5 @@
= time_ago_in_words(key.created_at)
ago
%td
= link_to 'Remove', project_deploy_key_path(key.project, key), confirm: 'Are you sure?', method: :delete, class: "danger btn delete-key small right"
= link_to 'Remove', project_deploy_key_path(key.project, key), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove delete-key btn-small pull-right"
......@@ -4,7 +4,7 @@
Deploy keys allow read-only access to repository. It matches perfectly for CI, staging or production servers.
- if can? current_user, :admin_project, @project
= link_to new_project_deploy_key_path(@project), class: "btn small", title: "New Deploy Key" do
= link_to new_project_deploy_key_path(@project), class: "btn btn-small", title: "New Deploy Key" do
Add Deploy Key
- if @keys.any?
%table
......
......@@ -10,5 +10,5 @@
&larr; To keys list
%hr
%pre= @key.key
.right
= link_to 'Remove', project_deploy_key_path(@key.project, @key), confirm: 'Are you sure?', method: :delete, class: "danger btn delete-key"
.pull-right
= link_to 'Remove', project_deploy_key_path(@key.project, @key), confirm: 'Are you sure?', method: :delete, class: "btn-remove btn delete-key"
......@@ -8,5 +8,5 @@
%div
= f.password_field :password_confirmation, class: "text bottom", placeholder: "Confirm new password"
%div
= f.submit "Change my password", class: "btn primary"
.right= render partial: "devise/shared/links"
= f.submit "Change my password", class: "btn btn-primary"
.pull-right= render partial: "devise/shared/links"
<%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :class => "login-box", :method => :post }) do |f| %>
<%= image_tag "login-logo.png", :width => "304", :height => "66", :class => "login-logo", :alt => "Login Logo" %>
<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { class: "login-box", method: :post }) do |f| %>
<%= image_tag "login-logo.png", width: "304", height: "66", class: "login-logo", alt: "Login Logo" %>
<%= devise_error_messages! %>
<%= f.email_field :email, :placeholder => "Email", :class => "text" %>
<%= f.email_field :email, placeholder: "Email", class: "text" %>
<br/>
<br/>
<%= f.submit "Reset password", :class => "primary btn" %>
<div class="right"> <%= link_to "Sign in", new_session_path(resource_name), :class => "btn" %><br /></div>
<%= f.submit "Reset password", class: "btn-primary btn" %>
<div class="pull-right"> <%= link_to "Sign in", new_session_path(resource_name), class: "btn" %><br /></div>
<% end %>
= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :class => "login-box" }) do |f|
= image_tag "login-logo.png", :width => "304", :height => "66", :class => "login-logo", :alt => "Login Logo"
= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { class: "login-box" }) do |f|
= image_tag "login-logo.png", width: "304", height: "66", class: "login-logo", alt: "Login Logo"
= devise_error_messages!
%div
= f.text_field :name, :class => "text top", :placeholder => "Name", :required => true
= f.text_field :name, class: "text top", placeholder: "Name", required: true
%div
= f.text_field :username, :class => "text middle", :placeholder => "Username", :required => true
= f.text_field :username, class: "text middle", placeholder: "Username", required: true
%div
= f.email_field :email, :class => "text middle", :placeholder => "Email", :required => true
= f.email_field :email, class: "text middle", placeholder: "Email", required: true
%div
= f.password_field :password, :class => "text middle", :placeholder => "Password", :required => true
= f.password_field :password, class: "text middle", placeholder: "Password", required: true
%div
= f.password_field :password_confirmation, :class => "text bottom", :placeholder => "Confirm password", :required => true
= f.password_field :password_confirmation, class: "text bottom", placeholder: "Confirm password", required: true
%div
= f.submit "Sign up", :class => "primary btn wide"
%br
= f.submit "Sign up", class: "btn-create btn"
%hr
= link_to "Sign in", new_session_path(resource_name)
= link_to "Forgot your password?", new_password_path(resource_name), :class => "right"
= link_to "Forgot your password?", new_password_path(resource_name), class: "pull-right"
......@@ -3,11 +3,11 @@
= text_field_tag :username, nil, {:class => "text top", :placeholder => "LDAP Login"}
= password_field_tag :password, nil, {:class => "text bottom", :placeholder => "Password"}
%br/
= submit_tag "LDAP Sign in", :class => "primary btn"
= submit_tag "LDAP Sign in", :class => "btn-primary btn"
- if devise_mapping.omniauthable?
- (resource_class.omniauth_providers - [:ldap]).each do |provider|
%hr/
= link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider), :class => "btn primary"
= link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider), :class => "btn btn-primary"
%br/
%hr/
%a#other_form_toggle{:href => "#", :onclick => "javascript:$('#new_user').toggle();"} Other Sign in
......@@ -24,6 +24,6 @@
= f.check_box :remember_me
%span Remember me
%br/
= f.submit "Sign in", :class => "primary btn"
.right
= f.submit "Sign in", :class => "btn-primary btn"
.pull-right
= render :partial => "devise/shared/links"
......@@ -11,18 +11,18 @@
= f.check_box :remember_me
%span Remember me
%br/
= f.submit "Sign in", :class => "primary btn wide"
.right
= f.submit "Sign in", :class => "btn-create btn"
.pull-right
= link_to "Forgot your password?", new_password_path(resource_name), :class => "btn"
%br/
%br/
- if Gitlab.config.gitlab.signup_enabled
%hr/
Don't have an account?
= link_to "Sign up", new_registration_path(resource_name)
.clearfix
- if devise_mapping.omniauthable? && resource_class.omniauth_providers.present?
%hr
%div
%span Sign in with: &nbsp;
- resource_class.omniauth_providers.each do |provider|
%span
= link_to authbutton(provider, 32), omniauth_authorize_path(resource_name, provider)
- if event.proper?
%div.event-item
%span.cgray.right
%span.cgray.pull-right
#{time_ago_in_words(event.created_at)} ago.
= image_tag gravatar_icon(event.author_email), class: "avatar s24"
......
%h3.page_title Project Network Graph
%br
= render partial: 'shared/ref_switcher', locals: {destination: 'graph', path: @path}
%br
.graph_holder
%h4
%small You can move around the graph by using the arrow keys.
......@@ -11,7 +12,8 @@
var branch_graph;
$(function(){
branch_graph = new BranchGraph($("#holder"), {
url: '#{url_for controller: 'projects', action: 'graph', format: :json}',
commit_url: '#{project_commit_path(@project, 'ae45ca32').gsub("ae45ca32", "%s")}'
url: '#{project_graph_path(@project, @ref, format: :json)}',
commit_url: '#{project_commit_path(@project, 'ae45ca32').gsub("ae45ca32", "%s")}',
ref: '#{@ref}'
});
});
......@@ -25,9 +25,9 @@
%li{class: ("active" if params[:project_id] == project.id.to_s)}
= link_to group_filter_path(entity, project_id: project.id) do
= project.name_with_namespace
%small.right= entities_per_project(project, entity)
%small.pull-right= entities_per_project(project, entity)
%fieldset
%hr
= link_to "Reset", group_filter_path(entity), class: 'btn right'
= link_to "Reset", group_filter_path(entity), class: 'btn pull-right'
......@@ -14,5 +14,5 @@
.form-actions
= hidden_field_tag :redirect_to, people_group_path(@group)
= f.submit 'Add', class: "btn save-btn"
= f.submit 'Add', class: "btn btn-save"
......@@ -14,5 +14,5 @@
.form-actions
= hidden_field_tag :redirect_to, people_group_path(@group, project_id: @project.id)
= f.submit 'Add', class: "btn save-btn"
= f.submit 'Add', class: "btn btn-save"
......@@ -6,9 +6,9 @@
%li{class: ("active" if params[:project_id] == project.id.to_s)}
= link_to people_group_path(@group, project_id: project.id) do
= project.name_with_namespace
%small.right= project.users.count
%small.pull-right= project.users.count
%fieldset
%hr
= link_to "Reset", people_group_path(@group), class: 'btn right'
= link_to "Reset", people_group_path(@group), class: 'btn pull-right'
......@@ -4,8 +4,8 @@
%small
(#{projects.count})
- if can? current_user, :manage_group, @group
%span.right
= link_to new_project_path(namespace_id: @group.id), class: "btn very_small info" do
%span.pull-right
= link_to new_project_path(namespace_id: @group.id), class: "btn btn-tiny info" do
%i.icon-plus
New Project
%ul.well-list
......
%h3.page_title Edit Group
%hr
= form_for @group do |f|
- if @group.errors.any?
.alert.alert-error
%span= @group.errors.full_messages.first
.clearfix
= f.label :name do
Group name is
.input
= f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
&nbsp;
= f.submit 'Save group', class: "btn btn-save"
%hr
.row
.span7
.ui-box
%h5.title Projects
%ul.well-list
- @group.projects.each do |project|
%li
- if project.public
%i.icon-share
- else
%i.icon-lock.cgreen
= link_to project.name_with_namespace, project
.pull-right
= link_to 'Team', project_team_index_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small"
= link_to '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"
.span5
.ui-box
%h5.title Transfer group
.padded
%p
Transferring group will cause loss of admin control over group and all child projects
= form_for @group do |f|
= f.select :owner_id, User.all.map { |user| [user.name, user.id] }, {}, {class: 'chosen'}
= f.submit 'Transfer group', class: "btn btn-small"
.ui-box
%h5.title Remove group
.padded.bgred
%p
Remove of group will cause removing all child projects and resources
%br
Removed group can not be restored!
= link_to 'Remove Group', @group, confirm: 'Removed group can not be restored! Are you sure?', method: :delete, class: "btn btn-remove btn-small"
%h3.page_title
Issues
%small (assigned to you)
%small.right #{@issues.total_count} issues
%small.pull-right #{@issues.total_count} issues
%hr
.row
......
%h3.page_title
Merge Requests
%small (authored by or assigned to you)
%small.right #{@merge_requests.total_count} merge requests
%small.pull-right #{@merge_requests.total_count} merge requests
%hr
.row
......
......@@ -2,7 +2,7 @@
%hr
= form_for @group do |f|
- if @group.errors.any?
.alert-message.block-message.error
.alert.alert-error
%span= @group.errors.full_messages.first
.clearfix
= f.label :name do
......@@ -10,7 +10,7 @@
.input
= f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
&nbsp;
= f.submit 'Create group', class: "btn primary"
= f.submit 'Create group', class: "btn btn-create"
%hr
.padded
%ul
......
......@@ -16,5 +16,5 @@
%strong= user.name
%span.cgray= user.email
- if @group.owner == user
%span.btn.btn-small.disabled.right Group Owner
%span.btn.btn-small.disabled.pull-right Group Owner
......@@ -4,6 +4,6 @@
%strong Looking for
.input
= search_field_tag :search, params[:search], placeholder: "issue 143", class: "input-xxlarge search-text-input", id: "dashboard_search"
= submit_tag 'Search', class: "btn primary wide"
= submit_tag 'Search', class: "btn btn-primary wide"
- if params[:search].present?
= render 'search/result'
.projects
.activities.span8
= render "events/event_last_push", event: @last_push
= link_to dashboard_path, class: 'btn very_small' do
= link_to dashboard_path, class: 'btn btn-tiny' do
&larr; To dashboard
&nbsp;
%span.cgray You will only see events from projects in this group
......
......@@ -30,5 +30,5 @@
%li
%strong= link_to "Public Access", help_public_access_path
.span9.right
.span9.pull-right
= yield
%h3.page_title
GITLAB
.right
.pull-right
%span= Gitlab::Version
%small= Gitlab::Revision
%hr
......
......@@ -10,7 +10,7 @@
= form_for [@project, @hook], as: :hook, url: project_hooks_path(@project), html: { class: 'form-inline' } do |f|
-if @hook.errors.any?
.alert-message.block-message.error
.alert.alert-error
- @hook.errors.full_messages.each do |msg|
%p= msg
.clearfix
......@@ -18,7 +18,7 @@
.input
= f.text_field :url, class: "text_field xxlarge"
&nbsp;
= f.submit "Add Web Hook", class: "btn primary"
= f.submit "Add Web Hook", class: "btn btn-primary"
%hr
-if @hooks.any?
......@@ -37,6 +37,6 @@
&rarr;
%span.monospace= hook.url
%td
.right
= link_to 'Test Hook', test_project_hook_path(@project, hook), class: "btn small grouped"
= link_to 'Remove', project_hook_path(@project, hook), confirm: 'Are you sure?', method: :delete, class: "danger btn small grouped"
.pull-right
= link_to 'Test Hook', test_project_hook_path(@project, hook), class: "btn btn-small grouped"
= link_to 'Remove', project_hook_path(@project, hook), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove btn-small grouped"
......@@ -16,5 +16,5 @@
%fieldset
%hr
= link_to "Reset", project_issues_path(@project), class: 'btn right'
= link_to "Reset", project_issues_path(@project), class: 'btn pull-right'
......@@ -2,7 +2,7 @@
%h3.page_title= @issue.new_record? ? "New Issue" : "Edit Issue ##{@issue.id}"
= form_for [@project, @issue] do |f|
-if @issue.errors.any?
.alert-message.block-message.error
.alert.alert-error
- @issue.errors.full_messages.each do |msg|
%span= msg
%br
......@@ -44,12 +44,12 @@
.actions
- if @issue.new_record?
= f.submit 'Submit new issue', class: "btn success"
= f.submit 'Submit new issue', class: "btn btn-create"
-else
= f.submit 'Save changes', class: "save-btn btn"
= f.submit 'Save changes', class: "btn-save btn"
- cancel_path = @issue.new_record? ? project_issues_path(@project) : project_issue_path(@project, @issue)
= link_to "Cancel", cancel_path, class: 'btn cancel-btn'
= link_to "Cancel", cancel_path, class: 'btn btn-cancel'
......
......@@ -5,7 +5,7 @@
= link_to 'Milestones', project_milestones_path(@project), class: "tab"
= nav_link(controller: :labels) do
= link_to 'Labels', project_labels_path(@project), class: "tab"
%li.right
%li.pull-right
%span.rss-icon
= link_to project_issues_path(@project, :atom, { private_token: current_user.private_token }) do
= image_tag "rss_ui.png", title: "feed"
......@@ -4,7 +4,7 @@
- if @issues.present?
%li.bottom
.left= paginate @issues, remote: true, theme: "gitlab"
.right
.pull-right
%span.issue_counter #{@issues.total_count}
issues for this filter
- else
......
......@@ -2,17 +2,17 @@
- if controller.controller_name == 'issues'
.issue_check
= check_box_tag dom_id(issue,"selected"), nil, false, 'data-id' => issue.id, class: "selected_issue", disabled: !can?(current_user, :modify_issue, issue)
.right
.pull-right
- if issue.notes.any?
%span.btn.small.disabled.grouped
%span.btn.btn-small.disabled.grouped
%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 small grouped reopen_issue", remote: true
= 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
- else
= link_to 'Close', project_issue_path(issue.project, issue, issue: {closed: true }, status_only: true), method: :put, class: "btn small grouped close_issue", remote: true
= link_to edit_project_issue_path(issue.project, issue), class: "btn small edit-issue-link grouped" do
= 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 edit_project_issue_path(issue.project, issue), class: "btn btn-small edit-issue-link grouped" do
%i.icon-edit
Edit
......
......@@ -3,16 +3,16 @@
%h3.page_title
Issues
%span (<span class=issue_counter>#{@issues.total_count}</span>)
.right
.pull-right
.span5
- if can? current_user, :write_issue, @project
= link_to new_project_issue_path(@project, issue: { assignee_id: params[:assignee_id], milestone_id: params[:milestone_id]}), class: "right btn primary", title: "New Issue", id: "new_issue_link" do
= link_to new_project_issue_path(@project, issue: { assignee_id: params[:assignee_id], milestone_id: params[:milestone_id]}), class: "btn btn-primary pull-right", title: "New Issue", id: "new_issue_link" do
%i.icon-plus
New Issue
= form_tag search_project_issues_path(@project), method: :get, remote: true, id: "issue_search_form", class: :right do
= form_tag search_project_issues_path(@project), method: :get, remote: true, id: "issue_search_form", class: 'pull-right' do
= hidden_field_tag :project_id, @project.id, { id: 'project_id' }
= hidden_field_tag :status, params[:status]
= search_field_tag :issue_search, nil, { placeholder: 'Search', class: 'issue_search span3 right neib search-text-input' }
= search_field_tag :issue_search, nil, { placeholder: 'Search', class: 'issue_search span3 pull-right neib search-text-input' }
.clearfix
......@@ -33,7 +33,7 @@
= select_tag('update[milestone_id]', options_from_collection_for_select(issues_active_milestones, "id", "title", params[:milestone_id]), prompt: "Milestone")
= hidden_field_tag 'update[issues_ids]', []
= hidden_field_tag :status, params[:status]
= button_tag "Save", class: "btn update_selected_issues btn-small save-btn"
= button_tag "Save", class: "btn update_selected_issues btn-small btn-save"
.issues_filters
= form_tag project_issues_path(@project), method: :get do
= select_tag(:label_name, options_for_select(issue_tags, params[:label_name]), prompt: "Labels")
......
......@@ -5,7 +5,7 @@
created at
= @issue.created_at.stamp("Aug 21, 2011")
%span.right
%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"
......@@ -16,7 +16,7 @@
%i.icon-edit
Edit
.right
.pull-right
.span3#votes= render 'votes/votes_block', votable: @issue
.back_link
......@@ -42,7 +42,7 @@
%cite.cgray and attached to milestone
%strong= link_to_gfm truncate(milestone.title, length: 20), project_milestone_path(milestone.project, milestone)
.right
.pull-right
- @issue.labels.each do |label|
%span.label
%i.icon-tag
......
%div
= form_for @key do |f|
-if @key.errors.any?
.alert-message.block-message.error
.alert.alert-error
%ul
- @key.errors.full_messages.each do |msg|
%li= msg
......@@ -19,6 +19,6 @@
.actions
= f.submit 'Save', class: "btn save-btn"
= link_to "Cancel", keys_path, class: "btn cancel-btn"
= f.submit 'Save', class: "btn btn-save"
= link_to "Cancel", keys_path, class: "btn btn-cancel"
......@@ -8,5 +8,5 @@
= time_ago_in_words(key.created_at)
ago
%td
= link_to 'Remove', key, confirm: 'Are you sure?', method: :delete, class: "btn small danger delete-key right"
= link_to 'Remove', key, confirm: 'Are you sure?', method: :delete, class: "btn btn-small btn-remove delete-key pull-right"
%h3.page_title
SSH Keys
= link_to "Add new", new_key_path, class: "btn right"
= link_to "Add new", new_key_path, class: "btn pull-right"
%hr
%p.slead
......
......@@ -10,5 +10,5 @@
%hr
%pre= @key.key
.right
= link_to 'Remove', @key, confirm: 'Are you sure?', method: :delete, class: "btn danger delete-key"
.pull-right
= link_to 'Remove', @key, confirm: 'Are you sure?', method: :delete, class: "btn btn-remove delete-key"
......@@ -2,7 +2,7 @@
%strong
%i.icon-tag
= label.name
.right
.pull-right
= link_to project_issues_path(label_name: label.name) do
%strong
= pluralize(label.count, 'issue')
......
......@@ -7,7 +7,8 @@
.container
%ul.main_menu
= nav_link(controller: :dashboard, html_options: {class: 'home'}) do
= link_to "Stats", admin_root_path
= link_to admin_root_path, title: "Stats" do
%i.icon-home
= nav_link(controller: :projects) do
= link_to "Projects", admin_projects_path
= nav_link(controller: :teams) do
......
......@@ -7,7 +7,8 @@
.container
%ul.main_menu
= nav_link(path: 'dashboard#show', html_options: {class: 'home'}) do
= link_to "Home", root_path, title: "Home"
= link_to root_path, title: "Home" do
%i.icon-home
= nav_link(path: 'dashboard#projects') do
= link_to projects_dashboard_path do
Projects
......
......@@ -7,7 +7,8 @@
.container
%ul.main_menu
= nav_link(path: 'groups#show', html_options: {class: 'home'}) do
= link_to "Home", group_path(@group), title: "Home"
= link_to group_path(@group), title: "Home" do
%i.icon-home
= nav_link(path: 'groups#issues') do
= link_to issues_group_path(@group) do
Issues
......@@ -21,4 +22,10 @@
= nav_link(path: 'groups#people') do
= link_to "People", people_group_path(@group)
- if can?(current_user, :manage_group, @group)
= nav_link(path: 'groups#edit') do
= link_to edit_group_path(@group), class: "tab " do
%i.icon-edit
Edit Group
.content= yield
......@@ -7,7 +7,8 @@
.container
%ul.main_menu
= nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
= link_to "Profile", profile_path
= link_to profile_path, title: "Profile" do
%i.icon-home
= nav_link(path: 'profiles#account') do
= link_to "Account", account_profile_path
= nav_link(controller: :keys) do
......
......@@ -12,7 +12,8 @@
.container
%ul.main_menu
= nav_link(html_options: {class: "home #{project_tab_class}"}) do
= link_to @project.path, project_path(@project), title: "Project"
= link_to project_path(@project), title: "Project" do
%i.icon-home
- if @project.repo_exists?
- if can? current_user, :download_code, @project
......@@ -20,8 +21,8 @@
= link_to 'Files', project_tree_path(@project, @ref || @repository.root_ref)
= nav_link(controller: %w(commit commits compare repositories protected_branches)) do
= link_to "Commits", project_commits_path(@project, @ref || @repository.root_ref)
= nav_link(path: 'projects#graph') do
= link_to "Network", graph_project_path(@project)
= nav_link(controller: %w(graph)) do
= link_to "Network", project_graph_path(@project, @ref || @repository.root_ref)
- if @project.issues_enabled
= nav_link(controller: %w(issues milestones labels)) do
......
......@@ -7,7 +7,8 @@
.container
%ul.main_menu
= nav_link(path: 'teams#show', html_options: {class: 'home'}) do
= link_to "Home", team_path(@team), title: "Home"
= link_to team_path(@team), title: "Home" do
%i.icon-home
= nav_link(path: 'teams#issues') do
= link_to issues_team_path(@team) do
......
......@@ -16,5 +16,5 @@
%fieldset
%hr
= link_to "Reset", project_merge_requests_path(@project), class: 'btn right'
= link_to "Reset", project_merge_requests_path(@project), class: 'btn pull-right'
= form_for [@project, @merge_request], html: { class: "#{controller.action_name}-merge-request form-horizontal" } do |f|
-if @merge_request.errors.any?
.alert-message.block-message.error
.alert.alert-error
%ul
- @merge_request.errors.full_messages.each do |msg|
%li= msg
......@@ -51,19 +51,19 @@
.form-actions
- if @merge_request.new_record?
= f.submit 'Submit merge request', class: "btn success"
= f.submit 'Submit merge request', class: "btn btn-create"
-else
= f.submit 'Save changes', class: "save-btn btn"
= f.submit 'Save changes', class: "btn btn-save"
- if @merge_request.new_record?
= link_to project_merge_requests_path(@project), class: "btn cancel-btn" do
= link_to project_merge_requests_path(@project), class: "btn btn-cancel" do
Cancel
- else
= link_to project_merge_request_path(@project, @merge_request), class: "btn cancel-btn" do
= link_to project_merge_request_path(@project, @merge_request), class: "btn btn-cancel" do
Cancel
:javascript
$(function(){
disableButtonIfEmptyField("#merge_request_title", ".save-btn");
disableButtonIfEmptyField("#merge_request_title", ".btn-save");
var source_branch = $("#merge_request_source_branch")
, target_branch = $("#merge_request_target_branch");
......
%li{ class: mr_css_classes(merge_request) }
.right
.pull-right
.left
- if merge_request.merged?
%span.btn.small.disabled.grouped
%span.btn.btn-small.disabled.grouped
%strong
%i.icon-ok
= "MERGED"
- if merge_request.notes.any?
%span.btn.small.disabled.grouped
%span.btn.btn-small.disabled.grouped
%i.icon-comment
= merge_request.mr_and_commit_notes.count
- if merge_request.milestone_id?
%span.btn.small.disabled.grouped
%span.btn.btn-small.disabled.grouped
%i.icon-time
= merge_request.milestone.title
%span.btn.small.disabled.grouped
%span.btn.btn-small.disabled.grouped
= merge_request.source_branch
&rarr;
= merge_request.target_branch
......
- if can? current_user, :write_merge_request, @project
= link_to new_project_merge_request_path(@project), class: "right btn primary", title: "New Merge Request" do
= link_to new_project_merge_request_path(@project), class: "pull-right btn btn-primary", title: "New Merge Request" do
%i.icon-plus
New Merge Request
%h3.page_title
......@@ -28,8 +28,8 @@
- if @merge_requests.present?
%li.bottom
.left= paginate @merge_requests, theme: "gitlab"
.right
%span.cgray.right #{@merge_requests.total_count} merge requests for this filter
.pull-right
%span.cgray.pull-right #{@merge_requests.total_count} merge requests for this filter
:javascript
$(merge_requestsPage);
- unless can?(current_user, :accept_mr, @project)
.alert-message
.alert
%strong Only masters can accept MR
......@@ -29,14 +29,14 @@
%strong This repository does not have satellite. Ask administrator to fix this issue
.automerge_widget.cannot_be_merged{style: "display:none"}
.alert.alert-info
.alert.alert-disabled
%span
= link_to "Show how to merge", "#", class: "how_to_merge_link btn small padded", title: "How To Merge"
= link_to "Show how to merge", "#", class: "how_to_merge_link btn btn-small padded", title: "How To Merge"
&nbsp;
%strong This request can't be merged with GitLab. You should do it manually
.automerge_widget.unchecked
.alert-message
.alert
%strong
%i.icon-refresh
Checking for ability to automatically merge…
......
......@@ -23,7 +23,7 @@
= link_to "Build page", ci_build_details_path(@merge_request)
.ci_widget
.alert-message
.alert
%strong
%i.icon-refresh
Checking for CI status for #{@merge_request.last_commit_short_sha}
......
......@@ -5,7 +5,7 @@
&rarr;
%span.label_branch= @merge_request.target_branch
%span.right
%span.pull-right
- if can?(current_user, :modify_merge_request, @merge_request)
- if @merge_request.open?
.left.btn-group
......@@ -17,13 +17,13 @@
%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 danger", title: "Close merge request"
= 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 edit_project_merge_request_path(@project, @merge_request), class: "btn grouped" do
%i.icon-edit
Edit
.right
.pull-right
.span3#votes= render 'votes/votes_block', votable: @merge_request
.back_link
......
......@@ -7,7 +7,7 @@
= form_for [@project, @milestone], html: {class: "new_milestone form-horizontal"} do |f|
-if @milestone.errors.any?
.alert-message.block-message.error
.alert.alert-error
%ul
- @milestone.errors.full_messages.each do |msg|
%li= msg
......@@ -32,16 +32,16 @@
.form-actions
- if @milestone.new_record?
= f.submit 'Create milestone', class: "save-btn btn"
= link_to "Cancel", project_milestones_path(@project), class: "btn cancel-btn"
= f.submit 'Create milestone', class: "btn-save btn"
= link_to "Cancel", project_milestones_path(@project), class: "btn btn-cancel"
-else
= f.submit 'Save changes', class: "save-btn btn"
= link_to "Cancel", project_milestone_path(@project, @milestone), class: "btn cancel-btn"
= f.submit 'Save changes', class: "btn-save btn"
= link_to "Cancel", project_milestone_path(@project, @milestone), class: "btn btn-cancel"
:javascript
$(function() {
disableButtonIfEmptyField("#milestone_title", ".save-btn");
disableButtonIfEmptyField("#milestone_title", ".btn-save");
$( ".datepicker" ).datepicker({
dateFormat: "yy-mm-dd",
onSelect: function(dateText, inst) { $("#milestone_due_date").val(dateText) }
......
%li{class: "milestone milestone-#{milestone.closed ? 'closed' : 'open'}", id: dom_id(milestone) }
.right
.pull-right
- if can?(current_user, :admin_milestone, milestone.project) and milestone.open?
= link_to edit_project_milestone_path(milestone.project, milestone), class: "btn small edit-milestone-link grouped" do
= link_to edit_project_milestone_path(milestone.project, milestone), class: "btn btn-small edit-milestone-link grouped" do
%i.icon-edit
Edit
%h4
......
......@@ -3,7 +3,7 @@
%h3.page_title
Milestones
- if can? current_user, :admin_milestone, @project
= link_to "New Milestone", new_project_milestone_path(@project), class: "right btn small", title: "New Milestone"
= link_to "New Milestone", new_project_milestone_path(@project), class: "pull-right btn btn-small", title: "New Milestone"
%br
%div.ui-box
.title
......
......@@ -8,14 +8,14 @@
= link_to project_milestones_path(@project) do
&larr; To milestones list
.span6
.right
.pull-right
- unless @milestone.closed
= link_to new_project_issue_path(@project, issue: { milestone_id: @milestone.id }), class: "btn small grouped", title: "New Issue" do
= 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
= link_to 'Browse Issues', project_issues_path(@milestone.project, milestone_id: @milestone.id), class: "btn edit-milestone-link small grouped"
- if can?(current_user, :admin_milestone, @project)
= link_to edit_project_milestone_path(@project, @milestone), class: "btn small grouped" do
= link_to edit_project_milestone_path(@project, @milestone), class: "btn btn-small grouped" do
%i.icon-edit
Edit
......@@ -25,7 +25,7 @@
%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 small danger"
= link_to 'Close Milestone', project_milestone_path(@project, @milestone, milestone: {closed: true }), method: :put, class: "btn btn-small btn-remove"
.ui-box.ui-box-show
.ui-box-head
......@@ -43,7 +43,7 @@
#{@milestone.closed_items_count} closed
&ndash;
#{@milestone.open_items_count} open
%span.right= @milestone.expires_at
%span.pull-right= @milestone.expires_at
.progress.progress-info
.bar{style: "width: #{@milestone.percent_complete}%;"}
......
......@@ -15,30 +15,30 @@
= f.text_area :note, size: 255, class: 'note_text js-note-text js-gfm-input turn-on'
.note_preview.js-note-preview.turn-off
.buttons
= f.submit 'Add Comment', class: "btn comment-btn grouped js-comment-button"
%a.btn.grouped.js-close-discussion-note-form Cancel
.hint
.right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
.pull-right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
.clearfix
.note_options
.attachment
%h6 Attachment:
.file_name.js-attachment-filename File name...
%a.choose-btn.btn.small.js-choose-note-attachment-button Choose File ...
.hint Any file up to 10 MB
.note-form-actions
.buttons
= f.submit 'Add Comment', class: "btn comment-btn grouped js-comment-button"
%a.btn.grouped.js-close-discussion-note-form Cancel
= f.file_field :attachment, class: "js-note-attachment-input"
.notify_options
%h6 Notify via email:
.note-form-option
= label_tag :notify do
= check_box_tag :notify, 1, !@note.for_commit?
Project team
%span.light Notify team via email
.js-notify-commit-author
= label_tag :notify_author do
= check_box_tag :notify_author, 1 , @note.for_commit?
Commit author
.clearfix
%span.light Notify commit author
.note-form-option
%a.choose-btn.btn.btn-small.js-choose-note-attachment-button
%i.icon-paper-clip
%span Choose File ...
&nbsp;
%span.file_name.js-attachment-filename File name...
= f.file_field :attachment, class: "js-note-attachment-input hide"
.clearfix
......@@ -30,8 +30,8 @@
- if note.attachment.url
- if note.attachment.image?
= image_tag note.attachment.url, class: 'note-image-attach'
.attachment.right
.attachment.pull-right
= link_to note.attachment.url, target: "_blank" do
%i.icon-attachment
%i.icon-paper-clip
= note.attachment_identifier
.clear
......@@ -12,7 +12,7 @@
%fieldset
%legend
Private token
%span.cred.right
%span.cred.pull-right
keep it secret!
.padded
= form_for @user, url: reset_private_token_profile_path, method: :put do |f|
......@@ -24,7 +24,7 @@
%p.cgray
- if current_user.private_token
= text_field_tag "token", current_user.private_token, class: "xxlarge large_text"
= f.submit 'Reset', confirm: "Are you sure?", class: "btn primary btn-build-token"
= f.submit 'Reset', confirm: "Are you sure?", class: "btn btn-primary btn-build-token"
- else
%span You don`t have one yet. Click generate to fix it.
= f.submit 'Generate', class: "btn success btn-build-token"
......@@ -35,7 +35,7 @@
.padded
%p.slead After successful password update you will be redirected to login page where you should login with new password
-if @user.errors.any?
.alert-message.block-message.error
.alert.alert-error
%ul
- @user.errors.full_messages.each do |msg|
%li= msg
......@@ -49,14 +49,14 @@
= f.password_field :password_confirmation, required: true
.clearfix
.input
= f.submit 'Save password', class: "btn save-btn"
= f.submit 'Save password', class: "btn btn-save"
%fieldset.update-username
%legend
Username
%small.cred.right
%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
......@@ -75,6 +75,6 @@
%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 save-btn"
= f.submit 'Save username', class: "btn btn-save"
......@@ -6,7 +6,7 @@
%small
= @user.email
.right
.pull-right
= link_to destroy_user_session_path, class: "logout", method: :delete do
%small
%i.icon-signout
......@@ -15,7 +15,7 @@
= form_for @user, url: profile_path, method: :put, html: { class: "edit_user form-horizontal" } do |f|
-if @user.errors.any?
%div.alert-message.block-message.error
%div.alert.alert-error
%ul
- @user.errors.full_messages.each do |msg|
%li= msg
......@@ -46,7 +46,7 @@
= f.text_area :bio, rows: 6, class: "input-xlarge", maxlength: 250
%span.help-block Tell us about yourself in fewer than 250 characters.
.span5.right
.span5.pull-right
%fieldset.tips
%legend Tips:
%ul
......@@ -65,18 +65,18 @@
%li
%p
Need a group for several dependent projects?
= link_to new_group_path, class: "btn very_small" do
= link_to new_group_path, class: "btn btn-tiny" do
Create a group
- if current_user.can_create_team?
%li
%p
Want to share a team between projects?
= link_to new_team_path, class: "btn very_small" do
= link_to new_team_path, class: "btn btn-tiny" do
Create a team
%fieldset
%legend
Personal projects:
%small.right
%small.pull-right
%span= current_user.personal_projects.count
of
%span= current_user.projects_limit
......@@ -87,10 +87,10 @@
%fieldset
%legend
SSH public keys:
%span.right
%span.pull-right
= link_to pluralize(current_user.keys.count, 'key'), keys_path
.padded
= link_to "Add Public Key", new_key_path, class: "btn small"
= link_to "Add Public Key", new_key_path, class: "btn btn-small"
.form-actions
= f.submit 'Save', class: "btn save-btn"
= f.submit 'Save', class: "btn btn-save"
......@@ -2,8 +2,8 @@
.row
.span7
.form-horizontal= render "shared/clone_panel"
.span4.right
.right
.span4.pull-right
.pull-right
- unless @project.empty_repo?
- if can? current_user, :download_code, @project
= link_to archive_project_repository_path(@project), class: "btn-small btn grouped" do
......
= form_for(@project, remote: true) do |f|
- if @project.errors.any?
.alert-message.block-message.error
.alert.alert-error
%ul
- @project.errors.full_messages.each do |msg|
%li= msg
......@@ -42,7 +42,7 @@
= f.check_box :wiki_enabled
%span.descr Pages for project documentation
- if can? current_user, :change_public_mode, @project
- if can?(current_user, :change_public_mode, @project)
%fieldset.features
%legend
%i.icon-share
......@@ -77,9 +77,9 @@
%br
.actions
= f.submit 'Save', class: "btn save-btn"
= f.submit 'Save', class: "btn btn-save"
= link_to 'Cancel', @project, class: "btn"
- unless @project.new_record?
- if can?(current_user, :remove_project, @project)
.right
= link_to 'Remove Project', @project, confirm: 'Removed project can not be restored! Are you sure?', method: :delete, class: "btn danger"
.pull-right
= link_to 'Remove Project', @project, confirm: 'Removed project can not be restored! Are you sure?', method: :delete, class: "btn btn-remove"
= form_for(@project, remote: true) do |f|
- if @project.errors.any?
.alert-message.block-message.error
.alert.alert-error
%span= @project.errors.full_messages.first
.clearfix.project_name_holder
= f.label :name do
Project name is
.input
= f.text_field :name, placeholder: "Example Project", class: "xxlarge"
= f.submit 'Create project', class: "btn success project-submit"
= f.submit 'Create project', class: "btn btn-create project-submit"
- if current_user.can_select_namespace?
.clearfix
......@@ -24,11 +24,11 @@
.clearfix
.input.light
Need a group for several dependent projects?
= link_to new_group_path, class: "btn very_small" do
= link_to new_group_path, class: "btn btn-tiny" do
Create a group
- if current_user.can_create_team?
.clearfix
.input.light
Want to share a project between team?
= link_to new_team_path, class: "btn very_small" do
= link_to new_team_path, class: "btn btn-tiny" do
Create a team
......@@ -13,19 +13,19 @@
= link_to 'Snippets', project_snippets_path(@project), class: "snippets-tab tab"
- if can? current_user, :admin_project, @project
= nav_link(controller: :deploy_keys, html_options: {class: 'right'}) do
= nav_link(controller: :deploy_keys, html_options: {class: 'pull-right'}) do
= link_to project_deploy_keys_path(@project) do
%span
Deploy Keys
= nav_link(controller: :hooks, html_options: {class: 'right'}) do
= nav_link(controller: :hooks, html_options: {class: 'pull-right'}) do
= link_to project_hooks_path(@project) do
%span
Hooks
= nav_link(controller: :services, html_options: {class: 'right'}) do
= nav_link(controller: :services, html_options: {class: 'pull-right'}) do
= link_to project_services_path(@project) do
%span
Services
= nav_link(path: 'projects#edit', html_options: {class: 'right'}) do
= nav_link(path: 'projects#edit', html_options: {class: 'pull-right'}) do
= link_to edit_project_path(@project), class: "stat-tab tab " do
%i.icon-edit
Edit
......@@ -31,4 +31,4 @@
- if can? current_user, :remove_project, @project
.prepend-top-20
= link_to 'Remove project', @project, confirm: 'Are you sure?', method: :delete, class: "btn danger right"
= link_to 'Remove project', @project, confirm: 'Are you sure?', method: :delete, class: "btn btn-remove pull-right"
......@@ -17,6 +17,6 @@
.actions
= submit_tag 'Assign', class: "btn save-btn"
= link_to "Cancel", project_team_index_path(@project), class: "btn cancel-btn"
= submit_tag 'Assign', class: "btn btn-create"
= link_to "Cancel", project_team_index_path(@project), class: "btn btn-cancel"
......@@ -14,7 +14,7 @@
- if can? current_user, :admin_project, @project
= form_for [@project, @protected_branch] do |f|
-if @protected_branch.errors.any?
.alert-message.block-message.error
.alert.alert-error
%ul
- @protected_branch.errors.full_messages.each do |msg|
%li= msg
......@@ -24,7 +24,7 @@
.span3
= f.select(:name, @project.open_branches.map { |br| [br.name, br.name] } , {include_blank: "Select branch"}, {class: "chosen span3"})
&nbsp;
= f.submit 'Protect', class: "primary btn"
= f.submit 'Protect', class: "btn-primary btn"
- unless @branches.empty?
%table
......@@ -51,4 +51,4 @@
(branch was removed from repository)
%td
- if can? current_user, :admin_project, @project
= link_to 'Unprotect', [@project, branch], confirm: 'Are you sure?', method: :delete, class: "danger btn small"
= link_to 'Unprotect', [@project, branch], confirm: 'Are you sure?', method: :delete, class: "btn btn-remove btn-small"
......@@ -9,7 +9,7 @@
%h5
%i.icon-share
= project.name_with_namespace
.right
.pull-right
%pre.dark.tiny git clone #{project.http_url_to_repo}
......
......@@ -15,6 +15,6 @@
= image_tag gravatar_icon(commit.author_email), class: "", width: 16
= gfm escape_once(truncate(commit.title, length: 40))
%td
%span.right.cgray
%span.pull-right.cgray
= time_ago_in_words(commit.committed_date)
ago
......@@ -23,7 +23,7 @@
= image_tag gravatar_icon(author.email, 16), class: 'avatar s16'
= author.name
%small.light= author.email
.right
.pull-right
= author.commits
......
......@@ -4,7 +4,7 @@
%span Looking for
.input
= search_field_tag :search, params[:search], placeholder: "issue 143", class: "input-xxlarge search-text-input", id: "dashboard_search"
= submit_tag 'Search', class: "btn primary wide"
= submit_tag 'Search', class: "btn btn-primary wide"
.clearfix
.row
.span3
......
%h3.page_title
GitLab CI
%small Continuous integration server from GitLab
.right
.pull-right
- if @service.active
%small.cgreen Enabled
- else
......@@ -16,7 +16,7 @@
%hr
= form_for(@service, :as => :service, :url => project_service_path(@project, :gitlab_ci), :method => :put) do |f|
- if @service.errors.any?
.alert-message.block-message.error
.alert.alert-error
%ul
- @service.errors.full_messages.each do |msg|
%li= msg
......@@ -40,7 +40,7 @@
.form-actions
= f.submit 'Save', class: 'btn save-btn'
= f.submit 'Save', class: 'btn btn-save'
&nbsp;
- if @service.valid? && @service.active
= link_to 'Test settings', test_project_service_path(@project), class: 'btn btn-small'
......@@ -8,7 +8,7 @@
= link_to edit_project_service_path(@project, :gitlab_ci) do
GitLab CI
%small Continuous integration server from GitLab
.right
.pull-right
- if @gitlab_ci_service.try(:active)
%small.cgreen
%i.icon-ok
......@@ -21,11 +21,11 @@
%h4
Jenkins CI
%small An extendable open source continuous integration server
.right
.pull-right
%small Not implemented yet
%li.disabled
%h4
Campfire
%small Web-based group chat tool
.right
.pull-right
%small Not implemented yet
......@@ -3,7 +3,7 @@
%i.icon-file
%strong= @snippet.file_name
%span.options
= link_to "raw", raw_project_snippet_path(@project, @snippet), class: "btn very_small", target: "_blank"
= link_to "raw", raw_project_snippet_path(@project, @snippet), class: "btn btn-tiny", target: "_blank"
.file_content.code
- unless @snippet.content.empty?
%div{class: user_color_scheme_class}
......
......@@ -4,7 +4,7 @@
.snippet-form-holder
= form_for [@project, @snippet] do |f|
-if @snippet.errors.any?
.alert-message.block-message.error
.alert.alert-error
%ul
- @snippet.errors.full_messages.each do |msg|
%li= msg
......@@ -27,10 +27,10 @@
= f.hidden_field :content, class: 'snippet-file-content'
.form-actions
= f.submit 'Save', class: "save-btn btn"
= f.submit 'Save', class: "btn-save btn"
= link_to "Cancel", project_snippets_path(@project), class: " btn"
- unless @snippet.new_record?
.right= link_to 'Destroy', [@project, @snippet], confirm: 'Are you sure?', method: :delete, class: "btn right danger delete-snippet", id: "destroy_snippet_#{@snippet.id}"
.pull-right= link_to 'Destroy', [@project, @snippet], confirm: 'Are you sure?', method: :delete, class: "btn pull-right danger delete-snippet", id: "destroy_snippet_#{@snippet.id}"
:javascript
......
......@@ -5,7 +5,7 @@
%small share code pastes with others out of git repository
- if can? current_user, :write_snippet, @project
= link_to new_project_snippet_path(@project), class: "btn small add_new right", title: "New Snippet" do
= link_to new_project_snippet_path(@project), class: "btn btn-small add_new pull-right", title: "New Snippet" do
Add new snippet
%br
%table
......
......@@ -4,7 +4,7 @@
= @snippet.title
%small= @snippet.file_name
- if can?(current_user, :admin_snippet, @project) || @snippet.author == current_user
= link_to "Edit", edit_project_snippet_path(@project, @snippet), class: "btn small right"
= link_to "Edit", edit_project_snippet_path(@project, @snippet), class: "btn btn-small pull-right"
%br
%div= render 'blob'
......
......@@ -3,7 +3,7 @@
%hr
= form_for @user_project_relation, as: :team_member, url: project_team_members_path(@project) do |f|
-if @user_project_relation.errors.any?
.alert-message.block-message.error
.alert.alert-error
%ul
- @user_project_relation.errors.full_messages.each do |msg|
%li= msg
......@@ -19,5 +19,5 @@
.input= select_tag :project_access, options_for_select(Project.access_options, @user_project_relation.project_access), class: "project-access-select chosen"
.actions
= f.submit 'Save', class: "btn save-btn"
= link_to "Cancel", project_team_index_path(@project), class: "btn cancel-btn"
= f.submit 'Add users', class: "btn btn-create"
= link_to "Cancel", project_team_index_path(@project), class: "btn btn-cancel"
......@@ -10,19 +10,19 @@
%br
%small.cgray= user.email
.span5.right
.span5.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"
.right
.pull-right
- if current_user == user
%span.btn.disabled This is you!
- if @project.namespace_owner == user
%span.btn.disabled.success Owner
%span.btn.disabled Owner
- elsif user.blocked
%span.btn.disabled.blocked Blocked
- elsif allow_admin
= link_to project_team_member_path(@project, user), confirm: remove_from_project_team_message(@project, user), method: :delete, class: "very_small btn danger" do
= 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
......@@ -7,9 +7,9 @@
%br
%small.cgray Members: #{team.members.count}
.span5.right
.right
.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 danger small" do
= 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
......@@ -12,6 +12,6 @@
.input= select_tag(:source_project_id, options_from_collection_for_select(current_user.authorized_projects, :id, :name_with_namespace), prompt: "Select project", class: "chosen xxlarge", required: true)
.actions
= submit_tag 'Import', class: "btn save-btn"
= link_to "Cancel", project_team_index_path(@project), class: "btn cancel-btn"
= submit_tag 'Import', class: "btn btn-save"
= link_to "Cancel", project_team_index_path(@project), class: "btn btn-cancel"
......@@ -7,12 +7,12 @@
%strong= link_to "here", help_permissions_path, class: "vlink"
- if can? current_user, :admin_team_member, @project
%span.right
= link_to import_project_team_members_path(@project), class: "btn small grouped", title: "Import team from another project" do
%span.pull-right
= link_to import_project_team_members_path(@project), class: "btn btn-small grouped", title: "Import team from another project" do
Import team from another project
= link_to available_project_teams_path(@project), class: "btn small grouped", title: "Assign project to team of users" do
= link_to available_project_teams_path(@project), class: "btn btn-small grouped", title: "Assign project to team of users" do
Assign project to Team of users
= link_to new_project_team_member_path(@project), class: "btn success small grouped", title: "New Team Member" do
= link_to new_project_team_member_path(@project), class: "btn btn-primary small grouped", title: "New Team Member" do
New Team Member
%hr
......
......@@ -2,7 +2,7 @@
.team_member_show
- if can? current_user, :admin_project, @project
= link_to 'Remove from team', project_team_member_path(@project, @member), confirm: 'Are you sure?', method: :delete, class: "right btn danger"
= link_to 'Remove from team', project_team_member_path(@project, @member), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove pull-right"
.profile_avatar_holder
= image_tag gravatar_icon(@member.email, 60), class: "borders"
%h3.page_title
......
......@@ -25,9 +25,9 @@
%li{class: ("active" if params[:project_id] == project.id.to_s)}
= link_to team_filter_path(entity, project_id: project.id) do
= project.name_with_namespace
%small.right= entities_per_project(project, entity)
%small.pull-right= entities_per_project(project, entity)
%fieldset
%hr
= link_to "Reset", team_filter_path(entity), class: 'btn right'
= link_to "Reset", team_filter_path(entity), class: 'btn pull-right'
......@@ -4,8 +4,8 @@
%small
(#{projects.count})
- if can? current_user, :manage_user_team, @team
%span.right
= link_to new_team_project_path(@team), class: "btn very_small info" do
%span.pull-right
= link_to new_team_project_path(@team), class: "btn btn-tiny info" do
%i.icon-plus
Assign Project
%ul.well-list
......
%h3.page_title= "Edit Team #{@team.name}"
%hr
= form_for @team, url: teams_path do |f|
= form_for @team, url: team_path(@team) do |f|
- if @team.errors.any?
.alert-message.block-message.error
.alert.alert-error
%span= @team.errors.full_messages.first
.clearfix
= f.label :name do
......@@ -15,8 +15,6 @@
Team path is
.input
= f.text_field :path, placeholder: "opensource", class: "xxlarge left"
.clearfix
.input.span3.center
= f.submit 'Save team changes', class: "btn primary"
.input.span3.center
= link_to 'Delete team', team_path(@team), method: :delete, confirm: "You are shure?", class: "btn danger"
.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"
%h3.page_title
Issues
%small (in Team projects assigned to Team members)
%small.right #{@issues.total_count} issues
%small.pull-right #{@issues.total_count} issues
%hr
.row
......
= form_tag admin_team_member_path(@team, @member), method: :put do
-if @member.errors.any?
.alert-message.block-message.error
.alert.alert-error
%ul
- @member.errors.full_messages.each do |msg|
%li= msg
......@@ -16,5 +16,5 @@
%br
.actions
= submit_tag 'Save', class: "btn primary"
= submit_tag 'Save', class: "btn btn-save"
= link_to 'Cancel', :back, class: "btn"
......@@ -10,22 +10,22 @@
%br
%small.cgray= user.email
.span6.right
.span6.pull-right
- 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
Admin access
= check_box_tag :group_admin, true, @team.admin?(user)
.right
Admin access
.pull-right
- if current_user == user
%span.btn.disabled This is you!
- if @team.owner == user
%span.btn.disabled.success Owner
%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: "very_small btn danger" do
= 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
......@@ -6,8 +6,8 @@
%strong= link_to "here", help_permissions_path, class: "vlink"
- if can? current_user, :manage_user_team, @team
%span.right
= link_to new_team_member_path(@team), class: "btn success small grouped", title: "New Team Member" do
%span.pull-right
= link_to new_team_member_path(@team), class: "btn btn-primary small grouped", title: "New Team Member" do
New Team Member
%hr
......
......@@ -25,4 +25,4 @@
%td
%span= check_box_tag :group_admin
%span Admin?
%td= submit_tag 'Add', class: "btn primary", id: :add_members_to_team
%td= submit_tag 'Add User', class: "btn btn-create", id: :add_members_to_team
......@@ -3,7 +3,7 @@
.team_member_show
- if can? current_user, :admin_project, @project
= link_to 'Remove from team', project_team_member_path(project_id: @project, id: @team_member.id), confirm: 'Are you sure?', method: :delete, class: "right btn danger"
= link_to 'Remove from team', project_team_member_path(project_id: @project, id: @team_member.id), confirm: 'Are you sure?', method: :delete, class: "pull-right btn btn-remove"
.profile_avatar_holder
= image_tag gravatar_icon(user.email, 60), class: "borders"
%h3.page_title
......
%h3.page_title
Merge Requests
%small (authored by or assigned to Team members)
%small.right #{@merge_requests.total_count} merge requests
%small.pull-right #{@merge_requests.total_count} merge requests
%hr
.row
......
......@@ -2,7 +2,7 @@
%hr
= form_for @team, url: teams_path do |f|
- if @team.errors.any?
.alert-message.block-message.error
.alert.alert-error
%span= @team.errors.full_messages.first
.clearfix
= f.label :name do
......@@ -10,7 +10,7 @@
.input
= f.text_field :name, placeholder: "Ex. Ruby Developers", class: "xxlarge left"
&nbsp;
= f.submit 'Create team', class: "btn primary"
= f.submit 'Create team', class: "btn btn-create"
%hr
.padded
%ul
......
= form_tag team_project_path(@team, @project), method: :put do
-if @project.errors.any?
.alert-message.block-message.error
.alert.alert-error
%ul
- @project.errors.full_messages.each do |msg|
%li= msg
......@@ -12,5 +12,5 @@
%br
.actions
= submit_tag 'Save', class: "btn primary"
= link_to 'Cancel', :back, class: "btn"
= submit_tag 'Save', class: "btn btn-save"
= link_to 'Cancel', :back, class: "btn btn-cancel"
%h3
Edit max access in #{@project.name} for #{@team.name} team
%h3.page_title
Edit max access in #{link_to @project.name_with_namespace, @project} for #{link_to(@team.name, team_path(@team))} team
%hr
%table.zebra-striped
%tr
%td Project:
%td= @project.name
%tr
%td Team:
%td= @team.name
%tr
%td Since:
%td= assigned_since(@team, @project).stamp("Nov 11, 2010")
= render 'form'
......@@ -5,8 +5,8 @@
%strong= link_to "here", help_permissions_path, class: "vlink"
- if current_user.can?(:manage_user_team, @team) && @avaliable_projects.any?
%span.right
= link_to new_team_project_path(@team), class: "btn success small grouped", title: "New Team Member" do
%span.pull-right
= link_to new_team_project_path(@team), class: "btn btn-primary small grouped", title: "New Team Member" do
Assign project to Team
%hr
......@@ -29,8 +29,8 @@
- if current_user.can?(:admin_user_team, @team)
%td.bgred
= link_to 'Edit max access', edit_team_project_path(@team, project), class: "btn small"
= link_to 'Relegate', team_project_path(@team, project), confirm: 'Remove project from team and move to global namespace. Are you sure?', method: :delete, class: "btn danger small"
= link_to 'Edit max access', edit_team_project_path(@team, project), class: "btn btn-small"
= link_to 'Relegate', team_project_path(@team, project), confirm: 'Remove project from team and move to global namespace. Are you sure?', method: :delete, class: "btn btn-remove small"
- else
%p.nothing_here_message This team has no projects yet
......@@ -20,4 +20,4 @@
%tr
%td= select_tag :project_ids, options_from_collection_for_select(@avaliable_projects , :id, :name_with_namespace), multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5'
%td= select_tag :greatest_project_access, options_for_select(UserTeam.access_roles), {class: "project-access-select chosen span3" }
%td= submit_tag 'Add', class: "btn primary", id: :assign_projects_to_team
%td= submit_tag 'Add Project', class: "btn btn-create", id: :assign_projects_to_team
.projects
.activities.span8
= link_to dashboard_path, class: 'btn very_small' do
= link_to dashboard_path, class: 'btn btn-tiny' do
&larr; To dashboard
&nbsp;
%span.cgray Events and projects are filtered in scope of team
......
.btn-group.tree-btn-group
-# only show edit link for text files
- if @tree.text?
= link_to "edit", edit_project_tree_path(@project, @id), class: "btn very_small", disabled: !allowed_tree_edit?
= link_to "raw", project_blob_path(@project, @id), class: "btn very_small", target: "_blank"
= link_to "edit", edit_project_tree_path(@project, @id), class: "btn btn-tiny", disabled: !allowed_tree_edit?
= link_to "raw", project_blob_path(@project, @id), class: "btn btn-tiny", target: "_blank"
-# only show normal/blame view links for text files
- if @tree.text?
- if current_page? project_blame_path(@project, @id)
= link_to "normal view", project_tree_path(@project, @id), class: "btn very_small"
= link_to "normal view", project_tree_path(@project, @id), class: "btn btn-tiny"
- else
= link_to "blame", project_blame_path(@project, @id), class: "btn very_small"
= link_to "history", project_commits_path(@project, @id), class: "btn very_small"
= link_to "blame", project_blame_path(@project, @id), class: "btn btn-tiny"
= link_to "history", project_commits_path(@project, @id), class: "btn btn-tiny"
......@@ -3,5 +3,5 @@
= render partial: 'shared/ref_switcher', locals: {destination: 'tree', path: @path}
= nav_link(controller: :tree) do
= link_to 'Source', project_tree_path(@project, @ref)
%li.right
%li.pull-right
= render "shared/clone_panel"
......@@ -24,7 +24,7 @@
%th Name
%th Last Update
%th Last Commit
%th= link_to "history", project_commits_path(@project, @id), class: "btn very_small right"
%th= link_to "history", project_commits_path(@project, @id), class: "btn btn-tiny pull-right"
- if tree.up_dir?
%tr.tree-item
......
......@@ -10,7 +10,7 @@
%strong= @ref
%span.options
.btn-group.tree-btn-group
= link_to "Cancel", project_tree_path(@project, @id), class: "btn very_small cancel-btn", confirm: "Are you sure?"
= link_to "Cancel", project_tree_path(@project, @id), class: "btn btn-tiny btn-cancel", confirm: "Are you sure?"
.file_content.code
%pre#editor= @tree.data
......@@ -27,7 +27,7 @@
.message
to branch
%strong= @ref
= link_to "Cancel", project_tree_path(@project, @id), class: "btn cancel-btn", confirm: "Are you sure?"
= link_to "Cancel", project_tree_path(@project, @id), class: "btn btn-cancel", confirm: "Are you sure?"
:javascript
var ace_mode = "#{@tree.language.try(:ace_mode)}";
......
......@@ -4,20 +4,20 @@
%ul.well-list
%li
%strong Email
%span.right= mail_to @user.email
%span.pull-right= mail_to @user.email
- unless @user.skype.blank?
%li
%strong Skype
%span.right= @user.skype
%span.pull-right= @user.skype
- unless @user.linkedin.blank?
%li
%strong LinkedIn
%span.right= @user.linkedin
%span.pull-right= @user.linkedin
- unless @user.twitter.blank?
%li
%strong Twitter
%span.right= @user.twitter
%span.pull-right= @user.twitter
- unless @user.bio.blank?
%li
%strong Bio
%span.right= @user.bio
%span.pull-right= @user.bio
......@@ -9,7 +9,7 @@
\/
%strong.well-title
= truncate(project.name, length: 45)
%span.right.light
%span.pull-right.light
- if project.owner == @user
%i.icon-wrench
- tm = project.team.get_tm(@user.id)
......
......@@ -4,8 +4,8 @@
= image_tag gravatar_icon(@user.email, 90), class: "avatar s90"
= @user.name
- if @user == current_user
.right
= link_to profile_path, class: 'btn small' do
.pull-right
= link_to profile_path, class: 'btn btn-small' do
%i.icon-edit
Edit Profile
%br
......
......@@ -23,5 +23,5 @@
= f.label :content
.input= f.text_area :content, class: 'span8 js-gfm-input'
.actions
= f.submit 'Save', class: "save-btn btn"
= link_to "Cancel", project_wiki_path(@project, :index), class: "btn cancel-btn"
= f.submit 'Save', class: "btn-save btn"
= link_to "Cancel", project_wiki_path(@project, :index), class: "btn btn-cancel"
......@@ -2,7 +2,7 @@
%hr
= render 'form'
.right
.pull-right
- if can? current_user, :admin_wiki, @project
= link_to project_wiki_path(@project, @wiki), confirm: "Are you sure you want to delete this page?", method: :delete, class: "btn small danger" do
= link_to project_wiki_path(@project, @wiki), confirm: "Are you sure you want to delete this page?", method: :delete, class: "btn btn-small btn-remove" do
Delete this page
\ No newline at end of file
%h3.page_title
= @wiki.title
%span.right
= link_to pages_project_wikis_path(@project), class: "btn small grouped" do
%span.pull-right
= link_to pages_project_wikis_path(@project), class: "btn btn-small grouped" do
Pages
- if can? current_user, :write_wiki, @project
= link_to history_project_wiki_path(@project, @wiki), class: "btn small grouped" do
= link_to history_project_wiki_path(@project, @wiki), class: "btn btn-small grouped" do
History
= link_to edit_project_wiki_path(@project, @wiki), class: "btn small grouped" do
= link_to edit_project_wiki_path(@project, @wiki), class: "btn btn-small grouped" do
%i.icon-edit
Edit
%br
......
......@@ -27,11 +27,15 @@ class PostReceive
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)
else
Key.find_by_identifier(identifier).try(:user)
elsif identifier =~ /key/
key_id = identifier.gsub("key-", "")
Key.find_by_id(key_id).try(:user)
end
return false unless user
unless user
Gitlab::GitLogger.error("POST-RECEIVE: Triggered hook for non-existing user \"#{identifier} \"")
return false
end
project.trigger_post_receive(oldrev, newrev, ref, user)
end
......
......@@ -6,7 +6,7 @@ production:
encoding: unicode
database: gitlabhq_production
pool: 5
username: postgres
username: gitlab
password:
# host: localhost
# port: 5432
......
......@@ -96,7 +96,7 @@ omniauth:
# GitLab Satellites
satellites:
# Relative paths are relative to Rails.root (default: tmp/repo_satellites/)
path: /home/gitlab/gitlab-satellites/
path: /home/git/gitlab-satellites/
## Backup settings
backup:
......@@ -105,8 +105,6 @@ backup:
## Gitolite settings
gitolite:
admin_uri: git@localhost:gitolite-admin
# REPOS_PATH MUST NOT BE A SYMLINK!!!
repos_path: /home/git/repositories/
hooks_path: /home/git/.gitolite/hooks/
......
......@@ -51,7 +51,7 @@ Settings.gitlab['protocol'] ||= Settings.gitlab.https ? "https" : "http"
Settings.gitlab['email_from'] ||= "gitlab@#{Settings.gitlab.host}"
Settings.gitlab['support_email'] ||= Settings.gitlab.email_from
Settings.gitlab['url'] ||= Settings.send(:build_gitlab_url)
Settings.gitlab['user'] ||= 'gitlab'
Settings.gitlab['user'] ||= 'git'
Settings.gitlab['signup_enabled'] ||= false
Settings['gravatar'] ||= Settingslogic.new({})
......
# GIT over HTTP
require Rails.root.join("lib", "gitlab", "backend", "grack_auth")
# GITOLITE backend
require Rails.root.join("lib", "gitlab", "backend", "gitolite")
# GIT over SSH
require Rails.root.join("lib", "gitlab", "backend", "shell")
......@@ -130,7 +130,7 @@ Gitlab::Application.routes.draw do
#
# Groups Area
#
resources :groups, constraints: { id: /[^\/]+/ }, only: [:show, :new, :create] do
resources :groups, constraints: { id: /[^\/]+/ } do
member do
get :issues
get :merge_requests
......@@ -164,7 +164,6 @@ Gitlab::Application.routes.draw do
resources :projects, constraints: { id: /[a-zA-Z.0-9_\-\/]+/ }, except: [:new, :create, :index], path: "/" do
member do
get "wall"
get "graph"
get "files"
end
......@@ -174,6 +173,7 @@ Gitlab::Application.routes.draw do
resources :compare, only: [:index, :create]
resources :blame, only: [:show], constraints: {id: /.+/}
resources :blob, only: [:show], constraints: {id: /.+/}
resources :graph, only: [:show], constraints: {id: /.+/}
match "/compare/:from...:to" => "compare#show", as: "compare",
:via => [:get, :post], constraints: {from: /.+/, to: /.+/}
......
......@@ -2,7 +2,7 @@
# note that config/gitlab.yml web path should also be changed
# ENV['RAILS_RELATIVE_URL_ROOT'] = "/gitlab"
app_dir = "/home/gitlab/gitlab/"
app_dir = "/home/git/gitlab/"
worker_processes 2
working_directory app_dir
......
class RemovePrivateFlagFromProject < ActiveRecord::Migration
def up
remove_column :projects, :private_flag
end
def down
add_column :projects, :private_flag, :boolean, default: true, null: false
end
end
......@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20130125090214) do
ActiveRecord::Schema.define(:version => 20130131070232) do
create_table "events", :force => true do |t|
t.string "target_type"
......@@ -147,7 +147,6 @@ ActiveRecord::Schema.define(:version => 20130125090214) do
t.text "description"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.boolean "private_flag", :default => true, :null => false
t.integer "creator_id"
t.string "default_branch"
t.boolean "issues_enabled", :default => true, :null => false
......
......@@ -32,6 +32,7 @@ When listing resources you can pass the following parameters:
+ [Users](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/users.md)
+ [Session](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/session.md)
+ [Projects](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/projects.md)
+ [Groups](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/groups.md)
+ [Snippets](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/snippets.md)
+ [Repositories](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/repositories.md)
+ [Issues](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/issues.md)
......
## List project groups
Get a list of groups. (As user: my groups, as admin: all groups)
```
GET /groups
```
```json
[
{
"id": 1,
"name": "Foobar Group",
"path": "foo-bar",
"owner_id": 18
}
]
```
## Details of group
Get all details of a group.
```
GET /groups/:id
```
Parameters:
+ `id` (required) - The ID of a group
## New group
Create a new project group. Available only for admin
```
POST /groups
```
Parameters:
+ `name` (required) - Email
+ `path` - Password
Will return created group with status `201 Created` on success, or `404 Not found` on fail.
......@@ -30,6 +30,19 @@ Parameters:
+ `id` (required) - The ID of a project
### List merge request notes
Get a list of merge request notes.
```
GET /projects/:id/merge_requests/:merge_request_id/notes
```
Parameters:
+ `id` (required) - The ID of a project
+ `merge_request_id` (required) - The ID of an merge request
### List issue notes
Get a list of issue notes.
......
......@@ -22,6 +22,8 @@ GET /projects
"created_at": "2012-05-23T08:00:58Z"
},
"private": true,
"path": "rails",
"path_with_namespace": "rails/rails",
"issues_enabled": false,
"merge_requests_enabled": false,
"wall_enabled": true,
......@@ -42,6 +44,8 @@ GET /projects
"created_at": "2012-05-23T08:00:58Z"
},
"private": true,
"path": "gitlab",
"path_with_namespace": "randx/gitlab",
"issues_enabled": true,
"merge_requests_enabled": true,
"wall_enabled": true,
......@@ -78,6 +82,8 @@ Parameters:
"created_at": "2012-05-23T08:00:58Z"
},
"private": true,
"path": "gitlab",
"path_with_namespace": "randx/gitlab",
"issues_enabled": true,
"merge_requests_enabled": true,
"wall_enabled": true,
......
......@@ -33,7 +33,8 @@ Parameters:
},
"authored_date": "2012-06-27T05:51:39-07:00",
"committed_date": "2012-06-28T03:44:20-07:00"
}
},
"protected": true
}
]
```
......@@ -73,7 +74,88 @@ Parameters:
},
"authored_date": "2012-06-27T05:51:39-07:00",
"committed_date": "2012-06-28T03:44:20-07:00"
}
},
"protected": true
}
```
## Protect a project repository branch
Protect a single project repository branch.
```
PUT /projects/:id/repository/branches/:branch/protect
```
Parameters:
+ `id` (required) - The ID of a project
+ `branch` (required) - The name of the branch
```json
{
"name": "master",
"commit": {
"id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
"parents": [
{
"id": "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
}
],
"tree": "46e82de44b1061621357f24c05515327f2795a95",
"message": "add projects API",
"author": {
"name": "John Smith",
"email": "john@example.com"
},
"committer": {
"name": "John Smith",
"email": "john@example.com"
},
"authored_date": "2012-06-27T05:51:39-07:00",
"committed_date": "2012-06-28T03:44:20-07:00"
},
"protected": true
}
```
## Unprotect a project repository branch
Unprotect a single project repository branch.
```
PUT /projects/:id/repository/branches/:branch/unprotect
```
Parameters:
+ `id` (required) - The ID of a project
+ `branch` (required) - The name of the branch
```json
{
"name": "master",
"commit": {
"id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
"parents": [
{
"id": "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
}
],
"tree": "46e82de44b1061621357f24c05515327f2795a95",
"message": "add projects API",
"author": {
"name": "John Smith",
"email": "john@example.com"
},
"committer": {
"name": "John Smith",
"email": "john@example.com"
},
"authored_date": "2012-06-27T05:51:39-07:00",
"committed_date": "2012-06-28T03:44:20-07:00"
},
"protected": false
}
```
......@@ -110,7 +192,8 @@ Parameters:
},
"authored_date": "2012-05-28T04:42:42-07:00",
"committed_date": "2012-05-28T04:42:42-07:00"
}
},
"protected": null
}
]
```
......
......@@ -20,6 +20,8 @@ GET /users
"linkedin": "",
"twitter": "",
"dark_scheme": false,
"extern_uid": "john.smith",
"provider": "provider_name",
"theme_id": 1
},
{
......@@ -34,6 +36,8 @@ GET /users
"linkedin": "",
"twitter": "",
"dark_scheme": true,
"extern_uid": "jack.smith",
"provider": "provider_name",
"theme_id": 1
}
]
......@@ -64,6 +68,8 @@ Parameters:
"linkedin": "",
"twitter": "",
"dark_scheme": false,
"extern_uid": "john.smith",
"provider": "provider_name",
"theme_id": 1
}
```
......@@ -84,10 +90,47 @@ Parameters:
+ `linkedin` - Linkedin
+ `twitter` - Twitter account
+ `projects_limit` - Number of projects user can create
+ `extern_uid` - External UID
+ `provider` - External provider name
+ `bio` - User's bio
Will return created user with status `201 Created` on success, or `404 Not
found` on fail.
## User modification
Modify user. Available only for admin
```
PUT /users/:id
```
Parameters:
+ `email` - Email
+ `username` - Username
+ `name` - Name
+ `password` - Password
+ `skype` - Skype ID
+ `linkedin` - Linkedin
+ `twitter` - Twitter account
+ `projects_limit` - Limit projects wich user can create
+ `extern_uid` - External UID
+ `provider` - External provider name
+ `bio` - User's bio
Will return created user with status `200 OK` on success, or `404 Not
found` on fail.
## User deletion
Delete user. Available only for admin
```
DELETE /users/:id
```
Will return deleted user with status `200 OK` on success, or `404 Not
found` on fail.
## Current user
Get currently authenticated user.
......
......@@ -90,134 +90,75 @@ Install the Bundler Gem:
# 3. System Users
Create a user for Git and Gitolite:
Create a `git` user for Gitlab:
sudo adduser \
--system \
--shell /bin/sh \
--gecos 'Git Version Control' \
--group \
--disabled-password \
--home /home/git \
git
sudo adduser --disabled-login --gecos 'GitLab' git
Create a user for GitLab:
# 4. GitLab shell
sudo adduser --disabled-login --gecos 'GitLab' gitlab
# Add it to the git group
sudo usermod -a -G git gitlab
# Generate the SSH key
sudo -u gitlab -H ssh-keygen -q -N '' -t rsa -f /home/gitlab/.ssh/id_rsa
# 4. Gitolite
Clone GitLab's fork of the Gitolite source code:
# login as git
sudo su git
# go to home directory
cd /home/git
sudo -u git -H git clone -b gl-v320 https://github.com/gitlabhq/gitolite.git /home/git/gitolite
Setup Gitolite with GitLab as its admin:
**Important Note:**
GitLab assumes *full and unshared* control over this Gitolite installation.
# Add Gitolite scripts to $PATH
sudo -u git -H mkdir /home/git/bin
sudo -u git -H sh -c 'printf "%b\n%b\n" "PATH=\$PATH:/home/git/bin" "export PATH" >> /home/git/.profile'
sudo -u git -H sh -c 'gitolite/install -ln /home/git/bin'
# Copy the gitlab user's (public) SSH key ...
sudo cp /home/gitlab/.ssh/id_rsa.pub /home/git/gitlab.pub
sudo chmod 0444 /home/git/gitlab.pub
# ... and use it as the admin key for the Gitolite setup
sudo -u git -H sh -c "PATH=/home/git/bin:$PATH; gitolite setup -pk /home/git/gitlab.pub"
Fix the directory permissions for the configuration directory:
# Make sure the Gitolite config dir is owned by git
sudo chmod 750 /home/git/.gitolite/
sudo chown -R git:git /home/git/.gitolite/
Fix the directory permissions for the repositories:
# clone gitlab shell
git clone https://github.com/gitlabhq/gitlab-shell.git
# Make sure the repositories dir is owned by git and it stays that way
sudo chmod -R ug+rwXs,o-rwx /home/git/repositories/
sudo chown -R git:git /home/git/repositories/
# setup
cd gitlab-shell
cp config.yml.example config.yml
./bin/install
## Add domains to list to the list of known hosts
sudo -u gitlab -H ssh git@localhost
sudo -u gitlab -H ssh git@YOUR_DOMAIN_NAME
sudo -u gitlab -H ssh git@YOUR_GITOLITE_DOMAIN_NAME
## Test if everything works so far
# Clone the admin repo so SSH adds localhost to known_hosts ...
# ... and to be sure your users have access to Gitolite
sudo -u gitlab -H git clone git@localhost:gitolite-admin.git /tmp/gitolite-admin
# If it succeeded without errors you can remove the cloned repo
sudo rm -rf /tmp/gitolite-admin
**Important Note:**
If you can't clone the `gitolite-admin` repository: **DO NOT PROCEED WITH INSTALLATION**!
Check the [Trouble Shooting Guide](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Trouble-Shooting-Guide)
and make sure you have followed all of the above steps carefully.
# 5. Database
See `doc/install/databases.md`
To setup the MySQL/PostgreSQL database and dependencies please see [`doc/install/databases.md`](./databases.md) .
# 6. GitLab
# We'll install GitLab into home directory of the user "gitlab"
cd /home/gitlab
# We'll install GitLab into home directory of the user "git"
cd /home/git
## Clone the Source
# Clone GitLab repository
sudo -u gitlab -H git clone https://github.com/gitlabhq/gitlabhq.git gitlab
sudo -u git -H git clone https://github.com/gitlabhq/gitlabhq.git gitlab
# Go to gitlab dir
cd /home/gitlab/gitlab
cd /home/git/gitlab
# Checkout to stable release
sudo -u gitlab -H git checkout 4-1-stable
sudo -u git -H git checkout 5-0-stable
**Note:**
You can change `4-1-stable` to `master` if you want the *bleeding edge* version, but
You can change `5-0-stable` to `master` if you want the *bleeding edge* version, but
do so with caution!
## Configure it
cd /home/gitlab/gitlab
cd /home/git/gitlab
# Copy the example GitLab config
sudo -u gitlab -H cp config/gitlab.yml.example config/gitlab.yml
sudo -u git -H cp config/gitlab.yml.example config/gitlab.yml
# Make sure to change "localhost" to the fully-qualified domain name of your
# host serving GitLab where necessary
sudo -u gitlab -H vim config/gitlab.yml
sudo -u git -H vim config/gitlab.yml
# Make sure GitLab can write to the log/ and tmp/ directories
sudo chown -R gitlab log/
sudo chown -R gitlab tmp/
sudo chown -R git log/
sudo chown -R git tmp/
sudo chmod -R u+rwX log/
sudo chmod -R u+rwX tmp/
# Make directory for satellites
sudo -u gitlab -H mkdir /home/gitlab/gitlab-satellites
sudo -u git -H mkdir /home/git/gitlab-satellites
# Copy the example Unicorn config
sudo -u gitlab -H cp config/unicorn.rb.example config/unicorn.rb
sudo -u git -H cp config/unicorn.rb.example config/unicorn.rb
**Important Note:**
Make sure to edit both files to match your setup.
......@@ -225,42 +166,29 @@ Make sure to edit both files to match your setup.
## Configure GitLab DB settings
# Mysql
sudo -u gitlab cp config/database.yml.mysql config/database.yml
sudo -u git cp config/database.yml.mysql config/database.yml
# PostgreSQL
sudo -u gitlab cp config/database.yml.postgresql config/database.yml
sudo -u git cp config/database.yml.postgresql config/database.yml
Make sure to update username/password in config/database.yml.
## Install Gems
cd /home/gitlab/gitlab
cd /home/git/gitlab
sudo gem install charlock_holmes --version '0.6.9'
# For MySQL (note, the option says "without")
sudo -u gitlab -H bundle install --deployment --without development test postgres
sudo -u git -H bundle install --deployment --without development test postgres
# Or for PostgreSQL
sudo -u gitlab -H bundle install --deployment --without development test mysql
## Configure Git
GitLab needs to be able to commit and push changes to Gitolite. In order to do
that Git requires a username and email. (We recommend using the same address
used for the `email.from` setting in `config/gitlab.yml`)
sudo -u gitlab -H git config --global user.name "GitLab"
sudo -u gitlab -H git config --global user.email "gitlab@localhost"
## Setup GitLab Hooks
sudo -u git -H bundle install --deployment --without development test mysql
sudo cp ./lib/hooks/post-receive /home/git/.gitolite/hooks/common/post-receive
sudo chown git:git /home/git/.gitolite/hooks/common/post-receive
## Initialise Database and Activate Advanced Features
sudo -u gitlab -H bundle exec rake gitlab:setup RAILS_ENV=production
sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production
## Install Init Script
......@@ -279,11 +207,11 @@ Make GitLab start on boot:
Check if GitLab and its environment is configured correctly:
sudo -u gitlab -H bundle exec rake gitlab:env:info RAILS_ENV=production
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
To make sure you didn't miss anything run a more thorough check with:
sudo -u gitlab -H bundle exec rake gitlab:check RAILS_ENV=production
sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
If all items are green, then congratulations on successfully installing GitLab!
However there are still a few steps left.
......@@ -356,7 +284,7 @@ a different host, you can configure its connection string via the
If you are running SSH on a non-standard port, you must change the gitlab user'S SSH config.
# Add to /home/gitlab/.ssh/config
# Add to /home/git/.ssh/config
host localhost # Give your setup a name (here: override localhost)
user git # Your remote git user
port 2222 # Your port number
......
......@@ -3,37 +3,23 @@
This is the directory structure you will end up with following the instructions in the Installation Guide.
|-- home
| |-- gitlab
| |-- git
| |-- .ssh
| |-- gitlab
| |-- gitlab-satellites
| |-- git
| |-- .gitolite
| |-- .ssh
| |-- bin
| |-- gitolite
| |-- gitlab-shell
| |-- repositories
**/home/gitlab/.ssh**
Contains the Gitolite admin key GitLab uses to configure Gitolite.
**/home/git/.ssh**
**/home/gitlab/gitlab**
**/home/git/gitlab**
This is where GitLab lives.
**/home/gitlab/gitlab-satellites**
**/home/git/gitlab-satellites**
Contains a copy of all repositories with a working tree.
It's used for merge requests, editing files, etc.
**/home/git/.ssh**
Contains the SSH access configuration managed by Gitolite.
**/home/git/bin**
Contains Gitolite executables.
**/home/git/gitolite**
This is where Gitolite lives.
**/home/git/repositories**
Holds all your repositories in bare format.
This is the place Git uses when you pull/push to your projects.
......
......@@ -81,7 +81,7 @@ Config directory owned by git:git? ... yes
Config directory access is drwxr-x---? ... yes
Repo base directory exists? ... yes
Repo base owned by git:git? ... yes
Repo base access is drwsrws---? ... yes
Repo base access is drwxrws---? ... yes
Can clone gitolite-admin? ... yes
Can commit to gitolite-admin? ... yes
post-receive hook exists? ... yes
......
......@@ -24,3 +24,9 @@ Feature: Groups
When I visit group people page
And I select user "John" from list with role "Reporter"
Then I should see user "John" in team list
Scenario: I should see edit group page
When I visit group settings page
And I change group name
Then I should see new group name
......@@ -4,7 +4,7 @@ class AdminActiveTab < Spinach::FeatureSteps
include SharedActiveTab
Then 'the active main tab should be Home' do
ensure_active_main_tab('Stats')
ensure_active_main_tab('Home')
end
Then 'the active main tab should be Projects' do
......
......@@ -82,6 +82,17 @@ class Groups < Spinach::FeatureSteps
current_path.should == group_path(Group.last)
end
And 'I change group name' do
fill_in 'group_name', :with => 'new-name'
click_button "Save group"
end
Then 'I should see new group name' do
within ".navbar-gitlab" do
page.should have_content "group: new-name"
end
end
protected
def current_group
......
......@@ -4,7 +4,7 @@ class ProfileActiveTab < Spinach::FeatureSteps
include SharedActiveTab
Then 'the active main tab should be Home' do
ensure_active_main_tab('Profile')
ensure_active_main_tab('Home')
end
Then 'the active main tab should be Account' do
......
......@@ -7,7 +7,7 @@ class ProjectActiveTab < Spinach::FeatureSteps
# Main Tabs
Then 'the active main tab should be Home' do
ensure_active_main_tab(@project.name)
ensure_active_main_tab('Home')
end
Then 'the active main tab should be Files' do
......
......@@ -14,6 +14,6 @@ class ProjectNetworkGraph < Spinach::FeatureSteps
Gitlab::Graph::JsonBuilder.stub(max_count: 10)
project = Project.find_by_name("Shop")
visit graph_project_path(project)
visit project_graph_path(project, "master")
end
end
......@@ -24,7 +24,7 @@ class ProjectTeamManagement < Spinach::FeatureSteps
select user.name, :from => "user_ids"
select "Reporter", :from => "project_access"
end
click_button "Save"
click_button "Add users"
end
Then 'I should see "Mike" in team list as "Reporter"' do
......
......@@ -2,7 +2,11 @@ module SharedActiveTab
include Spinach::DSL
def ensure_active_main_tab(content)
page.find('ul.main_menu li.active').should have_content(content)
if content == "Home"
page.find('ul.main_menu li.active').should have_css('i.icon-home')
else
page.find('ul.main_menu li.active').should have_content(content)
end
end
def ensure_active_sub_tab(content)
......
......@@ -25,6 +25,10 @@ module SharedPaths
visit people_group_path(current_group)
end
When 'I visit group settings page' do
visit edit_group_path(current_group)
end
# ----------------------------------------
# Dashboard
# ----------------------------------------
......@@ -141,7 +145,7 @@ module SharedPaths
# Stub Graph::JsonBuilder max_size to speed up test (10 commits vs. 650)
Gitlab::Graph::JsonBuilder.stub(max_count: 10)
visit graph_project_path(@project)
visit project_graph_path(@project, root_ref)
end
Given "I visit my project's issues page" do
......
......@@ -9,17 +9,12 @@ require 'spinach/capybara'
require 'sidekiq/testing/inline'
%w(gitolite_stub stubbed_repository valid_commit).each do |f|
%w(stubbed_repository valid_commit).each do |f|
require Rails.root.join('spec', 'support', f)
end
Dir["#{Rails.root}/features/steps/shared/*.rb"].each {|file| require file}
#
# Stub gitolite
#
include GitoliteStub
WebMock.allow_net_connect!
#
# JS driver
......@@ -49,6 +44,4 @@ Spinach.hooks.before_run do
RSpec::Mocks::setup self
include FactoryGirl::Syntax::Methods
stub_gitolite!
end
......@@ -24,7 +24,8 @@ module Gitlab
format :json
error_format :json
helpers APIHelpers
mount Groups
mount Users
mount Projects
mount Issues
......@@ -32,5 +33,6 @@ module Gitlab
mount Session
mount MergeRequests
mount Notes
mount Internal
end
end
......@@ -2,7 +2,7 @@ module Gitlab
module Entities
class User < Grape::Entity
expose :id, :username, :email, :name, :bio, :skype, :linkedin, :twitter,
:dark_scheme, :theme_id, :blocked, :created_at
:dark_scheme, :theme_id, :blocked, :created_at, :extern_uid, :provider
end
class UserBasic < Grape::Entity
......@@ -21,6 +21,7 @@ module Gitlab
expose :id, :name, :description, :default_branch
expose :owner, using: Entities::UserBasic
expose :private_flag, as: :private
expose :path, :path_with_namespace
expose :issues_enabled, :merge_requests_enabled, :wall_enabled, :wiki_enabled, :created_at
expose :namespace
end
......@@ -31,8 +32,22 @@ module Gitlab
end
end
class Group < Grape::Entity
expose :id, :name, :path, :owner_id
end
class GroupDetail < Group
expose :projects, using: Entities::Project
end
class RepoObject < Grape::Entity
expose :name, :commit
expose :protected do |repo, options|
if options[:project]
options[:project].protected_branch? repo.name
end
end
end
class RepoCommit < Grape::Entity
......
module Gitlab
# groups API
class Groups < Grape::API
before { authenticate! }
resource :groups do
# Get a groups list
#
# Example Request:
# GET /groups
get do
if current_user.admin
@groups = paginate Group
else
@groups = paginate current_user.groups
end
present @groups, with: Entities::Group
end
# Create group. Available only for admin
#
# Parameters:
# name (required) - Name
# path (required) - Path
# Example Request:
# POST /groups
post do
authenticated_as_admin!
attrs = attributes_for_keys [:name, :path]
@group = Group.new(attrs)
@group.owner = current_user
if @group.save
present @group, with: Entities::Group
else
not_found!
end
end
# Get a single group, with containing projects
#
# Parameters:
# id (required) - The ID of a group
# Example Request:
# GET /groups/:id
get ":id" do
@group = Group.find(params[:id])
if current_user.admin or current_user.groups.include? @group
present @group, with: Entities::GroupDetail
else
not_found!
end
end
end
end
end
module Gitlab
# Internal access API
class Internal < Grape::API
namespace 'internal' do
#
# Check if ssh key has access to project code
#
get "/allowed" do
key = Key.find(params[:key_id])
project = Project.find_with_namespace(params[:project])
git_cmd = params[:action]
if key.is_deploy_key
project == key.project && git_cmd == 'git-upload-pack'
else
user = key.user
action = case git_cmd
when 'git-upload-pack'
then :download_code
when 'git-receive-pack'
then
if project.protected_branch?(params[:ref])
:push_code_to_protected_branches
else
:push_code
end
end
user.can?(action, project)
end
end
#
# Discover user by ssh key
#
get "/discover" do
key = Key.find(params[:key_id])
present key.user, with: Entities::User
end
get "/check" do
{
api_version: '3'
}
end
end
end
end
......@@ -3,7 +3,7 @@ module Gitlab
class Notes < Grape::API
before { authenticate! }
NOTEABLE_TYPES = [Issue, Snippet]
NOTEABLE_TYPES = [Issue, MergeRequest, Snippet]
resource :projects do
# Get a list of project wall notes
......
......@@ -222,7 +222,7 @@ module Gitlab
# Example Request:
# GET /projects/:id/repository/branches
get ":id/repository/branches" do
present user_project.repo.heads.sort_by(&:name), with: Entities::RepoObject
present user_project.repo.heads.sort_by(&:name), with: Entities::RepoObject, project: user_project
end
# Get a single branch
......@@ -234,7 +234,43 @@ module Gitlab
# GET /projects/:id/repository/branches/:branch
get ":id/repository/branches/:branch" do
@branch = user_project.repo.heads.find { |item| item.name == params[:branch] }
present @branch, with: Entities::RepoObject
present @branch, with: Entities::RepoObject, project: user_project
end
# Protect a single branch
#
# Parameters:
# id (required) - The ID of a project
# branch (required) - The name of the branch
# Example Request:
# PUT /projects/:id/repository/branches/:branch/protect
put ":id/repository/branches/:branch/protect" do
@branch = user_project.repo.heads.find { |item| item.name == params[:branch] }
protected = user_project.protected_branches.find_by_name(@branch.name)
unless protected
user_project.protected_branches.create(:name => @branch.name)
end
present @branch, with: Entities::RepoObject, project: user_project
end
# Unprotect a single branch
#
# Parameters:
# id (required) - The ID of a project
# branch (required) - The name of the branch
# Example Request:
# PUT /projects/:id/repository/branches/:branch/unprotect
put ":id/repository/branches/:branch/unprotect" do
@branch = user_project.repo.heads.find { |item| item.name == params[:branch] }
protected = user_project.protected_branches.find_by_name(@branch.name)
if protected
protected.destroy
end
present @branch, with: Entities::RepoObject, project: user_project
end
# Get a project repository tags
......
......@@ -34,11 +34,14 @@ module Gitlab
# linkedin - Linkedin
# twitter - Twitter account
# projects_limit - Number of projects user can create
# extern_uid - External authentication provider UID
# provider - External provider
# bio - Bio
# Example Request:
# POST /users
post do
authenticated_as_admin!
attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username]
attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio]
user = User.new attrs, as: :admin
if user.save
present user, with: Entities::User
......@@ -46,6 +49,48 @@ module Gitlab
not_found!
end
end
# Update user. Available only for admin
#
# Parameters:
# email - Email
# name - Name
# password - Password
# skype - Skype ID
# linkedin - Linkedin
# twitter - Twitter account
# projects_limit - Limit projects wich user can create
# extern_uid - External authentication provider UID
# provider - External provider
# bio - Bio
# Example Request:
# PUT /users/:id
put ":id" do
authenticated_as_admin!
attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio]
user = User.find_by_id(params[:id])
if user && user.update_attributes(attrs)
present user, with: Entities::User
else
not_found!
end
end
# Delete user. Available only for admin
#
# Example Request:
# DELETE /users/:id
delete ":id" do
authenticated_as_admin!
user = User.find_by_id(params[:id])
if user
user.destroy
else
not_found!
end
end
end
resource :user do
......
......@@ -54,9 +54,10 @@ module ExtractsPath
input.gsub!(/^#{Gitlab.config.gitlab.relative_url_root}/, "")
# Remove project, actions and all other staff from path
input.gsub!(/^\/#{Regexp.escape(@project.path_with_namespace)}/, "")
input.gsub!(/^\/(tree|commits|blame|blob|refs)\//, "") # remove actions
input.gsub!(/^\/(tree|commits|blame|blob|refs|graph)\//, "") # remove actions
input.gsub!(/\?.*$/, "") # remove stamps suffix
input.gsub!(/.atom$/, "") # remove rss feed
input.gsub!(/.json$/, "") # remove json suffix
input.gsub!(/\/edit$/, "") # remove edit route part
if input.match(/^([[:alnum:]]{40})(.+)/)
......
require_relative 'gitolite_config'
module Gitlab
class Gitolite
class AccessDenied < StandardError; end
def config
Gitlab::GitoliteConfig.new
end
# Update gitolite config with new key
#
# Ex.
# set_key("m_gitlab_com_12343", "sha-rsa ...", [2, 3, 6])
#
def set_key(key_id, key_content, project_ids)
projects = Project.where(id: project_ids)
config.apply do |config|
config.write_key(key_id, key_content)
config.update_projects(projects)
end
end
# Remove ssh key from gitolite config
#
# Ex.
# remove_key("m_gitlab_com_12343", [2, 3, 6])
#
def remove_key(key_id, project_ids)
projects = Project.where(id: project_ids)
config.apply do |config|
config.rm_key(key_id)
config.update_projects(projects)
end
end
# Update project config in gitolite by project id
#
# Ex.
# update_repository(23)
#
def update_repository(project_id)
project = Project.find(project_id)
config.update_project!(project)
end
def move_repository(old_repo, project)
config.apply do |config|
config.clean_repo(old_repo)
config.update_project(project)
end
end
# Remove repository from gitolite
#
# name - project path with namespace
#
# Ex.
# remove_repository("gitlab/gitlab-ci")
#
def remove_repository(name)
config.destroy_project!(name)
end
# Update projects configs in gitolite by project ids
#
# Ex.
# update_repositories([1, 4, 6])
#
def update_repositories(project_ids)
projects = Project.where(id: project_ids)
config.apply do |config|
config.update_projects(projects)
end
end
def url_to_repo path
Gitlab.config.gitolite.ssh_path_prefix + "#{path}.git"
end
def enable_automerge
config.admin_all_repo!
end
alias_method :create_repository, :update_repository
end
end
require 'gitolite'
require 'timeout'
require 'fileutils'
module Gitlab
class GitoliteConfig
include Gitlab::Popen
class PullError < StandardError; end
class PushError < StandardError; end
class BrokenGitolite < StandardError; end
attr_reader :config_tmp_dir, :tmp_dir, :ga_repo, :conf
def initialize
@tmp_dir = Rails.root.join("tmp").to_s
@config_tmp_dir = File.join(@tmp_dir,"gitlabhq-gitolite-#{Time.now.to_i}")
end
def ga_repo
@ga_repo ||= ::Gitolite::GitoliteAdmin.new(
File.join(config_tmp_dir,'gitolite'),
conf: Gitlab.config.gitolite.config_file
)
end
def apply
Timeout::timeout(30) do
File.open(File.join(tmp_dir, "gitlabhq-gitolite.lock"), "w+") do |f|
begin
# Set exclusive lock
# to prevent race condition
f.flock(File::LOCK_EX)
# Pull gitolite-admin repo
# in tmp dir before do any changes
pull
# Build ga_repo object and @conf
# to access gitolite-admin configuration
@conf = ga_repo.config
# Do any changes
# in gitolite-admin
# config here
yield(self)
# Save changes in
# gitolite-admin repo
# before push it
ga_repo.save
# Push gitolite-admin repo
# to apply all changes
push
ensure
# Remove tmp dir
# removing the gitolite folder first is important to avoid
# NFS issues.
FileUtils.rm_rf(File.join(config_tmp_dir, 'gitolite'))
# Remove parent tmp dir
FileUtils.rm_rf(config_tmp_dir)
# Unlock so other task can access
# gitolite configuration
f.flock(File::LOCK_UN)
end
end
end
rescue PullError => ex
log("Pull error -> " + ex.message)
raise Gitolite::AccessDenied, ex.message
rescue PushError => ex
log("Push error -> " + " " + ex.message)
raise Gitolite::AccessDenied, ex.message
rescue BrokenGitolite => ex
log("Gitolite error -> " + " " + ex.message)
raise Gitolite::AccessDenied, ex.message
rescue Exception => ex
log(ex.class.name + " " + ex.message)
raise Gitolite::AccessDenied.new("gitolite timeout")
end
def log message
Gitlab::GitLogger.error(message)
end
def path_to_repo(name)
File.join(Gitlab.config.gitolite.repos_path, "#{name}.git")
end
def destroy_project(name)
full_path = path_to_repo(name)
FileUtils.rm_rf(full_path) if File.exists?(full_path)
conf.rm_repo(name)
end
def clean_repo repo_name
conf.rm_repo(repo_name)
end
def destroy_project!(project)
apply do |config|
config.destroy_project(project)
end
end
def write_key(id, key)
File.open(File.join(config_tmp_dir, 'gitolite/keydir',"#{id}.pub"), 'w') do |f|
f.write(key.gsub(/\n/,''))
end
end
def rm_key(user)
key_path = File.join(config_tmp_dir, 'gitolite/keydir', "#{user}.pub")
ga_key = ::Gitolite::SSHKey.from_file(key_path)
ga_repo.rm_key(ga_key)
end
# update or create
def update_project(project)
repo = update_project_config(project, conf)
conf.add_repo(repo, true)
end
def update_project!( project)
apply do |config|
config.update_project(project)
end
end
# Updates many projects and uses project.path_with_namespace as the repo path
# An order of magnitude faster than update_project
def update_projects(projects)
projects.each do |project|
repo = update_project_config(project, conf)
conf.add_repo(repo, true)
end
end
def update_project_config(project, conf)
repo_name = project.path_with_namespace
repo = if conf.has_repo?(repo_name)
conf.get_repo(repo_name)
else
::Gitolite::Config::Repo.new(repo_name)
end
name_readers = project.team.repository_readers
name_writers = project.team.repository_writers
name_masters = project.team.repository_masters
pr_br = project.protected_branches.map(&:name).join("$ ")
repo.clean_permissions
# Deny access to protected branches for writers
unless name_writers.blank? || pr_br.blank?
repo.add_permission("-", pr_br.strip + "$ ", name_writers)
end
# Add read permissions
repo.add_permission("R", "", name_readers) unless name_readers.blank?
# Add write permissions
repo.add_permission("RW+", "", name_writers) unless name_writers.blank?
repo.add_permission("RW+", "", name_masters) unless name_masters.blank?
# Add sharedRepository config
repo.set_git_config("core.sharedRepository", "0660")
repo
end
# Enable access to all repos for gitolite admin.
# We use it for accept merge request feature
def admin_all_repo
owner_name = Gitlab.config.gitolite.admin_key
# @ALL repos premission for gitolite owner
repo_name = "@all"
repo = if conf.has_repo?(repo_name)
conf.get_repo(repo_name)
else
::Gitolite::Config::Repo.new(repo_name)
end
repo.add_permission("RW+", "", owner_name)
conf.add_repo(repo, true)
end
def admin_all_repo!
apply { |config| config.admin_all_repo }
end
private
def pull
# Create config tmp dir like "RAILS_ROOT/tmp/gitlabhq-gitolite-132545"
Dir.mkdir config_tmp_dir
# Clone gitolite-admin repo into tmp dir
popen("git clone #{Gitlab.config.gitolite.admin_uri} #{config_tmp_dir}/gitolite", tmp_dir)
# Ensure file with config presents after cloning
unless File.exists?(File.join(config_tmp_dir, 'gitolite', 'conf', 'gitolite.conf'))
raise PullError, "unable to clone gitolite-admin repo"
end
end
def push
output, status = popen('git add -A', tmp_conf_path)
raise "Git add failed." unless status.zero?
# git commit returns 0 on success, and 1 if there is nothing to commit
output, status = popen('git commit -m "GitLab"', tmp_conf_path)
raise "Git add failed." unless [0,1].include?(status)
output, status = popen('git push', tmp_conf_path)
if output =~ /remote\: FATAL/
raise BrokenGitolite, output
end
if status.zero? || output =~ /Everything up\-to\-date/
return true
else
raise PushError, "unable to push gitolite-admin repo"
end
end
def tmp_conf_path
File.join(config_tmp_dir,'gitolite')
end
end
end
module Gitlab
class Shell
class AccessDenied < StandardError; end
# Init new repository
#
# name - project path with namespace
#
# Ex.
# add_repository("gitlab/gitlab-ci")
#
def add_repository(name)
system("/home/git/gitlab-shell/bin/gitlab-projects add-project #{name}.git")
end
# Remove repository from file system
#
# name - project path with namespace
#
# Ex.
# remove_repository("gitlab/gitlab-ci")
#
def remove_repository(name)
system("/home/git/gitlab-shell/bin/gitlab-projects rm-project #{name}.git")
end
# Add new key to gitlab-shell
#
# Ex.
# add_key("key-42", "sha-rsa ...")
#
def add_key(key_id, key_content)
system("/home/git/gitlab-shell/bin/gitlab-keys add-key #{key_id} \"#{key_content}\"")
end
# Remove ssh key from gitlab shell
#
# Ex.
# remove_key("key-342", "sha-rsa ...")
#
def remove_key(key_id, key_content)
system("/home/git/gitlab-shell/bin/gitlab-keys rm-key #{key_id} \"#{key_content}\"")
end
def url_to_repo path
Gitlab.config.gitolite.ssh_path_prefix + "#{path}.git"
end
end
end
......@@ -5,12 +5,13 @@ module Gitlab
class Commit
include ActionView::Helpers::TagHelper
attr_accessor :time, :space, :refs
attr_accessor :time, :space, :refs, :parent_spaces
def initialize(commit)
@_commit = commit
@time = -1
@space = 0
@parent_spaces = []
end
def method_missing(m, *args, &block)
......@@ -28,6 +29,7 @@ module Gitlab
}
h[:time] = time
h[:space] = space
h[:parent_spaces] = parent_spaces
h[:refs] = refs.collect{|r|r.name}.join(" ") unless refs.nil?
h[:id] = sha
h[:date] = date
......
......@@ -9,14 +9,14 @@ module Gitlab
@max_count ||= 650
end
def initialize project
def initialize project, ref
@project = project
@ref = ref
@repo = project.repo
@ref_cache = {}
@commits = collect_commits
@days = index_commits
@space = 0
end
def to_json(*args)
......@@ -53,7 +53,7 @@ module Gitlab
#
# @return [Array<TimeDate>] list of commit dates corelated with time on commits
def index_commits
days, heads = [], []
days, heads, times = [], [], []
map = {}
commits.reverse.each_with_index do |c,i|
......@@ -61,14 +61,15 @@ module Gitlab
days[i] = c.committed_date
map[c.id] = c
heads += c.refs unless c.refs.nil?
times[i] = c
end
heads.select!{|h| h.is_a? Grit::Head or h.is_a? Grit::Remote}
# sort heads so the master is top and current branches are closer
heads.sort! do |a,b|
if a.name == "master"
if a.name == @ref
-1
elsif b.name == "master"
elsif b.name == @ref
1
else
b.commit.committed_date <=> a.commit.committed_date
......@@ -86,9 +87,62 @@ module Gitlab
end
end
# find parent spaces for not overlap lines
times.each do |c|
c.parent_spaces.concat(find_free_parent_spaces(c, map, times))
end
days
end
def find_free_parent_spaces(commit, map, times)
spaces = []
commit.parents.each do |p|
if map.include?(p.id) then
parent = map[p.id]
range = if commit.time < parent.time then
commit.time..parent.time
else
parent.time..commit.time
end
space = if commit.space >= parent.space then
find_free_parent_space(range, parent.space, 1, commit.space, times)
else
find_free_parent_space(range, parent.space, -1, parent.space, times)
end
mark_reserved(range, space)
spaces << space
end
end
spaces
end
def find_free_parent_space(range, space_base, space_step, space_default, times)
if is_overlap?(range, times, space_default) then
find_free_space(range, space_base, space_step)
else
space_default
end
end
def is_overlap?(range, times, overlap_space)
range.each do |i|
if i != range.first &&
i != range.last &&
times[i].space == overlap_space then
return true;
end
end
false
end
# Add space mark on commit and its parents
#
# @param [Graph::Commit] the commit object.
......@@ -98,10 +152,9 @@ module Gitlab
if leaves.empty?
return
end
@space = find_free_space(leaves, map)
leaves.each{|l| l.space = @space}
# and mark it as reserved
min_time = leaves.last.time
max_space = 1
parents = leaves.last.parents.collect
parents.each do |p|
if map.include? p.id
......@@ -109,6 +162,9 @@ module Gitlab
if parent.time < min_time
min_time = parent.time
end
if max_space < parent.space then
max_space = parent.space
end
end
end
if parent_time.nil?
......@@ -116,7 +172,12 @@ module Gitlab
else
max_time = parent_time - 1
end
mark_reserved(min_time..max_time, @space)
time_range = leaves.last.time..leaves.first.time
space = find_free_space(time_range, max_space, 2)
leaves.each{|l| l.space = space}
mark_reserved(min_time..max_time, space)
# Visit branching chains
leaves.each do |l|
......@@ -133,30 +194,25 @@ module Gitlab
end
end
def find_free_space(leaves, map)
time_range = leaves.last.time..leaves.first.time
def find_free_space(time_range, space_base, space_step)
reserved = []
for day in time_range
reserved += @_reserved[day]
end
space = base_space(leaves, map)
while (reserved.include? space) || (space == @space) do
space += 1
reserved.uniq!
space = space_base
while reserved.include?(space) do
space += space_step
if space <= 0 then
space_step *= -1
space = space_base + space_step
end
end
space
end
def base_space(leaves, map)
parents = []
leaves.each do |l|
parents.concat l.parents.collect.select{|p| map.include? p.id and map[p.id].space.nonzero?}
end
space = parents.map{|p| map[p.id].space}.max || 0
space += 1
end
# Takes most left subtree branch of commits
# which don't have space mark yet.
#
......
......@@ -30,10 +30,10 @@ module Gitlab
end
def create
output, status = popen("git clone #{project.url_to_repo} #{path}",
output, status = popen("git clone #{project.repository.path_to_repo} #{path}",
Gitlab.config.satellites.path)
log("PID: #{project.id}: git clone #{project.url_to_repo} #{path}")
log("PID: #{project.id}: git clone #{project.repository.path_to_repo} #{path}")
log("PID: #{project.id}: -> #{output}")
if status.zero?
......
......@@ -6,6 +6,6 @@
#
module Gitolited
def gitolite
Gitlab::Gitolite.new
Gitlab::Shell.new
end
end
#!/usr/bin/env bash
# Version 4.1
# This file was placed here by GitLab. It makes sure that your pushed commits
# will be processed properly.
while read oldrev newrev ref
do
# For every branch or tag that was pushed, create a Resque job in redis.
repo_path=`pwd`
env -i redis-cli rpush "resque:gitlab:queue:post_receive" "{\"class\":\"PostReceive\",\"args\":[\"$repo_path\",\"$oldrev\",\"$newrev\",\"$ref\",\"$GL_USER\"]}" > /dev/null 2>&1
done
#!/bin/bash
src="/home/git/repositories"
for dir in `ls "$src/"`
do
if [ -d "$src/$dir" ]; then
if [ "$dir" = "gitolite-admin.git" ]
then
continue
fi
if [[ "$dir" =~ ^.*.git$ ]]
then
project_hook="$src/$dir/hooks/post-receive"
gitolite_hook="/home/git/.gitolite/hooks/common/post-receive"
ln -s -f $gitolite_hook $project_hook
else
for subdir in `ls "$src/$dir/"`
do
if [ -d "$src/$dir/$subdir" ] && [[ "$subdir" =~ ^.*.git$ ]]; then
project_hook="$src/$dir/$subdir/hooks/post-receive"
gitolite_hook="/home/git/.gitolite/hooks/common/post-receive"
ln -s -f $gitolite_hook $project_hook
fi
done
fi
fi
done
#!/bin/bash
echo "Danger!!! Data Loss"
while true; do
read -p "Do you wish to all directories except gitolite-admin.git from /home/git/repositories/ (y/n) ?: " yn
case $yn in
[Yy]* ) sh -c "find /home/git/repositories/. -maxdepth 1 -not -name 'gitolite-admin.git' -not -name '.' | xargs sudo rm -rf"; break;;
[Nn]* ) exit;;
* ) echo "Please answer yes or no.";;
esac
done
......@@ -716,7 +716,7 @@ namespace :gitlab do
end
def check_repo_base_permissions
print "Repo base access is drwsrws---? ... "
print "Repo base access is drwxrws---? ... "
repo_base_path = Gitlab.config.gitolite.repos_path
unless File.exists?(repo_base_path)
......@@ -724,12 +724,14 @@ namespace :gitlab do
return
end
if File.stat(repo_base_path).mode.to_s(8).ends_with?("6770")
if File.stat(repo_base_path).mode.to_s(8).ends_with?("2770")
puts "yes".green
else
puts "no".red
try_fixing_it(
"sudo chmod -R ug+rwXs,o-rwx #{repo_base_path}"
"sudo chmod -R ug+rwX,o-rwx #{repo_base_path}",
"sudo chmod -R ug-s #{repo_base_path}",
"find #{repo_base_path} -type d -print0 | sudo xargs -0 chmod g+s"
)
for_more_information(
see_installation_guide_section "Gitolite"
......@@ -780,21 +782,25 @@ namespace :gitlab do
Project.find_each(batch_size: 100) do |project|
print "#{project.name_with_namespace.yellow} ... "
correct_options = options.map do |name, value|
run("git --git-dir=\"#{project.repository.path_to_repo}\" config --get #{name}").try(:chomp) == value
end
if correct_options.all?
puts "ok".green
if project.empty_repo?
puts "repository is empty".magenta
else
puts "wrong or missing".red
try_fixing_it(
sudo_gitlab("bundle exec rake gitlab:gitolite:update_repos RAILS_ENV=production")
)
for_more_information(
"doc/raketasks/maintenance.md"
)
fix_and_rerun
correct_options = options.map do |name, value|
run("git --git-dir=\"#{project.repository.path_to_repo}\" config --get #{name}").try(:chomp) == value
end
if correct_options.all?
puts "ok".green
else
puts "wrong or missing".red
try_fixing_it(
sudo_gitlab("bundle exec rake gitlab:gitolite:update_repos RAILS_ENV=production")
)
for_more_information(
"doc/raketasks/maintenance.md"
)
fix_and_rerun
end
end
end
end
......@@ -820,32 +826,37 @@ namespace :gitlab do
Project.find_each(batch_size: 100) do |project|
print "#{project.name_with_namespace.yellow} ... "
project_hook_file = File.join(project.repository.path_to_repo, "hooks", hook_file)
unless File.exists?(project_hook_file)
puts "missing".red
try_fixing_it(
"sudo -u #{gitolite_ssh_user} ln -sf #{gitolite_hook_file} #{project_hook_file}"
)
for_more_information(
"lib/support/rewrite-hooks.sh"
)
fix_and_rerun
next
end
if File.lstat(project_hook_file).symlink? &&
File.realpath(project_hook_file) == File.realpath(gitolite_hook_file)
puts "ok".green
if project.empty_repo?
puts "repository is empty".magenta
else
puts "not a link to Gitolite's hook".red
try_fixing_it(
"sudo -u #{gitolite_ssh_user} ln -sf #{gitolite_hook_file} #{project_hook_file}"
)
for_more_information(
"lib/support/rewrite-hooks.sh"
)
fix_and_rerun
project_hook_file = File.join(project.repository.path_to_repo, "hooks", hook_file)
unless File.exists?(project_hook_file)
puts "missing".red
try_fixing_it(
"sudo -u #{gitolite_ssh_user} ln -sf #{gitolite_hook_file} #{project_hook_file}"
)
for_more_information(
"lib/support/rewrite-hooks.sh"
)
fix_and_rerun
next
end
if File.lstat(project_hook_file).symlink? &&
File.realpath(project_hook_file) == File.realpath(gitolite_hook_file)
puts "ok".green
else
puts "not a link to Gitolite's hook".red
try_fixing_it(
"sudo -u #{gitolite_ssh_user} ln -sf #{gitolite_hook_file} #{project_hook_file}"
)
for_more_information(
"lib/support/rewrite-hooks.sh"
)
fix_and_rerun
end
end
end
end
......
......@@ -3,11 +3,6 @@ namespace :gitlab do
task :enable_automerge => :environment do
warn_user_is_not_gitlab
puts "Updating repo permissions ..."
Gitlab::Gitolite.new.enable_automerge
puts "... #{"done".green}"
puts ""
print "Creating satellites for ..."
unless Project.count > 0
puts "skipping, because you have no projects".magenta
......
namespace :gitlab do
namespace :shell do
desc "GITLAB | Setup gitlab-shell"
task :setup => :environment do
setup
end
end
def setup
warn_user_is_not_gitlab
puts "This will rebuild an authorized_keys file."
puts "You will lose any data stored in /home/git/.ssh/authorized_keys."
ask_to_continue
puts ""
system("echo '# Managed by gitlab-shell' > /home/git/.ssh/authorized_keys")
Key.find_each(:batch_size => 1000) do |key|
if Gitlab::Shell.new.add_key(key.shell_id, key.key)
print '.'
else
print 'F'
end
end
rescue Gitlab::TaskAbortedByUserError
puts "Quitting...".red
exit 1
end
end
# == Schema Information
#
# Table name: user_team_project_relationships
#
# id :integer not null, primary key
# project_id :integer
# user_team_id :integer
# greatest_access :integer
# created_at :datetime not null
# updated_at :datetime not null
#
# Read about factories at https://github.com/thoughtbot/factory_girl
FactoryGirl.define do
......
# == Schema Information
#
# Table name: user_team_user_relationships
#
# id :integer not null, primary key
# user_id :integer
# user_team_id :integer
# group_admin :boolean
# permission :integer
# created_at :datetime not null
# updated_at :datetime not null
#
# Read about factories at https://github.com/thoughtbot/factory_girl
FactoryGirl.define do
......
# == Schema Information
#
# Table name: user_teams
#
# id :integer not null, primary key
# name :string(255)
# path :string(255)
# owner_id :integer
# created_at :datetime not null
# updated_at :datetime not null
#
# Read about factories at https://github.com/thoughtbot/factory_girl
FactoryGirl.define do
......
require 'spec_helper'
describe Gitlab::GitoliteConfig do
let(:gitolite) { Gitlab::GitoliteConfig.new }
it { should respond_to :write_key }
it { should respond_to :rm_key }
it { should respond_to :update_project }
it { should respond_to :update_project! }
it { should respond_to :update_projects }
it { should respond_to :destroy_project }
it { should respond_to :destroy_project! }
it { should respond_to :apply }
it { should respond_to :admin_all_repo }
it { should respond_to :admin_all_repo! }
end
require 'spec_helper'
describe Gitlab::Gitolite do
describe Gitlab::Shell do
let(:project) { double('Project', id: 7, path: 'diaspora') }
let(:gitolite_config) { double('Gitlab::GitoliteConfig') }
let(:gitolite) { Gitlab::Gitolite.new }
let(:gitolite) { Gitlab::Shell.new }
before do
gitolite.stub(config: gitolite_config)
Project.stub(find: project)
end
it { should respond_to :set_key }
it { should respond_to :add_key }
it { should respond_to :remove_key }
it { should respond_to :update_repository }
it { should respond_to :create_repository }
it { should respond_to :add_repository }
it { should respond_to :remove_repository }
it { gitolite.url_to_repo('diaspora').should == Gitlab.config.gitolite.ssh_path_prefix + "diaspora.git" }
it "should call config update" do
gitolite_config.should_receive(:update_project!)
gitolite.update_repository(project.id)
end
end
......@@ -266,7 +266,7 @@ describe Notify do
before(:each) { note.stub(:noteable).and_return(commit) }
subject { Notify.note_commit_email(recipient.email, note.id) }
subject { Notify.note_commit_email(recipient.id, note.id) }
it_behaves_like 'a note email'
......
......@@ -46,9 +46,9 @@ describe Key do
key.should_not be_valid
end
it "does accept the same key for another project" do
it "does not accept the same key for another project" do
key = build(:key, project_id: 0)
key.should be_valid
key.should_not be_valid
end
end
......
......@@ -8,7 +8,6 @@
# description :text
# created_at :datetime not null
# updated_at :datetime not null
# private_flag :boolean default(TRUE), not null
# creator_id :integer
# default_branch :string(255)
# issues_enabled :boolean default(TRUE), not null
......@@ -16,6 +15,7 @@
# merge_requests_enabled :boolean default(TRUE), not null
# wiki_enabled :boolean default(TRUE), not null
# namespace_id :integer
# public :boolean default(FALSE), not null
#
require 'spec_helper'
......@@ -42,7 +42,6 @@ describe Project do
describe "Mass assignment" do
it { should_not allow_mass_assignment_of(:namespace_id) }
it { should_not allow_mass_assignment_of(:creator_id) }
it { should_not allow_mass_assignment_of(:private_flag) }
end
describe "Validation" do
......@@ -78,8 +77,6 @@ describe Project do
it { should respond_to(:url_to_repo) }
it { should respond_to(:repo_exists?) }
it { should respond_to(:satellite) }
it { should respond_to(:update_repository) }
it { should respond_to(:destroy_repository) }
it { should respond_to(:observe_push) }
it { should respond_to(:update_merge_requests) }
it { should respond_to(:execute_hooks) }
......
......@@ -24,19 +24,4 @@ describe ProtectedBranch do
it { should validate_presence_of(:project) }
it { should validate_presence_of(:name) }
end
describe 'Callbacks' do
let(:branch) { build(:protected_branch) }
it 'call update_repository after save' do
branch.should_receive(:update_repository)
branch.save
end
it 'call update_repository after destroy' do
branch.save
branch.should_receive(:update_repository)
branch.destroy
end
end
end
......@@ -31,6 +31,8 @@
# extern_uid :string(255)
# provider :string(255)
# username :string(255)
# can_create_group :boolean default(TRUE), not null
# can_create_team :boolean default(TRUE), not null
#
require 'spec_helper'
......
# == Schema Information
#
# Table name: user_team_project_relationships
#
# id :integer not null, primary key
# project_id :integer
# user_team_id :integer
# greatest_access :integer
# created_at :datetime not null
# updated_at :datetime not null
#
require 'spec_helper'
describe UserTeamProjectRelationship do
......
# == Schema Information
#
# Table name: user_teams
#
# id :integer not null, primary key
# name :string(255)
# path :string(255)
# owner_id :integer
# created_at :datetime not null
# updated_at :datetime not null
#
require 'spec_helper'
describe UserTeam do
......
# == Schema Information
#
# Table name: user_team_user_relationships
#
# id :integer not null, primary key
# user_id :integer
# user_team_id :integer
# group_admin :boolean
# permission :integer
# created_at :datetime not null
# updated_at :datetime not null
#
require 'spec_helper'
describe UserTeamUserRelationship do
......
......@@ -3,7 +3,7 @@ require 'spec_helper'
describe KeyObserver do
before do
@key = double('Key',
identifier: 'admin_654654',
shell_id: 'key-32',
key: '== a vaild ssh key',
projects: [],
is_deploy_key: false
......@@ -14,14 +14,14 @@ describe KeyObserver do
context :after_save do
it do
GitoliteWorker.should_receive(:perform_async).with(:set_key, @key.identifier, @key.key, @key.projects.map(&:id))
GitoliteWorker.should_receive(:perform_async).with(:add_key, @key.shell_id, @key.key)
@observer.after_save(@key)
end
end
context :after_destroy do
it do
GitoliteWorker.should_receive(:perform_async).with(:remove_key, @key.identifier, @key.projects.map(&:id))
GitoliteWorker.should_receive(:perform_async).with(:remove_key, @key.shell_id, @key.key)
@observer.after_destroy(@key)
end
end
......
require 'spec_helper'
describe Gitlab::API do
include ApiHelpers
let(:user1) { create(:user) }
let(:user2) { create(:user) }
let(:admin) { create(:admin) }
let!(:group1) { create(:group, owner: user1) }
let!(:group2) { create(:group, owner: user2) }
describe "GET /groups" do
context "when unauthenticated" do
it "should return authentication error" do
get api("/groups")
response.status.should == 401
end
end
context "when authenticated as user" do
it "normal user: should return an array of groups of user1" do
get api("/groups", user1)
response.status.should == 200
json_response.should be_an Array
json_response.length.should == 1
json_response.first['name'].should == group1.name
end
end
context "when authenticated as admin" do
it "admin: should return an array of all groups" do
get api("/groups", admin)
response.status.should == 200
json_response.should be_an Array
json_response.length.should == 2
end
end
end
describe "GET /groups/:id" do
context "when authenticated as user" do
it "should return one of user1's groups" do
get api("/groups/#{group1.id}", user1)
response.status.should == 200
json_response['name'] == group1.name
end
it "should not return a non existing group" do
get api("/groups/1328", user1)
response.status.should == 404
end
it "should not return a group not attached to user1" do
get api("/groups/#{group2.id}", user1)
response.status.should == 404
end
end
context "when authenticated as admin" do
it "should return any existing group" do
get api("/groups/#{group2.id}", admin)
response.status.should == 200
json_response['name'] == group2.name
end
it "should not return a non existing group" do
get api("/groups/1328", admin)
response.status.should == 404
end
end
end
describe "POST /groups" do
context "when authenticated as user" do
it "should not create group" do
post api("/groups", user1), attributes_for(:group)
response.status.should == 403
end
end
context "when authenticated as admin" do
it "should create group" do
post api("/groups", admin), attributes_for(:group)
response.status.should == 201
end
it "should not create group, duplicate" do
post api("/groups", admin), {:name => "Duplicate Test", :path => group2.path}
response.status.should == 404
end
end
end
end
......@@ -6,8 +6,10 @@ describe Gitlab::API do
let(:user) { create(:user) }
let!(:project) { create(:project, namespace: user.namespace ) }
let!(:issue) { create(:issue, project: project, author: user) }
let!(:merge_request) { create(:merge_request, project: project, author: user) }
let!(:snippet) { create(:snippet, project: project, author: user) }
let!(:issue_note) { create(:note, noteable: issue, project: project, author: user) }
let!(:merge_request_note) { create(:note, noteable: merge_request, project: project, author: user) }
let!(:snippet_note) { create(:note, noteable: snippet, project: project, author: user) }
let!(:wall_note) { create(:note, project: project, author: user) }
before { project.team << [user, :reporter] }
......@@ -84,6 +86,15 @@ describe Gitlab::API do
response.status.should == 404
end
end
context "when noteable is a Merge Request" do
it "should return an array of merge_requests notes" do
get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/notes", user)
response.status.should == 200
json_response.should be_an Array
json_response.first['body'].should == merge_request_note.note
end
end
end
describe "GET /projects/:id/noteable/:noteable_id/notes/:note_id" do
......
......@@ -113,6 +113,29 @@ describe Gitlab::API do
json_response['name'].should == 'new_design'
json_response['commit']['id'].should == '621491c677087aa243f165eab467bfdfbee00be1'
json_response['protected'].should == false
end
end
describe "PUT /projects/:id/repository/branches/:branch/protect" do
it "should protect a single branch" do
put api("/projects/#{project.id}/repository/branches/new_design/protect", user)
response.status.should == 200
json_response['name'].should == 'new_design'
json_response['commit']['id'].should == '621491c677087aa243f165eab467bfdfbee00be1'
json_response['protected'].should == true
end
end
describe "PUT /projects/:id/repository/branches/:branch/unprotect" do
it "should unprotect a single branch" do
put api("/projects/#{project.id}/repository/branches/new_design/unprotect", user)
response.status.should == 200
json_response['name'].should == 'new_design'
json_response['commit']['id'].should == '621491c677087aa243f165eab467bfdfbee00be1'
json_response['protected'].should == false
end
end
......
......@@ -83,6 +83,54 @@ describe Gitlab::API do
end
end
describe "PUT /users/:id" do
before { admin }
it "should update user" do
put api("/users/#{user.id}", admin), {bio: 'new test bio'}
response.status.should == 200
json_response['bio'].should == 'new test bio'
user.reload.bio.should == 'new test bio'
end
it "should not allow invalid update" do
put api("/users/#{user.id}", admin), {email: 'invalid email'}
response.status.should == 404
user.reload.email.should_not == 'invalid email'
end
it "shouldn't available for non admin users" do
put api("/users/#{user.id}", user), attributes_for(:user)
response.status.should == 403
end
it "should return 404 for non-existing user" do
put api("/users/999999", admin), {bio: 'update should fail'}
response.status.should == 404
end
end
describe "DELETE /users/:id" do
before { admin }
it "should delete user" do
delete api("/users/#{user.id}", admin)
response.status.should == 200
expect { User.find(user.id) }.to raise_error ActiveRecord::RecordNotFound
json_response['email'].should == user.email
end
it "shouldn't available for non admin users" do
delete api("/users/#{user.id}", user)
response.status.should == 403
end
it "should return 404 for non-existing user" do
delete api("/users/999999", admin)
response.status.should == 404
end
end
describe "GET /user" do
it "should return current user" do
get api("/user", user)
......
......@@ -22,9 +22,9 @@ describe "On a merge request", js: true do
it { within(".js-main-target-form") { should_not have_link("Cancel") } }
# notifiactions
it { within(".js-main-target-form") { should have_checked_field("Project team") } }
it { within(".js-main-target-form") { should_not have_checked_field("Commit author") } }
it { within(".js-main-target-form") { should_not have_unchecked_field("Commit author") } }
it { within(".js-main-target-form") { should have_checked_field("Notify team via email") } }
it { within(".js-main-target-form") { should_not have_checked_field("Notify commit author") } }
it { within(".js-main-target-form") { should_not have_unchecked_field("Notify commit author") } }
describe "without text" do
it { within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: false) } }
......@@ -125,7 +125,7 @@ describe "On a merge request diff", js: true, focus: true do
it { should have_css(".js-close-discussion-note-form", text: "Cancel") }
# notification options
it { should have_checked_field("Project team") }
it { should have_checked_field("Notify team via email") }
it "shouldn't add a second form for same row" do
find("#4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185.line_holder .js-add-diff-note-button").trigger("click")
......
......@@ -21,9 +21,9 @@ describe "On the project wall", js: true do
it { within(".js-main-target-form") { should_not have_link("Cancel") } }
# notifiactions
it { within(".js-main-target-form") { should have_checked_field("Project team") } }
it { within(".js-main-target-form") { should_not have_checked_field("Commit author") } }
it { within(".js-main-target-form") { should_not have_unchecked_field("Commit author") } }
it { within(".js-main-target-form") { should have_checked_field("Notify team via email") } }
it { within(".js-main-target-form") { should_not have_checked_field("Notify commit author") } }
it { within(".js-main-target-form") { should_not have_unchecked_field("Notify commit author") } }
describe "without text" do
it { within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: false) } }
......
......@@ -76,7 +76,7 @@ describe ProjectsController, "routing" do
end
it "to #graph" do
get("/gitlabhq/graph").should route_to('projects#graph', id: 'gitlabhq')
get("/gitlabhq/graph/master").should route_to('graph#show', project_id: 'gitlabhq', id: 'master')
end
it "to #files" do
......
......@@ -24,7 +24,6 @@ RSpec.configure do |config|
config.mock_with :rspec
config.include LoginHelpers, type: :request
config.include GitoliteStub
config.include FactoryGirl::Syntax::Methods
config.include Devise::TestHelpers, type: :controller
......@@ -34,8 +33,6 @@ RSpec.configure do |config|
config.use_transactional_fixtures = false
config.before do
stub_gitolite!
# Use tmp dir for FS manipulations
temp_repos_path = Rails.root.join('tmp', 'test-git-base-path')
Gitlab.config.gitolite.stub(repos_path: temp_repos_path)
......
module GitoliteStub
def stub_gitolite!
stub_gitlab_gitolite
stub_gitolite_admin
end
def stub_gitolite_admin
gitolite_admin = double('Gitolite::GitoliteAdmin')
gitolite_admin.as_null_object
Gitolite::GitoliteAdmin.stub(new: gitolite_admin)
end
def stub_gitlab_gitolite
gitolite_config = double('Gitlab::GitoliteConfig')
gitolite_config.stub(apply: ->() { yield(self) })
gitolite_config.as_null_object
Gitlab::GitoliteConfig.stub(new: gitolite_config)
end
end
require "repository"
require "project"
require "shell"
# Stubs out all Git repository access done by models so that specs can run
# against fake repositories without Grit complaining that they don't exist.
......@@ -36,3 +37,23 @@ class GitLabTestRepo < Repository
@repo ||= Grit::Repo.new(Rails.root.join('tmp', 'repositories', 'gitlabhq'))
end
end
module Gitlab
class Shell
def add_repository name
true
end
def remove_repository name
true
end
def add_key id, key
true
end
def remove_key id, key
true
end
end
end
......@@ -11,7 +11,7 @@ describe PostReceive do
context "web hook" do
let(:project) { create(:project) }
let(:key) { create(:key, user: project.owner) }
let(:key_id) { key.identifier }
let(:key_id) { key.shell_id }
it "fetches the correct project" do
Project.should_receive(:find_with_namespace).with(project.path_with_namespace).and_return(project)
......@@ -19,7 +19,7 @@ describe PostReceive do
end
it "does not run if the author is not in the project" do
Key.stub(find_by_identifier: nil)
Key.stub(find_by_id: nil)
project.should_not_receive(:observe_push)
project.should_not_receive(:execute_hooks)
......
......@@ -73,7 +73,8 @@
, cumonth = ""
, offsetX = 20
, offsetY = 60
, barWidth = Math.max(graphWidth, this.dayCount * 20 + 320);
, barWidth = Math.max(graphWidth, this.dayCount * 20 + 320)
, scrollLeft = cw;
this.raphael = r;
......@@ -103,8 +104,9 @@
for (i = 0; i < this.commitCount; i++) {
var x = offsetX + 20 * this.commits[i].time
, y = offsetY + 20 * this.commits[i].space
, c;
, y = offsetY + 10 * this.commits[i].space
, c
, ps;
// Draw dot
r.circle(x, y, 3).attr({
......@@ -115,10 +117,12 @@
// Draw lines
for (var j = 0, jj = this.commits[i].parents.length; j < jj; j++) {
c = this.preparedCommits[this.commits[i].parents[j][0]];
ps = this.commits[i].parent_spaces[j];
if (c) {
var cx = offsetX + 20 * c.time
, cy = offsetY + 20 * c.space;
if (c.space == this.commits[i].space) {
, cy = offsetY + 10 * c.space
, psy = offsetY + 10 * ps;
if (c.space == this.commits[i].space && c.space == ps) {
r.path([
"M", x, y,
"L", cx, cy
......@@ -128,13 +132,25 @@
});
} else if (c.space < this.commits[i].space) {
r.path(["M", x - 5, y + .0001, "l-5-2,0,4,5,-2C", x - 5, y, x - 17, y + 2, x - 20, y - 5, "L", cx, y - 5, cx, cy])
r.path([
"M", x - 5, y,
"l-5-2,0,4,5,-2",
"L", x - 10, y,
"L", x - 15, psy,
"L", cx + 5, psy,
"L", cx, cy])
.attr({
stroke: this.colors[this.commits[i].space],
"stroke-width": 2
});
} else {
r.path(["M", x - 3, y + 6, "l-4,3,4,2,0,-5L", x - 10, y + 20, "L", x - 10, cy, cx, cy])
r.path([
"M", x - 3, y + 6,
"l-4,3,4,2,0,-5",
"L", x - 5, y + 10,
"L", x - 10, psy,
"L", cx + 5, psy,
"L", cx, cy])
.attr({
stroke: this.colors[c.space],
"stroke-width": 2
......@@ -145,12 +161,18 @@
if (this.commits[i].refs) {
this.appendLabel(x, y, this.commits[i].refs);
// The main branch is displayed in the center.
re = new RegExp('(^| )' + this.options.ref + '( |$)');
if (this.commits[i].refs.match(re)) {
scrollLeft = x - graphWidth / 2;
}
}
this.appendAnchor(top, this.commits[i], x, y);
}
top.toFront();
this.element.scrollLeft(cw);
this.element.scrollLeft(scrollLeft);
this.bindEvents();
};
......@@ -260,7 +282,7 @@
cursor: "pointer"
})
.click(function(){
window.location = options.commit_url.replace('%s', commit.id);
window.open(options.commit_url.replace('%s', commit.id), '_blank');
})
.hover(function(){
this.tooltip = r.commitTooltip(x, y + 5, commit);
......
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