Commit f5e65e2e authored by Vinnie Okada's avatar Vinnie Okada

Merge branch 'master' into markdown-tags

Merge updated CHANGELOG entries
parents cc29ce49 6cf189f0
......@@ -2,6 +2,20 @@ Please view this file on the master branch, on stable branches it's out of date.
v 7.10.0 (unreleased)
- Allow HTML tags in Markdown input
- Update poltergeist to version 1.6.0 to support PhantomJS 2.0 (Zeger-Jan van de Weg)
- Fix cross references when usernames, milestones, or project names contain underscores (Stan Hu)
- enable line wrapping per default and remove the checkbox to toggle it (Hannes Rosenögger)
- extend the commit calendar to show the actual commits made on a date (Hannes Rosenögger)
- Add a service to support external wikis (Hannes Rosenögger)
- List new commits for newly pushed branch in activity view.
- Add changelog, license and contribution guide links to project sidebar.
- Improve diff UI
- Fix alignment of navbar toggle button (Cody Mize)
- Identical look of selectboxes in UI
- Move "Import existing repository by URL" option to button.
- Improve error message when save profile has error.
- Passing the name of pushed ref to CI service (requires GitLab CI 7.9+)
- Add location field to user profile
v 7.9.0 (unreleased)
- Add HipChat integration documentation (Stan Hu)
......@@ -80,6 +94,8 @@ v 7.9.0 (unreleased)
- Ability to unsubscribe/subscribe to issue or merge request
- Delete deploy key when last connection to a project is destroyed.
- Fix invalid Atom feeds when using emoji, horizontal rules, or images (Christian Walther)
- Backup of repositories with tar instead of git bundle (only now are git-annex files included in the backup)
- Add canceled status for CI
v 7.8.4
- Fix issue_tracker_id substitution in custom issue trackers
......
......@@ -31,7 +31,7 @@ gem 'omniauth-shibboleth'
gem 'omniauth-kerberos'
gem 'omniauth-gitlab'
gem 'omniauth-bitbucket'
gem 'doorkeeper', '2.1.0'
gem 'doorkeeper', '2.1.3'
gem "rack-oauth2", "~> 1.0.5"
# Browser detection
......@@ -39,7 +39,7 @@ gem "browser"
# Extracting information from a git repository
# Provide access to Gitlab::Git library
gem "gitlab_git", '~> 7.1.0'
gem "gitlab_git", '~> 7.1.2'
# Ruby/Rack Git Smart-HTTP Server Handler
gem 'gitlab-grack', '~> 2.0.0.rc2', require: 'grack'
......@@ -48,7 +48,7 @@ gem 'gitlab-grack', '~> 2.0.0.rc2', require: 'grack'
gem 'gitlab_omniauth-ldap', '1.2.1', require: "omniauth-ldap"
# Git Wiki
gem 'gollum-lib', '~> 4.0.0'
gem 'gollum-lib', '~> 4.0.2'
# Language detection
gem "gitlab-linguist", "~> 3.0.1", require: "linguist"
......@@ -180,9 +180,6 @@ gem 'mousetrap-rails'
# Detect and convert string character encoding
gem 'charlock_holmes'
# Shutting down requests that take too long
gem "slowpoke"
gem "sass-rails", '~> 4.0.2'
gem "coffee-rails"
gem "uglifier"
......
......@@ -136,8 +136,8 @@ GEM
diff-lcs (1.2.5)
diffy (3.0.3)
docile (1.1.5)
doorkeeper (2.1.0)
railties (>= 3.1)
doorkeeper (2.1.3)
railties (>= 3.2)
dotenv (0.9.0)
dropzonejs-rails (0.4.14)
rails (> 3.1)
......@@ -147,7 +147,6 @@ GEM
enumerize (0.7.0)
activesupport (>= 3.2)
equalizer (0.0.8)
errbase (0.0.2)
erubis (2.7.0)
escape_utils (0.2.4)
eventmachine (1.0.4)
......@@ -213,7 +212,7 @@ GEM
mime-types (~> 1.19)
gitlab_emoji (0.1.0)
gemojione (~> 2.0)
gitlab_git (7.1.1)
gitlab_git (7.1.2)
activesupport (~> 4.0)
charlock_holmes (~> 0.6)
gitlab-linguist (~> 3.0)
......@@ -224,11 +223,11 @@ GEM
omniauth (~> 1.0)
pyu-ruby-sasl (~> 0.0.3.1)
rubyntlm (~> 0.3)
gollum-grit_adapter (0.1.0)
gitlab-grit (~> 2.7.1)
gollum-lib (4.0.0)
gollum-grit_adapter (0.1.3)
gitlab-grit (~> 2.7, >= 2.7.1)
gollum-lib (4.0.2)
github-markup (~> 1.3.1)
gollum-grit_adapter (~> 0.1.0)
gollum-grit_adapter (~> 0.1, >= 0.1.1)
nokogiri (~> 1.6.4)
rouge (~> 1.7.4)
sanitize (~> 2.1.0)
......@@ -429,7 +428,6 @@ GEM
rack
rack-test (0.6.3)
rack (>= 1.0)
rack-timeout (0.2.0)
rails (4.1.9)
actionmailer (= 4.1.9)
actionpack (= 4.1.9)
......@@ -482,9 +480,7 @@ GEM
rest-client (1.6.7)
mime-types (>= 1.16)
rinku (1.7.3)
robustly (0.0.3)
errbase
rouge (1.7.4)
rouge (1.7.7)
rspec (2.99.0)
rspec-core (~> 2.99.0)
rspec-expectations (~> 2.99.0)
......@@ -519,7 +515,7 @@ GEM
rubyntlm (0.5.0)
rubypants (0.2.0)
rugged (0.21.4)
rugments (1.0.0.beta4)
rugments (1.0.0.beta5)
safe_yaml (0.9.7)
sanitize (2.1.0)
nokogiri (>= 1.4.4)
......@@ -566,9 +562,6 @@ GEM
temple (~> 0.6.6)
tilt (>= 1.3.3, < 2.1)
slop (3.6.0)
slowpoke (0.0.5)
rack-timeout (>= 0.1.0)
robustly
spinach (0.8.7)
colorize (= 0.5.8)
gherkin-ruby (>= 0.3.1)
......@@ -690,7 +683,7 @@ DEPENDENCIES
devise (= 3.2.4)
devise-async (= 0.9.0)
diffy (~> 3.0.3)
doorkeeper (= 2.1.0)
doorkeeper (= 2.1.3)
dropzonejs-rails
email_spec
enumerize
......@@ -705,10 +698,10 @@ DEPENDENCIES
gitlab-grack (~> 2.0.0.rc2)
gitlab-linguist (~> 3.0.1)
gitlab_emoji (~> 0.1)
gitlab_git (~> 7.1.0)
gitlab_git (~> 7.1.2)
gitlab_meta (= 7.0)
gitlab_omniauth-ldap (= 1.2.1)
gollum-lib (~> 4.0.0)
gollum-lib (~> 4.0.2)
gon (~> 5.0.0)
grape (~> 0.6.1)
grape-entity (~> 0.4.2)
......@@ -776,7 +769,6 @@ DEPENDENCIES
six
slack-notifier (~> 1.0.0)
slim
slowpoke
spinach-rails
spring (~> 1.3.1)
spring-commands-rspec (= 1.0.4)
......
......@@ -169,9 +169,7 @@ $ ->
# Show/hide comments on diff
$("body").on "click", ".js-toggle-diff-comments", (e) ->
$(@).find('i').
toggleClass('fa fa-chevron-down').
toggleClass('fa fa-chevron-up')
$(@).toggleClass('active')
$(@).closest(".diff-file").find(".notes_holder").toggle()
e.preventDefault()
......
$ ->
# Toggle line wrapping in diff.
#
# %div.diff-file
# %input.js-toggle-diff-line-wrap
# %td.line_content
#
$("body").on "click", ".js-toggle-diff-line-wrap", (e) ->
diffFile = $(@).closest(".diff-file")
if $(@).is(":checked")
diffFile.addClass("diff-wrap-lines")
else
diffFile.removeClass("diff-wrap-lines")
......@@ -4,7 +4,7 @@ class @calendar
day: "numeric"
year: "numeric"
constructor: (timestamps, starting_year, starting_month) ->
constructor: (timestamps, starting_year, starting_month, calendar_activities_path) ->
cal = new CalHeatMap()
cal.init
itemName: ["commit"]
......@@ -26,5 +26,16 @@ class @calendar
]
legendCellPadding: 3
onClick: (date, count) ->
return
return
formated_date = date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate()
$(".calendar_commit_activity").fadeOut 400
$.ajax
url: calendar_activities_path
data:
date: formated_date
cache: false
dataType: "html"
success: (data) ->
$(".user-calendar-activities").html data
$(".calendar_commit_activity").find(".js-toggle-content").hide()
$(".calendar_commit_activity").fadeIn 400
......@@ -19,6 +19,6 @@ class @Issue
$('.issue-details').waitForImages ->
$('.issuable-affix').affix offset:
top: ->
@top = $('.issue-details').outerHeight(true) + 25
@top = ($('.issuable-affix').offset().top - 70)
bottom: ->
@bottom = $('.footer').outerHeight(true)
......@@ -23,7 +23,7 @@ class @MergeRequest
$('.merge-request-details').waitForImages ->
$('.issuable-affix').affix offset:
top: ->
@top = $('.merge-request-details').outerHeight(true) + 91
@top = ($('.issuable-affix').offset().top - 70)
bottom: ->
@bottom = $('.footer').outerHeight(true)
......@@ -110,7 +110,7 @@ class @MergeRequest
showCiState: (state) ->
$('.ci_widget').hide()
allowed_states = ["failed", "running", "pending", "success"]
allowed_states = ["failed", "canceled", "running", "pending", "success"]
if state in allowed_states
$('.ci_widget.ci-' + state).show()
else
......
......@@ -425,7 +425,7 @@ class @Notes
@removeDiscussionNoteForm(form)
updateVotes: ->
(new NotesVotes).updateVotes()
true
###
Called after an attachment file has been selected.
......
class @NotesVotes
updateVotes: ->
votes = $("#votes .votes")
notes = $("#notes-list .note .vote")
# only update if there is a vote display
if votes.size()
upvotes = notes.filter(".upvote").size()
downvotes = notes.filter(".downvote").size()
votesCount = upvotes + downvotes
upvotesPercent = (if votesCount then (100.0 / votesCount * upvotes) else 0)
downvotesPercent = (if votesCount then (100.0 - upvotesPercent) else 0)
# change vote bar lengths
votes.find(".bar-success").css "width", upvotesPercent + "%"
votes.find(".bar-danger").css "width", downvotesPercent + "%"
# replace vote numbers
votes.find(".upvotes").text votes.find(".upvotes").text().replace(/\d+/, upvotes)
votes.find(".downvotes").text votes.find(".downvotes").text().replace(/\d+/, downvotes)
// Override Bootstrap variables here (defaults from bootstrap-sass v3.3.3):
// For all variables see https://github.com/twbs/bootstrap-sass/blob/master/templates/project/_bootstrap-variables.sass
//
// Variables
// --------------------------------------------------
......@@ -15,12 +15,6 @@
// $gray: lighten($gray-base, 33.5%) // #555
// $gray-light: lighten($gray-base, 46.7%) // #777
// $gray-lighter: lighten($gray-base, 93.5%) // #eee
$gray-base: #000;
$gray-darker: lighten($gray-base, 13.5%); // #222
$gray-dark: #7b8a8b; // #333
$gray: #95a5a6; // #555
$gray-light: #b4bcc2; // #999
$gray-lighter: #ecf0f1; // #eee
$brand-primary: $gl-primary;
$brand-success: $gl-success;
......@@ -31,68 +25,17 @@ $brand-danger: $gl-danger;
//== Scaffolding
//
//## Settings for some of the most global styles.
//** Background color for `<body>`.
// $body-bg: #fff
//** Global text color on `<body>`.
$text-color: $brand-primary;
//** Global textual link color.
$text-color: $gl-text-color;
$link-color: $gl-link-color;
//** Link hover color set via `darken()` function.
// $link-hover-color: darken($link-color, 15%)
//** Link hover decoration.
// $link-hover-decoration: underline
//== Typography
//
//## Font, line-height, and color for body text, headings, and more.
// $font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif
// $font-family-serif: Georgia, "Times New Roman", Times, serif
//** Default monospace fonts for `<code>`, `<kbd>`, and `<pre>`.
// $font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace
// $font-family-base: $font-family-sans-serif
$font-size-base: $gl-font-size;
// $font-size-large: ceil(($font-size-base * 1.25)) // ~18px
// $font-size-small: ceil(($font-size-base * 0.85)) // ~12px
// $font-size-h1: floor(($font-size-base * 2.6)) // ~36px
// $font-size-h2: floor(($font-size-base * 2.15)) // ~30px
// $font-size-h3: ceil(($font-size-base * 1.7)) // ~24px
// $font-size-h4: ceil(($font-size-base * 1.25)) // ~18px
// $font-size-h5: $font-size-base
// $font-size-h6: ceil(($font-size-base * 0.85)) // ~12px
//** Unit-less `line-height` for use in components like buttons.
// $line-height-base: 1.428571429 // 20/14
//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
// $line-height-computed: floor(($font-size-base * $line-height-base)) // ~20px
//** By default, this inherits from the `<body>`.
// $headings-font-family: inherit
// $headings-font-weight: 500
// $headings-line-height: 1.1
// $headings-color: inherit
//== Iconography
//
//## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via Bower.
//** Load fonts from this directory.
// [converter] If $bootstrap-sass-asset-helper if used, provide path relative to the assets load path.
// [converter] This is because some asset helpers, such as Sprockets, do not work with file-relative paths.
// $icon-font-path: if($bootstrap-sass-asset-helper, "bootstrap/", "../fonts/bootstrap/")
//** File name for all font files.
// $icon-font-name: "glyphicons-halflings-regular"
//** Element ID within SVG icon file.
// $icon-font-svg-id: "glyphicons_halflingsregular"
$font-family-sans-serif: $regular_font;
$font-family-monospace: $monospace_font;
$font-size-base: $gl-font-size;
//== Components
......@@ -102,348 +45,15 @@ $font-size-base: $gl-font-size;
$padding-base-vertical: 6px;
$padding-base-horizontal: 14px;
// $padding-large-vertical: 10px
// $padding-large-horizontal: 16px
// $padding-small-vertical: 5px
// $padding-small-horizontal: 10px
// $padding-xs-vertical: 1px
// $padding-xs-horizontal: 5px
// $line-height-large: 1.3333333 // extra decimals for Win 8.1 Chrome
// $line-height-small: 1.5
// $border-radius-base: 4px
// $border-radius-large: 6px
// $border-radius-small: 3px
//** Global color for active items (e.g., navs or dropdowns).
// $component-active-color: #fff
//** Global background color for active items (e.g., navs or dropdowns).
// $component-active-bg: $brand-primary
//** Width of the `border` for generating carets that indicator dropdowns.
// $caret-width-base: 4px
//** Carets increase slightly in size for larger components.
// $caret-width-large: 5px
//== Tables
//
//## Customizes the `.table` component with basic values, each used across all table variations.
//** Padding for `<th>`s and `<td>`s.
// $table-cell-padding: 8px
//** Padding for cells in `.table-condensed`.
// $table-condensed-cell-padding: 5px
//** Default background color used for all tables.
// $table-bg: transparent
//** Background color used for `.table-striped`.
// $table-bg-accent: #f9f9f9
//** Background color used for `.table-hover`.
// $table-bg-hover: #f5f5f5
// $table-bg-active: $table-bg-hover
//** Border color for table and cell borders.
// $table-border-color: #ddd
//== Buttons
//
//## For each of Bootstrap's buttons, define text, background and border color.
// $btn-font-weight: normal
// $btn-default-color: #333
// $btn-default-bg: #fff
// $btn-default-border: #ccc
// $btn-primary-color: #fff
// $btn-primary-bg: $brand-primary
// $btn-primary-border: darken($btn-primary-bg, 5%)
// $btn-success-color: #fff
// $btn-success-bg: $brand-success
// $btn-success-border: darken($btn-success-bg, 5%)
// $btn-info-color: #fff
// $btn-info-bg: $brand-info
// $btn-info-border: darken($btn-info-bg, 5%)
// $btn-warning-color: #fff
// $btn-warning-bg: $brand-warning
// $btn-warning-border: darken($btn-warning-bg, 5%)
// $btn-danger-color: #fff
// $btn-danger-bg: $brand-danger
// $btn-danger-border: darken($btn-danger-bg, 5%)
// $btn-link-disabled-color: $gray-light
//== Forms
//
//##
//** `<input>` background color
// $input-bg: #fff
//** `<input disabled>` background color
// $input-bg-disabled: $gray-lighter
//** Text color for `<input>`s
$input-color: $text-color;
//** `<input>` border color
$input-border: #dce4ec;
// TODO: Rename `$input-border-radius` to `$input-border-radius-base` in v4
//** Default `.form-control` border radius
// This has no effect on `<select>`s in some browsers, due to the limited stylability of `<select>`s in CSS.
// $input-border-radius: $border-radius-base
//** Large `.form-control` border radius
// $input-border-radius-large: $border-radius-large
//** Small `.form-control` border radius
// $input-border-radius-small: $border-radius-small
//** Border color for inputs on focus
$input-border: #DDD;
$input-border-focus: $brand-info;
//** Placeholder text color
// $input-color-placeholder: #999
//** Default `.form-control` height
// $input-height-base: ($line-height-computed + ($padding-base-vertical * 2) + 2)
//** Large `.form-control` height
// $input-height-large: (ceil($font-size-large * $line-height-large) + ($padding-large-vertical * 2) + 2)
//** Small `.form-control` height
// $input-height-small: (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2)
$legend-color: $text-color;
// $legend-border-color: #e5e5e5
//** Background color for textual input addons
// $input-group-addon-bg: $gray-lighter
//** Border color for textual input addons
// $input-group-addon-border-color: $input-border
//** Disabled cursor for form controls and buttons.
// $cursor-disabled: not-allowed
//== Dropdowns
//
//## Dropdown menu container and contents.
//** Background for the dropdown menu.
// $dropdown-bg: #fff
//** Dropdown menu `border-color`.
// $dropdown-border: rgba(0,0,0,.15)
//** Dropdown menu `border-color` **for IE8**.
// $dropdown-fallback-border: #ccc
//** Divider color for between dropdown items.
// $dropdown-divider-bg: #e5e5e5
//** Dropdown link text color.
// $dropdown-link-color: $gray-dark
//** Hover color for dropdown links.
// $dropdown-link-hover-color: darken($gray-dark, 5%)
//** Hover background for dropdown links.
// $dropdown-link-hover-bg: #f5f5f5
//** Active dropdown menu item text color.
// $dropdown-link-active-color: $component-active-color
//** Active dropdown menu item background color.
// $dropdown-link-active-bg: $component-active-bg
//** Disabled dropdown menu item background color.
// $dropdown-link-disabled-color: $gray-light
//** Text color for headers within dropdown menus.
// $dropdown-header-color: $gray-light
//** Deprecated `$dropdown-caret-color` as of v3.1.0
// $dropdown-caret-color: #000
//-- Z-index master list
//
// Warning: Avoid customizing these values. They're used for a bird's eye view
// of components dependent on the z-axis and are designed to all work together.
//
// Note: These variables are not generated into the Customizer.
// $zindex-navbar: 1000
// $zindex-dropdown: 1000
// $zindex-popover: 1060
// $zindex-tooltip: 1070
// $zindex-navbar-fixed: 1030
// $zindex-modal: 1040
//== Media queries breakpoints
//
//## Define the breakpoints at which your layout will change, adapting to different screen sizes.
// Extra small screen / phone
//** Deprecated `$screen-xs` as of v3.0.1
// $screen-xs: 480px
//** Deprecated `$screen-xs-min` as of v3.2.0
// $screen-xs-min: $screen-xs
//** Deprecated `$screen-phone` as of v3.0.1
// $screen-phone: $screen-xs-min
// Small screen / tablet
//** Deprecated `$screen-sm` as of v3.0.1
// $screen-sm: 768px
// $screen-sm-min: $screen-sm
//** Deprecated `$screen-tablet` as of v3.0.1
// $screen-tablet: $screen-sm-min
// Medium screen / desktop
//** Deprecated `$screen-md` as of v3.0.1
// $screen-md: 992px
// $screen-md-min: $screen-md
//** Deprecated `$screen-desktop` as of v3.0.1
// $screen-desktop: $screen-md-min
// Large screen / wide desktop
//** Deprecated `$screen-lg` as of v3.0.1
// $screen-lg: 1200px
// $screen-lg-min: $screen-lg
//** Deprecated `$screen-lg-desktop` as of v3.0.1
// $screen-lg-desktop: $screen-lg-min
// So media queries don't overlap when required, provide a maximum
// $screen-xs-max: ($screen-sm-min - 1)
// $screen-sm-max: ($screen-md-min - 1)
// $screen-md-max: ($screen-lg-min - 1)
//== Grid system
//
//## Define your custom responsive grid.
//** Number of columns in the grid.
// $grid-columns: 12
//** Padding between columns. Gets divided in half for the left and right.
// $grid-gutter-width: 30px
// Navbar collapse
//** Point at which the navbar becomes uncollapsed.
// $grid-float-breakpoint: $screen-sm-min
//** Point at which the navbar begins collapsing.
// $grid-float-breakpoint-max: ($grid-float-breakpoint - 1)
//== Container sizes
//
//## Define the maximum width of `.container` for different screen sizes.
// Small screen / tablet
// $container-tablet: (720px + $grid-gutter-width)
//** For `$screen-sm-min` and up.
// $container-sm: $container-tablet
// Medium screen / desktop
// $container-desktop: (940px + $grid-gutter-width)
//** For `$screen-md-min` and up.
// $container-md: $container-desktop
// Large screen / wide desktop
// $container-large-desktop: (1140px + $grid-gutter-width)
//** For `$screen-lg-min` and up.
// $container-lg: $container-large-desktop
//== Navbar
//
//##
// Basics of a navbar
// $navbar-height: 50px
// $navbar-margin-bottom: $line-height-computed
// $navbar-border-radius: $border-radius-base
// $navbar-padding-horizontal: floor(($grid-gutter-width / 2))
// $navbar-padding-vertical: (($navbar-height - $line-height-computed) / 2)
// $navbar-collapse-max-height: 340px
// $navbar-default-color: #777
// $navbar-default-bg: #f8f8f8
// $navbar-default-border: darken($navbar-default-bg, 6.5%)
// Navbar links
// $navbar-default-link-color: #777
// $navbar-default-link-hover-color: #333
// $navbar-default-link-hover-bg: transparent
// $navbar-default-link-active-color: #555
// $navbar-default-link-active-bg: darken($navbar-default-bg, 6.5%)
// $navbar-default-link-disabled-color: #ccc
// $navbar-default-link-disabled-bg: transparent
// Navbar brand label
// $navbar-default-brand-color: $navbar-default-link-color
// $navbar-default-brand-hover-color: darken($navbar-default-brand-color, 10%)
// $navbar-default-brand-hover-bg: transparent
// Navbar toggle
// $navbar-default-toggle-hover-bg: #ddd
// $navbar-default-toggle-icon-bar-bg: #888
// $navbar-default-toggle-border-color: #ddd
// Inverted navbar
// Reset inverted navbar basics
// $navbar-inverse-color: lighten($gray-light, 15%)
// $navbar-inverse-bg: #222
// $navbar-inverse-border: darken($navbar-inverse-bg, 10%)
// Inverted navbar links
// $navbar-inverse-link-color: lighten($gray-light, 15%)
// $navbar-inverse-link-hover-color: #fff
// $navbar-inverse-link-hover-bg: transparent
// $navbar-inverse-link-active-color: $navbar-inverse-link-hover-color
// $navbar-inverse-link-active-bg: darken($navbar-inverse-bg, 10%)
// $navbar-inverse-link-disabled-color: #444
// $navbar-inverse-link-disabled-bg: transparent
// Inverted navbar brand label
// $navbar-inverse-brand-color: $navbar-inverse-link-color
// $navbar-inverse-brand-hover-color: #fff
// $navbar-inverse-brand-hover-bg: transparent
// Inverted navbar toggle
// $navbar-inverse-toggle-hover-bg: #333
// $navbar-inverse-toggle-icon-bar-bg: #fff
// $navbar-inverse-toggle-border-color: #333
//== Navs
//
//##
//=== Shared nav styles
// $nav-link-padding: 10px 15px
// $nav-link-hover-bg: $gray-lighter
// $nav-disabled-link-color: $gray-light
// $nav-disabled-link-hover-color: $gray-light
//== Tabs
// $nav-tabs-border-color: #ddd
// $nav-tabs-link-hover-border-color: $gray-lighter
// $nav-tabs-active-link-hover-bg: $body-bg
// $nav-tabs-active-link-hover-color: $gray
// $nav-tabs-active-link-hover-border-color: #ddd
// $nav-tabs-justified-link-border-color: #ddd
// $nav-tabs-justified-active-link-border-color: $body-bg
//== Pills
// $nav-pills-border-radius: $border-radius-base
// $nav-pills-active-link-hover-bg: $component-active-bg
// $nav-pills-active-link-hover-color: $component-active-color
//== Pagination
......@@ -467,38 +77,10 @@ $pagination-disabled-bg: lighten($brand-success, 15%);
$pagination-disabled-border: transparent;
//== Pager
//
//##
// $pager-bg: $pagination-bg
// $pager-border: $pagination-border
// $pager-border-radius: 15px
// $pager-hover-bg: $pagination-hover-bg
// $pager-active-bg: $pagination-active-bg
// $pager-active-color: $pagination-active-color
// $pager-disabled-color: $pagination-disabled-color
//== Jumbotron
//
//##
// $jumbotron-padding: 30px
// $jumbotron-color: inherit
// $jumbotron-bg: $gray-lighter
// $jumbotron-heading-color: inherit
// $jumbotron-font-size: ceil(($font-size-base * 1.5))
//== Form states and alerts
//
//## Define colors for form feedback states and, by default, alerts.
$state-success-text: #fff;
$state-success-bg: $brand-success;
$state-success-border: $brand-success;
......@@ -516,316 +98,22 @@ $state-danger-bg: $brand-danger;
$state-danger-border: $brand-danger;
//== Tooltips
//
//##
//** Tooltip max width
// $tooltip-max-width: 200px
//** Tooltip text color
// $tooltip-color: #fff
//** Tooltip background color
// $tooltip-bg: #000
// $tooltip-opacity: .9
//** Tooltip arrow width
// $tooltip-arrow-width: 5px
//** Tooltip arrow color
// $tooltip-arrow-color: $tooltip-bg
//== Popovers
//
//##
//** Popover body background color
// $popover-bg: #fff
//** Popover maximum width
// $popover-max-width: 276px
//** Popover border color
// $popover-border-color: rgba(0,0,0,.2)
//** Popover fallback border color
// $popover-fallback-border-color: #ccc
//** Popover title background color
// $popover-title-bg: darken($popover-bg, 3%)
//** Popover arrow width
// $popover-arrow-width: 10px
//** Popover arrow color
// $popover-arrow-color: $popover-bg
//** Popover outer arrow width
// $popover-arrow-outer-width: ($popover-arrow-width + 1)
//** Popover outer arrow color
// $popover-arrow-outer-color: fade_in($popover-border-color, 0.05)
//** Popover outer arrow fallback color
// $popover-arrow-outer-fallback-color: darken($popover-fallback-border-color, 20%)
//== Labels
//
//##
//** Default label background color
// $label-default-bg: $gray-light
//** Primary label background color
// $label-primary-bg: $brand-primary
//** Success label background color
// $label-success-bg: $brand-success
//** Info label background color
// $label-info-bg: $brand-info
//** Warning label background color
// $label-warning-bg: $brand-warning
//** Danger label background color
// $label-danger-bg: $brand-danger
//** Default label text color
// $label-color: #fff
//** Default text color of a linked label
// $label-link-hover-color: #fff
//== Modals
//
//##
//** Padding applied to the modal body
// $modal-inner-padding: 15px
//** Padding applied to the modal title
// $modal-title-padding: 15px
//** Modal title line-height
// $modal-title-line-height: $line-height-base
//** Background color of modal content area
// $modal-content-bg: #fff
//** Modal content border color
// $modal-content-border-color: rgba(0,0,0,.2)
//** Modal content border color **for IE8**
// $modal-content-fallback-border-color: #999
//** Modal backdrop background color
// $modal-backdrop-bg: #000
//** Modal backdrop opacity
// $modal-backdrop-opacity: .5
//** Modal header border color
// $modal-header-border-color: #e5e5e5
//** Modal footer border color
// $modal-footer-border-color: $modal-header-border-color
// $modal-lg: 900px
// $modal-md: 600px
// $modal-sm: 300px
//== Alerts
//
//## Define alert colors, border radius, and padding.
// $alert-padding: 15px
$alert-border-radius: 0;
// $alert-link-font-weight: bold
// $alert-success-bg: $state-success-bg
// $alert-success-text: $state-success-text
// $alert-success-border: $state-success-border
// $alert-info-bg: $state-info-bg
// $alert-info-text: $state-info-text
// $alert-info-border: $state-info-border
// $alert-warning-bg: $state-warning-bg
// $alert-warning-text: $state-warning-text
// $alert-warning-border: $state-warning-border
// $alert-danger-bg: $state-danger-bg
// $alert-danger-text: $state-danger-text
// $alert-danger-border: $state-danger-border
//== Progress bars
//
//##
//** Background color of the whole progress component
// $progress-bg: #f5f5f5
//** Progress bar text color
// $progress-bar-color: #fff
//** Variable for setting rounded corners on progress bar.
// $progress-border-radius: $border-radius-base
//** Default progress bar color
// $progress-bar-bg: $brand-primary
//** Success progress bar color
// $progress-bar-success-bg: $brand-success
//** Warning progress bar color
// $progress-bar-warning-bg: $brand-warning
//** Danger progress bar color
// $progress-bar-danger-bg: $brand-danger
//** Info progress bar color
// $progress-bar-info-bg: $brand-info
//== List group
//
//##
//** Background color on `.list-group-item`
// $list-group-bg: #fff
//** `.list-group-item` border color
// $list-group-border: #ddd
//** List group border radius
// $list-group-border-radius: $border-radius-base
//** Background color of single list items on hover
// $list-group-hover-bg: #f5f5f5
//** Text color of active list items
// $list-group-active-color: $component-active-color
//** Background color of active list items
// $list-group-active-bg: $component-active-bg
//** Border color of active list elements
// $list-group-active-border: $list-group-active-bg
//** Text color for content within active list items
// $list-group-active-text-color: lighten($list-group-active-bg, 40%)
//** Text color of disabled list items
// $list-group-disabled-color: $gray-light
//** Background color of disabled list items
// $list-group-disabled-bg: $gray-lighter
//** Text color for content within disabled list items
// $list-group-disabled-text-color: $list-group-disabled-color
// $list-group-link-color: #555
// $list-group-link-hover-color: $list-group-link-color
// $list-group-link-heading-color: #333
//== Panels
//
//##
// $panel-bg: #fff
// $panel-body-padding: 15px
// $panel-heading-padding: 10px 15px
// $panel-footer-padding: $panel-heading-padding
$panel-border-radius: 0;
//** Border color for elements within panels
// $panel-inner-border: #ddd
// $panel-footer-bg: #f5f5f5
$panel-default-text: $text-color;
$panel-default-border: $border-color;
$panel-default-heading-bg: $background-color;
// $panel-primary-text: #fff
// $panel-primary-border: $brand-primary
// $panel-primary-heading-bg: $brand-primary
// $panel-success-text: $state-success-text
// $panel-success-border: $state-success-border
// $panel-success-heading-bg: $state-success-bg
// $panel-info-text: $state-info-text
// $panel-info-border: $state-info-border
// $panel-info-heading-bg: $state-info-bg
// $panel-warning-text: $state-warning-text
// $panel-warning-border: $state-warning-border
// $panel-warning-heading-bg: $state-warning-bg
// $panel-danger-text: $state-danger-text
// $panel-danger-border: $state-danger-border
// $panel-danger-heading-bg: $state-danger-bg
//== Thumbnails
//
//##
//** Padding around the thumbnail image
// $thumbnail-padding: 4px
//** Thumbnail background color
// $thumbnail-bg: $body-bg
//** Thumbnail border color
// $thumbnail-border: #ddd
//** Thumbnail border radius
// $thumbnail-border-radius: $border-radius-base
//** Custom text color for thumbnail captions
// $thumbnail-caption-color: $text-color
//** Padding around the thumbnail caption
// $thumbnail-caption-padding: 9px
//== Wells
//
//##
$well-bg: $gray-lighter;
$well-border: transparent;
//== Badges
//
//##
// $badge-color: #fff
//** Linked badge text color on hover
// $badge-link-hover-color: #fff
// $badge-bg: $gray-light
//** Badge text color in active nav link
// $badge-active-color: $link-color
//** Badge background color in active nav link
// $badge-active-bg: #fff
// $badge-font-weight: bold
// $badge-line-height: 1
// $badge-border-radius: 10px
//== Breadcrumbs
//
//##
// $breadcrumb-padding-vertical: 8px
// $breadcrumb-padding-horizontal: 15px
//** Breadcrumb background color
// $breadcrumb-bg: #f5f5f5
//** Breadcrumb text color
// $breadcrumb-color: #ccc
//** Text color of current page in the breadcrumb
// $breadcrumb-active-color: $gray-light
//** Textual separator for between breadcrumb elements
// $breadcrumb-separator: "/"
//== Carousel
//
//##
// $carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6)
// $carousel-control-color: #fff
// $carousel-control-width: 15%
// $carousel-control-opacity: .5
// $carousel-control-font-size: 20px
// $carousel-indicator-active-bg: #fff
// $carousel-indicator-border-color: #fff
// $carousel-caption-color: #fff
//== Close
//
//##
// $close-font-weight: bold
// $close-color: #000
// $close-text-shadow: 0 1px 0 #fff
//== Code
......@@ -837,34 +125,3 @@ $code-bg: #f9f2f4;
$kbd-color: #fff;
$kbd-bg: #333;
$pre-bg: $gray-lighter;
$pre-color: $text-color;
$pre-border-color: #ccc;
// $pre-scrollable-max-height: 340px
//== Type
//
//##
//** Horizontal offset for forms and lists.
// $component-offset-horizontal: 180px
//** Text muted color
// $text-muted: $gray-light
//** Abbreviations and acronyms border color
// $abbr-border-color: $gray-light
//** Headings small color
$headings-small-color: $gray-dark;
//** Blockquote small color
// $blockquote-small-color: $gray-light
//** Blockquote font size
// $blockquote-font-size: ($font-size-base * 1.25)
//** Blockquote border color
// $blockquote-border-color: $gray-lighter
//** Page header border color
// $page-header-border-color: $gray-lighter
//** Width of horizontal description list titles
// $dl-horizontal-offset: $component-offset-horizontal
//** Horizontal line color.
// $hr-border: $gray-lighter
$style_color: #474D57;
$hover: #FFF3EB;
$gl-text-color: #222222;
$gl-link-color: #446e9b;
$nprogress-color: #c0392b;
$gl-font-size: 14px;
......@@ -8,23 +9,18 @@ $sidebar_width: 230px;
$avatar_radius: 50%;
$code_font_size: 13px;
$code_line_height: 1.5;
$border-color: #dce4ec;
$background-color: #ECF0F1;
$border-color: #E5E5E5;
$background-color: #f5f5f5;
/*
* State colors:
*/
$gl-success: #019875;
$gl-danger: #d9534f;
$gl-primary: #446e9b;
$gl-success: #019875;
$gl-info: #029ACF;
$gl-warning: #EB9532;
$gl-danger: #d9534f;
$gl-primary: #2C3E50;
$gl-success: #18BC9C;
$gl-info: #3498DB;
$gl-warning: #F39C12;
$gl-danger: #E74C3C;
/*
* Commit Diff Colors
*/
......
.calendar_onclick_placeholder {
padding: 0 0 2px 0;
}
.calendar_commit_activity {
padding: 5px 0 0;
}
.calendar_onclick_second {
font-size: 14px;
display: block;
}
.calendar_onclick_hr {
padding: 0;
margin: 10px 0;
}
.user-calendar-activities {
.calendar_commit_activity {
padding: 5px 0 0;
}
.calendar_onclick_hr {
padding: 0;
margin: 10px 0;
}
.calendar_commit_date {
color: #999;
}
.calendar_activity_summary {
font-size: 14px;
}
.calendar_commit_date {
color: #999;
}
.str-truncated {
max-width: 70%;
}
.calendar_activity_summary {
font-size: 14px;
.text-expander {
background: #eee;
color: #555;
padding: 0 5px;
cursor: pointer;
margin-left: 4px;
&:hover {
background-color: #ddd;
}
}
.commit-row-message {
color: #333;
&:hover {
color: #444;
text-decoration: underline;
}
}
}
/**
* This overwrites the default values of the cal-heatmap gem
*/
......
......@@ -355,3 +355,22 @@ table {
bottom: 20px !important;
left: 20px !important;
}
.header-with-avatar {
h3 {
margin: 0;
font-weight: bold;
}
.username {
font-size: 18px;
color: #666;
margin-top: 8px;
}
.description {
font-size: 16px;
color: #666;
margin-top: 8px;
}
}
......@@ -94,7 +94,7 @@
}
.author,
.blame_commit {
background: #f5f5f5;
background: $background-color;
vertical-align: top;
}
.lines {
......
......@@ -29,8 +29,8 @@ fieldset legend {
padding: 17px 20px 18px;
margin-top: 18px;
margin-bottom: 18px;
background-color: #ecf0f1;
border-top: 1px solid #e5e5e5;
background-color: $background-color;
border-top: 1px solid $border-color;
}
@media (min-width: $screen-sm-min) {
......
......@@ -35,7 +35,7 @@
color: #8a6d3b;
}
&.smoke { background-color: #f5f5f5; }
&.smoke { background-color: $background-color; }
&:hover {
background: $hover;
......@@ -46,7 +46,7 @@
border-bottom: none;
&.bottom {
background: #f5f5f5;
background: $background-color;
}
}
......@@ -61,7 +61,7 @@
p {
padding-top: 1px;
margin: 0;
color: #222;
color: $gray-dark;
img {
position: relative;
top: 3px;
......@@ -74,9 +74,10 @@
}
.row_title {
color: #444;
color: $gray-dark;
&:hover {
color: #444;
color: $text-color;
text-decoration: underline;
}
}
......
.page-with-sidebar {
background: #F5F5F5;
background: $background-color;
.sidebar-wrapper {
position: fixed;
top: 0;
left: 0;
height: 100%;
border-right: 1px solid #EAEAEA;
border-right: 1px solid $border-color;
}
}
.sidebar-wrapper {
z-index: 99;
background: #F5F5F5;
background: $background-color;
}
.content-wrapper {
......@@ -39,7 +39,7 @@
.nav-sidebar li {
&.active a {
color: #333;
color: $text-color;
background: #FFF !important;
font-weight: bold;
border: 1px solid #EEE;
......@@ -52,32 +52,31 @@
}
i {
color: #444;
color: $text-color;
}
}
}
.nav-sidebar li {
&.separate-item {
border-top: 1px solid #ddd;
border-top: 1px solid $border-color;
padding-top: 10px;
margin-top: 10px;
}
a {
color: #555;
color: $gray;
display: block;
text-decoration: none;
padding: 8px 15px;
font-size: 13px;
line-height: 20px;
text-shadow: 0 1px 2px #FFF;
padding-left: 20px;
&:hover {
text-decoration: none;
color: #333;
background: #EEE;
color: $text-color;
background: $border-color;
}
&:active, &:focus {
......@@ -86,7 +85,7 @@
i {
width: 20px;
color: #888;
color: $gray-light;
margin-right: 23px;
}
}
......@@ -156,18 +155,17 @@
position: fixed;
top: 46px;
padding: 5px 13px 5px 13px;
left: 197px;
left: 198px;
font-size: 13px;
background: #EEE;
background: transparent;
color: black;
border-left: 1px solid rgba(0,0,0,0.035);
border-right: 1px solid rgba(0,0,0,0.035);
border-left: 1px solid $border-color;
border-bottom: 1px solid $border-color;
}
.collapse-nav a:hover {
text-decoration: none;
color: #333;
background: #eaeaea;
background: #f2f6f7;
}
@media (max-width: $screen-md-max) {
......
......@@ -46,55 +46,13 @@
}
}
select {
&.select2 {
width: 100px;
}
&.select2-sm {
width: 100px;
}
}
@media (min-width: $screen-sm-min) {
select {
&.select2 {
width: 150px;
}
&.select2-sm {
width: 120px;
}
}
.select2-container {
width: 100% !important;
}
/* Medium devices (desktops, 992px and up) */
@media (min-width: $screen-md-min) {
select {
&.select2 {
width: 170px;
}
&.select2-sm {
width: 140px;
}
}
}
/* Large devices (large desktops, 1200px and up) */
@media (min-width: $screen-lg-min) {
select {
&.select2 {
width: 200px;
}
&.select2-sm {
width: 150px;
}
}
}
/** Branch/tag selector **/
.project-refs-form .select2-container {
margin-right: 10px;
width: 160px !important;
}
.ajax-users-dropdown, .ajax-project-users-dropdown {
......
......@@ -54,7 +54,7 @@
.timeline-content {
position: relative;
background: #f5f5f6;
background: $background-color;
padding: 10px 15px;
margin-left: 60px;
......@@ -70,7 +70,7 @@
height: 0;
border-style: solid;
border-width: 9px 9px 9px 0;
border-color: transparent #f5f5f6 transparent transparent;
border-color: transparent $background-color transparent transparent;
left: 0;
top: 10px;
margin-left: -9px;
......
......@@ -4,7 +4,6 @@
*/
.page-title {
margin-top: 0px;
color: #333;
line-height: 1.5;
font-weight: normal;
margin-bottom: 5px;
......@@ -16,7 +15,7 @@ pre {
&.dark {
background: #333;
color: #f5f5f5;
color: $background-color;
}
}
......
......@@ -28,6 +28,10 @@
font-size: 14px;
line-height: 24px;
.str-truncated {
max-width: 72%;
}
a {
display: block;
padding: 8px 15px;
......@@ -87,16 +91,3 @@
margin-right: 5px;
width: 16px;
}
.dash-new-project {
background: $gl-success;
border: 1px solid $gl-success;
a {
color: #FFF;
}
}
.dash-list .str-truncated {
max-width: 72%;
}
......@@ -11,8 +11,10 @@
z-index: 10;
> span {
@include str-truncated(65%);
font-family: $monospace_font;
word-break: break-all;
margin-right: 200px;
display: block;
}
.diff-btn-group {
......@@ -89,7 +91,7 @@
margin: 0px;
padding: 0px;
border: none;
background: #F5F5F5;
background: $background-color;
color: rgba(0,0,0,0.3);
padding: 0px 5px;
border-right: 1px solid $border-color;
......
......@@ -37,7 +37,7 @@
}
.editor-ref {
background: #f5f5f5;
background: $background-color;
padding: 11px 15px;
border-right: 1px solid #CCC;
display: inline-block;
......
......@@ -154,10 +154,12 @@
overflow: auto;
.event-last-push-text {
@include str-truncated(100%);
padding: 5px 0;
font-size: 13px;
float:left;
margin-right: -150px;
padding-right: 150px;
line-height: 24px;
line-height: 20px;
}
}
......@@ -188,7 +190,7 @@
li a {
font-size: 13px;
padding: 5px 10px;
background: rgba(0,0,0,0.045);
background: $background-color;
margin-left: 4px;
}
}
.new-group-member-holder {
margin-top: 50px;
background: #f9f9f9;
padding-top: 20px;
}
......
......@@ -31,7 +31,7 @@ header {
.navbar-toggle {
color: $style_color;
margin: 0 -15px 0 0;
margin: 0;
padding: 10px;
border-radius: 0;
......
......@@ -25,7 +25,7 @@
}
.issuable-context-title {
font-size: 15px;
font-size: 14px;
line-height: 1.4;
margin-bottom: 5px;
......@@ -39,3 +39,9 @@
margin-right: 4px;
}
}
.issuable-affix .context {
font-size: 13px;
.btn { font-size: 13px; }
}
......@@ -59,33 +59,34 @@
}
}
@media (min-width: 800px) { .issues_filters select { width: 160px; } }
@media (min-width: 1200px) { .issues_filters select { width: 220px; } }
@media (min-width: 800px) {
.issues_bulk_update {
select, .select2-container {
width: 120px !important;
display: inline-block;
}
}
}
@media (min-width: 800px) { .issues_bulk_update .select2-container { min-width: 120px; } }
@media (min-width: 1200px) { .issues_bulk_update .select2-container { min-width: 160px; } }
@media (min-width: 1200px) {
.issues_bulk_update {
select, .select2-container {
width: 160px !important;
display: inline-block;
}
}
}
.issues_bulk_update {
.select2-container .select2-choice {
color: #444 !important;
font-weight: 500;
}
}
#update_status {
width: 100px;
}
.participants {
margin-bottom: 20px;
}
.issues_bulk_update {
.select2-container {
text-shadow: none;
}
}
.issue-search-form {
margin: 0;
height: 24px;
......@@ -177,6 +178,6 @@ h2.issue-title {
font-weight: bold;
}
.context .select2-container {
width: 100% !important;
.issue-form .select2-container {
width: 250px !important;
}
......@@ -129,7 +129,7 @@
font-size: 15px;
border-bottom: 1px solid #BBB;
color: #777;
background-color: #F5F5F5;
background-color: $background-color;
&.ci-success {
color: $gl-success;
......@@ -155,6 +155,12 @@
background-color: #FAF1F1;
}
&.ci-canceled {
color: $gl-warning;
border-color: $gl-danger;
background-color: #FAF5F1;
}
&.ci-error {
color: $gl-danger;
border-color: $gl-danger;
......@@ -194,3 +200,7 @@
}
}
}
.merge-request-form .select2-container {
width: 250px !important;
}
......@@ -41,11 +41,6 @@
}
}
.user-show-username {
font-weight: 200;
color: #666;
}
/*
* Appearance settings
*
......
......@@ -49,16 +49,20 @@
@extend .clearfix;
margin-bottom: 15px;
.project-home-desc,
.star-fork-buttons {
font-size: 16px;
line-height: 1.3;
}
.project-home-desc {
float: left;
color: #666;
font-size: 16px;
}
.star-fork-buttons {
float: right;
min-width: 200px;
font-size: 14px;
font-weight: bold;
.star-buttons, .fork-buttons {
......
......@@ -27,7 +27,7 @@
}
&.selected {
td {
background: #f5f5f5;
background: $background-color;
border-top: 1px solid #EEE;
border-bottom: 1px solid #EEE;
}
......@@ -112,7 +112,7 @@
.tree-ref-holder {
float: left;
margin-right: 6px;
margin-right: 15px;
.select2-container .select2-choice, .select2-container.select2-drop-above .select2-choice {
padding: 4px 12px;
......
.votes {
font-size: 13px;
line-height: 15px;
.progress {
height: 4px;
margin: 0;
.bar {
float: left;
height: 100%;
}
.bar-success {
@include linear-gradient(#62C462, #51A351);
background-color: #468847;
}
.bar-danger {
@include linear-gradient(#EE5F5B, #BD362F);
background-color: #B94A48;
}
}
.upvotes {
display: inline-block;
color: #468847;
}
.downvotes {
display: inline-block;
color: #B94A48;
}
}
.votes-block {
margin: 6px;
.downvotes {
float: right;
}
}
.votes-inline {
display: inline-block;
margin: 0 8px;
}
......@@ -25,7 +25,8 @@ class ProfilesController < ApplicationController
if @user.update_attributes(user_params)
flash[:notice] = "Profile was successfully updated"
else
flash[:alert] = "Failed to update profile"
messages = @user.errors.full_messages.uniq.join('. ')
flash[:alert] = "Failed to update profile. #{messages}"
end
respond_to do |format|
......@@ -68,7 +69,7 @@ class ProfilesController < ApplicationController
params.require(:user).permit(
:email, :password, :password_confirmation, :bio, :name, :username,
:skype, :linkedin, :twitter, :website_url, :color_scheme_id, :theme_id,
:avatar, :hide_no_ssh_key, :hide_no_password
:avatar, :hide_no_ssh_key, :hide_no_password, :location
)
end
end
......@@ -160,10 +160,10 @@ class Projects::MergeRequestsController < Projects::ApplicationController
def ci_status
ci_service = @merge_request.source_project.ci_service
status = ci_service.commit_status(merge_request.last_commit.sha)
status = ci_service.commit_status(merge_request.last_commit.sha, merge_request.source_branch)
if ci_service.respond_to?(:commit_coverage)
coverage = ci_service.commit_coverage(merge_request.last_commit.sha)
coverage = ci_service.commit_coverage(merge_request.last_commit.sha, merge_request.source_branch)
end
response = {
......
......@@ -53,7 +53,7 @@ class Projects::ServicesController < Projects::ApplicationController
:description, :issues_url, :new_issue_url, :restrict_to_branch, :channel,
:colorize_messages, :channels,
:push_events, :issues_events, :merge_requests_events, :tag_push_events,
:note_events, :send_from_committer_email, :disable_diffs
:note_events, :send_from_committer_email, :disable_diffs, :external_wiki_url
)
end
end
......@@ -2,34 +2,34 @@ class SearchController < ApplicationController
include SearchHelper
def show
return if params[:search].nil? || params[:search].blank?
@project = Project.find_by(id: params[:project_id]) if params[:project_id].present?
@group = Group.find_by(id: params[:group_id]) if params[:group_id].present?
@scope = params[:scope]
@show_snippets = params[:snippets].eql? 'true'
@search_results = if @project
return access_denied! unless can?(current_user, :download_code, @project)
unless %w(blobs notes issues merge_requests wiki_blobs).
include?(@scope)
@scope = 'blobs'
end
Search::ProjectService.new(@project, current_user, params).execute
elsif @show_snippets
unless %w(snippet_blobs snippet_titles).include?(@scope)
@scope = 'snippet_blobs'
end
Search::SnippetService.new(current_user, params).execute
else
unless %w(projects issues merge_requests).include?(@scope)
@scope = 'projects'
end
Search::GlobalService.new(current_user, params).execute
end
@search_results =
if @project
return access_denied! unless can?(current_user, :download_code, @project)
unless %w(blobs notes issues merge_requests wiki_blobs).
include?(@scope)
@scope = 'blobs'
end
Search::ProjectService.new(@project, current_user, params).execute
elsif @show_snippets
unless %w(snippet_blobs snippet_titles).include?(@scope)
@scope = 'snippet_blobs'
end
Search::SnippetService.new(current_user, params).execute
else
unless %w(projects issues merge_requests).include?(@scope)
@scope = 'projects'
end
Search::GlobalService.new(current_user, params).execute
end
@objects = @search_results.objects(@scope, params[:page])
end
......
......@@ -32,6 +32,7 @@ class UsersController < ApplicationController
def calendar
projects = Project.where(id: authorized_projects_ids & @user.contributed_projects_ids)
calendar = Gitlab::CommitsCalendar.new(projects, @user)
@timestamps = calendar.timestamps
@starting_year = calendar.starting_year
......@@ -40,6 +41,24 @@ class UsersController < ApplicationController
render 'calendar', layout: false
end
def calendar_activities
projects = Project.where(id: authorized_projects_ids & @user.contributed_projects_ids)
date = Date.parse(params[:date]) rescue nil
if date
@calendar_activities = Gitlab::CommitsCalendar.get_commits_for_date(projects, @user, date)
else
@calendar_activities = {}
end
# get the total number of unique commits
@commit_count = @calendar_activities.values.flatten.map(&:id).uniq.count
@calendar_date = date
render 'calendar_activities', layout: false
end
def determine_layout
if current_user
'navless'
......
......@@ -96,7 +96,7 @@ module EventsHelper
end
end
elsif event.push?
if event.push_with_commits?
if event.push_with_commits? && event.md_ref?
if event.commits_count > 1
namespace_project_compare_url(event.project.namespace, event.project,
from: event.commit_from, to:
......
module ExternalWikiHelper
def get_project_wiki_path(project)
external_wiki_service = project.services.
select { |service| service.to_param == 'external_wiki' }.first
if external_wiki_service.present? && external_wiki_service.active?
external_wiki_service.properties['external_wiki_url']
else
namespace_project_wiki_path(project.namespace, project, :home)
end
end
end
......@@ -47,6 +47,5 @@ module GitlabRoutingHelper
def project_snippet_url(entity, *args)
namespace_project_snippet_url(entity.project.namespace, entity.project, entity, *args)
end
end
......@@ -35,7 +35,7 @@ module MergeRequestsHelper
end
def ci_build_details_path(merge_request)
merge_request.source_project.ci_service.build_page(merge_request.last_commit.sha)
merge_request.source_project.ci_service.build_page(merge_request.last_commit.sha, merge_request.source_branch)
end
def merge_path_description(merge_request, separator)
......
......@@ -232,12 +232,45 @@ module ProjectsHelper
end
def contribution_guide_url(project)
if project && project.repository.contribution_guide
if project && contribution_guide = project.repository.contribution_guide
namespace_project_blob_path(
project.namespace,
project,
tree_join(project.default_branch,
project.repository.contribution_guide.name)
contribution_guide.name)
)
end
end
def changelog_url(project)
if project && changelog = project.repository.changelog
namespace_project_blob_path(
project.namespace,
project,
tree_join(project.default_branch,
changelog.name)
)
end
end
def license_url(project)
if project && license = project.repository.license
namespace_project_blob_path(
project.namespace,
project,
tree_join(project.default_branch,
license.name)
)
end
end
def version_url(project)
if project && version = project.repository.version
namespace_project_blob_path(
project.namespace,
project,
tree_join(project.default_branch,
version.name)
)
end
end
......
......@@ -247,7 +247,7 @@ class Event < ActiveRecord::Base
end
def push_with_commits?
md_ref? && commits.any? && commit_from && commit_to
!commits.empty? && commit_from && commit_to
end
def last_push_to_non_root?
......
......@@ -95,11 +95,11 @@ class MergeRequest < ActiveRecord::Base
end
event :mark_as_mergeable do
transition unchecked: :can_be_merged
transition [:unchecked, :cannot_be_merged] => :can_be_merged
end
event :mark_as_unmergeable do
transition unchecked: :cannot_be_merged
transition [:unchecked, :can_be_merged] => :cannot_be_merged
end
state :unchecked
......
......@@ -59,7 +59,7 @@ class Note < ActiveRecord::Base
class << self
def create_status_change_note(noteable, project, author, status, source)
body = "_Status changed to #{status}#{' by ' + source.gfm_reference if source}_"
body = "Status changed to #{status}#{' by ' + source.gfm_reference if source}"
create(
noteable: noteable,
......@@ -95,9 +95,9 @@ class Note < ActiveRecord::Base
def create_milestone_change_note(noteable, project, author, milestone)
body = if milestone.nil?
'_Milestone removed_'
'Milestone removed'
else
"_Milestone changed to #{milestone.title}_"
"Milestone changed to #{milestone.title}"
end
create(
......@@ -110,7 +110,7 @@ class Note < ActiveRecord::Base
end
def create_assignee_change_note(noteable, project, author, assignee)
body = assignee.nil? ? '_Assignee removed_' : "_Reassigned to @#{assignee.username}_"
body = assignee.nil? ? 'Assignee removed' : "Reassigned to @#{assignee.username}"
create({
noteable: noteable,
......@@ -140,7 +140,7 @@ class Note < ActiveRecord::Base
end
message << ' ' << 'label'.pluralize(labels_count)
body = "_#{message.capitalize}_"
body = "#{message.capitalize}"
create(
noteable: noteable,
......@@ -151,7 +151,7 @@ class Note < ActiveRecord::Base
)
end
def create_new_commits_note(merge_request, project, author, new_commits, existing_commits = [])
def create_new_commits_note(merge_request, project, author, new_commits, existing_commits = [], oldrev = nil)
total_count = new_commits.length + existing_commits.length
commits_text = ActionController::Base.helpers.pluralize(total_count, 'commit')
body = "Added #{commits_text}:\n\n"
......@@ -161,19 +161,23 @@ class Note < ActiveRecord::Base
if existing_commits.length == 1
existing_commits.first.short_id
else
"#{existing_commits.first.short_id}..#{existing_commits.last.short_id}"
if oldrev
"#{Commit.truncate_sha(oldrev)}...#{existing_commits.last.short_id}"
else
"#{existing_commits.first.short_id}..#{existing_commits.last.short_id}"
end
end
commits_text = ActionController::Base.helpers.pluralize(existing_commits.length, 'commit')
branch =
branch =
if merge_request.for_fork?
"#{merge_request.target_project_namespace}:#{merge_request.target_branch}"
else
merge_request.target_branch
end
message = "* #{commit_ids} - _#{commits_text} from branch `#{branch}`_"
message = "* #{commit_ids} - #{commits_text} from branch `#{branch}`"
body << message
body << "\n"
end
......@@ -236,7 +240,7 @@ class Note < ActiveRecord::Base
where(noteable_id: noteable.id)
end
notes.where('note like ?', cross_reference_note_content(gfm_reference)).
notes.where('note like ?', cross_reference_note_pattern(gfm_reference)).
system.any?
end
......@@ -245,13 +249,18 @@ class Note < ActiveRecord::Base
end
def cross_reference_note_prefix
'_mentioned in '
'mentioned in '
end
private
def cross_reference_note_content(gfm_reference)
cross_reference_note_prefix + "#{gfm_reference}_"
cross_reference_note_prefix + "#{gfm_reference}"
end
def cross_reference_note_pattern(gfm_reference)
# Older cross reference notes contained underscores for emphasis
"%" + cross_reference_note_content(gfm_reference) + "%"
end
# Prepend the mentioner's namespaced project path to the GFM reference for
......
......@@ -89,6 +89,7 @@ class Project < ActiveRecord::Base
has_one :redmine_service, dependent: :destroy
has_one :custom_issue_tracker_service, dependent: :destroy
has_one :gitlab_issue_tracker_service, dependent: :destroy
has_one :external_wiki_service, dependent: :destroy
has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id"
......
......@@ -17,6 +17,15 @@ class ProjectContributions
end
end
def user_commits_on_date(date)
repository = @project.repository
if !repository.exists? || repository.empty?
return []
end
commits = repository.commits_by_user_on_date_log(@user, date)
end
def cache_key
"#{Date.today.to_s}-commits-log-#{project.id}-#{user.email}"
end
......
......@@ -93,7 +93,7 @@ class BambooService < CiService
end
end
def build_page(sha)
def build_page(sha, ref)
build_info(sha) if @response.nil? || !@response.code
if @response.code != 200 || @response['results']['results']['size'] == '0'
......@@ -106,7 +106,7 @@ class BambooService < CiService
end
end
def commit_status(sha)
def commit_status(sha, ref)
build_info(sha) if @response.nil? || !@response.code
return :error unless @response.code == 200 || @response.code == 404
......
......@@ -48,7 +48,7 @@ class BuildboxService < CiService
service_hook.execute(data)
end
def commit_status(sha)
def commit_status(sha, ref)
response = HTTParty.get(commit_status_path(sha), verify: false)
if response.code == 200 && response['status']
......@@ -62,7 +62,7 @@ class BuildboxService < CiService
"#{buildbox_endpoint('gitlab')}/status/#{status_token}.json?commit=#{sha}"
end
def build_page(sha)
def build_page(sha, ref)
"#{project_url}/builds?commit=#{sha}"
end
......
......@@ -34,7 +34,7 @@ class CiService < Service
# Ex.
# http://jenkins.example.com:8888/job/test1/scm/bySHA1/12d65c
#
def build_page(sha)
def build_page(sha, ref)
# implement inside child
end
......@@ -51,7 +51,7 @@ class CiService < Service
# # => 'running'
#
#
def commit_status(sha)
def commit_status(sha, ref)
# implement inside child
end
end
# == Schema Information
#
# Table name: services
#
# id :integer not null, primary key
# type :string(255)
# title :string(255)
# project_id :integer not null
# created_at :datetime
# updated_at :datetime
# active :boolean default(FALSE), not null
# properties :text
#
class ExternalWikiService < Service
include HTTParty
prop_accessor :external_wiki_url
validates :external_wiki_url,
presence: true,
format: { with: URI::regexp },
if: :activated?
def title
'External Wiki'
end
def description
'Replaces the link to the internal wiki with a link to an external wiki.'
end
def to_param
'external_wiki'
end
def fields
[
{ type: 'text', name: 'external_wiki_url', placeholder: 'The URL of the external Wiki' },
]
end
def execute(_data)
@response = HTTParty.get(properties['external_wiki_url'], verify: true) rescue nil
if @response !=200
nil
end
end
end
......@@ -40,17 +40,17 @@ class GitlabCiService < CiService
service_hook.execute(data)
end
def commit_status_path(sha)
project_url + "/commits/#{sha}/status.json?token=#{token}"
def commit_status_path(sha, ref)
project_url + "/refs/#{ref}/commits/#{sha}/status.json?token=#{token}"
end
def get_ci_build(sha)
def get_ci_build(sha, ref)
@ci_builds ||= {}
@ci_builds[sha] ||= HTTParty.get(commit_status_path(sha), verify: false)
@ci_builds[sha] ||= HTTParty.get(commit_status_path(sha, ref), verify: false)
end
def commit_status(sha)
response = get_ci_build(sha)
def commit_status(sha, ref)
response = get_ci_build(sha, ref)
if response.code == 200 and response["status"]
response["status"]
......@@ -59,16 +59,16 @@ class GitlabCiService < CiService
end
end
def commit_coverage(sha)
response = get_ci_build(sha)
def commit_coverage(sha, ref)
response = get_ci_build(sha, ref)
if response.code == 200 and response["coverage"]
response["coverage"]
end
end
def build_page(sha)
project_url + "/commits/#{sha}"
def build_page(sha, ref)
project_url + "/refs/#{ref}/commits/#{sha}"
end
def builds_path
......
......@@ -88,7 +88,7 @@ class TeamcityService < CiService
@response = HTTParty.get("#{url}", verify: false, basic_auth: auth)
end
def build_page(sha)
def build_page(sha, ref)
build_info(sha) if @response.nil? || !@response.code
if @response.code != 200
......@@ -103,7 +103,7 @@ class TeamcityService < CiService
end
end
def commit_status(sha)
def commit_status(sha, ref)
build_info(sha) if @response.nil? || !@response.code
return :error unless @response.code == 200 || @response.code == 404
......
......@@ -122,7 +122,7 @@ class Repository
def expire_cache
%i(size branch_names tag_names commit_count graph_log
readme version contribution_guide).each do |key|
readme version contribution_guide changelog license).each do |key|
cache.expire(key)
end
end
......@@ -157,6 +157,20 @@ class Repository
end
end
def commits_by_user_on_date_log(user, date)
# format the date string for git
start_date = date.strftime("%Y-%m-%d 00:00:00")
end_date = date.strftime("%Y-%m-%d 23:59:59")
author_emails = '(' + user.all_emails.map{ |e| Regexp.escape(e) }.join('|') + ')'
args = %W(git log -E --author=#{author_emails} --after=#{start_date.to_s} --until=#{end_date.to_s} --branches --pretty=format:%h)
commits = Gitlab::Popen.popen(args, path_to_repo).first.split("\n")
commits.map! do |commit_id|
commit(commit_id)
end
end
def commits_per_day_for_user(user)
timestamps_by_user_log(user).
group_by { |commit_date| commit_date }.
......@@ -197,7 +211,27 @@ class Repository
end
def contribution_guide
cache.fetch(:contribution_guide) { tree(:head).contribution_guide }
cache.fetch(:contribution_guide) do
tree(:head).blobs.find do |file|
file.contributing?
end
end
end
def changelog
cache.fetch(:changelog) do
tree(:head).blobs.find do |file|
file.name =~ /^(changelog|history)/i
end
end
end
def license
cache.fetch(:license) do
tree(:head).blobs.find do |file|
file.name =~ /^license/i
end
end
end
def head_commit
......
......@@ -112,7 +112,7 @@ class Service < ActiveRecord::Base
def async_execute(data)
return unless supported_events.include?(data[:object_kind])
Sidekiq::Client.enqueue(ProjectServiceWorker, id, data)
end
......@@ -121,9 +121,27 @@ class Service < ActiveRecord::Base
end
def self.available_services_names
%w(gitlab_ci campfire hipchat pivotaltracker flowdock assembla asana
emails_on_push gemnasium slack pushover buildbox bamboo teamcity jira
redmine custom_issue_tracker irker)
%w(
gitlab_ci
campfire
hipchat
pivotaltracker
flowdock
assembla
asana
emails_on_push
gemnasium
slack
pushover
buildbox
bamboo
teamcity
jira
redmine
custom_issue_tracker
irker
external_wiki
)
end
def self.create_from_template(project_id, template)
......
class Tree
include Gitlab::MarkdownHelper
attr_accessor :entries, :readme, :contribution_guide
attr_accessor :repository, :sha, :path, :entries
def initialize(repository, sha, path = '/')
path = '/' if path.blank?
git_repo = repository.raw_repository
@entries = Gitlab::Git::Tree.where(git_repo, sha, path)
available_readmes = @entries.select(&:readme?)
if available_readmes.count > 0
# If there is more than 1 readme in tree, find readme which is supported
# by markup renderer.
if available_readmes.length > 1
supported_readmes = available_readmes.select do |readme|
previewable?(readme.name)
end
# Take the first supported readme, or the first available readme, if we
# don't support any of them
readme_tree = supported_readmes.first || available_readmes.first
else
readme_tree = available_readmes.first
end
readme_path = path == '/' ? readme_tree.name : File.join(path, readme_tree.name)
@readme = Gitlab::Git::Blob.find(git_repo, sha, readme_path)
end
@repository = repository
@sha = sha
@path = path
git_repo = @repository.raw_repository
@entries = Gitlab::Git::Tree.where(git_repo, @sha, @path)
end
def readme
return @readme if defined?(@readme)
if contribution_tree = @entries.find(&:contributing?)
contribution_path = path == '/' ? contribution_tree.name : File.join(path, contribution_tree.name)
@contribution_guide = Gitlab::Git::Blob.find(git_repo, sha, contribution_path)
available_readmes = blobs.select(&:readme?)
if available_readmes.count == 0
return @readme = nil
end
# Take the first previewable readme, or the first available readme, if we
# can't preview any of them
readme_tree = available_readmes.find do |readme|
previewable?(readme.name)
end || available_readmes.first
readme_path = path == '/' ? readme_tree.name : File.join(path, readme_tree.name)
git_repo = repository.raw_repository
@readme = Gitlab::Git::Blob.find(git_repo, sha, readme_path)
end
def trees
......
......@@ -109,7 +109,7 @@ class GitPushService
def push_to_existing_branch?(ref, oldrev)
# Return if this is not a push to a branch (e.g. new commits)
Gitlab::Git.branch_ref?(ref) && oldrev != Gitlab::Git::BLANK_SHA
Gitlab::Git.branch_ref?(ref) && !Gitlab::Git.blank_ref?(oldrev)
end
def push_to_new_branch?(ref, oldrev)
......
......@@ -89,7 +89,7 @@ module MergeRequests
end
Note.create_new_commits_note(merge_request, merge_request.project,
@current_user, new_commits, existing_commits)
@current_user, new_commits, existing_commits, @oldrev)
end
end
......
......@@ -120,7 +120,7 @@ class NotificationService
return true unless note.noteable_type.present?
# ignore gitlab service messages
return true if note.note.start_with?('_Status changed to closed_')
return true if note.note.start_with?('Status changed to closed')
return true if note.cross_reference? && note.system == true
opts = { noteable_type: note.noteable_type, project_id: note.project_id }
......
......@@ -12,13 +12,13 @@
.checkbox
= f.label :signup_enabled do
= f.check_box :signup_enabled
Signin enabled
Signup enabled
.form-group
.col-sm-offset-2.col-sm-10
.checkbox
= f.label :signin_enabled do
= f.check_box :signin_enabled
Signup enabled
Signin enabled
.form-group
.col-sm-offset-2.col-sm-10
.checkbox
......
......@@ -3,8 +3,8 @@
.input-group
= search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control'
- if current_user.can_create_project?
.input-group-addon.dash-new-project
= link_to new_project_path do
%strong New project
%span.input-group-btn
= link_to new_project_path, class: 'btn btn-success' do
New project
= render 'shared/projects_list', projects: @projects, projects_limit: 20
......@@ -8,9 +8,9 @@
.input-group
= search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control'
- if current_user.can_create_project?
.input-group-addon.dash-new-project
= link_to new_project_path do
%strong New project
%span.input-group-btn
= link_to new_project_path, class: 'btn btn-success' do
New project
= render 'shared/projects_list', projects: @projects,
projects_limit: 20, stars: true, avatar: false
......
......@@ -21,5 +21,11 @@
%li.commits-stat
- if event.commits_count > 2
%span ... and #{event.commits_count - 2} more commits.
= link_to namespace_project_compare_path(event.project.namespace, event.project, from: event.commit_from, to: event.commit_to) do
%strong Compare &rarr; #{truncate_sha(event.commit_from)}...#{truncate_sha(event.commit_to)}
- if event.md_ref?
- from = event.commit_from
- from_label = truncate_sha(from)
- else
- from = event.project.default_branch
- from_label = from
= link_to namespace_project_compare_path(event.project.namespace, event.project, from: from, to: event.commit_to) do
%strong Compare &rarr; #{from_label}...#{truncate_sha(event.commit_to)}
......@@ -3,8 +3,8 @@
.input-group
= search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control'
- if can? current_user, :create_projects, @group
.input-group-addon.dash-new-project
= link_to new_project_path(namespace_id: @group.id) do
%strong New project
%span.input-group-btn
= link_to new_project_path(namespace_id: @group.id), class: 'btn btn-success' do
New project
= render 'shared/projects_list', projects: @projects, projects_limit: 20
......@@ -31,7 +31,9 @@
%i.fa.fa-minus.fa-inverse
.edit-member.hide.js-toggle-content
%br
= form_for [@group, member], remote: true do |f|
.alert.prepend-top-20
= f.select :access_level, options_for_select(GroupMember.access_level_roles, member.access_level)
.prepend-top-10
= f.select :access_level, options_for_select(GroupMember.access_level_roles, member.access_level), {}, class: 'form-control'
.prepend-top-10
= f.submit 'Save', class: 'btn btn-save btn-sm'
.dashboard
%div
.header-with-avatar.clearfix
= image_tag group_icon(@group), class: "avatar group-avatar s90"
.clearfix
%h2
= @group.name
- if @group.description.present?
%p
= escaped_autolink(@group.description)
%h3
= @group.name
.username
@#{@group.path}
- if @group.description.present?
.description
= escaped_autolink(@group.description)
%hr
.row
%section.activities.col-md-8
......
......@@ -75,7 +75,7 @@
- if project_nav_tab? :wiki
= nav_link(controller: :wikis) do
= link_to namespace_project_wiki_path(@project.namespace, @project, :home), title: 'Wiki', class: 'shortcuts-wiki' do
= link_to get_project_wiki_path(@project), title: 'Wiki', class: 'shortcuts-wiki' do
%i.fa.fa-book
%span
Wiki
......
......@@ -6,10 +6,10 @@
= @project.name_with_namespace
%p
To update the remote url in your local repository run (for ssh):
%p{ style: "background:#f5f5f5; padding:10px; border:1px solid #ddd" }
%p{ style: "background: #f5f5f5; padding:10px; border:1px solid #ddd" }
git remote set-url origin #{@project.ssh_url_to_repo}
%p
or for http(s):
%p{ style: "background:#f5f5f5; padding:10px; border:1px solid #ddd" }
%p{ style: "background: #f5f5f5; padding:10px; border:1px solid #ddd" }
git remote set-url origin #{@project.http_url_to_repo}
%br
......@@ -53,6 +53,9 @@
.form-group
= f.label :website_url, 'Website', class: "control-label"
.col-sm-10= f.text_field :website_url, class: "form-control"
.form-group
= f.label :location, 'Location', class: "control-label"
.col-sm-10= f.text_field :location, class: "form-control"
.form-group
= f.label :bio, class: "control-label"
.col-sm-10
......
......@@ -2,8 +2,5 @@
.commit-button-annotation
= button_tag 'Commit Changes',
class: 'btn commit-btn js-commit-button btn-create'
.message
to branch
%strong= ref
= link_to 'Cancel', cancel_path,
class: 'btn btn-cancel', data: {confirm: leave_edit_message}
......@@ -71,10 +71,10 @@
= link_to 'Create new label', new_namespace_project_label_path(issuable.project.namespace, issuable.project), target: :blank
.form-actions
- if !issuable.project.empty_repo? && contribution_guide_url(issuable.project) && !issuable.persisted?
- if !issuable.project.empty_repo? && (guide_url = contribution_guide_url(issuable.project)) && !issuable.persisted?
%p
Please review the
%strong #{link_to 'guidelines for contribution', contribution_guide_url(issuable.project)}
%strong #{link_to 'guidelines for contribution', guide_url}
to this repository.
- if issuable.new_record?
= f.submit "Submit new #{issuable.class.model_name.human.downcase}", class: 'btn btn-create'
......
.row
.row.prepend-top-20.append-bottom-10
.col-md-8
= render 'projects/diffs/stats', diffs: diffs
.col-md-4
......
......@@ -22,14 +22,8 @@
.diff-btn-group
- if blob.text?
- unless params[:view] == 'parallel'
%label
= check_box_tag nil, 1, false, class: 'js-toggle-diff-line-wrap'
Wrap text
&nbsp;
= link_to '#', class: 'js-toggle-diff-comments btn btn-sm' do
%i.fa.fa-chevron-down
Show/Hide comments
= link_to '#', class: 'js-toggle-diff-comments btn btn-sm active has_tooltip', title: "Toggle comments for this file" do
%i.fa.fa-comments
&nbsp;
- if @merge_request && @merge_request.source_project
......@@ -39,7 +33,7 @@
= view_file_btn(@commit.id, diff_file, project)
.diff-content
.diff-content.diff-wrap-lines
-# Skipp all non non-supported blobs
- return unless blob.respond_to?('text?')
- if blob.text?
......
.js-toggle-container
.commit-stat-summary
Showing
%strong.cdark #{pluralize(diffs.count, "changed file")}
= link_to '#', class: 'js-toggle-button' do
%strong #{pluralize(diffs.count, "changed file")}
- if current_controller?(:commit)
- unless @commit.has_zero_stats?
with
%strong.cgreen #{@commit.stats.additions} additions
and
%strong.cred #{@commit.stats.deletions} deletions
&nbsp;
= link_to '#', class: 'btn btn-sm js-toggle-button' do
Show diff stats
%i.fa.fa-chevron-down
.file-stats.js-toggle-content.hide
%ul.bordered-list
- diffs.each_with_index do |diff, i|
......
......@@ -6,11 +6,12 @@
= link_to 'Close Issue', issue_path(@issue, issue: {state_event: :close }, status_only: true), method: :put, class: "btn btn-grouped btn-close js-note-target-close", title: "Close Issue"
.row
%section.col-md-9
.votes-holder.pull-right
#votes= render 'votes/votes_block', votable: @issue
.participants
%span= pluralize(@issue.participants.count, 'participant')
- @issue.participants.each do |participant|
= link_to_member(@project, participant, name: false, size: 24)
.voting_notes#notes= render "projects/notes/notes_with_form"
%aside.col-md-3
.issuable-affix
......@@ -20,15 +21,10 @@
%hr
.context
= render partial: 'issue_context', locals: { issue: @issue }
%hr
.clearfix
.votes-holder
%h6 Votes
#votes= render 'votes/votes_block', votable: @issue
- if @issue.labels.any?
%hr
%h6 Labels
.issuable-context-title
%label Labels
.issue-show-labels
- @issue.labels.each do |label|
= link_to namespace_project_issues_path(@project.namespace, @project, label_name: label.name) do
......
......@@ -17,7 +17,7 @@
= issue.notes.count
.issue-info
%span.light= "##{issue.iid}"
= link_to "##{issue.iid}", issue_path(issue), class: "light"
- if issue.assignee
assigned to #{link_to_member(@project, issue.assignee)}
- if issue.votes_count > 0
......
......@@ -27,22 +27,23 @@
= hidden_field_tag :issue_context
= f.submit class: 'btn'
%div.prepend-top-20.clearfix
.issuable-context-title
%label
Subscription:
%button.btn.btn-block.subscribe-button
%i.fa.fa-eye
%span= @issue.subscribed?(current_user) ? "Unsubscribe" : "Subscribe"
- subscribtion_status = @issue.subscribed?(current_user) ? "subscribed" : "unsubscribed"
.subscription-status{"data-status" => subscribtion_status}
.description-block.unsubscribed{class: ( "hidden" if @issue.subscribed?(current_user) )}
You're not receiving notifications from this thread.
.description-block.subscribed{class: ( "hidden" unless @issue.subscribed?(current_user) )}
You're receiving notifications because you're subscribed to this thread.
- if current_user
%div.prepend-top-20.clearfix
.issuable-context-title
%label
Subscription:
%button.btn.btn-block.subscribe-button
%i.fa.fa-eye
%span= @issue.subscribed?(current_user) ? "Unsubscribe" : "Subscribe"
- subscribtion_status = @issue.subscribed?(current_user) ? "subscribed" : "unsubscribed"
.subscription-status{"data-status" => subscribtion_status}
.description-block.unsubscribed{class: ( "hidden" if @issue.subscribed?(current_user) )}
You're not receiving notifications from this thread.
.description-block.subscribed{class: ( "hidden" unless @issue.subscribed?(current_user) )}
You're receiving notifications because you're subscribed to this thread.
:coffeescript
$ ->
new Subscription("#{toggle_subscription_namespace_project_issue_path(@issue.project.namespace, @project, @issue)}")
\ No newline at end of file
......@@ -18,7 +18,7 @@
.clearfix
.issues_bulk_update.hide
= form_tag bulk_update_namespace_project_issues_path(@project.namespace, @project), method: :post do
= select_tag('update[state_event]', options_for_select([['Open', 'reopen'], ['Closed', 'close']]), prompt: "Status")
= select_tag('update[state_event]', options_for_select([['Open', 'reopen'], ['Closed', 'close']]), prompt: "Status", class: 'form-control')
= project_users_select_tag('update[assignee_id]', placeholder: 'Assignee')
= select_tag('update[milestone_id]', bulk_update_milestone_options, prompt: "Milestone")
= hidden_field_tag 'update[issues_ids]', []
......
......@@ -7,6 +7,8 @@
.row
%section.col-md-9
.votes-holder.pull-right
#votes= render 'votes/votes_block', votable: @merge_request
= render "projects/merge_requests/show/participants"
= render "projects/notes/notes_with_form"
%aside.col-md-3
......@@ -17,14 +19,10 @@
%hr
.context
= render partial: 'projects/merge_requests/show/context', locals: { merge_request: @merge_request }
%hr
.votes-holder
%h6 Votes
#votes= render 'votes/votes_block', votable: @merge_request
- if @merge_request.labels.any?
%hr
%h6 Labels
.issuable-context-title
%label Labels
.merge-request-show-labels
- @merge_request.labels.each do |label|
= link_to namespace_project_merge_requests_path(@project.namespace, @project, label_name: label.name) do
......
......@@ -22,7 +22,7 @@
%i.fa.fa-comments
= merge_request.mr_and_commit_notes.count
.merge-request-info
%span.light= "##{merge_request.iid}"
= link_to "##{merge_request.iid}", merge_request_path(merge_request), class: "light"
- if merge_request.assignee
assigned to #{link_to_member(merge_request.source_project, merge_request.assignee)}
- else
......
......@@ -69,10 +69,10 @@
= link_to 'Create new label', new_namespace_project_label_path(@merge_request.target_project.namespace, @merge_request.target_project), target: :blank
.form-actions
- if contribution_guide_url(@target_project)
- if guide_url = contribution_guide_url(@target_project)
%p
Please review the
%strong #{link_to 'guidelines for contribution', contribution_guide_url(@target_project)}
%strong #{link_to 'guidelines for contribution', guide_url}
to this repository.
= f.hidden_field :source_project_id
= f.hidden_field :source_branch
......
......@@ -29,19 +29,20 @@
= hidden_field_tag :merge_request_context
= f.submit class: 'btn'
%div.prepend-top-20.clearfix
.issuable-context-title
%label
Subscription:
%button.btn.btn-block.subscribe-button
%i.fa.fa-eye
%span= @merge_request.subscribed?(current_user) ? "Unsubscribe" : "Subscribe"
- subscribtion_status = @merge_request.subscribed?(current_user) ? "subscribed" : "unsubscribed"
.subscription-status{"data-status" => subscribtion_status}
.description-block.unsubscribed{class: ( "hidden" if @merge_request.subscribed?(current_user) )}
You're not receiving notifications from this thread.
.description-block.subscribed{class: ( "hidden" unless @merge_request.subscribed?(current_user) )}
You're receiving notifications because you're subscribed to this thread.
- if current_user
%div.prepend-top-20.clearfix
.issuable-context-title
%label
Subscription:
%button.btn.btn-block.subscribe-button
%i.fa.fa-eye
%span= @merge_request.subscribed?(current_user) ? "Unsubscribe" : "Subscribe"
- subscribtion_status = @merge_request.subscribed?(current_user) ? "subscribed" : "unsubscribed"
.subscription-status{"data-status" => subscribtion_status}
.description-block.unsubscribed{class: ( "hidden" if @merge_request.subscribed?(current_user) )}
You're not receiving notifications from this thread.
.description-block.subscribed{class: ( "hidden" unless @merge_request.subscribed?(current_user) )}
You're receiving notifications because you're subscribed to this thread.
:coffeescript
$ ->
......
......@@ -23,6 +23,12 @@
%i.fa.fa-spinner
Checking for CI status for #{@merge_request.last_commit_short_sha}
.ci_widget.ci-canceled{style: "display:none"}
%i.fa.fa-times
%span CI build canceled
for #{@merge_request.last_commit_short_sha}.
= link_to "View build page", ci_build_details_path(@merge_request), :"data-no-turbolink" => "data-no-turbolink"
.ci_widget.ci-error{style: "display:none"}
%i.fa.fa-times
%span Cannot connect to the CI server. Please check your settings and try again.
......@@ -21,64 +21,65 @@
= f.select :namespace_id, namespaces_options(params[:namespace_id] || :current_user), {}, {class: 'select2', tabindex: 2}
%hr
.js-toggle-container
.project-import.js-toggle-container
.form-group
.col-sm-2
%label.control-label Import project from
.col-sm-10
= link_to "#", class: 'js-toggle-button' do
%i.fa.fa-upload
%span Import existing repository by URL
.js-toggle-content.hide
.form-group.import-url-data
= f.label :import_url, class: 'control-label' do
%span Import existing git repo
.col-sm-10
= f.text_field :import_url, class: 'form-control', placeholder: 'https://github.com/randx/six.git'
.alert.alert-info.prepend-top-10
This URL must be publicly accessible or you can add a username and password like this: https://username:password@gitlab.com/company/project.git.
%br
The import will time out after 4 minutes. For big repositories, use a clone/push combination.
For SVN repositories, check #{link_to "this migrating from SVN doc.", "http://doc.gitlab.com/ce/workflow/migrating_from_svn.html"}
- if github_import_enabled?
= link_to status_import_github_path, class: 'btn' do
%i.fa.fa-github
GitHub
- else
= link_to '#', class: 'how_to_import_link light btn' do
%i.fa.fa-github
GitHub
= render 'github_import_modal'
.project-import.form-group
%label.control-label Import projects from
.col-sm-10
- if github_import_enabled?
= link_to status_import_github_path, class: 'btn' do
%i.fa.fa-github
GitHub
- else
= link_to '#', class: 'how_to_import_link light btn' do
%i.fa.fa-github
GitHub
= render 'github_import_modal'
- if bitbucket_import_enabled?
= link_to status_import_bitbucket_path, class: 'btn' do
%i.fa.fa-bitbucket
Bitbucket
- else
= link_to '#', class: 'how_to_import_link light btn' do
%i.fa.fa-bitbucket
Bitbucket
= render 'bitbucket_import_modal'
- unless request.host == 'gitlab.com'
- if gitlab_import_enabled?
= link_to status_import_gitlab_path, class: 'btn' do
%i.fa.fa-heart
GitLab.com
- if bitbucket_import_enabled?
= link_to status_import_bitbucket_path, class: 'btn' do
%i.fa.fa-bitbucket
Bitbucket
- else
= link_to '#', class: 'how_to_import_link light btn' do
%i.fa.fa-heart
GitLab.com
= render 'gitlab_import_modal'
%i.fa.fa-bitbucket
Bitbucket
= render 'bitbucket_import_modal'
= link_to new_import_gitorious_path, class: 'btn' do
%i.icon-gitorious.icon-gitorious-small
Gitorious.org
- unless request.host == 'gitlab.com'
- if gitlab_import_enabled?
= link_to status_import_gitlab_path, class: 'btn' do
%i.fa.fa-heart
GitLab.com
- else
= link_to '#', class: 'how_to_import_link light btn' do
%i.fa.fa-heart
GitLab.com
= render 'gitlab_import_modal'
= link_to new_import_gitorious_path, class: 'btn' do
%i.icon-gitorious.icon-gitorious-small
Gitorious.org
= link_to "#", class: 'btn js-toggle-button' do
%i.fa.fa-git
%span Any repo by URL
.js-toggle-content.hide
.form-group.import-url-data
= f.label :import_url, class: 'control-label' do
%span Git repository URL
.col-sm-10
= f.text_field :import_url, class: 'form-control', placeholder: 'https://username:password@gitlab.company.com/group/project.git'
.alert.alert-info.prepend-top-10
%ul
%li
The repository must be accessible over HTTP(S). If it is not publicly accessible, you can add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>.
%li
The import will time out after 4 minutes. For big repositories, use a clone/push combination.
%li
To migrate an SVN repository, check out #{link_to "this document", "http://doc.gitlab.com/ce/workflow/migrating_from_svn.html"}.
%hr.prepend-botton-10
......
......@@ -29,7 +29,9 @@
%i.fa.fa-minus.fa-inverse
.edit-member.hide.js-toggle-content
%br
= form_for member, as: :project_member, url: namespace_project_project_member_path(@project.namespace, @project, member.user), remote: true do |f|
.alert.prepend-top-20
= f.select :access_level, options_for_select(ProjectMember.access_roles, member.access_level)
= f.submit 'Save', class: 'btn btn-save btn-sm'
.prepend-top-10
= f.select :access_level, options_for_select(ProjectMember.access_roles, member.access_level), {}, class: 'form-control'
.prepend-top-10
= f.submit 'Save', class: 'btn btn-save'
......@@ -23,12 +23,12 @@
.col-sm-10
= f.select(:name, @project.open_branches.map { |br| [br.name, br.name] } , {include_blank: "Select branch"}, {class: "select2"})
.form-group
= f.label :developers_can_push, class: 'control-label' do
Developers can push
.col-sm-10
.col-sm-offset-2.col-sm-10
.checkbox
= f.check_box :developers_can_push
%span.descr Allow developers to push to this branch
= f.label :developers_can_push do
= f.check_box :developers_can_push
%strong Developers can push
.help-block Allow developers to push to this branch
.form-actions
= f.submit 'Protect', class: "btn-create btn"
= render 'branches_list'
......
......@@ -101,5 +101,6 @@
.form-actions
= f.submit 'Save', class: 'btn btn-save'
&nbsp;
- if @service.valid? && @service.activated? && @service.can_test?
= link_to 'Test settings', test_namespace_project_service_path(@project.namespace, @project, @service.to_param), class: 'btn'
- if @service.valid? && @service.activated?
- disabled = @service.can_test? ? '':'disabled'
= link_to 'Test settings', test_namespace_project_service_path(@project.namespace, @project, @service.to_param), class: "btn #{disabled}"
......@@ -44,25 +44,36 @@
%i.fa.fa-code-fork.project-fork-icon
Forked from:
%br
= link_to @project.forked_from_project.name_with_namespace, namespace_project_path(@project.namespace, @project.forked_from_project)
= link_to @project.forked_from_project.name_with_namespace, project_path(@project.forked_from_project)
- unless @project.empty_repo?
= link_to namespace_project_compare_index_path(@project.namespace, @project, from: @repository.root_ref, to: @ref || @repository.root_ref), class: 'btn btn-block' do
Compare code
- if @repository.version
- version = @repository.version
= link_to namespace_project_blob_path(@project.namespace, @project, tree_join(@repository.root_ref, version.name)), class: 'btn btn-block' do
- if version = @repository.version
- detail_url = changelog_url(@project) || version_url(@project)
= link_to detail_url, class: 'btn btn-block' do
Version:
%span.count
= @repository.blob_by_oid(version.id).data
- elsif @repository.changelog
= link_to changelog_url(@project), class: 'btn btn-block' do
View changelog
- if @repository.contribution_guide
= link_to contribution_guide_url(@project), class: 'btn btn-block' do
View contribution guide
- if @repository.license
= link_to license_url(@project), class: 'btn btn-block' do
View license
.prepend-top-10
%p
%span.light Created on
#{@project.created_at.stamp('Aug 22, 2013')}
%p
%span.light Owned by
%span.light Owned by #{@project.group ? "the" : nil}
- if @project.group
#{link_to @project.group.name, @project.group} group
- else
......
......@@ -15,7 +15,7 @@
= f.text_field :path, placeholder: 'open-source', class: 'form-control',
autofocus: local_assigns[:autofocus] || false
- if @group.persisted?
.alert.alert-danger
.alert.alert-warning.prepend-top-10
%ul
%li Changing group path can have unintended side effects.
%li Renaming group path will rename directory for all related projects
......
......@@ -21,7 +21,7 @@
%li
%span.light Website:
%strong= link_to user.short_website_url, user.full_website_url
- unless user.bio.blank?
- unless user.location.blank?
%li
%span.light Bio:
%span= user.bio
%span.light Location:
%strong= user.location
......@@ -4,5 +4,6 @@
new calendar(
#{@timestamps.to_json},
#{@starting_year},
#{@starting_month}
#{@starting_month},
'#{user_calendar_activities_path}'
);
.calendar_commit_activity
%hr
%h4
Commit Activity
%strong
- if @commit_count == 0
no
- else
= @commit_count
%span.calendar_commit_date
unique
= 'commit'.pluralize(@commit_count)
on
= @calendar_date.strftime("%b %d, %Y") rescue ''
-unless @commit_count == 0
%hr
- @calendar_activities.each do |project, commits|
- next if commits.empty?
%div.js-toggle-container
%strong
= pluralize(commits.count, 'commit')
in project
= link_to project.name_with_namespace, project_path(project)
%a.text-expander.js-toggle-button &hellip;
%hr
%div.js-toggle-content
- commits.each do |commit|
%span.monospace
= commit.committed_date.strftime("%H:%M")
= link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id"
= link_to commit.message, namespace_project_commit_path(project.namespace, project, commit), class: "commit-row-message str-truncated"
%br
%hr
......@@ -2,29 +2,34 @@
= link_to '#aside', class: 'show-aside' do
%i.fa.fa-angle-left
%section.col-md-8
%h3.page-title
.header-with-avatar
= image_tag avatar_icon(@user.email, 90), class: "avatar avatar-tile s90", alt: ''
= @user.name
- if @user == current_user
.pull-right
= link_to profile_path, class: 'btn' do
%i.fa.fa-pencil-square-o
Edit Profile settings
%br
%span.user-show-username #{@user.username}
%br
%small member since #{@user.created_at.stamp("Nov 12, 2031")}
%h3
= @user.name
- if @user == current_user
.pull-right
= link_to profile_path, class: 'btn btn-sm' do
%i.fa.fa-pencil-square-o
Edit Profile settings
.username
@#{@user.username}
.description
- if @user.bio.present?
= @user.bio
.clearfix
- if @groups.any?
%h4 Groups
= render 'groups', groups: @groups
%hr
.prepend-top-20
%h4 Groups
= render 'groups', groups: @groups
%hr
.hidden-xs
.user-calendar
%h4.center.light
%i.fa.fa-spinner.fa-spin
.user-calendar-activities
%hr
%h4
User Activity
......
.votes.votes-block
.progress
.progress-bar.progress-bar-success{style: "width: #{votable.upvotes_in_percent}%;"}
.progress-bar.progress-bar-danger{style: "width: #{votable.downvotes_in_percent}%;"}
.upvotes= "#{votable.upvotes} up"
.downvotes= "#{votable.downvotes} down"
.btn-group
- unless votable.upvotes.zero?
.btn.btn-sm.disabled.cgreen
%i.fa.fa-thumbs-up
= votable.upvotes
- unless votable.downvotes.zero?
.btn.btn-sm.disabled.cred
%i.fa.fa-thumbs-down
= votable.downvotes
.votes.votes-inline
- unless votable.upvotes.zero?
.upvotes
%span.upvotes.cgreen
+ #{votable.upvotes}
- unless votable.downvotes.zero?
\/
- unless votable.downvotes.zero?
.downvotes
%span.downvotes.cred
\- #{votable.downvotes}
......@@ -57,9 +57,9 @@ class IrkerWorker
end
def send_branch_updates(push_data, project, repo_name, committer, branch)
if push_data['before'] == Gitlab::Git::BLANK_SHA
if Gitlab::Git.blank_ref?(push_data['before'])
send_new_branch project, repo_name, committer, branch
elsif push_data['after'] == Gitlab::Git::BLANK_SHA
elsif Gitlab::Git.blank_ref?(push_data['after'])
send_del_branch repo_name, committer, branch
end
end
......@@ -83,7 +83,7 @@ class IrkerWorker
return if push_data['total_commits_count'] == 0
# Next message is for number of commit pushed, if any
if push_data['before'] == Gitlab::Git::BLANK_SHA
if Gitlab::Git.blank_ref?(push_data['before'])
# Tweak on push_data["before"] in order to have a nice compare URL
push_data['before'] = before_on_new_branch push_data, project
end
......
#!/usr/bin/env ruby
#
# This file was generated by Bundler.
#
# The application 'guard' is installed as part of a gem, and
# this file is here to facilitate running it.
#
require 'pathname'
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
Pathname.new(__FILE__).realpath)
require 'rubygems'
require 'bundler/setup'
load Gem.bin_path('guard', 'guard')
path = File.expand_path("~/.ssh/id_rsa.pub")
path = File.expand_path("~/.ssh/bitbucket_rsa.pub")
Gitlab::BitbucketImport.public_key = File.read(path) if File.exist?(path)
# Slowpoke extends Rack::Timeout to gracefully kill Unicorn workers so they can clean up state.
Slowpoke.timeout = 60
# The `Rack::Timeout` middleware kills requests after 60 seconds (as set above).
# We're replacing it with our `Gitlab::Middleware::Timeout` that does the same,
# except ignoring Git-over-HTTP requests, letting those take as long as they need.
Rails.application.config.middleware.swap(Rack::Timeout, Gitlab::Middleware::Timeout)
......@@ -23,8 +23,8 @@ en:
timeout: 'Your session expired, please sign in again to continue.'
inactive: 'Your account was not activated yet.'
sessions:
signed_in: 'Signed in successfully.'
signed_out: 'Signed out successfully.'
signed_in: ''
signed_out: ''
users_sessions:
user:
signed_in: 'Signed in successfully.'
......@@ -57,4 +57,4 @@ en:
reset_password_instructions:
subject: 'Reset password instructions'
unlock_instructions:
subject: 'Unlock Instructions'
subject: 'Unlock Instructions'
\ No newline at end of file
......@@ -198,7 +198,10 @@ Gitlab::Application.routes.draw do
end
get 'u/:username/calendar' => 'users#calendar', as: :user_calendar,
constraints: { username: /(?:[^.]|\.(?!atom$))+/, format: /atom/ }
constraints: { username: /.*/ }
get 'u/:username/calendar_activities' => 'users#calendar_activities', as: :user_calendar_activities,
constraints: { username: /.*/ }
get '/u/:username' => 'users#show', as: :user,
constraints: { username: /(?:[^.]|\.(?!atom$))+/, format: /atom/ }
......@@ -239,7 +242,7 @@ Gitlab::Application.routes.draw do
resources :group_members, only: [:index, :create, :update, :destroy] do
delete :leave, on: :collection
end
resource :avatar, only: [:destroy]
resources :milestones, only: [:index, :show, :update]
end
......@@ -315,14 +318,6 @@ Gitlab::Application.routes.draw do
as: :tree
)
end
resource :avatar, only: [:show, :destroy]
resources :commit, only: [:show], constraints: { id: /[[:alnum:]]{6,40}/ } do
get :branches, on: :member
end
resources :commits, only: [:show], constraints: { id: /(?:[^.]|\.(?!atom$))+/, format: /atom/ }
resources :compare, only: [:index, :create]
scope do
get(
......@@ -333,8 +328,24 @@ Gitlab::Application.routes.draw do
)
end
resources :network, only: [:show], constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ }
resources :graphs, only: [:show], constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ } do
scope do
get(
'/commits/*id',
to: 'commits#show',
constraints: { id: /(?:[^.]|\.(?!atom$))+/, format: /atom/ },
as: :commits
)
end
resource :avatar, only: [:show, :destroy]
resources :commit, only: [:show], constraints: { id: /[[:alnum:]]{6,40}/ } do
get :branches, on: :member
end
resources :compare, only: [:index, :create]
resources :network, only: [:show], constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ }
resources :graphs, only: [:show], constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ } do
member do
get :commits
end
......
......@@ -35,10 +35,22 @@ working_directory "/home/git/gitlab" # available in 0.94.0+
listen "/home/git/gitlab/tmp/sockets/gitlab.socket", :backlog => 1024
listen "127.0.0.1:8080", :tcp_nopush => true
# Kill workers after 1 hour.
# A shorter timeout of 60 seconds is enforced by rack-timeout for web requests.
# Git-over-HTTP only has the below timeout since large pulls/pushes can take a long time.
timeout 60 * 60
# nuke workers after 30 seconds instead of 60 seconds (the default)
#
# NOTICE: git push over http depends on this value.
# If you want be able to push huge amount of data to git repository over http
# you will have to increase this value too.
#
# Example of output if you try to push 1GB repo to GitLab over http.
# -> git push http://gitlab.... master
#
# error: RPC failed; result=18, HTTP code = 200
# fatal: The remote end hung up unexpectedly
# fatal: The remote end hung up unexpectedly
#
# For more information see http://stackoverflow.com/a/21682112/752049
#
timeout 60
# feel free to point this anywhere accessible on the filesystem
pid "/home/git/gitlab/tmp/pids/unicorn.pid"
......
class AddLocationToUser < ActiveRecord::Migration
def change
add_column :users, :location, :string
end
end
......@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20150313012111) do
ActiveRecord::Schema.define(version: 20150320234437) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
......@@ -458,7 +458,6 @@ ActiveRecord::Schema.define(version: 20150313012111) do
t.integer "notification_level", default: 1, null: false
t.datetime "password_expires_at"
t.integer "created_by_id"
t.datetime "last_credential_check_at"
t.string "avatar"
t.string "confirmation_token"
t.datetime "confirmed_at"
......@@ -466,6 +465,7 @@ ActiveRecord::Schema.define(version: 20150313012111) do
t.string "unconfirmed_email"
t.boolean "hide_no_ssh_key", default: false
t.string "website_url", default: "", null: false
t.datetime "last_credential_check_at"
t.string "github_access_token"
t.string "gitlab_access_token"
t.string "notification_email"
......@@ -473,6 +473,7 @@ ActiveRecord::Schema.define(version: 20150313012111) do
t.boolean "password_automatically_set", default: false
t.string "bitbucket_access_token"
t.string "bitbucket_access_token_secret"
t.string "location"
end
add_index "users", ["admin"], name: "index_users_on_admin", using: :btree
......
......@@ -375,7 +375,7 @@ Parameters:
}
},
{
"note": "_Status changed to closed_",
"note": "Status changed to closed",
"author": {
"id": 11,
"username": "admin",
......
......@@ -21,7 +21,7 @@ Parameters:
[
{
"id": 302,
"body": "_Status changed to closed_",
"body": "Status changed to closed",
"attachment": null,
"author": {
"id": 1,
......
......@@ -54,7 +54,7 @@ To serve repositories over SSH there's an add-on application called gitlab-shell
![GitLab Diagram Overview](gitlab_diagram_overview.png)
A typical install of GitLab will be on Ubuntu Linux or RHEL/CentOS. It uses Nginx or Apache as a web front end to proxypass the Unicorn web server. By default, communication between Unicorn and the front end is via a Unix domain socket but forwarding requests via TCP is also supported. The web front end accesses `/home/git/gitlab/public` bypassing the Unicorn server to serve static pages, uploads (e.g. avatar images or attachments), and precompiled assets. GitLab serves web pages and a [GitLab API](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/api) using the Unicorn web server. It uses Sidekiq as a job queue which, in turn, uses redis as a non-persistent database backend for job information, meta data, and incoming jobs.
A typical install of GitLab will be on GNU/Linux. It uses Nginx or Apache as a web front end to proxypass the Unicorn web server. By default, communication between Unicorn and the front end is via a Unix domain socket but forwarding requests via TCP is also supported. The web front end accesses `/home/git/gitlab/public` bypassing the Unicorn server to serve static pages, uploads (e.g. avatar images or attachments), and precompiled assets. GitLab serves web pages and a [GitLab API](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/api) using the Unicorn web server. It uses Sidekiq as a job queue which, in turn, uses redis as a non-persistent database backend for job information, meta data, and incoming jobs.
The GitLab web app uses MySQL or PostgreSQL for persistent database information (e.g. users, permissions, issues, other meta data). GitLab stores the bare git repositories it serves in `/home/git/repositories` by default. It also keeps default branch and hook information with the bare repository. `/home/git/gitlab-satellites` keeps checked out repositories when performing actions such as a merge request, editing files in the web interface, etc.
......
......@@ -76,7 +76,7 @@ Notice: The 25 workers of Sidekiq will show up as separate processes in your pro
## Unicorn Workers
It's possible to increase the amount of unicorn workers and tis will usually help for to reduce the response time of the applications and increase the ability to handle parallel requests.
It's possible to increase the amount of unicorn workers and this will usually help for to reduce the response time of the applications and increase the ability to handle parallel requests.
For most instances we recommend using: CPU cores + 1 = unicorn workers.
So for a machine with 2 cores, 3 unicorn workers is ideal.
......@@ -106,4 +106,4 @@ On a very active server (10,000 active users) the Sidekiq process can use 1GB+ o
- Firefox (Latest released version and [latest ESR version](https://www.mozilla.org/en-US/firefox/organizations/))
- Safari 7+ (known problem: required fields in html5 do not work)
- Opera (Latest released version)
- IE 10+
- IE 10+
\ No newline at end of file
......@@ -2,7 +2,7 @@
Import projects from Bitbucket and login to your GitLab instance with your Bitbucket account.
To enable the Bitbucket OmniAuth provider you must register your application with Bitbucket.
To enable the Bitbucket OmniAuth provider you must register your application with Bitbucket.
Bitbucket will generate an application ID and secret key for you to use.
1. Sign in to Bitbucket.
......@@ -19,8 +19,8 @@ Bitbucket will generate an application ID and secret key for you to use.
- URL: The URL to your GitLab installation. 'https://gitlab.company.com'
1. Select "Save".
1. You should now see a Key and Secret in the list of OAuth customers.
Keep this page open as you continue configuration.
1. You should now see a Key and Secret in the list of OAuth customers.
Keep this page open as you continue configuration.
1. On your GitLab server, open the configuration file.
......@@ -70,13 +70,13 @@ Bitbucket will generate an application ID and secret key for you to use.
1. Restart GitLab for the changes to take effect.
On the sign in page there should now be a Bitbucket icon below the regular sign in form.
Click the icon to begin the authentication process. Bitbucket will ask the user to sign in and authorize the GitLab application.
On the sign in page there should now be a Bitbucket icon below the regular sign in form.
Click the icon to begin the authentication process. Bitbucket will ask the user to sign in and authorize the GitLab application.
If everything goes well the user will be returned to GitLab and will be signed in.
## Bitbucket project import
To allow projects to be imported directly into GitLab, Bitbucket requires two extra setup steps compared to GitHub and GitLab.com.
To allow projects to be imported directly into GitLab, Bitbucket requires two extra setup steps compared to GitHub and GitLab.com.
Bitbucket doesn't allow OAuth applications to clone repositories over HTTPS, and instead requires GitLab to use SSH and identify itself using your GitLab server's SSH key.
......@@ -95,7 +95,7 @@ To allow GitLab to connect to Bitbucket over SSH, you need to add 'bitbucket.org
```sh
The authenticity of host 'bitbucket.org (207.223.240.182)' can't be established.
RSA key fingerprint is 97:8c:1b:f2:6f:14:6b:5c:3b:ec:aa:46:46:74:7c:40.
Are you sure you want to continue connecting (yes/no)?
Are you sure you want to continue connecting (yes/no)?
```
1. If the fingerprint matches, type `yes` to continue connecting and have 'bitbucket.org' be added to your known hosts.
......@@ -104,7 +104,7 @@ To allow GitLab to connect to Bitbucket over SSH, you need to add 'bitbucket.org
### Step 2: Public key
To be able to access repositories on Bitbucket, GitLab will automatically register your public key with Bitbucket as a deploy key for the repositories to be imported. Your public key needs to be at `~/.ssh/id_rsa.pub`, which will expand to `/home/git/.ssh/id_rsa.pub` in most configurations.
To be able to access repositories on Bitbucket, GitLab will automatically register your public key with Bitbucket as a deploy key for the repositories to be imported. Your public key needs to be at `~/.ssh/bitbucket_rsa.pub`, which will expand to `/home/git/.ssh/bitbucket_rsa.pub` in most configurations.
If you have that file in place, you're all set and should see the "Import projects from Bitbucket" option enabled. If you don't, do the following:
......@@ -114,6 +114,7 @@ If you have that file in place, you're all set and should see the "Import projec
sudo -u git -H ssh-keygen
```
When asked `Enter file in which to save the key` specify the correct path, eg. `/home/git/.ssh/bitbucket_rsa`.
Make sure to use an **empty passphrase**.
2. Restart GitLab to allow it to find the new public key.
......
......@@ -6,7 +6,7 @@
* [Newlines](#newlines)
* [Multiple underscores in words](#multiple-underscores-in-words)
* [URL auto-linking](#url-autolinking)
* [URL auto-linking](#url-auto-linking)
* [Code and Syntax Highlighting](#code-and-syntax-highlighting)
* [Emoji](#emoji)
* [Special GitLab references](#special-gitlab-references)
......
......@@ -45,7 +45,7 @@ clip < ~/.ssh/id_rsa.pub
pbcopy < ~/.ssh/id_rsa.pub
```
**Linux (requires xclip):**
**GNU/Linux (requires xclip):**
```bash
xclip -sel clip < ~/.ssh/id_rsa.pub
```
......
......@@ -11,6 +11,7 @@ class Spinach::Features::Profile < Spinach::FeatureSteps
fill_in "user_linkedin", with: "testlinkedin"
fill_in "user_twitter", with: "testtwitter"
fill_in "user_website_url", with: "testurl"
fill_in "user_location", with: "Ukraine"
click_button "Save changes"
@user.reload
end
......@@ -20,6 +21,7 @@ class Spinach::Features::Profile < Spinach::FeatureSteps
@user.linkedin.should == 'testlinkedin'
@user.twitter.should == 'testtwitter'
@user.website_url.should == 'testurl'
find("#user_location").value.should == "Ukraine"
end
step 'I change my avatar' do
......
......@@ -209,13 +209,13 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
step 'I click link "Hide inline discussion" of the second file' do
within '.files [id^=diff]:nth-child(2)' do
click_link 'Show/Hide comments'
find('.js-toggle-diff-comments').click
end
end
step 'I click link "Show inline discussion" of the second file' do
within '.files [id^=diff]:nth-child(2)' do
click_link 'Show/Hide comments'
find('.js-toggle-diff-comments').click
end
end
......
......@@ -16,7 +16,7 @@ module Backup
if project.empty_repo?
$progress.puts "[SKIPPED]".cyan
else
cmd = %W(git --git-dir=#{path_to_repo(project)} bundle create #{path_to_bundle(project)} --all)
cmd = %W(tar -cf #{path_to_bundle(project)} -C #{path_to_repo(project)} .)
output, status = Gitlab::Popen.popen(cmd)
if status.zero?
$progress.puts "[DONE]".green
......@@ -64,7 +64,8 @@ module Backup
project.namespace.ensure_dir_exist if project.namespace
if File.exists?(path_to_bundle(project))
cmd = %W(git clone --bare #{path_to_bundle(project)} #{path_to_repo(project)})
FileUtils.mkdir_p(path_to_repo(project))
cmd = %W(tar -xf #{path_to_bundle(project)} -C #{path_to_repo(project)})
else
cmd = %W(git init --bare #{path_to_repo(project)})
end
......
......@@ -22,6 +22,14 @@ module Gitlab
end
end
def self.get_commits_for_date(projects, user, date)
user_commits = {}
projects.reject(&:forked?).each do |project|
user_commits[project] = ProjectContributions.new(project, user).user_commits_on_date(date)
end
user_commits
end
def starting_year
(Time.now - 1.year).strftime("%Y")
end
......
......@@ -3,11 +3,12 @@ module Gitlab
def self.force_push?(project, oldrev, newrev)
return false if project.empty_repo?
if oldrev != Gitlab::Git::BLANK_SHA && newrev != Gitlab::Git::BLANK_SHA
# Created or deleted branch
if Gitlab::Git.blank_ref?(oldrev) || Gitlab::Git.blank_ref?(newrev)
false
else
missed_refs, _ = Gitlab::Popen.popen(%W(git --git-dir=#{project.repository.path_to_repo} rev-list #{oldrev} ^#{newrev}))
missed_refs.split("\n").size > 0
else
false
end
end
end
......
module Gitlab
module Middleware
class Timeout < Rack::Timeout
GRACK_REGEX = /[-\/\w\.]+\.git\//.freeze
def call(env)
return @app.call(env) if env['PATH_INFO'] =~ GRACK_REGEX
super
end
end
end
end
......@@ -27,6 +27,12 @@ module Gitlab
# Get latest 20 commits ASC
commits_limited = commits.last(20)
# For performance purposes maximum 20 latest commits
# will be passed as post receive hook data.
commit_attrs = commits_limited.map do |commit|
commit.hook_attrs(project)
end
type = Gitlab::Git.tag_ref?(ref) ? "tag_push" : "push"
# Hash to be passed as post_receive_data
......@@ -49,17 +55,10 @@ module Gitlab
git_ssh_url: project.ssh_url_to_repo,
visibility_level: project.visibility_level
},
commits: [],
commits: commit_attrs,
total_commits_count: commits_count
}
# For performance purposes maximum 20 latest commits
# will be passed as post receive hook data.
commits_limited.each do |commit|
data[:commits] << commit.hook_attrs(project)
end
data[:commits] = "" if data[:commits].count == 0
data
end
......@@ -72,7 +71,8 @@ module Gitlab
end
def checkout_sha(repository, newrev, ref)
if newrev != Gitlab::Git::BLANK_SHA && Gitlab::Git.tag_ref?(ref)
# Find sha for tag, except when it was deleted.
if Gitlab::Git.tag_ref?(ref) && !Gitlab::Git.blank_ref?(newrev)
tag_name = Gitlab::Git.ref_name(ref)
tag = repository.find_tag(tag_name)
......
......@@ -35,7 +35,13 @@ module Gitlab
end
def non_restricted_level?(level)
! current_application_settings.restricted_visibility_levels.include?(level)
restricted_levels = current_application_settings.restricted_visibility_levels
if restricted_levels.nil?
true
else
!restricted_levels.include?(level)
end
end
def valid_level?(level)
......
desc 'Security check via brakeman'
task :brakeman do
if system("brakeman --skip-files lib/backup/repository.rb -w3 -z")
exit 0
puts 'Security check succeed'
else
puts 'Security check failed'
exit 1
......
......@@ -90,13 +90,14 @@ namespace :gitlab do
warn_user_is_not_gitlab
block_flag = ENV['BLOCK']
User.ldap.each do |ldap_user|
print "#{ldap_user.name} (#{ldap_user.extern_uid}) ..."
if Gitlab::LDAP::Access.allowed?(ldap_user)
User.find_each do |user|
next unless user.ldap_user?
print "#{user.name} (#{user.ldap_identity.extern_uid}) ..."
if Gitlab::LDAP::Access.allowed?(user)
puts " [OK]".green
else
if block_flag
ldap_user.block! unless ldap_user.blocked?
user.block! unless user.blocked?
puts " [BLOCKED]".red
else
puts " [NOT IN LDAP]".yellow
......
<!DOCTYPE html>
<html>
<head>
<title>Page took too long to load (503)</title>
<link href="/static.css" media="screen" rel="stylesheet" type="text/css" />
</head>
<body>
<h1>503</h1>
<h3>Page took too long to load.</h3>
<hr/>
<p>Please contact your GitLab administrator if this problem persists.</p>
</body>
</html>
require 'spec_helper'
describe UsersController do
let(:user) { create(:user, username: "user1", name: "User 1", email: "user1@gitlab.com") }
let(:user) { create(:user, username: 'user1', name: 'User 1', email: 'user1@gitlab.com') }
before do
sign_in(user)
end
describe "GET #show" do
describe 'GET #show' do
render_views
it "renders the show template" do
it 'renders the show template' do
get :show, username: user.username
expect(response.status).to eq(200)
expect(response).to render_template("show")
expect(response).to render_template('show')
end
end
describe "GET #calendar" do
it "renders calendar" do
describe 'GET #calendar' do
it 'renders calendar' do
get :calendar, username: user.username
expect(response).to render_template("calendar")
expect(response).to render_template('calendar')
end
end
end
describe 'GET #calendar_activities' do
include RepoHelpers
let(:project) { create(:project) }
let(:calendar_user) { create(:user, email: sample_commit.author_email) }
let(:commit1) { '0ed8c6c6752e8c6ea63e7b92a517bf5ac1209c80' }
let(:commit2) { '7d3b0f7cff5f37573aea97cebfd5692ea1689924' }
before do
allow_any_instance_of(User).to receive(:contributed_projects_ids).and_return([project.id])
project.team << [user, :developer]
end
it 'assigns @commit_count' do
get :calendar_activities, username: calendar_user.username, date: '2014-07-31'
expect(assigns(:commit_count)).to eq(2)
end
it 'assigns @calendar_date' do
get :calendar_activities, username: calendar_user.username, date: '2014-07-31'
expect(assigns(:calendar_date)).to eq(Date.parse('2014-07-31'))
end
it 'assigns @calendar_activities' do
get :calendar_activities, username: calendar_user.username, date: '2014-07-31'
expect(assigns(:calendar_activities).values.flatten.map(&:id)).to eq([commit1, commit2])
end
it 'renders calendar_activities' do
get :calendar_activities, username: calendar_user.username
expect(response).to render_template('calendar_activities')
end
end
end
......@@ -120,4 +120,18 @@ describe Gitlab::ReferenceExtractor do
expect(extracted[0][1].message).to eq(commit.message)
end
end
context 'with a project with an underscore' do
let(:project) { create(:project, path: 'test_project') }
let(:issue) { create(:issue, project: project) }
it 'handles project issue references' do
subject.analyze("this refers issue #{project.path_with_namespace}##{issue.iid}",
project)
extracted = subject.issues_for(project)
expect(extracted.size).to eq(1)
expect(extracted).to eq([issue])
end
end
end
require 'spec_helper'
describe ExternalWikiService do
include ExternalWikiHelper
describe "Associations" do
it { should belong_to :project }
it { should have_one :service_hook }
end
describe "Validations" do
context "active" do
before do
subject.active = true
end
it { should validate_presence_of :external_wiki_url }
end
end
describe 'External wiki' do
let(:project) { create(:project) }
context 'when it is active' do
before do
properties = { 'external_wiki_url' => 'https://gitlab.com' }
@service = project.create_external_wiki_service(active: true, properties: properties)
end
after do
@service.destroy!
end
it 'should replace the wiki url' do
wiki_path = get_project_wiki_path(project)
wiki_path.should match('https://gitlab.com')
end
end
end
end
......@@ -182,14 +182,14 @@ describe Note do
describe '#note' do
subject { super().note }
it { is_expected.to match(/Status changed to #{status}/) }
it { is_expected.to eq("Status changed to #{status}") }
end
it 'appends a back-reference if a closing mentionable is supplied' do
commit = double('commit', gfm_reference: 'commit 123456')
n = Note.create_status_change_note(thing, project, author, status, commit)
expect(n.note).to match(/Status changed to #{status} by commit 123456/)
expect(n.note).to eq("Status changed to #{status} by commit 123456")
end
end
......@@ -197,7 +197,7 @@ describe Note do
let(:project) { create(:project) }
let(:thing) { create(:issue, project: project) }
let(:author) { create(:user) }
let(:assignee) { create(:user) }
let(:assignee) { create(:user, username: "assigned_user") }
subject { Note.create_assignee_change_note(thing, project, author, assignee) }
......@@ -227,7 +227,7 @@ describe Note do
describe '#note' do
subject { super().note }
it { is_expected.to match(/Reassigned to @#{assignee.username}/) }
it { is_expected.to eq('Reassigned to @assigned_user') }
end
context 'assignee is removed' do
......@@ -235,11 +235,95 @@ describe Note do
describe '#note' do
subject { super().note }
it { is_expected.to match(/Assignee removed/) }
it { is_expected.to eq('Assignee removed') }
end
end
end
describe '#create_labels_change_note' do
let(:project) { create(:project) }
let(:thing) { create(:issue, project: project) }
let(:author) { create(:user) }
let(:label1) { create(:label) }
let(:label2) { create(:label) }
let(:added_labels) { [label1, label2] }
let(:removed_labels) { [] }
subject { Note.create_labels_change_note(thing, project, author, added_labels, removed_labels) }
context 'creates and saves a Note' do
it { is_expected.to be_a Note }
describe '#id' do
subject { super().id }
it { is_expected.not_to be_nil }
end
end
describe '#noteable' do
subject { super().noteable }
it { is_expected.to eq(thing) }
end
describe '#project' do
subject { super().project }
it { is_expected.to eq(thing.project) }
end
describe '#author' do
subject { super().author }
it { is_expected.to eq(author) }
end
describe '#note' do
subject { super().note }
it { is_expected.to eq("Added ~#{label1.id} ~#{label2.id} labels") }
end
context 'label is removed' do
let(:added_labels) { [label1] }
let(:removed_labels) { [label2] }
describe '#note' do
subject { super().note }
it { is_expected.to eq("Added ~#{label1.id} and removed ~#{label2.id} labels") }
end
end
end
describe '#create_milestone_change_note' do
let(:project) { create(:project) }
let(:thing) { create(:issue, project: project) }
let(:milestone) { create(:milestone, project: project, title: "first_milestone") }
let(:author) { create(:user) }
subject { Note.create_milestone_change_note(thing, project, author, milestone) }
context 'creates and saves a Note' do
it { is_expected.to be_a Note }
describe '#id' do
subject { super().id }
it { is_expected.not_to be_nil }
end
end
describe '#project' do
subject { super().project }
it { is_expected.to eq(thing.project) }
end
describe '#author' do
subject { super().author }
it { is_expected.to eq(author) }
end
describe '#note' do
subject { super().note }
it { is_expected.to eq("Milestone changed to first_milestone") }
end
end
describe '#create_cross_reference_note' do
let(:project) { create(:project) }
let(:author) { create(:user) }
......@@ -272,7 +356,7 @@ describe Note do
describe '#note' do
subject { super().note }
it { is_expected.to eq("_mentioned in merge request !#{mergereq.iid}_") }
it { is_expected.to eq("mentioned in merge request !#{mergereq.iid}") }
end
end
......@@ -288,7 +372,7 @@ describe Note do
describe '#note' do
subject { super().note }
it { is_expected.to eq("_mentioned in commit #{commit.sha}_") }
it { is_expected.to eq("mentioned in commit #{commit.sha}") }
end
end
......@@ -309,7 +393,7 @@ describe Note do
describe '#note' do
subject { super().note }
it { is_expected.to eq("_mentioned in issue ##{issue.iid}_") }
it { is_expected.to eq("mentioned in issue ##{issue.iid}") }
end
end
......@@ -330,7 +414,7 @@ describe Note do
describe '#note' do
subject { super().note }
it { is_expected.to eq("_mentioned in merge request !#{mergereq.iid}_") }
it { is_expected.to eq("mentioned in merge request !#{mergereq.iid}") }
end
end
......@@ -362,7 +446,7 @@ describe Note do
describe '#note' do
subject { super().note }
it { is_expected.to eq("_mentioned in issue ##{issue.iid}_") }
it { is_expected.to eq("mentioned in issue ##{issue.iid}") }
end
end
......@@ -389,7 +473,7 @@ describe Note do
describe '#note' do
subject { super().note }
it { is_expected.to eq("_mentioned in commit #{parent_commit.id}_") }
it { is_expected.to eq("mentioned in commit #{parent_commit.id}") }
end
end
end
......@@ -421,6 +505,41 @@ describe Note do
it { expect(Note.cross_reference_exists?(commit0, commit1)).to be_truthy }
it { expect(Note.cross_reference_exists?(commit1, commit0)).to be_falsey }
end
context 'legacy note with Markdown emphasis' do
let(:issue2) { create :issue, project: project }
let!(:note) do
create :note, system: true, noteable_id: issue2.id,
noteable_type: "Issue", note: "_mentioned in issue " \
"#{issue.project.path_with_namespace}##{issue.iid}_"
end
it 'detects if a mentionable with emphasis has been mentioned' do
expect(Note.cross_reference_exists?(issue2, issue)).to be_truthy
end
end
end
describe '#cross_references_with_underscores?' do
let(:project) { create :project, path: "first_project" }
let(:second_project) { create :project, path: "second_project" }
let(:author) { create :user }
let(:issue0) { create :issue, project: project }
let(:issue1) { create :issue, project: second_project }
let!(:note) { Note.create_cross_reference_note(issue0, issue1, author, project) }
it 'detects if a mentionable has already been mentioned' do
expect(Note.cross_reference_exists?(issue0, issue1)).to be_truthy
end
it 'detects if a mentionable has not already been mentioned' do
expect(Note.cross_reference_exists?(issue1, issue0)).to be_falsey
end
it 'detects that text has underscores' do
expect(note.note).to eq("mentioned in issue #{second_project.path_with_namespace}##{issue1.iid}")
end
end
describe '#system?' do
......@@ -429,6 +548,8 @@ describe Note do
let(:other) { create(:issue, project: project) }
let(:author) { create(:user) }
let(:assignee) { create(:user) }
let(:label) { create(:label) }
let(:milestone) { create(:milestone) }
it 'should recognize user-supplied notes as non-system' do
@note = create(:note_on_issue)
......@@ -449,6 +570,16 @@ describe Note do
@note = Note.create_assignee_change_note(issue, project, author, assignee)
expect(@note).to be_system
end
it 'should identify label-change notes as system notes' do
@note = Note.create_labels_change_note(issue, project, author, [label], [])
expect(@note).to be_system
end
it 'should identify milestone-change notes as system notes' do
@note = Note.create_milestone_change_note(issue, project, author, milestone)
expect(@note).to be_system
end
end
describe :authorization do
......
......@@ -59,7 +59,7 @@ describe BuildboxService do
describe :build_page do
it 'returns the correct build page' do
expect(@service.build_page('2ab7834c')).to eq(
expect(@service.build_page('2ab7834c', nil)).to eq(
'https://buildbox.io/account-name/example-project/builds?commit=2ab7834c'
)
end
......
......@@ -39,11 +39,11 @@ describe GitlabCiService do
end
describe :commit_status_path do
it { expect(@service.commit_status_path("2ab7834c")).to eq("http://ci.gitlab.org/projects/2/commits/2ab7834c/status.json?token=verySecret")}
it { expect(@service.commit_status_path("2ab7834c", 'master')).to eq("http://ci.gitlab.org/projects/2/refs/master/commits/2ab7834c/status.json?token=verySecret")}
end
describe :build_page do
it { expect(@service.build_page("2ab7834c")).to eq("http://ci.gitlab.org/projects/2/commits/2ab7834c")}
it { expect(@service.build_page("2ab7834c", 'master')).to eq("http://ci.gitlab.org/projects/2/refs/master/commits/2ab7834c")}
end
end
end
......@@ -29,7 +29,7 @@ describe Repository do
subject { repository.timestamps_by_user_log(user) }
it { is_expected.to eq(["2014-08-06", "2014-07-31", "2014-07-31"]) }
it { is_expected.to eq(['2014-08-06', '2014-07-31', '2014-07-31']) }
end
describe 'multiple emails for user' do
......@@ -38,7 +38,22 @@ describe Repository do
subject { repository.timestamps_by_user_log(user) }
it { is_expected.to eq(["2015-01-10", "2014-08-06", "2014-07-31", "2014-07-31"]) }
it { is_expected.to eq(['2015-01-10', '2014-08-06', '2014-07-31', '2014-07-31']) }
end
end
context :commits_by_user_on_date_log do
describe 'single e-mail for user' do
let(:user) { create(:user, email: sample_commit.author_email) }
let(:commit1) { '0ed8c6c6752e8c6ea63e7b92a517bf5ac1209c80' }
let(:commit2) { '7d3b0f7cff5f37573aea97cebfd5692ea1689924' }
subject { repository.commits_by_user_on_date_log(user,Date.new(2014, 07, 31)) }
it 'contains the exepected commits' do
expect(subject.flatten.map(&:id)).to eq([commit1, commit2])
end
end
end
end
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