Commit a6997e33 authored by Douwe Maan's avatar Douwe Maan

Merge branch 'master' into dashboard-titles

parents e4b30f9d dadf6daa
......@@ -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.
......
......@@ -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
......
......@@ -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)
......
......@@ -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
*
*/
.container-blank .panel .panel-heading {
font-size: 17px;
line-height: 38px;
}
.panel {
.panel-heading {
font-weight: bold;
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,
......
......@@ -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;
......@@ -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;
}
}
}
......@@ -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;
......
......@@ -10,7 +10,7 @@
}
&.btn-save {
@extend .btn-primary;
@extend .btn-success;
}
&.btn-remove {
......
......@@ -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;
}
}
}
......@@ -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;
}
......
......@@ -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%;
......
......@@ -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;
......
.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;
&:target {
.timeline-entry-inner .timeline-content {
-webkit-animation:target-note 2s linear;
background: $hover;
}
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;
&:last-child {
border-bottom: none;
}
.timeline-entry-inner {
position: relative;
margin-left: -20px;
&: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%;
}
.avatar {
margin-right: 15px;
}
&: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;
}
......@@ -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;
......
......@@ -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;
}
......
.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;
}
......@@ -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;
}
}
}
.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;
}
......@@ -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;
}
}
......
......@@ -6,4 +6,8 @@ li.milestone {
h4 {
font-weight: bold;
}
.progress {
height: 6px;
}
}
......@@ -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;
}
......@@ -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;
......
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
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
......
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
......@@ -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
......@@ -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
......
......@@ -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
......@@ -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
......
......@@ -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)
......
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
= 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
%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?"}
- if @labels.size == 0
$('.labels').load(document.URL + ' .light-well').hide().fadeIn(1000)
- 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'
- 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
\ No newline at end of file
- page_title "New Label"
%h3 New label
.back-link
= link_to admin_labels_path do
&larr; To labels list
%hr
= render 'form'
%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
- @blank_container = true
.panel.panel-default
.panel-heading
%strong= @group.name
......
- 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
......
%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"
- 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'
- 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()
- 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}")
......@@ -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
......
......@@ -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
......@@ -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')
......
......@@ -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
......@@ -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')
......
- 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"
- 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')
......
- 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
......
- 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
\ No newline at end of file
.gray-content-block.top-block
History of authentications
.prepend-top-default
= render 'event_table', events: @events
- page_title "Emails"
%h3.page-title
= page_title
%p.light
Control emails linked to your account
%hr
- header_title page_title, profile_emails_path
.gray-content-block.top-block
Control emails linked to your account
%ul
%ul.prepend-top-default
%li
Your
%b Primary Email
......
- 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'
- page_title "Notifications"
%h3.page-title
= page_title
%p.light
- header_title page_title, profile_notifications_path
.gray-content-block.top-block
These are your global notification settings.
%hr
.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
......
- 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
......
......@@ -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'
......
- 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
......
- 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
......
.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
......
......@@ -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?
......
- 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
......
......@@ -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
......
- @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|
......
......@@ -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"
......
......@@ -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
......
......@@ -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')}
- 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'
......@@ -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
......
......@@ -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')}
......@@ -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.
......
......@@ -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
......
......@@ -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
......
......@@ -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.
......
%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
%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
......
......@@ -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
......
%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
......@@ -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
......
%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
......
%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'
%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'
- 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
......
- 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
......
- 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
......
- page_title @page.title, "Wiki"
= render 'nav'
%h3.page-title
= @page.title
.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)}
.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)}
......@@ -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)
......
......@@ -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'
......
......@@ -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
......
# 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
......@@ -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.
......
......@@ -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
......
class AddTemplateToLabel < ActiveRecord::Migration
def change
add_column :labels, :template, :boolean, default: false
end
end
\ No newline at end of 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
......
......@@ -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:
......
......@@ -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
......
......@@ -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.
......
......@@ -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
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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