summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG2
-rw-r--r--Gemfile3
-rw-r--r--Gemfile.lock7
-rw-r--r--app/assets/javascripts/profile.js.coffee10
-rw-r--r--app/assets/javascripts/users_select.js.coffee10
-rw-r--r--app/assets/stylesheets/common.scss21
-rw-r--r--app/assets/stylesheets/gitlab_bootstrap/avatar.scss1
-rw-r--r--app/assets/stylesheets/gitlab_bootstrap/blocks.scss2
-rw-r--r--app/assets/stylesheets/sections/commits.scss3
-rw-r--r--app/assets/stylesheets/sections/dashboard.scss2
-rw-r--r--app/assets/stylesheets/sections/profile.scss38
-rw-r--r--app/controllers/application_controller.rb9
-rw-r--r--app/controllers/profiles/accounts_controller.rb7
-rw-r--r--app/controllers/profiles/passwords_controller.rb43
-rw-r--r--app/controllers/profiles_controller.rb31
-rw-r--r--app/helpers/application_helper.rb11
-rw-r--r--app/helpers/commits_helper.rb2
-rw-r--r--app/helpers/gitlab_markdown_helper.rb96
-rw-r--r--app/helpers/projects_helper.rb27
-rw-r--r--app/models/gollum_wiki.rb4
-rw-r--r--app/models/tree.rb3
-rw-r--r--app/models/user.rb13
-rw-r--r--app/observers/project_observer.rb5
-rw-r--r--app/services/git_push_service.rb2
-rw-r--r--app/views/admin/dashboard/index.html.haml31
-rw-r--r--app/views/admin/users/show.html.haml8
-rw-r--r--app/views/dashboard/issues.atom.builder2
-rw-r--r--app/views/dashboard/show.atom.builder2
-rw-r--r--app/views/events/_event.html.haml2
-rw-r--r--app/views/events/event/_push.html.haml2
-rw-r--r--app/views/groups/issues.atom.builder2
-rw-r--r--app/views/groups/show.atom.builder2
-rw-r--r--app/views/help/permissions.html.haml4
-rw-r--r--app/views/layouts/_head_panel.html.haml4
-rw-r--r--app/views/layouts/nav/_profile.html.haml7
-rw-r--r--app/views/profiles/account.html.haml141
-rw-r--r--app/views/profiles/accounts/show.html.haml73
-rw-r--r--app/views/profiles/passwords/edit.html.haml32
-rw-r--r--app/views/profiles/show.html.haml76
-rw-r--r--app/views/profiles/update_username.js.haml4
-rw-r--r--app/views/projects/branches/_branch.html.haml2
-rw-r--r--app/views/projects/commits/show.atom.builder2
-rw-r--r--app/views/projects/edit.html.haml2
-rw-r--r--app/views/projects/hooks/_data_ex.html.erb1
-rw-r--r--app/views/projects/issues/_issue.html.haml3
-rw-r--r--app/views/projects/issues/_issues.html.haml2
-rw-r--r--app/views/projects/issues/index.atom.builder2
-rw-r--r--app/views/projects/merge_requests/index.html.haml2
-rw-r--r--app/views/projects/milestones/_issues.html.haml2
-rw-r--r--app/views/projects/milestones/show.html.haml2
-rw-r--r--app/views/projects/network/show.json.erb2
-rw-r--r--app/views/projects/notes/_discussion.html.haml2
-rw-r--r--app/views/projects/notes/_note.html.haml2
-rw-r--r--app/views/projects/repositories/_feed.html.haml2
-rw-r--r--app/views/projects/repositories/stats.html.haml2
-rw-r--r--app/views/projects/show.html.haml2
-rw-r--r--app/views/projects/snippets/_snippet.html.haml2
-rw-r--r--app/views/projects/snippets/show.html.haml2
-rw-r--r--app/views/projects/team_members/_team_member.html.haml2
-rw-r--r--app/views/projects/tree/_submodule_item.html.haml15
-rw-r--r--app/views/snippets/_snippet.html.haml2
-rw-r--r--app/views/snippets/show.html.haml2
-rw-r--r--app/views/snippets/user_index.html.haml2
-rw-r--r--app/views/users/_projects.html.haml7
-rw-r--r--app/views/users/show.html.haml4
-rw-r--r--app/views/users_groups/_users_group.html.haml2
-rw-r--r--config/gitlab.yml.example3
-rw-r--r--config/initializers/devise_async.rb1
-rw-r--r--config/initializers/session_store.rb16
-rw-r--r--config/routes.rb10
-rw-r--r--db/migrate/20131005191208_add_avatar_to_users.rb5
-rw-r--r--db/schema.rb3
-rw-r--r--doc/api/projects.md12
-rw-r--r--doc/api/repositories.md13
-rw-r--r--doc/api/system_hooks.md2
-rw-r--r--doc/install/installation.md4
-rw-r--r--features/profile/profile.feature15
-rw-r--r--features/project/source/markdown_render.feature75
-rw-r--r--features/steps/profile/profile.rb21
-rw-r--r--features/steps/project/project_markdown_render.rb165
-rw-r--r--features/steps/shared/paths.rb6
-rw-r--r--lib/api/groups.rb1
-rw-r--r--lib/api/projects.rb10
-rw-r--r--lib/api/repositories.rb30
-rw-r--r--lib/backup/repository.rb4
-rw-r--r--lib/redcarpet/render/gitlab_html.rb14
-rwxr-xr-xlib/support/init.d/gitlab4
-rw-r--r--lib/tasks/sidekiq.rake18
-rw-r--r--spec/features/notes_on_merge_requests_spec.rb6
-rw-r--r--spec/features/profile_spec.rb6
-rw-r--r--spec/features/security/profile_access_spec.rb2
-rw-r--r--spec/helpers/application_helper_spec.rb18
-rw-r--r--spec/helpers/gitlab_markdown_helper_spec.rb24
-rw-r--r--spec/helpers/projects_helper_spec.rb11
-rw-r--r--spec/lib/gitlab/satellite/merge_action_spec.rb2
-rw-r--r--spec/models/gollum_wiki_spec.rb21
-rw-r--r--spec/models/project_spec.rb8
-rw-r--r--spec/observers/users_project_observer_spec.rb28
-rw-r--r--spec/requests/api/projects_spec.rb38
-rw-r--r--spec/requests/api/repositories_spec.rb12
-rw-r--r--spec/routing/routing_spec.rb2
-rw-r--r--spec/seed_project.tar.gzbin9744833 -> 9795570 bytes
-rw-r--r--spec/services/git_push_service_spec.rb1
103 files changed, 1040 insertions, 387 deletions
diff --git a/CHANGELOG b/CHANGELOG
index c4e411e2df5..1843311d763 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -13,6 +13,8 @@ v 6.2.0
- Rake tasks for web hooks management (Jonhnny Weslley)
- Extended User API to expose admin and can_create_group for user creation/updating (Boyan Tabakov)
- API: Remove group
+ - Avatar upload on profile page with a maximum of 200KB (Steven Thonus)
+ - Store the sessions in Redis instead of the cookie store
v 6.1.0
- Project specific IDs for issues, mr, milestones
diff --git a/Gemfile b/Gemfile
index fb67f301f72..faa7f362be4 100644
--- a/Gemfile
+++ b/Gemfile
@@ -16,6 +16,7 @@ gem "pg", group: :postgres
# Auth
gem "devise", '~> 2.2'
+gem "devise-async"
gem 'omniauth', "~> 1.1.3"
gem 'omniauth-google-oauth2'
gem 'omniauth-twitter'
@@ -23,7 +24,7 @@ gem 'omniauth-github'
# Extracting information from a git repository
# Provide access to Gitlab::Git library
-gem "gitlab_git", "~> 3.0.0.beta1"
+gem "gitlab_git", "~> 3.0.0.rc1"
# Ruby/Rack Git Smart-HTTP Server Handler
gem 'gitlab-grack', '~> 1.0.1', require: 'grack'
diff --git a/Gemfile.lock b/Gemfile.lock
index ce3aeb7994b..38d53eca14e 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -106,6 +106,8 @@ GEM
orm_adapter (~> 0.1)
railties (~> 3.1)
warden (~> 1.2.1)
+ devise-async (0.8.0)
+ devise (>= 2.2, < 3.2)
diff-lcs (1.2.4)
dotenv (0.8.0)
email_spec (1.4.0)
@@ -177,7 +179,7 @@ GEM
gitlab-pygments.rb (0.3.2)
posix-spawn (~> 0.3.6)
yajl-ruby (~> 1.1.0)
- gitlab_git (3.0.0.beta1)
+ gitlab_git (3.0.0.rc1)
activesupport (~> 3.2.13)
github-linguist (~> 2.3.4)
gitlab-grit (~> 2.6.0)
@@ -564,6 +566,7 @@ DEPENDENCIES
d3_rails (~> 3.1.4)
database_cleaner
devise (~> 2.2)
+ devise-async
email_spec
enumerize
factory_girl_rails
@@ -578,7 +581,7 @@ DEPENDENCIES
gitlab-gollum-lib (~> 1.0.1)
gitlab-grack (~> 1.0.1)
gitlab-pygments.rb (~> 0.3.2)
- gitlab_git (~> 3.0.0.beta1)
+ gitlab_git (~> 3.0.0.rc1)
gitlab_meta (= 6.0)
gitlab_omniauth-ldap (= 1.0.3)
gon
diff --git a/app/assets/javascripts/profile.js.coffee b/app/assets/javascripts/profile.js.coffee
index e7974611cbe..744f3086d55 100644
--- a/app/assets/javascripts/profile.js.coffee
+++ b/app/assets/javascripts/profile.js.coffee
@@ -16,3 +16,13 @@ $ ->
$('.update-notifications').on 'ajax:complete', ->
$(this).find('.btn-save').enableButton()
+
+
+ $('.js-choose-user-avatar-button').bind "click", ->
+ form = $(this).closest("form")
+ form.find(".js-user-avatar-input").click()
+
+ $('.js-user-avatar-input').bind "change", ->
+ form = $(this).closest("form")
+ filename = $(this).val().replace(/^.*[\\\/]/, '')
+ form.find(".js-avatar-filename").text(filename)
diff --git a/app/assets/javascripts/users_select.js.coffee b/app/assets/javascripts/users_select.js.coffee
index 8286ca2f0c1..327667fede0 100644
--- a/app/assets/javascripts/users_select.js.coffee
+++ b/app/assets/javascripts/users_select.js.coffee
@@ -1,9 +1,11 @@
$ ->
userFormatResult = (user) ->
- avatar = gon.gravatar_url
- avatar = avatar.replace('%{hash}', md5(user.email))
- avatar = avatar.replace('%{size}', '24')
-
+ if user.avatar
+ avatar = user.avatar.url
+ else
+ avatar = gon.gravatar_url
+ avatar = avatar.replace('%{hash}', md5(user.email))
+ avatar = avatar.replace('%{size}', '24')
markup = "<div class='user-result'>"
markup += "<div class='user-image'><img class='avatar s24' src='" + avatar + "'></div>"
markup += "<div class='user-name'>" + user.name + "</div>"
diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss
index 1572227ec3a..a3156ec10fc 100644
--- a/app/assets/stylesheets/common.scss
+++ b/app/assets/stylesheets/common.scss
@@ -270,27 +270,6 @@ li.note {
}
}
-.oauth_select_holder {
- padding: 20px;
- img {
- padding: 5px;
- margin-right: 10px;
- }
- .active {
- img {
- border: 1px solid #ccc;
- background: $hover;
- @include border-radius(5px);
- }
- }
-}
-
-.btn-build-token {
- float: left;
- padding: 6px 20px;
- margin-right: 12px;
-}
-
.gitlab-promo {
a {
color: #aaa;
diff --git a/app/assets/stylesheets/gitlab_bootstrap/avatar.scss b/app/assets/stylesheets/gitlab_bootstrap/avatar.scss
index c23970c13eb..98fbbd64e99 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/avatar.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/avatar.scss
@@ -19,4 +19,5 @@
&.s32 { width: 32px; height: 32px; margin-right: 10px; }
&.s60 { width: 60px; height: 60px; margin-right: 12px; }
&.s90 { width: 90px; height: 90px; margin-right: 15px; }
+ &.s160 { width: 160px; height: 160px; margin-right: 20px; }
}
diff --git a/app/assets/stylesheets/gitlab_bootstrap/blocks.scss b/app/assets/stylesheets/gitlab_bootstrap/blocks.scss
index fcf1159cd33..f0a77bb8add 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/blocks.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/blocks.scss
@@ -12,7 +12,7 @@
.ui-box {
background: #FFF;
margin-bottom: 20px;
- border: 1px solid #CCC;
+ border: 1px solid #DDD;
word-wrap: break-word;
&.small-box {
diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss
index be6fb29c817..45a83cb6081 100644
--- a/app/assets/stylesheets/sections/commits.scss
+++ b/app/assets/stylesheets/sections/commits.scss
@@ -419,7 +419,6 @@
.commit-title {
margin: 0;
font-size: 20px;
- font-weight: bold;
}
.commit-description {
@@ -505,4 +504,4 @@ li.commit {
@extend .cgray;
}
}
-} \ No newline at end of file
+}
diff --git a/app/assets/stylesheets/sections/dashboard.scss b/app/assets/stylesheets/sections/dashboard.scss
index 3f7825d71ce..04df7656b0d 100644
--- a/app/assets/stylesheets/sections/dashboard.scss
+++ b/app/assets/stylesheets/sections/dashboard.scss
@@ -60,7 +60,7 @@
}
a {
- border-color: #CCC !important;
+ border-color: #DDD !important;
}
}
}
diff --git a/app/assets/stylesheets/sections/profile.scss b/app/assets/stylesheets/sections/profile.scss
index 5c7516ce6f9..21f4ed0577d 100644
--- a/app/assets/stylesheets/sections/profile.scss
+++ b/app/assets/stylesheets/sections/profile.scss
@@ -4,3 +4,41 @@
margin-bottom: 0;
}
}
+
+.account-page {
+ fieldset {
+ margin-bottom: 15px;
+ border-bottom: 1px dashed #ddd;
+ padding-bottom: 15px;
+
+ &:last-child {
+ border: none;
+ }
+
+ legend {
+ border: none;
+ margin: 0;
+ }
+ }
+}
+
+.oauth_select_holder {
+ img {
+ padding: 2px;
+ margin-right: 10px;
+ }
+ .active {
+ img {
+ border: 1px solid #4BD;
+ background: $hover;
+ @include border-radius(5px);
+ }
+ }
+}
+
+.btn-build-token {
+ float: left;
+ padding: 6px 20px;
+ margin-right: 12px;
+}
+
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index d974600dcc1..85b95862a17 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -63,6 +63,15 @@ class ApplicationController < ActionController::Base
def project
id = params[:project_id] || params[:id]
+ # Redirect from
+ # localhost/group/project.git
+ # to
+ # localhost/group/project
+ #
+ if id =~ /\.git\Z/
+ redirect_to request.original_url.gsub(/\.git\Z/, '') and return
+ end
+
@project = Project.find_with_namespace(id)
if @project and can?(current_user, :read_project, @project)
diff --git a/app/controllers/profiles/accounts_controller.rb b/app/controllers/profiles/accounts_controller.rb
new file mode 100644
index 00000000000..fe121691a10
--- /dev/null
+++ b/app/controllers/profiles/accounts_controller.rb
@@ -0,0 +1,7 @@
+class Profiles::AccountsController < ApplicationController
+ layout "profile"
+
+ def show
+ @user = current_user
+ end
+end
diff --git a/app/controllers/profiles/passwords_controller.rb b/app/controllers/profiles/passwords_controller.rb
index 432899f857d..df6954554ea 100644
--- a/app/controllers/profiles/passwords_controller.rb
+++ b/app/controllers/profiles/passwords_controller.rb
@@ -1,10 +1,11 @@
class Profiles::PasswordsController < ApplicationController
- layout 'navless'
+ layout :determine_layout
- skip_before_filter :check_password_expiration
+ skip_before_filter :check_password_expiration, only: [:new, :create]
before_filter :set_user
before_filter :set_title
+ before_filter :authorize_change_password!
def new
end
@@ -26,6 +27,32 @@ class Profiles::PasswordsController < ApplicationController
end
end
+ def edit
+ end
+
+ def update
+ password_attributes = params[:user].select do |key, value|
+ %w(password password_confirmation).include?(key.to_s)
+ end
+
+ unless @user.valid_password?(params[:user][:current_password])
+ redirect_to edit_profile_password_path, alert: 'You must provide a valid current password'
+ return
+ end
+
+ if @user.update_attributes(password_attributes)
+ flash[:notice] = "Password was successfully updated. Please login with it"
+ redirect_to new_user_session_path
+ else
+ render 'edit'
+ end
+ end
+
+ def reset
+ current_user.send_reset_password_instructions
+ redirect_to edit_profile_password_path, notice: 'We sent you an email with reset password instructions'
+ end
+
private
def set_user
@@ -35,4 +62,16 @@ class Profiles::PasswordsController < ApplicationController
def set_title
@title = "New password"
end
+
+ def determine_layout
+ if [:new, :create].include?(action_name.to_sym)
+ 'navless'
+ else
+ 'profile'
+ end
+ end
+
+ def authorize_change_password!
+ return render_404 if @user.ldap_user?
+ end
end
diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb
index 75f12f8a6af..47cfc5e63f5 100644
--- a/app/controllers/profiles_controller.rb
+++ b/app/controllers/profiles_controller.rb
@@ -2,7 +2,6 @@ class ProfilesController < ApplicationController
include ActionView::Helpers::SanitizeHelper
before_filter :user
- before_filter :authorize_change_password!, only: :update_password
before_filter :authorize_change_username!, only: :update_username
layout 'profile'
@@ -13,9 +12,6 @@ class ProfilesController < ApplicationController
def design
end
- def account
- end
-
def update
if @user.update_attributes(params[:user])
flash[:notice] = "Profile was successfully updated"
@@ -29,33 +25,12 @@ class ProfilesController < ApplicationController
end
end
- def token
- end
-
- def update_password
- password_attributes = params[:user].select do |key, value|
- %w(password password_confirmation).include?(key.to_s)
- end
-
- unless @user.valid_password?(params[:user][:current_password])
- redirect_to account_profile_path, alert: 'You must provide a valid current password'
- return
- end
-
- if @user.update_attributes(password_attributes)
- flash[:notice] = "Password was successfully updated. Please login with it"
- redirect_to new_user_session_path
- else
- render 'account'
- end
- end
-
def reset_private_token
if current_user.reset_authentication_token!
flash[:notice] = "Token was successfully updated"
end
- redirect_to account_profile_path
+ redirect_to profile_account_path
end
def history
@@ -76,10 +51,6 @@ class ProfilesController < ApplicationController
@user = current_user
end
- def authorize_change_password!
- return render_404 if @user.ldap_user?
- end
-
def authorize_change_username!
return render_404 unless @user.can_change_username?
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 7e5c10fee05..0e48889ebf8 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -49,6 +49,15 @@ module ApplicationHelper
args.any? { |v| v.to_s.downcase == action_name }
end
+ def avatar_icon(user_email = '', size = nil)
+ user = User.find_by_email(user_email)
+ if user && user.avatar.present?
+ user.avatar.url
+ else
+ gravatar_icon(user_email, size)
+ end
+ end
+
def gravatar_icon(user_email = '', size = nil)
size = 40 if size.nil? || size <= 0
@@ -96,7 +105,7 @@ module ApplicationHelper
groups = current_user.authorized_groups.map { |group| { label: "group: #{simple_sanitize(group.name)}", url: group_path(group) } }
default_nav = [
- { label: "My Profile", url: profile_path },
+ { label: "My Profile settings", url: profile_path },
{ label: "My SSH Keys", url: profile_keys_path },
{ label: "My Dashboard", url: root_path },
{ label: "Admin Section", url: admin_root_path },
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index f8f84ff8b62..7e24cbd3e58 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -108,7 +108,7 @@ module CommitsHelper
source_name = commit.send "#{options[:source]}_name".to_sym
source_email = commit.send "#{options[:source]}_email".to_sym
text = if options[:avatar]
- avatar = image_tag(gravatar_icon(source_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "")
+ avatar = image_tag(avatar_icon(source_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "")
%Q{#{avatar} <span class="commit-#{options[:source]}-name">#{source_name}</span>}
else
source_name
diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb
index 375f8861dae..0210bea2f40 100644
--- a/app/helpers/gitlab_markdown_helper.rb
+++ b/app/helpers/gitlab_markdown_helper.rb
@@ -34,7 +34,8 @@ module GitlabMarkdownHelper
# see https://github.com/vmg/redcarpet#darling-i-packed-you-a-couple-renderers-for-lunch-
filter_html: true,
with_toc_data: true,
- hard_wrap: true)
+ hard_wrap: true,
+ safe_links_only: true)
@markdown = Redcarpet::Markdown.new(gitlab_renderer,
# see https://github.com/vmg/redcarpet#and-its-like-really-simple-to-use
no_intra_emphasis: true,
@@ -57,4 +58,97 @@ module GitlabMarkdownHelper
wiki_page.formatted_content.html_safe
end
end
+
+ # text - whole text from a markdown file
+ # project_path_with_namespace - namespace/projectname, eg. gitlabhq/gitlabhq
+ # ref - name of the branch or reference, eg. stable
+ # requested_path - path of request, eg. doc/api/README.md, used in special case when path is pointing to the .md file were the original request is coming from
+ # wiki - whether the markdown is from wiki or not
+ def create_relative_links(text, project_path_with_namespace, ref, requested_path, wiki = false)
+ paths = extract_paths(text)
+ paths.each do |file_path|
+ new_path = rebuild_path(project_path_with_namespace, file_path, requested_path, ref)
+ # Replacing old string with a new one with brackets ]() to prevent replacing occurence of a word
+ # e.g. If we have a markdown like [test](test) this will replace ](test) and not the word test
+ text.gsub!("](#{file_path})", "](/#{new_path})")
+ end
+ text
+ end
+
+ def extract_paths(markdown_text)
+ all_markdown_paths = pick_out_paths(markdown_text)
+ paths = remove_empty(all_markdown_paths)
+ select_relative(paths)
+ end
+
+ # Split the markdown text to each line and find all paths, this will match anything with - ]("some_text")
+ def pick_out_paths(markdown_text)
+ markdown_text.split("\n").map { |text| text.scan(/\]\(([^(]+)\)/) }
+ end
+
+ # Removes any empty result produced by not matching the regexp
+ def remove_empty(paths)
+ paths.reject{|l| l.empty? }.flatten
+ end
+
+ # Reject any path that contains ignored protocol
+ # eg. reject "https://gitlab.org} but accept "doc/api/README.md"
+ def select_relative(paths)
+ paths.reject{|path| ignored_protocols.map{|protocol| path.include?(protocol)}.any?}
+ end
+
+ def ignored_protocols
+ ["http://","https://", "ftp://", "mailto:"]
+ end
+
+ def rebuild_path(path_with_namespace, path, requested_path, ref)
+ file_path = relative_file_path(path, requested_path)
+ [
+ path_with_namespace,
+ path_with_ref(file_path, ref),
+ file_path
+ ].compact.join("/")
+ end
+
+ # Checks if the path exists in the repo
+ # eg. checks if doc/README.md exists, if it doesn't then it is a wiki link
+ def path_with_ref(path, ref)
+ if file_exists?(path)
+ "#{local_path(path)}/#{correct_ref(ref)}"
+ else
+ "wikis"
+ end
+ end
+
+ def relative_file_path(path, requested_path)
+ nested_path = build_nested_path(path, requested_path)
+ return nested_path if file_exists?(nested_path)
+ path
+ end
+
+ # Covering a special case, when the link is referencing file in the same directory eg:
+ # If we are at doc/api/README.md and the README.md contains relative links like [Users](users.md)
+ # this takes the request path(doc/api/README.md), and replaces the README.md with users.md so the path looks like doc/api/users.md
+ def build_nested_path(path, request_path)
+ return path unless request_path
+ base = request_path.split("/")
+ base.pop
+ (base + [path]).join("/")
+ end
+
+ def file_exists?(path)
+ return false if path.nil? || path.empty?
+ File.exists?(Rails.root.join(path))
+ end
+
+ # Check if the path is pointing to a directory(tree) or a file(blob)
+ # eg. doc/api is directory and doc/README.md is file
+ def local_path(path)
+ File.directory?(Rails.root.join(path)) ? "tree" : "blob"
+ end
+
+ # We will assume that if no ref exists we can point to master
+ def correct_ref(ref)
+ ref ? ref : "master"
+ end
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 9071c688df1..d4f1a8f741f 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -5,10 +5,10 @@ module ProjectsHelper
def link_to_project project
link_to project do
- title = content_tag(:strong, project.name)
+ title = content_tag(:span, project.name, class: 'projet-name')
if project.namespace
- namespace = content_tag(:span, "#{project.namespace.human_name} / ", class: 'tiny')
+ namespace = content_tag(:span, "#{project.namespace.human_name} / ", class: 'namespace-name')
title = namespace + title
end
@@ -25,7 +25,7 @@ module ProjectsHelper
author_html = ""
# Build avatar image tag
- author_html << image_tag(gravatar_icon(author.try(:email), opts[:size]), width: opts[:size], class: "avatar avatar-inline #{"s#{opts[:size]}" if opts[:size]}", alt:'') if opts[:avatar]
+ author_html << image_tag(avatar_icon(author.try(:email), opts[:size]), width: opts[:size], class: "avatar avatar-inline #{"s#{opts[:size]}" if opts[:size]}", alt:'') if opts[:avatar]
# Build name span tag
author_html << content_tag(:span, sanitize(author.name), class: 'author') if opts[:name]
@@ -80,6 +80,18 @@ module ProjectsHelper
@project.milestones.active.order("id desc").all
end
+ def project_issues_trackers
+ values = Project.issues_tracker.values.map do |tracker_key|
+ if tracker_key.to_sym == :gitlab
+ ['GitLab', tracker_key]
+ else
+ [Gitlab.config.issues_tracker[tracker_key]['title'] || tracker_key, tracker_key]
+ end
+ end
+
+ options_for_select(values)
+ end
+
private
def get_project_nav_tabs(project, current_user)
@@ -119,4 +131,13 @@ module ProjectsHelper
"your@email.com"
end
end
+
+ def repository_size
+ "#{@project.repository.size} MB"
+ rescue
+ # In order to prevent 500 error
+ # when application cannot allocate memory
+ # to calculate repo size - just show 'Unknown'
+ 'unknown'
+ end
end
diff --git a/app/models/gollum_wiki.rb b/app/models/gollum_wiki.rb
index d1edbab4533..05fc2a745b4 100644
--- a/app/models/gollum_wiki.rb
+++ b/app/models/gollum_wiki.rb
@@ -45,6 +45,10 @@ class GollumWiki
end
end
+ def empty?
+ pages.empty?
+ end
+
# Returns an Array of Gitlab WikiPage instances or an
# empty Array if this Wiki has no pages.
def pages
diff --git a/app/models/tree.rb b/app/models/tree.rb
index 5fbad19b468..ed06cb1a128 100644
--- a/app/models/tree.rb
+++ b/app/models/tree.rb
@@ -7,7 +7,8 @@ class Tree
@entries = Gitlab::Git::Tree.where(git_repo, sha, path)
if readme_tree = @entries.find(&:readme?)
- @readme = Gitlab::Git::Blob.find(git_repo, sha, readme_tree.name)
+ readme_path = path == '/' ? readme_tree.name : File.join(path, readme_tree.name)
+ @readme = Gitlab::Git::Blob.find(git_repo, sha, readme_path)
end
end
diff --git a/app/models/user.rb b/app/models/user.rb
index c61b074f504..29c53b88331 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -38,13 +38,16 @@
# created_by_id :integer
#
+require 'carrierwave/orm/activerecord'
+require 'file_size_validator'
+
class User < ActiveRecord::Base
- devise :database_authenticatable, :token_authenticatable, :lockable,
+ devise :database_authenticatable, :token_authenticatable, :lockable, :async,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable, :registerable
attr_accessible :email, :password, :password_confirmation, :remember_me, :bio, :name, :username,
:skype, :linkedin, :twitter, :color_scheme_id, :theme_id, :force_random_password,
- :extern_uid, :provider, :password_expires_at,
+ :extern_uid, :provider, :password_expires_at, :avatar,
as: [:default, :admin]
attr_accessible :projects_limit, :can_create_group,
@@ -113,6 +116,8 @@ class User < ActiveRecord::Base
validate :namespace_uniq, if: ->(user) { user.username_changed? }
+ validates :avatar, file_size: { maximum: 100.kilobytes.to_i }
+
before_validation :generate_password, on: :create
before_validation :sanitize_attrs
@@ -150,6 +155,8 @@ class User < ActiveRecord::Base
end
end
+ mount_uploader :avatar, AttachmentUploader
+
# Scopes
scope :admins, -> { where(admin: true) }
scope :blocked, -> { with_state(:blocked) }
@@ -391,4 +398,4 @@ class User < ActiveRecord::Base
self
end
-end
+end \ No newline at end of file
diff --git a/app/observers/project_observer.rb b/app/observers/project_observer.rb
index acbb719b69a..b82e7d9a03f 100644
--- a/app/observers/project_observer.rb
+++ b/app/observers/project_observer.rb
@@ -14,6 +14,11 @@ class ProjectObserver < BaseObserver
log_info("#{project.owner.name} created a new project \"#{project.name_with_namespace}\"")
end
+
+ if project.wiki_enabled?
+ # force the creation of a wiki,
+ GollumWiki.new(project, project.owner).wiki
+ end
end
def after_update(project)
diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb
index f9d43e60de6..3ad41de397f 100644
--- a/app/services/git_push_service.rb
+++ b/app/services/git_push_service.rb
@@ -112,6 +112,7 @@ class GitPushService
# ref: String,
# user_id: String,
# user_name: String,
+ # project_id: String,
# repository: {
# name: String,
# url: String,
@@ -136,6 +137,7 @@ class GitPushService
ref: ref,
user_id: user.id,
user_name: user.name,
+ project_id: project.id,
repository: {
name: project.name,
url: project.url_to_repo,
diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml
index 9ed788d0d9d..3064763b993 100644
--- a/app/views/admin/dashboard/index.html.haml
+++ b/app/views/admin/dashboard/index.html.haml
@@ -1,30 +1,35 @@
+%h3.page-title
+ Admin area
+%p.light
+ You can manage projects, users and other GitLab data from here.
+%hr
.admin_dash.row
.span4
- .ui-box
- .title Projects
- .data.padded
+ .light-well
+ %h4 Projects
+ .data
= link_to admin_projects_path do
%h1= Project.count
%hr
- = link_to 'New Project', new_project_path, class: "btn btn-small"
+ = link_to 'New Project', new_project_path, class: "btn btn-new"
.span4
- .ui-box
- .title Users
- .data.padded
+ .light-well
+ %h4 Users
+ .data
= link_to admin_users_path do
%h1= User.count
%hr
- = link_to 'New User', new_admin_user_path, class: "btn btn-small"
+ = link_to 'New User', new_admin_user_path, class: "btn btn-new"
.span4
- .ui-box
- .title Groups
- .data.padded
+ .light-well
+ %h4 Groups
+ .data
= link_to admin_groups_path do
%h1= Group.count
%hr
- = link_to 'New Group', new_admin_group_path, class: "btn btn-small"
+ = link_to 'New Group', new_admin_group_path, class: "btn btn-new"
-.row
+.row.prepend-top-10
.span4
%h4 Latest projects
%hr
diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index 3df9903e409..df9fc687478 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -20,7 +20,7 @@
.title
Account:
.pull-right
- = image_tag gravatar_icon(@user.email, 32), class: "avatar s32"
+ = image_tag avatar_icon(@user.email, 32), class: "avatar s32"
%ul.well-list
%li
%span.light Name:
@@ -117,11 +117,7 @@
- tm = project.team.find_tm(@user.id)
%li.users_project
= link_to admin_project_path(project), class: dom_class(project) do
- - if project.namespace
- = project.namespace.human_name
- \/
- %strong.well-title
- = truncate(project.name, length: 45)
+ = project.name_with_namespace
- if tm
.pull-right
diff --git a/app/views/dashboard/issues.atom.builder b/app/views/dashboard/issues.atom.builder
index 0f0f3466e92..f5413557783 100644
--- a/app/views/dashboard/issues.atom.builder
+++ b/app/views/dashboard/issues.atom.builder
@@ -12,7 +12,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.link :href => project_issue_url(issue.project, issue)
xml.title truncate(issue.title, :length => 80)
xml.updated issue.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
- xml.media :thumbnail, :width => "40", :height => "40", :url => gravatar_icon(issue.author_email)
+ xml.media :thumbnail, :width => "40", :height => "40", :url => avatar_icon(issue.author_email)
xml.author do |author|
xml.name issue.author_name
xml.email issue.author_email
diff --git a/app/views/dashboard/show.atom.builder b/app/views/dashboard/show.atom.builder
index a913df92299..f4cf24ccd99 100644
--- a/app/views/dashboard/show.atom.builder
+++ b/app/views/dashboard/show.atom.builder
@@ -17,7 +17,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.link :href => event_link
xml.title truncate(event_title, :length => 80)
xml.updated event.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
- xml.media :thumbnail, :width => "40", :height => "40", :url => gravatar_icon(event.author_email)
+ xml.media :thumbnail, :width => "40", :height => "40", :url => avatar_icon(event.author_email)
xml.author do |author|
xml.name event.author_name
xml.email event.author_email
diff --git a/app/views/events/_event.html.haml b/app/views/events/_event.html.haml
index b3543460d65..892dacafa62 100644
--- a/app/views/events/_event.html.haml
+++ b/app/views/events/_event.html.haml
@@ -4,7 +4,7 @@
#{time_ago_in_words(event.created_at)} ago.
= cache event do
- = image_tag gravatar_icon(event.author_email), class: "avatar s24", alt:''
+ = image_tag avatar_icon(event.author_email), class: "avatar s24", alt:''
- if event.push?
= render "events/event/push", event: event
diff --git a/app/views/events/event/_push.html.haml b/app/views/events/event/_push.html.haml
index adba9a5f619..f181df23eb4 100644
--- a/app/views/events/event/_push.html.haml
+++ b/app/views/events/event/_push.html.haml
@@ -7,7 +7,7 @@
= link_to project_commits_path(event.project, event.ref_name) do
%strong= truncate(event.ref_name, length: 30)
at
- %strong= link_to_project event.project
+ = link_to_project event.project
- if event.push_with_commits?
- project = event.project
diff --git a/app/views/groups/issues.atom.builder b/app/views/groups/issues.atom.builder
index 701747bdbc3..f2005193f83 100644
--- a/app/views/groups/issues.atom.builder
+++ b/app/views/groups/issues.atom.builder
@@ -12,7 +12,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.link :href => project_issue_url(issue.project, issue)
xml.title truncate(issue.title, :length => 80)
xml.updated issue.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
- xml.media :thumbnail, :width => "40", :height => "40", :url => gravatar_icon(issue.author_email)
+ xml.media :thumbnail, :width => "40", :height => "40", :url => avatar_icon(issue.author_email)
xml.author do |author|
xml.name issue.author_name
xml.email issue.author_email
diff --git a/app/views/groups/show.atom.builder b/app/views/groups/show.atom.builder
index edf03642d82..e07bb7d2fb7 100644
--- a/app/views/groups/show.atom.builder
+++ b/app/views/groups/show.atom.builder
@@ -16,7 +16,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.link :href => event_link
xml.title truncate(event_title, :length => 80)
xml.updated event.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
- xml.media :thumbnail, :width => "40", :height => "40", :url => gravatar_icon(event.author_email)
+ xml.media :thumbnail, :width => "40", :height => "40", :url => avatar_icon(event.author_email)
xml.author do |author|
xml.name event.author_name
xml.email event.author_email
diff --git a/app/views/help/permissions.html.haml b/app/views/help/permissions.html.haml
index bab1e7c0a41..df35f41fc90 100644
--- a/app/views/help/permissions.html.haml
+++ b/app/views/help/permissions.html.haml
@@ -1,6 +1,8 @@
= render layout: 'help/layout' do
%h3.page-title Permissions
- %p.light User has different abilities depends on access level he has in particular group or project
+ %p.light Users have different abilities depending on the access level they have in particular group or project.
+ %p.light If a user is both in a project group and in the project itself the highest permission level is used.
+ %p.light If a user is a GitLab administrator they receive all permissions.
%hr
%h4 Project:
diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml
index 6492c122ba0..80c42fe6387 100644
--- a/app/views/layouts/_head_panel.html.haml
+++ b/app/views/layouts/_head_panel.html.haml
@@ -30,11 +30,11 @@
= link_to new_project_path, title: "New project", class: 'has_bottom_tooltip', 'data-original-title' => 'New project' do
%i.icon-plus
%li
- = link_to profile_path, title: "My profile", class: 'has_bottom_tooltip', 'data-original-title' => 'My profile' do
+ = link_to profile_path, title: "Profile settings", class: 'has_bottom_tooltip', 'data-original-title' => 'Profile settings"' do
%i.icon-user
%li
= link_to destroy_user_session_path, class: "logout", method: :delete, title: "Logout", class: 'has_bottom_tooltip', 'data-original-title' => 'Logout' do
%i.icon-signout
%li
= link_to current_user, class: "profile-pic", id: 'profile-pic' do
- = image_tag gravatar_icon(current_user.email, 26), alt: ''
+ = image_tag avatar_icon(current_user.email, 26), alt: 'User activity'
diff --git a/app/views/layouts/nav/_profile.html.haml b/app/views/layouts/nav/_profile.html.haml
index 7c3acfc398a..d44cb975ea5 100644
--- a/app/views/layouts/nav/_profile.html.haml
+++ b/app/views/layouts/nav/_profile.html.haml
@@ -2,8 +2,11 @@
= nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
= link_to profile_path, title: "Profile" do
%i.icon-home
- = nav_link(path: 'profiles#account') do
- = link_to "Account", account_profile_path
+ = nav_link(controller: :accounts) do
+ = link_to "Account", profile_account_path
+ - unless current_user.ldap_user?
+ = nav_link(controller: :passwords) do
+ = link_to "Password", edit_profile_password_path
= nav_link(controller: :notifications) do
= link_to "Notifications", profile_notifications_path
= nav_link(controller: :keys) do
diff --git a/app/views/profiles/account.html.haml b/app/views/profiles/account.html.haml
deleted file mode 100644
index 42c7ec051cb..00000000000
--- a/app/views/profiles/account.html.haml
+++ /dev/null
@@ -1,141 +0,0 @@
-%h3.page-title
- Account settings
-%p.light
- You can change your password, username and private token here.
- - if current_user.ldap_user?
- Some options are unavailable for LDAP accounts
-%hr
-
-
-.row
- .span2
- %ul.nav.nav-pills.nav-stacked.nav-stacked-menu
- %li.active
- = link_to '#tab-token', 'data-toggle' => 'tab' do
- Private Token
- %li
- = link_to '#tab-password', 'data-toggle' => 'tab' do
- Password
-
- - if show_profile_social_tab?
- %li
- = link_to '#tab-social', 'data-toggle' => 'tab' do
- Social Accounts
-
- - if show_profile_username_tab?
- %li
- = link_to '#tab-username', 'data-toggle' => 'tab' do
- Change Username
-
- - if show_profile_remove_tab?
- %li
- = link_to '#tab-remove', 'data-toggle' => 'tab' do
- Remove Account
- .span10
- .tab-content
- .tab-pane.active#tab-token
- %fieldset.update-token
- %legend
- Private token
- %span.cred.pull-right
- keep it secret!
- %div
- = form_for @user, url: reset_private_token_profile_path, method: :put do |f|
- .data
- %p.slead
- Your private token is used to access application resources without authentication.
- %br
- It can be used for atom feeds or the API.
- %p.cgray
- - if current_user.private_token
- = text_field_tag "token", current_user.private_token, class: "input-xxlarge large_text input-xpadding"
- = f.submit 'Reset', confirm: "Are you sure?", class: "btn btn-primary btn-build-token"
- - else
- %span You don`t have one yet. Click generate to fix it.
- = f.submit 'Generate', class: "btn success btn-build-token"
-
- .tab-pane#tab-password
- %fieldset.update-password
- %legend Password
- - if current_user.ldap_user?
- %h3.nothing_here_message Not available for LDAP user
- - else
- = form_for @user, url: update_password_profile_path, method: :put do |f|
- %div
- %p.slead
- You must provide current password in order to change it.
- %br
- After a successful password update you will be redirected to login page where you should login with your new password
- -if @user.errors.any?
- .alert.alert-error
- %ul
- - @user.errors.full_messages.each do |msg|
- %li= msg
- .control-group
- = f.label :current_password, class: 'cgreen'
- .controls= f.password_field :current_password, required: true
- .control-group
- = f.label :password, 'New password'
- .controls= f.password_field :password, required: true
- .control-group
- = f.label :password_confirmation
- .controls
- = f.password_field :password_confirmation, required: true
- .control-group
- .controls
- = f.submit 'Save password', class: "btn btn-save"
-
- - if show_profile_social_tab?
- .tab-pane#tab-social
- %fieldset
- %legend Social Accounts
- .oauth_select_holder
- %p.hint Tip: Click on icon to activate signin with one of the following services
- - enabled_social_providers.each do |provider|
- %span{class: oauth_active_class(provider) }
- = link_to authbutton(provider, 32), omniauth_authorize_path(User, provider)
-
- - if show_profile_username_tab?
- .tab-pane#tab-username
- %fieldset.update-username
- %legend
- Username
- %small.cred.pull-right
- Changing your username can have unintended side effects!
- = form_for @user, url: update_username_profile_path, method: :put, remote: true do |f|
- %div
- .control-group
- = f.label :username
- .controls
- = f.text_field :username, required: true
- &nbsp;
- %span.loading-gif.hide= image_tag "ajax_loader.gif"
- %span.update-success.cgreen.hide
- %i.icon-ok
- Saved
- %span.update-failed.cred.hide
- %i.icon-remove
- Failed
- %ul.cred
- %li This will change the web URL for personal projects.
- %li This will change the git path to repositories for personal projects.
- .controls
- = f.submit 'Save username', class: "btn btn-save"
-
- - if show_profile_remove_tab?
- .tab-pane#tab-remove
- %fieldset.remove-account
- %legend
- Remove account
- %div
- %p Deleting an account has the following effects:
- %ul
- %li All user content like authored issues, snippets, comments will be removed
- - rp = current_user.personal_projects.count
- - unless rp.zero?
- %li #{pluralize rp, 'personal project'} will be removed and cannot be restored
- - if current_user.solo_owned_groups.present?
- %li
- Next groups will be abandoned. You should transfer or remove them:
- %strong #{current_user.solo_owned_groups.map(&:name).join(', ')}
- = link_to 'Delete account', user_registration_path, confirm: "REMOVE #{current_user.name}? Are you sure?", method: :delete, class: "btn btn-remove"
diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml
new file mode 100644
index 00000000000..453ef8b60db
--- /dev/null
+++ b/app/views/profiles/accounts/show.html.haml
@@ -0,0 +1,73 @@
+%h3.page-title
+ Account settings
+%p.light
+ You can change your username and private token here.
+ - if current_user.ldap_user?
+ Some options are unavailable for LDAP accounts
+%hr
+
+
+.account-page
+ %fieldset.update-token
+ %legend
+ Private token
+ %div
+ = form_for @user, url: reset_private_token_profile_path, method: :put do |f|
+ .data
+ %p
+ Your private token is used to access application resources without authentication.
+ %br
+ It can be used for atom feeds or the API.
+ %span.cred
+ Keep it secret!
+
+ %p.cgray
+ - if current_user.private_token
+ = text_field_tag "token", current_user.private_token, class: "input-xlarge input-xpadding pull-left"
+ = f.submit 'Reset', confirm: "Are you sure?", class: "btn btn-primary btn-build-token prepend-left-10"
+ - else
+ %span You don`t have one yet. Click generate to fix it.
+ = f.submit 'Generate', class: "btn success btn-build-token"
+
+
+ - if show_profile_social_tab?
+ %fieldset
+ %legend Social Accounts
+ .oauth_select_holder.append-bottom-10
+ %p Click on icon to activate signin with one of the following services
+ - enabled_social_providers.each do |provider|
+ %span{class: oauth_active_class(provider) }
+ = link_to authbutton(provider, 32), omniauth_authorize_path(User, provider)
+
+ - if show_profile_username_tab?
+ %fieldset.update-username
+ %legend
+ Username
+ = form_for @user, url: update_username_profile_path, method: :put, remote: true do |f|
+ %p
+ Changing your username will change path to all personl projects!
+ %div
+ = f.text_field :username, required: true, class: 'input-xlarge input-xpadding'
+ &nbsp;
+ %span.loading-gif.hide= image_tag "ajax_loader.gif"
+ %p.light
+ = user_url(@user)
+ %div
+ = f.submit 'Save username', class: "btn btn-save"
+
+ - if show_profile_remove_tab?
+ %fieldset.remove-account
+ %legend
+ Remove account
+ %div
+ %p Deleting an account has the following effects:
+ %ul
+ %li All user content like authored issues, snippets, comments will be removed
+ - rp = current_user.personal_projects.count
+ - unless rp.zero?
+ %li #{pluralize rp, 'personal project'} will be removed and cannot be restored
+ - if current_user.solo_owned_groups.present?
+ %li
+ Next groups will be abandoned. You should transfer or remove them:
+ %strong #{current_user.solo_owned_groups.map(&:name).join(', ')}
+ = link_to 'Delete account', user_registration_path, confirm: "REMOVE #{current_user.name}? Are you sure?", method: :delete, class: "btn btn-remove"
diff --git a/app/views/profiles/passwords/edit.html.haml b/app/views/profiles/passwords/edit.html.haml
new file mode 100644
index 00000000000..a5fa6e7f186
--- /dev/null
+++ b/app/views/profiles/passwords/edit.html.haml
@@ -0,0 +1,32 @@
+%h3.page-title Password
+%p.light
+ Change your password or recover your current one.
+%hr
+.update-password
+ = form_for @user, url: profile_password_path, method: :put do |f|
+ %div
+ %p.slead
+ You must provide current password in order to change it.
+ %br
+ After a successful password update you will be redirected to login page where you should login with your new password
+ -if @user.errors.any?
+ .alert.alert-error
+ %ul
+ - @user.errors.full_messages.each do |msg|
+ %li= msg
+ .control-group
+ = f.label :current_password
+ .controls
+ = f.password_field :current_password, required: true
+ %div
+ = link_to "Forgot your password?", reset_profile_password_path, method: :put
+
+ .control-group
+ = f.label :password, 'New password'
+ .controls= f.password_field :password, required: true
+ .control-group
+ = f.label :password_confirmation
+ .controls
+ = f.password_field :password_confirmation, required: true
+ .form-actions
+ = f.submit 'Save password', class: "btn btn-save"
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index 25bf7912f1e..ada2892c6ba 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -1,18 +1,14 @@
-= image_tag gravatar_icon(@user.email, 60), alt: '', class: 'avatar s60'
%h3.page-title
- = @user.name
- %br
- %small
- = @user.email
-
- .pull-right
- = link_to destroy_user_session_path, class: "logout", method: :delete do
- %small
- %i.icon-signout
- Logout
+ Profile settings
+%p.light
+ This information appears on your profile.
+ - if current_user.ldap_user?
+ Some options are unavailable for LDAP accounts
%hr
-= form_for @user, url: profile_path, method: :put, html: { class: "edit_user form-horizontal" } do |f|
+
+
+= form_for @user, url: profile_path, method: :put, html: { multipart: true, class: "edit_user form-horizontal" } do |f|
-if @user.errors.any?
%div.alert.alert-error
%ul
@@ -29,7 +25,7 @@
= f.label :email, class: "control-label"
.controls
= f.text_field :email, class: "input-xlarge", required: true
- %span.help-block We also use email for avatar detection.
+ %span.help-block We also use email for avatar detection if no avatar is uploaded.
.control-group
= f.label :skype, class: "control-label"
.controls= f.text_field :skype, class: "input-xlarge"
@@ -46,45 +42,23 @@
%span.help-block Tell us about yourself in fewer than 250 characters.
.span5.pull-right
- %fieldset.tips
- %legend Tips:
- %ul
- %li
- %p You can change your password on the Account page
- - if Gitlab.config.gravatar.enabled
- %li
- %p You can change your avatar at #{link_to "gravatar.com", "http://gravatar.com"}
-
- - if Gitlab.config.omniauth.enabled && @user.provider?
- %li
- %p
- You can login through #{@user.provider.titleize}!
- = link_to "click here to change", account_profile_path
- - if current_user.can_create_group?
- %li
- %p
- Need a group for several dependent projects?
- = link_to new_group_path, class: "btn btn-tiny" do
- Create a group
- - unless current_user.projects_limit_left > 100
- %fieldset
- %legend
- Personal projects:
- %small.pull-right
- %span= current_user.personal_projects.count
- of
- %span= current_user.projects_limit
- .padded
- .progress
- .bar{style: "width: #{current_user.projects_limit_percent}%;"}
+ .light-well
+ = image_tag avatar_icon(@user.email, 160), alt: '', class: 'avatar s160'
- %fieldset
- %legend
- SSH public keys:
- %span.pull-right
- = link_to pluralize(current_user.keys.count, 'key'), profile_keys_path
- .padded
- = link_to "Add Public Key", new_profile_key_path, class: "btn btn-small"
+ .clearfix
+ .profile-avatar-form-option
+ %p.light
+ You can upload an avatar here
+ %br
+ or change it at #{link_to "gravatar.com", "http://gravatar.com"}
+ %hr
+ %a.choose-btn.btn.btn-small.js-choose-user-avatar-button
+ %i.icon-paper-clip
+ %span Choose File ...
+ &nbsp;
+ %span.file_name.js-avatar-filename File name...
+ = f.file_field :avatar, class: "js-user-avatar-input hide"
+ %span.help-block The maximum file size allowed is 200KB.
.form-actions
= f.submit 'Save changes', class: "btn btn-save"
diff --git a/app/views/profiles/update_username.js.haml b/app/views/profiles/update_username.js.haml
index abd90269c93..249680bcab6 100644
--- a/app/views/profiles/update_username.js.haml
+++ b/app/views/profiles/update_username.js.haml
@@ -1,6 +1,6 @@
- if @user.valid?
:plain
- $('.update-username .update-success').show();
+ new Flash("Username sucessfully changed", "notice")
- else
:plain
- $('.update-username .update-failed').show();
+ new Flash("Username change failed - #{@user.errors.full_messages.first}", "alert")
diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml
index b8392525791..4372647a41c 100644
--- a/app/views/projects/branches/_branch.html.haml
+++ b/app/views/projects/branches/_branch.html.haml
@@ -24,7 +24,7 @@
%p
= link_to project_commit_path(@project, commit.id), class: 'commit_short_id' do
= commit.short_id
- = image_tag gravatar_icon(commit.author_email), class: "avatar s16", alt: ''
+ = image_tag avatar_icon(commit.author_email), class: "avatar s16", alt: ''
%span.light
= gfm escape_once(truncate(commit.title, length: 40))
%span
diff --git a/app/views/projects/commits/show.atom.builder b/app/views/projects/commits/show.atom.builder
index 46f9838e84a..27c8fa6da72 100644
--- a/app/views/projects/commits/show.atom.builder
+++ b/app/views/projects/commits/show.atom.builder
@@ -12,7 +12,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.link :href => project_commit_url(@project, :id => commit.id)
xml.title truncate(commit.title, :length => 80)
xml.updated commit.committed_date.strftime("%Y-%m-%dT%H:%M:%SZ")
- xml.media :thumbnail, :width => "40", :height => "40", :url => gravatar_icon(commit.author_email)
+ xml.media :thumbnail, :width => "40", :height => "40", :url => avatar_icon(commit.author_email)
xml.author do |author|
xml.name commit.author_name
xml.email commit.author_email
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index 117ee13140e..03cd3cbd658 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -67,7 +67,7 @@
- if Project.issues_tracker.values.count > 1
.control-group
= f.label :issues_tracker, "Issues tracker", class: 'control-label'
- .controls= f.select(:issues_tracker, Project.issues_tracker.values, {}, { disabled: !@project.issues_enabled })
+ .controls= f.select(:issues_tracker, project_issues_trackers, {}, { disabled: !@project.issues_enabled })
.control-group
= f.label :issues_tracker_id, "Project name or id in issues tracker", class: 'control-label'
diff --git a/app/views/projects/hooks/_data_ex.html.erb b/app/views/projects/hooks/_data_ex.html.erb
index b4281fa18c7..5092aaf6750 100644
--- a/app/views/projects/hooks/_data_ex.html.erb
+++ b/app/views/projects/hooks/_data_ex.html.erb
@@ -5,6 +5,7 @@
"ref": "refs/heads/master",
"user_id": 4,
"user_name": "John Smith",
+ "project_id": 15,
"repository": {
"name": "Diaspora",
"url": "git@localhost:diaspora.git",
diff --git a/app/views/projects/issues/_issue.html.haml b/app/views/projects/issues/_issue.html.haml
index b9a2c18efdc..effad718c80 100644
--- a/app/views/projects/issues/_issue.html.haml
+++ b/app/views/projects/issues/_issue.html.haml
@@ -6,6 +6,9 @@
.issue-title
%span.light= "##{issue.iid}"
= link_to_gfm truncate(issue.title, length: 100), project_issue_path(issue.project, issue), class: "row_title"
+ - if issue.closed?
+ %small.pull-right
+ = "CLOSED"
.issue-info
- if issue.assignee
diff --git a/app/views/projects/issues/_issues.html.haml b/app/views/projects/issues/_issues.html.haml
index 539c45edd94..427d6533134 100644
--- a/app/views/projects/issues/_issues.html.haml
+++ b/app/views/projects/issues/_issues.html.haml
@@ -52,7 +52,7 @@
- @project.team.members.sort_by(&:name).each do |user|
%li
= link_to project_filter_path(assignee_id: user.id) do
- = image_tag gravatar_icon(user.email), class: "avatar s16", alt: ''
+ = image_tag avatar_icon(user.email), class: "avatar s16", alt: ''
= user.name
.dropdown.inline.prepend-left-10
diff --git a/app/views/projects/issues/index.atom.builder b/app/views/projects/issues/index.atom.builder
index 00ddd4bf702..012ba235951 100644
--- a/app/views/projects/issues/index.atom.builder
+++ b/app/views/projects/issues/index.atom.builder
@@ -12,7 +12,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.link :href => project_issue_url(@project, issue)
xml.title truncate(issue.title, :length => 80)
xml.updated issue.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
- xml.media :thumbnail, :width => "40", :height => "40", :url => gravatar_icon(issue.author_email)
+ xml.media :thumbnail, :width => "40", :height => "40", :url => avatar_icon(issue.author_email)
xml.author do |author|
xml.name issue.author_name
xml.email issue.author_email
diff --git a/app/views/projects/merge_requests/index.html.haml b/app/views/projects/merge_requests/index.html.haml
index 2bd5a027a02..e256ee2153c 100644
--- a/app/views/projects/merge_requests/index.html.haml
+++ b/app/views/projects/merge_requests/index.html.haml
@@ -35,7 +35,7 @@
- @project.team.members.sort_by(&:name).each do |user|
%li
= link_to project_filter_path(assignee_id: user.id) do
- = image_tag gravatar_icon(user.email), class: "avatar s16", alt: ''
+ = image_tag avatar_icon(user.email), class: "avatar s16", alt: ''
= user.name
.dropdown.inline.prepend-left-10
diff --git a/app/views/projects/milestones/_issues.html.haml b/app/views/projects/milestones/_issues.html.haml
index bf81cfda45f..21939ad0132 100644
--- a/app/views/projects/milestones/_issues.html.haml
+++ b/app/views/projects/milestones/_issues.html.haml
@@ -8,4 +8,4 @@
= link_to_gfm truncate(issue.title, length: 40), [@project, issue]
- if issue.assignee
.pull-right
- = image_tag gravatar_icon(issue.assignee.email, 16), class: "avatar s16"
+ = image_tag avatar_icon(issue.assignee.email, 16), class: "avatar s16"
diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml
index b755a813419..dc7fd40d5e3 100644
--- a/app/views/projects/milestones/show.html.haml
+++ b/app/views/projects/milestones/show.html.haml
@@ -99,7 +99,7 @@
- @users.each do |user|
%li
= link_to user, title: user.name, class: "dark" do
- = image_tag gravatar_icon(user.email, 32), class: "avatar s32"
+ = image_tag avatar_icon(user.email, 32), class: "avatar s32"
%strong= truncate(user.name, lenght: 40)
%br
%small.cgray= user.username
diff --git a/app/views/projects/network/show.json.erb b/app/views/projects/network/show.json.erb
index f0bedcf2d35..dc82adcb2c6 100644
--- a/app/views/projects/network/show.json.erb
+++ b/app/views/projects/network/show.json.erb
@@ -9,7 +9,7 @@
author: {
name: c.author_name,
email: c.author_email,
- icon: gravatar_icon(c.author_email, 20)
+ icon: avatar_icon(c.author_email, 20)
},
time: c.time,
space: c.spaces.first,
diff --git a/app/views/projects/notes/_discussion.html.haml b/app/views/projects/notes/_discussion.html.haml
index a964d86a8dc..e0aad0cc956 100644
--- a/app/views/projects/notes/_discussion.html.haml
+++ b/app/views/projects/notes/_discussion.html.haml
@@ -8,7 +8,7 @@
= link_to "javascript:;", class: "js-details-target turn-off js-toggler-target" do
%i.icon-eye-open
Show discussion
- = image_tag gravatar_icon(note.author_email), class: "avatar s32"
+ = image_tag avatar_icon(note.author_email), class: "avatar s32"
%div
= link_to_member(@project, note.author, avatar: false)
- if note.for_merge_request?
diff --git a/app/views/projects/notes/_note.html.haml b/app/views/projects/notes/_note.html.haml
index 324b698f3b5..e56e9153c2f 100644
--- a/app/views/projects/notes/_note.html.haml
+++ b/app/views/projects/notes/_note.html.haml
@@ -13,7 +13,7 @@
= link_to project_note_path(@project, note), title: "Remove comment", method: :delete, confirm: 'Are you sure you want to remove this comment?', remote: true, class: "danger js-note-delete" do
%i.icon-trash.cred
Remove
- = image_tag gravatar_icon(note.author_email), class: "avatar s32"
+ = image_tag avatar_icon(note.author_email), class: "avatar s32"
= link_to_member(@project, note.author, avatar: false)
%span.note-last-update
= note_timestamp(note)
diff --git a/app/views/projects/repositories/_feed.html.haml b/app/views/projects/repositories/_feed.html.haml
index faa3ed1746c..6e537d2959b 100644
--- a/app/views/projects/repositories/_feed.html.haml
+++ b/app/views/projects/repositories/_feed.html.haml
@@ -11,7 +11,7 @@
%div
= link_to project_commits_path(@project, commit.id) do
%code= commit.short_id
- = image_tag gravatar_icon(commit.author_email), class: "", width: 16, alt: ''
+ = image_tag avatar_icon(commit.author_email), class: "", width: 16, alt: ''
= gfm escape_once(truncate(commit.title, length: 40))
%td
%span.pull-right.cgray
diff --git a/app/views/projects/repositories/stats.html.haml b/app/views/projects/repositories/stats.html.haml
index 454296e82fd..679b4211cde 100644
--- a/app/views/projects/repositories/stats.html.haml
+++ b/app/views/projects/repositories/stats.html.haml
@@ -19,7 +19,7 @@
%ol.styled
- @stats.authors[0...50].each do |author|
%li
- = image_tag gravatar_icon(author.email, 16), class: 'avatar s16', alt: ''
+ = image_tag avatar_icon(author.email, 16), class: 'avatar s16', alt: ''
= author.name
%small.light= author.email
.pull-right
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index 06ca5169dff..aefcd833952 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -17,7 +17,7 @@
%p
%p
%span.light Repo size is
- #{@project.repository.size} MB
+ = repository_size
%p
%span.light Created at
#{@project.created_at.stamp('Aug 22, 2013')}
diff --git a/app/views/projects/snippets/_snippet.html.haml b/app/views/projects/snippets/_snippet.html.haml
index fc1c0893b08..6185e35cf6f 100644
--- a/app/views/projects/snippets/_snippet.html.haml
+++ b/app/views/projects/snippets/_snippet.html.haml
@@ -16,6 +16,6 @@
= "##{snippet.id}"
%span
by
- = image_tag gravatar_icon(snippet.author_email), class: "avatar avatar-inline s16"
+ = image_tag avatar_icon(snippet.author_email), class: "avatar avatar-inline s16"
= snippet.author_name
%span.light #{time_ago_in_words(snippet.created_at)} ago
diff --git a/app/views/projects/snippets/show.html.haml b/app/views/projects/snippets/show.html.haml
index 4a07ebf7fd9..ac32f4866b6 100644
--- a/app/views/projects/snippets/show.html.haml
+++ b/app/views/projects/snippets/show.html.haml
@@ -5,7 +5,7 @@
= "##{@snippet.id}"
%span.light
by
- = image_tag gravatar_icon(@snippet.author_email), class: "avatar avatar-inline s16"
+ = image_tag avatar_icon(@snippet.author_email), class: "avatar avatar-inline s16"
= @snippet.author_name
%div= render 'projects/snippets/blob'
%div#notes= render "projects/notes/notes_with_form"
diff --git a/app/views/projects/team_members/_team_member.html.haml b/app/views/projects/team_members/_team_member.html.haml
index 916cf2e7a87..5c93e6e3eae 100644
--- a/app/views/projects/team_members/_team_member.html.haml
+++ b/app/views/projects/team_members/_team_member.html.haml
@@ -9,7 +9,7 @@
&nbsp;
= link_to project_team_member_path(@project, user), confirm: remove_from_project_team_message(@project, user), method: :delete, class: "btn-tiny btn btn-remove", title: 'Remove user from team' do
%i.icon-minus.icon-white
- = image_tag gravatar_icon(user.email, 32), class: "avatar s32"
+ = image_tag avatar_icon(user.email, 32), class: "avatar s32"
%p
%strong= user.name
%span.cgray= user.username
diff --git a/app/views/projects/tree/_submodule_item.html.haml b/app/views/projects/tree/_submodule_item.html.haml
index 26aad16e2c0..badc7d992bd 100644
--- a/app/views/projects/tree/_submodule_item.html.haml
+++ b/app/views/projects/tree/_submodule_item.html.haml
@@ -1,11 +1,10 @@
-- url = submodule_item.url(@ref) rescue ''
-- name = submodule_item.basename
-- return '' unless url
-%tr{ class: "tree-item", url: url }
+%tr{ class: "tree-item" }
%td.tree-item-file-name
= image_tag "submodule.png"
- %span= truncate(name, length: 40)
+ %span
+ = link_to truncate(submodule_item.name, length: 40), submodule_item.submodule_url
+ @
+ %span.monospace #{submodule_item.id[0..10]}
+ %td
+ %td
%td
- %code= submodule_item.id[0..10]
- %td{ colspan: 2 }
- = link_to truncate(url, length: 40), url
diff --git a/app/views/snippets/_snippet.html.haml b/app/views/snippets/_snippet.html.haml
index 9689c9c4d38..8514bc3ddd0 100644
--- a/app/views/snippets/_snippet.html.haml
+++ b/app/views/snippets/_snippet.html.haml
@@ -18,6 +18,6 @@
%span
by
= link_to user_snippets_path(snippet.author) do
- = image_tag gravatar_icon(snippet.author_email), class: "avatar avatar-inline s16", alt: ''
+ = image_tag avatar_icon(snippet.author_email), class: "avatar avatar-inline s16", alt: ''
= snippet.author_name
%span.light #{time_ago_in_words(snippet.created_at)} ago
diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml
index 37f9e7576f5..a680e5eb5b7 100644
--- a/app/views/snippets/show.html.haml
+++ b/app/views/snippets/show.html.haml
@@ -17,7 +17,7 @@
%span.light
by
= link_to user_snippets_path(@snippet.author) do
- = image_tag gravatar_icon(@snippet.author_email), class: "avatar avatar-inline s16"
+ = image_tag avatar_icon(@snippet.author_email), class: "avatar avatar-inline s16"
= @snippet.author_name
.back-link
diff --git a/app/views/snippets/user_index.html.haml b/app/views/snippets/user_index.html.haml
index 49636c3f5f0..1cb53ec6a25 100644
--- a/app/views/snippets/user_index.html.haml
+++ b/app/views/snippets/user_index.html.haml
@@ -1,5 +1,5 @@
%h3.page-title
- = image_tag gravatar_icon(@user.email), class: "avatar s24"
+ = image_tag avatar_icon(@user.email), class: "avatar s24"
= @user.name
%span
\/
diff --git a/app/views/users/_projects.html.haml b/app/views/users/_projects.html.haml
index f1b2c8dd7f7..a61c6ba5b86 100644
--- a/app/views/users/_projects.html.haml
+++ b/app/views/users/_projects.html.haml
@@ -3,9 +3,4 @@
%ul.well-list
- @projects.each do |project|
%li
- = link_to project_path(project), class: dom_class(project) do
- - if project.namespace
- = project.namespace.human_name
- \/
- %strong.well-title
- = truncate(project.name, length: 45)
+ = link_to_project project
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index 743ab0949a1..53a0a9232a4 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -1,13 +1,13 @@
.row
.span8
%h3.page-title
- = image_tag gravatar_icon(@user.email, 90), class: "avatar s90", alt: ''
+ = image_tag avatar_icon(@user.email, 90), class: "avatar s90", alt: ''
= @user.name
- if @user == current_user
.pull-right
= link_to profile_path, class: 'btn' do
%i.icon-edit
- Edit Profile
+ Edit Profile settings
%br
%small #{@user.username}
%br
diff --git a/app/views/users_groups/_users_group.html.haml b/app/views/users_groups/_users_group.html.haml
index 5cdb5bb8c40..5934ff72e8e 100644
--- a/app/views/users_groups/_users_group.html.haml
+++ b/app/views/users_groups/_users_group.html.haml
@@ -1,7 +1,7 @@
- user = member.user
- return unless user
%li{class: "#{dom_class(member)} js-toggle-container", id: dom_id(member)}
- = image_tag gravatar_icon(user.email, 16), class: "avatar s16"
+ = image_tag avatar_icon(user.email, 16), class: "avatar s16"
%strong= user.name
%span.cgray= user.username
- if user == current_user
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 28578eee50a..163af226aaa 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -73,6 +73,7 @@ production: &base
## External issues trackers
issues_tracker:
# redmine:
+ # title: "Redmine"
# ## If not nil, link 'Issues' on project page will be replaced with this
# ## Use placeholders:
# ## :project_id - GitLab project identifier
@@ -93,6 +94,7 @@ production: &base
# new_issue_url: "http://redmine.sample/projects/:issues_tracker_id/issues/new"
#
# jira:
+ # title: "Atlassian Jira"
# project_url: "http://jira.sample/issues/?jql=project=:issues_tracker_id"
# issues_url: "http://jira.sample/browse/:id"
# new_issue_url: "http://jira.sample/secure/CreateIssue.jspa"
@@ -206,6 +208,7 @@ test:
<<: *base
issues_tracker:
redmine:
+ title: "Redmine"
project_url: "http://redmine/projects/:issues_tracker_id"
issues_url: "http://redmine/:project_id/:issues_tracker_id/:id"
new_issue_url: "http://redmine/projects/:issues_tracker_id/issues/new"
diff --git a/config/initializers/devise_async.rb b/config/initializers/devise_async.rb
new file mode 100644
index 00000000000..05a1852cdbd
--- /dev/null
+++ b/config/initializers/devise_async.rb
@@ -0,0 +1 @@
+Devise::Async.backend = :sidekiq
diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb
index 52a099c3e16..501cad4a838 100644
--- a/config/initializers/session_store.rb
+++ b/config/initializers/session_store.rb
@@ -1,11 +1,9 @@
# Be sure to restart your server when you modify this file.
-Gitlab::Application.config.session_store :cookie_store, key: '_gitlab_session',
- secure: Gitlab::Application.config.force_ssl,
- httponly: true,
- path: (Rails.application.config.relative_url_root.nil?) ? '/' : Rails.application.config.relative_url_root
-
-# Use the database for sessions instead of the cookie-based default,
-# which shouldn't be used to store highly confidential information
-# (create the session table with "rails generate session_migration")
-# Gitlab::Application.config.session_store :active_record_store
+Gitlab::Application.config.session_store(
+ :redis_store, # Using the cookie_store would enable session replay attacks.
+ key: '_gitlab_session',
+ secure: Gitlab::Application.config.force_ssl,
+ httponly: true,
+ path: (Rails.application.config.relative_url_root.nil?) ? '/' : Rails.application.config.relative_url_root
+)
diff --git a/config/routes.rb b/config/routes.rb
index 612a7327ec5..6d7358608ea 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -99,19 +99,21 @@ Gitlab::Application.routes.draw do
#
resource :profile, only: [:show, :update] do
member do
- get :account
get :history
- get :token
get :design
- put :update_password
put :reset_private_token
put :update_username
end
scope module: :profiles do
+ resource :account, only: [:show, :update]
resource :notifications, only: [:show, :update]
- resource :password, only: [:new, :create]
+ resource :password, only: [:new, :create, :edit, :update] do
+ member do
+ put :reset
+ end
+ end
resources :keys
resources :groups, only: [:index] do
member do
diff --git a/db/migrate/20131005191208_add_avatar_to_users.rb b/db/migrate/20131005191208_add_avatar_to_users.rb
new file mode 100644
index 00000000000..7b4de37ad72
--- /dev/null
+++ b/db/migrate/20131005191208_add_avatar_to_users.rb
@@ -0,0 +1,5 @@
+class AddAvatarToUsers < ActiveRecord::Migration
+ def change
+ add_column :users, :avatar, :string
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 713d9f733d6..b3bc31c76dd 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20130926081215) do
+ActiveRecord::Schema.define(:version => 20131005191208) do
create_table "deploy_keys_projects", :force => true do |t|
t.integer "deploy_key_id", :null => false
@@ -283,6 +283,7 @@ ActiveRecord::Schema.define(:version => 20130926081215) do
t.integer "notification_level", :default => 1, :null => false
t.datetime "password_expires_at"
t.integer "created_by_id"
+ t.string "avatar"
end
add_index "users", ["admin"], :name => "index_users_on_admin"
diff --git a/doc/api/projects.md b/doc/api/projects.md
index 0f73fb434da..af9e682c24f 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -244,6 +244,18 @@ Parameters:
+ `public` (optional)
+## Remove project
+
+Removes project with all resources(issues, merge requests etc)
+
+```
+DELETE /projects/:id
+```
+
+Parameters:
+
++ `id` (required) - The ID of a project
+
## Team members
diff --git a/doc/api/repositories.md b/doc/api/repositories.md
index cb0626972e5..2769c22d6aa 100644
--- a/doc/api/repositories.md
+++ b/doc/api/repositories.md
@@ -356,3 +356,16 @@ Parameters:
+ `id` (required) - The ID of a project
+ `sha` (required) - The commit or branch name
+ `filepath` (required) - The path the file
+
+
+## Get file archive
+
+Get a an archive of the repository
+
+```
+GET /projects/:id/repository/archive
+```
+
+Parameters:
++ `id` (required) - The ID of a project
++ `sha` (optional) - The commit sha to download defaults to the tip of the default branch \ No newline at end of file
diff --git a/doc/api/system_hooks.md b/doc/api/system_hooks.md
index 5eeb3652d57..355ce31c126 100644
--- a/doc/api/system_hooks.md
+++ b/doc/api/system_hooks.md
@@ -1,5 +1,7 @@
All methods require admin authorization.
+The url endpoint of the system hooks can be configured in [the admin area under hooks](/admin/hooks).
+
## List system hooks
Get list of system hooks
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 933799776bd..7c6a2db9734 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -63,7 +63,7 @@ Make sure you have the right version of Python installed.
python --version
# If it's Python 3 you might need to install Python 2 separately
- sudo apt-get install python2.7
+ sudo apt-get install -y python2.7
# Make sure you can access Python via python2
python2 --version
@@ -72,7 +72,7 @@ Make sure you have the right version of Python installed.
sudo ln -s /usr/bin/python /usr/bin/python2
# For reStructuredText markup language support install required package:
- sudo apt-get install python-docutils
+ sudo apt-get install -y python-docutils
**Note:** In order to receive mail notifications, make sure to install a
mail server. By default, Debian is shipped with exim4 whereas Ubuntu
diff --git a/features/profile/profile.feature b/features/profile/profile.feature
index c74b0993fb3..6198fd2b306 100644
--- a/features/profile/profile.feature
+++ b/features/profile/profile.feature
@@ -12,26 +12,31 @@ Feature: Profile
And I should see new contact info
Scenario: I change my password without old one
- Given I visit profile account page
+ Given I visit profile password page
When I try change my password w/o old one
Then I should see a missing password error message
- And I should be redirected to account page
+ And I should be redirected to password page
Scenario: I change my password
- Given I visit profile account page
+ Given I visit profile password page
Then I change my password
And I should be redirected to sign in page
+ Scenario: I edit my avatar
+ Given I visit profile page
+ Then I change my avatar
+ And I should see new avatar
+
Scenario: My password is expired
Given my password is expired
And I am not an ldap user
- And I visit profile account page
+ Given I visit profile password page
Then I redirected to expired password page
And I submit new password
And I redirected to sign in page
Scenario: I unsuccessfully change my password
- Given I visit profile account page
+ Given I visit profile password page
When I unsuccessfully change my password
Then I should see a password error message
diff --git a/features/project/source/markdown_render.feature b/features/project/source/markdown_render.feature
new file mode 100644
index 00000000000..a7a9cee7b0d
--- /dev/null
+++ b/features/project/source/markdown_render.feature
@@ -0,0 +1,75 @@
+Feature: Project markdown render
+ Background:
+ Given I sign in as a user
+ And I own project "Delta"
+ Given I visit project source page
+
+ Scenario: I browse files from master branch
+ Then I should see files from repository in master
+ And I should see rendered README which contains correct links
+ And I click on Gitlab API in README
+ Then I should see correct document rendered
+
+ Scenario: I view README in master branch
+ Then I should see files from repository in master
+ And I should see rendered README which contains correct links
+ And I click on Rake tasks in README
+ Then I should see correct directory rendered
+
+ Scenario: I navigate to doc directory to view documentation in master
+ And I navigate to the doc/api/README
+ And I see correct file rendered
+ And I click on users in doc/api/README
+ Then I should see the correct document file
+
+ Scenario: I navigate to doc directory to view user doc in master
+ And I navigate to the doc/api/README
+ And I see correct file rendered
+ And I click on raketasks in doc/api/README
+ Then I should see correct directory rendered
+
+ Scenario: I browse files from markdown branch
+ When I visit markdown branch
+ Then I should see files from repository in markdown branch
+ And I should see rendered README which contains correct links
+ And I click on Gitlab API in README
+ Then I should see correct document rendered for markdown branch
+
+ Scenario: I browse directory from markdown branch
+ When I visit markdown branch
+ Then I should see files from repository in markdown branch
+ And I should see rendered README which contains correct links
+ And I click on Rake tasks in README
+ Then I should see correct directory rendered for markdown branch
+
+ Scenario: I navigate to doc directory to view documentation in markdown branch
+ When I visit markdown branch
+ And I navigate to the doc/api/README
+ And I see correct file rendered in markdown branch
+ And I click on users in doc/api/README
+ Then I should see the users document file in markdown branch
+
+ Scenario: I navigate to doc directory to view user doc in markdown branch
+ When I visit markdown branch
+ And I navigate to the doc/api/README
+ And I see correct file rendered in markdown branch
+ And I click on raketasks in doc/api/README
+ Then I should see correct directory rendered for markdown branch
+
+ Scenario: I create a wiki page with different links
+ Given I go to wiki page
+ And I add various links to the wiki page
+ Then Wiki page should have added links
+ And I click on test link
+ Then I see new wiki page named test
+ When I go back to wiki page home
+ And I click on GitLab API doc link
+ Then I see Gitlab API document
+ When I go back to wiki page home
+ And I click on Rake tasks link
+ Then I see Rake tasks directory
+
+ Scenario: I visit the help page with markdown
+ Given I visit to the help page
+ And I select a page with markdown
+ Then I should see a help page with markdown \ No newline at end of file
diff --git a/features/steps/profile/profile.rb b/features/steps/profile/profile.rb
index 5b2a6321265..753e2c19bcb 100644
--- a/features/steps/profile/profile.rb
+++ b/features/steps/profile/profile.rb
@@ -3,9 +3,7 @@ class Profile < Spinach::FeatureSteps
include SharedPaths
step 'I should see my profile info' do
- page.should have_content "Profile"
- page.should have_content @user.name
- page.should have_content @user.email
+ page.should have_content "Profile settings"
end
step 'I change my contact info' do
@@ -22,6 +20,17 @@ class Profile < Spinach::FeatureSteps
@user.twitter.should == 'testtwitter'
end
+ step 'I change my avatar' do
+ attach_file(:user_avatar, File.join(Rails.root, 'public', 'gitlab_logo.png'))
+ click_button "Save changes"
+ @user.reload
+ end
+
+ step 'I should see new avatar' do
+ @user.avatar.should be_instance_of AttachmentUploader
+ @user.avatar.url.should == "/uploads/user/avatar/#{ @user.id }/gitlab_logo.png"
+ end
+
step 'I try change my password w/o old one' do
within '.update-password' do
fill_in "user_password", with: "222333"
@@ -124,8 +133,12 @@ class Profile < Spinach::FeatureSteps
current_path.should == new_user_session_path
end
+ step 'I should be redirected to password page' do
+ current_path.should == edit_profile_password_path
+ end
+
step 'I should be redirected to account page' do
- current_path.should == account_profile_path
+ current_path.should == profile_account_path
end
step 'I click on my profile picture' do
diff --git a/features/steps/project/project_markdown_render.rb b/features/steps/project/project_markdown_render.rb
new file mode 100644
index 00000000000..951c831838d
--- /dev/null
+++ b/features/steps/project/project_markdown_render.rb
@@ -0,0 +1,165 @@
+class Spinach::Features::ProjectMarkdownRender < Spinach::FeatureSteps
+ include SharedAuthentication
+ include SharedPaths
+
+ And 'I own project "Delta"' do
+ @project = Project.find_by_name "Delta"
+ @project ||= create(:project_with_code, name: "Delta", namespace: @user.namespace)
+ @project.team << [@user, :master]
+ end
+
+ Then 'I should see files from repository in master' do
+ current_path.should == project_tree_path(@project, "master")
+ page.should have_content "Gemfile"
+ page.should have_content "app"
+ page.should have_content "README"
+ end
+
+ And 'I should see rendered README which contains correct links' do
+ page.should have_content "Welcome to GitLab GitLab is a free project and repository management application"
+ page.should have_link "GitLab API doc"
+ page.should have_link "GitLab API website"
+ page.should have_link "Rake tasks"
+ page.should have_link "backup and restore procedure"
+ end
+
+ And 'I click on Gitlab API in README' do
+ click_link "GitLab API doc"
+ end
+
+ Then 'I should see correct document rendered' do
+ current_path.should == project_blob_path(@project, "master/doc/api/README.md")
+ page.should have_content "All API requests require authentication"
+ end
+
+ And 'I click on Rake tasks in README' do
+ click_link "Rake tasks"
+ end
+
+ Then 'I should see correct directory rendered' do
+ current_path.should == project_tree_path(@project, "master/doc/raketasks")
+ page.should have_content "backup_restore.md"
+ page.should have_content "maintenance.md"
+ end
+
+ And 'I navigate to the doc/api/README' do
+ click_link "doc"
+ click_link "api"
+ click_link "README.md"
+ end
+
+ And 'I see correct file rendered' do
+ current_path.should == project_blob_path(@project, "master/doc/api/README.md")
+ page.should have_content "Contents"
+ page.should have_link "Users"
+ page.should have_link "Rake tasks"
+ end
+
+ And 'I click on users in doc/api/README' do
+ click_link "Users"
+ end
+
+ Then 'I should see the correct document file' do
+ current_path.should == project_blob_path(@project, "master/doc/api/users.md")
+ page.should have_content "Get a list of users."
+ end
+
+ And 'I click on raketasks in doc/api/README' do
+ click_link "Rake tasks"
+ end
+
+ When 'I visit markdown branch' do
+ visit project_tree_path(@project, "markdown")
+ end
+
+ Then 'I should see files from repository in markdown branch' do
+ current_path.should == project_tree_path(@project, "markdown")
+ page.should have_content "Gemfile"
+ page.should have_content "app"
+ page.should have_content "README"
+ end
+
+ And 'I see correct file rendered in markdown branch' do
+ current_path.should == project_blob_path(@project, "markdown/doc/api/README.md")
+ page.should have_content "Contents"
+ page.should have_link "Users"
+ page.should have_link "Rake tasks"
+ end
+
+ Then 'I should see correct document rendered for markdown branch' do
+ current_path.should == project_blob_path(@project, "markdown/doc/api/README.md")
+ page.should have_content "All API requests require authentication"
+ end
+
+ Then 'I should see correct directory rendered for markdown branch' do
+ current_path.should == project_tree_path(@project, "markdown/doc/raketasks")
+ page.should have_content "backup_restore.md"
+ page.should have_content "maintenance.md"
+ end
+
+ Then 'I should see the users document file in markdown branch' do
+ current_path.should == project_blob_path(@project, "markdown/doc/api/users.md")
+ page.should have_content "Get a list of users."
+ end
+
+ Given 'I go to wiki page' do
+ click_link "Wiki"
+ current_path.should == project_wiki_path(@project, "home")
+ end
+
+ And 'I add various links to the wiki page' do
+ fill_in "wiki[content]", with: "[test](test)\n[GitLab API doc](doc/api/README.md)\n[Rake tasks](doc/raketasks)\n"
+ fill_in "wiki[message]", with: "Adding links to wiki"
+ click_button "Create page"
+ end
+
+ Then 'Wiki page should have added links' do
+ current_path.should == project_wiki_path(@project, "home")
+ page.should have_content "test GitLab API doc Rake tasks"
+ end
+
+ And 'I click on test link' do
+ click_link "test"
+ end
+
+ Then 'I see new wiki page named test' do
+ current_path.should == project_wiki_path(@project, "test")
+ page.should have_content "Editing page"
+ end
+
+ When 'I go back to wiki page home' do
+ visit project_wiki_path(@project, "home")
+ current_path.should == project_wiki_path(@project, "home")
+ end
+
+ And 'I click on GitLab API doc link' do
+ click_link "GitLab API"
+ end
+
+ Then 'I see Gitlab API document' do
+ current_path.should == project_blob_path(@project, "master/doc/api/README.md")
+ page.should have_content "Status codes"
+ end
+
+ And 'I click on Rake tasks link' do
+ click_link "Rake tasks"
+ end
+
+ Then 'I see Rake tasks directory' do
+ current_path.should == project_tree_path(@project, "master/doc/raketasks")
+ page.should have_content "backup_restore.md"
+ page.should have_content "maintenance.md"
+ end
+
+ Given 'I visit to the help page' do
+ visit help_path
+ end
+
+ And 'I select a page with markdown' do
+ click_link "Rake Tasks"
+ end
+
+ Then 'I should see a help page with markdown' do
+ page.should have_content "GitLab provides some specific rake tasks to enable special features or perform maintenance tasks"
+ end
+end \ No newline at end of file
diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb
index c30eccce1c5..156fa5bab4e 100644
--- a/features/steps/shared/paths.rb
+++ b/features/steps/shared/paths.rb
@@ -65,8 +65,12 @@ module SharedPaths
visit profile_path
end
+ step 'I visit profile password page' do
+ visit edit_profile_password_path
+ end
+
step 'I visit profile account page' do
- visit account_profile_path
+ visit profile_account_path
end
step 'I visit profile SSH keys page' do
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index 265417fd6bc..290b78d8017 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -66,7 +66,6 @@ module API
present group, with: Entities::GroupDetail
end
-
# Remove group
#
# Parameters:
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index cf357b23c40..221f1f1e23c 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -129,6 +129,16 @@ module API
end
end
+ # Remove project
+ #
+ # Parameters:
+ # id (required) - The ID of a project
+ # Example Request:
+ # DELETE /projects/:id
+ delete ":id" do
+ authorize! :remove_project, user_project
+ user_project.destroy
+ end
# Mark this project as forked from another
#
diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb
index 1a911eae2bb..c9422fdb165 100644
--- a/lib/api/repositories.rb
+++ b/lib/api/repositories.rb
@@ -144,7 +144,7 @@ module API
trees = []
%w(trees blobs submodules).each do |type|
- trees += tree.send(type).map { |t| { name: t.name, type: type.singularize, mode: t.mode, id: t.id } }
+ trees += tree.send(type).map { |t| {name: t.name, type: type.singularize, mode: t.mode, id: t.id} }
end
trees
@@ -176,6 +176,34 @@ module API
content_type blob.mime_type
present blob.data
end
+
+ # Get a an archive of the repository
+ #
+ # Parameters:
+ # id (required) - The ID of a project
+ # sha (optional) - the commit sha to download defaults to the tip of the default branch
+ # Example Request:
+ # GET /projects/:id/repository/archive
+ get ":id/repository/archive" do
+ authorize! :download_code, user_project
+ repo = user_project.repository
+ ref = params[:sha]
+ storage_path = Rails.root.join("tmp", "repositories")
+
+ file_path = repo.archive_repo(ref, storage_path)
+ if file_path && File.exists?(file_path)
+ data = File.open(file_path, 'rb').read
+
+ header "Content-Disposition:", " infile; filename=\"#{File.basename(file_path)}\""
+ content_type 'application/x-gzip'
+
+ env['api.format'] = :binary
+
+ present data
+ else
+ not_found!
+ end
+ end
end
end
end
diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb
index c5e3d049fd7..252201f11be 100644
--- a/lib/backup/repository.rb
+++ b/lib/backup/repository.rb
@@ -28,7 +28,9 @@ module Backup
if File.exists?(path_to_repo(wiki))
print " * #{wiki.path_with_namespace} ... "
- if system("cd #{path_to_repo(wiki)} > /dev/null 2>&1 && git bundle create #{path_to_bundle(wiki)} --all > /dev/null 2>&1")
+ if wiki.empty?
+ puts " [SKIPPED]".cyan
+ elsif system("cd #{path_to_repo(wiki)} > /dev/null 2>&1 && git bundle create #{path_to_bundle(wiki)} --all > /dev/null 2>&1")
puts " [DONE]".green
else
puts " [FAILED]".red
diff --git a/lib/redcarpet/render/gitlab_html.rb b/lib/redcarpet/render/gitlab_html.rb
index d9c2d3b626d..b84c005524f 100644
--- a/lib/redcarpet/render/gitlab_html.rb
+++ b/lib/redcarpet/render/gitlab_html.rb
@@ -6,6 +6,8 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML
def initialize(template, options = {})
@template = template
@project = @template.instance_variable_get("@project")
+ @ref = @template.instance_variable_get("@ref")
+ @request_path = @template.instance_variable_get("@path")
super options
end
@@ -32,7 +34,19 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML
h.link_to_gfm(content, link, title: title)
end
+ def preprocess(full_document)
+ if @project
+ h.create_relative_links(full_document, @project.path_with_namespace, @ref, @request_path, is_wiki?)
+ else
+ full_document
+ end
+ end
+
def postprocess(full_document)
h.gfm(full_document)
end
+
+ def is_wiki?
+ @template.instance_variable_get("@wiki")
+ end
end
diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab
index 6aff7b5a8f9..f157d71b14f 100755
--- a/lib/support/init.d/gitlab
+++ b/lib/support/init.d/gitlab
@@ -218,9 +218,7 @@ reload(){
kill -USR2 "$wpid"
echo "Done."
echo "Restarting GitLab Sidekiq since it isn't capable of reloading its config..."
- RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:stop
- echo "Starting Sidekiq..."
- RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:start
+ RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:restart
# Waiting 2 seconds for sidekiq to write it.
sleep 2
status
diff --git a/lib/tasks/sidekiq.rake b/lib/tasks/sidekiq.rake
index d0e9dfe46a1..ba79b6e035d 100644
--- a/lib/tasks/sidekiq.rake
+++ b/lib/tasks/sidekiq.rake
@@ -5,16 +5,28 @@ namespace :sidekiq do
end
desc "GITLAB | Start sidekiq"
- task :start do
- system "nohup bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,gitlab_shell,common,default -e #{Rails.env} -P #{pidfile} >> #{Rails.root.join("log", "sidekiq.log")} 2>&1 &"
+ task :start => :restart
+
+ desc 'GitLab | Restart sidekiq'
+ task :restart do
+ if File.exist?(pidfile)
+ puts 'Shutting down existing sidekiq process.'
+ Rake::Task['sidekiq:stop'].invoke
+ puts 'Starting new sidekiq process.'
+ end
+ system "bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,gitlab_shell,common,default -e #{Rails.env} -P #{pidfile} -d -L #{log_file} >> #{log_file} 2>&1"
end
desc "GITLAB | Start sidekiq with launchd on Mac OS X"
task :launchd do
- system "bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,gitlab_shell,common,default -e #{Rails.env} -P #{pidfile} >> #{Rails.root.join("log", "sidekiq.log")} 2>&1"
+ system "bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,gitlab_shell,common,default -e #{Rails.env} -P #{pidfile} >> #{log_file} 2>&1"
end
def pidfile
Rails.root.join("tmp", "pids", "sidekiq.pid")
end
+
+ def log_file
+ Rails.root.join("log", "sidekiq.log")
+ end
end
diff --git a/spec/features/notes_on_merge_requests_spec.rb b/spec/features/notes_on_merge_requests_spec.rb
index ba580d9484d..d29bed4dea7 100644
--- a/spec/features/notes_on_merge_requests_spec.rb
+++ b/spec/features/notes_on_merge_requests_spec.rb
@@ -216,12 +216,6 @@ describe "On a merge request diff", js: true, focus: true do
end
end
- it do
- within("tr[id='342e16cbbd482ac2047dc679b2749d248cc1428f_18_17'] + .js-temp-notes-holder") do
- should have_no_css(".js-temp-notes-holder")
- end
- end
-
it 'should be added as discussion' do
should have_content("Another comment on line 17")
should have_css(".notes_holder")
diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb
index 80c9f5d7f14..b67ce3c67f1 100644
--- a/spec/features/profile_spec.rb
+++ b/spec/features/profile_spec.rb
@@ -12,7 +12,7 @@ describe "Profile account page" do
describe "when signup is enabled" do
before do
Gitlab.config.gitlab.stub(:signup_enabled).and_return(true)
- visit account_profile_path
+ visit profile_account_path
end
it { page.should have_content("Remove account") }
@@ -26,12 +26,12 @@ describe "Profile account page" do
describe "when signup is disabled" do
before do
Gitlab.config.gitlab.stub(:signup_enabled).and_return(false)
- visit account_profile_path
+ visit profile_account_path
end
it "should not have option to remove account" do
page.should_not have_content("Remove account")
- current_path.should == account_profile_path
+ current_path.should == profile_account_path
end
end
end
diff --git a/spec/features/security/profile_access_spec.rb b/spec/features/security/profile_access_spec.rb
index 7754b28347a..078c257538f 100644
--- a/spec/features/security/profile_access_spec.rb
+++ b/spec/features/security/profile_access_spec.rb
@@ -29,7 +29,7 @@ describe "Users Security" do
end
describe "GET /profile/account" do
- subject { account_profile_path }
+ subject { profile_account_path }
it { should be_allowed_for @u1 }
it { should be_allowed_for :admin }
diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb
index 229f49659cf..0d066be5b45 100644
--- a/spec/helpers/application_helper_spec.rb
+++ b/spec/helpers/application_helper_spec.rb
@@ -38,6 +38,24 @@ describe ApplicationHelper do
current_action?(:baz, :bar, :foo).should be_true
end
end
+
+ describe "avatar_icon" do
+ avatar_file_path = File.join(Rails.root, 'public', 'gitlab_logo.png')
+
+ it "should return an url for the avatar" do
+ user = create(:user)
+ user.avatar = File.open(avatar_file_path)
+ user.save!
+ avatar_icon(user.email).to_s.should == "/uploads/user/avatar/#{ user.id }/gitlab_logo.png"
+ end
+
+ it "should call gravatar_icon when no avatar is present" do
+ user = create(:user)
+ user.save!
+ stub!(:gravatar_icon).and_return('gravatar_method_called')
+ avatar_icon(user.email).to_s.should == "gravatar_method_called"
+ end
+ end
describe "gravatar_icon" do
let(:user_email) { 'user@email.com' }
diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb
index d49247accc2..a0bbc026421 100644
--- a/spec/helpers/gitlab_markdown_helper_spec.rb
+++ b/spec/helpers/gitlab_markdown_helper_spec.rb
@@ -406,6 +406,30 @@ describe GitlabMarkdownHelper do
it "should generate absolute urls for emoji" do
markdown(":smile:").should include("src=\"#{url_to_image("emoji/smile")}")
end
+
+ it "should handle relative urls for a file in master" do
+ actual = "[GitLab API doc](doc/api/README.md)\n"
+ expected = "<p><a href=\"/#{project.path_with_namespace}/blob/master/doc/api/README.md\">GitLab API doc</a></p>\n"
+ markdown(actual).should match(expected)
+ end
+
+ it "should handle relative urls for a directory in master" do
+ actual = "[GitLab API doc](doc/api)\n"
+ expected = "<p><a href=\"/#{project.path_with_namespace}/tree/master/doc/api\">GitLab API doc</a></p>\n"
+ markdown(actual).should match(expected)
+ end
+
+ it "should handle absolute urls" do
+ actual = "[GitLab](https://www.gitlab.com)\n"
+ expected = "<p><a href=\"https://www.gitlab.com\">GitLab</a></p>\n"
+ markdown(actual).should match(expected)
+ end
+
+ it "should handle wiki urls" do
+ actual = "[Link](test/link)\n"
+ expected = "<p><a href=\"/#{project.path_with_namespace}/wikis/test/link\">Link</a></p>\n"
+ markdown(actual).should match(expected)
+ end
end
describe "#render_wiki_content" do
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
new file mode 100644
index 00000000000..62f88dd522b
--- /dev/null
+++ b/spec/helpers/projects_helper_spec.rb
@@ -0,0 +1,11 @@
+require 'spec_helper'
+
+describe ProjectsHelper do
+ describe '#project_issues_trackers' do
+ it "returns the correct issues trackers available" do
+ project_issues_trackers.should ==
+ "<option value=\"redmine\">Redmine</option>\n" \
+ "<option value=\"gitlab\">GitLab</option>"
+ end
+ end
+end
diff --git a/spec/lib/gitlab/satellite/merge_action_spec.rb b/spec/lib/gitlab/satellite/merge_action_spec.rb
index 3be14383e06..e40ff73b7f0 100644
--- a/spec/lib/gitlab/satellite/merge_action_spec.rb
+++ b/spec/lib/gitlab/satellite/merge_action_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe 'Gitlab::Satellite::MergeAction' do
before(:each) do
# TestEnv.init(mailer: false, init_repos: true, repos: true)
- @master = ['master', 'bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a']
+ @master = ['master', 'b1e6a9dbf1c85e6616497a5e7bad9143a4bd0828']
@one_after_stable = ['stable', '6ea87c47f0f8a24ae031c3fff17bc913889ecd00'] #this commit sha is one after stable
@wiki_branch = ['wiki', '635d3e09b72232b6e92a38de6cc184147e5bcb41'] #this is the commit sha where the wiki branch goes off from master
@conflicting_metior = ['metior', '313d96e42b313a0af5ab50fa233bf43e27118b3f'] #this branch conflicts with the wiki branch
diff --git a/spec/models/gollum_wiki_spec.rb b/spec/models/gollum_wiki_spec.rb
index aa850dfd0a3..9e07d9ee191 100644
--- a/spec/models/gollum_wiki_spec.rb
+++ b/spec/models/gollum_wiki_spec.rb
@@ -86,6 +86,27 @@ describe GollumWiki do
end
end
+ describe "#empty?" do
+ context "when the wiki repository is empty" do
+ before do
+ Gitlab::Shell.any_instance.stub(:add_repository) do
+ create_temp_repo("#{Rails.root}/tmp/test-git-base-path/non-existant.wiki.git")
+ end
+ project.stub(:path_with_namespace).and_return("non-existant")
+ end
+
+ its(:empty?) { should be_true }
+ end
+
+ context "when the wiki has pages" do
+ before do
+ create_page("index", "This is an awesome new Gollum Wiki")
+ end
+
+ its(:empty?) { should be_false }
+ end
+ end
+
describe "#pages" do
before do
create_page("index", "This is an awesome new Gollum Wiki")
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 47ae760a7ed..dcaee39fa68 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -132,17 +132,17 @@ describe Project do
it "should close merge request if last commit from source branch was pushed to target branch" do
@merge_request.reloaded_commits
- @merge_request.last_commit.id.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a"
- project.update_merge_requests("8716fc78f3c65bbf7bcf7b574febd583bc5d2812", "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a", "refs/heads/stable", @key.user)
+ @merge_request.last_commit.id.should == "b1e6a9dbf1c85e6616497a5e7bad9143a4bd0828"
+ project.update_merge_requests("8716fc78f3c65bbf7bcf7b574febd583bc5d2812", "b1e6a9dbf1c85e6616497a5e7bad9143a4bd0828", "refs/heads/stable", @key.user)
@merge_request.reload
@merge_request.merged?.should be_true
end
it "should update merge request commits with new one if pushed to source branch" do
@merge_request.last_commit.should == nil
- project.update_merge_requests("8716fc78f3c65bbf7bcf7b574febd583bc5d2812", "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a", "refs/heads/master", @key.user)
+ project.update_merge_requests("8716fc78f3c65bbf7bcf7b574febd583bc5d2812", "b1e6a9dbf1c85e6616497a5e7bad9143a4bd0828", "refs/heads/master", @key.user)
@merge_request.reload
- @merge_request.last_commit.id.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a"
+ @merge_request.last_commit.id.should == "b1e6a9dbf1c85e6616497a5e7bad9143a4bd0828"
end
end
diff --git a/spec/observers/users_project_observer_spec.rb b/spec/observers/users_project_observer_spec.rb
index e33d8cc50fd..e7c624fce59 100644
--- a/spec/observers/users_project_observer_spec.rb
+++ b/spec/observers/users_project_observer_spec.rb
@@ -65,4 +65,30 @@ describe UsersProjectObserver do
@users_project.destroy
end
end
-end
+
+ describe "#after_create" do
+ context 'wiki_enabled creates repository directory' do
+ context 'wiki_enabled true creates wiki repository directory' do
+ before do
+ @project = create(:project, wiki_enabled: true)
+ @path = GollumWiki.new(@project, user).send(:path_to_repo)
+ end
+
+ after do
+ FileUtils.rm_rf(@path)
+ end
+
+ it { File.exists?(@path).should be_true }
+ end
+
+ context 'wiki_enabled false does not create wiki repository directory' do
+ before do
+ @project = create(:project, wiki_enabled: false)
+ @path = GollumWiki.new(@project, user).send(:path_to_repo)
+ end
+
+ it { File.exists?(@path).should be_false }
+ end
+ end
+ end
+end \ No newline at end of file
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index b8c0b6f33ed..bf4a1749418 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -730,4 +730,42 @@ describe API::API do
end
end
end
+
+ describe "DELETE /projects/:id" do
+ context "when authenticated as user" do
+ it "should remove project" do
+ delete api("/projects/#{project.id}", user)
+ response.status.should == 200
+ end
+
+ it "should not remove a project if not an owner" do
+ user3 = create(:user)
+ project.team << [user3, :developer]
+ delete api("/projects/#{project.id}", user3)
+ response.status.should == 403
+ end
+
+ it "should not remove a non existing project" do
+ delete api("/projects/1328", user)
+ response.status.should == 404
+ end
+
+ it "should not remove a project not attached to user" do
+ delete api("/projects/#{project.id}", user2)
+ response.status.should == 404
+ end
+ end
+
+ context "when authenticated as admin" do
+ it "should remove any existing project" do
+ delete api("/projects/#{project.id}", admin)
+ response.status.should == 200
+ end
+
+ it "should not remove a non existing project" do
+ delete api("/projects/1328", admin)
+ response.status.should == 404
+ end
+ end
+ end
end
diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb
index 2e509ea2933..9649c4d09c8 100644
--- a/spec/requests/api/repositories_spec.rb
+++ b/spec/requests/api/repositories_spec.rb
@@ -225,4 +225,16 @@ describe API::API do
end
end
+ describe "GET /projects/:id/repository/archive/:sha" do
+ it "should get the archive" do
+ get api("/projects/#{project.id}/repository/archive", user)
+ response.status.should == 200
+ response.content_type.should == 'application/x-gzip'
+ end
+
+ it "should return 404 for invalid sha" do
+ get api("/projects/#{project.id}/repository/archive/?sha=xxx", user)
+ response.status.should == 404
+ end
+ end
end
diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb
index 946ef7c28cb..1b1d19d26b1 100644
--- a/spec/routing/routing_spec.rb
+++ b/spec/routing/routing_spec.rb
@@ -128,7 +128,7 @@ end
# profile_update PUT /profile/update(.:format) profile#update
describe ProfilesController, "routing" do
it "to #account" do
- get("/profile/account").should route_to('profiles#account')
+ get("/profile/account").should route_to('profiles/accounts#show')
end
it "to #history" do
diff --git a/spec/seed_project.tar.gz b/spec/seed_project.tar.gz
index 3ffafed18d0..7abb51ebdfd 100644
--- a/spec/seed_project.tar.gz
+++ b/spec/seed_project.tar.gz
Binary files differ
diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb
index e3c25fa0469..2870f59195a 100644
--- a/spec/services/git_push_service_spec.rb
+++ b/spec/services/git_push_service_spec.rb
@@ -26,6 +26,7 @@ describe GitPushService do
it { should include(ref: @ref) }
it { should include(user_id: user.id) }
it { should include(user_name: user.name) }
+ it { should include(project_id: project.id) }
context "with repository data" do
subject { @push_data[:repository] }