Merge branch 'master' into dashboard-titles

This commit is contained in:
Douwe Maan 2015-09-10 13:13:01 +01:00
commit a6997e339b
124 changed files with 1794 additions and 484 deletions

View File

@ -2,6 +2,7 @@ Please view this file on the master branch, on stable branches it's out of date.
v 8.0.0 (unreleased)
- Fix URL construction for merge requests, issues, notes, and commits for relative URL config (Stan Hu)
- Fix emoji URLs in Markdown when relative_url_root is used (Stan Hu)
- Omit filename in Content-Disposition header in raw file download to avoid RFC 6266 encoding issues (Stan HU)
- Fix broken Wiki Page History (Stan Hu)
- Prevent anchors from being hidden by header (Stan Hu)
@ -40,13 +41,19 @@ v 8.0.0 (unreleased)
- Add ability to get user information by ID of an SSH key via the API
- Fix bug which IE cannot show image at markdown when the image is raw file of gitlab
- Add support for Crowd
- Global Labels that are available to all projects
- Fix highlighting of deleted lines in diffs.
v 7.14.1
- Improve abuse reports management from admin area
- Fix "Reload with full diff" URL button in compare branch view (Stan Hu)
- Disabled DNS lookups for SSH in docker image (Rowan Wookey)
v 7.14.1 (unreleased)
- Only include base URL in OmniAuth full_host parameter (Stan Hu)
- Fix Error 500 in API when accessing a group that has an avatar (Stan Hu)
- Ability to enable SSL verification for Webhooks
- Add FogBugz project import (Jared Szechy)
v 7.14.0
- Fix bug where non-project members of the target project could set labels on new merge requests.

View File

@ -1 +1 @@
2.6.4
2.6.5

View File

@ -157,6 +157,9 @@ gem "slack-notifier", "~> 1.0.0"
# Asana integration
gem 'asana', '~> 0.0.6'
# FogBugz integration
gem 'ruby-fogbugz'
# d3
gem 'd3_rails', '~> 3.5.5'
@ -259,6 +262,7 @@ group :test do
gem 'email_spec', '~> 1.6.0'
gem 'webmock', '~> 1.21.0'
gem 'test_after_commit'
gem 'sham_rack'
end
group :production do

View File

@ -575,6 +575,8 @@ GEM
powerpack (~> 0.0.6)
rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.4)
ruby-fogbugz (0.1.1)
crack
ruby-progressbar (1.7.1)
ruby-saml (1.0.0)
nokogiri (>= 1.5.10)
@ -609,6 +611,8 @@ GEM
thor (~> 0.14)
settingslogic (2.0.9)
sexp_processor (4.4.5)
sham_rack (1.3.6)
rack
shoulda-matchers (2.8.0)
activesupport (>= 3.0.0)
sidekiq (3.3.0)
@ -845,12 +849,14 @@ DEPENDENCIES
rqrcode-rails3
rspec-rails (~> 3.3.0)
rubocop (= 0.28.0)
ruby-fogbugz
sanitize (~> 2.0)
sass-rails (~> 4.0.5)
sdoc
seed-fu
select2-rails (~> 3.5.9)
settingslogic
sham_rack
shoulda-matchers (~> 2.8.0)
sidekiq (~> 3.3)
sidetiq (= 0.6.3)

View File

