summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRegis <boudinot.regis@yahoo.com>2017-01-04 10:55:25 -0700
committerRegis <boudinot.regis@yahoo.com>2017-01-04 10:55:25 -0700
commit1655824fa44c428b9570dc96688d27faef186024 (patch)
tree14bbb2ba241efbabef6def3b3415f9f1b6851d3a
parentcf039f58585e5238cd979ba70a5fd2d5c1eee650 (diff)
parentec4fe4432a2c4daa14c8e8f7c5d8567553062ebf (diff)
downloadgitlab-ce-1655824fa44c428b9570dc96688d27faef186024.tar.gz
Merge branch 'master' into auto-pipelines-vue
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock12
-rw-r--r--app/assets/javascripts/compare_autocomplete.js.es67
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js.es611
-rw-r--r--app/assets/stylesheets/framework/awards.scss14
-rw-r--r--app/assets/stylesheets/framework/files.scss49
-rw-r--r--app/assets/stylesheets/framework/lists.scss42
-rw-r--r--app/assets/stylesheets/framework/panels.scss8
-rw-r--r--app/assets/stylesheets/framework/variables.scss1
-rw-r--r--app/assets/stylesheets/notify.scss12
-rw-r--r--app/assets/stylesheets/pages/branches.scss55
-rw-r--r--app/assets/stylesheets/pages/commit.scss132
-rw-r--r--app/assets/stylesheets/pages/commits.scss173
-rw-r--r--app/assets/stylesheets/pages/issuable.scss6
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss4
-rw-r--r--app/assets/stylesheets/pages/notes.scss12
-rw-r--r--app/assets/stylesheets/pages/projects.scss31
-rw-r--r--app/assets/stylesheets/pages/status.scss6
-rw-r--r--app/assets/stylesheets/pages/tree.scss15
-rw-r--r--app/controllers/projects/mattermosts_controller.rb2
-rw-r--r--app/controllers/projects/merge_requests_controller.rb3
-rw-r--r--app/controllers/registrations_controller.rb18
-rw-r--r--app/helpers/gitlab_markdown_helper.rb44
-rw-r--r--app/helpers/issues_helper.rb12
-rw-r--r--app/models/commit.rb8
-rw-r--r--app/models/commit_range.rb4
-rw-r--r--app/models/concerns/referable.rb2
-rw-r--r--app/models/external_issue.rb2
-rw-r--r--app/models/group.rb2
-rw-r--r--app/models/group_label.rb4
-rw-r--r--app/models/issue.rb4
-rw-r--r--app/models/label.rb10
-rw-r--r--app/models/merge_request.rb4
-rw-r--r--app/models/milestone.rb4
-rw-r--r--app/models/project.rb8
-rw-r--r--app/models/project_label.rb4
-rw-r--r--app/models/snippet.rb4
-rw-r--r--app/models/user.rb3
-rw-r--r--app/uploaders/avatar_uploader.rb11
-rw-r--r--app/views/award_emoji/_awards_block.html.haml3
-rw-r--r--app/views/devise/shared/_signup_box.html.haml3
-rw-r--r--app/views/projects/blob/_blob.html.haml2
-rw-r--r--app/views/projects/commits/_commit.html.haml46
-rw-r--r--app/views/projects/commits/_commit_list.html.haml2
-rw-r--r--app/views/projects/commits/_commits.html.haml2
-rw-r--r--app/views/projects/compare/_form.html.haml10
-rw-r--r--app/views/projects/cycle_analytics/_empty_stage.html.haml2
-rw-r--r--app/views/projects/cycle_analytics/show.html.haml4
-rw-r--r--app/views/projects/merge_requests/_show.html.haml2
-rw-r--r--app/views/projects/merge_requests/show/_versions.html.haml2
-rw-r--r--app/views/projects/services/slack_slash_commands/_help.html.haml2
-rw-r--r--changelogs/unreleased/25580-trucate-dropdown-for-long-branch.yml4
-rw-r--r--changelogs/unreleased/add_email_password_confirmation.yml4
-rw-r--r--changelogs/unreleased/additional-award-emoji-repositioning-fixes.yml4
-rw-r--r--changelogs/unreleased/api-hooks-changelog-entry.yml4
-rw-r--r--changelogs/unreleased/fix-cross-project-ref-path.yml4
-rw-r--r--changelogs/unreleased/ldap_person_attributes.yml4
-rw-r--r--changelogs/unreleased/project-avatar-fork.yml4
-rw-r--r--changelogs/unreleased/recaptcha_500.yml4
-rw-r--r--changelogs/unreleased/regression-note-headline-light.yml4
-rw-r--r--doc/development/changelog.md15
-rw-r--r--lib/api/issues.rb29
-rw-r--r--lib/api/project_hooks.rb2
-rw-r--r--lib/api/users.rb2
-rw-r--r--lib/gitlab/chat_commands/deploy.rb6
-rw-r--r--lib/gitlab/gfm/reference_rewriter.rb2
-rw-r--r--lib/gitlab/ldap/person.rb19
-rw-r--r--public/slash-command-logo.pngbin0 -> 9509 bytes
-rw-r--r--spec/controllers/registrations_controller_spec.rb60
-rw-r--r--spec/features/cycle_analytics_spec.rb126
-rw-r--r--spec/features/issues/award_emoji_spec.rb2
-rw-r--r--spec/features/merge_requests/merge_request_versions_spec.rb48
-rw-r--r--spec/features/projects/services/mattermost_slash_command_spec.rb6
-rw-r--r--spec/features/signup_spec.rb21
-rw-r--r--spec/features/users_spec.rb18
-rw-r--r--spec/helpers/gitlab_markdown_helper_spec.rb10
-rw-r--r--spec/helpers/issues_helper_spec.rb8
-rw-r--r--spec/lib/gitlab/ldap/person_spec.rb44
-rw-r--r--spec/models/group_label_spec.rb2
-rw-r--r--spec/models/issue_spec.rb4
-rw-r--r--spec/models/merge_request_spec.rb4
-rw-r--r--spec/models/project_spec.rb8
-rw-r--r--spec/requests/api/project_hooks_spec.rb5
-rw-r--r--spec/requests/api/users_spec.rb4
-rw-r--r--spec/services/projects/fork_service_spec.rb13
-rw-r--r--spec/uploaders/avatar_uploader_spec.rb8
-rw-r--r--spec/uploaders/file_uploader_spec.rb6
87 files changed, 845 insertions, 488 deletions
diff --git a/Gemfile b/Gemfile
index eadb67405ee..0b59cca5b84 100644
--- a/Gemfile
+++ b/Gemfile
@@ -328,7 +328,7 @@ end
gem 'newrelic_rpm', '~> 3.16'
-gem 'octokit', '~> 4.3.0'
+gem 'octokit', '~> 4.6.2'
gem 'mail_room', '~> 0.9.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index 1c192d2fc6e..5dcf3744d99 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -420,8 +420,8 @@ GEM
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (>= 1.2, < 3)
- octokit (4.3.0)
- sawyer (~> 0.7.0, >= 0.5.3)
+ octokit (4.6.2)
+ sawyer (~> 0.8.0, >= 0.5.3)
oj (2.17.4)
omniauth (1.3.1)
hashie (>= 1.2, < 4)
@@ -650,9 +650,9 @@ GEM
sprockets (>= 2.8, < 4.0)
sprockets-rails (>= 2.0, < 4.0)
tilt (>= 1.1, < 3)
- sawyer (0.7.0)
- addressable (>= 2.3.5, < 2.5)
- faraday (~> 0.8, < 0.10)
+ sawyer (0.8.1)
+ addressable (>= 2.3.5, < 2.6)
+ faraday (~> 0.8, < 1.0)
scss_lint (0.47.1)
rake (>= 0.9, < 11)
sass (~> 3.4.15)
@@ -895,7 +895,7 @@ DEPENDENCIES
newrelic_rpm (~> 3.16)
nokogiri (~> 1.6.7, >= 1.6.7.2)
oauth2 (~> 1.2.0)
- octokit (~> 4.3.0)
+ octokit (~> 4.6.2)
oj (~> 2.17.4)
omniauth (~> 1.3.1)
omniauth-auth0 (~> 1.4.1)
diff --git a/app/assets/javascripts/compare_autocomplete.js.es6 b/app/assets/javascripts/compare_autocomplete.js.es6
index 45c974b2b68..251f2ded347 100644
--- a/app/assets/javascripts/compare_autocomplete.js.es6
+++ b/app/assets/javascripts/compare_autocomplete.js.es6
@@ -55,6 +55,13 @@
$('.dropdown-toggle-text', $dropdown).text(text);
$dropdownContainer.removeClass('open');
});
+
+ $dropdownContainer.on('click', '.dropdown-content a', (e) => {
+ $dropdown.prop('title', e.target.text.replace(/_+?/g, '-'));
+ if ($dropdown.hasClass('has-tooltip')) {
+ $dropdown.tooltip('fixTitle');
+ }
+ });
});
};
diff --git a/app/assets/javascripts/gfm_auto_complete.js.es6 b/app/assets/javascripts/gfm_auto_complete.js.es6
index 87c579ac757..6ca543c2b00 100644
--- a/app/assets/javascripts/gfm_auto_complete.js.es6
+++ b/app/assets/javascripts/gfm_auto_complete.js.es6
@@ -48,6 +48,7 @@
},
DefaultOptions: {
sorter: function(query, items, searchKey) {
+ this.setting.highlightFirst = query.length > 0;
if (gl.GfmAutoComplete.isLoading(items)) {
return items;
}
@@ -55,11 +56,9 @@
},
filter: function(query, data, searchKey) {
if (gl.GfmAutoComplete.isLoading(data)) {
- gl.GfmAutoComplete.togglePreventSelection.call(this, true);
gl.GfmAutoComplete.fetchData(this.$inputor, this.at);
return data;
} else {
- gl.GfmAutoComplete.togglePreventSelection.call(this, false);
return $.fn.atwho["default"].callbacks.filter(query, data, searchKey);
}
},
@@ -257,9 +256,9 @@
insertTpl: '${atwho-at}${title}',
callbacks: {
matcher: this.DefaultOptions.matcher,
- sorter: this.DefaultOptions.sorter,
beforeInsert: this.DefaultOptions.beforeInsert,
filter: this.DefaultOptions.filter,
+ sorter: this.DefaultOptions.sorter,
beforeSave: function(merges) {
if (gl.GfmAutoComplete.isLoading(merges)) return merges;
var sanitizeLabelTitle;
@@ -370,11 +369,7 @@
if (!data || !data.length) return false;
if (Array.isArray(data)) data = data[0];
return data === this.defaultLoadingData[0] || data.name === this.defaultLoadingData[0];
- },
- togglePreventSelection(isPrevented = !!this.setting.tabSelectsMatch) {
- this.setting.tabSelectsMatch = !isPrevented;
- this.setting.spaceSelectsMatch = !isPrevented;
- },
+ }
};
}).call(this);
diff --git a/app/assets/stylesheets/framework/awards.scss b/app/assets/stylesheets/framework/awards.scss
index 9fc9bcebc44..49907417e26 100644
--- a/app/assets/stylesheets/framework/awards.scss
+++ b/app/assets/stylesheets/framework/awards.scss
@@ -97,8 +97,20 @@
padding: 5px 6px;
outline: 0;
- &:hover,
+ &.disabled {
+ cursor: default;
+
+ &:hover,
+ &:focus,
+ &:active {
+ background-color: $white-light;
+ border-color: $border-color;
+ box-shadow: none;
+ }
+ }
+
&.active,
+ &:hover,
&:active {
background-color: $row-hover;
border-color: $row-hover-border;
diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss
index 88ed0a4a17e..c51912b4ac4 100644
--- a/app/assets/stylesheets/framework/files.scss
+++ b/app/assets/stylesheets/framework/files.scss
@@ -182,3 +182,52 @@ span.idiff {
border-bottom-right-radius: 2px;
}
}
+
+.file-stats {
+ ul {
+ list-style: none;
+ margin: 0;
+ padding: 10px 0;
+
+ li {
+ padding: 3px 0;
+ line-height: 20px;
+ }
+ }
+
+ .new-file {
+ a {
+ color: $gl-text-green;
+ }
+ }
+
+ .renamed-file {
+ a {
+ color: $gl-text-orange;
+ }
+ }
+
+ .deleted-file {
+ a {
+ color: $gl-text-red;
+ }
+ }
+
+ .edit-file {
+ a {
+ color: $gl-text-color;
+ }
+ }
+
+ a {
+ text-decoration: none;
+
+ .new-file {
+ color: $notify-new-file;
+ }
+
+ .deleted-file {
+ color: $notify-deleted-file;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss
index 277d4202950..bffd0e6f0cd 100644
--- a/app/assets/stylesheets/framework/lists.scss
+++ b/app/assets/stylesheets/framework/lists.scss
@@ -234,14 +234,46 @@ ul.content-list {
}
}
-.panel > .content-list > li {
- padding: $gl-padding-top $gl-padding;
+// Table list
+.table-list {
+ display: table;
+ width: 100%;
+
+ .table-list-row {
+ display: table-row;
+ }
+
+ .table-list-cell {
+ display: table-cell;
+ vertical-align: top;
+ padding: 10px 16px;
+ border-bottom: 1px solid $gray-darker;
- &.commit {
- @media (min-width: $screen-sm-min) {
- padding-left: 46px + $gl-padding;
+ &.avatar-cell {
+ width: 36px;
+ padding-right: 0;
+
+ img {
+ margin-right: 0;
+ }
}
}
+
+ &.table-wide {
+ .table-list-cell {
+ &:last-of-type {
+ padding-right: 0;
+ }
+
+ &:first-of-type {
+ padding-left: 0;
+ }
+ }
+ }
+}
+
+.panel > .content-list > li {
+ padding: $gl-padding-top $gl-padding;
}
ul.controls {
diff --git a/app/assets/stylesheets/framework/panels.scss b/app/assets/stylesheets/framework/panels.scss
index 9d8d08dff88..efe93724013 100644
--- a/app/assets/stylesheets/framework/panels.scss
+++ b/app/assets/stylesheets/framework/panels.scss
@@ -48,3 +48,11 @@
line-height: inherit;
}
}
+
+.panel-default {
+ .table-list-row:last-child {
+ .table-list-cell {
+ border-bottom: 0;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index b0c4a6edf57..dc211fc55a7 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -376,7 +376,6 @@ $callout-success-color: #3c763d;
/*
* Commit Page
*/
-$commit-committer-color: #999;
$commit-max-width-marker-color: rgba(0, 0, 0, 0.0);
$commit-message-text-area-bg: rgba(0, 0, 0, 0.0);
diff --git a/app/assets/stylesheets/notify.scss b/app/assets/stylesheets/notify.scss
index ddc382362f7..a81e5eb5ebf 100644
--- a/app/assets/stylesheets/notify.scss
+++ b/app/assets/stylesheets/notify.scss
@@ -18,15 +18,3 @@ p.details {
pre.commit-message {
white-space: pre-wrap;
}
-
-.file-stats > a {
- text-decoration: none;
-
- > .new-file {
- color: $notify-new-file;
- }
-
- > .deleted-file {
- color: $notify-deleted-file;
- }
-}
diff --git a/app/assets/stylesheets/pages/branches.scss b/app/assets/stylesheets/pages/branches.scss
new file mode 100644
index 00000000000..8d671585b7a
--- /dev/null
+++ b/app/assets/stylesheets/pages/branches.scss
@@ -0,0 +1,55 @@
+.divergence-graph {
+ padding: 12px 12px 0 0;
+ float: right;
+
+ .graph-side {
+ position: relative;
+ width: 80px;
+ height: 22px;
+ padding: 5px 0 13px;
+ float: left;
+
+ .bar {
+ position: absolute;
+ height: 4px;
+ background-color: $divergence-graph-bar-bg;
+ }
+
+ .bar-behind {
+ right: 0;
+ border-radius: 3px 0 0 3px;
+ }
+
+ .bar-ahead {
+ left: 0;
+ border-radius: 0 3px 3px 0;
+ }
+
+ .count {
+ padding-top: 6px;
+ padding-bottom: 0;
+ font-size: 12px;
+ color: $gl-title-color;
+ display: block;
+ }
+
+ .count-behind {
+ padding-right: 4px;
+ text-align: right;
+ }
+
+ .count-ahead {
+ padding-left: 4px;
+ text-align: left;
+ }
+ }
+
+ .graph-separator {
+ position: relative;
+ width: 1px;
+ height: 18px;
+ margin: 5px 0 0;
+ float: left;
+ background-color: $divergence-graph-separator-bg;
+ }
+}
diff --git a/app/assets/stylesheets/pages/commit.scss b/app/assets/stylesheets/pages/commit.scss
deleted file mode 100644
index bf656d0e28e..00000000000
--- a/app/assets/stylesheets/pages/commit.scss
+++ /dev/null
@@ -1,132 +0,0 @@
-.commit-title {
- display: block;
-}
-
-.commit-author,
-.commit-committer {
- display: block;
- color: $commit-committer-color;
- font-weight: normal;
- font-style: italic;
-}
-
-.commit-author strong,
-.commit-committer strong {
- font-weight: bold;
- font-style: normal;
-}
-
-.commit-description {
- background: none;
- border: none;
- margin: 0;
- padding: 0;
- margin-top: 10px;
- word-break: normal;
- white-space: pre-wrap;
-}
-
-.js-details-expand {
- &:hover {
- text-decoration: none;
- }
-}
-
-.ci-status-link {
- svg {
- overflow: visible;
- }
-}
-
-.commit-box {
- border-top: 1px solid $border-color;
- padding: $gl-padding 0;
-
- .commit-title {
- margin: 0;
- font-size: 23px;
- color: $gl-gray-dark;
- }
-
- .commit-description {
- margin-top: 15px;
- }
-}
-
-.commit-hash-full {
- @media (max-width: $screen-sm-max) {
- width: 80px;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- display: inline-block;
- vertical-align: bottom;
- }
-}
-
-.file-stats {
- ul {
- list-style: none;
- margin: 0;
- padding: 10px 0;
-
- li {
- padding: 3px 0;
- line-height: 20px;
- }
- }
-
- .new-file {
- a {
- color: $gl-text-green;
- }
- }
-
- .renamed-file {
- a {
- color: $gl-text-orange;
- }
- }
-
- .deleted-file {
- a {
- color: $gl-text-red;
- }
- }
-
- .edit-file {
- a {
- color: $gl-text-color;
- }
- }
-}
-
-/*
- * Commit message textarea for web editor and
- * custom merge request message
- */
-.commit-message-container {
- background-color: $body-bg;
- position: relative;
- font-family: $monospace_font;
- $left: 12px;
- overflow: hidden; // See https://gitlab.com/gitlab-org/gitlab-ce/issues/13987
- .max-width-marker {
- width: 72ch;
- color: $commit-max-width-marker-color;
- font-family: inherit;
- left: $left;
- height: 100%;
- border-right: 1px solid mix($input-border, $white-light);
- position: absolute;
- z-index: 1;
- }
-
- > textarea {
- background-color: $commit-message-text-area-bg;
- font-family: inherit;
- padding-left: $left;
- position: relative;
- z-index: 2;
- }
-}
diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss
index e76e1a73b25..d890cf3502b 100644
--- a/app/assets/stylesheets/pages/commits.scss
+++ b/app/assets/stylesheets/pages/commits.scss
@@ -1,6 +1,75 @@
+.commit-description {
+ background: none;
+ border: none;
+ padding: 0;
+ margin-top: 10px;
+ word-break: normal;
+ white-space: pre-wrap;
+}
+
+.js-details-expand {
+ &:hover {
+ text-decoration: none;
+ }
+}
+
+.commit-box {
+ border-top: 1px solid $border-color;
+ padding: $gl-padding 0;
+
+ .commit-title {
+ margin: 0;
+ color: $gl-gray-dark;
+ }
+
+ .commit-description {
+ margin-top: 15px;
+ }
+}
+
+.commit-hash-full {
+ @media (max-width: $screen-sm-max) {
+ width: 80px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ display: inline-block;
+ vertical-align: bottom;
+ }
+}
+
+/*
+ * Commit message textarea for web editor and
+ * custom merge request message
+ */
+.commit-message-container {
+ background-color: $body-bg;
+ position: relative;
+ font-family: $monospace_font;
+ $left: 12px;
+ overflow: hidden; // See https://gitlab.com/gitlab-org/gitlab-ce/issues/13987
+ .max-width-marker {
+ width: 72ch;
+ color: $commit-max-width-marker-color;
+ font-family: inherit;
+ left: $left;
+ height: 100%;
+ border-right: 1px solid mix($input-border, $white-light);
+ position: absolute;
+ z-index: 1;
+ }
+
+ textarea {
+ background-color: $commit-message-text-area-bg;
+ font-family: inherit;
+ padding-left: $left;
+ position: relative;
+ z-index: 2;
+ }
+}
+
+
.commits-compare-switch {
- @include btn-default;
- @include btn-white;
float: left;
margin-right: 9px;
}
@@ -8,7 +77,6 @@
.commit-header {
padding: 5px 10px;
background-color: $gray-light;
- border-top: 1px solid $gray-darker;
border-bottom: 1px solid $gray-darker;
font-size: 14px;
@@ -18,8 +86,6 @@
}
.commit-row-title {
- line-height: 1.35;
-
.notes_count {
float: right;
margin-right: 10px;
@@ -32,7 +98,6 @@
.commit-row-message {
color: $gl-dark-link-color;
}
-
}
.text-expander {
@@ -54,9 +119,8 @@
.commit-actions {
@media (min-width: $screen-sm-min) {
- float: right;
- margin-left: $gl-padding;
- margin-top: 2px;
+ width: 300px;
+ text-align: right;
font-size: 0;
}
@@ -86,16 +150,6 @@
.commit,
.generic_commit_status {
- padding: 10px 0;
- position: relative;
-
- @media (min-width: $screen-sm-min) {
- padding-left: 46px;
- }
-
- &:not(:last-child) {
- border-bottom: 1px solid $gray-darker;
- }
a,
button {
@@ -103,18 +157,6 @@
vertical-align: baseline;
}
- .avatar {
- margin-left: -46px;
- }
-
- .item-title {
- display: inline-block;
-
- @media (min-width: $screen-sm-min) {
- max-width: 70%;
- }
- }
-
.commit-row-description {
font-size: 14px;
border-left: 1px solid $white-normal;
@@ -138,19 +180,6 @@
}
}
- .commit-row-info {
- color: $gl-gray;
- line-height: 1.35;
-
- a {
- color: $gl-gray;
- }
-
- .avatar {
- margin-right: 8px;
- }
- }
-
&.inline-commit {
.commit-row-title {
font-size: 13px;
@@ -186,59 +215,3 @@
color: $gl-gray;
}
}
-
-.divergence-graph {
- padding: 12px 12px 0 0;
- float: right;
-
- .graph-side {
- position: relative;
- width: 80px;
- height: 22px;
- padding: 5px 0 13px;
- float: left;
-
- .bar {
- position: absolute;
- height: 4px;
- background-color: $divergence-graph-bar-bg;
- }
-
- .bar-behind {
- right: 0;
- border-radius: 3px 0 0 3px;
- }
-
- .bar-ahead {
- left: 0;
- border-radius: 0 3px 3px 0;
- }
-
- .count {
- padding-top: 6px;
- padding-bottom: 0;
- font-size: 12px;
- color: $gl-title-color;
- display: block;
- }
-
- .count-behind {
- padding-right: 4px;
- text-align: right;
- }
-
- .count-ahead {
- padding-left: 4px;
- text-align: left;
- }
- }
-
- .graph-separator {
- position: relative;
- width: 1px;
- height: 18px;
- margin: 5px 0 0;
- float: left;
- background-color: $divergence-graph-separator-bg;
- }
-}
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index 6b4d1f85564..42a3f5baed9 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -5,6 +5,12 @@
}
}
+ .title {
+ padding: 0;
+ margin: 0;
+ border-bottom: none;
+ }
+
// Border around images in issue and MR descriptions.
.description img:not(.emoji) {
border: 1px solid $white-normal;
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index 1b1126695a1..98d5967e76a 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -310,10 +310,6 @@
left: 0;
top: 2px;
}
-
- .commit-row-info {
- line-height: 20px;
- }
}
.btn-clipboard {
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index 8f15775ee03..21d72791e81 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -43,7 +43,7 @@ ul.notes {
}
.system-note-message {
- display: inline-block;
+ display: inline;
&::first-letter {
text-transform: lowercase;
@@ -55,7 +55,7 @@ ul.notes {
}
p {
- display: inline-block;
+ display: inline;
margin: 0;
&::first-letter {
@@ -353,6 +353,14 @@ ul.notes {
font-size: 14px;
}
+.note-headline-light {
+ display: inline;
+
+ @media (max-width: $screen-xs-min) {
+ display: block;
+ }
+}
+
.note-headline-light,
.discussion-headline-light {
color: $notes-light-color;
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index b99be02ab0c..4a1bc560292 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -26,7 +26,7 @@
margin-bottom: 5px;
}
- &> .form-group {
+ & > .form-group {
padding-left: 0;
}
}
@@ -73,7 +73,7 @@
border: 1px solid $border-color;
}
- &+ .select2 a {
+ & + .select2 a {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
@@ -618,7 +618,6 @@ pre.light-well {
margin: 0;
}
-
.activity-filter-block {
.controls {
padding-bottom: 7px;
@@ -811,7 +810,31 @@ pre.light-well {
.compare-form-group {
.dropdown-menu {
- width: 300px;
+ width: 100%;
+
+ @media (min-width: $screen-sm-min) {
+ width: 300px;
+ }
+ }
+
+ + .compare-ellipsis {
+ width: 100%;
+ vertical-align: middle;
+ text-align: center;
+ margin-top: -20px;
+
+ @media (min-width: $screen-sm-min) {
+ margin-top: 0;
+ width: auto;
+ }
+ }
+
+ .inline-input-group {
+ width: 100%;
+
+ @media (min-width: $screen-sm-min) {
+ width: 250px;
+ }
}
}
diff --git a/app/assets/stylesheets/pages/status.scss b/app/assets/stylesheets/pages/status.scss
index 4acd17360c1..2f6f03e9877 100644
--- a/app/assets/stylesheets/pages/status.scss
+++ b/app/assets/stylesheets/pages/status.scss
@@ -135,3 +135,9 @@
left: 5px;
}
}
+
+.ci-status-link {
+ svg {
+ overflow: visible;
+ }
+}
diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss
index cad4e149845..fe4f08e4749 100644
--- a/app/assets/stylesheets/pages/tree.scss
+++ b/app/assets/stylesheets/pages/tree.scss
@@ -134,21 +134,18 @@
.blob-commit-info {
list-style: none;
- padding: $gl-padding;
background: $gray-light;
+ padding: 6px 0;
border: 1px solid $border-color;
border-bottom: none;
margin: 0;
- .commit {
- padding-top: 0;
- padding-bottom: 0;
+ .table-list-cell {
+ border-bottom: none;
+ }
- .commit-row-title {
- .commit-row-message {
- font-weight: normal;
- }
- }
+ .commit-actions {
+ width: 200px;
}
}
diff --git a/app/controllers/projects/mattermosts_controller.rb b/app/controllers/projects/mattermosts_controller.rb
index d87dff2a80e..01d99c7df35 100644
--- a/app/controllers/projects/mattermosts_controller.rb
+++ b/app/controllers/projects/mattermosts_controller.rb
@@ -30,7 +30,7 @@ class Projects::MattermostsController < Projects::ApplicationController
def configure_params
params.require(:mattermost).permit(:trigger, :team_id).merge(
url: service_trigger_url(@service),
- icon_url: asset_url('gitlab_logo.png'))
+ icon_url: asset_url('slash-command-logo.png'))
end
def teams
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index fc8a289d49d..6004e7d7115 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -98,7 +98,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@start_version = @comparable_diffs.find { |diff| diff.head_commit_sha == @start_sha }
unless @start_version
- render_404
+ @start_sha = @merge_request_diff.head_commit_sha
+ @start_version = @merge_request_diff
end
end
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index c45196cc3e9..bf27f3d4d51 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -7,17 +7,17 @@ class RegistrationsController < Devise::RegistrationsController
end
def create
- if !Gitlab::Recaptcha.load_configurations! || verify_recaptcha
- # To avoid duplicate form fields on the login page, the registration form
- # names fields using `new_user`, but Devise still wants the params in
- # `user`.
- if params["new_#{resource_name}"].present? && params[resource_name].blank?
- params[resource_name] = params.delete(:"new_#{resource_name}")
- end
+ # To avoid duplicate form fields on the login page, the registration form
+ # names fields using `new_user`, but Devise still wants the params in
+ # `user`.
+ if params["new_#{resource_name}"].present? && params[resource_name].blank?
+ params[resource_name] = params.delete(:"new_#{resource_name}")
+ end
+ if !Gitlab::Recaptcha.load_configurations! || verify_recaptcha
super
else
- flash[:alert] = "There was an error with the reCAPTCHA code below. Please re-enter the code."
+ flash[:alert] = 'There was an error with the reCAPTCHA. Please re-solve the reCAPTCHA.'
flash.delete :recaptcha_error
render action: 'new'
end
@@ -57,7 +57,7 @@ class RegistrationsController < Devise::RegistrationsController
end
def sign_up_params
- params.require(:user).permit(:username, :email, :name, :password, :password_confirmation)
+ params.require(:user).permit(:username, :email, :email_confirmation, :name, :password)
end
def resource_name
diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb
index eb435cc1783..6d365ea9251 100644
--- a/app/helpers/gitlab_markdown_helper.rb
+++ b/app/helpers/gitlab_markdown_helper.rb
@@ -110,6 +110,28 @@ module GitlabMarkdownHelper
end
end
+ # Returns the text necessary to reference `entity` across projects
+ #
+ # project - Project to reference
+ # entity - Object that responds to `to_reference`
+ #
+ # Examples:
+ #
+ # cross_project_reference(project, project.issues.first)
+ # # => 'namespace1/project1#123'
+ #
+ # cross_project_reference(project, project.merge_requests.first)
+ # # => 'namespace1/project1!345'
+ #
+ # Returns a String
+ def cross_project_reference(project, entity)
+ if entity.respond_to?(:to_reference)
+ entity.to_reference(project, full: true)
+ else
+ ''
+ end
+ end
+
private
# Return +text+, truncated to +max_chars+ characters, excluding any HTML
@@ -158,28 +180,6 @@ module GitlabMarkdownHelper
end
end
- # Returns the text necessary to reference `entity` across projects
- #
- # project - Project to reference
- # entity - Object that responds to `to_reference`
- #
- # Examples:
- #
- # cross_project_reference(project, project.issues.first)
- # # => 'namespace1/project1#123'
- #
- # cross_project_reference(project, project.merge_requests.first)
- # # => 'namespace1/project1!345'
- #
- # Returns a String
- def cross_project_reference(project, entity)
- if entity.respond_to?(:to_reference)
- entity.to_reference(project)
- else
- ''
- end
- end
-
def markdown_toolbar_button(options = {})
data = options[:data].merge({ container: "body" })
content_tag :button,
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index a8a49e43b05..a2d21b67a77 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -58,13 +58,13 @@ module IssuesHelper
end
def status_box_class(item)
- if item.respond_to?(:expired?) && item.expired?
+ if item.try(:expired?)
'status-box-expired'
- elsif item.respond_to?(:merged?) && item.merged?
+ elsif item.try(:merged?)
'status-box-merged'
elsif item.closed?
'status-box-closed'
- elsif item.respond_to?(:upcoming?) && item.upcoming?
+ elsif item.try(:upcoming?)
'status-box-upcoming'
else
'status-box-open'
@@ -128,8 +128,10 @@ module IssuesHelper
names.to_sentence
end
- def award_active_class(awards, current_user)
- if current_user && awards.find { |a| a.user_id == current_user.id }
+ def award_state_class(awards, current_user)
+ if !current_user
+ "disabled"
+ elsif current_user && awards.find { |a| a.user_id == current_user.id }
"active"
else
""
diff --git a/app/models/commit.rb b/app/models/commit.rb
index 69cfc47f5bf..0b924b063a4 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -91,8 +91,8 @@ class Commit
@link_reference_pattern ||= super("commit", /(?<commit>\h{7,40})/)
end
- def to_reference(from_project = nil)
- commit_reference(from_project, id)
+ def to_reference(from_project = nil, full: false)
+ commit_reference(from_project, id, full: full)
end
def reference_link_text(from_project = nil)
@@ -320,8 +320,8 @@ class Commit
private
- def commit_reference(from_project, referable_commit_id)
- reference = project.to_reference(from_project)
+ def commit_reference(from_project, referable_commit_id, full: false)
+ reference = project.to_reference(from_project, full: full)
if reference.present?
"#{reference}#{self.class.reference_prefix}#{referable_commit_id}"
diff --git a/app/models/commit_range.rb b/app/models/commit_range.rb
index d9af7f6c139..84e2e8a5dd5 100644
--- a/app/models/commit_range.rb
+++ b/app/models/commit_range.rb
@@ -89,8 +89,8 @@ class CommitRange
alias_method :id, :to_s
- def to_reference(from_project = nil)
- project_reference = project.to_reference(from_project)
+ def to_reference(from_project = nil, full: false)
+ project_reference = project.to_reference(from_project, full: full)
if project_reference.present?
project_reference + self.class.reference_prefix + self.id
diff --git a/app/models/concerns/referable.rb b/app/models/concerns/referable.rb
index 8ba009fe04f..da803c7f481 100644
--- a/app/models/concerns/referable.rb
+++ b/app/models/concerns/referable.rb
@@ -17,7 +17,7 @@ module Referable
# Issue.last.to_reference(other_project) # => "cross-project#1"
#
# Returns a String
- def to_reference(_from_project = nil)
+ def to_reference(_from_project = nil, full:)
''
end
diff --git a/app/models/external_issue.rb b/app/models/external_issue.rb
index 91b508eb325..26712c19b5a 100644
--- a/app/models/external_issue.rb
+++ b/app/models/external_issue.rb
@@ -38,7 +38,7 @@ class ExternalIssue
@reference_pattern ||= %r{(?<issue>\b([A-Z][A-Z0-9_]+-)\d+)}
end
- def to_reference(_from_project = nil)
+ def to_reference(_from_project = nil, full: nil)
id
end
diff --git a/app/models/group.rb b/app/models/group.rb
index 9888b242e98..99675ddb366 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -80,7 +80,7 @@ class Group < Namespace
end
end
- def to_reference(_from_project = nil)
+ def to_reference(_from_project = nil, full: nil)
"#{self.class.reference_prefix}#{name}"
end
diff --git a/app/models/group_label.rb b/app/models/group_label.rb
index 68841ace2e6..92c83b54861 100644
--- a/app/models/group_label.rb
+++ b/app/models/group_label.rb
@@ -8,8 +8,4 @@ class GroupLabel < Label
def subject_foreign_key
'group_id'
end
-
- def to_reference(source_project = nil, target_project = nil, format: :id)
- super(source_project, target_project, format: format)
- end
end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 6825553512f..65638d9a299 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -97,10 +97,10 @@ class Issue < ActiveRecord::Base
end
end
- def to_reference(from_project = nil)
+ def to_reference(from_project = nil, full: false)
reference = "#{self.class.reference_prefix}#{iid}"
- "#{project.to_reference(from_project)}#{reference}"
+ "#{project.to_reference(from_project, full: full)}#{reference}"
end
def referenced_merge_requests(current_user = nil)
diff --git a/app/models/label.rb b/app/models/label.rb
index d38c37344c9..5c01c15e5af 100644
--- a/app/models/label.rb
+++ b/app/models/label.rb
@@ -146,17 +146,17 @@ class Label < ActiveRecord::Base
#
# Label.first.to_reference # => "~1"
# Label.first.to_reference(format: :name) # => "~\"bug\""
- # Label.first.to_reference(project, same_namespace_project) # => "gitlab-ce~1"
- # Label.first.to_reference(project, another_namespace_project) # => "gitlab-org/gitlab-ce~1"
+ # Label.first.to_reference(project, target_project: same_namespace_project) # => "gitlab-ce~1"
+ # Label.first.to_reference(project, target_project: another_namespace_project) # => "gitlab-org/gitlab-ce~1"
#
# Returns a String
#
- def to_reference(source_project = nil, target_project = nil, format: :id)
+ def to_reference(from_project = nil, target_project: nil, format: :id, full: false)
format_reference = label_format_reference(format)
reference = "#{self.class.reference_prefix}#{format_reference}"
- if source_project
- "#{source_project.to_reference(target_project)}#{reference}"
+ if from_project
+ "#{from_project.to_reference(target_project, full: full)}#{reference}"
else
reference
end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 61845bf4036..926944bc3b3 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -175,10 +175,10 @@ class MergeRequest < ActiveRecord::Base
work_in_progress?(title) ? title : "WIP: #{title}"
end
- def to_reference(from_project = nil)
+ def to_reference(from_project = nil, full: false)
reference = "#{self.class.reference_prefix}#{iid}"
- "#{project.to_reference(from_project)}#{reference}"
+ "#{project.to_reference(from_project, full: full)}#{reference}"
end
def first_commit
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index 0dcfec89f14..8a11f47dd67 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -118,11 +118,11 @@ class Milestone < ActiveRecord::Base
# Milestone.first.to_reference(cross_namespace_project) # => "gitlab-org/gitlab-ce%1"
# Milestone.first.to_reference(same_namespace_project) # => "gitlab-ce%1"
#
- def to_reference(from_project = nil, format: :iid)
+ def to_reference(from_project = nil, format: :iid, full: false)
format_reference = milestone_format_reference(format)
reference = "#{self.class.reference_prefix}#{format_reference}"
- "#{project.to_reference(from_project)}#{reference}"
+ "#{project.to_reference(from_project, full: full)}#{reference}"
end
def reference_link_text(from_project = nil)
diff --git a/app/models/project.rb b/app/models/project.rb
index e0ffa7e7af7..ec40def6fb1 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -589,8 +589,8 @@ class Project < ActiveRecord::Base
end
end
- def to_reference(from_project = nil)
- if cross_namespace_reference?(from_project)
+ def to_reference(from_project = nil, full: false)
+ if full || cross_namespace_reference?(from_project)
path_with_namespace
elsif cross_project_reference?(from_project)
path
@@ -609,10 +609,6 @@ class Project < ActiveRecord::Base
Gitlab::Routing.url_helpers.namespace_project_url(self.namespace, self)
end
- def web_url_without_protocol
- web_url.split('://')[1]
- end
-
def new_issue_address(author)
return unless Gitlab::IncomingEmail.supports_issue_creation? && author
diff --git a/app/models/project_label.rb b/app/models/project_label.rb
index 82f47f0e8fd..313815e5869 100644
--- a/app/models/project_label.rb
+++ b/app/models/project_label.rb
@@ -16,8 +16,8 @@ class ProjectLabel < Label
'project_id'
end
- def to_reference(target_project = nil, format: :id)
- super(project, target_project, format: format)
+ def to_reference(target_project = nil, format: :id, full: false)
+ super(project, target_project: target_project, format: format, full: full)
end
private
diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index 98ccf5f331f..771a7350556 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -64,11 +64,11 @@ class Snippet < ActiveRecord::Base
@link_reference_pattern ||= super("snippets", /(?<snippet>\d+)/)
end
- def to_reference(from_project = nil)
+ def to_reference(from_project = nil, full: false)
reference = "#{self.class.reference_prefix}#{id}"
if project.present?
- "#{project.to_reference(from_project)}#{reference}"
+ "#{project.to_reference(from_project, full: full)}#{reference}"
else
reference
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 899a89a4eaa..66a768d54bb 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -99,6 +99,7 @@ class User < ActiveRecord::Base
#
# Note: devise :validatable above adds validations for :email and :password
validates :name, presence: true
+ validates_confirmation_of :email
validates :notification_email, presence: true
validates :notification_email, email: true, if: ->(user) { user.notification_email != user.email }
validates :public_email, presence: true, uniqueness: true, email: true, allow_blank: true
@@ -332,7 +333,7 @@ class User < ActiveRecord::Base
username
end
- def to_reference(_from_project = nil, _target_project = nil)
+ def to_reference(_from_project = nil, target_project: nil, full: nil)
"#{self.class.reference_prefix}#{username}"
end
diff --git a/app/uploaders/avatar_uploader.rb b/app/uploaders/avatar_uploader.rb
index a1ecb7bc00b..265cea2d2c6 100644
--- a/app/uploaders/avatar_uploader.rb
+++ b/app/uploaders/avatar_uploader.rb
@@ -10,4 +10,15 @@ class AvatarUploader < GitlabUploader
def exists?
model.avatar.file && model.avatar.file.exists?
end
+
+ # We set move_to_store and move_to_cache to 'false' to prevent stealing
+ # the avatar file from a project when forking it.
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/26158
+ def move_to_store
+ false
+ end
+
+ def move_to_cache
+ false
+ end
end
diff --git a/app/views/award_emoji/_awards_block.html.haml b/app/views/award_emoji/_awards_block.html.haml
index d8912eda314..e3305e21e96 100644
--- a/app/views/award_emoji/_awards_block.html.haml
+++ b/app/views/award_emoji/_awards_block.html.haml
@@ -2,8 +2,7 @@
.awards.js-awards-block{ class: ("hidden" if !inline && grouped_emojis.empty?), data: { award_url: toggle_award_url(awardable) } }
- awards_sort(grouped_emojis).each do |emoji, awards|
%button.btn.award-control.js-emoji-btn.has-tooltip{ type: "button",
- disabled: !current_user,
- class: (award_active_class(awards, current_user)),
+ class: (award_state_class(awards, current_user)),
data: { placement: "bottom", title: award_user_list(awards, current_user) } }
= emoji_icon(emoji, sprite: false)
%span.award-control-text.js-counter
diff --git a/app/views/devise/shared/_signup_box.html.haml b/app/views/devise/shared/_signup_box.html.haml
index 545a938f4be..681eb303b49 100644
--- a/app/views/devise/shared/_signup_box.html.haml
+++ b/app/views/devise/shared/_signup_box.html.haml
@@ -15,6 +15,9 @@
.form-group
= f.label :email
= f.email_field :email, class: "form-control middle", required: true, title: "Please provide a valid email address."
+ %div.form-group
+ = f.label :email_confirmation
+ = f.email_field :email_confirmation, class: "form-control middle", required: true, title: "Please retype the email address."
.form-group.append-bottom-20#password-strength
= f.label :password
= f.password_field :password, class: "form-control bottom", required: true, pattern: ".{#{@minimum_password_length},}", title: "Minimum length is #{@minimum_password_length} characters."
diff --git a/app/views/projects/blob/_blob.html.haml b/app/views/projects/blob/_blob.html.haml
index 350bdf5f836..f75f438ee4f 100644
--- a/app/views/projects/blob/_blob.html.haml
+++ b/app/views/projects/blob/_blob.html.haml
@@ -18,7 +18,7 @@
- else
= link_to title, '#'
-%ul.blob-commit-info.hidden-xs
+%ul.blob-commit-info.table-list.hidden-xs
- blob_commit = @repository.last_commit_for_path(@commit.id, blob.path)
= render blob_commit, project: @project, ref: @ref
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index a940515fadf..3c6c50dce3c 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -9,33 +9,33 @@
- cache_key.push(commit.status(ref)) if commit.status(ref)
= cache(cache_key, expires_in: 1.day) do
- %li.commit.js-toggle-container{ id: "commit-#{commit.short_id}" }
- = author_avatar(commit, size: 36)
+ %li.commit.table-list-row.js-toggle-container{ id: "commit-#{commit.short_id}" }
- .commit-info-block
- .commit-row-title
- %span.item-title
- = link_to_gfm commit.title, namespace_project_commit_path(project.namespace, project, commit.id), class: "commit-row-message"
- %span.commit-row-message.visible-xs-inline
- &middot;
- = commit.short_id
- - if commit.status(ref)
- .visible-xs-inline
- = render_commit_status(commit, ref: ref)
- - if commit.description?
- %a.text-expander.hidden-xs.js-toggle-button ...
+ .table-list-cell.avatar-cell.hidden-xs
+ = author_avatar(commit, size: 36)
- .commit-actions.hidden-xs
- - if commit.status(ref)
- = render_commit_status(commit, ref: ref)
- = clipboard_button(clipboard_text: commit.id)
- = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit-short-id btn btn-transparent"
- = link_to_browse_code(project, commit)
+ .table-list-cell.commit-content
+ = link_to_gfm commit.title, namespace_project_commit_path(project.namespace, project, commit.id), class: "commit-row-message item-title"
+ %span.commit-row-message.visible-xs-inline
+ &middot;
+ = commit.short_id
+ - if commit.status(ref)
+ .visible-xs-inline
+ = render_commit_status(commit, ref: ref)
+ - if commit.description?
+ %a.text-expander.hidden-xs.js-toggle-button ...
- if commit.description?
%pre.commit-row-description.js-toggle-content
= preserve(markdown(commit.description, pipeline: :single_line, author: commit.author))
+ .commiter
+ = commit_author_link(commit, avatar: false, size: 24)
+ committed
+ #{time_ago_with_tooltip(commit.committed_date)}
- = commit_author_link(commit, avatar: false, size: 24)
- committed
- #{time_ago_with_tooltip(commit.committed_date)}
+ .table-list-cell.commit-actions.hidden-xs
+ - if commit.status(ref)
+ = render_commit_status(commit, ref: ref)
+ = clipboard_button(clipboard_text: commit.id)
+ = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit-short-id btn btn-transparent"
+ = link_to_browse_code(project, commit)
diff --git a/app/views/projects/commits/_commit_list.html.haml b/app/views/projects/commits/_commit_list.html.haml
index 6f5835cb9be..64d93e4141c 100644
--- a/app/views/projects/commits/_commit_list.html.haml
+++ b/app/views/projects/commits/_commit_list.html.haml
@@ -11,4 +11,4 @@
%li.warning-row.unstyled
#{number_with_delimiter(hidden)} additional commits have been omitted to prevent performance issues.
- else
- %ul.content-list= render commits, project: @project, ref: @ref
+ %ul.content-list.table-list= render commits, project: @project, ref: @ref
diff --git a/app/views/projects/commits/_commits.html.haml b/app/views/projects/commits/_commits.html.haml
index 48756c68941..fcc367951ad 100644
--- a/app/views/projects/commits/_commits.html.haml
+++ b/app/views/projects/commits/_commits.html.haml
@@ -4,7 +4,7 @@
- commits.chunk { |c| c.committed_date.in_time_zone.to_date }.each do |day, commits|
%li.commit-header= "#{day.strftime('%d %b, %Y')} #{pluralize(commits.count, 'commit')}"
%li.commits-row
- %ul.list-unstyled.commit-list
+ %ul.content-list.commit-list.table-list.table-wide
= render commits, project: project, ref: ref
- if hidden > 0
diff --git a/app/views/projects/compare/_form.html.haml b/app/views/projects/compare/_form.html.haml
index 7bde20c3286..d76d48187cd 100644
--- a/app/views/projects/compare/_form.html.haml
+++ b/app/views/projects/compare/_form.html.haml
@@ -2,21 +2,21 @@
.clearfix
- if params[:to] && params[:from]
.compare-switch-container
- = link_to icon('exchange'), {from: params[:to], to: params[:from]}, {class: 'commits-compare-switch has-tooltip', title: 'Switch base of comparison'}
+ = link_to icon('exchange'), {from: params[:to], to: params[:from]}, {class: 'commits-compare-switch has-tooltip btn btn-white', title: 'Switch base of comparison'}
.form-group.dropdown.compare-form-group.from.js-compare-from-dropdown
.input-group.inline-input-group
%span.input-group-addon from
= hidden_field_tag :from, params[:from]
- = button_tag type: 'button', class: "form-control compare-dropdown-toggle js-compare-dropdown", required: true, data: { refs_url: refs_namespace_project_path(@project.namespace, @project), toggle: "dropdown", target: ".js-compare-from-dropdown", selected: params[:from], field_name: :from } do
- .dropdown-toggle-text= params[:from] || 'Select branch/tag'
+ = button_tag type: 'button', title: params[:from], class: "form-control compare-dropdown-toggle js-compare-dropdown has-tooltip", required: true, data: { refs_url: refs_namespace_project_path(@project.namespace, @project), toggle: "dropdown", target: ".js-compare-from-dropdown", selected: params[:from], field_name: :from } do
+ .dropdown-toggle-text.str-truncated= params[:from] || 'Select branch/tag'
= render "ref_dropdown"
.compare-ellipsis.inline ...
.form-group.dropdown.compare-form-group.to.js-compare-to-dropdown
.input-group.inline-input-group
%span.input-group-addon to
= hidden_field_tag :to, params[:to]
- = button_tag type: 'button', class: "form-control compare-dropdown-toggle js-compare-dropdown", required: true, data: { refs_url: refs_namespace_project_path(@project.namespace, @project), toggle: "dropdown", target: ".js-compare-to-dropdown", selected: params[:to], field_name: :to } do
- .dropdown-toggle-text= params[:to] || 'Select branch/tag'
+ = button_tag type: 'button', title: params[:to], class: "form-control compare-dropdown-toggle js-compare-dropdown has-tooltip", required: true, data: { refs_url: refs_namespace_project_path(@project.namespace, @project), toggle: "dropdown", target: ".js-compare-to-dropdown", selected: params[:to], field_name: :to } do
+ .dropdown-toggle-text.str-truncated= params[:to] || 'Select branch/tag'
= render "ref_dropdown"
&nbsp;
= button_tag "Compare", class: "btn btn-create commits-compare-btn"
diff --git a/app/views/projects/cycle_analytics/_empty_stage.html.haml b/app/views/projects/cycle_analytics/_empty_stage.html.haml
index b200ce22970..c3f95860e92 100644
--- a/app/views/projects/cycle_analytics/_empty_stage.html.haml
+++ b/app/views/projects/cycle_analytics/_empty_stage.html.haml
@@ -2,6 +2,6 @@
.empty-stage
.icon-no-data
= custom_icon ('icon_no_data')
- %h4 We don’t have enough data to show this stage.
+ %h4 We don't have enough data to show this stage.
%p
{{currentStage.emptyStageText}}
diff --git a/app/views/projects/cycle_analytics/show.html.haml b/app/views/projects/cycle_analytics/show.html.haml
index 89e2e162b5b..479ce44f378 100644
--- a/app/views/projects/cycle_analytics/show.html.haml
+++ b/app/views/projects/cycle_analytics/show.html.haml
@@ -28,8 +28,8 @@
.container-fluid
.row
.col-sm-3.col-xs-12.column{ "v-for" => "item in state.summary" }
- %h3.header {{item.value}}
- %p.text {{item.title}}
+ %h3.header {{ item.value }}
+ %p.text {{ item.title }}
.col-sm-3.col-xs-12.column
.dropdown.inline.js-ca-dropdown
%button.dropdown-menu-toggle{ "data-toggle" => "dropdown", :type => "button" }
diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml
index 633701c6f40..d9a3220b002 100644
--- a/app/views/projects/merge_requests/_show.html.haml
+++ b/app/views/projects/merge_requests/_show.html.haml
@@ -42,7 +42,7 @@
= render "projects/merge_requests/widget/show.html.haml"
- if @merge_request.source_branch_exists? && @merge_request.mergeable? && @merge_request.can_be_merged_by?(current_user)
- .merge-manually.light.prepend-top-default.append-bottom-default
+ .merge-manually.light.prepend-top-default
You can also accept this merge request manually using the
= succeed '.' do
= link_to "command line", "#modal_merge_info", class: "how_to_merge_link vlink", title: "How To Merge", "data-toggle" => "modal"
diff --git a/app/views/projects/merge_requests/show/_versions.html.haml b/app/views/projects/merge_requests/show/_versions.html.haml
index ac4a03220b9..b0f3c86fd21 100644
--- a/app/views/projects/merge_requests/show/_versions.html.haml
+++ b/app/views/projects/merge_requests/show/_versions.html.haml
@@ -19,7 +19,7 @@
%ul
- @merge_request_diffs.each do |merge_request_diff|
%li
- = link_to merge_request_version_path(@project, @merge_request, merge_request_diff), class: ('is-active' if merge_request_diff == @merge_request_diff) do
+ = link_to merge_request_version_path(@project, @merge_request, merge_request_diff, @start_sha), class: ('is-active' if merge_request_diff == @merge_request_diff) do
%strong
- if merge_request_diff.latest?
latest version
diff --git a/app/views/projects/services/slack_slash_commands/_help.html.haml b/app/views/projects/services/slack_slash_commands/_help.html.haml
index c45052e3954..6d7c2defe2b 100644
--- a/app/views/projects/services/slack_slash_commands/_help.html.haml
+++ b/app/views/projects/services/slack_slash_commands/_help.html.haml
@@ -50,7 +50,7 @@
.form-group
= label_tag nil, 'Customize icon', class: 'col-sm-2 col-xs-12 control-label'
.col-sm-10.col-xs-12.text-block
- = image_tag(asset_url('gitlab_logo.png'), width: 36, height: 36)
+ = image_tag(asset_url('slash-command-logo.png'), width: 36, height: 36)
= link_to('Download image', asset_url('gitlab_logo.png'), class: 'btn btn-sm', target: '_blank')
.form-group
diff --git a/changelogs/unreleased/25580-trucate-dropdown-for-long-branch.yml b/changelogs/unreleased/25580-trucate-dropdown-for-long-branch.yml
new file mode 100644
index 00000000000..18d3ac050ae
--- /dev/null
+++ b/changelogs/unreleased/25580-trucate-dropdown-for-long-branch.yml
@@ -0,0 +1,4 @@
+---
+title: Resolves overflow in compare branch and tags dropdown
+merge_request: 8118
+author:
diff --git a/changelogs/unreleased/add_email_password_confirmation.yml b/changelogs/unreleased/add_email_password_confirmation.yml
new file mode 100644
index 00000000000..92f9b9b7a6d
--- /dev/null
+++ b/changelogs/unreleased/add_email_password_confirmation.yml
@@ -0,0 +1,4 @@
+---
+title: Add email confirmation field to registration form
+merge_request: 7432
+author:
diff --git a/changelogs/unreleased/additional-award-emoji-repositioning-fixes.yml b/changelogs/unreleased/additional-award-emoji-repositioning-fixes.yml
new file mode 100644
index 00000000000..8d5a94c3aa8
--- /dev/null
+++ b/changelogs/unreleased/additional-award-emoji-repositioning-fixes.yml
@@ -0,0 +1,4 @@
+---
+title: Removed bottom padding from merge manually from CLI because of repositioning award emoji's
+merge_request:
+author:
diff --git a/changelogs/unreleased/api-hooks-changelog-entry.yml b/changelogs/unreleased/api-hooks-changelog-entry.yml
new file mode 100644
index 00000000000..7d0b515ddf1
--- /dev/null
+++ b/changelogs/unreleased/api-hooks-changelog-entry.yml
@@ -0,0 +1,4 @@
+---
+title: Rename wiki_events to wiki_page_events in project hooks API to avoid errors
+merge_request: Robert Schilling
+author: 8425
diff --git a/changelogs/unreleased/fix-cross-project-ref-path.yml b/changelogs/unreleased/fix-cross-project-ref-path.yml
new file mode 100644
index 00000000000..91acc1db0a6
--- /dev/null
+++ b/changelogs/unreleased/fix-cross-project-ref-path.yml
@@ -0,0 +1,4 @@
+---
+title: Fix cross-project references copy to include the project reference
+merge_request:
+author:
diff --git a/changelogs/unreleased/ldap_person_attributes.yml b/changelogs/unreleased/ldap_person_attributes.yml
new file mode 100644
index 00000000000..d04b5dbe7e0
--- /dev/null
+++ b/changelogs/unreleased/ldap_person_attributes.yml
@@ -0,0 +1,4 @@
+---
+title: Gitlab::LDAP::Person uses LDAP attributes configuration
+merge_request: 8418
+author:
diff --git a/changelogs/unreleased/project-avatar-fork.yml b/changelogs/unreleased/project-avatar-fork.yml
new file mode 100644
index 00000000000..6facffe7887
--- /dev/null
+++ b/changelogs/unreleased/project-avatar-fork.yml
@@ -0,0 +1,4 @@
+---
+title: Copy, don't move uploaded avatar files
+merge_request: 8396
+author:
diff --git a/changelogs/unreleased/recaptcha_500.yml b/changelogs/unreleased/recaptcha_500.yml
new file mode 100644
index 00000000000..de9ef183d5e
--- /dev/null
+++ b/changelogs/unreleased/recaptcha_500.yml
@@ -0,0 +1,4 @@
+---
+title: Properly handle failed reCAPTCHA on user registration
+merge_request: 8403
+author:
diff --git a/changelogs/unreleased/regression-note-headline-light.yml b/changelogs/unreleased/regression-note-headline-light.yml
new file mode 100644
index 00000000000..f24d4cb014c
--- /dev/null
+++ b/changelogs/unreleased/regression-note-headline-light.yml
@@ -0,0 +1,4 @@
+---
+title: Fixed regression of note-headline-light where it was always placed on 2 lines, even on wide viewports
+merge_request:
+author:
diff --git a/doc/development/changelog.md b/doc/development/changelog.md
index 6a97fae9cac..c71858c6a24 100644
--- a/doc/development/changelog.md
+++ b/doc/development/changelog.md
@@ -40,6 +40,15 @@ Its simplest usage is to provide the value for `title`:
```text
$ bin/changelog 'Hey DZ, I added a feature to GitLab!'
+```
+
+The entry filename is based on the name of the current Git branch. If you run
+the command above on a branch called `feature/hey-dz`, it will generate a
+`changelogs/unreleased/feature-hey-dz.yml` file.
+
+The command will output the path of the generated file and its contents:
+
+```text
create changelogs/unreleased/my-feature.yml
---
title: Hey DZ, I added a feature to GitLab!
@@ -47,10 +56,6 @@ merge_request:
author:
```
-The entry filename is based on the name of the current Git branch. If you run
-the command above on a branch called `feature/hey-dz`, it will generate a
-`changelogs/unreleased/feature-hey-dz.yml` file.
-
### Arguments
| Argument | Shorthand | Purpose |
@@ -139,7 +144,7 @@ Use the **`--git-username`** or **`-u`** argument to automatically fill in the
$ git config user.name
Jane Doe
-$ bin/changelog --u 'Hey DZ, I added a feature to GitLab!'
+$ bin/changelog -u 'Hey DZ, I added a feature to GitLab!'
create changelogs/unreleased/feature-hey-dz.yml
---
title: Hey DZ, I added a feature to GitLab!
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index 91f65882f47..54b97402426 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -5,28 +5,18 @@ module API
before { authenticate! }
helpers do
- def filter_issues_state(issues, state)
- case state
- when 'opened' then issues.opened
- when 'closed' then issues.closed
- else issues
- end
- end
-
+ # TODO: Remove in 9.0 and switch to IssueFinder-based label filtering
def filter_issues_labels(issues, labels)
issues.includes(:labels).where('labels.title' => labels.split(','))
end
- def filter_issues_milestone(issues, milestone)
- issues.includes(:milestone).where('milestones.title' => milestone)
- end
-
params :issues_params do
optional :labels, type: String, desc: 'Comma-separated list of label names'
optional :order_by, type: String, values: %w[created_at updated_at], default: 'created_at',
desc: 'Return issues ordered by `created_at` or `updated_at` fields.'
optional :sort, type: String, values: %w[asc desc], default: 'desc',
desc: 'Return issues sorted in `asc` or `desc` order.'
+ optional :milestone, type: String, desc: 'Return issues for a specific milestone'
use :pagination
end
@@ -50,8 +40,7 @@ module API
use :issues_params
end
get do
- issues = current_user.issues.inc_notes_with_associations
- issues = filter_issues_state(issues, params[:state])
+ issues = IssuesFinder.new(current_user, scope: 'all', author_id: current_user.id, state: params[:state]).execute.inc_notes_with_associations
issues = filter_issues_labels(issues, params[:labels]) unless params[:labels].nil?
issues = issues.reorder(params[:order_by] => params[:sort])
@@ -99,16 +88,14 @@ module API
use :issues_params
end
get ":id/issues" do
- issues = IssuesFinder.new(current_user, project_id: user_project.id).execute.inc_notes_with_associations
- issues = filter_issues_state(issues, params[:state])
+ issues = IssuesFinder.new(current_user,
+ project_id: user_project.id,
+ state: params[:state],
+ milestone_title: params[:milestone]).execute.inc_notes_with_associations
issues = filter_issues_labels(issues, params[:labels]) unless params[:labels].nil?
issues = filter_by_iid(issues, params[:iid]) unless params[:iid].nil?
-
- unless params[:milestone].nil?
- issues = filter_issues_milestone(issues, params[:milestone])
- end
-
issues = issues.reorder(params[:order_by] => params[:sort])
+
present paginate(issues), with: Entities::Issue, current_user: current_user, project: user_project
end
diff --git a/lib/api/project_hooks.rb b/lib/api/project_hooks.rb
index dcc0fb7a911..cb679e6658a 100644
--- a/lib/api/project_hooks.rb
+++ b/lib/api/project_hooks.rb
@@ -15,7 +15,7 @@ module API
optional :note_events, type: Boolean, desc: "Trigger hook on note(comment) events"
optional :build_events, type: Boolean, desc: "Trigger hook on build events"
optional :pipeline_events, type: Boolean, desc: "Trigger hook on pipeline events"
- optional :wiki_events, type: Boolean, desc: "Trigger hook on wiki events"
+ optional :wiki_page_events, type: Boolean, desc: "Trigger hook on wiki events"
optional :enable_ssl_verification, type: Boolean, desc: "Do SSL verification when triggering the hook"
optional :token, type: String, desc: "Secret token to validate received payloads; this will not be returned in the response"
end
diff --git a/lib/api/users.rb b/lib/api/users.rb
index 4c22287b5c6..de07fbf59fc 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -16,7 +16,7 @@ module API
optional :website_url, type: String, desc: 'The website of the user'
optional :organization, type: String, desc: 'The organization of the user'
optional :projects_limit, type: Integer, desc: 'The number of projects a user can create'
- optional :extern_uid, type: Integer, desc: 'The external authentication provider UID'
+ optional :extern_uid, type: String, desc: 'The external authentication provider UID'
optional :provider, type: String, desc: 'The external provider'
optional :bio, type: String, desc: 'The biography of the user'
optional :location, type: String, desc: 'The location of the user'
diff --git a/lib/gitlab/chat_commands/deploy.rb b/lib/gitlab/chat_commands/deploy.rb
index 0f70323810d..7127d2f6d04 100644
--- a/lib/gitlab/chat_commands/deploy.rb
+++ b/lib/gitlab/chat_commands/deploy.rb
@@ -49,9 +49,9 @@ module Gitlab
end
def url(subject)
- project = subject.project
-
- namespace_project_build_url(project.namespace.becomes(Namespace), project, subject)
+ polymorphic_url(
+ [subject.project.namespace.becomes(Namespace), subject.project, subject]
+ )
end
end
end
diff --git a/lib/gitlab/gfm/reference_rewriter.rb b/lib/gitlab/gfm/reference_rewriter.rb
index a7c596dced0..b984492d369 100644
--- a/lib/gitlab/gfm/reference_rewriter.rb
+++ b/lib/gitlab/gfm/reference_rewriter.rb
@@ -76,7 +76,7 @@ module Gitlab
if referable.respond_to?(:project)
referable.to_reference(target_project)
else
- referable.to_reference(@source_project, target_project)
+ referable.to_reference(@source_project, target_project: target_project)
end
end
diff --git a/lib/gitlab/ldap/person.rb b/lib/gitlab/ldap/person.rb
index b81f3e8e8f5..333f170a484 100644
--- a/lib/gitlab/ldap/person.rb
+++ b/lib/gitlab/ldap/person.rb
@@ -28,7 +28,7 @@ module Gitlab
end
def name
- entry.cn.first
+ attribute_value(:name)
end
def uid
@@ -40,7 +40,7 @@ module Gitlab
end
def email
- entry.try(:mail)
+ attribute_value(:email)
end
def dn
@@ -56,6 +56,21 @@ module Gitlab
def config
@config ||= Gitlab::LDAP::Config.new(provider)
end
+
+ # Using the LDAP attributes configuration, find and return the first
+ # attribute with a value. For example, by default, when given 'email',
+ # this method looks for 'mail', 'email' and 'userPrincipalName' and
+ # returns the first with a value.
+ def attribute_value(attribute)
+ attributes = Array(config.attributes[attribute.to_sym])
+ selected_attr = attributes.find { |attr| entry.respond_to?(attr) }
+
+ return nil unless selected_attr
+
+ # Some LDAP attributes return an array,
+ # even if it is a single value (like 'cn')
+ Array(entry.public_send(selected_attr)).first
+ end
end
end
end
diff --git a/public/slash-command-logo.png b/public/slash-command-logo.png
new file mode 100644
index 00000000000..05c8b0d0ccf
--- /dev/null
+++ b/public/slash-command-logo.png
Binary files differ
diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb
index 026f41c926b..42fbfe89368 100644
--- a/spec/controllers/registrations_controller_spec.rb
+++ b/spec/controllers/registrations_controller_spec.rb
@@ -2,30 +2,60 @@ require 'spec_helper'
describe RegistrationsController do
describe '#create' do
- around(:each) do |example|
- perform_enqueued_jobs do
- example.run
+ let(:user_params) { { user: { name: 'new_user', username: 'new_username', email: 'new@user.com', password: 'Any_password' } } }
+
+ context 'email confirmation' do
+ around(:each) do |example|
+ perform_enqueued_jobs do
+ example.run
+ end
end
- end
- let(:user_params) { { user: { name: "new_user", username: "new_username", email: "new@user.com", password: "Any_password" } } }
+ context 'when send_user_confirmation_email is false' do
+ it 'signs the user in' do
+ allow_any_instance_of(ApplicationSetting).to receive(:send_user_confirmation_email).and_return(false)
+
+ expect { post(:create, user_params) }.not_to change{ ActionMailer::Base.deliveries.size }
+ expect(subject.current_user).not_to be_nil
+ end
+ end
- context 'when sending email confirmation' do
- before { allow_any_instance_of(ApplicationSetting).to receive(:send_user_confirmation_email).and_return(false) }
+ context 'when send_user_confirmation_email is true' do
+ it 'does not authenticate user and sends confirmation email' do
+ allow_any_instance_of(ApplicationSetting).to receive(:send_user_confirmation_email).and_return(true)
- it 'logs user in directly' do
- expect { post(:create, user_params) }.not_to change{ ActionMailer::Base.deliveries.size }
- expect(subject.current_user).not_to be_nil
+ post(:create, user_params)
+
+ expect(ActionMailer::Base.deliveries.last.to.first).to eq(user_params[:user][:email])
+ expect(subject.current_user).to be_nil
+ end
end
end
- context 'when not sending email confirmation' do
- before { allow_any_instance_of(ApplicationSetting).to receive(:send_user_confirmation_email).and_return(true) }
+ context 'when reCAPTCHA is enabled' do
+ before do
+ stub_application_setting(recaptcha_enabled: true)
+ end
+
+ it 'displays an error when the reCAPTCHA is not solved' do
+ # Without this, `verify_recaptcha` arbitraily returns true in test env
+ Recaptcha.configuration.skip_verify_env.delete('test')
- it 'does not authenticate user and sends confirmation email' do
post(:create, user_params)
- expect(ActionMailer::Base.deliveries.last.to.first).to eq(user_params[:user][:email])
- expect(subject.current_user).to be_nil
+
+ expect(response).to render_template(:new)
+ expect(flash[:alert]).to include 'There was an error with the reCAPTCHA. Please re-solve the reCAPTCHA.'
+ end
+
+ it 'redirects to the dashboard when the recaptcha is solved' do
+ # Avoid test ordering issue and ensure `verify_recaptcha` returns true
+ unless Recaptcha.configuration.skip_verify_env.include?('test')
+ Recaptcha.configuration.skip_verify_env << 'test'
+ end
+
+ post(:create, user_params)
+
+ expect(flash[:notice]).to include 'Welcome! You have signed up successfully.'
end
end
end
diff --git a/spec/features/cycle_analytics_spec.rb b/spec/features/cycle_analytics_spec.rb
new file mode 100644
index 00000000000..e48a2b0c92e
--- /dev/null
+++ b/spec/features/cycle_analytics_spec.rb
@@ -0,0 +1,126 @@
+require 'spec_helper'
+
+feature 'Cycle Analytics', feature: true, js: true do
+ include WaitForAjax
+
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+ let(:guest) { create(:user) }
+ let(:project) { create(:project) }
+ let(:issue) { create(:issue, project: project, created_at: 2.days.ago) }
+ let(:milestone) { create(:milestone, project: project) }
+ let(:mr) { create_merge_request_closing_issue(issue) }
+ let(:pipeline) { create(:ci_empty_pipeline, status: 'created', project: project, ref: mr.source_branch, sha: mr.source_branch_sha) }
+
+ context 'as an allowed user' do
+ context 'when project is new' do
+ before do
+ project.team << [user, :master]
+ login_as(user)
+ visit namespace_project_cycle_analytics_path(project.namespace, project)
+ wait_for_ajax
+ end
+
+ it 'shows introductory message' do
+ expect(page).to have_content('Introducing Cycle Analytics')
+ end
+
+ it 'shows active stage with empty message' do
+ expect(page).to have_selector('.stage-nav-item.active', text: 'Issue')
+ expect(page).to have_content("We don't have enough data to show this stage.")
+ end
+ end
+
+ context "when there's cycle analytics data" do
+ before do
+ project.team << [user, :master]
+
+ allow_any_instance_of(Gitlab::ReferenceExtractor).to receive(:issues).and_return([issue])
+ create_cycle
+ deploy_master
+
+ login_as(user)
+ visit namespace_project_cycle_analytics_path(project.namespace, project)
+ end
+
+ it 'shows data on each stage' do
+ expect_issue_to_be_present
+
+ click_stage('Plan')
+ expect(find('.stage-events')).to have_content(mr.commits.last.title)
+
+ click_stage('Code')
+ expect_merge_request_to_be_present
+
+ click_stage('Test')
+ expect_build_to_be_present
+
+ click_stage('Review')
+ expect_merge_request_to_be_present
+
+ click_stage('Staging')
+ expect_build_to_be_present
+
+ click_stage('Production')
+ expect_issue_to_be_present
+ end
+ end
+ end
+
+ context "as a guest" do
+ before do
+ project.team << [guest, :guest]
+
+ allow_any_instance_of(Gitlab::ReferenceExtractor).to receive(:issues).and_return([issue])
+ create_cycle
+ deploy_master
+
+ login_as(guest)
+ visit namespace_project_cycle_analytics_path(project.namespace, project)
+ wait_for_ajax
+ end
+
+ it 'needs permissions to see restricted stages' do
+ expect(find('.stage-events')).to have_content(issue.title)
+
+ click_stage('Code')
+ expect(find('.stage-events')).to have_content('You need permission.')
+
+ click_stage('Review')
+ expect(find('.stage-events')).to have_content('You need permission.')
+ end
+ end
+
+ def expect_issue_to_be_present
+ expect(find('.stage-events')).to have_content(issue.title)
+ expect(find('.stage-events')).to have_content(issue.author.name)
+ expect(find('.stage-events')).to have_content("##{issue.iid}")
+ end
+
+ def expect_build_to_be_present
+ expect(find('.stage-events')).to have_content(@build.ref)
+ expect(find('.stage-events')).to have_content(@build.short_sha)
+ expect(find('.stage-events')).to have_content("##{@build.id}")
+ end
+
+ def expect_merge_request_to_be_present
+ expect(find('.stage-events')).to have_content(mr.title)
+ expect(find('.stage-events')).to have_content(mr.author.name)
+ expect(find('.stage-events')).to have_content("!#{mr.iid}")
+ end
+
+ def create_cycle
+ issue.update(milestone: milestone)
+ pipeline.run
+
+ @build = create(:ci_build, pipeline: pipeline, status: :success, author: user)
+
+ merge_merge_requests_closing_issue(issue)
+ ProcessCommitWorker.new.perform(project.id, user.id, mr.commits.last.to_hash)
+ end
+
+ def click_stage(stage_name)
+ find('.stage-nav li', text: stage_name).click
+ wait_for_ajax
+ end
+end
diff --git a/spec/features/issues/award_emoji_spec.rb b/spec/features/issues/award_emoji_spec.rb
index efb53026449..73e43316dc7 100644
--- a/spec/features/issues/award_emoji_spec.rb
+++ b/spec/features/issues/award_emoji_spec.rb
@@ -76,7 +76,7 @@ describe 'Awards Emoji', feature: true do
end
it 'has disabled emoji button' do
- expect(first('.award-control')[:disabled]).to be(true)
+ expect(first('.award-control')[:class]).to have_text('disabled')
end
end
diff --git a/spec/features/merge_requests/merge_request_versions_spec.rb b/spec/features/merge_requests/merge_request_versions_spec.rb
index cd2272dd38f..04e85ed3f73 100644
--- a/spec/features/merge_requests/merge_request_versions_spec.rb
+++ b/spec/features/merge_requests/merge_request_versions_spec.rb
@@ -81,4 +81,52 @@ feature 'Merge Request versions', js: true, feature: true do
expect(page).to have_content '8 changed files'
end
end
+
+ describe 'compare with same version' do
+ before do
+ page.within '.mr-version-compare-dropdown' do
+ find('.btn-default').click
+ click_link 'version 1'
+ end
+ end
+
+ it 'should have 0 chages between versions' do
+ page.within '.mr-version-compare-dropdown' do
+ expect(page).to have_content 'version 1'
+ end
+
+ page.within '.mr-version-dropdown' do
+ find('.btn-default').click
+ find(:link, 'version 1').trigger('click')
+ end
+
+ expect(page).to have_content '0 changed files'
+ end
+ end
+
+ describe 'compare with newer version' do
+ before do
+ page.within '.mr-version-compare-dropdown' do
+ find('.btn-default').click
+ click_link 'version 2'
+ end
+ end
+
+ it 'should set the compared versions to be the same' do
+ page.within '.mr-version-compare-dropdown' do
+ expect(page).to have_content 'version 2'
+ end
+
+ page.within '.mr-version-dropdown' do
+ find('.btn-default').click
+ find(:link, 'version 1').trigger('click')
+ end
+
+ page.within '.mr-version-compare-dropdown' do
+ expect(page).to have_content 'version 1'
+ end
+
+ expect(page).to have_content '0 changed files'
+ end
+ end
end
diff --git a/spec/features/projects/services/mattermost_slash_command_spec.rb b/spec/features/projects/services/mattermost_slash_command_spec.rb
index 274d50e7ce4..8de827447ff 100644
--- a/spec/features/projects/services/mattermost_slash_command_spec.rb
+++ b/spec/features/projects/services/mattermost_slash_command_spec.rb
@@ -49,4 +49,10 @@ feature 'Setup Mattermost slash commands', feature: true do
end
end
end
+
+ describe 'stable logo url' do
+ it 'shows a publicly available logo' do
+ expect(File.exist?(Rails.root.join('public/slash-command-logo.png')))
+ end
+ end
end
diff --git a/spec/features/signup_spec.rb b/spec/features/signup_spec.rb
index 65544f79eba..9fde8d6e5cf 100644
--- a/spec/features/signup_spec.rb
+++ b/spec/features/signup_spec.rb
@@ -10,10 +10,11 @@ feature 'Signup', feature: true do
visit root_path
- fill_in 'new_user_name', with: user.name
- fill_in 'new_user_username', with: user.username
- fill_in 'new_user_email', with: user.email
- fill_in 'new_user_password', with: user.password
+ fill_in 'new_user_name', with: user.name
+ fill_in 'new_user_username', with: user.username
+ fill_in 'new_user_email', with: user.email
+ fill_in 'new_user_email_confirmation', with: user.email
+ fill_in 'new_user_password', with: user.password
click_button "Register"
expect(current_path).to eq users_almost_there_path
@@ -29,10 +30,11 @@ feature 'Signup', feature: true do
visit root_path
- fill_in 'new_user_name', with: user.name
- fill_in 'new_user_username', with: user.username
- fill_in 'new_user_email', with: user.email
- fill_in 'new_user_password', with: user.password
+ fill_in 'new_user_name', with: user.name
+ fill_in 'new_user_username', with: user.username
+ fill_in 'new_user_email', with: user.email
+ fill_in 'new_user_email_confirmation', with: user.email
+ fill_in 'new_user_password', with: user.password
click_button "Register"
expect(current_path).to eq dashboard_projects_path
@@ -55,8 +57,9 @@ feature 'Signup', feature: true do
click_button "Register"
expect(current_path).to eq user_registration_path
- expect(page).to have_content("error prohibited this user from being saved")
+ expect(page).to have_content("errors prohibited this user from being saved")
expect(page).to have_content("Email has already been taken")
+ expect(page).to have_content("Email confirmation doesn't match")
end
it 'does not redisplay the password' do
diff --git a/spec/features/users_spec.rb b/spec/features/users_spec.rb
index afa98f3f715..2de0fbe7ab2 100644
--- a/spec/features/users_spec.rb
+++ b/spec/features/users_spec.rb
@@ -6,10 +6,11 @@ feature 'Users', feature: true, js: true do
scenario 'GET /users/sign_in creates a new user account' do
visit new_user_session_path
click_link 'Register'
- fill_in 'new_user_name', with: 'Name Surname'
- fill_in 'new_user_username', with: 'Great'
- fill_in 'new_user_email', with: 'name@mail.com'
- fill_in 'new_user_password', with: 'password1234'
+ fill_in 'new_user_name', with: 'Name Surname'
+ fill_in 'new_user_username', with: 'Great'
+ fill_in 'new_user_email', with: 'name@mail.com'
+ fill_in 'new_user_email_confirmation', with: 'name@mail.com'
+ fill_in 'new_user_password', with: 'password1234'
expect { click_button 'Register' }.to change { User.count }.by(1)
end
@@ -33,10 +34,11 @@ feature 'Users', feature: true, js: true do
scenario 'Should show one error if email is already taken' do
visit new_user_session_path
click_link 'Register'
- fill_in 'new_user_name', with: 'Another user name'
- fill_in 'new_user_username', with: 'anotheruser'
- fill_in 'new_user_email', with: user.email
- fill_in 'new_user_password', with: '12341234'
+ fill_in 'new_user_name', with: 'Another user name'
+ fill_in 'new_user_username', with: 'anotheruser'
+ fill_in 'new_user_email', with: user.email
+ fill_in 'new_user_email_confirmation', with: user.email
+ fill_in 'new_user_password', with: '12341234'
expect { click_button 'Register' }.to change { User.count }.by(0)
expect(page).to have_text('Email has already been taken')
expect(number_of_errors_on_page(page)).to be(1), 'errors on page:\n #{errors_on_page page}'
diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb
index 1d494edcd3b..810311e2b1a 100644
--- a/spec/helpers/gitlab_markdown_helper_spec.rb
+++ b/spec/helpers/gitlab_markdown_helper_spec.rb
@@ -170,4 +170,14 @@ describe GitlabMarkdownHelper do
expect(doc.content).to eq "@#{user.username}, can you look at this?..."
end
end
+
+ describe '#cross_project_reference' do
+ it 'shows the full MR reference' do
+ expect(helper.cross_project_reference(project, merge_request)).to include(project.path_with_namespace)
+ end
+
+ it 'shows the full issue reference' do
+ expect(helper.cross_project_reference(project, issue)).to include(project.path_with_namespace)
+ end
+ end
end
diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb
index abe08d95ece..9c7e0ee2fe0 100644
--- a/spec/helpers/issues_helper_spec.rb
+++ b/spec/helpers/issues_helper_spec.rb
@@ -98,15 +98,15 @@ describe IssuesHelper do
end
end
- describe '#award_active_class' do
+ describe '#award_state_class' do
let!(:upvote) { create(:award_emoji) }
- it "returns empty string for unauthenticated user" do
- expect(award_active_class(AwardEmoji.all, nil)).to eq("")
+ it "returns disabled string for unauthenticated user" do
+ expect(award_state_class(AwardEmoji.all, nil)).to eq("disabled")
end
it "returns active string for author" do
- expect(award_active_class(AwardEmoji.all, upvote.user)).to eq("active")
+ expect(award_state_class(AwardEmoji.all, upvote.user)).to eq("active")
end
end
diff --git a/spec/lib/gitlab/ldap/person_spec.rb b/spec/lib/gitlab/ldap/person_spec.rb
new file mode 100644
index 00000000000..60afe046788
--- /dev/null
+++ b/spec/lib/gitlab/ldap/person_spec.rb
@@ -0,0 +1,44 @@
+require 'spec_helper'
+
+describe Gitlab::LDAP::Person do
+ include LdapHelpers
+
+ let(:entry) { ldap_user_entry('john.doe') }
+
+ before do
+ stub_ldap_config(
+ attributes: {
+ name: 'cn',
+ email: %w(mail email userPrincipalName)
+ }
+ )
+ end
+
+ describe '#name' do
+ it 'uses the configured name attribute and handles values as an array' do
+ name = 'John Doe'
+ entry['cn'] = [name]
+ person = Gitlab::LDAP::Person.new(entry, 'ldapmain')
+
+ expect(person.name).to eq(name)
+ end
+ end
+
+ describe '#email' do
+ it 'returns the value of mail, if present' do
+ mail = 'john@example.com'
+ entry['mail'] = mail
+ person = Gitlab::LDAP::Person.new(entry, 'ldapmain')
+
+ expect(person.email).to eq(mail)
+ end
+
+ it 'returns the value of userPrincipalName, if mail and email are not present' do
+ user_principal_name = 'john.doe@example.com'
+ entry['userPrincipalName'] = user_principal_name
+ person = Gitlab::LDAP::Person.new(entry, 'ldapmain')
+
+ expect(person.email).to eq(user_principal_name)
+ end
+ end
+end
diff --git a/spec/models/group_label_spec.rb b/spec/models/group_label_spec.rb
index 668aa6fb357..555a876daeb 100644
--- a/spec/models/group_label_spec.rb
+++ b/spec/models/group_label_spec.rb
@@ -43,7 +43,7 @@ describe GroupLabel, models: true do
let(:target_project) { build_stubbed(:empty_project, name: 'project-2', namespace: namespace) }
it 'returns a String reference to the object' do
- expect(label.to_reference(source_project, target_project)).to eq %(project-1~#{label.id})
+ expect(label.to_reference(source_project, target_project: target_project)).to eq %(project-1~#{label.id})
end
end
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index bb56e44db29..bfa36d92ac3 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -30,6 +30,10 @@ describe Issue, models: true do
expect(issue.to_reference).to eq "#1"
end
+ it 'returns a String reference with the full path' do
+ expect(issue.to_reference(full: true)).to eq(project.path_with_namespace + '#1')
+ end
+
it 'supports a cross-project reference' do
another_project = build(:project, name: 'another-project', namespace: project.namespace)
expect(issue.to_reference(another_project)).to eq "sample-project#1"
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 646e6c6dbb3..8d1385016fd 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -153,6 +153,10 @@ describe MergeRequest, models: true do
another_project = build(:project, name: 'another-project', namespace: project.namespace)
expect(merge_request.to_reference(another_project)).to eq "sample-project!1"
end
+
+ it 'returns a String reference with the full path' do
+ expect(merge_request.to_reference(full: true)).to eq(project.path_with_namespace + '!1')
+ end
end
describe '#raw_diffs' do
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index fb225eb7625..3ec7bb46686 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -362,14 +362,6 @@ describe Project, models: true do
end
end
- describe "#web_url_without_protocol" do
- let(:project) { create(:empty_project, path: "somewhere") }
-
- it 'returns the web URL without the protocol for this repo' do
- expect(project.web_url_without_protocol).to eq("#{Gitlab.config.gitlab.url.split('://')[1]}/#{project.namespace.path}/somewhere")
- end
- end
-
describe "#new_issue_address" do
let(:project) { create(:empty_project, path: "somewhere") }
let(:user) { create(:user) }
diff --git a/spec/requests/api/project_hooks_spec.rb b/spec/requests/api/project_hooks_spec.rb
index a42cedae614..36fbcf088e7 100644
--- a/spec/requests/api/project_hooks_spec.rb
+++ b/spec/requests/api/project_hooks_spec.rb
@@ -86,7 +86,8 @@ describe API::ProjectHooks, 'ProjectHooks', api: true do
describe "POST /projects/:id/hooks" do
it "adds hook to project" do
expect do
- post api("/projects/#{project.id}/hooks", user), url: "http://example.com", issues_events: true
+ post api("/projects/#{project.id}/hooks", user),
+ url: "http://example.com", issues_events: true, wiki_page_events: true
end.to change {project.hooks.count}.by(1)
expect(response).to have_http_status(201)
@@ -98,7 +99,7 @@ describe API::ProjectHooks, 'ProjectHooks', api: true do
expect(json_response['note_events']).to eq(false)
expect(json_response['build_events']).to eq(false)
expect(json_response['pipeline_events']).to eq(false)
- expect(json_response['wiki_page_events']).to eq(false)
+ expect(json_response['wiki_page_events']).to eq(true)
expect(json_response['enable_ssl_verification']).to eq(true)
expect(json_response).not_to include('token')
end
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 9e317f3a7e9..45b7988a054 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -317,9 +317,9 @@ describe API::Users, api: true do
end
it 'updates user with new identity' do
- put api("/users/#{user.id}", admin), provider: 'github', extern_uid: '67890'
+ put api("/users/#{user.id}", admin), provider: 'github', extern_uid: 'john'
expect(response).to have_http_status(200)
- expect(user.reload.identities.first.extern_uid).to eq('67890')
+ expect(user.reload.identities.first.extern_uid).to eq('john')
expect(user.reload.identities.first.provider).to eq('github')
end
diff --git a/spec/services/projects/fork_service_spec.rb b/spec/services/projects/fork_service_spec.rb
index 64d15c0523c..8e614211116 100644
--- a/spec/services/projects/fork_service_spec.rb
+++ b/spec/services/projects/fork_service_spec.rb
@@ -5,10 +5,12 @@ describe Projects::ForkService, services: true do
before do
@from_namespace = create(:namespace)
@from_user = create(:user, namespace: @from_namespace )
+ avatar = fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "image/png")
@from_project = create(:project,
creator_id: @from_user.id,
namespace: @from_namespace,
star_count: 107,
+ avatar: avatar,
description: 'wow such project')
@to_namespace = create(:namespace)
@to_user = create(:user, namespace: @to_namespace)
@@ -36,6 +38,17 @@ describe Projects::ForkService, services: true do
it { expect(to_project.namespace).to eq(@to_user.namespace) }
it { expect(to_project.star_count).to be_zero }
it { expect(to_project.description).to eq(@from_project.description) }
+ it { expect(to_project.avatar.file).to be_exists }
+
+ # This test is here because we had a bug where the from-project lost its
+ # avatar after being forked.
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/26158
+ it "after forking the from-project still has its avatar" do
+ # If we do not fork the project first we cannot detect the bug.
+ expect(to_project).to be_persisted
+
+ expect(@from_project.avatar.file).to be_exists
+ end
end
end
diff --git a/spec/uploaders/avatar_uploader_spec.rb b/spec/uploaders/avatar_uploader_spec.rb
index 1f0e8732587..76f5a4b42ed 100644
--- a/spec/uploaders/avatar_uploader_spec.rb
+++ b/spec/uploaders/avatar_uploader_spec.rb
@@ -5,14 +5,14 @@ describe AvatarUploader do
subject { described_class.new(user) }
describe '#move_to_cache' do
- it 'is true' do
- expect(subject.move_to_cache).to eq(true)
+ it 'is false' do
+ expect(subject.move_to_cache).to eq(false)
end
end
describe '#move_to_store' do
- it 'is true' do
- expect(subject.move_to_store).to eq(true)
+ it 'is false' do
+ expect(subject.move_to_store).to eq(false)
end
end
end
diff --git a/spec/uploaders/file_uploader_spec.rb b/spec/uploaders/file_uploader_spec.rb
index bc86adfef68..6a712e33c96 100644
--- a/spec/uploaders/file_uploader_spec.rb
+++ b/spec/uploaders/file_uploader_spec.rb
@@ -17,7 +17,7 @@ describe FileUploader do
describe '#image_or_video?' do
context 'given an image file' do
before do
- @uploader.store!(File.new(Rails.root.join('spec', 'fixtures', 'rails_sample.jpg')))
+ @uploader.store!(fixture_file_upload(Rails.root.join('spec', 'fixtures', 'rails_sample.jpg')))
end
it 'detects an image based on file extension' do
@@ -27,7 +27,7 @@ describe FileUploader do
context 'given an video file' do
before do
- video_file = File.new(Rails.root.join('spec', 'fixtures', 'video_sample.mp4'))
+ video_file = fixture_file_upload(Rails.root.join('spec', 'fixtures', 'video_sample.mp4'))
@uploader.store!(video_file)
end
@@ -37,7 +37,7 @@ describe FileUploader do
end
it 'does not return image_or_video? for other types' do
- @uploader.store!(File.new(Rails.root.join('spec', 'fixtures', 'doc_sample.txt')))
+ @uploader.store!(fixture_file_upload(Rails.root.join('spec', 'fixtures', 'doc_sample.txt')))
expect(@uploader.image_or_video?).to be false
end