diff --git a/.rubocop.yml b/.rubocop.yml index dbdabbb9d4cb6adb83fd661c836e0b529b92e157..cd13f58151753603489087ffaae90fb9a58afa6d 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 eb5a5f7fcf48f060096ab3a5ea8a286e2471f72d..8efdcd2453ee40036b1c8d053fe66dce33014978 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 4a36342fcab700951adb18ae7adc930997f6c3f4..fd2a01863fdd3035fac5918c59666363544bfe23 100644 --- a/GITLAB_SHELL_VERSION +++ b/GITLAB_SHELL_VERSION @@ -1 +1 @@ -3.0.0 +3.1.0 diff --git a/Gemfile b/Gemfile index 52de9ef981309dea29ab0f68997a429e41d59c71..d622af6b0a396173d6ef818a24b65abb051c3fa6 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 4c5350ba63988c92adc54b9229466ab81b2f05da..45cb327168c8fa3041ba43156ef0417ab6b952af 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 b6dbf2d0cc1dba0cf57537da7775e82004ca350c..20fe5a5cc2733962fc3e893aa3dc04d42d66d046 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 4f73d215b8561a2a391a026bd177e99ca0fe8fd2..b76d214790af2bd459d95d45b5e8b73de5729cb5 100644 --- a/app/assets/javascripts/flash.js.coffee +++ b/app/assets/javascripts/flash.js.coffee @@ -4,11 +4,19 @@ class @Flash @flash.html("") innerDiv = $('<div/>', - class: "flash-#{type}", - text: message + class: "flash-#{type}" ) innerDiv.appendTo(".flash-container") + textDiv = $("<div/>", + class: "flash-text", + text: message + ) + textDiv.appendTo(innerDiv) + + if @flash.parent().hasClass('content-wrapper') + textDiv.addClass('container-fluid container-limited') + @flash.click -> $(@).fadeOut() @flash.show() diff --git a/app/assets/javascripts/gfm_auto_complete.js.coffee b/app/assets/javascripts/gfm_auto_complete.js.coffee index 190bb38504c97c66af697c6962ca17085d717b55..b7d040bae85895455afeff3105f3feeeebbd28ce 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 b0edc8956498d17e5b2733e88021b4b3136d3e8e..eb046eb2eff90b60ab308459cb2548260c7d0987 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 c03877e9b0697a6d5fe86d154505dee6361db98f..3319a67a79d9037d2a5cc6c0f33642f4f0413094 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 de8eebcd0b2c6c14a456bba0ceebadac817522b3..83de584f2d92ab6240a340cac8e2a05a5e25de67 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 1bfd0213995c45b4bdbd034803eb41b7dbc928bc..a951a2b97fe2baaf7d12ad6b42aa9583afebfa58 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 fd8eaa8a691a3ee7679bce034d865bc831382b71..5d3273ea64ddc8c50012b8ce6aadf0ccb42a9812 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 c74682dfef4db1ada19bb6fac2366d5aa010e449..367c7d019441b4c5500ec106914ab05c9070cb60 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 87f8a17659fce4d8562740f4d9b1f840e62a3902..211a9af23483261cdf41dfbe7dce567e90e2ff44 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 de534d284219326d0184ee708d92fbae3bfdc1fa..85bbf70e1883efead710d5b8bdd2f3dcc4d1e8b1 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 101faf5917430cead44c9c2b3f7c76d1652fd440..3d79f4400e24a0a73eb853610b71d50fb67d698e 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 89ce1b2df2093a8b6f327496cc59e577abc92334..817c2982923c22cd94ec6cfba263cfe838c7caca 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 99c9e81ddb9acd69e4788756d14d97a6bfbb7b99..5b61270daa8ddeb2c18104a01beb131f1c9cdfcd 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 f4eda864aac9285bc7ca588d4d90f731615f53ab..5f65dd3aff08942c433529328f8ec9e413decbb7 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 a6db4690df03f3993c46348b86fcb50dd7ca6425..94b5aaa71d076b6f440357a96ec7290c987976d2 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 4e85b6b4cf200026c1207a68f98e14726dc16655..cbfc4581411031a7f81cdd01e9c4e43a345971a3 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 87986fdf8b13625397bfd40bfac4130e9c6c17db..4c9c6362ffc591e53076b7d48956e67f6931dd84 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 bf20c5305a7b9d821cd1d11491cdf206043e5477..bc65dcc33d3c582a097f4d17d69a6cbf4e45f5c6 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 3c67370b667beb7bf44ab593a0d5df9c0c0bbb87..e4c730088269169b3b5b3953d77e1e540b6776f7 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 8bf71a1adbb15e9cda1e38c85de3f23d0d122c02..aa894fde36b8fc978b0aeeb311c48618d8fd10fd 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 52dc396af6af21f8b050ce361300edd5b3e64c6d..52682ef9dc9833eeb9d79665900137e4314ed4d6 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 7b66ad3f92c5e72042afbb8a18273cf8fae429d2..3da44b9b8880780814422288583d3df51c499596 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 2c49fe3833ecceb4d5970b720053e45fb1c0bf7e..9fc41a125364f74a8b0f7651fcb4cb995d01d02c 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 93a7ace3530b87b976b5e79ea58b6c20730965b1..7e8597a5eb3afe098348335198208b4834f709e4 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 18300390851edcc3d2177ecd253951466b6e159b..99b10b2f9b35b3f1970f377cb1895d840b799693 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 67bf4190e7e66ca5b84fc27cb8cb4b96f378fab0..9c1b0eb20f43e005011e89889b41ca55c66844b1 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 eecbe380c9e7f7da752020f67833519bfb7c7f71..a4c4ad230279d342b8e8ef43b135a4552b95c0a2 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 e0de31f225146f61172b8d7d1984552fda48f2f6..8d0de158f98e47024912edda5a08160e2c88fb4c 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 94bb108c5f58228de0f2c5c8883bf377e971ebcc..58964a0e65d7677e14790f7b2ca63a1038ffa184 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 f907d63258b19e20e27be07f83c365dde9f5cd67..62c3fa8de531a75f4ac77067b99cd299c61b2d72 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 8b8df6807397b8fb8048686bfa16f13ec6c5e3c1..b6e80762e3c5a00637c60af3957d856c34861d76 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 b181c47baecf9b4d0fdc64095f01756a62e1ffd4..34318391dd909e3603ff5869dd61d336b2aae730 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 6ba32d33403afb8fd11346ee5ba5c1ff98db3ea0..3435a1189647e71c6eb2b20890f3caa86e6fffeb 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 dc1a18f8d4209aa393520e0d59e12ef02af139f3..8267b14941dff11bf55e96e456b30710cbf05545 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 6d2901a24a4cedc2438b874a380c684fffe949ff..6d0a7ee10317da6f66b3a24018f237fee8b0d1d6 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 7ec1e73b3be8e8db673959d5b025f84e66193ed7..607fe9c7fed02d8bccc9af787ccea1284c4ed544 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 2b1f50fd01ef89ab0b4b63689131c55a2f464716..12e0d5a84132a2c74e0d36ecbbab9eefd4028b46 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 58a00f88af76c1b821cc232a5e3b6feab3c7dd5c..7806d9e4cc50fe46d9f7e599ef62f28896f8fbd0 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 55313fd835763e593826961c924687123ad8eb19..6e580c62ccd74aea671b5a13699c379eb74b8013 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 6b617e1730a627be19dcfd7adddc94ac81a0a821..7c140538012e5be23d0235b684cee67291426976 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 8466d0aa0ba3233d399ae421275a963e1626a1e1..2843ad96efadbb2dd63495db80c8e402febb7fa6 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 8231ce49fac335b65f535474e95d51bfbe36ad75..294b7e92b8ddb15f499b193441dfcdec19857fcf 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 0000000000000000000000000000000000000000..f5b0aa7549a23643de7f60c15999c1f73852ca72 --- /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 5074e645769bda3ded7e3c6dc9309279c9423d0d..5e9f5837101608e60e80a160736bec970e2989cd 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 ec106418f2dc4f69b051688ab30ab1dcd8fa59d4..c70cd19b587a50ced7651c19cee33251ad4678e9 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 b401c8385beeb2798f54222d89a890b7c7a92c55..e85ba76887d72873ca27d46ec77a010876a6638b 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 e4e8b934bc8299d64d640e0b18411cb3d74f8871..22387d664518a9a55e79448d29339da1837ae8c5 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 d91e3332e4879afa9086609f1ab35df3953f1b70..f312a7ccca3618f59f60e139e72af2d5d2eca10f 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 d2f94d4ae6ff4b3db16ad7b62a43d7999d18a437..f9fc525df6fd8d81877fd37a34efff0f601bbb94 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 f5950879ccb5ce3637c12d228d61bbbab2b11190..ba1f2ae40752c3558b68471bbdb9759192d68e59 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 d914b0b26eb40206c631d115c3d43f98cbc1977c..5fa6eacd23453868df893fb54c5a7572b6c3a879 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 2b0bec33131a5c6979d3b17cd7f9029e3dcd9ee7..c11f8e6884dc8935d39bd1a368d3874fdb8bf26f 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 d6f55885dd6c57200361905aa82806a5e92f8e5d..acb6f5a2998bfd07b6497302e6d333862f320684 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 c70c719e33856d4e24c7d17b2ac876e27616788f..a8be7004ee82b5bab3533c40442341d3fd2e8139 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 3c5859194b40fc4c5d04042e258b1022f873f718..60abd47409e5bc51dbab480bbeb4192f44723814 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 57161397e2bc244bea742a65c070f88d1b82b473..44db3d977faf05c922e088c5073b48939b0202a2 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 e9d3a82ba15b3c6112c89816801b17a739cd7a57..f39afc61ce95ae5086f1d0b1f07d027b73ee1059 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 53d9aa588af8bba38d0279f7ac4d50774f686606..5ebc8f0c99feb4a1461e7772bfce4f4f70cd04a0 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 e0c8454a9985738267f59e1dd1ce75cae9fec7ea..2bd7f1980306197886e0159267d6caa26dd74281 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 da19462f2652ffe92182394dd3b45e4b3e091e0b..8b52cc824cd6c860cbf9af349cd7575bdb58170b 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -21,8 +21,10 @@ class Namespace < ActiveRecord::Base delegate :name, to: :owner, allow_nil: true, prefix: true - after_create :ensure_dir_exist after_update :move_dir, if: :path_changed? + + # Save the storage paths before the projects are destroyed to use them on after destroy + before_destroy(prepend: true) { @old_repository_storage_paths = repository_storage_paths } after_destroy :rm_dir scope :root, -> { where('type IS NULL') } @@ -87,51 +89,35 @@ class Namespace < ActiveRecord::Base owner_name end - def ensure_dir_exist - gitlab_shell.add_namespace(path) - end - - def rm_dir - # Move namespace directory into trash. - # We will remove it later async - new_path = "#{path}+#{id}+deleted" - - if gitlab_shell.mv_namespace(path, new_path) - message = "Namespace directory \"#{path}\" moved to \"#{new_path}\"" - Gitlab::AppLogger.info message - - # Remove namespace directroy async with delay so - # GitLab has time to remove all projects first - GitlabShellWorker.perform_in(5.minutes, :rm_namespace, new_path) - end - end - def move_dir - # Ensure old directory exists before moving it - gitlab_shell.add_namespace(path_was) - if any_project_has_container_registry_tags? raise Exception.new('Namespace cannot be moved, because at least one project has tags in container registry') end - if gitlab_shell.mv_namespace(path_was, path) - Gitlab::UploadsTransfer.new.rename_namespace(path_was, path) - - # If repositories moved successfully we need to - # send update instructions to users. - # However we cannot allow rollback since we moved namespace dir - # So we basically we mute exceptions in next actions - begin - send_update_instructions - rescue - # Returning false does not rollback after_* transaction but gives - # us information about failing some of tasks - false + # Move the namespace directory in all storages paths used by member projects + repository_storage_paths.each do |repository_storage_path| + # Ensure old directory exists before moving it + gitlab_shell.add_namespace(repository_storage_path, path_was) + + unless gitlab_shell.mv_namespace(repository_storage_path, path_was, path) + # if we cannot move namespace directory we should rollback + # db changes in order to prevent out of sync between db and fs + raise Exception.new('namespace directory cannot be moved') end - else - # if we cannot move namespace directory we should rollback - # db changes in order to prevent out of sync between db and fs - raise Exception.new('namespace directory cannot be moved') + end + + Gitlab::UploadsTransfer.new.rename_namespace(path_was, path) + + # If repositories moved successfully we need to + # send update instructions to users. + # However we cannot allow rollback since we moved namespace dir + # So we basically we mute exceptions in next actions + begin + send_update_instructions + rescue + # Returning false does not rollback after_* transaction but gives + # us information about failing some of tasks + false end end @@ -152,4 +138,33 @@ class Namespace < ActiveRecord::Base def find_fork_of(project) projects.joins(:forked_project_link).find_by('forked_project_links.forked_from_project_id = ?', project.id) end + + private + + def repository_storage_paths + # We need to get the storage paths for all the projects, even the ones that are + # pending delete. Unscoping also get rids of the default order, which causes + # problems with SELECT DISTINCT. + Project.unscoped do + projects.select('distinct(repository_storage)').to_a.map(&:repository_storage_path) + end + end + + def rm_dir + # Remove the namespace directory in all storages paths used by member projects + @old_repository_storage_paths.each do |repository_storage_path| + # Move namespace directory into trash. + # We will remove it later async + new_path = "#{path}+#{id}+deleted" + + if gitlab_shell.mv_namespace(repository_storage_path, path, new_path) + message = "Namespace directory \"#{path}\" moved to \"#{new_path}\"" + Gitlab::AppLogger.info message + + # Remove namespace directroy async with delay so + # GitLab has time to remove all projects first + GitlabShellWorker.perform_in(5.minutes, :rm_namespace, repository_storage_path, new_path) + end + end + end end diff --git a/app/models/network/graph.rb b/app/models/network/graph.rb index a2aee2f925bca3f13769243b312d25168cdcee9c..345041a6ad18b233cb77a5a016ab5cd5ba670a49 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 8db500a521997532333cf5843870dfcc84c81092..c2bb117eb03c5cb23809b111d9fa3ee0908949e6 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 73ded09c162ed50b3ba1d71c2cb12bb526730d05..ae96f00a7057f70534c36166f9ad057e04ac1f17 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 260f60309576112905a5aa37598730310729e081..81af55aa29adeb17b6edaf2bfed4624dbd8cba50 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 8f2db46a7ba3832effcdeb8a28ce82e8e5e3839f..63a5ed144841a16c8e6d185f2f08754d3418984b 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 966dbc41d737ed7155863cc364ece180858569c8..5e4dd101c53e6a9713f50168cc4a8fcc10224160 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 0ff4f4c8dd2cd9e41295cbb95b2b071db64efa1c..23e5b16221bfb34f957c628c6b2c1432ec181091 100644 --- a/app/models/project_services/hipchat_service.rb +++ b/app/models/project_services/hipchat_service.rb @@ -106,7 +106,7 @@ class HipchatService < Service else message << "pushed to #{ref_type} <a href=\""\ "#{project.web_url}/commits/#{CGI.escape(ref)}\">#{ref}</a> " - message << "of <a href=\"#{project.web_url}\">#{project.name_with_namespace.gsub!(/\s/,'')}</a> " + message << "of <a href=\"#{project.web_url}\">#{project.name_with_namespace.gsub!(/\s/, '')}</a> " message << "(<a href=\"#{project.web_url}/compare/#{before}...#{after}\">Compare changes</a>)" push[:commits].take(MAX_COMMITS).each do |commit| diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb index 87ecb3b8b868d2fad8211cbdbe74cbd4c634fd42..d1df6d0292f84c0da475268a696d665d469a3f39 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 beda89d396317adf94b70a435d18ee2d6a50de35..27bf08bf7d928a9937cc7ce15953e76669d62512 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 11cce3e0561f827f6023dce431ca2afc6957416c..f634e0772c0480d1dff2e925b167c8ef650e0fb1 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 0865b979ce052cf6dc56e45db69e4e77f553199d..0b700930641e32cd8021399fbe8455fb6f79cf43 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 25d82929c0b1ff454f6f8cb53e5be8f75fdb3a99..a255710f57711952d797d5ae5a8af20f27c0d579 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 2a6a3b086c200282120f5bf5a0e3c4c67b336d85..11ecb281a559a7522806746a247731936ea19166 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 2792fa9b9a8a1c00a55fb470a30678a8e780935d..3ba67078d481572f8678ef8755c3bb7211fad836 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 767d6366c79fcda2f98e87e916752cf9bf727eb0..5036a3e300c9d2bc98b7257055c742085261be97 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 e06a6f2f47a4d391a0bdc5ccfcf98e9fddb3f337..f029db72d405ff622168c64e6eec37a2f3232c0d 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 772f5c5fffad6b69f302f2578b405ae14d88e225..089b0f527e21262e8ade9957c7e34f83317cbf3d 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 bc93ba2552d185ab235c0f1c16b46d50ade2cd3a..bc3606a14c27ea3e95ee73470d8e3c920794f7c6 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 12edfb2d671c258d875721c7087e2ed0669e5ad8..870f5705184a7806fe0152373291f56a9ff85ce1 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 2414966505bf9b82cbba7c7a06f20a4c12685aa9..e457212508f311cdee24ebe6490082429d9e2d64 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 f09072975c3e9a109b18b00d7103984962dcbeb6..882606e38d0e9c907bfc8e56a1ed0ff65b7575c6 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 6386f57fb0d3357a40f46fe14c493ecde197fdec..f06a3d44c175e41b2e31a52f0003e83ebe4e5038 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 43db29315a166cb3b2360765831a7c5e6220ff2d..a47df22f1bacbe51a3f760b5d3de9316effa4b7e 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 80c7193efcb1dff5d78e0ff8512db201a5a2ea82..3f507d5c4003e5620536846645c1748d9c94f799 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 9159ec089593d122f9168de7c9a62a014cd1c2a2..163ebf26c84393982360b8f7652ae47d989bac3b 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 03b57dea51e4d4a9c8f83fa3d0ab8306ed19c3df..bc7f8bf433b6ed5f77bfdc8310fb0d0fa92c9b50 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 4e8fa0818b9e2a06f51ed438a87b8dd23c48e407..b868d2e7e83bb9a880b977400c1e178a0fdea72a 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 25eb13ef09a4312a95ca0b7f1dd86bb1451d3f67..0c0f68d169bea398b72c09c15ee6afa2f8206f8b 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 4c0a2c6b4d834c744a69bb0759bb010a5403d2d3..14317ea65c8454e6d834736953d65ba8146b5cb0 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 28085b310837712ae030988964280158950e0dee..046a1d641a92c7e77b07e99dc5d2e23346e75dd9 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 30ab07171642ca704e8aa05c42b291d24a261d6e..c1f70bc1866a65c38b0362fab15bea0536f52a2a 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 654d261aa997712ba25441fe84508af1ad453ea0..4f680b507c493983d66295c120aebebd6610f200 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 efd5b12cfeb4b182be40679949312c992ad1c9c8..1e60205f91a1e605540e9977d4d91c9c0f3d40ec 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 4682016a8862378246759a91f7332315993f81c9..a2ac407c159b79d2d6e765538486b454bee659d3 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 4f1996ef7ab26de3b261d36ba04aac4540df1f4a..94aa5f5a942f81626e12b2c8af0610c2b3219a9b 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 50770465f0780144a42bfe175cc30d01c62b9125..522153b37e3d30aab8aa2cd79a85caa80193c408 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 7b8407f9152ea221deb516a4d10be2c442e59da0..e79303240f0d6b08deb827865fb0d221ae356617 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 5ddc3b9ea85111de9f622ecbf53f3575da5cde04..676812121d773d2901c1b7ca0e3237975a53bbaf 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 4822cb693c2d2b2a99b8fe1ea67bee5b37a8a3a2..7d2eb423223cb02cdaf1a88ef9ceb12d4786e1ef 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 461d588415db7b8cc52d8527d0ad23eaeba63f5d..82d3169c6f9626cd6bb42a1c0c53b10ee1747950 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 36b21eefdee8ddc25286fc242595c0fec1dcba42..64893b38c58deef0c7f0f8c28cabc1c346173e2c 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 5eff77aff2db1dd8ce994c47ce7d78ca9ba53a32..a53876d67573d3e767473aacb1635be1292d304a 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 3ef2f20b589cb87f3be0d7b2f35188a2ebc5373d..6956e5ab7958a003ae5eead0e8789b5a4daf0e20 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 d0a696da64b98d7ab6fd136437adc2502bf9d935..21bb99a792c4fac69e78569e1916e7820c5f998c 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 d6acade84f1ce6957b0717044c3641884f4ea582..90f362c052be70f24ba822a0d6e8bfaa02cbf5dd 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 a0a6762edcf4a9ed150f9171949ccb8887d781dc..a83eb7e88bb3a001e2eb90807742df5808d74570 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 57bc91ea5a95c76e02554ebfdbd7cd8fa2299793..57601ae9be0970a173f57489beba03099964052c 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 dfebf7768d9a7d4509daf401cd2aae5696e45b81..804ad88468f31c205c2c88d82f1a04a3c30fb12f 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 0000000000000000000000000000000000000000..435ed7bd4cb5c7b339a9cf5112f06dae345e9fbe --- /dev/null +++ b/app/views/import/github/new.html.haml @@ -0,0 +1,43 @@ +- page_title "GitHub Import" +- header_title "Projects", root_path + +%h3.page-title + = icon 'github', text: 'Import Projects from GitHub' + +- if github_import_configured? + %p + To import a GitHub project, you first need to authorize GitLab to access + the list of your GitHub repositories: + + = link_to 'List Your GitHub Repositories', status_import_github_path, class: 'btn btn-success' + + %hr + +%p + - if github_import_configured? + Alternatively, + - else + To import a GitHub project, + you can use a + = succeed '.' do + = link_to 'Personal Access Token', 'https://github.com/settings/tokens' + When you create your Personal Access Token, + you will need to select the <code>repo</code> scope, so we can display a + list of your public and private repositories which are available for import. + += form_tag personal_access_token_import_github_path, method: :post, class: 'form-inline' do + .form-group + = text_field_tag :personal_access_token, '', class: 'form-control', placeholder: "Personal Access Token", size: 40 + = submit_tag 'List Your GitHub Repositories', class: 'btn btn-success' + +- unless github_import_configured? + %hr + %p + Note: + - if current_user.admin? + As an administrator you may like to configure + - else + Consider asking your GitLab administrator to configure + = link_to 'GitHub integration', help_page_path("integration", "github") + which will allow login via GitHub and allow importing projects without + generating a Personal Access Token. diff --git a/app/views/layouts/_init_auto_complete.html.haml b/app/views/layouts/_init_auto_complete.html.haml index 96b3848542590e30c57305255026880e979565b9..12e7ed0e792be75ebfb04955795c57a0ef3eee05 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 3a24b09ab7eda3ec0e3b99186d3cf15f4255e56a..bf9a7ecb78679cfa46ee9708bc38f91d71ee6f0d 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 dcef427cda30fca32f8199f6b783ebedbffd8698..9e65d94186b99924eee01a1a224803ebcddaf923 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 46ad1559356ea26ece89af7db6548264e02a6721..0000000000000000000000000000000000000000 --- 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 86ea08dd229a81f83b807a3ea40886388bed1126..540efa4780f72856125746cf14c6dfaeab5d37a6 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 e0ca2a3109cd97ca8be9c456f6cc672bc2c40f68..434d8644b831e81c884daa565a0664d4ecb041f2 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 ed670dae88d9f91ab9c4cbfc10d0a53a0080e923..0ab78a39cf9a98f85370a7d71b53fde427fe4dbb 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 e0367c40272bf92cb4f7536cb2573f17631887a5..77b405f1f3977f1d7b51d4ebc35442bb0b03bd98 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 181547316aabcfe76b347344b4a5ae36a1dfecf0..a131289ee97d9e0767c3fb15a24d795a95928e21 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 4e2702c2e445fedbf77c6078484ce9d590b1b2cf..d1c468c46927efe4eadba8bd82ff581bb46575c8 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 51ca4eb903e547f333847e0db156c918ea0605ef..9a44ba94970cbba016f37bbbd064c9ec9a4ef1ec 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 b22285c11e0df9b55c6681dde869c927460c4bff..e9ff8e90dd56989b1f6577fd0ab6307cedbe5e64 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 f4ec7b767f63e1c67469f13d747454753d265502..28a50e7031a14ca45ebd6b329c0d57627b4af008 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 a03f117291f6d12eaed18e1867551ab6279ac1c8..5242021243e7d5b5debe12886f0ab38bc510f92f 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 4c15e2759d6033b60284d406e8b57f414e93a430..53c62ef234d4549ac7cb3582932ebaf79489cca2 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 e695d3ae369ca92585e9288acbd3d3dfe376287e..6be4273b6abbdae6aa19c0dcfc5516c2ece29943 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 0daffe68f6fd55fe7c001c983d9fbc708a809fe9..65db8af494d4926cc93a12bd46840c9875a9fee4 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 6d97f552a8e83f28b64b6fd1c806405d2ece3c48..fcfcae0be2098df40bd7c76e10e2fd4906faef3c 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 9f7e2a361ff7ddca93806b1f4b02d8659816a53c..a985b442b2d6e6c303c701d1cd702f4c2c948916 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 a8a8caf728036728c601804cad75f5a6e5f9b80f..2cd8d03e30e9f20c86692304e50620de485f6152 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 cd876b5ea62d5aa58f65fc54278c44dd90108dcc..7ce4c1e555568ac146276f0d6452f659267c1c11 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 aa4d69550ec6b6cfc728e03970ffbc5b7b441741..db66a0edbd8f399469c2464e40cfd375a7c3c7ee 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 9f948d41ddaf8a963d3b0388d60d9da9d4bf7a0a..ace275c689b8770e1ae420c6802ecfca86424a32 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 b0e0bdfff5ad60ca8d6eb8b7ee2e1dd00ae72321..ad2bfbec915d57387d843b5e38c398925faccbbf 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 86295a3d0110034cda2efe4602b1c5a7672b8b33..8f6805268d506b581c40001ea697a8a3042b94a9 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 3ca30b4ba6b5cff8aab9bdd463ce409434d9921d..091af4df4a1fdec89a70598301a9c8166d40dc73 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 8a73b0773574ae66ade3ef51b36a59c0c2a5a486..05f33b78a47e4e0394b1a17a91c4543acc0c1055 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 a5e163b91e90821d22b1738c1e16265988fdbf99..af0046886fbbeab813e1c1bb70f9260a97eea64f 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 b70693eeb62923d748691fe1b7398342ac623d7d..28b475d5c2f8aecb1cc5d2aa4ab5d453d5e05cd5 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 840b57c2e6364b6af6db350808a17862f914b206..77370c14def6276cfb408d853c0136d097e40bba 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 a2026c41d014df9c90bf5f75a90819b9a35df365..9031f01b496d51c94e62ee659843436b4fc572d3 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 15f0d85194b899ee1da71875e0a30b31603891bd..f6e81af26386c8802af6170d8dd2a0286dc797b1 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 4ca1f58ac5c35cd116d57f8bbeed15611b275e7e..c375bb6dd1b37a09745e93d124677ea5c2bc7e15 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 2abcfcdd7b27d0fe66f56b085674e9a8d2031041..bf5360b4deee9195834eca9859419a845d3ad686 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 4f8abcdc8e1a167b7b9908d3e011941ee4317785..c32cb122c26fe33b8e4f263fff88275f7033fab2 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 817bf9b3f69d898379d36084da08ceb00186b581..233538bb488cff19f8c1606c02ea9cb36c8dacfe 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 6caf7230f350d6ee4c3f5f471947bf40e1ab1105..b8811a28dd66cce0c58e3d57a6be4423415e617d 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 630ee35b70b9473104e764209db9a0f699ebee35..4c0b14e2c420e4bda836fc70760051077c6cf62a 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 81d9f391c1c50f435282afe30a2a3dec4f474416..9c10acd4cb6b6373ab937cd01f4277524f61a05e 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 76f9b1ecd762b7ddda0e9a6e4735331491754af9..5cebb538cf563d51cf2fc97779a4eda0bc94b4f5 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 87028ececd4bf21d4d1ee917c2909b5bff206957..5507a05f6c1f4690afdc794678f70716a7d40641 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 480e8ba6c8545e422644025dffb363c6f6fa2114..35dcdccc92122cd0ec16fd3c16159a34015bdd2d 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 e4bd2bdc265d4f40365293ac6a03bce8223feaf6..40b39e850b00844cc1dd923452d6a6cde6567ef7 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 f3327ca9e61909f117fee35a63ba4daf8c5b1a5b..09035a7cf2daaaef53c1e531d1e8e8d9e9b25888 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 d947f1055160b7f4ae23d6d1c42ee8d74e17ea25..f7604e48f8320778277c4140d3d10629502f20a4 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 436a2c5e17a76a4921faa1c2bbf65a2b0c76df04..293f2b71d65df0d4d3a85a4c49d4af45a466283c 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 8cca0039b4af0da69f7491b6cd3d46038a7a7558..45a8c1add3e44917cdb1f396015eb86eb74b72e9 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 01c8dc5ff98e2cd278ccea0a1146131a69958137..75b79b837e0c75a3dd9c1fa3bd9b10fae294fa86 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 75e1a3c1093343ffe062df4efa988c8f0603d86f..325eca72862841ab5c8d251edebfba41388b485c 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 c6dc1e4ab38da2b2a162c878665d82ef7bbbc1e9..51d93e8cde088b9abf4ae114f098ae8d4eaf554c 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 0000000000000000000000000000000000000000..3ba9e36c567c13aaacd8018524052358cbb7c0f5 --- /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 021bdb11251103fdee823492d0e8dfa0ca0c5f86..73977341b73ae679c5382f7c0390be6d39bd778c 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 751fccead07c09537c7820da47a16cf2c01dcaa3..7454c33c9ddafd5ee0694b415eb602722096d109 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 75f89d524e71543b73c24883dec1b4ed9be14e74..44601f2b2bde5a428daac152a6ae2f0f23101288 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 30d05f1615381e5fd7de7bfe12be323aba4836c1..69052c029f24d478fafdb4d85f524ca345a912fc 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 7a2b9a7f6c1cfffb3fb51f6edd5b858bbd3931e6..593c14a289fa4b831a907522a038d669fa76827b 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 d256a16d42b803ba6274905a3d2272c388180ae0..df4a933e22f3aec9aa9a35ec5794b1252705b097 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 bdfb16a66bf3188e0f65580992ac227b6e35216d..1572656b8c5f3eb1d57926e23bfde6c06616dd49 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -133,12 +133,12 @@ Rails.application.routes.draw do # resources :notification_settings, only: [:create, :update] - # # Import # namespace :import do resource :github, only: [:create, :new], controller: :github do + post :personal_access_token get :status get :callback get :jobs @@ -465,7 +465,6 @@ Rails.application.routes.draw do resources :namespaces, path: '/', constraints: { id: /[a-zA-Z.0-9_\-]+/ }, only: [] do resources(:projects, constraints: { id: /[a-zA-Z.0-9_\-]+(?<!\.atom)/ }, except: [:new, :create, :index], path: "/") do - member do put :transfer delete :remove_fork @@ -653,7 +652,7 @@ Rails.application.routes.draw do get '/wikis/*id', to: 'wikis#show', as: 'wiki', constraints: WIKI_SLUG_ID delete '/wikis/*id', to: 'wikis#destroy', constraints: WIKI_SLUG_ID put '/wikis/*id', to: 'wikis#update', constraints: WIKI_SLUG_ID - post '/wikis/*id/markdown_preview', to:'wikis#markdown_preview', constraints: WIKI_SLUG_ID, as: 'wiki_markdown_preview' + post '/wikis/*id/markdown_preview', to: 'wikis#markdown_preview', constraints: WIKI_SLUG_ID, as: 'wiki_markdown_preview' end resource :repository, only: [:show, :create] do diff --git a/db/migrate/20160608195742_add_repository_storage_to_projects.rb b/db/migrate/20160608195742_add_repository_storage_to_projects.rb new file mode 100644 index 0000000000000000000000000000000000000000..c700d2b569d2d074997a700cad33d28eaf2fb903 --- /dev/null +++ b/db/migrate/20160608195742_add_repository_storage_to_projects.rb @@ -0,0 +1,12 @@ +class AddRepositoryStorageToProjects < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + disable_ddl_transaction! + + def up + add_column_with_default(:projects, :repository_storage, :string, default: 'default') + end + + def down + remove_column(:projects, :repository_storage) + end +end diff --git a/db/migrate/20160614182521_add_repository_storage_to_application_settings.rb b/db/migrate/20160614182521_add_repository_storage_to_application_settings.rb new file mode 100644 index 0000000000000000000000000000000000000000..6dae91b700b866f54f7d7c8904ec9e2023c26bb9 --- /dev/null +++ b/db/migrate/20160614182521_add_repository_storage_to_application_settings.rb @@ -0,0 +1,5 @@ +class AddRepositoryStorageToApplicationSettings < ActiveRecord::Migration + def change + add_column :application_settings, :repository_storage, :string, default: 'default' + end +end diff --git a/db/schema.rb b/db/schema.rb index 7a8377f687c00aede850a1901fcd3414abdb3646..beb723c3bc584aa63bf86e35f214130dd201c640 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -85,6 +85,7 @@ ActiveRecord::Schema.define(version: 20160620115026) do t.boolean "send_user_confirmation_email", default: false t.integer "container_registry_token_expire_delay", default: 5 t.text "after_sign_up_text" + t.string "repository_storage", default: "default" end create_table "audit_events", force: :cascade do |t| @@ -796,38 +797,39 @@ ActiveRecord::Schema.define(version: 20160620115026) do t.datetime "created_at" t.datetime "updated_at" t.integer "creator_id" - t.boolean "issues_enabled", default: true, null: false - t.boolean "merge_requests_enabled", default: true, null: false - t.boolean "wiki_enabled", default: true, null: false + t.boolean "issues_enabled", default: true, null: false + t.boolean "merge_requests_enabled", default: true, null: false + t.boolean "wiki_enabled", default: true, null: false t.integer "namespace_id" - t.boolean "snippets_enabled", default: true, null: false + t.boolean "snippets_enabled", default: true, null: false t.datetime "last_activity_at" t.string "import_url" - t.integer "visibility_level", default: 0, null: false - t.boolean "archived", default: false, null: false + t.integer "visibility_level", default: 0, null: false + t.boolean "archived", default: false, null: false t.string "avatar" t.string "import_status" t.float "repository_size", default: 0.0 - t.integer "star_count", default: 0, null: false + t.integer "star_count", default: 0, null: false t.string "import_type" t.string "import_source" t.integer "commit_count", default: 0 t.text "import_error" t.integer "ci_id" - t.boolean "builds_enabled", default: true, null: false - t.boolean "shared_runners_enabled", default: true, null: false + t.boolean "builds_enabled", default: true, null: false + t.boolean "shared_runners_enabled", default: true, null: false t.string "runners_token" t.string "build_coverage_regex" - t.boolean "build_allow_git_fetch", default: true, null: false - t.integer "build_timeout", default: 3600, null: false + t.boolean "build_allow_git_fetch", default: true, null: false + t.integer "build_timeout", default: 3600, null: false t.boolean "pending_delete", default: false - t.boolean "public_builds", default: true, null: false + t.boolean "public_builds", default: true, null: false t.integer "pushes_since_gc", default: 0 t.boolean "last_repository_check_failed" t.datetime "last_repository_check_at" t.boolean "container_registry_enabled" - t.boolean "only_allow_merge_if_build_succeeds", default: false, null: false + t.boolean "only_allow_merge_if_build_succeeds", default: false, null: false t.boolean "has_external_issue_tracker" + t.string "repository_storage", default: "default", null: false end add_index "projects", ["builds_enabled", "shared_runners_enabled"], name: "index_projects_on_builds_enabled_and_shared_runners_enabled", using: :btree diff --git a/doc/README.md b/doc/README.md index be0d17084c7f6dcaac3cb6f3c6fb96356a848c30..b98d6812a81556af24b59e8f9cb67d38f3d82d76 100644 --- a/doc/README.md +++ b/doc/README.md @@ -34,6 +34,7 @@ - [Operations](operations/README.md) Keeping GitLab up and running. - [Raketasks](raketasks/README.md) Backups, maintenance, automatic webhook setup and the importing of projects. - [Repository checks](administration/repository_checks.md) Periodic Git repository checks. +- [Repository storages](administration/repository_storages.md) Manage the paths used to store repositories. - [Security](security/README.md) Learn what you can do to further secure your GitLab instance. - [System hooks](system_hooks/system_hooks.md) Notifications when users, projects and keys are changed. - [Update](update/README.md) Update guides to upgrade your installation. diff --git a/doc/administration/repository_storages.md b/doc/administration/repository_storages.md new file mode 100644 index 0000000000000000000000000000000000000000..81bfe173151eb183a42993e3eb6fefb59c6533c1 --- /dev/null +++ b/doc/administration/repository_storages.md @@ -0,0 +1,18 @@ +# Repository storages + +GitLab allows you to define repository storage paths to enable distribution of +storage load between several mount points. + +## For installations from source + +Add your repository storage paths in your `gitlab.yml` under repositories -> storages, using key -> value pairs. + +>**Notes:** +- You must have at least one storage path called `default`. +- In order for backups to work correctly the storage path must **not** be a +mount point and the GitLab user should have correct permissions for the parent +directory of the path. + +## For omnibus installations + +Follow the instructions at https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/configuration.md#storing-git-data-in-an-alternative-directory diff --git a/doc/api/README.md b/doc/api/README.md index 288f7f9ee6998ac75a0a4adc5cee086068a80f31..d1e6c54c521f55cb99bcc646a90160870dd9f138 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 708fc691f679673b703de2598e68380c45bcb9f0..3ced787b23e7cadf3b240a69b7787f15a0c45a83 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 2930f615fc17655aff28e82aa35f001a224983ab..f60b0d0ebc68b6a2631594d87696558db7bbcd7d 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 b5152311f2814284e43de14a2153ea950703e8c7..741c5a295818e5f22fb85ae2c244ffbb0ac2703d 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 0000000000000000000000000000000000000000..29e736644107b8840cae47815b6575a950e1759a --- /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 27bc21c2922d6e6aaba18a4e93424c8020b9736a..c134106bfd0eb631d80230913b63fb42abba3b5d 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 8a38937062e003b658d54d081539f00029735543..2b305cb5c991f7cb83eed7c37d171509e9e3ad4c 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 e9641cb4f85b9112a2ab2bfc4868081fe28caaae..5c9b510ba9ded53271e25134779e766f5602bab0 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 1a316e80976d8c3e80932831680809139f71b103..9b50286b179dd4c4f4d9e31aefea11449b674768 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  -## 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 ffede8e9bd68495ad70e5ac2b12fc47d7da03260..5202434f00f6a8eef27a2ce9a58de2b6572a5767 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 ff0ac8747a7cde212a2cc01581ea656bd7294b82..0eec5cb937d01f011618b92ccc516589b1d9cf1f 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 99d7a326ed897d328154d3b8f959a7b2da9ba228..b7de830a78057a2e73262c7205f835ef0bcc71d2 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 a7dfac2c12066139773216e2e93f0a2b256b31be..a2b2a4b88f9d6690d525c207fa01be3d50f1958c 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.  diff --git a/features/dashboard/new_project.feature b/features/dashboard/new_project.feature index 56b4a639c015f9a3b26babde961de28f0fc77c26..8ddafb6a7ac13c6b41789c92f9ee89462d539f5c 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 31f8924c38c38c04e563bfb01a154240b1146d09..727a6a71373ac3b3f80c6289babfe30256b0927e 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 cb6fa8a47da7e9aab8faf9002a521feec3c44ad1..2b4a5ab08642fe7d4f212148e423230a9c8f6996 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 483370f41c6f775cc43f5081aacd392ff96bbd60..4fa7d7c656775b03cc8669ae6b6593a9bf723d26 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 db1387763d59615058a522d1d15ff9baa4d01cb5..b6f1d417e21a620540a7b19f101e0e375300c8aa 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 0ead83d6937d9660c5316716f1615eee73496181..6b56a77b832b99eebfdc3421344fa279a9aad8f7 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 439363e6f141d6b15142bb04af886275f5a267e5..35f166c7c08bc5196f10dd17c754d127b0f9b8f6 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 90771847909e1c3bb3677a1f3c4cc0285fb72f34..b8da5e6435d5ed3e1db50ffc6039b8535267675d 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 c6572cf386ef50affab220c37c30feafcb302640..b5fd24d246f20d357aee49bc3956a7b48e981639 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 cf999879579a1f9429829601387b530080ec47d5..32e29ffad1e2b5831b330558f40caac93057a4b4 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 edc08cf0986a5397a69c2f82f128c7c36e4a8e1b..ab3f0ca7aeb8d70beb684c64358f0028c3fa26ea 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 c3fff8b2f8f11de5349e1af8e069fe0583d1b198..3d7d67510a83ac12c19114400671e8b5f2c70e26 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 985590312e36cac46a9a1759606669922214eac4..c4fa1838b5a4bb1e3db6f0cf4eeedffcf983a477 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 231840148d97bb2b1cd5762eb2547a04131e3eec..d467eb9d4742c31a7a07c4783a860d3cc18b85b3 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 086d8511e8ffafd3da92cb007058719701eb79be..d36047acd1f65c03a11d39a67c1ded42f20ebd2d 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 5a23a18fe9c7e22dda765b9b86130f26276a609e..8cc4368b5c26e56ca1658378cdd64d0d8919bfa5 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 ab9b7c602b5dc728f206b05a2f8edac8face4b50..dbe5bb08d3ff05bf22e8de31acbd80ee8967c175 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 1d361569d595c623b4ea178df6c0905e2f9b0216..b32503e8516b7608eae864a99e46be97d89818db 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 132043cf3f7d6a917950cd571d5717cbdd00b877..7a0cb7c99f32a33e216acd92c2da6e2f6fc6128c 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 ccca65cbe1cdf17febadf23e70f6336648a5d2e8..6bb70bc8bc39dc19c299000ba6adb69124de97fb 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 b703da0557a095a2a14f0b4338fac8d7e8a9d95d..6a0b3e7d134321ff5c8c15d0e32aa5d847a1af45 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 5a22d14988f4a0f1b4fd767865b2915d3327efe6..0cc1edd65c83566d96b91a83be01c3fdec70de68 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 203f04a6259203b46ed4ebca5168c6053c0409d5..fc8598daa323b56df0f0d9dc0a9fd7ef10408694 100644 --- a/lib/api/services.rb +++ b/lib/api/services.rb @@ -4,7 +4,6 @@ module API before { authenticate! } before { authorize_admin_project } - resource :projects do # Set <service_slug> service for project # diff --git a/lib/api/tags.rb b/lib/api/tags.rb index 3e1ed3fe5c76b806fc6860cac1fd7caca2fd16c0..7b675e05fbb7be686d47945d991edc5c3546280d 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 0000000000000000000000000000000000000000..2a6bfa98ca4c666c002dcf12fd2fecfbd4252f58 --- /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 7b91215d50b6f17118917404ae5a01089bdd5bd1..b9773f98d752a7c8ea4a077c387f8b3776a1bd57 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 81d66271136ab19f7006f1d1bb130fa42de5c6cf..d77a5e3ff09099ef5047d2d0517702d75ed595ef 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 8aa6f8f124a8e0ccbad7493a7a80c78390f5e2cf..f0fb6084a35e3cea7cd7ae8a24bee854469e1e17 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 5351272f42d0b4ce514d9f06a17e0968e90f767e..4042e9a4c250f0bc29c307ba73451cbff6d5564f 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 2d6f34c9cd8633fec321e97241b5e556e9981765..bf058241cda706d8896b8ad76ab2103b3cc26375 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 62a79c62e20ef90183a8e2f3d7ee8d3ea2ef17d0..536b478979f78ad64babe872bf3f1baf18d4f199 100644 --- a/lib/banzai/filter/syntax_highlight_filter.rb +++ b/lib/banzai/filter/syntax_highlight_filter.rb @@ -27,12 +27,17 @@ module Banzai highlighted = "<pre>#{code}</pre>" end - # Replace the parent `pre` element with the entire highlighted block - node.parent.replace(highlighted) + # Extracted to a method to measure it + replace_parent_pre_element(node, highlighted) end private + def replace_parent_pre_element(node, highlighted) + # Replace the parent `pre` element with the entire highlighted block + node.parent.replace(highlighted) + end + # Override Rouge::Plugins::Redcarpet#rouge_formatter def rouge_formatter(lexer) Rouge::Formatters::HTMLGitlab.new( diff --git a/lib/banzai/filter/wiki_link_filter.rb b/lib/banzai/filter/wiki_link_filter.rb index 1bb6d6bba87da3d426b7756d6fe51f8336ed1494..269d5bf74fa973603cf498e1ed990b362a51e70e 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 d47ddfda4be60cd4a163b77b8bee191697974ec8..3c974f731762c9cac1975843bc0491c5038de636 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 5270108ef0fd0a73d4bf023c4e3166de98310506..1d7126a432df01f854a8af361d2219564c1eda3a 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 1b80be112a436dfad99e68a4b6a8a1ab6d5373ba..cee664b8951958b8cc9525f28ac694c17ef04496 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 37f4c34054fedace368980ef3acf70f822e171c7..c3064163e076d0c3a2a7d0e8cff0f1a9033cc51e 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 0b9c2e730f9c6d91542fb36cf21b73d61f9c7009..1a22ad9acf5e70e46137a37d3c84746cb38381f8 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 51b1df9ecbd86a878771c7a664f4ea11d91217cd..c94bfc0e65ff751232d869c355f7e59289175d77 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 ab7b811c5d81c59e3d45194c3f91f35c3c1c9abd..478f145bfedaf9782c3fccc433775e889d3528f0 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 3e3986d63827811c894e741869c09f1fadb64da1..34e0143a82ee793bce189617e36fd9cce4ff4306 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 28c34429c1f910527216d5771485119ec581167a..54b46e5d23f8eb3571d1c0c098560dbe6a0d248c 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 522dd2b942897de3cea13eda428b41403d5a33ae..59a2367b65d2b01d2e9394e0e3d4302e01c701a9 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 d325eca6d99cd4ab6a6d0a967a8a0b3a1b305803..043f10d96a953192f84668446005377c2d92fbf4 100644 --- a/lib/gitlab/github_import/client.rb +++ b/lib/gitlab/github_import/client.rb @@ -4,26 +4,39 @@ module Gitlab GITHUB_SAFE_REMAINING_REQUESTS = 100 GITHUB_SAFE_SLEEP_TIME = 500 - attr_reader :client, :api + attr_reader :access_token def initialize(access_token) - @client = ::OAuth2::Client.new( - config.app_id, - config.app_secret, - github_options.merge(ssl: { verify: config['verify_ssl'] }) - ) + @access_token = access_token if access_token ::Octokit.auto_paginate = false + end + end + + def api + @api ||= ::Octokit::Client.new( + access_token: access_token, + api_endpoint: github_options[:site], + # If there is no config, we're connecting to github.com and we + # should verify ssl. + connection_options: { + ssl: { verify: config ? config['verify_ssl'] : true } + } + ) + end - @api = ::Octokit::Client.new( - access_token: access_token, - api_endpoint: github_options[:site], - connection_options: { - ssl: { verify: config['verify_ssl'] } - } - ) + def client + unless config + raise Projects::ImportService::Error, + 'OAuth configuration for GitHub missing.' end + + @client ||= ::OAuth2::Client.new( + config.app_id, + config.app_secret, + github_options.merge(ssl: { verify: config['verify_ssl'] }) + ) end def authorize_url(redirect_uri) @@ -56,7 +69,11 @@ module Gitlab end def github_options - config["args"]["client_options"].deep_symbolize_keys + if config + config["args"]["client_options"].deep_symbolize_keys + else + OmniAuth::Strategies::GitHub.default_options[:client_options].symbolize_keys + end end def rate_limit diff --git a/lib/gitlab/github_import/importer.rb b/lib/gitlab/github_import/importer.rb index 2286ac8829c9813ca17e60670e0aecc3b85046b9..730978d502b501b613c59299cda2beca9145f85f 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 99cf85d9a3b07bd5c2d4555679c6a0a1dcdf0ae3..588647e5adb6e47859360958306d8f0fc08756da 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 164ab6238c44ef74cfd15b5b73dde1a77b58d605..05f4ad527ac356ca14130690202d9a626e9d3f45 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 595b20a09bd34911a5f79c1d1f823ffd6fffd624..8f66f48cbfeff88fb39d6fb63b294d51e5e4ec52 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 c569a35a48bcae3b042bb2326fd28ba57651ab79..b459054c198a0c826f457bdfbebb7d934a2337a4 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 89388d1984b2f57b9cfd1072df2eba2c36c548b0..77bb3ca65819da60393486b2be793e367374fc13 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 dd71b92c5229db96d56ac383cdf83436aa875b00..0ac6ff01e3beb7dc4bdd7cf5cbbaf403c191ae95 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 19defd8f03a0c08a3b527d8d0afbf36bc89d8c4e..15f5dd31035ca9cd43efbddeb983f8faf030bd25 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 92bf7e0a2fced86608459b2a6ccbcdad35aa176a..9824df3f2748a0e80678886e6c60f50dfd821a59 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 6aff05b886a011c230bc5649a394be5ca48a8c85..5d6de8bc47576463a815aadb6e55a3fbfa77a506 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 7292e9d9712bb878266734bb590496d0c12ae1dd..d6f4fa5751055e8aaca02a95e835852fe616c059 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 cf5c62c5e3c14c6e6ec851f8d782c36c1c175ec7..abfc694b87947ec165b4189b988209719bf98f42 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 f7f73dc9343a04f5c39263e0c4a2e464d917a253..9b642d740b7c6087e5fe20b490337bae2616b4b6 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 948d43582cf7551b8aa08a9246daaccf1895a504..59a05411fe9dc36395087ced47fb0ecc3e9bfd59 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 8684b4636ea1fbb80c6f7bf68a33ff9fdd8ee924..b75ae512d9264ca42828078265764fb0c116edf3 100644 --- a/lib/gitlab/key_fingerprint.rb +++ b/lib/gitlab/key_fingerprint.rb @@ -39,7 +39,7 @@ module Gitlab # OpenSSH 6.8 introduces a new default output format for fingerprints. # Check the version and decide which command to use. - version_output, version_status = popen(%W(ssh -V)) + version_output, version_status = popen(%w(ssh -V)) return false unless version_status.zero? version_matches = version_output.match(/OpenSSH_(?<major>\d+)\.(?<minor>\d+)/) diff --git a/lib/gitlab/lfs/response.rb b/lib/gitlab/lfs/response.rb index e3ed2f6791d5dc852538c964f9e0e87055a29cfa..811363405a813110f1ee5df06e3b24a9a57ac5b3 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 36e5c2670bbf04c1c8b0f3fe897a371f8156f58f..7d6911a1ab3e19fc8f25b6bdd122f62c642fcbfb 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 746ec2833308622d2af1ec8b0a2ce8022a56b9a2..4e2f8ed55877c03a1e6dcd67e36e260fe49948dc 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 c84c68f96f63714078fb915000dd525a445c91c6..ffad5e17c78394f621e9a4514b0b7a32d31ebef6 100644 --- a/lib/gitlab/regex.rb +++ b/lib/gitlab/regex.rb @@ -13,7 +13,6 @@ module Gitlab "Cannot start with '-' or end in '.'." \ end - def namespace_name_regex @namespace_name_regex ||= /\A[\p{Alnum}\p{Pd}_\. ]*\z/.freeze end @@ -22,7 +21,6 @@ module Gitlab "can contain only letters, digits, '_', '.', dash and space." end - def project_name_regex @project_name_regex ||= /\A[\p{Alnum}_][\p{Alnum}\p{Pd}_\. ]*\z/.freeze end @@ -32,7 +30,6 @@ module Gitlab "It must start with letter, digit or '_'." end - def project_path_regex @project_path_regex ||= /\A[a-zA-Z0-9_.][a-zA-Z0-9_\-\.]*(?<!\.git|\.atom)\z/.freeze end @@ -42,7 +39,6 @@ module Gitlab "Cannot start with '-', end in '.git' or end in '.atom'" \ end - def file_name_regex @file_name_regex ||= /\A[a-zA-Z0-9_\-\.\@]*\z/.freeze end @@ -59,7 +55,6 @@ module Gitlab "can contain only letters, digits, '_', '-', '@' and '.'. Separate directories with a '/'. " end - def directory_traversal_regex @directory_traversal_regex ||= /\.{2}/.freeze end @@ -68,7 +63,6 @@ module Gitlab "cannot include directory traversal. " end - def archive_formats_regex # |zip|tar| tar.gz | tar.bz2 | @archive_formats_regex ||= /(zip|tar|tar\.gz|tgz|gz|tar\.bz2|tbz|tbz2|tb2|bz2)/.freeze diff --git a/lib/gitlab/saml/auth_hash.rb b/lib/gitlab/saml/auth_hash.rb index 32c1c9ec5bb7ad8c1227e6a0f3cf2425c1fc9807..67a5f368bdb5ec6c2b439564bfed42441ce53853 100644 --- a/lib/gitlab/saml/auth_hash.rb +++ b/lib/gitlab/saml/auth_hash.rb @@ -1,7 +1,6 @@ module Gitlab module Saml class AuthHash < Gitlab::OAuth::AuthHash - def groups get_raw(Gitlab::Saml::Config.groups) end @@ -13,7 +12,6 @@ module Gitlab # otherwise just the first value is returned auth_hash.extra[:raw_info].all[key] end - end end end diff --git a/lib/gitlab/saml/config.rb b/lib/gitlab/saml/config.rb index 0f40c00f547470eb55dcaf9af81f14f170f06b03..574c3a4b28c33c1f72b00fd52a9543cba0b393f8 100644 --- a/lib/gitlab/saml/config.rb +++ b/lib/gitlab/saml/config.rb @@ -1,7 +1,6 @@ module Gitlab module Saml class Config - class << self def options Gitlab.config.omniauth.providers.find { |provider| provider.name == 'saml' } @@ -15,7 +14,6 @@ module Gitlab options[:external_groups] end end - end end end diff --git a/lib/gitlab/saml/user.rb b/lib/gitlab/saml/user.rb index 8943022612ceae6129aeb268e1026362e78f7e32..f253dc7477e7a31a2c6af33c2f9c38337dfd1843 100644 --- a/lib/gitlab/saml/user.rb +++ b/lib/gitlab/saml/user.rb @@ -6,7 +6,6 @@ module Gitlab module Saml class User < Gitlab::OAuth::User - def save super('SAML') end diff --git a/lib/tasks/gitlab/backup.rake b/lib/tasks/gitlab/backup.rake index 9ee72fde92f021c9669ac39b1ced24bfe375c5d7..b43ee5b338312ee2e13bc824ce0f23bbe6c1092d 100644 --- a/lib/tasks/gitlab/backup.rake +++ b/lib/tasks/gitlab/backup.rake @@ -33,12 +33,13 @@ namespace :gitlab do unless backup.skipped?('db') unless ENV['force'] == 'yes' - warning = warning = <<-MSG.strip_heredoc + warning = <<-MSG.strip_heredoc Before restoring the database we recommend removing all existing tables to avoid future upgrade problems. Be aware that if you have custom tables in the GitLab database these tables and all data will be removed. MSG + puts warning.color(:red) ask_to_continue puts 'Removing all tables. Press `Ctrl-C` within 5 seconds to abort'.color(:yellow) sleep(5) diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index 12d6ac45fb6d0a75008f35b6cc7306b12a6c51d0..e9a4e37ec484b9063ee0d4aa6b3d3eab5b5d0305 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -356,97 +356,108 @@ namespace :gitlab do ######################## def check_repo_base_exists - print "Repo base directory exists? ... " + puts "Repo base directory exists?" - repo_base_path = Gitlab.config.gitlab_shell.repos_path + Gitlab.config.repositories.storages.each do |name, repo_base_path| + print "#{name}... " - if File.exists?(repo_base_path) - puts "yes".color(:green) - else - puts "no".color(:red) - puts "#{repo_base_path} is missing".color(:red) - try_fixing_it( - "This should have been created when setting up GitLab Shell.", - "Make sure it's set correctly in config/gitlab.yml", - "Make sure GitLab Shell is installed correctly." - ) - for_more_information( - see_installation_guide_section "GitLab Shell" - ) - fix_and_rerun + if File.exists?(repo_base_path) + puts "yes".color(:green) + else + puts "no".color(:red) + puts "#{repo_base_path} is missing".color(:red) + try_fixing_it( + "This should have been created when setting up GitLab Shell.", + "Make sure it's set correctly in config/gitlab.yml", + "Make sure GitLab Shell is installed correctly." + ) + for_more_information( + see_installation_guide_section "GitLab Shell" + ) + fix_and_rerun + end end end def check_repo_base_is_not_symlink - print "Repo base directory is a symlink? ... " + puts "Repo storage directories are symlinks?" - repo_base_path = Gitlab.config.gitlab_shell.repos_path - unless File.exists?(repo_base_path) - puts "can't check because of previous errors".color(:magenta) - return - end + Gitlab.config.repositories.storages.each do |name, repo_base_path| + print "#{name}... " - unless File.symlink?(repo_base_path) - puts "no".color(:green) - else - puts "yes".color(:red) - try_fixing_it( - "Make sure it's set to the real directory in config/gitlab.yml" - ) - fix_and_rerun + unless File.exists?(repo_base_path) + puts "can't check because of previous errors".color(:magenta) + return + end + + unless File.symlink?(repo_base_path) + puts "no".color(:green) + else + puts "yes".color(:red) + try_fixing_it( + "Make sure it's set to the real directory in config/gitlab.yml" + ) + fix_and_rerun + end end end def check_repo_base_permissions - print "Repo base access is drwxrws---? ... " + puts "Repo paths access is drwxrws---?" - repo_base_path = Gitlab.config.gitlab_shell.repos_path - unless File.exists?(repo_base_path) - puts "can't check because of previous errors".color(:magenta) - return - end + Gitlab.config.repositories.storages.each do |name, repo_base_path| + print "#{name}... " - if File.stat(repo_base_path).mode.to_s(8).ends_with?("2770") - puts "yes".color(:green) - else - puts "no".color(:red) - try_fixing_it( - "sudo chmod -R ug+rwX,o-rwx #{repo_base_path}", - "sudo chmod -R ug-s #{repo_base_path}", - "sudo find #{repo_base_path} -type d -print0 | sudo xargs -0 chmod g+s" - ) - for_more_information( - see_installation_guide_section "GitLab Shell" - ) - fix_and_rerun + unless File.exists?(repo_base_path) + puts "can't check because of previous errors".color(:magenta) + return + end + + if File.stat(repo_base_path).mode.to_s(8).ends_with?("2770") + puts "yes".color(:green) + else + puts "no".color(:red) + try_fixing_it( + "sudo chmod -R ug+rwX,o-rwx #{repo_base_path}", + "sudo chmod -R ug-s #{repo_base_path}", + "sudo find #{repo_base_path} -type d -print0 | sudo xargs -0 chmod g+s" + ) + for_more_information( + see_installation_guide_section "GitLab Shell" + ) + fix_and_rerun + end end end def check_repo_base_user_and_group gitlab_shell_ssh_user = Gitlab.config.gitlab_shell.ssh_user gitlab_shell_owner_group = Gitlab.config.gitlab_shell.owner_group - print "Repo base owned by #{gitlab_shell_ssh_user}:#{gitlab_shell_owner_group}? ... " + puts "Repo paths owned by #{gitlab_shell_ssh_user}:#{gitlab_shell_owner_group}?" - repo_base_path = Gitlab.config.gitlab_shell.repos_path - unless File.exists?(repo_base_path) - puts "can't check because of previous errors".color(:magenta) - return - end + Gitlab.config.repositories.storages.each do |name, repo_base_path| + print "#{name}... " - uid = uid_for(gitlab_shell_ssh_user) - gid = gid_for(gitlab_shell_owner_group) - if File.stat(repo_base_path).uid == uid && File.stat(repo_base_path).gid == gid - puts "yes".color(:green) - else - puts "no".color(:red) - puts " User id for #{gitlab_shell_ssh_user}: #{uid}. Groupd id for #{gitlab_shell_owner_group}: #{gid}".color(:blue) - try_fixing_it( - "sudo chown -R #{gitlab_shell_ssh_user}:#{gitlab_shell_owner_group} #{repo_base_path}" - ) - for_more_information( - see_installation_guide_section "GitLab Shell" - ) - fix_and_rerun + unless File.exists?(repo_base_path) + puts "can't check because of previous errors".color(:magenta) + return + end + + uid = uid_for(gitlab_shell_ssh_user) + gid = gid_for(gitlab_shell_owner_group) + if File.stat(repo_base_path).uid == uid && File.stat(repo_base_path).gid == gid + puts "yes".color(:green) + else + puts "no".color(:red) + puts " User id for #{gitlab_shell_ssh_user}: #{uid}. Groupd id for #{gitlab_shell_owner_group}: #{gid}".color(:blue) + try_fixing_it( + "sudo chown -R #{gitlab_shell_ssh_user}:#{gitlab_shell_owner_group} #{repo_base_path}" + ) + for_more_information( + see_installation_guide_section "GitLab Shell" + ) + fix_and_rerun + end end end @@ -473,7 +484,7 @@ namespace :gitlab do else puts "wrong or missing hooks".color(:red) try_fixing_it( - sudo_gitlab("#{File.join(gitlab_shell_path, 'bin/create-hooks')}"), + sudo_gitlab("#{File.join(gitlab_shell_path, 'bin/create-hooks')} #{repository_storage_paths_args.join(' ')}"), 'Check the hooks_path in config/gitlab.yml', 'Check your gitlab-shell installation' ) @@ -785,13 +796,13 @@ namespace :gitlab do namespace :repo do desc "GitLab | Check the integrity of the repositories managed by GitLab" task check: :environment do - namespace_dirs = Dir.glob( - File.join(Gitlab.config.gitlab_shell.repos_path, '*') - ) + Gitlab.config.repositories.storages.each do |name, path| + namespace_dirs = Dir.glob(File.join(path, '*')) - namespace_dirs.each do |namespace_dir| - repo_dirs = Dir.glob(File.join(namespace_dir, '*')) - repo_dirs.each { |repo_dir| check_repo_integrity(repo_dir) } + namespace_dirs.each do |namespace_dir| + repo_dirs = Dir.glob(File.join(namespace_dir, '*')) + repo_dirs.each { |repo_dir| check_repo_integrity(repo_dir) } + end end end end @@ -799,12 +810,12 @@ namespace :gitlab do namespace :user do desc "GitLab | Check the integrity of a specific user's repositories" task :check_repos, [:username] => :environment do |t, args| - username = args[:username] || prompt("Check repository integrity for which username? ".color(:blue)) + username = args[:username] || prompt("Check repository integrity for fsername? ".color(:blue)) user = User.find_by(username: username) if user repo_dirs = user.authorized_projects.map do |p| File.join( - Gitlab.config.gitlab_shell.repos_path, + p.repository_storage_path, "#{p.path_with_namespace}.git" ) end diff --git a/lib/tasks/gitlab/cleanup.rake b/lib/tasks/gitlab/cleanup.rake index ab0028d6603013ad73ef92fdf97ac643282e6fdc..b7cbdc6cd78f2901cf7aeee2d3b8771886cf793f 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 4753f00c26ab76512a3033c939e04e6e2a49bb8b..dbdd4e977e8becc230551f32abbda26a691ab8b6 100644 --- a/lib/tasks/gitlab/import.rake +++ b/lib/tasks/gitlab/import.rake @@ -2,73 +2,73 @@ namespace :gitlab do namespace :import do # How to use: # - # 1. copy the bare repos under the repos_path (commonly /home/git/repositories) + # 1. copy the bare repos under the repository storage paths (commonly the default path is /home/git/repositories) # 2. run: bundle exec rake gitlab:import:repos RAILS_ENV=production # # Notes: # * The project owner will set to the first administator of the system # * Existing projects will be skipped # - desc "GitLab | Import bare repositories from gitlab_shell -> repos_path into GitLab project instance" + desc "GitLab | Import bare repositories from repositories -> storages into GitLab project instance" task repos: :environment do + Gitlab.config.repositories.storages.each do |name, git_base_path| + repos_to_import = Dir.glob(git_base_path + '/**/*.git') - git_base_path = Gitlab.config.gitlab_shell.repos_path - repos_to_import = Dir.glob(git_base_path + '/**/*.git') + repos_to_import.each do |repo_path| + # strip repo base path + repo_path[0..git_base_path.length] = '' - repos_to_import.each do |repo_path| - # strip repo base path - repo_path[0..git_base_path.length] = '' + path = repo_path.sub(/\.git$/, '') + group_name, name = File.split(path) + group_name = nil if group_name == '.' - path = repo_path.sub(/\.git$/, '') - group_name, name = File.split(path) - group_name = nil if group_name == '.' + puts "Processing #{repo_path}".color(:yellow) - puts "Processing #{repo_path}".color(:yellow) - - if path.end_with?('.wiki') - puts " * Skipping wiki repo" - next - end + if path.end_with?('.wiki') + puts " * Skipping wiki repo" + next + end - project = Project.find_with_namespace(path) + project = Project.find_with_namespace(path) - if project - puts " * #{project.name} (#{repo_path}) exists" - else - user = User.admins.reorder("id").first + if project + puts " * #{project.name} (#{repo_path}) exists" + else + user = User.admins.reorder("id").first - project_params = { - name: name, - path: name - } + project_params = { + name: name, + path: name + } - # find group namespace - if group_name - group = Namespace.find_by(path: group_name) - # create group namespace - unless group - group = Group.new(:name => group_name) - group.path = group_name - group.owner = user - if group.save - puts " * Created Group #{group.name} (#{group.id})".color(:green) - else - puts " * Failed trying to create group #{group.name}".color(:red) + # find group namespace + if group_name + group = Namespace.find_by(path: group_name) + # create group namespace + unless group + group = Group.new(:name => group_name) + group.path = group_name + group.owner = user + if group.save + puts " * Created Group #{group.name} (#{group.id})".color(:green) + else + puts " * Failed trying to create group #{group.name}".color(:red) + end end + # set project group + project_params[:namespace_id] = group.id end - # set project group - project_params[:namespace_id] = group.id - end - project = Projects::CreateService.new(user, project_params).execute + project = Projects::CreateService.new(user, project_params).execute - if project.persisted? - puts " * Created #{project.name} (#{repo_path})".color(:green) - project.update_repository_size - project.update_commit_count - else - puts " * Failed trying to create #{project.name} (#{repo_path})".color(:red) - puts " Errors: #{project.errors.messages}".color(:red) + if project.persisted? + puts " * Created #{project.name} (#{repo_path})".color(:green) + project.update_repository_size + project.update_commit_count + else + puts " * Failed trying to create #{project.name} (#{repo_path})".color(:red) + puts " Errors: #{project.errors.messages}".color(:red) + end end end end diff --git a/lib/tasks/gitlab/info.rake b/lib/tasks/gitlab/info.rake index 352b566df247a5a58f53ee9647df945777a114c4..fe43d40e6d23dac528ca1b3dc8f8185a049f7e00 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 c7596e7abcb72d33b1403f84c37a4f43dcf8362c..ffcc76e549891f1ff13051f35d146c968b08abfe 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 b1648a4602abab48320fdb1a0350017b722df1e9..c85ebdf8619b0072f1264b211a4119df3c8119d0 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 d0c019044b7eed695b8a82d2a810a799894e492f..ab96b1d35932c9802787ef65e6db2f189961993e 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 c5666d49e61d3cbc939f9ed6d56e404459b050a2..21c0e5f1d41c398765f2823cf0b3ec972dd4ae60 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 d4291f012d342ac6e0d86d1d1b3d024ffd7f2bf7..41dee5fdc06477d34e916358bb52cf2db9b721a2 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 0000000000000000000000000000000000000000..d9247a1f7ea379d4ceff88974b6408b47cec4948 --- /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 0000000000000000000000000000000000000000..97ee8b11044d293209e0f37811cb550a65b4b929 --- /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 0000000000000000000000000000000000000000..3160a784a042299eb5cc450ca09cd859eef96a36 --- /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 0000000000000000000000000000000000000000..7922e19768b6a75d3e788e5e4f4ad026f15469bc --- /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 10824c20c8724809ee4ecc2c9f5141574c7605be..8bd210cbc3dd4a5a4c095d681fd8f5070737e739 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 ddc54108a7b195d9f419b3057cf8e0d33859a8f7..c34475976c6367addda843969dbf21edb8086c79 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 c55a3c28208f7c66a5bb628597f9a921e2d6c112..51d595268541584acd3be7bb0164ef68788c28c1 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 2dc9adfd60ca8046369dc4629b259ce80ff24e39..18148acde3ef0b298c59928852f861aa8c89e4ca 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 f59d4937157c97812e3ddfcc38eb5c3d460ed5a0..644de308c644a23a93df4453404ff4eab1d04c83 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 70ed8f3a62e1d2addb47766fe0f606cbabdcdd9c..f66bcb8099cb37b8c00fa4f825c2f15177a66bad 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 ab1dd34ed575b74496832482bd1534ff8abc4377..3492b6ffbbb8f686eef5814608744e5ce65deb9d 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 74c050f48f1b80e4af72bb9048e3ae498fc65be4..eff74e1286926d86c07f58515e37f6cc8b38ff05 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 29aaceb23025a42b964a4633afa217022a2c6a0b..5e2a8cf38490ba81d46d6e900ecac8ca0da5be31 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 ee905d11fb2878ec631c81f96eaa7fe22ac7f5e5..2fe3c2635247dbca8209648d14bc556588ef1941 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 4e3a2bdb19e95e43c53a3f26d868d00415e47517..1cc050247c66d221a05c652eaad23dddd9e14d43 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 d60579030c070659216546e1c13e71f3bcfe9c40..1b1b1bdf52d23cd36845df856b25c12a71150513 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 8d6f486efddbe30607b7177a27f78e7706c29e5b..54a2d3d9460b651bc028dd9b0eb8222d8f6449dd 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 f426e27afedddc709c1d40d69a5f82e73abaa207..7fc20cd55557336e832f2ae115e98bce35b96a45 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 31633817d534afaf43ca777c76ad2d05aad3c8cc..7964951ae99c66996d496226ad272124d457167d 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 2d297776cb021a87aeea909c7a889d39159717f2..2f82fafc13aaaf0a62fd79afb1f3d10943c3869e 100644 --- a/spec/features/admin/admin_runners_spec.rb +++ b/spec/features/admin/admin_runners_spec.rb @@ -62,19 +62,45 @@ describe "Admin Runners" do end describe 'enable/create' do - before do - @project1.runners << runner - visit admin_runner_path(runner) + shared_examples 'assignable runner' do + it 'enables a runner for a project' do + within '.unassigned-projects' do + click_on 'Enable' + end + + assigned_project = page.find('.assigned-projects') + + expect(assigned_project).to have_content(@project2.path) + end end - it 'enables specific runner for project' do - within '.unassigned-projects' do - click_on 'Enable' + context 'with specific runner' do + before do + @project1.runners << runner + visit admin_runner_path(runner) end - assigned_project = page.find('.assigned-projects') + it_behaves_like 'assignable runner' + end + + context 'with locked runner' do + before do + runner.update(locked: true) + @project1.runners << runner + visit admin_runner_path(runner) + end + + it_behaves_like 'assignable runner' + end + + context 'with shared runner' do + before do + @project1.destroy + runner.update(is_shared: true) + visit admin_runner_path(runner) + end - expect(assigned_project).to have_content(@project2.path) + it_behaves_like 'assignable runner' end end diff --git a/spec/features/admin/admin_system_info_spec.rb b/spec/features/admin/admin_system_info_spec.rb index dbc1d829b674a8b45e15e160db3f3d54f063c2a4..f4e5c26b51918579b76041fd35ae40d7f8d973e6 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 cf86e2c85e95b51cb52e76f65e2b70f71b397495..c2e0612aef83dae64e379df9fbcbc8ebaee229cf 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 7852c39fee26553231d6efc000591e8927118eae..a89ac09f23692e81866c942674255b137454359a 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 321c9bad7d06db4790c3656c1bf138c51a1034fa..10d3713f19f7264582226365d3f98888340df6fa 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 4944301c938c61dfdbcb93535488c3451222c831..d1a6a98ab7219687b11406d02e3d624ecfa41505 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 4bcb105b17d76f044d24400ee9dfc786b5dcd57b..006a06b82350a6207a7093f19c35bce2672e8284 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 5065dfb849cf07d3471d5fe1adaaa81231e0adb7..d51c9abea19f061cbd71fed251da78aa94f85bf7 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 15c381c0f5a726e2fc8d6eef48ce3b09d024da7f..fcdf7870f34f2ffd889a50e4406ecb9df44b5323 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 f88c0616b52abd827b793bc9f2c98bb6c4dbb3c2..1b4ff6b6f1b15c4c13213bca3c9532e875027036 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 c5fb0fc783be1be6f9f6a463ac64e9b9f8b3dc41..9d66f76ef58b402304a7cadb64d1e7427dc27122 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 1fd04416d959363f9d348438c978330e58d2c704..7bb0d26b21c03d96db4363bd0543422bcf5df536 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 461f1737928908d57c42b524673a601d48b98034..81b0c991d4fb586513d054f0c31392b76815ca81 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 aa2d906fa2e9c09d025aed0629ec5731c1716dc5..f7fcd9b67313be821404ec7c6ff9088e50588dec 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 af420c170ef55aa96d9dcf0da0f690fceab66fd7..f2fe3ef364d0f777cabd24bdd1bef857a79ac762 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 b9e63a7152c74d7ee76a18606daf43cf8afe97cf..85923f0a19d851fdb0c66bd8aab503f1fbf368e4 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 71b783b7276ad1992c0dd8229d4e7f4dd896aa46..35fcef7a71279bff017d14c21586f5985ed6cc0a 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 cc9aee802f98b96877035cbefe97176a41c7a568..75a9334262837113db853097940476439323116a 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 db986683dbeaa42141f8edb5ebff346a0fd204d6..6c5ee93970b27f56d39a80d29ae91c6408fe60ce 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 4229e82b4438c5c1aea00153079cf3ef32a5b613..a752c1d7235aff87995af8a82a9889bfe3cf9d59 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 f0990118e3c04ab46cc3e101522690303610e6fc..0f30f562539ba6ad02d146281126337e1e724164 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 cf116040394fd289ca74c47a5569eec74c09fe62..b5a94fe03831fa43bd25a3808cfa9ec323317423 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 fdd3849816fae4a79d00f43b21b347be7c29861f..fbe09b28b3c1bff6de2c0cc458b1a3477b577f4c 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 810016c96583e5fe9bc1e7f4aa678d74f99ab483..28bdc18e8405e23c7ce61f64e5b587f8dd889154 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 f75fdb739f6891b0f547928043cc2210e19f30d0..7b2155e9a4e35b36a1dd43f9981f018d6efbb408 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 0000000000000000000000000000000000000000..08a9350325872fb451a6657f9791ba41ba4826c5 --- /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 09e0bbfd00b807f702bd336cc980a396975f56bb..604204cca0a4c3a6ce760694bd4101d50990fde0 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 5e7594170c5240c2ad859d83c34ab0bc22d8b6d3..db3ad1b99e97b4e26422ae414a7cd56e4b3d7cbd 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 0000000000000000000000000000000000000000..5178bd130f4c1748935693ddbae1266abf5f9448 --- /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 1bcae8a27dbfd851e283e088f7a3a8ad4b47b66c..47b4e431823a92041cc98e3b306ee9a2021ea317 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 4bb149f25ffe8961eb55157b2f2f1ff829f61e54..14c8df954a6fc7b41a8cf7be7f9f3b8e1e6ef25b 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 8d6ce114aa90be3ee4daf3b652e8dbe727d2f255..a005b4990e7937e9affaa6d651a430c98edc12f5 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 72bc6a0b704fff34fcbc295c5bb41eae58d0d1c7..51c89ac4889f0adf0bf3bc078de60299d9b3f510 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 9c6b4ea50861f095b1837bd2797abd656467b67a..97f2e97b062711776540b709949b38c6372c9b9c 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 2ca9f554b07d5dd21298a4fbfcb026412f90e4ea..ec658668c61b3687377272e06bdd6627b96d71de 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 736bf7872084af7b0a360d9f3382f20e97958a23..32ca8239845ef2474d9193f7de177a1d457b4c08 100644 --- a/spec/lib/gitlab/asciidoc_spec.rb +++ b/spec/lib/gitlab/asciidoc_spec.rb @@ -3,13 +3,11 @@ require 'nokogiri' module Gitlab describe Asciidoc, lib: true do - let(:input) { '<b>ascii</b>' } let(:context) { {} } let(:html) { 'H<sub>2</sub>O' } context "without project" do - it "should convert the input using Asciidoctor and default options" do expected_asciidoc_opts = { safe: :secure, @@ -24,7 +22,6 @@ module Gitlab end context "with asciidoc_opts" do - let(:asciidoc_opts) { { safe: :safe, attributes: ['foo'] } } it "should merge the options with default ones" do diff --git a/spec/lib/gitlab/award_emoji_spec.rb b/spec/lib/gitlab/award_emoji_spec.rb index 0f3852b172920d99553d3e8331e826b71d48cbda..00a110e31f85272c51e76a9c6071fecf1265bd55 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 fd869f48b5c223890d58c5f85b86219212b986fb..6e5ba21138210ba34d9212c30d6fc5bae044229e 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 711a3e1c7d41a4f827435d2ff165bba0e0978b15..abc93e1b44a92a0e056e3e74dd2aab0e6748e3a7 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 0000000000000000000000000000000000000000..004341ffd0214cc05eb1a39cf7c5bac04e4e5ac1 --- /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 ea5c31011f0c01c29fabba12291a0526fd5400d8..198ff977f2418f7729f35846ed5e4bea5dda9503 100644 --- a/spec/lib/gitlab/diff/inline_diff_marker_spec.rb +++ b/spec/lib/gitlab/diff/inline_diff_marker_spec.rb @@ -2,7 +2,6 @@ require 'spec_helper' describe Gitlab::Diff::InlineDiffMarker, lib: true do describe '#inline_diffs' do - context "when the rich text is html safe" do let(:raw) { "abc 'def'" } let(:rich) { %{<span class="abc">abc</span><span class="space"> </span><span class="def">'def'</span>}.html_safe } diff --git a/spec/lib/gitlab/fogbugz_import/client_spec.rb b/spec/lib/gitlab/fogbugz_import/client_spec.rb index 2dc71be0254c5ce775c0ae8995fbdd789e0a13b7..252cd4c55c747bf7f891f904c67d8b5de67c44c8 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 9b3a0e3a75fab280ea5a94406ec79c68d6963eee..9b7986fa12d6dd6d73212bcd786f9d957e953648 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 7c21cbe96d9fdbd26da9d33d3f8f811fa296ae33..3b023a3544681b0d9386065f49f8f376a99778d6 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 e94440a7fb05b2251accb3823f79a5ef5b0b4071..87593e32db0dc9282d240b1fcef84d0ea4dfad66 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 647631271e0004725cf22834897ce7d15ccb6d39..54f85f8cffc699b19249a77696ad98e1c06a562c 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 f135a285dfb32d2e2c2d285c7766d353a095b321..6d5aa0d04a22ea6750a0d5305fbaf0b197fa7cb3 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 403bd582ef302ac05db0f2837f25986e9538276d..0b30e8c9b0499aff119947332742056f9c6513aa 100644 --- a/spec/lib/gitlab/import_export/project.json +++ b/spec/lib/gitlab/import_export/project.json @@ -1,62 +1,63 @@ { - "name": "Gitlab Test", - "path": "gitlab-test", - "description": "Aut saepe in eos dolorem aliquam hic.", + "description": "Nisi et repellendus ut enim quo accusamus vel magnam.", "issues_enabled": true, "merge_requests_enabled": true, "wiki_enabled": true, "snippets_enabled": false, - "visibility_level": 20, + "visibility_level": 10, "archived": false, "issues": [ { "id": 40, - "title": "Voluptatem modi rerum ipsum vero voluptas repudiandae veniam quibusdam.", + "title": "Voluptatem amet doloribus deleniti eos maxime repudiandae molestias.", "assignee_id": 1, - "author_id": 4, + "author_id": 22, "project_id": 5, - "created_at": "2016-03-22T15:13:28.411Z", - "updated_at": "2016-04-12T13:08:26.029Z", + "created_at": "2016-06-14T15:02:08.340Z", + "updated_at": "2016-06-14T15:02:47.967Z", "position": 0, "branch_name": null, - "description": "Aut minima non sit qui nulla rerum laborum.", - "milestone_id": 10, + "description": "Aliquam enim illo et possimus.", + "milestone_id": 18, "state": "opened", "iid": 10, "updated_by_id": null, "confidential": false, "deleted_at": null, - "moved_to_id": null, "due_date": null, + "moved_to_id": null, "notes": [ { - "id": 1357, - "note": "test", + "id": 351, + "note": "Quo reprehenderit aliquam qui dicta impedit cupiditate eligendi.", "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-04-12T13:08:26.006Z", - "updated_at": "2016-04-12T13:08:26.006Z", + "author_id": 26, + "created_at": "2016-06-14T15:02:47.770Z", + "updated_at": "2016-06-14T15:02:47.770Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, - "commit_id": "", + "commit_id": null, "noteable_id": 40, "system": false, "st_diff": null, "updated_by_id": null, "author": { - "name": "Administrator" - } + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 338, - "note": "Fugit in aliquid voluptas dolor.", + "id": 352, + "note": "Est reprehenderit quas aut aspernatur autem recusandae voluptatem.", "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-03-22T15:19:59.213Z", - "updated_at": "2016-03-22T15:19:59.213Z", + "author_id": 25, + "created_at": "2016-06-14T15:02:47.795Z", + "updated_at": "2016-06-14T15:02:47.795Z", "project_id": 5, "attachment": { "url": null @@ -68,16 +69,19 @@ "st_diff": null, "updated_by_id": null, "author": { - "name": "Administrator" - } + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 337, - "note": "Occaecati consequatur facilis doloribus omnis hic placeat nihil.", + "id": 353, + "note": "Perspiciatis suscipit voluptates in eius nihil.", "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:19:59.186Z", - "updated_at": "2016-03-22T15:19:59.186Z", + "author_id": 22, + "created_at": "2016-06-14T15:02:47.823Z", + "updated_at": "2016-06-14T15:02:47.823Z", "project_id": 5, "attachment": { "url": null @@ -89,16 +93,19 @@ "st_diff": null, "updated_by_id": null, "author": { - "name": "Alexie Trantow" - } + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 336, - "note": "Nostrum et et est repudiandae non dolores voluptatem.", + "id": 354, + "note": "Aut vel voluptas corrupti nisi provident laboriosam magnam aut.", "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:19:59.156Z", - "updated_at": "2016-03-22T15:19:59.156Z", + "author_id": 20, + "created_at": "2016-06-14T15:02:47.850Z", + "updated_at": "2016-06-14T15:02:47.850Z", "project_id": 5, "attachment": { "url": null @@ -110,37 +117,19 @@ "st_diff": null, "updated_by_id": null, "author": { - "name": "Julius Moore" - } - }, - { - "id": 335, - "note": "Nihil et aut dolorum aut sit maxime.", - "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:19:59.130Z", - "updated_at": "2016-03-22T15:19:59.130Z", - "project_id": 5, - "attachment": { - "url": null + "name": "Ottis Schuster II" }, - "line_code": null, - "commit_id": null, - "noteable_id": 40, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "events": [ + + ] }, { - "id": 334, - "note": "Non blanditiis voluptatem sit earum accusantium distinctio voluptas officiis.", + "id": 355, + "note": "Officia dolore consequatur in saepe cum magni.", "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:19:59.101Z", - "updated_at": "2016-03-22T15:19:59.101Z", + "author_id": 16, + "created_at": "2016-06-14T15:02:47.876Z", + "updated_at": "2016-06-14T15:02:47.876Z", "project_id": 5, "attachment": { "url": null @@ -151,17 +140,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 333, - "note": "Nesciunt non dolorem similique nam ipsa et.", + "id": 356, + "note": "Cum ipsum rem voluptas eaque et ea.", "noteable_type": "Issue", - "author_id": 22, - "created_at": "2016-03-22T15:19:59.075Z", - "updated_at": "2016-03-22T15:19:59.075Z", + "author_id": 15, + "created_at": "2016-06-14T15:02:47.908Z", + "updated_at": "2016-06-14T15:02:47.908Z", "project_id": 5, "attachment": { "url": null @@ -172,17 +164,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 332, - "note": "Sed aut fugit et officiis dolor.", + "id": 357, + "note": "Recusandae excepturi asperiores suscipit autem nostrum.", "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:19:59.047Z", - "updated_at": "2016-03-22T15:19:59.047Z", + "author_id": 6, + "created_at": "2016-06-14T15:02:47.937Z", + "updated_at": "2016-06-14T15:02:47.937Z", "project_id": 5, "attachment": { "url": null @@ -193,17 +188,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 331, - "note": "Officiis iste eum recusandae suscipit consequatur consequatur.", + "id": 358, + "note": "Et hic est id similique et non nesciunt voluptate.", "noteable_type": "Issue", - "author_id": 26, - "created_at": "2016-03-22T15:19:59.015Z", - "updated_at": "2016-03-22T15:19:59.015Z", + "author_id": 1, + "created_at": "2016-06-14T15:02:47.965Z", + "updated_at": "2016-06-14T15:02:47.965Z", "project_id": 5, "attachment": { "url": null @@ -214,39 +212,42 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ] }, { "id": 39, - "title": "Sit ut adipisci sint temporibus velit quis.", - "assignee_id": 1, - "author_id": 12, + "title": "Delectus veniam ratione in eos culpa et natus molestiae earum aut.", + "assignee_id": 20, + "author_id": 22, "project_id": 5, - "created_at": "2016-03-22T15:13:28.278Z", - "updated_at": "2016-03-22T15:19:59.473Z", + "created_at": "2016-06-14T15:02:08.233Z", + "updated_at": "2016-06-14T15:02:48.194Z", "position": 0, "branch_name": null, - "description": "Ab sint nostrum aliquam laudantium magni recusandae qui.", - "milestone_id": 10, - "state": "closed", + "description": "Voluptate vel reprehenderit facilis omnis voluptas magnam tenetur.", + "milestone_id": 16, + "state": "opened", "iid": 9, "updated_by_id": null, "confidential": false, "deleted_at": null, - "moved_to_id": null, "due_date": null, + "moved_to_id": null, "notes": [ { - "id": 346, - "note": "Natus rerum qui dolorem dolorum voluptas.", + "id": 359, + "note": "Quo eius velit quia et id quam.", "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-03-22T15:19:59.469Z", - "updated_at": "2016-03-22T15:19:59.469Z", + "author_id": 26, + "created_at": "2016-06-14T15:02:48.009Z", + "updated_at": "2016-06-14T15:02:48.009Z", "project_id": 5, "attachment": { "url": null @@ -257,17 +258,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 345, - "note": "Voluptatibus et qui quis id sed necessitatibus quos.", + "id": 360, + "note": "Nulla commodi ratione cumque id autem.", "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:19:59.438Z", - "updated_at": "2016-03-22T15:19:59.438Z", + "author_id": 25, + "created_at": "2016-06-14T15:02:48.032Z", + "updated_at": "2016-06-14T15:02:48.032Z", "project_id": 5, "attachment": { "url": null @@ -278,17 +282,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 344, - "note": "Aperiam possimus ipsam quibusdam in.", + "id": 361, + "note": "Illum non ea sed dolores corrupti.", "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:19:59.410Z", - "updated_at": "2016-03-22T15:19:59.410Z", + "author_id": 22, + "created_at": "2016-06-14T15:02:48.056Z", + "updated_at": "2016-06-14T15:02:48.056Z", "project_id": 5, "attachment": { "url": null @@ -299,17 +306,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 343, - "note": "Ad vel hic molestiae tempora.", + "id": 362, + "note": "Facere dolores ipsum dolorum maiores omnis occaecati ab.", "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:19:59.379Z", - "updated_at": "2016-03-22T15:19:59.379Z", + "author_id": 20, + "created_at": "2016-06-14T15:02:48.082Z", + "updated_at": "2016-06-14T15:02:48.082Z", "project_id": 5, "attachment": { "url": null @@ -320,17 +330,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 342, - "note": "Vel magnam sed quidem aut molestiae facilis alias.", + "id": 363, + "note": "Quod laudantium similique sint aut est ducimus.", "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:19:59.348Z", - "updated_at": "2016-03-22T15:19:59.348Z", + "author_id": 16, + "created_at": "2016-06-14T15:02:48.113Z", + "updated_at": "2016-06-14T15:02:48.113Z", "project_id": 5, "attachment": { "url": null @@ -341,17 +354,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 341, - "note": "Veritatis dolorum aut qui quod.", + "id": 364, + "note": "Aut omnis eos esse incidunt vero reiciendis.", "noteable_type": "Issue", - "author_id": 22, - "created_at": "2016-03-22T15:19:59.319Z", - "updated_at": "2016-03-22T15:19:59.319Z", + "author_id": 15, + "created_at": "2016-06-14T15:02:48.139Z", + "updated_at": "2016-06-14T15:02:48.139Z", "project_id": 5, "attachment": { "url": null @@ -362,17 +378,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 340, - "note": "Illum at cumque dolorum et quia.", + "id": 365, + "note": "Beatae dolore et doloremque asperiores sunt.", "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:19:59.289Z", - "updated_at": "2016-03-22T15:19:59.289Z", + "author_id": 6, + "created_at": "2016-06-14T15:02:48.162Z", + "updated_at": "2016-06-14T15:02:48.162Z", "project_id": 5, "attachment": { "url": null @@ -383,17 +402,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 339, - "note": "Fugiat et error molestiae cumque quos aperiam.", + "id": 366, + "note": "Doloribus ipsam ex delectus rerum libero recusandae modi repellendus.", "noteable_type": "Issue", - "author_id": 26, - "created_at": "2016-03-22T15:19:59.255Z", - "updated_at": "2016-03-22T15:19:59.255Z", + "author_id": 1, + "created_at": "2016-06-14T15:02:48.192Z", + "updated_at": "2016-06-14T15:02:48.192Z", "project_id": 5, "attachment": { "url": null @@ -404,39 +426,42 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ] }, { "id": 38, - "title": "Quod quo est quis vel natus nulla eos reiciendis.", - "assignee_id": 12, - "author_id": 3, + "title": "Quasi adipisci non cupiditate dolorem quo qui earum sed.", + "assignee_id": 1, + "author_id": 6, "project_id": 5, - "created_at": "2016-03-22T15:13:28.137Z", - "updated_at": "2016-03-22T15:19:59.712Z", + "created_at": "2016-06-14T15:02:08.154Z", + "updated_at": "2016-06-14T15:02:48.614Z", "position": 0, "branch_name": null, - "description": "Fugit dolor accusantium suscipit facere voluptate.", - "milestone_id": 10, - "state": "opened", + "description": "Ea recusandae neque autem tempora.", + "milestone_id": 16, + "state": "closed", "iid": 8, "updated_by_id": null, "confidential": false, "deleted_at": null, - "moved_to_id": null, "due_date": null, + "moved_to_id": null, "notes": [ { - "id": 354, - "note": "Id commodi natus vel corrupti ea placeat cum nihil.", + "id": 367, + "note": "Accusantium fugiat et eaque quisquam esse corporis.", "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-03-22T15:19:59.708Z", - "updated_at": "2016-03-22T15:19:59.708Z", + "author_id": 26, + "created_at": "2016-06-14T15:02:48.235Z", + "updated_at": "2016-06-14T15:02:48.235Z", "project_id": 5, "attachment": { "url": null @@ -447,17 +472,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 353, - "note": "Quia hic sed ratione eos voluptate dolor occaecati dolorem.", + "id": 368, + "note": "Ea labore eum nam qui laboriosam.", "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:19:59.680Z", - "updated_at": "2016-03-22T15:19:59.680Z", + "author_id": 25, + "created_at": "2016-06-14T15:02:48.261Z", + "updated_at": "2016-06-14T15:02:48.261Z", "project_id": 5, "attachment": { "url": null @@ -468,17 +496,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 352, - "note": "Commodi sint voluptatem est aut.", + "id": 369, + "note": "Accusantium quis sed molestiae et.", "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:19:59.650Z", - "updated_at": "2016-03-22T15:19:59.650Z", + "author_id": 22, + "created_at": "2016-06-14T15:02:48.294Z", + "updated_at": "2016-06-14T15:02:48.294Z", "project_id": 5, "attachment": { "url": null @@ -489,17 +520,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 351, - "note": "Et quibusdam voluptatibus dolores aut quam architecto optio.", + "id": 370, + "note": "Corporis numquam a voluptatem pariatur asperiores dolorem delectus autem.", "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:19:59.622Z", - "updated_at": "2016-03-22T15:19:59.622Z", + "author_id": 20, + "created_at": "2016-06-14T15:02:48.523Z", + "updated_at": "2016-06-14T15:02:48.523Z", "project_id": 5, "attachment": { "url": null @@ -510,17 +544,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 350, - "note": "Fugit natus explicabo sed pariatur et quasi autem.", + "id": 371, + "note": "Ea accusantium maxime voluptas rerum.", "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:19:59.590Z", - "updated_at": "2016-03-22T15:19:59.590Z", + "author_id": 16, + "created_at": "2016-06-14T15:02:48.546Z", + "updated_at": "2016-06-14T15:02:48.546Z", "project_id": 5, "attachment": { "url": null @@ -531,17 +568,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 349, - "note": "Corporis commodi eos quia optio sunt corrupti.", + "id": 372, + "note": "Pariatur iusto et et excepturi similique ipsam eum.", "noteable_type": "Issue", - "author_id": 22, - "created_at": "2016-03-22T15:19:59.562Z", - "updated_at": "2016-03-22T15:19:59.562Z", + "author_id": 15, + "created_at": "2016-06-14T15:02:48.569Z", + "updated_at": "2016-06-14T15:02:48.569Z", "project_id": 5, "attachment": { "url": null @@ -552,17 +592,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 348, - "note": "Occaecati nostrum hic dolor tenetur aliquid maxime animi.", + "id": 373, + "note": "Aliquam et culpa officia iste eius.", "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:19:59.536Z", - "updated_at": "2016-03-22T15:19:59.536Z", + "author_id": 6, + "created_at": "2016-06-14T15:02:48.591Z", + "updated_at": "2016-06-14T15:02:48.591Z", "project_id": 5, "attachment": { "url": null @@ -573,17 +616,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 347, - "note": "Inventore ullam sed repellendus laudantium itaque et quia.", + "id": 374, + "note": "Ab id velit id unde laborum.", "noteable_type": "Issue", - "author_id": 26, - "created_at": "2016-03-22T15:19:59.506Z", - "updated_at": "2016-03-22T15:19:59.506Z", + "author_id": 1, + "created_at": "2016-06-14T15:02:48.613Z", + "updated_at": "2016-06-14T15:02:48.613Z", "project_id": 5, "attachment": { "url": null @@ -594,39 +640,42 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ] }, { "id": 37, - "title": "Animi suscipit quia ut hic asperiores perferendis nisi ut.", - "assignee_id": 22, - "author_id": 10, + "title": "Cupiditate quo aut ducimus minima molestiae vero numquam possimus.", + "assignee_id": 15, + "author_id": 20, "project_id": 5, - "created_at": "2016-03-22T15:13:27.994Z", - "updated_at": "2016-03-22T15:19:59.972Z", + "created_at": "2016-06-14T15:02:08.051Z", + "updated_at": "2016-06-14T15:02:48.854Z", "position": 0, "branch_name": null, - "description": "Non quibusdam in maxime earum eveniet itaque culpa.", - "milestone_id": 11, - "state": "closed", + "description": "Maiores architecto quos in dolorem.", + "milestone_id": 17, + "state": "opened", "iid": 7, "updated_by_id": null, "confidential": false, "deleted_at": null, - "moved_to_id": null, "due_date": null, + "moved_to_id": null, "notes": [ { - "id": 362, - "note": "Quia qui quis molestiae in praesentium.", + "id": 375, + "note": "Quasi fugit qui sed eligendi aut quia.", "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-03-22T15:19:59.966Z", - "updated_at": "2016-03-22T15:19:59.966Z", + "author_id": 26, + "created_at": "2016-06-14T15:02:48.647Z", + "updated_at": "2016-06-14T15:02:48.647Z", "project_id": 5, "attachment": { "url": null @@ -637,17 +686,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 361, - "note": "Maxime sed eius qui consequatur beatae.", + "id": 376, + "note": "Esse nesciunt voluptatem ex vero est consequatur.", "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:19:59.924Z", - "updated_at": "2016-03-22T15:19:59.924Z", + "author_id": 25, + "created_at": "2016-06-14T15:02:48.674Z", + "updated_at": "2016-06-14T15:02:48.674Z", "project_id": 5, "attachment": { "url": null @@ -658,17 +710,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 360, - "note": "Voluptatum quasi corrupti eveniet sed ut quis quibusdam.", + "id": 377, + "note": "Similique qui quas non aut et velit sequi in.", "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:19:59.897Z", - "updated_at": "2016-03-22T15:19:59.897Z", + "author_id": 22, + "created_at": "2016-06-14T15:02:48.696Z", + "updated_at": "2016-06-14T15:02:48.696Z", "project_id": 5, "attachment": { "url": null @@ -679,17 +734,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 359, - "note": "Molestias quia eius ipsum non.", + "id": 378, + "note": "Eveniet ut cupiditate repellendus numquam in esse eius.", "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:19:59.866Z", - "updated_at": "2016-03-22T15:19:59.866Z", + "author_id": 20, + "created_at": "2016-06-14T15:02:48.720Z", + "updated_at": "2016-06-14T15:02:48.720Z", "project_id": 5, "attachment": { "url": null @@ -700,17 +758,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 358, - "note": "Aut non est accusantium aliquam.", + "id": 379, + "note": "Velit est dolorem adipisci rerum sed iure.", "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:19:59.834Z", - "updated_at": "2016-03-22T15:19:59.834Z", + "author_id": 16, + "created_at": "2016-06-14T15:02:48.755Z", + "updated_at": "2016-06-14T15:02:48.755Z", "project_id": 5, "attachment": { "url": null @@ -721,17 +782,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 357, - "note": "Aspernatur voluptas id voluptas vel cum ipsam.", + "id": 380, + "note": "Voluptatem ullam ab ut illo ut quo.", "noteable_type": "Issue", - "author_id": 22, - "created_at": "2016-03-22T15:19:59.805Z", - "updated_at": "2016-03-22T15:19:59.805Z", + "author_id": 15, + "created_at": "2016-06-14T15:02:48.793Z", + "updated_at": "2016-06-14T15:02:48.793Z", "project_id": 5, "attachment": { "url": null @@ -742,17 +806,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 356, - "note": "Harum dignissimos provident tempora sit numquam est qui.", + "id": 381, + "note": "Voluptatem impedit beatae quasi ipsa earum consectetur.", "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:19:59.773Z", - "updated_at": "2016-03-22T15:19:59.773Z", + "author_id": 6, + "created_at": "2016-06-14T15:02:48.823Z", + "updated_at": "2016-06-14T15:02:48.823Z", "project_id": 5, "attachment": { "url": null @@ -763,17 +830,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 355, - "note": "Sint dignissimos molestiae recusandae delectus.", + "id": 382, + "note": "Nihil officiis eaque incidunt sunt voluptatum excepturi.", "noteable_type": "Issue", - "author_id": 26, - "created_at": "2016-03-22T15:19:59.746Z", - "updated_at": "2016-03-22T15:19:59.746Z", + "author_id": 1, + "created_at": "2016-06-14T15:02:48.852Z", + "updated_at": "2016-06-14T15:02:48.852Z", "project_id": 5, "attachment": { "url": null @@ -784,39 +854,42 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ] }, { "id": 36, - "title": "Quia dolores commodi eligendi ut nemo totam.", - "assignee_id": 3, - "author_id": 4, + "title": "Necessitatibus dolor est enim quia rem suscipit quidem voluptas ullam.", + "assignee_id": 20, + "author_id": 16, "project_id": 5, - "created_at": "2016-03-22T15:13:27.814Z", - "updated_at": "2016-03-22T15:20:00.371Z", + "created_at": "2016-06-14T15:02:07.958Z", + "updated_at": "2016-06-14T15:02:49.044Z", "position": 0, "branch_name": null, - "description": "Molestiae veniam laudantium autem et natus.", - "milestone_id": 11, + "description": "Ut aut ut et tenetur velit aut id modi.", + "milestone_id": 16, "state": "opened", "iid": 6, "updated_by_id": null, "confidential": false, "deleted_at": null, - "moved_to_id": null, "due_date": null, + "moved_to_id": null, "notes": [ { - "id": 370, - "note": "Occaecati temporibus tempore harum vero incidunt veniam iste.", + "id": 383, + "note": "Excepturi deleniti sunt rerum nesciunt vero fugiat possimus.", "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-03-22T15:20:00.365Z", - "updated_at": "2016-03-22T15:20:00.365Z", + "author_id": 26, + "created_at": "2016-06-14T15:02:48.885Z", + "updated_at": "2016-06-14T15:02:48.885Z", "project_id": 5, "attachment": { "url": null @@ -827,17 +900,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 369, - "note": "Modi architecto officiis quia iste voluptas libero nihil quo.", + "id": 384, + "note": "Et est nemo sed nam sed.", "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:20:00.331Z", - "updated_at": "2016-03-22T15:20:00.331Z", + "author_id": 25, + "created_at": "2016-06-14T15:02:48.910Z", + "updated_at": "2016-06-14T15:02:48.910Z", "project_id": 5, "attachment": { "url": null @@ -848,17 +924,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 368, - "note": "Eaque est tenetur ex est molestiae nobis.", + "id": 385, + "note": "Animi mollitia nulla facere amet aut quaerat.", "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:20:00.296Z", - "updated_at": "2016-03-22T15:20:00.296Z", + "author_id": 22, + "created_at": "2016-06-14T15:02:48.934Z", + "updated_at": "2016-06-14T15:02:48.934Z", "project_id": 5, "attachment": { "url": null @@ -869,17 +948,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 367, - "note": "Odit enim ut a quo qui.", + "id": 386, + "note": "Excepturi id voluptas ut odio officiis omnis.", "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:20:00.261Z", - "updated_at": "2016-03-22T15:20:00.261Z", + "author_id": 20, + "created_at": "2016-06-14T15:02:48.955Z", + "updated_at": "2016-06-14T15:02:48.955Z", "project_id": 5, "attachment": { "url": null @@ -890,17 +972,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 366, - "note": "Omnis unde cum officiis est.", + "id": 387, + "note": "Molestiae labore officiis magni et eligendi quasi maxime.", "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:20:00.223Z", - "updated_at": "2016-03-22T15:20:00.223Z", + "author_id": 16, + "created_at": "2016-06-14T15:02:48.978Z", + "updated_at": "2016-06-14T15:02:48.978Z", "project_id": 5, "attachment": { "url": null @@ -911,17 +996,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 365, - "note": "Ab consequuntur aliquam illo voluptatum.", + "id": 388, + "note": "Officia tenetur praesentium rem nam non.", "noteable_type": "Issue", - "author_id": 22, - "created_at": "2016-03-22T15:20:00.178Z", - "updated_at": "2016-03-22T15:20:00.178Z", + "author_id": 15, + "created_at": "2016-06-14T15:02:49.001Z", + "updated_at": "2016-06-14T15:02:49.001Z", "project_id": 5, "attachment": { "url": null @@ -932,17 +1020,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 364, - "note": "Molestiae dolorem est eos dolores aut.", + "id": 389, + "note": "Et et et molestiae reprehenderit.", "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:20:00.127Z", - "updated_at": "2016-03-22T15:20:00.127Z", + "author_id": 6, + "created_at": "2016-06-14T15:02:49.022Z", + "updated_at": "2016-06-14T15:02:49.022Z", "project_id": 5, "attachment": { "url": null @@ -953,17 +1044,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 363, - "note": "Nemo velit nam quod veniam.", + "id": 390, + "note": "Aperiam in consequatur est sunt cum quia.", "noteable_type": "Issue", - "author_id": 26, - "created_at": "2016-03-22T15:20:00.083Z", - "updated_at": "2016-03-22T15:20:00.083Z", + "author_id": 1, + "created_at": "2016-06-14T15:02:49.043Z", + "updated_at": "2016-06-14T15:02:49.043Z", "project_id": 5, "attachment": { "url": null @@ -974,39 +1068,42 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ] }, { "id": 35, - "title": "Rerum tenetur harum molestiae quam aut praesentium quaerat doloremque.", - "assignee_id": 4, - "author_id": 1, + "title": "Repellat praesentium deserunt maxime incidunt harum porro qui.", + "assignee_id": 6, + "author_id": 20, "project_id": 5, - "created_at": "2016-03-22T15:13:27.660Z", - "updated_at": "2016-03-22T15:20:00.665Z", + "created_at": "2016-06-14T15:02:07.832Z", + "updated_at": "2016-06-14T15:02:49.226Z", "position": 0, "branch_name": null, - "description": "Omnis et voluptatibus expedita qui et explicabo rem ut.", - "milestone_id": 11, - "state": "opened", + "description": "Dicta nisi nihil non ipsa velit.", + "milestone_id": 20, + "state": "closed", "iid": 5, "updated_by_id": null, "confidential": false, "deleted_at": null, - "moved_to_id": null, "due_date": null, + "moved_to_id": null, "notes": [ { - "id": 378, - "note": "Molestiae atque exercitationem culpa harum nemo.", + "id": 391, + "note": "Qui magnam et assumenda quod id dicta necessitatibus.", "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-03-22T15:20:00.660Z", - "updated_at": "2016-03-22T15:20:00.660Z", + "author_id": 26, + "created_at": "2016-06-14T15:02:49.075Z", + "updated_at": "2016-06-14T15:02:49.075Z", "project_id": 5, "attachment": { "url": null @@ -1017,17 +1114,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 377, - "note": "Porro sed nobis neque amet velit velit.", + "id": 392, + "note": "Consectetur deserunt possimus dolor est odio.", "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:20:00.625Z", - "updated_at": "2016-03-22T15:20:00.625Z", + "author_id": 25, + "created_at": "2016-06-14T15:02:49.095Z", + "updated_at": "2016-06-14T15:02:49.095Z", "project_id": 5, "attachment": { "url": null @@ -1038,17 +1138,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 376, - "note": "Dicta officiis doloremque voluptatum qui omnis.", + "id": 393, + "note": "Labore nisi quo cumque voluptas consequatur aut qui.", "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:20:00.589Z", - "updated_at": "2016-03-22T15:20:00.589Z", + "author_id": 22, + "created_at": "2016-06-14T15:02:49.117Z", + "updated_at": "2016-06-14T15:02:49.117Z", "project_id": 5, "attachment": { "url": null @@ -1059,17 +1162,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 375, - "note": "Incidunt rerum omnis cum laudantium aut impedit.", + "id": 394, + "note": "Et totam facilis voluptas et enim.", "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:20:00.553Z", - "updated_at": "2016-03-22T15:20:00.553Z", + "author_id": 20, + "created_at": "2016-06-14T15:02:49.138Z", + "updated_at": "2016-06-14T15:02:49.138Z", "project_id": 5, "attachment": { "url": null @@ -1080,17 +1186,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 374, - "note": "Et suscipit omnis dolorum officia vero.", + "id": 395, + "note": "Ratione sint pariatur sed omnis eligendi quo libero exercitationem.", "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:20:00.517Z", - "updated_at": "2016-03-22T15:20:00.517Z", + "author_id": 16, + "created_at": "2016-06-14T15:02:49.160Z", + "updated_at": "2016-06-14T15:02:49.160Z", "project_id": 5, "attachment": { "url": null @@ -1101,17 +1210,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 373, - "note": "Doloremque adipisci et cumque inventore beatae consectetur.", + "id": 396, + "note": "Iure hic autem id voluptatem.", "noteable_type": "Issue", - "author_id": 22, - "created_at": "2016-03-22T15:20:00.485Z", - "updated_at": "2016-03-22T15:20:00.485Z", + "author_id": 15, + "created_at": "2016-06-14T15:02:49.182Z", + "updated_at": "2016-06-14T15:02:49.182Z", "project_id": 5, "attachment": { "url": null @@ -1122,17 +1234,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 372, - "note": "Dolores sapiente ea dolorum et quae adipisci id.", + "id": 397, + "note": "Excepturi eum laboriosam delectus repellendus odio nisi et voluptatem.", "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:20:00.455Z", - "updated_at": "2016-03-22T15:20:00.455Z", + "author_id": 6, + "created_at": "2016-06-14T15:02:49.205Z", + "updated_at": "2016-06-14T15:02:49.205Z", "project_id": 5, "attachment": { "url": null @@ -1143,17 +1258,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 371, - "note": "Accusantium repellat tenetur natus dicta ullam saepe facere.", + "id": 398, + "note": "Ut quis ex soluta consequatur et blanditiis.", "noteable_type": "Issue", - "author_id": 26, - "created_at": "2016-03-22T15:20:00.420Z", - "updated_at": "2016-03-22T15:20:00.420Z", + "author_id": 1, + "created_at": "2016-06-14T15:02:49.225Z", + "updated_at": "2016-06-14T15:02:49.225Z", "project_id": 5, "attachment": { "url": null @@ -1164,39 +1282,42 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ] }, { "id": 34, - "title": "Enim occaecati aut sed quia mollitia eligendi atque dolores voluptatem.", - "assignee_id": 24, + "title": "Ullam expedita deserunt libero consequatur quia dolor harum perferendis facere quidem.", + "assignee_id": 20, "author_id": 1, "project_id": 5, - "created_at": "2016-03-22T15:13:27.506Z", - "updated_at": "2016-03-22T15:20:00.961Z", + "created_at": "2016-06-14T15:02:07.717Z", + "updated_at": "2016-06-14T15:02:49.416Z", "position": 0, "branch_name": null, - "description": "Voluptatem totam magnam fugit assumenda consequatur illo qui.", - "milestone_id": 10, - "state": "opened", + "description": "Ut et explicabo vel voluptatem consequuntur ut sed.", + "milestone_id": 19, + "state": "closed", "iid": 4, "updated_by_id": null, "confidential": false, "deleted_at": null, - "moved_to_id": null, "due_date": null, + "moved_to_id": null, "notes": [ { - "id": 379, - "note": "Praesentium odio quia fugit consequuntur repudiandae ducimus.", + "id": 399, + "note": "Dolor iste tempora tenetur non vitae maiores voluptatibus.", "noteable_type": "Issue", "author_id": 26, - "created_at": "2016-03-22T15:20:00.717Z", - "updated_at": "2016-03-22T15:20:00.717Z", + "created_at": "2016-06-14T15:02:49.256Z", + "updated_at": "2016-06-14T15:02:49.256Z", "project_id": 5, "attachment": { "url": null @@ -1207,17 +1328,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { + "author": { "name": "User 4" - } + }, + "events": [ + + ] }, { - "id": 380, - "note": "Dolores aut dolorem quia soluta incidunt commodi quia.", + "id": 400, + "note": "Aut sit quidem qui adipisci maxime excepturi iusto.", "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:20:00.754Z", - "updated_at": "2016-03-22T15:20:00.754Z", + "author_id": 25, + "created_at": "2016-06-14T15:02:49.284Z", + "updated_at": "2016-06-14T15:02:49.284Z", "project_id": 5, "attachment": { "url": null @@ -1228,17 +1352,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 381, - "note": "Enim et velit iure ad.", + "id": 401, + "note": "Et a necessitatibus autem quidem animi sunt voluptatum rerum.", "noteable_type": "Issue", "author_id": 22, - "created_at": "2016-03-22T15:20:00.787Z", - "updated_at": "2016-03-22T15:20:00.787Z", + "created_at": "2016-06-14T15:02:49.305Z", + "updated_at": "2016-06-14T15:02:49.305Z", "project_id": 5, "attachment": { "url": null @@ -1249,17 +1376,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { + "author": { "name": "User 0" - } + }, + "events": [ + + ] }, { - "id": 382, - "note": "Impedit nobis quis laudantium ad assumenda.", + "id": 402, + "note": "Esse laboriosam quo voluptatem quis molestiae.", "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:20:00.822Z", - "updated_at": "2016-03-22T15:20:00.822Z", + "author_id": 20, + "created_at": "2016-06-14T15:02:49.328Z", + "updated_at": "2016-06-14T15:02:49.328Z", "project_id": 5, "attachment": { "url": null @@ -1270,17 +1400,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 383, - "note": "Facere sed numquam quos quas.", + "id": 403, + "note": "Nemo magnam distinctio est ut voluptate ea.", "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:20:00.855Z", - "updated_at": "2016-03-22T15:20:00.855Z", + "author_id": 16, + "created_at": "2016-06-14T15:02:49.350Z", + "updated_at": "2016-06-14T15:02:49.350Z", "project_id": 5, "attachment": { "url": null @@ -1291,17 +1424,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 384, - "note": "Ex voluptatem sit provident error.", + "id": 404, + "note": "Omnis sed rerum neque rerum quae quam nulla officiis.", "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:20:00.889Z", - "updated_at": "2016-03-22T15:20:00.889Z", + "author_id": 15, + "created_at": "2016-06-14T15:02:49.372Z", + "updated_at": "2016-06-14T15:02:49.372Z", "project_id": 5, "attachment": { "url": null @@ -1312,17 +1448,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 385, - "note": "Soluta laboriosam recusandae est cupiditate.", + "id": 405, + "note": "Quo soluta dolorem vitae ad consequatur qui aut dicta.", "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:20:00.925Z", - "updated_at": "2016-03-22T15:20:00.925Z", + "author_id": 6, + "created_at": "2016-06-14T15:02:49.394Z", + "updated_at": "2016-06-14T15:02:49.394Z", "project_id": 5, "attachment": { "url": null @@ -1333,17 +1472,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 386, - "note": "Similique dolorem rerum iusto animi perferendis aut inventore.", + "id": 406, + "note": "Magni minus est aut aut totam ut.", "noteable_type": "Issue", "author_id": 1, - "created_at": "2016-03-22T15:20:00.957Z", - "updated_at": "2016-03-22T15:20:00.957Z", + "created_at": "2016-06-14T15:02:49.414Z", + "updated_at": "2016-06-14T15:02:49.414Z", "project_id": 5, "attachment": { "url": null @@ -1354,39 +1496,42 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { + "author": { "name": "Administrator" - } + }, + "events": [ + + ] } ] }, { "id": 33, - "title": "Rem fugiat fugit occaecati quibusdam enim consectetur numquam.", - "assignee_id": 22, - "author_id": 22, + "title": "Numquam accusamus eos iste exercitationem magni non inventore.", + "assignee_id": 15, + "author_id": 26, "project_id": 5, - "created_at": "2016-03-22T15:13:27.364Z", - "updated_at": "2016-03-22T15:20:01.227Z", + "created_at": "2016-06-14T15:02:07.611Z", + "updated_at": "2016-06-14T15:02:49.661Z", "position": 0, "branch_name": null, - "description": "Provident nulla architecto neque beatae fuga alias repudiandae.", - "milestone_id": 10, + "description": "Non asperiores velit accusantium voluptate.", + "milestone_id": 18, "state": "closed", "iid": 3, "updated_by_id": null, "confidential": false, "deleted_at": null, - "moved_to_id": null, "due_date": null, + "moved_to_id": null, "notes": [ { - "id": 394, - "note": "Suscipit numquam voluptatibus ipsam libero dolorum dolore totam.", + "id": 407, + "note": "Quod ea et possimus architecto.", "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-03-22T15:20:01.223Z", - "updated_at": "2016-03-22T15:20:01.223Z", + "author_id": 26, + "created_at": "2016-06-14T15:02:49.450Z", + "updated_at": "2016-06-14T15:02:49.450Z", "project_id": 5, "attachment": { "url": null @@ -1397,17 +1542,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 393, - "note": "Et et sed sit sint.", + "id": 408, + "note": "Reiciendis est et unde perferendis dicta ut praesentium quasi.", "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:20:01.194Z", - "updated_at": "2016-03-22T15:20:01.194Z", + "author_id": 25, + "created_at": "2016-06-14T15:02:49.503Z", + "updated_at": "2016-06-14T15:02:49.503Z", "project_id": 5, "attachment": { "url": null @@ -1418,17 +1566,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 392, - "note": "Corrupti perferendis voluptas et iure omnis officia.", + "id": 409, + "note": "Magni quia odio blanditiis pariatur voluptas.", "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:20:01.160Z", - "updated_at": "2016-03-22T15:20:01.160Z", + "author_id": 22, + "created_at": "2016-06-14T15:02:49.527Z", + "updated_at": "2016-06-14T15:02:49.527Z", "project_id": 5, "attachment": { "url": null @@ -1439,17 +1590,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 391, - "note": "Autem quo fugit in iste nesciunt tempora.", + "id": 410, + "note": "Enim quam ut et et et.", "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:20:01.131Z", - "updated_at": "2016-03-22T15:20:01.131Z", + "author_id": 20, + "created_at": "2016-06-14T15:02:49.551Z", + "updated_at": "2016-06-14T15:02:49.551Z", "project_id": 5, "attachment": { "url": null @@ -1460,17 +1614,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 390, - "note": "Magni porro ut soluta quis et eveniet maiores.", + "id": 411, + "note": "Fugit voluptatem ratione maxime expedita.", "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:20:01.101Z", - "updated_at": "2016-03-22T15:20:01.101Z", + "author_id": 16, + "created_at": "2016-06-14T15:02:49.578Z", + "updated_at": "2016-06-14T15:02:49.578Z", "project_id": 5, "attachment": { "url": null @@ -1481,17 +1638,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 389, - "note": "Sed consequuntur debitis nisi veniam exercitationem recusandae a quisquam.", + "id": 412, + "note": "Voluptatem enim aut ipsa et et ducimus.", "noteable_type": "Issue", - "author_id": 22, - "created_at": "2016-03-22T15:20:01.070Z", - "updated_at": "2016-03-22T15:20:01.070Z", + "author_id": 15, + "created_at": "2016-06-14T15:02:49.604Z", + "updated_at": "2016-06-14T15:02:49.604Z", "project_id": 5, "attachment": { "url": null @@ -1502,17 +1662,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 388, - "note": "Aut impedit qui consectetur dicta temporibus.", + "id": 413, + "note": "Quia repellat fugiat consectetur quidem.", "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:20:01.042Z", - "updated_at": "2016-03-22T15:20:01.042Z", + "author_id": 6, + "created_at": "2016-06-14T15:02:49.631Z", + "updated_at": "2016-06-14T15:02:49.631Z", "project_id": 5, "attachment": { "url": null @@ -1523,17 +1686,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 387, - "note": "Officia repudiandae ut culpa ipsa reiciendis.", + "id": 414, + "note": "Corporis ipsum et ea necessitatibus quod assumenda repudiandae quam.", "noteable_type": "Issue", - "author_id": 26, - "created_at": "2016-03-22T15:20:01.005Z", - "updated_at": "2016-03-22T15:20:01.005Z", + "author_id": 1, + "created_at": "2016-06-14T15:02:49.659Z", + "updated_at": "2016-06-14T15:02:49.659Z", "project_id": 5, "attachment": { "url": null @@ -1544,39 +1710,42 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ] }, { "id": 32, - "title": "Velit nihil est alias blanditiis eius earum autem hic.", + "title": "Necessitatibus magnam qui at velit consequatur perspiciatis.", "assignee_id": 22, - "author_id": 26, + "author_id": 15, "project_id": 5, - "created_at": "2016-03-22T15:13:27.225Z", - "updated_at": "2016-03-22T15:20:01.495Z", + "created_at": "2016-06-14T15:02:07.431Z", + "updated_at": "2016-06-14T15:02:49.884Z", "position": 0, "branch_name": null, - "description": "Id voluptas ut sint aut laborum nobis commodi.", - "milestone_id": 11, - "state": "opened", + "description": "Molestiae corporis magnam et fugit aliquid nulla quia.", + "milestone_id": 17, + "state": "closed", "iid": 2, "updated_by_id": null, "confidential": false, "deleted_at": null, - "moved_to_id": null, "due_date": null, + "moved_to_id": null, "notes": [ { - "id": 402, - "note": "Magni ut eligendi sit sint recusandae voluptas tempore necessitatibus.", + "id": 415, + "note": "Nemo consequatur sed blanditiis qui id iure dolores.", "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-03-22T15:20:01.489Z", - "updated_at": "2016-03-22T15:20:01.489Z", + "author_id": 26, + "created_at": "2016-06-14T15:02:49.694Z", + "updated_at": "2016-06-14T15:02:49.694Z", "project_id": 5, "attachment": { "url": null @@ -1587,17 +1756,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 401, - "note": "Est repellat commodi incidunt tempore earum optio unde sint.", + "id": 416, + "note": "Voluptas ab accusantium dicta in.", "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:20:01.455Z", - "updated_at": "2016-03-22T15:20:01.455Z", + "author_id": 25, + "created_at": "2016-06-14T15:02:49.718Z", + "updated_at": "2016-06-14T15:02:49.718Z", "project_id": 5, "attachment": { "url": null @@ -1608,17 +1780,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 400, - "note": "Vero unde debitis tempore est laboriosam ut esse.", + "id": 417, + "note": "Esse odit qui a et eum ducimus.", "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:20:01.421Z", - "updated_at": "2016-03-22T15:20:01.421Z", + "author_id": 22, + "created_at": "2016-06-14T15:02:49.741Z", + "updated_at": "2016-06-14T15:02:49.741Z", "project_id": 5, "attachment": { "url": null @@ -1629,17 +1804,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 399, - "note": "Omnis qui asperiores expedita harum voluptatem eius.", + "id": 418, + "note": "Sequi dolor doloribus ratione placeat repellendus.", "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:20:01.391Z", - "updated_at": "2016-03-22T15:20:01.391Z", + "author_id": 20, + "created_at": "2016-06-14T15:02:49.767Z", + "updated_at": "2016-06-14T15:02:49.767Z", "project_id": 5, "attachment": { "url": null @@ -1650,17 +1828,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 398, - "note": "Dolorem doloribus delectus quo ratione esse veritatis.", + "id": 419, + "note": "Quae aspernatur rem est similique.", "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:20:01.358Z", - "updated_at": "2016-03-22T15:20:01.358Z", + "author_id": 16, + "created_at": "2016-06-14T15:02:49.796Z", + "updated_at": "2016-06-14T15:02:49.796Z", "project_id": 5, "attachment": { "url": null @@ -1671,17 +1852,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 397, - "note": "Quia esse et odit id est omnis dolorum quia.", + "id": 420, + "note": "Voluptate omnis et id rerum non nesciunt laudantium assumenda.", "noteable_type": "Issue", - "author_id": 22, - "created_at": "2016-03-22T15:20:01.329Z", - "updated_at": "2016-03-22T15:20:01.329Z", + "author_id": 15, + "created_at": "2016-06-14T15:02:49.825Z", + "updated_at": "2016-06-14T15:02:49.825Z", "project_id": 5, "attachment": { "url": null @@ -1692,17 +1876,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 396, - "note": "Exercitationem suscipit non rerum tempore sit.", + "id": 421, + "note": "Quia enim ab et eligendi.", "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:20:01.297Z", - "updated_at": "2016-03-22T15:20:01.297Z", + "author_id": 6, + "created_at": "2016-06-14T15:02:49.853Z", + "updated_at": "2016-06-14T15:02:49.853Z", "project_id": 5, "attachment": { "url": null @@ -1713,17 +1900,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 395, - "note": "Nihil veniam magni sit officiis.", + "id": 422, + "note": "In fugiat rerum voluptas quas officia.", "noteable_type": "Issue", - "author_id": 26, - "created_at": "2016-03-22T15:20:01.268Z", - "updated_at": "2016-03-22T15:20:01.268Z", + "author_id": 1, + "created_at": "2016-06-14T15:02:49.881Z", + "updated_at": "2016-06-14T15:02:49.881Z", "project_id": 5, "attachment": { "url": null @@ -1734,39 +1924,42 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ] }, { "id": 31, - "title": "Asperiores recusandae praesentium voluptas pariatur provident qui exercitationem quis.", - "assignee_id": 26, - "author_id": 24, + "title": "Libero nam magnam incidunt eaque placeat error et.", + "assignee_id": 1, + "author_id": 16, "project_id": 5, - "created_at": "2016-03-22T15:13:26.889Z", - "updated_at": "2016-03-22T15:20:01.834Z", + "created_at": "2016-06-14T15:02:07.280Z", + "updated_at": "2016-06-14T15:02:50.134Z", "position": 0, "branch_name": null, - "description": "Ex voluptates qui excepturi cupiditate.", - "milestone_id": 11, + "description": "Quod ad architecto qui est sed quia.", + "milestone_id": 20, "state": "closed", "iid": 1, "updated_by_id": null, "confidential": false, "deleted_at": null, - "moved_to_id": null, "due_date": null, + "moved_to_id": null, "notes": [ { - "id": 410, - "note": "Sit itaque non nihil nisi qui voluptatem dolorem error.", + "id": 423, + "note": "A mollitia qui iste consequatur eaque iure omnis sunt.", "noteable_type": "Issue", - "author_id": 1, - "created_at": "2016-03-22T15:20:01.828Z", - "updated_at": "2016-03-22T15:20:01.828Z", + "author_id": 26, + "created_at": "2016-06-14T15:02:49.933Z", + "updated_at": "2016-06-14T15:02:49.933Z", "project_id": 5, "attachment": { "url": null @@ -1777,17 +1970,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 409, - "note": "Omnis rem nihil molestiae enim laudantium doloremque.", + "id": 424, + "note": "Eveniet est et blanditiis sequi alias.", "noteable_type": "Issue", - "author_id": 3, - "created_at": "2016-03-22T15:20:01.783Z", - "updated_at": "2016-03-22T15:20:01.783Z", + "author_id": 25, + "created_at": "2016-06-14T15:02:49.965Z", + "updated_at": "2016-06-14T15:02:49.965Z", "project_id": 5, "attachment": { "url": null @@ -1798,17 +1994,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 408, - "note": "Ullam harum sit et optio incidunt.", + "id": 425, + "note": "Commodi tempore voluptas doloremque est.", "noteable_type": "Issue", - "author_id": 4, - "created_at": "2016-03-22T15:20:01.746Z", - "updated_at": "2016-03-22T15:20:01.746Z", + "author_id": 22, + "created_at": "2016-06-14T15:02:49.996Z", + "updated_at": "2016-06-14T15:02:49.996Z", "project_id": 5, "attachment": { "url": null @@ -1819,17 +2018,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 407, - "note": "Fugit distinctio ab quo ipsam.", + "id": 426, + "note": "Quo libero impedit odio debitis rerum aspernatur.", "noteable_type": "Issue", - "author_id": 10, - "created_at": "2016-03-22T15:20:01.716Z", - "updated_at": "2016-03-22T15:20:01.716Z", + "author_id": 20, + "created_at": "2016-06-14T15:02:50.024Z", + "updated_at": "2016-06-14T15:02:50.024Z", "project_id": 5, "attachment": { "url": null @@ -1840,17 +2042,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 406, - "note": "Impedit iste possimus ad ea.", + "id": 427, + "note": "Dolorem voluptatem qui labore deserunt.", "noteable_type": "Issue", - "author_id": 12, - "created_at": "2016-03-22T15:20:01.676Z", - "updated_at": "2016-03-22T15:20:01.676Z", + "author_id": 16, + "created_at": "2016-06-14T15:02:50.049Z", + "updated_at": "2016-06-14T15:02:50.049Z", "project_id": 5, "attachment": { "url": null @@ -1861,17 +2066,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 405, - "note": "Nemo recusandae dolore distinctio quam consequuntur ut et aut.", + "id": 428, + "note": "Est blanditiis laboriosam enim ipsam.", "noteable_type": "Issue", - "author_id": 22, - "created_at": "2016-03-22T15:20:01.641Z", - "updated_at": "2016-03-22T15:20:01.641Z", + "author_id": 15, + "created_at": "2016-06-14T15:02:50.077Z", + "updated_at": "2016-06-14T15:02:50.077Z", "project_id": 5, "attachment": { "url": null @@ -1882,17 +2090,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 404, - "note": "Nisi repudiandae repellat nulla culpa quasi expedita quod velit.", + "id": 429, + "note": "Et in voluptatem animi dolorem eos.", "noteable_type": "Issue", - "author_id": 24, - "created_at": "2016-03-22T15:20:01.601Z", - "updated_at": "2016-03-22T15:20:01.601Z", + "author_id": 6, + "created_at": "2016-06-14T15:02:50.107Z", + "updated_at": "2016-06-14T15:02:50.107Z", "project_id": 5, "attachment": { "url": null @@ -1903,17 +2114,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 403, - "note": "Quibusdam odio temporibus nemo voluptatibus accusamus.", + "id": 430, + "note": "Unde culpa voluptate qui sint quos.", "noteable_type": "Issue", - "author_id": 26, - "created_at": "2016-03-22T15:20:01.552Z", - "updated_at": "2016-03-22T15:20:01.552Z", + "author_id": 1, + "created_at": "2016-06-14T15:02:50.132Z", + "updated_at": "2016-06-14T15:02:50.132Z", "project_id": 5, "attachment": { "url": null @@ -1924,470 +2138,338 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ] } ], "labels": [ - { - "id": 12, - "title": "test", - "color": "#428bca", - "project_id": 5, - "created_at": "2016-05-10T10:53:14.214Z", - "updated_at": "2016-05-10T10:53:14.214Z", - "template": false, - "description": "test label" - } + ], "milestones": [ { - "id": 11, - "title": "v2.0", + "id": 20, + "title": "v4.0", "project_id": 5, - "description": "Sapiente facilis architecto reprehenderit aut sed enim.", + "description": "Totam quam laborum id magnam natus eaque aspernatur.", "due_date": null, - "created_at": "2016-03-22T15:13:21.631Z", - "updated_at": "2016-03-22T15:13:21.631Z", - "state": "closed", - "iid": 2 + "created_at": "2016-06-14T15:02:04.590Z", + "updated_at": "2016-06-14T15:02:04.590Z", + "state": "active", + "iid": 5, + "events": [ + { + "id": 240, + "target_type": "Milestone", + "target_id": 20, + "title": null, + "data": null, + "project_id": 36, + "created_at": "2016-06-14T15:02:04.593Z", + "updated_at": "2016-06-14T15:02:04.593Z", + "action": 1, + "author_id": 1 + }, + { + "id": 60, + "target_type": "Milestone", + "target_id": 20, + "title": null, + "data": null, + "project_id": 5, + "created_at": "2016-06-14T15:02:04.593Z", + "updated_at": "2016-06-14T15:02:04.593Z", + "action": 1, + "author_id": 20 + } + ] }, { - "id": 10, - "title": "v1.0", + "id": 19, + "title": "v3.0", "project_id": 5, - "description": "Est sed eos minima veniam culpa aut non.", + "description": "Rerum at autem exercitationem ea voluptates harum quam placeat.", "due_date": null, - "created_at": "2016-03-22T15:13:21.622Z", - "updated_at": "2016-03-22T15:13:21.622Z", - "state": "closed", - "iid": 1 - } - ], - "snippets": [ - - ], - "releases": [ - - ], - "events": [ - { - "id": 301, - "target_type": "Note", - "target_id": 1357, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-04-12T13:08:30.886Z", - "updated_at": "2016-04-12T13:08:30.886Z", - "action": 6, - "author_id": 1 - }, - { - "id": 227, - "target_type": "MergeRequest", - "target_id": 85, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:19:44.957Z", - "updated_at": "2016-03-22T15:19:44.957Z", - "action": 1, - "author_id": 1 - }, - { - "id": 226, - "target_type": "MergeRequest", - "target_id": 84, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:19:44.600Z", - "updated_at": "2016-03-22T15:19:44.600Z", - "action": 1, - "author_id": 1 - }, - { - "id": 157, - "target_type": "MergeRequest", - "target_id": 15, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:45.936Z", - "updated_at": "2016-03-22T15:13:45.936Z", - "action": 1, - "author_id": 3 - }, - { - "id": 156, - "target_type": "MergeRequest", - "target_id": 14, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:45.500Z", - "updated_at": "2016-03-22T15:13:45.500Z", - "action": 1, - "author_id": 10 - }, - { - "id": 155, - "target_type": "MergeRequest", - "target_id": 13, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:45.242Z", - "updated_at": "2016-03-22T15:13:45.242Z", - "action": 1, - "author_id": 1 - }, - { - "id": 154, - "target_type": "MergeRequest", - "target_id": 12, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:44.940Z", - "updated_at": "2016-03-22T15:13:44.940Z", - "action": 1, - "author_id": 24 - }, - { - "id": 153, - "target_type": "MergeRequest", - "target_id": 11, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:44.568Z", - "updated_at": "2016-03-22T15:13:44.568Z", - "action": 1, - "author_id": 26 - }, - { - "id": 152, - "target_type": "MergeRequest", - "target_id": 10, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:44.225Z", - "updated_at": "2016-03-22T15:13:44.225Z", - "action": 1, - "author_id": 22 - }, - { - "id": 151, - "target_type": "MergeRequest", - "target_id": 9, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:43.868Z", - "updated_at": "2016-03-22T15:13:43.868Z", - "action": 1, - "author_id": 24 - }, - { - "id": 102, - "target_type": "Issue", - "target_id": 40, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:28.474Z", - "updated_at": "2016-03-22T15:13:28.474Z", - "action": 1, - "author_id": 4 - }, - { - "id": 101, - "target_type": "Issue", - "target_id": 39, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:28.328Z", - "updated_at": "2016-03-22T15:13:28.328Z", - "action": 1, - "author_id": 12 - }, - { - "id": 100, - "target_type": "Issue", - "target_id": 38, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:28.204Z", - "updated_at": "2016-03-22T15:13:28.204Z", - "action": 1, - "author_id": 3 - }, - { - "id": 99, - "target_type": "Issue", - "target_id": 37, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:28.055Z", - "updated_at": "2016-03-22T15:13:28.055Z", - "action": 1, - "author_id": 10 - }, - { - "id": 98, - "target_type": "Issue", - "target_id": 36, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:27.913Z", - "updated_at": "2016-03-22T15:13:27.913Z", - "action": 1, - "author_id": 4 - }, - { - "id": 97, - "target_type": "Issue", - "target_id": 35, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:27.731Z", - "updated_at": "2016-03-22T15:13:27.731Z", - "action": 1, - "author_id": 1 - }, - { - "id": 96, - "target_type": "Issue", - "target_id": 34, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:27.564Z", - "updated_at": "2016-03-22T15:13:27.564Z", - "action": 1, - "author_id": 1 - }, - { - "id": 95, - "target_type": "Issue", - "target_id": 33, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:27.429Z", - "updated_at": "2016-03-22T15:13:27.429Z", - "action": 1, - "author_id": 22 - }, - { - "id": 94, - "target_type": "Issue", - "target_id": 32, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:27.287Z", - "updated_at": "2016-03-22T15:13:27.287Z", - "action": 1, - "author_id": 26 - }, - { - "id": 93, - "target_type": "Issue", - "target_id": 31, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:26.997Z", - "updated_at": "2016-03-22T15:13:26.997Z", - "action": 1, - "author_id": 24 - }, - { - "id": 51, - "target_type": "Milestone", - "target_id": 11, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:21.634Z", - "updated_at": "2016-03-22T15:13:21.634Z", - "action": 1, - "author_id": 26 - }, - { - "id": 50, - "target_type": "Milestone", - "target_id": 10, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:21.625Z", - "updated_at": "2016-03-22T15:13:21.625Z", - "action": 1, - "author_id": 22 - }, - { - "id": 24, - "target_type": null, - "target_id": null, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:20.750Z", - "updated_at": "2016-03-22T15:13:20.750Z", - "action": 8, - "author_id": 12 - }, - { - "id": 23, - "target_type": null, - "target_id": null, - "title": null, - "data": null, - "project_id": 5, - "created_at": "2016-03-22T15:13:20.711Z", - "updated_at": "2016-03-22T15:13:20.711Z", - "action": 8, - "author_id": 22 + "created_at": "2016-06-14T15:02:04.583Z", + "updated_at": "2016-06-14T15:02:04.583Z", + "state": "active", + "iid": 4, + "events": [ + { + "id": 241, + "target_type": "Milestone", + "target_id": 19, + "title": null, + "data": null, + "project_id": 36, + "created_at": "2016-06-14T15:02:04.585Z", + "updated_at": "2016-06-14T15:02:04.585Z", + "action": 1, + "author_id": 1 + }, + { + "id": 59, + "target_type": "Milestone", + "target_id": 19, + "title": null, + "data": { + "object_kind": "push", + "before": "0000000000000000000000000000000000000000", + "after": "de990aa15829d0ab182ad5a55b4c527846c0d39c", + "ref": "refs/heads/removable-group-owner", + "checkout_sha": "de990aa15829d0ab182ad5a55b4c527846c0d39c", + "message": null, + "user_id": 273486, + "user_name": "James Lopez", + "user_email": "james@jameslopez.es", + "project_id": 562317, + "repository": { + "name": "GitLab Community Edition", + "url": "git@gitlab.com:james11/gitlab-ce.git", + "description": "Version Control on your Server. See http://gitlab.org/gitlab-ce/ and the README for more information", + "homepage": "https://gitlab.com/james11/gitlab-ce", + "git_http_url": "https://gitlab.com/james11/gitlab-ce.git", + "git_ssh_url": "git@gitlab.com:james11/gitlab-ce.git", + "visibility_level": 20 + }, + "commits": [ + { + "id": "de990aa15829d0ab182ad5a55b4c527846c0d39c", + "message": "fixed last group owner issue and added test\\n", + "timestamp": "2015-10-29T16:10:27+00:00", + "url": "https://gitlab.com/james11/gitlab-ce/commit/de990aa15829d0ab182ad5a55b4c527846c0d39c", + "author": { + "name": "James Lopez", + "email": "james.lopez@vodafone.com" + } + } + ], + "total_commits_count": 1 + }, + "project_id": 5, + "created_at": "2016-06-14T15:02:04.585Z", + "updated_at": "2016-06-14T15:02:04.585Z", + "action": 1, + "author_id": 25 + } + ] }, { - "id": 22, - "target_type": null, - "target_id": null, - "title": null, - "data": null, + "id": 18, + "title": "v2.0", "project_id": 5, - "created_at": "2016-03-22T15:13:20.667Z", - "updated_at": "2016-03-22T15:13:20.667Z", - "action": 8, - "author_id": 26 + "description": "Error dolorem rerum aut nulla.", + "due_date": null, + "created_at": "2016-06-14T15:02:04.576Z", + "updated_at": "2016-06-14T15:02:04.576Z", + "state": "active", + "iid": 3, + "events": [ + { + "id": 242, + "target_type": "Milestone", + "target_id": 18, + "title": null, + "data": null, + "project_id": 36, + "created_at": "2016-06-14T15:02:04.579Z", + "updated_at": "2016-06-14T15:02:04.579Z", + "action": 1, + "author_id": 1 + }, + { + "id": 58, + "target_type": "Milestone", + "target_id": 18, + "title": null, + "data": null, + "project_id": 5, + "created_at": "2016-06-14T15:02:04.579Z", + "updated_at": "2016-06-14T15:02:04.579Z", + "action": 1, + "author_id": 22 + } + ] }, { - "id": 21, - "target_type": null, - "target_id": null, - "title": null, - "data": null, + "id": 17, + "title": "v1.0", "project_id": 5, - "created_at": "2016-03-22T15:13:20.646Z", - "updated_at": "2016-03-22T15:13:20.646Z", - "action": 8, - "author_id": 1 + "description": "Molestiae perspiciatis voluptates doloremque commodi veniam consequatur.", + "due_date": null, + "created_at": "2016-06-14T15:02:04.569Z", + "updated_at": "2016-06-14T15:02:04.569Z", + "state": "active", + "iid": 2, + "events": [ + { + "id": 243, + "target_type": "Milestone", + "target_id": 17, + "title": null, + "data": null, + "project_id": 36, + "created_at": "2016-06-14T15:02:04.570Z", + "updated_at": "2016-06-14T15:02:04.570Z", + "action": 1, + "author_id": 1 + }, + { + "id": 57, + "target_type": "Milestone", + "target_id": 17, + "title": null, + "data": null, + "project_id": 5, + "created_at": "2016-06-14T15:02:04.570Z", + "updated_at": "2016-06-14T15:02:04.570Z", + "action": 1, + "author_id": 20 + } + ] }, { - "id": 5, - "target_type": null, - "target_id": null, - "title": null, - "data": null, + "id": 16, + "title": "v0.0", "project_id": 5, - "created_at": "2016-03-22T15:13:10.369Z", - "updated_at": "2016-03-22T15:13:10.369Z", - "action": 1, - "author_id": 1 + "description": "Velit numquam et sed sit.", + "due_date": null, + "created_at": "2016-06-14T15:02:04.561Z", + "updated_at": "2016-06-14T15:02:04.561Z", + "state": "closed", + "iid": 1, + "events": [ + { + "id": 244, + "target_type": "Milestone", + "target_id": 16, + "title": null, + "data": null, + "project_id": 36, + "created_at": "2016-06-14T15:02:04.563Z", + "updated_at": "2016-06-14T15:02:04.563Z", + "action": 1, + "author_id": 26 + }, + { + "id": 56, + "target_type": "Milestone", + "target_id": 16, + "title": null, + "data": null, + "project_id": 5, + "created_at": "2016-06-14T15:02:04.563Z", + "updated_at": "2016-06-14T15:02:04.563Z", + "action": 1, + "author_id": 26 + } + ] } + ], + "snippets": [ + + ], + "releases": [ + ], "project_members": [ { - "id": 35, + "id": 36, "access_level": 40, "source_id": 5, "source_type": "Project", - "user_id": 12, + "user_id": 16, "notification_level": 3, - "created_at": "2016-03-22T15:13:20.743Z", - "updated_at": "2016-03-22T15:13:20.743Z", + "created_at": "2016-06-14T15:02:03.834Z", + "updated_at": "2016-06-14T15:02:03.834Z", "created_by_id": null, "invite_email": null, "invite_token": null, "invite_accepted_at": null, + "requested_at": null, "user": { - "id": 12, - "email": "maureen.bogisich@russelkessler.com", - "username": "evans" + "id": 16, + "email": "maritza_schoen@block.ca", + "username": "bernard_willms" } }, { - "id": 34, - "access_level": 40, + "id": 35, + "access_level": 10, "source_id": 5, "source_type": "Project", - "user_id": 22, + "user_id": 6, "notification_level": 3, - "created_at": "2016-03-22T15:13:20.708Z", - "updated_at": "2016-03-22T15:13:20.708Z", + "created_at": "2016-06-14T15:02:03.811Z", + "updated_at": "2016-06-14T15:02:03.811Z", "created_by_id": null, "invite_email": null, "invite_token": null, "invite_accepted_at": null, + "requested_at": null, "user": { - "id": 22, - "email": "user0@example.com", - "username": "user0" + "id": 6, + "email": "shaina@koelpindenesik.com", + "username": "saul_will" } }, { - "id": 33, - "access_level": 40, + "id": 34, + "access_level": 20, "source_id": 5, "source_type": "Project", - "user_id": 26, + "user_id": 15, "notification_level": 3, - "created_at": "2016-03-22T15:13:20.664Z", - "updated_at": "2016-03-22T15:13:20.664Z", + "created_at": "2016-06-14T15:02:03.776Z", + "updated_at": "2016-06-14T15:02:03.776Z", "created_by_id": null, "invite_email": null, "invite_token": null, "invite_accepted_at": null, + "requested_at": null, "user": { - "id": 26, - "email": "user4@example.com", - "username": "user4" + "id": 15, + "email": "breanna_sanford@wolf.com", + "username": "emmet.schamberger" } }, { - "id": 32, + "id": 33, "access_level": 20, "source_id": 5, "source_type": "Project", - "user_id": 1, + "user_id": 26, "notification_level": 3, - "created_at": "2016-03-22T15:13:20.643Z", - "updated_at": "2016-03-22T15:13:20.643Z", + "created_at": "2016-06-14T15:02:03.742Z", + "updated_at": "2016-06-14T15:02:03.742Z", "created_by_id": null, "invite_email": null, "invite_token": null, "invite_accepted_at": null, + "requested_at": null, "user": { - "id": 1, - "email": "nospam@bluegod.net", - "username": "root" + "id": 26, + "email": "user4@example.com", + "username": "user4" } } ], "merge_requests": [ { - "id": 85, + "id": 27, "target_branch": "feature", "source_branch": "feature_conflict", "source_project_id": 5, "author_id": 1, "assignee_id": null, "title": "Cannot be automatically merged", - "created_at": "2016-03-22T15:19:44.807Z", - "updated_at": "2016-03-22T15:20:09.557Z", + "created_at": "2016-06-14T15:02:36.568Z", + "updated_at": "2016-06-14T15:02:56.815Z", "milestone_id": null, "state": "opened", "merge_status": "unchecked", @@ -2399,7 +2481,7 @@ "updated_by_id": null, "merge_error": null, "merge_params": { - + "force_remove_source_branch": null }, "merge_when_build_succeeds": false, "merge_user_id": null, @@ -2407,176 +2489,200 @@ "deleted_at": null, "notes": [ { - "id": 638, - "note": "Ab velit ducimus totam sunt ut.", + "id": 671, + "note": "Sit voluptatibus eveniet architecto quidem.", "noteable_type": "MergeRequest", - "author_id": 1, - "created_at": "2016-03-22T15:20:09.553Z", - "updated_at": "2016-03-22T15:20:09.553Z", + "author_id": 26, + "created_at": "2016-06-14T15:02:56.632Z", + "updated_at": "2016-06-14T15:02:56.632Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 85, + "noteable_id": 27, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 637, - "note": "Ipsum aliquam est in unde similique nihil illo ea.", + "id": 672, + "note": "Odio maxime ratione voluptatibus sed.", "noteable_type": "MergeRequest", - "author_id": 3, - "created_at": "2016-03-22T15:20:09.528Z", - "updated_at": "2016-03-22T15:20:09.528Z", + "author_id": 25, + "created_at": "2016-06-14T15:02:56.656Z", + "updated_at": "2016-06-14T15:02:56.656Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 85, + "noteable_id": 27, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 636, - "note": "Soluta inventore adipisci et consequatur expedita aliquid earum modi.", + "id": 673, + "note": "Et deserunt et omnis nihil excepturi accusantium.", "noteable_type": "MergeRequest", - "author_id": 4, - "created_at": "2016-03-22T15:20:09.496Z", - "updated_at": "2016-03-22T15:20:09.496Z", + "author_id": 22, + "created_at": "2016-06-14T15:02:56.679Z", + "updated_at": "2016-06-14T15:02:56.679Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 85, + "noteable_id": 27, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 635, - "note": "Corporis incidunt tempore est deleniti.", + "id": 674, + "note": "Saepe asperiores exercitationem non dignissimos laborum reiciendis et ipsum.", "noteable_type": "MergeRequest", - "author_id": 10, - "created_at": "2016-03-22T15:20:09.469Z", - "updated_at": "2016-03-22T15:20:09.469Z", + "author_id": 20, + "created_at": "2016-06-14T15:02:56.700Z", + "updated_at": "2016-06-14T15:02:56.700Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 85, + "noteable_id": 27, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 634, - "note": "Hic dolores voluptatibus qui necessitatibus.", + "id": 675, + "note": "Numquam est at dolor quo et sed eligendi similique.", "noteable_type": "MergeRequest", - "author_id": 12, - "created_at": "2016-03-22T15:20:09.440Z", - "updated_at": "2016-03-22T15:20:09.440Z", + "author_id": 16, + "created_at": "2016-06-14T15:02:56.720Z", + "updated_at": "2016-06-14T15:02:56.720Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 85, + "noteable_id": 27, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 633, - "note": "Rerum architecto placeat doloribus voluptates consequuntur quo.", + "id": 676, + "note": "Et perferendis aliquam sunt nisi labore delectus.", "noteable_type": "MergeRequest", - "author_id": 22, - "created_at": "2016-03-22T15:20:09.412Z", - "updated_at": "2016-03-22T15:20:09.412Z", + "author_id": 15, + "created_at": "2016-06-14T15:02:56.742Z", + "updated_at": "2016-06-14T15:02:56.742Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 85, + "noteable_id": 27, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 632, - "note": "Vel earum aut ut occaecati aut ut rerum qui.", + "id": 677, + "note": "Aut ex rerum et in.", "noteable_type": "MergeRequest", - "author_id": 24, - "created_at": "2016-03-22T15:20:09.389Z", - "updated_at": "2016-03-22T15:20:09.389Z", + "author_id": 6, + "created_at": "2016-06-14T15:02:56.791Z", + "updated_at": "2016-06-14T15:02:56.791Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 85, + "noteable_id": 27, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 631, - "note": "Est voluptatibus dolores animi numquam.", + "id": 678, + "note": "Dolor laborum earum ut exercitationem.", "noteable_type": "MergeRequest", - "author_id": 26, - "created_at": "2016-03-22T15:20:09.361Z", - "updated_at": "2016-03-22T15:20:09.361Z", + "author_id": 1, + "created_at": "2016-06-14T15:02:56.814Z", + "updated_at": "2016-06-14T15:02:56.814Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 85, + "noteable_id": 27, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ], "merge_request_diff": { - "id": 85, + "id": 27, "state": "collected", "st_commits": [ { @@ -2759,23 +2865,49 @@ "too_large": false } ], - "merge_request_id": 85, - "created_at": "2016-03-22T15:19:44.810Z", - "updated_at": "2016-03-22T15:19:44.901Z", + "merge_request_id": 27, + "created_at": "2016-06-14T15:02:36.572Z", + "updated_at": "2016-06-14T15:02:36.658Z", "base_commit_sha": "ae73cb07c9eeaf35924a10f713b364d32b2dd34f", "real_size": "9" - } + }, + "events": [ + { + "id": 221, + "target_type": "MergeRequest", + "target_id": 27, + "title": null, + "data": null, + "project_id": 36, + "created_at": "2016-06-14T15:02:36.703Z", + "updated_at": "2016-06-14T15:02:36.703Z", + "action": 1, + "author_id": 1 + }, + { + "id": 187, + "target_type": "MergeRequest", + "target_id": 27, + "title": null, + "data": null, + "project_id": 5, + "created_at": "2016-06-14T15:02:36.703Z", + "updated_at": "2016-06-14T15:02:36.703Z", + "action": 1, + "author_id": 1 + } + ] }, { - "id": 84, + "id": 26, "target_branch": "master", "source_branch": "feature", "source_project_id": 5, "author_id": 1, "assignee_id": null, "title": "Can be automatically merged", - "created_at": "2016-03-22T15:19:44.482Z", - "updated_at": "2016-03-22T15:20:09.773Z", + "created_at": "2016-06-14T15:02:36.418Z", + "updated_at": "2016-06-14T15:02:57.013Z", "milestone_id": null, "state": "opened", "merge_status": "unchecked", @@ -2787,7 +2919,7 @@ "updated_by_id": null, "merge_error": null, "merge_params": { - + "force_remove_source_branch": null }, "merge_when_build_succeeds": false, "merge_user_id": null, @@ -2795,176 +2927,200 @@ "deleted_at": null, "notes": [ { - "id": 646, - "note": "Temporibus debitis veniam est ut sit nihil.", + "id": 679, + "note": "Qui rerum totam nisi est.", "noteable_type": "MergeRequest", - "author_id": 1, - "created_at": "2016-03-22T15:20:09.770Z", - "updated_at": "2016-03-22T15:20:09.770Z", + "author_id": 26, + "created_at": "2016-06-14T15:02:56.848Z", + "updated_at": "2016-06-14T15:02:56.848Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 84, + "noteable_id": 26, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 645, - "note": "Ut assumenda dignissimos quibusdam veritatis sequi dolores.", + "id": 680, + "note": "Pariatur magni corrupti consequatur debitis minima error beatae voluptatem.", "noteable_type": "MergeRequest", - "author_id": 3, - "created_at": "2016-03-22T15:20:09.740Z", - "updated_at": "2016-03-22T15:20:09.740Z", + "author_id": 25, + "created_at": "2016-06-14T15:02:56.871Z", + "updated_at": "2016-06-14T15:02:56.871Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 84, + "noteable_id": 26, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 644, - "note": "Velit quae quidem cupiditate laudantium nihil ut eveniet.", + "id": 681, + "note": "Qui quis ut modi eos rerum ratione.", "noteable_type": "MergeRequest", - "author_id": 4, - "created_at": "2016-03-22T15:20:09.717Z", - "updated_at": "2016-03-22T15:20:09.717Z", + "author_id": 22, + "created_at": "2016-06-14T15:02:56.895Z", + "updated_at": "2016-06-14T15:02:56.895Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 84, + "noteable_id": 26, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 643, - "note": "Repellat quas porro sed mollitia laborum ut fugiat.", + "id": 682, + "note": "Illum quidem expedita mollitia fugit.", "noteable_type": "MergeRequest", - "author_id": 10, - "created_at": "2016-03-22T15:20:09.690Z", - "updated_at": "2016-03-22T15:20:09.690Z", + "author_id": 20, + "created_at": "2016-06-14T15:02:56.918Z", + "updated_at": "2016-06-14T15:02:56.918Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 84, + "noteable_id": 26, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 642, - "note": "Qui aut debitis perspiciatis et voluptatem.", + "id": 683, + "note": "Consectetur voluptate sit sint possimus veritatis quod.", "noteable_type": "MergeRequest", - "author_id": 12, - "created_at": "2016-03-22T15:20:09.665Z", - "updated_at": "2016-03-22T15:20:09.665Z", + "author_id": 16, + "created_at": "2016-06-14T15:02:56.942Z", + "updated_at": "2016-06-14T15:02:56.942Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 84, + "noteable_id": 26, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 641, - "note": "Quia id quia velit et.", + "id": 684, + "note": "Natus libero quibusdam rem assumenda deleniti accusamus sed earum.", "noteable_type": "MergeRequest", - "author_id": 22, - "created_at": "2016-03-22T15:20:09.639Z", - "updated_at": "2016-03-22T15:20:09.639Z", + "author_id": 15, + "created_at": "2016-06-14T15:02:56.966Z", + "updated_at": "2016-06-14T15:02:56.966Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 84, + "noteable_id": 26, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 640, - "note": "Corporis commodi doloremque itaque non animi.", + "id": 685, + "note": "Tenetur autem nihil rerum odit.", "noteable_type": "MergeRequest", - "author_id": 24, - "created_at": "2016-03-22T15:20:09.617Z", - "updated_at": "2016-03-22T15:20:09.617Z", + "author_id": 6, + "created_at": "2016-06-14T15:02:56.989Z", + "updated_at": "2016-06-14T15:02:56.989Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 84, + "noteable_id": 26, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 639, - "note": "Possimus dignissimos voluptatum in tenetur.", + "id": 686, + "note": "Quia maiores et odio sed.", "noteable_type": "MergeRequest", - "author_id": 26, - "created_at": "2016-03-22T15:20:09.589Z", - "updated_at": "2016-03-22T15:20:09.589Z", + "author_id": 1, + "created_at": "2016-06-14T15:02:57.012Z", + "updated_at": "2016-06-14T15:02:57.012Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 84, + "noteable_id": 26, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ], "merge_request_diff": { - "id": 84, + "id": 26, "state": "collected", "st_commits": [ { @@ -2994,35 +3150,61 @@ "too_large": false } ], - "merge_request_id": 84, - "created_at": "2016-03-22T15:19:44.485Z", - "updated_at": "2016-03-22T15:19:44.577Z", + "merge_request_id": 26, + "created_at": "2016-06-14T15:02:36.421Z", + "updated_at": "2016-06-14T15:02:36.474Z", "base_commit_sha": "ae73cb07c9eeaf35924a10f713b364d32b2dd34f", "real_size": "1" - } + }, + "events": [ + { + "id": 222, + "target_type": "MergeRequest", + "target_id": 26, + "title": null, + "data": null, + "project_id": 36, + "created_at": "2016-06-14T15:02:36.496Z", + "updated_at": "2016-06-14T15:02:36.496Z", + "action": 1, + "author_id": 1 + }, + { + "id": 186, + "target_type": "MergeRequest", + "target_id": 26, + "title": null, + "data": null, + "project_id": 5, + "created_at": "2016-06-14T15:02:36.496Z", + "updated_at": "2016-06-14T15:02:36.496Z", + "action": 1, + "author_id": 1 + } + ] }, { "id": 15, - "target_branch": "markdown", - "source_branch": "master", + "target_branch": "test-7", + "source_branch": "test-1", "source_project_id": 5, - "author_id": 3, - "assignee_id": 3, - "title": "Nulla explicabo iure voluptas perferendis autem autem unde nemo totam optio.", - "created_at": "2016-03-22T15:13:45.689Z", - "updated_at": "2016-03-22T15:20:30.476Z", - "milestone_id": 10, + "author_id": 22, + "assignee_id": 16, + "title": "Qui accusantium et inventore facilis doloribus occaecati officiis.", + "created_at": "2016-06-14T15:02:25.168Z", + "updated_at": "2016-06-14T15:02:59.521Z", + "milestone_id": 17, "state": "opened", "merge_status": "unchecked", "target_project_id": 5, "iid": 7, - "description": "Doloribus dignissimos impedit qui et provident exercitationem. Veniam quis magni qui fugiat. Et quia voluptate et vel consequatur pariatur ea est.", + "description": "Et commodi deserunt aspernatur vero rerum. Ut non dolorum alias in odit est libero. Voluptatibus eos in et vitae repudiandae facilis ex mollitia.", "position": 0, "locked_at": null, "updated_by_id": null, "merge_error": null, "merge_params": { - + "force_remove_source_branch": null }, "merge_when_build_succeeds": false, "merge_user_id": null, @@ -3030,12 +3212,12 @@ "deleted_at": null, "notes": [ { - "id": 1231, - "note": "Rerum optio quibusdam provident possimus quis cum.", + "id": 777, + "note": "Pariatur voluptas placeat aspernatur culpa suscipit soluta.", "noteable_type": "MergeRequest", - "author_id": 1, - "created_at": "2016-03-22T15:20:30.472Z", - "updated_at": "2016-03-22T15:20:30.472Z", + "author_id": 26, + "created_at": "2016-06-14T15:02:59.348Z", + "updated_at": "2016-06-14T15:02:59.348Z", "project_id": 5, "attachment": { "url": null @@ -3046,17 +3228,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 1230, - "note": "Quasi odit repudiandae ut officiis ut nihil illo.", + "id": 778, + "note": "Alias et iure mollitia suscipit molestiae voluptatum nostrum asperiores.", "noteable_type": "MergeRequest", - "author_id": 3, - "created_at": "2016-03-22T15:20:30.444Z", - "updated_at": "2016-03-22T15:20:30.444Z", + "author_id": 25, + "created_at": "2016-06-14T15:02:59.372Z", + "updated_at": "2016-06-14T15:02:59.372Z", "project_id": 5, "attachment": { "url": null @@ -3067,17 +3252,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 1229, - "note": "Aut vero dolores facere sed.", + "id": 779, + "note": "Laudantium qui eum qui sunt.", "noteable_type": "MergeRequest", - "author_id": 4, - "created_at": "2016-03-22T15:20:30.412Z", - "updated_at": "2016-03-22T15:20:30.412Z", + "author_id": 22, + "created_at": "2016-06-14T15:02:59.395Z", + "updated_at": "2016-06-14T15:02:59.395Z", "project_id": 5, "attachment": { "url": null @@ -3088,17 +3276,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 1228, - "note": "Autem voluptatem et blanditiis accusantium deserunt et et.", + "id": 780, + "note": "Quas rem est iusto ut delectus fugiat recusandae mollitia.", "noteable_type": "MergeRequest", - "author_id": 10, - "created_at": "2016-03-22T15:20:30.383Z", - "updated_at": "2016-03-22T15:20:30.383Z", + "author_id": 20, + "created_at": "2016-06-14T15:02:59.418Z", + "updated_at": "2016-06-14T15:02:59.418Z", "project_id": 5, "attachment": { "url": null @@ -3109,17 +3300,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 1227, - "note": "Voluptatem aliquam voluptatem molestiae est.", + "id": 781, + "note": "Repellendus ab et qui nesciunt.", "noteable_type": "MergeRequest", - "author_id": 12, - "created_at": "2016-03-22T15:20:30.352Z", - "updated_at": "2016-03-22T15:20:30.352Z", + "author_id": 16, + "created_at": "2016-06-14T15:02:59.444Z", + "updated_at": "2016-06-14T15:02:59.444Z", "project_id": 5, "attachment": { "url": null @@ -3130,17 +3324,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 1226, - "note": "Ea aut cupiditate est consequatur animi error qui et.", + "id": 782, + "note": "Non possimus voluptatum odio qui ut.", "noteable_type": "MergeRequest", - "author_id": 22, - "created_at": "2016-03-22T15:20:30.319Z", - "updated_at": "2016-03-22T15:20:30.319Z", + "author_id": 15, + "created_at": "2016-06-14T15:02:59.469Z", + "updated_at": "2016-06-14T15:02:59.469Z", "project_id": 5, "attachment": { "url": null @@ -3151,17 +3348,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 1225, - "note": "Voluptates est voluptas et nostrum modi beatae inventore et.", + "id": 783, + "note": "Dolores repellendus eum ducimus quam ab dolorem quia.", "noteable_type": "MergeRequest", - "author_id": 24, - "created_at": "2016-03-22T15:20:30.289Z", - "updated_at": "2016-03-22T15:20:30.289Z", + "author_id": 6, + "created_at": "2016-06-14T15:02:59.494Z", + "updated_at": "2016-06-14T15:02:59.494Z", "project_id": 5, "attachment": { "url": null @@ -3172,17 +3372,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 1224, - "note": "Quia est rerum adipisci cupiditate.", + "id": 784, + "note": "Facilis dolorem aut corrupti id ratione occaecati.", "noteable_type": "MergeRequest", - "author_id": 26, - "created_at": "2016-03-22T15:20:30.260Z", - "updated_at": "2016-03-22T15:20:30.260Z", + "author_id": 1, + "created_at": "2016-06-14T15:02:59.520Z", + "updated_at": "2016-06-14T15:02:59.520Z", "project_id": 5, "attachment": { "url": null @@ -3193,9 +3396,12 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ], "merge_request_diff": { @@ -3203,51 +3409,349 @@ "state": "collected", "st_commits": [ { - "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", + "id": "94b8d581c48d894b86661718582fecbc5e3ed2eb", + "message": "fixes #10\n", "parent_ids": [ - "5f923865dde3436854e9ceb9cdb7815618d4e849", - "048721d90c449b244b7b4c53a9186b04330174ec" + "be93687618e4b132087f430a4d8fc3a609c9b77c" ], - "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" - }, + "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": [ { - "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" + "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 }, - { - "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" + "line_code": null, + "commit_id": null, + "noteable_id": 14, + "system": false, + "st_diff": null, + "updated_by_id": null, + "author": { + "name": "User 4" }, - { - "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" + "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", @@ -3388,31 +3892,140 @@ "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": "--- 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", + "diff": "Binary files a/.DS_Store and /dev/null differ\n", + "new_path": ".DS_Store", + "old_path": ".DS_Store", "a_mode": "100644", - "b_mode": "100644", + "b_mode": "0", "new_file": false, "renamed_file": false, - "deleted_file": false, + "deleted_file": true, "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, + "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", @@ -3435,6 +4048,28 @@ "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", @@ -3456,37 +4091,96 @@ "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": 15, - "created_at": "2016-03-22T15:13:45.692Z", - "updated_at": "2016-03-22T15:13:45.808Z", - "base_commit_sha": "5937ac0a7beb003549fc5fd26fc247adbce4a52e", - "real_size": "6" - } + "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": 14, - "target_branch": "test-1", - "source_branch": "test-10", + "id": 13, + "target_branch": "improve/awesome", + "source_branch": "test-8", "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, + "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": 6, - "description": "Quis et et autem saepe ut. Eum corporis tempore cum dolore. Molestiae pariatur voluptatem officia perferendis aut veniam.", + "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, @@ -3494,428 +4188,970 @@ "deleted_at": null, "notes": [ { - "id": 1239, - "note": "Aspernatur suscipit veritatis aliquid rerum.", + "id": 793, + "note": "In illum maxime aperiam nulla est aspernatur.", "noteable_type": "MergeRequest", - "author_id": 1, - "created_at": "2016-03-22T15:20:30.731Z", - "updated_at": "2016-03-22T15:20:30.731Z", + "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": 14, + "noteable_id": 13, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 1238, - "note": "Rerum deleniti omnis porro commodi.", + "id": 794, + "note": "Enim quia perferendis cum distinctio tenetur optio voluptas veniam.", "noteable_type": "MergeRequest", - "author_id": 3, - "created_at": "2016-03-22T15:20:30.701Z", - "updated_at": "2016-03-22T15:20:30.701Z", + "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": 14, + "noteable_id": 13, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 1237, - "note": "Eaque ut magnam rerum non dolores esse.", + "id": 795, + "note": "Dolor ad quia quis pariatur ducimus.", "noteable_type": "MergeRequest", - "author_id": 4, - "created_at": "2016-03-22T15:20:30.667Z", - "updated_at": "2016-03-22T15:20:30.667Z", + "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": 14, + "noteable_id": 13, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 1236, - "note": "Fugit et aut similique illum ut natus maiores et.", + "id": 796, + "note": "Et a odio voluptate aut.", "noteable_type": "MergeRequest", - "author_id": 10, - "created_at": "2016-03-22T15:20:30.637Z", - "updated_at": "2016-03-22T15:20:30.637Z", + "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": 14, + "noteable_id": 13, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 1235, - "note": "Qui qui temporibus eos aliquam.", + "id": 797, + "note": "Quis nihil temporibus voluptatum modi minima a ut.", "noteable_type": "MergeRequest", - "author_id": 12, - "created_at": "2016-03-22T15:20:30.608Z", - "updated_at": "2016-03-22T15:20:30.608Z", + "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": 14, + "noteable_id": 13, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 1234, - "note": "Voluptates hic dolorum aut inventore.", + "id": 798, + "note": "Ut alias consequatur in nostrum.", "noteable_type": "MergeRequest", - "author_id": 22, - "created_at": "2016-03-22T15:20:30.575Z", - "updated_at": "2016-03-22T15:20:30.575Z", + "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": 14, + "noteable_id": 13, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 1233, - "note": "Dolorum iure at dolor dolores numquam iusto.", + "id": 799, + "note": "Voluptatibus aperiam assumenda et neque sint libero.", "noteable_type": "MergeRequest", - "author_id": 24, - "created_at": "2016-03-22T15:20:30.548Z", - "updated_at": "2016-03-22T15:20:30.548Z", + "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": 14, + "noteable_id": 13, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 1232, - "note": "Nihil est eum aspernatur amet minus et corporis consectetur.", + "id": 800, + "note": "Veritatis voluptatem dolor dolores magni quo ut ipsa fuga.", "noteable_type": "MergeRequest", - "author_id": 26, - "created_at": "2016-03-22T15:20:30.517Z", - "updated_at": "2016-03-22T15:20:30.517Z", + "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": 14, + "noteable_id": 13, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ], "merge_request_diff": { - "id": 14, + "id": 13, "state": "collected", "st_commits": [ { - "id": "bce96ecee98f51fa5d91021e6c42859a35a701ad", + "id": "0bfedc29d30280c7e8564e19f654584b459e5868", "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 + "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" }, - "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 + { + "id": "be93687618e4b132087f430a4d8fc3a609c9b77c", + "message": "Merge branch 'master' into 'master'\r\n\r\nLFS object pointer.\r\n\r\n\r\n\r\nSee merge request !6", + "parent_ids": [ + "5f923865dde3436854e9ceb9cdb7815618d4e849", + "048721d90c449b244b7b4c53a9186b04330174ec" + ], + "authored_date": "2015-12-07T12:52:12.000+01:00", + "author_name": "Marin Jankovski", + "author_email": "marin@gitlab.com", + "committed_date": "2015-12-07T12:52:12.000+01:00", + "committer_name": "Marin Jankovski", + "committer_email": "marin@gitlab.com" + }, + { + "id": "048721d90c449b244b7b4c53a9186b04330174ec", + "message": "LFS object pointer.\n", + "parent_ids": [ + "5f923865dde3436854e9ceb9cdb7815618d4e849" + ], + "authored_date": "2015-12-07T11:54:28.000+01:00", + "author_name": "Marin Jankovski", + "author_email": "maxlazio@gmail.com", + "committed_date": "2015-12-07T11:54:28.000+01:00", + "committer_name": "Marin Jankovski", + "committer_email": "maxlazio@gmail.com" + }, + { + "id": "5f923865dde3436854e9ceb9cdb7815618d4e849", + "message": "GitLab currently doesn't support patches that involve a merge commit: add a commit here\n", + "parent_ids": [ + "d2d430676773caa88cdaf7c55944073b2fd5561a" + ], + "authored_date": "2015-11-13T16:27:12.000+01:00", + "author_name": "Stan Hu", + "author_email": "stanhu@gmail.com", + "committed_date": "2015-11-13T16:27:12.000+01:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@gmail.com" + }, + { + "id": "d2d430676773caa88cdaf7c55944073b2fd5561a", + "message": "Merge branch 'add-svg' into 'master'\r\n\r\nAdd GitLab SVG\r\n\r\nAdded to test preview of sanitized SVG images\r\n\r\nSee merge request !5", + "parent_ids": [ + "59e29889be61e6e0e5e223bfa9ac2721d31605b8", + "2ea1f3dec713d940208fb5ce4a38765ecb5d3f73" + ], + "authored_date": "2015-11-13T08:50:17.000+01:00", + "author_name": "Stan Hu", + "author_email": "stanhu@gmail.com", + "committed_date": "2015-11-13T08:50:17.000+01:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@gmail.com" + }, + { + "id": "2ea1f3dec713d940208fb5ce4a38765ecb5d3f73", + "message": "Add GitLab SVG\n", + "parent_ids": [ + "59e29889be61e6e0e5e223bfa9ac2721d31605b8" + ], + "authored_date": "2015-11-13T08:39:43.000+01:00", + "author_name": "Stan Hu", + "author_email": "stanhu@gmail.com", + "committed_date": "2015-11-13T08:39:43.000+01:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@gmail.com" + }, + { + "id": "59e29889be61e6e0e5e223bfa9ac2721d31605b8", + "message": "Merge branch 'whitespace' into 'master'\r\n\r\nadd whitespace test file\r\n\r\nSorry, I did a mistake.\r\nGit ignore empty files.\r\nSo I add a new whitespace test file.\r\n\r\nSee merge request !4", + "parent_ids": [ + "19e2e9b4ef76b422ce1154af39a91323ccc57434", + "66eceea0db202bb39c4e445e8ca28689645366c5" + ], + "authored_date": "2015-11-13T07:21:40.000+01:00", + "author_name": "Stan Hu", + "author_email": "stanhu@gmail.com", + "committed_date": "2015-11-13T07:21:40.000+01:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@gmail.com" + }, + { + "id": "66eceea0db202bb39c4e445e8ca28689645366c5", + "message": "add spaces in whitespace file\n", + "parent_ids": [ + "08f22f255f082689c0d7d39d19205085311542bc" + ], + "authored_date": "2015-11-13T06:01:27.000+01:00", + "author_name": "윤민식", + "author_email": "minsik.yoon@samsung.com", + "committed_date": "2015-11-13T06:01:27.000+01:00", + "committer_name": "윤민식", + "committer_email": "minsik.yoon@samsung.com" + }, + { + "id": "08f22f255f082689c0d7d39d19205085311542bc", + "message": "remove emtpy file.(beacase git ignore empty file)\nadd whitespace test file.\n", + "parent_ids": [ + "c642fe9b8b9f28f9225d7ea953fe14e74748d53b" + ], + "authored_date": "2015-11-13T06:00:16.000+01:00", + "author_name": "윤민식", + "author_email": "minsik.yoon@samsung.com", + "committed_date": "2015-11-13T06:00:16.000+01:00", + "committer_name": "윤민식", + "committer_email": "minsik.yoon@samsung.com" + }, + { + "id": "19e2e9b4ef76b422ce1154af39a91323ccc57434", + "message": "Merge branch 'whitespace' into 'master'\r\n\r\nadd spaces\r\n\r\nTo test this pull request.(https://github.com/gitlabhq/gitlabhq/pull/9757)\r\nJust add whitespaces.\r\n\r\nSee merge request !3", + "parent_ids": [ + "c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd", + "c642fe9b8b9f28f9225d7ea953fe14e74748d53b" + ], + "authored_date": "2015-11-13T05:23:14.000+01:00", + "author_name": "Stan Hu", + "author_email": "stanhu@gmail.com", + "committed_date": "2015-11-13T05:23:14.000+01:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@gmail.com" + }, + { + "id": "c642fe9b8b9f28f9225d7ea953fe14e74748d53b", + "message": "add whitespace in empty\n", + "parent_ids": [ + "9a944d90955aaf45f6d0c88f30e27f8d2c41cec0" + ], + "authored_date": "2015-11-13T05:08:45.000+01:00", + "author_name": "윤민식", + "author_email": "minsik.yoon@samsung.com", + "committed_date": "2015-11-13T05:08:45.000+01:00", + "committer_name": "윤민식", + "committer_email": "minsik.yoon@samsung.com" + }, + { + "id": "9a944d90955aaf45f6d0c88f30e27f8d2c41cec0", + "message": "add empty file\n", + "parent_ids": [ + "c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd" + ], + "authored_date": "2015-11-13T05:08:04.000+01:00", + "author_name": "윤민식", + "author_email": "minsik.yoon@samsung.com", + "committed_date": "2015-11-13T05:08:04.000+01:00", + "committer_name": "윤민식", + "committer_email": "minsik.yoon@samsung.com" + }, + { + "id": "c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd", + "message": "Add ISO-8859 test file\n", + "parent_ids": [ + "e56497bb5f03a90a51293fc6d516788730953899" + ], + "authored_date": "2015-08-25T17:53:12.000+02:00", + "author_name": "Stan Hu", + "author_email": "stanhu@packetzoom.com", + "committed_date": "2015-08-25T17:53:12.000+02:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@packetzoom.com" + }, + { + "id": "e56497bb5f03a90a51293fc6d516788730953899", + "message": "Merge branch 'tree_helper_spec' into 'master'\n\nAdd directory structure for tree_helper spec\n\nThis directory structure is needed for a testing the method flatten_tree(tree) in the TreeHelper module\n\nSee [merge request #275](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/275#note_732774)\n\nSee merge request !2\n", + "parent_ids": [ + "5937ac0a7beb003549fc5fd26fc247adbce4a52e", + "4cd80ccab63c82b4bad16faa5193fbd2aa06df40" + ], + "authored_date": "2015-01-10T22:23:29.000+01:00", + "author_name": "Sytse Sijbrandij", + "author_email": "sytse@gitlab.com", + "committed_date": "2015-01-10T22:23:29.000+01:00", + "committer_name": "Sytse Sijbrandij", + "committer_email": "sytse@gitlab.com" + }, + { + "id": "4cd80ccab63c82b4bad16faa5193fbd2aa06df40", + "message": "add directory structure for tree_helper spec\n", + "parent_ids": [ + "5937ac0a7beb003549fc5fd26fc247adbce4a52e" + ], + "authored_date": "2015-01-10T21:28:18.000+01:00", + "author_name": "marmis85", + "author_email": "marmis85@gmail.com", + "committed_date": "2015-01-10T21:28:18.000+01:00", + "committer_name": "marmis85", + "committer_email": "marmis85@gmail.com" + } + ], + "st_diffs": [ + { + "diff": "--- a/CHANGELOG\n+++ b/CHANGELOG\n@@ -1,4 +1,6 @@\n-v 6.7.0\n+v6.8.0\n+\n+v6.7.0\n - Add support for Gemnasium as a Project Service (Olivier Gonzalez)\n - Add edit file button to MergeRequest diff\n - Public groups (Jason Hollingsworth)\n", + "new_path": "CHANGELOG", + "old_path": "CHANGELOG", + "a_mode": "100644", + "b_mode": "100644", + "new_file": false, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- /dev/null\n+++ b/encoding/iso8859.txt\n@@ -0,0 +1 @@\n+Äü\n", + "new_path": "encoding/iso8859.txt", + "old_path": "encoding/iso8859.txt", + "a_mode": "0", + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- /dev/null\n+++ b/files/images/wm.svg\n@@ -0,0 +1,78 @@\n+\u003c?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?\u003e\n+\u003csvg width=\"1300px\" height=\"680px\" viewBox=\"0 0 1300 680\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\"\u003e\n+ \u003c!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch --\u003e\n+ \u003ctitle\u003ewm\u003c/title\u003e\n+ \u003cdesc\u003eCreated with Sketch.\u003c/desc\u003e\n+ \u003cdefs\u003e\n+ \u003cpath id=\"path-1\" d=\"M-69.8,1023.54607 L1675.19996,1023.54607 L1675.19996,0 L-69.8,0 L-69.8,1023.54607 L-69.8,1023.54607 Z\"\u003e\u003c/path\u003e\n+ \u003c/defs\u003e\n+ \u003cg id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\"\u003e\n+ \u003cpath d=\"M1300,680 L0,680 L0,0 L1300,0 L1300,680 L1300,680 Z\" id=\"bg\" fill=\"#30353E\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003cg id=\"gitlab_logo\" sketch:type=\"MSLayerGroup\" transform=\"translate(-262.000000, -172.000000)\"\u003e\n+ \u003cg id=\"g10\" transform=\"translate(872.500000, 512.354581) scale(1, -1) translate(-872.500000, -512.354581) translate(0.000000, 0.290751)\"\u003e\n+ \u003cg id=\"g12\" transform=\"translate(1218.022652, 440.744871)\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\n+ \u003cpath d=\"M-50.0233338,141.900706 L-69.07059,141.900706 L-69.0100967,0.155858152 L8.04444805,0.155858152 L8.04444805,17.6840847 L-49.9628405,17.6840847 L-50.0233338,141.900706 L-50.0233338,141.900706 Z\" id=\"path14\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g16\"\u003e\n+ \u003cg id=\"g18-Clipped\"\u003e\n+ \u003cmask id=\"mask-2\" sketch:name=\"path22\" fill=\"white\"\u003e\n+ \u003cuse xlink:href=\"#path-1\"\u003e\u003c/use\u003e\n+ \u003c/mask\u003e\n+ \u003cg id=\"path22\"\u003e\u003c/g\u003e\n+ \u003cg id=\"g18\" mask=\"url(#mask-2)\"\u003e\n+ \u003cg transform=\"translate(382.736659, 312.879425)\"\u003e\n+ \u003cg id=\"g24\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(852.718192, 124.992771)\"\u003e\n+ \u003cpath d=\"M63.9833317,27.9148929 C59.2218085,22.9379001 51.2134221,17.9597442 40.3909323,17.9597442 C25.8888194,17.9597442 20.0453962,25.1013043 20.0453962,34.4074318 C20.0453962,48.4730484 29.7848226,55.1819277 50.5642821,55.1819277 C54.4602853,55.1819277 60.7364685,54.7492469 63.9833317,54.1002256 L63.9833317,27.9148929 L63.9833317,27.9148929 Z M44.2869356,113.827628 C28.9053426,113.827628 14.7975996,108.376082 3.78897657,99.301416 L10.5211864,87.6422957 C18.3131929,92.1866076 27.8374026,96.7320827 41.4728323,96.7320827 C57.0568452,96.7320827 63.9833317,88.7239978 63.9833317,75.3074024 L63.9833317,68.3821827 C60.9528485,69.0312039 54.6766653,69.4650479 50.7806621,69.4650479 C17.4476729,69.4650479 0.565379986,57.7791759 0.565379986,33.3245665 C0.565379986,11.4683685 13.9844297,0.43151772 34.3299658,0.43151772 C48.0351955,0.43151772 61.1692285,6.70771614 65.7143717,16.8780421 L69.1776149,3.02876588 L82.5978279,3.02876588 L82.5978279,75.5237428 C82.5978279,98.462806 72.6408582,113.827628 44.2869356,113.827628 L44.2869356,113.827628 Z\" id=\"path26\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g28\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(959.546624, 124.857151)\"\u003e\n+ \u003cpath d=\"M37.2266657,17.4468081 C30.0837992,17.4468081 23.8064527,18.3121698 19.0449295,20.4767371 L19.0449295,79.2306079 L19.0449295,86.0464943 C25.538656,91.457331 33.5470425,95.3526217 43.7203922,95.3526217 C62.1173451,95.3526217 69.2602116,82.3687072 69.2602116,61.3767077 C69.2602116,31.5135879 57.7885819,17.4468081 37.2266657,17.4468081 M45.2315622,113.963713 C28.208506,113.963713 19.0449295,102.384849 19.0449295,102.384849 L19.0449295,120.67143 L18.9844362,144.908535 L10.3967097,144.908535 L0.371103324,144.908535 L0.431596656,6.62629771 C9.73826309,2.73100702 22.5081728,0.567602823 36.3611458,0.567602823 C71.8579349,0.567602823 88.9566078,23.2891625 88.9566078,62.4584098 C88.9566078,93.4043948 73.1527248,113.963713 45.2315622,113.963713\" id=\"path30\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g32\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(509.576747, 125.294950)\"\u003e\n+ \u003cpath d=\"M68.636665,129.10638 C85.5189579,129.10638 96.3414476,123.480366 103.484314,117.853189 L111.669527,132.029302 C100.513161,141.811145 85.5073245,147.06845 69.5021849,147.06845 C29.0274926,147.06845 0.673569983,122.3975 0.673569983,72.6252464 C0.673569983,20.4709215 31.2622559,0.12910638 66.2553217,0.12910638 C83.7879179,0.12910638 98.7227909,4.24073748 108.462217,8.35236859 L108.063194,64.0763105 L108.063194,70.6502677 L108.063194,81.6057001 L56.1168719,81.6057001 L56.1168719,64.0763105 L89.2323178,64.0763105 L89.6313411,21.7701271 C85.3025779,19.6055598 77.7269514,17.8748364 67.554765,17.8748364 C39.4172223,17.8748364 20.5863462,35.5717154 20.5863462,72.8415868 C20.5863462,110.711628 40.0663623,129.10638 68.636665,129.10638\" id=\"path34\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g36\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(692.388992, 124.376085)\"\u003e\n+ \u003cpath d=\"M19.7766662,145.390067 L1.16216997,145.390067 L1.2226633,121.585642 L1.2226633,111.846834 L1.2226633,106.170806 L1.2226633,96.2656714 L1.2226633,39.5681976 L1.2226633,39.3518572 C1.2226633,16.4127939 11.1796331,1.04797161 39.5335557,1.04797161 C43.4504989,1.04797161 47.2836822,1.40388649 51.0051854,2.07965952 L51.0051854,18.7925385 C48.3109055,18.3796307 45.4351455,18.1446804 42.3476589,18.1446804 C26.763646,18.1446804 19.8371595,26.1516022 19.8371595,39.5681976 L19.8371595,96.2656714 L51.0051854,96.2656714 L51.0051854,111.846834 L19.8371595,111.846834 L19.7766662,145.390067 L19.7766662,145.390067 Z\" id=\"path38\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cpath d=\"M646.318899,128.021188 L664.933395,128.021188 L664.933395,236.223966 L646.318899,236.223966 L646.318899,128.021188 L646.318899,128.021188 Z\" id=\"path40\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003cpath d=\"M646.318899,251.154944 L664.933395,251.154944 L664.933395,269.766036 L646.318899,269.766036 L646.318899,251.154944 L646.318899,251.154944 Z\" id=\"path42\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003cg id=\"g44\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.464170, 0.676006)\"\u003e\n+ \u003cpath d=\"M429.269989,169.815599 L405.225053,243.802859 L357.571431,390.440955 C355.120288,397.984955 344.444378,397.984955 341.992071,390.440955 L294.337286,243.802859 L136.094873,243.802859 L88.4389245,390.440955 C85.9877812,397.984955 75.3118715,397.984955 72.8595648,390.440955 L25.2059427,243.802859 L1.16216997,169.815599 C-1.03187664,163.067173 1.37156997,155.674379 7.11261982,151.503429 L215.215498,0.336141836 L423.319539,151.503429 C429.060589,155.674379 431.462873,163.067173 429.269989,169.815599\" id=\"path46\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g48\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(135.410135, 1.012147)\"\u003e\n+ \u003cpath d=\"M80.269998,0 L80.269998,0 L159.391786,243.466717 L1.14820997,243.466717 L80.269998,0 L80.269998,0 Z\" id=\"path50\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g52\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\"\u003e\n+ \u003cg id=\"path54\"\u003e\u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g56\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(24.893471, 1.012613)\"\u003e\n+ \u003cpath d=\"M190.786662,0 L111.664874,243.465554 L0.777106647,243.465554 L190.786662,0 L190.786662,0 Z\" id=\"path58\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g60\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\"\u003e\n+ \u003cg id=\"path62\"\u003e\u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g64\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.077245, 0.223203)\"\u003e\n+ \u003cpath d=\"M25.5933327,244.255313 L25.5933327,244.255313 L1.54839663,170.268052 C-0.644486651,163.519627 1.75779662,156.126833 7.50000981,151.957046 L215.602888,0.789758846 L25.5933327,244.255313 L25.5933327,244.255313 Z\" id=\"path66\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g68\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\"\u003e\n+ \u003cg id=\"path70\"\u003e\u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g72\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(25.670578, 244.478283)\"\u003e\n+ \u003cpath d=\"M0,0 L110.887767,0 L63.2329818,146.638096 C60.7806751,154.183259 50.1047654,154.183259 47.6536221,146.638096 L0,0 L0,0 Z\" id=\"path74\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g76\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\"\u003e\n+ \u003cpath d=\"M0,0 L79.121788,243.465554 L190.009555,243.465554 L0,0 L0,0 Z\" id=\"path78\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g80\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(214.902910, 0.223203)\"\u003e\n+ \u003cpath d=\"M190.786662,244.255313 L190.786662,244.255313 L214.831598,170.268052 C217.024481,163.519627 214.622198,156.126833 208.879985,151.957046 L0.777106647,0.789758846 L190.786662,244.255313 L190.786662,244.255313 Z\" id=\"path82\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003cg id=\"g84\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(294.009575, 244.478283)\"\u003e\n+ \u003cpath d=\"M111.679997,0 L0.79222998,0 L48.4470155,146.638096 C50.8993221,154.183259 61.5752318,154.183259 64.0263751,146.638096 L111.679997,0 L111.679997,0 Z\" id=\"path86\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"\u003e\u003c/path\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+ \u003c/g\u003e\n+\u003c/svg\u003e\n\\ No newline at end of file\n", + "new_path": "files/images/wm.svg", + "old_path": "files/images/wm.svg", + "a_mode": "0", + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- /dev/null\n+++ b/files/lfs/lfs_object.iso\n@@ -0,0 +1,4 @@\n+version https://git-lfs.github.com/spec/v1\n+oid sha256:91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897\n+size 1575078\n+\n", + "new_path": "files/lfs/lfs_object.iso", + "old_path": "files/lfs/lfs_object.iso", + "a_mode": "0", + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- /dev/null\n+++ b/files/whitespace\n@@ -0,0 +1 @@\n+test \n", + "new_path": "files/whitespace", + "old_path": "files/whitespace", + "a_mode": "0", + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- /dev/null\n+++ b/foo/bar/.gitkeep\n", + "new_path": "foo/bar/.gitkeep", + "old_path": "foo/bar/.gitkeep", + "a_mode": "0", + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- /dev/null\n+++ b/test\n", + "new_path": "test", + "old_path": "test", + "a_mode": "0", + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + } + ], + "merge_request_id": 13, + "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": "flatten-dirs", + "source_branch": "test-2", + "source_project_id": 5, + "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": "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, + "merge_commit_sha": null, + "deleted_at": null, + "notes": [ + { + "id": 801, + "note": "Nihil dicta molestias expedita atque.", + "noteable_type": "MergeRequest", + "author_id": 26, + "created_at": "2016-06-14T15:03:00.001Z", + "updated_at": "2016-06-14T15:03:00.001Z", + "project_id": 5, + "attachment": { + "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 13, + "noteable_id": 12, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 1245, - "note": "Reprehenderit in atque dolor et repudiandae a est.", + "id": 802, + "note": "Illum culpa voluptas enim accusantium deserunt.", "noteable_type": "MergeRequest", - "author_id": 4, - "created_at": "2016-03-22T15:20:30.928Z", - "updated_at": "2016-03-22T15:20:30.928Z", + "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": 13, + "noteable_id": 12, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 1244, - "note": "Numquam fugit doloremque iure odio et.", + "id": 803, + "note": "Dicta esse aliquam laboriosam unde alias.", "noteable_type": "MergeRequest", - "author_id": 10, - "created_at": "2016-03-22T15:20:30.902Z", - "updated_at": "2016-03-22T15:20:30.902Z", + "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": 13, + "noteable_id": 12, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 1243, - "note": "Doloribus laboriosam id harum voluptatum vitae ut quam.", + "id": 804, + "note": "Dicta autem et sed molestiae ut quae.", "noteable_type": "MergeRequest", - "author_id": 12, - "created_at": "2016-03-22T15:20:30.863Z", - "updated_at": "2016-03-22T15:20:30.863Z", + "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": 13, + "noteable_id": 12, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 1242, - "note": "Harum et ut ipsum dolore ea.", + "id": 805, + "note": "Ut ut temporibus voluptas dolore quia velit.", "noteable_type": "MergeRequest", - "author_id": 22, - "created_at": "2016-03-22T15:20:30.832Z", - "updated_at": "2016-03-22T15:20:30.832Z", + "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": 13, + "noteable_id": 12, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 1241, - "note": "Corporis sed soluta ut est modi natus ab.", + "id": 806, + "note": "Dolores similique sint pariatur error id quia fugit aut.", "noteable_type": "MergeRequest", - "author_id": 24, - "created_at": "2016-03-22T15:20:30.802Z", - "updated_at": "2016-03-22T15:20:30.802Z", + "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": 13, + "noteable_id": 12, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 1240, - "note": "Corrupti totam tenetur officiis ratione dolores est qui vel.", + "id": 807, + "note": "Quisquam provident nihil aperiam voluptatem.", "noteable_type": "MergeRequest", - "author_id": 26, - "created_at": "2016-03-22T15:20:30.771Z", - "updated_at": "2016-03-22T15:20:30.771Z", + "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": 13, - "system": false, - "st_diff": null, - "updated_by_id": null, - "author": { - "name": "User 4" - } - } - ], - "merge_request_diff": { - "id": 13, - "state": "collected", - "st_commits": [ + "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": { + "id": 12, + "state": "collected", + "st_commits": [ + { + "id": "97a0df9696e2aebf10c31b3016f40214e0e8f243", + "message": "fixes #10\n", + "parent_ids": [ + "be93687618e4b132087f430a4d8fc3a609c9b77c" + ], + "authored_date": "2016-01-19T14:08:21.000+01:00", + "author_name": "James Lopez", + "author_email": "james@jameslopez.es", + "committed_date": "2016-01-19T14:08:21.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": "a4e5dfebf42e34596526acb8611bc7ed80e4eb3f", - "message": "fixes #10\n", + "id": "c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd", + "message": "Add ISO-8859 test file\n", "parent_ids": [ - "be93687618e4b132087f430a4d8fc3a609c9b77c" + "e56497bb5f03a90a51293fc6d516788730953899" ], - "authored_date": "2016-01-19T15:44:02.000+01:00", - "author_name": "Test Lopez", - "author_email": "Test@Testlopez.es", - "committed_date": "2016-01-19T15:44:02.000+01:00", - "committer_name": "Test Lopez", - "committer_email": "Test@Testlopez.es" + "authored_date": "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", @@ -3928,35 +5164,61 @@ "too_large": false } ], - "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" - } + "merge_request_id": 12, + "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": 12, + "id": 11, "target_branch": "test-15", - "source_branch": "test-2", + "source_branch": "'test'", "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": 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": 4, - "description": "Soluta excepturi quis iste vero delectus rerum. Consequatur possimus aliquam necessitatibus deleniti rerum est impedit. Eius rem et consequatur assumenda est commodi.", + "iid": 3, + "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, @@ -3964,234 +5226,260 @@ "deleted_at": null, "notes": [ { - "id": 1255, - "note": "Quibusdam rem aut similique ipsum recusandae ut accusamus.", + "id": 809, + "note": "Omnis ratione laboriosam dolores qui.", "noteable_type": "MergeRequest", - "author_id": 1, - "created_at": "2016-03-22T15:20:31.253Z", - "updated_at": "2016-03-22T15:20:31.253Z", + "author_id": 26, + "created_at": "2016-06-14T15:03:00.260Z", + "updated_at": "2016-06-14T15:03:00.260Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 12, + "noteable_id": 11, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 1254, - "note": "Cumque sed omnis ipsa et magnam dolorem et.", + "id": 810, + "note": "Voluptas voluptates pariatur dolores maxime est voluptas.", "noteable_type": "MergeRequest", - "author_id": 3, - "created_at": "2016-03-22T15:20:31.224Z", - "updated_at": "2016-03-22T15:20:31.224Z", + "author_id": 25, + "created_at": "2016-06-14T15:03:00.290Z", + "updated_at": "2016-06-14T15:03:00.290Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 12, + "noteable_id": 11, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 1253, - "note": "Molestiae beatae id consequatur nam minus quia.", + "id": 811, + "note": "Sit perspiciatis facilis ipsum consequatur.", "noteable_type": "MergeRequest", - "author_id": 4, - "created_at": "2016-03-22T15:20:31.195Z", - "updated_at": "2016-03-22T15:20:31.195Z", + "author_id": 22, + "created_at": "2016-06-14T15:03:00.323Z", + "updated_at": "2016-06-14T15:03:00.323Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 12, + "noteable_id": 11, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 1252, - "note": "Voluptatem dolorem dignissimos itaque tempora quas ut.", + "id": 812, + "note": "Ut neque aliquam nam et est.", "noteable_type": "MergeRequest", - "author_id": 10, - "created_at": "2016-03-22T15:20:31.166Z", - "updated_at": "2016-03-22T15:20:31.166Z", + "author_id": 20, + "created_at": "2016-06-14T15:03:00.349Z", + "updated_at": "2016-06-14T15:03:00.349Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 12, + "noteable_id": 11, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 1251, - "note": "Debitis qui quibusdam voluptas repellat veritatis dicta rerum id.", + "id": 813, + "note": "Et debitis rerum minima sit aut dolorem.", "noteable_type": "MergeRequest", - "author_id": 12, - "created_at": "2016-03-22T15:20:31.137Z", - "updated_at": "2016-03-22T15:20:31.137Z", + "author_id": 16, + "created_at": "2016-06-14T15:03:00.374Z", + "updated_at": "2016-06-14T15:03:00.374Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 12, + "noteable_id": 11, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 1250, - "note": "Suscipit optio ad voluptatem dignissimos temporibus amet molestias ut.", + "id": 814, + "note": "Ea nisi earum fugit iste aperiam consequatur.", "noteable_type": "MergeRequest", - "author_id": 22, - "created_at": "2016-03-22T15:20:31.107Z", - "updated_at": "2016-03-22T15:20:31.107Z", + "author_id": 15, + "created_at": "2016-06-14T15:03:00.397Z", + "updated_at": "2016-06-14T15:03:00.397Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 12, + "noteable_id": 11, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 1249, - "note": "Nemo aut vitae et ducimus autem ex dolores.", + "id": 815, + "note": "Amet ratione consequatur laudantium rerum voluptas est nobis.", "noteable_type": "MergeRequest", - "author_id": 24, - "created_at": "2016-03-22T15:20:31.073Z", - "updated_at": "2016-03-22T15:20:31.073Z", + "author_id": 6, + "created_at": "2016-06-14T15:03:00.450Z", + "updated_at": "2016-06-14T15:03:00.450Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 12, + "noteable_id": 11, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 1248, - "note": "Repellendus eaque ex molestiae laudantium placeat quidem vitae recusandae.", + "id": 816, + "note": "Ab ducimus cumque quia dolorem vitae sint beatae rerum.", "noteable_type": "MergeRequest", - "author_id": 26, - "created_at": "2016-03-22T15:20:31.038Z", - "updated_at": "2016-03-22T15:20:31.038Z", + "author_id": 1, + "created_at": "2016-06-14T15:03:00.474Z", + "updated_at": "2016-06-14T15:03:00.474Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 12, + "noteable_id": 11, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ], "merge_request_diff": { - "id": 12, - "state": "collected", - "st_commits": [ - { - "id": "97a0df9696e2aebf10c31b3016f40214e0e8f243", - "message": "fixes #10\n", - "parent_ids": [ - "be93687618e4b132087f430a4d8fc3a609c9b77c" - ], - "authored_date": "2016-01-19T14:08:21.000+01:00", - "author_name": "Test Lopez", - "author_email": "Test@Testlopez.es", - "committed_date": "2016-01-19T14:08:21.000+01:00", - "committer_name": "Test Lopez", - "committer_email": "Test@Testlopez.es" - } - ], + "id": 11, + "state": "empty", + "st_commits": null, "st_diffs": [ - { - "diff": "--- /dev/null\n+++ b/test\n", - "new_path": "test", - "old_path": "test", - "a_mode": "0", - "b_mode": "100644", - "new_file": true, - "renamed_file": false, - "deleted_file": false, - "too_large": false - } + ], - "merge_request_id": 12, - "created_at": "2016-03-22T15:13:44.840Z", - "updated_at": "2016-03-22T15:13:44.908Z", - "base_commit_sha": "be93687618e4b132087f430a4d8fc3a609c9b77c", - "real_size": "1" - } + "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": 11, - "target_branch": "test-3", + "id": 10, + "target_branch": "feature", "source_branch": "test-5", "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": 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": 3, - "description": "Et hic maxime harum ullam. Nulla velit pariatur libero recusandae. Dolor est earum laboriosam harum quo.", + "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, @@ -4199,428 +5487,623 @@ "deleted_at": null, "notes": [ { - "id": 1263, - "note": "Beatae incidunt exercitationem voluptates recusandae fuga quia enim.", + "id": 817, + "note": "Recusandae et voluptas enim qui et.", "noteable_type": "MergeRequest", - "author_id": 1, - "created_at": "2016-03-22T15:20:31.883Z", - "updated_at": "2016-03-22T15:20:31.883Z", + "author_id": 26, + "created_at": "2016-06-14T15:03:00.510Z", + "updated_at": "2016-06-14T15:03:00.510Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 11, + "noteable_id": 10, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 1262, - "note": "Illum sunt id consequuntur fugit et quo ullam eum.", + "id": 818, + "note": "Asperiores dolorem rerum ipsum totam.", "noteable_type": "MergeRequest", - "author_id": 3, - "created_at": "2016-03-22T15:20:31.860Z", - "updated_at": "2016-03-22T15:20:31.860Z", + "author_id": 25, + "created_at": "2016-06-14T15:03:00.538Z", + "updated_at": "2016-06-14T15:03:00.538Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 11, + "noteable_id": 10, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 1261, - "note": "Alias reiciendis autem ipsa sequi autem nemo odio.", + "id": 819, + "note": "Qui quam et iure quasi provident cumque itaque sequi.", "noteable_type": "MergeRequest", - "author_id": 4, - "created_at": "2016-03-22T15:20:31.456Z", - "updated_at": "2016-03-22T15:20:31.456Z", + "author_id": 22, + "created_at": "2016-06-14T15:03:00.562Z", + "updated_at": "2016-06-14T15:03:00.562Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 11, + "noteable_id": 10, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 1260, - "note": "Maxime nisi odit eos nulla vel ex accusamus velit.", + "id": 820, + "note": "Sint accusantium aliquid iste qui iusto minus vel.", "noteable_type": "MergeRequest", - "author_id": 10, - "created_at": "2016-03-22T15:20:31.426Z", - "updated_at": "2016-03-22T15:20:31.426Z", + "author_id": 20, + "created_at": "2016-06-14T15:03:00.585Z", + "updated_at": "2016-06-14T15:03:00.585Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 11, + "noteable_id": 10, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 1259, - "note": "Excepturi et qui sapiente ut ducimus sunt nesciunt.", + "id": 821, + "note": "Dolor corrupti dolorem blanditiis voluptas.", "noteable_type": "MergeRequest", - "author_id": 12, - "created_at": "2016-03-22T15:20:31.397Z", - "updated_at": "2016-03-22T15:20:31.397Z", + "author_id": 16, + "created_at": "2016-06-14T15:03:00.610Z", + "updated_at": "2016-06-14T15:03:00.610Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 11, + "noteable_id": 10, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 1258, - "note": "Quis rerum dolores et dolorem modi neque ullam doloribus.", + "id": 822, + "note": "Est perferendis assumenda aliquam aliquid sit ipsum ullam aut.", "noteable_type": "MergeRequest", - "author_id": 22, - "created_at": "2016-03-22T15:20:31.364Z", - "updated_at": "2016-03-22T15:20:31.364Z", + "author_id": 15, + "created_at": "2016-06-14T15:03:00.635Z", + "updated_at": "2016-06-14T15:03:00.635Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 11, + "noteable_id": 10, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 1257, - "note": "Voluptatum et mollitia neque aut.", + "id": 823, + "note": "Hic neque reiciendis quaerat maiores.", "noteable_type": "MergeRequest", - "author_id": 24, - "created_at": "2016-03-22T15:20:31.328Z", - "updated_at": "2016-03-22T15:20:31.328Z", + "author_id": 6, + "created_at": "2016-06-14T15:03:00.659Z", + "updated_at": "2016-06-14T15:03:00.659Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 11, + "noteable_id": 10, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 1256, - "note": "Rerum laudantium dolor natus doloribus voluptas aliquid a.", + "id": 824, + "note": "Sequi architecto doloribus ut vel autem.", "noteable_type": "MergeRequest", - "author_id": 26, - "created_at": "2016-03-22T15:20:31.298Z", - "updated_at": "2016-03-22T15:20:31.298Z", + "author_id": 1, + "created_at": "2016-06-14T15:03:00.683Z", + "updated_at": "2016-06-14T15:03:00.683Z", "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 11, + "noteable_id": 10, "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ], "merge_request_diff": { - "id": 11, + "id": 10, "state": "collected", "st_commits": [ { - "id": "f998ac87ac9244f15e9c15109a6f4e62a54b779d", - "message": "fixes #10\n", + "id": "f998ac87ac9244f15e9c15109a6f4e62a54b779d", + "message": "fixes #10\n", + "parent_ids": [ + "be93687618e4b132087f430a4d8fc3a609c9b77c" + ], + "authored_date": "2016-01-19T14:43:23.000+01:00", + "author_name": "James Lopez", + "author_email": "james@jameslopez.es", + "committed_date": "2016-01-19T14:43:23.000+01:00", + "committer_name": "James Lopez", + "committer_email": "james@jameslopez.es" + }, + { + "id": "be93687618e4b132087f430a4d8fc3a609c9b77c", + "message": "Merge branch 'master' into 'master'\r\n\r\nLFS object pointer.\r\n\r\n\r\n\r\nSee merge request !6", + "parent_ids": [ + "5f923865dde3436854e9ceb9cdb7815618d4e849", + "048721d90c449b244b7b4c53a9186b04330174ec" + ], + "authored_date": "2015-12-07T12:52:12.000+01:00", + "author_name": "Marin Jankovski", + "author_email": "marin@gitlab.com", + "committed_date": "2015-12-07T12:52:12.000+01:00", + "committer_name": "Marin Jankovski", + "committer_email": "marin@gitlab.com" + }, + { + "id": "048721d90c449b244b7b4c53a9186b04330174ec", + "message": "LFS object pointer.\n", + "parent_ids": [ + "5f923865dde3436854e9ceb9cdb7815618d4e849" + ], + "authored_date": "2015-12-07T11:54:28.000+01:00", + "author_name": "Marin Jankovski", + "author_email": "maxlazio@gmail.com", + "committed_date": "2015-12-07T11:54:28.000+01:00", + "committer_name": "Marin Jankovski", + "committer_email": "maxlazio@gmail.com" + }, + { + "id": "5f923865dde3436854e9ceb9cdb7815618d4e849", + "message": "GitLab currently doesn't support patches that involve a merge commit: add a commit here\n", + "parent_ids": [ + "d2d430676773caa88cdaf7c55944073b2fd5561a" + ], + "authored_date": "2015-11-13T16:27:12.000+01:00", + "author_name": "Stan Hu", + "author_email": "stanhu@gmail.com", + "committed_date": "2015-11-13T16:27:12.000+01:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@gmail.com" + }, + { + "id": "d2d430676773caa88cdaf7c55944073b2fd5561a", + "message": "Merge branch 'add-svg' into 'master'\r\n\r\nAdd GitLab SVG\r\n\r\nAdded to test preview of sanitized SVG images\r\n\r\nSee merge request !5", + "parent_ids": [ + "59e29889be61e6e0e5e223bfa9ac2721d31605b8", + "2ea1f3dec713d940208fb5ce4a38765ecb5d3f73" + ], + "authored_date": "2015-11-13T08:50:17.000+01:00", + "author_name": "Stan Hu", + "author_email": "stanhu@gmail.com", + "committed_date": "2015-11-13T08:50:17.000+01:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@gmail.com" + }, + { + "id": "2ea1f3dec713d940208fb5ce4a38765ecb5d3f73", + "message": "Add GitLab SVG\n", + "parent_ids": [ + "59e29889be61e6e0e5e223bfa9ac2721d31605b8" + ], + "authored_date": "2015-11-13T08:39:43.000+01:00", + "author_name": "Stan Hu", + "author_email": "stanhu@gmail.com", + "committed_date": "2015-11-13T08:39:43.000+01:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@gmail.com" + }, + { + "id": "59e29889be61e6e0e5e223bfa9ac2721d31605b8", + "message": "Merge branch 'whitespace' into 'master'\r\n\r\nadd whitespace test file\r\n\r\nSorry, I did a mistake.\r\nGit ignore empty files.\r\nSo I add a new whitespace test file.\r\n\r\nSee merge request !4", + "parent_ids": [ + "19e2e9b4ef76b422ce1154af39a91323ccc57434", + "66eceea0db202bb39c4e445e8ca28689645366c5" + ], + "authored_date": "2015-11-13T07:21:40.000+01:00", + "author_name": "Stan Hu", + "author_email": "stanhu@gmail.com", + "committed_date": "2015-11-13T07:21:40.000+01:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@gmail.com" + }, + { + "id": "66eceea0db202bb39c4e445e8ca28689645366c5", + "message": "add spaces in whitespace file\n", + "parent_ids": [ + "08f22f255f082689c0d7d39d19205085311542bc" + ], + "authored_date": "2015-11-13T06:01:27.000+01:00", + "author_name": "윤민식", + "author_email": "minsik.yoon@samsung.com", + "committed_date": "2015-11-13T06:01:27.000+01:00", + "committer_name": "윤민식", + "committer_email": "minsik.yoon@samsung.com" + }, + { + "id": "08f22f255f082689c0d7d39d19205085311542bc", + "message": "remove emtpy file.(beacase git ignore empty file)\nadd whitespace test file.\n", + "parent_ids": [ + "c642fe9b8b9f28f9225d7ea953fe14e74748d53b" + ], + "authored_date": "2015-11-13T06:00:16.000+01:00", + "author_name": "윤민식", + "author_email": "minsik.yoon@samsung.com", + "committed_date": "2015-11-13T06:00:16.000+01:00", + "committer_name": "윤민식", + "committer_email": "minsik.yoon@samsung.com" + }, + { + "id": "19e2e9b4ef76b422ce1154af39a91323ccc57434", + "message": "Merge branch 'whitespace' into 'master'\r\n\r\nadd spaces\r\n\r\nTo test this pull request.(https://github.com/gitlabhq/gitlabhq/pull/9757)\r\nJust add whitespaces.\r\n\r\nSee merge request !3", + "parent_ids": [ + "c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd", + "c642fe9b8b9f28f9225d7ea953fe14e74748d53b" + ], + "authored_date": "2015-11-13T05:23:14.000+01:00", + "author_name": "Stan Hu", + "author_email": "stanhu@gmail.com", + "committed_date": "2015-11-13T05:23:14.000+01:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@gmail.com" + }, + { + "id": "c642fe9b8b9f28f9225d7ea953fe14e74748d53b", + "message": "add whitespace in empty\n", + "parent_ids": [ + "9a944d90955aaf45f6d0c88f30e27f8d2c41cec0" + ], + "authored_date": "2015-11-13T05:08:45.000+01:00", + "author_name": "윤민식", + "author_email": "minsik.yoon@samsung.com", + "committed_date": "2015-11-13T05:08:45.000+01:00", + "committer_name": "윤민식", + "committer_email": "minsik.yoon@samsung.com" + }, + { + "id": "9a944d90955aaf45f6d0c88f30e27f8d2c41cec0", + "message": "add empty file\n", + "parent_ids": [ + "c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd" + ], + "authored_date": "2015-11-13T05:08:04.000+01:00", + "author_name": "윤민식", + "author_email": "minsik.yoon@samsung.com", + "committed_date": "2015-11-13T05:08:04.000+01:00", + "committer_name": "윤민식", + "committer_email": "minsik.yoon@samsung.com" + }, + { + "id": "c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd", + "message": "Add ISO-8859 test file\n", + "parent_ids": [ + "e56497bb5f03a90a51293fc6d516788730953899" + ], + "authored_date": "2015-08-25T17:53:12.000+02:00", + "author_name": "Stan Hu", + "author_email": "stanhu@packetzoom.com", + "committed_date": "2015-08-25T17:53:12.000+02:00", + "committer_name": "Stan Hu", + "committer_email": "stanhu@packetzoom.com" + }, + { + "id": "e56497bb5f03a90a51293fc6d516788730953899", + "message": "Merge branch 'tree_helper_spec' into 'master'\n\nAdd directory structure for tree_helper spec\n\nThis directory structure is needed for a testing the method flatten_tree(tree) in the TreeHelper module\n\nSee [merge request #275](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/275#note_732774)\n\nSee merge request !2\n", + "parent_ids": [ + "5937ac0a7beb003549fc5fd26fc247adbce4a52e", + "4cd80ccab63c82b4bad16faa5193fbd2aa06df40" + ], + "authored_date": "2015-01-10T22:23:29.000+01:00", + "author_name": "Sytse Sijbrandij", + "author_email": "sytse@gitlab.com", + "committed_date": "2015-01-10T22:23:29.000+01:00", + "committer_name": "Sytse Sijbrandij", + "committer_email": "sytse@gitlab.com" + }, + { + "id": "4cd80ccab63c82b4bad16faa5193fbd2aa06df40", + "message": "add directory structure for tree_helper spec\n", + "parent_ids": [ + "5937ac0a7beb003549fc5fd26fc247adbce4a52e" + ], + "authored_date": "2015-01-10T21:28:18.000+01:00", + "author_name": "marmis85", + "author_email": "marmis85@gmail.com", + "committed_date": "2015-01-10T21:28:18.000+01:00", + "committer_name": "marmis85", + "committer_email": "marmis85@gmail.com" + }, + { + "id": "5937ac0a7beb003549fc5fd26fc247adbce4a52e", + "message": "Add submodule from gitlab.com\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n", + "parent_ids": [ + "570e7b2abdd848b95f2f578043fc23bd6f6fd24d" + ], + "authored_date": "2014-02-27T10:01:38.000+01:00", + "author_name": "Dmitriy Zaporozhets", + "author_email": "dmitriy.zaporozhets@gmail.com", + "committed_date": "2014-02-27T10:01:38.000+01:00", + "committer_name": "Dmitriy Zaporozhets", + "committer_email": "dmitriy.zaporozhets@gmail.com" + }, + { + "id": "570e7b2abdd848b95f2f578043fc23bd6f6fd24d", + "message": "Change some files\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n", + "parent_ids": [ + "6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9" + ], + "authored_date": "2014-02-27T09:57:31.000+01:00", + "author_name": "Dmitriy Zaporozhets", + "author_email": "dmitriy.zaporozhets@gmail.com", + "committed_date": "2014-02-27T09:57:31.000+01:00", + "committer_name": "Dmitriy Zaporozhets", + "committer_email": "dmitriy.zaporozhets@gmail.com" + }, + { + "id": "6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9", + "message": "More submodules\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n", + "parent_ids": [ + "d14d6c0abdd253381df51a723d58691b2ee1ab08" + ], + "authored_date": "2014-02-27T09:54:21.000+01:00", + "author_name": "Dmitriy Zaporozhets", + "author_email": "dmitriy.zaporozhets@gmail.com", + "committed_date": "2014-02-27T09:54:21.000+01:00", + "committer_name": "Dmitriy Zaporozhets", + "committer_email": "dmitriy.zaporozhets@gmail.com" + }, + { + "id": "d14d6c0abdd253381df51a723d58691b2ee1ab08", + "message": "Remove ds_store files\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n", + "parent_ids": [ + "c1acaa58bbcbc3eafe538cb8274ba387047b69f8" + ], + "authored_date": "2014-02-27T09:49:50.000+01:00", + "author_name": "Dmitriy Zaporozhets", + "author_email": "dmitriy.zaporozhets@gmail.com", + "committed_date": "2014-02-27T09:49:50.000+01:00", + "committer_name": "Dmitriy Zaporozhets", + "committer_email": "dmitriy.zaporozhets@gmail.com" + }, + { + "id": "c1acaa58bbcbc3eafe538cb8274ba387047b69f8", + "message": "Ignore DS files\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n", "parent_ids": [ - "be93687618e4b132087f430a4d8fc3a609c9b77c" + "ae73cb07c9eeaf35924a10f713b364d32b2dd34f" ], - "authored_date": "2016-01-19T14:43:23.000+01:00", - "author_name": "Test Lopez", - "author_email": "Test@Testlopez.es", - "committed_date": "2016-01-19T14:43:23.000+01:00", - "committer_name": "Test Lopez", - "committer_email": "Test@Testlopez.es" + "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 + { + "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 }, - "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 + { + "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 }, - "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 + { + "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 }, - "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 + { + "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 }, - "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 + { + "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 }, - "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 + { + "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 }, - "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 + { + "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 }, - "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": "--- /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,12 +6178,12 @@ "deleted_at": null, "notes": [ { - "id": 1279, - "note": "A corrupti nesciunt pariatur ea.", + "id": 825, + "note": "Aliquid voluptatem consequatur voluptas ex perspiciatis.", "noteable_type": "MergeRequest", - "author_id": 1, - "created_at": "2016-03-22T15:20:32.307Z", - "updated_at": "2016-03-22T15:20:32.307Z", + "author_id": 26, + "created_at": "2016-06-14T15:03:00.722Z", + "updated_at": "2016-06-14T15:03:00.722Z", "project_id": 5, "attachment": { "url": null @@ -4685,17 +6194,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Administrator" - } + "author": { + "name": "User 4" + }, + "events": [ + + ] }, { - "id": 1278, - "note": "Adipisci aut ut et voluptate numquam.", + "id": 826, + "note": "Itaque optio voluptatem praesentium voluptas.", "noteable_type": "MergeRequest", - "author_id": 3, - "created_at": "2016-03-22T15:20:32.281Z", - "updated_at": "2016-03-22T15:20:32.281Z", + "author_id": 25, + "created_at": "2016-06-14T15:03:00.745Z", + "updated_at": "2016-06-14T15:03:00.745Z", "project_id": 5, "attachment": { "url": null @@ -4706,17 +6218,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Alexie Trantow" - } + "author": { + "name": "User 3" + }, + "events": [ + + ] }, { - "id": 1277, - "note": "Adipisci voluptatem quod ut placeat repellendus deleniti.", + "id": 827, + "note": "Ut est corporis fuga asperiores delectus excepturi aperiam.", "noteable_type": "MergeRequest", - "author_id": 4, - "created_at": "2016-03-22T15:20:32.255Z", - "updated_at": "2016-03-22T15:20:32.255Z", + "author_id": 22, + "created_at": "2016-06-14T15:03:00.771Z", + "updated_at": "2016-06-14T15:03:00.771Z", "project_id": 5, "attachment": { "url": null @@ -4727,17 +6242,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Julius Moore" - } + "author": { + "name": "User 0" + }, + "events": [ + + ] }, { - "id": 1276, - "note": "Vitae et doloremque aut et aspernatur velit placeat sed.", + "id": 828, + "note": "Similique ea dolore officiis temporibus.", "noteable_type": "MergeRequest", - "author_id": 10, - "created_at": "2016-03-22T15:20:32.230Z", - "updated_at": "2016-03-22T15:20:32.230Z", + "author_id": 20, + "created_at": "2016-06-14T15:03:00.798Z", + "updated_at": "2016-06-14T15:03:00.798Z", "project_id": 5, "attachment": { "url": null @@ -4748,17 +6266,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Robyn McCullough Jr." - } + "author": { + "name": "Ottis Schuster II" + }, + "events": [ + + ] }, { - "id": 1275, - "note": "Quos cupiditate nesciunt expedita aspernatur.", + "id": 829, + "note": "Qui laudantium qui quae quis.", "noteable_type": "MergeRequest", - "author_id": 12, - "created_at": "2016-03-22T15:20:32.207Z", - "updated_at": "2016-03-22T15:20:32.207Z", + "author_id": 16, + "created_at": "2016-06-14T15:03:00.828Z", + "updated_at": "2016-06-14T15:03:00.828Z", "project_id": 5, "attachment": { "url": null @@ -4769,17 +6290,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "Vladimir McCullough" - } + "author": { + "name": "Rhett Emmerich IV" + }, + "events": [ + + ] }, { - "id": 1274, - "note": "Optio rem inventore dicta praesentium sit.", + "id": 830, + "note": "Et vel voluptas amet laborum qui soluta.", "noteable_type": "MergeRequest", - "author_id": 22, - "created_at": "2016-03-22T15:20:32.181Z", - "updated_at": "2016-03-22T15:20:32.181Z", + "author_id": 15, + "created_at": "2016-06-14T15:03:00.850Z", + "updated_at": "2016-06-14T15:03:00.850Z", "project_id": 5, "attachment": { "url": null @@ -4790,17 +6314,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 0" - } + "author": { + "name": "Burdette Bernier" + }, + "events": [ + + ] }, { - "id": 1273, - "note": "Sit incidunt molestiae maxime officiis rerum necessitatibus.", + "id": 831, + "note": "Enim ad consequuntur assumenda provident voluptatem similique deleniti.", "noteable_type": "MergeRequest", - "author_id": 24, - "created_at": "2016-03-22T15:20:32.159Z", - "updated_at": "2016-03-22T15:20:32.159Z", + "author_id": 6, + "created_at": "2016-06-14T15:03:00.876Z", + "updated_at": "2016-06-14T15:03:00.876Z", "project_id": 5, "attachment": { "url": null @@ -4811,17 +6338,20 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 2" - } + "author": { + "name": "Ari Wintheiser" + }, + "events": [ + + ] }, { - "id": 1272, - "note": "Autem ut non itaque molestiae nisi quia officiis doloribus.", + "id": 832, + "note": "Officiis sequi commodi pariatur totam fugiat voluptas corporis dignissimos.", "noteable_type": "MergeRequest", - "author_id": 26, - "created_at": "2016-03-22T15:20:32.129Z", - "updated_at": "2016-03-22T15:20:32.129Z", + "author_id": 1, + "created_at": "2016-06-14T15:03:00.902Z", + "updated_at": "2016-06-14T15:03:00.902Z", "project_id": 5, "attachment": { "url": null @@ -4832,9 +6362,12 @@ "system": false, "st_diff": null, "updated_by_id": null, - "author": { - "name": "User 4" - } + "author": { + "name": "Administrator" + }, + "events": [ + + ] } ], "merge_request_diff": { @@ -4842,17 +6375,17 @@ "state": "collected", "st_commits": [ { - "id": "e239ba8c97b80b2874579a4d625ea9628f4c8ff5", + "id": "a4e5dfebf42e34596526acb8611bc7ed80e4eb3f", "message": "fixes #10\n", "parent_ids": [ "be93687618e4b132087f430a4d8fc3a609c9b77c" ], - "authored_date": "2016-01-19T15:38:06.000+01:00", - "author_name": "Test Lopez", - "author_email": "Test@Testlopez.es", - "committed_date": "2016-01-19T15:38:06.000+01:00", - "committer_name": "Test Lopez", - "committer_email": "Test@Testlopez.es" + "authored_date": "2016-01-19T15:44:02.000+01:00", + "author_name": "James Lopez", + "author_email": "james@jameslopez.es", + "committed_date": "2016-01-19T15:44:02.000+01:00", + "committer_name": "James Lopez", + "committer_email": "james@jameslopez.es" } ], "st_diffs": [ @@ -4869,11 +6402,37 @@ } ], "merge_request_id": 9, - "created_at": "2016-03-22T15:13:43.794Z", - "updated_at": "2016-03-22T15:13:43.848Z", + "created_at": "2016-06-14T15:02:22.829Z", + "updated_at": "2016-06-14T15:02:22.900Z", "base_commit_sha": "be93687618e4b132087f430a4d8fc3a609c9b77c", "real_size": "1" - } + }, + "events": [ + { + "id": 229, + "target_type": "MergeRequest", + "target_id": 9, + "title": null, + "data": null, + "project_id": 36, + "created_at": "2016-06-14T15:02:22.927Z", + "updated_at": "2016-06-14T15:02:22.927Z", + "action": 1, + "author_id": 16 + }, + { + "id": 169, + "target_type": "MergeRequest", + "target_id": 9, + "title": null, + "data": null, + "project_id": 5, + "created_at": "2016-06-14T15:02:22.927Z", + "updated_at": "2016-06-14T15:02:22.927Z", + "action": 1, + "author_id": 16 + } + ] } ], "pipelines": [ @@ -5360,5 +6919,464 @@ } ] } + ], + "variables": [ + + ], + "triggers": [ + + ], + "deploy_keys": [ + + ], + "services": [ + { + "id": 164, + "title": null, + "project_id": 5, + "created_at": "2016-06-14T15:02:07.372Z", + "updated_at": "2016-06-14T15:02:07.372Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "issue_tracker", + "default": true, + "wiki_page_events": true + }, + { + "id": 100, + "title": "JetBrains TeamCity CI", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.315Z", + "updated_at": "2016-06-14T15:01:51.315Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "ci", + "default": false, + "wiki_page_events": true + }, + { + "id": 99, + "title": "Slack", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.303Z", + "updated_at": "2016-06-14T15:01:51.303Z", + "active": false, + "properties": { + "notify_only_broken_builds": true + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "common", + "default": false, + "wiki_page_events": true + }, + { + "id": 98, + "title": "Redmine", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.289Z", + "updated_at": "2016-06-14T15:01:51.289Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "issue_tracker", + "default": false, + "wiki_page_events": true + }, + { + "id": 97, + "title": "Pushover", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.277Z", + "updated_at": "2016-06-14T15:01:51.277Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "common", + "default": false, + "wiki_page_events": true + }, + { + "id": 96, + "title": "PivotalTracker", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.267Z", + "updated_at": "2016-06-14T15:01:51.267Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "common", + "default": false, + "wiki_page_events": true + }, + { + "id": 95, + "title": "JIRA", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.255Z", + "updated_at": "2016-06-14T15:01:51.255Z", + "active": false, + "properties": { + "api_url": "", + "jira_issue_transition_id": "2" + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "issue_tracker", + "default": false, + "wiki_page_events": true + }, + { + "id": 94, + "title": "Irker (IRC gateway)", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.232Z", + "updated_at": "2016-06-14T15:01:51.232Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "common", + "default": false, + "wiki_page_events": true + }, + { + "id": 93, + "title": "HipChat", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.219Z", + "updated_at": "2016-06-14T15:01:51.219Z", + "active": false, + "properties": { + "notify_only_broken_builds": true + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "common", + "default": false, + "wiki_page_events": true + }, + { + "id": 92, + "title": "Gemnasium", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.202Z", + "updated_at": "2016-06-14T15:01:51.202Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "common", + "default": false, + "wiki_page_events": true + }, + { + "id": 91, + "title": "Flowdock", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.182Z", + "updated_at": "2016-06-14T15:01:51.182Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "common", + "default": false, + "wiki_page_events": true + }, + { + "id": 90, + "title": "External Wiki", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.166Z", + "updated_at": "2016-06-14T15:01:51.166Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "common", + "default": false, + "wiki_page_events": true + }, + { + "id": 89, + "title": "Emails on push", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.153Z", + "updated_at": "2016-06-14T15:01:51.153Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "common", + "default": false, + "wiki_page_events": true + }, + { + "id": 88, + "title": "Drone CI", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.139Z", + "updated_at": "2016-06-14T15:01:51.139Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "ci", + "default": false, + "wiki_page_events": true + }, + { + "id": 87, + "title": "Custom Issue Tracker", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.125Z", + "updated_at": "2016-06-14T15:01:51.125Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "issue_tracker", + "default": false, + "wiki_page_events": true + }, + { + "id": 86, + "title": "Campfire", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.113Z", + "updated_at": "2016-06-14T15:01:51.113Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "common", + "default": false, + "wiki_page_events": true + }, + { + "id": 85, + "title": "Builds emails", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.090Z", + "updated_at": "2016-06-14T15:01:51.090Z", + "active": false, + "properties": { + "notify_only_broken_builds": true + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "common", + "default": false, + "wiki_page_events": true + }, + { + "id": 84, + "title": "Buildkite", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.080Z", + "updated_at": "2016-06-14T15:01:51.080Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "ci", + "default": false, + "wiki_page_events": true + }, + { + "id": 83, + "title": "Atlassian Bamboo CI", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.067Z", + "updated_at": "2016-06-14T15:01:51.067Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "ci", + "default": false, + "wiki_page_events": true + }, + { + "id": 82, + "title": "Assembla", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.047Z", + "updated_at": "2016-06-14T15:01:51.047Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "common", + "default": false, + "wiki_page_events": true + }, + { + "id": 81, + "title": "Asana", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.031Z", + "updated_at": "2016-06-14T15:01:51.031Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "common", + "default": false, + "wiki_page_events": true + } + ], + "hooks": [ + + ], + "protected_branches": [ + ] } \ No newline at end of file diff --git a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb index 23036ab8108c1e378c5363b753da8c8c6b3154f9..a72aaa44e823efd418d18566e9e3a8b5e562a53b 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 8d29b2f8fd1906e9976ff8e4031a59dc5fc0499d..a75eaa4d51fc968feab805e62135d17fcab7d005 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 109522fa626a0bb27e6d500b46b9514ab9a30c47..b76e14deca1fd4e8bd2cb44e6b1d4dca22c66d30 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 590a9a7e1a51ba26551895e3bee385d42321775b..135e99bc95322ef299bb5391cc0a562ecbe6e4a4 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 b9ffc8694a58b68dd63028b027f00b04719c1a76..b628da0f3e87a2aa39ff2448bd46179412946263 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 6a53ed1db64019ddc289cbb392a108b8a24630a3..69c49051156681ea80bb52c2e299706f68a4a696 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 fbb5895c2ef57adfd93e7441188d5c6a605a015c..1fca8a13037875d601f183b773f0122bbb0a609a 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 795cf241278aad1abd989a6b1d1b2ef39b0c5ff1..e8b236426e907248b41d4c25d52662f7ecf01355 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 7fc34139eff2ee8e54138001ded97b2858cf473b..6bd7393aaa7bd85ae7539583229a493fc176a938 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 2753aecc1f48c7484a722cc75aca9a982e5ab245..56bf08e704170ed5d0c3811efa9f41e4018acdde 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 de55334118f659d845d72f00b0248d401d8f8ec4..59024d3290be9d1cbf20ae1d4ed94f6b36dee41c 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 c59dfea5c55f1dce507915547fcff4ee8f2541a6..c4c107c9eea387cc66d6e1d9fe42cb3f86efe67d 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 ae55a01ebea85a375351e8e98056af2a30b38da7..aa382f930d7365a3f5de5f180b62649d0bd27a57 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 d84f3e998f570b467e2466c345ab1f20d077169a..2ea1320267c34927b0aa4d808da01bb92d3b49c1 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 8154001cf460e4f0f87038220d89e7d8daeea5f5..e8171788872383d1b9645919fa32b49170263f6e 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 983078769626dfe26ea90408b86cad0cd0685b9e..96eee0e8bdd2505e9498c98461d7300e818d03a6 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 89730ab8eb8179b4ed89d206e9ed542d6a7ed541..60e4bbc85647025e44aafaf370a0f8315b8e37a3 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 6445e29c3efb3584ad71f1617c9fdfa4940e9587..c3af7a0960ffb28d42fe2b8e64992efe520c6182 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 5d0bd31db5af363aad82ba6242816e8d7dbe2f59..d9df9e0f9071223af1980433f374b5c400d93565 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 3b817608ce0dfcd2374a734edb627f961fb93439..fa1a0d4e0c77f37960cb3394f61634ec9dafc9fc 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 2c19aa3f67ff2154ba89ba221980e423c1619764..a878ff1b2278536d2f3b88ad2887ef562eb23103 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 1b987588f592cdd9602120eb258fef63fc4f88b0..b3aed66a5b68c8339d488b135b780c4444adffd3 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 e9134a3d28324badff2e80058bf16ccd37c87d19..40181a8b906e46ab0e0e78e1f9d60a1d52998f58 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 bbf65edb27c077386fc12d575e1e6000b27b16a2..4c10346243357e085a9f7b4a2f9fa69d023fe1d5 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 4e68ac5e63af9e0e9894a28732a76bde4ed147e9..5f68cd2b066925bdab9d0151b47fb63164cc3695 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 c95173245411f378dd880ec495c49e5560d0bac0..5a97cf370dae20dab8f3b05e1149db16ef70f3ac 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 6ecab645b497cc379db9df701f2342a910ad9f17..46dedb66c7c112b6e279b57ddc2ab173eb1e10c3 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 d305cd9ff1e39e4a77a065c932af9bfc1a3d79fe..a8c777d1e3e9c65a75afd8a6f387c32dafaf3e22 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 d8350000bf63044ef0ec91752ef5a136d6b162e4..851b8b241d7beb465a50debef2141c2534d558a1 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 2f000dbc01a2b239fc06025f95ee8347f34f1988..96bbbec9ea11be23879cf285454b8a2c70459294 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 f22db61e744d706b35b9310138f94715e5ae985c..830259538899382380009f8e3c35a5812d909c5d 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 ed78d582bd0446e0421641515506e2d92626f6c3..72a6d45f47d92ae80a5052e059cd6d32ad67eb8c 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 6668f3543f6f7312f75244aaa7d36022635272a4..2da01da7fa1201f36bdf66d5f8a5ebbe221c8796 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 881b818b5e9dd5c625bb2bce269c6f2d1673678a..5262a623761545d84291e4672de894640a6957b6 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 437c89c35776ab35a7424a8bd58cd5253072bb6d..fcea45f19bad486070cd0f8ea58e64d5075859e4 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 3973677998639cd1e76bf89da028857e287ad36b..0404cf31ff7c6b356c9ccec157e43e386eca5b50 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 bacd01f8e748dded436dec1e571abef63af88cc4..65c53211dd312d0a7b0dca6f8d465abce6fbcb33 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 41b5ed9bc3384cbb71106e5231efeb91592c59e7..611dd2a2a888e61cd51c3e6b96e4684f7296d6a9 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 bf7eaaaaaed9b77f1cb90b8f476144803d451dca..a2446e12804762c36bd956a86512a01efb61ff95 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 f756101c51402f00badd86206fabeabf9a9e4316..684c2cd8e244557bf58706453e113915d9e74d3d 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 0000000000000000000000000000000000000000..92a4fa216cd2b4d4c3fea0f5094837def558bdcb --- /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 056256a29f5ccdb599137adb1b081d0b771fa60d..e43e3e269bfc28146101c4d6b491e70dbb57372a 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 bae56334be48a2432f980060a757f80759ab00b3..82ab582beace731f4a57baee10450cca3f5691a1 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 b5ed8584c8a4fe4b2e74e5f91f40b716d34a7fff..8b19936ae6d0ca5c74aeab2669e35161a19c04c0 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 538f44e4f3fbeffa0f7432cb98a66b99fff5a22e..620f328a1147c88226f04e7c4550da9439f9fe82 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 de13c0db5d185e7692850d297c0b8519aa66ae75..8a8e131c57b823c40a07f9983ab714503912de60 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 afa89b84175a778dbc10224f686288676aaf8878..eca8ddd8ea4bc4d2da1d96fdf0b0ef6c6039a6ea 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 2bb9c3b3db3f9b66e1a051ceb6fdbe8de8e55c92..6367ac832e82816b31112a77b00e18628b36aa3d 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 f99ad046f0dbba07203a42a41e8c014b06ec5bb1..afabeed4a80f095df92c7efff04047189acca865 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 a63656e626801a040eaad3253a1f82bf6d38b7ce..a4fcd44882d987294ded49c00902c073c0925355 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 31b93850c7c9a95f424ae4af55371fb9e743c700..7d5cb876063ebe31c5ef0a0fc67c6ef2afe8b753 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 776a6ab5edbd4ed8233515e6f3594bf287564328..54719cbb8d85b6ae66f880f1d7f34540fe7186d7 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 4c5ced7e746a29bb00fe8bcbd9533c9b30ef39c2..bd4dc6a0f7989d3c2815991b8a04230d53e0c1a2 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 068c9a1219c984f127524b7004d8843c00cc9975..d5d4d7c56ef5d492f7a03a861b4797d0113c9cdd 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 d5aa115a074cba7625d57a1753bc989b8cd0629e..57c71544dfffada67f92d9a80c6f47e582bc6510 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 b43f38ef2021c24ee46432a432df6645d8f6eccb..606da1b7605b6de5e75873e555c5b1ca399f81b4 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 5ebe095743bbd13850d488cdd1ba1418b4012dc2..f3ea206f387efd2ec26f472ccb3342eb4b6ddb66 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 426bf53f19852563f5e3a64c46b2e4148bdde72c..9f9ef20f99b55015692d58f5bd0e92b5d53a2ee3 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 25da0917134cdb819157f77327580da9780da22a..d2c056d8e14c0a28d8fc8f006ac005d0925b7348 100644 --- a/spec/tasks/gitlab/backup_rake_spec.rb +++ b/spec/tasks/gitlab/backup_rake_spec.rb @@ -76,7 +76,6 @@ describe 'gitlab:app namespace rake task' do expect { run_rake_task('gitlab:backup:restore') }.not_to raise_error end end - end # backup_restore task describe 'backup_create' do @@ -98,67 +97,107 @@ describe 'gitlab:app namespace rake task' do @backup_tar = tars_glob.first end - before do - create_backup - end - - after do - FileUtils.rm(@backup_tar) - end + context 'tar creation' do + before do + create_backup + end - context 'archive file permissions' do - it 'should set correct permissions on the tar file' do - expect(File.exist?(@backup_tar)).to be_truthy - expect(File::Stat.new(@backup_tar).mode.to_s(8)).to eq('100600') + after do + FileUtils.rm(@backup_tar) end - context 'with custom archive_permissions' do - before do - allow(Gitlab.config.backup).to receive(:archive_permissions).and_return(0651) - # We created a backup in a before(:all) so it got the default permissions. - # We now need to do some work to create a _new_ backup file using our stub. - FileUtils.rm(@backup_tar) - create_backup + context 'archive file permissions' do + it 'should set correct permissions on the tar file' do + expect(File.exist?(@backup_tar)).to be_truthy + expect(File::Stat.new(@backup_tar).mode.to_s(8)).to eq('100600') end - it 'uses the custom permissions' do - expect(File::Stat.new(@backup_tar).mode.to_s(8)).to eq('100651') + context 'with custom archive_permissions' do + before do + allow(Gitlab.config.backup).to receive(:archive_permissions).and_return(0651) + # We created a backup in a before(:all) so it got the default permissions. + # We now need to do some work to create a _new_ backup file using our stub. + FileUtils.rm(@backup_tar) + create_backup + end + + it 'uses the custom permissions' do + expect(File::Stat.new(@backup_tar).mode.to_s(8)).to eq('100651') + end end end - end - it 'should set correct permissions on the tar contents' do - tar_contents, exit_status = Gitlab::Popen.popen( - %W{tar -tvf #{@backup_tar} db uploads.tar.gz repositories builds.tar.gz artifacts.tar.gz lfs.tar.gz registry.tar.gz} - ) - expect(exit_status).to eq(0) - expect(tar_contents).to match('db/') - expect(tar_contents).to match('uploads.tar.gz') - expect(tar_contents).to match('repositories/') - expect(tar_contents).to match('builds.tar.gz') - expect(tar_contents).to match('artifacts.tar.gz') - expect(tar_contents).to match('lfs.tar.gz') - expect(tar_contents).to match('registry.tar.gz') - expect(tar_contents).not_to match(/^.{4,9}[rwx].* (database.sql.gz|uploads.tar.gz|repositories|builds.tar.gz|artifacts.tar.gz|registry.tar.gz)\/$/) - end + it 'should set correct permissions on the tar contents' do + tar_contents, exit_status = Gitlab::Popen.popen( + %W{tar -tvf #{@backup_tar} db uploads.tar.gz repositories builds.tar.gz artifacts.tar.gz lfs.tar.gz registry.tar.gz} + ) + expect(exit_status).to eq(0) + expect(tar_contents).to match('db/') + expect(tar_contents).to match('uploads.tar.gz') + expect(tar_contents).to match('repositories/') + expect(tar_contents).to match('builds.tar.gz') + expect(tar_contents).to match('artifacts.tar.gz') + expect(tar_contents).to match('lfs.tar.gz') + expect(tar_contents).to match('registry.tar.gz') + expect(tar_contents).not_to match(/^.{4,9}[rwx].* (database.sql.gz|uploads.tar.gz|repositories|builds.tar.gz|artifacts.tar.gz|registry.tar.gz)\/$/) + end - it 'should delete temp directories' do - temp_dirs = Dir.glob( - File.join(Gitlab.config.backup.path, '{db,repositories,uploads,builds,artifacts,lfs,registry}') - ) + it 'should delete temp directories' do + temp_dirs = Dir.glob( + File.join(Gitlab.config.backup.path, '{db,repositories,uploads,builds,artifacts,lfs,registry}') + ) + + expect(temp_dirs).to be_empty + end - expect(temp_dirs).to be_empty + context 'registry disabled' do + let(:enable_registry) { false } + + it 'should not create registry.tar.gz' do + tar_contents, exit_status = Gitlab::Popen.popen( + %W{tar -tvf #{@backup_tar}} + ) + expect(exit_status).to eq(0) + expect(tar_contents).not_to match('registry.tar.gz') + end + end end - context 'registry disabled' do - let(:enable_registry) { false } + context 'multiple repository storages' do + let(:project_a) { create(:project, repository_storage: 'default') } + let(:project_b) { create(:project, repository_storage: 'custom') } + + before do + FileUtils.mkdir('tmp/tests/default_storage') + FileUtils.mkdir('tmp/tests/custom_storage') + storages = { + 'default' => 'tmp/tests/default_storage', + 'custom' => 'tmp/tests/custom_storage' + } + allow(Gitlab.config.repositories).to receive(:storages).and_return(storages) + + # Create the projects now, after mocking the settings but before doing the backup + project_a + project_b + + # We only need a backup of the repositories for this test + ENV["SKIP"] = "db,uploads,builds,artifacts,lfs,registry" + create_backup + end + + after do + FileUtils.rm_rf('tmp/tests/default_storage') + FileUtils.rm_rf('tmp/tests/custom_storage') + FileUtils.rm(@backup_tar) + end - it 'should not create registry.tar.gz' do + it 'should include repositories in all repository storages' do tar_contents, exit_status = Gitlab::Popen.popen( - %W{tar -tvf #{@backup_tar}} + %W{tar -tvf #{@backup_tar} repositories} ) expect(exit_status).to eq(0) - expect(tar_contents).not_to match('registry.tar.gz') + expect(tar_contents).to match("repositories/#{project_a.path_with_namespace}.bundle") + expect(tar_contents).to match("repositories/#{project_b.path_with_namespace}.bundle") end end end # backup_create task diff --git a/spec/views/projects/builds/show.html.haml_spec.rb b/spec/views/projects/builds/show.html.haml_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..cd18d19ef5e7c2cbc5eedd34bd7b4e146a8b696b --- /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 b8e73682c91ca61910d3f1c1674de82a546a39c5..20b1a343c27887d7d7121652dc5e3ed3dfd976b6 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 7e59bd2fced3dce2e77b081d36b6473ea30068c2..5785a6a06ff9932d5355c4ebaca372b5d9241af3 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 4ef05eb29d2b3f1c95f7b97bd7ed92325b0aa2ec..5f762282b5ea7ddae6a61adc14e006fe1c8780e3 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