diff --git a/.rubocop.yml b/.rubocop.yml index dbdabbb9d4..cd13f58151 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 eb5a5f7fcf..8efdcd2453 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 4a36342fca..fd2a01863f 100644 --- a/GITLAB_SHELL_VERSION +++ b/GITLAB_SHELL_VERSION @@ -1 +1 @@ -3.0.0 +3.1.0 diff --git a/Gemfile b/Gemfile index 52de9ef981..d622af6b0a 100644 --- a/Gemfile +++ b/Gemfile @@ -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 4c5350ba63..45cb327168 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 b6dbf2d0cc..20fe5a5cc2 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 4f73d215b8..b76d214790 100644 --- a/app/assets/javascripts/flash.js.coffee +++ b/app/assets/javascripts/flash.js.coffee @@ -4,11 +4,19 @@ class @Flash @flash.html("") innerDiv = $('
', - class: "flash-#{type}", - text: message + class: "flash-#{type}" ) innerDiv.appendTo(".flash-container") + textDiv = $("
", + 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 190bb38504..b7d040bae8 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 b0edc89564..eb046eb2ef 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 c03877e9b0..3319a67a79 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 de8eebcd0b..83de584f2d 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 1bfd021399..a951a2b97f 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 fd8eaa8a69..5d3273ea64 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 c74682dfef..367c7d0194 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 87f8a17659..211a9af234 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 de534d2842..85bbf70e18 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 101faf5917..3d79f4400e 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 89ce1b2df2..817c298292 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 99c9e81ddb..5b61270daa 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 f4eda864aa..5f65dd3aff 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 a6db4690df..94b5aaa71d 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 4e85b6b4cf..cbfc458141 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 87986fdf8b..4c9c6362ff 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 bf20c5305a..bc65dcc33d 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 3c67370b66..e4c7300882 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 8bf71a1adb..aa894fde36 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 52dc396af6..52682ef9dc 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 7b66ad3f92..3da44b9b88 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 2c49fe3833..9fc41a1253 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 93a7ace353..7e8597a5eb 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 1830039085..99b10b2f9b 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 67bf4190e7..9c1b0eb20f 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 eecbe380c9..a4c4ad2302 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 e0de31f225..8d0de158f9 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 94bb108c5f..58964a0e65 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 f907d63258..62c3fa8de5 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 8b8df68073..b6e80762e3 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 b181c47bae..34318391dd 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 6ba32d3340..3435a11896 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 dc1a18f8d4..8267b14941 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 6d2901a24a..6d0a7ee103 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 7ec1e73b3b..607fe9c7fe 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 2b1f50fd01..12e0d5a841 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 58a00f88af..7806d9e4cc 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 55313fd835..6e580c62cc 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 6b617e1730..7c14053801 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 8466d0aa0b..2843ad96ef 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 8231ce49fa..294b7e92b8 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 0000000000..f5b0aa7549 --- /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 5074e64576..5e9f583710 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 ec106418f2..c70cd19b58 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 b401c8385b..e85ba76887 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 e4e8b934bc..22387d6645 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 d91e3332e4..f312a7ccca 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 d2f94d4ae6..f9fc525df6 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 f5950879cc..ba1f2ae407 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 d914b0b26e..5fa6eacd23 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 2b0bec3313..c11f8e6884 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 d6f55885dd..acb6f5a299 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 c70c719e33..a8be7004ee 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 3c5859194b..60abd47409 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 57161397e2..44db3d977f 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 e9d3a82ba1..f39afc61ce 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 53d9aa588a..5ebc8f0c99 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 e0c8454a99..2bd7f19803 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 da19462f26..8b52cc824c 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) + # 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) - # 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 + 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 a2aee2f925..345041a6ad 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 8db500a521..c2bb117eb0 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 73ded09c16..ae96f00a70 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 260f603095..81af55aa29 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 8f2db46a7b..63a5ed1448 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 966dbc41d7..5e4dd101c5 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 0ff4f4c8dd..23e5b16221 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} #{ref} " - message << "of #{project.name_with_namespace.gsub!(/\s/,'')} " + message << "of #{project.name_with_namespace.gsub!(/\s/, '')} " message << "(Compare changes)" 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 87ecb3b8b8..d1df6d0292 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 beda89d396..27bf08bf7d 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 11cce3e056..f634e0772c 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 0865b979ce..0b70093064 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 25d82929c0..a255710f57 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 2a6a3b086c..11ecb281a5 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 2792fa9b9a..3ba67078d4 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 767d6366c7..5036a3e300 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 e06a6f2f47..f029db72d4 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 772f5c5fff..089b0f527e 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 bc93ba2552..bc3606a14c 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 12edfb2d67..870f570518 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 2414966505..e457212508 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 f09072975c..882606e38d 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 6386f57fb0..f06a3d44c1 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 43db29315a..a47df22f1b 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 80c7193efc..3f507d5c40 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 9159ec0895..163ebf26c8 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 03b57dea51..bc7f8bf433 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 4e8fa0818b..b868d2e7e8 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 25eb13ef09..0c0f68d169 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 4c0a2c6b4d..14317ea65c 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 28085b3108..046a1d641a 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 30ab071716..c1f70bc186 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -310,6 +310,15 @@ .col-sm-10 = 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 diff --git a/app/views/admin/background_jobs/show.html.haml b/app/views/admin/background_jobs/show.html.haml index 654d261aa9..4f680b507c 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 efd5b12cfe..1e60205f91 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 4682016a88..a2ac407c15 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 4f1996ef7a..94aa5f5a94 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 50770465f0..522153b37e 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 7b8407f915..e79303240f 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 5ddc3b9ea8..676812121d 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 4822cb693c..7d2eb42322 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 461d588415..82d3169c6f 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 36b21eefde..64893b38c5 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 5eff77aff2..a53876d675 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 @@ -39,6 +39,9 @@ %li %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 3ef2f20b58..6956e5ab79 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 d0a696da64..21bb99a792 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 d6acade84f..90f362c052 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 a0a6762edc..a83eb7e88b 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 57bc91ea5a..57601ae9be 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 dfebf7768d..804ad88468 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 0000000000..435ed7bd4c --- /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 repo 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 96b3848542..12e7ed0e79 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 3a24b09ab7..bf9a7ecb78 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 dcef427cda..9e65d94186 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 46ad155935..0000000000 --- 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 86ea08dd22..540efa4780 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 e0ca2a3109..434d8644b8 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 ed670dae88..0ab78a39cf 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 e0367c4027..77b405f1f3 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 181547316a..a131289ee9 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 4e2702c2e4..d1c468c469 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 51ca4eb903..9a44ba9497 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 b22285c11e..e9ff8e90dd 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 f4ec7b767f..28a50e7031 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 a03f117291..5242021243 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 4c15e2759d..53c62ef234 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 e695d3ae36..6be4273b6a 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 0daffe68f6..65db8af494 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 6d97f552a8..fcfcae0be2 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 9f7e2a361f..a985b442b2 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 a8a8caf728..2cd8d03e30 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 cd876b5ea6..7ce4c1e555 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 aa4d69550e..db66a0edbd 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 9f948d41dd..ace275c689 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 b0e0bdfff5..ad2bfbec91 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 86295a3d01..8f6805268d 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 3ca30b4ba6..091af4df4a 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 8a73b07735..05f33b78a4 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 a5e163b91e..af0046886f 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 b70693eeb6..28b475d5c2 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 840b57c2e6..77370c14de 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 a2026c41d0..9031f01b49 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 15f0d85194..f6e81af263 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 4ca1f58ac5..c375bb6dd1 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 2abcfcdd7b..bf5360b4de 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 4f8abcdc8e..c32cb122c2 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 817bf9b3f6..233538bb48 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 6caf7230f3..b8811a28dd 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 630ee35b70..4c0b14e2c4 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 81d9f391c1..9c10acd4cb 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 76f9b1ecd7..5cebb538cf 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 87028ececd..5507a05f6c 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 480e8ba6c8..35dcdccc92 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 e4bd2bdc26..40b39e850b 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 f3327ca9e6..09035a7cf2 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 d947f10551..f7604e48f8 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 436a2c5e17..293f2b71d6 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 8cca0039b4..45a8c1add3 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 01c8dc5ff9..75b79b837e 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 75e1a3c109..325eca7286 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 c6dc1e4ab3..51d93e8cde 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,13 +301,20 @@ 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 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 # @@ -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 0000000000..3ba9e36c56 --- /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 021bdb1125..73977341b7 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 751fccead0..7454c33c9d 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 75f89d524e..44601f2b2b 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 30d05f1615..69052c029f 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 7a2b9a7f6c..593c14a289 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 d256a16d42..df4a933e22 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 bdfb16a66b..1572656b8c 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_\-]+(? 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 288f7f9ee6..d1e6c54c52 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 708fc691f6..3ced787b23 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 2930f615fc..f60b0d0ebc 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 b5152311f2..741c5a2958 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 0000000000..29e7366441 --- /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 27bc21c292..c134106bfd 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 8a38937062..2b305cb5c9 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 index e9641cb4f8..5c9b510ba9 100644 Binary files a/doc/workflow/add-user/img/access_requests_management.png and b/doc/workflow/add-user/img/access_requests_management.png differ diff --git a/doc/workflow/groups.md b/doc/workflow/groups.md index 1a316e8097..9b50286b17 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 index ffede8e9bd..5202434f00 100644 Binary files a/doc/workflow/groups/access_requests_management.png and b/doc/workflow/groups/access_requests_management.png differ diff --git a/doc/workflow/groups/request_access_button.png b/doc/workflow/groups/request_access_button.png index ff0ac8747a..0eec5cb937 100644 Binary files a/doc/workflow/groups/request_access_button.png and b/doc/workflow/groups/request_access_button.png differ diff --git a/doc/workflow/groups/withdraw_access_request_button.png b/doc/workflow/groups/withdraw_access_request_button.png index 99d7a326ed..b7de830a78 100644 Binary files a/doc/workflow/groups/withdraw_access_request_button.png and b/doc/workflow/groups/withdraw_access_request_button.png differ diff --git a/doc/workflow/importing/import_projects_from_github.md b/doc/workflow/importing/import_projects_from_github.md index a7dfac2c12..a2b2a4b88f 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 56b4a639c0..8ddafb6a7a 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 31f8924c38..727a6a7137 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 cb6fa8a47d..2b4a5ab086 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 483370f41c..4fa7d7c656 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 db1387763d..b6f1d417e2 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 0ead83d693..6b56a77b83 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 439363e6f1..35f166c7c0 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 9077184790..b8da5e6435 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 c6572cf386..b5fd24d246 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 cf99987957..32e29ffad1 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 edc08cf098..ab3f0ca7ae 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 c3fff8b2f8..3d7d67510a 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 985590312e..c4fa1838b5 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 231840148d..d467eb9d47 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 086d8511e8..d36047acd1 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 5a23a18fe9..8cc4368b5c 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 ab9b7c602b..dbe5bb08d3 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 1d361569d5..b32503e851 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 132043cf3f..7a0cb7c99f 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 ccca65cbe1..6bb70bc8bc 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 b703da0557..6a0b3e7d13 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 5a22d14988..0cc1edd65c 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 203f04a625..fc8598daa3 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 for project # diff --git a/lib/api/tags.rb b/lib/api/tags.rb index 3e1ed3fe5c..7b675e05fb 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 0000000000..2a6bfa98ca --- /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 7b91215d50..b9773f98d7 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 81d6627113..d77a5e3ff0 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 8aa6f8f124..f0fb6084a3 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 5351272f42..4042e9a4c2 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 2d6f34c9cd..bf058241cd 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 62a79c62e2..536b478979 100644 --- a/lib/banzai/filter/syntax_highlight_filter.rb +++ b/lib/banzai/filter/syntax_highlight_filter.rb @@ -27,12 +27,17 @@ module Banzai highlighted = "
#{code}
" 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 1bb6d6bba8..269d5bf74f 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 d47ddfda4b..3c974f7317 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 5270108ef0..1d7126a432 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 1b80be112a..cee664b895 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 37f4c34054..c3064163e0 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 0b9c2e730f..1a22ad9acf 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 51b1df9ecb..c94bfc0e65 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 ab7b811c5d..478f145bfe 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 3e3986d638..34e0143a82 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 28c34429c1..54b46e5d23 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 522dd2b942..59a2367b65 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 d325eca6d9..043f10d96a 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( + @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 + + 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'] }) ) - - if access_token - ::Octokit.auto_paginate = false - - @api = ::Octokit::Client.new( - access_token: access_token, - api_endpoint: github_options[:site], - connection_options: { - ssl: { verify: config['verify_ssl'] } - } - ) - end 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 2286ac8829..730978d502 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 99cf85d9a3..588647e5ad 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 164ab6238c..05f4ad527a 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 595b20a09b..8f66f48cbf 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 c569a35a48..b459054c19 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 89388d1984..77bb3ca658 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 dd71b92c52..0ac6ff01e3 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 19defd8f03..15f5dd3103 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 92bf7e0a2f..9824df3f27 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 6aff05b886..5d6de8bc47 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 7292e9d971..d6f4fa5751 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 cf5c62c5e3..abfc694b87 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 f7f73dc934..9b642d740b 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 948d43582c..59a05411fe 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 8684b4636e..b75ae512d9 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_(?\d+)\.(?\d+)/) diff --git a/lib/gitlab/lfs/response.rb b/lib/gitlab/lfs/response.rb index e3ed2f6791..811363405a 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 36e5c2670b..7d6911a1ab 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 746ec28333..4e2f8ed558 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 c84c68f96f..ffad5e17c7 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_\-\.]*(? :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 ab0028d660..b7cbdc6cd7 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 4753f00c26..dbdd4e977e 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 - - project = Project.find_with_namespace(path) - - if project - puts " * #{project.name} (#{repo_path}) exists" - else - user = User.admins.reorder("id").first - - 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) - end - end - # set project group - project_params[:namespace_id] = group.id + if path.end_with?('.wiki') + puts " * Skipping wiki repo" + next end - project = Projects::CreateService.new(user, project_params).execute + project = Project.find_with_namespace(path) - if project.persisted? - puts " * Created #{project.name} (#{repo_path})".color(:green) - project.update_repository_size - project.update_commit_count + if project + puts " * #{project.name} (#{repo_path}) exists" else - puts " * Failed trying to create #{project.name} (#{repo_path})".color(:red) - puts " Errors: #{project.errors.messages}".color(:red) + user = User.admins.reorder("id").first + + 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) + end + end + # set project group + project_params[:namespace_id] = group.id + end + + 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) + end end end end diff --git a/lib/tasks/gitlab/info.rake b/lib/tasks/gitlab/info.rake index 352b566df2..fe43d40e6d 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 c7596e7abc..ffcc76e549 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 b1648a4602..c85ebdf861 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 d0c019044b..ab96b1d359 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 c5666d49e6..21c0e5f1d4 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 d4291f012d..41dee5fdc0 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 0000000000..d9247a1f7e --- /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 0000000000..97ee8b1104 --- /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 0000000000..3160a784a0 --- /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 0000000000..7922e19768 --- /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 10824c20c8..8bd210cbc3 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 ddc54108a7..c34475976c 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 c55a3c2820..51d5952685 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 2dc9adfd60..18148acde3 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 f59d493715..644de308c6 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 70ed8f3a62..f66bcb8099 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 ab1dd34ed5..3492b6ffbb 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 74c050f48f..eff74e1286 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 29aaceb230..5e2a8cf384 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 ee905d11fb..2fe3c26352 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 4e3a2bdb19..1cc050247c 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 d60579030c..1b1b1bdf52 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 8d6f486efd..54a2d3d946 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 f426e27afe..7fc20cd555 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 31633817d5..7964951ae9 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 2d297776cb..2f82fafc13 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 - expect(assigned_project).to have_content(@project2.path) + 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 + + 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 dbc1d829b6..f4e5c26b51 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 cf86e2c85e..c2e0612aef 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 7852c39fee..a89ac09f23 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 321c9bad7d..10d3713f19 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 4944301c93..d1a6a98ab7 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 4bcb105b17..006a06b823 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 5065dfb849..d51c9abea1 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 15c381c0f5..fcdf7870f3 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 f88c0616b5..1b4ff6b6f1 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 c5fb0fc783..9d66f76ef5 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 index 1fd04416d9..7bb0d26b21 100644 Binary files a/spec/features/projects/import_export/test_project_export.tar.gz and b/spec/features/projects/import_export/test_project_export.tar.gz differ 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 461f173792..81b0c991d4 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 aa2d906fa2..f7fcd9b673 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 af420c170e..f2fe3ef364 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 b9e63a7152..85923f0a19 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 71b783b727..35fcef7a71 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 cc9aee802f..75a9334262 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 db986683db..6c5ee93970 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 4229e82b44..a752c1d723 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 f0990118e3..0f30f56253 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 cf11604039..b5a94fe038 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 fdd3849816..fbe09b28b3 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 810016c965..28bdc18e84 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 f75fdb739f..7b2155e9a4 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 0000000000..08a9350325 --- /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 09e0bbfd00..604204cca0 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 5e7594170c..db3ad1b99e 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 0000000000..5178bd130f --- /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 1bcae8a27d..47b4e43182 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 4bb149f25f..14c8df954a 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 8d6ce114aa..a005b4990e 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 72bc6a0b70..51c89ac488 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 9c6b4ea508..97f2e97b06 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 2ca9f554b0..ec658668c6 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 736bf78720..32ca823984 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) { 'ascii' } let(:context) { {} } let(:html) { 'H2O' } 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 0f3852b172..00a110e31f 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 fd869f48b5..6e5ba21138 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 711a3e1c7d..abc93e1b44 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 0000000000..004341ffd0 --- /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 ea5c31011f..198ff977f2 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) { %{abc 'def'}.html_safe } diff --git a/spec/lib/gitlab/fogbugz_import/client_spec.rb b/spec/lib/gitlab/fogbugz_import/client_spec.rb index 2dc71be025..252cd4c55c 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 9b3a0e3a75..9b7986fa12 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 7c21cbe96d..3b023a3544 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 e94440a7fb..87593e32db 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 647631271e..54f85f8cff 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 f135a285df..6d5aa0d04a 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 403bd582ef..0b30e8c9b0 100644 --- a/spec/lib/gitlab/import_export/project.json +++ b/spec/lib/gitlab/import_export/project.json @@ -1,209 +1,39 @@ { - "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", - "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-04-12T13:08:26.006Z", - "updated_at": "2016-04-12T13:08:26.006Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": "", - "noteable_id": 40, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Administrator" - } - }, - { - "id": 338, - "note": "Fugit in aliquid voluptas dolor.", - "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-03-22T15:19:59.213Z", - "updated_at": "2016-03-22T15:19:59.213Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 40, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Administrator" - } - }, - { - "id": 337, - "note": "Occaecati consequatur facilis doloribus omnis hic placeat nihil.", - "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:19:59.186Z", - "updated_at": "2016-03-22T15:19:59.186Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 40, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } - }, - { - "id": 336, - "note": "Nostrum et et est repudiandae non dolores voluptatem.", - "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:19:59.156Z", - "updated_at": "2016-03-22T15:19:59.156Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 40, - "system": false, - "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 - }, - "line_code": null, - "commit_id": null, - "noteable_id": 40, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } - }, - { - "id": 334, - "note": "Non blanditiis voluptatem sit earum accusantium distinctio voluptas officiis.", - "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:19:59.101Z", - "updated_at": "2016-03-22T15:19:59.101Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 40, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } - }, - { - "id": 333, - "note": "Nesciunt non dolorem similique nam ipsa et.", - "noteable_type": "Issue", - "author_id": 22, - "created_at": "2016-03-22T15:19:59.075Z", - "updated_at": "2016-03-22T15:19:59.075Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 40, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 0" - } - }, - { - "id": 332, - "note": "Sed aut fugit et officiis dolor.", - "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:19:59.047Z", - "updated_at": "2016-03-22T15:19:59.047Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 40, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 2" - } - }, - { - "id": 331, - "note": "Officiis iste eum recusandae suscipit consequatur consequatur.", + "id": 351, + "note": "Quo reprehenderit aliquam qui dicta impedit cupiditate eligendi.", "noteable_type": "Issue", "author_id": 26, - "created_at": "2016-03-22T15:19:59.015Z", - "updated_at": "2016-03-22T15:19:59.015Z", + "created_at": "2016-06-14T15:02:47.770Z", + "updated_at": "2016-06-14T15:02:47.770Z", "project_id": 5, "attachment": { "url": null @@ -214,186 +44,210 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { + "author": { "name": "User 4" - } + }, + "events": [ + + ] + }, + { + "id": 352, + "note": "Est reprehenderit quas aut aspernatur autem recusandae voluptatem.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 40, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 3" + }, + "events": [ + + ] + }, + { + "id": 353, + "note": "Perspiciatis suscipit voluptates in eius nihil.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 40, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 0" + }, + "events": [ + + ] + }, + { + "id": 354, + "note": "Aut vel voluptas corrupti nisi provident laboriosam magnam aut.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 40, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] + }, + { + "id": 355, + "note": "Officia dolore consequatur in saepe cum magni.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 40, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] + }, + { + "id": 356, + "note": "Cum ipsum rem voluptas eaque et ea.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 40, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] + }, + { + "id": 357, + "note": "Recusandae excepturi asperiores suscipit autem nostrum.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 40, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] + }, + { + "id": 358, + "note": "Et hic est id similique et non nesciunt voluptate.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 40, + "system": false, + "st_diff": null, + "updated_by_id": null, + "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.", - "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-03-22T15:19:59.469Z", - "updated_at": "2016-03-22T15:19:59.469Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 39, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Administrator" - } - }, - { - "id": 345, - "note": "Voluptatibus et qui quis id sed necessitatibus quos.", - "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:19:59.438Z", - "updated_at": "2016-03-22T15:19:59.438Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 39, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } - }, - { - "id": 344, - "note": "Aperiam possimus ipsam quibusdam in.", - "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:19:59.410Z", - "updated_at": "2016-03-22T15:19:59.410Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 39, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Julius Moore" - } - }, - { - "id": 343, - "note": "Ad vel hic molestiae tempora.", - "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:19:59.379Z", - "updated_at": "2016-03-22T15:19:59.379Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 39, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } - }, - { - "id": 342, - "note": "Vel magnam sed quidem aut molestiae facilis alias.", - "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:19:59.348Z", - "updated_at": "2016-03-22T15:19:59.348Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 39, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } - }, - { - "id": 341, - "note": "Veritatis dolorum aut qui quod.", - "noteable_type": "Issue", - "author_id": 22, - "created_at": "2016-03-22T15:19:59.319Z", - "updated_at": "2016-03-22T15:19:59.319Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 39, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 0" - } - }, - { - "id": 340, - "note": "Illum at cumque dolorum et quia.", - "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:19:59.289Z", - "updated_at": "2016-03-22T15:19:59.289Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 39, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 2" - } - }, - { - "id": 339, - "note": "Fugiat et error molestiae cumque quos aperiam.", + "id": 359, + "note": "Quo eius velit quia et id quam.", "noteable_type": "Issue", "author_id": 26, - "created_at": "2016-03-22T15:19:59.255Z", - "updated_at": "2016-03-22T15:19:59.255Z", + "created_at": "2016-06-14T15:02:48.009Z", + "updated_at": "2016-06-14T15:02:48.009Z", "project_id": 5, "attachment": { "url": null @@ -404,186 +258,210 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { + "author": { "name": "User 4" - } + }, + "events": [ + + ] + }, + { + "id": 360, + "note": "Nulla commodi ratione cumque id autem.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 39, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 3" + }, + "events": [ + + ] + }, + { + "id": 361, + "note": "Illum non ea sed dolores corrupti.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 39, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 0" + }, + "events": [ + + ] + }, + { + "id": 362, + "note": "Facere dolores ipsum dolorum maiores omnis occaecati ab.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 39, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] + }, + { + "id": 363, + "note": "Quod laudantium similique sint aut est ducimus.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 39, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] + }, + { + "id": 364, + "note": "Aut omnis eos esse incidunt vero reiciendis.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 39, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] + }, + { + "id": 365, + "note": "Beatae dolore et doloremque asperiores sunt.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 39, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] + }, + { + "id": 366, + "note": "Doloribus ipsam ex delectus rerum libero recusandae modi repellendus.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 39, + "system": false, + "st_diff": null, + "updated_by_id": null, + "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.", - "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-03-22T15:19:59.708Z", - "updated_at": "2016-03-22T15:19:59.708Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 38, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Administrator" - } - }, - { - "id": 353, - "note": "Quia hic sed ratione eos voluptate dolor occaecati dolorem.", - "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:19:59.680Z", - "updated_at": "2016-03-22T15:19:59.680Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 38, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } - }, - { - "id": 352, - "note": "Commodi sint voluptatem est aut.", - "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:19:59.650Z", - "updated_at": "2016-03-22T15:19:59.650Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 38, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Julius Moore" - } - }, - { - "id": 351, - "note": "Et quibusdam voluptatibus dolores aut quam architecto optio.", - "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:19:59.622Z", - "updated_at": "2016-03-22T15:19:59.622Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 38, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } - }, - { - "id": 350, - "note": "Fugit natus explicabo sed pariatur et quasi autem.", - "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:19:59.590Z", - "updated_at": "2016-03-22T15:19:59.590Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 38, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } - }, - { - "id": 349, - "note": "Corporis commodi eos quia optio sunt corrupti.", - "noteable_type": "Issue", - "author_id": 22, - "created_at": "2016-03-22T15:19:59.562Z", - "updated_at": "2016-03-22T15:19:59.562Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 38, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 0" - } - }, - { - "id": 348, - "note": "Occaecati nostrum hic dolor tenetur aliquid maxime animi.", - "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:19:59.536Z", - "updated_at": "2016-03-22T15:19:59.536Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 38, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 2" - } - }, - { - "id": 347, - "note": "Inventore ullam sed repellendus laudantium itaque et quia.", + "id": 367, + "note": "Accusantium fugiat et eaque quisquam esse corporis.", "noteable_type": "Issue", "author_id": 26, - "created_at": "2016-03-22T15:19:59.506Z", - "updated_at": "2016-03-22T15:19:59.506Z", + "created_at": "2016-06-14T15:02:48.235Z", + "updated_at": "2016-06-14T15:02:48.235Z", "project_id": 5, "attachment": { "url": null @@ -594,186 +472,210 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { + "author": { "name": "User 4" - } + }, + "events": [ + + ] + }, + { + "id": 368, + "note": "Ea labore eum nam qui laboriosam.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 38, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 3" + }, + "events": [ + + ] + }, + { + "id": 369, + "note": "Accusantium quis sed molestiae et.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 38, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 0" + }, + "events": [ + + ] + }, + { + "id": 370, + "note": "Corporis numquam a voluptatem pariatur asperiores dolorem delectus autem.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 38, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] + }, + { + "id": 371, + "note": "Ea accusantium maxime voluptas rerum.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 38, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] + }, + { + "id": 372, + "note": "Pariatur iusto et et excepturi similique ipsam eum.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 38, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] + }, + { + "id": 373, + "note": "Aliquam et culpa officia iste eius.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 38, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] + }, + { + "id": 374, + "note": "Ab id velit id unde laborum.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 38, + "system": false, + "st_diff": null, + "updated_by_id": null, + "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.", - "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-03-22T15:19:59.966Z", - "updated_at": "2016-03-22T15:19:59.966Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 37, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Administrator" - } - }, - { - "id": 361, - "note": "Maxime sed eius qui consequatur beatae.", - "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:19:59.924Z", - "updated_at": "2016-03-22T15:19:59.924Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 37, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } - }, - { - "id": 360, - "note": "Voluptatum quasi corrupti eveniet sed ut quis quibusdam.", - "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:19:59.897Z", - "updated_at": "2016-03-22T15:19:59.897Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 37, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Julius Moore" - } - }, - { - "id": 359, - "note": "Molestias quia eius ipsum non.", - "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:19:59.866Z", - "updated_at": "2016-03-22T15:19:59.866Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 37, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } - }, - { - "id": 358, - "note": "Aut non est accusantium aliquam.", - "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:19:59.834Z", - "updated_at": "2016-03-22T15:19:59.834Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 37, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } - }, - { - "id": 357, - "note": "Aspernatur voluptas id voluptas vel cum ipsam.", - "noteable_type": "Issue", - "author_id": 22, - "created_at": "2016-03-22T15:19:59.805Z", - "updated_at": "2016-03-22T15:19:59.805Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 37, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 0" - } - }, - { - "id": 356, - "note": "Harum dignissimos provident tempora sit numquam est qui.", - "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:19:59.773Z", - "updated_at": "2016-03-22T15:19:59.773Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 37, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 2" - } - }, - { - "id": 355, - "note": "Sint dignissimos molestiae recusandae delectus.", + "id": 375, + "note": "Quasi fugit qui sed eligendi aut quia.", "noteable_type": "Issue", "author_id": 26, - "created_at": "2016-03-22T15:19:59.746Z", - "updated_at": "2016-03-22T15:19:59.746Z", + "created_at": "2016-06-14T15:02:48.647Z", + "updated_at": "2016-06-14T15:02:48.647Z", "project_id": 5, "attachment": { "url": null @@ -784,186 +686,210 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { + "author": { "name": "User 4" - } + }, + "events": [ + + ] + }, + { + "id": 376, + "note": "Esse nesciunt voluptatem ex vero est consequatur.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 37, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 3" + }, + "events": [ + + ] + }, + { + "id": 377, + "note": "Similique qui quas non aut et velit sequi in.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 37, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 0" + }, + "events": [ + + ] + }, + { + "id": 378, + "note": "Eveniet ut cupiditate repellendus numquam in esse eius.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 37, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] + }, + { + "id": 379, + "note": "Velit est dolorem adipisci rerum sed iure.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 37, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] + }, + { + "id": 380, + "note": "Voluptatem ullam ab ut illo ut quo.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 37, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] + }, + { + "id": 381, + "note": "Voluptatem impedit beatae quasi ipsa earum consectetur.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 37, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] + }, + { + "id": 382, + "note": "Nihil officiis eaque incidunt sunt voluptatum excepturi.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 37, + "system": false, + "st_diff": null, + "updated_by_id": null, + "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.", - "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-03-22T15:20:00.365Z", - "updated_at": "2016-03-22T15:20:00.365Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 36, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Administrator" - } - }, - { - "id": 369, - "note": "Modi architecto officiis quia iste voluptas libero nihil quo.", - "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:20:00.331Z", - "updated_at": "2016-03-22T15:20:00.331Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 36, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } - }, - { - "id": 368, - "note": "Eaque est tenetur ex est molestiae nobis.", - "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:20:00.296Z", - "updated_at": "2016-03-22T15:20:00.296Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 36, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Julius Moore" - } - }, - { - "id": 367, - "note": "Odit enim ut a quo qui.", - "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:20:00.261Z", - "updated_at": "2016-03-22T15:20:00.261Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 36, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } - }, - { - "id": 366, - "note": "Omnis unde cum officiis est.", - "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:20:00.223Z", - "updated_at": "2016-03-22T15:20:00.223Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 36, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } - }, - { - "id": 365, - "note": "Ab consequuntur aliquam illo voluptatum.", - "noteable_type": "Issue", - "author_id": 22, - "created_at": "2016-03-22T15:20:00.178Z", - "updated_at": "2016-03-22T15:20:00.178Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 36, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 0" - } - }, - { - "id": 364, - "note": "Molestiae dolorem est eos dolores aut.", - "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:20:00.127Z", - "updated_at": "2016-03-22T15:20:00.127Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 36, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 2" - } - }, - { - "id": 363, - "note": "Nemo velit nam quod veniam.", + "id": 383, + "note": "Excepturi deleniti sunt rerum nesciunt vero fugiat possimus.", "noteable_type": "Issue", "author_id": 26, - "created_at": "2016-03-22T15:20:00.083Z", - "updated_at": "2016-03-22T15:20:00.083Z", + "created_at": "2016-06-14T15:02:48.885Z", + "updated_at": "2016-06-14T15:02:48.885Z", "project_id": 5, "attachment": { "url": null @@ -974,186 +900,210 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { + "author": { "name": "User 4" - } + }, + "events": [ + + ] + }, + { + "id": 384, + "note": "Et est nemo sed nam sed.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 36, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 3" + }, + "events": [ + + ] + }, + { + "id": 385, + "note": "Animi mollitia nulla facere amet aut quaerat.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 36, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 0" + }, + "events": [ + + ] + }, + { + "id": 386, + "note": "Excepturi id voluptas ut odio officiis omnis.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 36, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] + }, + { + "id": 387, + "note": "Molestiae labore officiis magni et eligendi quasi maxime.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 36, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] + }, + { + "id": 388, + "note": "Officia tenetur praesentium rem nam non.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 36, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] + }, + { + "id": 389, + "note": "Et et et molestiae reprehenderit.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 36, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] + }, + { + "id": 390, + "note": "Aperiam in consequatur est sunt cum quia.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 36, + "system": false, + "st_diff": null, + "updated_by_id": null, + "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.", - "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-03-22T15:20:00.660Z", - "updated_at": "2016-03-22T15:20:00.660Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 35, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Administrator" - } - }, - { - "id": 377, - "note": "Porro sed nobis neque amet velit velit.", - "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:20:00.625Z", - "updated_at": "2016-03-22T15:20:00.625Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 35, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } - }, - { - "id": 376, - "note": "Dicta officiis doloremque voluptatum qui omnis.", - "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:20:00.589Z", - "updated_at": "2016-03-22T15:20:00.589Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 35, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Julius Moore" - } - }, - { - "id": 375, - "note": "Incidunt rerum omnis cum laudantium aut impedit.", - "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:20:00.553Z", - "updated_at": "2016-03-22T15:20:00.553Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 35, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } - }, - { - "id": 374, - "note": "Et suscipit omnis dolorum officia vero.", - "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:20:00.517Z", - "updated_at": "2016-03-22T15:20:00.517Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 35, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } - }, - { - "id": 373, - "note": "Doloremque adipisci et cumque inventore beatae consectetur.", - "noteable_type": "Issue", - "author_id": 22, - "created_at": "2016-03-22T15:20:00.485Z", - "updated_at": "2016-03-22T15:20:00.485Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 35, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 0" - } - }, - { - "id": 372, - "note": "Dolores sapiente ea dolorum et quae adipisci id.", - "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:20:00.455Z", - "updated_at": "2016-03-22T15:20:00.455Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 35, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 2" - } - }, - { - "id": 371, - "note": "Accusantium repellat tenetur natus dicta ullam saepe facere.", + "id": 391, + "note": "Qui magnam et assumenda quod id dicta necessitatibus.", "noteable_type": "Issue", "author_id": 26, - "created_at": "2016-03-22T15:20:00.420Z", - "updated_at": "2016-03-22T15:20:00.420Z", + "created_at": "2016-06-14T15:02:49.075Z", + "updated_at": "2016-06-14T15:02:49.075Z", "project_id": 5, "attachment": { "url": null @@ -1164,39 +1114,210 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { + "author": { "name": "User 4" - } + }, + "events": [ + + ] + }, + { + "id": 392, + "note": "Consectetur deserunt possimus dolor est odio.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 35, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 3" + }, + "events": [ + + ] + }, + { + "id": 393, + "note": "Labore nisi quo cumque voluptas consequatur aut qui.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 35, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 0" + }, + "events": [ + + ] + }, + { + "id": 394, + "note": "Et totam facilis voluptas et enim.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 35, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] + }, + { + "id": 395, + "note": "Ratione sint pariatur sed omnis eligendi quo libero exercitationem.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 35, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] + }, + { + "id": 396, + "note": "Iure hic autem id voluptatem.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 35, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] + }, + { + "id": 397, + "note": "Excepturi eum laboriosam delectus repellendus odio nisi et voluptatem.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 35, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] + }, + { + "id": 398, + "note": "Ut quis ex soluta consequatur et blanditiis.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 35, + "system": false, + "st_diff": null, + "updated_by_id": null, + "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,186 +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.", - "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-03-22T15:20:01.223Z", - "updated_at": "2016-03-22T15:20:01.223Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 33, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Administrator" - } - }, - { - "id": 393, - "note": "Et et sed sit sint.", - "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:20:01.194Z", - "updated_at": "2016-03-22T15:20:01.194Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 33, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } - }, - { - "id": 392, - "note": "Corrupti perferendis voluptas et iure omnis officia.", - "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:20:01.160Z", - "updated_at": "2016-03-22T15:20:01.160Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 33, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Julius Moore" - } - }, - { - "id": 391, - "note": "Autem quo fugit in iste nesciunt tempora.", - "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:20:01.131Z", - "updated_at": "2016-03-22T15:20:01.131Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 33, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } - }, - { - "id": 390, - "note": "Magni porro ut soluta quis et eveniet maiores.", - "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:20:01.101Z", - "updated_at": "2016-03-22T15:20:01.101Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 33, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } - }, - { - "id": 389, - "note": "Sed consequuntur debitis nisi veniam exercitationem recusandae a quisquam.", - "noteable_type": "Issue", - "author_id": 22, - "created_at": "2016-03-22T15:20:01.070Z", - "updated_at": "2016-03-22T15:20:01.070Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 33, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 0" - } - }, - { - "id": 388, - "note": "Aut impedit qui consectetur dicta temporibus.", - "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:20:01.042Z", - "updated_at": "2016-03-22T15:20:01.042Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 33, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 2" - } - }, - { - "id": 387, - "note": "Officia repudiandae ut culpa ipsa reiciendis.", + "id": 407, + "note": "Quod ea et possimus architecto.", "noteable_type": "Issue", "author_id": 26, - "created_at": "2016-03-22T15:20:01.005Z", - "updated_at": "2016-03-22T15:20:01.005Z", + "created_at": "2016-06-14T15:02:49.450Z", + "updated_at": "2016-06-14T15:02:49.450Z", "project_id": 5, "attachment": { "url": null @@ -1544,186 +1542,210 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { + "author": { "name": "User 4" - } + }, + "events": [ + + ] + }, + { + "id": 408, + "note": "Reiciendis est et unde perferendis dicta ut praesentium quasi.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 33, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 3" + }, + "events": [ + + ] + }, + { + "id": 409, + "note": "Magni quia odio blanditiis pariatur voluptas.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 33, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 0" + }, + "events": [ + + ] + }, + { + "id": 410, + "note": "Enim quam ut et et et.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 33, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] + }, + { + "id": 411, + "note": "Fugit voluptatem ratione maxime expedita.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 33, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] + }, + { + "id": 412, + "note": "Voluptatem enim aut ipsa et et ducimus.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 33, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] + }, + { + "id": 413, + "note": "Quia repellat fugiat consectetur quidem.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 33, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] + }, + { + "id": 414, + "note": "Corporis ipsum et ea necessitatibus quod assumenda repudiandae quam.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 33, + "system": false, + "st_diff": null, + "updated_by_id": null, + "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.", - "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-03-22T15:20:01.489Z", - "updated_at": "2016-03-22T15:20:01.489Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 32, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Administrator" - } - }, - { - "id": 401, - "note": "Est repellat commodi incidunt tempore earum optio unde sint.", - "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:20:01.455Z", - "updated_at": "2016-03-22T15:20:01.455Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 32, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } - }, - { - "id": 400, - "note": "Vero unde debitis tempore est laboriosam ut esse.", - "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:20:01.421Z", - "updated_at": "2016-03-22T15:20:01.421Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 32, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Julius Moore" - } - }, - { - "id": 399, - "note": "Omnis qui asperiores expedita harum voluptatem eius.", - "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:20:01.391Z", - "updated_at": "2016-03-22T15:20:01.391Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 32, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } - }, - { - "id": 398, - "note": "Dolorem doloribus delectus quo ratione esse veritatis.", - "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:20:01.358Z", - "updated_at": "2016-03-22T15:20:01.358Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 32, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } - }, - { - "id": 397, - "note": "Quia esse et odit id est omnis dolorum quia.", - "noteable_type": "Issue", - "author_id": 22, - "created_at": "2016-03-22T15:20:01.329Z", - "updated_at": "2016-03-22T15:20:01.329Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 32, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 0" - } - }, - { - "id": 396, - "note": "Exercitationem suscipit non rerum tempore sit.", - "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:20:01.297Z", - "updated_at": "2016-03-22T15:20:01.297Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 32, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 2" - } - }, - { - "id": 395, - "note": "Nihil veniam magni sit officiis.", + "id": 415, + "note": "Nemo consequatur sed blanditiis qui id iure dolores.", "noteable_type": "Issue", "author_id": 26, - "created_at": "2016-03-22T15:20:01.268Z", - "updated_at": "2016-03-22T15:20:01.268Z", + "created_at": "2016-06-14T15:02:49.694Z", + "updated_at": "2016-06-14T15:02:49.694Z", "project_id": 5, "attachment": { "url": null @@ -1734,186 +1756,210 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { + "author": { "name": "User 4" - } + }, + "events": [ + + ] + }, + { + "id": 416, + "note": "Voluptas ab accusantium dicta in.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 32, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 3" + }, + "events": [ + + ] + }, + { + "id": 417, + "note": "Esse odit qui a et eum ducimus.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 32, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 0" + }, + "events": [ + + ] + }, + { + "id": 418, + "note": "Sequi dolor doloribus ratione placeat repellendus.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 32, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] + }, + { + "id": 419, + "note": "Quae aspernatur rem est similique.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 32, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] + }, + { + "id": 420, + "note": "Voluptate omnis et id rerum non nesciunt laudantium assumenda.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 32, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] + }, + { + "id": 421, + "note": "Quia enim ab et eligendi.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 32, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] + }, + { + "id": 422, + "note": "In fugiat rerum voluptas quas officia.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 32, + "system": false, + "st_diff": null, + "updated_by_id": null, + "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.", - "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-03-22T15:20:01.828Z", - "updated_at": "2016-03-22T15:20:01.828Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 31, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Administrator" - } - }, - { - "id": 409, - "note": "Omnis rem nihil molestiae enim laudantium doloremque.", - "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:20:01.783Z", - "updated_at": "2016-03-22T15:20:01.783Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 31, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } - }, - { - "id": 408, - "note": "Ullam harum sit et optio incidunt.", - "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:20:01.746Z", - "updated_at": "2016-03-22T15:20:01.746Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 31, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Julius Moore" - } - }, - { - "id": 407, - "note": "Fugit distinctio ab quo ipsam.", - "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:20:01.716Z", - "updated_at": "2016-03-22T15:20:01.716Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 31, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } - }, - { - "id": 406, - "note": "Impedit iste possimus ad ea.", - "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:20:01.676Z", - "updated_at": "2016-03-22T15:20:01.676Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 31, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } - }, - { - "id": 405, - "note": "Nemo recusandae dolore distinctio quam consequuntur ut et aut.", - "noteable_type": "Issue", - "author_id": 22, - "created_at": "2016-03-22T15:20:01.641Z", - "updated_at": "2016-03-22T15:20:01.641Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 31, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 0" - } - }, - { - "id": 404, - "note": "Nisi repudiandae repellat nulla culpa quasi expedita quod velit.", - "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:20:01.601Z", - "updated_at": "2016-03-22T15:20:01.601Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 31, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 2" - } - }, - { - "id": 403, - "note": "Quibusdam odio temporibus nemo voluptatibus accusamus.", + "id": 423, + "note": "A mollitia qui iste consequatur eaque iure omnis sunt.", "noteable_type": "Issue", "author_id": 26, - "created_at": "2016-03-22T15:20:01.552Z", - "updated_at": "2016-03-22T15:20:01.552Z", + "created_at": "2016-06-14T15:02:49.933Z", + "updated_at": "2016-06-14T15:02:49.933Z", "project_id": 5, "attachment": { "url": null @@ -1924,47 +1970,405 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { + "author": { "name": "User 4" - } + }, + "events": [ + + ] + }, + { + "id": 424, + "note": "Eveniet est et blanditiis sequi alias.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 31, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 3" + }, + "events": [ + + ] + }, + { + "id": 425, + "note": "Commodi tempore voluptas doloremque est.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 31, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 0" + }, + "events": [ + + ] + }, + { + "id": 426, + "note": "Quo libero impedit odio debitis rerum aspernatur.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 31, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] + }, + { + "id": 427, + "note": "Dolorem voluptatem qui labore deserunt.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 31, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] + }, + { + "id": 428, + "note": "Est blanditiis laboriosam enim ipsam.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 31, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] + }, + { + "id": 429, + "note": "Et in voluptatem animi dolorem eos.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 31, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] + }, + { + "id": 430, + "note": "Unde culpa voluptate qui sint quos.", + "noteable_type": "Issue", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 31, + "system": false, + "st_diff": null, + "updated_by_id": null, + "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, + "id": 19, + "title": "v3.0", + "project_id": 5, + "description": "Rerum at autem exercitationem ea voluptates harum quam placeat.", + "due_date": null, + "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": 18, + "title": "v2.0", + "project_id": 5, + "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": 17, "title": "v1.0", "project_id": 5, - "description": "Est sed eos minima veniam culpa aut non.", + "description": "Molestiae perspiciatis voluptates doloremque commodi veniam consequatur.", "due_date": null, - "created_at": "2016-03-22T15:13:21.622Z", - "updated_at": "2016-03-22T15:13:21.622Z", + "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": 16, + "title": "v0.0", + "project_id": 5, + "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 + "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": [ @@ -1972,422 +2376,100 @@ ], "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 - }, - { - "id": 22, - "target_type": null, - "target_id": null, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:20.667Z", - "updated_at": "2016-03-22T15:13:20.667Z", - "action": 8, - "author_id": 26 - }, - { - "id": 21, - "target_type": null, - "target_id": null, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:20.646Z", - "updated_at": "2016-03-22T15:13:20.646Z", - "action": 8, - "author_id": 1 - }, - { - "id": 5, - "target_type": null, - "target_id": null, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:10.369Z", - "updated_at": "2016-03-22T15:13:10.369Z", - "action": 1, - "author_id": 1 - } ], "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": 35, + "access_level": 10, + "source_id": 5, + "source_type": "Project", + "user_id": 6, + "notification_level": 3, + "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": 6, + "email": "shaina@koelpindenesik.com", + "username": "saul_will" } }, { "id": 34, - "access_level": 40, + "access_level": 20, "source_id": 5, "source_type": "Project", - "user_id": 22, + "user_id": 15, "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.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": 22, - "email": "user0@example.com", - "username": "user0" + "id": 15, + "email": "breanna_sanford@wolf.com", + "username": "emmet.schamberger" } }, { "id": 33, - "access_level": 40, + "access_level": 20, "source_id": 5, "source_type": "Project", "user_id": 26, "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.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": 26, "email": "user4@example.com", "username": "user4" } - }, - { - "id": 32, - "access_level": 20, - "source_id": 5, - "source_type": "Project", - "user_id": 1, - "notification_level": 3, - "created_at": "2016-03-22T15:13:20.643Z", - "updated_at": "2016-03-22T15:13:20.643Z", - "created_by_id": null, - "invite_email": null, - "invite_token": null, - "invite_accepted_at": null, - "user": { - "id": 1, - "email": "nospam@bluegod.net", - "username": "root" - } } ], "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.", - "noteable_type": "MergeRequest", - "author_id": 1, - "created_at": "2016-03-22T15:20:09.553Z", - "updated_at": "2016-03-22T15:20:09.553Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 85, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Administrator" - } - }, - { - "id": 637, - "note": "Ipsum aliquam est in unde similique nihil illo ea.", - "noteable_type": "MergeRequest", - "author_id": 3, - "created_at": "2016-03-22T15:20:09.528Z", - "updated_at": "2016-03-22T15:20:09.528Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 85, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } - }, - { - "id": 636, - "note": "Soluta inventore adipisci et consequatur expedita aliquid earum modi.", - "noteable_type": "MergeRequest", - "author_id": 4, - "created_at": "2016-03-22T15:20:09.496Z", - "updated_at": "2016-03-22T15:20:09.496Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 85, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Julius Moore" - } - }, - { - "id": 635, - "note": "Corporis incidunt tempore est deleniti.", - "noteable_type": "MergeRequest", - "author_id": 10, - "created_at": "2016-03-22T15:20:09.469Z", - "updated_at": "2016-03-22T15:20:09.469Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 85, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } - }, - { - "id": 634, - "note": "Hic dolores voluptatibus qui necessitatibus.", - "noteable_type": "MergeRequest", - "author_id": 12, - "created_at": "2016-03-22T15:20:09.440Z", - "updated_at": "2016-03-22T15:20:09.440Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 85, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } - }, - { - "id": 633, - "note": "Rerum architecto placeat doloribus voluptates consequuntur quo.", - "noteable_type": "MergeRequest", - "author_id": 22, - "created_at": "2016-03-22T15:20:09.412Z", - "updated_at": "2016-03-22T15:20:09.412Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 85, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 0" - } - }, - { - "id": 632, - "note": "Vel earum aut ut occaecati aut ut rerum qui.", - "noteable_type": "MergeRequest", - "author_id": 24, - "created_at": "2016-03-22T15:20:09.389Z", - "updated_at": "2016-03-22T15:20:09.389Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 85, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 2" - } - }, - { - "id": 631, - "note": "Est voluptatibus dolores animi numquam.", + "id": 671, + "note": "Sit voluptatibus eveniet architecto quidem.", "noteable_type": "MergeRequest", "author_id": 26, - "created_at": "2016-03-22T15:20:09.361Z", - "updated_at": "2016-03-22T15:20:09.361Z", + "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": { + "author": { "name": "User 4" - } + }, + "events": [ + + ] + }, + { + "id": 672, + "note": "Odio maxime ratione voluptatibus sed.", + "noteable_type": "MergeRequest", + "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": 27, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 3" + }, + "events": [ + + ] + }, + { + "id": 673, + "note": "Et deserunt et omnis nihil excepturi accusantium.", + "noteable_type": "MergeRequest", + "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": 27, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 0" + }, + "events": [ + + ] + }, + { + "id": 674, + "note": "Saepe asperiores exercitationem non dignissimos laborum reiciendis et ipsum.", + "noteable_type": "MergeRequest", + "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": 27, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] + }, + { + "id": 675, + "note": "Numquam est at dolor quo et sed eligendi similique.", + "noteable_type": "MergeRequest", + "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": 27, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] + }, + { + "id": 676, + "note": "Et perferendis aliquam sunt nisi labore delectus.", + "noteable_type": "MergeRequest", + "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": 27, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] + }, + { + "id": 677, + "note": "Aut ex rerum et in.", + "noteable_type": "MergeRequest", + "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": 27, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] + }, + { + "id": 678, + "note": "Dolor laborum earum ut exercitationem.", + "noteable_type": "MergeRequest", + "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": 27, + "system": false, + "st_diff": null, + "updated_by_id": null, + "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.", - "noteable_type": "MergeRequest", - "author_id": 1, - "created_at": "2016-03-22T15:20:09.770Z", - "updated_at": "2016-03-22T15:20:09.770Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 84, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Administrator" - } - }, - { - "id": 645, - "note": "Ut assumenda dignissimos quibusdam veritatis sequi dolores.", - "noteable_type": "MergeRequest", - "author_id": 3, - "created_at": "2016-03-22T15:20:09.740Z", - "updated_at": "2016-03-22T15:20:09.740Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 84, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } - }, - { - "id": 644, - "note": "Velit quae quidem cupiditate laudantium nihil ut eveniet.", - "noteable_type": "MergeRequest", - "author_id": 4, - "created_at": "2016-03-22T15:20:09.717Z", - "updated_at": "2016-03-22T15:20:09.717Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 84, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Julius Moore" - } - }, - { - "id": 643, - "note": "Repellat quas porro sed mollitia laborum ut fugiat.", - "noteable_type": "MergeRequest", - "author_id": 10, - "created_at": "2016-03-22T15:20:09.690Z", - "updated_at": "2016-03-22T15:20:09.690Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 84, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } - }, - { - "id": 642, - "note": "Qui aut debitis perspiciatis et voluptatem.", - "noteable_type": "MergeRequest", - "author_id": 12, - "created_at": "2016-03-22T15:20:09.665Z", - "updated_at": "2016-03-22T15:20:09.665Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 84, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } - }, - { - "id": 641, - "note": "Quia id quia velit et.", - "noteable_type": "MergeRequest", - "author_id": 22, - "created_at": "2016-03-22T15:20:09.639Z", - "updated_at": "2016-03-22T15:20:09.639Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 84, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 0" - } - }, - { - "id": 640, - "note": "Corporis commodi doloremque itaque non animi.", - "noteable_type": "MergeRequest", - "author_id": 24, - "created_at": "2016-03-22T15:20:09.617Z", - "updated_at": "2016-03-22T15:20:09.617Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 84, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 2" - } - }, - { - "id": 639, - "note": "Possimus dignissimos voluptatum in tenetur.", + "id": 679, + "note": "Qui rerum totam nisi est.", "noteable_type": "MergeRequest", "author_id": 26, - "created_at": "2016-03-22T15:20:09.589Z", - "updated_at": "2016-03-22T15:20:09.589Z", + "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": { + "author": { "name": "User 4" - } + }, + "events": [ + + ] + }, + { + "id": 680, + "note": "Pariatur magni corrupti consequatur debitis minima error beatae voluptatem.", + "noteable_type": "MergeRequest", + "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": 26, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 3" + }, + "events": [ + + ] + }, + { + "id": 681, + "note": "Qui quis ut modi eos rerum ratione.", + "noteable_type": "MergeRequest", + "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": 26, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 0" + }, + "events": [ + + ] + }, + { + "id": 682, + "note": "Illum quidem expedita mollitia fugit.", + "noteable_type": "MergeRequest", + "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": 26, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] + }, + { + "id": 683, + "note": "Consectetur voluptate sit sint possimus veritatis quod.", + "noteable_type": "MergeRequest", + "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": 26, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] + }, + { + "id": 684, + "note": "Natus libero quibusdam rem assumenda deleniti accusamus sed earum.", + "noteable_type": "MergeRequest", + "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": 26, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] + }, + { + "id": 685, + "note": "Tenetur autem nihil rerum odit.", + "noteable_type": "MergeRequest", + "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": 26, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] + }, + { + "id": 686, + "note": "Quia maiores et odio sed.", + "noteable_type": "MergeRequest", + "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": 26, + "system": false, + "st_diff": null, + "updated_by_id": null, + "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,159 +3212,12 @@ "deleted_at": null, "notes": [ { - "id": 1231, - "note": "Rerum optio quibusdam provident possimus quis cum.", - "noteable_type": "MergeRequest", - "author_id": 1, - "created_at": "2016-03-22T15:20:30.472Z", - "updated_at": "2016-03-22T15:20:30.472Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 15, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Administrator" - } - }, - { - "id": 1230, - "note": "Quasi odit repudiandae ut officiis ut nihil illo.", - "noteable_type": "MergeRequest", - "author_id": 3, - "created_at": "2016-03-22T15:20:30.444Z", - "updated_at": "2016-03-22T15:20:30.444Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 15, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } - }, - { - "id": 1229, - "note": "Aut vero dolores facere sed.", - "noteable_type": "MergeRequest", - "author_id": 4, - "created_at": "2016-03-22T15:20:30.412Z", - "updated_at": "2016-03-22T15:20:30.412Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 15, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Julius Moore" - } - }, - { - "id": 1228, - "note": "Autem voluptatem et blanditiis accusantium deserunt et et.", - "noteable_type": "MergeRequest", - "author_id": 10, - "created_at": "2016-03-22T15:20:30.383Z", - "updated_at": "2016-03-22T15:20:30.383Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 15, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } - }, - { - "id": 1227, - "note": "Voluptatem aliquam voluptatem molestiae est.", - "noteable_type": "MergeRequest", - "author_id": 12, - "created_at": "2016-03-22T15:20:30.352Z", - "updated_at": "2016-03-22T15:20:30.352Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 15, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } - }, - { - "id": 1226, - "note": "Ea aut cupiditate est consequatur animi error qui et.", - "noteable_type": "MergeRequest", - "author_id": 22, - "created_at": "2016-03-22T15:20:30.319Z", - "updated_at": "2016-03-22T15:20:30.319Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 15, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 0" - } - }, - { - "id": 1225, - "note": "Voluptates est voluptas et nostrum modi beatae inventore et.", - "noteable_type": "MergeRequest", - "author_id": 24, - "created_at": "2016-03-22T15:20:30.289Z", - "updated_at": "2016-03-22T15:20:30.289Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 15, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 2" - } - }, - { - "id": 1224, - "note": "Quia est rerum adipisci cupiditate.", + "id": 777, + "note": "Pariatur voluptas placeat aspernatur culpa suscipit soluta.", "noteable_type": "MergeRequest", "author_id": 26, - "created_at": "2016-03-22T15:20:30.260Z", - "updated_at": "2016-03-22T15:20:30.260Z", + "created_at": "2016-06-14T15:02:59.348Z", + "updated_at": "2016-06-14T15:02:59.348Z", "project_id": 5, "attachment": { "url": null @@ -3193,15 +3228,1175 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { + "author": { "name": "User 4" - } + }, + "events": [ + + ] + }, + { + "id": 778, + "note": "Alias et iure mollitia suscipit molestiae voluptatum nostrum asperiores.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 15, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 3" + }, + "events": [ + + ] + }, + { + "id": 779, + "note": "Laudantium qui eum qui sunt.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 15, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 0" + }, + "events": [ + + ] + }, + { + "id": 780, + "note": "Quas rem est iusto ut delectus fugiat recusandae mollitia.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 15, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] + }, + { + "id": 781, + "note": "Repellendus ab et qui nesciunt.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 15, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] + }, + { + "id": 782, + "note": "Non possimus voluptatum odio qui ut.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 15, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] + }, + { + "id": 783, + "note": "Dolores repellendus eum ducimus quam ab dolorem quia.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 15, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] + }, + { + "id": 784, + "note": "Facilis dolorem aut corrupti id ratione occaecati.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 15, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ], "merge_request_diff": { "id": 15, "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": [ + "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", + "a_mode": "0", + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + } + ], + "merge_request_id": 14, + "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": "improve/awesome", + "source_branch": "test-8", + "source_project_id": 5, + "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": "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, + "merge_commit_sha": null, + "deleted_at": null, + "notes": [ + { + "id": 793, + "note": "In illum maxime aperiam nulla est aspernatur.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 13, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 4" + }, + "events": [ + + ] + }, + { + "id": 794, + "note": "Enim quia perferendis cum distinctio tenetur optio voluptas veniam.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 13, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 3" + }, + "events": [ + + ] + }, + { + "id": 795, + "note": "Dolor ad quia quis pariatur ducimus.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 13, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 0" + }, + "events": [ + + ] + }, + { + "id": 796, + "note": "Et a odio voluptate aut.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 13, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] + }, + { + "id": 797, + "note": "Quis nihil temporibus voluptatum modi minima a ut.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 13, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] + }, + { + "id": 798, + "note": "Ut alias consequatur in nostrum.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 13, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] + }, + { + "id": 799, + "note": "Voluptatibus aperiam assumenda et neque sint libero.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 13, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] + }, + { + "id": 800, + "note": "Veritatis voluptatem dolor dolores magni quo ut ipsa fuga.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 13, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Administrator" + }, + "events": [ + + ] + } + ], + "merge_request_diff": { + "id": 13, + "state": "collected", + "st_commits": [ + { + "id": "0bfedc29d30280c7e8564e19f654584b459e5868", + "message": "fixes #10\n", + "parent_ids": [ + "be93687618e4b132087f430a4d8fc3a609c9b77c" + ], + "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", @@ -3456,466 +4651,7 @@ "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 - }, - "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/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": 14, - "created_at": "2016-03-22T15:13:45.444Z", - "updated_at": "2016-03-22T15:13:45.486Z", - "base_commit_sha": "be93687618e4b132087f430a4d8fc3a609c9b77c", - "real_size": "1" - } - }, - { - "id": 13, - "target_branch": "test-11", - "source_branch": "test-12", - "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, - "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.", - "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": 1247, - "note": "Non error magnam placeat cupiditate eum.", - "noteable_type": "MergeRequest", - "author_id": 1, - "created_at": "2016-03-22T15:20:30.989Z", - "updated_at": "2016-03-22T15:20:30.989Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 13, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Administrator" - } - }, - { - "id": 1246, - "note": "Eos optio et architecto eligendi ea est nihil.", - "noteable_type": "MergeRequest", - "author_id": 3, - "created_at": "2016-03-22T15:20:30.957Z", - "updated_at": "2016-03-22T15:20:30.957Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 13, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } - }, - { - "id": 1245, - "note": "Reprehenderit in atque dolor et repudiandae a est.", - "noteable_type": "MergeRequest", - "author_id": 4, - "created_at": "2016-03-22T15:20:30.928Z", - "updated_at": "2016-03-22T15:20:30.928Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 13, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Julius Moore" - } - }, - { - "id": 1244, - "note": "Numquam fugit doloremque iure odio et.", - "noteable_type": "MergeRequest", - "author_id": 10, - "created_at": "2016-03-22T15:20:30.902Z", - "updated_at": "2016-03-22T15:20:30.902Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 13, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } - }, - { - "id": 1243, - "note": "Doloribus laboriosam id harum voluptatum vitae ut quam.", - "noteable_type": "MergeRequest", - "author_id": 12, - "created_at": "2016-03-22T15:20:30.863Z", - "updated_at": "2016-03-22T15:20:30.863Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 13, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } - }, - { - "id": 1242, - "note": "Harum et ut ipsum dolore ea.", - "noteable_type": "MergeRequest", - "author_id": 22, - "created_at": "2016-03-22T15:20:30.832Z", - "updated_at": "2016-03-22T15:20:30.832Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 13, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 0" - } - }, - { - "id": 1241, - "note": "Corporis sed soluta ut est modi natus ab.", - "noteable_type": "MergeRequest", - "author_id": 24, - "created_at": "2016-03-22T15:20:30.802Z", - "updated_at": "2016-03-22T15:20:30.802Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 13, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 2" - } - }, - { - "id": 1240, - "note": "Corrupti totam tenetur officiis ratione dolores est qui vel.", - "noteable_type": "MergeRequest", - "author_id": 26, - "created_at": "2016-03-22T15:20:30.771Z", - "updated_at": "2016-03-22T15:20:30.771Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 13, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 4" - } - } - ], - "merge_request_diff": { - "id": 13, - "state": "collected", - "st_commits": [ - { - "id": "a4e5dfebf42e34596526acb8611bc7ed80e4eb3f", - "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" - } - ], - "st_diffs": [ { "diff": "--- /dev/null\n+++ b/test\n", "new_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,159 +4726,12 @@ "deleted_at": null, "notes": [ { - "id": 1255, - "note": "Quibusdam rem aut similique ipsum recusandae ut accusamus.", - "noteable_type": "MergeRequest", - "author_id": 1, - "created_at": "2016-03-22T15:20:31.253Z", - "updated_at": "2016-03-22T15:20:31.253Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 12, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Administrator" - } - }, - { - "id": 1254, - "note": "Cumque sed omnis ipsa et magnam dolorem et.", - "noteable_type": "MergeRequest", - "author_id": 3, - "created_at": "2016-03-22T15:20:31.224Z", - "updated_at": "2016-03-22T15:20:31.224Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 12, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } - }, - { - "id": 1253, - "note": "Molestiae beatae id consequatur nam minus quia.", - "noteable_type": "MergeRequest", - "author_id": 4, - "created_at": "2016-03-22T15:20:31.195Z", - "updated_at": "2016-03-22T15:20:31.195Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 12, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Julius Moore" - } - }, - { - "id": 1252, - "note": "Voluptatem dolorem dignissimos itaque tempora quas ut.", - "noteable_type": "MergeRequest", - "author_id": 10, - "created_at": "2016-03-22T15:20:31.166Z", - "updated_at": "2016-03-22T15:20:31.166Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 12, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } - }, - { - "id": 1251, - "note": "Debitis qui quibusdam voluptas repellat veritatis dicta rerum id.", - "noteable_type": "MergeRequest", - "author_id": 12, - "created_at": "2016-03-22T15:20:31.137Z", - "updated_at": "2016-03-22T15:20:31.137Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 12, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } - }, - { - "id": 1250, - "note": "Suscipit optio ad voluptatem dignissimos temporibus amet molestias ut.", - "noteable_type": "MergeRequest", - "author_id": 22, - "created_at": "2016-03-22T15:20:31.107Z", - "updated_at": "2016-03-22T15:20:31.107Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 12, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 0" - } - }, - { - "id": 1249, - "note": "Nemo aut vitae et ducimus autem ex dolores.", - "noteable_type": "MergeRequest", - "author_id": 24, - "created_at": "2016-03-22T15:20:31.073Z", - "updated_at": "2016-03-22T15:20:31.073Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 12, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 2" - } - }, - { - "id": 1248, - "note": "Repellendus eaque ex molestiae laudantium placeat quidem vitae recusandae.", + "id": 801, + "note": "Nihil dicta molestias expedita atque.", "noteable_type": "MergeRequest", "author_id": 26, - "created_at": "2016-03-22T15:20:31.038Z", - "updated_at": "2016-03-22T15:20:31.038Z", + "created_at": "2016-06-14T15:03:00.001Z", + "updated_at": "2016-06-14T15:03:00.001Z", "project_id": 5, "attachment": { "url": null @@ -4127,9 +4742,180 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { + "author": { "name": "User 4" - } + }, + "events": [ + + ] + }, + { + "id": 802, + "note": "Illum culpa voluptas enim accusantium deserunt.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 12, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 3" + }, + "events": [ + + ] + }, + { + "id": 803, + "note": "Dicta esse aliquam laboriosam unde alias.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 12, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 0" + }, + "events": [ + + ] + }, + { + "id": 804, + "note": "Dicta autem et sed molestiae ut quae.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 12, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] + }, + { + "id": 805, + "note": "Ut ut temporibus voluptas dolore quia velit.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 12, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] + }, + { + "id": 806, + "note": "Dolores similique sint pariatur error id quia fugit aut.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 12, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] + }, + { + "id": 807, + "note": "Quisquam provident nihil aperiam voluptatem.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 12, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] + }, + { + "id": 808, + "note": "Similique quo vero expedita deserunt ipsam earum.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 12, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ], "merge_request_diff": { @@ -4143,14 +4929,229 @@ "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", @@ -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,159 +5226,12 @@ "deleted_at": null, "notes": [ { - "id": 1263, - "note": "Beatae incidunt exercitationem voluptates recusandae fuga quia enim.", - "noteable_type": "MergeRequest", - "author_id": 1, - "created_at": "2016-03-22T15:20:31.883Z", - "updated_at": "2016-03-22T15:20:31.883Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 11, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Administrator" - } - }, - { - "id": 1262, - "note": "Illum sunt id consequuntur fugit et quo ullam eum.", - "noteable_type": "MergeRequest", - "author_id": 3, - "created_at": "2016-03-22T15:20:31.860Z", - "updated_at": "2016-03-22T15:20:31.860Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 11, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } - }, - { - "id": 1261, - "note": "Alias reiciendis autem ipsa sequi autem nemo odio.", - "noteable_type": "MergeRequest", - "author_id": 4, - "created_at": "2016-03-22T15:20:31.456Z", - "updated_at": "2016-03-22T15:20:31.456Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 11, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Julius Moore" - } - }, - { - "id": 1260, - "note": "Maxime nisi odit eos nulla vel ex accusamus velit.", - "noteable_type": "MergeRequest", - "author_id": 10, - "created_at": "2016-03-22T15:20:31.426Z", - "updated_at": "2016-03-22T15:20:31.426Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 11, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } - }, - { - "id": 1259, - "note": "Excepturi et qui sapiente ut ducimus sunt nesciunt.", - "noteable_type": "MergeRequest", - "author_id": 12, - "created_at": "2016-03-22T15:20:31.397Z", - "updated_at": "2016-03-22T15:20:31.397Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 11, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } - }, - { - "id": 1258, - "note": "Quis rerum dolores et dolorem modi neque ullam doloribus.", - "noteable_type": "MergeRequest", - "author_id": 22, - "created_at": "2016-03-22T15:20:31.364Z", - "updated_at": "2016-03-22T15:20:31.364Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 11, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 0" - } - }, - { - "id": 1257, - "note": "Voluptatum et mollitia neque aut.", - "noteable_type": "MergeRequest", - "author_id": 24, - "created_at": "2016-03-22T15:20:31.328Z", - "updated_at": "2016-03-22T15:20:31.328Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 11, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 2" - } - }, - { - "id": 1256, - "note": "Rerum laudantium dolor natus doloribus voluptas aliquid a.", + "id": 809, + "note": "Omnis ratione laboriosam dolores qui.", "noteable_type": "MergeRequest", "author_id": 26, - "created_at": "2016-03-22T15:20:31.298Z", - "updated_at": "2016-03-22T15:20:31.298Z", + "created_at": "2016-06-14T15:03:00.260Z", + "updated_at": "2016-06-14T15:03:00.260Z", "project_id": 5, "attachment": { "url": null @@ -4362,13 +5242,445 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { + "author": { "name": "User 4" - } + }, + "events": [ + + ] + }, + { + "id": 810, + "note": "Voluptas voluptates pariatur dolores maxime est voluptas.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 11, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 3" + }, + "events": [ + + ] + }, + { + "id": 811, + "note": "Sit perspiciatis facilis ipsum consequatur.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 11, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 0" + }, + "events": [ + + ] + }, + { + "id": 812, + "note": "Ut neque aliquam nam et est.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 11, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] + }, + { + "id": 813, + "note": "Et debitis rerum minima sit aut dolorem.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 11, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] + }, + { + "id": 814, + "note": "Ea nisi earum fugit iste aperiam consequatur.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 11, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] + }, + { + "id": 815, + "note": "Amet ratione consequatur laudantium rerum voluptas est nobis.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 11, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] + }, + { + "id": 816, + "note": "Ab ducimus cumque quia dolorem vitae sint beatae rerum.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 11, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ], "merge_request_diff": { "id": 11, + "state": "empty", + "st_commits": null, + "st_diffs": [ + + ], + "merge_request_id": 11, + "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": "feature", + "source_branch": "test-5", + "source_project_id": 5, + "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": "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, + "merge_commit_sha": null, + "deleted_at": null, + "notes": [ + { + "id": 817, + "note": "Recusandae et voluptas enim qui et.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 10, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 4" + }, + "events": [ + + ] + }, + { + "id": 818, + "note": "Asperiores dolorem rerum ipsum totam.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 10, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 3" + }, + "events": [ + + ] + }, + { + "id": 819, + "note": "Qui quam et iure quasi provident cumque itaque sequi.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 10, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 0" + }, + "events": [ + + ] + }, + { + "id": 820, + "note": "Sint accusantium aliquid iste qui iusto minus vel.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 10, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] + }, + { + "id": 821, + "note": "Dolor corrupti dolorem blanditiis voluptas.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 10, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] + }, + { + "id": 822, + "note": "Est perferendis assumenda aliquam aliquid sit ipsum ullam aut.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 10, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] + }, + { + "id": 823, + "note": "Hic neque reiciendis quaerat maiores.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 10, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] + }, + { + "id": 824, + "note": "Sequi architecto doloribus ut vel autem.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 10, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Administrator" + }, + "events": [ + + ] + } + ], + "merge_request_diff": { + "id": 10, "state": "collected", "st_commits": [ { @@ -4378,249 +5690,420 @@ "be93687618e4b132087f430a4d8fc3a609c9b77c" ], "authored_date": "2016-01-19T14:43:23.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:43:23.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" + }, + { + "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": "--- /dev/null\n+++ b/test\n", - "new_path": "test", - "old_path": "test", + "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 - } - ], - "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" - } - }, - { - "id": 10, - "target_branch": "test-6", - "source_branch": "test-7", - "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, - "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.", - "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": 1271, - "note": "Quod ut ut quisquam et ut dolorem dolor.", - "noteable_type": "MergeRequest", - "author_id": 1, - "created_at": "2016-03-22T15:20:32.093Z", - "updated_at": "2016-03-22T15:20:32.093Z", - "project_id": 5, - "attachment": { - "url": null }, - "line_code": null, - "commit_id": null, - "noteable_id": 10, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Administrator" - } - }, - { - "id": 1270, - "note": "Sed deserunt et explicabo rem repellat voluptatem.", - "noteable_type": "MergeRequest", - "author_id": 3, - "created_at": "2016-03-22T15:20:32.070Z", - "updated_at": "2016-03-22T15:20:32.070Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 10, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } - }, - { - "id": 1269, - "note": "Veritatis architecto omnis consequatur et optio.", - "noteable_type": "MergeRequest", - "author_id": 4, - "created_at": "2016-03-22T15:20:32.046Z", - "updated_at": "2016-03-22T15:20:32.046Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 10, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Julius Moore" - } - }, - { - "id": 1268, - "note": "Omnis suscipit odio molestiae debitis quia autem magni.", - "noteable_type": "MergeRequest", - "author_id": 10, - "created_at": "2016-03-22T15:20:32.019Z", - "updated_at": "2016-03-22T15:20:32.019Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 10, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } - }, - { - "id": 1267, - "note": "Molestias est sunt est tempora consequatur cupiditate magnam.", - "noteable_type": "MergeRequest", - "author_id": 12, - "created_at": "2016-03-22T15:20:31.993Z", - "updated_at": "2016-03-22T15:20:31.993Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 10, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } - }, - { - "id": 1266, - "note": "Ratione blanditiis eveniet voluptatem nostrum rerum excepturi in molestiae.", - "noteable_type": "MergeRequest", - "author_id": 22, - "created_at": "2016-03-22T15:20:31.969Z", - "updated_at": "2016-03-22T15:20:31.969Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 10, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 0" - } - }, - { - "id": 1265, - "note": "Illo voluptatibus vel odio ea.", - "noteable_type": "MergeRequest", - "author_id": 24, - "created_at": "2016-03-22T15:20:31.944Z", - "updated_at": "2016-03-22T15:20:31.944Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 10, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 2" - } - }, - { - "id": 1264, - "note": "Earum veritatis quis facere itaque iure.", - "noteable_type": "MergeRequest", - "author_id": 26, - "created_at": "2016-03-22T15:20:31.919Z", - "updated_at": "2016-03-22T15:20:31.919Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 10, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 4" - } - } - ], - "merge_request_diff": { - "id": 10, - "state": "collected", - "st_commits": [ { - "id": "b42bb86cea49bdcef943e521584b7f417d8ddd3d", - "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" - } - ], - "st_diffs": [ + "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", @@ -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,159 +6178,12 @@ "deleted_at": null, "notes": [ { - "id": 1279, - "note": "A corrupti nesciunt pariatur ea.", - "noteable_type": "MergeRequest", - "author_id": 1, - "created_at": "2016-03-22T15:20:32.307Z", - "updated_at": "2016-03-22T15:20:32.307Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 9, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Administrator" - } - }, - { - "id": 1278, - "note": "Adipisci aut ut et voluptate numquam.", - "noteable_type": "MergeRequest", - "author_id": 3, - "created_at": "2016-03-22T15:20:32.281Z", - "updated_at": "2016-03-22T15:20:32.281Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 9, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } - }, - { - "id": 1277, - "note": "Adipisci voluptatem quod ut placeat repellendus deleniti.", - "noteable_type": "MergeRequest", - "author_id": 4, - "created_at": "2016-03-22T15:20:32.255Z", - "updated_at": "2016-03-22T15:20:32.255Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 9, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Julius Moore" - } - }, - { - "id": 1276, - "note": "Vitae et doloremque aut et aspernatur velit placeat sed.", - "noteable_type": "MergeRequest", - "author_id": 10, - "created_at": "2016-03-22T15:20:32.230Z", - "updated_at": "2016-03-22T15:20:32.230Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 9, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } - }, - { - "id": 1275, - "note": "Quos cupiditate nesciunt expedita aspernatur.", - "noteable_type": "MergeRequest", - "author_id": 12, - "created_at": "2016-03-22T15:20:32.207Z", - "updated_at": "2016-03-22T15:20:32.207Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 9, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } - }, - { - "id": 1274, - "note": "Optio rem inventore dicta praesentium sit.", - "noteable_type": "MergeRequest", - "author_id": 22, - "created_at": "2016-03-22T15:20:32.181Z", - "updated_at": "2016-03-22T15:20:32.181Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 9, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 0" - } - }, - { - "id": 1273, - "note": "Sit incidunt molestiae maxime officiis rerum necessitatibus.", - "noteable_type": "MergeRequest", - "author_id": 24, - "created_at": "2016-03-22T15:20:32.159Z", - "updated_at": "2016-03-22T15:20:32.159Z", - "project_id": 5, - "attachment": { - "url": null - }, - "line_code": null, - "commit_id": null, - "noteable_id": 9, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 2" - } - }, - { - "id": 1272, - "note": "Autem ut non itaque molestiae nisi quia officiis doloribus.", + "id": 825, + "note": "Aliquid voluptatem consequatur voluptas ex perspiciatis.", "noteable_type": "MergeRequest", "author_id": 26, - "created_at": "2016-03-22T15:20:32.129Z", - "updated_at": "2016-03-22T15:20:32.129Z", + "created_at": "2016-06-14T15:03:00.722Z", + "updated_at": "2016-06-14T15:03:00.722Z", "project_id": 5, "attachment": { "url": null @@ -4832,9 +6194,180 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { + "author": { "name": "User 4" - } + }, + "events": [ + + ] + }, + { + "id": 826, + "note": "Itaque optio voluptatem praesentium voluptas.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 9, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 3" + }, + "events": [ + + ] + }, + { + "id": 827, + "note": "Ut est corporis fuga asperiores delectus excepturi aperiam.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 9, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 0" + }, + "events": [ + + ] + }, + { + "id": 828, + "note": "Similique ea dolore officiis temporibus.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 9, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] + }, + { + "id": 829, + "note": "Qui laudantium qui quae quis.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 9, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] + }, + { + "id": 830, + "note": "Et vel voluptas amet laborum qui soluta.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 9, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] + }, + { + "id": 831, + "note": "Enim ad consequuntur assumenda provident voluptatem similique deleniti.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 9, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] + }, + { + "id": 832, + "note": "Officiis sequi commodi pariatur totam fugiat voluptas corporis dignissimos.", + "noteable_type": "MergeRequest", + "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 + }, + "line_code": null, + "commit_id": null, + "noteable_id": 9, + "system": false, + "st_diff": null, + "updated_by_id": null, + "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 23036ab810..a72aaa44e8 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 8d29b2f8fd..a75eaa4d51 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 109522fa62..b76e14deca 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 590a9a7e1a..135e99bc95 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 b9ffc8694a..b628da0f3e 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 6a53ed1db6..69c4905115 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 fbb5895c2e..1fca8a1303 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 795cf24127..e8b236426e 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 7fc34139ef..6bd7393aaa 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 2753aecc1f..56bf08e704 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 de55334118..59024d3290 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 c59dfea5c5..c4c107c9ee 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 ae55a01ebe..aa382f930d 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 d84f3e998f..2ea1320267 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 8154001cf4..e817178887 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 9830787696..96eee0e8bd 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 89730ab8eb..60e4bbc856 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 6445e29c3e..c3af7a0960 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 5d0bd31db5..d9df9e0f90 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 3b817608ce..fa1a0d4e0c 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 2c19aa3f67..a878ff1b22 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 1b987588f5..b3aed66a5b 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 e9134a3d28..40181a8b90 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 bbf65edb27..4c10346243 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 4e68ac5e63..5f68cd2b06 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 c951732454..5a97cf370d 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 6ecab645b4..46dedb66c7 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 d305cd9ff1..a8c777d1e3 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 d8350000bf..851b8b241d 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 2f000dbc01..96bbbec9ea 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 f22db61e74..8302595388 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 ed78d582bd..72a6d45f47 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 6668f3543f..2da01da7fa 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 881b818b5e..5262a62376 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 437c89c357..fcea45f19b 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 3973677998..0404cf31ff 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 bacd01f8e7..65c53211dd 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 41b5ed9bc3..611dd2a2a8 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 bf7eaaaaae..a2446e1280 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 f756101c51..684c2cd8e2 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 0000000000..92a4fa216c --- /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 056256a29f..e43e3e269b 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 bae56334be..82ab582bea 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 b5ed8584c8..8b19936ae6 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 538f44e4f3..620f328a11 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 de13c0db5d..8a8e131c57 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 afa89b8417..eca8ddd8ea 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 2bb9c3b3db..6367ac832e 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 f99ad046f0..afabeed4a8 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 a63656e626..a4fcd44882 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 31b93850c7..7d5cb87606 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 776a6ab5ed..54719cbb8d 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 4c5ced7e74..bd4dc6a0f7 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 068c9a1219..d5d4d7c56e 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 d5aa115a07..57c71544df 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 b43f38ef20..606da1b760 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 5ebe095743..f3ea206f38 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 426bf53f19..9f9ef20f99 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 25da091713..d2c056d8e1 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 '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') + context 'tar creation' do + before do + create_backup 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 + after do + FileUtils.rm(@backup_tar) + 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') 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 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 - - context 'registry disabled' do - let(:enable_registry) { false } - - it 'should not create registry.tar.gz' do + it 'should set correct permissions on the tar contents' do tar_contents, exit_status = Gitlab::Popen.popen( - %W{tar -tvf #{@backup_tar}} + %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).not_to match('registry.tar.gz') + 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}') + ) + + expect(temp_dirs).to be_empty + end + + 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 '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 include repositories in all repository storages' do + tar_contents, exit_status = Gitlab::Popen.popen( + %W{tar -tvf #{@backup_tar} repositories} + ) + expect(exit_status).to eq(0) + 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 0000000000..cd18d19ef5 --- /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 b8e73682c9..20b1a343c2 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 7e59bd2fce..5785a6a06f 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 4ef05eb29d..5f762282b5 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