@ -85,14 +85,14 @@
// Labels
.label {
padding: 2px 4px;
font-size: 12px;
font-size: 13px;
font-style: normal;
font-weight: normal;
display: inline-block;
&.label-gray {
background-color: #eee;
color: #999;
background-color: #f8fafc;
color: $gl-gray;
text-shadow: none;
}
@ -156,10 +156,16 @@
* Add some extra stuff to panels
*
*/
.panel {
.panel-heading {
font-weight: bold;
.container-blank .panel .panel-heading {
font-size: 17px;
line-height: 38px;
}
.panel {
box-shadow: none;
.panel-heading {
.panel-head-actions {
position: relative;
top: -5px;
@ -182,6 +188,10 @@
.pagination {
margin: 0;
}
.btn {
min-width: 124px;
}
}
&.panel-small {
@ -209,6 +219,12 @@
}
}
.alert-help {
background-color: $background-color;
border: 1px solid $border-color;
color: $gl-gray;
}
// Typography =================================================================
.text-primary,

View File

@ -22,6 +22,10 @@ $brand-info: $gl-info;
$brand-warning: $gl-warning;
$brand-danger: $gl-danger;
$border-radius-base: 3px !default;
$border-radius-large: 5px !default;
$border-radius-small: 2px !default;
//== Scaffolding
//
@ -110,11 +114,12 @@ $alert-border-radius: 0;
//
//##
$panel-border-radius: 0;
$panel-default-text: $text-color;
$panel-default-border: #E7E9ED;
$panel-default-heading-bg: #F8FAFC;
$panel-border-radius: 2px;
$panel-default-text: $text-color;
$panel-default-border: $border-color;
$panel-default-heading-bg: $background-color;
$panel-footer-bg: $background-color;
$panel-inner-border: $border-color;
//== Wells
//
@ -144,3 +149,10 @@ $btn-default-border: #e7e9ed;
//
//##
$nav-link-padding: 13px $gl-padding;
//== Code
//
//##
$pre-bg: #f8fafc !default;
$pre-color: $gl-gray !default;
$pre-border-color: #e7e9ed;

View File

@ -177,7 +177,7 @@
margin: 0px;
&:last-child {
border:none
border-bottom: none;
}
&.active {
@ -215,3 +215,39 @@
font-size: 16px;
line-height: 24px;
}
@mixin nav-menu {
padding: 0;
margin: 0;
list-style: none;
margin-top: 5px;
height: 56px;
li {
display: inline-block;
a {
padding: 14px;
font-size: 17px;
line-height: 28px;
color: #7f8fa4;
border-bottom: 2px solid transparent;
&:hover, &:active, &:focus {
text-decoration: none;
}
}
&.active a {
color: #4c4e54;
border-bottom: 2px solid #1cacfc;
}
.badge {
font-weight: normal;
background-color: #fff;
background-color: #eee;
color: #78a;
}
}
}

View File

@ -27,6 +27,15 @@
border-bottom: 1px solid #e7e9ed;
color: $gl-gray;
&.top-block {
border-top: none;
}
&.middle-block {
margin-top: 0;
margin-bottom: 0;
}
&.second-block {
margin-top: -1px;
margin-bottom: 0;

View File

@ -10,7 +10,7 @@
}
&.btn-save {
@extend .btn-primary;
@extend .btn-success;
}
&.btn-remove {

View File

@ -370,41 +370,11 @@ table {
}
.center-top-menu {
padding: 0;
margin: 0;
list-style: none;
@include nav-menu;
text-align: center;
margin-top: 5px;
margin-bottom: $gl-padding;
height: 56px;
margin-top: -$gl-padding;
padding-top: $gl-padding;
li {
display: inline-block;
a {
padding: 14px;
font-size: 17px;
line-height: 28px;
color: #7f8fa4;
border-bottom: 2px solid transparent;
&:hover, &:active, &:focus {
text-decoration: none;
}
}
&.active a {
color: #4c4e54;
border-bottom: 2px solid #1cacfc;
}
.badge {
font-weight: normal;
background-color: #fff;
background-color: #eee;
color: #78a;
}
}
}

View File

@ -5,10 +5,13 @@
*/
.issue-box {
@include border-radius(3px);
display: inline-block;
padding: 4px 13px;
padding: 10px $gl-padding;
font-weight: normal;
margin-right: 5px;
margin-right: 10px;
font-size: $gl-font-size;
&.issue-box-closed {
background-color: $gl-danger;
@ -21,7 +24,7 @@
}
&.issue-box-open {
background-color: $gl-success;
background-color: #019875;
color: #FFF;
}

View File

@ -65,8 +65,11 @@
position: relative;
}
.md-header ul {
float: left;
.md-header {
ul {
float: left;
margin-bottom: 1px;
}
}
.referenced-users {
@ -80,7 +83,7 @@
.md-preview-holder {
background: #FFF;
border: 1px solid #ddd;
min-height: 100px;
min-height: 169px;
padding: 5px;
box-shadow: none;
}
@ -105,7 +108,7 @@
.markdown-area {
background: #FFF;
border: 1px solid #ddd;
min-height: 100px;
min-height: 140px;
padding: 5px;
box-shadow: none;
width: 100%;

View File

@ -28,12 +28,18 @@
padding: $gl-padding;
border: 1px solid #e7e9ed;
min-height: 90vh;
&.container-blank {
background: none;
padding: 0;
border: none;
}
}
}
.nav-sidebar {
margin-top: 14 + $header-height;
margin-bottom: 50px;
margin-bottom: 100px;
transition-duration: .3s;
list-style: none;
overflow: hidden;

View File

@ -1,119 +1,50 @@
.timeline {
list-style: none;
padding: 20px 0 20px;
position: relative;
@include basic-list;
&:before {
top: 0;
bottom: 0;
position: absolute;
content: " ";
width: 3px;
background-color: #eeeeee;
margin-left: 29px;
}
margin: 0;
padding: 0;
.timeline-entry {
position: relative;
margin-top: 5px;
margin-left: 30px;
margin-bottom: 10px;
clear: both;
padding: $gl-padding;
border-color: #f1f2f4;
margin-left: -$gl-padding;
margin-right: -$gl-padding;
color: $gl-gray;
border-bottom: 1px solid #f1f2f4;
border-right: 1px solid #f1f2f4;
&:target {
.timeline-entry-inner .timeline-content {
-webkit-animation:target-note 2s linear;
background: $hover;
}
&:last-child {
border-bottom: none;
}
.timeline-entry-inner {
position: relative;
margin-left: -20px;
.avatar {
margin-right: 15px;
}
&:before, &:after {
content: " ";
display: table;
}
.timeline-icon {
margin-top: 2px;
background: #fff;
color: #737881;
float: left;
@include border-radius($avatar_radius);
@include box-shadow(0 0 0 3px #EEE);
overflow: hidden;
.avatar {
margin: 0;
padding: 0;
}
}
.timeline-content {
position: relative;
background: $background-color;
padding: 10px 15px;
margin-left: 60px;
img {
max-width: 100%;
}
&:after {
content: '';
display: block;
position: absolute;
width: 0;
height: 0;
border-style: solid;
border-width: 9px 9px 9px 0;
border-color: transparent $background-color transparent transparent;
left: 0;
top: 10px;
margin-left: -9px;
}
}
.controls {
padding-top: 10px;
float: right;
}
}
.system-note .timeline-entry-inner {
.timeline-icon {
background: none;
margin-left: 12px;
margin-top: 0;
@include box-shadow(none);
span {
margin: 0 2px;
font-size: 16px;
color: #eeeeee;
}
.note-text {
p:last-child {
margin-bottom: 0;
}
}
.timeline-content {
background: none;
margin-left: 45px;
padding: 0px 15px;
&:after { border: 0; }
.note-header {
span { font-size: 12px; }
.avatar {
margin-right: 5px;
}
}
.note-text {
font-size: 12px;
margin-left: 20px;
}
.system-note {
.note-text {
color: $gl-gray !important;
}
}
.diff-file {
border: 1px solid $border-color;
border-bottom: none;
margin-left: 0;
margin-right: 0;
}
}
@media (max-width: $screen-xs-max) {
@ -132,3 +63,8 @@
}
}
}
.discussion .timeline-entry {
margin: 0;
border-right: none;
}

View File

@ -4,7 +4,7 @@
}
.zen-enter-link {
color: #888;
color: $gl-gray;
position: absolute;
top: 0px;
right: 4px;
@ -13,7 +13,7 @@
.zen-leave-link {
display: none;
color: #888;
color: $gl-text-color;
position: absolute;
top: 10px;
right: 10px;

View File

@ -26,14 +26,6 @@
margin-top: 10px;
}
.commit-stat-summary {
color: #666;
font-size: 14px;
font-weight: normal;
padding: 3px 0;
margin-bottom: 10px;
}
.commit-info-row {
margin-bottom: 10px;
.avatar {
@ -47,11 +39,6 @@
}
.commit-box {
margin: 10px 0;
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
padding: 20px 0;
.commit-title {
margin: 0;
}

View File

@ -1,6 +1,8 @@
.diff-file {
border: 1px solid $border-color;
margin-bottom: 1em;
margin-left: -16px;
margin-right: -16px;
border: none;
border-bottom: 1px solid #E7E9EE;
.diff-header {
position: relative;
@ -45,7 +47,7 @@
overflow-y: hidden;
background: #FFF;
color: #333;
font-size: $code_font_size;
.old {
span.idiff {
background-color: #f8cbcb;
@ -82,7 +84,7 @@
border: none;
margin: 0px;
padding: 0px;
td {
.line_holder td {
line-height: $code_line_height;
font-size: $code_font_size;
}
@ -367,3 +369,7 @@
white-space: pre-wrap;
}
.inline-parallel-buttons {
float: right;
margin-top: -5px;
}

View File

@ -25,8 +25,6 @@
}
.issuable-context-title {
font-size: 14px;
line-height: 1.4;
margin-bottom: 5px;
.avatar {
@ -34,18 +32,12 @@
}
label {
color: #666;
color: $gl-gray;
font-weight: normal;
margin-right: 4px;
}
}
.issuable-affix .context {
font-size: 13px;
.btn { font-size: 13px; }
}
.project-issuable-filter {
.controls {
float: right;
@ -56,3 +48,34 @@
text-align: left;
}
}
.issuable-details {
.page-title {
margin-top: -15px;
padding: 10px 0;
margin-bottom: 0;
color: $gl-gray;
font-size: 16px;
.author {
color: $gl-gray;
}
.issue-id {
font-size: 19px;
color: $gl-text-color;
}
}
.issue-title {
margin: 0;
}
.description {
margin-top: 6px;
p:last-child {
margin-bottom: 0;
}
}
}

View File

@ -1,6 +1,6 @@
.issues-list {
.issue {
padding: 10px 15px;
padding: 10px $gl-padding;
position: relative;
.issue-title {
@ -11,7 +11,6 @@
.issue-info {
color: $gl-gray;
font-size: 13px;
}
.issue-check {
@ -47,10 +46,6 @@
}
}
.participants {
margin-bottom: 20px;
}
.issue-search-form {
margin: 0;
height: 24px;
@ -137,11 +132,6 @@ form.edit-issue {
}
}
h2.issue-title {
margin-top: 0;
font-weight: bold;
}
.issue-form .select2-container {
width: 250px !important;
}

View File

@ -3,10 +3,10 @@
*
*/
.mr-state-widget {
background: #FAFAFA;
background: #f8fafc;
margin-bottom: 20px;
color: #666;
border: 1px solid #e5e5e5;
color: $gl-gray;
border: 1px solid #eef0f2;
@include box-shadow(0 1px 1px rgba(0, 0, 0, 0.05));
@include border-radius(3px);
@ -29,6 +29,14 @@
padding: 5px;
line-height: 20px;
&.right {
float: right;
padding-top: 12px;
a {
color: $gl-gray;
}
}
.remove_source_checkbox {
margin: 0;
}
@ -36,7 +44,7 @@
}
.ci_widget {
border-bottom: 1px solid #EEE;
border-bottom: 1px solid #eef0f2;
i {
margin-right: 4px;
@ -89,20 +97,14 @@
}
}
@media(min-width: $screen-sm-max) {
.merge-request .merge-request-tabs{
li {
a {
padding: 15px 40px;
font-size: 14px;
}
}
}
}
.merge-request .merge-request-tabs{
margin-top: 30px;
margin-bottom: 20px;
@include nav-menu;
margin: -$gl-padding;
padding: $gl-padding;
text-align: center;
border-top: 1px solid #e7e9ed;
margin-top: 18px;
margin-bottom: 3px;
}
.mr_source_commit,
@ -137,7 +139,6 @@
.merge-request-info {
color: $gl-gray;
font-size: 13px;
}
}

View File

@ -6,4 +6,8 @@ li.milestone {
h4 {
font-weight: bold;
}
.progress {
height: 6px;
}
}

View File

@ -72,9 +72,13 @@
.common-note-form {
margin: 0;
background: #F9F9F9;
padding: 5px;
border: 1px solid #DDD;
background: #f8fafc;
padding: $gl-padding;
margin-left: -$gl-padding;
margin-right: -$gl-padding;
border-right: 1px solid #f1f2f4;
border-top: 1px solid #f1f2f4;
margin-bottom: -$gl-padding;
}
.note-form-actions {
@ -142,9 +146,9 @@
}
.discussion-reply-holder {
background: #f9f9f9;
background: $background-color;
padding: 10px 15px;
border-top: 1px solid #DDD;
border-top: 1px solid $border-color;
}
}
@ -166,6 +170,6 @@
background: #FFF;
padding: 5px;
margin-top: -11px;
border: 1px solid #DDD;
border: 1px solid $border-color;
font-size: 13px;
}

View File

@ -14,6 +14,19 @@ ul.notes {
margin: 0px;
padding: 0px;
.system-note {
font-size: 14px;
padding-top: 10px;
padding-bottom: 10px;
background: #f8fafc;
.timeline-icon {
.avatar {
visibility: hidden;
}
}
}
.discussion-header,
.note-header {
@extend .cgray;
@ -34,10 +47,8 @@ ul.notes {
content: "\00b7";
}
font-size: 13px;
a {
@extend .cgray;
color: $gl-gray;
&:hover {
text-decoration: underline;
@ -45,8 +56,9 @@ ul.notes {
}
}
.author {
color: #333;
font-weight: bold;
color: #4c4e54;
margin-right: 3px;
&:hover {
color: $gl-link-color;
}
@ -59,7 +71,7 @@ ul.notes {
margin-top: 1px;
border: 1px solid #bbb;
background-color: transparent;
color: #999;
color: $gl-gray;
}
}
@ -133,8 +145,6 @@ ul.notes {
}
.diff-file .notes_holder {
font-size: 13px;
line-height: 18px;
font-family: $regular_font;
td {
@ -176,8 +186,7 @@ ul.notes {
a {
margin-left: 5px;
color: #999;
color: $gl-gray;
i.fa {
font-size: 16px;

View File

@ -0,0 +1,58 @@
class Admin::LabelsController < Admin::ApplicationController
before_action :set_label, only: [:show, :edit, :update, :destroy]
def index
@labels = Label.templates.page(params[:page]).per(PER_PAGE)
end
def show
end
def new
@label = Label.new
end
def edit
end
def create
@label = Label.new(label_params)
@label.template = true
if @label.save
redirect_to admin_labels_url, notice: "Label was created"
else
render :new
end
end
def update
if @label.update(label_params)
redirect_to admin_labels_path, notice: 'label was successfully updated.'
else
render :edit
end
end
def destroy
@label.destroy
@labels = Label.templates
respond_to do |format|
format.html do
redirect_to(admin_labels_path, notice: 'Label was removed')
end
format.js
end
end
private
def set_label
@label = Label.find(params[:id])
end
def label_params
params[:label].permit(:title, :color)
end
end

View File

@ -1,4 +1,5 @@
require 'gon'
require 'fogbugz'
class ApplicationController < ActionController::Base
include Gitlab::CurrentSettings
@ -20,7 +21,7 @@ class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
helper_method :abilities, :can?, :current_application_settings
helper_method :import_sources_enabled?, :github_import_enabled?, :github_import_configured?, :gitlab_import_enabled?, :gitlab_import_configured?, :bitbucket_import_enabled?, :bitbucket_import_configured?, :gitorious_import_enabled?, :google_code_import_enabled?, :git_import_enabled?
helper_method :import_sources_enabled?, :github_import_enabled?, :github_import_configured?, :gitlab_import_enabled?, :gitlab_import_configured?, :bitbucket_import_enabled?, :bitbucket_import_configured?, :gitorious_import_enabled?, :google_code_import_enabled?, :fogbugz_import_enabled?, :git_import_enabled?
rescue_from Encoding::CompatibilityError do |exception|
log_exception(exception)
@ -337,6 +338,10 @@ class ApplicationController < ActionController::Base
current_application_settings.import_sources.include?('google_code')
end
def fogbugz_import_enabled?
current_application_settings.import_sources.include?('fogbugz')
end
def git_import_enabled?
current_application_settings.import_sources.include?('git')
end

View File

@ -0,0 +1,106 @@
class Import::FogbugzController < Import::BaseController
before_action :verify_fogbugz_import_enabled
before_action :user_map, only: [:new_user_map, :create_user_map]
# Doesn't work yet due to bug in ruby-fogbugz, see below
rescue_from Fogbugz::AuthenticationException, with: :fogbugz_unauthorized
def new
end
def callback
begin
res = Gitlab::FogbugzImport::Client.new(import_params.symbolize_keys)
rescue
# Needed until https://github.com/firmafon/ruby-fogbugz/pull/9 is merged
return redirect_to :back, alert: 'Could not authenticate with FogBugz, check your URL, email, and password'
end
session[:fogbugz_token] = res.get_token
session[:fogbugz_uri] = params[:uri]
redirect_to new_user_map_import_fogbugz_path
end
def new_user_map
end
def create_user_map
user_map = params[:users]
unless user_map.is_a?(Hash) && user_map.all? { |k, v| !v[:name].blank? }
flash.now[:alert] = 'All users must have a name.'
render 'new_user_map' and return
end
session[:fogbugz_user_map] = user_map
flash[:notice] = 'The user map has been saved. Continue by selecting the projects you want to import.'
redirect_to status_import_fogbugz_path
end
def status
unless client.valid?
return redirect_to new_import_fogbugz_path
end
@repos = client.repos
@already_added_projects = current_user.created_projects.where(import_type: 'fogbugz')
already_added_projects_names = @already_added_projects.pluck(:import_source)
@repos.reject! { |repo| already_added_projects_names.include? repo.name }
end
def jobs
jobs = current_user.created_projects.where(import_type: 'fogbugz').to_json(only: [:id, :import_status])
render json: jobs
end
def create
@repo_id = params[:repo_id]
repo = client.repo(@repo_id)
fb_session = { uri: session[:fogbugz_uri], token: session[:fogbugz_token] }
@target_namespace = current_user.namespace
@project_name = repo.name
namespace = @target_namespace
umap = session[:fogbugz_user_map] || client.user_map
@project = Gitlab::FogbugzImport::ProjectCreator.new(repo, fb_session, namespace, current_user, umap).execute
end
private
def client
@client ||= Gitlab::FogbugzImport::Client.new(token: session[:fogbugz_token], uri: session[:fogbugz_uri])
end
def user_map
@user_map ||= begin
user_map = client.user_map
stored_user_map = session[:fogbugz_user_map]
user_map.update(stored_user_map) if stored_user_map
user_map
end
end
def fogbugz_unauthorized(exception)
flash[:alert] = exception.message
redirect_to new_import_fogbugz_path
end
def import_params
params.permit(:uri, :email, :password)
end
def verify_fogbugz_import_enabled
not_found! unless fogbugz_import_enabled?
end
end

View File

@ -31,4 +31,26 @@ module PageLayoutHelper
@fluid_layout
end
end
def blank_container(enabled = false)
if @blank_container.nil?
@blank_container = enabled
else
@blank_container
end
end
def container_class
css_class = "container-fluid"
unless fluid_layout
css_class += " container-limited"
end
if blank_container
css_class += " container-blank"
end
css_class
end
end

View File

@ -83,7 +83,7 @@ class ApplicationSetting < ActiveRecord::Base
default_project_visibility: Settings.gitlab.default_projects_features['visibility_level'],
default_snippet_visibility: Settings.gitlab.default_projects_features['visibility_level'],
restricted_signup_domains: Settings.gitlab['restricted_signup_domains'],
import_sources: ['github','bitbucket','gitlab','gitorious','google_code','git']
import_sources: ['github','bitbucket','gitlab','gitorious','google_code','fogbugz','git']
)
end

View File

@ -24,7 +24,7 @@ class Label < ActiveRecord::Base
validates :color,
format: { with: /\A#[0-9A-Fa-f]{6}\Z/ },
allow_blank: false
validates :project, presence: true
validates :project, presence: true, unless: Proc.new { |service| service.template? }
# Don't allow '?', '&', and ',' for label titles
validates :title,
@ -34,6 +34,8 @@ class Label < ActiveRecord::Base
default_scope { order(title: :asc) }
scope :templates, -> { where(template: true) }
alias_attribute :name, :title
def self.reference_prefix
@ -78,4 +80,8 @@ class Label < ActiveRecord::Base
def open_issues_count
issues.opened.count
end
def template?
template
end
end

View File

@ -43,6 +43,8 @@ class Project < ActiveRecord::Base
extend Gitlab::ConfigHelper
extend Enumerize
UNKNOWN_IMPORT_URL = 'http://unknown.git'
default_value_for :archived, false
default_value_for :visibility_level, gitlab_config_features.visibility_level
default_value_for :issues_enabled, gitlab_config_features.issues
@ -401,6 +403,15 @@ class Project < ActiveRecord::Base
end
end
def create_labels
Label.templates.each do |label|
label = label.dup
label.template = nil
label.project_id = self.id
label.save
end
end
def find_service(list, name)
list.find { |service| service.to_param == name }
end

View File

@ -87,6 +87,8 @@ module Projects
@project.build_missing_services
@project.create_labels
event_service.create_project(@project, current_user)
system_hook_service.execute_hooks_for(@project, :create)

View File

@ -0,0 +1,43 @@
module Projects
class DownloadService < BaseService
WHITELIST = [
/^[^.]+\.fogbugz.com$/
]
def initialize(project, url)
@project, @url = project, url
end
def execute
return nil unless valid_url?(@url)
uploader = FileUploader.new(@project)
uploader.download!(@url)
uploader.store!
filename = uploader.image? ? uploader.file.basename : uploader.file.filename
{
'alt' => filename,
'url' => uploader.secure_url,
'is_image' => uploader.image?
}
end
private
def valid_url?(url)
url && http?(url) && valid_domain?(url)
end
def http?(url)
url =~ /\A#{URI::regexp(['http', 'https'])}\z/
end
def valid_domain?(url)
host = URI.parse(url).host
WHITELIST.any? { |entry| entry === host }
end
end
end

View File

@ -0,0 +1,35 @@
= form_for [:admin, @label], html: { class: 'form-horizontal label-form js-requires-input' } do |f|
-if @label.errors.any?
.row
.col-sm-offset-2.col-sm-10
.alert.alert-danger
- @label.errors.full_messages.each do |msg|
%span= msg
%br
.form-group
= f.label :title, class: 'control-label'
.col-sm-10
= f.text_field :title, class: "form-control", required: true
.form-group
= f.label :color, "Background Color", class: 'control-label'
.col-sm-10
.input-group
.input-group-addon.label-color-preview &nbsp;
= f.color_field :color, class: "form-control"
.help-block
Choose any color.
%br
Or you can choose one of suggested colors below
.suggest-colors
- suggested_colors.each do |color|
= link_to '#', style: "background-color: #{color}", data: { color: color } do
&nbsp;
.form-actions
= f.submit 'Save', class: 'btn btn-save js-save-button'
= link_to "Cancel", admin_labels_path, class: 'btn btn-cancel'
:coffeescript
new Labels

View File

@ -0,0 +1,5 @@
%li{id: dom_id(label)}
= render_colored_label(label)
.pull-right
= link_to 'Edit', edit_admin_label_path(label), class: 'btn btn-sm'
= link_to 'Remove', admin_label_path(label), class: 'btn btn-sm btn-remove remove-row', method: :delete, remote: true, data: {confirm: "Remove this label? Are you sure?"}

View File

@ -0,0 +1,2 @@
- if @labels.size == 0
$('.labels').load(document.URL + ' .light-well').hide().fadeIn(1000)

View File

@ -0,0 +1,9 @@
- page_title "Edit", @label.name, "Labels"
%h3
Edit label
%span.light #{@label.name}
.back-link
= link_to admin_labels_path do
&larr; To labels list
%hr
= render 'form'

View File

@ -0,0 +1,16 @@
- page_title "Labels"
= link_to new_admin_label_path, class: "pull-right btn btn-new" do
New label
%h3.page-title
Labels
%hr
.labels
- if @labels.present?
%ul.bordered-list.manage-labels-list
= render @labels
= paginate @labels, theme: 'gitlab'
- else
.light-well
.nothing-here-block There are no any labels yet

View File

@ -0,0 +1,7 @@
- page_title "New Label"
%h3 New label
.back-link
= link_to admin_labels_path do
&larr; To labels list
%hr
= render 'form'

View File

@ -1,20 +1,22 @@
%li{class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: dom_id(milestone.milestones.first) }
%h4
= link_to_gfm truncate(milestone.title, length: 100), dashboard_milestone_path(milestone.safe_title, title: milestone.title)
.row
.col-sm-6
%strong
= link_to_gfm truncate(milestone.title, length: 100), dashboard_milestone_path(milestone.safe_title, title: milestone.title)
.col-sm-6
.pull-right.light #{milestone.percent_complete}% complete
.row
.col-sm-6
= link_to issues_dashboard_path(milestone_title: milestone.title) do
= pluralize milestone.issue_count, 'Issue'
&nbsp;
&middot;
= link_to merge_requests_dashboard_path(milestone_title: milestone.title) do
= pluralize milestone.merge_requests_count, 'Merge Request'
&nbsp;
%span.light #{milestone.percent_complete}% complete
.col-sm-6
= milestone_progress_bar(milestone)
%div
- milestone.milestones.each do |milestone|
= link_to milestone_path(milestone) do
%span.label.label-gray
= milestone.project.name_with_namespace
.row
.col-sm-6
- milestone.milestones.each do |milestone|
= link_to milestone_path(milestone) do
%span.label.label-gray
= milestone.project.name_with_namespace

View File

@ -1,3 +1,4 @@
- @blank_container = true
.panel.panel-default
.panel-heading
%strong= @group.name

View File

@ -1,15 +1,13 @@
- page_title "Members"
- header_title group_title(@group, "Members", group_group_members_path(@group))
- show_roles = should_user_see_group_roles?(current_user, @group)
%h3.page-title
Group members
- if show_roles
%p.light
Members of group have access to all group projects.
Read more about permissions
%strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink"
%hr
.clearfix.js-toggle-container
= form_tag group_group_members_path(@group), method: :get, class: 'form-inline member-search-form' do

View File

@ -1,25 +1,29 @@
%li{class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: dom_id(milestone.milestones.first) }
.pull-right
- if can?(current_user, :admin_group, @group)
- if milestone.closed?
= link_to 'Reopen Milestone', group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-sm btn-grouped btn-reopen"
- else
= link_to 'Close Milestone', group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-sm btn-close"
%h4
= link_to_gfm truncate(milestone.title, length: 100), group_milestone_path(@group, milestone.safe_title, title: milestone.title)
.row
.col-sm-6
%strong
= link_to_gfm truncate(milestone.title, length: 100), group_milestone_path(@group, milestone.safe_title, title: milestone.title)
.col-sm-6
.pull-right.light #{milestone.percent_complete}% complete
.row
.col-sm-6
= link_to issues_group_path(@group, milestone_title: milestone.title) do
= pluralize milestone.issue_count, 'Issue'
&nbsp;
&middot;
= link_to merge_requests_group_path(@group, milestone_title: milestone.title) do
= pluralize milestone.merge_requests_count, 'Merge Request'
&nbsp;
%span.light #{milestone.percent_complete}% complete
.col-sm-6
= milestone_progress_bar(milestone)
%div
- milestone.milestones.each do |milestone|
= link_to milestone_path(milestone) do
%span.label.label-gray
= milestone.project.name
.row
.col-sm-6
%div
- milestone.milestones.each do |milestone|
= link_to milestone_path(milestone) do
%span.label.label-gray
= milestone.project.name
.col-sm-6
- if can?(current_user, :admin_group, @group)
- if milestone.closed?
= link_to 'Reopen Milestone', group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-xs btn-grouped btn-reopen"
- else
= link_to 'Close Milestone', group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-xs btn-close"

View File

@ -0,0 +1,25 @@
- page_title "FogBugz Import"
%h3.page-title
%i.fa.fa-bug
Import projects from FogBugz
%hr
= form_tag callback_import_fogbugz_path, class: 'form-horizontal' do
%p
To get started you enter your FogBugz URL and login information below.
In the next steps, you'll be able to map users and select the projects
you want to import.
.form-group
= label_tag :uri, 'FogBugz URL', class: 'control-label'
.col-sm-4
= text_field_tag :uri, nil, placeholder: 'https://mycompany.fogbugz.com', class: 'form-control'
.form-group
= label_tag :email, 'FogBugz Email', class: 'control-label'
.col-sm-4
= text_field_tag :email, nil, class: 'form-control'
.form-group
= label_tag :password, 'FogBugz Password', class: 'control-label'
.col-sm-4
= password_field_tag :password, nil, class: 'form-control'
.form-actions
= submit_tag 'Continue to the next step', class: 'btn btn-create'

View File

@ -0,0 +1,49 @@
- page_title 'User map', 'FogBugz import'
%h3.page-title
%i.fa.fa-bug
Import projects from FogBugz
%hr
= form_tag create_user_map_import_fogbugz_path, class: 'form-horizontal' do
%p
Customize how FogBugz email addresses and usernames are imported into GitLab.
In the next step, you'll be able to select the projects you want to import.
%p
The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames wil be imported into GitLab. You can change this by populating the table below.
%ul
%li
%strong Default: Map a FogBugz account ID to a full name
%p
An empty GitLab User field will add the FogBugz user's full name
(e.g. "By John Smith") in the description of all issues and comments.
It will also associate and/or assign these issues and comments with
the project creator.
%li
%strong Map a FogBugz account ID to a GitLab user
%p
Selecting a GitLab user will add a link to the GitLab user in the descriptions
of issues and comments (e.g. "By <a href="#">@johnsmith</a>"). It will also
associate and/or assign these issues and comments with the selected user.
%table.table
%thead
%tr
%th ID
%th Name
%th Email
%th GitLab User
%tbody
- @user_map.each do |id, user|
%tr
%td= id
%td= text_field_tag "users[#{id}][name]", user[:name], class: 'form-control'
%td= text_field_tag "users[#{id}][email]", user[:email], class: 'form-control'
%td
= users_select_tag("users[#{id}][gitlab_user]", class: 'custom-form-control',
scope: :all, email_user: true, selected: user[:gitlab_user])
.form-actions
= submit_tag 'Continue to the next step', class: 'btn btn-create'
:coffeescript
new UsersSelect()

View File

@ -0,0 +1,51 @@
- page_title "FogBugz import"
%h3.page-title
%i.fa.fa-bug
Import projects from FogBugz
- if @repos.any?
%p.light
Select projects you want to import.
%p.light
Optionally, you can
= link_to 'customize', new_user_map_import_fogbugz_path
how FogBugz email addresses and usernames are imported into GitLab.
%hr
%p
= button_tag 'Import all projects', class: 'btn btn-success js-import-all'
%table.table.import-jobs
%thead
%tr
%th From FogBugz
%th To GitLab
%th Status
%tbody
- @already_added_projects.each do |project|
%tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"}
%td
= project.import_source
%td
%strong= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project]
%td.job-status
- if project.import_status == 'finished'
%span
%i.fa.fa-check
done
- elsif project.import_status == 'started'
%i.fa.fa-spinner.fa-spin
started
- else
= project.human_import_status_name
- @repos.each do |repo|
%tr{id: "repo_#{repo.id}"}
%td
= repo.name
%td.import-target
= "#{current_user.username}/#{repo.name}"
%td.import-actions.job-status
= button_tag "Import", class: "btn js-add-to-import"
:coffeescript
new ImporterStatus("#{jobs_import_fogbugz_path}", "#{import_fogbugz_path}")

View File

@ -3,6 +3,7 @@
%meta{charset: "utf-8"}
%meta{'http-equiv' => 'X-UA-Compatible', content: 'IE=edge'}
%meta{content: "GitLab Community Edition", name: "description"}
%meta{name: 'referrer', content: 'origin'}
%title= page_title

View File

@ -23,7 +23,7 @@
= current_user.username
.content-wrapper
= render "layouts/flash"
%div{ class: fluid_layout ? "container-fluid" : "container-fluid container-limited" }
%div{ class: container_class }
.content
.clearfix
= yield

View File

@ -57,6 +57,12 @@
%span
Service Templates
= nav_link(controller: :labels) do
= link_to admin_labels_path, title: 'Labels', data: {placement: 'right'} do
= icon('tags fw')
%span
Labels
= nav_link(controller: :abuse_reports) do
= link_to admin_abuse_reports_path, title: "Abuse reports" do
= icon('exclamation-circle fw')

View File

@ -36,13 +36,13 @@
= icon('clipboard fw')
%span
Snippets
= nav_link(controller: :profile) do
= link_to profile_path, title: 'Profile settings', data: {placement: 'bottom'} do
= icon('user fw')
%span
Profile Settings
= nav_link(controller: :help) do
= link_to help_path, title: 'Help', data: {placement: 'right'} do
= icon('question-circle fw')
%span
Help
= nav_link(controller: :profile) do
= link_to profile_path, title: 'Profile settings', data: {placement: 'bottom'} do
= icon('user fw')
%span
Profile Settings

View File

@ -11,7 +11,7 @@
= link_to profile_path, title: 'Profile', data: {placement: 'right'} do
= icon('user fw')
%span
Profile
Profile Settings
= nav_link(controller: [:accounts, :two_factor_auths]) do
= link_to profile_account_path, title: 'Account', data: {placement: 'right'} do
= icon('gear fw')

View File

@ -1,5 +1,6 @@
- page_title "Profile Settings"
- header_title "Profile Settings", profile_path
- unless @header_title
- header_title "Profile Settings", profile_path
- sidebar "profile"
= render template: "layouts/application"

View File

@ -1,9 +1,7 @@
- page_title "Account"
%h3.page-title
= page_title
%p.light
Change your username and basic account settings.
%hr
- header_title page_title, profile_account_path
- @blank_container = true
- if current_user.ldap_user?
.alert.alert-info
Some options are unavailable for LDAP accounts
@ -69,7 +67,7 @@
- button_based_providers.each do |provider|
.btn-group
= link_to provider_image_tag(provider), user_omniauth_authorize_path(provider), method: :post, class: "btn btn-lg #{'active' if auth_active?(provider)}", "data-no-turbolink" => "true"
- if auth_active?(provider)
= link_to unlink_profile_account_path(provider: provider), method: :delete, class: 'btn btn-lg' do
= icon('close')

View File

@ -1,13 +1,12 @@
- page_title "Applications"
%h3.page-title
= page_title
%p.light
- header_title page_title, applications_profile_path
.gray-content-block.top-block
- if user_oauth_applications?
Manage applications that can use GitLab as an OAuth provider,
Manage applications that can use GitLab as an OAuth provider,
and applications that you've authorized to use your account.
- else
Manage applications that you've authorized to use your account.
%hr
- if user_oauth_applications?
.oauth-applications

View File

@ -1,5 +1,8 @@
- page_title "Audit Log"
%h3.page-title Audit Log
%p.light History of authentications
- header_title page_title, audit_log_profile_path
= render 'event_table', events: @events
.gray-content-block.top-block
History of authentications
.prepend-top-default
= render 'event_table', events: @events

View File

@ -1,12 +1,10 @@
- page_title "Emails"
%h3.page-title
= page_title
%p.light
- header_title page_title, profile_emails_path
.gray-content-block.top-block
Control emails linked to your account
%hr
%ul
%ul.prepend-top-default
%li
Your
%b Primary Email

View File

@ -1,11 +1,12 @@
- page_title "SSH Keys"
%h3.page-title
= page_title
- header_title page_title, profile_keys_path
.gray-content-block.top-block
.pull-right
= link_to "Add SSH Key", new_profile_key_path, class: "btn btn-new"
%p.light
Before you can add an SSH key you need to
= link_to "generate it.", help_page_path("ssh", "README")
%hr
.oneline
Before you can add an SSH key you need to
= link_to "generate it.", help_page_path("ssh", "README")
.prepend-top-default
= render 'key_table'

View File

@ -1,10 +1,10 @@
- page_title "Notifications"
%h3.page-title
= page_title
%p.light
These are your global notification settings.
%hr
- header_title page_title, profile_notifications_path
.gray-content-block.top-block
These are your global notification settings.
.prepend-top-default
= form_for @user, url: profile_notifications_path, method: :put, html: { class: 'update-notifications form-horizontal global-notifications-form' } do |f|
-if @user.errors.any?
%div.alert.alert-danger

View File

@ -1,13 +1,13 @@
- page_title "Password"
%h3.page-title
= page_title
%p.light
- header_title page_title, edit_profile_password_path
.gray-content-block.top-block
- if @user.password_automatically_set?
Set your password.
- else
Change your password or recover your current one.
%hr
.update-password
.update-password.prepend-top-default
= form_for @user, url: profile_password_path, method: :put, html: { class: 'form-horizontal' } do |f|
%div
%p.slead

View File

@ -12,7 +12,7 @@
%ul
- @user.errors.full_messages.each do |msg|
%li= msg
- unless @user.password_automatically_set?
.form-group
= f.label :current_password, class: 'control-label'

View File

@ -1,11 +1,11 @@
- page_title 'Preferences'
%h3.page-title
= page_title
%p.light
- header_title page_title, profile_preferences_path
- @blank_container = true
.alert.alert-help
These settings allow you to customize the appearance and behavior of the site.
They are saved with your account and will persist to any device you use to
access the site.
%hr
= form_for @user, url: profile_preferences_path, remote: true, method: :put, html: {class: 'js-preferences-form form-horizontal'} do |f|
.panel.panel-default.application-theme

View File

@ -1,14 +1,9 @@
- page_title "Profile"
%h3.page-title
= page_title
%p.light
.gray-content-block.top-block
This information will appear on your profile.
- if current_user.ldap_user?
Some options are unavailable for LDAP accounts
%hr
.prepend-top-default
= form_for @user, url: profile_path, method: :put, html: { multipart: true, class: "edit_user form-horizontal" }, authenticity_token: true do |f|
-if @user.errors.any?
%div.alert.alert-danger

View File

@ -1,6 +1,6 @@
.md-area
.md-header.clearfix
%ul.nav.nav-tabs
%ul.center-top-menu
%li.active
= link_to '#md-write-holder', class: 'js-md-write-button', tabindex: '-1' do
Write
@ -14,7 +14,7 @@
You are about to add
%strong
%span.js-referenced-users-count 0
people
people
to the discussion. Proceed with caution.
%div

View File

@ -41,7 +41,7 @@
.commit-info-row.branches
%i.fa.fa-spinner.fa-spin
.commit-box
.commit-box.gray-content-block.middle-block
%h3.commit-title
= gfm escape_once(@commit.title)
- if @commit.description.present?

View File

@ -1,8 +1,8 @@
- if params[:view] == 'parallel'
- fluid_layout true
.prepend-top-20.append-bottom-20
.pull-right
.gray-content-block.second-block
.inline-parallel-buttons
.btn-group
= inline_diff_btn
= parallel_diff_btn

View File

@ -10,7 +10,7 @@
and
%strong.cred #{@commit.stats.deletions} deletions
.file-stats.js-toggle-content.hide
%ul.bordered-list
%ul
- diffs.each_with_index do |diff, i|
%li
- if diff.deleted_file

View File

@ -1,10 +1,11 @@
- @blank_container = true
.project-edit-container
.project-edit-errors
.project-edit-content
%div
%h3.page-title
.panel.panel-default
.panel-heading
Project settings
%hr
.panel-body
= form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "edit_project form-horizontal fieldset-form" }, authenticity_token: true do |f|

View File

@ -22,15 +22,15 @@
%h5 Git global setup
%pre.light-well
:preserve
git config --global user.name "#{git_user_name}"
git config --global user.email "#{git_user_email}"
git config --global user.name "#{h git_user_name}"
git config --global user.email "#{h git_user_email}"
%fieldset
%h5 Create a new repository
%pre.light-well
:preserve
git clone #{ content_tag(:span, default_url_to_repo, class: 'clone')}
cd #{@project.path}
cd #{h @project.path}
touch README.md
git add README.md
git commit -m "add README"

View File

@ -7,21 +7,24 @@
= render 'shared/show_aside'
.gray-content-block.second-block
.row
.col-md-9
.votes-holder.pull-right
#votes= render 'votes/votes_block', votable: @issue
.participants
%span= pluralize(@participants.count, 'participant')
- @participants.each do |participant|
= link_to_member(@project, participant, name: false, size: 24)
.col-md-3
%span.slead.has_tooltip{title: 'Cross-project reference'}
= cross_project_reference(@project, @issue)
.row
%section.col-md-9
.votes-holder.pull-right
#votes= render 'votes/votes_block', votable: @issue
.participants
%span= pluralize(@participants.count, 'participant')
- @participants.each do |participant|
= link_to_member(@project, participant, name: false, size: 24)
.voting_notes#notes= render 'projects/notes/notes_with_form'
%aside.col-md-3
.issuable-affix
.clearfix
%span.slead.has_tooltip{title: 'Cross-project reference'}
= cross_project_reference(@project, @issue)
%hr
.context
= render 'shared/issuable/context', issuable: @issue

View File

@ -41,4 +41,4 @@
= issue.task_status
.pull-right.issue-updated-at
%small updated #{time_ago_with_tooltip(issue.updated_at, placement: 'bottom', html_class: 'issue_update_ago')}
%span updated #{time_ago_with_tooltip(issue.updated_at, placement: 'bottom', html_class: 'issue_update_ago')}

View File

@ -1,15 +1,16 @@
- page_title "#{@issue.title} (##{@issue.iid})", "Issues"
.issue
.issue-details.issuable-details
%h4.page-title
.page-title
.issue-box{ class: issue_box_class(@issue) }
- if @issue.closed?
Closed
- else
Open
Issue ##{@issue.iid}
%small.creator
&middot; created by #{link_to_member(@project, @issue.author)}
%span.issue-id Issue ##{@issue.iid}
%span.creator
&middot; created by #{link_to_member(@project, @issue.author, size: 24)}
&middot;
= time_ago_with_tooltip(@issue.created_at, placement: 'bottom', html_class: 'issue_created_ago')
- if @issue.updated_at != @issue.created_at
%span
@ -32,18 +33,17 @@
= icon('pencil-square-o')
Edit
%hr
%h2.issue-title
= gfm escape_once(@issue.title)
%div
- if @issue.description.present?
.description{class: can?(current_user, :update_issue, @issue) ? 'js-task-list-container' : ''}
.wiki
= preserve do
= markdown(@issue.description)
%textarea.hidden.js-task-list-field
= @issue.description
.gray-content-block.middle-block
%h2.issue-title
= gfm escape_once(@issue.title)
%div
- if @issue.description.present?
.description{class: can?(current_user, :update_issue, @issue) ? 'js-task-list-container' : ''}
.wiki
= preserve do
= markdown(@issue.description)
%textarea.hidden.js-task-list-field
= @issue.description
%hr
.issue-discussion
= render 'projects/issues/discussion'

View File

@ -7,18 +7,21 @@
= render 'shared/show_aside'
.gray-content-block.second-block
.row
.col-md-9
.votes-holder.pull-right
#votes= render 'votes/votes_block', votable: @merge_request
= render "projects/merge_requests/show/participants"
.col-md-3
%span.slead.has_tooltip{:"data-original-title" => 'Cross-project reference'}
= cross_project_reference(@project, @merge_request)
.row
%section.col-md-9
.votes-holder.pull-right
#votes= render 'votes/votes_block', votable: @merge_request
= render "projects/merge_requests/show/participants"
= render "projects/notes/notes_with_form"
%aside.col-md-3
.issuable-affix
.clearfix
%span.slead.has_tooltip{:"data-original-title" => 'Cross-project reference'}
= cross_project_reference(@project, @merge_request)
%hr
.context
= render 'shared/issuable/context', issuable: @merge_request

View File

@ -43,4 +43,4 @@
= merge_request.task_status
.pull-right.hidden-xs
%small updated #{time_ago_with_tooltip(merge_request.updated_at, placement: 'bottom', html_class: 'merge_request_updated_ago')}
%span updated #{time_ago_with_tooltip(merge_request.updated_at, placement: 'bottom', html_class: 'merge_request_updated_ago')}

View File

@ -37,7 +37,7 @@
%h4 Compare failed
%p We can't compare selected branches. It may be because of huge diff. Please try again or select different branches.
- else
.light-well
.light-well.append-bottom-10
.center
%h4
There isn't anything to merge.

View File

@ -18,15 +18,13 @@
= f.hidden_field :target_branch
.mr-compare.merge-request
%ul.nav.nav-tabs.merge-request-tabs
%ul.merge-request-tabs
%li.commits-tab
= link_to url_for(params), data: {target: '#commits', action: 'commits', toggle: 'tab'} do
= icon('history')
Commits
%span.badge= @commits.size
%li.diffs-tab.active
= link_to url_for(params), data: {target: '#diffs', action: 'diffs', toggle: 'tab'} do
= icon('list-alt')
Changes
%span.badge= @diffs.size

View File

@ -5,10 +5,8 @@
.merge-request{'data-url' => merge_request_path(@merge_request)}
.merge-request-details.issuable-details
= render "projects/merge_requests/show/mr_title"
%hr
= render "projects/merge_requests/show/mr_box"
%hr
.append-bottom-20.mr-source-target
.append-bottom-20.mr-source-target.prepend-top-default
- if @merge_request.open?
.pull-right
- if @merge_request.source_branch_exists?
@ -39,20 +37,17 @@
= link_to "command line", "#modal_merge_info", class: "how_to_merge_link vlink", title: "How To Merge", "data-toggle" => "modal"
- if @commits.present?
%ul.nav.nav-tabs.merge-request-tabs
%ul.merge-request-tabs
%li.notes-tab
= link_to namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: '#notes', action: 'notes', toggle: 'tab'} do
= icon('comments')
Discussion
%span.badge= @merge_request.mr_and_commit_notes.user.count
%li.commits-tab
= link_to commits_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: '#commits', action: 'commits', toggle: 'tab'} do
= icon('history')
Commits
%span.badge= @commits.size
%li.diffs-tab
= link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: '#diffs', action: 'diffs', toggle: 'tab'} do
= icon('list-alt')
Changes
%span.badge= @merge_request.diffs.size

View File

@ -11,12 +11,12 @@
%pre.dark
- if @merge_request.for_fork?
:preserve
git fetch #{@merge_request.source_project.http_url_to_repo} #{@merge_request.source_branch}
git checkout -b #{@merge_request.source_project_path}-#{@merge_request.source_branch} FETCH_HEAD
git fetch #{h @merge_request.source_project.http_url_to_repo} #{h @merge_request.source_branch}
git checkout -b #{h @merge_request.source_project_path}-#{h @merge_request.source_branch} FETCH_HEAD
- else
:preserve
git fetch origin
git checkout -b #{@merge_request.source_branch} origin/#{@merge_request.source_branch}
git checkout -b #{h @merge_request.source_branch} origin/#{h @merge_request.source_branch}
%p
%strong Step 2.
Review the changes locally
@ -27,18 +27,18 @@
%pre.dark
- if @merge_request.for_fork?
:preserve
git checkout #{@merge_request.target_branch}
git merge --no-ff #{@merge_request.source_project_path}-#{@merge_request.source_branch}
git checkout #{h @merge_request.target_branch}
git merge --no-ff #{h @merge_request.source_project_path}-#{h @merge_request.source_branch}
- else
:preserve
git checkout #{@merge_request.target_branch}
git merge --no-ff #{@merge_request.source_branch}
git checkout #{h @merge_request.target_branch}
git merge --no-ff #{h @merge_request.source_branch}
%p
%strong Step 4.
Push the result of the merge to GitLab
%pre.dark
:preserve
git push origin #{@merge_request.target_branch}
git push origin #{h @merge_request.target_branch}
- unless @merge_request.can_be_merged_by?(current_user)
%p
Note that pushing to GitLab requires write access to this repository.

View File

@ -1,11 +1,12 @@
%h2.issue-title
= gfm escape_once(@merge_request.title)
.gray-content-block.middle-block
%h2.issue-title
= gfm escape_once(@merge_request.title)
%div
- if @merge_request.description.present?
.description{class: can?(current_user, :update_merge_request, @merge_request) ? 'js-task-list-container' : ''}
.wiki
= preserve do
= markdown(@merge_request.description)
%textarea.hidden.js-task-list-field
= @merge_request.description
%div
- if @merge_request.description.present?
.description{class: can?(current_user, :update_merge_request, @merge_request) ? 'js-task-list-container' : ''}
.wiki
= preserve do
= markdown(@merge_request.description)
%textarea.hidden.js-task-list-field
= @merge_request.description

View File

@ -1,10 +1,11 @@
%h4.page-title
.page-title
.issue-box{ class: issue_box_class(@merge_request) }
= @merge_request.state_human_name
Merge Request ##{@merge_request.iid}
%small.creator
%span.issue-id Merge Request ##{@merge_request.iid}
%span.creator
&middot;
created by #{link_to_member(@project, @merge_request.author, size: 24)}
&middot;
created by #{link_to_member(@project, @merge_request.author)}
= time_ago_with_tooltip(@merge_request.created_at)
- if @merge_request.updated_at != @merge_request.created_at
%span

View File

@ -9,7 +9,7 @@
= label_tag :should_remove_source_branch, class: "remove_source_checkbox" do
= check_box_tag :should_remove_source_branch
Remove source branch
.accept-control
.accept-control.right
= link_to "#", class: "modify-merge-commit-link js-toggle-button" do
= icon('edit')
Modify commit message

View File

@ -1,28 +1,34 @@
%li{class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: dom_id(milestone) }
.pull-right
- if can?(current_user, :admin_milestone, milestone.project) and milestone.active?
= link_to edit_namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone), class: "btn btn-sm edit-milestone-link btn-grouped" do
%i.fa.fa-pencil-square-o
Edit
= link_to 'Close Milestone', namespace_project_milestone_path(@project.namespace, @project, milestone, milestone: {state_event: :close }), method: :put, remote: true, class: "btn btn-sm btn-close"
= link_to namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone), data: { confirm: 'Are you sure?' }, method: :delete, class: "btn btn-sm btn-remove" do
%i.fa.fa-trash-o
Remove
.row
.col-sm-6
%strong
= link_to_gfm truncate(milestone.title, length: 100), namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone)
%h4
= link_to_gfm truncate(milestone.title, length: 100), namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone)
- if milestone.expired? and not milestone.closed?
%span.cred (Expired)
%small
= milestone.expires_at
.col-sm-6
.pull-right.light #{milestone.percent_complete}% complete
.row
.col-sm-6
= link_to namespace_project_issues_path(milestone.project.namespace, milestone.project, milestone_title: milestone.title) do
= pluralize milestone.issues.count, 'Issue'
&nbsp;
&middot;
= link_to namespace_project_merge_requests_path(milestone.project.namespace, milestone.project, milestone_title: milestone.title) do
= pluralize milestone.merge_requests.count, 'Merge Request'
&nbsp;
%span.light #{milestone.percent_complete}% complete
.col-sm-6
= milestone_progress_bar(milestone)
.row
.col-sm-6
- if milestone.expired? and not milestone.closed?
%span.cred (Expired)
- if milestone.expires_at
%span
= milestone.expires_at
.col-sm-6
- if can?(current_user, :admin_milestone, milestone.project) and milestone.active?
= link_to edit_namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone), class: "btn btn-xs edit-milestone-link btn-grouped" do
%i.fa.fa-pencil-square-o
Edit
= link_to 'Close Milestone', namespace_project_milestone_path(@project.namespace, @project, milestone, milestone: {state_event: :close }), method: :put, remote: true, class: "btn btn-xs btn-close"
= link_to namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone), data: { confirm: 'Are you sure?' }, method: :delete, class: "btn btn-xs btn-remove" do
%i.fa.fa-trash-o
Remove

View File

@ -72,6 +72,11 @@
%i.fa.fa-google
Google Code
- if fogbugz_import_enabled?
= link_to new_import_fogbugz_path, class: 'btn import_fogbugz' do
%i.fa.fa-bug
Fogbugz
- if git_import_enabled?
= link_to "#", class: 'btn js-toggle-button import_git' do
%i.fa.fa-git

View File

@ -1,11 +1,8 @@
%li.timeline-entry{ id: dom_id(note), class: [dom_class(note), "note-row-#{note.id}", ('system-note' if note.system)], data: { discussion: note.discussion_id } }
.timeline-entry-inner
.timeline-icon
- if note.system
%span= icon('circle')
- else
= link_to user_path(note.author) do
= image_tag avatar_icon(note.author_email), class: 'avatar s40', alt: ''
= link_to user_path(note.author) do
= image_tag avatar_icon(note.author_email), class: 'avatar s40', alt: ''
.timeline-content
.note-header
- if note_editable?(note)
@ -22,10 +19,6 @@
%span.note-role.label
= member.human_access
- if note.system
= link_to user_path(note.author) do
= image_tag avatar_icon(note.author_email), class: 'avatar s16', alt: ''
= link_to_member(note.project, note.author, avatar: false)
%span.author-username

View File

@ -1,4 +1,9 @@
%span.pull-right
- if can?(current_user, :create_wiki, @project)
= link_to '#modal-new-wiki', class: "add-new-wiki btn btn-new btn-grouped", "data-toggle" => "modal" do
%i.fa.fa-plus
New Page
- if (@page && @page.persisted?)
= link_to namespace_project_wiki_history_path(@project.namespace, @project, @page), class: "btn btn-grouped" do
Page History
@ -6,3 +11,5 @@
= link_to namespace_project_wiki_edit_path(@project.namespace, @project, @page), class: "btn btn-grouped" do
%i.fa.fa-pencil-square-o
Edit
= render 'projects/wikis/new'

View File

@ -1,4 +1,4 @@
%ul.nav.nav-tabs
%ul.center-top-menu
= nav_link(html_options: {class: params[:id] == 'home' ? 'active' : '' }) do
= link_to 'Home', namespace_project_wiki_path(@project.namespace, @project, :home)
@ -7,13 +7,4 @@
= nav_link(path: 'wikis#git_access') do
= link_to namespace_project_wikis_git_access_path(@project.namespace, @project) do
%i.fa.fa-download
Git Access
- if can?(current_user, :create_wiki, @project)
.pull-right
= link_to '#modal-new-wiki', class: "add-new-wiki btn btn-new", "data-toggle" => "modal" do
%i.fa.fa-plus
New Page
= render 'projects/wikis/new'

View File

@ -1,15 +1,16 @@
- page_title "Git Access", "Wiki"
= render 'nav'
.row
.col-sm-6
%h3.page-title
Git access for
%strong= @project_wiki.path_with_namespace
.gray-content-block
.row
.col-sm-6
%h3.page-title
Git access for
%strong= @project_wiki.path_with_namespace
.col-sm-6
= render "shared/clone_panel", project: @project_wiki
.col-sm-6
= render "shared/clone_panel", project: @project_wiki
.git-empty
.git-empty.prepend-top-default
%fieldset
%legend Install Gollum:
%pre.dark
@ -20,7 +21,7 @@
%pre.dark
:preserve
git clone #{ content_tag(:span, default_url_to_repo(@project_wiki), class: 'clone')}
cd #{@project_wiki.path}
cd #{h @project_wiki.path}
%legend Start Gollum And Edit Locally:
%pre.dark

View File

@ -1,8 +1,9 @@
- page_title "History", @page.title, "Wiki"
= render 'nav'
%h3.page-title
%span.light History for
= link_to @page.title, namespace_project_wiki_path(@project.namespace, @project, @page)
.gray-content-block
%h3.page-title
%span.light History for
= link_to @page.title, namespace_project_wiki_path(@project.namespace, @project, @page)
%table.table
%thead

View File

@ -1,8 +1,9 @@
- page_title "All Pages", "Wiki"
= render 'nav'
%h3.page-title
All Pages
%ul.bordered-list
.gray-content-block
%h3.page-title
All Pages
%ul.content-list
- @wiki_pages.each do |wiki_page|
%li
%h4

View File

@ -1,25 +1,26 @@
- page_title @page.title, "Wiki"
= render 'nav'
%h3.page-title
= @page.title
= render 'main_links'
.wiki-last-edit-by
Last edited by #{@page.commit.author.name} #{time_ago_with_tooltip(@page.commit.authored_date)}
.gray-content-block
= render 'main_links'
%h3.page-title
= @page.title.capitalize
.wiki-last-edit-by
Last edited by #{@page.commit.author.name} #{time_ago_with_tooltip(@page.commit.authored_date)}
- if @page.historical?
.warning_message
This is an old version of this page.
You can view the #{link_to "most recent version", namespace_project_wiki_path(@project.namespace, @project, @page)} or browse the #{link_to "history", namespace_project_wiki_history_path(@project.namespace, @project, @page)}.
%hr
.wiki-holder
.wiki-holder.prepend-top-default
.wiki
= preserve do
= render_wiki_content(@page)
%hr
.wiki-last-edit-by
Last edited by #{@page.commit.author.name} #{time_ago_with_tooltip(@page.commit.authored_date)}
.gray-content-block.footer-block
.wiki-last-edit-by
Last edited by #{@page.commit.author.name} #{time_ago_with_tooltip(@page.commit.authored_date)}

View File

@ -9,7 +9,7 @@
= f.label :title, class: 'control-label' do
%strong= 'Title *'
.col-sm-10
= f.text_field :title, maxlength: 255, autofocus: true,
= f.text_field :title, maxlength: 255, autofocus: true, autocomplete: 'off',
class: 'form-control pad js-gfm-input', required: true
- if issuable.is_a?(MergeRequest)

View File

@ -7,22 +7,31 @@ class RepositoryImportWorker
def perform(project_id)
project = Project.find(project_id)
import_result = gitlab_shell.send(:import_repository,
unless project.import_url == Project::UNKNOWN_IMPORT_URL
import_result = gitlab_shell.send(:import_repository,
project.path_with_namespace,
project.import_url)
return project.import_fail unless import_result
return project.import_fail unless import_result
else
unless project.create_repository
return project.import_fail
end
end
data_import_result = if project.import_type == 'github'
Gitlab::GithubImport::Importer.new(project).execute
elsif project.import_type == 'gitlab'
Gitlab::GitlabImport::Importer.new(project).execute
elsif project.import_type == 'bitbucket'
Gitlab::BitbucketImport::Importer.new(project).execute
elsif project.import_type == 'google_code'
Gitlab::GoogleCodeImport::Importer.new(project).execute
else
true
end
data_import_result = case project.import_type
when 'github'
Gitlab::GithubImport::Importer.new(project).execute
when 'gitlab'
Gitlab::GitlabImport::Importer.new(project).execute
when 'bitbucket'
Gitlab::BitbucketImport::Importer.new(project).execute
when 'google_code'
Gitlab::GoogleCodeImport::Importer.new(project).execute
when 'fogbugz'
Gitlab::FogbugzImport::Importer.new(project).execute
else
true
end
return project.import_fail unless data_import_result
Gitlab::BitbucketImport::KeyDeleter.new(project).execute if project.import_type == 'bitbucket'

View File

@ -158,7 +158,7 @@ Settings.gitlab.default_projects_features['snippets'] = false if Settings.
Settings.gitlab.default_projects_features['visibility_level'] = Settings.send(:verify_constant, Gitlab::VisibilityLevel, Settings.gitlab.default_projects_features['visibility_level'], Gitlab::VisibilityLevel::PRIVATE)
Settings.gitlab['repository_downloads_path'] = File.absolute_path(Settings.gitlab['repository_downloads_path'] || 'tmp/repositories', Rails.root)
Settings.gitlab['restricted_signup_domains'] ||= []
Settings.gitlab['import_sources'] ||= ['github','bitbucket','gitlab','gitorious','google_code','git']
Settings.gitlab['import_sources'] ||= ['github','bitbucket','gitlab','gitorious','google_code','fogbugz','git']
#
# Reply by email

View File

@ -0,0 +1,24 @@
# Here until https://github.com/jneen/rouge/pull/297 is merged into Rouge and the gem is updated in GitLab.
module Rouge
module Lexers
class Diff
def self.analyze_text(text)
return 1 if text.start_with?('Index: ')
return 1 if text.start_with?('diff ')
return 0.9 if text.start_with?('--- ')
end
state :root do
rule(/^ .*\n/, Text)
rule(/^---\n/, Text)
rule(/^\+.*\n/, Generic::Inserted)
rule(/^-+.*\n/, Generic::Deleted)
rule(/^!.*\n/, Generic::Strong)
rule(/^@.*\n/, Generic::Subheading)
rule(/^([Ii]ndex|diff).*\n/, Generic::Heading)
rule(/^=.*\n/, Generic::Heading)
rule(/.*\n/, Text)
end
end
end
end

View File

@ -2,7 +2,12 @@
require 'gitlab/current_settings'
include Gitlab::CurrentSettings
Settings.gitlab['session_expire_delay'] = current_application_settings.session_expire_delay
# allow it to fail: it may to do so when create_from_defaults is executed before migrations are actually done
begin
Settings.gitlab['session_expire_delay'] = current_application_settings.session_expire_delay
rescue
end
Gitlab::Application.config.session_store(
:redis_store, # Using the cookie_store would enable session replay attacks.

View File

@ -99,6 +99,15 @@ Gitlab::Application.routes.draw do
get :new_user_map, path: :user_map
post :create_user_map, path: :user_map
end
resource :fogbugz, only: [:create, :new], controller: :fogbugz do
get :status
post :callback
get :jobs
get :new_user_map, path: :user_map
post :create_user_map, path: :user_map
end
end
#
@ -202,6 +211,8 @@ Gitlab::Application.routes.draw do
resources :services
end
resources :labels
root to: 'dashboard#index'
end

View File

@ -0,0 +1,5 @@
class AddTemplateToLabel < ActiveRecord::Migration
def change
add_column :labels, :template, :boolean, default: false
end
end

View File

@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20150824002011) do
ActiveRecord::Schema.define(version: 20150902001023) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -186,6 +186,7 @@ ActiveRecord::Schema.define(version: 20150824002011) do
t.integer "project_id"
t.datetime "created_at"
t.datetime "updated_at"
t.boolean "template", default: false
end
add_index "labels", ["project_id"], name: "index_labels_on_project_id", using: :btree

View File

@ -299,7 +299,7 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da
GitLab Shell is an SSH access and repository management software developed specially for GitLab.
# Run the installation task for gitlab-shell (replace `REDIS_URL` if needed):
sudo -u git -H bundle exec rake gitlab:shell:install[v2.6.3] REDIS_URL=unix:/var/run/redis/redis.sock RAILS_ENV=production
sudo -u git -H bundle exec rake gitlab:shell:install[v2.6.5] REDIS_URL=unix:/var/run/redis/redis.sock RAILS_ENV=production
# By default, the gitlab-shell config is generated from your main GitLab config.
# You can review (and modify) the gitlab-shell config as follows:

View File

@ -127,7 +127,7 @@ sudo apt-get install nodejs
```bash
cd /home/git/gitlab-shell
sudo -u git -H git fetch
sudo -u git -H git checkout v2.6.4
sudo -u git -H git checkout v2.6.5
```
## 7. Install libs, migrations, etc.
@ -162,12 +162,12 @@ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
TIP: to see what changed in `gitlab.yml.example` in this release use next command:
```
git diff 6-0-stable:config/gitlab.yml.example 7.14-stable:config/gitlab.yml.example
git diff 6-0-stable:config/gitlab.yml.example 7-14-stable:config/gitlab.yml.example
```
* Make `/home/git/gitlab/config/gitlab.yml` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-14-stable/config/gitlab.yml.example but with your settings.
* Make `/home/git/gitlab/config/unicorn.rb` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-14-stable/config/unicorn.rb.example but with your settings.
* Make `/home/git/gitlab-shell/config.yml` the same as https://gitlab.com/gitlab-org/gitlab-shell/blob/v2.6.0/config.yml.example but with your settings.
* Make `/home/git/gitlab-shell/config.yml` the same as https://gitlab.com/gitlab-org/gitlab-shell/blob/v2.6.5/config.yml.example but with your settings.
* Copy rack attack middleware config
```bash

View File

@ -63,7 +63,7 @@ sudo -u git -H git checkout 7-14-stable-ee
```bash
cd /home/git/gitlab-shell
sudo -u git -H git fetch
sudo -u git -H git checkout v2.6.4
sudo -u git -H git checkout v2.6.5
```
### 5. Install libs, migrations, etc.

View File

@ -3,6 +3,7 @@
1. [Bitbucket](import_projects_from_bitbucket.md)
2. [GitHub](import_projects_from_github.md)
3. [GitLab.com](import_projects_from_gitlab_com.md)
4. [FogBugz](import_projects_from_fogbugz.md)
4. [SVN](migrating_from_svn.md)
### Note

Some files were not shown because too many files have changed in this diff Show More