Commit 0b9517e5 authored by Douwe Maan's avatar Douwe Maan

Merge branch 'master' into fix-mirror

parents ff1f58ec aa6ac83e
......@@ -9,7 +9,7 @@ variables:
MYSQL_ALLOW_EMPTY_PASSWORD: "1"
before_script:
- ./scripts/prepare_build.sh
- source ./scripts/prepare_build.sh
- ruby -v
- which ruby
- gem install bundler --no-ri --no-rdoc
......@@ -17,7 +17,7 @@ before_script:
- touch log/application.log
- touch log/test.log
- bundle install --without postgres production --jobs $(nproc) "${FLAGS[@]}"
- bundle exec rake db:reset db:create RAILS_ENV=test
- RAILS_ENV=test bundle exec rake db:drop db:create db:schema:load db:migrate
spec:feature:
script:
......@@ -127,7 +127,7 @@ flay:
- mysql
bundler:audit:
script:
script:
- "bundle exec bundle-audit update"
- "bundle exec bundle-audit check"
tags:
......
Please view this file on the master branch, on stable branches it's out of date.
v 8.5.0 (unreleased)
- Add "visibility" flag to GET /projects api endpoint
- Ignore binary files in code search to prevent Error 500 (Stan Hu)
- Upgrade gitlab_git to 7.2.23 to fix commit message mentions in first branch push
- New UI for pagination
- Fix diff comments loaded by AJAX to load comment with diff in discussion tab
- Whitelist raw "abbr" elements when parsing Markdown (Benedict Etzel)
- Don't vendor minified JS
v 8.4.0 (unreleased)
- Hide issues settings when issues are disabled (Hannes Rosenögger)
v 8.4.0
- Allow LDAP users to change their email if it was not set by the LDAP server
- Ensure Gravatar host looks like an actual host
- Consider re-assign as a mention from a notification point of view
- Add pagination headers to already paginated API resources
- Properly generate diff of orphan commits, like the first commit in a repository
- Improve the consistency of commit titles, branch names, tag names, issue/MR titles, on their respective project pages
- Autocomplete data is now always loaded, instead of when focusing a comment text area (Yorick Peterse)
- Improved performance of finding issues for an entire group (Yorick Peterse)
- Added custom application performance measuring system powered by InfluxDB (Yorick Peterse)
- Autocomplete data is now always loaded, instead of when focusing a comment text area
- Improved performance of finding issues for an entire group
- Added custom application performance measuring system powered by InfluxDB
- Add syntax highlighting to diffs
- Gracefully handle invalid UTF-8 sequences in Markdown links (Stan Hu)
- Bump fog to 1.36.0 (Stan Hu)
- Add user's last used IP addresses to admin page (Stan Hu)
- Add housekeeping function to project settings page
......@@ -62,10 +77,19 @@ v 8.4.0 (unreleased)
- Autosize Markdown textareas
- Import GitHub wiki into GitLab
- Add reporters ability to download and browse build artifacts (Andrew Johnson)
- Autofill referring url in message box when reporting user abuse.
- Remove leading comma on award emoji when the user is the first to award the emoji (Zeger-Jan van de Weg)
- Add build artifacts browser
- Improve UX in builds artifacts browser
- Increase default size of `data` column in `events` table when using MySQL
- Expose button to CI Lint tool on project builds page
- Fix: Creator should be added as a master of the project on creation
- Added X-GitLab-... headers to emails from CI and Email On Push services (Anton Baklanov)
- Add IP check against DNSBLs at account sign-up
- Added cache:key to .gitlab-ci.yml allowing to fine tune the caching
v 8.3.4
- Use gitlab-workhorse 0.5.4 (fixes API routing bug)
- Add build artifacts browser
v 8.3.3
- Preserve CE behavior with JIRA integration by only calling API if URL is set
......@@ -113,6 +137,7 @@ v 8.3.0
- Fix: Assignee selector is empty when 'Unassigned' is selected (Jose Corcuera)
- Add rake tasks for git repository maintainance (Zeger-Jan van de Weg)
- Fix 500 error when update group member permission
- Fix: As an admin, cannot add oneself as a member to a group/project
- Trim leading and trailing whitespace of milestone and issueable titles (Jose Corcuera)
- Recognize issue/MR/snippet/commit links as references
- Backport JIRA features from EE to CE
......@@ -174,7 +199,6 @@ v 8.2.2
- Fix Error 500 when viewing user's personal projects from admin page (Stan Hu)
- Fix: Raw private snippets access workflow
- Prevent "413 Request entity too large" errors when pushing large files with LFS
- Fix: As an admin, cannot add oneself as a member to a group/project
- Fix invalid links within projects dashboard header
- Make current user the first user in assignee dropdown in issues detail page (Stan Hu)
- Fix: duplicate email notifications on issue comments
......
source "https://rubygems.org"
gem 'rails', '4.2.4'
gem 'rails', '4.2.5'
gem 'rails-deprecated_sanitizer', '~> 1.0.3'
# Responders respond_to and respond_with
......@@ -18,7 +18,7 @@ gem "mysql2", '~> 0.3.16', group: :mysql
gem "pg", '~> 0.18.2', group: :postgres
# Authentication libraries
gem 'devise', '~> 3.5.3'
gem 'devise', '~> 3.5.4'
gem 'devise-async', '~> 0.9.0'
gem 'doorkeeper', '~> 2.2.0'
gem 'omniauth', '~> 1.2.2'
......@@ -50,7 +50,7 @@ gem "browser", '~> 1.0.0'
# Extracting information from a git repository
# Provide access to Gitlab::Git library
gem "gitlab_git", '~> 7.2.22'
gem "gitlab_git", '~> 7.2.23'
# LDAP Auth
# GitLab fork with several improvements to original library. For full list of changes
......@@ -218,8 +218,9 @@ gem 'request_store', '~> 1.2.0'
gem 'select2-rails', '~> 3.5.9'
gem 'virtus', '~> 1.0.1'
gem 'net-ssh', '~> 3.0.1'
gem "gitlab-license", "~> 0.0.4"
# Sentry integration
gem 'sentry-raven'
# Metrics
group :metrics do
......
......@@ -4,41 +4,41 @@ GEM
CFPropertyList (2.3.2)
RedCloth (4.2.9)
ace-rails-ap (2.0.1)
actionmailer (4.2.4)
actionpack (= 4.2.4)
actionview (= 4.2.4)
activejob (= 4.2.4)
actionmailer (4.2.5)
actionpack (= 4.2.5)
actionview (= 4.2.5)
activejob (= 4.2.5)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 1.0, >= 1.0.5)
actionpack (4.2.4)
actionview (= 4.2.4)
activesupport (= 4.2.4)
actionpack (4.2.5)
actionview (= 4.2.5)
activesupport (= 4.2.5)
rack (~> 1.6)
rack-test (~> 0.6.2)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionview (4.2.4)
activesupport (= 4.2.4)
actionview (4.2.5)
activesupport (= 4.2.5)
builder (~> 3.1)
erubis (~> 2.7.0)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
activejob (4.2.4)
activesupport (= 4.2.4)
activejob (4.2.5)
activesupport (= 4.2.5)
globalid (>= 0.3.0)
activemodel (4.2.4)
activesupport (= 4.2.4)
activemodel (4.2.5)
activesupport (= 4.2.5)
builder (~> 3.1)
activerecord (4.2.4)
activemodel (= 4.2.4)
activesupport (= 4.2.4)
activerecord (4.2.5)
activemodel (= 4.2.5)
activesupport (= 4.2.5)
arel (~> 6.0)
activerecord-deprecated_finders (1.0.4)
activerecord-session_store (0.1.2)
actionpack (>= 4.0.0, < 5)
activerecord (>= 4.0.0, < 5)
railties (>= 4.0.0, < 5)
activesupport (4.2.4)
activesupport (4.2.5)
i18n (~> 0.7)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
......@@ -157,7 +157,7 @@ GEM
activerecord (>= 3.2.0, < 5.0)
descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1)
devise (3.5.3)
devise (3.5.4)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 3.2.6, < 5)
......@@ -378,7 +378,7 @@ GEM
gitlab-license (0.0.4)
gitlab_emoji (0.2.0)
gemojione (~> 2.1)
gitlab_git (7.2.22)
gitlab_git (7.2.24)
activesupport (~> 4.0)
charlock_holmes (~> 0.7.3)
github-linguist (~> 4.7.0)
......@@ -612,16 +612,16 @@ GEM
rack
rack-test (0.6.3)
rack (>= 1.0)
rails (4.2.4)
actionmailer (= 4.2.4)
actionpack (= 4.2.4)
actionview (= 4.2.4)
activejob (= 4.2.4)
activemodel (= 4.2.4)
activerecord (= 4.2.4)
activesupport (= 4.2.4)
rails (4.2.5)
actionmailer (= 4.2.5)
actionpack (= 4.2.5)
actionview (= 4.2.5)
activejob (= 4.2.5)
activemodel (= 4.2.5)
activerecord (= 4.2.5)
activesupport (= 4.2.5)
bundler (>= 1.3.0, < 2.0)
railties (= 4.2.4)
railties (= 4.2.5)
sprockets-rails
rails-deprecated_sanitizer (1.0.3)
activesupport (>= 4.2.0.alpha)
......@@ -631,14 +631,14 @@ GEM
rails-deprecated_sanitizer (>= 1.0.1)
rails-html-sanitizer (1.0.2)
loofah (~> 2.0)
railties (4.2.4)
actionpack (= 4.2.4)
activesupport (= 4.2.4)
railties (4.2.5)
actionpack (= 4.2.5)
activesupport (= 4.2.5)
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rainbow (2.0.0)
raindrops (0.15.0)
rake (10.4.2)
rake (10.5.0)
raphael-rails (2.1.2)
rb-fsevent (0.9.6)
rb-inotify (0.9.5)
......@@ -672,8 +672,8 @@ GEM
request_store (1.2.1)
rerun (0.11.0)
listen (~> 3.0)
responders (2.1.0)
railties (>= 4.2.0, < 5)
responders (2.1.1)
railties (>= 4.2.0, < 5.1)
rest-client (1.8.0)
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 3.0)
......@@ -749,6 +749,8 @@ GEM
activesupport (>= 3.1, < 4.3)
select2-rails (3.5.9.3)
thor (~> 0.14)
sentry-raven (0.15.3)
faraday (>= 0.7.6)
settingslogic (2.0.9)
sexp_processor (4.6.0)
sham_rack (1.3.6)
......@@ -935,7 +937,7 @@ DEPENDENCIES
d3_rails (~> 3.5.0)
database_cleaner (~> 1.4.0)
default_value_for (~> 3.0.0)
devise (~> 3.5.3)
devise (~> 3.5.4)
devise-async (~> 0.9.0)
devise-two-factor (~> 2.0.0)
diffy (~> 3.0.3)
......@@ -960,7 +962,7 @@ DEPENDENCIES
gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-license (~> 0.0.4)
gitlab_emoji (~> 0.2.0)
gitlab_git (~> 7.2.22)
gitlab_git (~> 7.2.23)
gitlab_meta (= 7.0)
gitlab_omniauth-ldap (~> 1.2.1)
gollum-lib (~> 4.1.0)
......@@ -1016,7 +1018,7 @@ DEPENDENCIES
rack-attack (~> 4.3.1)
rack-cors (~> 0.4.0)
rack-oauth2 (~> 1.2.1)
rails (= 4.2.4)
rails (= 4.2.5)
rails-deprecated_sanitizer (~> 1.0.3)
raphael-rails (~> 2.1.2)
rblineprof
......@@ -1038,6 +1040,7 @@ DEPENDENCIES
sdoc (~> 0.3.20)
seed-fu (~> 2.3.5)
select2-rails (~> 3.5.9)
sentry-raven
settingslogic (~> 2.0.9)
sham_rack
shoulda-matchers (~> 2.8.0)
......
File mode changed from 100644 to 100755
8.4.0.pre-ee
8.5.0-pre-ee
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
......@@ -22,9 +22,9 @@
#= require bootstrap
#= require select2
#= require raphael
#= require g.raphael-min
#= require g.bar-min
#= require chart-lib.min
#= require g.raphael
#= require g.bar
#= require Chart
#= require branch-graph
#= require ace/ace
#= require ace/ext-searchbox
......@@ -39,9 +39,9 @@
#= require shortcuts_dashboard_navigation
#= require shortcuts_issuable
#= require shortcuts_network
#= require jquery.nicescroll.min
#= require jquery.nicescroll
#= require_tree .
#= require fuzzaldrin-plus.min
#= require fuzzaldrin-plus
window.slugify = (text) ->
text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase()
......
......@@ -5,7 +5,7 @@ class @AwardsHandler
event.preventDefault()
$(".emoji-menu").show()
$("html").click ->
$("html").on 'click', (event) ->
if !$(event.target).closest(".emoji-menu").length
if $(".emoji-menu").is(":visible")
$(".emoji-menu").hide()
......@@ -19,7 +19,7 @@ class @AwardsHandler
@addAwardToEmojiBar(emoji)
$(".emoji-menu").hide()
addAwardToEmojiBar: (emoji) ->
@addEmojiToFrequentlyUsedList(emoji)
......@@ -44,7 +44,6 @@ class @AwardsHandler
decrementCounter: (emoji) ->
counter = @findEmojiIcon(emoji).siblings(".counter")
emojiIcon = counter.parent()
if parseInt(counter.text()) > 1
counter.text(parseInt(counter.text()) - 1)
emojiIcon.removeClass("active")
......@@ -60,13 +59,16 @@ class @AwardsHandler
removeMeFromAuthorList: (emoji) ->
award_block = @findEmojiIcon(emoji).parent()
authors = award_block.attr("data-original-title").split(", ")
authors = _.without(authors, "me").join(", ")
award_block.attr("title", authors)
authors.splice(authors.indexOf("me"),1)
award_block.closest(".award").attr("data-original-title", authors.join(", "))
@resetTooltip(award_block)
addMeToAuthorList: (emoji) ->
award_block = @findEmojiIcon(emoji).parent()
authors = award_block.attr("data-original-title").split(", ")
origTitle = award_block.attr("data-original-title").trim()
authors = []
if origTitle
authors = origTitle.split(', ')
authors.push("me")
award_block.attr("title", authors.join(", "))
@resetTooltip(award_block)
......@@ -78,7 +80,7 @@ class @AwardsHandler
setTimeout (->
award.tooltip()
), 200
createEmoji: (emoji) ->
emojiCssClass = @resolveNameToCssClass(emoji)
......
class @BuildArtifacts
constructor: () ->
@disablePropagation()
@setupEntryClick()
disablePropagation: ->
$('.top-block').on 'click', '.download', (e) ->
e.stopPropagation()
$('.tree-holder').on 'click', 'tr[data-link] a', (e) ->
e.stopImmediatePropagation()
setupEntryClick: ->
$('.tree-holder').on 'click', 'tr[data-link]', (e) ->
window.location = @dataset.link
......@@ -87,7 +87,6 @@ class Dispatcher
new GroupAvatar()
when 'projects:tree:show'
new TreeView()
shortcut_handler = new ShortcutsTree()
when 'projects:find_file:show'
shortcut_handler = true
when 'projects:blob:show'
......@@ -101,6 +100,8 @@ class Dispatcher
shortcut_handler = true
when 'projects:forks:new'
new ProjectFork()
when 'projects:artifacts:browse'
new BuildArtifacts()
when 'users:show'
new User()
new Activities()
......
......@@ -6,11 +6,25 @@ class @Issue
constructor: ->
# Prevent duplicate event bindings
@disableTaskList()
@fixAffixScroll()
if $('a.btn-close').length
@initTaskList()
@initIssueBtnEventListeners()
fixAffixScroll: ->
fixAffix = ->
$discussion = $('.issuable-discussion')
$sidebar = $('.issuable-sidebar')
if $sidebar.hasClass('no-affix')
$sidebar.removeClass(['affix-top','affix'])
discussionHeight = $discussion.height()
sidebarHeight = $sidebar.height()
if sidebarHeight > discussionHeight
$discussion.height(sidebarHeight + 50)
$sidebar.addClass('no-affix')
$(window).on('resize', fixAffix)
fixAffix()
initTaskList: ->
$('.detail-page-description .js-task-list-container').taskList('enable')
$(document).on 'tasklist:changed', '.detail-page-description .js-task-list-container', @updateTaskList
......
......@@ -15,6 +15,8 @@ class @MergeRequest
this.$('.show-all-commits').on 'click', =>
this.showAllCommits()
@fixAffixScroll();
@initTabs()
# Prevent duplicate event bindings
......@@ -28,6 +30,20 @@ class @MergeRequest
$: (selector) ->
this.$el.find(selector)
fixAffixScroll: ->
fixAffix = ->
$discussion = $('.issuable-discussion')
$sidebar = $('.issuable-sidebar')
if $sidebar.hasClass('no-affix')
$sidebar.removeClass(['affix-top','affix'])
discussionHeight = $discussion.height()
sidebarHeight = $sidebar.height()
if sidebarHeight > discussionHeight
$discussion.height(sidebarHeight + 50)
$sidebar.addClass('no-affix')
$(window).on('resize', fixAffix)
fixAffix()
initTabs: ->
if @opts.action != 'new'
# `MergeRequests#new` has no tab-persisting or lazy-loading behavior
......
......@@ -15,6 +15,8 @@ class @Notes
@last_fetched_at = last_fetched_at
@view = view
@noteable_url = document.URL
@notesCountBadge ||= $(".issuable-details").find(".notes-tab .badge")
@initRefresh()
@setupMainTargetNoteForm()
@cleanBinding()
......@@ -89,7 +91,7 @@ class @Notes
, 15000
refresh: ->
unless document.hidden or (@noteable_url != document.URL)
if not document.hidden and document.URL.indexOf(@noteable_url) is 0
@getContent()
getContent: ->
......@@ -101,7 +103,10 @@ class @Notes
notes = data.notes
@last_fetched_at = data.last_fetched_at
$.each notes, (i, note) =>
@renderNote(note)
if note.discussion_with_diff_html?
@renderDiscussionNote(note)
else
@renderNote(note)
###
......@@ -116,18 +121,21 @@ class @Notes
flash.pinTo('.header-content')
return
if note.award
awards_handler.addAwardToEmojiBar(note.note)
awards_handler.scrollToAwards()
# render note if it not present in loaded list
# or skip if rendered
if @isNewNote(note) && !note.award
else if @isNewNote(note)
@note_ids.push(note.id)
$('ul.main-notes-list').
append(note.html).
syntaxHighlight()
$('ul.main-notes-list')
.append(note.html)
.syntaxHighlight()
@initTaskList()
@updateNotesCount(1)
if note.award
awards_handler.addAwardToEmojiBar(note.note)
awards_handler.scrollToAwards()
###
Check if note does not exists on page
......@@ -144,34 +152,39 @@ class @Notes
Note: for rendering inline notes use renderDiscussionNote
###
renderDiscussionNote: (note) ->
return unless @isNewNote(note)
@note_ids.push(note.id)
form = $("form[rel='" + note.discussion_id + "']")
form = $("#new-discussion-note-form-#{note.discussion_id}")
row = form.closest("tr")
note_html = $(note.html)
note_html.syntaxHighlight()
# is this the first note of discussion?
if row.is(".js-temp-notes-holder")
discussionContainer = $(".notes[data-discussion-id='" + note.discussion_id + "']")
if discussionContainer.length is 0
# insert the note and the reply button after the temp row
row.after note.discussion_html
# remove the note (will be added again below)
row.next().find(".note").remove()
# Before that, the container didn't exist
discussionContainer = $(".notes[data-discussion-id='" + note.discussion_id + "']")
# Add note to 'Changes' page discussions
$(".notes[rel='" + note.discussion_id + "']").append note_html
discussionContainer.append note_html
# Init discussion on 'Discussion' page if it is merge request page
if $('body').attr('data-page').indexOf('projects:merge_request') == 0
discussion_html = $(note.discussion_with_diff_html)
discussion_html.syntaxHighlight()
$('ul.main-notes-list').append(discussion_html)
if $('body').attr('data-page').indexOf('projects:merge_request') is 0
$('ul.main-notes-list')
.append(note.discussion_with_diff_html)
.syntaxHighlight()
else
# append new note to all matching discussions
$(".notes[rel='" + note.discussion_id + "']").append note_html
discussionContainer.append note_html
# cleanup after successfully creating a diff/discussion note
@removeDiscussionNoteForm(form)
@updateNotesCount(1)
###
Called in response the main target form has been successfully submitted.
......@@ -278,6 +291,9 @@ class @Notes
addDiscussionNote: (xhr, note, status) =>
@renderDiscussionNote(note)
# cleanup after successfully creating a diff/discussion note
@removeDiscussionNoteForm($("#new-discussion-note-form-#{note.discussion_id}"))
###
Called in response to the edit note form being submitted
......@@ -320,6 +336,7 @@ class @Notes
form.show()
textarea = form.find("textarea")
textarea.focus()
autosize(textarea)
# HACK (rspeicher/DouweM): Work around a Chrome 43 bug(?).
# The textarea has the correct value, Chrome just won't show it unless we
......@@ -348,30 +365,32 @@ class @Notes
Removes the actual note from view.
Removes the whole discussion if the last note is being removed.
###
removeNote: ->
note = $(this).closest(".note")
note_id = note.attr('id')
removeNote: (e) =>
noteId = $(e.currentTarget)
.closest(".note")
.attr("id")
$('.note[id="' + note_id + '"]').each ->
note = $(this)
# A same note appears in the "Discussion" and in the "Changes" tab, we have
# to remove all. Using $(".note[id='noteId']") ensure we get all the notes,
# where $("#noteId") would return only one.
$(".note[id='#{noteId}']").each (i, el) =>
note = $(el)
notes = note.closest(".notes")
count = notes.closest(".issuable-details").find(".notes-tab .badge")
# check if this is the last note for this line
if notes.find(".note").length is 1
# for discussions
notes.closest(".discussion").remove()
# "Discussions" tab
notes.closest(".timeline-entry").remove()
# for diff lines
# "Changes" tab / commit view
notes.closest("tr").remove()
# update notes count
oldNum = parseInt(count.text())
count.text(oldNum - 1)
note.remove()
# Decrement the "Discussions" counter only once
@updateNotesCount(-1)
###
Called in response to clicking the delete attachment link
......@@ -411,7 +430,7 @@ class @Notes
###
setupDiscussionNoteForm: (dataHolder, form) =>
# setup note target
form.attr "rel", dataHolder.data("discussionId")
form.attr 'id', "new-discussion-note-form-#{dataHolder.data("discussionId")}"
form.find("#line_type").val dataHolder.data("lineType")
form.find("#note_commit_id").val dataHolder.data("commitId")
form.find("#note_line_code").val dataHolder.data("lineCode")
......@@ -541,3 +560,6 @@ class @Notes
updateTaskList: ->
$('form', this).submit()
updateNotesCount: (updateCount) ->
@notesCountBadge.text(parseInt(@notesCountBadge.text()) + updateCount)
......@@ -4,6 +4,7 @@ class @Shortcuts
Mousetrap.reset()
Mousetrap.bind('?', @selectiveHelp)
Mousetrap.bind('s', Shortcuts.focusSearch)
Mousetrap.bind('t', -> Turbolinks.visit(findFileURL)) if findFileURL?
selectiveHelp: (e) =>
Shortcuts.showHelp(e, @enabledHelp)
......
class @ShortcutsTree extends ShortcutsNavigation
constructor: ->
super()
Mousetrap.bind('t', -> ShortcutsTree.findAndFollowLink('.shortcuts-find-file'))
......@@ -6,7 +6,7 @@ class @Star
$starIcon = $this.find('i')
toggleStar = (isStarred) ->
$this.parent().find('span.count').text data.star_count
$this.parent().find('.star-count').text data.star_count
if isStarred
$starSpan.removeClass('starred').text 'Star'
$starIcon.removeClass('fa-star').addClass 'fa-star-o'
......@@ -19,4 +19,4 @@ class @Star
return
).on 'ajax:error', (e, xhr, status, error) ->
new Flash('Star toggle failed. Try again later.', 'alert')
return
\ No newline at end of file
return
......@@ -146,6 +146,10 @@
border-bottom: 1px solid $border-color;
&.oneline-block {
line-height: 42px;
line-height: 36px;
}
> .controls {
float: right;
}
}
......@@ -120,14 +120,6 @@ span.update-author {
display: inline;
}
.line_holder {
&:hover {
td {
background: #FFFFCF !important;
}
}
}
p.time {
color: #999;
font-size: 90%;
......
......@@ -92,15 +92,6 @@
&:last-child {
border-right: none;
}
background: #fff;
}
.lines {
pre {
padding: 0;
margin: 0;
background: none;
border: none;
}
}
img.avatar {
border: 0 none;
......@@ -116,18 +107,18 @@
color: #888;
}
}
td.blame-numbers {
pre {
color: #AAA;
white-space: pre;
}
background: #f1f1f1;
td.line-numbers {
float: none;
border-left: 1px solid #DDD;
}
td.lines {
padding: 0;
code {
font-family: $monospace_font;
}
pre {
margin: 0;
}
}
}
......
.filter-item {
margin-right: 15px;
margin-right: 6px;
}
@media (min-width: 800px) {
......
......@@ -53,3 +53,14 @@
color: #333;
}
}
.ui-sortable-handle {
cursor: move;
cursor: -webkit-grab;
cursor: -moz-grab;
&:active {
cursor: -webkit-grabbing;
cursor: -moz-grabbing;
}
}
.gl-pagination {
text-align: center;
border-top: 1px solid $border-color;
background-color: $background-color;
margin: -$gl-padding;
margin: 0;
margin-top: 0;
.pagination {
padding: 0;
margin: 0;
display: block;
li.first,
li.last,
li.next,
li.prev {
> a {
color: $link-color;
&:hover {
color: #fff;
}
}
}
li > a,
li > span {
border: none;
margin: 0;
@include border-radius(0 !important);
padding: 13px 19px;
border-right: 1px solid $border-color;
}
}
}
......
......@@ -2,7 +2,13 @@
margin-bottom: $gl-padding;
.panel-heading {
padding: 7px $gl-padding;
padding: $gl-vert-padding $gl-padding;
line-height: 36px;
.controls {
margin-top: -2px;
float: right;
}
}
.panel-body {
......@@ -14,7 +20,3 @@
}
}
}
.container-blank .panel .panel-heading {
line-height: 42px !important;
}
......@@ -114,22 +114,9 @@
*
*/
.container-blank .panel .panel-heading {
font-size: 17px;
line-height: 38px;
}
.panel {
box-shadow: none;
.panel-heading {
.panel-head-actions {
position: relative;
top: -5px;
float: right;
}
}
.panel-body {
form, pre {
margin: 0;
......
......@@ -66,20 +66,20 @@ $legend-color: $text-color;
//##
$pagination-color: $gl-gray;
$pagination-bg: $background-color;
$pagination-border: transparent;
$pagination-bg: #fff;
$pagination-border: $border-color;
$pagination-hover-color: #fff;
$pagination-hover-bg: $brand-info;
$pagination-hover-border: transparent;
$pagination-hover-color: $gl-gray;
$pagination-hover-bg: $hover;
$pagination-hover-border: $border-color;
$pagination-active-color: #fff;
$pagination-active-bg: $brand-info;
$pagination-active-border: transparent;
$pagination-active-color: $blue-dark;
$pagination-active-bg: #fff;
$pagination-active-border: $border-color;
$pagination-disabled-color: #fff;
$pagination-disabled-bg: lighten($brand-info, 15%);
$pagination-disabled-border: transparent;
$pagination-disabled-color: #cdcdcd;
$pagination-disabled-bg: $background-color;
$pagination-disabled-border: $border-color;
//== Form states and alerts
......
......@@ -26,6 +26,7 @@ $gl-vert-padding: 6px;
$gl-padding-top:10px;
$gl-avatar-size: 46px;
$secondary-text: #7f8fa4;
$error-exclamation-point: #E62958;
/*
* Color schema
......
/* https://github.com/MozMorris/tomorrow-pygments */
.code.dark {
// Line numbers
.line-numbers, .diff-line-num {
background-color: #1d1f21;
}
background-color: #1d1f21 !important;
color: #c5c8c6 !important;
pre.highlight,
.line-numbers,
.line-numbers a {
background-color: #1d1f21 !important;
color: #c5c8c6 !important;
.diff-line-num, .diff-line-num a {
color: rgba(255, 255, 255, 0.3);
}
// Code itself
pre.code {
border-left: 1px solid #666;
}
&, pre.code, .line_holder .line_content {
background-color: #1d1f21;
color: #c5c8c6;
}
// Diff line
.line_holder {
.diff-line-num.new, .line_content.new {
@include diff_background(rgba(51, 255, 51, 0.1), rgba(51, 255, 51, 0.3), #808080);
}
.diff-line-num.old, .line_content.old {
@include diff_background(rgba(255, 51, 51, 0.2), rgba(255, 51, 51, 0.3), #808080);
}
.line_content.match {
color: rgba(255, 255, 255, 0.3);
background: rgba(255, 255, 255, 0.1);
}
}
// highlight line via anchor
pre .hll {
background-color: #557 !important;
......
/* https://github.com/richleland/pygments-css/blob/master/monokai.css */
.code.monokai {
// Line numbers
.line-numbers, .diff-line-num {
background-color: #272822;
}
background-color: #272822 !important;
color: #f8f8f2 !important;
pre.highlight,
.line-numbers,
.line-numbers a {
background-color :#272822 !important;
color: #f8f8f2 !important;
.diff-line-num, .diff-line-num a {
color: rgba(255, 255, 255, 0.3);
}
// Code itself
pre.code {
border-left: 1px solid #555;
}
&, pre.code, .line_holder .line_content {
background-color: #272822;
color: #f8f8f2;
}
// Diff line
.line_holder {
.diff-line-num.new, .line_content.new {
@include diff_background(rgba(166, 226, 46, 0.2), rgba(166, 226, 46, 0.3), #808080);
}
.diff-line-num.old, .line_content.old {
@include diff_background(rgba(254, 147, 140, 0.2), rgba(254, 147, 140, 0.3), #808080);
}
.line_content.match {
color: rgba(255, 255, 255, 0.3);
background: rgba(255, 255, 255, 0.1);
}
}
// highlight line via anchor
pre .hll {
background-color: #49483e !important;
......
/* https://gist.github.com/qguv/7936275 */
.code.solarized-dark {
// Line numbers
.line-numbers, .diff-line-num {
background-color: #002b36;
}
background-color: #002b36 !important;
color: #93a1a1 !important;
pre.highlight,
.line-numbers,
.line-numbers a {
background-color: #002b36 !important;
color: #93a1a1 !important;
.diff-line-num, .diff-line-num a {
color: rgba(255, 255, 255, 0.3);
}
// Code itself
pre.code {
border-left: 1px solid #113b46;
}
&, pre.code, .line_holder .line_content {
background-color: #002b36;
color: #93a1a1;
}
// Diff line
.line_holder {
.diff-line-num.new, .line_content.new {
@include diff_background(rgba(133, 153, 0, 0.2), rgba(133, 153, 0, 0.3), #808080);
}
.diff-line-num.old, .line_content.old {
@include diff_background(rgba(220, 50, 47, 0.3), rgba(220, 50, 47, 0.3), #808080);
}
.line_content.match {
color: rgba(255, 255, 255, 0.3);
background: rgba(255, 255, 255, 0.1);
}
}
// highlight line via anchor
pre .hll {
background-color: #174652 !important;
......
/* https://gist.github.com/qguv/7936275 */
.code.solarized-light {
// Line numbers
.line-numbers, .diff-line-num {
background-color: #fdf6e3;
}
background-color: #fdf6e3 !important;
color: #586e75 !important;
pre.highlight,
.line-numbers,
.line-numbers a {
background-color: #fdf6e3 !important;
color: #586e75 !important;
.diff-line-num, .diff-line-num a {
color: rgba(0, 0, 0, 0.3);
}
// Code itself
pre.code {
border-left: 1px solid #c5d0d4;
}
&, pre.code, .line_holder .line_content {
background-color: #fdf6e3;
color: #586e75;
}
// Diff line
.line_holder {
.diff-line-num.new, .line_content.new {
@include diff_background(rgba(133, 153, 0, 0.2), rgba(133, 153, 0, 0.3), #FAF3DD);
}
.diff-line-num.old, .line_content.old {
@include diff_background(rgba(220, 50, 47, 0.2), rgba(220, 50, 47, 0.3), #FAF3DD);
}
.line_content.match {
color: rgba(0, 0, 0, 0.3);
background: rgba(255, 255, 255, 0.4);
}
}
// highlight line via anchor
pre .hll {
background-color: #ddd8c5 !important;
......
/* https://github.com/aahan/pygments-github-style */
.code.white {
// Line numbers
.line-numbers, .diff-line-num {
background-color: $background-color;
}
background-color: #f8fafc !important;
color: #5b6169 !important;
pre.highlight,
.line-numbers,
.line-numbers a {
background-color: $background-color !important;
color: $gl-gray !important;
.diff-line-num, .diff-line-num a {
color: rgba(0, 0, 0, 0.3);
}
// Code itself
pre.code {
border-left: 1px solid $border-color;
background-color: #fff !important;
color: #333 !important;
}
&, pre.code, .line_holder .line_content {
background-color: #fff;
color: #333;
}
// Diff line
.line_holder {
.diff-line-num {
&.old {
background: #ffdddd;
border-color: #f1c0c0;
}
&.new {
background: #dbffdb;
border-color: #c1e9c1;
}
}
.line_content {
&.old {
background: #ffecec;
span.idiff {
background-color: #f8cbcb;
}
}
&.new {
background: #eaffea;
span.idiff {
background-color: #a6f3a6;
}
}
&.match {
color: rgba(0, 0, 0, 0.3);
background: #fafafa;
}
}
}
// highlight line via anchor
......
......@@ -36,6 +36,10 @@ li.commit {
line-height: 20px;
margin-bottom: 2px;
.btn-clipboard {
margin-top: -1px;
}
.notes_count {
float: right;
margin-right: 10px;
......
......@@ -32,16 +32,6 @@
background: #FFF;
color: #333;
.old {
span.idiff {
background-color: #f8cbcb;
}
}
.new {
span.idiff {
background-color: #a6f3a6;
}
}
.unfold {
cursor: pointer;
}
......@@ -66,6 +56,7 @@
width: 100%;
font-family: $monospace_font;
border: none;
border-collapse: separate;
margin: 0px;
padding: 0px;
.line_holder td {
......@@ -75,7 +66,7 @@
}
tr.line_holder.parallel {
.old_line, .new_line, .diff_line {
.old_line, .new_line {
min-width: 50px;
}
......@@ -84,7 +75,7 @@
}
}
.old_line, .new_line, .diff_line {
.old_line, .new_line {
margin: 0px;
padding: 0px;
border: none;
......@@ -106,43 +97,12 @@
text-decoration: underline;
}
}
&.new {
background: #CFD;
}
&.old {
background: #FDD;
}
}
.diff_line {
padding: 0;
}
.line_holder {
&.old .old_line,
&.old .new_line {
background: #ffdddd;
border-color: #f1c0c0;
}
&.new .old_line,
&.new .new_line {
background: #dbffdb;
border-color: #c1e9c1;
}
}
.line_content {
display: block;
margin: 0px;
padding: 0px 0.5em;
border: none;
&.new {
background: #eaffea;
}
&.old {
background: #ffecec;
}
&.matched {
color: $border-color;
background: #fafafa;
}
&.parallel {
display: table-cell;
}
......@@ -392,3 +352,15 @@
right: 15px;
}
}
@mixin diff_background($background, $idiff, $border) {
background: $background;
&.line_content span.idiff {
background: $idiff;
}
&.diff-line-num {
border-color: $border;
}
}
......@@ -20,6 +20,11 @@
position: fixed;
top: 70px;
margin-right: 35px;
&.no-affix {
position: relative;
top: 0;
}
}
}
}
......
......@@ -201,3 +201,39 @@
.mr-source-target {
line-height: 31px;
}
.disabled-comment-area {
padding: 16px 0;
.disabled-profile {
width: 40px;
height: 40px;
background: $border-gray-dark;
border-radius: 20px;
display: inline-block;
margin-right: 10px;
}
.disabled-comment {
background: $gray-light;
display: inline-block;
vertical-align: top;
height: 200px;
border-radius: 4px;
border: 1px solid $border-gray-normal;
padding-top: 90px;
text-align: center;
right: 20px;
position: absolute;
left: 70px;
margin-bottom: 20px;
span {
color: #B2B2B2;
a {
color: $md-link-color;
}
}
}
}
\ No newline at end of file
......@@ -10,18 +10,6 @@
margin: 10px $gl-padding;
}
.diff-file .diff-content {
tr.line_holder:hover {
&> td.line_content {
background: $hover !important;
border-color: darken($hover, 10%) !important;
}
&> td.new_line,
&> td.old_line {
background: darken($hover, 4%) !important;
border-color: darken($hover, 10%) !important;
}
}
tr.line_holder:hover > td .line_note_link {
opacity: 1.0;
filter: alpha(opacity=100);
......
......@@ -242,11 +242,8 @@ ul.notes {
// "show" the icon also if we just hover somewhere over the line
&:hover > td {
background: $hover !important;
.add-diff-note {
@include show-add-diff-note;
}
}
}
......@@ -92,12 +92,12 @@
}
.project-repo-buttons {
margin-top: 12px;
margin-top: 20px;
margin-bottom: 0px;
.count-buttons {
display: block;
margin-bottom: 12px;
margin-bottom: 20px;
}
.clone-row {
......@@ -163,7 +163,7 @@
line-height: 13px;
padding: $gl-vert-padding $gl-padding;
letter-spacing: .4px;
padding: 10px;
padding: 10px 14px;
text-align: center;
vertical-align: middle;
touch-action: manipulation;
......@@ -558,3 +558,9 @@ pre.light-well {
width: 101%;
}
}
.cannot-be-merged,
.cannot-be-merged:hover {
color: #E62958;
margin-top: 2px;
}
......@@ -2,6 +2,7 @@ class AbuseReportsController < ApplicationController
def new
@abuse_report = AbuseReport.new
@abuse_report.user_id = params[:user_id]
@ref_url = params.fetch(:ref_url, '')
end
def create
......
......@@ -76,9 +76,13 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:metrics_timeout,
:metrics_method_call_threshold,
:metrics_sample_interval,
:ip_blocking_enabled,
:dnsbl_servers_list,
:recaptcha_enabled,
:recaptcha_site_key,
:recaptcha_private_key,
:sentry_enabled,
:sentry_dsn,
restricted_visibility_levels: [],
import_sources: []
)
......
......@@ -15,6 +15,7 @@ class ApplicationController < ActionController::Base
before_action :check_password_expiration
before_action :check_2fa_requirement
before_action :ldap_security_check
before_action :sentry_user_context
before_action :default_headers
before_action :add_gon_variables
before_action :configure_permitted_parameters, if: :devise_controller?
......@@ -24,6 +25,7 @@ class ApplicationController < ActionController::Base
helper_method :abilities, :can?, :current_application_settings
helper_method :import_sources_enabled?, :github_import_enabled?, :github_import_configured?, :gitlab_import_enabled?, :gitlab_import_configured?, :bitbucket_import_enabled?, :bitbucket_import_configured?, :gitorious_import_enabled?, :google_code_import_enabled?, :fogbugz_import_enabled?, :git_import_enabled?
helper_method :repository
rescue_from Encoding::CompatibilityError do |exception|
log_exception(exception)
......@@ -41,6 +43,16 @@ class ApplicationController < ActionController::Base
protected
def sentry_user_context
if Rails.env.production? && current_application_settings.sentry_enabled && current_user
Raven.user_context(
id: current_user.id,
email: current_user.email,
username: current_user.username,
)
end
end
# From https://github.com/plataformatec/devise/wiki/How-To:-Simple-Token-Authentication-Example
# https://gist.github.com/josevalim/fb706b1e933ef01e4fb6
def authenticate_user_from_token!
......
......@@ -97,7 +97,7 @@ module CreatesCommit
# Merge request from fork to this project
@mr_source_project = @tree_edit_project
@mr_target_project = @project
@mr_target_branch = @mr_target_project.repository.root_ref
@mr_target_branch = @ref
end
end
end
......@@ -52,7 +52,9 @@ class Projects::BlobController < Projects::ApplicationController
def preview
@content = params[:content]
diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3', include_diff_info: true)
@diff_lines = Gitlab::Diff::Parser.new.parse(diffy.diff.scan(/.*\n/))
diff_lines = diffy.diff.scan(/.*\n/)[2..-1]
diff_lines = Gitlab::Diff::Parser.new.parse(diff_lines)
@diff_lines = Gitlab::Diff::Highlight.new(diff_lines).highlight
render layout: false
end
......@@ -65,8 +67,9 @@ class Projects::BlobController < Projects::ApplicationController
end
def diff
@form = UnfoldForm.new(params)
@lines = @blob.data.lines[@form.since - 1..@form.to - 1]
@form = UnfoldForm.new(params)
@lines = Gitlab::Highlight.highlight_lines(repository, @ref, @path)
@lines = @lines[@form.since - 1..@form.to - 1]
if @form.bottom?
@match_line = ''
......
......@@ -72,6 +72,7 @@ class Projects::CommitController < Projects::ApplicationController
@diffs = commit.diffs
end
@diff_refs = [commit.parent || commit, commit]
@notes_count = commit.notes.count
@statuses = ci_commit.statuses if ci_commit
......
......@@ -21,7 +21,8 @@ class Projects::CompareController < Projects::ApplicationController
@commits = Commit.decorate(compare_result.commits, @project)
@diffs = compare_result.diffs
@commit = @project.commit(head_ref)
@first_commit = @project.commit(base_ref)
@base_commit = @project.commit(base_ref)
@diff_refs = [@base_commit, @commit]
@line_notes = []
end
end
......
......@@ -49,7 +49,7 @@ class Projects::IssuesController < Projects::ApplicationController
assignee_id: ""
)
@issue = @project.issues.new(issue_params)
@issue = @noteable = @project.issues.new(issue_params)
# Set Issue description based on project template
if @project.issues_template.present?
......
......@@ -58,7 +58,11 @@ class Projects::MergeRequestsController < Projects::ApplicationController
def diffs
@commit = @merge_request.last_commit
@first_commit = @merge_request.first_commit
@base_commit = @merge_request.diff_base_commit
# MRs created before 8.4 don't have a diff_base_commit,
# but we need it for the "View file @ ..." link by deleted files
@base_commit ||= @merge_request.first_commit.parent || @merge_request.first_commit
@comments_allowed = @reply_allowed = true
@comments_target = {
......@@ -90,6 +94,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
def new
params[:merge_request] ||= ActionController::Parameters.new(source_project: @project)
@merge_request = MergeRequests::BuildService.new(project, current_user, merge_request_params).execute
@noteable = @merge_request
@target_branches = if @merge_request.target_project
@merge_request.target_project.repository.branch_names
......@@ -101,7 +106,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@source_project = merge_request.source_project
@commits = @merge_request.compare_commits.reverse
@commit = @merge_request.last_commit
@first_commit = @merge_request.first_commit
@base_commit = @merge_request.diff_base_commit
@diffs = @merge_request.compare_diffs
@ci_commit = @merge_request.ci_commit
......
......@@ -11,11 +11,9 @@ class Projects::NotesController < Projects::ApplicationController
notes_json = { notes: [], last_fetched_at: current_fetched_at }
@notes.each do |note|
notes_json[:notes] << {
id: note.id,
html: note_to_html(note),
valid: note.valid?
}
next if note.cross_reference_not_visible_for?(current_user)
notes_json[:notes] << note_json(note)
end
render json: notes_json
......@@ -25,7 +23,7 @@ class Projects::NotesController < Projects::ApplicationController
@note = Notes::CreateService.new(project, current_user, note_params).execute
respond_to do |format|
format.json { render_note_json(@note) }
format.json { render json: note_json(@note) }
format.html { redirect_back_or_default }
end
end
......@@ -34,7 +32,7 @@ class Projects::NotesController < Projects::ApplicationController
@note = Notes::UpdateService.new(project, current_user, note_params).execute(note)
respond_to do |format|
format.json { render_note_json(@note) }
format.json { render json: note_json(@note) }
format.html { redirect_back_or_default }
end
end
......@@ -99,6 +97,8 @@ class Projects::NotesController < Projects::ApplicationController
end
def note_to_discussion_html(note)
return unless note.for_diff_line?
if params[:view] == 'parallel'
template = "projects/notes/_diff_notes_with_reply_parallel"
locals =
......@@ -131,9 +131,9 @@ class Projects::NotesController < Projects::ApplicationController
)
end
def render_note_json(note)
def note_json(note)
if note.valid?
render json: {
{
valid: true,
id: note.id,
discussion_id: note.discussion_id,
......@@ -144,7 +144,7 @@ class Projects::NotesController < Projects::ApplicationController
discussion_with_diff_html: note_to_discussion_with_diff_html(note)
}
else
render json: {
{
valid: false,
award: note.is_award,
errors: note.errors
......@@ -163,8 +163,6 @@ class Projects::NotesController < Projects::ApplicationController
)
end
private
def find_current_user_notes
@notes = NotesFinder.new.execute(project, current_user, params)
end
......
......@@ -25,7 +25,7 @@ class Projects::SnippetsController < Projects::ApplicationController
end
def new
@snippet = @project.snippets.build
@snippet = @noteable = @project.snippets.build
end
def create
......
......@@ -8,6 +8,11 @@ class RegistrationsController < Devise::RegistrationsController
def create
if !Gitlab::Recaptcha.load_configurations! || verify_recaptcha
if Gitlab::IpCheck.new(request.remote_ip).spam?
flash[:alert] = 'Could not create an account. This IP is listed for spam.'
return render action: 'new'
end
super
else
flash[:alert] = "There was an error with the reCAPTCHA code below. Please re-enter the code."
......
......@@ -82,7 +82,8 @@ class IssuableFinder
elsif current_user && params[:authorized_only].presence && !current_user_related?
@projects = current_user.authorized_projects.reorder(nil)
else
@projects = ProjectsFinder.new.execute(current_user).reorder(nil)
@projects = ProjectsFinder.new.execute(current_user, group: group).
reorder(nil)
end
end
......
......@@ -8,11 +8,11 @@ module ApplicationSettingsHelper
end
def signup_enabled?
current_application_settings.signup_enabled
current_application_settings.signup_enabled?
end
def signin_enabled?
current_application_settings.signin_enabled
current_application_settings.signin_enabled?
end
def extra_sign_in_text
......
module BlobHelper
def highlight(blob_name, blob_content, nowrap: false, continue: false)
@formatter ||= Rouge::Formatters::HTMLGitlab.new(
nowrap: nowrap,
cssclass: 'code highlight',
lineanchors: true,
lineanchorsid: 'LC'
)
begin
@lexer ||= Rouge::Lexer.guess(filename: blob_name, source: blob_content).new
result = @formatter.format(@lexer.lex(blob_content, continue: continue)).html_safe
rescue
@lexer = Rouge::Lexers::PlainText
result = @formatter.format(@lexer.lex(blob_content)).html_safe
end
def highlighter(blob_name, blob_content, nowrap: false)
Gitlab::Highlight.new(blob_name, blob_content, nowrap: nowrap)
end
result
def highlight(blob_name, blob_content, nowrap: false)
Gitlab::Highlight.highlight(blob_name, blob_content, nowrap: nowrap)
end
def no_highlight_files
......@@ -37,10 +26,10 @@ module BlobHelper
tree_join(ref, path),
link_opts)
if !on_top_of_branch?
if !on_top_of_branch?(project, ref)
button_tag "Edit", class: "btn btn-default disabled has_tooltip", title: "You can only edit files when you are on a branch", data: { container: 'body' }
elsif can_edit_blob?(blob)
link_to "Edit", edit_path, class: 'btn btn-small'
elsif can_edit_blob?(blob, project, ref)
link_to "Edit", edit_path, class: 'btn'
elsif can?(current_user, :fork_project, project)
continue_params = {
to: edit_path,
......@@ -50,7 +39,7 @@ module BlobHelper
fork_path = namespace_project_fork_path(project.namespace, project, namespace_key: current_user.namespace.id,
continue: continue_params)
link_to "Edit", fork_path, class: 'btn btn-small', method: :post
link_to "Edit", fork_path, class: 'btn', method: :post
end
end
......@@ -61,11 +50,11 @@ module BlobHelper
return unless blob
if !on_top_of_branch?
if !on_top_of_branch?(project, ref)
button_tag label, class: "btn btn-#{btn_class} disabled has_tooltip", title: "You can only #{action} files when you are on a branch", data: { container: 'body' }
elsif blob.lfs_pointer?
button_tag label, class: "btn btn-#{btn_class} disabled has_tooltip", title: "It is not possible to #{action} files that are stored in LFS using the web interface", data: { container: 'body' }
elsif can_edit_blob?(blob)
elsif can_edit_blob?(blob, project, ref)
button_tag label, class: "btn btn-#{btn_class}", 'data-target' => "#modal-#{modal_type}-blob", 'data-toggle' => 'modal'
elsif can?(current_user, :fork_project, project)
continue_params = {
......
......@@ -166,7 +166,7 @@ module CommitsHelper
link_to(
namespace_project_blob_path(project.namespace, project,
tree_join(commit_sha, diff.new_path)),
class: 'btn btn-small view-file js-view-file'
class: 'btn view-file js-view-file'
) do
raw('View file @') + content_tag(:span, commit_sha[0..6],
class: 'commit-short-id')
......
......@@ -19,13 +19,13 @@ module DiffHelper
end
end
def safe_diff_files(diffs)
def safe_diff_files(diffs, diff_refs)
lines = 0
safe_files = []
diffs.first(allowed_diff_size).each do |diff|
lines += diff.diff.lines.count
break if lines > allowed_diff_lines
safe_files << Gitlab::Diff::File.new(diff)
safe_files << Gitlab::Diff::File.new(diff, diff_refs)
end
safe_files
end
......@@ -43,64 +43,6 @@ module DiffHelper
Gitlab::Diff::LineCode.generate(file_path, line.new_pos, line.old_pos)
end
def parallel_diff(diff_file, index)
lines = []
skip_next = false
# Building array of lines
#
# [
# left_type, left_line_number, left_line_content, left_line_code,
# right_line_type, right_line_number, right_line_content, right_line_code
# ]
#
diff_file.diff_lines.each do |line|
full_line = line.text
type = line.type
line_code = generate_line_code(diff_file.file_path, line)
line_new = line.new_pos
line_old = line.old_pos
next_line = diff_file.next_line(line.index)
if next_line
next_line_code = generate_line_code(diff_file.file_path, next_line)
next_type = next_line.type
next_line = next_line.text
end
if type == 'match' || type.nil?
# line in the right panel is the same as in the left one
line = [type, line_old, full_line, line_code, type, line_new, full_line, line_code]
lines.push(line)
elsif type == 'old'
if next_type == 'new'
# Left side has text removed, right side has text added
line = [type, line_old, full_line, line_code, next_type, line_new, next_line, next_line_code]
lines.push(line)
skip_next = true
elsif next_type == 'old' || next_type.nil?
# Left side has text removed, right side doesn't have any change
# No next line code, no new line number, no new line text
line = [type, line_old, full_line, line_code, next_type, nil, "&nbsp;", nil]
lines.push(line)
end
elsif type == 'new'
if skip_next
# Change has been already included in previous line so no need to do it again
skip_next = false
next
else
# Change is only on the right side, left side has no change
line = [nil, nil, "&nbsp;", line_code, type, line_new, full_line, line_code]
lines.push(line)
end
end
end
lines
end
def unfold_bottom_class(bottom)
(bottom) ? 'js-unfold-bottom' : ''
end
......@@ -111,9 +53,9 @@ module DiffHelper
def diff_line_content(line)
if line.blank?
" &nbsp;"
" &nbsp;".html_safe
else
line
line.html_safe
end
end
......@@ -160,8 +102,7 @@ module DiffHelper
def commit_for_diff(diff)
if diff.deleted_file
first_commit = @first_commit || @commit
first_commit.parent || @first_commit
@base_commit || @commit.parent || @commit
else
@commit
end
......
......@@ -3,13 +3,26 @@ module Emails
def build_fail_email(build_id, to)
@build = Ci::Build.find(build_id)
@project = @build.project
add_project_headers
add_build_headers
headers['X-GitLab-Build-Status'] = "failed"
mail(to: to, subject: subject("Build failed for #{@project.name}", @build.short_sha))
end
def build_success_email(build_id, to)
@build = Ci::Build.find(build_id)
@project = @build.project
add_project_headers
add_build_headers
headers['X-GitLab-Build-Status'] = "success"
mail(to: to, subject: subject("Build success for #{@project.name}", @build.short_sha))
end
private
def add_build_headers
headers['X-GitLab-Build-Id'] = @build.id
headers['X-GitLab-Build-Ref'] = @build.ref
end
end
end
......@@ -43,7 +43,7 @@ module Emails
@current_user = @created_by = User.find(created_by_id)
@access_level = access_level
@invite_email = invite_email
@target_url = namespace_project_url(@project.namespace, @project)
mail(to: @created_by.notification_email,
......@@ -65,6 +65,10 @@ module Emails
# used in notify layout
@target_url = @message.target_url
@project = Project.find project_id
add_project_headers
headers['X-GitLab-Author'] = @message.author_username
mail(from: sender(@message.author_id, @message.send_from_committer_email?),
reply_to: @message.reply_to,
......
......@@ -101,12 +101,7 @@ class Notify < BaseMailer
end
def mail_thread(model, headers = {})
if @project
headers['X-GitLab-Project'] = @project.name
headers['X-GitLab-Project-Id'] = @project.id
headers['X-GitLab-Project-Path'] = @project.path_with_namespace
end
add_project_headers
headers["X-GitLab-#{model.class.name}-ID"] = model.id
headers['X-GitLab-Reply-Key'] = reply_key
......@@ -153,4 +148,12 @@ class Notify < BaseMailer
def reply_key
@reply_key ||= SentNotification.reply_key
end
def add_project_headers
return unless @project
headers['X-GitLab-Project'] = @project.name
headers['X-GitLab-Project-Id'] = @project.id
headers['X-GitLab-Project-Path'] = @project.path_with_namespace
end
end
......@@ -17,7 +17,7 @@ class AbuseReport < ActiveRecord::Base
validates :reporter, presence: true
validates :user, presence: true
validates :message, presence: true
validates :user_id, uniqueness: true
validates :user_id, uniqueness: { message: 'has already been reported' }
def remove_user
user.block
......
......@@ -42,6 +42,10 @@
# recaptcha_site_key :string
# recaptcha_private_key :string
# metrics_port :integer default(8089)
# sentry_enabled :boolean default(FALSE)
# sentry_dsn :string
# ip_blocking_enabled :boolean default(FALSE)
# dns_blacklist_threshold :float default(0.33)
#
class ApplicationSetting < ActiveRecord::Base
......@@ -83,6 +87,10 @@ class ApplicationSetting < ActiveRecord::Base
presence: true,
if: :recaptcha_enabled
validates :sentry_dsn,
presence: true,
if: :sentry_enabled
validates_each :restricted_visibility_levels do |record, attr, value|
unless value.nil?
value.each do |level|
......
......@@ -3,11 +3,11 @@
# Table name: web_hooks
#
# id :integer not null, primary key
# url :string(255)
# url :string(2000)
# project_id :integer
# created_at :datetime
# updated_at :datetime
# type :string(255) default("ProjectHook")
# type :string default("ProjectHook")
# service_id :integer
# push_events :boolean default(TRUE), not null
# issues_events :boolean default(FALSE), not null
......
......@@ -3,11 +3,11 @@
# Table name: web_hooks
#
# id :integer not null, primary key
# url :string(255)
# url :string(2000)
# project_id :integer
# created_at :datetime
# updated_at :datetime
# type :string(255) default("ProjectHook")
# type :string default("ProjectHook")
# service_id :integer
# push_events :boolean default(TRUE), not null
# issues_events :boolean default(FALSE), not null
......
......@@ -3,11 +3,11 @@
# Table name: web_hooks
#
# id :integer not null, primary key
# url :string(255)
# url :string(2000)
# project_id :integer
# created_at :datetime
# updated_at :datetime
# type :string(255) default("ProjectHook")
# type :string default("ProjectHook")
# service_id :integer
# push_events :boolean default(TRUE), not null
# issues_events :boolean default(FALSE), not null
......
......@@ -3,11 +3,11 @@
# Table name: web_hooks
#
# id :integer not null, primary key
# url :string(255)
# url :string(2000)
# project_id :integer
# created_at :datetime
# updated_at :datetime
# type :string(255) default("ProjectHook")
# type :string default("ProjectHook")
# service_id :integer
# push_events :boolean default(TRUE), not null
# issues_events :boolean default(FALSE), not null
......
......@@ -92,7 +92,7 @@ class Member < ActiveRecord::Base
member.invite_email = user
end
if can_update_member?(current_user, member)
if can_update_member?(current_user, member) || project_creator?(member, access_level)
member.created_by ||= current_user
member.access_level = access_level
......@@ -110,6 +110,11 @@ class Member < ActiveRecord::Base
current_user.can?(:update_group_member, member) ||
current_user.can?(:update_project_member, member)
end
def project_creator?(member, access_level)
member.new_record? && member.owner? &&
access_level.to_i == ProjectMember::MASTER
end
end
def invite?
......
......@@ -84,7 +84,7 @@ class ProjectMember < Member
def truncate_teams(project_ids)
ProjectMember.transaction do
members = ProjectMember.where(source_id: project_ids)
members.each do |member|
member.destroy
end
......@@ -133,7 +133,7 @@ class ProjectMember < Member
event_service.join_project(self.project, self.user)
notification_service.new_project_member(self) unless @skip_notification
end
super
end
......
......@@ -184,6 +184,14 @@ class MergeRequest < ActiveRecord::Base
merge_request_diff ? merge_request_diff.first_commit : compare_commits.first
end
def diff_base_commit
if merge_request_diff
merge_request_diff.base_commit
else
self.target_project.commit(self.target_branch)
end
end
def last_commit_short_sha
last_commit.short_id
end
......@@ -258,7 +266,7 @@ class MergeRequest < ActiveRecord::Base
end
def mergeable?
return false unless open? && !work_in_progress?
return false unless open? && !work_in_progress? && !broken?
check_if_can_be_merged
......@@ -533,8 +541,7 @@ class MergeRequest < ActiveRecord::Base
end
def target_sha
@target_sha ||= target_project.
repository.commit(target_branch).sha
@target_sha ||= target_project.repository.commit(target_branch).sha
end
def source_sha
......@@ -593,4 +600,10 @@ class MergeRequest < ActiveRecord::Base
def ci_commit
@ci_commit ||= source_project.ci_commit(last_commit.id) if last_commit && source_project
end
def diff_refs
return nil unless diff_base_commit
[diff_base_commit, last_commit]
end
end
......@@ -73,6 +73,12 @@ class MergeRequestDiff < ActiveRecord::Base
commits.last
end
def base_commit
return nil unless self.base_commit_sha
merge_request.target_project.commit(self.base_commit_sha)
end
def last_commit_short_sha
@last_commit_short_sha ||= last_commit.short_id
end
......@@ -156,6 +162,9 @@ class MergeRequestDiff < ActiveRecord::Base
end
self.st_diffs = new_diffs
self.base_commit_sha = merge_request.target_project.commit(target_branch).try(:sha)
self.save
end
......
......@@ -34,7 +34,7 @@ class Note < ActiveRecord::Base
participant :author
belongs_to :project
belongs_to :noteable, polymorphic: true
belongs_to :noteable, polymorphic: true, touch: true
belongs_to :author, class_name: "User"
belongs_to :updated_by, class_name: "User"
......@@ -246,7 +246,7 @@ class Note < ActiveRecord::Base
prev_match_line = nil
prev_lines = []
diff_lines.each do |line|
highlighted_diff_lines.each do |line|
if line.type == "match"
prev_lines.clear
prev_match_line = line
......@@ -263,7 +263,11 @@ class Note < ActiveRecord::Base
end
def diff_lines
@diff_lines ||= Gitlab::Diff::Parser.new.parse(diff.diff.lines.to_a)
@diff_lines ||= Gitlab::Diff::Parser.new.parse(diff.diff.lines)
end
def highlighted_diff_lines
Gitlab::Diff::Highlight.new(diff_lines).highlight
end
def discussion_id
......
......@@ -306,6 +306,10 @@ class Project < ActiveRecord::Base
query: "%#{query.try(:downcase)}%")
end
def search_by_visibility(level)
where(visibility_level: Gitlab::VisibilityLevel.const_get(level.upcase))
end
def search_by_title(query)
where('projects.archived = ?', false).where('LOWER(projects.name) LIKE :query', query: "%#{query.downcase}%")
end
......@@ -558,12 +562,9 @@ class Project < ActiveRecord::Base
!external_issue_tracker
end
def external_issues_trackers
services.select(&:issue_tracker?).reject(&:default?)
end
def external_issue_tracker
@external_issues_tracker ||= external_issues_trackers.find(&:activated?)
@external_issue_tracker ||=
services.issue_trackers.active.without_defaults.first
end
def can_have_issues_tracker_id?
......
......@@ -23,14 +23,12 @@
# List methods you need to implement to get your CI service
# working with GitLab Merge Requests
class CiService < Service
def category
:ci
end
default_value_for :category, 'ci'
def valid_token?(token)
self.respond_to?(:token) && self.token.present? && self.token == token
end
def supported_events
%w(push)
end
......
......@@ -24,9 +24,7 @@ class GitlabIssueTrackerService < IssueTrackerService
prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url
def default?
true
end
default_value_for :default, true
def to_param
'gitlab'
......
......@@ -23,12 +23,10 @@ class IssueTrackerService < Service
validates :project_url, :issues_url, :new_issue_url, presence: true, if: :activated?
def category
:issue_tracker
end
default_value_for :category, 'issue_tracker'
def default?
false
default
end
def create_cross_reference_note
......
......@@ -61,7 +61,7 @@ class Repository
# This method return true if repository contains some content visible in project page.
#
def has_visible_content?
!raw_repository.branches.empty?
raw_repository.branch_count > 0
end
def commit(id = 'HEAD')
......@@ -673,7 +673,7 @@ class Repository
def search_files(query, ref)
offset = 2
args = %W(#{Gitlab.config.git.bin_path} grep -i -n --before-context #{offset} --after-context #{offset} -e #{query} #{ref || root_ref})
args = %W(#{Gitlab.config.git.bin_path} grep -i -I -n --before-context #{offset} --after-context #{offset} -e #{query} #{ref || root_ref})
Gitlab::Popen.popen(args, path_to_repo).first.scrub.split(/^--$/)
end
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment