diff options
author | Tomasz Maczukin <tomasz@maczukin.pl> | 2016-07-02 22:58:21 +0200 |
---|---|---|
committer | Tomasz Maczukin <tomasz@maczukin.pl> | 2016-07-02 22:58:21 +0200 |
commit | f1a85747ca94cfe0aea25416da1e2ba498b636be (patch) | |
tree | fd0ae2b443ee90b90fa61817be7e7ee23059c6c9 | |
parent | 3a6ebb1fd624c216a4ce65380e64072793b7ccda (diff) | |
parent | fc3402b7eaa9e9839ac2b7087d9582f518b0bf96 (diff) | |
download | gitlab-ce-f1a85747ca94cfe0aea25416da1e2ba498b636be.tar.gz |
Merge branch 'master' into dev-master
* master: (98 commits)
Enable Style/EmptyLines cop, remove redundant ones
Update CHANGELOG
Cache results from jQuery selectors to retrieve namespace name
Fix import button when import fail due the namespace already been taken
Fix snippets comments not displayed
Fix emoji paths in relative root configurations
Exclude requesters from Project#members, Group#members and User#members
Upgrade Thin from 1.6.1 to 1.7.0.
Many squashed commits
Cache autocomplete results
Upgrade Sidekiq from 4.1.2 to 4.1.4.
Upgrade seed-fu from 2.3.5 to 2.3.6
use has_many relationship with events
Support creating a todo on issuables via API
Expose target, filter by state as string
Add todos API documentation and changelog
Improve the request / withdraw access button
Metrics for Rouge::Plugins::Redcarpet and Rouge::Formatters::HTMLGitlab
Groundwork for Kerberos SPNEGO (EE feature)
Update CHANGELOG 8.9.5 for runners related fixes
...
396 files changed, 7106 insertions, 3101 deletions
diff --git a/.rubocop.yml b/.rubocop.yml index dbdabbb9d4c..cd13f581517 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,4 +1,6 @@ -require: rubocop-rspec +require: + - rubocop-rspec + - ./rubocop/rubocop AllCops: TargetRubyVersion: 2.1 @@ -191,7 +193,7 @@ Style/EmptyLineBetweenDefs: # Don't use several empty lines in a row. Style/EmptyLines: - Enabled: false + Enabled: true # Keep blank lines around access modifiers. Style/EmptyLinesAroundAccessModifier: @@ -532,11 +534,11 @@ Style/SingleLineMethods: # Use spaces after colons. Style/SpaceAfterColon: - Enabled: false + Enabled: true # Use spaces after commas. Style/SpaceAfterComma: - Enabled: false + Enabled: true # Do not put a space between a method name and the opening parenthesis in a # method definition. @@ -679,7 +681,7 @@ Style/UnlessElse: # Checks for %W when interpolation is not needed. Style/UnneededCapitalW: - Enabled: false + Enabled: true # TODO: Enable UnneededInterpolation Cop. # Checks for strings that are just an interpolated expression. diff --git a/CHANGELOG b/CHANGELOG index eb5a5f7fcf4..8efdcd2453e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,8 +3,12 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.10.0 (unreleased) - Fix commit builds API, return all builds for all pipelines for given commit. !4849 - Replace Haml with Hamlit to make view rendering faster. !3666 + - Refactor repository paths handling to allow multiple git mount points + - Add Application Setting to configure default Repository Path for new projects - Wrap code blocks on Activies and Todos page. !4783 (winniehell) + - Align flash messages with left side of page content !4959 (winniehell) - Display last commit of deleted branch in push events !4699 (winniehell) + - Apply the trusted_proxies config to the rack request object for use with rack_attack - Add Sidekiq queue duration to transaction metrics. - Let Workhorse serve format-patch diffs - Make images fit to the size of the viewport !4810 @@ -14,17 +18,42 @@ v 8.10.0 (unreleased) - Exclude email check from the standard health check - Fix changing issue state columns in milestone view - Add notification settings dropdown for groups + - Allow importing from Github using Personal Access Tokens. (Eric K Idema) + - API: Todos !3188 (Robert Schilling) - Fix user creation with stronger minimum password requirements !4054 (nathan-pmt) - PipelinesFinder uses git cache data - Check for conflicts with existing Project's wiki path when creating a new project. + - Don't instantiate a git tree on Projects show default view - Remove unused front-end variable -> default_issues_tracker + - Better caching of git calls on ProjectsController#show. - Add API endpoint for a group issues !4520 (mahcsig) - Add Bugzilla integration !4930 (iamtjg) + - Metrics for Rouge::Plugins::Redcarpet and Rouge::Formatters::HTMLGitlab - Allow [ci skip] to be in any case and allow [skip ci]. !4785 (simon_w) - Add basic system information like memory and disk usage to the admin panel v 8.9.4 (unreleased) - Ensure references to private repos aren't shown to logged-out users +v 8.9.5 (unreleased) + - Improve the request / withdraw access button. !4860 + - Fix assigning shared runners as admins. !4961 + - Show "locked" label for locked runners on runners admin. !4961 + - Fixes issues importing events in Import/Export. Import/Export version bumped to 0.1.1 + - Fix import button disabled when import process fail due to the namespace already been taken. + +v 8.9.4 + - Fix privilege escalation issue with OAuth external users. + - Ensure references to private repos aren't shown to logged-out users. + - Fixed search field blur not removing focus. !4704 + - Resolve "Sub nav isn't showing on file view". !4890 + - Fixes middle click and double request when navigating through the file browser. !4891 + - Fixed URL on label button when filtering. !4897 + - Fixed commit avatar alignment. !4933 + - Do not show build retry link when build is active. !4967 + - Fix restore Rake task warning message output. !4980 + - Handle external issues in IssueReferenceFilter. !4988 + - Expiry date on pinned nav cookie. !5009 + - Updated breakpoint for sidebar pinning. !5019 v 8.9.3 - Fix encrypted data backwards compatibility after upgrading attr_encrypted gem. !4963 @@ -41,6 +70,7 @@ v 8.9.3 - Fix missing avatar on system notes. !4954 - Reduce overhead and optimize ProjectTeam#max_member_access performance. !4973 - Use update_columns to by_pass all the dirty code on active_record. !4985 + - Fix restore Rake task warning message output !4980 v 8.9.2 - Fix visibility of snippets when searching. @@ -91,7 +121,6 @@ v 8.9.1 - Remove duplicate 'New Page' button on edit wiki page v 8.9.0 -v 8.9.0 (unreleased) - Fix group visibility form layout in application settings - Fix builds API response not including commit data - Fix error when CI job variables key specified but not defined @@ -238,12 +267,17 @@ v 8.9.0 (unreleased) - Filter parameters for request_uri value on instrumented transactions. - Remove duplicated keys add UNIQUE index to keys fingerprint column - ExtractsPath get ref_names from repository cache, if not there access git. + - Show a flash warning about the error detail of XHR requests which failed with status code 404 and 500 - Cache user todo counts from TodoService - Ensure Todos counters doesn't count Todos for projects pending delete - Add left/right arrows horizontal navigation - Add tooltip to pin/unpin navbar - Add new sub nav style to Wiki and Graphs sub navigation +v 8.8.7 + - Fix privilege escalation issue with OAuth external users. + - Ensure references to private repos aren't shown to logged-out users. + v 8.8.6 - Fix visibility of snippets when searching. - Update omniauth-saml to 1.6.0 !4951 @@ -378,6 +412,10 @@ v 8.8.0 - When creating a .gitignore file a dropdown with templates will be provided - Shows the issue/MR list search/filter form and corrects the mobile styling for guest users. #17562 +v 8.7.9 + - Fix privilege escalation issue with OAuth external users. + - Ensure references to private repos aren't shown to logged-out users. + v 8.7.8 - Fix visibility of snippets when searching. - Update omniauth-saml to 1.6.0 !4951 diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION index 4a36342fcab..fd2a01863fd 100644 --- a/GITLAB_SHELL_VERSION +++ b/GITLAB_SHELL_VERSION @@ -1 +1 @@ -3.0.0 +3.1.0 @@ -251,7 +251,6 @@ group :development do gem 'brakeman', '~> 3.3.0', require: false gem 'letter_opener_web', '~> 1.3.0' - gem 'quiet_assets', '~> 1.0.2' gem 'rerun', '~> 0.11.0' gem 'bullet', require: false gem 'rblineprof', platform: :mri, require: false @@ -265,7 +264,7 @@ group :development do gem "sdoc", '~> 0.3.20' # thin instead webrick - gem 'thin', '~> 1.6.1' + gem 'thin', '~> 1.7.0' end group :development, :test do @@ -303,7 +302,6 @@ group :development, :test do gem 'rubocop', '~> 0.40.0', require: false gem 'rubocop-rspec', '~> 1.5.0', require: false gem 'scss_lint', '~> 0.47.0', require: false - gem 'coveralls', '~> 0.8.2', require: false gem 'simplecov', '~> 0.11.0', require: false gem 'flog', require: false gem 'flay', require: false @@ -350,3 +348,4 @@ gem 'health_check', '~> 1.5.1' # System information gem 'vmstat', '~> 2.1.0' +gem 'sys-filesystem', '~> 1.1.6' diff --git a/Gemfile.lock b/Gemfile.lock index 4c5350ba639..45cb327168c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -141,12 +141,6 @@ GEM colorize (0.7.7) concurrent-ruby (1.0.2) connection_pool (2.2.0) - coveralls (0.8.13) - json (~> 1.8) - simplecov (~> 0.11.0) - term-ansicolor (~> 1.3) - thor (~> 0.19.1) - tins (~> 1.6.0) crack (0.4.3) safe_yaml (~> 1.0.0) creole (0.5.0) @@ -505,8 +499,6 @@ GEM pry-rails (0.3.4) pry (>= 0.9.10) pyu-ruby-sasl (0.0.3.3) - quiet_assets (1.0.3) - railties (>= 3.1, < 5.0) rack (1.6.4) rack-accept (0.4.5) rack (>= 0.4) @@ -640,8 +632,8 @@ GEM sanitize (2.1.0) nokogiri (>= 1.4.4) sass (3.4.22) - sass-rails (5.0.4) - railties (>= 4.0.0, < 5.0) + sass-rails (5.0.5) + railties (>= 4.0.0, < 6) sass (~> 3.1) sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) @@ -655,9 +647,9 @@ GEM sdoc (0.3.20) json (>= 1.1.3) rdoc (~> 3.10) - seed-fu (2.3.5) - activerecord (>= 3.1, < 4.3) - activesupport (>= 3.1, < 4.3) + seed-fu (2.3.6) + activerecord (>= 3.1) + activesupport (>= 3.1) select2-rails (3.5.9.3) thor (~> 0.14) sentry-raven (1.1.0) @@ -668,10 +660,11 @@ GEM rack shoulda-matchers (2.8.0) activesupport (>= 3.0.0) - sidekiq (4.1.2) + sidekiq (4.1.4) concurrent-ruby (~> 1.0) connection_pool (~> 2.2, >= 2.2.0) redis (~> 3.2, >= 3.2.1) + sinatra (>= 1.4.7) sidekiq-cron (0.4.0) redis-namespace (>= 1.5.2) rufus-scheduler (>= 2.0.24) @@ -682,8 +675,8 @@ GEM json (~> 1.8) simplecov-html (~> 0.10.0) simplecov-html (0.10.0) - sinatra (1.4.6) - rack (~> 1.4) + sinatra (1.4.7) + rack (~> 1.5) rack-protection (~> 1.4) tilt (>= 1.3, < 3) six (0.2.0) @@ -706,10 +699,10 @@ GEM spring (>= 0.9.1) spring-commands-teaspoon (0.0.2) spring (>= 0.9.1) - sprockets (3.6.0) + sprockets (3.6.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) - sprockets-rails (3.0.4) + sprockets-rails (3.1.1) actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) @@ -721,6 +714,8 @@ GEM activerecord (>= 4.1, < 5.1) state_machines-activemodel (>= 0.3.0) stringex (2.5.2) + sys-filesystem (1.1.6) + ffi systemu (2.6.5) task_list (1.0.2) html-pipeline @@ -729,14 +724,12 @@ GEM teaspoon-jasmine (2.2.0) teaspoon (>= 1.0.0) temple (0.7.7) - term-ansicolor (1.3.2) - tins (~> 1.0) test_after_commit (0.4.2) activerecord (>= 3.2) - thin (1.6.4) + thin (1.7.0) daemons (~> 1.0, >= 1.0.9) eventmachine (~> 1.0, >= 1.0.4) - rack (~> 1.0) + rack (>= 1, < 3) thor (0.19.1) thread_safe (0.3.5) tilt (2.0.5) @@ -751,7 +744,6 @@ GEM mime-types multi_json (~> 1.7) twitter-stream (~> 0.1) - tins (1.6.0) turbolinks (2.5.3) coffee-rails twitter-stream (0.1.16) @@ -841,7 +833,6 @@ DEPENDENCIES chronic_duration (~> 0.10.6) coffee-rails (~> 4.1.0) connection_pool (~> 2.0) - coveralls (~> 0.8.2) creole (~> 0.5.0) d3_rails (~> 3.5.0) database_cleaner (~> 1.4.0) @@ -928,7 +919,6 @@ DEPENDENCIES poltergeist (~> 1.9.0) premailer-rails (~> 1.9.0) pry-rails - quiet_assets (~> 1.0.2) rack-attack (~> 4.3.1) rack-cors (~> 0.4.0) rack-oauth2 (~> 1.2.1) @@ -976,11 +966,12 @@ DEPENDENCIES spring-commands-teaspoon (~> 0.0.2) sprockets (~> 3.6.0) state_machines-activerecord (~> 0.4.0) + sys-filesystem (~> 1.1.6) task_list (~> 1.0.2) teaspoon (~> 1.1.0) teaspoon-jasmine (~> 2.2.0) test_after_commit (~> 0.4.2) - thin (~> 1.6.1) + thin (~> 1.7.0) tinder (~> 1.10.0) turbolinks (~> 2.5.0) u2f (~> 0.2.1) diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee index b6dbf2d0cc1..20fe5a5cc27 100644 --- a/app/assets/javascripts/application.js.coffee +++ b/app/assets/javascripts/application.js.coffee @@ -185,6 +185,15 @@ $ -> else buttons.enable() + $(document).ajaxError (e, xhrObj, xhrSetting, xhrErrorText) -> + + if xhrObj.status is 401 + new Flash 'You need to be logged in.', 'alert' + + else if xhrObj.status in [ 404, 500 ] + new Flash 'Something went wrong on our end.', 'alert' + + # Show/Hide the profile menu when hovering the account box $('.account-box').hover -> $(@).toggleClass('hover') @@ -260,8 +269,8 @@ $ -> new Aside() # Sidenav pinning - if $window.width() < 1280 and $.cookie('pin_nav') is 'true' - $.cookie('pin_nav', 'false', { path: '/' }) + if $window.width() < 1024 and $.cookie('pin_nav') is 'true' + $.cookie('pin_nav', 'false', { path: '/', expires: 365 * 10 }) $('.page-with-sidebar') .toggleClass('page-sidebar-collapsed page-sidebar-expanded') .removeClass('page-sidebar-pinned') @@ -292,7 +301,7 @@ $ -> .toggleClass('header-collapsed header-expanded') # Save settings - $.cookie 'pin_nav', doPinNav, { path: '/' } + $.cookie 'pin_nav', doPinNav, { path: '/', expires: 365 * 10 } if $.cookie('pin_nav') is 'true' or doPinNav tooltipText = 'Unpin navigation' diff --git a/app/assets/javascripts/flash.js.coffee b/app/assets/javascripts/flash.js.coffee index 4f73d215b85..b76d214790a 100644 --- a/app/assets/javascripts/flash.js.coffee +++ b/app/assets/javascripts/flash.js.coffee @@ -4,11 +4,19 @@ class @Flash @flash.html("") innerDiv = $('<div/>', - class: "flash-#{type}", - text: message + class: "flash-#{type}" ) innerDiv.appendTo(".flash-container") + textDiv = $("<div/>", + class: "flash-text", + text: message + ) + textDiv.appendTo(innerDiv) + + if @flash.parent().hasClass('content-wrapper') + textDiv.addClass('container-fluid container-limited') + @flash.click -> $(@).fadeOut() @flash.show() diff --git a/app/assets/javascripts/gfm_auto_complete.js.coffee b/app/assets/javascripts/gfm_auto_complete.js.coffee index 190bb38504c..b7d040bae85 100644 --- a/app/assets/javascripts/gfm_auto_complete.js.coffee +++ b/app/assets/javascripts/gfm_auto_complete.js.coffee @@ -4,7 +4,7 @@ window.GitLab ?= {} GitLab.GfmAutoComplete = dataLoading: false dataLoaded: false - + cachedData: {} dataSource: '' # Emoji @@ -55,7 +55,7 @@ GitLab.GfmAutoComplete = @setupAtWho() if @dataSource - if !@dataLoading + if not @dataLoading and not @cachedData @dataLoading = true # We should wait until initializations are done @@ -70,6 +70,8 @@ GitLab.GfmAutoComplete = @loadData(data) , 1000) + if @cachedData? + @loadData(@cachedData) setupAtWho: -> # Emoji @@ -205,6 +207,7 @@ GitLab.GfmAutoComplete = $.getJSON(dataSource) loadData: (data) -> + @cachedData = data @dataLoaded = true # load members diff --git a/app/assets/javascripts/importer_status.js.coffee b/app/assets/javascripts/importer_status.js.coffee index b0edc895649..eb046eb2eff 100644 --- a/app/assets/javascripts/importer_status.js.coffee +++ b/app/assets/javascripts/importer_status.js.coffee @@ -7,13 +7,16 @@ class @ImporterStatus $('.js-add-to-import') .off 'click' .on 'click', (e) => - new_namespace = null $btn = $(e.currentTarget) $tr = $btn.closest('tr') + $target_field = $tr.find('.import-target') + $namespace_input = $target_field.find('input') id = $tr.attr('id').replace('repo_', '') - if $tr.find('.import-target input').length > 0 - new_namespace = $tr.find('.import-target input').prop('value') - $tr.find('.import-target').empty().append("#{new_namespace} / #{$tr.find('.import-target').data('project_name')}") + new_namespace = null + + if $namespace_input.length > 0 + new_namespace = $namespace_input.prop('value') + $target_field.empty().append("#{new_namespace}/#{$target_field.data('project_name')}") $btn .disable() diff --git a/app/assets/javascripts/shortcuts.js.coffee b/app/assets/javascripts/shortcuts.js.coffee index c03877e9b06..3319a67a79d 100644 --- a/app/assets/javascripts/shortcuts.js.coffee +++ b/app/assets/javascripts/shortcuts.js.coffee @@ -9,12 +9,12 @@ class @Shortcuts onToggleHelp: (e) => e.preventDefault() - @toggleHelp(@enabledHelp) + Shortcuts.toggleHelp(@enabledHelp) - toggleMarkdownPreview: (e) => + toggleMarkdownPreview: (e) -> $(document).triggerHandler('markdown-preview:toggle', [e]) - toggleHelp: (location) -> + @toggleHelp: (location) -> $modal = $('#modal-shortcuts') if $modal.length diff --git a/app/assets/javascripts/tree.js.coffee b/app/assets/javascripts/tree.js.coffee index de8eebcd0b2..83de584f2d9 100644 --- a/app/assets/javascripts/tree.js.coffee +++ b/app/assets/javascripts/tree.js.coffee @@ -5,9 +5,15 @@ class @TreeView # Code browser tree slider # Make the entire tree-item row clickable, but not if clicking another link (like a commit message) $(".tree-content-holder .tree-item").on 'click', (e) -> - if (e.target.nodeName != "A") - path = $('.tree-item-file-name a', this).attr('href') - Turbolinks.visit(path) + $clickedEl = $(e.target) + path = $('.tree-item-file-name a', this).attr('href') + + if not $clickedEl.is('a') and not $clickedEl.is('.str-truncated') + if e.metaKey or e.which is 2 + e.preventDefault() + window.open path, '_blank' + else + Turbolinks.visit path # Show the "Loading commit data" for only the first element $('span.log_loading:first').removeClass('hide') diff --git a/app/assets/stylesheets/framework/flash.scss b/app/assets/stylesheets/framework/flash.scss index 1bfd0213995..a951a2b97fe 100644 --- a/app/assets/stylesheets/framework/flash.scss +++ b/app/assets/stylesheets/framework/flash.scss @@ -16,4 +16,11 @@ @extend .alert-danger; margin: 0; } + + .flash-notice, .flash-alert { + .container-fluid.flash-text { + background: transparent; + } + } } + diff --git a/app/assets/stylesheets/framework/markdown_area.scss b/app/assets/stylesheets/framework/markdown_area.scss index fd8eaa8a691..5d3273ea64d 100644 --- a/app/assets/stylesheets/framework/markdown_area.scss +++ b/app/assets/stylesheets/framework/markdown_area.scss @@ -125,7 +125,8 @@ border: 0; outline: 0; - &:hover { + &:hover, + &:focus { color: $gl-link-color; } } diff --git a/app/assets/stylesheets/framework/mobile.scss b/app/assets/stylesheets/framework/mobile.scss index c74682dfef4..367c7d01944 100644 --- a/app/assets/stylesheets/framework/mobile.scss +++ b/app/assets/stylesheets/framework/mobile.scss @@ -71,6 +71,10 @@ display: none; } + .group-right-buttons { + display: none; + } + .container .title { padding-left: 15px !important; } diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 87f8a17659f..211a9af2348 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -7,7 +7,7 @@ $gutter_collapsed_width: 62px; $gutter_width: 290px; $gutter_inner_width: 258px; $sidebar-transition-duration: .15s; -$sidebar-breakpoint: 1280px; +$sidebar-breakpoint: 1024px; /* * UI elements diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss index de534d28421..85bbf70e188 100644 --- a/app/assets/stylesheets/pages/commits.scss +++ b/app/assets/stylesheets/pages/commits.scss @@ -83,11 +83,7 @@ position: relative; @media (min-width: $screen-sm-min) { - padding-left: 20px; - - .commit-info-block { - padding-left: 44px; - } + padding-left: 46px; } &:not(:last-child) { @@ -102,9 +98,7 @@ .avatar { - position: absolute; - top: 10px; - left: 16px; + margin-left: -46px; } .item-title { diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss index 101faf59174..3d79f4400e2 100644 --- a/app/assets/stylesheets/pages/groups.scss +++ b/app/assets/stylesheets/pages/groups.scss @@ -41,14 +41,17 @@ } .groups-cover-block { - .container-fluid { position: relative; } - .access-request-button { - @include btn-gray; - margin-right: 10px; - text-transform: none; + .group-right-buttons { + position: absolute; + right: 16px; + .btn { + @include btn-gray; + padding: 3px 10px; + background-color: $background-color; + } } } diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 89ce1b2df20..817c2982923 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -266,18 +266,6 @@ @media (max-width: $screen-md-max) { top: 0; } - - .access-request-button { - position: absolute; - right: 0; - bottom: 61px; - - @media (max-width: $screen-md-max) { - position: relative; - bottom: 0; - margin-right: 10px; - } - } } @media (max-width: $screen-md-max) { diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss index 99c9e81ddb9..5b61270daa8 100644 --- a/app/assets/stylesheets/pages/tree.scss +++ b/app/assets/stylesheets/pages/tree.scss @@ -101,7 +101,8 @@ margin: 0; .commit { - padding: 0 0 0 55px; + padding-top: 0; + padding-bottom: 0; .commit-row-title { .commit-row-message { diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index f4eda864aac..5f65dd3aff0 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -109,6 +109,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController :metrics_packet_size, :send_user_confirmation_email, :container_registry_token_expire_delay, + :repository_storage, restricted_visibility_levels: [], import_sources: [], disabled_oauth_sign_in_sources: [] diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb index a6db4690df0..94b5aaa71d0 100644 --- a/app/controllers/admin/groups_controller.rb +++ b/app/controllers/admin/groups_controller.rb @@ -10,6 +10,7 @@ class Admin::GroupsController < Admin::ApplicationController def show @members = @group.members.order("access_level DESC").page(params[:members_page]) + @requesters = @group.requesters @projects = @group.projects.page(params[:projects_page]) end diff --git a/app/controllers/admin/hooks_controller.rb b/app/controllers/admin/hooks_controller.rb index 4e85b6b4cf2..cbfc4581411 100644 --- a/app/controllers/admin/hooks_controller.rb +++ b/app/controllers/admin/hooks_controller.rb @@ -22,7 +22,6 @@ class Admin::HooksController < Admin::ApplicationController redirect_to admin_hooks_path end - def test @hook = SystemHook.find(params[:hook_id]) data = { diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb index 87986fdf8b1..4c9c6362ffc 100644 --- a/app/controllers/admin/projects_controller.rb +++ b/app/controllers/admin/projects_controller.rb @@ -20,7 +20,8 @@ class Admin::ProjectsController < Admin::ApplicationController @group_members = @group.members.order("access_level DESC").page(params[:group_members_page]) end - @project_members = @project.project_members.page(params[:project_members_page]) + @project_members = @project.members.page(params[:project_members_page]) + @requesters = @project.requesters end def transfer diff --git a/app/controllers/admin/runner_projects_controller.rb b/app/controllers/admin/runner_projects_controller.rb index bf20c5305a7..bc65dcc33d3 100644 --- a/app/controllers/admin/runner_projects_controller.rb +++ b/app/controllers/admin/runner_projects_controller.rb @@ -4,8 +4,6 @@ class Admin::RunnerProjectsController < Admin::ApplicationController def create @runner = Ci::Runner.find(params[:runner_project][:runner_id]) - return head(403) if @runner.is_shared? || @runner.locked? - runner_project = @runner.assign_to(@project, current_user) if runner_project.persisted? diff --git a/app/controllers/admin/system_info_controller.rb b/app/controllers/admin/system_info_controller.rb index 3c67370b667..e4c73008826 100644 --- a/app/controllers/admin/system_info_controller.rb +++ b/app/controllers/admin/system_info_controller.rb @@ -1,13 +1,59 @@ class Admin::SystemInfoController < Admin::ApplicationController + EXCLUDED_MOUNT_OPTIONS = [ + 'nobrowse', + 'read-only', + 'ro' + ] + + EXCLUDED_MOUNT_TYPES = [ + 'autofs', + 'binfmt_misc', + 'cgroup', + 'debugfs', + 'devfs', + 'devpts', + 'devtmpfs', + 'efivarfs', + 'fuse.gvfsd-fuse', + 'fuseblk', + 'fusectl', + 'hugetlbfs', + 'mqueue', + 'proc', + 'pstore', + 'securityfs', + 'sysfs', + 'tmpfs', + 'tracefs', + 'vfat' + ] + def show system_info = Vmstat.snapshot + mounts = Sys::Filesystem.mounts + + @disks = [] + mounts.each do |mount| + mount_options = mount.options.split(',') + + next if (EXCLUDED_MOUNT_OPTIONS & mount_options).any? + next if (EXCLUDED_MOUNT_TYPES & [mount.mount_type]).any? + + begin + disk = Sys::Filesystem.stat(mount.mount_point) + @disks.push({ + bytes_total: disk.bytes_total, + bytes_used: disk.bytes_used, + disk_name: mount.name, + mount_path: disk.path + }) + rescue Sys::Filesystem::Error + end + end @cpus = system_info.cpus.length @mem_used = system_info.memory.active_bytes @mem_total = system_info.memory.total_bytes - - @disk_used = system_info.disks[0].used_bytes - @disk_total = system_info.disks[0].total_bytes end end diff --git a/app/controllers/ci/projects_controller.rb b/app/controllers/ci/projects_controller.rb index 8bf71a1adbb..aa894fde36b 100644 --- a/app/controllers/ci/projects_controller.rb +++ b/app/controllers/ci/projects_controller.rb @@ -25,7 +25,7 @@ module Ci return render_404 unless @project image = Ci::ImageForBuildService.new.execute(@project, params) - send_file image.path, filename: image.name, disposition: 'inline', type:"image/svg+xml" + send_file image.path, filename: image.name, disposition: 'inline', type: "image/svg+xml" end protected diff --git a/app/controllers/concerns/membership_actions.rb b/app/controllers/concerns/membership_actions.rb index 52dc396af6a..52682ef9dc9 100644 --- a/app/controllers/concerns/membership_actions.rb +++ b/app/controllers/concerns/membership_actions.rb @@ -10,7 +10,7 @@ module MembershipActions end def approve_access_request - @member = membershipable.members.request.find(params[:id]) + @member = membershipable.requesters.find(params[:id]) return render_403 unless can?(current_user, action_member_permission(:update, @member), @member) @@ -20,7 +20,8 @@ module MembershipActions end def leave - @member = membershipable.members.find_by(user_id: current_user) + @member = membershipable.members.find_by(user_id: current_user) || + membershipable.requesters.find_by(user_id: current_user) Members::DestroyService.new(@member, current_user).execute source_type = @member.real_source_type.humanize(capitalize: false) diff --git a/app/controllers/confirmations_controller.rb b/app/controllers/confirmations_controller.rb index 7b66ad3f92c..3da44b9b888 100644 --- a/app/controllers/confirmations_controller.rb +++ b/app/controllers/confirmations_controller.rb @@ -1,5 +1,4 @@ class ConfirmationsController < Devise::ConfirmationsController - def almost_there flash[:notice] = nil render layout: "devise_empty" diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb index 2c49fe3833e..9fc41a12536 100644 --- a/app/controllers/groups/group_members_controller.rb +++ b/app/controllers/groups/group_members_controller.rb @@ -7,7 +7,7 @@ class Groups::GroupMembersController < Groups::ApplicationController def index @project = @group.projects.find(params[:project_id]) if params[:project_id] @members = @group.group_members - @members = @members.non_pending unless can?(current_user, :admin_group, @group) + @members = @members.non_invite unless can?(current_user, :admin_group, @group) if params[:search].present? users = @group.users.search(params[:search]).to_a @@ -15,6 +15,7 @@ class Groups::GroupMembersController < Groups::ApplicationController end @members = @members.order('access_level DESC').page(params[:page]).per(50) + @requesters = @group.requesters if can?(current_user, :admin_group, @group) @group_member = @group.group_members.new end @@ -34,7 +35,8 @@ class Groups::GroupMembersController < Groups::ApplicationController end def destroy - @group_member = @group.group_members.find(params[:id]) + @group_member = @group.members.find_by(id: params[:id]) || + @group.requesters.find_by(id: params[:id]) Members::DestroyService.new(@group_member, current_user).execute diff --git a/app/controllers/import/base_controller.rb b/app/controllers/import/base_controller.rb index 93a7ace3530..7e8597a5eb3 100644 --- a/app/controllers/import/base_controller.rb +++ b/app/controllers/import/base_controller.rb @@ -1,5 +1,4 @@ class Import::BaseController < ApplicationController - private def get_or_create_namespace diff --git a/app/controllers/import/fogbugz_controller.rb b/app/controllers/import/fogbugz_controller.rb index 18300390851..99b10b2f9b3 100644 --- a/app/controllers/import/fogbugz_controller.rb +++ b/app/controllers/import/fogbugz_controller.rb @@ -5,7 +5,6 @@ class Import::FogbugzController < Import::BaseController rescue_from Fogbugz::AuthenticationException, with: :fogbugz_unauthorized def new - end def callback @@ -22,7 +21,6 @@ class Import::FogbugzController < Import::BaseController end def new_user_map - end def create_user_map diff --git a/app/controllers/import/github_controller.rb b/app/controllers/import/github_controller.rb index 67bf4190e7e..9c1b0eb20f4 100644 --- a/app/controllers/import/github_controller.rb +++ b/app/controllers/import/github_controller.rb @@ -1,14 +1,29 @@ class Import::GithubController < Import::BaseController before_action :verify_github_import_enabled - before_action :github_auth, except: :callback + before_action :github_auth, only: [:status, :jobs, :create] rescue_from Octokit::Unauthorized, with: :github_unauthorized + helper_method :logged_in_with_github? + + def new + if logged_in_with_github? + go_to_github_for_permissions + elsif session[:github_access_token] + redirect_to status_import_github_url + end + end + def callback session[:github_access_token] = client.get_token(params[:code]) redirect_to status_import_github_url end + def personal_access_token + session[:github_access_token] = params[:personal_access_token] + redirect_to status_import_github_url + end + def status @repos = client.repos @already_added_projects = current_user.created_projects.where(import_type: "github") @@ -57,10 +72,14 @@ class Import::GithubController < Import::BaseController end def github_unauthorized - go_to_github_for_permissions + session[:github_access_token] = nil + redirect_to new_import_github_url, + alert: 'Access denied to your GitHub account.' end - private + def logged_in_with_github? + current_user.identities.exists?(provider: 'github') + end def access_params { github_access_token: session[:github_access_token] } diff --git a/app/controllers/import/gitorious_controller.rb b/app/controllers/import/gitorious_controller.rb index eecbe380c9e..a4c4ad23027 100644 --- a/app/controllers/import/gitorious_controller.rb +++ b/app/controllers/import/gitorious_controller.rb @@ -44,5 +44,4 @@ class Import::GitoriousController < Import::BaseController def verify_gitorious_import_enabled render_404 unless gitorious_import_enabled? end - end diff --git a/app/controllers/import/google_code_controller.rb b/app/controllers/import/google_code_controller.rb index e0de31f2251..8d0de158f98 100644 --- a/app/controllers/import/google_code_controller.rb +++ b/app/controllers/import/google_code_controller.rb @@ -3,7 +3,6 @@ class Import::GoogleCodeController < Import::BaseController before_action :user_map, only: [:new_user_map, :create_user_map] def new - end def callback @@ -34,7 +33,6 @@ class Import::GoogleCodeController < Import::BaseController end def new_user_map - end def create_user_map diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb index 94bb108c5f5..58964a0e65d 100644 --- a/app/controllers/invites_controller.rb +++ b/app/controllers/invites_controller.rb @@ -5,7 +5,6 @@ class InvitesController < ApplicationController respond_to :html def show - end def accept diff --git a/app/controllers/projects/git_http_controller.rb b/app/controllers/projects/git_http_controller.rb index f907d63258b..62c3fa8de53 100644 --- a/app/controllers/projects/git_http_controller.rb +++ b/app/controllers/projects/git_http_controller.rb @@ -1,4 +1,9 @@ +# This file should be identical in GitLab Community Edition and Enterprise Edition + class Projects::GitHttpController < Projects::ApplicationController + include ActionController::HttpAuthentication::Basic + include KerberosSpnegoHelper + attr_reader :user # Git clients will not know what authenticity token to send along @@ -40,9 +45,12 @@ class Projects::GitHttpController < Projects::ApplicationController private def authenticate_user - return if project && project.public? && upload_pack? + if project && project.public? && upload_pack? + return # Allow access + end - authenticate_or_request_with_http_basic do |login, password| + if allow_basic_auth? && basic_auth_provided? + login, password = user_name_and_password(request) auth_result = Gitlab::Auth.find_for_git_client(login, password, project: project, ip: request.ip) if auth_result.type == :ci && upload_pack? @@ -53,8 +61,31 @@ class Projects::GitHttpController < Projects::ApplicationController @user = auth_result.user end - ci? || user + if ci? || user + return # Allow access + end + elsif allow_kerberos_spnego_auth? && spnego_provided? + @user = find_kerberos_user + + if user + send_final_spnego_response + return # Allow access + end end + + send_challenges + render plain: "HTTP Basic: Access denied\n", status: 401 + end + + def basic_auth_provided? + has_basic_credentials?(request) + end + + def send_challenges + challenges = [] + challenges << 'Basic realm="GitLab"' if allow_basic_auth? + challenges << spnego_challenge if allow_kerberos_spnego_auth? + headers['Www-Authenticate'] = challenges.join("\n") if challenges.any? end def ensure_project_found! @@ -120,7 +151,7 @@ class Projects::GitHttpController < Projects::ApplicationController end def render_not_found - render text: 'Not Found', status: :not_found + render plain: 'Not Found', status: :not_found end def ci? diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 8b8df680739..b6e80762e3c 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -76,7 +76,6 @@ class Projects::IssuesController < Projects::ApplicationController render json: @issue.to_json(include: [:milestone, :labels]) end end - end def create diff --git a/app/controllers/projects/network_controller.rb b/app/controllers/projects/network_controller.rb index b181c47baec..34318391dd9 100644 --- a/app/controllers/projects/network_controller.rb +++ b/app/controllers/projects/network_controller.rb @@ -7,7 +7,6 @@ class Projects::NetworkController < Projects::ApplicationController before_action :authorize_download_code! def show - @url = namespace_project_network_path(@project.namespace, @project, @ref, @options.merge(format: :json)) @commit_url = namespace_project_commit_path(@project.namespace, @project, 'ae45ca32').gsub("ae45ca32", "%s") diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index 6ba32d33403..3435a118964 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -6,7 +6,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController def index @project_members = @project.project_members - @project_members = @project_members.non_pending unless can?(current_user, :admin_project, @project) + @project_members = @project_members.non_invite unless can?(current_user, :admin_project, @project) if params[:search].present? users = @project.users.search(params[:search]).to_a @@ -19,7 +19,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController if @group @group_members = @group.group_members - @group_members = @group_members.non_pending unless can?(current_user, :admin_group, @group) + @group_members = @group_members.non_invite unless can?(current_user, :admin_group, @group) if params[:search].present? users = @group.users.search(params[:search]).to_a @@ -29,6 +29,8 @@ class Projects::ProjectMembersController < Projects::ApplicationController @group_members = @group_members.order('access_level DESC') end + @requesters = @project.requesters if can?(current_user, :admin_project, @project) + @project_member = @project.project_members.new @project_group_links = @project.project_group_links end @@ -48,7 +50,8 @@ class Projects::ProjectMembersController < Projects::ApplicationController end def destroy - @project_member = @project.project_members.find(params[:id]) + @project_member = @project.members.find_by(id: params[:id]) || + @project.requesters.find_by(id: params[:id]) Members::DestroyService.new(@project_member, current_user).execute diff --git a/app/controllers/projects/runner_projects_controller.rb b/app/controllers/projects/runner_projects_controller.rb index dc1a18f8d42..8267b14941d 100644 --- a/app/controllers/projects/runner_projects_controller.rb +++ b/app/controllers/projects/runner_projects_controller.rb @@ -6,8 +6,7 @@ class Projects::RunnerProjectsController < Projects::ApplicationController def create @runner = Ci::Runner.find(params[:runner_project][:runner_id]) - return head(403) if @runner.is_shared? || @runner.locked? - return head(403) unless current_user.ci_authorized_runners.include?(@runner) + return head(403) unless can?(current_user, :assign_runner, @runner) path = runners_path(project) runner_project = @runner.assign_to(project, current_user) diff --git a/app/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb index 6d2901a24a4..6d0a7ee1031 100644 --- a/app/controllers/projects/snippets_controller.rb +++ b/app/controllers/projects/snippets_controller.rb @@ -54,7 +54,7 @@ class Projects::SnippetsController < Projects::ApplicationController def show @note = @project.notes.new(noteable: @snippet) - @notes = @snippet.notes.fresh + @notes = Banzai::NoteRenderer.render(@snippet.notes.fresh, @project, current_user) @noteable = @snippet end diff --git a/app/controllers/projects/wikis_controller.rb b/app/controllers/projects/wikis_controller.rb index 7ec1e73b3be..607fe9c7fed 100644 --- a/app/controllers/projects/wikis_controller.rb +++ b/app/controllers/projects/wikis_controller.rb @@ -124,5 +124,4 @@ class Projects::WikisController < Projects::ApplicationController def wiki_params params[:wiki].slice(:title, :content, :format, :message) end - end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 2b1f50fd01e..12e0d5a8413 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -4,7 +4,8 @@ class ProjectsController < Projects::ApplicationController before_action :authenticate_user!, except: [:show, :activity, :refs] before_action :project, except: [:new, :create] before_action :repository, except: [:new, :create] - before_action :assign_ref_vars, :tree, only: [:show], if: :repo_exists? + before_action :assign_ref_vars, only: [:show], if: :repo_exists? + before_action :tree, only: [:show], if: :project_view_files? # Authorize before_action :authorize_admin_project!, only: [:edit, :update, :housekeeping, :download_export, :export, :remove_export, :generate_new_export] @@ -303,6 +304,10 @@ class ProjectsController < Projects::ApplicationController project.repository_exists? && !project.empty_repo? end + def project_view_files? + current_user && current_user.project_view == 'files' + end + # Override extract_ref from ExtractsPath, which returns the branch and file path # for the blob/tree, which in this case is just the root of the default branch. # This way we avoid to access the repository.ref_names. diff --git a/app/finders/todos_finder.rb b/app/finders/todos_finder.rb index 58a00f88af7..7806d9e4cc5 100644 --- a/app/finders/todos_finder.rb +++ b/app/finders/todos_finder.rb @@ -25,6 +25,7 @@ class TodosFinder def execute items = current_user.todos items = by_action_id(items) + items = by_action(items) items = by_author(items) items = by_project(items) items = by_state(items) @@ -43,6 +44,18 @@ class TodosFinder params[:action_id] end + def to_action_id + Todo::ACTION_NAMES.key(action.to_sym) + end + + def action? + action.present? && to_action_id + end + + def action + params[:action] + end + def author? params[:author_id].present? end @@ -96,6 +109,14 @@ class TodosFinder params[:type] end + def by_action(items) + if action? + items = items.where(action: to_action_id) + end + + items + end + def by_action_id(items) if action_id? items = items.where(action: action_id) diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index 55313fd8357..6e580c62ccd 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -78,4 +78,12 @@ module ApplicationSettingsHelper end end end + + def repository_storage_options_for_select + options = Gitlab.config.repositories.storages.map do |name, path| + ["#{name} - #{path}", name] + end + + options_for_select(options, @application_setting.repository_storage) + end end diff --git a/app/helpers/dropdowns_helper.rb b/app/helpers/dropdowns_helper.rb index 6b617e1730a..7c140538012 100644 --- a/app/helpers/dropdowns_helper.rb +++ b/app/helpers/dropdowns_helper.rb @@ -69,7 +69,7 @@ module DropdownsHelper def dropdown_filter(placeholder, search_id: nil) content_tag :div, class: "dropdown-input" do - filter_output = search_field_tag search_id, nil, class: "dropdown-input-field", placeholder: placeholder + filter_output = search_field_tag search_id, nil, class: "dropdown-input-field", placeholder: placeholder, autocomplete: 'off' filter_output << icon('search', class: "dropdown-input-search") filter_output << icon('times', class: "dropdown-input-clear js-dropdown-input-clear", role: "button") diff --git a/app/helpers/emails_helper.rb b/app/helpers/emails_helper.rb index 8466d0aa0ba..2843ad96efa 100644 --- a/app/helpers/emails_helper.rb +++ b/app/helpers/emails_helper.rb @@ -1,5 +1,4 @@ module EmailsHelper - # Google Actions # https://developers.google.com/gmail/markup/reference/go-to-action def email_action(url) diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index 8231ce49fac..294b7e92b8d 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -1,5 +1,4 @@ module IssuablesHelper - def sidebar_gutter_toggle_icon sidebar_gutter_collapsed? ? icon('angle-double-left') : icon('angle-double-right') end diff --git a/app/helpers/kerberos_spnego_helper.rb b/app/helpers/kerberos_spnego_helper.rb new file mode 100644 index 00000000000..f5b0aa7549a --- /dev/null +++ b/app/helpers/kerberos_spnego_helper.rb @@ -0,0 +1,9 @@ +module KerberosSpnegoHelper + def allow_basic_auth? + true # different behavior in GitLab Enterprise Edition + end + + def allow_kerberos_spnego_auth? + false # different behavior in GitLab Enterprise Edition + end +end diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb index 5074e645769..5e9f5837101 100644 --- a/app/helpers/labels_helper.rb +++ b/app/helpers/labels_helper.rb @@ -34,10 +34,7 @@ module LabelsHelper # Returns a String def link_to_label(label, project: nil, type: :issue, tooltip: true, css_class: nil, &block) project ||= @project || label.project - link = send("namespace_project_#{type.to_s.pluralize}_path", - project.namespace, - project, - label_name: [label.name]) + link = label_filter_path(project, label, type: type) if block_given? link_to link, class: css_class, &block @@ -46,6 +43,13 @@ module LabelsHelper end end + def label_filter_path(project, label, type: issue) + send("namespace_project_#{type.to_s.pluralize}_path", + project.namespace, + project, + label_name: [label.name]) + end + def project_label_names @project.labels.pluck(:title) end diff --git a/app/helpers/members_helper.rb b/app/helpers/members_helper.rb index ec106418f2d..c70cd19b587 100644 --- a/app/helpers/members_helper.rb +++ b/app/helpers/members_helper.rb @@ -12,6 +12,17 @@ module MembersHelper can?(current_user, action_member_permission(:admin, member), member.source) end + def can_see_request_access_button?(source) + source_parent = source.respond_to?(:group) && source.group + + return false if source_parent && source.group.members.exists?(user_id: current_user.id) + return false if source_parent && source.group.requesters.exists?(user_id: current_user.id) + return false if source.members.exists?(user_id: current_user.id) + return true if source.requesters.exists?(user_id: current_user.id) + + true + end + def remove_member_message(member, user: nil) user = current_user if defined?(current_user) diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb index b401c8385be..e85ba76887d 100644 --- a/app/helpers/notes_helper.rb +++ b/app/helpers/notes_helper.rb @@ -69,4 +69,14 @@ module NotesHelper button_tag 'Reply...', class: 'btn btn-text-field js-discussion-reply-button', data: data, title: 'Add a reply' end + + def note_max_access_for_user(note) + @max_access_by_user_id ||= Hash.new do |hash, key| + project = key[:project] + hash[key] = project.team.human_max_access(key[:user_id]) + end + + full_key = { project: note.project, user_id: note.author_id } + @max_access_by_user_id[full_key] + end end diff --git a/app/helpers/page_layout_helper.rb b/app/helpers/page_layout_helper.rb index e4e8b934bc8..22387d66451 100644 --- a/app/helpers/page_layout_helper.rb +++ b/app/helpers/page_layout_helper.rb @@ -52,7 +52,7 @@ module PageLayoutHelper raise ArgumentError, 'cannot provide more than two attributes' if map.length > 2 @page_card_attributes ||= {} - @page_card_attributes = map.reject { |_,v| v.blank? } if map.present? + @page_card_attributes = map.reject { |_, v| v.blank? } if map.present? @page_card_attributes end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index d91e3332e48..f312a7ccca3 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -15,7 +15,7 @@ module ProjectsHelper def link_to_member_avatar(author, opts = {}) default_opts = { avatar: true, name: true, size: 16, author_class: 'author', title: ":name" } opts = default_opts.merge(opts) - image_tag(avatar_icon(author, opts[:size]), width: opts[:size], class: "avatar avatar-inline #{"s#{opts[:size]}" if opts[:size]}", alt:'') if opts[:avatar] + image_tag(avatar_icon(author, opts[:size]), width: opts[:size], class: "avatar avatar-inline #{"s#{opts[:size]}" if opts[:size]}", alt: '') if opts[:avatar] end def link_to_member(project, author, opts = {}, &block) @@ -27,7 +27,7 @@ module ProjectsHelper author_html = "" # Build avatar image tag - author_html << image_tag(avatar_icon(author, opts[:size]), width: opts[:size], class: "avatar avatar-inline #{"s#{opts[:size]}" if opts[:size]}", alt:'') if opts[:avatar] + author_html << image_tag(avatar_icon(author, opts[:size]), width: opts[:size], class: "avatar avatar-inline #{"s#{opts[:size]}" if opts[:size]}", alt: '') if opts[:avatar] # Build name span tag if opts[:by_username] @@ -327,9 +327,9 @@ module ProjectsHelper end end - def sanitize_repo_path(message) + def sanitize_repo_path(project, message) return '' unless message.present? - message.strip.gsub(Gitlab.config.gitlab_shell.repos_path.chomp('/'), "[REPOS PATH]") + message.strip.gsub(project.repository_storage_path.chomp('/'), "[REPOS PATH]") end end diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb index d2f94d4ae6f..f9fc525df6f 100644 --- a/app/helpers/search_helper.rb +++ b/app/helpers/search_helper.rb @@ -1,5 +1,4 @@ module SearchHelper - def search_autocomplete_opts(term) return unless current_user diff --git a/app/models/ability.rb b/app/models/ability.rb index f5950879ccb..ba1f2ae4075 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -1,5 +1,6 @@ class Ability class << self + # rubocop: disable Metrics/CyclomaticComplexity def allowed(user, subject) return anonymous_abilities(user, subject) if user.nil? return [] unless user.is_a?(User) @@ -19,6 +20,7 @@ class Ability when ProjectMember then project_member_abilities(user, subject) when User then user_abilities when ExternalIssue, Deployment, Environment then project_abilities(user, subject.project) + when Ci::Runner then runner_abilities(user, subject) else [] end.concat(global_abilities(user)) end @@ -512,6 +514,18 @@ class Ability rules end + def runner_abilities(user, runner) + if user.is_admin? + [:assign_runner] + elsif runner.is_shared? || runner.locked? + [] + elsif user.ci_authorized_runners.include?(runner) + [:assign_runner] + else + [] + end + end + def user_abilities [:read_user] end diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index d914b0b26eb..5fa6eacd234 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -55,6 +55,10 @@ class ApplicationSetting < ActiveRecord::Base presence: true, numericality: { only_integer: true, greater_than: 0 } + validates :repository_storage, + presence: true, + inclusion: { in: ->(_object) { Gitlab.config.repositories.storages.keys } } + validates_each :restricted_visibility_levels do |record, attr, value| unless value.nil? value.each do |level| @@ -134,6 +138,7 @@ class ApplicationSetting < ActiveRecord::Base disabled_oauth_sign_in_sources: [], send_user_confirmation_email: false, container_registry_token_expire_delay: 5, + repository_storage: 'default', ) end diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 2b0bec33131..c11f8e6884d 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -90,7 +90,7 @@ module Ci end def retryable? - project.builds_enabled? && commands.present? + project.builds_enabled? && commands.present? && complete? end def retried? diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index d6f55885dd6..acb6f5a2998 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -58,7 +58,6 @@ module Issuable scope :references_project, -> { references(:project) } scope :non_archived, -> { join_project.where(projects: { archived: false }) } - delegate :name, :email, to: :author, diff --git a/app/models/group.rb b/app/models/group.rb index c70c719e338..a8be7004ee8 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -6,15 +6,16 @@ class Group < Namespace include AccessRequestable include Referable - has_many :group_members, dependent: :destroy, as: :source, class_name: 'GroupMember' + has_many :group_members, -> { where(requested_at: nil) }, dependent: :destroy, as: :source, class_name: 'GroupMember' alias_method :members, :group_members - has_many :users, -> { where(members: { requested_at: nil }) }, through: :group_members - + has_many :users, through: :group_members has_many :owners, - -> { where(members: { requested_at: nil, access_level: Gitlab::Access::OWNER }) }, + -> { where(members: { access_level: Gitlab::Access::OWNER }) }, through: :group_members, source: :user + has_many :requesters, -> { where.not(requested_at: nil) }, dependent: :destroy, as: :source, class_name: 'GroupMember' + has_many :project_group_links, dependent: :destroy has_many :shared_projects, through: :project_group_links, source: :project has_many :notification_settings, dependent: :destroy, as: :source diff --git a/app/models/issue.rb b/app/models/issue.rb index 3c5859194b4..60abd47409e 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -19,6 +19,8 @@ class Issue < ActiveRecord::Base belongs_to :project belongs_to :moved_to, class_name: 'Issue' + has_many :events, as: :target, dependent: :destroy + validates :project, presence: true scope :cared, ->(user) { where(assignee_id: user) } diff --git a/app/models/member.rb b/app/models/member.rb index 57161397e2b..44db3d977fa 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -30,8 +30,6 @@ class Member < ActiveRecord::Base scope :invite, -> { where.not(invite_token: nil) } scope :non_invite, -> { where(invite_token: nil) } scope :request, -> { where.not(requested_at: nil) } - scope :non_request, -> { where(requested_at: nil) } - scope :non_pending, -> { non_request.non_invite } scope :has_access, -> { where('access_level > 0') } scope :guests, -> { where(access_level: GUEST) } diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb index e9d3a82ba15..f39afc61ce9 100644 --- a/app/models/members/project_member.rb +++ b/app/models/members/project_member.rb @@ -15,7 +15,6 @@ class ProjectMember < Member before_destroy :delete_member_todos class << self - # Add users to project teams with passed access option # # access can be an integer representing a access code diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 53d9aa588af..5ebc8f0c99f 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -12,6 +12,8 @@ class MergeRequest < ActiveRecord::Base has_one :merge_request_diff, dependent: :destroy + has_many :events, as: :target, dependent: :destroy + serialize :merge_params, Hash after_create :create_merge_request_diff, unless: :importing diff --git a/app/models/milestone.rb b/app/models/milestone.rb index e0c8454a998..2bd7f198030 100644 --- a/app/models/milestone.rb +++ b/app/models/milestone.rb @@ -17,6 +17,7 @@ class Milestone < ActiveRecord::Base has_many :labels, -> { distinct.reorder('labels.title') }, through: :issues has_many :merge_requests has_many :participants, -> { distinct.reorder('users.name') }, through: :issues, source: :assignee + has_many :events, as: :target, dependent: :destroy scope :active, -> { with_state(:active) } scope :closed, -> { with_state(:closed) } diff --git a/app/models/namespace.rb b/app/models/namespace.rb index da19462f265..8b52cc824cd 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -21,8 +21,10 @@ class Namespace < ActiveRecord::Base delegate :name, to: :owner, allow_nil: true, prefix: true - after_create :ensure_dir_exist after_update :move_dir, if: :path_changed? + + # Save the storage paths before the projects are destroyed to use them on after destroy + before_destroy(prepend: true) { @old_repository_storage_paths = repository_storage_paths } after_destroy :rm_dir scope :root, -> { where('type IS NULL') } @@ -87,51 +89,35 @@ class Namespace < ActiveRecord::Base owner_name end - def ensure_dir_exist - gitlab_shell.add_namespace(path) - end - - def rm_dir - # Move namespace directory into trash. - # We will remove it later async - new_path = "#{path}+#{id}+deleted" - - if gitlab_shell.mv_namespace(path, new_path) - message = "Namespace directory \"#{path}\" moved to \"#{new_path}\"" - Gitlab::AppLogger.info message - - # Remove namespace directroy async with delay so - # GitLab has time to remove all projects first - GitlabShellWorker.perform_in(5.minutes, :rm_namespace, new_path) - end - end - def move_dir - # Ensure old directory exists before moving it - gitlab_shell.add_namespace(path_was) - if any_project_has_container_registry_tags? raise Exception.new('Namespace cannot be moved, because at least one project has tags in container registry') end - if gitlab_shell.mv_namespace(path_was, path) - Gitlab::UploadsTransfer.new.rename_namespace(path_was, path) - - # If repositories moved successfully we need to - # send update instructions to users. - # However we cannot allow rollback since we moved namespace dir - # So we basically we mute exceptions in next actions - begin - send_update_instructions - rescue - # Returning false does not rollback after_* transaction but gives - # us information about failing some of tasks - false + # Move the namespace directory in all storages paths used by member projects + repository_storage_paths.each do |repository_storage_path| + # Ensure old directory exists before moving it + gitlab_shell.add_namespace(repository_storage_path, path_was) + + unless gitlab_shell.mv_namespace(repository_storage_path, path_was, path) + # if we cannot move namespace directory we should rollback + # db changes in order to prevent out of sync between db and fs + raise Exception.new('namespace directory cannot be moved') end - else - # if we cannot move namespace directory we should rollback - # db changes in order to prevent out of sync between db and fs - raise Exception.new('namespace directory cannot be moved') + end + + Gitlab::UploadsTransfer.new.rename_namespace(path_was, path) + + # If repositories moved successfully we need to + # send update instructions to users. + # However we cannot allow rollback since we moved namespace dir + # So we basically we mute exceptions in next actions + begin + send_update_instructions + rescue + # Returning false does not rollback after_* transaction but gives + # us information about failing some of tasks + false end end @@ -152,4 +138,33 @@ class Namespace < ActiveRecord::Base def find_fork_of(project) projects.joins(:forked_project_link).find_by('forked_project_links.forked_from_project_id = ?', project.id) end + + private + + def repository_storage_paths + # We need to get the storage paths for all the projects, even the ones that are + # pending delete. Unscoping also get rids of the default order, which causes + # problems with SELECT DISTINCT. + Project.unscoped do + projects.select('distinct(repository_storage)').to_a.map(&:repository_storage_path) + end + end + + def rm_dir + # Remove the namespace directory in all storages paths used by member projects + @old_repository_storage_paths.each do |repository_storage_path| + # Move namespace directory into trash. + # We will remove it later async + new_path = "#{path}+#{id}+deleted" + + if gitlab_shell.mv_namespace(repository_storage_path, path, new_path) + message = "Namespace directory \"#{path}\" moved to \"#{new_path}\"" + Gitlab::AppLogger.info message + + # Remove namespace directroy async with delay so + # GitLab has time to remove all projects first + GitlabShellWorker.perform_in(5.minutes, :rm_namespace, repository_storage_path, new_path) + end + end + end end diff --git a/app/models/network/graph.rb b/app/models/network/graph.rb index a2aee2f925b..345041a6ad1 100644 --- a/app/models/network/graph.rb +++ b/app/models/network/graph.rb @@ -54,7 +54,7 @@ module Network @map = {} @reserved = {} - @commits.each_with_index do |c,i| + @commits.each_with_index do |c, i| c.time = i days[i] = c.committed_date @map[c.id] = c @@ -116,7 +116,7 @@ module Network end def commits_sort_by_ref - @commits.sort do |a,b| + @commits.sort do |a, b| if include_ref?(a) -1 elsif include_ref?(b) diff --git a/app/models/note.rb b/app/models/note.rb index 8db500a5219..c2bb117eb03 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -21,6 +21,7 @@ class Note < ActiveRecord::Base belongs_to :updated_by, class_name: "User" has_many :todos, dependent: :destroy + has_many :events, as: :target, dependent: :destroy delegate :gfm_reference, :local_reference, to: :noteable delegate :name, to: :project, prefix: true diff --git a/app/models/project.rb b/app/models/project.rb index 73ded09c162..ae96f00a705 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -24,8 +24,12 @@ class Project < ActiveRecord::Base default_value_for :wiki_enabled, gitlab_config_features.wiki default_value_for :snippets_enabled, gitlab_config_features.snippets default_value_for :container_registry_enabled, gitlab_config_features.container_registry + default_value_for(:repository_storage) { current_application_settings.repository_storage } default_value_for(:shared_runners_enabled) { current_application_settings.shared_runners_enabled } + after_create :ensure_dir_exist + after_save :ensure_dir_exist, if: :namespace_id_changed? + # set last_activity_at to the same as created_at after_create :set_last_activity_at def set_last_activity_at @@ -104,9 +108,13 @@ class Project < ActiveRecord::Base has_many :snippets, dependent: :destroy, class_name: 'ProjectSnippet' has_many :hooks, dependent: :destroy, class_name: 'ProjectHook' has_many :protected_branches, dependent: :destroy - has_many :project_members, dependent: :destroy, as: :source, class_name: 'ProjectMember' + + has_many :project_members, -> { where(requested_at: nil) }, dependent: :destroy, as: :source, class_name: 'ProjectMember' alias_method :members, :project_members - has_many :users, -> { where(members: { requested_at: nil }) }, through: :project_members + has_many :users, through: :project_members + + has_many :requesters, -> { where.not(requested_at: nil) }, dependent: :destroy, as: :source, class_name: 'ProjectMember' + has_many :deploy_keys_projects, dependent: :destroy has_many :deploy_keys, through: :deploy_keys_projects has_many :users_star_projects, dependent: :destroy @@ -165,6 +173,9 @@ class Project < ActiveRecord::Base validate :visibility_level_allowed_by_group validate :visibility_level_allowed_as_fork validate :check_wiki_path_conflict + validates :repository_storage, + presence: true, + inclusion: { in: ->(_object) { Gitlab.config.repositories.storages.keys } } add_authentication_token_field :runners_token before_save :ensure_runners_token @@ -376,6 +387,10 @@ class Project < ActiveRecord::Base end end + def repository_storage_path + Gitlab.config.repositories.storages[repository_storage] + end + def team @team ||= ProjectTeam.new(self) end @@ -842,12 +857,12 @@ class Project < ActiveRecord::Base raise Exception.new('Project cannot be renamed, because tags are present in its container registry') end - if gitlab_shell.mv_repository(old_path_with_namespace, new_path_with_namespace) + if gitlab_shell.mv_repository(repository_storage_path, old_path_with_namespace, new_path_with_namespace) # If repository moved successfully we need to send update instructions to users. # However we cannot allow rollback since we moved repository # So we basically we mute exceptions in next actions begin - gitlab_shell.mv_repository("#{old_path_with_namespace}.wiki", "#{new_path_with_namespace}.wiki") + gitlab_shell.mv_repository(repository_storage_path, "#{old_path_with_namespace}.wiki", "#{new_path_with_namespace}.wiki") send_move_instructions(old_path_with_namespace) reset_events_cache @@ -988,7 +1003,7 @@ class Project < ActiveRecord::Base def create_repository # Forked import is handled asynchronously unless forked? - if gitlab_shell.add_repository(path_with_namespace) + if gitlab_shell.add_repository(repository_storage_path, path_with_namespace) repository.after_create true else @@ -1140,4 +1155,8 @@ class Project < ActiveRecord::Base _, status = Gitlab::Popen.popen(%W(find #{export_path} -not -path #{export_path} -delete)) status.zero? end + + def ensure_dir_exist + gitlab_shell.add_namespace(repository_storage_path, namespace.path) + end end diff --git a/app/models/project_services/bugzilla_service.rb b/app/models/project_services/bugzilla_service.rb index 260f6030957..81af55aa29a 100644 --- a/app/models/project_services/bugzilla_service.rb +++ b/app/models/project_services/bugzilla_service.rb @@ -1,5 +1,4 @@ class BugzillaService < IssueTrackerService - prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url def title @@ -21,5 +20,4 @@ class BugzillaService < IssueTrackerService def to_param 'bugzilla' end - end diff --git a/app/models/project_services/custom_issue_tracker_service.rb b/app/models/project_services/custom_issue_tracker_service.rb index 8f2db46a7ba..63a5ed14484 100644 --- a/app/models/project_services/custom_issue_tracker_service.rb +++ b/app/models/project_services/custom_issue_tracker_service.rb @@ -1,5 +1,4 @@ class CustomIssueTrackerService < IssueTrackerService - prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url def title @@ -31,5 +30,4 @@ class CustomIssueTrackerService < IssueTrackerService { type: 'text', name: 'new_issue_url', placeholder: 'New Issue url' } ] end - end diff --git a/app/models/project_services/drone_ci_service.rb b/app/models/project_services/drone_ci_service.rb index 966dbc41d73..5e4dd101c53 100644 --- a/app/models/project_services/drone_ci_service.rb +++ b/app/models/project_services/drone_ci_service.rb @@ -1,5 +1,4 @@ class DroneCiService < CiService - prop_accessor :drone_url, :token, :enable_ssl_verification validates :drone_url, presence: true, url: true, if: :activated? diff --git a/app/models/project_services/hipchat_service.rb b/app/models/project_services/hipchat_service.rb index 0ff4f4c8dd2..23e5b16221b 100644 --- a/app/models/project_services/hipchat_service.rb +++ b/app/models/project_services/hipchat_service.rb @@ -106,7 +106,7 @@ class HipchatService < Service else message << "pushed to #{ref_type} <a href=\""\ "#{project.web_url}/commits/#{CGI.escape(ref)}\">#{ref}</a> " - message << "of <a href=\"#{project.web_url}\">#{project.name_with_namespace.gsub!(/\s/,'')}</a> " + message << "of <a href=\"#{project.web_url}\">#{project.name_with_namespace.gsub!(/\s/, '')}</a> " message << "(<a href=\"#{project.web_url}/compare/#{before}...#{after}\">Compare changes</a>)" push[:commits].take(MAX_COMMITS).each do |commit| diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb index 87ecb3b8b86..d1df6d0292f 100644 --- a/app/models/project_services/issue_tracker_service.rb +++ b/app/models/project_services/issue_tracker_service.rb @@ -1,5 +1,4 @@ class IssueTrackerService < Service - validates :project_url, :issues_url, :new_issue_url, presence: true, url: true, if: :activated? default_value_for :category, 'issue_tracker' diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb index beda89d3963..27bf08bf7d9 100644 --- a/app/models/project_services/jira_service.rb +++ b/app/models/project_services/jira_service.rb @@ -124,7 +124,7 @@ class JiraService < IssueTrackerService def build_api_url_from_project_url server = URI(project_url) - default_ports = [["http",80],["https",443]].include?([server.scheme,server.port]) + default_ports = [["http", 80], ["https", 443]].include?([server.scheme, server.port]) server_url = "#{server.scheme}://#{server.host}" server_url.concat(":#{server.port}") unless default_ports "#{server_url}/rest/api/#{DEFAULT_API_VERSION}" @@ -190,7 +190,6 @@ class JiraService < IssueTrackerService end end - def auth require 'base64' Base64.urlsafe_encode64("#{self.username}:#{self.password}") diff --git a/app/models/project_services/redmine_service.rb b/app/models/project_services/redmine_service.rb index 11cce3e0561..f634e0772c0 100644 --- a/app/models/project_services/redmine_service.rb +++ b/app/models/project_services/redmine_service.rb @@ -1,5 +1,4 @@ class RedmineService < IssueTrackerService - prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url def title diff --git a/app/models/project_team.rb b/app/models/project_team.rb index 0865b979ce0..0b700930641 100644 --- a/app/models/project_team.rb +++ b/app/models/project_team.rb @@ -22,12 +22,12 @@ class ProjectTeam end def find_member(user_id) - member = project.members.non_request.find_by(user_id: user_id) + member = project.members.find_by(user_id: user_id) # If user is not in project members # we should check for group membership if group && !member - member = group.members.non_request.find_by(user_id: user_id) + member = group.members.find_by(user_id: user_id) end member @@ -137,10 +137,10 @@ class ProjectTeam def max_member_access(user_id) access = [] - access += project.members.non_request.where(user_id: user_id).has_access.pluck(:access_level) + access += project.members.where(user_id: user_id).has_access.pluck(:access_level) if group - access += group.members.non_request.where(user_id: user_id).has_access.pluck(:access_level) + access += group.members.where(user_id: user_id).has_access.pluck(:access_level) end if project.invited_groups.any? && project.allowed_to_share_with_group? @@ -168,14 +168,14 @@ class ProjectTeam end def fetch_members(level = nil) - project_members = project.members.non_request - group_members = group ? group.members.non_request : [] + project_members = project.members + group_members = group ? group.members : [] invited_members = [] if project.invited_groups.any? && project.allowed_to_share_with_group? project.project_group_links.each do |group_link| invited_group = group_link.group - im = invited_group.members.non_request + im = invited_group.members if level int_level = GroupMember.access_level_roles[level.to_s.singularize.titleize] diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb index 25d82929c0b..a255710f577 100644 --- a/app/models/project_wiki.rb +++ b/app/models/project_wiki.rb @@ -159,7 +159,7 @@ class ProjectWiki private def init_repo(path_with_namespace) - gitlab_shell.add_repository(path_with_namespace) + gitlab_shell.add_repository(project.repository_storage_path, path_with_namespace) end def commit_details(action, message = nil, title = nil) @@ -173,7 +173,7 @@ class ProjectWiki end def path_to_repo - @path_to_repo ||= File.join(Gitlab.config.gitlab_shell.repos_path, "#{path_with_namespace}.git") + @path_to_repo ||= File.join(project.repository_storage_path, "#{path_with_namespace}.git") end def update_project_activity diff --git a/app/models/repository.rb b/app/models/repository.rb index 2a6a3b086c2..11ecb281a55 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -39,7 +39,7 @@ class Repository # Return absolute path to repository def path_to_repo @path_to_repo ||= File.expand_path( - File.join(Gitlab.config.gitlab_shell.repos_path, path_with_namespace + ".git") + File.join(@project.repository_storage_path, path_with_namespace + ".git") ) end @@ -246,24 +246,26 @@ class Repository end end + # Keys for data that can be affected for any commit push. def cache_keys - %i(size branch_names tag_names branch_count tag_count commit_count + %i(size commit_count readme version contribution_guide changelog license_blob license_key gitignore) end + # Keys for data on branch/tag operations. + def cache_keys_for_branches_and_tags + %i(branch_names tag_names branch_count tag_count) + end + def build_cache - cache_keys.each do |key| + (cache_keys + cache_keys_for_branches_and_tags).each do |key| unless cache.exist?(key) send(key) end end end - def expire_gitignore - cache.expire(:gitignore) - end - def expire_tags_cache cache.expire(:tag_names) @tags = nil @@ -286,8 +288,6 @@ class Repository # This ensures this particular cache is flushed after the first commit to a # new repository. expire_emptiness_caches if empty? - expire_branch_count_cache - expire_tag_count_cache end def expire_branch_cache(branch_name = nil) @@ -875,7 +875,6 @@ class Repository merge_base(ancestor_id, descendant_id) == ancestor_id end - def search_files(query, ref) offset = 2 args = %W(#{Gitlab.config.git.bin_path} grep -i -I -n --before-context #{offset} --after-context #{offset} -E -e #{Regexp.escape(query)} #{ref || root_ref}) diff --git a/app/models/todo.rb b/app/models/todo.rb index 2792fa9b9a8..3ba67078d48 100644 --- a/app/models/todo.rb +++ b/app/models/todo.rb @@ -4,6 +4,13 @@ class Todo < ActiveRecord::Base BUILD_FAILED = 3 MARKED = 4 + ACTION_NAMES = { + ASSIGNED => :assigned, + MENTIONED => :mentioned, + BUILD_FAILED => :build_failed, + MARKED => :marked + } + belongs_to :author, class_name: "User" belongs_to :note belongs_to :project @@ -34,6 +41,10 @@ class Todo < ActiveRecord::Base action == BUILD_FAILED end + def action_name + ACTION_NAMES[action] + end + def body if note.present? note.note diff --git a/app/models/user.rb b/app/models/user.rb index 767d6366c79..5036a3e300c 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -764,7 +764,7 @@ class User < ActiveRecord::Base unless email_domains.blank? match_found = email_domains.any? do |domain| - escaped = Regexp.escape(domain).gsub('\*','.*?') + escaped = Regexp.escape(domain).gsub('\*', '.*?') regexp = Regexp.new "^#{escaped}$", Regexp::IGNORECASE email_domain = Mail::Address.new(self.email).domain email_domain =~ regexp @@ -852,7 +852,6 @@ class User < ActiveRecord::Base projects.select(:id), groups.joins(:shared_projects).select(:project_id)] - if min_access_level scope = { access_level: Gitlab::Access.values.select { |access| access >= min_access_level } } relations = [relations.shift] + relations.map { |relation| relation.where(members: scope) } diff --git a/app/services/create_release_service.rb b/app/services/create_release_service.rb index e06a6f2f47a..f029db72d40 100644 --- a/app/services/create_release_service.rb +++ b/app/services/create_release_service.rb @@ -2,7 +2,6 @@ require_relative 'base_service' class CreateReleaseService < BaseService def execute(tag_name, release_description) - repository = project.repository existing_tag = repository.find_tag(tag_name) diff --git a/app/services/issues/base_service.rb b/app/services/issues/base_service.rb index 772f5c5fffa..089b0f527e2 100644 --- a/app/services/issues/base_service.rb +++ b/app/services/issues/base_service.rb @@ -1,6 +1,5 @@ module Issues class BaseService < ::IssuableBaseService - def hook_data(issue, action) issue_data = issue.to_hook_data(current_user) issue_url = Gitlab::UrlBuilder.build(issue) diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb index bc93ba2552d..bc3606a14c2 100644 --- a/app/services/merge_requests/base_service.rb +++ b/app/services/merge_requests/base_service.rb @@ -1,6 +1,5 @@ module MergeRequests class BaseService < ::IssuableBaseService - def create_note(merge_request) SystemNoteService.change_status(merge_request, merge_request.target_project, current_user, merge_request.state, nil) end diff --git a/app/services/merge_requests/merge_when_build_succeeds_service.rb b/app/services/merge_requests/merge_when_build_succeeds_service.rb index 12edfb2d671..870f5705184 100644 --- a/app/services/merge_requests/merge_when_build_succeeds_service.rb +++ b/app/services/merge_requests/merge_when_build_succeeds_service.rb @@ -40,6 +40,5 @@ module MergeRequests error("Can't cancel the automatic merge", 406) end end - end end diff --git a/app/services/milestones/destroy_service.rb b/app/services/milestones/destroy_service.rb index 2414966505b..e457212508f 100644 --- a/app/services/milestones/destroy_service.rb +++ b/app/services/milestones/destroy_service.rb @@ -1,7 +1,6 @@ module Milestones class DestroyService < Milestones::BaseService def execute(milestone) - Milestone.transaction do update_params = { milestone: nil } diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb index f09072975c3..882606e38d0 100644 --- a/app/services/projects/destroy_service.rb +++ b/app/services/projects/destroy_service.rb @@ -51,13 +51,13 @@ module Projects return true if params[:skip_repo] == true # There is a possibility project does not have repository or wiki - return true unless gitlab_shell.exists?(path + '.git') + return true unless gitlab_shell.exists?(project.repository_storage_path, path + '.git') new_path = removal_path(path) - if gitlab_shell.mv_repository(path, new_path) + if gitlab_shell.mv_repository(project.repository_storage_path, path, new_path) log_info("Repository \"#{path}\" moved to \"#{new_path}\"") - GitlabShellWorker.perform_in(5.minutes, :remove_repository, new_path) + GitlabShellWorker.perform_in(5.minutes, :remove_repository, project.repository_storage_path, new_path) else false end diff --git a/app/services/projects/download_service.rb b/app/services/projects/download_service.rb index 6386f57fb0d..f06a3d44c17 100644 --- a/app/services/projects/download_service.rb +++ b/app/services/projects/download_service.rb @@ -1,6 +1,5 @@ module Projects class DownloadService < BaseService - WHITELIST = [ /^[^.]+\.fogbugz.com$/ ] diff --git a/app/services/projects/housekeeping_service.rb b/app/services/projects/housekeeping_service.rb index 43db29315a1..a47df22f1ba 100644 --- a/app/services/projects/housekeeping_service.rb +++ b/app/services/projects/housekeeping_service.rb @@ -24,7 +24,7 @@ module Projects def execute raise LeaseTaken unless try_obtain_lease - GitlabShellOneShotWorker.perform_async(:gc, @project.path_with_namespace) + GitlabShellOneShotWorker.perform_async(:gc, @project.repository_storage_path, @project.path_with_namespace) ensure Gitlab::Metrics.measure(:reset_pushes_since_gc) do @project.update_column(:pushes_since_gc, 0) diff --git a/app/services/projects/import_export/export_service.rb b/app/services/projects/import_export/export_service.rb index 80c7193efcb..3f507d5c400 100644 --- a/app/services/projects/import_export/export_service.rb +++ b/app/services/projects/import_export/export_service.rb @@ -1,7 +1,6 @@ module Projects module ImportExport class ExportService < BaseService - def execute(_options = {}) @shared = Gitlab::ImportExport::Shared.new(relative_path: File.join(project.path_with_namespace, 'work')) save_all diff --git a/app/services/projects/import_service.rb b/app/services/projects/import_service.rb index 9159ec08959..163ebf26c84 100644 --- a/app/services/projects/import_service.rb +++ b/app/services/projects/import_service.rb @@ -42,7 +42,7 @@ module Projects def import_repository begin - gitlab_shell.import_repository(project.path_with_namespace, project.import_url) + gitlab_shell.import_repository(project.repository_storage_path, project.path_with_namespace, project.import_url) rescue Gitlab::Shell::Error => e raise Error, "Error importing repository #{project.import_url} into #{project.path_with_namespace} - #{e.message}" end diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb index 03b57dea51e..bc7f8bf433b 100644 --- a/app/services/projects/transfer_service.rb +++ b/app/services/projects/transfer_service.rb @@ -50,12 +50,12 @@ module Projects project.send_move_instructions(old_path) # Move main repository - unless gitlab_shell.mv_repository(old_path, new_path) + unless gitlab_shell.mv_repository(project.repository_storage_path, old_path, new_path) raise TransferError.new('Cannot move project') end # Move wiki repo also if present - gitlab_shell.mv_repository("#{old_path}.wiki", "#{new_path}.wiki") + gitlab_shell.mv_repository(project.repository_storage_path, "#{old_path}.wiki", "#{new_path}.wiki") # clear project cached events project.reset_events_cache diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb index 4e8fa0818b9..b868d2e7e83 100644 --- a/app/services/system_note_service.rb +++ b/app/services/system_note_service.rb @@ -293,7 +293,6 @@ class SystemNoteService end end - def self.cross_reference?(note_text) note_text.start_with?(cross_reference_note_prefix) end diff --git a/app/services/update_release_service.rb b/app/services/update_release_service.rb index 25eb13ef09a..0c0f68d169b 100644 --- a/app/services/update_release_service.rb +++ b/app/services/update_release_service.rb @@ -2,7 +2,6 @@ require_relative 'base_service' class UpdateReleaseService < BaseService def execute(tag_name, release_description) - repository = project.repository existing_tag = repository.find_tag(tag_name) diff --git a/app/services/wiki_pages/base_service.rb b/app/services/wiki_pages/base_service.rb index 4c0a2c6b4d8..14317ea65c8 100644 --- a/app/services/wiki_pages/base_service.rb +++ b/app/services/wiki_pages/base_service.rb @@ -1,6 +1,5 @@ module WikiPages class BaseService < ::BaseService - def hook_data(page, action) hook_data = { object_kind: page.class.name.underscore, diff --git a/app/uploaders/lfs_object_uploader.rb b/app/uploaders/lfs_object_uploader.rb index 28085b31083..046a1d641a9 100644 --- a/app/uploaders/lfs_object_uploader.rb +++ b/app/uploaders/lfs_object_uploader.rb @@ -4,7 +4,7 @@ class LfsObjectUploader < CarrierWave::Uploader::Base storage :file def store_dir - "#{Gitlab.config.lfs.storage_path}/#{model.oid[0,2]}/#{model.oid[2,2]}" + "#{Gitlab.config.lfs.storage_path}/#{model.oid[0, 2]}/#{model.oid[2, 2]}" end def cache_dir diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index 30ab0717164..c1f70bc1866 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -311,6 +311,15 @@ = f.text_field :sentry_dsn, class: 'form-control' %fieldset + %legend Repository Storage + .form-group + = f.label :repository_storage, 'Storage path for new projects', class: 'control-label col-sm-2' + .col-sm-10 + = f.select :repository_storage, repository_storage_options_for_select, {}, class: 'form-control' + .help-block + You can manage the repository storage paths in your gitlab.yml configuration file + + %fieldset %legend Repository Checks .form-group .col-sm-offset-2.col-sm-10 diff --git a/app/views/admin/background_jobs/show.html.haml b/app/views/admin/background_jobs/show.html.haml index 654d261aa99..4f680b507c4 100644 --- a/app/views/admin/background_jobs/show.html.haml +++ b/app/views/admin/background_jobs/show.html.haml @@ -2,7 +2,7 @@ - page_title "Background Jobs" = render 'admin/background_jobs/head' -%div{ class: (container_class) } +%div{ class: container_class } %h3.page-title Background Jobs %p.light GitLab uses #{link_to "sidekiq", "http://sidekiq.org/"} library for async job processing diff --git a/app/views/admin/builds/index.html.haml b/app/views/admin/builds/index.html.haml index efd5b12cfeb..1e60205f91a 100644 --- a/app/views/admin/builds/index.html.haml +++ b/app/views/admin/builds/index.html.haml @@ -1,7 +1,7 @@ - @no_container = true = render "admin/dashboard/head" -%div{ class: (container_class) } +%div{ class: container_class } .top-area %ul.nav-links diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml index 4682016a886..a2ac407c159 100644 --- a/app/views/admin/dashboard/index.html.haml +++ b/app/views/admin/dashboard/index.html.haml @@ -1,7 +1,7 @@ - @no_container = true = render "admin/dashboard/head" -%div{ class: (container_class) } +%div{ class: container_class } .admin-dashboard.prepend-top-default .row .col-md-4 diff --git a/app/views/admin/groups/index.html.haml b/app/views/admin/groups/index.html.haml index 4f1996ef7ab..94aa5f5a942 100644 --- a/app/views/admin/groups/index.html.haml +++ b/app/views/admin/groups/index.html.haml @@ -2,7 +2,7 @@ - page_title "Groups" = render "admin/dashboard/head" -%div{ class: (container_class) } +%div{ class: container_class } %h3.page-title Groups (#{number_with_delimiter(@groups.total_count)}) @@ -39,7 +39,6 @@ = link_to 'New Group', new_admin_group_path, class: "btn btn-new" %ul.content-list - - @groups.each do |group| - = render 'group', group: group + = render @groups = paginate @groups, theme: "gitlab" diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml index 50770465f07..522153b37e3 100644 --- a/app/views/admin/groups/show.html.haml +++ b/app/views/admin/groups/show.html.haml @@ -89,16 +89,16 @@ %hr = button_tag 'Add users to group', class: "btn btn-create" - = render 'shared/members/requests', membership_source: @group, members: @members.request + = render 'shared/members/requests', membership_source: @group, requesters: @requesters .panel.panel-default .panel-heading %strong= @group.name group members - %span.badge= @group.members.non_request.size + %span.badge= @group.members.size .pull-right = link_to icon('pencil-square-o', text: 'Manage Access'), polymorphic_url([@group, :members]), class: "btn btn-xs" %ul.well-list.group-users-list.content-list - = render partial: 'shared/members/member', collection: @members.non_request, as: :member, locals: { show_controls: false } + = render partial: 'shared/members/member', collection: @members, as: :member, locals: { show_controls: false } .panel-footer - = paginate @members.non_request, param_name: 'members_page', theme: 'gitlab' + = paginate @members, param_name: 'members_page', theme: 'gitlab' diff --git a/app/views/admin/health_check/show.html.haml b/app/views/admin/health_check/show.html.haml index 7b8407f9152..e79303240f0 100644 --- a/app/views/admin/health_check/show.html.haml +++ b/app/views/admin/health_check/show.html.haml @@ -2,7 +2,7 @@ - page_title "Health Check" = render 'admin/background_jobs/head' -%div{ class: (container_class) } +%div{ class: container_class } %h3.page-title Health Check .bs-callout.clearfix diff --git a/app/views/admin/logs/show.html.haml b/app/views/admin/logs/show.html.haml index 5ddc3b9ea85..676812121d7 100644 --- a/app/views/admin/logs/show.html.haml +++ b/app/views/admin/logs/show.html.haml @@ -5,7 +5,7 @@ Gitlab::RepositoryCheckLogger] = render 'admin/background_jobs/head' -%div{ class: (container_class) } +%div{ class: container_class } %ul.nav-links.log-tabs - loggers.each do |klass| %li{ class: (klass == Gitlab::GitLogger ? 'active' : '') } diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml index 4822cb693c2..7d2eb423223 100644 --- a/app/views/admin/projects/index.html.haml +++ b/app/views/admin/projects/index.html.haml @@ -3,7 +3,7 @@ = render 'shared/show_aside' = render "admin/dashboard/head" -%div{ class: (container_class) } +%div{ class: container_class } .row.prepend-top-default %aside.col-md-3 .panel.admin-filter diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml index 461d588415d..82d3169c6f9 100644 --- a/app/views/admin/projects/show.html.haml +++ b/app/views/admin/projects/show.html.haml @@ -137,16 +137,16 @@ .panel-heading %strong= @group.name group members - %span.badge= @group_members.non_request.size + %span.badge= @group_members.size .pull-right = link_to admin_group_path(@group), class: 'btn btn-xs' do = icon('pencil-square-o', text: 'Manage Access') %ul.well-list.content-list - = render partial: 'shared/members/member', collection: @group_members.non_request, as: :member, locals: { show_controls: false } + = render partial: 'shared/members/member', collection: @group_members, as: :member, locals: { show_controls: false } .panel-footer - = paginate @group_members.non_request, param_name: 'group_members_page', theme: 'gitlab' + = paginate @group_members, param_name: 'group_members_page', theme: 'gitlab' - = render 'shared/members/requests', membership_source: @project, members: @project_members.request + = render 'shared/members/requests', membership_source: @project, requesters: @requesters .panel.panel-default .panel-heading @@ -156,6 +156,6 @@ .pull-right = link_to icon('pencil-square-o', text: 'Manage Access'), polymorphic_url([@project, :members]), class: "btn btn-xs" %ul.well-list.project_members.content-list - = render partial: 'shared/members/member', collection: @project_members.non_request, as: :member, locals: { show_controls: false } + = render partial: 'shared/members/member', collection: @project_members, as: :member, locals: { show_controls: false } .panel-footer - = paginate @project_members.non_request, param_name: 'project_members_page', theme: 'gitlab' + = paginate @project_members, param_name: 'project_members_page', theme: 'gitlab' diff --git a/app/views/admin/runners/_runner.html.haml b/app/views/admin/runners/_runner.html.haml index 36b21eefdee..64893b38c58 100644 --- a/app/views/admin/runners/_runner.html.haml +++ b/app/views/admin/runners/_runner.html.haml @@ -4,6 +4,8 @@ %span.label.label-success shared - else %span.label.label-info specific + - if runner.locked? + %span.label.label-warning locked - unless runner.active? %span.label.label-danger paused diff --git a/app/views/admin/runners/index.html.haml b/app/views/admin/runners/index.html.haml index 5eff77aff2d..a53876d6757 100644 --- a/app/views/admin/runners/index.html.haml +++ b/app/views/admin/runners/index.html.haml @@ -1,7 +1,7 @@ - @no_container = true = render "admin/dashboard/head" -%div{ class: (container_class) } +%div{ class: container_class } %p.prepend-top-default %span @@ -40,6 +40,9 @@ %span.label.label-info specific \- run builds from assigned projects %li + %span.label.label-warning locked + \- runner cannot be assigned to other projects + %li %span.label.label-danger paused \- runner will not receive any new builds diff --git a/app/views/admin/system_info/show.html.haml b/app/views/admin/system_info/show.html.haml index 3ef2f20b589..6956e5ab795 100644 --- a/app/views/admin/system_info/show.html.haml +++ b/app/views/admin/system_info/show.html.haml @@ -2,7 +2,7 @@ - page_title "System Info" = render 'admin/background_jobs/head' -%div{ class: (container_class) } +%div{ class: container_class } .prepend-top-default .row .col-sm-4 @@ -17,6 +17,9 @@ %h1= "#{number_to_human_size(@mem_used)} / #{number_to_human_size(@mem_total)}" .col-sm-4 .light-well - %h4 Disk + %h4 Disks .data - %h1= "#{number_to_human_size(@disk_used)} / #{number_to_human_size(@disk_total)}" + - @disks.each do |disk| + %h1= "#{number_to_human_size(disk[:bytes_used])} / #{number_to_human_size(disk[:bytes_total])}" + %p= "#{disk[:disk_name]}" + %p= "#{disk[:mount_path]}" diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml index d0a696da64b..21bb99a792c 100644 --- a/app/views/admin/users/index.html.haml +++ b/app/views/admin/users/index.html.haml @@ -3,7 +3,7 @@ = render 'shared/show_aside' = render "admin/dashboard/head" -%div{ class: (container_class) } +%div{ class: container_class } .admin-filter %ul.nav-links %li{class: "#{'active' unless params[:filter]}"} diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml index d6acade84f1..90f362c052b 100644 --- a/app/views/groups/group_members/index.html.haml +++ b/app/views/groups/group_members/index.html.haml @@ -1,7 +1,7 @@ - page_title "Members" .group-members-page.prepend-top-default - - if current_user && current_user.can?(:admin_group_member, @group) + - if can?(current_user, :admin_group_member, @group) .panel.panel-default .panel-heading Add new user to group @@ -11,13 +11,13 @@ .new-group-member-holder = render "new_group_member" - = render 'shared/members/requests', membership_source: @group, members: @members.request + = render 'shared/members/requests', membership_source: @group, requesters: @requesters .panel.panel-default .panel-heading %strong #{@group.name} group members - %span.badge= @members.non_request.size + %span.badge= @members.size .controls = form_tag group_group_members_path(@group), method: :get, class: 'form-inline member-search-form' do .form-group @@ -25,8 +25,8 @@ = button_tag class: 'btn', title: 'Search' do = icon("search") %ul.content-list - = render partial: 'shared/members/member', collection: @members.non_request, as: :member - = paginate @members.non_request, theme: 'gitlab' + = render partial: 'shared/members/member', collection: @members, as: :member + = paginate @members, theme: 'gitlab' :javascript $('form.member-search-form').on('submit', function(event) { diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml index a0a6762edcf..a83eb7e88bb 100644 --- a/app/views/groups/show.html.haml +++ b/app/views/groups/show.html.haml @@ -5,7 +5,7 @@ = auto_discovery_link_tag(:atom, group_url(@group, format: :atom, private_token: current_user.private_token), title: "#{@group.name} activity") .cover-block.groups-cover-block - %div{ class: (container_class) } + %div{ class: container_class } = link_to group_icon(@group), target: '_blank' do = image_tag group_icon(@group), class: "avatar group-avatar s70" .group-info @@ -15,18 +15,15 @@ %span.visibility-icon.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@group) } = visibility_level_icon(@group.visibility_level, fw: false) - %span.hidden-xs + .group-right-buttons.btn-group + - if current_user + .pull-left.append-right-10= render 'shared/members/access_request_buttons', source: @group = render 'shared/notifications/button', notification_setting: @notification_setting - - if current_user - .pull-right - = render 'shared/members/access_request_buttons', source: @group - - if @group.description.present? .cover-desc.description = markdown(@group.description, pipeline: :description) - %div{ class: container_class } .top-area %ul.nav-links diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml index 57bc91ea5a9..57601ae9be0 100644 --- a/app/views/help/index.html.haml +++ b/app/views/help/index.html.haml @@ -36,6 +36,6 @@ %ul.well-list %li= link_to 'See our website for getting help', promo_url + '/getting-help/' %li= link_to 'Use the search bar on the top of this page', '#', onclick: 'Shortcuts.focusSearch(event)' - %li= link_to 'Use shortcuts', '#', onclick: 'Shortcuts.showHelp(event)' + %li= link_to 'Use shortcuts', '#', onclick: 'Shortcuts.toggleHelp()' %li= link_to 'Get a support subscription', 'https://about.gitlab.com/pricing/' %li= link_to 'Compare GitLab editions', 'https://about.gitlab.com/features/#compare' diff --git a/app/views/import/base/create.js.haml b/app/views/import/base/create.js.haml index dfebf7768d9..804ad88468f 100644 --- a/app/views/import/base/create.js.haml +++ b/app/views/import/base/create.js.haml @@ -1,6 +1,8 @@ - if @already_been_taken :plain - target_field = $("tr#repo_#{@repo_id} .import-target") + tr = $("tr#repo_#{@repo_id}") + target_field = tr.find(".import-target") + import_button = tr.find(".btn-import") origin_target = target_field.text() project_name = "#{@project_name}" origin_namespace = "#{@target_namespace}" @@ -10,6 +12,7 @@ target_field.append("/" + project_name) target_field.data("project_name", project_name) target_field.find('input').prop("value", origin_namespace) + import_button.enable().removeClass('is-loading') - elsif @access_denied :plain job = $("tr#repo_#{@repo_id}") diff --git a/app/views/import/github/new.html.haml b/app/views/import/github/new.html.haml new file mode 100644 index 00000000000..435ed7bd4cb --- /dev/null +++ b/app/views/import/github/new.html.haml @@ -0,0 +1,43 @@ +- page_title "GitHub Import" +- header_title "Projects", root_path + +%h3.page-title + = icon 'github', text: 'Import Projects from GitHub' + +- if github_import_configured? + %p + To import a GitHub project, you first need to authorize GitLab to access + the list of your GitHub repositories: + + = link_to 'List Your GitHub Repositories', status_import_github_path, class: 'btn btn-success' + + %hr + +%p + - if github_import_configured? + Alternatively, + - else + To import a GitHub project, + you can use a + = succeed '.' do + = link_to 'Personal Access Token', 'https://github.com/settings/tokens' + When you create your Personal Access Token, + you will need to select the <code>repo</code> scope, so we can display a + list of your public and private repositories which are available for import. + += form_tag personal_access_token_import_github_path, method: :post, class: 'form-inline' do + .form-group + = text_field_tag :personal_access_token, '', class: 'form-control', placeholder: "Personal Access Token", size: 40 + = submit_tag 'List Your GitHub Repositories', class: 'btn btn-success' + +- unless github_import_configured? + %hr + %p + Note: + - if current_user.admin? + As an administrator you may like to configure + - else + Consider asking your GitLab administrator to configure + = link_to 'GitHub integration', help_page_path("integration", "github") + which will allow login via GitHub and allow importing projects without + generating a Personal Access Token. diff --git a/app/views/layouts/_init_auto_complete.html.haml b/app/views/layouts/_init_auto_complete.html.haml index 96b38485425..12e7ed0e792 100644 --- a/app/views/layouts/_init_auto_complete.html.haml +++ b/app/views/layouts/_init_auto_complete.html.haml @@ -3,4 +3,5 @@ - if @noteable :javascript GitLab.GfmAutoComplete.dataSource = "#{autocomplete_sources_namespace_project_path(project.namespace, project, type: @noteable.class, type_id: params[:id])}" + GitLab.GfmAutoComplete.cachedData = undefined; GitLab.GfmAutoComplete.setup(); diff --git a/app/views/layouts/nav/_group_settings.html.haml b/app/views/layouts/nav/_group_settings.html.haml index 3a24b09ab7e..bf9a7ecb786 100644 --- a/app/views/layouts/nav/_group_settings.html.haml +++ b/app/views/layouts/nav/_group_settings.html.haml @@ -1,6 +1,6 @@ - if current_user - can_edit = can?(current_user, :admin_group, @group) - - member = @group.members.non_request.find_by(user_id: current_user.id) + - member = @group.members.find_by(user_id: current_user.id) - can_leave = member && can?(current_user, :destroy_group_member, member) .controls diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml index dcef427cda3..9e65d94186b 100644 --- a/app/views/layouts/nav/_project.html.haml +++ b/app/views/layouts/nav/_project.html.haml @@ -7,7 +7,7 @@ %ul.dropdown-menu.dropdown-menu-align-right - can_edit = can?(current_user, :admin_project, @project) -# We don't use @project.team.find_member because it searches for group members too... - - member = @project.members.non_request.find_by(user_id: current_user.id) + - member = @project.members.find_by(user_id: current_user.id) - can_leave = member && can?(current_user, :destroy_project_member, member) = render 'layouts/nav/project_settings', can_edit: can_edit diff --git a/app/views/projects/_github_import_modal.html.haml b/app/views/projects/_github_import_modal.html.haml deleted file mode 100644 index 46ad1559356..00000000000 --- a/app/views/projects/_github_import_modal.html.haml +++ /dev/null @@ -1,13 +0,0 @@ -%div#github_import_modal.modal - .modal-dialog - .modal-content - .modal-header - %a.close{href: "#", "data-dismiss" => "modal"} × - %h3 Import projects from GitHub - .modal-body - To enable importing projects from GitHub, - - if current_user.admin? - as administrator you need to configure - - else - ask your Gitlab administrator to configure - == #{link_to 'OAuth integration', help_page_path("integration", "github")}. diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml index 86ea08dd229..540efa4780f 100644 --- a/app/views/projects/_home_panel.html.haml +++ b/app/views/projects/_home_panel.html.haml @@ -1,6 +1,6 @@ - empty_repo = @project.empty_repo? .project-home-panel.cover-block.clearfix{:class => ("empty-project" if empty_repo)} - %div{ class: (container_class) } + %div{ class: container_class } .row .project-image-container = project_icon(@project, alt: '', class: 'project-avatar avatar s70') @@ -31,7 +31,7 @@ .project-repo-buttons.btn-group.project-right-buttons - if current_user - = render 'shared/members/access_request_buttons', source: @project + .pull-left.append-right-10= render 'shared/members/access_request_buttons', source: @project = render "projects/buttons/download" = render 'projects/buttons/dropdown' diff --git a/app/views/projects/_last_push.html.haml b/app/views/projects/_last_push.html.haml index e0ca2a3109c..434d8644b83 100644 --- a/app/views/projects/_last_push.html.haml +++ b/app/views/projects/_last_push.html.haml @@ -1,7 +1,7 @@ - if event = last_push_event - if show_last_push_widget?(event) .row-content-block.top-block.clear-block.hidden-xs - %div{ class: (container_class) } + %div{ class: container_class } .event-last-push .event-last-push-text %span You pushed to diff --git a/app/views/projects/blob/show.html.haml b/app/views/projects/blob/show.html.haml index ed670dae88d..0ab78a39cf9 100644 --- a/app/views/projects/blob/show.html.haml +++ b/app/views/projects/blob/show.html.haml @@ -1,12 +1,15 @@ +- @no_container = true - page_title @blob.path, @ref += render "projects/commits/head" -= render 'projects/last_push' +%div{ class: container_class } + = render 'projects/last_push' -%div#tree-holder.tree-holder - = render 'blob', blob: @blob + %div#tree-holder.tree-holder + = render 'blob', blob: @blob -- if can_edit_blob?(@blob) - = render 'projects/blob/remove' + - if can_edit_blob?(@blob) + = render 'projects/blob/remove' - - title = "Replace #{@blob.name}" - = render 'projects/blob/upload', title: title, placeholder: title, button_title: 'Replace file', form_path: namespace_project_update_blob_path(@project.namespace, @project, @id), method: :put + - title = "Replace #{@blob.name}" + = render 'projects/blob/upload', title: title, placeholder: title, button_title: 'Replace file', form_path: namespace_project_update_blob_path(@project.namespace, @project, @id), method: :put diff --git a/app/views/projects/branches/index.html.haml b/app/views/projects/branches/index.html.haml index e0367c40272..77b405f1f39 100644 --- a/app/views/projects/branches/index.html.haml +++ b/app/views/projects/branches/index.html.haml @@ -2,7 +2,7 @@ - page_title "Branches" = render "projects/commits/head" -%div{ class: (container_class) } +%div{ class: container_class } .top-area .nav-text Protected branches can be managed in project settings @@ -27,7 +27,7 @@ = sort_title_recently_updated = link_to namespace_project_branches_path(sort: 'last_updated') do = sort_title_oldest_updated - - unless @branches.empty? + - if @branches.any? %ul.content-list.all-branches - @branches.each do |branch| = render "projects/branches/branch", branch: branch diff --git a/app/views/projects/builds/index.html.haml b/app/views/projects/builds/index.html.haml index 181547316aa..a131289ee97 100644 --- a/app/views/projects/builds/index.html.haml +++ b/app/views/projects/builds/index.html.haml @@ -2,7 +2,7 @@ - page_title "Builds" = render "projects/pipelines/head" -%div{ class: (container_class) } +%div{ class: container_class } .top-area %ul.nav-links %li{class: ('active' if @scope.nil?)} diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml index 4e2702c2e44..d1c468c4692 100644 --- a/app/views/projects/builds/show.html.haml +++ b/app/views/projects/builds/show.html.haml @@ -67,4 +67,4 @@ = render "sidebar" :javascript - new CiBuild("#{namespace_project_build_url(@project.namespace, @project, @build)}", "#{@build.status}", "#{trace_with_state[:state]}") + new CiBuild("#{namespace_project_build_url(@project.namespace, @project, @build, :json)}", "#{@build.status}", "#{trace_with_state[:state]}") diff --git a/app/views/projects/commits/show.html.haml b/app/views/projects/commits/show.html.haml index 51ca4eb903e..9a44ba94970 100644 --- a/app/views/projects/commits/show.html.haml +++ b/app/views/projects/commits/show.html.haml @@ -7,7 +7,7 @@ = render "head" -%div{ class: (container_class) } +%div{ class: container_class } .row-content-block.second-block.content-component-block .tree-ref-holder = render 'shared/ref_switcher', destination: 'commits' diff --git a/app/views/projects/compare/index.html.haml b/app/views/projects/compare/index.html.haml index b22285c11e0..e9ff8e90dd5 100644 --- a/app/views/projects/compare/index.html.haml +++ b/app/views/projects/compare/index.html.haml @@ -2,7 +2,7 @@ - page_title "Compare" = render "projects/commits/head" -%div{ class: (container_class) } +%div{ class: container_class } .sub-header-block Compare branches, tags or commit ranges. %br diff --git a/app/views/projects/compare/show.html.haml b/app/views/projects/compare/show.html.haml index f4ec7b767f6..28a50e7031a 100644 --- a/app/views/projects/compare/show.html.haml +++ b/app/views/projects/compare/show.html.haml @@ -2,7 +2,7 @@ - page_title "#{params[:from]}...#{params[:to]}" = render "projects/commits/head" -%div{ class: (container_class) } +%div{ class: container_class } .sub-header-block.no-bottom-space = render "form" diff --git a/app/views/projects/environments/index.html.haml b/app/views/projects/environments/index.html.haml index a03f117291f..5242021243e 100644 --- a/app/views/projects/environments/index.html.haml +++ b/app/views/projects/environments/index.html.haml @@ -2,7 +2,7 @@ - page_title "Environments" = render "projects/pipelines/head" -%div{ class: (container_class) } +%div{ class: container_class } - if can?(current_user, :create_environment, @project) && !@environments.blank? .top-area .nav-controls diff --git a/app/views/projects/environments/show.html.haml b/app/views/projects/environments/show.html.haml index 4c15e2759d6..53c62ef234d 100644 --- a/app/views/projects/environments/show.html.haml +++ b/app/views/projects/environments/show.html.haml @@ -2,7 +2,7 @@ - page_title "Environments" = render "projects/pipelines/head" -%div{ class: (container_class) } +%div{ class: container_class } .top-area .col-md-9 %h3.page-title= @environment.name.titleize diff --git a/app/views/projects/graphs/ci.html.haml b/app/views/projects/graphs/ci.html.haml index e695d3ae369..6be4273b6ab 100644 --- a/app/views/projects/graphs/ci.html.haml +++ b/app/views/projects/graphs/ci.html.haml @@ -2,7 +2,7 @@ - page_title "Continuous Integration", "Graphs" = render 'head' -%div{ class: (container_class) } +%div{ class: container_class } .sub-header-block .oneline A collection of graphs for Continuous Integration diff --git a/app/views/projects/graphs/commits.html.haml b/app/views/projects/graphs/commits.html.haml index 0daffe68f6f..65db8af494d 100644 --- a/app/views/projects/graphs/commits.html.haml +++ b/app/views/projects/graphs/commits.html.haml @@ -2,7 +2,7 @@ - page_title "Commits", "Graphs" = render 'head' -%div{ class: (container_class) } +%div{ class: container_class } .sub-header-block .tree-ref-holder = render 'shared/ref_switcher', destination: 'graphs_commits' diff --git a/app/views/projects/graphs/languages.html.haml b/app/views/projects/graphs/languages.html.haml index 6d97f552a8e..fcfcae0be20 100644 --- a/app/views/projects/graphs/languages.html.haml +++ b/app/views/projects/graphs/languages.html.haml @@ -2,7 +2,7 @@ - page_title "Languages", "Graphs" = render 'head' -%div{ class: (container_class) } +%div{ class: container_class } .sub-header-block .oneline Programming languages used in this repository diff --git a/app/views/projects/graphs/show.html.haml b/app/views/projects/graphs/show.html.haml index 9f7e2a361ff..a985b442b2d 100644 --- a/app/views/projects/graphs/show.html.haml +++ b/app/views/projects/graphs/show.html.haml @@ -2,7 +2,7 @@ - page_title "Contributors", "Graphs" = render 'head' -%div{ class: (container_class) } +%div{ class: container_class } .sub-header-block .tree-ref-holder = render 'shared/ref_switcher', destination: 'graphs' diff --git a/app/views/projects/imports/new.html.haml b/app/views/projects/imports/new.html.haml index a8a8caf7280..2cd8d03e30e 100644 --- a/app/views/projects/imports/new.html.haml +++ b/app/views/projects/imports/new.html.haml @@ -10,7 +10,7 @@ .panel-body %pre :preserve - #{sanitize_repo_path(@project.import_error)} + #{sanitize_repo_path(@project, @project.import_error)} = form_for @project, url: namespace_project_import_path(@project.namespace, @project), method: :post, html: { class: 'form-horizontal' } do |f| = render "shared/import_form", f: f diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml index cd876b5ea62..7ce4c1e5555 100644 --- a/app/views/projects/issues/index.html.haml +++ b/app/views/projects/issues/index.html.haml @@ -6,7 +6,7 @@ - if current_user = auto_discovery_link_tag(:atom, namespace_project_issues_url(@project.namespace, @project, :atom, private_token: current_user.private_token), title: "#{@project.name} issues") -%div{ class: (container_class) } +%div{ class: container_class } .top-area = render 'shared/issuable/nav', type: :issues .nav-controls diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml index aa4d69550ec..db66a0edbd8 100644 --- a/app/views/projects/labels/index.html.haml +++ b/app/views/projects/labels/index.html.haml @@ -3,7 +3,7 @@ - hide_class = '' = render "projects/issues/head" -%div{ class: (container_class) } +%div{ class: container_class } .top-area.adjust .nav-text Labels can be applied to issues and merge requests. Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging. diff --git a/app/views/projects/merge_requests/index.html.haml b/app/views/projects/merge_requests/index.html.haml index 9f948d41dda..ace275c689b 100644 --- a/app/views/projects/merge_requests/index.html.haml +++ b/app/views/projects/merge_requests/index.html.haml @@ -3,7 +3,7 @@ = render "projects/issues/head" = render 'projects/last_push' -%div{ class: (container_class) } +%div{ class: container_class } .top-area = render 'shared/issuable/nav', type: :merge_requests .nav-controls diff --git a/app/views/projects/milestones/index.html.haml b/app/views/projects/milestones/index.html.haml index b0e0bdfff5a..ad2bfbec915 100644 --- a/app/views/projects/milestones/index.html.haml +++ b/app/views/projects/milestones/index.html.haml @@ -2,7 +2,7 @@ - page_title "Milestones" = render "projects/issues/head" -%div{ class: (container_class) } +%div{ class: container_class } .top-area = render 'shared/milestones_filter' diff --git a/app/views/projects/network/_head.html.haml b/app/views/projects/network/_head.html.haml index 86295a3d011..8f6805268d5 100644 --- a/app/views/projects/network/_head.html.haml +++ b/app/views/projects/network/_head.html.haml @@ -1,6 +1,6 @@ - @no_container = true -%div{ class: (container_class) } +%div{ class: container_class } .row-content-block.second-block.content-component-block .tree-ref-holder = render partial: 'shared/ref_switcher', locals: {destination: 'graph'} diff --git a/app/views/projects/network/show.html.haml b/app/views/projects/network/show.html.haml index 3ca30b4ba6b..091af4df4a1 100644 --- a/app/views/projects/network/show.html.haml +++ b/app/views/projects/network/show.html.haml @@ -4,7 +4,7 @@ = page_specific_javascript_tag('network/application.js') = render "projects/commits/head" = render "head" -%div{ class: (container_class) } +%div{ class: container_class } .project-network .controls = form_tag namespace_project_network_path(@project.namespace, @project, @id), method: :get, class: 'form-inline network-form' do |f| diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index 8a73b077357..05f33b78a47 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -23,6 +23,7 @@ .input-group-addon = root_url = f.select :namespace_id, namespaces_options(params[:namespace_id] || :current_user, display_path: true), {}, {class: 'select2 js-select-namespace', tabindex: 1} + - else .input-group-addon.static-namespace #{root_url}#{current_user.username}/ @@ -44,15 +45,8 @@ .col-sm-12.import-buttons %div - if github_import_enabled? - - if github_import_configured? - = link_to status_import_github_path, class: 'btn import_github' do - %i.fa.fa-github - GitHub - - else - = link_to '#', class: 'how_to_import_link btn import_github' do - %i.fa.fa-github - GitHub - = render 'github_import_modal' + = link_to new_import_github_path, class: 'btn import_github' do + = icon 'github', text: 'GitHub' %div - if bitbucket_import_enabled? - if bitbucket_import_configured? diff --git a/app/views/projects/notes/_note.html.haml b/app/views/projects/notes/_note.html.haml index a5e163b91e9..af0046886fb 100644 --- a/app/views/projects/notes/_note.html.haml +++ b/app/views/projects/notes/_note.html.haml @@ -17,7 +17,7 @@ %a{ href: "##{dom_id(note)}" } = time_ago_with_tooltip(note.created_at, placement: 'bottom', html_class: 'note-created-ago') .note-actions - - access = note.project.team.human_max_access(note.author.id) + - access = note_max_access_for_user(note) - if access and not note.system %span.note-role.hidden-xs= access - if current_user and not note.system diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index b70693eeb62..28b475d5c2f 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -2,7 +2,7 @@ - page_title "Pipelines" = render "projects/pipelines/head" -%div{ class: (container_class) } +%div{ class: container_class } .top-area %ul.nav-links %li{class: ('active' if @scope.nil?)} diff --git a/app/views/projects/project_members/_shared_group_members.html.haml b/app/views/projects/project_members/_shared_group_members.html.haml index 840b57c2e63..77370c14def 100644 --- a/app/views/projects/project_members/_shared_group_members.html.haml +++ b/app/views/projects/project_members/_shared_group_members.html.haml @@ -1,6 +1,6 @@ - @project_group_links.each do |group_links| - shared_group = group_links.group - - shared_group_members = shared_group.members.non_request + - shared_group_members = shared_group.members - shared_group_users_count = shared_group_members.size .panel.panel-default .panel-heading diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml index a2026c41d01..9031f01b496 100644 --- a/app/views/projects/project_members/index.html.haml +++ b/app/views/projects/project_members/index.html.haml @@ -13,12 +13,12 @@ Users with access to this project are listed below. = render "new_project_member" - = render 'shared/members/requests', membership_source: @project, members: @project_members.request + = render 'shared/members/requests', membership_source: @project, requesters: @requesters - = render 'team', members: @project_members.non_request + = render 'team', members: @project_members - if @group - = render "group_members", members: @group_members.non_request + = render "group_members", members: @group_members - if @project_group_links.any? && @project.allowed_to_share_with_group? = render "shared_group_members" diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index 15f0d85194b..f6e81af2638 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -13,7 +13,7 @@ = render "home_panel" .project-stats.row-content-block.second-block - %div{ class: (container_class) } + %div{ class: container_class } %ul.nav %li = link_to project_files_path(@project) do diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml index 4ca1f58ac5c..c375bb6dd1b 100644 --- a/app/views/projects/tags/index.html.haml +++ b/app/views/projects/tags/index.html.haml @@ -2,7 +2,7 @@ - page_title "Tags" = render "projects/commits/head" -%div{ class: (container_class) } +%div{ class: container_class } .top-area .nav-text Tags give the ability to mark specific points in history as being important @@ -25,7 +25,7 @@ = sort_title_oldest_updated .tags - - unless @tags.empty? + - if @tags.any? %ul.content-list = render partial: 'tag', collection: @tags diff --git a/app/views/projects/tree/show.html.haml b/app/views/projects/tree/show.html.haml index 2abcfcdd7b2..bf5360b4dee 100644 --- a/app/views/projects/tree/show.html.haml +++ b/app/views/projects/tree/show.html.haml @@ -7,7 +7,7 @@ = render 'projects/last_push' = render "projects/commits/head" -%div{ class: (container_class) } +%div{ class: container_class } .tree-controls = render 'projects/find_file_link' - if can? current_user, :download_code, @project diff --git a/app/views/projects/wikis/_new.html.haml b/app/views/projects/wikis/_new.html.haml index 4f8abcdc8e1..c32cb122c26 100644 --- a/app/views/projects/wikis/_new.html.haml +++ b/app/views/projects/wikis/_new.html.haml @@ -1,6 +1,6 @@ - @no_container = true -%div{ class: (container_class) } +%div{ class: container_class } %div#modal-new-wiki.modal .modal-dialog .modal-content diff --git a/app/views/projects/wikis/edit.html.haml b/app/views/projects/wikis/edit.html.haml index 817bf9b3f69..233538bb488 100644 --- a/app/views/projects/wikis/edit.html.haml +++ b/app/views/projects/wikis/edit.html.haml @@ -2,7 +2,7 @@ - page_title "Edit", @page.title.capitalize, "Wiki" = render 'nav' -%div{ class: (container_class) } +%div{ class: container_class } .top-area .nav-text %strong diff --git a/app/views/projects/wikis/git_access.html.haml b/app/views/projects/wikis/git_access.html.haml index 6caf7230f35..b8811a28dd6 100644 --- a/app/views/projects/wikis/git_access.html.haml +++ b/app/views/projects/wikis/git_access.html.haml @@ -2,7 +2,7 @@ - page_title "Git Access", "Wiki" = render 'nav' -%div{ class: (container_class) } +%div{ class: container_class } .sub-header-block %span.oneline Git access for diff --git a/app/views/projects/wikis/history.html.haml b/app/views/projects/wikis/history.html.haml index 630ee35b70b..4c0b14e2c42 100644 --- a/app/views/projects/wikis/history.html.haml +++ b/app/views/projects/wikis/history.html.haml @@ -1,6 +1,6 @@ - page_title "History", @page.title.capitalize, "Wiki" = render 'nav' -%div{ class: (container_class) } +%div{ class: container_class } .top-area .nav-text %strong diff --git a/app/views/projects/wikis/pages.html.haml b/app/views/projects/wikis/pages.html.haml index 81d9f391c1c..9c10acd4cb6 100644 --- a/app/views/projects/wikis/pages.html.haml +++ b/app/views/projects/wikis/pages.html.haml @@ -3,7 +3,7 @@ = render 'nav' -%div{ class: (container_class) } +%div{ class: container_class } %ul.content-list - @wiki_pages.each do |wiki_page| %li diff --git a/app/views/projects/wikis/show.html.haml b/app/views/projects/wikis/show.html.haml index 76f9b1ecd76..5cebb538cf5 100644 --- a/app/views/projects/wikis/show.html.haml +++ b/app/views/projects/wikis/show.html.haml @@ -2,7 +2,7 @@ - page_title @page.title.capitalize, "Wiki" = render 'nav' -%div{ class: (container_class) } +%div{ class: container_class } .top-area .nav-text %strong= @page.title.capitalize diff --git a/app/views/shared/_labels_row.html.haml b/app/views/shared/_labels_row.html.haml index 87028ececd4..5507a05f6c1 100644 --- a/app/views/shared/_labels_row.html.haml +++ b/app/views/shared/_labels_row.html.haml @@ -1,6 +1,6 @@ - labels.each do |label| %span.label-row.btn-group{ role: "group", aria: { label: escape_once(label.name) }, style: "color: #{text_color_for_bg(label.color)}" } - = link_to namespace_project_label_path(@project.namespace, @project, label), + = link_to label_filter_path(@project, label, type: controller.controller_name), class: "btn btn-transparent has-tooltip", style: "background-color: #{label.color};", title: escape_once(label.description), diff --git a/app/views/shared/members/_access_request_buttons.html.haml b/app/views/shared/members/_access_request_buttons.html.haml index 480e8ba6c85..35dcdccc921 100644 --- a/app/views/shared/members/_access_request_buttons.html.haml +++ b/app/views/shared/members/_access_request_buttons.html.haml @@ -1,14 +1,10 @@ -- member = source.members.find_by(user_id: current_user.id) -- group_member = source.group.members.find_by(user_id: current_user.id) if source.respond_to?(:group) && source.group - -- unless group_member - - if member - - if member.request? - = link_to 'Withdraw Access Request', polymorphic_path([:leave, source, :members]), - method: :delete, - data: { confirm: remove_member_message(member) }, - class: 'btn access-request-button hidden-xs' +- if can_see_request_access_button?(source) + - if requester = source.requesters.find_by(user_id: current_user.id) + = link_to 'Withdraw Access Request', polymorphic_path([:leave, source, :members]), + method: :delete, + data: { confirm: remove_member_message(requester) }, + class: 'btn' - else = link_to 'Request Access', polymorphic_path([:request_access, source, :members]), method: :post, - class: 'btn access-request-button hidden-xs' + class: 'btn' diff --git a/app/views/shared/members/_requests.html.haml b/app/views/shared/members/_requests.html.haml index e4bd2bdc265..40b39e850b0 100644 --- a/app/views/shared/members/_requests.html.haml +++ b/app/views/shared/members/_requests.html.haml @@ -1,8 +1,8 @@ -- if members.any? +- if requesters.any? .panel.panel-default .panel-heading %strong= membership_source.name access requests - %span.badge= members.size + %span.badge= requesters.size %ul.content-list - = render partial: 'shared/members/member', collection: members, as: :member + = render partial: 'shared/members/member', collection: requesters, as: :member diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb index f3327ca9e61..09035a7cf2d 100644 --- a/app/workers/post_receive.rb +++ b/app/workers/post_receive.rb @@ -4,10 +4,10 @@ class PostReceive sidekiq_options queue: :post_receive def perform(repo_path, identifier, changes) - if repo_path.start_with?(Gitlab.config.gitlab_shell.repos_path.to_s) - repo_path.gsub!(Gitlab.config.gitlab_shell.repos_path.to_s, "") + if path = Gitlab.config.repositories.storages.find { |p| repo_path.start_with?(p[1].to_s) } + repo_path.gsub!(path[1].to_s, "") else - log("Check gitlab.yml config for correct gitlab_shell.repos_path variable. \"#{Gitlab.config.gitlab_shell.repos_path}\" does not match \"#{repo_path}\"") + log("Check gitlab.yml config for correct repositories.storages values. No repository storage path matches \"#{repo_path}\"") end post_received = Gitlab::GitPostReceive.new(repo_path, identifier, changes) diff --git a/app/workers/repository_fork_worker.rb b/app/workers/repository_fork_worker.rb index d947f105516..f7604e48f83 100644 --- a/app/workers/repository_fork_worker.rb +++ b/app/workers/repository_fork_worker.rb @@ -12,7 +12,7 @@ class RepositoryForkWorker return end - result = gitlab_shell.fork_repository(source_path, target_path) + result = gitlab_shell.fork_repository(project.repository_storage_path, source_path, target_path) unless result logger.error("Unable to fork project #{project_id} for repository #{source_path} -> #{target_path}") project.mark_import_as_failed('The project could not be forked.') diff --git a/config/dependency_decisions.yml b/config/dependency_decisions.yml index 436a2c5e17a..293f2b71d65 100644 --- a/config/dependency_decisions.yml +++ b/config/dependency_decisions.yml @@ -181,3 +181,9 @@ :why: Equivalent to LGPLv2 :versions: [] :when: 2016-06-07 17:14:10.907682000 Z +- - :whitelist + - Artistic 2.0 + - :who: Josh Frye + :why: Disk/mount information display on Admin pages + :versions: [] + :when: 2016-06-29 16:32:45.432113000 Z diff --git a/config/environments/development.rb b/config/environments/development.rb index 8cca0039b4a..45a8c1add3e 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -42,4 +42,7 @@ Rails.application.configure do config.action_mailer.preview_path = 'spec/mailers/previews' config.eager_load = false + + # Do not log asset requests + config.assets.quiet = true end diff --git a/config/gitlab.teatro.yml b/config/gitlab.teatro.yml index 01c8dc5ff98..75b79b837e0 100644 --- a/config/gitlab.teatro.yml +++ b/config/gitlab.teatro.yml @@ -47,11 +47,13 @@ production: &base backup: path: "tmp/backups" # Relative paths are relative to Rails.root (default: tmp/backups/) + repositories: + storages: # REPO PATHS MUST NOT BE A SYMLINK!!! + default: /apps/repositories/ + gitlab_shell: path: /apps/gitlab-shell/ - # REPOS_PATH MUST NOT BE A SYMLINK!!! - repos_path: /apps/repositories/ hooks_path: /apps/gitlab-shell/hooks/ upload_pack: true diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index 75e1a3c1093..325eca72862 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -428,6 +428,13 @@ production: &base satellites: path: /home/git/gitlab-satellites/ + ## Repositories settings + repositories: + # Paths where repositories can be stored. Give the canonicalized absolute pathname. + # NOTE: REPOS PATHS MUST NOT CONTAIN ANY SYMLINK!!! + storages: # You must have at least a `default` storage path. + default: /home/git/repositories/ + ## Backup settings backup: path: "tmp/backups" # Relative paths are relative to Rails.root (default: tmp/backups/) @@ -452,9 +459,6 @@ production: &base ## GitLab Shell settings gitlab_shell: path: /home/git/gitlab-shell/ - - # REPOS_PATH MUST NOT BE A SYMLINK!!! - repos_path: /home/git/repositories/ hooks_path: /home/git/gitlab-shell/hooks/ # File that contains the secret key for verifying access for gitlab-shell. @@ -528,11 +532,13 @@ test: # user: YOUR_USERNAME satellites: path: tmp/tests/gitlab-satellites/ + repositories: + storages: + default: tmp/tests/repositories/ backup: path: tmp/tests/backups gitlab_shell: path: tmp/tests/gitlab-shell/ - repos_path: tmp/tests/repositories/ hooks_path: tmp/tests/gitlab-shell/hooks/ issues_tracker: redmine: diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index c6dc1e4ab38..51d93e8cde0 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -96,7 +96,6 @@ class Settings < Settingslogic end end - # Default settings Settings['ldap'] ||= Settingslogic.new({}) Settings.ldap['enabled'] = false if Settings.ldap['enabled'].nil? @@ -124,7 +123,6 @@ if Settings.ldap['enabled'] || Rails.env.test? end end - Settings['omniauth'] ||= Settingslogic.new({}) Settings.omniauth['enabled'] = false if Settings.omniauth['enabled'].nil? Settings.omniauth['auto_sign_in_with_provider'] = false if Settings.omniauth['auto_sign_in_with_provider'].nil? @@ -218,7 +216,6 @@ Settings.gitlab['restricted_signup_domains'] ||= [] Settings.gitlab['import_sources'] ||= %w[github bitbucket gitlab gitorious google_code fogbugz git gitlab_project] Settings.gitlab['trusted_proxies'] ||= [] - # # CI # @@ -304,7 +301,6 @@ Settings.gitlab_shell['hooks_path'] ||= Settings.gitlab['user_home'] + '/gitla Settings.gitlab_shell['secret_file'] ||= Rails.root.join('.gitlab_shell_secret') Settings.gitlab_shell['receive_pack'] = true if Settings.gitlab_shell['receive_pack'].nil? Settings.gitlab_shell['upload_pack'] = true if Settings.gitlab_shell['upload_pack'].nil? -Settings.gitlab_shell['repos_path'] ||= Settings.gitlab['user_home'] + '/repositories/' Settings.gitlab_shell['ssh_host'] ||= Settings.gitlab.ssh_host Settings.gitlab_shell['ssh_port'] ||= 22 Settings.gitlab_shell['ssh_user'] ||= Settings.gitlab.user @@ -312,6 +308,14 @@ Settings.gitlab_shell['owner_group'] ||= Settings.gitlab.user Settings.gitlab_shell['ssh_path_prefix'] ||= Settings.send(:build_gitlab_shell_ssh_path_prefix) # +# Repositories +# +Settings['repositories'] ||= Settingslogic.new({}) +Settings.repositories['storages'] ||= {} +# Setting gitlab_shell.repos_path is DEPRECATED and WILL BE REMOVED in version 9.0 +Settings.repositories.storages['default'] ||= Settings.gitlab_shell['repos_path'] || Settings.gitlab['user_home'] + '/repositories/' + +# # Backup # Settings['backup'] ||= Settingslogic.new({}) @@ -341,7 +345,6 @@ Settings.git['timeout'] ||= 10 Settings['satellites'] ||= Settingslogic.new({}) Settings.satellites['path'] = File.expand_path(Settings.satellites['path'] || "tmp/repo_satellites/", Rails.root) - # # Extra customization # diff --git a/config/initializers/6_validations.rb b/config/initializers/6_validations.rb new file mode 100644 index 00000000000..3ba9e36c567 --- /dev/null +++ b/config/initializers/6_validations.rb @@ -0,0 +1,24 @@ +def storage_name_valid?(name) + !!(name =~ /\A[a-zA-Z0-9\-_]+\z/) +end + +def find_parent_path(name, path) + Gitlab.config.repositories.storages.detect do |n, p| + name != n && path.chomp('/').start_with?(p.chomp('/')) + end +end + +def error(message) + raise "#{message}. Please fix this in your gitlab.yml before starting GitLab." +end + +error('No repository storage path defined') if Gitlab.config.repositories.storages.empty? + +Gitlab.config.repositories.storages.each do |name, path| + error("\"#{name}\" is not a valid storage name") unless storage_name_valid?(name) + + parent_name, _parent_path = find_parent_path(name, path) + if parent_name + error("#{name} is a nested path of #{parent_name}. Nested paths are not supported for repository storages") + end +end diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 021bdb11251..73977341b73 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -212,7 +212,7 @@ Devise.setup do |config| if Gitlab::LDAP::Config.enabled? Gitlab.config.ldap.servers.values.each do |server| if server['allow_username_or_email_login'] - email_stripping_proc = ->(name) {name.gsub(/@.*\z/,'')} + email_stripping_proc = ->(name) {name.gsub(/@.*\z/, '')} else email_stripping_proc = ->(name) {name} end diff --git a/config/initializers/gitlab_shell_secret_token.rb b/config/initializers/gitlab_shell_secret_token.rb index 751fccead07..7454c33c9dd 100644 --- a/config/initializers/gitlab_shell_secret_token.rb +++ b/config/initializers/gitlab_shell_secret_token.rb @@ -1,19 +1 @@ -# Be sure to restart your server when you modify this file. - -require 'securerandom' - -# Your secret key for verifying the gitlab_shell. - - -secret_file = Gitlab.config.gitlab_shell.secret_file - -unless File.exist? secret_file - # Generate a new token of 16 random hexadecimal characters and store it in secret_file. - token = SecureRandom.hex(16) - File.write(secret_file, token) -end - -link_path = File.join(Gitlab.config.gitlab_shell.path, '.gitlab_shell_secret') -if File.exist?(Gitlab.config.gitlab_shell.path) && !File.exist?(link_path) - FileUtils.symlink(secret_file, link_path) -end +Gitlab::Shell.new.generate_and_link_secret_token diff --git a/config/initializers/metrics.rb b/config/initializers/metrics.rb index 75f89d524e7..44601f2b2bd 100644 --- a/config/initializers/metrics.rb +++ b/config/initializers/metrics.rb @@ -132,6 +132,9 @@ if Gitlab::Metrics.enabled? config.instrument_instance_methods(API::Helpers) config.instrument_instance_methods(RepositoryCheck::SingleRepositoryWorker) + + config.instrument_instance_methods(Rouge::Plugins::Redcarpet) + config.instrument_instance_methods(Rouge::Formatters::HTMLGitlab) end GC::Profiler.enable diff --git a/config/initializers/rack_attack.rb.example b/config/initializers/rack_attack.rb.example index 30d05f16153..69052c029f2 100644 --- a/config/initializers/rack_attack.rb.example +++ b/config/initializers/rack_attack.rb.example @@ -10,7 +10,8 @@ paths_to_be_protected = [ "#{Rails.application.config.relative_url_root}/api/#{API::API.version}/session", "#{Rails.application.config.relative_url_root}/users", "#{Rails.application.config.relative_url_root}/users/confirmation", - "#{Rails.application.config.relative_url_root}/unsubscribes/" + "#{Rails.application.config.relative_url_root}/unsubscribes/", + "#{Rails.application.config.relative_url_root}/import/github/personal_access_token" ] diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb index 7a2b9a7f6c1..593c14a289f 100644 --- a/config/initializers/sidekiq.rb +++ b/config/initializers/sidekiq.rb @@ -13,7 +13,7 @@ Sidekiq.configure_server do |config| # UGLY Hack to get nested hash from settingslogic cron_jobs = JSON.parse(Gitlab.config.cron_jobs.to_json) # UGLY hack: Settingslogic doesn't allow 'class' key - cron_jobs.each { |k,v| cron_jobs[k]['class'] = cron_jobs[k].delete('job_class') } + cron_jobs.each { |k, v| cron_jobs[k]['class'] = cron_jobs[k].delete('job_class') } Sidekiq::Cron::Job.load_from_hash! cron_jobs # Database pool should be at least `sidekiq_concurrency` + 2 diff --git a/config/initializers/trusted_proxies.rb b/config/initializers/trusted_proxies.rb index d256a16d42b..df4a933e22f 100644 --- a/config/initializers/trusted_proxies.rb +++ b/config/initializers/trusted_proxies.rb @@ -1,3 +1,16 @@ +# Override Rack::Request to make use of the same list of trusted_proxies +# as the ActionDispatch::Request object. This is necessary for libraries +# like rack_attack where they don't use ActionDispatch, and we want them +# to block/throttle requests on private networks. +# Rack Attack specific issue: https://github.com/kickstarter/rack-attack/issues/145 +module Rack + class Request + def trusted_proxy?(ip) + Rails.application.config.action_dispatch.trusted_proxies.any? { |proxy| proxy === ip } + end + end +end + Rails.application.config.action_dispatch.trusted_proxies = ( [ '127.0.0.1', '::1' ] + Array(Gitlab.config.gitlab.trusted_proxies) ).map { |proxy| IPAddr.new(proxy) } diff --git a/config/routes.rb b/config/routes.rb index bdfb16a66bf..1572656b8c5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -133,12 +133,12 @@ Rails.application.routes.draw do # resources :notification_settings, only: [:create, :update] - # # Import # namespace :import do resource :github, only: [:create, :new], controller: :github do + post :personal_access_token get :status get :callback get :jobs @@ -465,7 +465,6 @@ Rails.application.routes.draw do resources :namespaces, path: '/', constraints: { id: /[a-zA-Z.0-9_\-]+/ }, only: [] do resources(:projects, constraints: { id: /[a-zA-Z.0-9_\-]+(?<!\.atom)/ }, except: [:new, :create, :index], path: "/") do - member do put :transfer delete :remove_fork @@ -653,7 +652,7 @@ Rails.application.routes.draw do get '/wikis/*id', to: 'wikis#show', as: 'wiki', constraints: WIKI_SLUG_ID delete '/wikis/*id', to: 'wikis#destroy', constraints: WIKI_SLUG_ID put '/wikis/*id', to: 'wikis#update', constraints: WIKI_SLUG_ID - post '/wikis/*id/markdown_preview', to:'wikis#markdown_preview', constraints: WIKI_SLUG_ID, as: 'wiki_markdown_preview' + post '/wikis/*id/markdown_preview', to: 'wikis#markdown_preview', constraints: WIKI_SLUG_ID, as: 'wiki_markdown_preview' end resource :repository, only: [:show, :create] do diff --git a/db/migrate/20160608195742_add_repository_storage_to_projects.rb b/db/migrate/20160608195742_add_repository_storage_to_projects.rb new file mode 100644 index 00000000000..c700d2b569d --- /dev/null +++ b/db/migrate/20160608195742_add_repository_storage_to_projects.rb @@ -0,0 +1,12 @@ +class AddRepositoryStorageToProjects < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + disable_ddl_transaction! + + def up + add_column_with_default(:projects, :repository_storage, :string, default: 'default') + end + + def down + remove_column(:projects, :repository_storage) + end +end diff --git a/db/migrate/20160614182521_add_repository_storage_to_application_settings.rb b/db/migrate/20160614182521_add_repository_storage_to_application_settings.rb new file mode 100644 index 00000000000..6dae91b700b --- /dev/null +++ b/db/migrate/20160614182521_add_repository_storage_to_application_settings.rb @@ -0,0 +1,5 @@ +class AddRepositoryStorageToApplicationSettings < ActiveRecord::Migration + def change + add_column :application_settings, :repository_storage, :string, default: 'default' + end +end diff --git a/db/schema.rb b/db/schema.rb index 7a8377f687c..beb723c3bc5 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -85,6 +85,7 @@ ActiveRecord::Schema.define(version: 20160620115026) do t.boolean "send_user_confirmation_email", default: false t.integer "container_registry_token_expire_delay", default: 5 t.text "after_sign_up_text" + t.string "repository_storage", default: "default" end create_table "audit_events", force: :cascade do |t| @@ -796,38 +797,39 @@ ActiveRecord::Schema.define(version: 20160620115026) do t.datetime "created_at" t.datetime "updated_at" t.integer "creator_id" - t.boolean "issues_enabled", default: true, null: false - t.boolean "merge_requests_enabled", default: true, null: false - t.boolean "wiki_enabled", default: true, null: false + t.boolean "issues_enabled", default: true, null: false + t.boolean "merge_requests_enabled", default: true, null: false + t.boolean "wiki_enabled", default: true, null: false t.integer "namespace_id" - t.boolean "snippets_enabled", default: true, null: false + t.boolean "snippets_enabled", default: true, null: false t.datetime "last_activity_at" t.string "import_url" - t.integer "visibility_level", default: 0, null: false - t.boolean "archived", default: false, null: false + t.integer "visibility_level", default: 0, null: false + t.boolean "archived", default: false, null: false t.string "avatar" t.string "import_status" t.float "repository_size", default: 0.0 - t.integer "star_count", default: 0, null: false + t.integer "star_count", default: 0, null: false t.string "import_type" t.string "import_source" t.integer "commit_count", default: 0 t.text "import_error" t.integer "ci_id" - t.boolean "builds_enabled", default: true, null: false - t.boolean "shared_runners_enabled", default: true, null: false + t.boolean "builds_enabled", default: true, null: false + t.boolean "shared_runners_enabled", default: true, null: false t.string "runners_token" t.string "build_coverage_regex" - t.boolean "build_allow_git_fetch", default: true, null: false - t.integer "build_timeout", default: 3600, null: false + t.boolean "build_allow_git_fetch", default: true, null: false + t.integer "build_timeout", default: 3600, null: false t.boolean "pending_delete", default: false - t.boolean "public_builds", default: true, null: false + t.boolean "public_builds", default: true, null: false t.integer "pushes_since_gc", default: 0 t.boolean "last_repository_check_failed" t.datetime "last_repository_check_at" t.boolean "container_registry_enabled" - t.boolean "only_allow_merge_if_build_succeeds", default: false, null: false + t.boolean "only_allow_merge_if_build_succeeds", default: false, null: false t.boolean "has_external_issue_tracker" + t.string "repository_storage", default: "default", null: false end add_index "projects", ["builds_enabled", "shared_runners_enabled"], name: "index_projects_on_builds_enabled_and_shared_runners_enabled", using: :btree diff --git a/doc/README.md b/doc/README.md index be0d17084c7..b98d6812a81 100644 --- a/doc/README.md +++ b/doc/README.md @@ -34,6 +34,7 @@ - [Operations](operations/README.md) Keeping GitLab up and running. - [Raketasks](raketasks/README.md) Backups, maintenance, automatic webhook setup and the importing of projects. - [Repository checks](administration/repository_checks.md) Periodic Git repository checks. +- [Repository storages](administration/repository_storages.md) Manage the paths used to store repositories. - [Security](security/README.md) Learn what you can do to further secure your GitLab instance. - [System hooks](system_hooks/system_hooks.md) Notifications when users, projects and keys are changed. - [Update](update/README.md) Update guides to upgrade your installation. diff --git a/doc/administration/repository_storages.md b/doc/administration/repository_storages.md new file mode 100644 index 00000000000..81bfe173151 --- /dev/null +++ b/doc/administration/repository_storages.md @@ -0,0 +1,18 @@ +# Repository storages + +GitLab allows you to define repository storage paths to enable distribution of +storage load between several mount points. + +## For installations from source + +Add your repository storage paths in your `gitlab.yml` under repositories -> storages, using key -> value pairs. + +>**Notes:** +- You must have at least one storage path called `default`. +- In order for backups to work correctly the storage path must **not** be a +mount point and the GitLab user should have correct permissions for the parent +directory of the path. + +## For omnibus installations + +Follow the instructions at https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/configuration.md#storing-git-data-in-an-alternative-directory diff --git a/doc/api/README.md b/doc/api/README.md index 288f7f9ee69..d1e6c54c521 100644 --- a/doc/api/README.md +++ b/doc/api/README.md @@ -36,6 +36,7 @@ following locations: - [System Hooks](system_hooks.md) - [Tags](tags.md) - [Users](users.md) +- [Todos](todos.md) ### Internal CI API diff --git a/doc/api/issues.md b/doc/api/issues.md index 708fc691f67..3ced787b23e 100644 --- a/doc/api/issues.md +++ b/doc/api/issues.md @@ -594,12 +594,103 @@ Example response: "id": 11, "state": "active", "avatar_url": "http://www.gravatar.com/avatar/5224fd70153710e92fb8bcf79ac29d67?s=80&d=identicon", - "web_url": "http://lgitlab.example.com/u/orville" + "web_url": "https://gitlab.example.com/u/orville" }, "subscribed": false } ``` +## Create a todo + +Manually creates a todo for the current user on an issue. If the request is +successful, status code `200` together with the created todo is returned. If +there already exists a todo for the user on that issue, status code `304` is +returned. + +``` +POST /projects/:id/issues/:issue_id/todo +``` + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `id` | integer | yes | The ID of a project | +| `issue_id` | integer | yes | The ID of a project's issue | + +```bash +curl -X POST -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/issues/93/todo +``` + +Example response: + +```json +{ + "id": 112, + "project": { + "id": 5, + "name": "Gitlab Ci", + "name_with_namespace": "Gitlab Org / Gitlab Ci", + "path": "gitlab-ci", + "path_with_namespace": "gitlab-org/gitlab-ci" + }, + "author": { + "name": "Administrator", + "username": "root", + "id": 1, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "web_url": "https://gitlab.example.com/u/root" + }, + "action_name": "marked", + "target_type": "Issue", + "target": { + "id": 93, + "iid": 10, + "project_id": 5, + "title": "Vel voluptas atque dicta mollitia adipisci qui at.", + "description": "Tempora laboriosam sint magni sed voluptas similique.", + "state": "closed", + "created_at": "2016-06-17T07:47:39.486Z", + "updated_at": "2016-07-01T11:09:13.998Z", + "labels": [], + "milestone": { + "id": 26, + "iid": 1, + "project_id": 5, + "title": "v0.0", + "description": "Accusantium nostrum rerum quae quia quis nesciunt suscipit id.", + "state": "closed", + "created_at": "2016-06-17T07:47:33.832Z", + "updated_at": "2016-06-17T07:47:33.832Z", + "due_date": null + }, + "assignee": { + "name": "Jarret O'Keefe", + "username": "francisca", + "id": 14, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/a7fa515d53450023c83d62986d0658a8?s=80&d=identicon", + "web_url": "https://gitlab.example.com/u/francisca" + }, + "author": { + "name": "Maxie Medhurst", + "username": "craig_rutherford", + "id": 12, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/a0d477b3ea21970ce6ffcbb817b0b435?s=80&d=identicon", + "web_url": "https://gitlab.example.com/u/craig_rutherford" + }, + "subscribed": true, + "user_notes_count": 7, + "upvotes": 0, + "downvotes": 0 + }, + "target_url": "https://gitlab.example.com/gitlab-org/gitlab-ci/issues/10", + "body": "Vel voluptas atque dicta mollitia adipisci qui at.", + "state": "pending", + "created_at": "2016-07-01T11:09:13.992Z" +} +``` + ## Comments on issues Comments are done via the [notes](notes.md) resource. diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md index 2930f615fc1..f60b0d0ebc6 100644 --- a/doc/api/merge_requests.md +++ b/doc/api/merge_requests.md @@ -776,3 +776,101 @@ Example response: "subscribed": false } ``` + +## Create a todo + +Manually creates a todo for the current user on a merge request. If the +request is successful, status code `200` together with the created todo is +returned. If there already exists a todo for the user on that merge request, +status code `304` is returned. + +``` +POST /projects/:id/merge_requests/:merge_request_id/todo +``` + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `id` | integer | yes | The ID of a project | +| `merge_request_id` | integer | yes | The ID of the merge request | + +```bash +curl -X POST -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/merge_requests/27/todo +``` + +Example response: + +```json +{ + "id": 113, + "project": { + "id": 3, + "name": "Gitlab Ci", + "name_with_namespace": "Gitlab Org / Gitlab Ci", + "path": "gitlab-ci", + "path_with_namespace": "gitlab-org/gitlab-ci" + }, + "author": { + "name": "Administrator", + "username": "root", + "id": 1, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "web_url": "https://gitlab.example.com/u/root" + }, + "action_name": "marked", + "target_type": "MergeRequest", + "target": { + "id": 27, + "iid": 7, + "project_id": 3, + "title": "Et voluptas laudantium minus nihil recusandae ut accusamus earum aut non.", + "description": "Veniam sunt nihil modi earum cumque illum delectus. Nihil ad quis distinctio quia. Autem eligendi at quibusdam repellendus.", + "state": "opened", + "created_at": "2016-06-17T07:48:04.330Z", + "updated_at": "2016-07-01T11:14:15.537Z", + "target_branch": "allow_regex_for_project_skip_ref", + "source_branch": "backup", + "upvotes": 0, + "downvotes": 0, + "author": { + "name": "Jarret O'Keefe", + "username": "francisca", + "id": 14, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/a7fa515d53450023c83d62986d0658a8?s=80&d=identicon", + "web_url": "https://gitlab.example.com/u/francisca" + }, + "assignee": { + "name": "Dr. Gabrielle Strosin", + "username": "barrett.krajcik", + "id": 4, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/733005fcd7e6df12d2d8580171ccb966?s=80&d=identicon", + "web_url": "https://gitlab.example.com/u/barrett.krajcik" + }, + "source_project_id": 3, + "target_project_id": 3, + "labels": [], + "work_in_progress": false, + "milestone": { + "id": 27, + "iid": 2, + "project_id": 3, + "title": "v1.0", + "description": "Quis ea accusantium animi hic fuga assumenda.", + "state": "active", + "created_at": "2016-06-17T07:47:33.840Z", + "updated_at": "2016-06-17T07:47:33.840Z", + "due_date": null + }, + "merge_when_build_succeeds": false, + "merge_status": "unchecked", + "subscribed": true, + "user_notes_count": 7 + }, + "target_url": "https://gitlab.example.com/gitlab-org/gitlab-ci/merge_requests/7", + "body": "Et voluptas laudantium minus nihil recusandae ut accusamus earum aut non.", + "state": "pending", + "created_at": "2016-07-01T11:14:15.530Z" +} +``` diff --git a/doc/api/settings.md b/doc/api/settings.md index b5152311f28..741c5a29581 100644 --- a/doc/api/settings.md +++ b/doc/api/settings.md @@ -38,7 +38,8 @@ Example response: "default_project_visibility" : 0, "gravatar_enabled" : true, "sign_in_text" : null, - "container_registry_token_expire_delay": 5 + "container_registry_token_expire_delay": 5, + "repository_storage": "default" } ``` @@ -66,6 +67,7 @@ PUT /application/settings | `user_oauth_applications` | boolean | no | Allow users to register any application to use GitLab as an OAuth provider | | `after_sign_out_path` | string | no | Where to redirect users after logout | | `container_registry_token_expire_delay` | integer | no | Container Registry token duration in minutes | +| `repository_storage` | string | no | Storage path for new projects. The value should be the name of one of the repository storage paths defined in your gitlab.yml | ```bash curl -X PUT -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/application/settings?signup_enabled=false&default_project_visibility=1 @@ -93,6 +95,7 @@ Example response: "restricted_signup_domains": [], "user_oauth_applications": true, "after_sign_out_path": "", - "container_registry_token_expire_delay": 5 + "container_registry_token_expire_delay": 5, + "repository_storage": "default" } ``` diff --git a/doc/api/todos.md b/doc/api/todos.md new file mode 100644 index 00000000000..29e73664410 --- /dev/null +++ b/doc/api/todos.md @@ -0,0 +1,444 @@ +# Todos + +**Note:** This feature was [introduced][ce-3188] in GitLab 8.10 + +## Get a list of todos + +Returns a list of todos. When no filter is applied, it returns all pending todos +for the current user. Different filters allow the user to precise the request. + +``` +GET /todos +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `action` | string | no | The action to be filtered. Can be `assigned`, `mentioned`, `build_failed`, or `marked`. | +| `author_id` | integer | no | The ID of an author | +| `project_id` | integer | no | The ID of a project | +| `state` | string | no | The state of the todo. Can be either `pending` or `done` | +| `type` | string | no | The type of a todo. Can be either `Issue` or `MergeRequest` | + +```bash +curl -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/todos +``` + +Example Response: + +```json +[ + { + "id": 102, + "project": { + "id": 2, + "name": "Gitlab Ce", + "name_with_namespace": "Gitlab Org / Gitlab Ce", + "path": "gitlab-ce", + "path_with_namespace": "gitlab-org/gitlab-ce" + }, + "author": { + "name": "Administrator", + "username": "root", + "id": 1, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "web_url": "https://gitlab.example.com/u/root" + }, + "action_name": "marked", + "target_type": "MergeRequest", + "target": { + "id": 34, + "iid": 7, + "project_id": 2, + "title": "Dolores in voluptatem tenetur praesentium omnis repellendus voluptatem quaerat.", + "description": "Et ea et omnis illum cupiditate. Dolor aspernatur tenetur ducimus facilis est nihil. Quo esse cupiditate molestiae illo corrupti qui quidem dolor.", + "state": "opened", + "created_at": "2016-06-17T07:49:24.419Z", + "updated_at": "2016-06-17T07:52:43.484Z", + "target_branch": "tutorials_git_tricks", + "source_branch": "DNSBL_docs", + "upvotes": 0, + "downvotes": 0, + "author": { + "name": "Maxie Medhurst", + "username": "craig_rutherford", + "id": 12, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/a0d477b3ea21970ce6ffcbb817b0b435?s=80&d=identicon", + "web_url": "https://gitlab.example.com/u/craig_rutherford" + }, + "assignee": { + "name": "Administrator", + "username": "root", + "id": 1, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "web_url": "https://gitlab.example.com/u/root" + }, + "source_project_id": 2, + "target_project_id": 2, + "labels": [], + "work_in_progress": false, + "milestone": { + "id": 32, + "iid": 2, + "project_id": 2, + "title": "v1.0", + "description": "Assumenda placeat ea voluptatem voluptate qui.", + "state": "active", + "created_at": "2016-06-17T07:47:34.163Z", + "updated_at": "2016-06-17T07:47:34.163Z", + "due_date": null + }, + "merge_when_build_succeeds": false, + "merge_status": "cannot_be_merged", + "subscribed": true, + "user_notes_count": 7 + }, + "target_url": "https://gitlab.example.com/gitlab-org/gitlab-ce/merge_requests/7", + "body": "Dolores in voluptatem tenetur praesentium omnis repellendus voluptatem quaerat.", + "state": "pending", + "created_at": "2016-06-17T07:52:35.225Z" + }, + { + "id": 98, + "project": { + "id": 2, + "name": "Gitlab Ce", + "name_with_namespace": "Gitlab Org / Gitlab Ce", + "path": "gitlab-ce", + "path_with_namespace": "gitlab-org/gitlab-ce" + }, + "author": { + "name": "Maxie Medhurst", + "username": "craig_rutherford", + "id": 12, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/a0d477b3ea21970ce6ffcbb817b0b435?s=80&d=identicon", + "web_url": "https://gitlab.example.com/u/craig_rutherford" + }, + "action_name": "assigned", + "target_type": "MergeRequest", + "target": { + "id": 34, + "iid": 7, + "project_id": 2, + "title": "Dolores in voluptatem tenetur praesentium omnis repellendus voluptatem quaerat.", + "description": "Et ea et omnis illum cupiditate. Dolor aspernatur tenetur ducimus facilis est nihil. Quo esse cupiditate molestiae illo corrupti qui quidem dolor.", + "state": "opened", + "created_at": "2016-06-17T07:49:24.419Z", + "updated_at": "2016-06-17T07:52:43.484Z", + "target_branch": "tutorials_git_tricks", + "source_branch": "DNSBL_docs", + "upvotes": 0, + "downvotes": 0, + "author": { + "name": "Maxie Medhurst", + "username": "craig_rutherford", + "id": 12, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/a0d477b3ea21970ce6ffcbb817b0b435?s=80&d=identicon", + "web_url": "https://gitlab.example.com/u/craig_rutherford" + }, + "assignee": { + "name": "Administrator", + "username": "root", + "id": 1, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "web_url": "https://gitlab.example.com/u/root" + }, + "source_project_id": 2, + "target_project_id": 2, + "labels": [], + "work_in_progress": false, + "milestone": { + "id": 32, + "iid": 2, + "project_id": 2, + "title": "v1.0", + "description": "Assumenda placeat ea voluptatem voluptate qui.", + "state": "active", + "created_at": "2016-06-17T07:47:34.163Z", + "updated_at": "2016-06-17T07:47:34.163Z", + "due_date": null + }, + "merge_when_build_succeeds": false, + "merge_status": "cannot_be_merged", + "subscribed": true, + "user_notes_count": 7 + }, + "target_url": "https://gitlab.example.com/gitlab-org/gitlab-ce/merge_requests/7", + "body": "Dolores in voluptatem tenetur praesentium omnis repellendus voluptatem quaerat.", + "state": "pending", + "created_at": "2016-06-17T07:49:24.624Z" + } +] +``` + +## Mark a todo as done + +Marks a single pending todo given by its ID for the current user as done. The +todo marked as done is returned in the response. + +``` +DELETE /todos/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `id` | integer | yes | The ID of a todo | + +```bash +curl -X DELETE -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/todos/130 +``` + +Example Response: + +```json +{ + "id": 102, + "project": { + "id": 2, + "name": "Gitlab Ce", + "name_with_namespace": "Gitlab Org / Gitlab Ce", + "path": "gitlab-ce", + "path_with_namespace": "gitlab-org/gitlab-ce" + }, + "author": { + "name": "Administrator", + "username": "root", + "id": 1, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "web_url": "https://gitlab.example.com/u/root" + }, + "action_name": "marked", + "target_type": "MergeRequest", + "target": { + "id": 34, + "iid": 7, + "project_id": 2, + "title": "Dolores in voluptatem tenetur praesentium omnis repellendus voluptatem quaerat.", + "description": "Et ea et omnis illum cupiditate. Dolor aspernatur tenetur ducimus facilis est nihil. Quo esse cupiditate molestiae illo corrupti qui quidem dolor.", + "state": "opened", + "created_at": "2016-06-17T07:49:24.419Z", + "updated_at": "2016-06-17T07:52:43.484Z", + "target_branch": "tutorials_git_tricks", + "source_branch": "DNSBL_docs", + "upvotes": 0, + "downvotes": 0, + "author": { + "name": "Maxie Medhurst", + "username": "craig_rutherford", + "id": 12, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/a0d477b3ea21970ce6ffcbb817b0b435?s=80&d=identicon", + "web_url": "https://gitlab.example.com/u/craig_rutherford" + }, + "assignee": { + "name": "Administrator", + "username": "root", + "id": 1, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "web_url": "https://gitlab.example.com/u/root" + }, + "source_project_id": 2, + "target_project_id": 2, + "labels": [], + "work_in_progress": false, + "milestone": { + "id": 32, + "iid": 2, + "project_id": 2, + "title": "v1.0", + "description": "Assumenda placeat ea voluptatem voluptate qui.", + "state": "active", + "created_at": "2016-06-17T07:47:34.163Z", + "updated_at": "2016-06-17T07:47:34.163Z", + "due_date": null + }, + "merge_when_build_succeeds": false, + "merge_status": "cannot_be_merged", + "subscribed": true, + "user_notes_count": 7 + }, + "target_url": "https://gitlab.example.com/gitlab-org/gitlab-ce/merge_requests/7", + "body": "Dolores in voluptatem tenetur praesentium omnis repellendus voluptatem quaerat.", + "state": "done", + "created_at": "2016-06-17T07:52:35.225Z" +} +``` + +## Mark all todos as done + +Marks all pending todos for the current user as done. All todos marked as done +are returned in the response. + +``` +DELETE /todos +``` + +```bash +curl -X DELETE -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/todos +``` + +Example Response: + +```json +[ + { + "id": 102, + "project": { + "id": 2, + "name": "Gitlab Ce", + "name_with_namespace": "Gitlab Org / Gitlab Ce", + "path": "gitlab-ce", + "path_with_namespace": "gitlab-org/gitlab-ce" + }, + "author": { + "name": "Administrator", + "username": "root", + "id": 1, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "web_url": "https://gitlab.example.com/u/root" + }, + "action_name": "marked", + "target_type": "MergeRequest", + "target": { + "id": 34, + "iid": 7, + "project_id": 2, + "title": "Dolores in voluptatem tenetur praesentium omnis repellendus voluptatem quaerat.", + "description": "Et ea et omnis illum cupiditate. Dolor aspernatur tenetur ducimus facilis est nihil. Quo esse cupiditate molestiae illo corrupti qui quidem dolor.", + "state": "opened", + "created_at": "2016-06-17T07:49:24.419Z", + "updated_at": "2016-06-17T07:52:43.484Z", + "target_branch": "tutorials_git_tricks", + "source_branch": "DNSBL_docs", + "upvotes": 0, + "downvotes": 0, + "author": { + "name": "Maxie Medhurst", + "username": "craig_rutherford", + "id": 12, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/a0d477b3ea21970ce6ffcbb817b0b435?s=80&d=identicon", + "web_url": "https://gitlab.example.com/u/craig_rutherford" + }, + "assignee": { + "name": "Administrator", + "username": "root", + "id": 1, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "web_url": "https://gitlab.example.com/u/root" + }, + "source_project_id": 2, + "target_project_id": 2, + "labels": [], + "work_in_progress": false, + "milestone": { + "id": 32, + "iid": 2, + "project_id": 2, + "title": "v1.0", + "description": "Assumenda placeat ea voluptatem voluptate qui.", + "state": "active", + "created_at": "2016-06-17T07:47:34.163Z", + "updated_at": "2016-06-17T07:47:34.163Z", + "due_date": null + }, + "merge_when_build_succeeds": false, + "merge_status": "cannot_be_merged", + "subscribed": true, + "user_notes_count": 7 + }, + "target_url": "https://gitlab.example.com/gitlab-org/gitlab-ce/merge_requests/7", + "body": "Dolores in voluptatem tenetur praesentium omnis repellendus voluptatem quaerat.", + "state": "done", + "created_at": "2016-06-17T07:52:35.225Z" + }, + { + "id": 98, + "project": { + "id": 2, + "name": "Gitlab Ce", + "name_with_namespace": "Gitlab Org / Gitlab Ce", + "path": "gitlab-ce", + "path_with_namespace": "gitlab-org/gitlab-ce" + }, + "author": { + "name": "Maxie Medhurst", + "username": "craig_rutherford", + "id": 12, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/a0d477b3ea21970ce6ffcbb817b0b435?s=80&d=identicon", + "web_url": "https://gitlab.example.com/u/craig_rutherford" + }, + "action_name": "assigned", + "target_type": "MergeRequest", + "target": { + "id": 34, + "iid": 7, + "project_id": 2, + "title": "Dolores in voluptatem tenetur praesentium omnis repellendus voluptatem quaerat.", + "description": "Et ea et omnis illum cupiditate. Dolor aspernatur tenetur ducimus facilis est nihil. Quo esse cupiditate molestiae illo corrupti qui quidem dolor.", + "state": "opened", + "created_at": "2016-06-17T07:49:24.419Z", + "updated_at": "2016-06-17T07:52:43.484Z", + "target_branch": "tutorials_git_tricks", + "source_branch": "DNSBL_docs", + "upvotes": 0, + "downvotes": 0, + "author": { + "name": "Maxie Medhurst", + "username": "craig_rutherford", + "id": 12, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/a0d477b3ea21970ce6ffcbb817b0b435?s=80&d=identicon", + "web_url": "https://gitlab.example.com/u/craig_rutherford" + }, + "assignee": { + "name": "Administrator", + "username": "root", + "id": 1, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "web_url": "https://gitlab.example.com/u/root" + }, + "source_project_id": 2, + "target_project_id": 2, + "labels": [], + "work_in_progress": false, + "milestone": { + "id": 32, + "iid": 2, + "project_id": 2, + "title": "v1.0", + "description": "Assumenda placeat ea voluptatem voluptate qui.", + "state": "active", + "created_at": "2016-06-17T07:47:34.163Z", + "updated_at": "2016-06-17T07:47:34.163Z", + "due_date": null + }, + "merge_when_build_succeeds": false, + "merge_status": "cannot_be_merged", + "subscribed": true, + "user_notes_count": 7 + }, + "target_url": "https://gitlab.example.com/gitlab-org/gitlab-ce/merge_requests/7", + "body": "Dolores in voluptatem tenetur praesentium omnis repellendus voluptatem quaerat.", + "state": "done", + "created_at": "2016-06-17T07:49:24.624Z" + }, +] +``` + +[ce-3188]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3188 diff --git a/doc/ci/examples/README.md b/doc/ci/examples/README.md index 27bc21c2922..c134106bfd0 100644 --- a/doc/ci/examples/README.md +++ b/doc/ci/examples/README.md @@ -14,3 +14,4 @@ - [Blog post about using GitLab CI for iOS projects](https://about.gitlab.com/2016/03/10/setting-up-gitlab-ci-for-ios-projects/) - [Repo's with examples for various languages](https://gitlab.com/groups/gitlab-examples) - [The .gitlab-ci.yml file for GitLab itself](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab-ci.yml) +- [A collection of useful .gitlab-ci.yml templates](https://gitlab.com/gitlab-org/gitlab-ci-yml) diff --git a/doc/raketasks/import.md b/doc/raketasks/import.md index 8a38937062e..2b305cb5c99 100644 --- a/doc/raketasks/import.md +++ b/doc/raketasks/import.md @@ -14,7 +14,8 @@ - For omnibus-gitlab, it is located at: `/var/opt/gitlab/git-data/repositories` by default, unless you changed it in the `/etc/gitlab/gitlab.rb` file. - For installations from source, it is usually located at: `/home/git/repositories` or you can see where -your repositories are located by looking at `config/gitlab.yml` under the `gitlab_shell => repos_path` entry. +your repositories are located by looking at `config/gitlab.yml` under the `repositories => storages` entries +(you'll usually use the `default` storage path to start). New folder needs to have git user ownership and read/write/execute access for git user and its group: diff --git a/doc/workflow/add-user/img/access_requests_management.png b/doc/workflow/add-user/img/access_requests_management.png Binary files differindex e9641cb4f85..5c9b510ba9d 100644 --- a/doc/workflow/add-user/img/access_requests_management.png +++ b/doc/workflow/add-user/img/access_requests_management.png diff --git a/doc/workflow/groups.md b/doc/workflow/groups.md index 1a316e80976..9b50286b179 100644 --- a/doc/workflow/groups.md +++ b/doc/workflow/groups.md @@ -51,7 +51,7 @@ If necessary, you can increase the access level of an individual user for a spec ![Barry effectively has 'Master' access to GitLab CI now](groups/override_access_level.png) -## Request access to a group +## Requesting access to a group As a user, you can request to be a member of a group. Go to the group you'd like to be a member of, and click the **Request Access** button on the right diff --git a/doc/workflow/groups/access_requests_management.png b/doc/workflow/groups/access_requests_management.png Binary files differindex ffede8e9bd6..5202434f00f 100644 --- a/doc/workflow/groups/access_requests_management.png +++ b/doc/workflow/groups/access_requests_management.png diff --git a/doc/workflow/groups/request_access_button.png b/doc/workflow/groups/request_access_button.png Binary files differindex ff0ac8747a7..0eec5cb937d 100644 --- a/doc/workflow/groups/request_access_button.png +++ b/doc/workflow/groups/request_access_button.png diff --git a/doc/workflow/groups/withdraw_access_request_button.png b/doc/workflow/groups/withdraw_access_request_button.png Binary files differindex 99d7a326ed8..b7de830a780 100644 --- a/doc/workflow/groups/withdraw_access_request_button.png +++ b/doc/workflow/groups/withdraw_access_request_button.png diff --git a/doc/workflow/importing/import_projects_from_github.md b/doc/workflow/importing/import_projects_from_github.md index a7dfac2c120..a2b2a4b88f9 100644 --- a/doc/workflow/importing/import_projects_from_github.md +++ b/doc/workflow/importing/import_projects_from_github.md @@ -1,8 +1,10 @@ # Import your project from GitHub to GitLab
>**Note:**
-In order to enable the GitHub import setting, you should first
-enable the [GitHub integration][gh-import] in your GitLab instance.
+In order to enable the GitHub import setting, you may also want to
+enable the [GitHub integration][gh-import] in your GitLab instance. This
+configuration is optional, you will be able import your GitHub repositories
+with a Personal Access Token.
At its current state, GitHub importer can import:
@@ -20,9 +22,15 @@ It is not yet possible to import your cross-repository pull requests (those from forks). We are working on improving this in the near future.
The importer page is visible when you [create a new project][new-project].
-Click on the **GitHub** link and you will be redirected to GitHub for
-permission to access your projects. After accepting, you'll be automatically
-redirected to the importer.
+Click on the **GitHub** link and, if you are logged in via the GitHub
+integration, you will be redirected to GitHub for permission to access your
+projects. After accepting, you'll be automatically redirected to the importer.
+
+If you are not using the GitHub integration, you can still perform a one-off
+authorization with GitHub to access your projects.
+
+Alternatively, you can also enter a GitHub Personal Access Token. Once you enter
+your token, you'll be taken to the importer.
![New project page on GitLab](img/import_projects_from_github_new_project_page.png)
diff --git a/features/dashboard/new_project.feature b/features/dashboard/new_project.feature index 56b4a639c01..8ddafb6a7ac 100644 --- a/features/dashboard/new_project.feature +++ b/features/dashboard/new_project.feature @@ -21,7 +21,7 @@ Background: Scenario: I should see instructions on how to import from GitHub Given I see "New Project" page When I click on "Import project from GitHub" - Then I see instructions on how to import from GitHub + Then I am redirected to the GitHub import page @javascript Scenario: I should see Google Code import page diff --git a/features/steps/dashboard/new_project.rb b/features/steps/dashboard/new_project.rb index 31f8924c38c..727a6a71373 100644 --- a/features/steps/dashboard/new_project.rb +++ b/features/steps/dashboard/new_project.rb @@ -28,14 +28,8 @@ class Spinach::Features::NewProject < Spinach::FeatureSteps first('.import_github').click end - step 'I see instructions on how to import from GitHub' do - github_modal = first('.modal-body') - expect(github_modal).to be_visible - expect(github_modal).to have_content "To enable importing projects from GitHub" - - page.all('.modal-body').each do |element| - expect(element).not_to be_visible unless element == github_modal - end + step 'I am redirected to the GitHub import page' do + expect(current_path).to eq new_import_github_path end step 'I click on "Repo by URL"' do @@ -55,5 +49,4 @@ class Spinach::Features::NewProject < Spinach::FeatureSteps step 'I redirected to Google Code import page' do expect(current_path).to eq new_import_google_code_path end - end diff --git a/features/steps/explore/projects.rb b/features/steps/explore/projects.rb index cb6fa8a47da..2b4a5ab0864 100644 --- a/features/steps/explore/projects.rb +++ b/features/steps/explore/projects.rb @@ -69,7 +69,6 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps visit namespace_project_issues_path(public_project.namespace, public_project) end - step 'I should see list of issues for "Community" project' do expect(page).to have_content "Bug" expect(page).to have_content public_project.name @@ -88,7 +87,6 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps visit namespace_project_issues_path(internal_project.namespace, internal_project) end - step 'I should see list of issues for "Internal" project' do expect(page).to have_content "Internal Bug" expect(page).to have_content internal_project.name @@ -137,7 +135,6 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps @public_project ||= Project.find_by!(name: 'Community') end - def internal_merge_request @internal_merge_request ||= MergeRequest.find_by!(title: 'Feature implemented') end diff --git a/features/steps/groups.rb b/features/steps/groups.rb index 483370f41c6..4fa7d7c6567 100644 --- a/features/steps/groups.rb +++ b/features/steps/groups.rb @@ -93,7 +93,7 @@ class Spinach::Features::Groups < Spinach::FeatureSteps step 'I should see new group "Owned" avatar' do expect(owned_group.avatar).to be_instance_of AvatarUploader - expect(owned_group.avatar.url).to eq "/uploads/group/avatar/#{Group.find_by(name:"Owned").id}/banana_sample.gif" + expect(owned_group.avatar.url).to eq "/uploads/group/avatar/#{Group.find_by(name: "Owned").id}/banana_sample.gif" end step 'I should see the "Remove avatar" button' do diff --git a/features/steps/project/archived.rb b/features/steps/project/archived.rb index db1387763d5..b6f1d417e21 100644 --- a/features/steps/project/archived.rb +++ b/features/steps/project/archived.rb @@ -33,5 +33,4 @@ class Spinach::Features::ProjectArchived < Spinach::FeatureSteps When 'I set project unarchived' do click_link "Unarchive" end - end diff --git a/features/steps/project/forked_merge_requests.rb b/features/steps/project/forked_merge_requests.rb index 0ead83d6937..6b56a77b832 100644 --- a/features/steps/project/forked_merge_requests.rb +++ b/features/steps/project/forked_merge_requests.rb @@ -153,6 +153,6 @@ class Spinach::Features::ProjectForkedMergeRequests < Spinach::FeatureSteps # Verify a link is generated against the correct project def verify_commit_link(container_div, container_project) # This should force a wait for the javascript to execute - expect(find(:div,container_div).find(".commit_short_id")['href']).to have_content "#{container_project.path_with_namespace}/commit" + expect(find(:div, container_div).find(".commit_short_id")['href']).to have_content "#{container_project.path_with_namespace}/commit" end end diff --git a/features/steps/project/issues/issues.rb b/features/steps/project/issues/issues.rb index 439363e6f14..35f166c7c08 100644 --- a/features/steps/project/issues/issues.rb +++ b/features/steps/project/issues/issues.rb @@ -124,14 +124,12 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps end step 'project "Shop" has milestone "v2.2"' do - milestone = create(:milestone, title: "v2.2", project: project) 3.times { create(:issue, project: project, milestone: milestone) } end step 'project "Shop" has milestone "v3.0"' do - milestone = create(:milestone, title: "v3.0", project: project) 3.times { create(:issue, project: project, milestone: milestone) } @@ -147,7 +145,6 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps end When 'I select first assignee from "Shop" project' do - first_assignee = project.users.first select first_assignee.name, from: "assignee_id" end @@ -160,7 +157,6 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps end step 'project "Shop" have "Release 0.4" open issue' do - create(:issue, title: "Release 0.4", project: project, @@ -360,5 +356,4 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps def filter_issue(text) fill_in 'issue_search', with: text end - end diff --git a/features/steps/project/project_find_file.rb b/features/steps/project/project_find_file.rb index 90771847909..b8da5e6435d 100644 --- a/features/steps/project/project_find_file.rb +++ b/features/steps/project/project_find_file.rb @@ -66,7 +66,6 @@ class Spinach::Features::ProjectFindFile < Spinach::FeatureSteps expect(page).not_to have_content(".gitignore") end - def find_file(text) fill_in 'file_find', with: text end diff --git a/features/steps/shared/issuable.rb b/features/steps/shared/issuable.rb index c6572cf386e..b5fd24d246f 100644 --- a/features/steps/shared/issuable.rb +++ b/features/steps/shared/issuable.rb @@ -189,5 +189,4 @@ module SharedIssuable expect(page).to have_content content end end - end diff --git a/features/steps/snippet_search.rb b/features/steps/snippet_search.rb index cf999879579..32e29ffad1e 100644 --- a/features/steps/snippet_search.rb +++ b/features/steps/snippet_search.rb @@ -52,5 +52,4 @@ class Spinach::Features::SnippetSearch < Spinach::FeatureSteps step 'I should not see "Personal snippet private" in results' do expect(page).not_to have_content 'Personal snippet private' end - end diff --git a/features/support/env.rb b/features/support/env.rb index edc08cf0986..ab3f0ca7aeb 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -2,11 +2,6 @@ if ENV['SIMPLECOV'] require 'simplecov' end -if ENV['COVERALLS'] - require 'coveralls' - Coveralls.wear_merged! -end - ENV['RAILS_ENV'] = 'test' require './config/environment' require 'rspec/expectations' diff --git a/lib/api/api.rb b/lib/api/api.rb index c3fff8b2f8f..3d7d67510a8 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -58,6 +58,7 @@ module API mount ::API::SystemHooks mount ::API::Tags mount ::API::Templates + mount ::API::Todos mount ::API::Triggers mount ::API::Users mount ::API::Variables diff --git a/lib/api/award_emoji.rb b/lib/api/award_emoji.rb index 985590312e3..c4fa1838b5a 100644 --- a/lib/api/award_emoji.rb +++ b/lib/api/award_emoji.rb @@ -11,7 +11,6 @@ module API [ ":id/#{awardable_string}/:#{awardable_id_string}/award_emoji", ":id/#{awardable_string}/:#{awardable_id_string}/notes/:note_id/award_emoji" ].each do |endpoint| - # Get a list of project +awardable+ award emoji # # Parameters: diff --git a/lib/api/branches.rb b/lib/api/branches.rb index 231840148d9..d467eb9d474 100644 --- a/lib/api/branches.rb +++ b/lib/api/branches.rb @@ -25,7 +25,7 @@ module API # branch (required) - The name of the branch # Example Request: # GET /projects/:id/repository/branches/:branch - get ':id/repository/branches/:branch', requirements: { branch: /.*/ } do + get ':id/repository/branches/:branch', requirements: { branch: /.+/ } do @branch = user_project.repository.branches.find { |item| item.name == params[:branch] } not_found!("Branch") unless @branch present @branch, with: Entities::RepoObject, project: user_project @@ -39,8 +39,7 @@ module API # Example Request: # PUT /projects/:id/repository/branches/:branch/protect put ':id/repository/branches/:branch/protect', - requirements: { branch: /.*/ } do - + requirements: { branch: /.+/ } do authorize_admin_project @branch = user_project.repository.find_branch(params[:branch]) @@ -59,8 +58,7 @@ module API # Example Request: # PUT /projects/:id/repository/branches/:branch/unprotect put ':id/repository/branches/:branch/unprotect', - requirements: { branch: /.*/ } do - + requirements: { branch: /.+/ } do authorize_admin_project @branch = user_project.repository.find_branch(params[:branch]) @@ -101,7 +99,7 @@ module API # Example Request: # DELETE /projects/:id/repository/branches/:branch delete ":id/repository/branches/:branch", - requirements: { branch: /.*/ } do + requirements: { branch: /.+/ } do authorize_push_project result = DeleteBranchService.new(user_project, current_user). execute(params[:branch]) diff --git a/lib/api/builds.rb b/lib/api/builds.rb index 086d8511e8f..d36047acd1f 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -13,7 +13,6 @@ module API # Example Request: # GET /projects/:id/builds get ':id/builds' do - builds = user_project.builds.order('id DESC') builds = filter_builds(builds, params[:scope]) diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 5a23a18fe9c..8cc4368b5c2 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -272,6 +272,31 @@ module API expose :id, :project_id, :group_id, :group_access end + class Todo < Grape::Entity + expose :id + expose :project, using: Entities::BasicProjectDetails + expose :author, using: Entities::UserBasic + expose :action_name + expose :target_type + + expose :target do |todo, options| + Entities.const_get(todo.target_type).represent(todo.target, options) + end + + expose :target_url do |todo, options| + target_type = todo.target_type.underscore + target_url = "namespace_project_#{target_type}_url" + target_anchor = "note_#{todo.note_id}" if todo.note_id? + + Gitlab::Application.routes.url_helpers.public_send(target_url, + todo.project.namespace, todo.project, todo.target, anchor: target_anchor) + end + + expose :body + expose :state + expose :created_at + end + class Namespace < Grape::Entity expose :id, :path, :kind end @@ -376,6 +401,7 @@ module API expose :user_oauth_applications expose :after_sign_out_path expose :container_registry_token_expire_delay + expose :repository_storage end class Release < Grape::Entity diff --git a/lib/api/group_members.rb b/lib/api/group_members.rb index ab9b7c602b5..dbe5bb08d3f 100644 --- a/lib/api/group_members.rb +++ b/lib/api/group_members.rb @@ -77,7 +77,7 @@ module API member = group.group_members.find_by(user_id: params[:user_id]) if member.nil? - render_api_error!("404 Not Found - user_id:#{params[:user_id]} not a member of group #{group.name}",404) + render_api_error!("404 Not Found - user_id:#{params[:user_id]} not a member of group #{group.name}", 404) else member.destroy end diff --git a/lib/api/internal.rb b/lib/api/internal.rb index 1d361569d59..b32503e8516 100644 --- a/lib/api/internal.rb +++ b/lib/api/internal.rb @@ -20,6 +20,20 @@ module API @wiki ||= params[:project].end_with?('.wiki') && !Project.find_with_namespace(params[:project]) end + + def project + @project ||= begin + project_path = params[:project] + + # Check for *.wiki repositories. + # Strip out the .wiki from the pathname before finding the + # project. This applies the correct project permissions to + # the wiki repository as well. + project_path.chomp!('.wiki') if wiki? + + Project.find_with_namespace(project_path) + end + end end post "/allowed" do @@ -32,16 +46,6 @@ module API User.find_by(id: params[:user_id]) end - project_path = params[:project] - - # Check for *.wiki repositories. - # Strip out the .wiki from the pathname before finding the - # project. This applies the correct project permissions to - # the wiki repository as well. - project_path.chomp!('.wiki') if wiki? - - project = Project.find_with_namespace(project_path) - access = if wiki? Gitlab::GitAccessWiki.new(actor, project) @@ -49,7 +53,17 @@ module API Gitlab::GitAccess.new(actor, project) end - access.check(params[:action], params[:changes]) + access_status = access.check(params[:action], params[:changes]) + + response = { status: access_status.status, message: access_status.message } + + if access_status.status + # Return the repository full path so that gitlab-shell has it when + # handling ssh commands + response[:repository_path] = project.repository.path_to_repo + end + + response end # diff --git a/lib/api/milestones.rb b/lib/api/milestones.rb index 132043cf3f7..7a0cb7c99f3 100644 --- a/lib/api/milestones.rb +++ b/lib/api/milestones.rb @@ -115,7 +115,6 @@ module API issues = IssuesFinder.new(current_user, finder_params).execute present paginate(issues), with: Entities::Issue, current_user: current_user end - end end end diff --git a/lib/api/project_hooks.rb b/lib/api/project_hooks.rb index ccca65cbe1c..6bb70bc8bc3 100644 --- a/lib/api/project_hooks.rb +++ b/lib/api/project_hooks.rb @@ -28,7 +28,6 @@ module API present @hook, with: Entities::ProjectHook end - # Add hook to project # # Parameters: diff --git a/lib/api/project_members.rb b/lib/api/project_members.rb index b703da0557a..6a0b3e7d134 100644 --- a/lib/api/project_members.rb +++ b/lib/api/project_members.rb @@ -4,7 +4,6 @@ module API before { authenticate! } resource :projects do - # Get a project team members # # Parameters: diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 5a22d14988f..0cc1edd65c8 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -341,7 +341,6 @@ module API else not_found!("Source Project") end - end # Remove a forked_from relationship @@ -418,7 +417,6 @@ module API present paginate(projects), with: Entities::Project end - # Get a users list # # Example Request: diff --git a/lib/api/services.rb b/lib/api/services.rb index 203f04a6259..fc8598daa32 100644 --- a/lib/api/services.rb +++ b/lib/api/services.rb @@ -4,7 +4,6 @@ module API before { authenticate! } before { authorize_admin_project } - resource :projects do # Set <service_slug> service for project # diff --git a/lib/api/tags.rb b/lib/api/tags.rb index 3e1ed3fe5c7..7b675e05fbb 100644 --- a/lib/api/tags.rb +++ b/lib/api/tags.rb @@ -61,7 +61,7 @@ module API # tag_name (required) - The name of the tag # Example Request: # DELETE /projects/:id/repository/tags/:tag - delete ":id/repository/tags/:tag_name", requirements: { tag_name: /.*/ } do + delete ":id/repository/tags/:tag_name", requirements: { tag_name: /.+/ } do authorize_push_project result = DeleteTagService.new(user_project, current_user). execute(params[:tag_name]) @@ -83,7 +83,7 @@ module API # description (required) - Release notes with markdown support # Example Request: # POST /projects/:id/repository/tags/:tag_name/release - post ':id/repository/tags/:tag_name/release', requirements: { tag_name: /.*/ } do + post ':id/repository/tags/:tag_name/release', requirements: { tag_name: /.+/ } do authorize_push_project required_attributes! [:description] result = CreateReleaseService.new(user_project, current_user). @@ -104,7 +104,7 @@ module API # description (required) - Release notes with markdown support # Example Request: # PUT /projects/:id/repository/tags/:tag_name/release - put ':id/repository/tags/:tag_name/release', requirements: { tag_name: /.*/ } do + put ':id/repository/tags/:tag_name/release', requirements: { tag_name: /.+/ } do authorize_push_project required_attributes! [:description] result = UpdateReleaseService.new(user_project, current_user). diff --git a/lib/api/todos.rb b/lib/api/todos.rb new file mode 100644 index 00000000000..2a6bfa98ca4 --- /dev/null +++ b/lib/api/todos.rb @@ -0,0 +1,82 @@ +module API + # Todos API + class Todos < Grape::API + before { authenticate! } + + ISSUABLE_TYPES = { + 'merge_requests' => ->(id) { user_project.merge_requests.find(id) }, + 'issues' => ->(id) { find_project_issue(id) } + } + + resource :projects do + ISSUABLE_TYPES.each do |type, finder| + type_id_str = "#{type.singularize}_id".to_sym + + # Create a todo on an issuable + # + # Parameters: + # id (required) - The ID of a project + # issuable_id (required) - The ID of an issuable + # Example Request: + # POST /projects/:id/issues/:issuable_id/todo + # POST /projects/:id/merge_requests/:issuable_id/todo + post ":id/#{type}/:#{type_id_str}/todo" do + issuable = instance_exec(params[type_id_str], &finder) + todo = TodoService.new.mark_todo(issuable, current_user).first + + if todo + present todo, with: Entities::Todo, current_user: current_user + else + not_modified! + end + end + end + end + + resource :todos do + helpers do + def find_todos + TodosFinder.new(current_user, params).execute + end + end + + # Get a todo list + # + # Example Request: + # GET /todos + # + get do + todos = find_todos + + present paginate(todos), with: Entities::Todo, current_user: current_user + end + + # Mark a todo as done + # + # Parameters: + # id: (required) - The ID of the todo being marked as done + # + # Example Request: + # DELETE /todos/:id + # + delete ':id' do + todo = current_user.todos.find(params[:id]) + todo.done + + present todo, with: Entities::Todo, current_user: current_user + end + + # Mark all todos as done + # + # Example Request: + # DELETE /todos + # + delete do + todos = find_todos + todos.each(&:done) + + present paginate(Kaminari.paginate_array(todos)), with: Entities::Todo, current_user: current_user + end + end + end +end diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb index 7b91215d50b..b9773f98d75 100644 --- a/lib/backup/repository.rb +++ b/lib/backup/repository.rb @@ -2,8 +2,6 @@ require 'yaml' module Backup class Repository - attr_reader :repos_path - def dump prepare @@ -50,10 +48,12 @@ module Backup end def restore - if File.exists?(repos_path) + Gitlab.config.repositories.storages.each do |name, path| + next unless File.exists?(path) + # Move repos dir to 'repositories.old' dir - bk_repos_path = File.join(repos_path, '..', 'repositories.old.' + Time.now.to_i.to_s) - FileUtils.mv(repos_path, bk_repos_path) + bk_repos_path = File.join(path, '..', 'repositories.old.' + Time.now.to_i.to_s) + FileUtils.mv(path, bk_repos_path) end FileUtils.mkdir_p(repos_path) @@ -61,7 +61,7 @@ module Backup Project.find_each(batch_size: 1000) do |project| $progress.print " * #{project.path_with_namespace} ... " - project.namespace.ensure_dir_exist if project.namespace + project.ensure_dir_exist if File.exists?(path_to_bundle(project)) FileUtils.mkdir_p(path_to_repo(project)) @@ -100,8 +100,8 @@ module Backup end $progress.print 'Put GitLab hooks in repositories dirs'.color(:yellow) - cmd = "#{Gitlab.config.gitlab_shell.path}/bin/create-hooks" - if system(cmd) + cmd = %W(#{Gitlab.config.gitlab_shell.path}/bin/create-hooks) + repository_storage_paths_args + if system(*cmd) $progress.puts " [DONE]".color(:green) else puts " [FAILED]".color(:red) @@ -120,10 +120,6 @@ module Backup File.join(backup_repos_path, project.path_with_namespace + ".bundle") end - def repos_path - Gitlab.config.gitlab_shell.repos_path - end - def backup_repos_path File.join(Gitlab.config.backup.path, "repositories") end @@ -139,5 +135,11 @@ module Backup def silent {err: '/dev/null', out: '/dev/null'} end + + private + + def repository_storage_paths_args + Gitlab.config.repositories.storages.values + end end end diff --git a/lib/banzai/filter/abstract_reference_filter.rb b/lib/banzai/filter/abstract_reference_filter.rb index 81d66271136..d77a5e3ff09 100644 --- a/lib/banzai/filter/abstract_reference_filter.rb +++ b/lib/banzai/filter/abstract_reference_filter.rb @@ -160,11 +160,7 @@ module Banzai title = object_link_title(object) klass = reference_class(object_sym) - data = data_attribute( - original: link_text || match, - project: project.id, - object_sym => object.id - ) + data = data_attributes_for(link_text || match, project, object) if matches.names.include?("url") && matches[:url] url = matches[:url] @@ -183,6 +179,14 @@ module Banzai end end + def data_attributes_for(text, project, object) + data_attribute( + original: text, + project: project.id, + object_sym => object.id + ) + end + def object_link_text_extras(object, matches) extras = [] diff --git a/lib/banzai/filter/image_link_filter.rb b/lib/banzai/filter/image_link_filter.rb index 8aa6f8f124a..f0fb6084a35 100644 --- a/lib/banzai/filter/image_link_filter.rb +++ b/lib/banzai/filter/image_link_filter.rb @@ -8,7 +8,6 @@ module Banzai # of the anchor, and then replace the img with the link-wrapped version. def call doc.xpath('descendant-or-self::img[not(ancestor::a)]').each do |img| - div = doc.document.create_element( 'div', class: 'image-container' diff --git a/lib/banzai/filter/issue_reference_filter.rb b/lib/banzai/filter/issue_reference_filter.rb index 5351272f42d..4042e9a4c25 100644 --- a/lib/banzai/filter/issue_reference_filter.rb +++ b/lib/banzai/filter/issue_reference_filter.rb @@ -46,6 +46,26 @@ module Banzai end end + def object_link_title(object) + if object.is_a?(ExternalIssue) + "Issue in #{object.project.external_issue_tracker.title}" + else + super + end + end + + def data_attributes_for(text, project, object) + if object.is_a?(ExternalIssue) + data_attribute( + project: project.id, + external_issue: object.id, + reference_type: ExternalIssueReferenceFilter.reference_type + ) + else + super + end + end + def find_projects_for_paths(paths) super(paths).includes(:gitlab_issue_tracker_service) end diff --git a/lib/banzai/filter/reference_filter.rb b/lib/banzai/filter/reference_filter.rb index 2d6f34c9cd8..bf058241cda 100644 --- a/lib/banzai/filter/reference_filter.rb +++ b/lib/banzai/filter/reference_filter.rb @@ -29,7 +29,7 @@ module Banzai def data_attribute(attributes = {}) attributes = attributes.reject { |_, v| v.nil? } - attributes[:reference_type] = self.class.reference_type + attributes[:reference_type] ||= self.class.reference_type attributes.delete(:original) if context[:no_original_data] attributes.map { |key, value| %Q(data-#{key.to_s.dasherize}="#{escape_once(value)}") }.join(" ") end diff --git a/lib/banzai/filter/syntax_highlight_filter.rb b/lib/banzai/filter/syntax_highlight_filter.rb index 62a79c62e20..536b478979f 100644 --- a/lib/banzai/filter/syntax_highlight_filter.rb +++ b/lib/banzai/filter/syntax_highlight_filter.rb @@ -27,12 +27,17 @@ module Banzai highlighted = "<pre>#{code}</pre>" end - # Replace the parent `pre` element with the entire highlighted block - node.parent.replace(highlighted) + # Extracted to a method to measure it + replace_parent_pre_element(node, highlighted) end private + def replace_parent_pre_element(node, highlighted) + # Replace the parent `pre` element with the entire highlighted block + node.parent.replace(highlighted) + end + # Override Rouge::Plugins::Redcarpet#rouge_formatter def rouge_formatter(lexer) Rouge::Formatters::HTMLGitlab.new( diff --git a/lib/banzai/filter/wiki_link_filter.rb b/lib/banzai/filter/wiki_link_filter.rb index 1bb6d6bba87..269d5bf74fa 100644 --- a/lib/banzai/filter/wiki_link_filter.rb +++ b/lib/banzai/filter/wiki_link_filter.rb @@ -8,7 +8,6 @@ module Banzai # Context options: # :project_wiki class WikiLinkFilter < HTML::Pipeline::Filter - def call return doc unless project_wiki? diff --git a/lib/banzai/pipeline/full_pipeline.rb b/lib/banzai/pipeline/full_pipeline.rb index d47ddfda4be..3c974f73176 100644 --- a/lib/banzai/pipeline/full_pipeline.rb +++ b/lib/banzai/pipeline/full_pipeline.rb @@ -1,7 +1,6 @@ module Banzai module Pipeline class FullPipeline < CombinedPipeline.new(PlainMarkdownPipeline, GfmPipeline) - end end end diff --git a/lib/ci/charts.rb b/lib/ci/charts.rb index 5270108ef0f..1d7126a432d 100644 --- a/lib/ci/charts.rb +++ b/lib/ci/charts.rb @@ -13,7 +13,6 @@ module Ci collect end - def push(from, to, format) @labels << from.strftime(format) @total << project.builds. diff --git a/lib/disable_email_interceptor.rb b/lib/disable_email_interceptor.rb index 1b80be112a4..cee664b8951 100644 --- a/lib/disable_email_interceptor.rb +++ b/lib/disable_email_interceptor.rb @@ -1,6 +1,5 @@ # Read about interceptors in http://guides.rubyonrails.org/action_mailer_basics.html#intercepting-emails class DisableEmailInterceptor - def self.delivering_email(message) message.perform_deliveries = false Rails.logger.info "Emails disabled! Interceptor prevented sending mail #{message.subject}" diff --git a/lib/gitlab.rb b/lib/gitlab.rb index 37f4c34054f..c3064163e07 100644 --- a/lib/gitlab.rb +++ b/lib/gitlab.rb @@ -2,6 +2,11 @@ require_dependency 'gitlab/git' module Gitlab def self.com? - Gitlab.config.gitlab.url == 'https://gitlab.com' + # Check `staging?` as well to keep parity with gitlab.com + Gitlab.config.gitlab.url == 'https://gitlab.com' || staging? + end + + def self.staging? + Gitlab.config.gitlab.url == 'https://staging.gitlab.com' end end diff --git a/lib/gitlab/asciidoc.rb b/lib/gitlab/asciidoc.rb index 0b9c2e730f9..1a22ad9acf5 100644 --- a/lib/gitlab/asciidoc.rb +++ b/lib/gitlab/asciidoc.rb @@ -4,7 +4,6 @@ module Gitlab # Parser/renderer for the AsciiDoc format that uses Asciidoctor and filters # the resulting HTML through HTML pipeline filters. module Asciidoc - DEFAULT_ADOC_ATTRS = [ 'showtitle', 'idprefix=user-content-', 'idseparator=-', 'env=gitlab', 'env-gitlab', 'source-highlighter=html-pipeline' diff --git a/lib/gitlab/award_emoji.rb b/lib/gitlab/award_emoji.rb index 51b1df9ecbd..c94bfc0e65f 100644 --- a/lib/gitlab/award_emoji.rb +++ b/lib/gitlab/award_emoji.rb @@ -66,8 +66,17 @@ module Gitlab def self.urls @urls ||= begin path = File.join(Rails.root, 'fixtures', 'emojis', 'digests.json') + # Construct the full asset path ourselves because + # ActionView::Helpers::AssetUrlHelper.asset_url is slow for hundreds + # of entries since it has to do a lot of extra work (e.g. regexps). prefix = Gitlab::Application.config.assets.prefix digest = Gitlab::Application.config.assets.digest + base = + if defined?(Gitlab::Application.config.relative_url_root) && Gitlab::Application.config.relative_url_root + Gitlab::Application.config.relative_url_root + else + '' + end JSON.parse(File.read(path)).map do |hash| if digest @@ -76,7 +85,7 @@ module Gitlab fname = hash['unicode'] end - { name: hash['name'], path: "#{prefix}/#{fname}.png" } + { name: hash['name'], path: File.join(base, prefix, "#{fname}.png") } end end end diff --git a/lib/gitlab/backend/grack_auth.rb b/lib/gitlab/backend/grack_auth.rb index ab7b811c5d8..478f145bfed 100644 --- a/lib/gitlab/backend/grack_auth.rb +++ b/lib/gitlab/backend/grack_auth.rb @@ -8,7 +8,6 @@ module Grack end class Auth < Rack::Auth::Basic - attr_accessor :user, :project, :env def call(env) @@ -22,7 +21,7 @@ module Grack # Need this if under RELATIVE_URL_ROOT unless Gitlab.config.gitlab.relative_url_root.empty? # If website is mounted using relative_url_root need to remove it first - @env['PATH_INFO'] = @request.path.sub(Gitlab.config.gitlab.relative_url_root,'') + @env['PATH_INFO'] = @request.path.sub(Gitlab.config.gitlab.relative_url_root, '') else @env['PATH_INFO'] = @request.path end diff --git a/lib/gitlab/backend/shell.rb b/lib/gitlab/backend/shell.rb index 3e3986d6382..34e0143a82e 100644 --- a/lib/gitlab/backend/shell.rb +++ b/lib/gitlab/backend/shell.rb @@ -1,3 +1,5 @@ +require 'securerandom' + module Gitlab class Shell class Error < StandardError; end @@ -18,77 +20,82 @@ module Gitlab # Init new repository # + # storage - project's storage path # name - project path with namespace # # Ex. - # add_repository("gitlab/gitlab-ci") + # add_repository("/path/to/storage", "gitlab/gitlab-ci") # - def add_repository(name) + def add_repository(storage, name) Gitlab::Utils.system_silent([gitlab_shell_projects_path, - 'add-project', "#{name}.git"]) + 'add-project', storage, "#{name}.git"]) end # Import repository # + # storage - project's storage path # name - project path with namespace # # Ex. - # import_repository("gitlab/gitlab-ci", "https://github.com/randx/six.git") + # import_repository("/path/to/storage", "gitlab/gitlab-ci", "https://github.com/randx/six.git") # - def import_repository(name, url) - output, status = Popen::popen([gitlab_shell_projects_path, 'import-project', "#{name}.git", url, '900']) + def import_repository(storage, name, url) + output, status = Popen::popen([gitlab_shell_projects_path, 'import-project', + storage, "#{name}.git", url, '900']) raise Error, output unless status.zero? true end # Move repository - # + # storage - project's storage path # path - project path with namespace # new_path - new project path with namespace # # Ex. - # mv_repository("gitlab/gitlab-ci", "randx/gitlab-ci-new") + # mv_repository("/path/to/storage", "gitlab/gitlab-ci", "randx/gitlab-ci-new") # - def mv_repository(path, new_path) + def mv_repository(storage, path, new_path) Gitlab::Utils.system_silent([gitlab_shell_projects_path, 'mv-project', - "#{path}.git", "#{new_path}.git"]) + storage, "#{path}.git", "#{new_path}.git"]) end # Fork repository to new namespace - # + # storage - project's storage path # path - project path with namespace # fork_namespace - namespace for forked project # # Ex. - # fork_repository("gitlab/gitlab-ci", "randx") + # fork_repository("/path/to/storage", "gitlab/gitlab-ci", "randx") # - def fork_repository(path, fork_namespace) + def fork_repository(storage, path, fork_namespace) Gitlab::Utils.system_silent([gitlab_shell_projects_path, 'fork-project', - "#{path}.git", fork_namespace]) + storage, "#{path}.git", fork_namespace]) end # Remove repository from file system # + # storage - project's storage path # name - project path with namespace # # Ex. - # remove_repository("gitlab/gitlab-ci") + # remove_repository("/path/to/storage", "gitlab/gitlab-ci") # - def remove_repository(name) + def remove_repository(storage, name) Gitlab::Utils.system_silent([gitlab_shell_projects_path, - 'rm-project', "#{name}.git"]) + 'rm-project', storage, "#{name}.git"]) end # Gc repository # + # storage - project storage path # path - project path with namespace # # Ex. - # gc("gitlab/gitlab-ci") + # gc("/path/to/storage", "gitlab/gitlab-ci") # - def gc(path) + def gc(storage, path) Gitlab::Utils.system_silent([gitlab_shell_projects_path, 'gc', - "#{path}.git"]) + storage, "#{path}.git"]) end # Add new key to gitlab-shell @@ -133,31 +140,31 @@ module Gitlab # Add empty directory for storing repositories # # Ex. - # add_namespace("gitlab") + # add_namespace("/path/to/storage", "gitlab") # - def add_namespace(name) - FileUtils.mkdir(full_path(name), mode: 0770) unless exists?(name) + def add_namespace(storage, name) + FileUtils.mkdir(full_path(storage, name), mode: 0770) unless exists?(storage, name) end # Remove directory from repositories storage # Every repository inside this directory will be removed too # # Ex. - # rm_namespace("gitlab") + # rm_namespace("/path/to/storage", "gitlab") # - def rm_namespace(name) - FileUtils.rm_r(full_path(name), force: true) + def rm_namespace(storage, name) + FileUtils.rm_r(full_path(storage, name), force: true) end # Move namespace directory inside repositories storage # # Ex. - # mv_namespace("gitlab", "gitlabhq") + # mv_namespace("/path/to/storage", "gitlab", "gitlabhq") # - def mv_namespace(old_name, new_name) - return false if exists?(new_name) || !exists?(old_name) + def mv_namespace(storage, old_name, new_name) + return false if exists?(storage, new_name) || !exists?(storage, old_name) - FileUtils.mv(full_path(old_name), full_path(new_name)) + FileUtils.mv(full_path(storage, old_name), full_path(storage, new_name)) end def url_to_repo(path) @@ -176,11 +183,26 @@ module Gitlab # Check if such directory exists in repositories. # # Usage: - # exists?('gitlab') - # exists?('gitlab/cookies.git') + # exists?(storage, 'gitlab') + # exists?(storage, 'gitlab/cookies.git') # - def exists?(dir_name) - File.exist?(full_path(dir_name)) + def exists?(storage, dir_name) + File.exist?(full_path(storage, dir_name)) + end + + # Create (if necessary) and link the secret token file + def generate_and_link_secret_token + secret_file = Gitlab.config.gitlab_shell.secret_file + unless File.exist? secret_file + # Generate a new token of 16 random hexadecimal characters and store it in secret_file. + token = SecureRandom.hex(16) + File.write(secret_file, token) + end + + link_path = File.join(gitlab_shell_path, '.gitlab_shell_secret') + if File.exist?(gitlab_shell_path) && !File.exist?(link_path) + FileUtils.symlink(secret_file, link_path) + end end protected @@ -193,14 +215,10 @@ module Gitlab File.expand_path("~#{Gitlab.config.gitlab_shell.ssh_user}") end - def repos_path - Gitlab.config.gitlab_shell.repos_path - end - - def full_path(dir_name) + def full_path(storage, dir_name) raise ArgumentError.new("Directory name can't be blank") if dir_name.blank? - File.join(repos_path, dir_name) + File.join(storage, dir_name) end def gitlab_shell_projects_path diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb index 28c34429c1f..54b46e5d23f 100644 --- a/lib/gitlab/current_settings.rb +++ b/lib/gitlab/current_settings.rb @@ -9,10 +9,14 @@ module Gitlab end def ensure_application_settings! - settings = ::ApplicationSetting.cached + if connect_to_db? + begin + settings = ::ApplicationSetting.current + # In case Redis isn't running or the Redis UNIX socket file is not available + rescue ::Redis::BaseError, ::Errno::ENOENT + settings = ::ApplicationSetting.last + end - if !settings && connect_to_db? - settings = ::ApplicationSetting.current settings ||= ::ApplicationSetting.create_from_defaults unless ActiveRecord::Migrator.needs_migration? end diff --git a/lib/gitlab/diff/parser.rb b/lib/gitlab/diff/parser.rb index 522dd2b9428..59a2367b65d 100644 --- a/lib/gitlab/diff/parser.rb +++ b/lib/gitlab/diff/parser.rb @@ -40,7 +40,6 @@ module Gitlab line_obj_index += 1 end - case line[0] when "+" line_new += 1 diff --git a/lib/gitlab/github_import/client.rb b/lib/gitlab/github_import/client.rb index d325eca6d99..043f10d96a9 100644 --- a/lib/gitlab/github_import/client.rb +++ b/lib/gitlab/github_import/client.rb @@ -4,26 +4,39 @@ module Gitlab GITHUB_SAFE_REMAINING_REQUESTS = 100 GITHUB_SAFE_SLEEP_TIME = 500 - attr_reader :client, :api + attr_reader :access_token def initialize(access_token) - @client = ::OAuth2::Client.new( - config.app_id, - config.app_secret, - github_options.merge(ssl: { verify: config['verify_ssl'] }) - ) + @access_token = access_token if access_token ::Octokit.auto_paginate = false + end + end + + def api + @api ||= ::Octokit::Client.new( + access_token: access_token, + api_endpoint: github_options[:site], + # If there is no config, we're connecting to github.com and we + # should verify ssl. + connection_options: { + ssl: { verify: config ? config['verify_ssl'] : true } + } + ) + end - @api = ::Octokit::Client.new( - access_token: access_token, - api_endpoint: github_options[:site], - connection_options: { - ssl: { verify: config['verify_ssl'] } - } - ) + def client + unless config + raise Projects::ImportService::Error, + 'OAuth configuration for GitHub missing.' end + + @client ||= ::OAuth2::Client.new( + config.app_id, + config.app_secret, + github_options.merge(ssl: { verify: config['verify_ssl'] }) + ) end def authorize_url(redirect_uri) @@ -56,7 +69,11 @@ module Gitlab end def github_options - config["args"]["client_options"].deep_symbolize_keys + if config + config["args"]["client_options"].deep_symbolize_keys + else + OmniAuth::Strategies::GitHub.default_options[:client_options].symbolize_keys + end end def rate_limit diff --git a/lib/gitlab/github_import/importer.rb b/lib/gitlab/github_import/importer.rb index 2286ac8829c..730978d502b 100644 --- a/lib/gitlab/github_import/importer.rb +++ b/lib/gitlab/github_import/importer.rb @@ -167,7 +167,7 @@ module Gitlab def import_wiki unless project.wiki_enabled? wiki = WikiFormatter.new(project) - gitlab_shell.import_repository(wiki.path_with_namespace, wiki.import_url) + gitlab_shell.import_repository(project.repository_storage_path, wiki.path_with_namespace, wiki.import_url) project.update_attribute(:wiki_enabled, true) end diff --git a/lib/gitlab/import_export.rb b/lib/gitlab/import_export.rb index 99cf85d9a3b..588647e5adb 100644 --- a/lib/gitlab/import_export.rb +++ b/lib/gitlab/import_export.rb @@ -2,7 +2,7 @@ module Gitlab module ImportExport extend self - VERSION = '0.1.0' + VERSION = '0.1.1' def export_path(relative_path:) File.join(storage_path, relative_path) diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml index 164ab6238c4..05f4ad527ac 100644 --- a/lib/gitlab/import_export/import_export.yml +++ b/lib/gitlab/import_export/import_export.yml @@ -1,24 +1,29 @@ # Model relationships to be included in the project import/export project_tree: - issues: + - :events - notes: - :author + - :author + - :events - :labels - - :milestones + - milestones: + - :events - snippets: - notes: :author - :releases - - :events - project_members: - :user - merge_requests: - notes: - :author + - :author + - :events - :merge_request_diff + - :events - pipelines: - notes: - :author + - :author + - :events - :statuses - :variables - :triggers diff --git a/lib/gitlab/import_export/importer.rb b/lib/gitlab/import_export/importer.rb index 595b20a09bd..8f66f48cbfe 100644 --- a/lib/gitlab/import_export/importer.rb +++ b/lib/gitlab/import_export/importer.rb @@ -1,7 +1,6 @@ module Gitlab module ImportExport class Importer - def initialize(project) @archive_file = project.import_source @current_user = project.creator diff --git a/lib/gitlab/import_export/members_mapper.rb b/lib/gitlab/import_export/members_mapper.rb index c569a35a48b..b459054c198 100644 --- a/lib/gitlab/import_export/members_mapper.rb +++ b/lib/gitlab/import_export/members_mapper.rb @@ -1,7 +1,6 @@ module Gitlab module ImportExport class MembersMapper - attr_reader :missing_author_ids def initialize(exported_members:, user:, project:) diff --git a/lib/gitlab/import_export/project_creator.rb b/lib/gitlab/import_export/project_creator.rb index 89388d1984b..77bb3ca6581 100644 --- a/lib/gitlab/import_export/project_creator.rb +++ b/lib/gitlab/import_export/project_creator.rb @@ -1,7 +1,6 @@ module Gitlab module ImportExport class ProjectCreator - def initialize(namespace_id, current_user, file, project_path) @namespace_id = namespace_id @current_user = current_user diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index dd71b92c522..0ac6ff01e3b 100644 --- a/lib/gitlab/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -1,7 +1,6 @@ module Gitlab module ImportExport class ProjectTreeRestorer - def initialize(user:, shared:, project:) @path = File.join(shared.export_path, 'project.json') @user = user diff --git a/lib/gitlab/import_export/reader.rb b/lib/gitlab/import_export/reader.rb index 19defd8f03a..15f5dd31035 100644 --- a/lib/gitlab/import_export/reader.rb +++ b/lib/gitlab/import_export/reader.rb @@ -1,7 +1,6 @@ module Gitlab module ImportExport class Reader - attr_reader :tree def initialize(shared:) @@ -55,7 +54,6 @@ module Gitlab @json_config_hash end - # If the model is a hash, process the sub_models, which could also be hashes # If there is a list, add to an existing array, otherwise use hash syntax # +current_key+ main model that will be a key in the hash diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb index 92bf7e0a2fc..9824df3f274 100644 --- a/lib/gitlab/import_export/relation_factory.rb +++ b/lib/gitlab/import_export/relation_factory.rb @@ -1,7 +1,6 @@ module Gitlab module ImportExport class RelationFactory - OVERRIDES = { snippets: :project_snippets, pipelines: 'Ci::Pipeline', statuses: 'commit_status', @@ -33,6 +32,7 @@ module Gitlab update_user_references update_project_references reset_ci_tokens if @relation_name == 'Ci::Trigger' + @relation_hash['data'].deep_symbolize_keys! if @relation_name == :events && @relation_hash['data'] generate_imported_object end diff --git a/lib/gitlab/import_export/shared.rb b/lib/gitlab/import_export/shared.rb index 6aff05b886a..5d6de8bc475 100644 --- a/lib/gitlab/import_export/shared.rb +++ b/lib/gitlab/import_export/shared.rb @@ -1,7 +1,6 @@ module Gitlab module ImportExport class Shared - attr_reader :errors, :opts def initialize(opts) diff --git a/lib/gitlab/import_export/uploads_saver.rb b/lib/gitlab/import_export/uploads_saver.rb index 7292e9d9712..d6f4fa57510 100644 --- a/lib/gitlab/import_export/uploads_saver.rb +++ b/lib/gitlab/import_export/uploads_saver.rb @@ -1,7 +1,6 @@ module Gitlab module ImportExport class UploadsSaver - def initialize(project:, shared:) @project = project @shared = shared diff --git a/lib/gitlab/import_export/version_checker.rb b/lib/gitlab/import_export/version_checker.rb index cf5c62c5e3c..abfc694b879 100644 --- a/lib/gitlab/import_export/version_checker.rb +++ b/lib/gitlab/import_export/version_checker.rb @@ -1,7 +1,6 @@ module Gitlab module ImportExport class VersionChecker - def self.check!(*args) new(*args).check! end diff --git a/lib/gitlab/import_export/version_saver.rb b/lib/gitlab/import_export/version_saver.rb index f7f73dc9343..9b642d740b7 100644 --- a/lib/gitlab/import_export/version_saver.rb +++ b/lib/gitlab/import_export/version_saver.rb @@ -1,7 +1,6 @@ module Gitlab module ImportExport class VersionSaver - def initialize(shared:) @shared = shared end diff --git a/lib/gitlab/import_sources.rb b/lib/gitlab/import_sources.rb index 948d43582cf..59a05411fe9 100644 --- a/lib/gitlab/import_sources.rb +++ b/lib/gitlab/import_sources.rb @@ -24,8 +24,6 @@ module Gitlab 'GitLab export' => 'gitlab_project' } end - end - end end diff --git a/lib/gitlab/key_fingerprint.rb b/lib/gitlab/key_fingerprint.rb index 8684b4636ea..b75ae512d92 100644 --- a/lib/gitlab/key_fingerprint.rb +++ b/lib/gitlab/key_fingerprint.rb @@ -39,7 +39,7 @@ module Gitlab # OpenSSH 6.8 introduces a new default output format for fingerprints. # Check the version and decide which command to use. - version_output, version_status = popen(%W(ssh -V)) + version_output, version_status = popen(%w(ssh -V)) return false unless version_status.zero? version_matches = version_output.match(/OpenSSH_(?<major>\d+)\.(?<minor>\d+)/) diff --git a/lib/gitlab/lfs/response.rb b/lib/gitlab/lfs/response.rb index e3ed2f6791d..811363405a8 100644 --- a/lib/gitlab/lfs/response.rb +++ b/lib/gitlab/lfs/response.rb @@ -1,7 +1,6 @@ module Gitlab module Lfs class Response - def initialize(project, user, ci, request) @origin_project = project @project = storage_project(project) diff --git a/lib/gitlab/o_auth/auth_hash.rb b/lib/gitlab/o_auth/auth_hash.rb index 36e5c2670bb..7d6911a1ab3 100644 --- a/lib/gitlab/o_auth/auth_hash.rb +++ b/lib/gitlab/o_auth/auth_hash.rb @@ -66,7 +66,7 @@ module Gitlab # Get the first part of the email address (before @) # In addtion in removes illegal characters def generate_username(email) - email.match(/^[^@]*/)[0].mb_chars.normalize(:kd).gsub(/[^\x00-\x7F]/,'').to_s + email.match(/^[^@]*/)[0].mb_chars.normalize(:kd).gsub(/[^\x00-\x7F]/, '').to_s end def generate_temporarily_email(username) diff --git a/lib/gitlab/other_markup.rb b/lib/gitlab/other_markup.rb index 746ec283330..4e2f8ed5587 100644 --- a/lib/gitlab/other_markup.rb +++ b/lib/gitlab/other_markup.rb @@ -1,7 +1,6 @@ module Gitlab # Parser/renderer for markups without other special support code. module OtherMarkup - # Public: Converts the provided markup into HTML. # # input - the source text in a markup format diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb index c84c68f96f6..ffad5e17c78 100644 --- a/lib/gitlab/regex.rb +++ b/lib/gitlab/regex.rb @@ -13,7 +13,6 @@ module Gitlab "Cannot start with '-' or end in '.'." \ end - def namespace_name_regex @namespace_name_regex ||= /\A[\p{Alnum}\p{Pd}_\. ]*\z/.freeze end @@ -22,7 +21,6 @@ module Gitlab "can contain only letters, digits, '_', '.', dash and space." end - def project_name_regex @project_name_regex ||= /\A[\p{Alnum}_][\p{Alnum}\p{Pd}_\. ]*\z/.freeze end @@ -32,7 +30,6 @@ module Gitlab "It must start with letter, digit or '_'." end - def project_path_regex @project_path_regex ||= /\A[a-zA-Z0-9_.][a-zA-Z0-9_\-\.]*(?<!\.git|\.atom)\z/.freeze end @@ -42,7 +39,6 @@ module Gitlab "Cannot start with '-', end in '.git' or end in '.atom'" \ end - def file_name_regex @file_name_regex ||= /\A[a-zA-Z0-9_\-\.\@]*\z/.freeze end @@ -59,7 +55,6 @@ module Gitlab "can contain only letters, digits, '_', '-', '@' and '.'. Separate directories with a '/'. " end - def directory_traversal_regex @directory_traversal_regex ||= /\.{2}/.freeze end @@ -68,7 +63,6 @@ module Gitlab "cannot include directory traversal. " end - def archive_formats_regex # |zip|tar| tar.gz | tar.bz2 | @archive_formats_regex ||= /(zip|tar|tar\.gz|tgz|gz|tar\.bz2|tbz|tbz2|tb2|bz2)/.freeze diff --git a/lib/gitlab/saml/auth_hash.rb b/lib/gitlab/saml/auth_hash.rb index 32c1c9ec5bb..67a5f368bdb 100644 --- a/lib/gitlab/saml/auth_hash.rb +++ b/lib/gitlab/saml/auth_hash.rb @@ -1,7 +1,6 @@ module Gitlab module Saml class AuthHash < Gitlab::OAuth::AuthHash - def groups get_raw(Gitlab::Saml::Config.groups) end @@ -13,7 +12,6 @@ module Gitlab # otherwise just the first value is returned auth_hash.extra[:raw_info].all[key] end - end end end diff --git a/lib/gitlab/saml/config.rb b/lib/gitlab/saml/config.rb index 0f40c00f547..574c3a4b28c 100644 --- a/lib/gitlab/saml/config.rb +++ b/lib/gitlab/saml/config.rb @@ -1,7 +1,6 @@ module Gitlab module Saml class Config - class << self def options Gitlab.config.omniauth.providers.find { |provider| provider.name == 'saml' } @@ -15,7 +14,6 @@ module Gitlab options[:external_groups] end end - end end end diff --git a/lib/gitlab/saml/user.rb b/lib/gitlab/saml/user.rb index 8943022612c..f253dc7477e 100644 --- a/lib/gitlab/saml/user.rb +++ b/lib/gitlab/saml/user.rb @@ -6,7 +6,6 @@ module Gitlab module Saml class User < Gitlab::OAuth::User - def save super('SAML') end diff --git a/lib/tasks/gitlab/backup.rake b/lib/tasks/gitlab/backup.rake index 9ee72fde92f..b43ee5b3383 100644 --- a/lib/tasks/gitlab/backup.rake +++ b/lib/tasks/gitlab/backup.rake @@ -33,12 +33,13 @@ namespace :gitlab do unless backup.skipped?('db') unless ENV['force'] == 'yes' - warning = warning = <<-MSG.strip_heredoc + warning = <<-MSG.strip_heredoc Before restoring the database we recommend removing all existing tables to avoid future upgrade problems. Be aware that if you have custom tables in the GitLab database these tables and all data will be removed. MSG + puts warning.color(:red) ask_to_continue puts 'Removing all tables. Press `Ctrl-C` within 5 seconds to abort'.color(:yellow) sleep(5) diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index 12d6ac45fb6..e9a4e37ec48 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -356,97 +356,108 @@ namespace :gitlab do ######################## def check_repo_base_exists - print "Repo base directory exists? ... " + puts "Repo base directory exists?" - repo_base_path = Gitlab.config.gitlab_shell.repos_path + Gitlab.config.repositories.storages.each do |name, repo_base_path| + print "#{name}... " - if File.exists?(repo_base_path) - puts "yes".color(:green) - else - puts "no".color(:red) - puts "#{repo_base_path} is missing".color(:red) - try_fixing_it( - "This should have been created when setting up GitLab Shell.", - "Make sure it's set correctly in config/gitlab.yml", - "Make sure GitLab Shell is installed correctly." - ) - for_more_information( - see_installation_guide_section "GitLab Shell" - ) - fix_and_rerun + if File.exists?(repo_base_path) + puts "yes".color(:green) + else + puts "no".color(:red) + puts "#{repo_base_path} is missing".color(:red) + try_fixing_it( + "This should have been created when setting up GitLab Shell.", + "Make sure it's set correctly in config/gitlab.yml", + "Make sure GitLab Shell is installed correctly." + ) + for_more_information( + see_installation_guide_section "GitLab Shell" + ) + fix_and_rerun + end end end def check_repo_base_is_not_symlink - print "Repo base directory is a symlink? ... " + puts "Repo storage directories are symlinks?" - repo_base_path = Gitlab.config.gitlab_shell.repos_path - unless File.exists?(repo_base_path) - puts "can't check because of previous errors".color(:magenta) - return - end + Gitlab.config.repositories.storages.each do |name, repo_base_path| + print "#{name}... " - unless File.symlink?(repo_base_path) - puts "no".color(:green) - else - puts "yes".color(:red) - try_fixing_it( - "Make sure it's set to the real directory in config/gitlab.yml" - ) - fix_and_rerun + unless File.exists?(repo_base_path) + puts "can't check because of previous errors".color(:magenta) + return + end + + unless File.symlink?(repo_base_path) + puts "no".color(:green) + else + puts "yes".color(:red) + try_fixing_it( + "Make sure it's set to the real directory in config/gitlab.yml" + ) + fix_and_rerun + end end end def check_repo_base_permissions - print "Repo base access is drwxrws---? ... " + puts "Repo paths access is drwxrws---?" - repo_base_path = Gitlab.config.gitlab_shell.repos_path - unless File.exists?(repo_base_path) - puts "can't check because of previous errors".color(:magenta) - return - end + Gitlab.config.repositories.storages.each do |name, repo_base_path| + print "#{name}... " - if File.stat(repo_base_path).mode.to_s(8).ends_with?("2770") - puts "yes".color(:green) - else - puts "no".color(:red) - try_fixing_it( - "sudo chmod -R ug+rwX,o-rwx #{repo_base_path}", - "sudo chmod -R ug-s #{repo_base_path}", - "sudo find #{repo_base_path} -type d -print0 | sudo xargs -0 chmod g+s" - ) - for_more_information( - see_installation_guide_section "GitLab Shell" - ) - fix_and_rerun + unless File.exists?(repo_base_path) + puts "can't check because of previous errors".color(:magenta) + return + end + + if File.stat(repo_base_path).mode.to_s(8).ends_with?("2770") + puts "yes".color(:green) + else + puts "no".color(:red) + try_fixing_it( + "sudo chmod -R ug+rwX,o-rwx #{repo_base_path}", + "sudo chmod -R ug-s #{repo_base_path}", + "sudo find #{repo_base_path} -type d -print0 | sudo xargs -0 chmod g+s" + ) + for_more_information( + see_installation_guide_section "GitLab Shell" + ) + fix_and_rerun + end end end def check_repo_base_user_and_group gitlab_shell_ssh_user = Gitlab.config.gitlab_shell.ssh_user gitlab_shell_owner_group = Gitlab.config.gitlab_shell.owner_group - print "Repo base owned by #{gitlab_shell_ssh_user}:#{gitlab_shell_owner_group}? ... " + puts "Repo paths owned by #{gitlab_shell_ssh_user}:#{gitlab_shell_owner_group}?" - repo_base_path = Gitlab.config.gitlab_shell.repos_path - unless File.exists?(repo_base_path) - puts "can't check because of previous errors".color(:magenta) - return - end + Gitlab.config.repositories.storages.each do |name, repo_base_path| + print "#{name}... " - uid = uid_for(gitlab_shell_ssh_user) - gid = gid_for(gitlab_shell_owner_group) - if File.stat(repo_base_path).uid == uid && File.stat(repo_base_path).gid == gid - puts "yes".color(:green) - else - puts "no".color(:red) - puts " User id for #{gitlab_shell_ssh_user}: #{uid}. Groupd id for #{gitlab_shell_owner_group}: #{gid}".color(:blue) - try_fixing_it( - "sudo chown -R #{gitlab_shell_ssh_user}:#{gitlab_shell_owner_group} #{repo_base_path}" - ) - for_more_information( - see_installation_guide_section "GitLab Shell" - ) - fix_and_rerun + unless File.exists?(repo_base_path) + puts "can't check because of previous errors".color(:magenta) + return + end + + uid = uid_for(gitlab_shell_ssh_user) + gid = gid_for(gitlab_shell_owner_group) + if File.stat(repo_base_path).uid == uid && File.stat(repo_base_path).gid == gid + puts "yes".color(:green) + else + puts "no".color(:red) + puts " User id for #{gitlab_shell_ssh_user}: #{uid}. Groupd id for #{gitlab_shell_owner_group}: #{gid}".color(:blue) + try_fixing_it( + "sudo chown -R #{gitlab_shell_ssh_user}:#{gitlab_shell_owner_group} #{repo_base_path}" + ) + for_more_information( + see_installation_guide_section "GitLab Shell" + ) + fix_and_rerun + end end end @@ -473,7 +484,7 @@ namespace :gitlab do else puts "wrong or missing hooks".color(:red) try_fixing_it( - sudo_gitlab("#{File.join(gitlab_shell_path, 'bin/create-hooks')}"), + sudo_gitlab("#{File.join(gitlab_shell_path, 'bin/create-hooks')} #{repository_storage_paths_args.join(' ')}"), 'Check the hooks_path in config/gitlab.yml', 'Check your gitlab-shell installation' ) @@ -785,13 +796,13 @@ namespace :gitlab do namespace :repo do desc "GitLab | Check the integrity of the repositories managed by GitLab" task check: :environment do - namespace_dirs = Dir.glob( - File.join(Gitlab.config.gitlab_shell.repos_path, '*') - ) + Gitlab.config.repositories.storages.each do |name, path| + namespace_dirs = Dir.glob(File.join(path, '*')) - namespace_dirs.each do |namespace_dir| - repo_dirs = Dir.glob(File.join(namespace_dir, '*')) - repo_dirs.each { |repo_dir| check_repo_integrity(repo_dir) } + namespace_dirs.each do |namespace_dir| + repo_dirs = Dir.glob(File.join(namespace_dir, '*')) + repo_dirs.each { |repo_dir| check_repo_integrity(repo_dir) } + end end end end @@ -799,12 +810,12 @@ namespace :gitlab do namespace :user do desc "GitLab | Check the integrity of a specific user's repositories" task :check_repos, [:username] => :environment do |t, args| - username = args[:username] || prompt("Check repository integrity for which username? ".color(:blue)) + username = args[:username] || prompt("Check repository integrity for fsername? ".color(:blue)) user = User.find_by(username: username) if user repo_dirs = user.authorized_projects.map do |p| File.join( - Gitlab.config.gitlab_shell.repos_path, + p.repository_storage_path, "#{p.path_with_namespace}.git" ) end diff --git a/lib/tasks/gitlab/cleanup.rake b/lib/tasks/gitlab/cleanup.rake index ab0028d6603..b7cbdc6cd78 100644 --- a/lib/tasks/gitlab/cleanup.rake +++ b/lib/tasks/gitlab/cleanup.rake @@ -5,36 +5,36 @@ namespace :gitlab do warn_user_is_not_gitlab remove_flag = ENV['REMOVE'] - namespaces = Namespace.pluck(:path) - git_base_path = Gitlab.config.gitlab_shell.repos_path - all_dirs = Dir.glob(git_base_path + '/*') + Gitlab.config.repositories.storages.each do |name, git_base_path| + all_dirs = Dir.glob(git_base_path + '/*') - puts git_base_path.color(:yellow) - puts "Looking for directories to remove... " + puts git_base_path.color(:yellow) + puts "Looking for directories to remove... " - all_dirs.reject! do |dir| - # skip if git repo - dir =~ /.git$/ - end + all_dirs.reject! do |dir| + # skip if git repo + dir =~ /.git$/ + end - all_dirs.reject! do |dir| - dir_name = File.basename dir + all_dirs.reject! do |dir| + dir_name = File.basename dir - # skip if namespace present - namespaces.include?(dir_name) - end + # skip if namespace present + namespaces.include?(dir_name) + end - all_dirs.each do |dir_path| + all_dirs.each do |dir_path| - if remove_flag - if FileUtils.rm_rf dir_path - puts "Removed...#{dir_path}".color(:red) + if remove_flag + if FileUtils.rm_rf dir_path + puts "Removed...#{dir_path}".color(:red) + else + puts "Cannot remove #{dir_path}".color(:red) + end else - puts "Cannot remove #{dir_path}".color(:red) + puts "Can be removed: #{dir_path}".color(:red) end - else - puts "Can be removed: #{dir_path}".color(:red) end end @@ -48,20 +48,21 @@ namespace :gitlab do warn_user_is_not_gitlab move_suffix = "+orphaned+#{Time.now.to_i}" - repo_root = Gitlab.config.gitlab_shell.repos_path - # Look for global repos (legacy, depth 1) and normal repos (depth 2) - IO.popen(%W(find #{repo_root} -mindepth 1 -maxdepth 2 -name *.git)) do |find| - find.each_line do |path| - path.chomp! - repo_with_namespace = path. - sub(repo_root, ''). - sub(%r{^/*}, ''). - chomp('.git'). - chomp('.wiki') - next if Project.find_with_namespace(repo_with_namespace) - new_path = path + move_suffix - puts path.inspect + ' -> ' + new_path.inspect - File.rename(path, new_path) + Gitlab.config.repositories.storages.each do |name, repo_root| + # Look for global repos (legacy, depth 1) and normal repos (depth 2) + IO.popen(%W(find #{repo_root} -mindepth 1 -maxdepth 2 -name *.git)) do |find| + find.each_line do |path| + path.chomp! + repo_with_namespace = path. + sub(repo_root, ''). + sub(%r{^/*}, ''). + chomp('.git'). + chomp('.wiki') + next if Project.find_with_namespace(repo_with_namespace) + new_path = path + move_suffix + puts path.inspect + ' -> ' + new_path.inspect + File.rename(path, new_path) + end end end end diff --git a/lib/tasks/gitlab/import.rake b/lib/tasks/gitlab/import.rake index 4753f00c26a..dbdd4e977e8 100644 --- a/lib/tasks/gitlab/import.rake +++ b/lib/tasks/gitlab/import.rake @@ -2,73 +2,73 @@ namespace :gitlab do namespace :import do # How to use: # - # 1. copy the bare repos under the repos_path (commonly /home/git/repositories) + # 1. copy the bare repos under the repository storage paths (commonly the default path is /home/git/repositories) # 2. run: bundle exec rake gitlab:import:repos RAILS_ENV=production # # Notes: # * The project owner will set to the first administator of the system # * Existing projects will be skipped # - desc "GitLab | Import bare repositories from gitlab_shell -> repos_path into GitLab project instance" + desc "GitLab | Import bare repositories from repositories -> storages into GitLab project instance" task repos: :environment do + Gitlab.config.repositories.storages.each do |name, git_base_path| + repos_to_import = Dir.glob(git_base_path + '/**/*.git') - git_base_path = Gitlab.config.gitlab_shell.repos_path - repos_to_import = Dir.glob(git_base_path + '/**/*.git') + repos_to_import.each do |repo_path| + # strip repo base path + repo_path[0..git_base_path.length] = '' - repos_to_import.each do |repo_path| - # strip repo base path - repo_path[0..git_base_path.length] = '' + path = repo_path.sub(/\.git$/, '') + group_name, name = File.split(path) + group_name = nil if group_name == '.' - path = repo_path.sub(/\.git$/, '') - group_name, name = File.split(path) - group_name = nil if group_name == '.' + puts "Processing #{repo_path}".color(:yellow) - puts "Processing #{repo_path}".color(:yellow) - - if path.end_with?('.wiki') - puts " * Skipping wiki repo" - next - end + if path.end_with?('.wiki') + puts " * Skipping wiki repo" + next + end - project = Project.find_with_namespace(path) + project = Project.find_with_namespace(path) - if project - puts " * #{project.name} (#{repo_path}) exists" - else - user = User.admins.reorder("id").first + if project + puts " * #{project.name} (#{repo_path}) exists" + else + user = User.admins.reorder("id").first - project_params = { - name: name, - path: name - } + project_params = { + name: name, + path: name + } - # find group namespace - if group_name - group = Namespace.find_by(path: group_name) - # create group namespace - unless group - group = Group.new(:name => group_name) - group.path = group_name - group.owner = user - if group.save - puts " * Created Group #{group.name} (#{group.id})".color(:green) - else - puts " * Failed trying to create group #{group.name}".color(:red) + # find group namespace + if group_name + group = Namespace.find_by(path: group_name) + # create group namespace + unless group + group = Group.new(:name => group_name) + group.path = group_name + group.owner = user + if group.save + puts " * Created Group #{group.name} (#{group.id})".color(:green) + else + puts " * Failed trying to create group #{group.name}".color(:red) + end end + # set project group + project_params[:namespace_id] = group.id end - # set project group - project_params[:namespace_id] = group.id - end - project = Projects::CreateService.new(user, project_params).execute + project = Projects::CreateService.new(user, project_params).execute - if project.persisted? - puts " * Created #{project.name} (#{repo_path})".color(:green) - project.update_repository_size - project.update_commit_count - else - puts " * Failed trying to create #{project.name} (#{repo_path})".color(:red) - puts " Errors: #{project.errors.messages}".color(:red) + if project.persisted? + puts " * Created #{project.name} (#{repo_path})".color(:green) + project.update_repository_size + project.update_commit_count + else + puts " * Failed trying to create #{project.name} (#{repo_path})".color(:red) + puts " Errors: #{project.errors.messages}".color(:red) + end end end end diff --git a/lib/tasks/gitlab/info.rake b/lib/tasks/gitlab/info.rake index 352b566df24..fe43d40e6d2 100644 --- a/lib/tasks/gitlab/info.rake +++ b/lib/tasks/gitlab/info.rake @@ -62,7 +62,10 @@ namespace :gitlab do puts "" puts "GitLab Shell".color(:yellow) puts "Version:\t#{gitlab_shell_version || "unknown".color(:red)}" - puts "Repositories:\t#{Gitlab.config.gitlab_shell.repos_path}" + puts "Repository storage paths:" + Gitlab.config.repositories.storages.each do |name, path| + puts "- #{name}: \t#{path}" + end puts "Hooks:\t\t#{Gitlab.config.gitlab_shell.hooks_path}" puts "Git:\t\t#{Gitlab.config.git.bin_path}" diff --git a/lib/tasks/gitlab/list_repos.rake b/lib/tasks/gitlab/list_repos.rake index c7596e7abcb..ffcc76e5498 100644 --- a/lib/tasks/gitlab/list_repos.rake +++ b/lib/tasks/gitlab/list_repos.rake @@ -9,7 +9,7 @@ namespace :gitlab do scope = scope.where('id IN (?) OR namespace_id in (?)', project_ids, namespace_ids) end scope.find_each do |project| - base = File.join(Gitlab.config.gitlab_shell.repos_path, project.path_with_namespace) + base = File.join(project.repository_storage_path, project.path_with_namespace) puts base + '.git' puts base + '.wiki.git' end diff --git a/lib/tasks/gitlab/shell.rake b/lib/tasks/gitlab/shell.rake index b1648a4602a..c85ebdf8619 100644 --- a/lib/tasks/gitlab/shell.rake +++ b/lib/tasks/gitlab/shell.rake @@ -12,7 +12,6 @@ namespace :gitlab do gitlab_url = Gitlab.config.gitlab.url # gitlab-shell requires a / at the end of the url gitlab_url += '/' unless gitlab_url.end_with?('/') - repos_path = Gitlab.config.gitlab_shell.repos_path target_dir = Gitlab.config.gitlab_shell.path # Clone if needed @@ -35,7 +34,6 @@ namespace :gitlab do user: user, gitlab_url: gitlab_url, http_settings: {self_signed_cert: false}.stringify_keys, - repos_path: repos_path, auth_file: File.join(home_dir, ".ssh", "authorized_keys"), redis: { bin: %x{which redis-cli}.chomp, @@ -58,10 +56,10 @@ namespace :gitlab do File.open("config.yml", "w+") {|f| f.puts config.to_yaml} # Launch installation process - system(*%W(bin/install)) + system(*%W(bin/install) + repository_storage_paths_args) # (Re)create hooks - system(*%W(bin/create-hooks)) + system(*%W(bin/create-hooks) + repository_storage_paths_args) end # Required for debian packaging with PKGR: Setup .ssh/environment with @@ -73,6 +71,8 @@ namespace :gitlab do File.open(File.join(home_dir, ".ssh", "environment"), "w+") do |f| f.puts "PATH=#{ENV['PATH']}" end + + Gitlab::Shell.new.generate_and_link_secret_token end desc "GitLab | Setup gitlab-shell" @@ -87,7 +87,8 @@ namespace :gitlab do if File.exists?(path_to_repo) print '-' else - if Gitlab::Shell.new.add_repository(project.path_with_namespace) + if Gitlab::Shell.new.add_repository(project.repository_storage_path, + project.path_with_namespace) print '.' else print 'F' @@ -138,4 +139,3 @@ namespace :gitlab do system(*%W(#{Gitlab.config.git.bin_path} reset --hard #{tag})) end end - diff --git a/lib/tasks/gitlab/task_helpers.rake b/lib/tasks/gitlab/task_helpers.rake index d0c019044b7..ab96b1d3593 100644 --- a/lib/tasks/gitlab/task_helpers.rake +++ b/lib/tasks/gitlab/task_helpers.rake @@ -125,10 +125,16 @@ namespace :gitlab do end def all_repos - IO.popen(%W(find #{Gitlab.config.gitlab_shell.repos_path} -mindepth 2 -maxdepth 2 -type d -name *.git)) do |find| - find.each_line do |path| - yield path.chomp + Gitlab.config.repositories.storages.each do |name, path| + IO.popen(%W(find #{path} -mindepth 2 -maxdepth 2 -type d -name *.git)) do |find| + find.each_line do |path| + yield path.chomp + end end end end + + def repository_storage_paths_args + Gitlab.config.repositories.storages.values + end end diff --git a/lib/tasks/test.rake b/lib/tasks/test.rake index c5666d49e61..21c0e5f1d41 100644 --- a/lib/tasks/test.rake +++ b/lib/tasks/test.rake @@ -6,8 +6,6 @@ task :test do end unless Rails.env.production? - require 'coveralls/rake/task' - Coveralls::RakeTask.new desc "GitLab | Run all tests on CI with simplecov" - task :test_ci => [:rubocop, :brakeman, 'teaspoon', :spinach, :spec, 'coveralls:push'] + task test_ci: [:rubocop, :brakeman, 'teaspoon', :spinach, :spec] end diff --git a/lib/uploaded_file.rb b/lib/uploaded_file.rb index d4291f012d3..41dee5fdc06 100644 --- a/lib/uploaded_file.rb +++ b/lib/uploaded_file.rb @@ -3,7 +3,6 @@ require "fileutils" # Taken from: Rack::Test::UploadedFile class UploadedFile - # The filename, *not* including the path, of the "uploaded" file attr_reader :original_filename diff --git a/rubocop/cop/migration/add_index.rb b/rubocop/cop/migration/add_index.rb new file mode 100644 index 00000000000..d9247a1f7ea --- /dev/null +++ b/rubocop/cop/migration/add_index.rb @@ -0,0 +1,46 @@ +module RuboCop + module Cop + module Migration + # Cop that checks if indexes are added in a concurrent manner. + class AddIndex < RuboCop::Cop::Cop + include MigrationHelpers + + MSG = 'add_index requires downtime, use add_concurrent_index instead' + + def on_def(node) + return unless in_migration?(node) + + new_tables = [] + + node.each_descendant(:send) do |send_node| + first_arg = first_argument(send_node) + + # The first argument of "create_table" / "add_index" is the table + # name. + new_tables << first_arg if create_table?(send_node) + + next if method_name(send_node) != :add_index + + # Using "add_index" is fine for newly created tables as there's no + # data in these tables yet. + next if new_tables.include?(first_arg) + + add_offense(send_node, :selector) + end + end + + def create_table?(node) + method_name(node) == :create_table + end + + def method_name(node) + node.children[1] + end + + def first_argument(node) + node.children[2] ? node.children[0] : nil + end + end + end + end +end diff --git a/rubocop/cop/migration/column_with_default.rb b/rubocop/cop/migration/column_with_default.rb new file mode 100644 index 00000000000..97ee8b11044 --- /dev/null +++ b/rubocop/cop/migration/column_with_default.rb @@ -0,0 +1,50 @@ +module RuboCop + module Cop + module Migration + # Cop that checks if columns are added in a way that doesn't require + # downtime. + class ColumnWithDefault < RuboCop::Cop::Cop + include MigrationHelpers + + WHITELISTED_TABLES = [:application_settings] + + MSG = 'add_column with a default value requires downtime, ' \ + 'use add_column_with_default instead' + + def on_send(node) + return unless in_migration?(node) + + name = node.children[1] + + return unless name == :add_column + + # Ignore whitelisted tables. + return if table_whitelisted?(node.children[2]) + + opts = node.children.last + + return unless opts && opts.type == :hash + + opts.each_node(:pair) do |pair| + if hash_key_type(pair) == :sym && hash_key_name(pair) == :default + add_offense(node, :selector) + end + end + end + + def table_whitelisted?(symbol) + symbol && symbol.type == :sym && + WHITELISTED_TABLES.include?(symbol.children[0]) + end + + def hash_key_type(pair) + pair.children[0].type + end + + def hash_key_name(pair) + pair.children[0].children[0] + end + end + end + end +end diff --git a/rubocop/migration_helpers.rb b/rubocop/migration_helpers.rb new file mode 100644 index 00000000000..3160a784a04 --- /dev/null +++ b/rubocop/migration_helpers.rb @@ -0,0 +1,10 @@ +module RuboCop + # Module containing helper methods for writing migration cops. + module MigrationHelpers + # Returns true if the given node originated from the db/migrate directory. + def in_migration?(node) + File.dirname(node.location.expression.source_buffer.name). + end_with?('db/migrate') + end + end +end diff --git a/rubocop/rubocop.rb b/rubocop/rubocop.rb new file mode 100644 index 00000000000..7922e19768b --- /dev/null +++ b/rubocop/rubocop.rb @@ -0,0 +1,3 @@ +require_relative 'migration_helpers' +require_relative 'cop/migration/add_index' +require_relative 'cop/migration/column_with_default' diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index 10824c20c87..8bd210cbc3d 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -49,7 +49,6 @@ describe ApplicationController do end end - context "when the 'PRIVATE-TOKEN' header is populated with the private token" do it "logs the user in" do @request.headers['PRIVATE-TOKEN'] = user.private_token diff --git a/spec/controllers/groups/group_members_controller_spec.rb b/spec/controllers/groups/group_members_controller_spec.rb index ddc54108a7b..c34475976c6 100644 --- a/spec/controllers/groups/group_members_controller_spec.rb +++ b/spec/controllers/groups/group_members_controller_spec.rb @@ -133,7 +133,7 @@ describe Groups::GroupMembersController do expect(response).to set_flash.to 'Your access request to the group has been withdrawn.' expect(response).to redirect_to(group_path(group)) - expect(group.members.request).to be_empty + expect(group.requesters).to be_empty expect(group.users).not_to include user end end @@ -153,7 +153,7 @@ describe Groups::GroupMembersController do expect(response).to set_flash.to 'Your request for access has been queued for review.' expect(response).to redirect_to(group_path(group)) - expect(group.members.request.exists?(user_id: user)).to be_truthy + expect(group.requesters.exists?(user_id: user)).to be_truthy expect(group.users).not_to include user end end @@ -175,7 +175,7 @@ describe Groups::GroupMembersController do let(:group_requester) { create(:user) } let(:member) do group.request_access(group_requester) - group.members.request.find_by(user_id: group_requester) + group.requesters.find_by(user_id: group_requester) end context 'when user does not have enough rights' do diff --git a/spec/controllers/import/github_controller_spec.rb b/spec/controllers/import/github_controller_spec.rb index c55a3c28208..51d59526854 100644 --- a/spec/controllers/import/github_controller_spec.rb +++ b/spec/controllers/import/github_controller_spec.rb @@ -16,6 +16,24 @@ describe Import::GithubController do allow(controller).to receive(:github_import_enabled?).and_return(true) end + describe "GET new" do + it "redirects to GitHub for an access token if logged in with GitHub" do + allow(controller).to receive(:logged_in_with_github?).and_return(true) + expect(controller).to receive(:go_to_github_for_permissions) + + get :new + end + + it "redirects to status if we already have a token" do + assign_session_token + allow(controller).to receive(:logged_in_with_github?).and_return(false) + + get :new + + expect(controller).to redirect_to(status_import_github_url) + end + end + describe "GET callback" do it "updates access token" do token = "asdasd12345" @@ -32,6 +50,20 @@ describe Import::GithubController do end end + describe "POST personal_access_token" do + it "updates access token" do + token = "asdfasdf9876" + + allow_any_instance_of(Gitlab::GithubImport::Client). + to receive(:user).and_return(true) + + post :personal_access_token, personal_access_token: token + + expect(session[:github_access_token]).to eq(token) + expect(controller).to redirect_to(status_import_github_url) + end + end + describe "GET status" do before do @repo = OpenStruct.new(login: 'vim', full_name: 'asd/vim') @@ -59,6 +91,17 @@ describe Import::GithubController do expect(assigns(:already_added_projects)).to eq([@project]) expect(assigns(:repos)).to eq([]) end + + it "handles an invalid access token" do + allow_any_instance_of(Gitlab::GithubImport::Client). + to receive(:repos).and_raise(Octokit::Unauthorized) + + get :status + + expect(session[:github_access_token]).to eq(nil) + expect(controller).to redirect_to(new_import_github_url) + expect(flash[:alert]).to eq('Access denied to your GitHub account.') + end end describe "POST create" do diff --git a/spec/controllers/profiles/accounts_controller_spec.rb b/spec/controllers/profiles/accounts_controller_spec.rb index 2dc9adfd60c..18148acde3e 100644 --- a/spec/controllers/profiles/accounts_controller_spec.rb +++ b/spec/controllers/profiles/accounts_controller_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' describe Profiles::AccountsController do - let(:user) { create(:omniauth_user, provider: 'saml') } before do diff --git a/spec/controllers/projects/branches_controller_spec.rb b/spec/controllers/projects/branches_controller_spec.rb index f59d4937157..644de308c64 100644 --- a/spec/controllers/projects/branches_controller_spec.rb +++ b/spec/controllers/projects/branches_controller_spec.rb @@ -68,7 +68,6 @@ describe Projects::BranchesController do let(:branch) { "1-feature-branch" } let!(:issue) { create(:issue, project: project) } - it 'redirects' do post :create, namespace_id: project.namespace.to_param, @@ -89,7 +88,6 @@ describe Projects::BranchesController do branch_name: branch, issue_iid: issue.iid end - end end diff --git a/spec/controllers/projects/forks_controller_spec.rb b/spec/controllers/projects/forks_controller_spec.rb index 70ed8f3a62e..f66bcb8099c 100644 --- a/spec/controllers/projects/forks_controller_spec.rb +++ b/spec/controllers/projects/forks_controller_spec.rb @@ -64,9 +64,7 @@ describe Projects::ForksController do expect(assigns[:forks]).to be_present end end - end end end - end diff --git a/spec/controllers/projects/labels_controller_spec.rb b/spec/controllers/projects/labels_controller_spec.rb index ab1dd34ed57..3492b6ffbbb 100644 --- a/spec/controllers/projects/labels_controller_spec.rb +++ b/spec/controllers/projects/labels_controller_spec.rb @@ -18,7 +18,6 @@ describe Projects::LabelsController do 15.times { |i| create_label(priority: (i % 3) + 1, title: "label #{15 - i}") } 5.times { |i| create_label(title: "label #{100 - i}") } - get :index, namespace_id: project.namespace.to_param, project_id: project.to_param end diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 74c050f48f1..eff74e12869 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -117,7 +117,6 @@ describe Projects::MergeRequestsController do end context 'when filtering by opened state' do - context 'with opened merge requests' do it 'should list those merge requests' do get_merge_requests @@ -138,7 +137,6 @@ describe Projects::MergeRequestsController do expect(assigns(:merge_requests)).to include(merge_request) end end - end end diff --git a/spec/controllers/projects/project_members_controller_spec.rb b/spec/controllers/projects/project_members_controller_spec.rb index 29aaceb2302..5e2a8cf3849 100644 --- a/spec/controllers/projects/project_members_controller_spec.rb +++ b/spec/controllers/projects/project_members_controller_spec.rb @@ -187,7 +187,7 @@ describe Projects::ProjectMembersController do expect(response).to set_flash.to 'Your access request to the project has been withdrawn.' expect(response).to redirect_to(namespace_project_path(project.namespace, project)) - expect(project.members.request).to be_empty + expect(project.requesters).to be_empty expect(project.users).not_to include user end end @@ -210,7 +210,7 @@ describe Projects::ProjectMembersController do expect(response).to redirect_to( namespace_project_path(project.namespace, project) ) - expect(project.members.request.exists?(user_id: user)).to be_truthy + expect(project.requesters.exists?(user_id: user)).to be_truthy expect(project.users).not_to include user end end @@ -233,7 +233,7 @@ describe Projects::ProjectMembersController do let(:team_requester) { create(:user) } let(:member) do project.request_access(team_requester) - project.members.request.find_by(user_id: team_requester.id) + project.requesters.find_by(user_id: team_requester.id) end context 'when user does not have enough rights' do diff --git a/spec/controllers/projects/repositories_controller_spec.rb b/spec/controllers/projects/repositories_controller_spec.rb index ee905d11fb2..2fe3c263524 100644 --- a/spec/controllers/projects/repositories_controller_spec.rb +++ b/spec/controllers/projects/repositories_controller_spec.rb @@ -28,7 +28,6 @@ describe Projects::RepositoriesController do end context "when the service raises an error" do - before do allow(Gitlab::Workhorse).to receive(:send_git_archive).and_raise("Archive failed") end diff --git a/spec/controllers/projects/tree_controller_spec.rb b/spec/controllers/projects/tree_controller_spec.rb index 4e3a2bdb19e..1cc050247c6 100644 --- a/spec/controllers/projects/tree_controller_spec.rb +++ b/spec/controllers/projects/tree_controller_spec.rb @@ -66,7 +66,6 @@ describe Projects::TreeController do let(:id) { '6d39438/.gitignore' } it { expect(response).to have_http_status(302) } end - end describe 'GET show with blob path' do diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index d60579030c0..1b1b1bdf52d 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -89,15 +89,12 @@ describe ProjectsController do expect(response).to redirect_to("/#{public_project.path_with_namespace}") end - # MySQL queries are case insensitive by default, so this spec would fail. if Gitlab::Database.postgresql? context "when there is also a match with the same casing" do - let!(:other_project) { create(:project, :public, namespace: public_project.namespace, path: public_project.path.upcase) } it "loads the exactly matched project" do - get :show, namespace_id: public_project.namespace.path, id: public_project.path.upcase expect(assigns(:project)).to eq(other_project) diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index 8d6f486efdd..54a2d3d9460 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -64,7 +64,6 @@ describe UsersController do end describe 'GET #calendar' do - it 'renders calendar' do sign_in(user) diff --git a/spec/factories/todos.rb b/spec/factories/todos.rb index f426e27afed..7fc20cd5555 100644 --- a/spec/factories/todos.rb +++ b/spec/factories/todos.rb @@ -22,5 +22,9 @@ FactoryGirl.define do trait :build_failed do action { Todo::BUILD_FAILED } end + + trait :done do + state :done + end end end diff --git a/spec/features/admin/admin_hooks_spec.rb b/spec/features/admin/admin_hooks_spec.rb index 31633817d53..7964951ae99 100644 --- a/spec/features/admin/admin_hooks_spec.rb +++ b/spec/features/admin/admin_hooks_spec.rb @@ -6,7 +6,6 @@ describe "Admin::Hooks", feature: true do login_as :admin @system_hook = create(:system_hook) - end describe "GET /admin/hooks" do @@ -49,5 +48,4 @@ describe "Admin::Hooks", feature: true do it { expect(current_path).to eq(admin_hooks_path) } end - end diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb index 2d297776cb0..2f82fafc13a 100644 --- a/spec/features/admin/admin_runners_spec.rb +++ b/spec/features/admin/admin_runners_spec.rb @@ -62,19 +62,45 @@ describe "Admin Runners" do end describe 'enable/create' do - before do - @project1.runners << runner - visit admin_runner_path(runner) + shared_examples 'assignable runner' do + it 'enables a runner for a project' do + within '.unassigned-projects' do + click_on 'Enable' + end + + assigned_project = page.find('.assigned-projects') + + expect(assigned_project).to have_content(@project2.path) + end end - it 'enables specific runner for project' do - within '.unassigned-projects' do - click_on 'Enable' + context 'with specific runner' do + before do + @project1.runners << runner + visit admin_runner_path(runner) end - assigned_project = page.find('.assigned-projects') + it_behaves_like 'assignable runner' + end + + context 'with locked runner' do + before do + runner.update(locked: true) + @project1.runners << runner + visit admin_runner_path(runner) + end + + it_behaves_like 'assignable runner' + end + + context 'with shared runner' do + before do + @project1.destroy + runner.update(is_shared: true) + visit admin_runner_path(runner) + end - expect(assigned_project).to have_content(@project2.path) + it_behaves_like 'assignable runner' end end diff --git a/spec/features/admin/admin_system_info_spec.rb b/spec/features/admin/admin_system_info_spec.rb index dbc1d829b67..f4e5c26b519 100644 --- a/spec/features/admin/admin_system_info_spec.rb +++ b/spec/features/admin/admin_system_info_spec.rb @@ -11,7 +11,7 @@ describe 'Admin System Info' do expect(page).to have_content 'CPU' expect(page).to have_content 'Memory' - expect(page).to have_content 'Disk' + expect(page).to have_content 'Disks' end end end diff --git a/spec/features/dashboard/user_filters_projects_spec.rb b/spec/features/dashboard/user_filters_projects_spec.rb index cf86e2c85e9..c2e0612aef8 100644 --- a/spec/features/dashboard/user_filters_projects_spec.rb +++ b/spec/features/dashboard/user_filters_projects_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' describe "Dashboard > User filters projects", feature: true do - describe 'filtering personal projects' do before do user = create(:user) diff --git a/spec/features/gitlab_flavored_markdown_spec.rb b/spec/features/gitlab_flavored_markdown_spec.rb index 7852c39fee2..a89ac09f236 100644 --- a/spec/features/gitlab_flavored_markdown_spec.rb +++ b/spec/features/gitlab_flavored_markdown_spec.rb @@ -81,7 +81,6 @@ describe "GitLab Flavored Markdown", feature: true do end end - describe "for merge requests" do before do @merge_request = create(:merge_request, source_project: project, target_project: project, title: "fix #{issue.to_reference}") @@ -100,7 +99,6 @@ describe "GitLab Flavored Markdown", feature: true do end end - describe "for milestones" do before do @milestone = create(:milestone, diff --git a/spec/features/groups/members/owner_manages_access_requests_spec.rb b/spec/features/groups/members/owner_manages_access_requests_spec.rb index 321c9bad7d0..10d3713f19f 100644 --- a/spec/features/groups/members/owner_manages_access_requests_spec.rb +++ b/spec/features/groups/members/owner_manages_access_requests_spec.rb @@ -39,9 +39,8 @@ feature 'Groups > Members > Owner manages access requests', feature: true do expect(ActionMailer::Base.deliveries.last.subject).to match "Access to the #{group.name} group was denied" end - def expect_visible_access_request(group, user) - expect(group.members.request.exists?(user_id: user)).to be_truthy + expect(group.requesters.exists?(user_id: user)).to be_truthy expect(page).to have_content "#{group.name} access requests 1" expect(page).to have_content user.name end diff --git a/spec/features/groups/members/user_requests_access_spec.rb b/spec/features/groups/members/user_requests_access_spec.rb index 4944301c938..d1a6a98ab72 100644 --- a/spec/features/groups/members/user_requests_access_spec.rb +++ b/spec/features/groups/members/user_requests_access_spec.rb @@ -18,7 +18,7 @@ feature 'Groups > Members > User requests access', feature: true do expect(ActionMailer::Base.deliveries.last.to).to eq [owner.notification_email] expect(ActionMailer::Base.deliveries.last.subject).to match "Request to join the #{group.name} group" - expect(group.members.request.exists?(user_id: user)).to be_truthy + expect(group.requesters.exists?(user_id: user)).to be_truthy expect(page).to have_content 'Your request for access has been queued for review.' expect(page).to have_content 'Withdraw Access Request' @@ -42,7 +42,7 @@ feature 'Groups > Members > User requests access', feature: true do scenario 'user is not listed in the group members page' do click_link 'Request Access' - expect(group.members.request.exists?(user_id: user)).to be_truthy + expect(group.requesters.exists?(user_id: user)).to be_truthy click_link 'Members' @@ -54,11 +54,11 @@ feature 'Groups > Members > User requests access', feature: true do scenario 'user can withdraw its request for access' do click_link 'Request Access' - expect(group.members.request.exists?(user_id: user)).to be_truthy + expect(group.requesters.exists?(user_id: user)).to be_truthy click_link 'Withdraw Access Request' - expect(group.members.request.exists?(user_id: user)).to be_falsey + expect(group.requesters.exists?(user_id: user)).to be_falsey expect(page).to have_content 'Your access request to the group has been withdrawn.' end end diff --git a/spec/features/issues/filter_issues_spec.rb b/spec/features/issues/filter_issues_spec.rb index 4bcb105b17d..006a06b8235 100644 --- a/spec/features/issues/filter_issues_spec.rb +++ b/spec/features/issues/filter_issues_spec.rb @@ -14,7 +14,6 @@ describe 'Filter issues', feature: true do end describe 'Filter issues for assignee from issues#index' do - before do visit namespace_project_issues_path(project.namespace, project) @@ -36,7 +35,6 @@ describe 'Filter issues', feature: true do expect(find('.js-assignee-search .dropdown-toggle-text')).to have_content(user.name) end - it 'should not change when all link is clicked' do find('.issues-state-filters a', text: "All").click @@ -46,7 +44,6 @@ describe 'Filter issues', feature: true do end describe 'Filter issues for milestone from issues#index' do - before do visit namespace_project_issues_path(project.namespace, project) @@ -68,7 +65,6 @@ describe 'Filter issues', feature: true do expect(find('.js-milestone-select .dropdown-toggle-text')).to have_content(milestone.title) end - it 'should not change when all link is clicked' do find('.issues-state-filters a', text: "All").click @@ -113,7 +109,6 @@ describe 'Filter issues', feature: true do end describe 'Filter issues for assignee and label from issues#index' do - before do visit namespace_project_issues_path(project.namespace, project) @@ -144,7 +139,6 @@ describe 'Filter issues', feature: true do expect(find('.js-label-select .dropdown-toggle-text')).to have_content(label.title) end - it 'should not change when all link is clicked' do find('.issues-state-filters a', text: "All").click diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb index 5065dfb849c..d51c9abea19 100644 --- a/spec/features/issues_spec.rb +++ b/spec/features/issues_spec.rb @@ -92,7 +92,7 @@ describe 'Issues', feature: true do end context 'on edit form' do - let(:issue) { create(:issue, author: @user,project: project, due_date: Date.today.at_beginning_of_month.to_s) } + let(:issue) { create(:issue, author: @user, project: project, due_date: Date.today.at_beginning_of_month.to_s) } before do visit edit_namespace_project_issue_path(project.namespace, project, issue) @@ -361,7 +361,6 @@ describe 'Issues', feature: true do let(:issue) { create(:issue, project: project, author: @user, assignee: @user) } context 'by authorized user' do - it 'allows user to select unassigned', js: true do visit namespace_project_issue_path(project.namespace, project, issue) @@ -420,7 +419,6 @@ describe 'Issues', feature: true do end context 'by unauthorized user' do - let(:guest) { create(:user) } before do @@ -442,8 +440,6 @@ describe 'Issues', feature: true do let!(:milestone) { create(:milestone, project: project) } context 'by authorized user' do - - it 'allows user to select unassigned', js: true do visit namespace_project_issue_path(project.namespace, project, issue) diff --git a/spec/features/projects/commit/builds_spec.rb b/spec/features/projects/commit/builds_spec.rb index 15c381c0f5a..fcdf7870f34 100644 --- a/spec/features/projects/commit/builds_spec.rb +++ b/spec/features/projects/commit/builds_spec.rb @@ -20,7 +20,6 @@ feature 'project commit builds' do visit builds_namespace_project_commit_path(project.namespace, project, project.commit.sha) - expect(page).to have_content('Builds') end end diff --git a/spec/features/projects/commits/cherry_pick_spec.rb b/spec/features/projects/commits/cherry_pick_spec.rb index f88c0616b52..1b4ff6b6f1b 100644 --- a/spec/features/projects/commits/cherry_pick_spec.rb +++ b/spec/features/projects/commits/cherry_pick_spec.rb @@ -5,7 +5,6 @@ describe 'Cherry-pick Commits' do let(:master_pickable_commit) { project.commit('7d3b0f7cff5f37573aea97cebfd5692ea1689924') } let(:master_pickable_merge) { project.commit('e56497bb5f03a90a51293fc6d516788730953899') } - before do login_as :user project.team << [@user, :master] diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb index c5fb0fc783b..9d66f76ef58 100644 --- a/spec/features/projects/import_export/import_file_spec.rb +++ b/spec/features/projects/import_export/import_file_spec.rb @@ -24,7 +24,7 @@ feature 'project import', feature: true, js: true do visit new_project_path select2('2', from: '#project_namespace_id') - fill_in :project_path, with:'test-project-path', visible: true + fill_in :project_path, with: 'test-project-path', visible: true click_link 'GitLab export' expect(page).to have_content('GitLab project export') diff --git a/spec/features/projects/import_export/test_project_export.tar.gz b/spec/features/projects/import_export/test_project_export.tar.gz Binary files differindex 1fd04416d95..7bb0d26b21c 100644 --- a/spec/features/projects/import_export/test_project_export.tar.gz +++ b/spec/features/projects/import_export/test_project_export.tar.gz diff --git a/spec/features/projects/labels/issues_sorted_by_priority_spec.rb b/spec/features/projects/labels/issues_sorted_by_priority_spec.rb index 461f1737928..81b0c991d4f 100644 --- a/spec/features/projects/labels/issues_sorted_by_priority_spec.rb +++ b/spec/features/projects/labels/issues_sorted_by_priority_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' feature 'Issue prioritization', feature: true do - let(:user) { create(:user) } let(:project) { create(:project, name: 'test', namespace: user.namespace) } @@ -15,7 +14,6 @@ feature 'Issue prioritization', feature: true do # According to https://gitlab.com/gitlab-org/gitlab-ce/issues/14189#note_4360653 context 'when issues have one label' do scenario 'Are sorted properly' do - # Issues issue_1 = create(:issue, title: 'issue_1', project: project) issue_2 = create(:issue, title: 'issue_2', project: project) @@ -46,7 +44,6 @@ feature 'Issue prioritization', feature: true do context 'when issues have multiple labels' do scenario 'Are sorted properly' do - # Issues issue_1 = create(:issue, title: 'issue_1', project: project) issue_2 = create(:issue, title: 'issue_2', project: project) diff --git a/spec/features/projects/members/master_manages_access_requests_spec.rb b/spec/features/projects/members/master_manages_access_requests_spec.rb index aa2d906fa2e..f7fcd9b6731 100644 --- a/spec/features/projects/members/master_manages_access_requests_spec.rb +++ b/spec/features/projects/members/master_manages_access_requests_spec.rb @@ -40,7 +40,7 @@ feature 'Projects > Members > Master manages access requests', feature: true do end def expect_visible_access_request(project, user) - expect(project.members.request.exists?(user_id: user)).to be_truthy + expect(project.requesters.exists?(user_id: user)).to be_truthy expect(page).to have_content "#{project.name} access requests 1" expect(page).to have_content user.name end diff --git a/spec/features/projects/members/user_requests_access_spec.rb b/spec/features/projects/members/user_requests_access_spec.rb index af420c170ef..f2fe3ef364d 100644 --- a/spec/features/projects/members/user_requests_access_spec.rb +++ b/spec/features/projects/members/user_requests_access_spec.rb @@ -17,7 +17,7 @@ feature 'Projects > Members > User requests access', feature: true do expect(ActionMailer::Base.deliveries.last.to).to eq [master.notification_email] expect(ActionMailer::Base.deliveries.last.subject).to eq "Request to join the #{project.name_with_namespace} project" - expect(project.members.request.exists?(user_id: user)).to be_truthy + expect(project.requesters.exists?(user_id: user)).to be_truthy expect(page).to have_content 'Your request for access has been queued for review.' expect(page).to have_content 'Withdraw Access Request' @@ -27,7 +27,7 @@ feature 'Projects > Members > User requests access', feature: true do scenario 'user is not listed in the project members page' do click_link 'Request Access' - expect(project.members.request.exists?(user_id: user)).to be_truthy + expect(project.requesters.exists?(user_id: user)).to be_truthy open_project_settings_menu click_link 'Members' @@ -41,11 +41,11 @@ feature 'Projects > Members > User requests access', feature: true do scenario 'user can withdraw its request for access' do click_link 'Request Access' - expect(project.members.request.exists?(user_id: user)).to be_truthy + expect(project.requesters.exists?(user_id: user)).to be_truthy click_link 'Withdraw Access Request' - expect(project.members.request.exists?(user_id: user)).to be_falsey + expect(project.requesters.exists?(user_id: user)).to be_falsey expect(page).to have_content 'Your access request to the project has been withdrawn.' end diff --git a/spec/features/search_spec.rb b/spec/features/search_spec.rb index b9e63a7152c..85923f0a19d 100644 --- a/spec/features/search_spec.rb +++ b/spec/features/search_spec.rb @@ -48,9 +48,7 @@ describe "Search", feature: true do end end - describe 'Right header search field', feature: true do - describe 'Search in project page' do before do visit namespace_project_path(project.namespace, project) @@ -73,7 +71,6 @@ describe "Search", feature: true do end context 'click the links in the category search dropdown', js: true do - before do page.find('#search').click end @@ -124,6 +121,4 @@ describe "Search", feature: true do end end end - - end diff --git a/spec/features/security/group/internal_access_spec.rb b/spec/features/security/group/internal_access_spec.rb index 71b783b7276..35fcef7a712 100644 --- a/spec/features/security/group/internal_access_spec.rb +++ b/spec/features/security/group/internal_access_spec.rb @@ -76,7 +76,6 @@ describe 'Internal Group access', feature: true do it { is_expected.to be_denied_for :visitor } end - describe 'GET /groups/:path/group_members' do subject { group_group_members_path(group) } diff --git a/spec/features/security/group/private_access_spec.rb b/spec/features/security/group/private_access_spec.rb index cc9aee802f9..75a93342628 100644 --- a/spec/features/security/group/private_access_spec.rb +++ b/spec/features/security/group/private_access_spec.rb @@ -76,7 +76,6 @@ describe 'Private Group access', feature: true do it { is_expected.to be_denied_for :visitor } end - describe 'GET /groups/:path/group_members' do subject { group_group_members_path(group) } diff --git a/spec/features/security/group/public_access_spec.rb b/spec/features/security/group/public_access_spec.rb index db986683dbe..6c5ee93970b 100644 --- a/spec/features/security/group/public_access_spec.rb +++ b/spec/features/security/group/public_access_spec.rb @@ -76,7 +76,6 @@ describe 'Public Group access', feature: true do it { is_expected.to be_allowed_for :visitor } end - describe 'GET /groups/:path/group_members' do subject { group_group_members_path(group) } diff --git a/spec/features/signup_spec.rb b/spec/features/signup_spec.rb index 4229e82b443..a752c1d7235 100644 --- a/spec/features/signup_spec.rb +++ b/spec/features/signup_spec.rb @@ -2,7 +2,6 @@ require 'spec_helper' feature 'Signup', feature: true do describe 'signup with no errors' do - context "when sending confirmation email" do before { allow_any_instance_of(ApplicationSetting).to receive(:send_user_confirmation_email).and_return(true) } @@ -40,7 +39,6 @@ feature 'Signup', feature: true do expect(page).to have_content("Welcome! You have signed up successfully.") end end - end describe 'signup with errors' do diff --git a/spec/features/tags/master_deletes_tag_spec.rb b/spec/features/tags/master_deletes_tag_spec.rb index f0990118e3c..0f30f562539 100644 --- a/spec/features/tags/master_deletes_tag_spec.rb +++ b/spec/features/tags/master_deletes_tag_spec.rb @@ -22,7 +22,6 @@ feature 'Master deletes tag', feature: true do namespace_project_tags_path(project.namespace, project)) expect(page).not_to have_content 'v1.1.0' end - end context 'from a specific tag page' do diff --git a/spec/features/users_spec.rb b/spec/features/users_spec.rb index cf116040394..b5a94fe0383 100644 --- a/spec/features/users_spec.rb +++ b/spec/features/users_spec.rb @@ -47,5 +47,4 @@ feature 'Users', feature: true do def number_of_errors_on_page(page) page.find('#error_explanation').find('ul').all('li').count end - end diff --git a/spec/finders/group_projects_finder_spec.rb b/spec/finders/group_projects_finder_spec.rb index fdd3849816f..fbe09b28b3c 100644 --- a/spec/finders/group_projects_finder_spec.rb +++ b/spec/finders/group_projects_finder_spec.rb @@ -12,14 +12,12 @@ describe GroupProjectsFinder do let!(:shared_project_2) { create(:project, :private, path: '4') } let!(:shared_project_3) { create(:project, :internal, path: '5') } - before do shared_project_1.project_group_links.create(group_access: Gitlab::Access::MASTER, group: group) shared_project_2.project_group_links.create(group_access: Gitlab::Access::MASTER, group: group) shared_project_3.project_group_links.create(group_access: Gitlab::Access::MASTER, group: group) end - describe 'with a group member current user' do before { group.add_user(current_user, Gitlab::Access::MASTER) } diff --git a/spec/finders/snippets_finder_spec.rb b/spec/finders/snippets_finder_spec.rb index 810016c9658..28bdc18e840 100644 --- a/spec/finders/snippets_finder_spec.rb +++ b/spec/finders/snippets_finder_spec.rb @@ -69,7 +69,6 @@ describe SnippetsFinder do expect(snippets).to include(@snippet3) expect(snippets).not_to include(@snippet2, @snippet1) end - end context 'by_project filter' do diff --git a/spec/helpers/members_helper_spec.rb b/spec/helpers/members_helper_spec.rb index f75fdb739f6..7b2155e9a4e 100644 --- a/spec/helpers/members_helper_spec.rb +++ b/spec/helpers/members_helper_spec.rb @@ -57,6 +57,72 @@ describe MembersHelper do end end + describe '#can_see_request_access_button?' do + let(:user) { create(:user) } + let(:group) { create(:group, :public) } + let(:project) { create(:project, :public, group: group) } + + before do + allow(helper).to receive(:current_user).and_return(user) + end + + context 'source is a group' do + context 'current_user is not a member' do + it 'returns true' do + expect(helper.can_see_request_access_button?(group)).to be_truthy + end + end + + context 'current_user is a member' do + it 'returns false' do + group.add_owner(user) + + expect(helper.can_see_request_access_button?(group)).to be_falsy + end + end + + context 'current_user is a requester' do + it 'returns true' do + group.request_access(user) + + expect(helper.can_see_request_access_button?(group)).to be_truthy + end + end + end + + context 'source is a project' do + context 'current_user is not a member' do + it 'returns true' do + expect(helper.can_see_request_access_button?(project)).to be_truthy + end + end + + context 'current_user is a group member' do + it 'returns false' do + group.add_owner(user) + + expect(helper.can_see_request_access_button?(project)).to be_falsy + end + end + + context 'current_user is a group requester' do + it 'returns false' do + group.request_access(user) + + expect(helper.can_see_request_access_button?(project)).to be_falsy + end + end + + context 'current_user is a member' do + it 'returns false' do + project.team << [user, :master] + + expect(helper.can_see_request_access_button?(project)).to be_falsy + end + end + end + end + describe '#remove_member_message' do let(:requester) { build(:user) } let(:project) { create(:project) } diff --git a/spec/helpers/notes_helper_spec.rb b/spec/helpers/notes_helper_spec.rb new file mode 100644 index 00000000000..08a93503258 --- /dev/null +++ b/spec/helpers/notes_helper_spec.rb @@ -0,0 +1,46 @@ +require "spec_helper" + +describe NotesHelper do + describe "#notes_max_access_for_users" do + let(:owner) { create(:owner) } + let(:group) { create(:group) } + let(:project) { create(:empty_project, namespace: group) } + let(:master) { create(:user) } + let(:reporter) { create(:user) } + let(:guest) { create(:user) } + + let(:owner_note) { create(:note, author: owner, project: project) } + let(:master_note) { create(:note, author: master, project: project) } + let(:reporter_note) { create(:note, author: reporter, project: project) } + let!(:notes) { [owner_note, master_note, reporter_note] } + + before do + group.add_owner(owner) + project.team << [master, :master] + project.team << [reporter, :reporter] + project.team << [guest, :guest] + end + + it 'return human access levels' do + original_method = project.team.method(:human_max_access) + expect_any_instance_of(ProjectTeam).to receive(:human_max_access).exactly(3).times do |*args| + original_method.call(args[1]) + end + + expect(helper.note_max_access_for_user(owner_note)).to eq('Owner') + expect(helper.note_max_access_for_user(master_note)).to eq('Master') + expect(helper.note_max_access_for_user(reporter_note)).to eq('Reporter') + # Call it again to ensure value is cached + expect(helper.note_max_access_for_user(owner_note)).to eq('Owner') + end + + it 'handles access in different projects' do + second_project = create(:empty_project) + second_project.team << [master, :reporter] + other_note = create(:note, author: master, project: second_project) + + expect(helper.note_max_access_for_user(master_note)).to eq('Master') + expect(helper.note_max_access_for_user(other_note)).to eq('Reporter') + end + end +end diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb index 09e0bbfd00b..604204cca0a 100644 --- a/spec/helpers/projects_helper_spec.rb +++ b/spec/helpers/projects_helper_spec.rb @@ -123,11 +123,17 @@ describe ProjectsHelper do end describe '#sanitized_import_error' do + let(:project) { create(:project) } + + before do + allow(project).to receive(:repository_storage_path).and_return('/base/repo/path') + end + it 'removes the repo path' do - repo = File.join(Gitlab.config.gitlab_shell.repos_path, '/namespace/test.git') + repo = '/base/repo/path/namespace/test.git' import_error = "Could not clone #{repo}\n" - expect(sanitize_repo_path(import_error)).to eq('Could not clone [REPOS PATH]/namespace/test.git') + expect(sanitize_repo_path(project, import_error)).to eq('Could not clone [REPOS PATH]/namespace/test.git') end end end diff --git a/spec/helpers/visibility_level_helper_spec.rb b/spec/helpers/visibility_level_helper_spec.rb index 5e7594170c5..db3ad1b99e9 100644 --- a/spec/helpers/visibility_level_helper_spec.rb +++ b/spec/helpers/visibility_level_helper_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' describe VisibilityLevelHelper do - let(:project) { build(:project) } let(:group) { build(:group) } let(:personal_snippet) { build(:personal_snippet) } @@ -90,6 +89,5 @@ describe VisibilityLevelHelper do expect(skip_level?(snippet, Gitlab::VisibilityLevel::PRIVATE)).to be_falsey end end - end end diff --git a/spec/initializers/6_validations_spec.rb b/spec/initializers/6_validations_spec.rb new file mode 100644 index 00000000000..5178bd130f4 --- /dev/null +++ b/spec/initializers/6_validations_spec.rb @@ -0,0 +1,41 @@ +require 'spec_helper' + +describe '6_validations', lib: true do + context 'with correct settings' do + before do + mock_storages('foo' => '/a/b/c', 'bar' => 'a/b/d') + end + + it 'passes through' do + expect { load_validations }.not_to raise_error + end + end + + context 'with invalid storage names' do + before do + mock_storages('name with spaces' => '/a/b/c') + end + + it 'throws an error' do + expect { load_validations }.to raise_error('"name with spaces" is not a valid storage name. Please fix this in your gitlab.yml before starting GitLab.') + end + end + + context 'with nested storage paths' do + before do + mock_storages('foo' => '/a/b/c', 'bar' => '/a/b/c/d') + end + + it 'throws an error' do + expect { load_validations }.to raise_error('bar is a nested path of foo. Nested paths are not supported for repository storages. Please fix this in your gitlab.yml before starting GitLab.') + end + end + + def mock_storages(storages) + allow(Gitlab.config.repositories).to receive(:storages).and_return(storages) + end + + def load_validations + load File.join(__dir__, '../../config/initializers/6_validations.rb') + end +end diff --git a/spec/initializers/settings_spec.rb b/spec/initializers/settings_spec.rb index 1bcae8a27db..47b4e431823 100644 --- a/spec/initializers/settings_spec.rb +++ b/spec/initializers/settings_spec.rb @@ -2,7 +2,6 @@ require 'spec_helper' require_relative '../../config/initializers/1_settings' describe Settings, lib: true do - describe '#host_without_www' do context 'URL with protocol' do it 'returns the host' do @@ -41,5 +40,4 @@ describe Settings, lib: true do end end end - end diff --git a/spec/initializers/trusted_proxies_spec.rb b/spec/initializers/trusted_proxies_spec.rb index 4bb149f25ff..14c8df954a6 100644 --- a/spec/initializers/trusted_proxies_spec.rb +++ b/spec/initializers/trusted_proxies_spec.rb @@ -6,14 +6,16 @@ describe 'trusted_proxies', lib: true do set_trusted_proxies([]) end - it 'preserves private IPs as remote_ip' do + it 'preserves private IPs' do request = stub_request('HTTP_X_FORWARDED_FOR' => '10.1.5.89') expect(request.remote_ip).to eq('10.1.5.89') + expect(request.ip).to eq('10.1.5.89') end - it 'filters out localhost from remote_ip' do + it 'filters out localhost' do request = stub_request('HTTP_X_FORWARDED_FOR' => '1.1.1.1, 10.1.5.89, 127.0.0.1') expect(request.remote_ip).to eq('10.1.5.89') + expect(request.ip).to eq('10.1.5.89') end end @@ -22,9 +24,10 @@ describe 'trusted_proxies', lib: true do set_trusted_proxies([ "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16" ]) end - it 'filters out private and local IPs from remote_ip' do + it 'filters out private and local IPs' do request = stub_request('HTTP_X_FORWARDED_FOR' => '1.2.3.6, 1.1.1.1, 10.1.5.89, 127.0.0.1') expect(request.remote_ip).to eq('1.1.1.1') + expect(request.ip).to eq('1.1.1.1') end end @@ -33,9 +36,10 @@ describe 'trusted_proxies', lib: true do set_trusted_proxies([ "60.98.25.47" ]) end - it 'filters out proxy IP from remote_ip' do + it 'filters out proxy IP' do request = stub_request('HTTP_X_FORWARDED_FOR' => '1.2.3.6, 1.1.1.1, 60.98.25.47, 127.0.0.1') expect(request.remote_ip).to eq('1.1.1.1') + expect(request.ip).to eq('1.1.1.1') end end diff --git a/spec/lib/banzai/filter/issue_reference_filter_spec.rb b/spec/lib/banzai/filter/issue_reference_filter_spec.rb index 8d6ce114aa9..a005b4990e7 100644 --- a/spec/lib/banzai/filter/issue_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/issue_reference_filter_spec.rb @@ -199,6 +199,19 @@ describe Banzai::Filter::IssueReferenceFilter, lib: true do end end + context 'referencing external issues' do + let(:project) { create(:redmine_project) } + + it 'renders internal issue IDs as external issue links' do + doc = reference_filter('#1') + link = doc.css('a').first + + expect(link.attr('data-reference-type')).to eq('external_issue') + expect(link.attr('title')).to eq('Issue in Redmine') + expect(link.attr('data-external-issue')).to eq('1') + end + end + describe '#issues_per_Project' do context 'using an internal issue tracker' do it 'returns a Hash containing the issues per project' do diff --git a/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb b/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb index 72bc6a0b704..51c89ac4889 100644 --- a/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb @@ -59,7 +59,6 @@ describe Banzai::Pipeline::WikiPipeline do { "when GitLab is hosted at a root URL" => '/', "when GitLab is hosted at a relative URL" => '/nested/relative/gitlab' }.each do |test_name, relative_url_root| - context test_name do before do allow(Gitlab.config.gitlab).to receive(:relative_url_root).and_return(relative_url_root) diff --git a/spec/lib/ci/charts_spec.rb b/spec/lib/ci/charts_spec.rb index 9c6b4ea5086..97f2e97b062 100644 --- a/spec/lib/ci/charts_spec.rb +++ b/spec/lib/ci/charts_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' describe Ci::Charts, lib: true do - context "build_times" do before do @pipeline = FactoryGirl.create(:ci_pipeline) diff --git a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb index 2ca9f554b07..ec658668c61 100644 --- a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb +++ b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb @@ -143,7 +143,6 @@ module Ci end it "returns build only for specified type" do - config = YAML.dump({ before_script: ["pwd"], rspec: { script: "rspec", type: "test", only: ["master", "deploy"] }, diff --git a/spec/lib/gitlab/asciidoc_spec.rb b/spec/lib/gitlab/asciidoc_spec.rb index 736bf787208..32ca8239845 100644 --- a/spec/lib/gitlab/asciidoc_spec.rb +++ b/spec/lib/gitlab/asciidoc_spec.rb @@ -3,13 +3,11 @@ require 'nokogiri' module Gitlab describe Asciidoc, lib: true do - let(:input) { '<b>ascii</b>' } let(:context) { {} } let(:html) { 'H<sub>2</sub>O' } context "without project" do - it "should convert the input using Asciidoctor and default options" do expected_asciidoc_opts = { safe: :secure, @@ -24,7 +22,6 @@ module Gitlab end context "with asciidoc_opts" do - let(:asciidoc_opts) { { safe: :safe, attributes: ['foo'] } } it "should merge the options with default ones" do diff --git a/spec/lib/gitlab/award_emoji_spec.rb b/spec/lib/gitlab/award_emoji_spec.rb index 0f3852b1729..00a110e31f8 100644 --- a/spec/lib/gitlab/award_emoji_spec.rb +++ b/spec/lib/gitlab/award_emoji_spec.rb @@ -2,6 +2,10 @@ require 'spec_helper' describe Gitlab::AwardEmoji do describe '.urls' do + after do + Gitlab::AwardEmoji.instance_variable_set(:@urls, nil) + end + subject { Gitlab::AwardEmoji.urls } it { is_expected.to be_an_instance_of(Array) } @@ -15,6 +19,17 @@ describe Gitlab::AwardEmoji do end end end + + context 'handles relative root' do + it 'includes the full path' do + allow(Gitlab::Application.config).to receive(:relative_url_root).and_return('/gitlab') + + subject.each do |hash| + expect(hash[:name]).to be_an_instance_of(String) + expect(hash[:path]).to start_with('/gitlab') + end + end + end end describe '.emoji_by_category' do diff --git a/spec/lib/gitlab/backend/shell_spec.rb b/spec/lib/gitlab/backend/shell_spec.rb index fd869f48b5c..6e5ba211382 100644 --- a/spec/lib/gitlab/backend/shell_spec.rb +++ b/spec/lib/gitlab/backend/shell_spec.rb @@ -13,9 +13,37 @@ describe Gitlab::Shell, lib: true do it { is_expected.to respond_to :add_repository } it { is_expected.to respond_to :remove_repository } it { is_expected.to respond_to :fork_repository } + it { is_expected.to respond_to :gc } + it { is_expected.to respond_to :add_namespace } + it { is_expected.to respond_to :rm_namespace } + it { is_expected.to respond_to :mv_namespace } + it { is_expected.to respond_to :exists? } it { expect(gitlab_shell.url_to_repo('diaspora')).to eq(Gitlab.config.gitlab_shell.ssh_path_prefix + "diaspora.git") } + describe 'generate_and_link_secret_token' do + let(:secret_file) { 'tmp/tests/.secret_shell_test' } + let(:link_file) { 'tmp/tests/shell-secret-test/.gitlab_shell_secret' } + + before do + allow(Gitlab.config.gitlab_shell).to receive(:path).and_return('tmp/tests/shell-secret-test') + allow(Gitlab.config.gitlab_shell).to receive(:secret_file).and_return(secret_file) + FileUtils.mkdir('tmp/tests/shell-secret-test') + gitlab_shell.generate_and_link_secret_token + end + + after do + FileUtils.rm_rf('tmp/tests/shell-secret-test') + FileUtils.rm_rf(secret_file) + end + + it 'creates and links the secret token file' do + expect(File.exist?(secret_file)).to be(true) + expect(File.symlink?(link_file)).to be(true) + expect(File.readlink(link_file)).to eq(secret_file) + end + end + describe Gitlab::Shell::KeyAdder, lib: true do describe '#add_key' do it 'normalizes space characters in the key' do diff --git a/spec/lib/gitlab/ci/build/artifacts/metadata/entry_spec.rb b/spec/lib/gitlab/ci/build/artifacts/metadata/entry_spec.rb index 711a3e1c7d4..abc93e1b44a 100644 --- a/spec/lib/gitlab/ci/build/artifacts/metadata/entry_spec.rb +++ b/spec/lib/gitlab/ci/build/artifacts/metadata/entry_spec.rb @@ -128,7 +128,6 @@ describe Gitlab::Ci::Build::Artifacts::Metadata::Entry do subject { |example| path(example).children } it { expect(subject.count).to eq 3 } end - end describe 'path/dir_1/subdir/subfile', path: 'path/dir_1/subdir/subfile' do diff --git a/spec/lib/gitlab/current_settings_spec.rb b/spec/lib/gitlab/current_settings_spec.rb new file mode 100644 index 00000000000..004341ffd02 --- /dev/null +++ b/spec/lib/gitlab/current_settings_spec.rb @@ -0,0 +1,36 @@ +require 'spec_helper' + +describe Gitlab::CurrentSettings do + describe '#current_application_settings' do + it 'attempts to use cached values first' do + allow_any_instance_of(Gitlab::CurrentSettings).to receive(:connect_to_db?).and_return(true) + expect(ApplicationSetting).to receive(:current).and_return(::ApplicationSetting.create_from_defaults) + expect(ApplicationSetting).not_to receive(:last) + + expect(current_application_settings).to be_a(ApplicationSetting) + end + + it 'does not attempt to connect to DB or Redis' do + allow_any_instance_of(Gitlab::CurrentSettings).to receive(:connect_to_db?).and_return(false) + expect(ApplicationSetting).not_to receive(:current) + expect(ApplicationSetting).not_to receive(:last) + + expect(current_application_settings).to eq fake_application_settings + end + + it 'falls back to DB if Redis returns an empty value' do + allow_any_instance_of(Gitlab::CurrentSettings).to receive(:connect_to_db?).and_return(true) + expect(ApplicationSetting).to receive(:last).and_call_original + + expect(current_application_settings).to be_a(ApplicationSetting) + end + + it 'falls back to DB if Redis fails' do + allow_any_instance_of(Gitlab::CurrentSettings).to receive(:connect_to_db?).and_return(true) + expect(ApplicationSetting).to receive(:current).and_raise(::Redis::BaseError) + expect(ApplicationSetting).to receive(:last).and_call_original + + expect(current_application_settings).to be_a(ApplicationSetting) + end + end +end diff --git a/spec/lib/gitlab/diff/inline_diff_marker_spec.rb b/spec/lib/gitlab/diff/inline_diff_marker_spec.rb index ea5c31011f0..198ff977f24 100644 --- a/spec/lib/gitlab/diff/inline_diff_marker_spec.rb +++ b/spec/lib/gitlab/diff/inline_diff_marker_spec.rb @@ -2,7 +2,6 @@ require 'spec_helper' describe Gitlab::Diff::InlineDiffMarker, lib: true do describe '#inline_diffs' do - context "when the rich text is html safe" do let(:raw) { "abc 'def'" } let(:rich) { %{<span class="abc">abc</span><span class="space"> </span><span class="def">'def'</span>}.html_safe } diff --git a/spec/lib/gitlab/fogbugz_import/client_spec.rb b/spec/lib/gitlab/fogbugz_import/client_spec.rb index 2dc71be0254..252cd4c55c7 100644 --- a/spec/lib/gitlab/fogbugz_import/client_spec.rb +++ b/spec/lib/gitlab/fogbugz_import/client_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' describe Gitlab::FogbugzImport::Client, lib: true do - let(:client) { described_class.new(uri: '', token: '') } let(:one_user) { { 'people' => { 'person' => { "ixPerson" => "2", "sFullName" => "James" } } } } let(:two_users) { { 'people' => { 'person' => [one_user, { "ixPerson" => "3" }] } } } diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb index 9b3a0e3a75f..9b7986fa12d 100644 --- a/spec/lib/gitlab/git_access_spec.rb +++ b/spec/lib/gitlab/git_access_spec.rb @@ -65,7 +65,6 @@ describe Gitlab::GitAccess, lib: true do expect(access.can_push_to_branch?(@branch.name)).to be_falsey end end - end describe 'download_access_check' do diff --git a/spec/lib/gitlab/github_import/client_spec.rb b/spec/lib/gitlab/github_import/client_spec.rb index 7c21cbe96d9..3b023a35446 100644 --- a/spec/lib/gitlab/github_import/client_spec.rb +++ b/spec/lib/gitlab/github_import/client_spec.rb @@ -20,6 +20,20 @@ describe Gitlab::GithubImport::Client, lib: true do expect { client.api }.not_to raise_error end + context 'when config is missing' do + before do + allow(Gitlab.config.omniauth).to receive(:providers).and_return([]) + end + + it 'is still possible to get an Octokit client' do + expect { client.api }.not_to raise_error + end + + it 'is not be possible to get an OAuth2 client' do + expect { client.client }.to raise_error(Projects::ImportService::Error) + end + end + context 'allow SSL verification to be configurable on API' do before do github_provider['verify_ssl'] = false diff --git a/spec/lib/gitlab/github_import/label_formatter_spec.rb b/spec/lib/gitlab/github_import/label_formatter_spec.rb index e94440a7fb0..87593e32db0 100644 --- a/spec/lib/gitlab/github_import/label_formatter_spec.rb +++ b/spec/lib/gitlab/github_import/label_formatter_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' describe Gitlab::GithubImport::LabelFormatter, lib: true do - describe '#attributes' do it 'returns formatted attributes' do project = create(:project) diff --git a/spec/lib/gitlab/google_code_import/importer_spec.rb b/spec/lib/gitlab/google_code_import/importer_spec.rb index 647631271e0..54f85f8cffc 100644 --- a/spec/lib/gitlab/google_code_import/importer_spec.rb +++ b/spec/lib/gitlab/google_code_import/importer_spec.rb @@ -19,7 +19,6 @@ describe Gitlab::GoogleCodeImport::Importer, lib: true do end describe "#execute" do - it "imports status labels" do subject.execute diff --git a/spec/lib/gitlab/import_export/members_mapper_spec.rb b/spec/lib/gitlab/import_export/members_mapper_spec.rb index f135a285dfb..6d5aa0d04a2 100644 --- a/spec/lib/gitlab/import_export/members_mapper_spec.rb +++ b/spec/lib/gitlab/import_export/members_mapper_spec.rb @@ -2,7 +2,6 @@ require 'spec_helper' describe Gitlab::ImportExport::MembersMapper, services: true do describe 'map members' do - let(:user) { create(:user) } let(:project) { create(:project, :public, name: 'searchable_project') } let(:user2) { create(:user) } diff --git a/spec/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json index 403bd582ef3..0b30e8c9b04 100644 --- a/spec/lib/gitlab/import_export/project.json +++ b/spec/lib/gitlab/import_export/project.json @@ -1,62 +1,63 @@ { - "name": "Gitlab Test", - "path": "gitlab-test", - "description": "Aut saepe in eos dolorem aliquam hic.", + "description": "Nisi et repellendus ut enim quo accusamus vel magnam.", "issues_enabled": true, "merge_requests_enabled": true, "wiki_enabled": true, "snippets_enabled": false, - "visibility_level": 20, + "visibility_level": 10, "archived": false, "issues": [ { "id": 40, - "title": "Voluptatem modi rerum ipsum vero voluptas repudiandae veniam quibusdam.", + "title": "Voluptatem amet doloribus deleniti eos maxime repudiandae molestias.", "assignee_id": 1, - "author_id": 4, + "author_id": 22, "project_id": 5, - "created_at": "2016-03-22T15:13:28.411Z", - "updated_at": "2016-04-12T13:08:26.029Z", + "created_at": "2016-06-14T15:02:08.340Z", + "updated_at": "2016-06-14T15:02:47.967Z", "position": 0, "branch_name": null, - "description": "Aut minima non sit qui nulla rerum laborum.", - "milestone_id": 10, + "description": "Aliquam enim illo et possimus.", + "milestone_id": 18, "state": "opened", "iid": 10, "updated_by_id": null, "confidential": false, "deleted_at": null, - "moved_to_id": null, "due_date": null, + "moved_to_id": null, "notes": [ { - "id": 1357, - "note": "test", + "id": 351, + "note": "Quo reprehenderit aliquam qui dicta impedit cupiditate eligendi.", "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-04-12T13:08:26.006Z", - "updated_at": "2016-04-12T13:08:26.006Z", + "author_id": 26, + "created_at": "2016-06-14T15:02:47.770Z", + "updated_at": "2016-06-14T15:02:47.770Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, - "commit_id": "", + "commit_id": null, "noteable_id": 40, "system": false, "st_diff": null, "updated_by_id": null, "author": { - "name": "Administrator" - } + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 338, - "note": "Fugit in aliquid voluptas dolor.", + "id": 352, + "note": "Est reprehenderit quas aut aspernatur autem recusandae voluptatem.", "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-03-22T15:19:59.213Z", - "updated_at": "2016-03-22T15:19:59.213Z", + "author_id": 25, + "created_at": "2016-06-14T15:02:47.795Z", + "updated_at": "2016-06-14T15:02:47.795Z", "project_id": 5, "attachment": { "url": null @@ -68,16 +69,19 @@ "st_diff": null, "updated_by_id": null, "author": { - "name": "Administrator" - } + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 337, - "note": "Occaecati consequatur facilis doloribus omnis hic placeat nihil.", + "id": 353, + "note": "Perspiciatis suscipit voluptates in eius nihil.", "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:19:59.186Z", - "updated_at": "2016-03-22T15:19:59.186Z", + "author_id": 22, + "created_at": "2016-06-14T15:02:47.823Z", + "updated_at": "2016-06-14T15:02:47.823Z", "project_id": 5, "attachment": { "url": null @@ -89,16 +93,19 @@ "st_diff": null, "updated_by_id": null, "author": { - "name": "Alexie Trantow" - } + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 336, - "note": "Nostrum et et est repudiandae non dolores voluptatem.", + "id": 354, + "note": "Aut vel voluptas corrupti nisi provident laboriosam magnam aut.", "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:19:59.156Z", - "updated_at": "2016-03-22T15:19:59.156Z", + "author_id": 20, + "created_at": "2016-06-14T15:02:47.850Z", + "updated_at": "2016-06-14T15:02:47.850Z", "project_id": 5, "attachment": { "url": null @@ -110,37 +117,19 @@ "st_diff": null, "updated_by_id": null, "author": { - "name": "Julius Moore" - } - }, - { - "id": 335, - "note": "Nihil et aut dolorum aut sit maxime.", - "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:19:59.130Z", - "updated_at": "2016-03-22T15:19:59.130Z", - "project_id": 5, - "attachment": { - "url": null + "name": "Ottis Schuster II" }, - "line_code": null, - "commit_id": null, - "noteable_id": 40, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "events": [ + + ] }, { - "id": 334, - "note": "Non blanditiis voluptatem sit earum accusantium distinctio voluptas officiis.", + "id": 355, + "note": "Officia dolore consequatur in saepe cum magni.", "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:19:59.101Z", - "updated_at": "2016-03-22T15:19:59.101Z", + "author_id": 16, + "created_at": "2016-06-14T15:02:47.876Z", + "updated_at": "2016-06-14T15:02:47.876Z", "project_id": 5, "attachment": { "url": null @@ -151,17 +140,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 333, - "note": "Nesciunt non dolorem similique nam ipsa et.", + "id": 356, + "note": "Cum ipsum rem voluptas eaque et ea.", "noteable_type": "Issue", - "author_id": 22, - "created_at": "2016-03-22T15:19:59.075Z", - "updated_at": "2016-03-22T15:19:59.075Z", + "author_id": 15, + "created_at": "2016-06-14T15:02:47.908Z", + "updated_at": "2016-06-14T15:02:47.908Z", "project_id": 5, "attachment": { "url": null @@ -172,17 +164,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 332, - "note": "Sed aut fugit et officiis dolor.", + "id": 357, + "note": "Recusandae excepturi asperiores suscipit autem nostrum.", "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:19:59.047Z", - "updated_at": "2016-03-22T15:19:59.047Z", + "author_id": 6, + "created_at": "2016-06-14T15:02:47.937Z", + "updated_at": "2016-06-14T15:02:47.937Z", "project_id": 5, "attachment": { "url": null @@ -193,17 +188,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 331, - "note": "Officiis iste eum recusandae suscipit consequatur consequatur.", + "id": 358, + "note": "Et hic est id similique et non nesciunt voluptate.", "noteable_type": "Issue", - "author_id": 26, - "created_at": "2016-03-22T15:19:59.015Z", - "updated_at": "2016-03-22T15:19:59.015Z", + "author_id": 1, + "created_at": "2016-06-14T15:02:47.965Z", + "updated_at": "2016-06-14T15:02:47.965Z", "project_id": 5, "attachment": { "url": null @@ -214,39 +212,42 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ] }, { "id": 39, - "title": "Sit ut adipisci sint temporibus velit quis.", - "assignee_id": 1, - "author_id": 12, + "title": "Delectus veniam ratione in eos culpa et natus molestiae earum aut.", + "assignee_id": 20, + "author_id": 22, "project_id": 5, - "created_at": "2016-03-22T15:13:28.278Z", - "updated_at": "2016-03-22T15:19:59.473Z", + "created_at": "2016-06-14T15:02:08.233Z", + "updated_at": "2016-06-14T15:02:48.194Z", "position": 0, "branch_name": null, - "description": "Ab sint nostrum aliquam laudantium magni recusandae qui.", - "milestone_id": 10, - "state": "closed", + "description": "Voluptate vel reprehenderit facilis omnis voluptas magnam tenetur.", + "milestone_id": 16, + "state": "opened", "iid": 9, "updated_by_id": null, "confidential": false, "deleted_at": null, - "moved_to_id": null, "due_date": null, + "moved_to_id": null, "notes": [ { - "id": 346, - "note": "Natus rerum qui dolorem dolorum voluptas.", + "id": 359, + "note": "Quo eius velit quia et id quam.", "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-03-22T15:19:59.469Z", - "updated_at": "2016-03-22T15:19:59.469Z", + "author_id": 26, + "created_at": "2016-06-14T15:02:48.009Z", + "updated_at": "2016-06-14T15:02:48.009Z", "project_id": 5, "attachment": { "url": null @@ -257,17 +258,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 345, - "note": "Voluptatibus et qui quis id sed necessitatibus quos.", + "id": 360, + "note": "Nulla commodi ratione cumque id autem.", "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:19:59.438Z", - "updated_at": "2016-03-22T15:19:59.438Z", + "author_id": 25, + "created_at": "2016-06-14T15:02:48.032Z", + "updated_at": "2016-06-14T15:02:48.032Z", "project_id": 5, "attachment": { "url": null @@ -278,17 +282,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 344, - "note": "Aperiam possimus ipsam quibusdam in.", + "id": 361, + "note": "Illum non ea sed dolores corrupti.", "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:19:59.410Z", - "updated_at": "2016-03-22T15:19:59.410Z", + "author_id": 22, + "created_at": "2016-06-14T15:02:48.056Z", + "updated_at": "2016-06-14T15:02:48.056Z", "project_id": 5, "attachment": { "url": null @@ -299,17 +306,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 343, - "note": "Ad vel hic molestiae tempora.", + "id": 362, + "note": "Facere dolores ipsum dolorum maiores omnis occaecati ab.", "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:19:59.379Z", - "updated_at": "2016-03-22T15:19:59.379Z", + "author_id": 20, + "created_at": "2016-06-14T15:02:48.082Z", + "updated_at": "2016-06-14T15:02:48.082Z", "project_id": 5, "attachment": { "url": null @@ -320,17 +330,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 342, - "note": "Vel magnam sed quidem aut molestiae facilis alias.", + "id": 363, + "note": "Quod laudantium similique sint aut est ducimus.", "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:19:59.348Z", - "updated_at": "2016-03-22T15:19:59.348Z", + "author_id": 16, + "created_at": "2016-06-14T15:02:48.113Z", + "updated_at": "2016-06-14T15:02:48.113Z", "project_id": 5, "attachment": { "url": null @@ -341,17 +354,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 341, - "note": "Veritatis dolorum aut qui quod.", + "id": 364, + "note": "Aut omnis eos esse incidunt vero reiciendis.", "noteable_type": "Issue", - "author_id": 22, - "created_at": "2016-03-22T15:19:59.319Z", - "updated_at": "2016-03-22T15:19:59.319Z", + "author_id": 15, + "created_at": "2016-06-14T15:02:48.139Z", + "updated_at": "2016-06-14T15:02:48.139Z", "project_id": 5, "attachment": { "url": null @@ -362,17 +378,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 340, - "note": "Illum at cumque dolorum et quia.", + "id": 365, + "note": "Beatae dolore et doloremque asperiores sunt.", "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:19:59.289Z", - "updated_at": "2016-03-22T15:19:59.289Z", + "author_id": 6, + "created_at": "2016-06-14T15:02:48.162Z", + "updated_at": "2016-06-14T15:02:48.162Z", "project_id": 5, "attachment": { "url": null @@ -383,17 +402,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 339, - "note": "Fugiat et error molestiae cumque quos aperiam.", + "id": 366, + "note": "Doloribus ipsam ex delectus rerum libero recusandae modi repellendus.", "noteable_type": "Issue", - "author_id": 26, - "created_at": "2016-03-22T15:19:59.255Z", - "updated_at": "2016-03-22T15:19:59.255Z", + "author_id": 1, + "created_at": "2016-06-14T15:02:48.192Z", + "updated_at": "2016-06-14T15:02:48.192Z", "project_id": 5, "attachment": { "url": null @@ -404,39 +426,42 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ] }, { "id": 38, - "title": "Quod quo est quis vel natus nulla eos reiciendis.", - "assignee_id": 12, - "author_id": 3, + "title": "Quasi adipisci non cupiditate dolorem quo qui earum sed.", + "assignee_id": 1, + "author_id": 6, "project_id": 5, - "created_at": "2016-03-22T15:13:28.137Z", - "updated_at": "2016-03-22T15:19:59.712Z", + "created_at": "2016-06-14T15:02:08.154Z", + "updated_at": "2016-06-14T15:02:48.614Z", "position": 0, "branch_name": null, - "description": "Fugit dolor accusantium suscipit facere voluptate.", - "milestone_id": 10, - "state": "opened", + "description": "Ea recusandae neque autem tempora.", + "milestone_id": 16, + "state": "closed", "iid": 8, "updated_by_id": null, "confidential": false, "deleted_at": null, - "moved_to_id": null, "due_date": null, + "moved_to_id": null, "notes": [ { - "id": 354, - "note": "Id commodi natus vel corrupti ea placeat cum nihil.", + "id": 367, + "note": "Accusantium fugiat et eaque quisquam esse corporis.", "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-03-22T15:19:59.708Z", - "updated_at": "2016-03-22T15:19:59.708Z", + "author_id": 26, + "created_at": "2016-06-14T15:02:48.235Z", + "updated_at": "2016-06-14T15:02:48.235Z", "project_id": 5, "attachment": { "url": null @@ -447,17 +472,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 353, - "note": "Quia hic sed ratione eos voluptate dolor occaecati dolorem.", + "id": 368, + "note": "Ea labore eum nam qui laboriosam.", "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:19:59.680Z", - "updated_at": "2016-03-22T15:19:59.680Z", + "author_id": 25, + "created_at": "2016-06-14T15:02:48.261Z", + "updated_at": "2016-06-14T15:02:48.261Z", "project_id": 5, "attachment": { "url": null @@ -468,17 +496,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 352, - "note": "Commodi sint voluptatem est aut.", + "id": 369, + "note": "Accusantium quis sed molestiae et.", "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:19:59.650Z", - "updated_at": "2016-03-22T15:19:59.650Z", + "author_id": 22, + "created_at": "2016-06-14T15:02:48.294Z", + "updated_at": "2016-06-14T15:02:48.294Z", "project_id": 5, "attachment": { "url": null @@ -489,17 +520,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 351, - "note": "Et quibusdam voluptatibus dolores aut quam architecto optio.", + "id": 370, + "note": "Corporis numquam a voluptatem pariatur asperiores dolorem delectus autem.", "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:19:59.622Z", - "updated_at": "2016-03-22T15:19:59.622Z", + "author_id": 20, + "created_at": "2016-06-14T15:02:48.523Z", + "updated_at": "2016-06-14T15:02:48.523Z", "project_id": 5, "attachment": { "url": null @@ -510,17 +544,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 350, - "note": "Fugit natus explicabo sed pariatur et quasi autem.", + "id": 371, + "note": "Ea accusantium maxime voluptas rerum.", "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:19:59.590Z", - "updated_at": "2016-03-22T15:19:59.590Z", + "author_id": 16, + "created_at": "2016-06-14T15:02:48.546Z", + "updated_at": "2016-06-14T15:02:48.546Z", "project_id": 5, "attachment": { "url": null @@ -531,17 +568,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 349, - "note": "Corporis commodi eos quia optio sunt corrupti.", + "id": 372, + "note": "Pariatur iusto et et excepturi similique ipsam eum.", "noteable_type": "Issue", - "author_id": 22, - "created_at": "2016-03-22T15:19:59.562Z", - "updated_at": "2016-03-22T15:19:59.562Z", + "author_id": 15, + "created_at": "2016-06-14T15:02:48.569Z", + "updated_at": "2016-06-14T15:02:48.569Z", "project_id": 5, "attachment": { "url": null @@ -552,17 +592,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 348, - "note": "Occaecati nostrum hic dolor tenetur aliquid maxime animi.", + "id": 373, + "note": "Aliquam et culpa officia iste eius.", "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:19:59.536Z", - "updated_at": "2016-03-22T15:19:59.536Z", + "author_id": 6, + "created_at": "2016-06-14T15:02:48.591Z", + "updated_at": "2016-06-14T15:02:48.591Z", "project_id": 5, "attachment": { "url": null @@ -573,17 +616,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 347, - "note": "Inventore ullam sed repellendus laudantium itaque et quia.", + "id": 374, + "note": "Ab id velit id unde laborum.", "noteable_type": "Issue", - "author_id": 26, - "created_at": "2016-03-22T15:19:59.506Z", - "updated_at": "2016-03-22T15:19:59.506Z", + "author_id": 1, + "created_at": "2016-06-14T15:02:48.613Z", + "updated_at": "2016-06-14T15:02:48.613Z", "project_id": 5, "attachment": { "url": null @@ -594,39 +640,42 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ] }, { "id": 37, - "title": "Animi suscipit quia ut hic asperiores perferendis nisi ut.", - "assignee_id": 22, - "author_id": 10, + "title": "Cupiditate quo aut ducimus minima molestiae vero numquam possimus.", + "assignee_id": 15, + "author_id": 20, "project_id": 5, - "created_at": "2016-03-22T15:13:27.994Z", - "updated_at": "2016-03-22T15:19:59.972Z", + "created_at": "2016-06-14T15:02:08.051Z", + "updated_at": "2016-06-14T15:02:48.854Z", "position": 0, "branch_name": null, - "description": "Non quibusdam in maxime earum eveniet itaque culpa.", - "milestone_id": 11, - "state": "closed", + "description": "Maiores architecto quos in dolorem.", + "milestone_id": 17, + "state": "opened", "iid": 7, "updated_by_id": null, "confidential": false, "deleted_at": null, - "moved_to_id": null, "due_date": null, + "moved_to_id": null, "notes": [ { - "id": 362, - "note": "Quia qui quis molestiae in praesentium.", + "id": 375, + "note": "Quasi fugit qui sed eligendi aut quia.", "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-03-22T15:19:59.966Z", - "updated_at": "2016-03-22T15:19:59.966Z", + "author_id": 26, + "created_at": "2016-06-14T15:02:48.647Z", + "updated_at": "2016-06-14T15:02:48.647Z", "project_id": 5, "attachment": { "url": null @@ -637,17 +686,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 361, - "note": "Maxime sed eius qui consequatur beatae.", + "id": 376, + "note": "Esse nesciunt voluptatem ex vero est consequatur.", "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:19:59.924Z", - "updated_at": "2016-03-22T15:19:59.924Z", + "author_id": 25, + "created_at": "2016-06-14T15:02:48.674Z", + "updated_at": "2016-06-14T15:02:48.674Z", "project_id": 5, "attachment": { "url": null @@ -658,17 +710,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 360, - "note": "Voluptatum quasi corrupti eveniet sed ut quis quibusdam.", + "id": 377, + "note": "Similique qui quas non aut et velit sequi in.", "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:19:59.897Z", - "updated_at": "2016-03-22T15:19:59.897Z", + "author_id": 22, + "created_at": "2016-06-14T15:02:48.696Z", + "updated_at": "2016-06-14T15:02:48.696Z", "project_id": 5, "attachment": { "url": null @@ -679,17 +734,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 359, - "note": "Molestias quia eius ipsum non.", + "id": 378, + "note": "Eveniet ut cupiditate repellendus numquam in esse eius.", "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:19:59.866Z", - "updated_at": "2016-03-22T15:19:59.866Z", + "author_id": 20, + "created_at": "2016-06-14T15:02:48.720Z", + "updated_at": "2016-06-14T15:02:48.720Z", "project_id": 5, "attachment": { "url": null @@ -700,17 +758,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 358, - "note": "Aut non est accusantium aliquam.", + "id": 379, + "note": "Velit est dolorem adipisci rerum sed iure.", "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:19:59.834Z", - "updated_at": "2016-03-22T15:19:59.834Z", + "author_id": 16, + "created_at": "2016-06-14T15:02:48.755Z", + "updated_at": "2016-06-14T15:02:48.755Z", "project_id": 5, "attachment": { "url": null @@ -721,17 +782,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 357, - "note": "Aspernatur voluptas id voluptas vel cum ipsam.", + "id": 380, + "note": "Voluptatem ullam ab ut illo ut quo.", "noteable_type": "Issue", - "author_id": 22, - "created_at": "2016-03-22T15:19:59.805Z", - "updated_at": "2016-03-22T15:19:59.805Z", + "author_id": 15, + "created_at": "2016-06-14T15:02:48.793Z", + "updated_at": "2016-06-14T15:02:48.793Z", "project_id": 5, "attachment": { "url": null @@ -742,17 +806,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 356, - "note": "Harum dignissimos provident tempora sit numquam est qui.", + "id": 381, + "note": "Voluptatem impedit beatae quasi ipsa earum consectetur.", "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:19:59.773Z", - "updated_at": "2016-03-22T15:19:59.773Z", + "author_id": 6, + "created_at": "2016-06-14T15:02:48.823Z", + "updated_at": "2016-06-14T15:02:48.823Z", "project_id": 5, "attachment": { "url": null @@ -763,17 +830,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 355, - "note": "Sint dignissimos molestiae recusandae delectus.", + "id": 382, + "note": "Nihil officiis eaque incidunt sunt voluptatum excepturi.", "noteable_type": "Issue", - "author_id": 26, - "created_at": "2016-03-22T15:19:59.746Z", - "updated_at": "2016-03-22T15:19:59.746Z", + "author_id": 1, + "created_at": "2016-06-14T15:02:48.852Z", + "updated_at": "2016-06-14T15:02:48.852Z", "project_id": 5, "attachment": { "url": null @@ -784,39 +854,42 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ] }, { "id": 36, - "title": "Quia dolores commodi eligendi ut nemo totam.", - "assignee_id": 3, - "author_id": 4, + "title": "Necessitatibus dolor est enim quia rem suscipit quidem voluptas ullam.", + "assignee_id": 20, + "author_id": 16, "project_id": 5, - "created_at": "2016-03-22T15:13:27.814Z", - "updated_at": "2016-03-22T15:20:00.371Z", + "created_at": "2016-06-14T15:02:07.958Z", + "updated_at": "2016-06-14T15:02:49.044Z", "position": 0, "branch_name": null, - "description": "Molestiae veniam laudantium autem et natus.", - "milestone_id": 11, + "description": "Ut aut ut et tenetur velit aut id modi.", + "milestone_id": 16, "state": "opened", "iid": 6, "updated_by_id": null, "confidential": false, "deleted_at": null, - "moved_to_id": null, "due_date": null, + "moved_to_id": null, "notes": [ { - "id": 370, - "note": "Occaecati temporibus tempore harum vero incidunt veniam iste.", + "id": 383, + "note": "Excepturi deleniti sunt rerum nesciunt vero fugiat possimus.", "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-03-22T15:20:00.365Z", - "updated_at": "2016-03-22T15:20:00.365Z", + "author_id": 26, + "created_at": "2016-06-14T15:02:48.885Z", + "updated_at": "2016-06-14T15:02:48.885Z", "project_id": 5, "attachment": { "url": null @@ -827,17 +900,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 369, - "note": "Modi architecto officiis quia iste voluptas libero nihil quo.", + "id": 384, + "note": "Et est nemo sed nam sed.", "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:20:00.331Z", - "updated_at": "2016-03-22T15:20:00.331Z", + "author_id": 25, + "created_at": "2016-06-14T15:02:48.910Z", + "updated_at": "2016-06-14T15:02:48.910Z", "project_id": 5, "attachment": { "url": null @@ -848,17 +924,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 368, - "note": "Eaque est tenetur ex est molestiae nobis.", + "id": 385, + "note": "Animi mollitia nulla facere amet aut quaerat.", "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:20:00.296Z", - "updated_at": "2016-03-22T15:20:00.296Z", + "author_id": 22, + "created_at": "2016-06-14T15:02:48.934Z", + "updated_at": "2016-06-14T15:02:48.934Z", "project_id": 5, "attachment": { "url": null @@ -869,17 +948,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 367, - "note": "Odit enim ut a quo qui.", + "id": 386, + "note": "Excepturi id voluptas ut odio officiis omnis.", "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:20:00.261Z", - "updated_at": "2016-03-22T15:20:00.261Z", + "author_id": 20, + "created_at": "2016-06-14T15:02:48.955Z", + "updated_at": "2016-06-14T15:02:48.955Z", "project_id": 5, "attachment": { "url": null @@ -890,17 +972,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 366, - "note": "Omnis unde cum officiis est.", + "id": 387, + "note": "Molestiae labore officiis magni et eligendi quasi maxime.", "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:20:00.223Z", - "updated_at": "2016-03-22T15:20:00.223Z", + "author_id": 16, + "created_at": "2016-06-14T15:02:48.978Z", + "updated_at": "2016-06-14T15:02:48.978Z", "project_id": 5, "attachment": { "url": null @@ -911,17 +996,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 365, - "note": "Ab consequuntur aliquam illo voluptatum.", + "id": 388, + "note": "Officia tenetur praesentium rem nam non.", "noteable_type": "Issue", - "author_id": 22, - "created_at": "2016-03-22T15:20:00.178Z", - "updated_at": "2016-03-22T15:20:00.178Z", + "author_id": 15, + "created_at": "2016-06-14T15:02:49.001Z", + "updated_at": "2016-06-14T15:02:49.001Z", "project_id": 5, "attachment": { "url": null @@ -932,17 +1020,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 364, - "note": "Molestiae dolorem est eos dolores aut.", + "id": 389, + "note": "Et et et molestiae reprehenderit.", "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:20:00.127Z", - "updated_at": "2016-03-22T15:20:00.127Z", + "author_id": 6, + "created_at": "2016-06-14T15:02:49.022Z", + "updated_at": "2016-06-14T15:02:49.022Z", "project_id": 5, "attachment": { "url": null @@ -953,17 +1044,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 363, - "note": "Nemo velit nam quod veniam.", + "id": 390, + "note": "Aperiam in consequatur est sunt cum quia.", "noteable_type": "Issue", - "author_id": 26, - "created_at": "2016-03-22T15:20:00.083Z", - "updated_at": "2016-03-22T15:20:00.083Z", + "author_id": 1, + "created_at": "2016-06-14T15:02:49.043Z", + "updated_at": "2016-06-14T15:02:49.043Z", "project_id": 5, "attachment": { "url": null @@ -974,39 +1068,42 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ] }, { "id": 35, - "title": "Rerum tenetur harum molestiae quam aut praesentium quaerat doloremque.", - "assignee_id": 4, - "author_id": 1, + "title": "Repellat praesentium deserunt maxime incidunt harum porro qui.", + "assignee_id": 6, + "author_id": 20, "project_id": 5, - "created_at": "2016-03-22T15:13:27.660Z", - "updated_at": "2016-03-22T15:20:00.665Z", + "created_at": "2016-06-14T15:02:07.832Z", + "updated_at": "2016-06-14T15:02:49.226Z", "position": 0, "branch_name": null, - "description": "Omnis et voluptatibus expedita qui et explicabo rem ut.", - "milestone_id": 11, - "state": "opened", + "description": "Dicta nisi nihil non ipsa velit.", + "milestone_id": 20, + "state": "closed", "iid": 5, "updated_by_id": null, "confidential": false, "deleted_at": null, - "moved_to_id": null, "due_date": null, + "moved_to_id": null, "notes": [ { - "id": 378, - "note": "Molestiae atque exercitationem culpa harum nemo.", + "id": 391, + "note": "Qui magnam et assumenda quod id dicta necessitatibus.", "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-03-22T15:20:00.660Z", - "updated_at": "2016-03-22T15:20:00.660Z", + "author_id": 26, + "created_at": "2016-06-14T15:02:49.075Z", + "updated_at": "2016-06-14T15:02:49.075Z", "project_id": 5, "attachment": { "url": null @@ -1017,17 +1114,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 377, - "note": "Porro sed nobis neque amet velit velit.", + "id": 392, + "note": "Consectetur deserunt possimus dolor est odio.", "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:20:00.625Z", - "updated_at": "2016-03-22T15:20:00.625Z", + "author_id": 25, + "created_at": "2016-06-14T15:02:49.095Z", + "updated_at": "2016-06-14T15:02:49.095Z", "project_id": 5, "attachment": { "url": null @@ -1038,17 +1138,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 376, - "note": "Dicta officiis doloremque voluptatum qui omnis.", + "id": 393, + "note": "Labore nisi quo cumque voluptas consequatur aut qui.", "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:20:00.589Z", - "updated_at": "2016-03-22T15:20:00.589Z", + "author_id": 22, + "created_at": "2016-06-14T15:02:49.117Z", + "updated_at": "2016-06-14T15:02:49.117Z", "project_id": 5, "attachment": { "url": null @@ -1059,17 +1162,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 375, - "note": "Incidunt rerum omnis cum laudantium aut impedit.", + "id": 394, + "note": "Et totam facilis voluptas et enim.", "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:20:00.553Z", - "updated_at": "2016-03-22T15:20:00.553Z", + "author_id": 20, + "created_at": "2016-06-14T15:02:49.138Z", + "updated_at": "2016-06-14T15:02:49.138Z", "project_id": 5, "attachment": { "url": null @@ -1080,17 +1186,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 374, - "note": "Et suscipit omnis dolorum officia vero.", + "id": 395, + "note": "Ratione sint pariatur sed omnis eligendi quo libero exercitationem.", "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:20:00.517Z", - "updated_at": "2016-03-22T15:20:00.517Z", + "author_id": 16, + "created_at": "2016-06-14T15:02:49.160Z", + "updated_at": "2016-06-14T15:02:49.160Z", "project_id": 5, "attachment": { "url": null @@ -1101,17 +1210,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 373, - "note": "Doloremque adipisci et cumque inventore beatae consectetur.", + "id": 396, + "note": "Iure hic autem id voluptatem.", "noteable_type": "Issue", - "author_id": 22, - "created_at": "2016-03-22T15:20:00.485Z", - "updated_at": "2016-03-22T15:20:00.485Z", + "author_id": 15, + "created_at": "2016-06-14T15:02:49.182Z", + "updated_at": "2016-06-14T15:02:49.182Z", "project_id": 5, "attachment": { "url": null @@ -1122,17 +1234,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 372, - "note": "Dolores sapiente ea dolorum et quae adipisci id.", + "id": 397, + "note": "Excepturi eum laboriosam delectus repellendus odio nisi et voluptatem.", "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:20:00.455Z", - "updated_at": "2016-03-22T15:20:00.455Z", + "author_id": 6, + "created_at": "2016-06-14T15:02:49.205Z", + "updated_at": "2016-06-14T15:02:49.205Z", "project_id": 5, "attachment": { "url": null @@ -1143,17 +1258,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 371, - "note": "Accusantium repellat tenetur natus dicta ullam saepe facere.", + "id": 398, + "note": "Ut quis ex soluta consequatur et blanditiis.", "noteable_type": "Issue", - "author_id": 26, - "created_at": "2016-03-22T15:20:00.420Z", - "updated_at": "2016-03-22T15:20:00.420Z", + "author_id": 1, + "created_at": "2016-06-14T15:02:49.225Z", + "updated_at": "2016-06-14T15:02:49.225Z", "project_id": 5, "attachment": { "url": null @@ -1164,39 +1282,42 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ] }, { "id": 34, - "title": "Enim occaecati aut sed quia mollitia eligendi atque dolores voluptatem.", - "assignee_id": 24, + "title": "Ullam expedita deserunt libero consequatur quia dolor harum perferendis facere quidem.", + "assignee_id": 20, "author_id": 1, "project_id": 5, - "created_at": "2016-03-22T15:13:27.506Z", - "updated_at": "2016-03-22T15:20:00.961Z", + "created_at": "2016-06-14T15:02:07.717Z", + "updated_at": "2016-06-14T15:02:49.416Z", "position": 0, "branch_name": null, - "description": "Voluptatem totam magnam fugit assumenda consequatur illo qui.", - "milestone_id": 10, - "state": "opened", + "description": "Ut et explicabo vel voluptatem consequuntur ut sed.", + "milestone_id": 19, + "state": "closed", "iid": 4, "updated_by_id": null, "confidential": false, "deleted_at": null, - "moved_to_id": null, "due_date": null, + "moved_to_id": null, "notes": [ { - "id": 379, - "note": "Praesentium odio quia fugit consequuntur repudiandae ducimus.", + "id": 399, + "note": "Dolor iste tempora tenetur non vitae maiores voluptatibus.", "noteable_type": "Issue", "author_id": 26, - "created_at": "2016-03-22T15:20:00.717Z", - "updated_at": "2016-03-22T15:20:00.717Z", + "created_at": "2016-06-14T15:02:49.256Z", + "updated_at": "2016-06-14T15:02:49.256Z", "project_id": 5, "attachment": { "url": null @@ -1207,17 +1328,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { + "author": { "name": "User 4" - } + }, + "events": [ + + ] }, { - "id": 380, - "note": "Dolores aut dolorem quia soluta incidunt commodi quia.", + "id": 400, + "note": "Aut sit quidem qui adipisci maxime excepturi iusto.", "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:20:00.754Z", - "updated_at": "2016-03-22T15:20:00.754Z", + "author_id": 25, + "created_at": "2016-06-14T15:02:49.284Z", + "updated_at": "2016-06-14T15:02:49.284Z", "project_id": 5, "attachment": { "url": null @@ -1228,17 +1352,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 381, - "note": "Enim et velit iure ad.", + "id": 401, + "note": "Et a necessitatibus autem quidem animi sunt voluptatum rerum.", "noteable_type": "Issue", "author_id": 22, - "created_at": "2016-03-22T15:20:00.787Z", - "updated_at": "2016-03-22T15:20:00.787Z", + "created_at": "2016-06-14T15:02:49.305Z", + "updated_at": "2016-06-14T15:02:49.305Z", "project_id": 5, "attachment": { "url": null @@ -1249,17 +1376,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { + "author": { "name": "User 0" - } + }, + "events": [ + + ] }, { - "id": 382, - "note": "Impedit nobis quis laudantium ad assumenda.", + "id": 402, + "note": "Esse laboriosam quo voluptatem quis molestiae.", "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:20:00.822Z", - "updated_at": "2016-03-22T15:20:00.822Z", + "author_id": 20, + "created_at": "2016-06-14T15:02:49.328Z", + "updated_at": "2016-06-14T15:02:49.328Z", "project_id": 5, "attachment": { "url": null @@ -1270,17 +1400,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 383, - "note": "Facere sed numquam quos quas.", + "id": 403, + "note": "Nemo magnam distinctio est ut voluptate ea.", "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:20:00.855Z", - "updated_at": "2016-03-22T15:20:00.855Z", + "author_id": 16, + "created_at": "2016-06-14T15:02:49.350Z", + "updated_at": "2016-06-14T15:02:49.350Z", "project_id": 5, "attachment": { "url": null @@ -1291,17 +1424,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 384, - "note": "Ex voluptatem sit provident error.", + "id": 404, + "note": "Omnis sed rerum neque rerum quae quam nulla officiis.", "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:20:00.889Z", - "updated_at": "2016-03-22T15:20:00.889Z", + "author_id": 15, + "created_at": "2016-06-14T15:02:49.372Z", + "updated_at": "2016-06-14T15:02:49.372Z", "project_id": 5, "attachment": { "url": null @@ -1312,17 +1448,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 385, - "note": "Soluta laboriosam recusandae est cupiditate.", + "id": 405, + "note": "Quo soluta dolorem vitae ad consequatur qui aut dicta.", "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:20:00.925Z", - "updated_at": "2016-03-22T15:20:00.925Z", + "author_id": 6, + "created_at": "2016-06-14T15:02:49.394Z", + "updated_at": "2016-06-14T15:02:49.394Z", "project_id": 5, "attachment": { "url": null @@ -1333,17 +1472,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 386, - "note": "Similique dolorem rerum iusto animi perferendis aut inventore.", + "id": 406, + "note": "Magni minus est aut aut totam ut.", "noteable_type": "Issue", "author_id": 1, - "created_at": "2016-03-22T15:20:00.957Z", - "updated_at": "2016-03-22T15:20:00.957Z", + "created_at": "2016-06-14T15:02:49.414Z", + "updated_at": "2016-06-14T15:02:49.414Z", "project_id": 5, "attachment": { "url": null @@ -1354,39 +1496,42 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { + "author": { "name": "Administrator" - } + }, + "events": [ + + ] } ] }, { "id": 33, - "title": "Rem fugiat fugit occaecati quibusdam enim consectetur numquam.", - "assignee_id": 22, - "author_id": 22, + "title": "Numquam accusamus eos iste exercitationem magni non inventore.", + "assignee_id": 15, + "author_id": 26, "project_id": 5, - "created_at": "2016-03-22T15:13:27.364Z", - "updated_at": "2016-03-22T15:20:01.227Z", + "created_at": "2016-06-14T15:02:07.611Z", + "updated_at": "2016-06-14T15:02:49.661Z", "position": 0, "branch_name": null, - "description": "Provident nulla architecto neque beatae fuga alias repudiandae.", - "milestone_id": 10, + "description": "Non asperiores velit accusantium voluptate.", + "milestone_id": 18, "state": "closed", "iid": 3, "updated_by_id": null, "confidential": false, "deleted_at": null, - "moved_to_id": null, "due_date": null, + "moved_to_id": null, "notes": [ { - "id": 394, - "note": "Suscipit numquam voluptatibus ipsam libero dolorum dolore totam.", + "id": 407, + "note": "Quod ea et possimus architecto.", "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-03-22T15:20:01.223Z", - "updated_at": "2016-03-22T15:20:01.223Z", + "author_id": 26, + "created_at": "2016-06-14T15:02:49.450Z", + "updated_at": "2016-06-14T15:02:49.450Z", "project_id": 5, "attachment": { "url": null @@ -1397,17 +1542,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 393, - "note": "Et et sed sit sint.", + "id": 408, + "note": "Reiciendis est et unde perferendis dicta ut praesentium quasi.", "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:20:01.194Z", - "updated_at": "2016-03-22T15:20:01.194Z", + "author_id": 25, + "created_at": "2016-06-14T15:02:49.503Z", + "updated_at": "2016-06-14T15:02:49.503Z", "project_id": 5, "attachment": { "url": null @@ -1418,17 +1566,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 392, - "note": "Corrupti perferendis voluptas et iure omnis officia.", + "id": 409, + "note": "Magni quia odio blanditiis pariatur voluptas.", "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:20:01.160Z", - "updated_at": "2016-03-22T15:20:01.160Z", + "author_id": 22, + "created_at": "2016-06-14T15:02:49.527Z", + "updated_at": "2016-06-14T15:02:49.527Z", "project_id": 5, "attachment": { "url": null @@ -1439,17 +1590,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 391, - "note": "Autem quo fugit in iste nesciunt tempora.", + "id": 410, + "note": "Enim quam ut et et et.", "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:20:01.131Z", - "updated_at": "2016-03-22T15:20:01.131Z", + "author_id": 20, + "created_at": "2016-06-14T15:02:49.551Z", + "updated_at": "2016-06-14T15:02:49.551Z", "project_id": 5, "attachment": { "url": null @@ -1460,17 +1614,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 390, - "note": "Magni porro ut soluta quis et eveniet maiores.", + "id": 411, + "note": "Fugit voluptatem ratione maxime expedita.", "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:20:01.101Z", - "updated_at": "2016-03-22T15:20:01.101Z", + "author_id": 16, + "created_at": "2016-06-14T15:02:49.578Z", + "updated_at": "2016-06-14T15:02:49.578Z", "project_id": 5, "attachment": { "url": null @@ -1481,17 +1638,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 389, - "note": "Sed consequuntur debitis nisi veniam exercitationem recusandae a quisquam.", + "id": 412, + "note": "Voluptatem enim aut ipsa et et ducimus.", "noteable_type": "Issue", - "author_id": 22, - "created_at": "2016-03-22T15:20:01.070Z", - "updated_at": "2016-03-22T15:20:01.070Z", + "author_id": 15, + "created_at": "2016-06-14T15:02:49.604Z", + "updated_at": "2016-06-14T15:02:49.604Z", "project_id": 5, "attachment": { "url": null @@ -1502,17 +1662,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 388, - "note": "Aut impedit qui consectetur dicta temporibus.", + "id": 413, + "note": "Quia repellat fugiat consectetur quidem.", "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:20:01.042Z", - "updated_at": "2016-03-22T15:20:01.042Z", + "author_id": 6, + "created_at": "2016-06-14T15:02:49.631Z", + "updated_at": "2016-06-14T15:02:49.631Z", "project_id": 5, "attachment": { "url": null @@ -1523,17 +1686,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 387, - "note": "Officia repudiandae ut culpa ipsa reiciendis.", + "id": 414, + "note": "Corporis ipsum et ea necessitatibus quod assumenda repudiandae quam.", "noteable_type": "Issue", - "author_id": 26, - "created_at": "2016-03-22T15:20:01.005Z", - "updated_at": "2016-03-22T15:20:01.005Z", + "author_id": 1, + "created_at": "2016-06-14T15:02:49.659Z", + "updated_at": "2016-06-14T15:02:49.659Z", "project_id": 5, "attachment": { "url": null @@ -1544,39 +1710,42 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ] }, { "id": 32, - "title": "Velit nihil est alias blanditiis eius earum autem hic.", + "title": "Necessitatibus magnam qui at velit consequatur perspiciatis.", "assignee_id": 22, - "author_id": 26, + "author_id": 15, "project_id": 5, - "created_at": "2016-03-22T15:13:27.225Z", - "updated_at": "2016-03-22T15:20:01.495Z", + "created_at": "2016-06-14T15:02:07.431Z", + "updated_at": "2016-06-14T15:02:49.884Z", "position": 0, "branch_name": null, - "description": "Id voluptas ut sint aut laborum nobis commodi.", - "milestone_id": 11, - "state": "opened", + "description": "Molestiae corporis magnam et fugit aliquid nulla quia.", + "milestone_id": 17, + "state": "closed", "iid": 2, "updated_by_id": null, "confidential": false, "deleted_at": null, - "moved_to_id": null, "due_date": null, + "moved_to_id": null, "notes": [ { - "id": 402, - "note": "Magni ut eligendi sit sint recusandae voluptas tempore necessitatibus.", + "id": 415, + "note": "Nemo consequatur sed blanditiis qui id iure dolores.", "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-03-22T15:20:01.489Z", - "updated_at": "2016-03-22T15:20:01.489Z", + "author_id": 26, + "created_at": "2016-06-14T15:02:49.694Z", + "updated_at": "2016-06-14T15:02:49.694Z", "project_id": 5, "attachment": { "url": null @@ -1587,17 +1756,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 401, - "note": "Est repellat commodi incidunt tempore earum optio unde sint.", + "id": 416, + "note": "Voluptas ab accusantium dicta in.", "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:20:01.455Z", - "updated_at": "2016-03-22T15:20:01.455Z", + "author_id": 25, + "created_at": "2016-06-14T15:02:49.718Z", + "updated_at": "2016-06-14T15:02:49.718Z", "project_id": 5, "attachment": { "url": null @@ -1608,17 +1780,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 400, - "note": "Vero unde debitis tempore est laboriosam ut esse.", + "id": 417, + "note": "Esse odit qui a et eum ducimus.", "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:20:01.421Z", - "updated_at": "2016-03-22T15:20:01.421Z", + "author_id": 22, + "created_at": "2016-06-14T15:02:49.741Z", + "updated_at": "2016-06-14T15:02:49.741Z", "project_id": 5, "attachment": { "url": null @@ -1629,17 +1804,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 399, - "note": "Omnis qui asperiores expedita harum voluptatem eius.", + "id": 418, + "note": "Sequi dolor doloribus ratione placeat repellendus.", "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:20:01.391Z", - "updated_at": "2016-03-22T15:20:01.391Z", + "author_id": 20, + "created_at": "2016-06-14T15:02:49.767Z", + "updated_at": "2016-06-14T15:02:49.767Z", "project_id": 5, "attachment": { "url": null @@ -1650,17 +1828,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 398, - "note": "Dolorem doloribus delectus quo ratione esse veritatis.", + "id": 419, + "note": "Quae aspernatur rem est similique.", "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:20:01.358Z", - "updated_at": "2016-03-22T15:20:01.358Z", + "author_id": 16, + "created_at": "2016-06-14T15:02:49.796Z", + "updated_at": "2016-06-14T15:02:49.796Z", "project_id": 5, "attachment": { "url": null @@ -1671,17 +1852,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 397, - "note": "Quia esse et odit id est omnis dolorum quia.", + "id": 420, + "note": "Voluptate omnis et id rerum non nesciunt laudantium assumenda.", "noteable_type": "Issue", - "author_id": 22, - "created_at": "2016-03-22T15:20:01.329Z", - "updated_at": "2016-03-22T15:20:01.329Z", + "author_id": 15, + "created_at": "2016-06-14T15:02:49.825Z", + "updated_at": "2016-06-14T15:02:49.825Z", "project_id": 5, "attachment": { "url": null @@ -1692,17 +1876,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 396, - "note": "Exercitationem suscipit non rerum tempore sit.", + "id": 421, + "note": "Quia enim ab et eligendi.", "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:20:01.297Z", - "updated_at": "2016-03-22T15:20:01.297Z", + "author_id": 6, + "created_at": "2016-06-14T15:02:49.853Z", + "updated_at": "2016-06-14T15:02:49.853Z", "project_id": 5, "attachment": { "url": null @@ -1713,17 +1900,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 395, - "note": "Nihil veniam magni sit officiis.", + "id": 422, + "note": "In fugiat rerum voluptas quas officia.", "noteable_type": "Issue", - "author_id": 26, - "created_at": "2016-03-22T15:20:01.268Z", - "updated_at": "2016-03-22T15:20:01.268Z", + "author_id": 1, + "created_at": "2016-06-14T15:02:49.881Z", + "updated_at": "2016-06-14T15:02:49.881Z", "project_id": 5, "attachment": { "url": null @@ -1734,39 +1924,42 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ] }, { "id": 31, - "title": "Asperiores recusandae praesentium voluptas pariatur provident qui exercitationem quis.", - "assignee_id": 26, - "author_id": 24, + "title": "Libero nam magnam incidunt eaque placeat error et.", + "assignee_id": 1, + "author_id": 16, "project_id": 5, - "created_at": "2016-03-22T15:13:26.889Z", - "updated_at": "2016-03-22T15:20:01.834Z", + "created_at": "2016-06-14T15:02:07.280Z", + "updated_at": "2016-06-14T15:02:50.134Z", "position": 0, "branch_name": null, - "description": "Ex voluptates qui excepturi cupiditate.", - "milestone_id": 11, + "description": "Quod ad architecto qui est sed quia.", + "milestone_id": 20, "state": "closed", "iid": 1, "updated_by_id": null, "confidential": false, "deleted_at": null, - "moved_to_id": null, "due_date": null, + "moved_to_id": null, "notes": [ { - "id": 410, - "note": "Sit itaque non nihil nisi qui voluptatem dolorem error.", + "id": 423, + "note": "A mollitia qui iste consequatur eaque iure omnis sunt.", "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-03-22T15:20:01.828Z", - "updated_at": "2016-03-22T15:20:01.828Z", + "author_id": 26, + "created_at": "2016-06-14T15:02:49.933Z", + "updated_at": "2016-06-14T15:02:49.933Z", "project_id": 5, "attachment": { "url": null @@ -1777,17 +1970,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 409, - "note": "Omnis rem nihil molestiae enim laudantium doloremque.", + "id": 424, + "note": "Eveniet est et blanditiis sequi alias.", "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:20:01.783Z", - "updated_at": "2016-03-22T15:20:01.783Z", + "author_id": 25, + "created_at": "2016-06-14T15:02:49.965Z", + "updated_at": "2016-06-14T15:02:49.965Z", "project_id": 5, "attachment": { "url": null @@ -1798,17 +1994,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 408, - "note": "Ullam harum sit et optio incidunt.", + "id": 425, + "note": "Commodi tempore voluptas doloremque est.", "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:20:01.746Z", - "updated_at": "2016-03-22T15:20:01.746Z", + "author_id": 22, + "created_at": "2016-06-14T15:02:49.996Z", + "updated_at": "2016-06-14T15:02:49.996Z", "project_id": 5, "attachment": { "url": null @@ -1819,17 +2018,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 407, - "note": "Fugit distinctio ab quo ipsam.", + "id": 426, + "note": "Quo libero impedit odio debitis rerum aspernatur.", "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:20:01.716Z", - "updated_at": "2016-03-22T15:20:01.716Z", + "author_id": 20, + "created_at": "2016-06-14T15:02:50.024Z", + "updated_at": "2016-06-14T15:02:50.024Z", "project_id": 5, "attachment": { "url": null @@ -1840,17 +2042,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 406, - "note": "Impedit iste possimus ad ea.", + "id": 427, + "note": "Dolorem voluptatem qui labore deserunt.", "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:20:01.676Z", - "updated_at": "2016-03-22T15:20:01.676Z", + "author_id": 16, + "created_at": "2016-06-14T15:02:50.049Z", + "updated_at": "2016-06-14T15:02:50.049Z", "project_id": 5, "attachment": { "url": null @@ -1861,17 +2066,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 405, - "note": "Nemo recusandae dolore distinctio quam consequuntur ut et aut.", + "id": 428, + "note": "Est blanditiis laboriosam enim ipsam.", "noteable_type": "Issue", - "author_id": 22, - "created_at": "2016-03-22T15:20:01.641Z", - "updated_at": "2016-03-22T15:20:01.641Z", + "author_id": 15, + "created_at": "2016-06-14T15:02:50.077Z", + "updated_at": "2016-06-14T15:02:50.077Z", "project_id": 5, "attachment": { "url": null @@ -1882,17 +2090,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 404, - "note": "Nisi repudiandae repellat nulla culpa quasi expedita quod velit.", + "id": 429, + "note": "Et in voluptatem animi dolorem eos.", "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:20:01.601Z", - "updated_at": "2016-03-22T15:20:01.601Z", + "author_id": 6, + "created_at": "2016-06-14T15:02:50.107Z", + "updated_at": "2016-06-14T15:02:50.107Z", "project_id": 5, "attachment": { "url": null @@ -1903,17 +2114,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 403, - "note": "Quibusdam odio temporibus nemo voluptatibus accusamus.", + "id": 430, + "note": "Unde culpa voluptate qui sint quos.", "noteable_type": "Issue", - "author_id": 26, - "created_at": "2016-03-22T15:20:01.552Z", - "updated_at": "2016-03-22T15:20:01.552Z", + "author_id": 1, + "created_at": "2016-06-14T15:02:50.132Z", + "updated_at": "2016-06-14T15:02:50.132Z", "project_id": 5, "attachment": { "url": null @@ -1924,470 +2138,338 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ] } ], "labels": [ - { - "id": 12, - "title": "test", - "color": "#428bca", - "project_id": 5, - "created_at": "2016-05-10T10:53:14.214Z", - "updated_at": "2016-05-10T10:53:14.214Z", - "template": false, - "description": "test label" - } + ], "milestones": [ { - "id": 11, - "title": "v2.0", + "id": 20, + "title": "v4.0", "project_id": 5, - "description": "Sapiente facilis architecto reprehenderit aut sed enim.", + "description": "Totam quam laborum id magnam natus eaque aspernatur.", "due_date": null, - "created_at": "2016-03-22T15:13:21.631Z", - "updated_at": "2016-03-22T15:13:21.631Z", - "state": "closed", - "iid": 2 + "created_at": "2016-06-14T15:02:04.590Z", + "updated_at": "2016-06-14T15:02:04.590Z", + "state": "active", + "iid": 5, + "events": [ + { + "id": 240, + "target_type": "Milestone", + "target_id": 20, + "title": null, + "data": null, + "project_id": 36, + "created_at": "2016-06-14T15:02:04.593Z", + "updated_at": "2016-06-14T15:02:04.593Z", + "action": 1, + "author_id": 1 + }, + { + "id": 60, + "target_type": "Milestone", + "target_id": 20, + "title": null, + "data": null, + "project_id": 5, + "created_at": "2016-06-14T15:02:04.593Z", + "updated_at": "2016-06-14T15:02:04.593Z", + "action": 1, + "author_id": 20 + } + ] }, { - "id": 10, - "title": "v1.0", + "id": 19, + "title": "v3.0", "project_id": 5, - "description": "Est sed eos minima veniam culpa aut non.", + "description": "Rerum at autem exercitationem ea voluptates harum quam placeat.", "due_date": null, - "created_at": "2016-03-22T15:13:21.622Z", - "updated_at": "2016-03-22T15:13:21.622Z", - "state": "closed", - "iid": 1 - } - ], - "snippets": [ - - ], - "releases": [ - - ], - "events": [ - { - "id": 301, - "target_type": "Note", - "target_id": 1357, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-04-12T13:08:30.886Z", - "updated_at": "2016-04-12T13:08:30.886Z", - "action": 6, - "author_id": 1 - }, - { - "id": 227, - "target_type": "MergeRequest", - "target_id": 85, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:19:44.957Z", - "updated_at": "2016-03-22T15:19:44.957Z", - "action": 1, - "author_id": 1 - }, - { - "id": 226, - "target_type": "MergeRequest", - "target_id": 84, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:19:44.600Z", - "updated_at": "2016-03-22T15:19:44.600Z", - "action": 1, - "author_id": 1 - }, - { - "id": 157, - "target_type": "MergeRequest", - "target_id": 15, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:45.936Z", - "updated_at": "2016-03-22T15:13:45.936Z", - "action": 1, - "author_id": 3 - }, - { - "id": 156, - "target_type": "MergeRequest", - "target_id": 14, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:45.500Z", - "updated_at": "2016-03-22T15:13:45.500Z", - "action": 1, - "author_id": 10 - }, - { - "id": 155, - "target_type": "MergeRequest", - "target_id": 13, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:45.242Z", - "updated_at": "2016-03-22T15:13:45.242Z", - "action": 1, - "author_id": 1 - }, - { - "id": 154, - "target_type": "MergeRequest", - "target_id": 12, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:44.940Z", - "updated_at": "2016-03-22T15:13:44.940Z", - "action": 1, - "author_id": 24 - }, - { - "id": 153, - "target_type": "MergeRequest", - "target_id": 11, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:44.568Z", - "updated_at": "2016-03-22T15:13:44.568Z", - "action": 1, - "author_id": 26 - }, - { - "id": 152, - "target_type": "MergeRequest", - "target_id": 10, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:44.225Z", - "updated_at": "2016-03-22T15:13:44.225Z", - "action": 1, - "author_id": 22 - }, - { - "id": 151, - "target_type": "MergeRequest", - "target_id": 9, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:43.868Z", - "updated_at": "2016-03-22T15:13:43.868Z", - "action": 1, - "author_id": 24 - }, - { - "id": 102, - "target_type": "Issue", - "target_id": 40, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:28.474Z", - "updated_at": "2016-03-22T15:13:28.474Z", - "action": 1, - "author_id": 4 - }, - { - "id": 101, - "target_type": "Issue", - "target_id": 39, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:28.328Z", - "updated_at": "2016-03-22T15:13:28.328Z", - "action": 1, - "author_id": 12 - }, - { - "id": 100, - "target_type": "Issue", - "target_id": 38, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:28.204Z", - "updated_at": "2016-03-22T15:13:28.204Z", - "action": 1, - "author_id": 3 - }, - { - "id": 99, - "target_type": "Issue", - "target_id": 37, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:28.055Z", - "updated_at": "2016-03-22T15:13:28.055Z", - "action": 1, - "author_id": 10 - }, - { - "id": 98, - "target_type": "Issue", - "target_id": 36, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:27.913Z", - "updated_at": "2016-03-22T15:13:27.913Z", - "action": 1, - "author_id": 4 - }, - { - "id": 97, - "target_type": "Issue", - "target_id": 35, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:27.731Z", - "updated_at": "2016-03-22T15:13:27.731Z", - "action": 1, - "author_id": 1 - }, - { - "id": 96, - "target_type": "Issue", - "target_id": 34, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:27.564Z", - "updated_at": "2016-03-22T15:13:27.564Z", - "action": 1, - "author_id": 1 - }, - { - "id": 95, - "target_type": "Issue", - "target_id": 33, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:27.429Z", - "updated_at": "2016-03-22T15:13:27.429Z", - "action": 1, - "author_id": 22 - }, - { - "id": 94, - "target_type": "Issue", - "target_id": 32, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:27.287Z", - "updated_at": "2016-03-22T15:13:27.287Z", - "action": 1, - "author_id": 26 - }, - { - "id": 93, - "target_type": "Issue", - "target_id": 31, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:26.997Z", - "updated_at": "2016-03-22T15:13:26.997Z", - "action": 1, - "author_id": 24 - }, - { - "id": 51, - "target_type": "Milestone", - "target_id": 11, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:21.634Z", - "updated_at": "2016-03-22T15:13:21.634Z", - "action": 1, - "author_id": 26 - }, - { - "id": 50, - "target_type": "Milestone", - "target_id": 10, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:21.625Z", - "updated_at": "2016-03-22T15:13:21.625Z", - "action": 1, - "author_id": 22 - }, - { - "id": 24, - "target_type": null, - "target_id": null, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:20.750Z", - "updated_at": "2016-03-22T15:13:20.750Z", - "action": 8, - "author_id": 12 - }, - { - "id": 23, - "target_type": null, - "target_id": null, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:20.711Z", - "updated_at": "2016-03-22T15:13:20.711Z", - "action": 8, - "author_id": 22 + "created_at": "2016-06-14T15:02:04.583Z", + "updated_at": "2016-06-14T15:02:04.583Z", + "state": "active", + "iid": 4, + "events": [ + { + "id": 241, + "target_type": "Milestone", + "target_id": 19, + "title": null, + "data": null, + "project_id": 36, + "created_at": "2016-06-14T15:02:04.585Z", + "updated_at": "2016-06-14T15:02:04.585Z", + "action": 1, + "author_id": 1 + }, + { + "id": 59, + "target_type": "Milestone", + "target_id": 19, + "title": null, + "data": { + "object_kind": "push", + "before": "0000000000000000000000000000000000000000", + "after": "de990aa15829d0ab182ad5a55b4c527846c0d39c", + "ref": "refs/heads/removable-group-owner", + "checkout_sha": "de990aa15829d0ab182ad5a55b4c527846c0d39c", + "message": null, + "user_id": 273486, + "user_name": "James Lopez", + "user_email": "james@jameslopez.es", + "project_id": 562317, + "repository": { + "name": "GitLab Community Edition", + "url": "git@gitlab.com:james11/gitlab-ce.git", + "description": "Version Control on your Server. See http://gitlab.org/gitlab-ce/ and the README for more information", + "homepage": "https://gitlab.com/james11/gitlab-ce", + "git_http_url": "https://gitlab.com/james11/gitlab-ce.git", + "git_ssh_url": "git@gitlab.com:james11/gitlab-ce.git", + "visibility_level": 20 + }, + "commits": [ + { + "id": "de990aa15829d0ab182ad5a55b4c527846c0d39c", + "message": "fixed last group owner issue and added test\\n", + "timestamp": "2015-10-29T16:10:27+00:00", + "url": "https://gitlab.com/james11/gitlab-ce/commit/de990aa15829d0ab182ad5a55b4c527846c0d39c", + "author": { + "name": "James Lopez", + "email": "james.lopez@vodafone.com" + } + } + ], + "total_commits_count": 1 + }, + "project_id": 5, + "created_at": "2016-06-14T15:02:04.585Z", + "updated_at": "2016-06-14T15:02:04.585Z", + "action": 1, + "author_id": 25 + } + ] }, { - "id": 22, - "target_type": null, - "target_id": null, - "title": null, - "data": null, + "id": 18, + "title": "v2.0", "project_id": 5, - "created_at": "2016-03-22T15:13:20.667Z", - "updated_at": "2016-03-22T15:13:20.667Z", - "action": 8, - "author_id": 26 + "description": "Error dolorem rerum aut nulla.", + "due_date": null, + "created_at": "2016-06-14T15:02:04.576Z", + "updated_at": "2016-06-14T15:02:04.576Z", + "state": "active", + "iid": 3, + "events": [ + { + "id": 242, + "target_type": "Milestone", + "target_id": 18, + "title": null, + "data": null, + "project_id": 36, + "created_at": "2016-06-14T15:02:04.579Z", + "updated_at": "2016-06-14T15:02:04.579Z", + "action": 1, + "author_id": 1 + }, + { + "id": 58, + "target_type": "Milestone", + "target_id": 18, + "title": null, + "data": null, + "project_id": 5, + "created_at": "2016-06-14T15:02:04.579Z", + "updated_at": "2016-06-14T15:02:04.579Z", + "action": 1, + "author_id": 22 + } + ] }, { - "id": 21, - "target_type": null, - "target_id": null, - "title": null, - "data": null, + "id": 17, + "title": "v1.0", "project_id": 5, - "created_at": "2016-03-22T15:13:20.646Z", - "updated_at": "2016-03-22T15:13:20.646Z", - "action": 8, - "author_id": 1 + "description": "Molestiae perspiciatis voluptates doloremque commodi veniam consequatur.", + "due_date": null, + "created_at": "2016-06-14T15:02:04.569Z", + "updated_at": "2016-06-14T15:02:04.569Z", + "state": "active", + "iid": 2, + "events": [ + { + "id": 243, + "target_type": "Milestone", + "target_id": 17, + "title": null, + "data": null, + "project_id": 36, + "created_at": "2016-06-14T15:02:04.570Z", + "updated_at": "2016-06-14T15:02:04.570Z", + "action": 1, + "author_id": 1 + }, + { + "id": 57, + "target_type": "Milestone", + "target_id": 17, + "title": null, + "data": null, + "project_id": 5, + "created_at": "2016-06-14T15:02:04.570Z", + "updated_at": "2016-06-14T15:02:04.570Z", + "action": 1, + "author_id": 20 + } + ] }, { - "id": 5, - "target_type": null, - "target_id": null, - "title": null, - "data": null, + "id": 16, + "title": "v0.0", "project_id": 5, - "created_at": "2016-03-22T15:13:10.369Z", - "updated_at": "2016-03-22T15:13:10.369Z", - "action": 1, - "author_id": 1 + "description": "Velit numquam et sed sit.", + "due_date": null, + "created_at": "2016-06-14T15:02:04.561Z", + "updated_at": "2016-06-14T15:02:04.561Z", + "state": "closed", + "iid": 1, + "events": [ + { + "id": 244, + "target_type": "Milestone", + "target_id": 16, + "title": null, + "data": null, + "project_id": 36, + "created_at": "2016-06-14T15:02:04.563Z", + "updated_at": "2016-06-14T15:02:04.563Z", + "action": 1, + "author_id": 26 + }, + { + "id": 56, + "target_type": "Milestone", + "target_id": 16, + "title": null, + "data": null, + "project_id": 5, + "created_at": "2016-06-14T15:02:04.563Z", + "updated_at": "2016-06-14T15:02:04.563Z", + "action": 1, + "author_id": 26 + } + ] } ], + "snippets": [ + + ], + "releases": [ + + ], "project_members": [ { - "id": 35, + "id": 36, "access_level": 40, "source_id": 5, "source_type": "Project", - "user_id": 12, + "user_id": 16, "notification_level": 3, - "created_at": "2016-03-22T15:13:20.743Z", - "updated_at": "2016-03-22T15:13:20.743Z", + "created_at": "2016-06-14T15:02:03.834Z", + "updated_at": "2016-06-14T15:02:03.834Z", "created_by_id": null, "invite_email": null, "invite_token": null, "invite_accepted_at": null, + "requested_at": null, "user": { - "id": 12, - "email": "maureen.bogisich@russelkessler.com", - "username": "evans" + "id": 16, + "email": "maritza_schoen@block.ca", + "username": "bernard_willms" } }, { - "id": 34, - "access_level": 40, + "id": 35, + "access_level": 10, "source_id": 5, "source_type": "Project", - "user_id": 22, + "user_id": 6, "notification_level": 3, - "created_at": "2016-03-22T15:13:20.708Z", - "updated_at": "2016-03-22T15:13:20.708Z", + "created_at": "2016-06-14T15:02:03.811Z", + "updated_at": "2016-06-14T15:02:03.811Z", "created_by_id": null, "invite_email": null, "invite_token": null, "invite_accepted_at": null, + "requested_at": null, "user": { - "id": 22, - "email": "user0@example.com", - "username": "user0" + "id": 6, + "email": "shaina@koelpindenesik.com", + "username": "saul_will" } }, { - "id": 33, - "access_level": 40, + "id": 34, + "access_level": 20, "source_id": 5, "source_type": "Project", - "user_id": 26, + "user_id": 15, "notification_level": 3, - "created_at": "2016-03-22T15:13:20.664Z", - "updated_at": "2016-03-22T15:13:20.664Z", + "created_at": "2016-06-14T15:02:03.776Z", + "updated_at": "2016-06-14T15:02:03.776Z", "created_by_id": null, "invite_email": null, "invite_token": null, "invite_accepted_at": null, + "requested_at": null, "user": { - "id": 26, - "email": "user4@example.com", - "username": "user4" + "id": 15, + "email": "breanna_sanford@wolf.com", + "username": "emmet.schamberger" } }, { - "id": 32, + "id": 33, "access_level": 20, "source_id": 5, "source_type": "Project", - "user_id": 1, + "user_id": 26, "notification_level": 3, - "created_at": "2016-03-22T15:13:20.643Z", - "updated_at": "2016-03-22T15:13:20.643Z", + "created_at": "2016-06-14T15:02:03.742Z", + "updated_at": "2016-06-14T15:02:03.742Z", "created_by_id": null, "invite_email": null, "invite_token": null, "invite_accepted_at": null, + "requested_at": null, "user": { - "id": 1, - "email": "nospam@bluegod.net", - "username": "root" + "id": 26, + "email": "user4@example.com", + "username": "user4" } } ], "merge_requests": [ { - "id": 85, + "id": 27, "target_branch": "feature", "source_branch": "feature_conflict", "source_project_id": 5, "author_id": 1, "assignee_id": null, "title": "Cannot be automatically merged", - "created_at": "2016-03-22T15:19:44.807Z", - "updated_at": "2016-03-22T15:20:09.557Z", + "created_at": "2016-06-14T15:02:36.568Z", + "updated_at": "2016-06-14T15:02:56.815Z", "milestone_id": null, "state": "opened", "merge_status": "unchecked", @@ -2399,7 +2481,7 @@ "updated_by_id": null, "merge_error": null, "merge_params": { - + "force_remove_source_branch": null }, "merge_when_build_succeeds": false, "merge_user_id": null, @@ -2407,176 +2489,200 @@ "deleted_at": null, "notes": [ { - "id": 638, - "note": "Ab velit ducimus totam sunt ut.", + "id": 671, + "note": "Sit voluptatibus eveniet architecto quidem.", "noteable_type": "MergeRequest", - "author_id": 1, - "created_at": "2016-03-22T15:20:09.553Z", - "updated_at": "2016-03-22T15:20:09.553Z", + "author_id": 26, + "created_at": "2016-06-14T15:02:56.632Z", + "updated_at": "2016-06-14T15:02:56.632Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 85, + "noteable_id": 27, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 637, - "note": "Ipsum aliquam est in unde similique nihil illo ea.", + "id": 672, + "note": "Odio maxime ratione voluptatibus sed.", "noteable_type": "MergeRequest", - "author_id": 3, - "created_at": "2016-03-22T15:20:09.528Z", - "updated_at": "2016-03-22T15:20:09.528Z", + "author_id": 25, + "created_at": "2016-06-14T15:02:56.656Z", + "updated_at": "2016-06-14T15:02:56.656Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 85, + "noteable_id": 27, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 636, - "note": "Soluta inventore adipisci et consequatur expedita aliquid earum modi.", + "id": 673, + "note": "Et deserunt et omnis nihil excepturi accusantium.", "noteable_type": "MergeRequest", - "author_id": 4, - "created_at": "2016-03-22T15:20:09.496Z", - "updated_at": "2016-03-22T15:20:09.496Z", + "author_id": 22, + "created_at": "2016-06-14T15:02:56.679Z", + "updated_at": "2016-06-14T15:02:56.679Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 85, + "noteable_id": 27, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 635, - "note": "Corporis incidunt tempore est deleniti.", + "id": 674, + "note": "Saepe asperiores exercitationem non dignissimos laborum reiciendis et ipsum.", "noteable_type": "MergeRequest", - "author_id": 10, - "created_at": "2016-03-22T15:20:09.469Z", - "updated_at": "2016-03-22T15:20:09.469Z", + "author_id": 20, + "created_at": "2016-06-14T15:02:56.700Z", + "updated_at": "2016-06-14T15:02:56.700Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 85, + "noteable_id": 27, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 634, - "note": "Hic dolores voluptatibus qui necessitatibus.", + "id": 675, + "note": "Numquam est at dolor quo et sed eligendi similique.", "noteable_type": "MergeRequest", - "author_id": 12, - "created_at": "2016-03-22T15:20:09.440Z", - "updated_at": "2016-03-22T15:20:09.440Z", + "author_id": 16, + "created_at": "2016-06-14T15:02:56.720Z", + "updated_at": "2016-06-14T15:02:56.720Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 85, + "noteable_id": 27, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 633, - "note": "Rerum architecto placeat doloribus voluptates consequuntur quo.", + "id": 676, + "note": "Et perferendis aliquam sunt nisi labore delectus.", "noteable_type": "MergeRequest", - "author_id": 22, - "created_at": "2016-03-22T15:20:09.412Z", - "updated_at": "2016-03-22T15:20:09.412Z", + "author_id": 15, + "created_at": "2016-06-14T15:02:56.742Z", + "updated_at": "2016-06-14T15:02:56.742Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 85, + "noteable_id": 27, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 632, - "note": "Vel earum aut ut occaecati aut ut rerum qui.", + "id": 677, + "note": "Aut ex rerum et in.", "noteable_type": "MergeRequest", - "author_id": 24, - "created_at": "2016-03-22T15:20:09.389Z", - "updated_at": "2016-03-22T15:20:09.389Z", + "author_id": 6, + "created_at": "2016-06-14T15:02:56.791Z", + "updated_at": "2016-06-14T15:02:56.791Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 85, + "noteable_id": 27, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 631, - "note": "Est voluptatibus dolores animi numquam.", + "id": 678, + "note": "Dolor laborum earum ut exercitationem.", "noteable_type": "MergeRequest", - "author_id": 26, - "created_at": "2016-03-22T15:20:09.361Z", - "updated_at": "2016-03-22T15:20:09.361Z", + "author_id": 1, + "created_at": "2016-06-14T15:02:56.814Z", + "updated_at": "2016-06-14T15:02:56.814Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 85, + "noteable_id": 27, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ], "merge_request_diff": { - "id": 85, + "id": 27, "state": "collected", "st_commits": [ { @@ -2759,23 +2865,49 @@ "too_large": false } ], - "merge_request_id": 85, - "created_at": "2016-03-22T15:19:44.810Z", - "updated_at": "2016-03-22T15:19:44.901Z", + "merge_request_id": 27, + "created_at": "2016-06-14T15:02:36.572Z", + "updated_at": "2016-06-14T15:02:36.658Z", "base_commit_sha": "ae73cb07c9eeaf35924a10f713b364d32b2dd34f", "real_size": "9" - } + }, + "events": [ + { + "id": 221, + "target_type": "MergeRequest", + "target_id": 27, + "title": null, + "data": null, + "project_id": 36, + "created_at": "2016-06-14T15:02:36.703Z", + "updated_at": "2016-06-14T15:02:36.703Z", + "action": 1, + "author_id": 1 + }, + { + "id": 187, + "target_type": "MergeRequest", + "target_id": 27, + "title": null, + "data": null, + "project_id": 5, + "created_at": "2016-06-14T15:02:36.703Z", + "updated_at": "2016-06-14T15:02:36.703Z", + "action": 1, + "author_id": 1 + } + ] }, { - "id": 84, + "id": 26, "target_branch": "master", "source_branch": "feature", "source_project_id": 5, "author_id": 1, "assignee_id": null, "title": "Can be automatically merged", - "created_at": "2016-03-22T15:19:44.482Z", - "updated_at": "2016-03-22T15:20:09.773Z", + "created_at": "2016-06-14T15:02:36.418Z", + "updated_at": "2016-06-14T15:02:57.013Z", "milestone_id": null, "state": "opened", "merge_status": "unchecked", @@ -2787,7 +2919,7 @@ "updated_by_id": null, "merge_error": null, "merge_params": { - + "force_remove_source_branch": null }, "merge_when_build_succeeds": false, "merge_user_id": null, @@ -2795,176 +2927,200 @@ "deleted_at": null, "notes": [ { - "id": 646, - "note": "Temporibus debitis veniam est ut sit nihil.", + "id": 679, + "note": "Qui rerum totam nisi est.", "noteable_type": "MergeRequest", - "author_id": 1, - "created_at": "2016-03-22T15:20:09.770Z", - "updated_at": "2016-03-22T15:20:09.770Z", + "author_id": 26, + "created_at": "2016-06-14T15:02:56.848Z", + "updated_at": "2016-06-14T15:02:56.848Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 84, + "noteable_id": 26, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 645, - "note": "Ut assumenda dignissimos quibusdam veritatis sequi dolores.", + "id": 680, + "note": "Pariatur magni corrupti consequatur debitis minima error beatae voluptatem.", "noteable_type": "MergeRequest", - "author_id": 3, - "created_at": "2016-03-22T15:20:09.740Z", - "updated_at": "2016-03-22T15:20:09.740Z", + "author_id": 25, + "created_at": "2016-06-14T15:02:56.871Z", + "updated_at": "2016-06-14T15:02:56.871Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 84, + "noteable_id": 26, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 644, - "note": "Velit quae quidem cupiditate laudantium nihil ut eveniet.", + "id": 681, + "note": "Qui quis ut modi eos rerum ratione.", "noteable_type": "MergeRequest", - "author_id": 4, - "created_at": "2016-03-22T15:20:09.717Z", - "updated_at": "2016-03-22T15:20:09.717Z", + "author_id": 22, + "created_at": "2016-06-14T15:02:56.895Z", + "updated_at": "2016-06-14T15:02:56.895Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 84, + "noteable_id": 26, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 643, - "note": "Repellat quas porro sed mollitia laborum ut fugiat.", + "id": 682, + "note": "Illum quidem expedita mollitia fugit.", "noteable_type": "MergeRequest", - "author_id": 10, - "created_at": "2016-03-22T15:20:09.690Z", - "updated_at": "2016-03-22T15:20:09.690Z", + "author_id": 20, + "created_at": "2016-06-14T15:02:56.918Z", + "updated_at": "2016-06-14T15:02:56.918Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 84, + "noteable_id": 26, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 642, - "note": "Qui aut debitis perspiciatis et voluptatem.", + "id": 683, + "note": "Consectetur voluptate sit sint possimus veritatis quod.", "noteable_type": "MergeRequest", - "author_id": 12, - "created_at": "2016-03-22T15:20:09.665Z", - "updated_at": "2016-03-22T15:20:09.665Z", + "author_id": 16, + "created_at": "2016-06-14T15:02:56.942Z", + "updated_at": "2016-06-14T15:02:56.942Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 84, + "noteable_id": 26, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 641, - "note": "Quia id quia velit et.", + "id": 684, + "note": "Natus libero quibusdam rem assumenda deleniti accusamus sed earum.", "noteable_type": "MergeRequest", - "author_id": 22, - "created_at": "2016-03-22T15:20:09.639Z", - "updated_at": "2016-03-22T15:20:09.639Z", + "author_id": 15, + "created_at": "2016-06-14T15:02:56.966Z", + "updated_at": "2016-06-14T15:02:56.966Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 84, + "noteable_id": 26, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 640, - "note": "Corporis commodi doloremque itaque non animi.", + "id": 685, + "note": "Tenetur autem nihil rerum odit.", "noteable_type": "MergeRequest", - "author_id": 24, - "created_at": "2016-03-22T15:20:09.617Z", - "updated_at": "2016-03-22T15:20:09.617Z", + "author_id": 6, + "created_at": "2016-06-14T15:02:56.989Z", + "updated_at": "2016-06-14T15:02:56.989Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 84, + "noteable_id": 26, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 639, - "note": "Possimus dignissimos voluptatum in tenetur.", + "id": 686, + "note": "Quia maiores et odio sed.", "noteable_type": "MergeRequest", - "author_id": 26, - "created_at": "2016-03-22T15:20:09.589Z", - "updated_at": "2016-03-22T15:20:09.589Z", + "author_id": 1, + "created_at": "2016-06-14T15:02:57.012Z", + "updated_at": "2016-06-14T15:02:57.012Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 84, + "noteable_id": 26, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ], "merge_request_diff": { - "id": 84, + "id": 26, "state": "collected", "st_commits": [ { @@ -2994,35 +3150,61 @@ "too_large": false } ], - "merge_request_id": 84, - "created_at": "2016-03-22T15:19:44.485Z", - "updated_at": "2016-03-22T15:19:44.577Z", + "merge_request_id": 26, + "created_at": "2016-06-14T15:02:36.421Z", + "updated_at": "2016-06-14T15:02:36.474Z", "base_commit_sha": "ae73cb07c9eeaf35924a10f713b364d32b2dd34f", "real_size": "1" - } + }, + "events": [ + { + "id": 222, + "target_type": "MergeRequest", + "target_id": 26, + "title": null, + "data": null, + "project_id": 36, + "created_at": "2016-06-14T15:02:36.496Z", + "updated_at": "2016-06-14T15:02:36.496Z", + "action": 1, + "author_id": 1 + }, + { + "id": 186, + "target_type": "MergeRequest", + "target_id": 26, + "title": null, + "data": null, + "project_id": 5, + "created_at": "2016-06-14T15:02:36.496Z", + "updated_at": "2016-06-14T15:02:36.496Z", + "action": 1, + "author_id": 1 + } + ] }, { "id": 15, - "target_branch": "markdown", - "source_branch": "master", + "target_branch": "test-7", + "source_branch": "test-1", "source_project_id": 5, - "author_id": 3, - "assignee_id": 3, - "title": "Nulla explicabo iure voluptas perferendis autem autem unde nemo totam optio.", - "created_at": "2016-03-22T15:13:45.689Z", - "updated_at": "2016-03-22T15:20:30.476Z", - "milestone_id": 10, + "author_id": 22, + "assignee_id": 16, + "title": "Qui accusantium et inventore facilis doloribus occaecati officiis.", + "created_at": "2016-06-14T15:02:25.168Z", + "updated_at": "2016-06-14T15:02:59.521Z", + "milestone_id": 17, "state": "opened", "merge_status": "unchecked", "target_project_id": 5, "iid": 7, - "description": "Doloribus dignissimos impedit qui et provident exercitationem. Veniam quis magni qui fugiat. Et quia voluptate et vel consequatur pariatur ea est.", + "description": "Et commodi deserunt aspernatur vero rerum. Ut non dolorum alias in odit est libero. Voluptatibus eos in et vitae repudiandae facilis ex mollitia.", "position": 0, "locked_at": null, "updated_by_id": null, "merge_error": null, "merge_params": { - + "force_remove_source_branch": null }, "merge_when_build_succeeds": false, "merge_user_id": null, @@ -3030,12 +3212,12 @@ "deleted_at": null, "notes": [ { - "id": 1231, - "note": "Rerum optio quibusdam provident possimus quis cum.", + "id": 777, + "note": "Pariatur voluptas placeat aspernatur culpa suscipit soluta.", "noteable_type": "MergeRequest", - "author_id": 1, - "created_at": "2016-03-22T15:20:30.472Z", - "updated_at": "2016-03-22T15:20:30.472Z", + "author_id": 26, + "created_at": "2016-06-14T15:02:59.348Z", + "updated_at": "2016-06-14T15:02:59.348Z", "project_id": 5, "attachment": { "url": null @@ -3046,17 +3228,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 1230, - "note": "Quasi odit repudiandae ut officiis ut nihil illo.", + "id": 778, + "note": "Alias et iure mollitia suscipit molestiae voluptatum nostrum asperiores.", "noteable_type": "MergeRequest", - "author_id": 3, - "created_at": "2016-03-22T15:20:30.444Z", - "updated_at": "2016-03-22T15:20:30.444Z", + "author_id": 25, + "created_at": "2016-06-14T15:02:59.372Z", + "updated_at": "2016-06-14T15:02:59.372Z", "project_id": 5, "attachment": { "url": null @@ -3067,17 +3252,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 1229, - "note": "Aut vero dolores facere sed.", + "id": 779, + "note": "Laudantium qui eum qui sunt.", "noteable_type": "MergeRequest", - "author_id": 4, - "created_at": "2016-03-22T15:20:30.412Z", - "updated_at": "2016-03-22T15:20:30.412Z", + "author_id": 22, + "created_at": "2016-06-14T15:02:59.395Z", + "updated_at": "2016-06-14T15:02:59.395Z", "project_id": 5, "attachment": { "url": null @@ -3088,17 +3276,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 1228, - "note": "Autem voluptatem et blanditiis accusantium deserunt et et.", + "id": 780, + "note": "Quas rem est iusto ut delectus fugiat recusandae mollitia.", "noteable_type": "MergeRequest", - "author_id": 10, - "created_at": "2016-03-22T15:20:30.383Z", - "updated_at": "2016-03-22T15:20:30.383Z", + "author_id": 20, + "created_at": "2016-06-14T15:02:59.418Z", + "updated_at": "2016-06-14T15:02:59.418Z", "project_id": 5, "attachment": { "url": null @@ -3109,17 +3300,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 1227, - "note": "Voluptatem aliquam voluptatem molestiae est.", + "id": 781, + "note": "Repellendus ab et qui nesciunt.", "noteable_type": "MergeRequest", - "author_id": 12, - "created_at": "2016-03-22T15:20:30.352Z", - "updated_at": "2016-03-22T15:20:30.352Z", + "author_id": 16, + "created_at": "2016-06-14T15:02:59.444Z", + "updated_at": "2016-06-14T15:02:59.444Z", "project_id": 5, "attachment": { "url": null @@ -3130,17 +3324,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 1226, - "note": "Ea aut cupiditate est consequatur animi error qui et.", + "id": 782, + "note": "Non possimus voluptatum odio qui ut.", "noteable_type": "MergeRequest", - "author_id": 22, - "created_at": "2016-03-22T15:20:30.319Z", - "updated_at": "2016-03-22T15:20:30.319Z", + "author_id": 15, + "created_at": "2016-06-14T15:02:59.469Z", + "updated_at": "2016-06-14T15:02:59.469Z", "project_id": 5, "attachment": { "url": null @@ -3151,17 +3348,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 1225, - "note": "Voluptates est voluptas et nostrum modi beatae inventore et.", + "id": 783, + "note": "Dolores repellendus eum ducimus quam ab dolorem quia.", "noteable_type": "MergeRequest", - "author_id": 24, - "created_at": "2016-03-22T15:20:30.289Z", - "updated_at": "2016-03-22T15:20:30.289Z", + "author_id": 6, + "created_at": "2016-06-14T15:02:59.494Z", + "updated_at": "2016-06-14T15:02:59.494Z", "project_id": 5, "attachment": { "url": null @@ -3172,17 +3372,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 1224, - "note": "Quia est rerum adipisci cupiditate.", + "id": 784, + "note": "Facilis dolorem aut corrupti id ratione occaecati.", "noteable_type": "MergeRequest", - "author_id": 26, - "created_at": "2016-03-22T15:20:30.260Z", - "updated_at": "2016-03-22T15:20:30.260Z", + "author_id": 1, + "created_at": "2016-06-14T15:02:59.520Z", + "updated_at": "2016-06-14T15:02:59.520Z", "project_id": 5, "attachment": { "url": null @@ -3193,9 +3396,12 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ], "merge_request_diff": { @@ -3203,6 +3409,304 @@ "state": "collected", "st_commits": [ { + "id": "94b8d581c48d894b86661718582fecbc5e3ed2eb", + "message": "fixes #10\n", + "parent_ids": [ + "be93687618e4b132087f430a4d8fc3a609c9b77c" + ], + "authored_date": "2016-01-19T13:22:56.000+01:00", + "author_name": "James Lopez", + "author_email": "james@jameslopez.es", + "committed_date": "2016-01-19T13:22:56.000+01:00", + "committer_name": "James Lopez", + "committer_email": "james@jameslopez.es" + } + ], + "st_diffs": [ + { + "diff": "--- /dev/null\n+++ b/test\n", + "new_path": "test", + "old_path": "test", + "a_mode": "0", + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + } + ], + "merge_request_id": 15, + "created_at": "2016-06-14T15:02:25.171Z", + "updated_at": "2016-06-14T15:02:25.230Z", + "base_commit_sha": "be93687618e4b132087f430a4d8fc3a609c9b77c", + "real_size": "1" + }, + "events": [ + { + "id": 223, + "target_type": "MergeRequest", + "target_id": 15, + "title": null, + "data": null, + "project_id": 36, + "created_at": "2016-06-14T15:02:25.262Z", + "updated_at": "2016-06-14T15:02:25.262Z", + "action": 1, + "author_id": 1 + }, + { + "id": 175, + "target_type": "MergeRequest", + "target_id": 15, + "title": null, + "data": null, + "project_id": 5, + "created_at": "2016-06-14T15:02:25.262Z", + "updated_at": "2016-06-14T15:02:25.262Z", + "action": 1, + "author_id": 22 + } + ] + }, + { + "id": 14, + "target_branch": "fix", + "source_branch": "test-3", + "source_project_id": 5, + "author_id": 20, + "assignee_id": 20, + "title": "In voluptas aut sequi voluptatem ullam vel corporis illum consequatur.", + "created_at": "2016-06-14T15:02:24.760Z", + "updated_at": "2016-06-14T15:02:59.749Z", + "milestone_id": 20, + "state": "opened", + "merge_status": "unchecked", + "target_project_id": 5, + "iid": 6, + "description": "Dicta magnam non voluptates nam dignissimos nostrum deserunt. Dolorum et suscipit iure quae doloremque. Necessitatibus saepe aut labore sed.", + "position": 0, + "locked_at": null, + "updated_by_id": null, + "merge_error": null, + "merge_params": { + "force_remove_source_branch": null + }, + "merge_when_build_succeeds": false, + "merge_user_id": null, + "merge_commit_sha": null, + "deleted_at": null, + "notes": [ + { + "id": 785, + "note": "Atque cupiditate necessitatibus deserunt minus natus odit.", + "noteable_type": "MergeRequest", + "author_id": 26, + "created_at": "2016-06-14T15:02:59.559Z", + "updated_at": "2016-06-14T15:02:59.559Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 14, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 4" + }, + "events": [ + + ] + }, + { + "id": 786, + "note": "Non dolorem provident mollitia nesciunt optio ex eveniet.", + "noteable_type": "MergeRequest", + "author_id": 25, + "created_at": "2016-06-14T15:02:59.587Z", + "updated_at": "2016-06-14T15:02:59.587Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 14, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 3" + }, + "events": [ + + ] + }, + { + "id": 787, + "note": "Similique officia nemo quasi commodi accusantium quae qui.", + "noteable_type": "MergeRequest", + "author_id": 22, + "created_at": "2016-06-14T15:02:59.621Z", + "updated_at": "2016-06-14T15:02:59.621Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 14, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 0" + }, + "events": [ + + ] + }, + { + "id": 788, + "note": "Et est et alias ad dolor qui.", + "noteable_type": "MergeRequest", + "author_id": 20, + "created_at": "2016-06-14T15:02:59.650Z", + "updated_at": "2016-06-14T15:02:59.650Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 14, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] + }, + { + "id": 789, + "note": "Numquam temporibus ratione voluptatibus aliquid.", + "noteable_type": "MergeRequest", + "author_id": 16, + "created_at": "2016-06-14T15:02:59.675Z", + "updated_at": "2016-06-14T15:02:59.675Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 14, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] + }, + { + "id": 790, + "note": "Ut ex aliquam consectetur perferendis est hic aut quia.", + "noteable_type": "MergeRequest", + "author_id": 15, + "created_at": "2016-06-14T15:02:59.703Z", + "updated_at": "2016-06-14T15:02:59.703Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 14, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] + }, + { + "id": 791, + "note": "Esse eos quam quaerat aut ut asperiores officiis.", + "noteable_type": "MergeRequest", + "author_id": 6, + "created_at": "2016-06-14T15:02:59.726Z", + "updated_at": "2016-06-14T15:02:59.726Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 14, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] + }, + { + "id": 792, + "note": "Sint facilis accusantium iure blanditiis.", + "noteable_type": "MergeRequest", + "author_id": 1, + "created_at": "2016-06-14T15:02:59.748Z", + "updated_at": "2016-06-14T15:02:59.748Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 14, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Administrator" + }, + "events": [ + + ] + } + ], + "merge_request_diff": { + "id": 14, + "state": "collected", + "st_commits": [ + { + "id": "ddd4ff416a931589c695eb4f5b23f844426f6928", + "message": "fixes #10\n", + "parent_ids": [ + "be93687618e4b132087f430a4d8fc3a609c9b77c" + ], + "authored_date": "2016-01-19T14:14:43.000+01:00", + "author_name": "James Lopez", + "author_email": "james@jameslopez.es", + "committed_date": "2016-01-19T14:14:43.000+01:00", + "committer_name": "James Lopez", + "committer_email": "james@jameslopez.es" + }, + { "id": "be93687618e4b132087f430a4d8fc3a609c9b77c", "message": "Merge branch 'master' into 'master'\r\n\r\nLFS object pointer.\r\n\r\n\r\n\r\nSee merge request !6", "parent_ids": [ @@ -3388,10 +3892,108 @@ "committed_date": "2015-01-10T21:28:18.000+01:00", "committer_name": "marmis85", "committer_email": "marmis85@gmail.com" + }, + { + "id": "5937ac0a7beb003549fc5fd26fc247adbce4a52e", + "message": "Add submodule from gitlab.com\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n", + "parent_ids": [ + "570e7b2abdd848b95f2f578043fc23bd6f6fd24d" + ], + "authored_date": "2014-02-27T10:01:38.000+01:00", + "author_name": "Dmitriy Zaporozhets", + "author_email": "dmitriy.zaporozhets@gmail.com", + "committed_date": "2014-02-27T10:01:38.000+01:00", + "committer_name": "Dmitriy Zaporozhets", + "committer_email": "dmitriy.zaporozhets@gmail.com" + }, + { + "id": "570e7b2abdd848b95f2f578043fc23bd6f6fd24d", + "message": "Change some files\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n", + "parent_ids": [ + "6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9" + ], + "authored_date": "2014-02-27T09:57:31.000+01:00", + "author_name": "Dmitriy Zaporozhets", + "author_email": "dmitriy.zaporozhets@gmail.com", + "committed_date": "2014-02-27T09:57:31.000+01:00", + "committer_name": "Dmitriy Zaporozhets", + "committer_email": "dmitriy.zaporozhets@gmail.com" + }, + { + "id": "6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9", + "message": "More submodules\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n", + "parent_ids": [ + "d14d6c0abdd253381df51a723d58691b2ee1ab08" + ], + "authored_date": "2014-02-27T09:54:21.000+01:00", + "author_name": "Dmitriy Zaporozhets", + "author_email": "dmitriy.zaporozhets@gmail.com", + "committed_date": "2014-02-27T09:54:21.000+01:00", + "committer_name": "Dmitriy Zaporozhets", + "committer_email": "dmitriy.zaporozhets@gmail.com" + }, + { + "id": "d14d6c0abdd253381df51a723d58691b2ee1ab08", + "message": "Remove ds_store files\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n", + "parent_ids": [ + "c1acaa58bbcbc3eafe538cb8274ba387047b69f8" + ], + "authored_date": "2014-02-27T09:49:50.000+01:00", + "author_name": "Dmitriy Zaporozhets", + "author_email": "dmitriy.zaporozhets@gmail.com", + "committed_date": "2014-02-27T09:49:50.000+01:00", + "committer_name": "Dmitriy Zaporozhets", + "committer_email": "dmitriy.zaporozhets@gmail.com" + }, + { + "id": "c1acaa58bbcbc3eafe538cb8274ba387047b69f8", + "message": "Ignore DS files\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n", + "parent_ids": [ + "ae73cb07c9eeaf35924a10f713b364d32b2dd34f" + ], + "authored_date": "2014-02-27T09:48:32.000+01:00", + "author_name": "Dmitriy Zaporozhets", + "author_email": "dmitriy.zaporozhets@gmail.com", + "committed_date": "2014-02-27T09:48:32.000+01:00", + "committer_name": "Dmitriy Zaporozhets", + "committer_email": "dmitriy.zaporozhets@gmail.com" } ], "st_diffs": [ { + "diff": "Binary files a/.DS_Store and /dev/null differ\n", + "new_path": ".DS_Store", + "old_path": ".DS_Store", + "a_mode": "100644", + "b_mode": "0", + "new_file": false, + "renamed_file": false, + "deleted_file": true, + "too_large": false + }, + { + "diff": "--- a/.gitignore\n+++ b/.gitignore\n@@ -17,3 +17,4 @@ rerun.txt\n pickle-email-*.html\n .project\n config/initializers/secret_token.rb\n+.DS_Store\n", + "new_path": ".gitignore", + "old_path": ".gitignore", + "a_mode": "100644", + "b_mode": "100644", + "new_file": false, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- a/.gitmodules\n+++ b/.gitmodules\n@@ -1,3 +1,9 @@\n [submodule \"six\"]\n \tpath = six\n \turl = git://github.com/randx/six.git\n+[submodule \"gitlab-shell\"]\n+\tpath = gitlab-shell\n+\turl = https://github.com/gitlabhq/gitlab-shell.git\n+[submodule \"gitlab-grack\"]\n+\tpath = gitlab-grack\n+\turl = https://gitlab.com/gitlab-org/gitlab-grack.git\n", + "new_path": ".gitmodules", + "old_path": ".gitmodules", + "a_mode": "100644", + "b_mode": "100644", + "new_file": false, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { "diff": "--- a/CHANGELOG\n+++ b/CHANGELOG\n@@ -1,4 +1,6 @@\n-v 6.7.0\n+v6.8.0\n+\n+v6.7.0\n - Add support for Gemnasium as a Project Service (Olivier Gonzalez)\n - Add edit file button to MergeRequest diff\n - Public groups (Jason Hollingsworth)\n", "new_path": "CHANGELOG", "old_path": "CHANGELOG", @@ -3414,6 +4016,17 @@ "too_large": false }, { + "diff": "Binary files a/files/.DS_Store and /dev/null differ\n", + "new_path": "files/.DS_Store", + "old_path": "files/.DS_Store", + "a_mode": "100644", + "b_mode": "0", + "new_file": false, + "renamed_file": false, + "deleted_file": true, + "too_large": false + }, + { "diff": "--- /dev/null\n+++ b/files/images/wm.svg\n@@ -0,0 +1,78 @@\n+\u003c?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?\u003e\n+\u003csvg width=\"1300px\" height=\"680px\" viewBox=\"0 0 1300 680\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\"\u003e\n+ \u003c!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch --\u003e\n+ \u003ctitle\u003ewm\u003c/title\u003e\n+ \u003cdesc\u003eCreated with Sketch.\u003c/desc\u003e\n+ \u003cdefs\u003e\n+ \u003cpath id=\"path-1\" d=\"M-69.8,1023.54607 L1675.19996,1023.54607 L1675.19996,0 L-69.8,0 L-69.8,1023.54607 L-69.8,1023.54607 Z\"\u003e\u003c/path\u003e\n+ \u003c/defs\u003e\n+ \u003cg id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\"\u003e\n+ \u003cpath d=\"M1300,680 L0,680 L0,0 L1300,0 L1300,680 L1300,680 Z\" id=\"bg\" fill=\"#30353E\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003cg id=\"gitlab_logo\" sketch:type=\"MSLayerGroup\" transform=\"translate(-262.000000, -172.000000)\"\u003e\n+ \u003cg id=\"g10\" transform=\"translate(872.500000, 512.354581) scale(1, -1) translate(-872.500000, -512.354581) translate(0.000000, 0.290751)\"\u003e\n+ \u003cg id=\"g12\" transform=\"translate(1218.022652, 440.744871)\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\n+ \u003cpath d=\"M-50.0233338,141.900706 L-69.07059,141.900706 L-69.0100967,0.155858152 L8.04444805,0.155858152 L8.04444805,17.6840847 L-49.9628405,17.6840847 L-50.0233338,141.900706 L-50.0233338,141.900706 Z\" id=\"path14\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g16\"\u003e\n+ \u003cg id=\"g18-Clipped\"\u003e\n+ \u003cmask id=\"mask-2\" sketch:name=\"path22\" fill=\"white\"\u003e\n+ \u003cuse xlink:href=\"#path-1\"\u003e\u003c/use\u003e\n+ \u003c/mask\u003e\n+ \u003cg id=\"path22\"\u003e\u003c/g\u003e\n+ \u003cg id=\"g18\" mask=\"url(#mask-2)\"\u003e\n+ \u003cg transform=\"translate(382.736659, 312.879425)\"\u003e\n+ \u003cg id=\"g24\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(852.718192, 124.992771)\"\u003e\n+ \u003cpath d=\"M63.9833317,27.9148929 C59.2218085,22.9379001 51.2134221,17.9597442 40.3909323,17.9597442 C25.8888194,17.9597442 20.0453962,25.1013043 20.0453962,34.4074318 C20.0453962,48.4730484 29.7848226,55.1819277 50.5642821,55.1819277 C54.4602853,55.1819277 60.7364685,54.7492469 63.9833317,54.1002256 L63.9833317,27.9148929 L63.9833317,27.9148929 Z M44.2869356,113.827628 C28.9053426,113.827628 14.7975996,108.376082 3.78897657,99.301416 L10.5211864,87.6422957 C18.3131929,92.1866076 27.8374026,96.7320827 41.4728323,96.7320827 C57.0568452,96.7320827 63.9833317,88.7239978 63.9833317,75.3074024 L63.9833317,68.3821827 C60.9528485,69.0312039 54.6766653,69.4650479 50.7806621,69.4650479 C17.4476729,69.4650479 0.565379986,57.7791759 0.565379986,33.3245665 C0.565379986,11.4683685 13.9844297,0.43151772 34.3299658,0.43151772 C48.0351955,0.43151772 61.1692285,6.70771614 65.7143717,16.8780421 L69.1776149,3.02876588 L82.5978279,3.02876588 L82.5978279,75.5237428 C82.5978279,98.462806 72.6408582,113.827628 44.2869356,113.827628 L44.2869356,113.827628 Z\" id=\"path26\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g28\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(959.546624, 124.857151)\"\u003e\n+ \u003cpath d=\"M37.2266657,17.4468081 C30.0837992,17.4468081 23.8064527,18.3121698 19.0449295,20.4767371 L19.0449295,79.2306079 L19.0449295,86.0464943 C25.538656,91.457331 33.5470425,95.3526217 43.7203922,95.3526217 C62.1173451,95.3526217 69.2602116,82.3687072 69.2602116,61.3767077 C69.2602116,31.5135879 57.7885819,17.4468081 37.2266657,17.4468081 M45.2315622,113.963713 C28.208506,113.963713 19.0449295,102.384849 19.0449295,102.384849 L19.0449295,120.67143 L18.9844362,144.908535 L10.3967097,144.908535 L0.371103324,144.908535 L0.431596656,6.62629771 C9.73826309,2.73100702 22.5081728,0.567602823 36.3611458,0.567602823 C71.8579349,0.567602823 88.9566078,23.2891625 88.9566078,62.4584098 C88.9566078,93.4043948 73.1527248,113.963713 45.2315622,113.963713\" id=\"path30\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g32\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(509.576747, 125.294950)\"\u003e\n+ \u003cpath d=\"M68.636665,129.10638 C85.5189579,129.10638 96.3414476,123.480366 103.484314,117.853189 L111.669527,132.029302 C100.513161,141.811145 85.5073245,147.06845 69.5021849,147.06845 C29.0274926,147.06845 0.673569983,122.3975 0.673569983,72.6252464 C0.673569983,20.4709215 31.2622559,0.12910638 66.2553217,0.12910638 C83.7879179,0.12910638 98.7227909,4.24073748 108.462217,8.35236859 L108.063194,64.0763105 L108.063194,70.6502677 L108.063194,81.6057001 L56.1168719,81.6057001 L56.1168719,64.0763105 L89.2323178,64.0763105 L89.6313411,21.7701271 C85.3025779,19.6055598 77.7269514,17.8748364 67.554765,17.8748364 C39.4172223,17.8748364 20.5863462,35.5717154 20.5863462,72.8415868 C20.5863462,110.711628 40.0663623,129.10638 68.636665,129.10638\" id=\"path34\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g36\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(692.388992, 124.376085)\"\u003e\n+ \u003cpath d=\"M19.7766662,145.390067 L1.16216997,145.390067 L1.2226633,121.585642 L1.2226633,111.846834 L1.2226633,106.170806 L1.2226633,96.2656714 L1.2226633,39.5681976 L1.2226633,39.3518572 C1.2226633,16.4127939 11.1796331,1.04797161 39.5335557,1.04797161 C43.4504989,1.04797161 47.2836822,1.40388649 51.0051854,2.07965952 L51.0051854,18.7925385 C48.3109055,18.3796307 45.4351455,18.1446804 42.3476589,18.1446804 C26.763646,18.1446804 19.8371595,26.1516022 19.8371595,39.5681976 L19.8371595,96.2656714 L51.0051854,96.2656714 L51.0051854,111.846834 L19.8371595,111.846834 L19.7766662,145.390067 L19.7766662,145.390067 Z\" id=\"path38\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cpath d=\"M646.318899,128.021188 L664.933395,128.021188 L664.933395,236.223966 L646.318899,236.223966 L646.318899,128.021188 L646.318899,128.021188 Z\" id=\"path40\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003cpath d=\"M646.318899,251.154944 L664.933395,251.154944 L664.933395,269.766036 L646.318899,269.766036 L646.318899,251.154944 L646.318899,251.154944 Z\" id=\"path42\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003cg id=\"g44\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.464170, 0.676006)\"\u003e\n+ \u003cpath d=\"M429.269989,169.815599 L405.225053,243.802859 L357.571431,390.440955 C355.120288,397.984955 344.444378,397.984955 341.992071,390.440955 L294.337286,243.802859 L136.094873,243.802859 L88.4389245,390.440955 C85.9877812,397.984955 75.3118715,397.984955 72.8595648,390.440955 L25.2059427,243.802859 L1.16216997,169.815599 C-1.03187664,163.067173 1.37156997,155.674379 7.11261982,151.503429 L215.215498,0.336141836 L423.319539,151.503429 C429.060589,155.674379 431.462873,163.067173 429.269989,169.815599\" id=\"path46\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g48\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(135.410135, 1.012147)\"\u003e\n+ \u003cpath d=\"M80.269998,0 L80.269998,0 L159.391786,243.466717 L1.14820997,243.466717 L80.269998,0 L80.269998,0 Z\" id=\"path50\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g52\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\"\u003e\n+ \u003cg id=\"path54\"\u003e\u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g56\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(24.893471, 1.012613)\"\u003e\n+ \u003cpath d=\"M190.786662,0 L111.664874,243.465554 L0.777106647,243.465554 L190.786662,0 L190.786662,0 Z\" id=\"path58\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g60\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\"\u003e\n+ \u003cg id=\"path62\"\u003e\u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g64\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.077245, 0.223203)\"\u003e\n+ \u003cpath d=\"M25.5933327,244.255313 L25.5933327,244.255313 L1.54839663,170.268052 C-0.644486651,163.519627 1.75779662,156.126833 7.50000981,151.957046 L215.602888,0.789758846 L25.5933327,244.255313 L25.5933327,244.255313 Z\" id=\"path66\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g68\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\"\u003e\n+ \u003cg id=\"path70\"\u003e\u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g72\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(25.670578, 244.478283)\"\u003e\n+ \u003cpath d=\"M0,0 L110.887767,0 L63.2329818,146.638096 C60.7806751,154.183259 50.1047654,154.183259 47.6536221,146.638096 L0,0 L0,0 Z\" id=\"path74\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g76\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\"\u003e\n+ \u003cpath d=\"M0,0 L79.121788,243.465554 L190.009555,243.465554 L0,0 L0,0 Z\" id=\"path78\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g80\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(214.902910, 0.223203)\"\u003e\n+ \u003cpath d=\"M190.786662,244.255313 L190.786662,244.255313 L214.831598,170.268052 C217.024481,163.519627 214.622198,156.126833 208.879985,151.957046 L0.777106647,0.789758846 L190.786662,244.255313 L190.786662,244.255313 Z\" id=\"path82\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g84\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(294.009575, 244.478283)\"\u003e\n+ \u003cpath d=\"M111.679997,0 L0.79222998,0 L48.4470155,146.638096 C50.8993221,154.183259 61.5752318,154.183259 64.0263751,146.638096 L111.679997,0 L111.679997,0 Z\" id=\"path86\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+\u003c/svg\u003e\n\\ No newline at end of file\n", "new_path": "files/images/wm.svg", "old_path": "files/images/wm.svg", @@ -3436,6 +4049,28 @@ "too_large": false }, { + "diff": "--- a/files/ruby/popen.rb\n+++ b/files/ruby/popen.rb\n@@ -6,12 +6,18 @@ module Popen\n \n def popen(cmd, path=nil)\n unless cmd.is_a?(Array)\n- raise \"System commands must be given as an array of strings\"\n+ raise RuntimeError, \"System commands must be given as an array of strings\"\n end\n \n path ||= Dir.pwd\n- vars = { \"PWD\" =\u003e path }\n- options = { chdir: path }\n+\n+ vars = {\n+ \"PWD\" =\u003e path\n+ }\n+\n+ options = {\n+ chdir: path\n+ }\n \n unless File.directory?(path)\n FileUtils.mkdir_p(path)\n@@ -19,6 +25,7 @@ module Popen\n \n @cmd_output = \"\"\n @cmd_status = 0\n+\n Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr|\n @cmd_output \u003c\u003c stdout.read\n @cmd_output \u003c\u003c stderr.read\n", + "new_path": "files/ruby/popen.rb", + "old_path": "files/ruby/popen.rb", + "a_mode": "100644", + "b_mode": "100644", + "new_file": false, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- a/files/ruby/regex.rb\n+++ b/files/ruby/regex.rb\n@@ -19,14 +19,12 @@ module Gitlab\n end\n \n def archive_formats_regex\n- #|zip|tar| tar.gz | tar.bz2 |\n- /(zip|tar|tar\\.gz|tgz|gz|tar\\.bz2|tbz|tbz2|tb2|bz2)/\n+ /(zip|tar|7z|tar\\.gz|tgz|gz|tar\\.bz2|tbz|tbz2|tb2|bz2)/\n end\n \n def git_reference_regex\n # Valid git ref regex, see:\n # https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html\n-\n %r{\n (?!\n (?# doesn't begins with)\n", + "new_path": "files/ruby/regex.rb", + "old_path": "files/ruby/regex.rb", + "a_mode": "100644", + "b_mode": "100644", + "new_file": false, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { "diff": "--- /dev/null\n+++ b/files/whitespace\n@@ -0,0 +1 @@\n+test \n", "new_path": "files/whitespace", "old_path": "files/whitespace", @@ -3456,231 +4091,29 @@ "renamed_file": false, "deleted_file": false, "too_large": false - } - ], - "merge_request_id": 15, - "created_at": "2016-03-22T15:13:45.692Z", - "updated_at": "2016-03-22T15:13:45.808Z", - "base_commit_sha": "5937ac0a7beb003549fc5fd26fc247adbce4a52e", - "real_size": "6" - } - }, - { - "id": 14, - "target_branch": "test-1", - "source_branch": "test-10", - "source_project_id": 5, - "author_id": 10, - "assignee_id": 1, - "title": "Tempore aliquid sit amet odit qui cum iusto voluptatibus asperiores.", - "created_at": "2016-03-22T15:13:45.442Z", - "updated_at": "2016-03-22T15:20:30.735Z", - "milestone_id": 10, - "state": "opened", - "merge_status": "unchecked", - "target_project_id": 5, - "iid": 6, - "description": "Quis et et autem saepe ut. Eum corporis tempore cum dolore. Molestiae pariatur voluptatem officia perferendis aut veniam.", - "position": 0, - "locked_at": null, - "updated_by_id": null, - "merge_error": null, - "merge_params": { - - }, - "merge_when_build_succeeds": false, - "merge_user_id": null, - "merge_commit_sha": null, - "deleted_at": null, - "notes": [ - { - "id": 1239, - "note": "Aspernatur suscipit veritatis aliquid rerum.", - "noteable_type": "MergeRequest", - "author_id": 1, - "created_at": "2016-03-22T15:20:30.731Z", - "updated_at": "2016-03-22T15:20:30.731Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 14, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Administrator" - } - }, - { - "id": 1238, - "note": "Rerum deleniti omnis porro commodi.", - "noteable_type": "MergeRequest", - "author_id": 3, - "created_at": "2016-03-22T15:20:30.701Z", - "updated_at": "2016-03-22T15:20:30.701Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 14, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } - }, - { - "id": 1237, - "note": "Eaque ut magnam rerum non dolores esse.", - "noteable_type": "MergeRequest", - "author_id": 4, - "created_at": "2016-03-22T15:20:30.667Z", - "updated_at": "2016-03-22T15:20:30.667Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 14, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Julius Moore" - } - }, - { - "id": 1236, - "note": "Fugit et aut similique illum ut natus maiores et.", - "noteable_type": "MergeRequest", - "author_id": 10, - "created_at": "2016-03-22T15:20:30.637Z", - "updated_at": "2016-03-22T15:20:30.637Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 14, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } - }, - { - "id": 1235, - "note": "Qui qui temporibus eos aliquam.", - "noteable_type": "MergeRequest", - "author_id": 12, - "created_at": "2016-03-22T15:20:30.608Z", - "updated_at": "2016-03-22T15:20:30.608Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 14, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } - }, - { - "id": 1234, - "note": "Voluptates hic dolorum aut inventore.", - "noteable_type": "MergeRequest", - "author_id": 22, - "created_at": "2016-03-22T15:20:30.575Z", - "updated_at": "2016-03-22T15:20:30.575Z", - "project_id": 5, - "attachment": { - "url": null }, - "line_code": null, - "commit_id": null, - "noteable_id": 14, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 0" - } - }, - { - "id": 1233, - "note": "Dolorum iure at dolor dolores numquam iusto.", - "noteable_type": "MergeRequest", - "author_id": 24, - "created_at": "2016-03-22T15:20:30.548Z", - "updated_at": "2016-03-22T15:20:30.548Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 14, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 2" - } - }, - { - "id": 1232, - "note": "Nihil est eum aspernatur amet minus et corporis consectetur.", - "noteable_type": "MergeRequest", - "author_id": 26, - "created_at": "2016-03-22T15:20:30.517Z", - "updated_at": "2016-03-22T15:20:30.517Z", - "project_id": 5, - "attachment": { - "url": null + { + "diff": "--- /dev/null\n+++ b/gitlab-grack\n@@ -0,0 +1 @@\n+Subproject commit 645f6c4c82fd3f5e06f67134450a570b795e55a6\n", + "new_path": "gitlab-grack", + "old_path": "gitlab-grack", + "a_mode": "0", + "b_mode": "160000", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false }, - "line_code": null, - "commit_id": null, - "noteable_id": 14, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 4" - } - } - ], - "merge_request_diff": { - "id": 14, - "state": "collected", - "st_commits": [ { - "id": "bce96ecee98f51fa5d91021e6c42859a35a701ad", - "message": "fixes #10\n", - "parent_ids": [ - "be93687618e4b132087f430a4d8fc3a609c9b77c" - ], - "authored_date": "2016-01-19T15:40:05.000+01:00", - "author_name": "Test Lopez", - "author_email": "Test@Testlopez.es", - "committed_date": "2016-01-19T15:40:05.000+01:00", - "committer_name": "Test Lopez", - "committer_email": "Test@Testlopez.es" - } - ], - "st_diffs": [ + "diff": "--- /dev/null\n+++ b/gitlab-shell\n@@ -0,0 +1 @@\n+Subproject commit 79bceae69cb5750d6567b223597999bfa91cb3b9\n", + "new_path": "gitlab-shell", + "old_path": "gitlab-shell", + "a_mode": "0", + "b_mode": "160000", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, { "diff": "--- /dev/null\n+++ b/test\n", "new_path": "test", @@ -3694,34 +4127,60 @@ } ], "merge_request_id": 14, - "created_at": "2016-03-22T15:13:45.444Z", - "updated_at": "2016-03-22T15:13:45.486Z", - "base_commit_sha": "be93687618e4b132087f430a4d8fc3a609c9b77c", - "real_size": "1" - } + "created_at": "2016-06-14T15:02:24.770Z", + "updated_at": "2016-06-14T15:02:25.007Z", + "base_commit_sha": "ae73cb07c9eeaf35924a10f713b364d32b2dd34f", + "real_size": "15" + }, + "events": [ + { + "id": 224, + "target_type": "MergeRequest", + "target_id": 14, + "title": null, + "data": null, + "project_id": 36, + "created_at": "2016-06-14T15:02:25.113Z", + "updated_at": "2016-06-14T15:02:25.113Z", + "action": 1, + "author_id": 1 + }, + { + "id": 174, + "target_type": "MergeRequest", + "target_id": 14, + "title": null, + "data": null, + "project_id": 5, + "created_at": "2016-06-14T15:02:25.113Z", + "updated_at": "2016-06-14T15:02:25.113Z", + "action": 1, + "author_id": 20 + } + ] }, { "id": 13, - "target_branch": "test-11", - "source_branch": "test-12", + "target_branch": "improve/awesome", + "source_branch": "test-8", "source_project_id": 5, - "author_id": 1, - "assignee_id": 26, - "title": "Voluptas minus sunt voluptatum quis quia ut velit distinctio itaque.", - "created_at": "2016-03-22T15:13:45.164Z", - "updated_at": "2016-03-22T15:20:30.994Z", - "milestone_id": 11, + "author_id": 16, + "assignee_id": 25, + "title": "Voluptates consequatur eius nemo amet libero animi illum delectus tempore.", + "created_at": "2016-06-14T15:02:24.415Z", + "updated_at": "2016-06-14T15:02:59.958Z", + "milestone_id": 17, "state": "opened", "merge_status": "unchecked", "target_project_id": 5, "iid": 5, - "description": "Ea ut modi consectetur et minus beatae. Et sunt ducimus praesentium libero officia maiores voluptas cumque. Rerum in aut corporis et ullam omnis.", + "description": "Est eaque quasi qui qui. Similique voluptatem impedit iusto ratione reprehenderit. Itaque est illum ut nulla aut.", "position": 0, "locked_at": null, "updated_by_id": null, "merge_error": null, "merge_params": { - + "force_remove_source_branch": null }, "merge_when_build_succeeds": false, "merge_user_id": null, @@ -3729,12 +4188,12 @@ "deleted_at": null, "notes": [ { - "id": 1247, - "note": "Non error magnam placeat cupiditate eum.", + "id": 793, + "note": "In illum maxime aperiam nulla est aspernatur.", "noteable_type": "MergeRequest", - "author_id": 1, - "created_at": "2016-03-22T15:20:30.989Z", - "updated_at": "2016-03-22T15:20:30.989Z", + "author_id": 26, + "created_at": "2016-06-14T15:02:59.782Z", + "updated_at": "2016-06-14T15:02:59.782Z", "project_id": 5, "attachment": { "url": null @@ -3745,17 +4204,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 1246, - "note": "Eos optio et architecto eligendi ea est nihil.", + "id": 794, + "note": "Enim quia perferendis cum distinctio tenetur optio voluptas veniam.", "noteable_type": "MergeRequest", - "author_id": 3, - "created_at": "2016-03-22T15:20:30.957Z", - "updated_at": "2016-03-22T15:20:30.957Z", + "author_id": 25, + "created_at": "2016-06-14T15:02:59.807Z", + "updated_at": "2016-06-14T15:02:59.807Z", "project_id": 5, "attachment": { "url": null @@ -3766,17 +4228,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 1245, - "note": "Reprehenderit in atque dolor et repudiandae a est.", + "id": 795, + "note": "Dolor ad quia quis pariatur ducimus.", "noteable_type": "MergeRequest", - "author_id": 4, - "created_at": "2016-03-22T15:20:30.928Z", - "updated_at": "2016-03-22T15:20:30.928Z", + "author_id": 22, + "created_at": "2016-06-14T15:02:59.831Z", + "updated_at": "2016-06-14T15:02:59.831Z", "project_id": 5, "attachment": { "url": null @@ -3787,17 +4252,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 1244, - "note": "Numquam fugit doloremque iure odio et.", + "id": 796, + "note": "Et a odio voluptate aut.", "noteable_type": "MergeRequest", - "author_id": 10, - "created_at": "2016-03-22T15:20:30.902Z", - "updated_at": "2016-03-22T15:20:30.902Z", + "author_id": 20, + "created_at": "2016-06-14T15:02:59.854Z", + "updated_at": "2016-06-14T15:02:59.854Z", "project_id": 5, "attachment": { "url": null @@ -3808,17 +4276,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 1243, - "note": "Doloribus laboriosam id harum voluptatum vitae ut quam.", + "id": 797, + "note": "Quis nihil temporibus voluptatum modi minima a ut.", "noteable_type": "MergeRequest", - "author_id": 12, - "created_at": "2016-03-22T15:20:30.863Z", - "updated_at": "2016-03-22T15:20:30.863Z", + "author_id": 16, + "created_at": "2016-06-14T15:02:59.879Z", + "updated_at": "2016-06-14T15:02:59.879Z", "project_id": 5, "attachment": { "url": null @@ -3829,17 +4300,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 1242, - "note": "Harum et ut ipsum dolore ea.", + "id": 798, + "note": "Ut alias consequatur in nostrum.", "noteable_type": "MergeRequest", - "author_id": 22, - "created_at": "2016-03-22T15:20:30.832Z", - "updated_at": "2016-03-22T15:20:30.832Z", + "author_id": 15, + "created_at": "2016-06-14T15:02:59.904Z", + "updated_at": "2016-06-14T15:02:59.904Z", "project_id": 5, "attachment": { "url": null @@ -3850,17 +4324,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 1241, - "note": "Corporis sed soluta ut est modi natus ab.", + "id": 799, + "note": "Voluptatibus aperiam assumenda et neque sint libero.", "noteable_type": "MergeRequest", - "author_id": 24, - "created_at": "2016-03-22T15:20:30.802Z", - "updated_at": "2016-03-22T15:20:30.802Z", + "author_id": 6, + "created_at": "2016-06-14T15:02:59.926Z", + "updated_at": "2016-06-14T15:02:59.926Z", "project_id": 5, "attachment": { "url": null @@ -3871,17 +4348,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 1240, - "note": "Corrupti totam tenetur officiis ratione dolores est qui vel.", + "id": 800, + "note": "Veritatis voluptatem dolor dolores magni quo ut ipsa fuga.", "noteable_type": "MergeRequest", - "author_id": 26, - "created_at": "2016-03-22T15:20:30.771Z", - "updated_at": "2016-03-22T15:20:30.771Z", + "author_id": 1, + "created_at": "2016-06-14T15:02:59.956Z", + "updated_at": "2016-06-14T15:02:59.956Z", "project_id": 5, "attachment": { "url": null @@ -3892,9 +4372,12 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ], "merge_request_diff": { @@ -3902,21 +4385,274 @@ "state": "collected", "st_commits": [ { - "id": "a4e5dfebf42e34596526acb8611bc7ed80e4eb3f", + "id": "0bfedc29d30280c7e8564e19f654584b459e5868", "message": "fixes #10\n", "parent_ids": [ "be93687618e4b132087f430a4d8fc3a609c9b77c" ], - "authored_date": "2016-01-19T15:44:02.000+01:00", - "author_name": "Test Lopez", - "author_email": "Test@Testlopez.es", - "committed_date": "2016-01-19T15:44:02.000+01:00", - "committer_name": "Test Lopez", - "committer_email": "Test@Testlopez.es" + "authored_date": "2016-01-19T15:25:23.000+01:00", + "author_name": "James Lopez", + "author_email": "james@jameslopez.es", + "committed_date": "2016-01-19T15:25:23.000+01:00", + "committer_name": "James Lopez", + "committer_email": "james@jameslopez.es" + }, + { + "id": "be93687618e4b132087f430a4d8fc3a609c9b77c", + "message": "Merge branch 'master' into 'master'\r\n\r\nLFS object pointer.\r\n\r\n\r\n\r\nSee merge request !6", + "parent_ids": [ + "5f923865dde3436854e9ceb9cdb7815618d4e849", + "048721d90c449b244b7b4c53a9186b04330174ec" + ], + "authored_date": "2015-12-07T12:52:12.000+01:00", + "author_name": "Marin Jankovski", + "author_email": "marin@gitlab.com", + "committed_date": "2015-12-07T12:52:12.000+01:00", + "committer_name": "Marin Jankovski", + "committer_email": "marin@gitlab.com" + }, + { + "id": "048721d90c449b244b7b4c53a9186b04330174ec", + "message": "LFS object pointer.\n", + "parent_ids": [ + "5f923865dde3436854e9ceb9cdb7815618d4e849" + ], + "authored_date": "2015-12-07T11:54:28.000+01:00", + "author_name": "Marin Jankovski", + "author_email": "maxlazio@gmail.com", + "committed_date": "2015-12-07T11:54:28.000+01:00", + "committer_name": "Marin Jankovski", + "committer_email": "maxlazio@gmail.com" + }, + { + "id": "5f923865dde3436854e9ceb9cdb7815618d4e849", + "message": "GitLab currently doesn't support patches that involve a merge commit: add a commit here\n", + "parent_ids": [ + "d2d430676773caa88cdaf7c55944073b2fd5561a" + ], + "authored_date": "2015-11-13T16:27:12.000+01:00", + "author_name": "Stan Hu", + "author_email": "stanhu@gmail.com", + "committed_date": "2015-11-13T16:27:12.000+01:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@gmail.com" + }, + { + "id": "d2d430676773caa88cdaf7c55944073b2fd5561a", + "message": "Merge branch 'add-svg' into 'master'\r\n\r\nAdd GitLab SVG\r\n\r\nAdded to test preview of sanitized SVG images\r\n\r\nSee merge request !5", + "parent_ids": [ + "59e29889be61e6e0e5e223bfa9ac2721d31605b8", + "2ea1f3dec713d940208fb5ce4a38765ecb5d3f73" + ], + "authored_date": "2015-11-13T08:50:17.000+01:00", + "author_name": "Stan Hu", + "author_email": "stanhu@gmail.com", + "committed_date": "2015-11-13T08:50:17.000+01:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@gmail.com" + }, + { + "id": "2ea1f3dec713d940208fb5ce4a38765ecb5d3f73", + "message": "Add GitLab SVG\n", + "parent_ids": [ + "59e29889be61e6e0e5e223bfa9ac2721d31605b8" + ], + "authored_date": "2015-11-13T08:39:43.000+01:00", + "author_name": "Stan Hu", + "author_email": "stanhu@gmail.com", + "committed_date": "2015-11-13T08:39:43.000+01:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@gmail.com" + }, + { + "id": "59e29889be61e6e0e5e223bfa9ac2721d31605b8", + "message": "Merge branch 'whitespace' into 'master'\r\n\r\nadd whitespace test file\r\n\r\nSorry, I did a mistake.\r\nGit ignore empty files.\r\nSo I add a new whitespace test file.\r\n\r\nSee merge request !4", + "parent_ids": [ + "19e2e9b4ef76b422ce1154af39a91323ccc57434", + "66eceea0db202bb39c4e445e8ca28689645366c5" + ], + "authored_date": "2015-11-13T07:21:40.000+01:00", + "author_name": "Stan Hu", + "author_email": "stanhu@gmail.com", + "committed_date": "2015-11-13T07:21:40.000+01:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@gmail.com" + }, + { + "id": "66eceea0db202bb39c4e445e8ca28689645366c5", + "message": "add spaces in whitespace file\n", + "parent_ids": [ + "08f22f255f082689c0d7d39d19205085311542bc" + ], + "authored_date": "2015-11-13T06:01:27.000+01:00", + "author_name": "윤민식", + "author_email": "minsik.yoon@samsung.com", + "committed_date": "2015-11-13T06:01:27.000+01:00", + "committer_name": "윤민식", + "committer_email": "minsik.yoon@samsung.com" + }, + { + "id": "08f22f255f082689c0d7d39d19205085311542bc", + "message": "remove emtpy file.(beacase git ignore empty file)\nadd whitespace test file.\n", + "parent_ids": [ + "c642fe9b8b9f28f9225d7ea953fe14e74748d53b" + ], + "authored_date": "2015-11-13T06:00:16.000+01:00", + "author_name": "윤민식", + "author_email": "minsik.yoon@samsung.com", + "committed_date": "2015-11-13T06:00:16.000+01:00", + "committer_name": "윤민식", + "committer_email": "minsik.yoon@samsung.com" + }, + { + "id": "19e2e9b4ef76b422ce1154af39a91323ccc57434", + "message": "Merge branch 'whitespace' into 'master'\r\n\r\nadd spaces\r\n\r\nTo test this pull request.(https://github.com/gitlabhq/gitlabhq/pull/9757)\r\nJust add whitespaces.\r\n\r\nSee merge request !3", + "parent_ids": [ + "c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd", + "c642fe9b8b9f28f9225d7ea953fe14e74748d53b" + ], + "authored_date": "2015-11-13T05:23:14.000+01:00", + "author_name": "Stan Hu", + "author_email": "stanhu@gmail.com", + "committed_date": "2015-11-13T05:23:14.000+01:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@gmail.com" + }, + { + "id": "c642fe9b8b9f28f9225d7ea953fe14e74748d53b", + "message": "add whitespace in empty\n", + "parent_ids": [ + "9a944d90955aaf45f6d0c88f30e27f8d2c41cec0" + ], + "authored_date": "2015-11-13T05:08:45.000+01:00", + "author_name": "윤민식", + "author_email": "minsik.yoon@samsung.com", + "committed_date": "2015-11-13T05:08:45.000+01:00", + "committer_name": "윤민식", + "committer_email": "minsik.yoon@samsung.com" + }, + { + "id": "9a944d90955aaf45f6d0c88f30e27f8d2c41cec0", + "message": "add empty file\n", + "parent_ids": [ + "c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd" + ], + "authored_date": "2015-11-13T05:08:04.000+01:00", + "author_name": "윤민식", + "author_email": "minsik.yoon@samsung.com", + "committed_date": "2015-11-13T05:08:04.000+01:00", + "committer_name": "윤민식", + "committer_email": "minsik.yoon@samsung.com" + }, + { + "id": "c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd", + "message": "Add ISO-8859 test file\n", + "parent_ids": [ + "e56497bb5f03a90a51293fc6d516788730953899" + ], + "authored_date": "2015-08-25T17:53:12.000+02:00", + "author_name": "Stan Hu", + "author_email": "stanhu@packetzoom.com", + "committed_date": "2015-08-25T17:53:12.000+02:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@packetzoom.com" + }, + { + "id": "e56497bb5f03a90a51293fc6d516788730953899", + "message": "Merge branch 'tree_helper_spec' into 'master'\n\nAdd directory structure for tree_helper spec\n\nThis directory structure is needed for a testing the method flatten_tree(tree) in the TreeHelper module\n\nSee [merge request #275](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/275#note_732774)\n\nSee merge request !2\n", + "parent_ids": [ + "5937ac0a7beb003549fc5fd26fc247adbce4a52e", + "4cd80ccab63c82b4bad16faa5193fbd2aa06df40" + ], + "authored_date": "2015-01-10T22:23:29.000+01:00", + "author_name": "Sytse Sijbrandij", + "author_email": "sytse@gitlab.com", + "committed_date": "2015-01-10T22:23:29.000+01:00", + "committer_name": "Sytse Sijbrandij", + "committer_email": "sytse@gitlab.com" + }, + { + "id": "4cd80ccab63c82b4bad16faa5193fbd2aa06df40", + "message": "add directory structure for tree_helper spec\n", + "parent_ids": [ + "5937ac0a7beb003549fc5fd26fc247adbce4a52e" + ], + "authored_date": "2015-01-10T21:28:18.000+01:00", + "author_name": "marmis85", + "author_email": "marmis85@gmail.com", + "committed_date": "2015-01-10T21:28:18.000+01:00", + "committer_name": "marmis85", + "committer_email": "marmis85@gmail.com" } ], "st_diffs": [ { + "diff": "--- a/CHANGELOG\n+++ b/CHANGELOG\n@@ -1,4 +1,6 @@\n-v 6.7.0\n+v6.8.0\n+\n+v6.7.0\n - Add support for Gemnasium as a Project Service (Olivier Gonzalez)\n - Add edit file button to MergeRequest diff\n - Public groups (Jason Hollingsworth)\n", + "new_path": "CHANGELOG", + "old_path": "CHANGELOG", + "a_mode": "100644", + "b_mode": "100644", + "new_file": false, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- /dev/null\n+++ b/encoding/iso8859.txt\n@@ -0,0 +1 @@\n+Äü\n", + "new_path": "encoding/iso8859.txt", + "old_path": "encoding/iso8859.txt", + "a_mode": "0", + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- /dev/null\n+++ b/files/images/wm.svg\n@@ -0,0 +1,78 @@\n+\u003c?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?\u003e\n+\u003csvg width=\"1300px\" height=\"680px\" viewBox=\"0 0 1300 680\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\"\u003e\n+ \u003c!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch --\u003e\n+ \u003ctitle\u003ewm\u003c/title\u003e\n+ \u003cdesc\u003eCreated with Sketch.\u003c/desc\u003e\n+ \u003cdefs\u003e\n+ \u003cpath id=\"path-1\" d=\"M-69.8,1023.54607 L1675.19996,1023.54607 L1675.19996,0 L-69.8,0 L-69.8,1023.54607 L-69.8,1023.54607 Z\"\u003e\u003c/path\u003e\n+ \u003c/defs\u003e\n+ \u003cg id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\"\u003e\n+ \u003cpath d=\"M1300,680 L0,680 L0,0 L1300,0 L1300,680 L1300,680 Z\" id=\"bg\" fill=\"#30353E\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003cg id=\"gitlab_logo\" sketch:type=\"MSLayerGroup\" transform=\"translate(-262.000000, -172.000000)\"\u003e\n+ \u003cg id=\"g10\" transform=\"translate(872.500000, 512.354581) scale(1, -1) translate(-872.500000, -512.354581) translate(0.000000, 0.290751)\"\u003e\n+ \u003cg id=\"g12\" transform=\"translate(1218.022652, 440.744871)\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\n+ \u003cpath d=\"M-50.0233338,141.900706 L-69.07059,141.900706 L-69.0100967,0.155858152 L8.04444805,0.155858152 L8.04444805,17.6840847 L-49.9628405,17.6840847 L-50.0233338,141.900706 L-50.0233338,141.900706 Z\" id=\"path14\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g16\"\u003e\n+ \u003cg id=\"g18-Clipped\"\u003e\n+ \u003cmask id=\"mask-2\" sketch:name=\"path22\" fill=\"white\"\u003e\n+ \u003cuse xlink:href=\"#path-1\"\u003e\u003c/use\u003e\n+ \u003c/mask\u003e\n+ \u003cg id=\"path22\"\u003e\u003c/g\u003e\n+ \u003cg id=\"g18\" mask=\"url(#mask-2)\"\u003e\n+ \u003cg transform=\"translate(382.736659, 312.879425)\"\u003e\n+ \u003cg id=\"g24\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(852.718192, 124.992771)\"\u003e\n+ \u003cpath d=\"M63.9833317,27.9148929 C59.2218085,22.9379001 51.2134221,17.9597442 40.3909323,17.9597442 C25.8888194,17.9597442 20.0453962,25.1013043 20.0453962,34.4074318 C20.0453962,48.4730484 29.7848226,55.1819277 50.5642821,55.1819277 C54.4602853,55.1819277 60.7364685,54.7492469 63.9833317,54.1002256 L63.9833317,27.9148929 L63.9833317,27.9148929 Z M44.2869356,113.827628 C28.9053426,113.827628 14.7975996,108.376082 3.78897657,99.301416 L10.5211864,87.6422957 C18.3131929,92.1866076 27.8374026,96.7320827 41.4728323,96.7320827 C57.0568452,96.7320827 63.9833317,88.7239978 63.9833317,75.3074024 L63.9833317,68.3821827 C60.9528485,69.0312039 54.6766653,69.4650479 50.7806621,69.4650479 C17.4476729,69.4650479 0.565379986,57.7791759 0.565379986,33.3245665 C0.565379986,11.4683685 13.9844297,0.43151772 34.3299658,0.43151772 C48.0351955,0.43151772 61.1692285,6.70771614 65.7143717,16.8780421 L69.1776149,3.02876588 L82.5978279,3.02876588 L82.5978279,75.5237428 C82.5978279,98.462806 72.6408582,113.827628 44.2869356,113.827628 L44.2869356,113.827628 Z\" id=\"path26\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g28\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(959.546624, 124.857151)\"\u003e\n+ \u003cpath d=\"M37.2266657,17.4468081 C30.0837992,17.4468081 23.8064527,18.3121698 19.0449295,20.4767371 L19.0449295,79.2306079 L19.0449295,86.0464943 C25.538656,91.457331 33.5470425,95.3526217 43.7203922,95.3526217 C62.1173451,95.3526217 69.2602116,82.3687072 69.2602116,61.3767077 C69.2602116,31.5135879 57.7885819,17.4468081 37.2266657,17.4468081 M45.2315622,113.963713 C28.208506,113.963713 19.0449295,102.384849 19.0449295,102.384849 L19.0449295,120.67143 L18.9844362,144.908535 L10.3967097,144.908535 L0.371103324,144.908535 L0.431596656,6.62629771 C9.73826309,2.73100702 22.5081728,0.567602823 36.3611458,0.567602823 C71.8579349,0.567602823 88.9566078,23.2891625 88.9566078,62.4584098 C88.9566078,93.4043948 73.1527248,113.963713 45.2315622,113.963713\" id=\"path30\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g32\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(509.576747, 125.294950)\"\u003e\n+ \u003cpath d=\"M68.636665,129.10638 C85.5189579,129.10638 96.3414476,123.480366 103.484314,117.853189 L111.669527,132.029302 C100.513161,141.811145 85.5073245,147.06845 69.5021849,147.06845 C29.0274926,147.06845 0.673569983,122.3975 0.673569983,72.6252464 C0.673569983,20.4709215 31.2622559,0.12910638 66.2553217,0.12910638 C83.7879179,0.12910638 98.7227909,4.24073748 108.462217,8.35236859 L108.063194,64.0763105 L108.063194,70.6502677 L108.063194,81.6057001 L56.1168719,81.6057001 L56.1168719,64.0763105 L89.2323178,64.0763105 L89.6313411,21.7701271 C85.3025779,19.6055598 77.7269514,17.8748364 67.554765,17.8748364 C39.4172223,17.8748364 20.5863462,35.5717154 20.5863462,72.8415868 C20.5863462,110.711628 40.0663623,129.10638 68.636665,129.10638\" id=\"path34\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g36\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(692.388992, 124.376085)\"\u003e\n+ \u003cpath d=\"M19.7766662,145.390067 L1.16216997,145.390067 L1.2226633,121.585642 L1.2226633,111.846834 L1.2226633,106.170806 L1.2226633,96.2656714 L1.2226633,39.5681976 L1.2226633,39.3518572 C1.2226633,16.4127939 11.1796331,1.04797161 39.5335557,1.04797161 C43.4504989,1.04797161 47.2836822,1.40388649 51.0051854,2.07965952 L51.0051854,18.7925385 C48.3109055,18.3796307 45.4351455,18.1446804 42.3476589,18.1446804 C26.763646,18.1446804 19.8371595,26.1516022 19.8371595,39.5681976 L19.8371595,96.2656714 L51.0051854,96.2656714 L51.0051854,111.846834 L19.8371595,111.846834 L19.7766662,145.390067 L19.7766662,145.390067 Z\" id=\"path38\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cpath d=\"M646.318899,128.021188 L664.933395,128.021188 L664.933395,236.223966 L646.318899,236.223966 L646.318899,128.021188 L646.318899,128.021188 Z\" id=\"path40\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003cpath d=\"M646.318899,251.154944 L664.933395,251.154944 L664.933395,269.766036 L646.318899,269.766036 L646.318899,251.154944 L646.318899,251.154944 Z\" id=\"path42\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003cg id=\"g44\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.464170, 0.676006)\"\u003e\n+ \u003cpath d=\"M429.269989,169.815599 L405.225053,243.802859 L357.571431,390.440955 C355.120288,397.984955 344.444378,397.984955 341.992071,390.440955 L294.337286,243.802859 L136.094873,243.802859 L88.4389245,390.440955 C85.9877812,397.984955 75.3118715,397.984955 72.8595648,390.440955 L25.2059427,243.802859 L1.16216997,169.815599 C-1.03187664,163.067173 1.37156997,155.674379 7.11261982,151.503429 L215.215498,0.336141836 L423.319539,151.503429 C429.060589,155.674379 431.462873,163.067173 429.269989,169.815599\" id=\"path46\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g48\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(135.410135, 1.012147)\"\u003e\n+ \u003cpath d=\"M80.269998,0 L80.269998,0 L159.391786,243.466717 L1.14820997,243.466717 L80.269998,0 L80.269998,0 Z\" id=\"path50\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g52\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\"\u003e\n+ \u003cg id=\"path54\"\u003e\u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g56\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(24.893471, 1.012613)\"\u003e\n+ \u003cpath d=\"M190.786662,0 L111.664874,243.465554 L0.777106647,243.465554 L190.786662,0 L190.786662,0 Z\" id=\"path58\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g60\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\"\u003e\n+ \u003cg id=\"path62\"\u003e\u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g64\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.077245, 0.223203)\"\u003e\n+ \u003cpath d=\"M25.5933327,244.255313 L25.5933327,244.255313 L1.54839663,170.268052 C-0.644486651,163.519627 1.75779662,156.126833 7.50000981,151.957046 L215.602888,0.789758846 L25.5933327,244.255313 L25.5933327,244.255313 Z\" id=\"path66\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g68\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\"\u003e\n+ \u003cg id=\"path70\"\u003e\u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g72\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(25.670578, 244.478283)\"\u003e\n+ \u003cpath d=\"M0,0 L110.887767,0 L63.2329818,146.638096 C60.7806751,154.183259 50.1047654,154.183259 47.6536221,146.638096 L0,0 L0,0 Z\" id=\"path74\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g76\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\"\u003e\n+ \u003cpath d=\"M0,0 L79.121788,243.465554 L190.009555,243.465554 L0,0 L0,0 Z\" id=\"path78\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g80\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(214.902910, 0.223203)\"\u003e\n+ \u003cpath d=\"M190.786662,244.255313 L190.786662,244.255313 L214.831598,170.268052 C217.024481,163.519627 214.622198,156.126833 208.879985,151.957046 L0.777106647,0.789758846 L190.786662,244.255313 L190.786662,244.255313 Z\" id=\"path82\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g84\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(294.009575, 244.478283)\"\u003e\n+ \u003cpath d=\"M111.679997,0 L0.79222998,0 L48.4470155,146.638096 C50.8993221,154.183259 61.5752318,154.183259 64.0263751,146.638096 L111.679997,0 L111.679997,0 Z\" id=\"path86\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+\u003c/svg\u003e\n\\ No newline at end of file\n", + "new_path": "files/images/wm.svg", + "old_path": "files/images/wm.svg", + "a_mode": "0", + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- /dev/null\n+++ b/files/lfs/lfs_object.iso\n@@ -0,0 +1,4 @@\n+version https://git-lfs.github.com/spec/v1\n+oid sha256:91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897\n+size 1575078\n+\n", + "new_path": "files/lfs/lfs_object.iso", + "old_path": "files/lfs/lfs_object.iso", + "a_mode": "0", + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- /dev/null\n+++ b/files/whitespace\n@@ -0,0 +1 @@\n+test \n", + "new_path": "files/whitespace", + "old_path": "files/whitespace", + "a_mode": "0", + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- /dev/null\n+++ b/foo/bar/.gitkeep\n", + "new_path": "foo/bar/.gitkeep", + "old_path": "foo/bar/.gitkeep", + "a_mode": "0", + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { "diff": "--- /dev/null\n+++ b/test\n", "new_path": "test", "old_path": "test", @@ -3929,34 +4665,60 @@ } ], "merge_request_id": 13, - "created_at": "2016-03-22T15:13:45.167Z", - "updated_at": "2016-03-22T15:13:45.216Z", - "base_commit_sha": "be93687618e4b132087f430a4d8fc3a609c9b77c", - "real_size": "1" - } + "created_at": "2016-06-14T15:02:24.420Z", + "updated_at": "2016-06-14T15:02:24.561Z", + "base_commit_sha": "5937ac0a7beb003549fc5fd26fc247adbce4a52e", + "real_size": "7" + }, + "events": [ + { + "id": 225, + "target_type": "MergeRequest", + "target_id": 13, + "title": null, + "data": null, + "project_id": 36, + "created_at": "2016-06-14T15:02:24.636Z", + "updated_at": "2016-06-14T15:02:24.636Z", + "action": 1, + "author_id": 16 + }, + { + "id": 173, + "target_type": "MergeRequest", + "target_id": 13, + "title": null, + "data": null, + "project_id": 5, + "created_at": "2016-06-14T15:02:24.636Z", + "updated_at": "2016-06-14T15:02:24.636Z", + "action": 1, + "author_id": 16 + } + ] }, { "id": 12, - "target_branch": "test-15", + "target_branch": "flatten-dirs", "source_branch": "test-2", "source_project_id": 5, - "author_id": 24, - "assignee_id": 12, - "title": "In assumenda nam quaerat qui eos sit facilis enim quia quis.", - "created_at": "2016-03-22T15:13:44.837Z", - "updated_at": "2016-03-22T15:20:31.258Z", - "milestone_id": 10, + "author_id": 1, + "assignee_id": 22, + "title": "In a rerum harum nihil accusamus aut quia nobis non.", + "created_at": "2016-06-14T15:02:24.000Z", + "updated_at": "2016-06-14T15:03:00.225Z", + "milestone_id": 19, "state": "opened", "merge_status": "unchecked", "target_project_id": 5, "iid": 4, - "description": "Soluta excepturi quis iste vero delectus rerum. Consequatur possimus aliquam necessitatibus deleniti rerum est impedit. Eius rem et consequatur assumenda est commodi.", + "description": "Nam magnam odit velit rerum. Sapiente dolore sunt saepe debitis. Culpa maiores ut ad dolores dolorem et.", "position": 0, "locked_at": null, "updated_by_id": null, "merge_error": null, "merge_params": { - + "force_remove_source_branch": null }, "merge_when_build_succeeds": false, "merge_user_id": null, @@ -3964,12 +4726,12 @@ "deleted_at": null, "notes": [ { - "id": 1255, - "note": "Quibusdam rem aut similique ipsum recusandae ut accusamus.", + "id": 801, + "note": "Nihil dicta molestias expedita atque.", "noteable_type": "MergeRequest", - "author_id": 1, - "created_at": "2016-03-22T15:20:31.253Z", - "updated_at": "2016-03-22T15:20:31.253Z", + "author_id": 26, + "created_at": "2016-06-14T15:03:00.001Z", + "updated_at": "2016-06-14T15:03:00.001Z", "project_id": 5, "attachment": { "url": null @@ -3980,17 +4742,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 1254, - "note": "Cumque sed omnis ipsa et magnam dolorem et.", + "id": 802, + "note": "Illum culpa voluptas enim accusantium deserunt.", "noteable_type": "MergeRequest", - "author_id": 3, - "created_at": "2016-03-22T15:20:31.224Z", - "updated_at": "2016-03-22T15:20:31.224Z", + "author_id": 25, + "created_at": "2016-06-14T15:03:00.034Z", + "updated_at": "2016-06-14T15:03:00.034Z", "project_id": 5, "attachment": { "url": null @@ -4001,17 +4766,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 1253, - "note": "Molestiae beatae id consequatur nam minus quia.", + "id": 803, + "note": "Dicta esse aliquam laboriosam unde alias.", "noteable_type": "MergeRequest", - "author_id": 4, - "created_at": "2016-03-22T15:20:31.195Z", - "updated_at": "2016-03-22T15:20:31.195Z", + "author_id": 22, + "created_at": "2016-06-14T15:03:00.065Z", + "updated_at": "2016-06-14T15:03:00.065Z", "project_id": 5, "attachment": { "url": null @@ -4022,17 +4790,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 1252, - "note": "Voluptatem dolorem dignissimos itaque tempora quas ut.", + "id": 804, + "note": "Dicta autem et sed molestiae ut quae.", "noteable_type": "MergeRequest", - "author_id": 10, - "created_at": "2016-03-22T15:20:31.166Z", - "updated_at": "2016-03-22T15:20:31.166Z", + "author_id": 20, + "created_at": "2016-06-14T15:03:00.097Z", + "updated_at": "2016-06-14T15:03:00.097Z", "project_id": 5, "attachment": { "url": null @@ -4043,17 +4814,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 1251, - "note": "Debitis qui quibusdam voluptas repellat veritatis dicta rerum id.", + "id": 805, + "note": "Ut ut temporibus voluptas dolore quia velit.", "noteable_type": "MergeRequest", - "author_id": 12, - "created_at": "2016-03-22T15:20:31.137Z", - "updated_at": "2016-03-22T15:20:31.137Z", + "author_id": 16, + "created_at": "2016-06-14T15:03:00.129Z", + "updated_at": "2016-06-14T15:03:00.129Z", "project_id": 5, "attachment": { "url": null @@ -4064,17 +4838,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 1250, - "note": "Suscipit optio ad voluptatem dignissimos temporibus amet molestias ut.", + "id": 806, + "note": "Dolores similique sint pariatur error id quia fugit aut.", "noteable_type": "MergeRequest", - "author_id": 22, - "created_at": "2016-03-22T15:20:31.107Z", - "updated_at": "2016-03-22T15:20:31.107Z", + "author_id": 15, + "created_at": "2016-06-14T15:03:00.162Z", + "updated_at": "2016-06-14T15:03:00.162Z", "project_id": 5, "attachment": { "url": null @@ -4085,17 +4862,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 1249, - "note": "Nemo aut vitae et ducimus autem ex dolores.", + "id": 807, + "note": "Quisquam provident nihil aperiam voluptatem.", "noteable_type": "MergeRequest", - "author_id": 24, - "created_at": "2016-03-22T15:20:31.073Z", - "updated_at": "2016-03-22T15:20:31.073Z", + "author_id": 6, + "created_at": "2016-06-14T15:03:00.193Z", + "updated_at": "2016-06-14T15:03:00.193Z", "project_id": 5, "attachment": { "url": null @@ -4106,17 +4886,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 1248, - "note": "Repellendus eaque ex molestiae laudantium placeat quidem vitae recusandae.", + "id": 808, + "note": "Similique quo vero expedita deserunt ipsam earum.", "noteable_type": "MergeRequest", - "author_id": 26, - "created_at": "2016-03-22T15:20:31.038Z", - "updated_at": "2016-03-22T15:20:31.038Z", + "author_id": 1, + "created_at": "2016-06-14T15:03:00.224Z", + "updated_at": "2016-06-14T15:03:00.224Z", "project_id": 5, "attachment": { "url": null @@ -4127,9 +4910,12 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ], "merge_request_diff": { @@ -4143,15 +4929,230 @@ "be93687618e4b132087f430a4d8fc3a609c9b77c" ], "authored_date": "2016-01-19T14:08:21.000+01:00", - "author_name": "Test Lopez", - "author_email": "Test@Testlopez.es", + "author_name": "James Lopez", + "author_email": "james@jameslopez.es", "committed_date": "2016-01-19T14:08:21.000+01:00", - "committer_name": "Test Lopez", - "committer_email": "Test@Testlopez.es" + "committer_name": "James Lopez", + "committer_email": "james@jameslopez.es" + }, + { + "id": "be93687618e4b132087f430a4d8fc3a609c9b77c", + "message": "Merge branch 'master' into 'master'\r\n\r\nLFS object pointer.\r\n\r\n\r\n\r\nSee merge request !6", + "parent_ids": [ + "5f923865dde3436854e9ceb9cdb7815618d4e849", + "048721d90c449b244b7b4c53a9186b04330174ec" + ], + "authored_date": "2015-12-07T12:52:12.000+01:00", + "author_name": "Marin Jankovski", + "author_email": "marin@gitlab.com", + "committed_date": "2015-12-07T12:52:12.000+01:00", + "committer_name": "Marin Jankovski", + "committer_email": "marin@gitlab.com" + }, + { + "id": "048721d90c449b244b7b4c53a9186b04330174ec", + "message": "LFS object pointer.\n", + "parent_ids": [ + "5f923865dde3436854e9ceb9cdb7815618d4e849" + ], + "authored_date": "2015-12-07T11:54:28.000+01:00", + "author_name": "Marin Jankovski", + "author_email": "maxlazio@gmail.com", + "committed_date": "2015-12-07T11:54:28.000+01:00", + "committer_name": "Marin Jankovski", + "committer_email": "maxlazio@gmail.com" + }, + { + "id": "5f923865dde3436854e9ceb9cdb7815618d4e849", + "message": "GitLab currently doesn't support patches that involve a merge commit: add a commit here\n", + "parent_ids": [ + "d2d430676773caa88cdaf7c55944073b2fd5561a" + ], + "authored_date": "2015-11-13T16:27:12.000+01:00", + "author_name": "Stan Hu", + "author_email": "stanhu@gmail.com", + "committed_date": "2015-11-13T16:27:12.000+01:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@gmail.com" + }, + { + "id": "d2d430676773caa88cdaf7c55944073b2fd5561a", + "message": "Merge branch 'add-svg' into 'master'\r\n\r\nAdd GitLab SVG\r\n\r\nAdded to test preview of sanitized SVG images\r\n\r\nSee merge request !5", + "parent_ids": [ + "59e29889be61e6e0e5e223bfa9ac2721d31605b8", + "2ea1f3dec713d940208fb5ce4a38765ecb5d3f73" + ], + "authored_date": "2015-11-13T08:50:17.000+01:00", + "author_name": "Stan Hu", + "author_email": "stanhu@gmail.com", + "committed_date": "2015-11-13T08:50:17.000+01:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@gmail.com" + }, + { + "id": "2ea1f3dec713d940208fb5ce4a38765ecb5d3f73", + "message": "Add GitLab SVG\n", + "parent_ids": [ + "59e29889be61e6e0e5e223bfa9ac2721d31605b8" + ], + "authored_date": "2015-11-13T08:39:43.000+01:00", + "author_name": "Stan Hu", + "author_email": "stanhu@gmail.com", + "committed_date": "2015-11-13T08:39:43.000+01:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@gmail.com" + }, + { + "id": "59e29889be61e6e0e5e223bfa9ac2721d31605b8", + "message": "Merge branch 'whitespace' into 'master'\r\n\r\nadd whitespace test file\r\n\r\nSorry, I did a mistake.\r\nGit ignore empty files.\r\nSo I add a new whitespace test file.\r\n\r\nSee merge request !4", + "parent_ids": [ + "19e2e9b4ef76b422ce1154af39a91323ccc57434", + "66eceea0db202bb39c4e445e8ca28689645366c5" + ], + "authored_date": "2015-11-13T07:21:40.000+01:00", + "author_name": "Stan Hu", + "author_email": "stanhu@gmail.com", + "committed_date": "2015-11-13T07:21:40.000+01:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@gmail.com" + }, + { + "id": "66eceea0db202bb39c4e445e8ca28689645366c5", + "message": "add spaces in whitespace file\n", + "parent_ids": [ + "08f22f255f082689c0d7d39d19205085311542bc" + ], + "authored_date": "2015-11-13T06:01:27.000+01:00", + "author_name": "윤민식", + "author_email": "minsik.yoon@samsung.com", + "committed_date": "2015-11-13T06:01:27.000+01:00", + "committer_name": "윤민식", + "committer_email": "minsik.yoon@samsung.com" + }, + { + "id": "08f22f255f082689c0d7d39d19205085311542bc", + "message": "remove emtpy file.(beacase git ignore empty file)\nadd whitespace test file.\n", + "parent_ids": [ + "c642fe9b8b9f28f9225d7ea953fe14e74748d53b" + ], + "authored_date": "2015-11-13T06:00:16.000+01:00", + "author_name": "윤민식", + "author_email": "minsik.yoon@samsung.com", + "committed_date": "2015-11-13T06:00:16.000+01:00", + "committer_name": "윤민식", + "committer_email": "minsik.yoon@samsung.com" + }, + { + "id": "19e2e9b4ef76b422ce1154af39a91323ccc57434", + "message": "Merge branch 'whitespace' into 'master'\r\n\r\nadd spaces\r\n\r\nTo test this pull request.(https://github.com/gitlabhq/gitlabhq/pull/9757)\r\nJust add whitespaces.\r\n\r\nSee merge request !3", + "parent_ids": [ + "c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd", + "c642fe9b8b9f28f9225d7ea953fe14e74748d53b" + ], + "authored_date": "2015-11-13T05:23:14.000+01:00", + "author_name": "Stan Hu", + "author_email": "stanhu@gmail.com", + "committed_date": "2015-11-13T05:23:14.000+01:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@gmail.com" + }, + { + "id": "c642fe9b8b9f28f9225d7ea953fe14e74748d53b", + "message": "add whitespace in empty\n", + "parent_ids": [ + "9a944d90955aaf45f6d0c88f30e27f8d2c41cec0" + ], + "authored_date": "2015-11-13T05:08:45.000+01:00", + "author_name": "윤민식", + "author_email": "minsik.yoon@samsung.com", + "committed_date": "2015-11-13T05:08:45.000+01:00", + "committer_name": "윤민식", + "committer_email": "minsik.yoon@samsung.com" + }, + { + "id": "9a944d90955aaf45f6d0c88f30e27f8d2c41cec0", + "message": "add empty file\n", + "parent_ids": [ + "c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd" + ], + "authored_date": "2015-11-13T05:08:04.000+01:00", + "author_name": "윤민식", + "author_email": "minsik.yoon@samsung.com", + "committed_date": "2015-11-13T05:08:04.000+01:00", + "committer_name": "윤민식", + "committer_email": "minsik.yoon@samsung.com" + }, + { + "id": "c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd", + "message": "Add ISO-8859 test file\n", + "parent_ids": [ + "e56497bb5f03a90a51293fc6d516788730953899" + ], + "authored_date": "2015-08-25T17:53:12.000+02:00", + "author_name": "Stan Hu", + "author_email": "stanhu@packetzoom.com", + "committed_date": "2015-08-25T17:53:12.000+02:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@packetzoom.com" } ], "st_diffs": [ { + "diff": "--- a/CHANGELOG\n+++ b/CHANGELOG\n@@ -1,4 +1,6 @@\n-v 6.7.0\n+v6.8.0\n+\n+v6.7.0\n - Add support for Gemnasium as a Project Service (Olivier Gonzalez)\n - Add edit file button to MergeRequest diff\n - Public groups (Jason Hollingsworth)\n", + "new_path": "CHANGELOG", + "old_path": "CHANGELOG", + "a_mode": "100644", + "b_mode": "100644", + "new_file": false, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- /dev/null\n+++ b/encoding/iso8859.txt\n@@ -0,0 +1 @@\n+Äü\n", + "new_path": "encoding/iso8859.txt", + "old_path": "encoding/iso8859.txt", + "a_mode": "0", + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- /dev/null\n+++ b/files/images/wm.svg\n@@ -0,0 +1,78 @@\n+\u003c?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?\u003e\n+\u003csvg width=\"1300px\" height=\"680px\" viewBox=\"0 0 1300 680\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\"\u003e\n+ \u003c!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch --\u003e\n+ \u003ctitle\u003ewm\u003c/title\u003e\n+ \u003cdesc\u003eCreated with Sketch.\u003c/desc\u003e\n+ \u003cdefs\u003e\n+ \u003cpath id=\"path-1\" d=\"M-69.8,1023.54607 L1675.19996,1023.54607 L1675.19996,0 L-69.8,0 L-69.8,1023.54607 L-69.8,1023.54607 Z\"\u003e\u003c/path\u003e\n+ \u003c/defs\u003e\n+ \u003cg id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\"\u003e\n+ \u003cpath d=\"M1300,680 L0,680 L0,0 L1300,0 L1300,680 L1300,680 Z\" id=\"bg\" fill=\"#30353E\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003cg id=\"gitlab_logo\" sketch:type=\"MSLayerGroup\" transform=\"translate(-262.000000, -172.000000)\"\u003e\n+ \u003cg id=\"g10\" transform=\"translate(872.500000, 512.354581) scale(1, -1) translate(-872.500000, -512.354581) translate(0.000000, 0.290751)\"\u003e\n+ \u003cg id=\"g12\" transform=\"translate(1218.022652, 440.744871)\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\n+ \u003cpath d=\"M-50.0233338,141.900706 L-69.07059,141.900706 L-69.0100967,0.155858152 L8.04444805,0.155858152 L8.04444805,17.6840847 L-49.9628405,17.6840847 L-50.0233338,141.900706 L-50.0233338,141.900706 Z\" id=\"path14\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g16\"\u003e\n+ \u003cg id=\"g18-Clipped\"\u003e\n+ \u003cmask id=\"mask-2\" sketch:name=\"path22\" fill=\"white\"\u003e\n+ \u003cuse xlink:href=\"#path-1\"\u003e\u003c/use\u003e\n+ \u003c/mask\u003e\n+ \u003cg id=\"path22\"\u003e\u003c/g\u003e\n+ \u003cg id=\"g18\" mask=\"url(#mask-2)\"\u003e\n+ \u003cg transform=\"translate(382.736659, 312.879425)\"\u003e\n+ \u003cg id=\"g24\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(852.718192, 124.992771)\"\u003e\n+ \u003cpath d=\"M63.9833317,27.9148929 C59.2218085,22.9379001 51.2134221,17.9597442 40.3909323,17.9597442 C25.8888194,17.9597442 20.0453962,25.1013043 20.0453962,34.4074318 C20.0453962,48.4730484 29.7848226,55.1819277 50.5642821,55.1819277 C54.4602853,55.1819277 60.7364685,54.7492469 63.9833317,54.1002256 L63.9833317,27.9148929 L63.9833317,27.9148929 Z M44.2869356,113.827628 C28.9053426,113.827628 14.7975996,108.376082 3.78897657,99.301416 L10.5211864,87.6422957 C18.3131929,92.1866076 27.8374026,96.7320827 41.4728323,96.7320827 C57.0568452,96.7320827 63.9833317,88.7239978 63.9833317,75.3074024 L63.9833317,68.3821827 C60.9528485,69.0312039 54.6766653,69.4650479 50.7806621,69.4650479 C17.4476729,69.4650479 0.565379986,57.7791759 0.565379986,33.3245665 C0.565379986,11.4683685 13.9844297,0.43151772 34.3299658,0.43151772 C48.0351955,0.43151772 61.1692285,6.70771614 65.7143717,16.8780421 L69.1776149,3.02876588 L82.5978279,3.02876588 L82.5978279,75.5237428 C82.5978279,98.462806 72.6408582,113.827628 44.2869356,113.827628 L44.2869356,113.827628 Z\" id=\"path26\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g28\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(959.546624, 124.857151)\"\u003e\n+ \u003cpath d=\"M37.2266657,17.4468081 C30.0837992,17.4468081 23.8064527,18.3121698 19.0449295,20.4767371 L19.0449295,79.2306079 L19.0449295,86.0464943 C25.538656,91.457331 33.5470425,95.3526217 43.7203922,95.3526217 C62.1173451,95.3526217 69.2602116,82.3687072 69.2602116,61.3767077 C69.2602116,31.5135879 57.7885819,17.4468081 37.2266657,17.4468081 M45.2315622,113.963713 C28.208506,113.963713 19.0449295,102.384849 19.0449295,102.384849 L19.0449295,120.67143 L18.9844362,144.908535 L10.3967097,144.908535 L0.371103324,144.908535 L0.431596656,6.62629771 C9.73826309,2.73100702 22.5081728,0.567602823 36.3611458,0.567602823 C71.8579349,0.567602823 88.9566078,23.2891625 88.9566078,62.4584098 C88.9566078,93.4043948 73.1527248,113.963713 45.2315622,113.963713\" id=\"path30\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g32\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(509.576747, 125.294950)\"\u003e\n+ \u003cpath d=\"M68.636665,129.10638 C85.5189579,129.10638 96.3414476,123.480366 103.484314,117.853189 L111.669527,132.029302 C100.513161,141.811145 85.5073245,147.06845 69.5021849,147.06845 C29.0274926,147.06845 0.673569983,122.3975 0.673569983,72.6252464 C0.673569983,20.4709215 31.2622559,0.12910638 66.2553217,0.12910638 C83.7879179,0.12910638 98.7227909,4.24073748 108.462217,8.35236859 L108.063194,64.0763105 L108.063194,70.6502677 L108.063194,81.6057001 L56.1168719,81.6057001 L56.1168719,64.0763105 L89.2323178,64.0763105 L89.6313411,21.7701271 C85.3025779,19.6055598 77.7269514,17.8748364 67.554765,17.8748364 C39.4172223,17.8748364 20.5863462,35.5717154 20.5863462,72.8415868 C20.5863462,110.711628 40.0663623,129.10638 68.636665,129.10638\" id=\"path34\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g36\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(692.388992, 124.376085)\"\u003e\n+ \u003cpath d=\"M19.7766662,145.390067 L1.16216997,145.390067 L1.2226633,121.585642 L1.2226633,111.846834 L1.2226633,106.170806 L1.2226633,96.2656714 L1.2226633,39.5681976 L1.2226633,39.3518572 C1.2226633,16.4127939 11.1796331,1.04797161 39.5335557,1.04797161 C43.4504989,1.04797161 47.2836822,1.40388649 51.0051854,2.07965952 L51.0051854,18.7925385 C48.3109055,18.3796307 45.4351455,18.1446804 42.3476589,18.1446804 C26.763646,18.1446804 19.8371595,26.1516022 19.8371595,39.5681976 L19.8371595,96.2656714 L51.0051854,96.2656714 L51.0051854,111.846834 L19.8371595,111.846834 L19.7766662,145.390067 L19.7766662,145.390067 Z\" id=\"path38\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cpath d=\"M646.318899,128.021188 L664.933395,128.021188 L664.933395,236.223966 L646.318899,236.223966 L646.318899,128.021188 L646.318899,128.021188 Z\" id=\"path40\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003cpath d=\"M646.318899,251.154944 L664.933395,251.154944 L664.933395,269.766036 L646.318899,269.766036 L646.318899,251.154944 L646.318899,251.154944 Z\" id=\"path42\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003cg id=\"g44\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.464170, 0.676006)\"\u003e\n+ \u003cpath d=\"M429.269989,169.815599 L405.225053,243.802859 L357.571431,390.440955 C355.120288,397.984955 344.444378,397.984955 341.992071,390.440955 L294.337286,243.802859 L136.094873,243.802859 L88.4389245,390.440955 C85.9877812,397.984955 75.3118715,397.984955 72.8595648,390.440955 L25.2059427,243.802859 L1.16216997,169.815599 C-1.03187664,163.067173 1.37156997,155.674379 7.11261982,151.503429 L215.215498,0.336141836 L423.319539,151.503429 C429.060589,155.674379 431.462873,163.067173 429.269989,169.815599\" id=\"path46\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g48\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(135.410135, 1.012147)\"\u003e\n+ \u003cpath d=\"M80.269998,0 L80.269998,0 L159.391786,243.466717 L1.14820997,243.466717 L80.269998,0 L80.269998,0 Z\" id=\"path50\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g52\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\"\u003e\n+ \u003cg id=\"path54\"\u003e\u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g56\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(24.893471, 1.012613)\"\u003e\n+ \u003cpath d=\"M190.786662,0 L111.664874,243.465554 L0.777106647,243.465554 L190.786662,0 L190.786662,0 Z\" id=\"path58\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g60\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\"\u003e\n+ \u003cg id=\"path62\"\u003e\u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g64\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.077245, 0.223203)\"\u003e\n+ \u003cpath d=\"M25.5933327,244.255313 L25.5933327,244.255313 L1.54839663,170.268052 C-0.644486651,163.519627 1.75779662,156.126833 7.50000981,151.957046 L215.602888,0.789758846 L25.5933327,244.255313 L25.5933327,244.255313 Z\" id=\"path66\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g68\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\"\u003e\n+ \u003cg id=\"path70\"\u003e\u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g72\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(25.670578, 244.478283)\"\u003e\n+ \u003cpath d=\"M0,0 L110.887767,0 L63.2329818,146.638096 C60.7806751,154.183259 50.1047654,154.183259 47.6536221,146.638096 L0,0 L0,0 Z\" id=\"path74\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g76\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\"\u003e\n+ \u003cpath d=\"M0,0 L79.121788,243.465554 L190.009555,243.465554 L0,0 L0,0 Z\" id=\"path78\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g80\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(214.902910, 0.223203)\"\u003e\n+ \u003cpath d=\"M190.786662,244.255313 L190.786662,244.255313 L214.831598,170.268052 C217.024481,163.519627 214.622198,156.126833 208.879985,151.957046 L0.777106647,0.789758846 L190.786662,244.255313 L190.786662,244.255313 Z\" id=\"path82\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g84\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(294.009575, 244.478283)\"\u003e\n+ \u003cpath d=\"M111.679997,0 L0.79222998,0 L48.4470155,146.638096 C50.8993221,154.183259 61.5752318,154.183259 64.0263751,146.638096 L111.679997,0 L111.679997,0 Z\" id=\"path86\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+\u003c/svg\u003e\n\\ No newline at end of file\n", + "new_path": "files/images/wm.svg", + "old_path": "files/images/wm.svg", + "a_mode": "0", + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- /dev/null\n+++ b/files/lfs/lfs_object.iso\n@@ -0,0 +1,4 @@\n+version https://git-lfs.github.com/spec/v1\n+oid sha256:91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897\n+size 1575078\n+\n", + "new_path": "files/lfs/lfs_object.iso", + "old_path": "files/lfs/lfs_object.iso", + "a_mode": "0", + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- /dev/null\n+++ b/files/whitespace\n@@ -0,0 +1 @@\n+test \n", + "new_path": "files/whitespace", + "old_path": "files/whitespace", + "a_mode": "0", + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { "diff": "--- /dev/null\n+++ b/test\n", "new_path": "test", "old_path": "test", @@ -4164,34 +5165,60 @@ } ], "merge_request_id": 12, - "created_at": "2016-03-22T15:13:44.840Z", - "updated_at": "2016-03-22T15:13:44.908Z", - "base_commit_sha": "be93687618e4b132087f430a4d8fc3a609c9b77c", - "real_size": "1" - } + "created_at": "2016-06-14T15:02:24.006Z", + "updated_at": "2016-06-14T15:02:24.169Z", + "base_commit_sha": "e56497bb5f03a90a51293fc6d516788730953899", + "real_size": "6" + }, + "events": [ + { + "id": 226, + "target_type": "MergeRequest", + "target_id": 12, + "title": null, + "data": null, + "project_id": 36, + "created_at": "2016-06-14T15:02:24.253Z", + "updated_at": "2016-06-14T15:02:24.253Z", + "action": 1, + "author_id": 1 + }, + { + "id": 172, + "target_type": "MergeRequest", + "target_id": 12, + "title": null, + "data": null, + "project_id": 5, + "created_at": "2016-06-14T15:02:24.253Z", + "updated_at": "2016-06-14T15:02:24.253Z", + "action": 1, + "author_id": 1 + } + ] }, { "id": 11, - "target_branch": "test-3", - "source_branch": "test-5", + "target_branch": "test-15", + "source_branch": "'test'", "source_project_id": 5, - "author_id": 26, - "assignee_id": 12, - "title": "Magni aut reprehenderit ut accusantium est eum.", - "created_at": "2016-03-22T15:13:44.494Z", - "updated_at": "2016-03-22T15:20:31.886Z", - "milestone_id": 10, + "author_id": 16, + "assignee_id": 16, + "title": "Corporis provident similique perspiciatis dolores eos animi.", + "created_at": "2016-06-14T15:02:23.767Z", + "updated_at": "2016-06-14T15:03:00.475Z", + "milestone_id": 18, "state": "opened", "merge_status": "unchecked", "target_project_id": 5, "iid": 3, - "description": "Et hic maxime harum ullam. Nulla velit pariatur libero recusandae. Dolor est earum laboriosam harum quo.", + "description": "Libero nesciunt mollitia quis odit eos vero quasi. Iure voluptatem ut sint pariatur voluptates ut aut. Laborum possimus unde illum ipsum eum.", "position": 0, "locked_at": null, "updated_by_id": null, "merge_error": null, "merge_params": { - + "force_remove_source_branch": null }, "merge_when_build_succeeds": false, "merge_user_id": null, @@ -4199,12 +5226,12 @@ "deleted_at": null, "notes": [ { - "id": 1263, - "note": "Beatae incidunt exercitationem voluptates recusandae fuga quia enim.", + "id": 809, + "note": "Omnis ratione laboriosam dolores qui.", "noteable_type": "MergeRequest", - "author_id": 1, - "created_at": "2016-03-22T15:20:31.883Z", - "updated_at": "2016-03-22T15:20:31.883Z", + "author_id": 26, + "created_at": "2016-06-14T15:03:00.260Z", + "updated_at": "2016-06-14T15:03:00.260Z", "project_id": 5, "attachment": { "url": null @@ -4215,17 +5242,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 1262, - "note": "Illum sunt id consequuntur fugit et quo ullam eum.", + "id": 810, + "note": "Voluptas voluptates pariatur dolores maxime est voluptas.", "noteable_type": "MergeRequest", - "author_id": 3, - "created_at": "2016-03-22T15:20:31.860Z", - "updated_at": "2016-03-22T15:20:31.860Z", + "author_id": 25, + "created_at": "2016-06-14T15:03:00.290Z", + "updated_at": "2016-06-14T15:03:00.290Z", "project_id": 5, "attachment": { "url": null @@ -4236,17 +5266,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 1261, - "note": "Alias reiciendis autem ipsa sequi autem nemo odio.", + "id": 811, + "note": "Sit perspiciatis facilis ipsum consequatur.", "noteable_type": "MergeRequest", - "author_id": 4, - "created_at": "2016-03-22T15:20:31.456Z", - "updated_at": "2016-03-22T15:20:31.456Z", + "author_id": 22, + "created_at": "2016-06-14T15:03:00.323Z", + "updated_at": "2016-06-14T15:03:00.323Z", "project_id": 5, "attachment": { "url": null @@ -4257,17 +5290,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 1260, - "note": "Maxime nisi odit eos nulla vel ex accusamus velit.", + "id": 812, + "note": "Ut neque aliquam nam et est.", "noteable_type": "MergeRequest", - "author_id": 10, - "created_at": "2016-03-22T15:20:31.426Z", - "updated_at": "2016-03-22T15:20:31.426Z", + "author_id": 20, + "created_at": "2016-06-14T15:03:00.349Z", + "updated_at": "2016-06-14T15:03:00.349Z", "project_id": 5, "attachment": { "url": null @@ -4278,17 +5314,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 1259, - "note": "Excepturi et qui sapiente ut ducimus sunt nesciunt.", + "id": 813, + "note": "Et debitis rerum minima sit aut dolorem.", "noteable_type": "MergeRequest", - "author_id": 12, - "created_at": "2016-03-22T15:20:31.397Z", - "updated_at": "2016-03-22T15:20:31.397Z", + "author_id": 16, + "created_at": "2016-06-14T15:03:00.374Z", + "updated_at": "2016-06-14T15:03:00.374Z", "project_id": 5, "attachment": { "url": null @@ -4299,17 +5338,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 1258, - "note": "Quis rerum dolores et dolorem modi neque ullam doloribus.", + "id": 814, + "note": "Ea nisi earum fugit iste aperiam consequatur.", "noteable_type": "MergeRequest", - "author_id": 22, - "created_at": "2016-03-22T15:20:31.364Z", - "updated_at": "2016-03-22T15:20:31.364Z", + "author_id": 15, + "created_at": "2016-06-14T15:03:00.397Z", + "updated_at": "2016-06-14T15:03:00.397Z", "project_id": 5, "attachment": { "url": null @@ -4320,17 +5362,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 1257, - "note": "Voluptatum et mollitia neque aut.", + "id": 815, + "note": "Amet ratione consequatur laudantium rerum voluptas est nobis.", "noteable_type": "MergeRequest", - "author_id": 24, - "created_at": "2016-03-22T15:20:31.328Z", - "updated_at": "2016-03-22T15:20:31.328Z", + "author_id": 6, + "created_at": "2016-06-14T15:03:00.450Z", + "updated_at": "2016-06-14T15:03:00.450Z", "project_id": 5, "attachment": { "url": null @@ -4341,17 +5386,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 1256, - "note": "Rerum laudantium dolor natus doloribus voluptas aliquid a.", + "id": 816, + "note": "Ab ducimus cumque quia dolorem vitae sint beatae rerum.", "noteable_type": "MergeRequest", - "author_id": 26, - "created_at": "2016-03-22T15:20:31.298Z", - "updated_at": "2016-03-22T15:20:31.298Z", + "author_id": 1, + "created_at": "2016-06-14T15:03:00.474Z", + "updated_at": "2016-06-14T15:03:00.474Z", "project_id": 5, "attachment": { "url": null @@ -4362,71 +5410,76 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ], "merge_request_diff": { "id": 11, - "state": "collected", - "st_commits": [ - { - "id": "f998ac87ac9244f15e9c15109a6f4e62a54b779d", - "message": "fixes #10\n", - "parent_ids": [ - "be93687618e4b132087f430a4d8fc3a609c9b77c" - ], - "authored_date": "2016-01-19T14:43:23.000+01:00", - "author_name": "Test Lopez", - "author_email": "Test@Testlopez.es", - "committed_date": "2016-01-19T14:43:23.000+01:00", - "committer_name": "Test Lopez", - "committer_email": "Test@Testlopez.es" - } - ], + "state": "empty", + "st_commits": null, "st_diffs": [ - { - "diff": "--- /dev/null\n+++ b/test\n", - "new_path": "test", - "old_path": "test", - "a_mode": "0", - "b_mode": "100644", - "new_file": true, - "renamed_file": false, - "deleted_file": false, - "too_large": false - } + ], "merge_request_id": 11, - "created_at": "2016-03-22T15:13:44.497Z", - "updated_at": "2016-03-22T15:13:44.547Z", - "base_commit_sha": "be93687618e4b132087f430a4d8fc3a609c9b77c", - "real_size": "1" - } + "created_at": "2016-06-14T15:02:23.772Z", + "updated_at": "2016-06-14T15:02:23.833Z", + "base_commit_sha": "e56497bb5f03a90a51293fc6d516788730953899", + "real_size": null + }, + "events": [ + { + "id": 227, + "target_type": "MergeRequest", + "target_id": 11, + "title": null, + "data": null, + "project_id": 36, + "created_at": "2016-06-14T15:02:23.865Z", + "updated_at": "2016-06-14T15:02:23.865Z", + "action": 1, + "author_id": 16 + }, + { + "id": 171, + "target_type": "MergeRequest", + "target_id": 11, + "title": null, + "data": null, + "project_id": 5, + "created_at": "2016-06-14T15:02:23.865Z", + "updated_at": "2016-06-14T15:02:23.865Z", + "action": 1, + "author_id": 16 + } + ] }, { "id": 10, - "target_branch": "test-6", - "source_branch": "test-7", + "target_branch": "feature", + "source_branch": "test-5", "source_project_id": 5, - "author_id": 22, - "assignee_id": 4, - "title": "Rerum commodi corporis quis qui fugit sed ut.", - "created_at": "2016-03-22T15:13:44.103Z", - "updated_at": "2016-03-22T15:20:32.096Z", - "milestone_id": 11, + "author_id": 20, + "assignee_id": 25, + "title": "Eligendi reprehenderit doloribus quia et sit id.", + "created_at": "2016-06-14T15:02:23.014Z", + "updated_at": "2016-06-14T15:03:00.685Z", + "milestone_id": 20, "state": "opened", "merge_status": "unchecked", "target_project_id": 5, "iid": 2, - "description": "Laudantium vel dignissimos aspernatur quis aut. Dolores et doloremque ipsa quia voluptate modi labore. Ipsa provident repellat error et nihil.", + "description": "Ut dolor quia aliquid dolore et nisi. Est minus suscipit enim quaerat sapiente consequatur rerum. Eveniet provident consequatur dolor accusantium reiciendis.", "position": 0, "locked_at": null, "updated_by_id": null, "merge_error": null, "merge_params": { - + "force_remove_source_branch": null }, "merge_when_build_succeeds": false, "merge_user_id": null, @@ -4434,12 +5487,12 @@ "deleted_at": null, "notes": [ { - "id": 1271, - "note": "Quod ut ut quisquam et ut dolorem dolor.", + "id": 817, + "note": "Recusandae et voluptas enim qui et.", "noteable_type": "MergeRequest", - "author_id": 1, - "created_at": "2016-03-22T15:20:32.093Z", - "updated_at": "2016-03-22T15:20:32.093Z", + "author_id": 26, + "created_at": "2016-06-14T15:03:00.510Z", + "updated_at": "2016-06-14T15:03:00.510Z", "project_id": 5, "attachment": { "url": null @@ -4450,17 +5503,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 1270, - "note": "Sed deserunt et explicabo rem repellat voluptatem.", + "id": 818, + "note": "Asperiores dolorem rerum ipsum totam.", "noteable_type": "MergeRequest", - "author_id": 3, - "created_at": "2016-03-22T15:20:32.070Z", - "updated_at": "2016-03-22T15:20:32.070Z", + "author_id": 25, + "created_at": "2016-06-14T15:03:00.538Z", + "updated_at": "2016-06-14T15:03:00.538Z", "project_id": 5, "attachment": { "url": null @@ -4471,17 +5527,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 1269, - "note": "Veritatis architecto omnis consequatur et optio.", + "id": 819, + "note": "Qui quam et iure quasi provident cumque itaque sequi.", "noteable_type": "MergeRequest", - "author_id": 4, - "created_at": "2016-03-22T15:20:32.046Z", - "updated_at": "2016-03-22T15:20:32.046Z", + "author_id": 22, + "created_at": "2016-06-14T15:03:00.562Z", + "updated_at": "2016-06-14T15:03:00.562Z", "project_id": 5, "attachment": { "url": null @@ -4492,17 +5551,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 1268, - "note": "Omnis suscipit odio molestiae debitis quia autem magni.", + "id": 820, + "note": "Sint accusantium aliquid iste qui iusto minus vel.", "noteable_type": "MergeRequest", - "author_id": 10, - "created_at": "2016-03-22T15:20:32.019Z", - "updated_at": "2016-03-22T15:20:32.019Z", + "author_id": 20, + "created_at": "2016-06-14T15:03:00.585Z", + "updated_at": "2016-06-14T15:03:00.585Z", "project_id": 5, "attachment": { "url": null @@ -4513,17 +5575,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 1267, - "note": "Molestias est sunt est tempora consequatur cupiditate magnam.", + "id": 821, + "note": "Dolor corrupti dolorem blanditiis voluptas.", "noteable_type": "MergeRequest", - "author_id": 12, - "created_at": "2016-03-22T15:20:31.993Z", - "updated_at": "2016-03-22T15:20:31.993Z", + "author_id": 16, + "created_at": "2016-06-14T15:03:00.610Z", + "updated_at": "2016-06-14T15:03:00.610Z", "project_id": 5, "attachment": { "url": null @@ -4534,17 +5599,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 1266, - "note": "Ratione blanditiis eveniet voluptatem nostrum rerum excepturi in molestiae.", + "id": 822, + "note": "Est perferendis assumenda aliquam aliquid sit ipsum ullam aut.", "noteable_type": "MergeRequest", - "author_id": 22, - "created_at": "2016-03-22T15:20:31.969Z", - "updated_at": "2016-03-22T15:20:31.969Z", + "author_id": 15, + "created_at": "2016-06-14T15:03:00.635Z", + "updated_at": "2016-06-14T15:03:00.635Z", "project_id": 5, "attachment": { "url": null @@ -4555,17 +5623,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 1265, - "note": "Illo voluptatibus vel odio ea.", + "id": 823, + "note": "Hic neque reiciendis quaerat maiores.", "noteable_type": "MergeRequest", - "author_id": 24, - "created_at": "2016-03-22T15:20:31.944Z", - "updated_at": "2016-03-22T15:20:31.944Z", + "author_id": 6, + "created_at": "2016-06-14T15:03:00.659Z", + "updated_at": "2016-06-14T15:03:00.659Z", "project_id": 5, "attachment": { "url": null @@ -4576,17 +5647,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 1264, - "note": "Earum veritatis quis facere itaque iure.", + "id": 824, + "note": "Sequi architecto doloribus ut vel autem.", "noteable_type": "MergeRequest", - "author_id": 26, - "created_at": "2016-03-22T15:20:31.919Z", - "updated_at": "2016-03-22T15:20:31.919Z", + "author_id": 1, + "created_at": "2016-06-14T15:03:00.683Z", + "updated_at": "2016-06-14T15:03:00.683Z", "project_id": 5, "attachment": { "url": null @@ -4597,9 +5671,12 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ], "merge_request_diff": { @@ -4607,21 +5684,427 @@ "state": "collected", "st_commits": [ { - "id": "b42bb86cea49bdcef943e521584b7f417d8ddd3d", + "id": "f998ac87ac9244f15e9c15109a6f4e62a54b779d", "message": "fixes #10\n", "parent_ids": [ "be93687618e4b132087f430a4d8fc3a609c9b77c" ], - "authored_date": "2016-01-19T15:03:09.000+01:00", - "author_name": "Test Lopez", - "author_email": "Test@Testlopez.es", - "committed_date": "2016-01-19T15:03:09.000+01:00", - "committer_name": "Test Lopez", - "committer_email": "Test@Testlopez.es" + "authored_date": "2016-01-19T14:43:23.000+01:00", + "author_name": "James Lopez", + "author_email": "james@jameslopez.es", + "committed_date": "2016-01-19T14:43:23.000+01:00", + "committer_name": "James Lopez", + "committer_email": "james@jameslopez.es" + }, + { + "id": "be93687618e4b132087f430a4d8fc3a609c9b77c", + "message": "Merge branch 'master' into 'master'\r\n\r\nLFS object pointer.\r\n\r\n\r\n\r\nSee merge request !6", + "parent_ids": [ + "5f923865dde3436854e9ceb9cdb7815618d4e849", + "048721d90c449b244b7b4c53a9186b04330174ec" + ], + "authored_date": "2015-12-07T12:52:12.000+01:00", + "author_name": "Marin Jankovski", + "author_email": "marin@gitlab.com", + "committed_date": "2015-12-07T12:52:12.000+01:00", + "committer_name": "Marin Jankovski", + "committer_email": "marin@gitlab.com" + }, + { + "id": "048721d90c449b244b7b4c53a9186b04330174ec", + "message": "LFS object pointer.\n", + "parent_ids": [ + "5f923865dde3436854e9ceb9cdb7815618d4e849" + ], + "authored_date": "2015-12-07T11:54:28.000+01:00", + "author_name": "Marin Jankovski", + "author_email": "maxlazio@gmail.com", + "committed_date": "2015-12-07T11:54:28.000+01:00", + "committer_name": "Marin Jankovski", + "committer_email": "maxlazio@gmail.com" + }, + { + "id": "5f923865dde3436854e9ceb9cdb7815618d4e849", + "message": "GitLab currently doesn't support patches that involve a merge commit: add a commit here\n", + "parent_ids": [ + "d2d430676773caa88cdaf7c55944073b2fd5561a" + ], + "authored_date": "2015-11-13T16:27:12.000+01:00", + "author_name": "Stan Hu", + "author_email": "stanhu@gmail.com", + "committed_date": "2015-11-13T16:27:12.000+01:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@gmail.com" + }, + { + "id": "d2d430676773caa88cdaf7c55944073b2fd5561a", + "message": "Merge branch 'add-svg' into 'master'\r\n\r\nAdd GitLab SVG\r\n\r\nAdded to test preview of sanitized SVG images\r\n\r\nSee merge request !5", + "parent_ids": [ + "59e29889be61e6e0e5e223bfa9ac2721d31605b8", + "2ea1f3dec713d940208fb5ce4a38765ecb5d3f73" + ], + "authored_date": "2015-11-13T08:50:17.000+01:00", + "author_name": "Stan Hu", + "author_email": "stanhu@gmail.com", + "committed_date": "2015-11-13T08:50:17.000+01:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@gmail.com" + }, + { + "id": "2ea1f3dec713d940208fb5ce4a38765ecb5d3f73", + "message": "Add GitLab SVG\n", + "parent_ids": [ + "59e29889be61e6e0e5e223bfa9ac2721d31605b8" + ], + "authored_date": "2015-11-13T08:39:43.000+01:00", + "author_name": "Stan Hu", + "author_email": "stanhu@gmail.com", + "committed_date": "2015-11-13T08:39:43.000+01:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@gmail.com" + }, + { + "id": "59e29889be61e6e0e5e223bfa9ac2721d31605b8", + "message": "Merge branch 'whitespace' into 'master'\r\n\r\nadd whitespace test file\r\n\r\nSorry, I did a mistake.\r\nGit ignore empty files.\r\nSo I add a new whitespace test file.\r\n\r\nSee merge request !4", + "parent_ids": [ + "19e2e9b4ef76b422ce1154af39a91323ccc57434", + "66eceea0db202bb39c4e445e8ca28689645366c5" + ], + "authored_date": "2015-11-13T07:21:40.000+01:00", + "author_name": "Stan Hu", + "author_email": "stanhu@gmail.com", + "committed_date": "2015-11-13T07:21:40.000+01:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@gmail.com" + }, + { + "id": "66eceea0db202bb39c4e445e8ca28689645366c5", + "message": "add spaces in whitespace file\n", + "parent_ids": [ + "08f22f255f082689c0d7d39d19205085311542bc" + ], + "authored_date": "2015-11-13T06:01:27.000+01:00", + "author_name": "윤민식", + "author_email": "minsik.yoon@samsung.com", + "committed_date": "2015-11-13T06:01:27.000+01:00", + "committer_name": "윤민식", + "committer_email": "minsik.yoon@samsung.com" + }, + { + "id": "08f22f255f082689c0d7d39d19205085311542bc", + "message": "remove emtpy file.(beacase git ignore empty file)\nadd whitespace test file.\n", + "parent_ids": [ + "c642fe9b8b9f28f9225d7ea953fe14e74748d53b" + ], + "authored_date": "2015-11-13T06:00:16.000+01:00", + "author_name": "윤민식", + "author_email": "minsik.yoon@samsung.com", + "committed_date": "2015-11-13T06:00:16.000+01:00", + "committer_name": "윤민식", + "committer_email": "minsik.yoon@samsung.com" + }, + { + "id": "19e2e9b4ef76b422ce1154af39a91323ccc57434", + "message": "Merge branch 'whitespace' into 'master'\r\n\r\nadd spaces\r\n\r\nTo test this pull request.(https://github.com/gitlabhq/gitlabhq/pull/9757)\r\nJust add whitespaces.\r\n\r\nSee merge request !3", + "parent_ids": [ + "c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd", + "c642fe9b8b9f28f9225d7ea953fe14e74748d53b" + ], + "authored_date": "2015-11-13T05:23:14.000+01:00", + "author_name": "Stan Hu", + "author_email": "stanhu@gmail.com", + "committed_date": "2015-11-13T05:23:14.000+01:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@gmail.com" + }, + { + "id": "c642fe9b8b9f28f9225d7ea953fe14e74748d53b", + "message": "add whitespace in empty\n", + "parent_ids": [ + "9a944d90955aaf45f6d0c88f30e27f8d2c41cec0" + ], + "authored_date": "2015-11-13T05:08:45.000+01:00", + "author_name": "윤민식", + "author_email": "minsik.yoon@samsung.com", + "committed_date": "2015-11-13T05:08:45.000+01:00", + "committer_name": "윤민식", + "committer_email": "minsik.yoon@samsung.com" + }, + { + "id": "9a944d90955aaf45f6d0c88f30e27f8d2c41cec0", + "message": "add empty file\n", + "parent_ids": [ + "c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd" + ], + "authored_date": "2015-11-13T05:08:04.000+01:00", + "author_name": "윤민식", + "author_email": "minsik.yoon@samsung.com", + "committed_date": "2015-11-13T05:08:04.000+01:00", + "committer_name": "윤민식", + "committer_email": "minsik.yoon@samsung.com" + }, + { + "id": "c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd", + "message": "Add ISO-8859 test file\n", + "parent_ids": [ + "e56497bb5f03a90a51293fc6d516788730953899" + ], + "authored_date": "2015-08-25T17:53:12.000+02:00", + "author_name": "Stan Hu", + "author_email": "stanhu@packetzoom.com", + "committed_date": "2015-08-25T17:53:12.000+02:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@packetzoom.com" + }, + { + "id": "e56497bb5f03a90a51293fc6d516788730953899", + "message": "Merge branch 'tree_helper_spec' into 'master'\n\nAdd directory structure for tree_helper spec\n\nThis directory structure is needed for a testing the method flatten_tree(tree) in the TreeHelper module\n\nSee [merge request #275](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/275#note_732774)\n\nSee merge request !2\n", + "parent_ids": [ + "5937ac0a7beb003549fc5fd26fc247adbce4a52e", + "4cd80ccab63c82b4bad16faa5193fbd2aa06df40" + ], + "authored_date": "2015-01-10T22:23:29.000+01:00", + "author_name": "Sytse Sijbrandij", + "author_email": "sytse@gitlab.com", + "committed_date": "2015-01-10T22:23:29.000+01:00", + "committer_name": "Sytse Sijbrandij", + "committer_email": "sytse@gitlab.com" + }, + { + "id": "4cd80ccab63c82b4bad16faa5193fbd2aa06df40", + "message": "add directory structure for tree_helper spec\n", + "parent_ids": [ + "5937ac0a7beb003549fc5fd26fc247adbce4a52e" + ], + "authored_date": "2015-01-10T21:28:18.000+01:00", + "author_name": "marmis85", + "author_email": "marmis85@gmail.com", + "committed_date": "2015-01-10T21:28:18.000+01:00", + "committer_name": "marmis85", + "committer_email": "marmis85@gmail.com" + }, + { + "id": "5937ac0a7beb003549fc5fd26fc247adbce4a52e", + "message": "Add submodule from gitlab.com\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n", + "parent_ids": [ + "570e7b2abdd848b95f2f578043fc23bd6f6fd24d" + ], + "authored_date": "2014-02-27T10:01:38.000+01:00", + "author_name": "Dmitriy Zaporozhets", + "author_email": "dmitriy.zaporozhets@gmail.com", + "committed_date": "2014-02-27T10:01:38.000+01:00", + "committer_name": "Dmitriy Zaporozhets", + "committer_email": "dmitriy.zaporozhets@gmail.com" + }, + { + "id": "570e7b2abdd848b95f2f578043fc23bd6f6fd24d", + "message": "Change some files\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n", + "parent_ids": [ + "6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9" + ], + "authored_date": "2014-02-27T09:57:31.000+01:00", + "author_name": "Dmitriy Zaporozhets", + "author_email": "dmitriy.zaporozhets@gmail.com", + "committed_date": "2014-02-27T09:57:31.000+01:00", + "committer_name": "Dmitriy Zaporozhets", + "committer_email": "dmitriy.zaporozhets@gmail.com" + }, + { + "id": "6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9", + "message": "More submodules\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n", + "parent_ids": [ + "d14d6c0abdd253381df51a723d58691b2ee1ab08" + ], + "authored_date": "2014-02-27T09:54:21.000+01:00", + "author_name": "Dmitriy Zaporozhets", + "author_email": "dmitriy.zaporozhets@gmail.com", + "committed_date": "2014-02-27T09:54:21.000+01:00", + "committer_name": "Dmitriy Zaporozhets", + "committer_email": "dmitriy.zaporozhets@gmail.com" + }, + { + "id": "d14d6c0abdd253381df51a723d58691b2ee1ab08", + "message": "Remove ds_store files\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n", + "parent_ids": [ + "c1acaa58bbcbc3eafe538cb8274ba387047b69f8" + ], + "authored_date": "2014-02-27T09:49:50.000+01:00", + "author_name": "Dmitriy Zaporozhets", + "author_email": "dmitriy.zaporozhets@gmail.com", + "committed_date": "2014-02-27T09:49:50.000+01:00", + "committer_name": "Dmitriy Zaporozhets", + "committer_email": "dmitriy.zaporozhets@gmail.com" + }, + { + "id": "c1acaa58bbcbc3eafe538cb8274ba387047b69f8", + "message": "Ignore DS files\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n", + "parent_ids": [ + "ae73cb07c9eeaf35924a10f713b364d32b2dd34f" + ], + "authored_date": "2014-02-27T09:48:32.000+01:00", + "author_name": "Dmitriy Zaporozhets", + "author_email": "dmitriy.zaporozhets@gmail.com", + "committed_date": "2014-02-27T09:48:32.000+01:00", + "committer_name": "Dmitriy Zaporozhets", + "committer_email": "dmitriy.zaporozhets@gmail.com" } ], "st_diffs": [ { + "diff": "Binary files a/.DS_Store and /dev/null differ\n", + "new_path": ".DS_Store", + "old_path": ".DS_Store", + "a_mode": "100644", + "b_mode": "0", + "new_file": false, + "renamed_file": false, + "deleted_file": true, + "too_large": false + }, + { + "diff": "--- a/.gitignore\n+++ b/.gitignore\n@@ -17,3 +17,4 @@ rerun.txt\n pickle-email-*.html\n .project\n config/initializers/secret_token.rb\n+.DS_Store\n", + "new_path": ".gitignore", + "old_path": ".gitignore", + "a_mode": "100644", + "b_mode": "100644", + "new_file": false, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- a/.gitmodules\n+++ b/.gitmodules\n@@ -1,3 +1,9 @@\n [submodule \"six\"]\n \tpath = six\n \turl = git://github.com/randx/six.git\n+[submodule \"gitlab-shell\"]\n+\tpath = gitlab-shell\n+\turl = https://github.com/gitlabhq/gitlab-shell.git\n+[submodule \"gitlab-grack\"]\n+\tpath = gitlab-grack\n+\turl = https://gitlab.com/gitlab-org/gitlab-grack.git\n", + "new_path": ".gitmodules", + "old_path": ".gitmodules", + "a_mode": "100644", + "b_mode": "100644", + "new_file": false, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- a/CHANGELOG\n+++ b/CHANGELOG\n@@ -1,4 +1,6 @@\n-v 6.7.0\n+v6.8.0\n+\n+v6.7.0\n - Add support for Gemnasium as a Project Service (Olivier Gonzalez)\n - Add edit file button to MergeRequest diff\n - Public groups (Jason Hollingsworth)\n", + "new_path": "CHANGELOG", + "old_path": "CHANGELOG", + "a_mode": "100644", + "b_mode": "100644", + "new_file": false, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- /dev/null\n+++ b/encoding/iso8859.txt\n@@ -0,0 +1 @@\n+Äü\n", + "new_path": "encoding/iso8859.txt", + "old_path": "encoding/iso8859.txt", + "a_mode": "0", + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "Binary files a/files/.DS_Store and /dev/null differ\n", + "new_path": "files/.DS_Store", + "old_path": "files/.DS_Store", + "a_mode": "100644", + "b_mode": "0", + "new_file": false, + "renamed_file": false, + "deleted_file": true, + "too_large": false + }, + { + "diff": "--- /dev/null\n+++ b/files/images/wm.svg\n@@ -0,0 +1,78 @@\n+\u003c?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?\u003e\n+\u003csvg width=\"1300px\" height=\"680px\" viewBox=\"0 0 1300 680\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\"\u003e\n+ \u003c!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch --\u003e\n+ \u003ctitle\u003ewm\u003c/title\u003e\n+ \u003cdesc\u003eCreated with Sketch.\u003c/desc\u003e\n+ \u003cdefs\u003e\n+ \u003cpath id=\"path-1\" d=\"M-69.8,1023.54607 L1675.19996,1023.54607 L1675.19996,0 L-69.8,0 L-69.8,1023.54607 L-69.8,1023.54607 Z\"\u003e\u003c/path\u003e\n+ \u003c/defs\u003e\n+ \u003cg id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\"\u003e\n+ \u003cpath d=\"M1300,680 L0,680 L0,0 L1300,0 L1300,680 L1300,680 Z\" id=\"bg\" fill=\"#30353E\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003cg id=\"gitlab_logo\" sketch:type=\"MSLayerGroup\" transform=\"translate(-262.000000, -172.000000)\"\u003e\n+ \u003cg id=\"g10\" transform=\"translate(872.500000, 512.354581) scale(1, -1) translate(-872.500000, -512.354581) translate(0.000000, 0.290751)\"\u003e\n+ \u003cg id=\"g12\" transform=\"translate(1218.022652, 440.744871)\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\n+ \u003cpath d=\"M-50.0233338,141.900706 L-69.07059,141.900706 L-69.0100967,0.155858152 L8.04444805,0.155858152 L8.04444805,17.6840847 L-49.9628405,17.6840847 L-50.0233338,141.900706 L-50.0233338,141.900706 Z\" id=\"path14\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g16\"\u003e\n+ \u003cg id=\"g18-Clipped\"\u003e\n+ \u003cmask id=\"mask-2\" sketch:name=\"path22\" fill=\"white\"\u003e\n+ \u003cuse xlink:href=\"#path-1\"\u003e\u003c/use\u003e\n+ \u003c/mask\u003e\n+ \u003cg id=\"path22\"\u003e\u003c/g\u003e\n+ \u003cg id=\"g18\" mask=\"url(#mask-2)\"\u003e\n+ \u003cg transform=\"translate(382.736659, 312.879425)\"\u003e\n+ \u003cg id=\"g24\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(852.718192, 124.992771)\"\u003e\n+ \u003cpath d=\"M63.9833317,27.9148929 C59.2218085,22.9379001 51.2134221,17.9597442 40.3909323,17.9597442 C25.8888194,17.9597442 20.0453962,25.1013043 20.0453962,34.4074318 C20.0453962,48.4730484 29.7848226,55.1819277 50.5642821,55.1819277 C54.4602853,55.1819277 60.7364685,54.7492469 63.9833317,54.1002256 L63.9833317,27.9148929 L63.9833317,27.9148929 Z M44.2869356,113.827628 C28.9053426,113.827628 14.7975996,108.376082 3.78897657,99.301416 L10.5211864,87.6422957 C18.3131929,92.1866076 27.8374026,96.7320827 41.4728323,96.7320827 C57.0568452,96.7320827 63.9833317,88.7239978 63.9833317,75.3074024 L63.9833317,68.3821827 C60.9528485,69.0312039 54.6766653,69.4650479 50.7806621,69.4650479 C17.4476729,69.4650479 0.565379986,57.7791759 0.565379986,33.3245665 C0.565379986,11.4683685 13.9844297,0.43151772 34.3299658,0.43151772 C48.0351955,0.43151772 61.1692285,6.70771614 65.7143717,16.8780421 L69.1776149,3.02876588 L82.5978279,3.02876588 L82.5978279,75.5237428 C82.5978279,98.462806 72.6408582,113.827628 44.2869356,113.827628 L44.2869356,113.827628 Z\" id=\"path26\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g28\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(959.546624, 124.857151)\"\u003e\n+ \u003cpath d=\"M37.2266657,17.4468081 C30.0837992,17.4468081 23.8064527,18.3121698 19.0449295,20.4767371 L19.0449295,79.2306079 L19.0449295,86.0464943 C25.538656,91.457331 33.5470425,95.3526217 43.7203922,95.3526217 C62.1173451,95.3526217 69.2602116,82.3687072 69.2602116,61.3767077 C69.2602116,31.5135879 57.7885819,17.4468081 37.2266657,17.4468081 M45.2315622,113.963713 C28.208506,113.963713 19.0449295,102.384849 19.0449295,102.384849 L19.0449295,120.67143 L18.9844362,144.908535 L10.3967097,144.908535 L0.371103324,144.908535 L0.431596656,6.62629771 C9.73826309,2.73100702 22.5081728,0.567602823 36.3611458,0.567602823 C71.8579349,0.567602823 88.9566078,23.2891625 88.9566078,62.4584098 C88.9566078,93.4043948 73.1527248,113.963713 45.2315622,113.963713\" id=\"path30\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g32\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(509.576747, 125.294950)\"\u003e\n+ \u003cpath d=\"M68.636665,129.10638 C85.5189579,129.10638 96.3414476,123.480366 103.484314,117.853189 L111.669527,132.029302 C100.513161,141.811145 85.5073245,147.06845 69.5021849,147.06845 C29.0274926,147.06845 0.673569983,122.3975 0.673569983,72.6252464 C0.673569983,20.4709215 31.2622559,0.12910638 66.2553217,0.12910638 C83.7879179,0.12910638 98.7227909,4.24073748 108.462217,8.35236859 L108.063194,64.0763105 L108.063194,70.6502677 L108.063194,81.6057001 L56.1168719,81.6057001 L56.1168719,64.0763105 L89.2323178,64.0763105 L89.6313411,21.7701271 C85.3025779,19.6055598 77.7269514,17.8748364 67.554765,17.8748364 C39.4172223,17.8748364 20.5863462,35.5717154 20.5863462,72.8415868 C20.5863462,110.711628 40.0663623,129.10638 68.636665,129.10638\" id=\"path34\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g36\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(692.388992, 124.376085)\"\u003e\n+ \u003cpath d=\"M19.7766662,145.390067 L1.16216997,145.390067 L1.2226633,121.585642 L1.2226633,111.846834 L1.2226633,106.170806 L1.2226633,96.2656714 L1.2226633,39.5681976 L1.2226633,39.3518572 C1.2226633,16.4127939 11.1796331,1.04797161 39.5335557,1.04797161 C43.4504989,1.04797161 47.2836822,1.40388649 51.0051854,2.07965952 L51.0051854,18.7925385 C48.3109055,18.3796307 45.4351455,18.1446804 42.3476589,18.1446804 C26.763646,18.1446804 19.8371595,26.1516022 19.8371595,39.5681976 L19.8371595,96.2656714 L51.0051854,96.2656714 L51.0051854,111.846834 L19.8371595,111.846834 L19.7766662,145.390067 L19.7766662,145.390067 Z\" id=\"path38\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cpath d=\"M646.318899,128.021188 L664.933395,128.021188 L664.933395,236.223966 L646.318899,236.223966 L646.318899,128.021188 L646.318899,128.021188 Z\" id=\"path40\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003cpath d=\"M646.318899,251.154944 L664.933395,251.154944 L664.933395,269.766036 L646.318899,269.766036 L646.318899,251.154944 L646.318899,251.154944 Z\" id=\"path42\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003cg id=\"g44\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.464170, 0.676006)\"\u003e\n+ \u003cpath d=\"M429.269989,169.815599 L405.225053,243.802859 L357.571431,390.440955 C355.120288,397.984955 344.444378,397.984955 341.992071,390.440955 L294.337286,243.802859 L136.094873,243.802859 L88.4389245,390.440955 C85.9877812,397.984955 75.3118715,397.984955 72.8595648,390.440955 L25.2059427,243.802859 L1.16216997,169.815599 C-1.03187664,163.067173 1.37156997,155.674379 7.11261982,151.503429 L215.215498,0.336141836 L423.319539,151.503429 C429.060589,155.674379 431.462873,163.067173 429.269989,169.815599\" id=\"path46\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g48\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(135.410135, 1.012147)\"\u003e\n+ \u003cpath d=\"M80.269998,0 L80.269998,0 L159.391786,243.466717 L1.14820997,243.466717 L80.269998,0 L80.269998,0 Z\" id=\"path50\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g52\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\"\u003e\n+ \u003cg id=\"path54\"\u003e\u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g56\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(24.893471, 1.012613)\"\u003e\n+ \u003cpath d=\"M190.786662,0 L111.664874,243.465554 L0.777106647,243.465554 L190.786662,0 L190.786662,0 Z\" id=\"path58\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g60\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\"\u003e\n+ \u003cg id=\"path62\"\u003e\u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g64\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.077245, 0.223203)\"\u003e\n+ \u003cpath d=\"M25.5933327,244.255313 L25.5933327,244.255313 L1.54839663,170.268052 C-0.644486651,163.519627 1.75779662,156.126833 7.50000981,151.957046 L215.602888,0.789758846 L25.5933327,244.255313 L25.5933327,244.255313 Z\" id=\"path66\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g68\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\"\u003e\n+ \u003cg id=\"path70\"\u003e\u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g72\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(25.670578, 244.478283)\"\u003e\n+ \u003cpath d=\"M0,0 L110.887767,0 L63.2329818,146.638096 C60.7806751,154.183259 50.1047654,154.183259 47.6536221,146.638096 L0,0 L0,0 Z\" id=\"path74\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g76\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\"\u003e\n+ \u003cpath d=\"M0,0 L79.121788,243.465554 L190.009555,243.465554 L0,0 L0,0 Z\" id=\"path78\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g80\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(214.902910, 0.223203)\"\u003e\n+ \u003cpath d=\"M190.786662,244.255313 L190.786662,244.255313 L214.831598,170.268052 C217.024481,163.519627 214.622198,156.126833 208.879985,151.957046 L0.777106647,0.789758846 L190.786662,244.255313 L190.786662,244.255313 Z\" id=\"path82\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g84\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(294.009575, 244.478283)\"\u003e\n+ \u003cpath d=\"M111.679997,0 L0.79222998,0 L48.4470155,146.638096 C50.8993221,154.183259 61.5752318,154.183259 64.0263751,146.638096 L111.679997,0 L111.679997,0 Z\" id=\"path86\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+\u003c/svg\u003e\n\\ No newline at end of file\n", + "new_path": "files/images/wm.svg", + "old_path": "files/images/wm.svg", + "a_mode": "0", + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- /dev/null\n+++ b/files/lfs/lfs_object.iso\n@@ -0,0 +1,4 @@\n+version https://git-lfs.github.com/spec/v1\n+oid sha256:91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897\n+size 1575078\n+\n", + "new_path": "files/lfs/lfs_object.iso", + "old_path": "files/lfs/lfs_object.iso", + "a_mode": "0", + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- a/files/ruby/popen.rb\n+++ b/files/ruby/popen.rb\n@@ -6,12 +6,18 @@ module Popen\n \n def popen(cmd, path=nil)\n unless cmd.is_a?(Array)\n- raise \"System commands must be given as an array of strings\"\n+ raise RuntimeError, \"System commands must be given as an array of strings\"\n end\n \n path ||= Dir.pwd\n- vars = { \"PWD\" =\u003e path }\n- options = { chdir: path }\n+\n+ vars = {\n+ \"PWD\" =\u003e path\n+ }\n+\n+ options = {\n+ chdir: path\n+ }\n \n unless File.directory?(path)\n FileUtils.mkdir_p(path)\n@@ -19,6 +25,7 @@ module Popen\n \n @cmd_output = \"\"\n @cmd_status = 0\n+\n Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr|\n @cmd_output \u003c\u003c stdout.read\n @cmd_output \u003c\u003c stderr.read\n", + "new_path": "files/ruby/popen.rb", + "old_path": "files/ruby/popen.rb", + "a_mode": "100644", + "b_mode": "100644", + "new_file": false, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- a/files/ruby/regex.rb\n+++ b/files/ruby/regex.rb\n@@ -19,14 +19,12 @@ module Gitlab\n end\n \n def archive_formats_regex\n- #|zip|tar| tar.gz | tar.bz2 |\n- /(zip|tar|tar\\.gz|tgz|gz|tar\\.bz2|tbz|tbz2|tb2|bz2)/\n+ /(zip|tar|7z|tar\\.gz|tgz|gz|tar\\.bz2|tbz|tbz2|tb2|bz2)/\n end\n \n def git_reference_regex\n # Valid git ref regex, see:\n # https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html\n-\n %r{\n (?!\n (?# doesn't begins with)\n", + "new_path": "files/ruby/regex.rb", + "old_path": "files/ruby/regex.rb", + "a_mode": "100644", + "b_mode": "100644", + "new_file": false, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- /dev/null\n+++ b/files/whitespace\n@@ -0,0 +1 @@\n+test \n", + "new_path": "files/whitespace", + "old_path": "files/whitespace", + "a_mode": "0", + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- /dev/null\n+++ b/foo/bar/.gitkeep\n", + "new_path": "foo/bar/.gitkeep", + "old_path": "foo/bar/.gitkeep", + "a_mode": "0", + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- /dev/null\n+++ b/gitlab-grack\n@@ -0,0 +1 @@\n+Subproject commit 645f6c4c82fd3f5e06f67134450a570b795e55a6\n", + "new_path": "gitlab-grack", + "old_path": "gitlab-grack", + "a_mode": "0", + "b_mode": "160000", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- /dev/null\n+++ b/gitlab-shell\n@@ -0,0 +1 @@\n+Subproject commit 79bceae69cb5750d6567b223597999bfa91cb3b9\n", + "new_path": "gitlab-shell", + "old_path": "gitlab-shell", + "a_mode": "0", + "b_mode": "160000", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { "diff": "--- /dev/null\n+++ b/test\n", "new_path": "test", "old_path": "test", @@ -4634,34 +6117,60 @@ } ], "merge_request_id": 10, - "created_at": "2016-03-22T15:13:44.107Z", - "updated_at": "2016-03-22T15:13:44.190Z", - "base_commit_sha": "be93687618e4b132087f430a4d8fc3a609c9b77c", - "real_size": "1" - } + "created_at": "2016-06-14T15:02:23.019Z", + "updated_at": "2016-06-14T15:02:23.493Z", + "base_commit_sha": "ae73cb07c9eeaf35924a10f713b364d32b2dd34f", + "real_size": "15" + }, + "events": [ + { + "id": 228, + "target_type": "MergeRequest", + "target_id": 10, + "title": null, + "data": null, + "project_id": 36, + "created_at": "2016-06-14T15:02:23.660Z", + "updated_at": "2016-06-14T15:02:23.660Z", + "action": 1, + "author_id": 1 + }, + { + "id": 170, + "target_type": "MergeRequest", + "target_id": 10, + "title": null, + "data": null, + "project_id": 5, + "created_at": "2016-06-14T15:02:23.660Z", + "updated_at": "2016-06-14T15:02:23.660Z", + "action": 1, + "author_id": 20 + } + ] }, { "id": 9, - "target_branch": "test-8", - "source_branch": "test-9", + "target_branch": "test-6", + "source_branch": "test-12", "source_project_id": 5, - "author_id": 24, - "assignee_id": 3, - "title": "Saepe et neque ut vero nobis et voluptatum facere qui minima.", - "created_at": "2016-03-22T15:13:43.792Z", - "updated_at": "2016-03-22T15:20:32.309Z", - "milestone_id": 10, + "author_id": 16, + "assignee_id": 6, + "title": "Et ipsam voluptas velit sequi illum ut.", + "created_at": "2016-06-14T15:02:22.825Z", + "updated_at": "2016-06-14T15:03:00.904Z", + "milestone_id": 16, "state": "opened", "merge_status": "unchecked", "target_project_id": 5, "iid": 1, - "description": "Autem enim aliquam labore qui voluptas ut voluptatem. Et corrupti sit fuga dolores alias iusto voluptatem. Excepturi ut saepe accusamus neque distinctio.", + "description": "Eveniet nihil ratione veniam similique qui aut sapiente tempora. Sed praesentium iusto dignissimos possimus id repudiandae quo nihil. Qui doloremque autem et iure fugit.", "position": 0, "locked_at": null, "updated_by_id": null, "merge_error": null, "merge_params": { - + "force_remove_source_branch": null }, "merge_when_build_succeeds": false, "merge_user_id": null, @@ -4669,12 +6178,12 @@ "deleted_at": null, "notes": [ { - "id": 1279, - "note": "A corrupti nesciunt pariatur ea.", + "id": 825, + "note": "Aliquid voluptatem consequatur voluptas ex perspiciatis.", "noteable_type": "MergeRequest", - "author_id": 1, - "created_at": "2016-03-22T15:20:32.307Z", - "updated_at": "2016-03-22T15:20:32.307Z", + "author_id": 26, + "created_at": "2016-06-14T15:03:00.722Z", + "updated_at": "2016-06-14T15:03:00.722Z", "project_id": 5, "attachment": { "url": null @@ -4685,17 +6194,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 1278, - "note": "Adipisci aut ut et voluptate numquam.", + "id": 826, + "note": "Itaque optio voluptatem praesentium voluptas.", "noteable_type": "MergeRequest", - "author_id": 3, - "created_at": "2016-03-22T15:20:32.281Z", - "updated_at": "2016-03-22T15:20:32.281Z", + "author_id": 25, + "created_at": "2016-06-14T15:03:00.745Z", + "updated_at": "2016-06-14T15:03:00.745Z", "project_id": 5, "attachment": { "url": null @@ -4706,17 +6218,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 1277, - "note": "Adipisci voluptatem quod ut placeat repellendus deleniti.", + "id": 827, + "note": "Ut est corporis fuga asperiores delectus excepturi aperiam.", "noteable_type": "MergeRequest", - "author_id": 4, - "created_at": "2016-03-22T15:20:32.255Z", - "updated_at": "2016-03-22T15:20:32.255Z", + "author_id": 22, + "created_at": "2016-06-14T15:03:00.771Z", + "updated_at": "2016-06-14T15:03:00.771Z", "project_id": 5, "attachment": { "url": null @@ -4727,17 +6242,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 1276, - "note": "Vitae et doloremque aut et aspernatur velit placeat sed.", + "id": 828, + "note": "Similique ea dolore officiis temporibus.", "noteable_type": "MergeRequest", - "author_id": 10, - "created_at": "2016-03-22T15:20:32.230Z", - "updated_at": "2016-03-22T15:20:32.230Z", + "author_id": 20, + "created_at": "2016-06-14T15:03:00.798Z", + "updated_at": "2016-06-14T15:03:00.798Z", "project_id": 5, "attachment": { "url": null @@ -4748,17 +6266,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 1275, - "note": "Quos cupiditate nesciunt expedita aspernatur.", + "id": 829, + "note": "Qui laudantium qui quae quis.", "noteable_type": "MergeRequest", - "author_id": 12, - "created_at": "2016-03-22T15:20:32.207Z", - "updated_at": "2016-03-22T15:20:32.207Z", + "author_id": 16, + "created_at": "2016-06-14T15:03:00.828Z", + "updated_at": "2016-06-14T15:03:00.828Z", "project_id": 5, "attachment": { "url": null @@ -4769,17 +6290,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 1274, - "note": "Optio rem inventore dicta praesentium sit.", + "id": 830, + "note": "Et vel voluptas amet laborum qui soluta.", "noteable_type": "MergeRequest", - "author_id": 22, - "created_at": "2016-03-22T15:20:32.181Z", - "updated_at": "2016-03-22T15:20:32.181Z", + "author_id": 15, + "created_at": "2016-06-14T15:03:00.850Z", + "updated_at": "2016-06-14T15:03:00.850Z", "project_id": 5, "attachment": { "url": null @@ -4790,17 +6314,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 1273, - "note": "Sit incidunt molestiae maxime officiis rerum necessitatibus.", + "id": 831, + "note": "Enim ad consequuntur assumenda provident voluptatem similique deleniti.", "noteable_type": "MergeRequest", - "author_id": 24, - "created_at": "2016-03-22T15:20:32.159Z", - "updated_at": "2016-03-22T15:20:32.159Z", + "author_id": 6, + "created_at": "2016-06-14T15:03:00.876Z", + "updated_at": "2016-06-14T15:03:00.876Z", "project_id": 5, "attachment": { "url": null @@ -4811,17 +6338,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 1272, - "note": "Autem ut non itaque molestiae nisi quia officiis doloribus.", + "id": 832, + "note": "Officiis sequi commodi pariatur totam fugiat voluptas corporis dignissimos.", "noteable_type": "MergeRequest", - "author_id": 26, - "created_at": "2016-03-22T15:20:32.129Z", - "updated_at": "2016-03-22T15:20:32.129Z", + "author_id": 1, + "created_at": "2016-06-14T15:03:00.902Z", + "updated_at": "2016-06-14T15:03:00.902Z", "project_id": 5, "attachment": { "url": null @@ -4832,9 +6362,12 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ], "merge_request_diff": { @@ -4842,17 +6375,17 @@ "state": "collected", "st_commits": [ { - "id": "e239ba8c97b80b2874579a4d625ea9628f4c8ff5", + "id": "a4e5dfebf42e34596526acb8611bc7ed80e4eb3f", "message": "fixes #10\n", "parent_ids": [ "be93687618e4b132087f430a4d8fc3a609c9b77c" ], - "authored_date": "2016-01-19T15:38:06.000+01:00", - "author_name": "Test Lopez", - "author_email": "Test@Testlopez.es", - "committed_date": "2016-01-19T15:38:06.000+01:00", - "committer_name": "Test Lopez", - "committer_email": "Test@Testlopez.es" + "authored_date": "2016-01-19T15:44:02.000+01:00", + "author_name": "James Lopez", + "author_email": "james@jameslopez.es", + "committed_date": "2016-01-19T15:44:02.000+01:00", + "committer_name": "James Lopez", + "committer_email": "james@jameslopez.es" } ], "st_diffs": [ @@ -4869,11 +6402,37 @@ } ], "merge_request_id": 9, - "created_at": "2016-03-22T15:13:43.794Z", - "updated_at": "2016-03-22T15:13:43.848Z", + "created_at": "2016-06-14T15:02:22.829Z", + "updated_at": "2016-06-14T15:02:22.900Z", "base_commit_sha": "be93687618e4b132087f430a4d8fc3a609c9b77c", "real_size": "1" - } + }, + "events": [ + { + "id": 229, + "target_type": "MergeRequest", + "target_id": 9, + "title": null, + "data": null, + "project_id": 36, + "created_at": "2016-06-14T15:02:22.927Z", + "updated_at": "2016-06-14T15:02:22.927Z", + "action": 1, + "author_id": 16 + }, + { + "id": 169, + "target_type": "MergeRequest", + "target_id": 9, + "title": null, + "data": null, + "project_id": 5, + "created_at": "2016-06-14T15:02:22.927Z", + "updated_at": "2016-06-14T15:02:22.927Z", + "action": 1, + "author_id": 16 + } + ] } ], "pipelines": [ @@ -5360,5 +6919,464 @@ } ] } + ], + "variables": [ + + ], + "triggers": [ + + ], + "deploy_keys": [ + + ], + "services": [ + { + "id": 164, + "title": null, + "project_id": 5, + "created_at": "2016-06-14T15:02:07.372Z", + "updated_at": "2016-06-14T15:02:07.372Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "issue_tracker", + "default": true, + "wiki_page_events": true + }, + { + "id": 100, + "title": "JetBrains TeamCity CI", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.315Z", + "updated_at": "2016-06-14T15:01:51.315Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "ci", + "default": false, + "wiki_page_events": true + }, + { + "id": 99, + "title": "Slack", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.303Z", + "updated_at": "2016-06-14T15:01:51.303Z", + "active": false, + "properties": { + "notify_only_broken_builds": true + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "common", + "default": false, + "wiki_page_events": true + }, + { + "id": 98, + "title": "Redmine", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.289Z", + "updated_at": "2016-06-14T15:01:51.289Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "issue_tracker", + "default": false, + "wiki_page_events": true + }, + { + "id": 97, + "title": "Pushover", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.277Z", + "updated_at": "2016-06-14T15:01:51.277Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "common", + "default": false, + "wiki_page_events": true + }, + { + "id": 96, + "title": "PivotalTracker", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.267Z", + "updated_at": "2016-06-14T15:01:51.267Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "common", + "default": false, + "wiki_page_events": true + }, + { + "id": 95, + "title": "JIRA", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.255Z", + "updated_at": "2016-06-14T15:01:51.255Z", + "active": false, + "properties": { + "api_url": "", + "jira_issue_transition_id": "2" + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "issue_tracker", + "default": false, + "wiki_page_events": true + }, + { + "id": 94, + "title": "Irker (IRC gateway)", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.232Z", + "updated_at": "2016-06-14T15:01:51.232Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "common", + "default": false, + "wiki_page_events": true + }, + { + "id": 93, + "title": "HipChat", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.219Z", + "updated_at": "2016-06-14T15:01:51.219Z", + "active": false, + "properties": { + "notify_only_broken_builds": true + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "common", + "default": false, + "wiki_page_events": true + }, + { + "id": 92, + "title": "Gemnasium", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.202Z", + "updated_at": "2016-06-14T15:01:51.202Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "common", + "default": false, + "wiki_page_events": true + }, + { + "id": 91, + "title": "Flowdock", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.182Z", + "updated_at": "2016-06-14T15:01:51.182Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "common", + "default": false, + "wiki_page_events": true + }, + { + "id": 90, + "title": "External Wiki", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.166Z", + "updated_at": "2016-06-14T15:01:51.166Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "common", + "default": false, + "wiki_page_events": true + }, + { + "id": 89, + "title": "Emails on push", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.153Z", + "updated_at": "2016-06-14T15:01:51.153Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "common", + "default": false, + "wiki_page_events": true + }, + { + "id": 88, + "title": "Drone CI", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.139Z", + "updated_at": "2016-06-14T15:01:51.139Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "ci", + "default": false, + "wiki_page_events": true + }, + { + "id": 87, + "title": "Custom Issue Tracker", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.125Z", + "updated_at": "2016-06-14T15:01:51.125Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "issue_tracker", + "default": false, + "wiki_page_events": true + }, + { + "id": 86, + "title": "Campfire", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.113Z", + "updated_at": "2016-06-14T15:01:51.113Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "common", + "default": false, + "wiki_page_events": true + }, + { + "id": 85, + "title": "Builds emails", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.090Z", + "updated_at": "2016-06-14T15:01:51.090Z", + "active": false, + "properties": { + "notify_only_broken_builds": true + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "common", + "default": false, + "wiki_page_events": true + }, + { + "id": 84, + "title": "Buildkite", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.080Z", + "updated_at": "2016-06-14T15:01:51.080Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "ci", + "default": false, + "wiki_page_events": true + }, + { + "id": 83, + "title": "Atlassian Bamboo CI", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.067Z", + "updated_at": "2016-06-14T15:01:51.067Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "ci", + "default": false, + "wiki_page_events": true + }, + { + "id": 82, + "title": "Assembla", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.047Z", + "updated_at": "2016-06-14T15:01:51.047Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "common", + "default": false, + "wiki_page_events": true + }, + { + "id": 81, + "title": "Asana", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.031Z", + "updated_at": "2016-06-14T15:01:51.031Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "common", + "default": false, + "wiki_page_events": true + } + ], + "hooks": [ + + ], + "protected_branches": [ + ] }
\ No newline at end of file diff --git a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb index 23036ab8108..a72aaa44e82 100644 --- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb @@ -2,7 +2,6 @@ require 'spec_helper' describe Gitlab::ImportExport::ProjectTreeRestorer, services: true do describe 'restore project tree' do - let(:user) { create(:user) } let(:namespace) { create(:namespace, owner: user) } let(:shared) { Gitlab::ImportExport::Shared.new(relative_path: "", project_path: 'path') } @@ -24,6 +23,12 @@ describe Gitlab::ImportExport::ProjectTreeRestorer, services: true do expect(Ci::Pipeline.first.notes).not_to be_empty end + + it 'restores the correct event' do + restored_project_json + + expect(Event.where.not(data: nil).first.data[:ref]).not_to be_empty + end end end end diff --git a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb index 8d29b2f8fd1..a75eaa4d51f 100644 --- a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb @@ -2,7 +2,6 @@ require 'spec_helper' describe Gitlab::ImportExport::ProjectTreeSaver, services: true do describe 'saves the project tree into a json object' do - let(:shared) { Gitlab::ImportExport::Shared.new(relative_path: project.path_with_namespace) } let(:project_tree_saver) { described_class.new(project: project, shared: shared) } let(:export_path) { "#{Dir::tmpdir}/project_tree_saver_spec" } @@ -23,7 +22,6 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do end context 'JSON' do - let(:saved_project_json) do project_tree_saver.save project_json(project_tree_saver.full_path) @@ -34,7 +32,7 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do end it 'has events' do - expect(saved_project_json['events']).not_to be_empty + expect(saved_project_json['milestones'].first['events']).not_to be_empty end it 'has milestones' do @@ -132,7 +130,7 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do statuses: [commit_status]) create(:ci_build, pipeline: ci_pipeline, project: project) - create(:milestone, project: project) + milestone = create(:milestone, project: project) create(:note, noteable: issue, project: project) create(:note, noteable: merge_request, project: project) create(:note, noteable: snippet, project: project) @@ -140,6 +138,9 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do author: user, project: project, commit_id: ci_pipeline.sha) + + create(:event, target: milestone, project: project, action: Event::CREATED, author: user) + project end diff --git a/spec/lib/gitlab/import_export/reader_spec.rb b/spec/lib/gitlab/import_export/reader_spec.rb index 109522fa626..b76e14deca1 100644 --- a/spec/lib/gitlab/import_export/reader_spec.rb +++ b/spec/lib/gitlab/import_export/reader_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe Gitlab::ImportExport::Reader, lib: true do - let(:shared) { Gitlab::ImportExport::Shared.new(relative_path:'') } + let(:shared) { Gitlab::ImportExport::Shared.new(relative_path: '') } let(:test_config) { 'spec/support/import_export/import_export.yml' } let(:project_tree_hash) do { @@ -25,7 +25,6 @@ describe Gitlab::ImportExport::Reader, lib: true do end context 'individual scenarios' do - it 'generates the correct hash for a single project relation' do setup_yaml(project_tree: [:issues]) diff --git a/spec/lib/gitlab/import_export/repo_bundler_spec.rb b/spec/lib/gitlab/import_export/repo_bundler_spec.rb index 590a9a7e1a5..135e99bc953 100644 --- a/spec/lib/gitlab/import_export/repo_bundler_spec.rb +++ b/spec/lib/gitlab/import_export/repo_bundler_spec.rb @@ -2,7 +2,6 @@ require 'spec_helper' describe Gitlab::ImportExport::RepoSaver, services: true do describe 'bundle a project Git repo' do - let(:user) { create(:user) } let!(:project) { create(:project, :public, name: 'searchable_project') } let(:export_path) { "#{Dir::tmpdir}/project_tree_saver_spec" } diff --git a/spec/lib/gitlab/import_export/wiki_repo_bundler_spec.rb b/spec/lib/gitlab/import_export/wiki_repo_bundler_spec.rb index b9ffc8694a5..b628da0f3e8 100644 --- a/spec/lib/gitlab/import_export/wiki_repo_bundler_spec.rb +++ b/spec/lib/gitlab/import_export/wiki_repo_bundler_spec.rb @@ -2,7 +2,6 @@ require 'spec_helper' describe Gitlab::ImportExport::WikiRepoSaver, services: true do describe 'bundle a wiki Git repo' do - let(:user) { create(:user) } let!(:project) { create(:project, :public, name: 'searchable_project') } let(:export_path) { "#{Dir::tmpdir}/project_tree_saver_spec" } diff --git a/spec/lib/gitlab/ldap/auth_hash_spec.rb b/spec/lib/gitlab/ldap/auth_hash_spec.rb index 6a53ed1db64..69c49051156 100644 --- a/spec/lib/gitlab/ldap/auth_hash_spec.rb +++ b/spec/lib/gitlab/ldap/auth_hash_spec.rb @@ -32,7 +32,6 @@ describe Gitlab::LDAP::AuthHash, lib: true do end context "without overridden attributes" do - it "has the correct username" do expect(auth_hash.username).to eq("123456") end diff --git a/spec/lib/gitlab/o_auth/user_spec.rb b/spec/lib/gitlab/o_auth/user_spec.rb index fbb5895c2ef..1fca8a13037 100644 --- a/spec/lib/gitlab/o_auth/user_spec.rb +++ b/spec/lib/gitlab/o_auth/user_spec.rb @@ -135,13 +135,12 @@ describe Gitlab::OAuth::User, lib: true do before do allow(ldap_user).to receive(:uid) { uid } allow(ldap_user).to receive(:username) { uid } - allow(ldap_user).to receive(:email) { ['johndoe@example.com','john2@example.com'] } + allow(ldap_user).to receive(:email) { ['johndoe@example.com', 'john2@example.com'] } allow(ldap_user).to receive(:dn) { 'uid=user1,ou=People,dc=example' } allow(Gitlab::LDAP::Person).to receive(:find_by_uid).and_return(ldap_user) end context "and no account for the LDAP user" do - it "creates a user with dual LDAP and omniauth identities" do oauth_user.save @@ -182,7 +181,6 @@ describe Gitlab::OAuth::User, lib: true do end end end - end describe 'blocking' do @@ -216,7 +214,7 @@ describe Gitlab::OAuth::User, lib: true do stub_omniauth_config(auto_link_ldap_user: true) allow(ldap_user).to receive(:uid) { uid } allow(ldap_user).to receive(:username) { uid } - allow(ldap_user).to receive(:email) { ['johndoe@example.com','john2@example.com'] } + allow(ldap_user).to receive(:email) { ['johndoe@example.com', 'john2@example.com'] } allow(ldap_user).to receive(:dn) { 'uid=user1,ou=People,dc=example' } allow(oauth_user).to receive(:ldap_person).and_return(ldap_user) end @@ -268,7 +266,6 @@ describe Gitlab::OAuth::User, lib: true do end end - context 'sign-in' do before do oauth_user.save diff --git a/spec/lib/gitlab/popen_spec.rb b/spec/lib/gitlab/popen_spec.rb index 795cf241278..e8b236426e9 100644 --- a/spec/lib/gitlab/popen_spec.rb +++ b/spec/lib/gitlab/popen_spec.rb @@ -10,7 +10,7 @@ describe 'Gitlab::Popen', lib: true, no_db: true do context 'zero status' do before do - @output, @status = @klass.new.popen(%W(ls), path) + @output, @status = @klass.new.popen(%w(ls), path) end it { expect(@status).to be_zero } @@ -19,7 +19,7 @@ describe 'Gitlab::Popen', lib: true, no_db: true do context 'non-zero status' do before do - @output, @status = @klass.new.popen(%W(cat NOTHING), path) + @output, @status = @klass.new.popen(%w(cat NOTHING), path) end it { expect(@status).to eq(1) } @@ -34,7 +34,7 @@ describe 'Gitlab::Popen', lib: true, no_db: true do context 'without a directory argument' do before do - @output, @status = @klass.new.popen(%W(ls)) + @output, @status = @klass.new.popen(%w(ls)) end it { expect(@status).to be_zero } diff --git a/spec/lib/gitlab/push_data_builder_spec.rb b/spec/lib/gitlab/push_data_builder_spec.rb index 7fc34139eff..6bd7393aaa7 100644 --- a/spec/lib/gitlab/push_data_builder_spec.rb +++ b/spec/lib/gitlab/push_data_builder_spec.rb @@ -4,7 +4,6 @@ describe Gitlab::PushDataBuilder, lib: true do let(:project) { create(:project) } let(:user) { create(:user) } - describe '.build_sample' do let(:data) { described_class.build_sample(project, user) } diff --git a/spec/lib/gitlab/saml/user_spec.rb b/spec/lib/gitlab/saml/user_spec.rb index 2753aecc1f4..56bf08e7041 100644 --- a/spec/lib/gitlab/saml/user_spec.rb +++ b/spec/lib/gitlab/saml/user_spec.rb @@ -214,7 +214,6 @@ describe Gitlab::Saml::User, lib: true do end end end - end describe 'blocking' do diff --git a/spec/lib/gitlab/url_sanitizer_spec.rb b/spec/lib/gitlab/url_sanitizer_spec.rb index de55334118f..59024d3290b 100644 --- a/spec/lib/gitlab/url_sanitizer_spec.rb +++ b/spec/lib/gitlab/url_sanitizer_spec.rb @@ -64,5 +64,4 @@ describe Gitlab::UrlSanitizer, lib: true do expect(sanitizer.full_url).to eq('user@server:project.git') end end - end diff --git a/spec/lib/gitlab_spec.rb b/spec/lib/gitlab_spec.rb index c59dfea5c55..c4c107c9eea 100644 --- a/spec/lib/gitlab_spec.rb +++ b/spec/lib/gitlab_spec.rb @@ -8,6 +8,12 @@ describe Gitlab, lib: true do expect(described_class.com?).to eq true end + it 'is true when on staging' do + stub_config_setting(url: 'https://staging.gitlab.com') + + expect(described_class.com?).to eq true + end + it 'is false when not on GitLab.com' do stub_config_setting(url: 'http://example.com') diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index ae55a01ebea..aa382f930d7 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -406,7 +406,7 @@ describe Notify do let(:user) { create(:user) } let(:project_member) do project.request_access(user) - project.members.request.find_by(user_id: user.id) + project.requesters.find_by(user_id: user.id) end subject { Notify.member_access_requested_email('project', project_member.id) } @@ -433,7 +433,7 @@ describe Notify do let(:user) { create(:user) } let(:project_member) do project.request_access(user) - project.members.request.find_by(user_id: user.id) + project.requesters.find_by(user_id: user.id) end subject { Notify.member_access_requested_email('project', project_member.id) } @@ -459,7 +459,7 @@ describe Notify do let(:user) { create(:user) } let(:project_member) do project.request_access(user) - project.members.request.find_by(user_id: user.id) + project.requesters.find_by(user_id: user.id) end subject { Notify.member_access_denied_email('project', project.id, user.id) } @@ -684,7 +684,7 @@ describe Notify do let(:user) { create(:user) } let(:group_member) do group.request_access(user) - group.members.request.find_by(user_id: user.id) + group.requesters.find_by(user_id: user.id) end subject { Notify.member_access_requested_email('group', group_member.id) } @@ -705,7 +705,7 @@ describe Notify do let(:user) { create(:user) } let(:group_member) do group.request_access(user) - group.members.request.find_by(user_id: user.id) + group.requesters.find_by(user_id: user.id) end subject { Notify.member_access_denied_email('group', group.id, user.id) } @@ -984,7 +984,6 @@ describe Notify do end context "when set to send from committer email if domain matches" do - let(:send_from_committer_email) { true } before do @@ -992,7 +991,6 @@ describe Notify do end context "when the committer email domain is within the GitLab domain" do - before do user.update_attribute(:email, "user@company.com") user.confirm @@ -1010,7 +1008,6 @@ describe Notify do end context "when the committer email domain is not completely within the GitLab domain" do - before do user.update_attribute(:email, "user@something.company.com") user.confirm @@ -1028,7 +1025,6 @@ describe Notify do end context "when the committer email domain is outside the GitLab domain" do - before do user.update_attribute(:email, "user@mpany.com") user.confirm @@ -1084,5 +1080,4 @@ describe Notify do is_expected.to have_body_text /#{diff_path}/ end end - end diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index d84f3e998f5..2ea1320267c 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -40,6 +40,16 @@ describe ApplicationSetting, models: true do it_behaves_like 'an object with email-formated attributes', :admin_notification_email do subject { setting } end + + context 'repository storages inclussion' do + before do + storages = { 'custom' => 'tmp/tests/custom_repositories' } + allow(Gitlab.config.repositories).to receive(:storages).and_return(storages) + end + + it { is_expected.to allow_value('custom').for(:repository_storage) } + it { is_expected.not_to allow_value('alternative').for(:repository_storage) } + end end context 'restricted signup domains' do diff --git a/spec/models/build_spec.rb b/spec/models/build_spec.rb index 8154001cf46..e8171788872 100644 --- a/spec/models/build_spec.rb +++ b/spec/models/build_spec.rb @@ -323,7 +323,6 @@ describe Ci::Build, models: true do expect_any_instance_of(Ci::Runner).to receive(:can_pick?).and_return(false) is_expected.to be_falsey end - end end @@ -669,4 +668,22 @@ describe Ci::Build, models: true do expect(build.commit).to eq project.commit end end + + describe '#retryable?' do + context 'when build is running' do + before { build.run! } + + it 'should return false' do + expect(build.retryable?).to be false + end + end + + context 'when build is finished' do + before { build.success! } + + it 'should return true' do + expect(build.retryable?).to be true + end + end + end end diff --git a/spec/models/concerns/access_requestable_spec.rb b/spec/models/concerns/access_requestable_spec.rb index 98307876962..96eee0e8bdd 100644 --- a/spec/models/concerns/access_requestable_spec.rb +++ b/spec/models/concerns/access_requestable_spec.rb @@ -16,7 +16,7 @@ describe AccessRequestable do before { group.request_access(user) } - it { expect(group.members.request.exists?(user_id: user)).to be_truthy } + it { expect(group.requesters.exists?(user_id: user)).to be_truthy } end end @@ -34,7 +34,7 @@ describe AccessRequestable do before { project.request_access(user) } - it { expect(project.members.request.exists?(user_id: user)).to be_truthy } + it { expect(project.requesters.exists?(user_id: user)).to be_truthy } end end end diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb index 89730ab8eb8..60e4bbc8564 100644 --- a/spec/models/concerns/issuable_spec.rb +++ b/spec/models/concerns/issuable_spec.rb @@ -170,7 +170,6 @@ describe Issue, "Issuable" do end end - describe '#subscribed?' do context 'user is not a participant in the issue' do before { allow(issue).to receive(:participants).with(user).and_return([]) } diff --git a/spec/models/concerns/strip_attribute_spec.rb b/spec/models/concerns/strip_attribute_spec.rb index 6445e29c3ef..c3af7a0960f 100644 --- a/spec/models/concerns/strip_attribute_spec.rb +++ b/spec/models/concerns/strip_attribute_spec.rb @@ -16,5 +16,4 @@ describe Milestone, "StripAttribute" do it { expect(milestone.title).to eq('8.3') } end - end diff --git a/spec/models/email_spec.rb b/spec/models/email_spec.rb index 5d0bd31db5a..d9df9e0f907 100644 --- a/spec/models/email_spec.rb +++ b/spec/models/email_spec.rb @@ -1,11 +1,9 @@ require 'spec_helper' describe Email, models: true do - describe 'validations' do it_behaves_like 'an object with email-formated attributes', :email do subject { build(:email) } end end - end diff --git a/spec/models/forked_project_link_spec.rb b/spec/models/forked_project_link_spec.rb index 3b817608ce0..fa1a0d4e0c7 100644 --- a/spec/models/forked_project_link_spec.rb +++ b/spec/models/forked_project_link_spec.rb @@ -23,14 +23,12 @@ describe :forked_from_project do let(:project_from) { create(:project) } let(:project_to) { create(:project, forked_project_link: forked_project_link) } - before :each do forked_project_link.forked_from_project = project_from forked_project_link.forked_to_project = project_to forked_project_link.save! end - it "project_to should know it is forked" do expect(project_to.forked?).to be_truthy end @@ -43,7 +41,6 @@ describe :forked_from_project do expect(forked_project_link).to receive(:destroy) project_to.destroy end - end def fork_project(from_project, user) diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb index 2c19aa3f67f..a878ff1b227 100644 --- a/spec/models/group_spec.rb +++ b/spec/models/group_spec.rb @@ -7,9 +7,38 @@ describe Group, models: true do it { is_expected.to have_many :projects } it { is_expected.to have_many(:group_members).dependent(:destroy) } it { is_expected.to have_many(:users).through(:group_members) } + it { is_expected.to have_many(:owners).through(:group_members) } + it { is_expected.to have_many(:requesters).dependent(:destroy) } it { is_expected.to have_many(:project_group_links).dependent(:destroy) } it { is_expected.to have_many(:shared_projects).through(:project_group_links) } it { is_expected.to have_many(:notification_settings).dependent(:destroy) } + + describe '#members & #requesters' do + let(:requester) { create(:user) } + let(:developer) { create(:user) } + before do + group.request_access(requester) + group.add_developer(developer) + end + + describe '#members' do + it 'includes members and exclude requesters' do + member_user_ids = group.members.pluck(:user_id) + + expect(member_user_ids).to include(developer.id) + expect(member_user_ids).not_to include(requester.id) + end + end + + describe '#requesters' do + it 'does not include requesters' do + requester_user_ids = group.requesters.pluck(:user_id) + + expect(requester_user_ids).to include(requester.id) + expect(requester_user_ids).not_to include(developer.id) + end + end + end end describe 'modules' do diff --git a/spec/models/identity_spec.rb b/spec/models/identity_spec.rb index 1b987588f59..b3aed66a5b6 100644 --- a/spec/models/identity_spec.rb +++ b/spec/models/identity_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' RSpec.describe Identity, models: true do - describe 'relations' do it { is_expected.to belong_to(:user) } end diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index e9134a3d283..40181a8b906 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -73,10 +73,10 @@ describe Member, models: true do @accepted_invite_member = project.members.invite.find_by_invite_email('toto2@example.com').tap { |u| u.accept_invite!(accepted_invite_user) } requested_user = create(:user).tap { |u| project.request_access(u) } - @requested_member = project.members.request.find_by(user_id: requested_user.id) + @requested_member = project.requesters.find_by(user_id: requested_user.id) accepted_request_user = create(:user).tap { |u| project.request_access(u) } - @accepted_request_member = project.members.request.find_by(user_id: accepted_request_user.id).tap { |m| m.accept_request } + @accepted_request_member = project.requesters.find_by(user_id: accepted_request_user.id).tap { |m| m.accept_request } end describe '.invite' do @@ -103,22 +103,6 @@ describe Member, models: true do it { expect(described_class.request).not_to include @accepted_request_member } end - describe '.non_request' do - it { expect(described_class.non_request).to include @master } - it { expect(described_class.non_request).to include @invited_member } - it { expect(described_class.non_request).to include @accepted_invite_member } - it { expect(described_class.non_request).not_to include @requested_member } - it { expect(described_class.non_request).to include @accepted_request_member } - end - - describe '.non_pending' do - it { expect(described_class.non_pending).to include @master } - it { expect(described_class.non_pending).not_to include @invited_member } - it { expect(described_class.non_pending).to include @accepted_invite_member } - it { expect(described_class.non_pending).not_to include @requested_member } - it { expect(described_class.non_pending).to include @accepted_request_member } - end - describe '.owners_and_masters' do it { expect(described_class.owners_and_masters).to include @owner } it { expect(described_class.owners_and_masters).to include @master } diff --git a/spec/models/members/project_member_spec.rb b/spec/models/members/project_member_spec.rb index bbf65edb27c..4c103462433 100644 --- a/spec/models/members/project_member_spec.rb +++ b/spec/models/members/project_member_spec.rb @@ -119,7 +119,6 @@ describe ProjectMember, models: true do it { expect(@project_1.users).to include(@user_1) } it { expect(@project_1.users).to include(@user_2) } - it { expect(@project_2.users).to include(@user_1) } it { expect(@project_2.users).to include(@user_2) } end diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb index 4e68ac5e63a..5f68cd2b066 100644 --- a/spec/models/namespace_spec.rb +++ b/spec/models/namespace_spec.rb @@ -57,6 +57,7 @@ describe Namespace, models: true do describe :move_dir do before do @namespace = create :namespace + @project = create :project, namespace: @namespace allow(@namespace).to receive(:path_changed?).and_return(true) end @@ -87,8 +88,13 @@ describe Namespace, models: true do end describe :rm_dir do - it "should remove dir" do - expect(namespace.rm_dir).to be_truthy + let!(:project) { create(:project, namespace: namespace) } + let!(:path) { File.join(Gitlab.config.repositories.storages.default, namespace.path) } + + before { namespace.destroy } + + it "should remove its dirs when deleted" do + expect(File.exist?(path)).to be(false) end end @@ -103,7 +109,6 @@ describe Namespace, models: true do end describe ".clean_path" do - let!(:user) { create(:user, username: "johngitlab-etc") } let!(:namespace) { create(:namespace, path: "JohnGitLab-etc1") } diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb index c9517324541..5a97cf370da 100644 --- a/spec/models/project_services/jira_service_spec.rb +++ b/spec/models/project_services/jira_service_spec.rb @@ -154,11 +154,9 @@ describe JiraService, models: true do expect(@jira_service.password).to eq("password") expect(@jira_service.api_url).to eq("http://jira_edited.example.com/rest/api/2") end - end end - describe "Validations" do context "active" do before do diff --git a/spec/models/project_services/slack_service/wiki_page_message_spec.rb b/spec/models/project_services/slack_service/wiki_page_message_spec.rb index 6ecab645b49..46dedb66c7c 100644 --- a/spec/models/project_services/slack_service/wiki_page_message_spec.rb +++ b/spec/models/project_services/slack_service/wiki_page_message_spec.rb @@ -47,7 +47,6 @@ describe SlackService::WikiPageMessage, models: true do context 'when :action == "create"' do before { args[:object_attributes][:action] = 'create' } - it 'it returns the attachment for a new wiki page' do expect(subject.attachments).to eq([ { diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index d305cd9ff1e..a8c777d1e3e 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -11,6 +11,8 @@ describe Project, models: true do it { is_expected.to have_many(:issues).dependent(:destroy) } it { is_expected.to have_many(:milestones).dependent(:destroy) } it { is_expected.to have_many(:project_members).dependent(:destroy) } + it { is_expected.to have_many(:users).through(:project_members) } + it { is_expected.to have_many(:requesters).dependent(:destroy) } it { is_expected.to have_many(:notes).dependent(:destroy) } it { is_expected.to have_many(:snippets).class_name('ProjectSnippet').dependent(:destroy) } it { is_expected.to have_many(:deploy_keys_projects).dependent(:destroy) } @@ -31,6 +33,34 @@ describe Project, models: true do it { is_expected.to have_many(:environments).dependent(:destroy) } it { is_expected.to have_many(:deployments).dependent(:destroy) } it { is_expected.to have_many(:todos).dependent(:destroy) } + + describe '#members & #requesters' do + let(:project) { create(:project) } + let(:requester) { create(:user) } + let(:developer) { create(:user) } + before do + project.request_access(requester) + project.team << [developer, :developer] + end + + describe '#members' do + it 'includes members and exclude requesters' do + member_user_ids = project.members.pluck(:user_id) + + expect(member_user_ids).to include(developer.id) + expect(member_user_ids).not_to include(requester.id) + end + end + + describe '#requesters' do + it 'does not include requesters' do + requester_user_ids = project.requesters.pluck(:user_id) + + expect(requester_user_ids).to include(requester.id) + expect(requester_user_ids).not_to include(developer.id) + end + end + end end describe 'modules' do @@ -56,6 +86,7 @@ describe Project, models: true do it { is_expected.to validate_length_of(:description).is_within(0..2000) } it { is_expected.to validate_presence_of(:creator) } it { is_expected.to validate_presence_of(:namespace) } + it { is_expected.to validate_presence_of(:repository_storage) } it 'should not allow new projects beyond user limits' do project2 = build(:project) @@ -84,6 +115,20 @@ describe Project, models: true do end end end + + context 'repository storages inclussion' do + let(:project2) { build(:project, repository_storage: 'missing') } + + before do + storages = { 'custom' => 'tmp/tests/custom_repositories' } + allow(Gitlab.config.repositories).to receive(:storages).and_return(storages) + end + + it "should not allow repository storages that don't match a label in the configuration" do + expect(project2).not_to be_valid + expect(project2.errors[:repository_storage].first).to match(/is not included in the list/) + end + end end describe 'default_scope' do @@ -131,6 +176,24 @@ describe Project, models: true do end end + describe '#repository_storage_path' do + let(:project) { create(:project, repository_storage: 'custom') } + + before do + FileUtils.mkdir('tmp/tests/custom_repositories') + storages = { 'custom' => 'tmp/tests/custom_repositories' } + allow(Gitlab.config.repositories).to receive(:storages).and_return(storages) + end + + after do + FileUtils.rm_rf('tmp/tests/custom_repositories') + end + + it 'returns the repository storage path' do + expect(project.repository_storage_path).to eq('tmp/tests/custom_repositories') + end + end + it 'should return valid url to repo' do project = Project.new(path: 'somewhere') expect(project.url_to_repo).to eq(Gitlab.config.gitlab_shell.ssh_path_prefix + 'somewhere.git') @@ -574,6 +637,21 @@ describe Project, models: true do end end + context 'repository storage by default' do + let(:project) { create(:empty_project) } + + subject { project.repository_storage } + + before do + storages = { 'alternative_storage' => '/some/path' } + allow(Gitlab.config.repositories).to receive(:storages).and_return(storages) + stub_application_setting(repository_storage: 'alternative_storage') + allow_any_instance_of(Project).to receive(:ensure_dir_exist).and_return(true) + end + + it { is_expected.to eq('alternative_storage') } + end + context 'shared runners by default' do let(:project) { create(:empty_project) } @@ -729,12 +807,12 @@ describe Project, models: true do expect(gitlab_shell).to receive(:mv_repository). ordered. - with("#{ns}/foo", "#{ns}/#{project.path}"). + with(project.repository_storage_path, "#{ns}/foo", "#{ns}/#{project.path}"). and_return(true) expect(gitlab_shell).to receive(:mv_repository). ordered. - with("#{ns}/foo.wiki", "#{ns}/#{project.path}.wiki"). + with(project.repository_storage_path, "#{ns}/foo.wiki", "#{ns}/#{project.path}.wiki"). and_return(true) expect_any_instance_of(SystemHooksService). @@ -826,7 +904,7 @@ describe Project, models: true do context 'using a regular repository' do it 'creates the repository' do expect(shell).to receive(:add_repository). - with(project.path_with_namespace). + with(project.repository_storage_path, project.path_with_namespace). and_return(true) expect(project.repository).to receive(:after_create) @@ -836,7 +914,7 @@ describe Project, models: true do it 'adds an error if the repository could not be created' do expect(shell).to receive(:add_repository). - with(project.path_with_namespace). + with(project.repository_storage_path, project.path_with_namespace). and_return(false) expect(project.repository).not_to receive(:after_create) diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index d8350000bf6..851b8b241d7 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -531,8 +531,6 @@ describe Repository, models: true do describe '#expire_cache' do it 'expires all caches' do expect(repository).to receive(:expire_branch_cache) - expect(repository).to receive(:expire_branch_count_cache) - expect(repository).to receive(:expire_tag_count_cache) repository.expire_cache end @@ -857,7 +855,6 @@ describe Repository, models: true do repository.after_create end - end describe "#copy_gitattributes" do @@ -1055,12 +1052,14 @@ describe Repository, models: true do let(:cache) { repository.send(:cache) } it 'builds the caches if they do not already exist' do + cache_keys = repository.cache_keys + repository.cache_keys_for_branches_and_tags + expect(cache).to receive(:exist?). - exactly(repository.cache_keys.length). + exactly(cache_keys.length). times. and_return(false) - repository.cache_keys.each do |key| + cache_keys.each do |key| expect(repository).to receive(key) end @@ -1068,12 +1067,14 @@ describe Repository, models: true do end it 'does not build any caches that already exist' do + cache_keys = repository.cache_keys + repository.cache_keys_for_branches_and_tags + expect(cache).to receive(:exist?). - exactly(repository.cache_keys.length). + exactly(cache_keys.length). times. and_return(true) - repository.cache_keys.each do |key| + cache_keys.each do |key| expect(repository).not_to receive(key) end diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb index 2f000dbc01a..96bbbec9ea1 100644 --- a/spec/models/service_spec.rb +++ b/spec/models/service_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' describe Service, models: true do - describe "Associations" do it { is_expected.to belong_to :project } it { is_expected.to have_one :service_hook } @@ -176,7 +175,6 @@ describe Service, models: true do ) end - it "returns nil when the property has not been assigned a new value" do service.username = "key_changed" expect(service.bamboo_url_was).to be_nil diff --git a/spec/requests/api/api_helpers_spec.rb b/spec/requests/api/api_helpers_spec.rb index f22db61e744..83025953889 100644 --- a/spec/requests/api/api_helpers_spec.rb +++ b/spec/requests/api/api_helpers_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' describe API::Helpers, api: true do - include API::Helpers include ApiHelpers diff --git a/spec/requests/api/award_emoji_spec.rb b/spec/requests/api/award_emoji_spec.rb index ed78d582bd0..72a6d45f47d 100644 --- a/spec/requests/api/award_emoji_spec.rb +++ b/spec/requests/api/award_emoji_spec.rb @@ -62,7 +62,6 @@ describe API::API, api: true do end end - describe "GET /projects/:id/awardable/:awardable_id/award_emoji/:award_id" do context 'on an issue' do it "returns the award emoji" do diff --git a/spec/requests/api/commit_statuses_spec.rb b/spec/requests/api/commit_statuses_spec.rb index 6668f3543f6..2da01da7fa1 100644 --- a/spec/requests/api/commit_statuses_spec.rb +++ b/spec/requests/api/commit_statuses_spec.rb @@ -11,7 +11,6 @@ describe API::CommitStatuses, api: true do let(:developer) { create_user(:developer) } let(:sha) { commit.id } - describe "GET /projects/:id/repository/commits/:sha/statuses" do let(:get_url) { "/projects/#{project.id}/repository/commits/#{sha}/statuses" } diff --git a/spec/requests/api/doorkeeper_access_spec.rb b/spec/requests/api/doorkeeper_access_spec.rb index 881b818b5e9..5262a623761 100644 --- a/spec/requests/api/doorkeeper_access_spec.rb +++ b/spec/requests/api/doorkeeper_access_spec.rb @@ -7,7 +7,6 @@ describe API::API, api: true do let!(:application) { Doorkeeper::Application.create!(name: "MyApp", redirect_uri: "https://app.com", owner: user) } let!(:token) { Doorkeeper::AccessToken.create! application_id: application.id, resource_owner_id: user.id } - describe "when unauthenticated" do it "returns authentication success" do get api("/user"), access_token: token.token diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb index 437c89c3577..fcea45f19ba 100644 --- a/spec/requests/api/internal_spec.rb +++ b/spec/requests/api/internal_spec.rb @@ -72,6 +72,7 @@ describe API::API, api: true do expect(response).to have_http_status(200) expect(json_response["status"]).to be_truthy + expect(json_response["repository_path"]).to eq(project.repository.path_to_repo) end end @@ -81,6 +82,7 @@ describe API::API, api: true do expect(response).to have_http_status(200) expect(json_response["status"]).to be_truthy + expect(json_response["repository_path"]).to eq(project.repository.path_to_repo) end end end diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb index 39736779986..0404cf31ff7 100644 --- a/spec/requests/api/labels_spec.rb +++ b/spec/requests/api/labels_spec.rb @@ -11,7 +11,6 @@ describe API::API, api: true do project.team << [user, :master] end - describe 'GET /projects/:id/labels' do it 'should return project labels' do get api("/projects/#{project.id}/labels", user) diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb index bacd01f8e74..65c53211dd3 100644 --- a/spec/requests/api/notes_spec.rb +++ b/spec/requests/api/notes_spec.rb @@ -159,7 +159,6 @@ describe API::API, api: true do end end - context "and current user can view the note" do it "should return an issue note by id" do get api("/projects/#{ext_proj.id}/issues/#{ext_issue.id}/notes/#{cross_reference_note.id}", private_user) @@ -221,7 +220,6 @@ describe API::API, api: true do expect(Time.parse(json_response['created_at'])).to be_within(1.second).of(creation_time) end end - end context "when noteable is a Snippet" do @@ -396,5 +394,4 @@ describe API::API, api: true do end end end - end diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 41b5ed9bc33..611dd2a2a88 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -217,7 +217,7 @@ describe API::API, api: true do post api('/projects', user), project - project.each_pair do |k,v| + project.each_pair do |k, v| expect(json_response[k.to_s]).to eq(v) end end @@ -325,7 +325,7 @@ describe API::API, api: true do post api("/projects/user/#{user.id}", admin), project - project.each_pair do |k,v| + project.each_pair do |k, v| next if k == :path expect(json_response[k.to_s]).to eq(v) end @@ -707,7 +707,6 @@ describe API::API, api: true do end describe 'DELETE /projects/:id/fork' do - it "shouldn't be visible to users outside group" do delete api("/projects/#{project_fork_target.id}/fork", user) expect(response).to have_http_status(404) @@ -805,7 +804,7 @@ describe API::API, api: true do context 'when authenticated' do it 'should return an array of projects' do - get api("/projects/search/#{query}",user) + get api("/projects/search/#{query}", user) expect(response).to have_http_status(200) expect(json_response).to be_an Array expect(json_response.size).to eq(6) diff --git a/spec/requests/api/services_spec.rb b/spec/requests/api/services_spec.rb index bf7eaaaaaed..a2446e12804 100644 --- a/spec/requests/api/services_spec.rb +++ b/spec/requests/api/services_spec.rb @@ -87,7 +87,6 @@ describe API::API, api: true do expect(response).to have_http_status(403) end - end end end diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb index f756101c514..684c2cd8e24 100644 --- a/spec/requests/api/settings_spec.rb +++ b/spec/requests/api/settings_spec.rb @@ -6,7 +6,6 @@ describe API::API, 'Settings', api: true do let(:user) { create(:user) } let(:admin) { create(:admin) } - describe "GET /application/settings" do it "should return application settings" do get api("/application/settings", admin) @@ -14,16 +13,23 @@ describe API::API, 'Settings', api: true do expect(json_response).to be_an Hash expect(json_response['default_projects_limit']).to eq(42) expect(json_response['signin_enabled']).to be_truthy + expect(json_response['repository_storage']).to eq('default') end end describe "PUT /application/settings" do + before do + storages = { 'custom' => 'tmp/tests/custom_repositories' } + allow(Gitlab.config.repositories).to receive(:storages).and_return(storages) + end + it "should update application settings" do put api("/application/settings", admin), - default_projects_limit: 3, signin_enabled: false + default_projects_limit: 3, signin_enabled: false, repository_storage: 'custom' expect(response).to have_http_status(200) expect(json_response['default_projects_limit']).to eq(3) expect(json_response['signin_enabled']).to be_falsey + expect(json_response['repository_storage']).to eq('custom') end end end diff --git a/spec/requests/api/todos_spec.rb b/spec/requests/api/todos_spec.rb new file mode 100644 index 00000000000..92a4fa216cd --- /dev/null +++ b/spec/requests/api/todos_spec.rb @@ -0,0 +1,190 @@ +require 'spec_helper' + +describe API::Todos, api: true do + include ApiHelpers + + let(:project_1) { create(:project) } + let(:project_2) { create(:project) } + let(:author_1) { create(:user) } + let(:author_2) { create(:user) } + let(:john_doe) { create(:user, username: 'john_doe') } + let(:merge_request) { create(:merge_request, source_project: project_1) } + let!(:pending_1) { create(:todo, :mentioned, project: project_1, author: author_1, user: john_doe) } + let!(:pending_2) { create(:todo, project: project_2, author: author_2, user: john_doe) } + let!(:pending_3) { create(:todo, project: project_1, author: author_2, user: john_doe) } + let!(:done) { create(:todo, :done, project: project_1, author: author_1, user: john_doe) } + + before do + project_1.team << [john_doe, :developer] + project_2.team << [john_doe, :developer] + end + + describe 'GET /todos' do + context 'when unauthenticated' do + it 'returns authentication error' do + get api('/todos') + + expect(response.status).to eq(401) + end + end + + context 'when authenticated' do + it 'returns an array of pending todos for current user' do + get api('/todos', john_doe) + + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(3) + expect(json_response[0]['id']).to eq(pending_3.id) + expect(json_response[0]['project']).to be_a Hash + expect(json_response[0]['author']).to be_a Hash + expect(json_response[0]['target_type']).to be_present + expect(json_response[0]['target']).to be_a Hash + expect(json_response[0]['target_url']).to be_present + expect(json_response[0]['body']).to be_present + expect(json_response[0]['state']).to eq('pending') + expect(json_response[0]['action_name']).to eq('assigned') + expect(json_response[0]['created_at']).to be_present + end + + context 'and using the author filter' do + it 'filters based on author_id param' do + get api('/todos', john_doe), { author_id: author_2.id } + + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(2) + end + end + + context 'and using the type filter' do + it 'filters based on type param' do + create(:todo, project: project_1, author: author_2, user: john_doe, target: merge_request) + + get api('/todos', john_doe), { type: 'MergeRequest' } + + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + end + end + + context 'and using the state filter' do + it 'filters based on state param' do + get api('/todos', john_doe), { state: 'done' } + + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + end + end + + context 'and using the project filter' do + it 'filters based on project_id param' do + get api('/todos', john_doe), { project_id: project_2.id } + + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + end + end + + context 'and using the action filter' do + it 'filters based on action param' do + get api('/todos', john_doe), { action: 'mentioned' } + + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + end + end + end + end + + describe 'DELETE /todos/:id' do + context 'when unauthenticated' do + it 'returns authentication error' do + delete api("/todos/#{pending_1.id}") + + expect(response.status).to eq(401) + end + end + + context 'when authenticated' do + it 'marks a todo as done' do + delete api("/todos/#{pending_1.id}", john_doe) + + expect(response.status).to eq(200) + expect(pending_1.reload).to be_done + end + end + end + + describe 'DELETE /todos' do + context 'when unauthenticated' do + it 'returns authentication error' do + delete api('/todos') + + expect(response.status).to eq(401) + end + end + + context 'when authenticated' do + it 'marks all todos as done' do + delete api('/todos', john_doe) + + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(3) + expect(pending_1.reload).to be_done + expect(pending_2.reload).to be_done + expect(pending_3.reload).to be_done + end + end + end + + shared_examples 'an issuable' do |issuable_type| + it 'creates a todo on an issuable' do + post api("/projects/#{project_1.id}/#{issuable_type}/#{issuable.id}/todo", john_doe) + + expect(response.status).to eq(201) + expect(json_response['project']).to be_a Hash + expect(json_response['author']).to be_a Hash + expect(json_response['target_type']).to eq(issuable.class.name) + expect(json_response['target']).to be_a Hash + expect(json_response['target_url']).to be_present + expect(json_response['body']).to be_present + expect(json_response['state']).to eq('pending') + expect(json_response['action_name']).to eq('marked') + expect(json_response['created_at']).to be_present + end + + it 'returns 304 there already exist a todo on that issuable' do + create(:todo, project: project_1, author: author_1, user: john_doe, target: issuable) + + post api("/projects/#{project_1.id}/#{issuable_type}/#{issuable.id}/todo", john_doe) + + expect(response.status).to eq(304) + end + + it 'returns 404 if the issuable is not found' do + post api("/projects/#{project_1.id}/#{issuable_type}/123/todo", john_doe) + + expect(response.status).to eq(404) + end + end + + describe 'POST :id/issuable_type/:issueable_id/todo' do + context 'for an issue' do + it_behaves_like 'an issuable', 'issues' do + let(:issuable) { create(:issue, author: author_1, project: project_1) } + end + end + + context 'for a merge request' do + it_behaves_like 'an issuable', 'merge_requests' do + let(:issuable) { merge_request } + end + end + end +end diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index 056256a29f5..e43e3e269bf 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -246,7 +246,6 @@ describe API::API, api: true do end describe "GET /users/sign_up" do - it "should redirect to sign in page" do get "/users/sign_up" expect(response).to have_http_status(302) diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb index bae56334be4..82ab582beac 100644 --- a/spec/requests/git_http_spec.rb +++ b/spec/requests/git_http_spec.rb @@ -350,23 +350,23 @@ describe 'Git HTTP requests', lib: true do end def clone_get(project, options={}) - get "/#{project}/info/refs", { service: 'git-upload-pack' }, auth_env(*options.values_at(:user, :password)) + get "/#{project}/info/refs", { service: 'git-upload-pack' }, auth_env(*options.values_at(:user, :password, :spnego_request_token)) end def clone_post(project, options={}) - post "/#{project}/git-upload-pack", {}, auth_env(*options.values_at(:user, :password)) + post "/#{project}/git-upload-pack", {}, auth_env(*options.values_at(:user, :password, :spnego_request_token)) end def push_get(project, options={}) - get "/#{project}/info/refs", { service: 'git-receive-pack' }, auth_env(*options.values_at(:user, :password)) + get "/#{project}/info/refs", { service: 'git-receive-pack' }, auth_env(*options.values_at(:user, :password, :spnego_request_token)) end def push_post(project, options={}) - post "/#{project}/git-receive-pack", {}, auth_env(*options.values_at(:user, :password)) + post "/#{project}/git-receive-pack", {}, auth_env(*options.values_at(:user, :password, :spnego_request_token)) end - def download(project, user: nil, password: nil) - args = [project, { user: user, password: password }] + def download(project, user: nil, password: nil, spnego_request_token: nil) + args = [project, { user: user, password: password, spnego_request_token: spnego_request_token }] clone_get(*args) yield response @@ -375,8 +375,8 @@ describe 'Git HTTP requests', lib: true do yield response end - def upload(project, user: nil, password: nil) - args = [project, { user: user, password: password }] + def upload(project, user: nil, password: nil, spnego_request_token: nil) + args = [project, { user: user, password: password, spnego_request_token: spnego_request_token }] push_get(*args) yield response @@ -385,11 +385,14 @@ describe 'Git HTTP requests', lib: true do yield response end - def auth_env(user, password) + def auth_env(user, password, spnego_request_token) + env = {} if user && password - { 'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials(user, password) } - else - {} + env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(user, password) + elsif spnego_request_token + env['HTTP_AUTHORIZATION'] = "Negotiate #{::Base64.strict_encode64('opaque_request_token')}" end + + env end end diff --git a/spec/routing/admin_routing_spec.rb b/spec/routing/admin_routing_spec.rb index b5ed8584c8a..8b19936ae6d 100644 --- a/spec/routing/admin_routing_spec.rb +++ b/spec/routing/admin_routing_spec.rb @@ -95,7 +95,6 @@ describe Admin::HooksController, "routing" do it "to #destroy" do expect(delete("/admin/hooks/1")).to route_to('admin/hooks#destroy', id: '1') end - end # admin_logs GET /admin/logs(.:format) admin/logs#show diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb index 538f44e4f3f..620f328a114 100644 --- a/spec/routing/project_routing_spec.rb +++ b/spec/routing/project_routing_spec.rb @@ -165,7 +165,6 @@ describe Projects::TagsController, 'routing' do end end - # project_deploy_keys GET /:project_id/deploy_keys(.:format) deploy_keys#index # POST /:project_id/deploy_keys(.:format) deploy_keys#create # new_project_deploy_key GET /:project_id/deploy_keys/new(.:format) deploy_keys#new diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb index de13c0db5d1..8a8e131c57b 100644 --- a/spec/routing/routing_spec.rb +++ b/spec/routing/routing_spec.rb @@ -253,7 +253,6 @@ describe RootController, 'routing' do end end - # new_user_session GET /users/sign_in(.:format) devise/sessions#new # user_session POST /users/sign_in(.:format) devise/sessions#create # destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy diff --git a/spec/services/destroy_group_service_spec.rb b/spec/services/destroy_group_service_spec.rb index afa89b84175..eca8ddd8ea4 100644 --- a/spec/services/destroy_group_service_spec.rb +++ b/spec/services/destroy_group_service_spec.rb @@ -23,8 +23,8 @@ describe DestroyGroupService, services: true do Sidekiq::Testing.inline! { destroy_group(group, user) } end - it { expect(gitlab_shell.exists?(group.path)).to be_falsey } - it { expect(gitlab_shell.exists?(remove_path)).to be_falsey } + it { expect(gitlab_shell.exists?(project.repository_storage_path, group.path)).to be_falsey } + it { expect(gitlab_shell.exists?(project.repository_storage_path, remove_path)).to be_falsey } end context 'Sidekiq fake' do @@ -33,8 +33,8 @@ describe DestroyGroupService, services: true do Sidekiq::Testing.fake! { destroy_group(group, user) } end - it { expect(gitlab_shell.exists?(group.path)).to be_falsey } - it { expect(gitlab_shell.exists?(remove_path)).to be_truthy } + it { expect(gitlab_shell.exists?(project.repository_storage_path, group.path)).to be_falsey } + it { expect(gitlab_shell.exists?(project.repository_storage_path, remove_path)).to be_truthy } end end diff --git a/spec/services/git_hooks_service_spec.rb b/spec/services/git_hooks_service_spec.rb index 2bb9c3b3db3..6367ac832e8 100644 --- a/spec/services/git_hooks_service_spec.rb +++ b/spec/services/git_hooks_service_spec.rb @@ -16,7 +16,6 @@ describe GitHooksService, services: true do end describe '#execute' do - context 'when receive hooks were successful' do it 'should call post-receive hook' do hook = double(trigger: true) @@ -48,6 +47,5 @@ describe GitHooksService, services: true do end.to raise_error(GitHooksService::PreReceiveError) end end - end end diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index f99ad046f0d..afabeed4a80 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -14,7 +14,6 @@ describe GitPushService, services: true do end describe 'Push branches' do - let(:oldrev) { @oldrev } let(:newrev) { @newrev } @@ -23,7 +22,6 @@ describe GitPushService, services: true do end context 'new branch' do - let(:oldrev) { @blankrev } it { is_expected.to be_truthy } @@ -40,10 +38,21 @@ describe GitPushService, services: true do subject end + + it 'flushes the branches cache' do + expect(project.repository).to receive(:expire_branches_cache) + + subject + end + + it 'flushes the branch count cache' do + expect(project.repository).to receive(:expire_branch_count_cache) + + subject + end end context 'existing branch' do - it { is_expected.to be_truthy } it 'flushes general cached data' do @@ -52,10 +61,21 @@ describe GitPushService, services: true do subject end + + it 'does not flush the branches cache' do + expect(project.repository).not_to receive(:expire_branches_cache) + + subject + end + + it 'does not flush the branch count cache' do + expect(project.repository).not_to receive(:expire_branch_count_cache) + + subject + end end context 'rm branch' do - let(:newrev) { @blankrev } it { is_expected.to be_truthy } @@ -66,6 +86,18 @@ describe GitPushService, services: true do subject end + it 'flushes the branches cache' do + expect(project.repository).to receive(:expire_branches_cache) + + subject + end + + it 'flushes the branch count cache' do + expect(project.repository).to receive(:expire_branch_count_cache) + + subject + end + it 'flushes general cached data' do expect(project.repository).to receive(:expire_cache). with('master', newrev) @@ -187,7 +219,6 @@ describe GitPushService, services: true do end end - describe "Webhooks" do context "execute webhooks" do it "when pushing a branch for the first time" do @@ -314,6 +345,8 @@ describe GitPushService, services: true do it "doesn't close issues when external issue tracker is in use" do allow_any_instance_of(Project).to receive(:default_issues_tracker?). and_return(false) + external_issue_tracker = double(title: 'My Tracker', issue_path: issue.iid) + allow_any_instance_of(Project).to receive(:external_issue_tracker).and_return(external_issue_tracker) # The push still shouldn't create cross-reference notes. expect do @@ -453,7 +486,6 @@ describe GitPushService, services: true do end end - it 'increments the push counter' do expect(housekeeping).to receive(:increment!) diff --git a/spec/services/git_tag_push_service_spec.rb b/spec/services/git_tag_push_service_spec.rb index a63656e6268..a4fcd44882d 100644 --- a/spec/services/git_tag_push_service_spec.rb +++ b/spec/services/git_tag_push_service_spec.rb @@ -11,6 +11,31 @@ describe GitTagPushService, services: true do let(:newrev) { "8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b" } # gitlab-test: git rev-parse refs/tags/v1.1.0 let(:ref) { 'refs/tags/v1.1.0' } + describe "Push tags" do + subject do + service.execute + service + end + + it 'flushes general cached data' do + expect(project.repository).to receive(:expire_cache) + + subject + end + + it 'flushes the tags cache' do + expect(project.repository).to receive(:expire_tags_cache) + + subject + end + + it 'flushes the tag count cache' do + expect(project.repository).to receive(:expire_tag_count_cache) + + subject + end + end + describe "Git Tag Push Data" do before do service.execute diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb index 31b93850c7c..7d5cb876063 100644 --- a/spec/services/merge_requests/refresh_service_spec.rb +++ b/spec/services/merge_requests/refresh_service_spec.rb @@ -175,7 +175,6 @@ describe MergeRequests::RefreshService, services: true do end end - def reload_mrs @merge_request.reload @fork_merge_request.reload diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index 776a6ab5edb..54719cbb8d8 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -95,7 +95,6 @@ describe NotificationService, services: true do notification.new_note(note) end - it { should_not_email(@u_lazy_participant) } end end @@ -377,7 +376,6 @@ describe NotificationService, services: true do end describe '#reassigned_issue' do - before do update_custom_notification(:reassign_issue, @u_guest_custom, project) update_custom_notification(:reassign_issue, @u_custom_global) @@ -566,7 +564,6 @@ describe NotificationService, services: true do end describe '#close_issue' do - before do update_custom_notification(:close_issue, @u_guest_custom, project) update_custom_notification(:close_issue, @u_custom_global) @@ -712,7 +709,6 @@ describe NotificationService, services: true do should_email(subscriber) end - context 'participating' do context 'by assignee' do before do @@ -880,7 +876,6 @@ describe NotificationService, services: true do end describe '#merged_merge_request' do - before do update_custom_notification(:merge_merge_request, @u_guest_custom, project) update_custom_notification(:merge_merge_request, @u_custom_global) diff --git a/spec/services/projects/housekeeping_service_spec.rb b/spec/services/projects/housekeeping_service_spec.rb index 4c5ced7e746..bd4dc6a0f79 100644 --- a/spec/services/projects/housekeeping_service_spec.rb +++ b/spec/services/projects/housekeeping_service_spec.rb @@ -12,7 +12,7 @@ describe Projects::HousekeepingService do it 'enqueues a sidekiq job' do expect(subject).to receive(:try_obtain_lease).and_return(true) - expect(GitlabShellOneShotWorker).to receive(:perform_async).with(:gc, project.path_with_namespace) + expect(GitlabShellOneShotWorker).to receive(:perform_async).with(:gc, project.repository_storage_path, project.path_with_namespace) subject.execute expect(project.pushes_since_gc).to eq(0) diff --git a/spec/services/projects/import_service_spec.rb b/spec/services/projects/import_service_spec.rb index 068c9a1219c..d5d4d7c56ef 100644 --- a/spec/services/projects/import_service_spec.rb +++ b/spec/services/projects/import_service_spec.rb @@ -36,7 +36,7 @@ describe Projects::ImportService, services: true do end it 'succeeds if repository import is successfully' do - expect_any_instance_of(Gitlab::Shell).to receive(:import_repository).with(project.path_with_namespace, project.import_url).and_return(true) + expect_any_instance_of(Gitlab::Shell).to receive(:import_repository).with(project.repository_storage_path, project.path_with_namespace, project.import_url).and_return(true) result = subject.execute @@ -44,7 +44,7 @@ describe Projects::ImportService, services: true do end it 'fails if repository import fails' do - expect_any_instance_of(Gitlab::Shell).to receive(:import_repository).with(project.path_with_namespace, project.import_url).and_raise(Gitlab::Shell::Error.new('Failed to import the repository')) + expect_any_instance_of(Gitlab::Shell).to receive(:import_repository).with(project.repository_storage_path, project.path_with_namespace, project.import_url).and_raise(Gitlab::Shell::Error.new('Failed to import the repository')) result = subject.execute @@ -64,7 +64,7 @@ describe Projects::ImportService, services: true do end it 'succeeds if importer succeeds' do - expect_any_instance_of(Gitlab::Shell).to receive(:import_repository).with(project.path_with_namespace, project.import_url).and_return(true) + expect_any_instance_of(Gitlab::Shell).to receive(:import_repository).with(project.repository_storage_path, project.path_with_namespace, project.import_url).and_return(true) expect_any_instance_of(Gitlab::GithubImport::Importer).to receive(:execute).and_return(true) result = subject.execute @@ -74,7 +74,7 @@ describe Projects::ImportService, services: true do it 'flushes various caches' do expect_any_instance_of(Gitlab::Shell).to receive(:import_repository). - with(project.path_with_namespace, project.import_url). + with(project.repository_storage_path, project.path_with_namespace, project.import_url). and_return(true) expect_any_instance_of(Gitlab::GithubImport::Importer).to receive(:execute). @@ -90,7 +90,7 @@ describe Projects::ImportService, services: true do end it 'fails if importer fails' do - expect_any_instance_of(Gitlab::Shell).to receive(:import_repository).with(project.path_with_namespace, project.import_url).and_return(true) + expect_any_instance_of(Gitlab::Shell).to receive(:import_repository).with(project.repository_storage_path, project.path_with_namespace, project.import_url).and_return(true) expect_any_instance_of(Gitlab::GithubImport::Importer).to receive(:execute).and_return(false) result = subject.execute @@ -100,7 +100,7 @@ describe Projects::ImportService, services: true do end it 'fails if importer raise an error' do - expect_any_instance_of(Gitlab::Shell).to receive(:import_repository).with(project.path_with_namespace, project.import_url).and_return(true) + expect_any_instance_of(Gitlab::Shell).to receive(:import_repository).with(project.repository_storage_path, project.path_with_namespace, project.import_url).and_return(true) expect_any_instance_of(Gitlab::GithubImport::Importer).to receive(:execute).and_raise(Projects::ImportService::Error.new('Github: failed to connect API')) result = subject.execute diff --git a/spec/services/projects/transfer_service_spec.rb b/spec/services/projects/transfer_service_spec.rb index d5aa115a074..57c71544dff 100644 --- a/spec/services/projects/transfer_service_spec.rb +++ b/spec/services/projects/transfer_service_spec.rb @@ -71,5 +71,4 @@ describe Projects::TransferService, services: true do it { expect(private_project.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE) } end end - end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index b43f38ef202..606da1b7605 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -3,11 +3,6 @@ if ENV['SIMPLECOV'] SimpleCov.start :rails end -if ENV['COVERALLS'] - require 'coveralls' - Coveralls.wear_merged! -end - ENV["RAILS_ENV"] ||= 'test' require File.expand_path("../../config/environment", __FILE__) diff --git a/spec/support/jira_service_helper.rb b/spec/support/jira_service_helper.rb index 5ebe095743b..f3ea206f387 100644 --- a/spec/support/jira_service_helper.rb +++ b/spec/support/jira_service_helper.rb @@ -1,5 +1,4 @@ module JiraServiceHelper - def jira_service_settings properties = { "title" => "JIRA tracker", diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index 426bf53f198..9f9ef20f99b 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -80,7 +80,7 @@ module TestEnv end def setup_gitlab_shell - unless File.directory?(Rails.root.join(*%w(tmp tests gitlab-shell))) + unless File.directory?(Gitlab.config.gitlab_shell.path) `rake gitlab:shell:install` end end @@ -127,14 +127,14 @@ module TestEnv def copy_repo(project) base_repo_path = File.expand_path(factory_repo_path_bare) - target_repo_path = File.expand_path(repos_path + "/#{project.namespace.path}/#{project.path}.git") + target_repo_path = File.expand_path(project.repository_storage_path + "/#{project.namespace.path}/#{project.path}.git") FileUtils.mkdir_p(target_repo_path) FileUtils.cp_r("#{base_repo_path}/.", target_repo_path) FileUtils.chmod_R 0755, target_repo_path end def repos_path - Gitlab.config.gitlab_shell.repos_path + Gitlab.config.repositories.storages.default end def backup_path @@ -143,7 +143,7 @@ module TestEnv def copy_forked_repo_with_submodules(project) base_repo_path = File.expand_path(forked_repo_path_bare) - target_repo_path = File.expand_path(repos_path + "/#{project.namespace.path}/#{project.path}.git") + target_repo_path = File.expand_path(project.repository_storage_path + "/#{project.namespace.path}/#{project.path}.git") FileUtils.mkdir_p(target_repo_path) FileUtils.cp_r("#{base_repo_path}/.", target_repo_path) FileUtils.chmod_R 0755, target_repo_path diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb index 25da0917134..d2c056d8e14 100644 --- a/spec/tasks/gitlab/backup_rake_spec.rb +++ b/spec/tasks/gitlab/backup_rake_spec.rb @@ -76,7 +76,6 @@ describe 'gitlab:app namespace rake task' do expect { run_rake_task('gitlab:backup:restore') }.not_to raise_error end end - end # backup_restore task describe 'backup_create' do @@ -98,67 +97,107 @@ describe 'gitlab:app namespace rake task' do @backup_tar = tars_glob.first end - before do - create_backup - end - - after do - FileUtils.rm(@backup_tar) - end + context 'tar creation' do + before do + create_backup + end - context 'archive file permissions' do - it 'should set correct permissions on the tar file' do - expect(File.exist?(@backup_tar)).to be_truthy - expect(File::Stat.new(@backup_tar).mode.to_s(8)).to eq('100600') + after do + FileUtils.rm(@backup_tar) end - context 'with custom archive_permissions' do - before do - allow(Gitlab.config.backup).to receive(:archive_permissions).and_return(0651) - # We created a backup in a before(:all) so it got the default permissions. - # We now need to do some work to create a _new_ backup file using our stub. - FileUtils.rm(@backup_tar) - create_backup + context 'archive file permissions' do + it 'should set correct permissions on the tar file' do + expect(File.exist?(@backup_tar)).to be_truthy + expect(File::Stat.new(@backup_tar).mode.to_s(8)).to eq('100600') end - it 'uses the custom permissions' do - expect(File::Stat.new(@backup_tar).mode.to_s(8)).to eq('100651') + context 'with custom archive_permissions' do + before do + allow(Gitlab.config.backup).to receive(:archive_permissions).and_return(0651) + # We created a backup in a before(:all) so it got the default permissions. + # We now need to do some work to create a _new_ backup file using our stub. + FileUtils.rm(@backup_tar) + create_backup + end + + it 'uses the custom permissions' do + expect(File::Stat.new(@backup_tar).mode.to_s(8)).to eq('100651') + end end end - end - it 'should set correct permissions on the tar contents' do - tar_contents, exit_status = Gitlab::Popen.popen( - %W{tar -tvf #{@backup_tar} db uploads.tar.gz repositories builds.tar.gz artifacts.tar.gz lfs.tar.gz registry.tar.gz} - ) - expect(exit_status).to eq(0) - expect(tar_contents).to match('db/') - expect(tar_contents).to match('uploads.tar.gz') - expect(tar_contents).to match('repositories/') - expect(tar_contents).to match('builds.tar.gz') - expect(tar_contents).to match('artifacts.tar.gz') - expect(tar_contents).to match('lfs.tar.gz') - expect(tar_contents).to match('registry.tar.gz') - expect(tar_contents).not_to match(/^.{4,9}[rwx].* (database.sql.gz|uploads.tar.gz|repositories|builds.tar.gz|artifacts.tar.gz|registry.tar.gz)\/$/) - end + it 'should set correct permissions on the tar contents' do + tar_contents, exit_status = Gitlab::Popen.popen( + %W{tar -tvf #{@backup_tar} db uploads.tar.gz repositories builds.tar.gz artifacts.tar.gz lfs.tar.gz registry.tar.gz} + ) + expect(exit_status).to eq(0) + expect(tar_contents).to match('db/') + expect(tar_contents).to match('uploads.tar.gz') + expect(tar_contents).to match('repositories/') + expect(tar_contents).to match('builds.tar.gz') + expect(tar_contents).to match('artifacts.tar.gz') + expect(tar_contents).to match('lfs.tar.gz') + expect(tar_contents).to match('registry.tar.gz') + expect(tar_contents).not_to match(/^.{4,9}[rwx].* (database.sql.gz|uploads.tar.gz|repositories|builds.tar.gz|artifacts.tar.gz|registry.tar.gz)\/$/) + end - it 'should delete temp directories' do - temp_dirs = Dir.glob( - File.join(Gitlab.config.backup.path, '{db,repositories,uploads,builds,artifacts,lfs,registry}') - ) + it 'should delete temp directories' do + temp_dirs = Dir.glob( + File.join(Gitlab.config.backup.path, '{db,repositories,uploads,builds,artifacts,lfs,registry}') + ) + + expect(temp_dirs).to be_empty + end - expect(temp_dirs).to be_empty + context 'registry disabled' do + let(:enable_registry) { false } + + it 'should not create registry.tar.gz' do + tar_contents, exit_status = Gitlab::Popen.popen( + %W{tar -tvf #{@backup_tar}} + ) + expect(exit_status).to eq(0) + expect(tar_contents).not_to match('registry.tar.gz') + end + end end - context 'registry disabled' do - let(:enable_registry) { false } + context 'multiple repository storages' do + let(:project_a) { create(:project, repository_storage: 'default') } + let(:project_b) { create(:project, repository_storage: 'custom') } + + before do + FileUtils.mkdir('tmp/tests/default_storage') + FileUtils.mkdir('tmp/tests/custom_storage') + storages = { + 'default' => 'tmp/tests/default_storage', + 'custom' => 'tmp/tests/custom_storage' + } + allow(Gitlab.config.repositories).to receive(:storages).and_return(storages) + + # Create the projects now, after mocking the settings but before doing the backup + project_a + project_b + + # We only need a backup of the repositories for this test + ENV["SKIP"] = "db,uploads,builds,artifacts,lfs,registry" + create_backup + end + + after do + FileUtils.rm_rf('tmp/tests/default_storage') + FileUtils.rm_rf('tmp/tests/custom_storage') + FileUtils.rm(@backup_tar) + end - it 'should not create registry.tar.gz' do + it 'should include repositories in all repository storages' do tar_contents, exit_status = Gitlab::Popen.popen( - %W{tar -tvf #{@backup_tar}} + %W{tar -tvf #{@backup_tar} repositories} ) expect(exit_status).to eq(0) - expect(tar_contents).not_to match('registry.tar.gz') + expect(tar_contents).to match("repositories/#{project_a.path_with_namespace}.bundle") + expect(tar_contents).to match("repositories/#{project_b.path_with_namespace}.bundle") end end end # backup_create task diff --git a/spec/views/projects/builds/show.html.haml_spec.rb b/spec/views/projects/builds/show.html.haml_spec.rb new file mode 100644 index 00000000000..cd18d19ef5e --- /dev/null +++ b/spec/views/projects/builds/show.html.haml_spec.rb @@ -0,0 +1,37 @@ +require 'spec_helper' + +describe 'projects/builds/show' do + include Devise::TestHelpers + + let(:build) { create(:ci_build) } + let(:project) { build.project } + + before do + assign(:build, build) + assign(:project, project) + + allow(view).to receive(:can?).and_return(true) + end + + context 'when build is running' do + before do + build.run! + render + end + + it 'does not show retry button' do + expect(rendered).not_to have_link('Retry') + end + end + + context 'when build is not running' do + before do + build.success! + render + end + + it 'shows retry button' do + expect(rendered).to have_link('Retry') + end + end +end diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb index b8e73682c91..20b1a343c27 100644 --- a/spec/workers/post_receive_spec.rb +++ b/spec/workers/post_receive_spec.rb @@ -91,6 +91,6 @@ describe PostReceive do end def pwd(project) - File.join(Gitlab.config.gitlab_shell.repos_path, project.path_with_namespace) + File.join(Gitlab.config.repositories.storages.default, project.path_with_namespace) end end diff --git a/spec/workers/project_cache_worker_spec.rb b/spec/workers/project_cache_worker_spec.rb index 7e59bd2fced..5785a6a06ff 100644 --- a/spec/workers/project_cache_worker_spec.rb +++ b/spec/workers/project_cache_worker_spec.rb @@ -7,7 +7,6 @@ describe ProjectCacheWorker do describe '#perform' do it 'updates project cache data' do - expect_any_instance_of(Repository).to receive(:size) expect_any_instance_of(Repository).to receive(:commit_count) diff --git a/spec/workers/repository_fork_worker_spec.rb b/spec/workers/repository_fork_worker_spec.rb index 4ef05eb29d2..5f762282b5e 100644 --- a/spec/workers/repository_fork_worker_spec.rb +++ b/spec/workers/repository_fork_worker_spec.rb @@ -14,6 +14,7 @@ describe RepositoryForkWorker do describe "#perform" do it "creates a new repository from a fork" do expect(shell).to receive(:fork_repository).with( + project.repository_storage_path, project.path_with_namespace, fork_project.namespace.path ).and_return(true) @@ -25,9 +26,11 @@ describe RepositoryForkWorker do end it 'flushes various caches' do - expect(shell).to receive(:fork_repository). - with(project.path_with_namespace, fork_project.namespace.path). - and_return(true) + expect(shell).to receive(:fork_repository).with( + project.repository_storage_path, + project.path_with_namespace, + fork_project.namespace.path + ).and_return(true) expect_any_instance_of(Repository).to receive(:expire_emptiness_caches). and_call_original |