summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVinnie Okada <vokada@mrvinn.com>2015-02-21 12:55:28 -0700
committerVinnie Okada <vokada@mrvinn.com>2015-02-21 12:55:28 -0700
commit2a9eed6620fd57c2a82edf5eab95dade3da250d3 (patch)
treed4c33eaaae008510086b0476db9bd4ae32dc298e
parent83e2a1ca12372279cf7948b4d4b3e8a11c50e428 (diff)
parent71e146999c405ab301cd3c3e3aa03b89d46c461e (diff)
downloadgitlab-ce-2a9eed6620fd57c2a82edf5eab95dade3da250d3.tar.gz
Merge branch 'master' into rails-4.1.9
Conflicts: app/views/projects/commits/_commit.html.haml app/views/projects/issues/_issue.html.haml app/views/projects/issues/_issue_context.html.haml app/views/projects/merge_requests/_merge_request.html.haml app/views/projects/merge_requests/show/_context.html.haml
-rw-r--r--CHANGELOG7
-rw-r--r--app/assets/javascripts/calendar.js.coffee3
-rw-r--r--app/assets/stylesheets/sections/commit.scss131
-rw-r--r--app/assets/stylesheets/sections/commits.scss168
-rw-r--r--app/assets/stylesheets/sections/issuable.scss16
-rw-r--r--app/assets/stylesheets/sections/issues.scss5
-rw-r--r--app/assets/stylesheets/sections/merge_requests.scss1
-rw-r--r--app/assets/stylesheets/sections/nav_sidebar.scss7
-rw-r--r--app/assets/stylesheets/sections/note_form.scss2
-rw-r--r--app/controllers/import/gitorious_controller.rb43
-rw-r--r--app/controllers/projects/blame_controller.rb2
-rw-r--r--app/controllers/projects/blob_controller.rb2
-rw-r--r--app/controllers/projects/branches_controller.rb1
-rw-r--r--app/controllers/projects/commit_controller.rb2
-rw-r--r--app/controllers/projects/commits_controller.rb2
-rw-r--r--app/controllers/projects/compare_controller.rb2
-rw-r--r--app/controllers/projects/forks_controller.rb2
-rw-r--r--app/controllers/projects/graphs_controller.rb2
-rw-r--r--app/controllers/projects/network_controller.rb2
-rw-r--r--app/controllers/projects/raw_controller.rb2
-rw-r--r--app/controllers/projects/refs_controller.rb2
-rw-r--r--app/controllers/projects/repositories_controller.rb2
-rw-r--r--app/controllers/projects/tree_controller.rb2
-rw-r--r--app/controllers/projects/uploads_controller.rb19
-rw-r--r--app/controllers/uploads_controller.rb17
-rw-r--r--app/models/note.rb18
-rw-r--r--app/services/merge_requests/build_service.rb12
-rw-r--r--app/views/import/gitorious/status.html.haml41
-rw-r--r--app/views/layouts/_head.html.haml7
-rw-r--r--app/views/projects/commits/_commit.html.haml16
-rw-r--r--app/views/projects/commits/_commits.html.haml9
-rw-r--r--app/views/projects/issues/_discussion.html.haml6
-rw-r--r--app/views/projects/issues/_issue.html.haml16
-rw-r--r--app/views/projects/issues/_issue_context.html.haml20
-rw-r--r--app/views/projects/issues/show.html.haml2
-rw-r--r--app/views/projects/merge_requests/_discussion.html.haml3
-rw-r--r--app/views/projects/merge_requests/_merge_request.html.haml39
-rw-r--r--app/views/projects/merge_requests/show/_context.html.haml33
-rw-r--r--app/views/projects/merge_requests/show/_mr_box.html.haml2
-rw-r--r--app/views/projects/merge_requests/show/_participants.html.haml2
-rw-r--r--app/views/projects/new.html.haml26
-rw-r--r--config/initializers/static_files.rb15
-rw-r--r--config/routes.rb20
-rw-r--r--doc/api/projects.md18
-rw-r--r--doc/update/6.x-or-7.x-to-7.8.md8
-rw-r--r--doc/update/7.7-to-7.8.md5
-rw-r--r--doc/web_hooks/web_hooks.md20
-rw-r--r--lib/gitlab/diff/parser.rb2
-rw-r--r--lib/gitlab/gitorious_import/client.rb63
-rw-r--r--lib/gitlab/gitorious_import/project_creator.rb39
-rw-r--r--lib/gitlab/middleware/static.rb13
-rw-r--r--lib/gitlab/push_data_builder.rb3
-rw-r--r--lib/support/nginx/gitlab33
-rw-r--r--lib/support/nginx/gitlab-ssl34
-rw-r--r--spec/controllers/import/gitorious_controller_spec.rb67
-rw-r--r--spec/lib/gitlab/gitorious_import/project_creator.rb23
-rw-r--r--spec/lib/gitlab/push_data_builder_spec.rb3
57 files changed, 787 insertions, 275 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 92500596656..2c6f87666cb 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,7 +1,10 @@
v 7.9.0 (unreleased)
- - Fix broken access control for note attachments (Hannes Rosenögger)
+ - Move labels/milestones tabs to sidebar
+ - Improve UI for commits, issues and merge request lists
+ - Fix commit comments on first line of diff not rendering in Merge Request Discussion view.
v 7.8.0 (unreleased)
+ - Fix access control and protection against XSS for note attachments and other uploads.
- Replace highlight.js with rouge-fork rugments (Stefan Tatschner)
- Make project search case insensitive (Hannes Rosenögger)
- Include issue/mr participants in list of recipients for reassign/close/reopen emails
@@ -64,6 +67,8 @@ v 7.8.0 (unreleased)
- Remove deprecated Group#owner_id from API
- Show projects user contributed to on user page. Show stars near project on user page.
- Improve database performance for GitLab
+ - Add Asana service (Jeremy Benoist)
+ - Improve project web hooks with extra data
v 7.7.2
- Update GitLab Shell to version 2.4.2 that fixes a bug when developers can push to protected branch
diff --git a/app/assets/javascripts/calendar.js.coffee b/app/assets/javascripts/calendar.js.coffee
index 70940e13858..19ea4ccc4cf 100644
--- a/app/assets/javascripts/calendar.js.coffee
+++ b/app/assets/javascripts/calendar.js.coffee
@@ -16,11 +16,8 @@ class @calendar
subDomain: "day"
range: 12
tooltip: true
- domainDynamicDimension: false
- colLimit: 4
label:
position: "top"
- domainMargin: 1
legend: [
0
1
diff --git a/app/assets/stylesheets/sections/commit.scss b/app/assets/stylesheets/sections/commit.scss
new file mode 100644
index 00000000000..0e2d9571a45
--- /dev/null
+++ b/app/assets/stylesheets/sections/commit.scss
@@ -0,0 +1,131 @@
+.commit-title{
+ display: block;
+}
+
+.commit-title{
+ margin-bottom: 10px;
+}
+
+.commit-author, .commit-committer{
+ display: block;
+ color: #999;
+ font-weight: normal;
+ font-style: italic;
+}
+
+.commit-author strong, .commit-committer strong{
+ font-weight: bold;
+ font-style: normal;
+}
+
+.commit-description {
+ background: none;
+ border: none;
+ margin: 0;
+ padding: 0;
+ margin-top: 10px;
+}
+
+.commit-stat-summary {
+ color: #666;
+ font-size: 14px;
+ font-weight: normal;
+ padding: 10px 0;
+}
+
+.commit-info-row {
+ margin-bottom: 10px;
+ .avatar {
+ @extend .avatar-inline;
+ }
+ .commit-committer-link,
+ .commit-author-link {
+ color: #444;
+ font-weight: bold;
+ }
+}
+
+.commit-committer-link,
+.commit-author-link {
+ font-size: 13px;
+ color: #555;
+ &:hover {
+ color: #999;
+ }
+}
+
+.commit-box {
+ margin: 10px 0;
+ border-top: 1px solid #ddd;
+ border-bottom: 1px solid #ddd;
+ padding: 20px 0;
+
+ .commit-title {
+ margin: 0;
+ }
+
+ .commit-description {
+ margin-top: 15px;
+ }
+}
+
+.file-stats a {
+ color: $style_color;
+}
+
+.file-stats {
+ .new-file {
+ a {
+ color: #090;
+ }
+ i {
+ color: #1BCF00;
+ }
+ }
+ .renamed-file {
+ i {
+ color: #FE9300;
+ }
+ }
+ .deleted-file {
+ a {
+ color: #B00;
+ }
+ i {
+ color: #EE0000;
+ }
+ }
+ .edit-file{
+ i{
+ color: #555;
+ }
+ }
+}
+
+/*
+ * Commit message textarea for web editor and
+ * custom merge request message
+ */
+.commit-message-container {
+ background-color: $body-bg;
+ position: relative;
+ font-family: $monospace_font;
+ $left: 12px;
+ .max-width-marker {
+ width: 72ch;
+ color: rgba(0, 0, 0, 0.0);
+ font-family: inherit;
+ left: $left;
+ height: 100%;
+ border-right: 1px solid mix($input-border, white);
+ position: absolute;
+ z-index: 1;
+ }
+ > textarea {
+ background-color: rgba(0, 0, 0, 0.0);
+ font-family: inherit;
+ padding-left: $left;
+ position: relative;
+ z-index: 2;
+ }
+}
diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss
index 2e274d06c12..683aca73593 100644
--- a/app/assets/stylesheets/sections/commits.scss
+++ b/app/assets/stylesheets/sections/commits.scss
@@ -1,77 +1,3 @@
-/**
- * Commit file
- */
-.commit-committer-link,
-.commit-author-link {
- font-size: 13px;
- color: #555;
- &:hover {
- color: #999;
- }
-}
-
-/** COMMIT BLOCK **/
-.commit-title{
- display: block;
-}
-.commit-title{
- margin-bottom: 10px;
-}
-.commit-author, .commit-committer{
- display: block;
- color: #999;
- font-weight: normal;
- font-style: italic;
-}
-.commit-author strong, .commit-committer strong{
- font-weight: bold;
- font-style: normal;
-}
-
-
-.file-stats a {
- color: $style_color;
-}
-
-.file-stats {
- .new-file {
- a {
- color: #090;
- }
- i {
- color: #1BCF00;
- }
- }
- .renamed-file {
- i {
- color: #FE9300;
- }
- }
- .deleted-file {
- a {
- color: #B00;
- }
- i {
- color: #EE0000;
- }
- }
- .edit-file{
- i{
- color: #555;
- }
- }
-}
-
-.label_commit {
- @include border-radius(4px);
- padding: 2px 4px;
- font-size: 13px;
- background: #474D57;
- color: #fff;
- font-family: $monospace_font;
-}
-
-
.commits-compare-switch{
background: image-url("switch_icon.png") no-repeat center center;
width: 32px;
@@ -85,60 +11,40 @@
background-color: #EEE;
}
-.commit-description {
- background: none;
- border: none;
- margin: 0;
- padding: 0;
- margin-top: 10px;
-}
-.commit-box {
+.lists-separator {
margin: 10px 0;
- border-top: 1px solid #ddd;
- border-bottom: 1px solid #ddd;
- padding: 20px 0;
+ border-color: #DDD;
+}
- .commit-title {
+.commits-row {
+ ul {
margin: 0;
+
+ li.commit {
+ padding: 8px 0;
+ }
}
- .commit-description {
- margin-top: 15px;
+ .commits-row-date {
+ font-size: 15px;
+ line-height: 20px;
+ margin-bottom: 5px;
}
}
+.commits-feed-holder {
+ float: right;
-.commit-stat-summary {
- color: #666;
- font-size: 14px;
- font-weight: normal;
- padding: 10px 0;
-}
-
-.commit-info-row {
- margin-bottom: 10px;
- .avatar {
- @extend .avatar-inline;
- }
- .commit-committer-link,
- .commit-author-link {
- color: #444;
- font-weight: bold;
+ .btn {
+ padding: 4px 12px;
}
}
-.lists-separator {
- margin: 10px 0;
- border-top: 1px dashed #CCC;
-}
-
-/**
- * COMMIT ROW
- */
li.commit {
.commit-row-title {
font-size: $list-font-size;
+ line-height: 20px;
margin-bottom: 2px;
.notes_count {
@@ -156,9 +62,9 @@ li.commit {
}
.commit-row-message {
- color: #333;
+ color: #444;
+
&:hover {
- color: #444;
text-decoration: underline;
}
}
@@ -193,13 +99,14 @@ li.commit {
.commit-row-info {
color: #777;
+ line-height: 24px;
a {
color: #777;
}
.committed_ago {
- float: right;
+ display: inline-block;
}
}
@@ -214,34 +121,3 @@ li.commit {
}
}
}
-
-.commits-feed-holder {
- float: right;
- .btn {
- padding: 4px 12px;
- }
-}
-
-.commit-message-container {
- background-color: $body-bg;
- position: relative;
- font-family: $monospace_font;
- $left: 12px;
- .max-width-marker {
- width: 72ch;
- color: rgba(0, 0, 0, 0.0);
- font-family: inherit;
- left: $left;
- height: 100%;
- border-right: 1px solid mix($input-border, white);
- position: absolute;
- z-index: 1;
- }
- > textarea {
- background-color: rgba(0, 0, 0, 0.0);
- font-family: inherit;
- padding-left: $left;
- position: relative;
- z-index: 2;
- }
-}
diff --git a/app/assets/stylesheets/sections/issuable.scss b/app/assets/stylesheets/sections/issuable.scss
index 75bd39853bd..d8d12338859 100644
--- a/app/assets/stylesheets/sections/issuable.scss
+++ b/app/assets/stylesheets/sections/issuable.scss
@@ -23,3 +23,19 @@
}
}
}
+
+.issuable-context-title {
+ font-size: 15px;
+ line-height: 1.4;
+ margin-bottom: 5px;
+
+ .avatar {
+ margin-left: 0;
+ }
+
+ label {
+ color: #666;
+ font-weight: normal;
+ margin-right: 4px;
+ }
+}
diff --git a/app/assets/stylesheets/sections/issues.scss b/app/assets/stylesheets/sections/issues.scss
index ccfc9b704a6..b909725bff5 100644
--- a/app/assets/stylesheets/sections/issues.scss
+++ b/app/assets/stylesheets/sections/issues.scss
@@ -6,6 +6,7 @@
.issue-title {
margin-bottom: 5px;
font-size: $list-font-size;
+ font-weight: bold;
}
.issue-info {
@@ -170,9 +171,9 @@ form.edit-issue {
}
}
-h3.issue-title {
+h2.issue-title {
margin-top: 0;
- font-size: 2em;
+ font-weight: bold;
}
.context .select2-container {
diff --git a/app/assets/stylesheets/sections/merge_requests.scss b/app/assets/stylesheets/sections/merge_requests.scss
index a3eabb5e330..0d2d8b0173e 100644
--- a/app/assets/stylesheets/sections/merge_requests.scss
+++ b/app/assets/stylesheets/sections/merge_requests.scss
@@ -91,6 +91,7 @@
.merge-request-title {
margin-bottom: 5px;
font-size: $list-font-size;
+ font-weight: bold;
}
.merge-request-info {
diff --git a/app/assets/stylesheets/sections/nav_sidebar.scss b/app/assets/stylesheets/sections/nav_sidebar.scss
index 3ef2a578b7f..17923ca499b 100644
--- a/app/assets/stylesheets/sections/nav_sidebar.scss
+++ b/app/assets/stylesheets/sections/nav_sidebar.scss
@@ -12,7 +12,6 @@
.sidebar-wrapper {
z-index: 99;
- overflow-y: auto;
background: #F5F5F5;
}
@@ -41,7 +40,7 @@
.nav-sidebar li {
&.active a {
color: #333;
- background: #FFF;
+ background: #FFF !important;
font-weight: bold;
border: 1px solid #EEE;
border-right: 1px solid transparent;
@@ -78,7 +77,7 @@
&:hover {
text-decoration: none;
color: #333;
- background: #DDD;
+ background: #EEE;
}
&:active, &:focus {
@@ -126,7 +125,6 @@
.sidebar-wrapper {
width: 52px;
- overflow-x: hidden;
.nav-sidebar {
margin-top: 20px;
@@ -140,6 +138,7 @@
padding: 8px 15px;
text-align: center;
+
& > span {
display: none;
}
diff --git a/app/assets/stylesheets/sections/note_form.scss b/app/assets/stylesheets/sections/note_form.scss
index 61a877a5e43..a0522030785 100644
--- a/app/assets/stylesheets/sections/note_form.scss
+++ b/app/assets/stylesheets/sections/note_form.scss
@@ -169,7 +169,7 @@
color: #999;
background: #FFF;
padding: 5px;
- margin-top: -7px;
+ margin-top: -11px;
border: 1px solid #DDD;
font-size: 13px;
}
diff --git a/app/controllers/import/gitorious_controller.rb b/app/controllers/import/gitorious_controller.rb
new file mode 100644
index 00000000000..627b4a171b8
--- /dev/null
+++ b/app/controllers/import/gitorious_controller.rb
@@ -0,0 +1,43 @@
+class Import::GitoriousController < Import::BaseController
+
+ def new
+ redirect_to client.authorize_url(callback_import_gitorious_url)
+ end
+
+ def callback
+ session[:gitorious_repos] = params[:repos]
+ redirect_to status_import_gitorious_url
+ end
+
+ def status
+ @repos = client.repos
+
+ @already_added_projects = current_user.created_projects.where(import_type: "gitorious")
+ already_added_projects_names = @already_added_projects.pluck(:import_source)
+
+ @repos.to_a.reject! { |repo| already_added_projects_names.include? repo.full_name }
+ end
+
+ def jobs
+ jobs = current_user.created_projects.where(import_type: "gitorious").to_json(only: [:id, :import_status])
+ render json: jobs
+ end
+
+ def create
+ @repo_id = params[:repo_id]
+ repo = client.repo(@repo_id)
+ @target_namespace = params[:new_namespace].presence || repo.namespace
+ @project_name = repo.name
+
+ namespace = get_or_create_namespace || (render and return)
+
+ @project = Gitlab::GitoriousImport::ProjectCreator.new(repo, namespace, current_user).execute
+ end
+
+ private
+
+ def client
+ @client ||= Gitlab::GitoriousImport::Client.new(session[:gitorious_repos])
+ end
+
+end
diff --git a/app/controllers/projects/blame_controller.rb b/app/controllers/projects/blame_controller.rb
index 106f21b83e6..489a6ae5666 100644
--- a/app/controllers/projects/blame_controller.rb
+++ b/app/controllers/projects/blame_controller.rb
@@ -2,9 +2,9 @@
class Projects::BlameController < Projects::ApplicationController
include ExtractsPath
+ before_filter :require_non_empty_project
before_filter :assign_ref_vars
before_filter :authorize_download_code!
- before_filter :require_non_empty_project
def show
@blob = @repository.blob_at(@commit.id, @path)
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index cc42b1512dc..1207548eae0 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -5,8 +5,8 @@ class Projects::BlobController < Projects::ApplicationController
# Raised when given an invalid file path
class InvalidPathError < StandardError; end
- before_filter :authorize_download_code!
before_filter :require_non_empty_project, except: [:new, :create]
+ before_filter :authorize_download_code!
before_filter :authorize_push_code!, only: [:destroy]
before_filter :assign_blob_vars
before_filter :commit, except: [:new, :create]
diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb
index 4d002aba972..690501f3060 100644
--- a/app/controllers/projects/branches_controller.rb
+++ b/app/controllers/projects/branches_controller.rb
@@ -2,7 +2,6 @@ class Projects::BranchesController < Projects::ApplicationController
include ActionView::Helpers::SanitizeHelper
# Authorize
before_filter :require_non_empty_project
-
before_filter :authorize_download_code!
before_filter :authorize_push_code!, only: [:create, :destroy]
diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb
index 96a782bdf7a..87e39f1363a 100644
--- a/app/controllers/projects/commit_controller.rb
+++ b/app/controllers/projects/commit_controller.rb
@@ -3,8 +3,8 @@
# Not to be confused with CommitsController, plural.
class Projects::CommitController < Projects::ApplicationController
# Authorize
- before_filter :authorize_download_code!
before_filter :require_non_empty_project
+ before_filter :authorize_download_code!
before_filter :commit
def show
diff --git a/app/controllers/projects/commits_controller.rb b/app/controllers/projects/commits_controller.rb
index b133afe44b5..4b6ab437476 100644
--- a/app/controllers/projects/commits_controller.rb
+++ b/app/controllers/projects/commits_controller.rb
@@ -3,9 +3,9 @@ require "base64"
class Projects::CommitsController < Projects::ApplicationController
include ExtractsPath
+ before_filter :require_non_empty_project
before_filter :assign_ref_vars
before_filter :authorize_download_code!
- before_filter :require_non_empty_project
def show
@repo = @project.repository
diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb
index 0e12bbdc49f..146808fa562 100644
--- a/app/controllers/projects/compare_controller.rb
+++ b/app/controllers/projects/compare_controller.rb
@@ -1,7 +1,7 @@
class Projects::CompareController < Projects::ApplicationController
# Authorize
- before_filter :authorize_download_code!
before_filter :require_non_empty_project
+ before_filter :authorize_download_code!
def index
end
diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb
index 72f73bedf54..21a151a426e 100644
--- a/app/controllers/projects/forks_controller.rb
+++ b/app/controllers/projects/forks_controller.rb
@@ -1,7 +1,7 @@
class Projects::ForksController < Projects::ApplicationController
# Authorize
- before_filter :authorize_download_code!
before_filter :require_non_empty_project
+ before_filter :authorize_download_code!
def new
@namespaces = current_user.manageable_namespaces
diff --git a/app/controllers/projects/graphs_controller.rb b/app/controllers/projects/graphs_controller.rb
index 4a318cb7d56..752474b4a4c 100644
--- a/app/controllers/projects/graphs_controller.rb
+++ b/app/controllers/projects/graphs_controller.rb
@@ -1,7 +1,7 @@
class Projects::GraphsController < Projects::ApplicationController
# Authorize
- before_filter :authorize_download_code!
before_filter :require_non_empty_project
+ before_filter :authorize_download_code!
def show
respond_to do |format|
diff --git a/app/controllers/projects/network_controller.rb b/app/controllers/projects/network_controller.rb
index 59f2a745367..83d1c1dacae 100644
--- a/app/controllers/projects/network_controller.rb
+++ b/app/controllers/projects/network_controller.rb
@@ -2,9 +2,9 @@ class Projects::NetworkController < Projects::ApplicationController
include ExtractsPath
include ApplicationHelper
+ before_filter :require_non_empty_project
before_filter :assign_ref_vars
before_filter :authorize_download_code!
- before_filter :require_non_empty_project
def show
respond_to do |format|
diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb
index c4ddc32e8c3..b1a029ce696 100644
--- a/app/controllers/projects/raw_controller.rb
+++ b/app/controllers/projects/raw_controller.rb
@@ -2,9 +2,9 @@
class Projects::RawController < Projects::ApplicationController
include ExtractsPath
+ before_filter :require_non_empty_project
before_filter :assign_ref_vars
before_filter :authorize_download_code!
- before_filter :require_non_empty_project
def show
@blob = @repository.blob_at(@commit.id, @path)
diff --git a/app/controllers/projects/refs_controller.rb b/app/controllers/projects/refs_controller.rb
index ec41cafda4d..67acf45ab7f 100644
--- a/app/controllers/projects/refs_controller.rb
+++ b/app/controllers/projects/refs_controller.rb
@@ -1,9 +1,9 @@
class Projects::RefsController < Projects::ApplicationController
include ExtractsPath
+ before_filter :require_non_empty_project
before_filter :assign_ref_vars
before_filter :authorize_download_code!
- before_filter :require_non_empty_project
def switch
respond_to do |format|
diff --git a/app/controllers/projects/repositories_controller.rb b/app/controllers/projects/repositories_controller.rb
index 8a997370dd7..245dfb7bb9a 100644
--- a/app/controllers/projects/repositories_controller.rb
+++ b/app/controllers/projects/repositories_controller.rb
@@ -1,7 +1,7 @@
class Projects::RepositoriesController < Projects::ApplicationController
# Authorize
- before_filter :authorize_download_code!
before_filter :require_non_empty_project, except: :create
+ before_filter :authorize_download_code!
before_filter :authorize_admin_project!, only: :create
def create
diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb
index c7112a3cc10..b23010bf595 100644
--- a/app/controllers/projects/tree_controller.rb
+++ b/app/controllers/projects/tree_controller.rb
@@ -2,9 +2,9 @@
class Projects::TreeController < Projects::ApplicationController
include ExtractsPath
+ before_filter :require_non_empty_project, except: [:new, :create]
before_filter :assign_ref_vars
before_filter :authorize_download_code!
- before_filter :require_non_empty_project, except: [:new, :create]
def show
if tree.entries.empty?
diff --git a/app/controllers/projects/uploads_controller.rb b/app/controllers/projects/uploads_controller.rb
new file mode 100644
index 00000000000..2b4da35bc7f
--- /dev/null
+++ b/app/controllers/projects/uploads_controller.rb
@@ -0,0 +1,19 @@
+class Projects::UploadsController < Projects::ApplicationController
+ layout "project"
+
+ before_filter :project
+
+ def show
+ path = File.join(project.path_with_namespace, params[:secret])
+ uploader = FileUploader.new('uploads', path)
+
+ uploader.retrieve_from_store!(params[:filename])
+
+ if uploader.file.exists?
+ # Right now, these are always images, so we can safely render them inline.
+ send_file uploader.file.path, disposition: 'inline'
+ else
+ not_found!
+ end
+ end
+end
diff --git a/app/controllers/uploads_controller.rb b/app/controllers/uploads_controller.rb
new file mode 100644
index 00000000000..d5877977258
--- /dev/null
+++ b/app/controllers/uploads_controller.rb
@@ -0,0 +1,17 @@
+class UploadsController < ApplicationController
+ def show
+ model = params[:model].camelize.constantize.find(params[:id])
+ uploader = model.send(params[:mounted_as])
+
+ if uploader.file_storage?
+ if !model.respond_to?(:project) || can?(current_user, :read_project, model.project)
+ disposition = uploader.image? ? 'inline' : 'attachment'
+ send_file uploader.file.path, disposition: disposition
+ else
+ not_found!
+ end
+ else
+ redirect_to uploader.url
+ end
+ end
+end
diff --git a/app/models/note.rb b/app/models/note.rb
index ccd9783e7d4..e6c258ffbe9 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -409,19 +409,19 @@ class Note < ActiveRecord::Base
prev_lines = []
diff_lines.each do |line|
- if generate_line_code(line) != self.line_code
- if line.type == "match"
- prev_lines.clear
- prev_match_line = line
- else
- prev_lines.push(line)
- prev_lines.shift if prev_lines.length >= max_number_of_lines
- end
+ if line.type == "match"
+ prev_lines.clear
+ prev_match_line = line
else
prev_lines << line
- return prev_lines
+
+ break if generate_line_code(line) == self.line_code
+
+ prev_lines.shift if prev_lines.length >= max_number_of_lines
end
end
+
+ prev_lines
end
def diff_lines
diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb
index 859c3f56b2b..a44b91166e8 100644
--- a/app/services/merge_requests/build_service.rb
+++ b/app/services/merge_requests/build_service.rb
@@ -16,9 +16,6 @@ module MergeRequests
return build_failed(merge_request, nil)
end
- # Generate suggested MR title based on source branch name
- merge_request.title = merge_request.source_branch.titleize.humanize
-
compare_result = CompareService.new.execute(
current_user,
merge_request.source_project,
@@ -52,6 +49,15 @@ module MergeRequests
merge_request.compare_failed = false
end
+ commits = merge_request.compare_commits
+ if commits && commits.count == 1
+ commit = commits.first
+ merge_request.title = commit.title
+ merge_request.description = commit.description.try(:strip)
+ else
+ merge_request.title = merge_request.source_branch.titleize.humanize
+ end
+
merge_request
rescue Gitlab::Satellite::BranchesWithoutParent
diff --git a/app/views/import/gitorious/status.html.haml b/app/views/import/gitorious/status.html.haml
new file mode 100644
index 00000000000..35ed0a717de
--- /dev/null
+++ b/app/views/import/gitorious/status.html.haml
@@ -0,0 +1,41 @@
+%h3.page-title
+ %i.fa.fa-gitorious
+ Import repositories from Gitorious.org
+
+%p.light
+ Select projects you want to import.
+%hr
+%p
+ = button_tag 'Import all projects', class: "btn btn-success js-import-all"
+
+%table.table.import-jobs
+ %thead
+ %tr
+ %th From Gitorious
+ %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
+ %td.job-status
+ - if project.import_status == 'finished'
+ %span.cgreen
+ %i.fa.fa-check
+ done
+ - else
+ = project.human_import_status_name
+
+ - @repos.each do |repo|
+ %tr{id: "repo_#{repo.id}"}
+ %td= repo.full_name
+ %td.import-target
+ = repo.full_name
+ %td.import-actions.job-status
+ = button_tag "Import", class: "btn js-add-to-import"
+
+:coffeescript
+ $ ->
+ new ImporterStatus("#{jobs_import_gitorious_path}", "#{import_gitorious_path}")
diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml
index bece8061fb9..d12145651af 100644
--- a/app/views/layouts/_head.html.haml
+++ b/app/views/layouts/_head.html.haml
@@ -1,12 +1,5 @@
%head
%meta{charset: "utf-8"}
-
- -# Go repository retrieval support
- -# Need to be the fist thing in the head
- -# Since Go is using an XML parser to process HTML5
- -# https://github.com/gitlabhq/gitlabhq/pull/5958#issuecomment-45397555
- - if controller_name == 'projects' && action_name == 'show'
- %meta{name: "go-import", content: "#{@project.web_url_without_protocol} git #{@project.web_url}.git"}
%meta{content: "GitLab Community Edition", name: "description"}
%title
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index 09c3f83fb3e..4c853f577e9 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -1,13 +1,12 @@
%li.commit.js-toggle-container
.commit-row-title
- = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id"
- &nbsp;
- %span.str-truncated
+ %strong.str-truncated
= link_to_gfm commit.title, namespace_project_commit_path(project.namespace, project, commit.id), class: "commit-row-message"
- if commit.description?
%a.text-expander.js-toggle-button ...
- = link_to_browse_code(project, commit)
+ .pull-right
+ = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id"
.notes_count
- if @note_counts
@@ -17,8 +16,9 @@
- note_count = notes.count
- if note_count > 0
- %span.label.label-gray
- %i.fa.fa-comment= note_count
+ %span.light
+ %i.fa.fa-comments
+ = note_count
- if commit.description?
.commit-row-description.js-toggle-content
@@ -26,6 +26,8 @@
= preserve(gfm(escape_once(commit.description)))
.commit-row-info
- = commit_author_link(commit, avatar: true, size: 16)
+ = commit_author_link(commit, avatar: true, size: 24)
+ authored
.committed_ago
#{time_ago_with_tooltip(commit.committed_date)} &nbsp;
+ = link_to_browse_code(project, commit)
diff --git a/app/views/projects/commits/_commits.html.haml b/app/views/projects/commits/_commits.html.haml
index 2d0ca671fa0..0cd9ce1f371 100644
--- a/app/views/projects/commits/_commits.html.haml
+++ b/app/views/projects/commits/_commits.html.haml
@@ -3,12 +3,13 @@
- @commits.group_by { |c| c.committed_date.to_date }.sort.reverse.each do |day, commits|
.row.commits-row
- .col-md-2
- %h4
+ .col-md-2.hidden-xs.hidden-sm
+ %h5.commits-row-date
%i.fa.fa-calendar
%span= day.stamp("28 Aug, 2010")
- %p= pluralize(commits.count, 'commit')
- .col-md-10
+ .light
+ = pluralize(commits.count, 'commit')
+ .col-md-10.col-sm-12
%ul.bordered-list
= render commits, project: project
%hr.lists-separator
diff --git a/app/views/projects/issues/_discussion.html.haml b/app/views/projects/issues/_discussion.html.haml
index 1579e7c5ccf..7c175ebb88a 100644
--- a/app/views/projects/issues/_discussion.html.haml
+++ b/app/views/projects/issues/_discussion.html.haml
@@ -7,8 +7,7 @@
.row
.col-md-9
.participants
- %cite.cgray
- = pluralize(@issue.participants.count, 'participant')
+ %span= pluralize(@issue.participants.count, 'participant')
- @issue.participants.each do |participant|
= link_to_member(@project, participant, name: false, size: 24)
@@ -20,8 +19,7 @@
= cross_project_reference(@project, @issue)
%hr
.context
- %cite.cgray
- = render partial: 'issue_context', locals: { issue: @issue }
+ = render partial: 'issue_context', locals: { issue: @issue }
%hr
.clearfix
.votes-holder
diff --git a/app/views/projects/issues/_issue.html.haml b/app/views/projects/issues/_issue.html.haml
index a5f9a5653e3..8af8da1d13e 100644
--- a/app/views/projects/issues/_issue.html.haml
+++ b/app/views/projects/issues/_issue.html.haml
@@ -6,9 +6,15 @@
.issue-title
%span.str-truncated
= link_to_gfm issue.title, namespace_project_issue_path(issue.project.namespace, issue.project, issue), class: "row_title"
- - if issue.closed?
- %small.pull-right
- CLOSED
+ .pull-right.light
+ - if issue.closed?
+ %span
+ CLOSED
+ - if issue.notes.any?
+ &nbsp;
+ %span
+ %i.fa.fa-comments
+ = issue.notes.count
.issue-info
%span.light= "##{issue.iid}"
@@ -16,10 +22,6 @@
assigned to #{link_to_member(@project, issue.assignee)}
- if issue.votes_count > 0
= render 'votes/votes_inline', votable: issue
- - if issue.notes.any?
- %span
- %i.fa.fa-comments
- = issue.notes.count
- if issue.milestone
%span
%i.fa.fa-clock-o
diff --git a/app/views/projects/issues/_issue_context.html.haml b/app/views/projects/issues/_issue_context.html.haml
index 9804658bebe..4c7654354f4 100644
--- a/app/views/projects/issues/_issue_context.html.haml
+++ b/app/views/projects/issues/_issue_context.html.haml
@@ -1,19 +1,25 @@
= form_for [@project.namespace.becomes(Namespace), @project, @issue], remote: true, html: {class: 'edit-issue inline-update'} do |f|
%div.prepend-top-20
- %p
- Assignee:
+ .issuable-context-title
+ %label
+ Assignee:
- if issue.assignee
- = link_to_member(@project, @issue.assignee)
+ %strong= link_to_member(@project, @issue.assignee, size: 24)
- else
none
- if can?(current_user, :modify_issue, @issue)
= project_users_select_tag('issue[assignee_id]', placeholder: 'Select assignee', class: 'custom-form-control js-select2 js-assignee', selected: @issue.assignee_id)
- %div.prepend-top-20
- %p
- Milestone:
+ %div.prepend-top-20.clearfix
+ .issuable-context-title
+ %label
+ Milestone:
- if issue.milestone
- #{link_to @issue.milestone.title, namespace_project_milestone_path(@project.namespace, @project, @issue.milestone)}
+ %span.back-to-milestone
+ = link_to namespace_project_milestone_path(@project.namespace, @project, @issue.milestone) do
+ %strong
+ %i.fa.fa-clock-o
+ = @issue.milestone.title
- else
none
- if can?(current_user, :modify_issue, @issue)
diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml
index 224ad4041ea..6849a15e7e9 100644
--- a/app/views/projects/issues/show.html.haml
+++ b/app/views/projects/issues/show.html.haml
@@ -26,7 +26,7 @@
Edit
%hr
- %h3.issue-title
+ %h2.issue-title
= gfm escape_once(@issue.title)
%div
- if @issue.description.present?
diff --git a/app/views/projects/merge_requests/_discussion.html.haml b/app/views/projects/merge_requests/_discussion.html.haml
index b05f0c24320..83947cf6ac2 100644
--- a/app/views/projects/merge_requests/_discussion.html.haml
+++ b/app/views/projects/merge_requests/_discussion.html.haml
@@ -16,8 +16,7 @@
= cross_project_reference(@project, @merge_request)
%hr
.context
- %cite.cgray
- = render partial: 'projects/merge_requests/show/context', locals: { merge_request: @merge_request }
+ = render partial: 'projects/merge_requests/show/context', locals: { merge_request: @merge_request }
%hr
.votes-holder
%h6 Votes
diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml
index fb1e5737680..d94636712be 100644
--- a/app/views/projects/merge_requests/_merge_request.html.haml
+++ b/app/views/projects/merge_requests/_merge_request.html.haml
@@ -1,18 +1,26 @@
%li{ class: mr_css_classes(merge_request) }
.merge-request-title
- = link_to_gfm truncate(merge_request.title, length: 80), namespace_project_merge_request_path(merge_request.target_project.namespace, merge_request.target_project, merge_request), class: "row_title"
- - if merge_request.merged?
- %small.pull-right
- %i.fa.fa-check
- MERGED
- - else
- %span.pull-right.hidden-xs
- - if merge_request.for_fork?
- %span.light
- #{merge_request.source_project_namespace}:
- = truncate merge_request.source_branch, length: 25
- %i.fa.fa-angle-right.light
- = merge_request.target_branch
+ %span.str-truncated
+ = link_to_gfm merge_request.title, namespace_project_merge_request_path(merge_request.target_project.namespace, merge_request.target_project, merge_request), class: "row_title"
+ .pull-right.light
+ - if merge_request.merged?
+ %span
+ %i.fa.fa-check
+ MERGED
+ - elsif merge_request.closed?
+ %span
+ %i.fa.fa-close
+ CLOSED
+ - else
+ %span.hidden-xs.hidden-sm
+ %span.label-branch<
+ %i.fa.fa-code-fork
+ %span= merge_request.target_branch
+ - if merge_request.notes.any?
+ &nbsp;
+ %span
+ %i.fa.fa-comments
+ = merge_request.mr_and_commit_notes.count
.merge-request-info
%span.light= "##{merge_request.iid}"
- if merge_request.assignee
@@ -21,10 +29,6 @@
Unassigned
- if merge_request.votes_count > 0
= render 'votes/votes_inline', votable: merge_request
- - if merge_request.notes.any?
- %span
- %i.fa.fa-comments
- = merge_request.mr_and_commit_notes.count
- if merge_request.milestone_id?
%span
%i.fa.fa-clock-o
@@ -33,6 +37,7 @@
%span.task-status
= merge_request.task_status
+
.pull-right.hidden-xs
%small updated #{time_ago_with_tooltip(merge_request.updated_at, 'bottom', 'merge_request_updated_ago')}
diff --git a/app/views/projects/merge_requests/show/_context.html.haml b/app/views/projects/merge_requests/show/_context.html.haml
index ddf21f75063..a74f3fb24e7 100644
--- a/app/views/projects/merge_requests/show/_context.html.haml
+++ b/app/views/projects/merge_requests/show/_context.html.haml
@@ -1,23 +1,30 @@
= form_for [@project.namespace.becomes(Namespace), @project, @merge_request], remote: true, html: {class: 'edit-merge_request inline-update'} do |f|
%div.prepend-top-20
- %p
- Assignee:
+ .issuable-context-title
+ %label
+ Assignee:
- if @merge_request.assignee
- = link_to_member(@project, @merge_request.assignee)
+ %strong= link_to_member(@project, @merge_request.assignee, size: 24)
- else
none
- - if can?(current_user, :modify_merge_request, @merge_request)
- = project_users_select_tag('merge_request[assignee_id]', placeholder: 'Select assignee', class: 'custom-form-control js-select2 js-assignee', selected: @merge_request.assignee_id)
+ .issuable-context-selectbox
+ - if can?(current_user, :modify_merge_request, @merge_request)
+ = project_users_select_tag('merge_request[assignee_id]', placeholder: 'Select assignee', class: 'custom-form-control js-select2 js-assignee', selected: @merge_request.assignee_id)
- %div.prepend-top-20
- %p
- Milestone:
+ %div.prepend-top-20.clearfix
+ .issuable-context-title
+ %label
+ Milestone:
- if @merge_request.milestone
%span.back-to-milestone
- #{link_to @merge_request.milestone.title, namespace_project_milestone_path(@project.namespace, @project, @merge_request.milestone)}
+ = link_to namespace_project_milestone_path(@project.namespace, @project, @merge_request.milestone) do
+ %strong
+ %i.fa.fa-clock-o
+ = @merge_request.milestone.title
- else
none
- - if can?(current_user, :modify_merge_request, @merge_request)
- = f.select(:milestone_id, milestone_options(@merge_request), { include_blank: "Select milestone" }, {class: 'select2 select2-compact js-select2 js-milestone'})
- = hidden_field_tag :merge_request_context
- = f.submit class: 'btn'
+ .issuable-context-selectbox
+ - if can?(current_user, :modify_merge_request, @merge_request)
+ = f.select(:milestone_id, milestone_options(@merge_request), { include_blank: "Select milestone" }, {class: 'select2 select2-compact js-select2 js-milestone'})
+ = hidden_field_tag :merge_request_context
+ = f.submit class: 'btn'
diff --git a/app/views/projects/merge_requests/show/_mr_box.html.haml b/app/views/projects/merge_requests/show/_mr_box.html.haml
index ab1284547ad..ada9ae58b8f 100644
--- a/app/views/projects/merge_requests/show/_mr_box.html.haml
+++ b/app/views/projects/merge_requests/show/_mr_box.html.haml
@@ -1,4 +1,4 @@
-%h3.issue-title
+%h2.issue-title
= gfm escape_once(@merge_request.title)
%div
diff --git a/app/views/projects/merge_requests/show/_participants.html.haml b/app/views/projects/merge_requests/show/_participants.html.haml
index 15a97404cb0..4f34af1737d 100644
--- a/app/views/projects/merge_requests/show/_participants.html.haml
+++ b/app/views/projects/merge_requests/show/_participants.html.haml
@@ -1,4 +1,4 @@
.participants
- %cite.cgray #{@merge_request.participants.count} participants
+ %span #{@merge_request.participants.count} participants
- @merge_request.participants.each do |participant|
= link_to_member(@project, participant, name: false, size: 24)
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index 6f5851d61a1..5216f308110 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -53,18 +53,26 @@
Import projects from GitHub
= render 'github_import_modal'
+ - unless request.host == 'gitlab.com'
+ .project-import.form-group
+ .col-sm-2
+ .col-sm-10
+ - if gitlab_import_enabled?
+ = link_to status_import_gitlab_path do
+ %i.fa.fa-heart
+ Import projects from GitLab.com
+ - else
+ = link_to '#', class: 'how_to_import_link light' do
+ %i.fa.fa-heart
+ Import projects from GitLab.com
+ = render 'gitlab_import_modal'
+
.project-import.form-group
.col-sm-2
.col-sm-10
- - if gitlab_import_enabled?
- = link_to status_import_gitlab_path do
- %i.fa.fa-heart
- Import projects from GitLab.com
- - elsif request.host != 'gitlab.com'
- = link_to '#', class: 'how_to_import_link light' do
- %i.fa.fa-heart
- Import projects from GitLab.com
- = render 'gitlab_import_modal'
+ = link_to new_import_gitorious_path do
+ %i.fa.fa-heart
+ Import projects from Gitorious.org
%hr.prepend-botton-10
diff --git a/config/initializers/static_files.rb b/config/initializers/static_files.rb
new file mode 100644
index 00000000000..d9042c652bb
--- /dev/null
+++ b/config/initializers/static_files.rb
@@ -0,0 +1,15 @@
+app = Rails.application
+
+if app.config.serve_static_assets
+ # The `ActionDispatch::Static` middleware intercepts requests for static files
+ # by checking if they exist in the `/public` directory.
+ # We're replacing it with our `Gitlab::Middleware::Static` that does the same,
+ # except ignoring `/uploads`, letting those go through to the GitLab Rails app.
+
+ app.config.middleware.swap(
+ ActionDispatch::Static,
+ Gitlab::Middleware::Static,
+ app.paths["public"].first,
+ app.config.static_cache_control
+ )
+end
diff --git a/config/routes.rb b/config/routes.rb
index 934653a2245..a3f047e36a4 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -67,9 +67,29 @@ Gitlab::Application.routes.draw do
get :callback
get :jobs
end
+
+ resource :gitorious, only: [:create, :new], controller: :gitorious do
+ get :status
+ get :callback
+ get :jobs
+ end
end
+ #
+ # Uploads
+ #
+ scope path: :uploads do
+ # Note attachments and User/Group/Project avatars
+ get ":model/:mounted_as/:id/:filename",
+ to: "uploads#show",
+ constraints: { model: /note|user|group|project/, mounted_as: /avatar|attachment/, filename: /.+/ }
+
+ # Project markdown uploads
+ get ":id/:secret/:filename",
+ to: "projects/uploads#show",
+ constraints: { id: /[a-zA-Z.0-9_\-]+\/[a-zA-Z.0-9_\-]+/, filename: /.+/ }
+ end
#
# Explore area
diff --git a/doc/api/projects.md b/doc/api/projects.md
index 454f6fa2e91..a1a23051d7e 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -1,5 +1,23 @@
# Projects
+
+### Project visibility level
+
+Project in GitLab has be either private, internal or public.
+You can determine it by `visibility_level` field in project.
+
+Constants for project visibility levels are next:
+
+* Private. `visibility_level` is `0`.
+ Project access must be granted explicitly for each user.
+
+* Internal. `visibility_level` is `10`.
+ The project can be cloned by any logged in user.
+
+* Public. `visibility_level` is `20`.
+ The project can be cloned without any authentication.
+
+
## List projects
Get a list of projects accessible by the authenticated user.
diff --git a/doc/update/6.x-or-7.x-to-7.8.md b/doc/update/6.x-or-7.x-to-7.8.md
index 90d889d5113..859f4c1a6d6 100644
--- a/doc/update/6.x-or-7.x-to-7.8.md
+++ b/doc/update/6.x-or-7.x-to-7.8.md
@@ -164,8 +164,6 @@ git diff 6-0-stable:config/gitlab.yml.example 7-8-stable:config/gitlab.yml.examp
* Make `/home/git/gitlab/config/gitlab.yml` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-8-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-8-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.4.3/config.yml.example but with your settings.
-* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-8-stable/lib/support/nginx/gitlab but with your settings.
-* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-8-stablef/lib/support/nginx/gitlab-ssl but with your settings.
* Copy rack attack middleware config
```bash
@@ -178,6 +176,12 @@ sudo -u git -H cp config/initializers/rack_attack.rb.example config/initializers
sudo cp lib/support/logrotate/gitlab /etc/logrotate.d/gitlab
```
+### Change Nginx settings
+
+* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-8-stable/lib/support/nginx/gitlab but with your settings.
+* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-8-stablef/lib/support/nginx/gitlab-ssl but with your settings.
+* A new `location /uploads/` section has been added that needs to have the same content as the existing `location @gitlab` section.
+
## 9. Start application
sudo service gitlab start
diff --git a/doc/update/7.7-to-7.8.md b/doc/update/7.7-to-7.8.md
index 01b4fc4c992..7ca0fe65785 100644
--- a/doc/update/7.7-to-7.8.md
+++ b/doc/update/7.7-to-7.8.md
@@ -75,8 +75,9 @@ git diff origin/7-6-stable:config/gitlab.yml.example origin/7-8-stable:config/gi
#### Change Nginx settings
-* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`](/lib/support/nginx/gitlab) but with your settings
-* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`](/lib/support/nginx/gitlab-ssl) but with your setting
+* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`](/lib/support/nginx/gitlab) but with your settings.
+* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`](/lib/support/nginx/gitlab-ssl) but with your settings.
+* A new `location /uploads/` section has been added that needs to have the same content as the existing `location @gitlab` section.
#### Setup time zone (optional)
diff --git a/doc/web_hooks/web_hooks.md b/doc/web_hooks/web_hooks.md
index e3399e5f1b8..29ef5b59bac 100644
--- a/doc/web_hooks/web_hooks.md
+++ b/doc/web_hooks/web_hooks.md
@@ -24,16 +24,19 @@ Triggered when you push to the repository except when pushing tags.
"project_id": 15,
"repository": {
"name": "Diaspora",
- "url": "git@example.com:diaspora.git",
+ "url": "git@example.com:mike/diasporadiaspora.git",
"description": "",
- "homepage": "http://example.com/diaspora"
+ "homepage": "http://example.com/mike/diaspora",
+ "git_http_url":"http://example.com/mike/diaspora.git",
+ "git_ssh_url":"git@example.com:mike/diaspora.git",
+ "visibility_level":0
},
"commits": [
{
"id": "b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
"message": "Update Catalan translation to e38cb41.",
"timestamp": "2011-12-12T14:27:31+02:00",
- "url": "http://example.com/diaspora/commits/b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
+ "url": "http://example.com/mike/diaspora/commit/b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
"author": {
"name": "Jordi Mallach",
"email": "jordi@softcatala.org"
@@ -43,7 +46,7 @@ Triggered when you push to the repository except when pushing tags.
"id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
"message": "fixed readme",
"timestamp": "2012-01-03T23:36:29+02:00",
- "url": "http://example.com/diaspora/commits/da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
+ "url": "http://example.com/mike/diaspora/commit/da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
"author": {
"name": "GitLab dev user",
"email": "gitlabdev@dv6700.(none)"
@@ -72,8 +75,13 @@ Triggered when you create (or delete) tags to the repository.
"name": "jsmith",
"url": "ssh://git@example.com/jsmith/example.git",
"description": "",
- "homepage": "http://example.com/jsmith/example"
- }
+ "homepage": "http://example.com/jsmith/example",
+ "git_http_url":"http://example.com/jsmith/example.git",
+ "git_ssh_url":"git@example.com:jsmith/example.git",
+ "visibility_level":0
+ },
+ "commits": [],
+ "total_commits_count": 0
}
```
diff --git a/lib/gitlab/diff/parser.rb b/lib/gitlab/diff/parser.rb
index 887ed76b36c..c1d9520ddf1 100644
--- a/lib/gitlab/diff/parser.rb
+++ b/lib/gitlab/diff/parser.rb
@@ -27,7 +27,7 @@ module Gitlab
line_old = line.match(/\-[0-9]*/)[0].to_i.abs rescue 0
line_new = line.match(/\+[0-9]*/)[0].to_i.abs rescue 0
- next if line_old == 1 && line_new == 1 #top of file
+ next if line_old <= 1 && line_new <= 1 #top of file
lines_obj << Gitlab::Diff::Line.new(full_line, type, line_obj_index, line_old, line_new)
line_obj_index += 1
next
diff --git a/lib/gitlab/gitorious_import/client.rb b/lib/gitlab/gitorious_import/client.rb
new file mode 100644
index 00000000000..5043f6a2ebd
--- /dev/null
+++ b/lib/gitlab/gitorious_import/client.rb
@@ -0,0 +1,63 @@
+module Gitlab
+ module GitoriousImport
+ GITORIOUS_HOST = "https://gitorious.org"
+
+ class Client
+ attr_reader :repo_list
+
+ def initialize(repo_list)
+ @repo_list = repo_list
+ end
+
+ def authorize_url(redirect_uri)
+ "#{GITORIOUS_HOST}/gitlab-import?callback_url=#{redirect_uri}"
+ end
+
+ def repos
+ @repos ||= repo_names.map { |full_name| Repository.new(full_name) }
+ end
+
+ def repo(id)
+ repos.find { |repo| repo.id == id }
+ end
+
+ private
+
+ def repo_names
+ repo_list.to_s.split(',').map(&:strip).reject(&:blank?)
+ end
+ end
+
+ Repository = Struct.new(:full_name) do
+ def id
+ Digest::SHA1.hexdigest(full_name)
+ end
+
+ def namespace
+ segments.first
+ end
+
+ def path
+ segments.last
+ end
+
+ def name
+ path.titleize
+ end
+
+ def description
+ ""
+ end
+
+ def import_url
+ "#{GITORIOUS_HOST}/#{full_name}.git"
+ end
+
+ private
+
+ def segments
+ full_name.split('/')
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/gitorious_import/project_creator.rb b/lib/gitlab/gitorious_import/project_creator.rb
new file mode 100644
index 00000000000..3cbebe53997
--- /dev/null
+++ b/lib/gitlab/gitorious_import/project_creator.rb
@@ -0,0 +1,39 @@
+module Gitlab
+ module GitoriousImport
+ class ProjectCreator
+ attr_reader :repo, :namespace, :current_user
+
+ def initialize(repo, namespace, current_user)
+ @repo = repo
+ @namespace = namespace
+ @current_user = current_user
+ end
+
+ def execute
+ @project = Project.new(
+ name: repo.name,
+ path: repo.path,
+ description: repo.description,
+ namespace: namespace,
+ creator: current_user,
+ visibility_level: Gitlab::VisibilityLevel::PUBLIC,
+ import_type: "gitorious",
+ import_source: repo.full_name,
+ import_url: repo.import_url
+ )
+
+ if @project.save!
+ @project.reload
+
+ if @project.import_failed?
+ @project.import_retry
+ else
+ @project.import_start
+ end
+ end
+
+ @project
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/middleware/static.rb b/lib/gitlab/middleware/static.rb
new file mode 100644
index 00000000000..85ffa8aca68
--- /dev/null
+++ b/lib/gitlab/middleware/static.rb
@@ -0,0 +1,13 @@
+module Gitlab
+ module Middleware
+ class Static < ActionDispatch::Static
+ UPLOADS_REGEX = /\A\/uploads(\/|\z)/.freeze
+
+ def call(env)
+ return @app.call(env) if env['PATH_INFO'] =~ UPLOADS_REGEX
+
+ super
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/push_data_builder.rb b/lib/gitlab/push_data_builder.rb
index faea6ae375c..9aa5c8967a7 100644
--- a/lib/gitlab/push_data_builder.rb
+++ b/lib/gitlab/push_data_builder.rb
@@ -41,6 +41,9 @@ module Gitlab
url: project.url_to_repo,
description: project.description,
homepage: project.web_url,
+ git_http_url: project.http_url_to_repo,
+ git_ssh_url: project.ssh_url_to_repo,
+ visibility_level: project.visibility_level
},
commits: [],
total_commits_count: commits_count
diff --git a/lib/support/nginx/gitlab b/lib/support/nginx/gitlab
index c8b769ace8e..fd5b2664786 100644
--- a/lib/support/nginx/gitlab
+++ b/lib/support/nginx/gitlab
@@ -1,5 +1,5 @@
## GitLab
-## Contributors: randx, yin8086, sashkab, orkoden, axilleas, bbodenmiller
+## Contributors: randx, yin8086, sashkab, orkoden, axilleas, bbodenmiller, DouweM
##
## Lines starting with two hashes (##) are comments with information.
## Lines starting with one hash (#) are configuration parameters that can be uncommented.
@@ -56,6 +56,37 @@ server {
try_files $uri $uri/index.html $uri.html @gitlab;
}
+ ## We route uploads through GitLab to prevent XSS and enforce access control.
+ location /uploads/ {
+ ## If you use HTTPS make sure you disable gzip compression
+ ## to be safe against BREACH attack.
+ # gzip off;
+
+ ## https://github.com/gitlabhq/gitlabhq/issues/694
+ ## Some requests take more than 30 seconds.
+ proxy_read_timeout 300;
+ proxy_connect_timeout 300;
+ proxy_redirect off;
+
+ proxy_set_header Host $http_host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_set_header X-Frame-Options SAMEORIGIN;
+
+ proxy_pass http://gitlab;
+ }
+
+ ## If ``go get`` detected, return go-import meta tag.
+ ## This works for public and for private repositories.
+ ## See also http://golang.org/cmd/go/#hdr-Remote_import_paths
+ if ($http_user_agent ~* "Go") {
+ return 200 "
+ <!DOCTYPE html>
+ <head><meta content='$host$uri git $scheme://$host$uri.git' name='go-import'></head>
+ </html>";
+ }
+
## If a file, which is not found in the root folder is requested,
## then the proxy passes the request to the upsteam (gitlab unicorn).
location @gitlab {
diff --git a/lib/support/nginx/gitlab-ssl b/lib/support/nginx/gitlab-ssl
index 19af010a9f7..a9699bac611 100644
--- a/lib/support/nginx/gitlab-ssl
+++ b/lib/support/nginx/gitlab-ssl
@@ -1,5 +1,5 @@
## GitLab
-## Contributors: randx, yin8086, sashkab, orkoden, axilleas, bbodenmiller
+## Contributors: randx, yin8086, sashkab, orkoden, axilleas, bbodenmiller, DouweM
##
## Modified from nginx http version
## Modified from http://blog.phusion.nl/2012/04/21/tutorial-setting-up-gitlab-on-debian-6/
@@ -101,6 +101,38 @@ server {
try_files $uri $uri/index.html $uri.html @gitlab;
}
+ ## We route uploads through GitLab to prevent XSS and enforce access control.
+ location /uploads/ {
+ ## If you use HTTPS make sure you disable gzip compression
+ ## to be safe against BREACH attack.
+ gzip off;
+
+ ## https://github.com/gitlabhq/gitlabhq/issues/694
+ ## Some requests take more than 30 seconds.
+ proxy_read_timeout 300;
+ proxy_connect_timeout 300;
+ proxy_redirect off;
+
+ proxy_set_header Host $http_host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-Ssl on;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_set_header X-Frame-Options SAMEORIGIN;
+
+ proxy_pass http://gitlab;
+ }
+
+ ## If ``go get`` detected, return go-import meta tag.
+ ## This works for public and for private repositories.
+ ## See also http://golang.org/cmd/go/#hdr-Remote_import_paths
+ if ($http_user_agent ~* "Go") {
+ return 200 "
+ <!DOCTYPE html>
+ <head><meta content='$host$uri git $scheme://$host$uri.git' name='go-import'></head>
+ </html>";
+ }
+
## If a file, which is not found in the root folder is requested,
## then the proxy passes the request to the upsteam (gitlab unicorn).
location @gitlab {
diff --git a/spec/controllers/import/gitorious_controller_spec.rb b/spec/controllers/import/gitorious_controller_spec.rb
new file mode 100644
index 00000000000..07c9484bf1a
--- /dev/null
+++ b/spec/controllers/import/gitorious_controller_spec.rb
@@ -0,0 +1,67 @@
+require 'spec_helper'
+
+describe Import::GitoriousController do
+ let(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+ end
+
+ describe "GET new" do
+ it "redirects to import endpoint on gitorious.org" do
+ get :new
+
+ expect(controller).to redirect_to("https://gitorious.org/gitlab-import?callback_url=http://test.host/import/gitorious/callback")
+ end
+ end
+
+ describe "GET callback" do
+ it "stores repo list in session" do
+ get :callback, repos: 'foo/bar,baz/qux'
+
+ expect(session[:gitorious_repos]).to eq('foo/bar,baz/qux')
+ end
+ end
+
+ describe "GET status" do
+ before do
+ @repo = OpenStruct.new(full_name: 'asd/vim')
+ end
+
+ it "assigns variables" do
+ @project = create(:project, import_type: 'gitorious', creator_id: user.id)
+ controller.stub_chain(:client, :repos).and_return([@repo])
+
+ get :status
+
+ expect(assigns(:already_added_projects)).to eq([@project])
+ expect(assigns(:repos)).to eq([@repo])
+ end
+
+ it "does not show already added project" do
+ @project = create(:project, import_type: 'gitorious', creator_id: user.id, import_source: 'asd/vim')
+ controller.stub_chain(:client, :repos).and_return([@repo])
+
+ get :status
+
+ expect(assigns(:already_added_projects)).to eq([@project])
+ expect(assigns(:repos)).to eq([])
+ end
+ end
+
+ describe "POST create" do
+ before do
+ @repo = Gitlab::GitoriousImport::Repository.new('asd/vim')
+ end
+
+ it "takes already existing namespace" do
+ namespace = create(:namespace, name: "asd", owner: user)
+ expect(Gitlab::GitoriousImport::ProjectCreator).
+ to receive(:new).with(@repo, namespace, user).
+ and_return(double(execute: true))
+ controller.stub_chain(:client, :repo).and_return(@repo)
+
+ post :create, format: :js
+ end
+ end
+end
diff --git a/spec/lib/gitlab/gitorious_import/project_creator.rb b/spec/lib/gitlab/gitorious_import/project_creator.rb
new file mode 100644
index 00000000000..cf2318bb3a2
--- /dev/null
+++ b/spec/lib/gitlab/gitorious_import/project_creator.rb
@@ -0,0 +1,23 @@
+require 'spec_helper'
+
+describe Gitlab::GitoriousImport::ProjectCreator do
+ let(:user) { create(:user) }
+ let(:repo) { Gitlab::GitoriousImport::Repository.new('foo/bar-baz-qux') }
+ let(:namespace){ create(:namespace) }
+
+ it 'creates project' do
+ allow_any_instance_of(Project).to receive(:add_import_job)
+
+ project_creator = Gitlab::GitoriousImport::ProjectCreator.new(repo, namespace, user)
+ project_creator.execute
+ project = Project.last
+
+ expect(project.name).to eq("Bar Baz Qux")
+ expect(project.path).to eq("bar-baz-qux")
+ expect(project.namespace).to eq(namespace)
+ expect(project.visibility_level).to eq(Gitlab::VisibilityLevel::PUBLIC)
+ expect(project.import_type).to eq("gitorious")
+ expect(project.import_source).to eq("foo/bar-baz-qux")
+ expect(project.import_url).to eq("https://gitorious.org/foo/bar-baz-qux.git")
+ end
+end
diff --git a/spec/lib/gitlab/push_data_builder_spec.rb b/spec/lib/gitlab/push_data_builder_spec.rb
index da25d45f1ff..1b8ba7b4d43 100644
--- a/spec/lib/gitlab/push_data_builder_spec.rb
+++ b/spec/lib/gitlab/push_data_builder_spec.rb
@@ -13,6 +13,9 @@ describe 'Gitlab::PushDataBuilder' do
it { expect(data[:after]).to eq('5937ac0a7beb003549fc5fd26fc247adbce4a52e') }
it { expect(data[:ref]).to eq('refs/heads/master') }
it { expect(data[:commits].size).to eq(3) }
+ it { expect(data[:repository][:git_http_url]).to eq(project.http_url_to_repo) }
+ it { expect(data[:repository][:git_ssh_url]).to eq(project.ssh_url_to_repo) }
+ it { expect(data[:repository][:visibility_level]).to eq(project.visibility_level) }
it { expect(data[:total_commits_count]).to eq(3) }
end