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)
$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)
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment