From f9eb3fc0aa3c99fd36d3f344dc95f6b4edad5e07 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 7 Mar 2016 18:26:15 +0100 Subject: [PATCH 001/730] WIP - initial export service and spec --- app/services/projects/import_export.rb | 23 +++++ .../projects/import_export/export_service.rb | 15 ++++ .../import_export/project_tree_saver.rb | 42 ++++++++++ .../import_export/project_tree_saver_spec.rb | 83 +++++++++++++++++++ 4 files changed, 163 insertions(+) create mode 100644 app/services/projects/import_export.rb create mode 100644 app/services/projects/import_export/export_service.rb create mode 100644 app/services/projects/import_export/project_tree_saver.rb create mode 100644 spec/services/projects/import_export/project_tree_saver_spec.rb diff --git a/app/services/projects/import_export.rb b/app/services/projects/import_export.rb new file mode 100644 index 0000000000..f87b10390a --- /dev/null +++ b/app/services/projects/import_export.rb @@ -0,0 +1,23 @@ +module Projects + module ImportExport + extend self + + def export_path(project_name:) + File.join(storage_path, "#{Time.now.strftime('%Y-%m-%d_%H-%M-%3N')}_gitlab_export_#{project_name}") + end + + def project_atts + %i(id name path description issues_enabled wall_enabled merge_requests_enabled wiki_enabled snippets_enabled visibility_level archived) + end + + def project_tree + %i(issues merge_requests labels milestones snippets releases events commit_statuses) + end + + private + + def storage_path + File.join(Settings.shared['path'], 'tmp/project_exports') + end + end +end diff --git a/app/services/projects/import_export/export_service.rb b/app/services/projects/import_export/export_service.rb new file mode 100644 index 0000000000..c89dd3d12e --- /dev/null +++ b/app/services/projects/import_export/export_service.rb @@ -0,0 +1,15 @@ +module Projects + module ImportExport + class ExportService < BaseService + def execute(options = {}) + save_project_tree + end + + private + + def save_project_tree + Projects::ImportExport::ProjectTreeSaver.save(project: project) + end + end + end +end diff --git a/app/services/projects/import_export/project_tree_saver.rb b/app/services/projects/import_export/project_tree_saver.rb new file mode 100644 index 0000000000..4801c791ff --- /dev/null +++ b/app/services/projects/import_export/project_tree_saver.rb @@ -0,0 +1,42 @@ +module Projects + module ImportExport + class ProjectTreeSaver + attr_reader :full_path + + def initialize(project: ) + @project = project + end + + def save + @full_path = File.join(export_path, project_filename) + save_to_disk + end + + private + + def save_to_disk + FileUtils.mkdir_p(export_path) + File.write(full_path, project_json_tree) + true + rescue + #TODO: handle error + false + end + + def export_path + @export_path ||= ImportExport.export_path(@project.name) + end + + def project_filename + # TODO sanitize name + "#{@project.name}.json" + end + + def project_json_tree + # TODO confirm children, also add subchildren (i.e comments) + # TODO confirm atts for children + @project.to_json(only: ImportExport.project_atts, include: ImportExport.project_tree) + end + end + end +end diff --git a/spec/services/projects/import_export/project_tree_saver_spec.rb b/spec/services/projects/import_export/project_tree_saver_spec.rb new file mode 100644 index 0000000000..00e44a9f33 --- /dev/null +++ b/spec/services/projects/import_export/project_tree_saver_spec.rb @@ -0,0 +1,83 @@ +require 'spec_helper' + +describe Projects::ImportExport::ProjectTreeSaver, services: true do + describe :save do + + let(:user) { create(:user) } + let!(:project) { create(:project, :public, name: 'searchable_project') } + let(:export_path) { "#{Dir::tmpdir}/project_tree_saver_spec" } + let(:project_tree_saver) { Projects::ImportExport::ProjectTreeSaver.new(project: project) } + + before(:each) do + project.team << [user, :master] + allow_any_instance_of(Projects::ImportExport::ProjectTreeSaver).to receive(:export_path).and_return(export_path) + end + + after(:each) do + FileUtils.rm_rf(export_path) + end + + it 'saves project successfully' do + expect(project_tree_saver.save).to be true + end + + it 'saves the correct json' do + project_tree_saver.save + expect(project_json(project_tree_saver.full_path)).to include({ "name" => project.name }) + end + end + + def project_json(filename) + JSON.parse(IO.read(filename)) + end + + # TODO: Remove this. Current JSON pretty printed: + # { + # "id": 1, + # "name": "searchable_project", + # "path": "gitlabhq", + # "description": null, + # "issues_enabled": true, + # "wall_enabled": false, + # "merge_requests_enabled": true, + # "wiki_enabled": true, + # "snippets_enabled": true, + # "visibility_level": 20, + # "archived": false, + # "issues": [ + # + # ], + # "merge_requests": [ + # + # ], + # "labels": [ + # + # ], + # "milestones": [ + # + # ], + # "snippets": [ + # + # ], + # "releases": [ + # + # ], + # "events": [ + # { + # "id": 1, + # "target_type": null, + # "target_id": null, + # "title": null, + # "data": null, + # "project_id": 1, + # "created_at": "2016-03-07T17:05:20.926Z", + # "updated_at": "2016-03-07T17:05:20.926Z", + # "action": 8, + # "author_id": 3 + # } + # ], + # "commit_statuses": [ + # + # ] + # } +end From e228453f47a98c1da51878fb9feeff8ae9ddd7a9 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 7 Mar 2016 19:14:06 +0100 Subject: [PATCH 002/730] updated spec --- .../import_export/project_tree_saver_spec.rb | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/spec/services/projects/import_export/project_tree_saver_spec.rb b/spec/services/projects/import_export/project_tree_saver_spec.rb index 00e44a9f33..b9768441ba 100644 --- a/spec/services/projects/import_export/project_tree_saver_spec.rb +++ b/spec/services/projects/import_export/project_tree_saver_spec.rb @@ -4,7 +4,8 @@ describe Projects::ImportExport::ProjectTreeSaver, services: true do describe :save do let(:user) { create(:user) } - let!(:project) { create(:project, :public, name: 'searchable_project') } + let(:issue) { create(:issue, assignee: user) } + let!(:project) { create(:project, :public, name: 'searchable_project', issues: [issue] )} let(:export_path) { "#{Dir::tmpdir}/project_tree_saver_spec" } let(:project_tree_saver) { Projects::ImportExport::ProjectTreeSaver.new(project: project) } @@ -21,9 +22,24 @@ describe Projects::ImportExport::ProjectTreeSaver, services: true do expect(project_tree_saver.save).to be true end - it 'saves the correct json' do - project_tree_saver.save - expect(project_json(project_tree_saver.full_path)).to include({ "name" => project.name }) + context 'JSON' do + + let(:saved_project_json) do + project_tree_saver.save + project_json(project_tree_saver.full_path) + end + + it 'saves the correct json' do + expect(saved_project_json).to include({ "name" => project.name }) + end + + it 'has events' do + expect(saved_project_json['events']).not_to be_empty + end + + it 'has issues' do + expect(saved_project_json['issues']).not_to be_empty + end end end From 68eae04538f296a15863235d7f1f59f3e9e8a1dd Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 8 Mar 2016 10:21:02 +0100 Subject: [PATCH 003/730] finish project tree saver spec --- .../import_export/project_tree_saver_spec.rb | 233 ++++++++++++++---- 1 file changed, 191 insertions(+), 42 deletions(-) diff --git a/spec/services/projects/import_export/project_tree_saver_spec.rb b/spec/services/projects/import_export/project_tree_saver_spec.rb index b9768441ba..42302ffee8 100644 --- a/spec/services/projects/import_export/project_tree_saver_spec.rb +++ b/spec/services/projects/import_export/project_tree_saver_spec.rb @@ -5,7 +5,23 @@ describe Projects::ImportExport::ProjectTreeSaver, services: true do let(:user) { create(:user) } let(:issue) { create(:issue, assignee: user) } - let!(:project) { create(:project, :public, name: 'searchable_project', issues: [issue] )} + let(:merge_request) { create(:merge_request) } + let(:label) { create(:label) } + let(:snippet) { create(:project_snippet) } + let(:commit_status) { create(:commit_status) } + let(:release) { create(:release) } + let!(:project) do + create(:project, + :public, + name: 'searchable_project', + issues: [issue], + merge_requests: [merge_request], + labels: [label], + snippets: [snippet], + releases: [release], + commit_statuses: [commit_status]) + end + let!(:milestone) { create(:milestone, title: "Milestone v1.2", project: project) } let(:export_path) { "#{Dir::tmpdir}/project_tree_saver_spec" } let(:project_tree_saver) { Projects::ImportExport::ProjectTreeSaver.new(project: project) } @@ -37,9 +53,33 @@ describe Projects::ImportExport::ProjectTreeSaver, services: true do expect(saved_project_json['events']).not_to be_empty end + it 'has milestones' do + expect(saved_project_json['milestones']).not_to be_empty + end + + it 'has merge requests' do + expect(saved_project_json['merge_requests']).not_to be_empty + end + + it 'has labels' do + expect(saved_project_json['labels']).not_to be_empty + end + + it 'has snippets' do + expect(saved_project_json['snippets']).not_to be_empty + end + + it 'has releases' do + expect(saved_project_json['releases']).not_to be_empty + end + it 'has issues' do expect(saved_project_json['issues']).not_to be_empty end + + it 'has commit statuses' do + expect(saved_project_json['commit_statuses']).not_to be_empty + end end end @@ -49,51 +89,160 @@ describe Projects::ImportExport::ProjectTreeSaver, services: true do # TODO: Remove this. Current JSON pretty printed: # { - # "id": 1, - # "name": "searchable_project", - # "path": "gitlabhq", - # "description": null, - # "issues_enabled": true, - # "wall_enabled": false, - # "merge_requests_enabled": true, - # "wiki_enabled": true, - # "snippets_enabled": true, - # "visibility_level": 20, - # "archived": false, - # "issues": [ - # - # ], - # "merge_requests": [ - # - # ], - # "labels": [ - # - # ], - # "milestones": [ - # - # ], - # "snippets": [ - # - # ], - # "releases": [ - # - # ], - # "events": [ + # "id":7, + # "name":"searchable_project", + # "path":"gitlabhq", + # "description":null, + # "issues_enabled":true, + # "wall_enabled":false, + # "merge_requests_enabled":true, + # "wiki_enabled":true, + # "snippets_enabled":true, + # "visibility_level":20, + # "archived":false, + # "issues":[ # { - # "id": 1, - # "target_type": null, - # "target_id": null, - # "title": null, - # "data": null, - # "project_id": 1, - # "created_at": "2016-03-07T17:05:20.926Z", - # "updated_at": "2016-03-07T17:05:20.926Z", - # "action": 8, - # "author_id": 3 + # "id":1, + # "title":"Voluptas dolores molestias iste excepturi quia atque sint et.", + # "assignee_id":1, + # "author_id":2, + # "project_id":7, + # "created_at":"2016-03-08T09:14:31.726Z", + # "updated_at":"2016-03-08T09:14:36.293Z", + # "position":0, + # "branch_name":null, + # "description":null, + # "milestone_id":null, + # "state":"opened", + # "iid":1, + # "updated_by_id":null # } # ], - # "commit_statuses": [ + # "merge_requests":[ + # { + # "id":1, + # "target_branch":"feature", + # "source_branch":"master", + # "source_project_id":2, + # "author_id":5, + # "assignee_id":null, + # "title":"Quam velit cupiditate culpa perspiciatis esse maiores quaerat.", + # "created_at":"2016-03-08T09:14:32.597Z", + # "updated_at":"2016-03-08T09:14:32.597Z", + # "milestone_id":null, + # "state":"opened", + # "merge_status":"can_be_merged", + # "target_project_id":7, + # "iid":1, + # "description":null, + # "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 + # } + # ], + # "labels":[ + # { + # "id":1, + # "title":"Bug", + # "color":"#990000", + # "project_id":7, + # "created_at":"2016-03-08T09:14:33.774Z", + # "updated_at":"2016-03-08T09:14:36.314Z", + # "template":false, + # "description":null + # } + # ], + # "milestones":[ + # { + # "id":1, + # "title":"Milestone v1.2", + # "project_id":7, + # "description":null, + # "due_date":null, + # "created_at":"2016-03-08T09:14:36.526Z", + # "updated_at":"2016-03-08T09:14:36.526Z", + # "state":"active", + # "iid":1 + # } + # ], + # "snippets":[ + # { + # "id":1, + # "title":"Voluptatem qui officiis modi ut fugit distinctio dolor qui.", + # "content":"Quaerat sunt eligendi voluptatum magnam.", + # "author_id":12, + # "project_id":7, + # "created_at":"2016-03-08T09:14:34.539Z", + # "updated_at":"2016-03-08T09:14:36.332Z", + # "file_name":"rowland.tremblay", + # "expires_at":null, + # "visibility_level":0 + # } + # ], + # "releases":[ + # { + # "id":1, + # "tag":"v1.1.0", + # "description":"Awesome release", + # "project_id":7, + # "created_at":"2016-03-08T09:14:35.023Z", + # "updated_at":"2016-03-08T09:14:36.351Z" + # } + # ], + # "events":[ + # { + # "id":1, + # "target_type":null, + # "target_id":null, + # "title":null, + # "data":null, + # "project_id":7, + # "created_at":"2016-03-08T09:14:36.806Z", + # "updated_at":"2016-03-08T09:14:36.806Z", + # "action":8, + # "author_id":1 + # } + # ], + # "commit_statuses":[ + # { + # "id":1, + # "project_id":null, + # "status":"success", + # "finished_at":"2016-01-26T07:23:42.000Z", + # "trace":null, + # "created_at":"2016-03-08T09:14:35.633Z", + # "updated_at":"2016-03-08T09:14:36.385Z", + # "started_at":"2016-01-26T07:21:42.000Z", + # "runner_id":null, + # "coverage":null, + # "commit_id":1, + # "commands":null, + # "job_id":null, + # "name":"default", + # "deploy":false, + # "options":null, + # "allow_failure":false, + # "stage":null, + # "trigger_request_id":null, + # "stage_idx":null, + # "tag":null, + # "ref":null, + # "user_id":null, + # "target_url":null, + # "description":"commit status", + # "artifacts_file":null, + # "gl_project_id":7, + # "artifacts_metadata":null, + # "erased_by_id":null, + # "erased_at":null + # } # ] # } end From 4e73f9827cc5b164e409a6beb9a305ef5604423d Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 8 Mar 2016 12:35:37 +0100 Subject: [PATCH 004/730] WIP - started working on bundle the repo, refactored some stuff and updated spec --- .../import_export/command_line_util.rb | 11 ++++++ .../projects/import_export/export_service.rb | 8 +++- .../import_export/project_tree_saver.rb | 11 ++---- .../projects/import_export/repo_bundler.rb | 37 +++++++++++++++++++ app/services/projects/import_export/shared.rb | 13 +++++++ .../import_export/project_tree_saver_spec.rb | 3 +- 6 files changed, 74 insertions(+), 9 deletions(-) create mode 100644 app/services/projects/import_export/command_line_util.rb create mode 100644 app/services/projects/import_export/repo_bundler.rb create mode 100644 app/services/projects/import_export/shared.rb diff --git a/app/services/projects/import_export/command_line_util.rb b/app/services/projects/import_export/command_line_util.rb new file mode 100644 index 0000000000..7b0cc08763 --- /dev/null +++ b/app/services/projects/import_export/command_line_util.rb @@ -0,0 +1,11 @@ +module Projects + module ImportExport + module CommandLineUtil + def tar_cf(archive:, dir:) + cmd = %W(tar -cf #{archive} -C #{dir} .) + _output, status = Gitlab::Popen.popen(cmd) + status.zero? + end + end + end +end diff --git a/app/services/projects/import_export/export_service.rb b/app/services/projects/import_export/export_service.rb index c89dd3d12e..b3ad278733 100644 --- a/app/services/projects/import_export/export_service.rb +++ b/app/services/projects/import_export/export_service.rb @@ -2,13 +2,19 @@ module Projects module ImportExport class ExportService < BaseService def execute(options = {}) + @shared = Projects::ImportExport::Shared.new(project_name: @project_name) save_project_tree + bundle_repo end private def save_project_tree - Projects::ImportExport::ProjectTreeSaver.save(project: project) + Projects::ImportExport::ProjectTreeSaver.new(project: project, shared: @shared).save + end + + def bundle_repo + Projects::ImportExport::RepoBundler.new(project: project, shared: @shared).bundle end end end diff --git a/app/services/projects/import_export/project_tree_saver.rb b/app/services/projects/import_export/project_tree_saver.rb index 4801c791ff..3ca90d1f79 100644 --- a/app/services/projects/import_export/project_tree_saver.rb +++ b/app/services/projects/import_export/project_tree_saver.rb @@ -3,19 +3,20 @@ module Projects class ProjectTreeSaver attr_reader :full_path - def initialize(project: ) + def initialize(project: , shared: ) @project = project + @export_path = shared.export_path end def save - @full_path = File.join(export_path, project_filename) + @full_path = File.join(@export_path, project_filename) save_to_disk end private def save_to_disk - FileUtils.mkdir_p(export_path) + FileUtils.mkdir_p(@export_path) File.write(full_path, project_json_tree) true rescue @@ -23,10 +24,6 @@ module Projects false end - def export_path - @export_path ||= ImportExport.export_path(@project.name) - end - def project_filename # TODO sanitize name "#{@project.name}.json" diff --git a/app/services/projects/import_export/repo_bundler.rb b/app/services/projects/import_export/repo_bundler.rb new file mode 100644 index 0000000000..27f1d5c87e --- /dev/null +++ b/app/services/projects/import_export/repo_bundler.rb @@ -0,0 +1,37 @@ +module Projects + module ImportExport + class RepoBundler + include Projects::ImportExport::CommandLineUtil + + attr_reader :full_path + + def initialize(project: , shared: ) + @project = project + @export_path = shared.export_path + end + + def bundle + return false if project.empty_repo? + @full_path = File.join(export_path, project_filename) + bundle_to_disk + end + + private + + def bundle_to_disk + tar_cf(archive: full_path, dir: path_to_repo) + rescue + #TODO: handle error + false + end + + def project_filename + @project.path_with_namespace + ".bundle" + end + + def path_to_repo + @project.repository.path_to_repo + end + end + end +end diff --git a/app/services/projects/import_export/shared.rb b/app/services/projects/import_export/shared.rb new file mode 100644 index 0000000000..cdff8b02dd --- /dev/null +++ b/app/services/projects/import_export/shared.rb @@ -0,0 +1,13 @@ +module Projects + module ImportExport + class Shared + def initialize(opts) + @opts = opts + end + + def export_path + @export_path ||= ImportExport.export_path(project_name: @opts[:project_name]) + end + end + end +end \ No newline at end of file diff --git a/spec/services/projects/import_export/project_tree_saver_spec.rb b/spec/services/projects/import_export/project_tree_saver_spec.rb index 42302ffee8..816171ca7e 100644 --- a/spec/services/projects/import_export/project_tree_saver_spec.rb +++ b/spec/services/projects/import_export/project_tree_saver_spec.rb @@ -23,7 +23,8 @@ describe Projects::ImportExport::ProjectTreeSaver, services: true do end let!(:milestone) { create(:milestone, title: "Milestone v1.2", project: project) } let(:export_path) { "#{Dir::tmpdir}/project_tree_saver_spec" } - let(:project_tree_saver) { Projects::ImportExport::ProjectTreeSaver.new(project: project) } + let(:shared) { Projects::ImportExport::Shared.new(project_name: @project_name) } + let(:project_tree_saver) { Projects::ImportExport::ProjectTreeSaver.new(project: project, shared: shared) } before(:each) do project.team << [user, :master] From 556cafa44e7baae4de0f4169703d8a6174de458a Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 8 Mar 2016 15:53:32 +0100 Subject: [PATCH 005/730] added repo bundler spec and refactored some of the export code --- app/services/projects/import_export.rb | 4 +-- .../projects/import_export/export_service.rb | 2 +- .../projects/import_export/repo_bundler.rb | 7 +++--- app/services/projects/import_export/shared.rb | 2 +- .../import_export/project_tree_saver_spec.rb | 4 +-- .../import_export/repo_bundler_spec.rb | 25 +++++++++++++++++++ 6 files changed, 35 insertions(+), 9 deletions(-) create mode 100644 spec/services/projects/import_export/repo_bundler_spec.rb diff --git a/app/services/projects/import_export.rb b/app/services/projects/import_export.rb index f87b10390a..2fc0d5dd7f 100644 --- a/app/services/projects/import_export.rb +++ b/app/services/projects/import_export.rb @@ -2,8 +2,8 @@ module Projects module ImportExport extend self - def export_path(project_name:) - File.join(storage_path, "#{Time.now.strftime('%Y-%m-%d_%H-%M-%3N')}_gitlab_export_#{project_name}") + def export_path(relative_path:) + File.join(storage_path, "#{Time.now.strftime('%Y-%m-%d_%H-%M-%3N')}_gitlab_export/#{relative_path}") end def project_atts diff --git a/app/services/projects/import_export/export_service.rb b/app/services/projects/import_export/export_service.rb index b3ad278733..99aa8489f6 100644 --- a/app/services/projects/import_export/export_service.rb +++ b/app/services/projects/import_export/export_service.rb @@ -2,7 +2,7 @@ module Projects module ImportExport class ExportService < BaseService def execute(options = {}) - @shared = Projects::ImportExport::Shared.new(project_name: @project_name) + @shared = Projects::ImportExport::Shared.new(relative_path: project.path_with_namespace) save_project_tree bundle_repo end diff --git a/app/services/projects/import_export/repo_bundler.rb b/app/services/projects/import_export/repo_bundler.rb index 27f1d5c87e..b0b2df1c14 100644 --- a/app/services/projects/import_export/repo_bundler.rb +++ b/app/services/projects/import_export/repo_bundler.rb @@ -11,14 +11,15 @@ module Projects end def bundle - return false if project.empty_repo? - @full_path = File.join(export_path, project_filename) + return false if @project.empty_repo? + @full_path = File.join(@export_path, project_filename) bundle_to_disk end private def bundle_to_disk + FileUtils.mkdir_p(@export_path) tar_cf(archive: full_path, dir: path_to_repo) rescue #TODO: handle error @@ -26,7 +27,7 @@ module Projects end def project_filename - @project.path_with_namespace + ".bundle" + "#{@project.namespace}#{@project.name}.bundle" end def path_to_repo diff --git a/app/services/projects/import_export/shared.rb b/app/services/projects/import_export/shared.rb index cdff8b02dd..5101f514ab 100644 --- a/app/services/projects/import_export/shared.rb +++ b/app/services/projects/import_export/shared.rb @@ -6,7 +6,7 @@ module Projects end def export_path - @export_path ||= ImportExport.export_path(project_name: @opts[:project_name]) + @export_path ||= Projects::ImportExport.export_path(relative_path: @opts[:relative_path]) end end end diff --git a/spec/services/projects/import_export/project_tree_saver_spec.rb b/spec/services/projects/import_export/project_tree_saver_spec.rb index 816171ca7e..1b3568bb7a 100644 --- a/spec/services/projects/import_export/project_tree_saver_spec.rb +++ b/spec/services/projects/import_export/project_tree_saver_spec.rb @@ -23,12 +23,12 @@ describe Projects::ImportExport::ProjectTreeSaver, services: true do end let!(:milestone) { create(:milestone, title: "Milestone v1.2", project: project) } let(:export_path) { "#{Dir::tmpdir}/project_tree_saver_spec" } - let(:shared) { Projects::ImportExport::Shared.new(project_name: @project_name) } + let(:shared) { Projects::ImportExport::Shared.new(relative_path: project.path_with_namespace) } let(:project_tree_saver) { Projects::ImportExport::ProjectTreeSaver.new(project: project, shared: shared) } before(:each) do project.team << [user, :master] - allow_any_instance_of(Projects::ImportExport::ProjectTreeSaver).to receive(:export_path).and_return(export_path) + allow_any_instance_of(Projects::ImportExport).to receive(:storage_path).and_return(export_path) end after(:each) do diff --git a/spec/services/projects/import_export/repo_bundler_spec.rb b/spec/services/projects/import_export/repo_bundler_spec.rb new file mode 100644 index 0000000000..1f8ed41718 --- /dev/null +++ b/spec/services/projects/import_export/repo_bundler_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' + +describe Projects::ImportExport::RepoBundler, services: true do + describe :bundle do + + let(:user) { create(:user) } + let!(:project) { create(:project, :public, name: 'searchable_project') } + let(:export_path) { "#{Dir::tmpdir}/project_tree_saver_spec" } + let(:shared) { Projects::ImportExport::Shared.new(relative_path: project.path_with_namespace) } + let(:bundler) { Projects::ImportExport::RepoBundler.new(project: project, shared: shared) } + + before(:each) do + project.team << [user, :master] + allow_any_instance_of(Projects::ImportExport).to receive(:storage_path).and_return(export_path) + end + + after(:each) do + FileUtils.rm_rf(export_path) + end + + it 'bundles the repo successfully' do + expect(bundler.bundle).to be true + end + end +end From 99d87d8698437f87c21ced1d5a7fab4f9d253493 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 8 Mar 2016 18:17:57 +0100 Subject: [PATCH 006/730] WIP - added wiki repo bundler --- .../import_export/command_line_util.rb | 6 ++++ .../import_export/wiki_repo_bundler.rb | 30 +++++++++++++++++++ .../import_export/wiki_repo_bundler_spec.rb | 25 ++++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 app/services/projects/import_export/wiki_repo_bundler.rb create mode 100644 spec/services/projects/import_export/wiki_repo_bundler_spec.rb diff --git a/app/services/projects/import_export/command_line_util.rb b/app/services/projects/import_export/command_line_util.rb index 7b0cc08763..3ca49e76c7 100644 --- a/app/services/projects/import_export/command_line_util.rb +++ b/app/services/projects/import_export/command_line_util.rb @@ -6,6 +6,12 @@ module Projects _output, status = Gitlab::Popen.popen(cmd) status.zero? end + + def git_bundle(git_bin_path: Gitlab.config.git.bin_path, repo_path:, bundle_path:) + cmd = %W(#{git_bin_path} --git-dir=#{repo_path} bundle create #{bundle_path} --all) + _output, status = Gitlab::Popen.popen(cmd) + status.zero? + end end end end diff --git a/app/services/projects/import_export/wiki_repo_bundler.rb b/app/services/projects/import_export/wiki_repo_bundler.rb new file mode 100644 index 0000000000..793c8efd14 --- /dev/null +++ b/app/services/projects/import_export/wiki_repo_bundler.rb @@ -0,0 +1,30 @@ +module Projects + module ImportExport + class WikiRepoBundler < RepoBundler + def bundle + @wiki = ProjectWiki.new(@project) + return false if !wiki? + @full_path = File.join(@export_path, project_filename) + bundle_to_disk + end + + def bundle_to_disk + FileUtils.mkdir_p(@export_path) + git_bundle(repo_path: path_to_repo, bundle_path: @full_path) + rescue + #TODO: handle error + false + end + + private + + def path_to_repo + @wiki.repository.path_to_repo + end + + def wiki? + File.exists?(@wiki.repository.path_to_repo) && !@wiki.repository.empty? + end + end + end +end diff --git a/spec/services/projects/import_export/wiki_repo_bundler_spec.rb b/spec/services/projects/import_export/wiki_repo_bundler_spec.rb new file mode 100644 index 0000000000..351419d061 --- /dev/null +++ b/spec/services/projects/import_export/wiki_repo_bundler_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' + +describe Projects::ImportExport::WikiRepoBundler, services: true do + describe :bundle do + + let(:user) { create(:user) } + let!(:project) { create(:project, :public, name: 'searchable_project') } + let(:export_path) { "#{Dir::tmpdir}/project_tree_saver_spec" } + let(:shared) { Projects::ImportExport::Shared.new(relative_path: project.path_with_namespace) } + let(:wiki_bundler) { Projects::ImportExport::WikiRepoBundler.new(project: project, shared: shared) } + + before(:each) do + project.team << [user, :master] + allow_any_instance_of(Projects::ImportExport).to receive(:storage_path).and_return(export_path) + end + + after(:each) do + FileUtils.rm_rf(export_path) + end + + it 'bundles the repo successfully' do + expect(wiki_bundler.bundle).to be true + end + end +end From f9c6168cc47496ac92e1a8c38dd9bd4ac39fd3d5 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 8 Mar 2016 18:20:32 +0100 Subject: [PATCH 007/730] fix new line issue --- app/services/projects/import_export/shared.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/projects/import_export/shared.rb b/app/services/projects/import_export/shared.rb index 5101f514ab..04fe01c0d6 100644 --- a/app/services/projects/import_export/shared.rb +++ b/app/services/projects/import_export/shared.rb @@ -10,4 +10,4 @@ module Projects end end end -end \ No newline at end of file +end From 4b88b4ffd5f49ea4cef189776783b58f7c6c141f Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 9 Mar 2016 10:35:38 +0100 Subject: [PATCH 008/730] fix wiki path issues and spec --- app/services/projects/import_export/repo_bundler.rb | 2 +- app/services/projects/import_export/wiki_repo_bundler.rb | 4 ++++ .../services/projects/import_export/wiki_repo_bundler_spec.rb | 3 +++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/services/projects/import_export/repo_bundler.rb b/app/services/projects/import_export/repo_bundler.rb index b0b2df1c14..d43fb4ea09 100644 --- a/app/services/projects/import_export/repo_bundler.rb +++ b/app/services/projects/import_export/repo_bundler.rb @@ -27,7 +27,7 @@ module Projects end def project_filename - "#{@project.namespace}#{@project.name}.bundle" + "#{@project.name}.bundle" end def path_to_repo diff --git a/app/services/projects/import_export/wiki_repo_bundler.rb b/app/services/projects/import_export/wiki_repo_bundler.rb index 793c8efd14..bf69936503 100644 --- a/app/services/projects/import_export/wiki_repo_bundler.rb +++ b/app/services/projects/import_export/wiki_repo_bundler.rb @@ -18,6 +18,10 @@ module Projects private + def project_filename + "#{@project.name}.wiki.bundle" + end + def path_to_repo @wiki.repository.path_to_repo end diff --git a/spec/services/projects/import_export/wiki_repo_bundler_spec.rb b/spec/services/projects/import_export/wiki_repo_bundler_spec.rb index 351419d061..a589f81c5f 100644 --- a/spec/services/projects/import_export/wiki_repo_bundler_spec.rb +++ b/spec/services/projects/import_export/wiki_repo_bundler_spec.rb @@ -8,10 +8,13 @@ describe Projects::ImportExport::WikiRepoBundler, services: true do let(:export_path) { "#{Dir::tmpdir}/project_tree_saver_spec" } let(:shared) { Projects::ImportExport::Shared.new(relative_path: project.path_with_namespace) } let(:wiki_bundler) { Projects::ImportExport::WikiRepoBundler.new(project: project, shared: shared) } + let!(:project_wiki) { ProjectWiki.new(project, user) } before(:each) do project.team << [user, :master] allow_any_instance_of(Projects::ImportExport).to receive(:storage_path).and_return(export_path) + project_wiki.wiki + project_wiki.create_page("index", "test content") end after(:each) do From 2dc2ce45d788e296a7b8c11417833573fcd721ea Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 9 Mar 2016 16:21:02 +0100 Subject: [PATCH 009/730] WIP - broken spec and some import stuff so I can create a MR on this. --- .../projects/import_export/import_service.rb | 19 ++++++++++++ .../import_export/project_tree_restorer.rb | 30 +++++++++++++++++++ .../import_export/relation_factory.rb | 18 +++++++++++ fixtures/import_export/project.json | 1 + .../project_tree_restorer_spec.rb | 29 ++++++++++++++++++ 5 files changed, 97 insertions(+) create mode 100644 app/services/projects/import_export/import_service.rb create mode 100644 app/services/projects/import_export/project_tree_restorer.rb create mode 100644 app/services/projects/import_export/relation_factory.rb create mode 100644 fixtures/import_export/project.json create mode 100644 spec/services/projects/import_export/project_tree_restorer_spec.rb diff --git a/app/services/projects/import_export/import_service.rb b/app/services/projects/import_export/import_service.rb new file mode 100644 index 0000000000..3efddf75e4 --- /dev/null +++ b/app/services/projects/import_export/import_service.rb @@ -0,0 +1,19 @@ +module Projects + module ImportExport + class ExportService < BaseService + def execute(options = {}) + @import_path = options[:import_path] + end + + private + + def restore_project_tree + Projects::ImportExport::ProjectTreeRestorer.new(path: @import_path).restore + end + + def restore_repo + + end + end + end +end diff --git a/app/services/projects/import_export/project_tree_restorer.rb b/app/services/projects/import_export/project_tree_restorer.rb new file mode 100644 index 0000000000..c6aabc42f4 --- /dev/null +++ b/app/services/projects/import_export/project_tree_restorer.rb @@ -0,0 +1,30 @@ +module Projects + module ImportExport + class ProjectTreeRestorer + attr_reader :full_path + + def initialize(path: ) + @path = path + end + + def restore + json = IO.read(@path) + tree_hash = ActiveSupport::JSON.decode(json) + ImportExport.project_tree.each do |relation| + next if tree_hash[relation.to_s].empty? + tree_hash[relation.to_s] = create_relation(relation, tree_hash[relation.to_s]) + end + project = Project.new(tree_hash) + project + end + + private + + def create_relation(relation, tree_hash) + Projects::ImportExport::RelationFactory.create( + relation_sym: relation, relation_hash: tree_hash[relation.to_s]) + end + + end + end +end diff --git a/app/services/projects/import_export/relation_factory.rb b/app/services/projects/import_export/relation_factory.rb new file mode 100644 index 0000000000..03fa36428c --- /dev/null +++ b/app/services/projects/import_export/relation_factory.rb @@ -0,0 +1,18 @@ +module Projects + module ImportExport + module RelationFactory + extend self + + def create(relation_sym: , relation_hash:) + klass = relation_class(relation_sym) + klass.new(relation_hash) + end + + private + + def relation_class(relation_sym) + relation_sym.to_s.classify.constantize + end + end + end +end diff --git a/fixtures/import_export/project.json b/fixtures/import_export/project.json new file mode 100644 index 0000000000..8ea17e4d99 --- /dev/null +++ b/fixtures/import_export/project.json @@ -0,0 +1 @@ +{"id":14,"name":"searchable_project","path":"gitlabhq","description":null,"issues_enabled":true,"wall_enabled":false,"merge_requests_enabled":true,"wiki_enabled":true,"snippets_enabled":true,"visibility_level":20,"archived":false,"issues":[{"id":2,"title":"Eos ut accusamus provident quis qui.","assignee_id":19,"author_id":20,"project_id":14,"created_at":"2016-03-09T11:41:00.754Z","updated_at":"2016-03-09T11:41:05.728Z","position":0,"branch_name":null,"description":null,"milestone_id":null,"state":"opened","iid":1,"updated_by_id":null}],"merge_requests":[{"id":2,"target_branch":"feature","source_branch":"master","source_project_id":9,"author_id":23,"assignee_id":null,"title":"Eos dolores molestias eum magni ut consequatur deleniti distinctio.","created_at":"2016-03-09T11:41:01.820Z","updated_at":"2016-03-09T11:41:01.820Z","milestone_id":null,"state":"opened","merge_status":"can_be_merged","target_project_id":14,"iid":1,"description":null,"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}],"labels":[{"id":2,"title":"Bug","color":"#990000","project_id":14,"created_at":"2016-03-09T11:41:02.959Z","updated_at":"2016-03-09T11:41:05.750Z","template":false,"description":null}],"milestones":[{"id":2,"title":"Milestone v1.2","project_id":14,"description":null,"due_date":null,"created_at":"2016-03-09T11:41:05.846Z","updated_at":"2016-03-09T11:41:05.846Z","state":"active","iid":1}],"snippets":[{"id":2,"title":"Unde adipisci molestiae modi quisquam qui itaque ut aut.","content":"Temporibus qui nisi ipsam maiores voluptatum.","author_id":30,"project_id":14,"created_at":"2016-03-09T11:41:03.720Z","updated_at":"2016-03-09T11:41:05.763Z","file_name":"sarah","expires_at":null,"visibility_level":0}],"releases":[{"id":2,"tag":"v1.1.0","description":"Awesome release","project_id":14,"created_at":"2016-03-09T11:41:04.342Z","updated_at":"2016-03-09T11:41:05.776Z"}],"events":[{"id":2,"target_type":null,"target_id":null,"title":null,"data":null,"project_id":14,"created_at":"2016-03-09T11:41:05.998Z","updated_at":"2016-03-09T11:41:05.998Z","action":8,"author_id":19}],"commit_statuses":[{"id":2,"project_id":null,"status":"success","finished_at":"2016-01-26T07:23:42.000Z","trace":null,"created_at":"2016-03-09T11:41:05.011Z","updated_at":"2016-03-09T11:41:05.801Z","started_at":"2016-01-26T07:21:42.000Z","runner_id":null,"coverage":null,"commit_id":2,"commands":null,"job_id":null,"name":"default","deploy":false,"options":null,"allow_failure":false,"stage":null,"trigger_request_id":null,"stage_idx":null,"tag":null,"ref":null,"user_id":null,"target_url":null,"description":"commit status","artifacts_file":null,"gl_project_id":14,"artifacts_metadata":null,"erased_by_id":null,"erased_at":null}]} \ No newline at end of file diff --git a/spec/services/projects/import_export/project_tree_restorer_spec.rb b/spec/services/projects/import_export/project_tree_restorer_spec.rb new file mode 100644 index 0000000000..f5b4340805 --- /dev/null +++ b/spec/services/projects/import_export/project_tree_restorer_spec.rb @@ -0,0 +1,29 @@ +require 'spec_helper' + +describe Projects::ImportExport::ProjectTreeRestorer, services: true do + describe :restore do + + let(:user) { create(:user) } + let(:project_tree_restorer) { Projects::ImportExport::ProjectTreeRestorer.new(path: "fixtures/import_export/project.json") } + + before(:each) do + #allow(project_tree_restorer) + # .to receive(:full_path).and_return("fixtures/import_export/project.json") + end + + context 'JSON' do + let(:restored_project_json) do + project_tree_restorer.restore + #project_json(project_tree_restorer.full_path) + end + + it 'restores models based on JSON' do + expect(restored_project_json).to be true + end + end + end + + def project_json + JSON.parse(IO.read("fixtures/import_export/project.json")) + end +end From 2cc6aaec4910be1c37b4eeab028ffcdb4c8b9b7f Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 9 Mar 2016 18:42:04 +0100 Subject: [PATCH 010/730] WIP (broken) - playing with import stuff --- .../import_export/project_tree_restorer.rb | 24 ++++++++++++------- .../import_export/relation_factory.rb | 10 +++++++- .../project_tree_restorer_spec.rb | 12 +--------- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/app/services/projects/import_export/project_tree_restorer.rb b/app/services/projects/import_export/project_tree_restorer.rb index c6aabc42f4..e30cb25ea6 100644 --- a/app/services/projects/import_export/project_tree_restorer.rb +++ b/app/services/projects/import_export/project_tree_restorer.rb @@ -1,30 +1,36 @@ module Projects module ImportExport class ProjectTreeRestorer - attr_reader :full_path + attr_reader :project - def initialize(path: ) + def initialize(path: , user: user) @path = path + @user = user end + #TODO deal with ID issues. + #TODO refactor this method def restore json = IO.read(@path) tree_hash = ActiveSupport::JSON.decode(json) + relation_hash = {} ImportExport.project_tree.each do |relation| next if tree_hash[relation.to_s].empty? - tree_hash[relation.to_s] = create_relation(relation, tree_hash[relation.to_s]) + relation_hash[relation.to_s] = create_relation(relation, tree_hash[relation.to_s]) end - project = Project.new(tree_hash) - project + project_params = tree_hash.delete_if { |_key, value | value.is_a?(Array)} + @project = ::Projects::CreateService.new(@user, project_params).execute + @project.saved? end private - def create_relation(relation, tree_hash) - Projects::ImportExport::RelationFactory.create( - relation_sym: relation, relation_hash: tree_hash[relation.to_s]) + def create_relation(relation, relation_hash_list) + relation_hash_list.map do |relation_hash| + Projects::ImportExport::RelationFactory.create( + relation_sym: relation, relation_hash: relation_hash) + end end - end end end diff --git a/app/services/projects/import_export/relation_factory.rb b/app/services/projects/import_export/relation_factory.rb index 03fa36428c..9f4bc7b99e 100644 --- a/app/services/projects/import_export/relation_factory.rb +++ b/app/services/projects/import_export/relation_factory.rb @@ -3,8 +3,12 @@ module Projects module RelationFactory extend self - def create(relation_sym: , relation_hash:) + OVERRIDES = { snippets: :project_snippets } + + def create(relation_sym:, relation_hash:) + relation_sym = parse_relation_sym(relation_sym) klass = relation_class(relation_sym) + relation_hash.delete('id') #screw IDs for now klass.new(relation_hash) end @@ -13,6 +17,10 @@ module Projects def relation_class(relation_sym) relation_sym.to_s.classify.constantize end + + def parse_relation_sym(relation_sym) + OVERRIDES[relation_sym] || relation_sym + end end end end diff --git a/spec/services/projects/import_export/project_tree_restorer_spec.rb b/spec/services/projects/import_export/project_tree_restorer_spec.rb index f5b4340805..4c8d182a21 100644 --- a/spec/services/projects/import_export/project_tree_restorer_spec.rb +++ b/spec/services/projects/import_export/project_tree_restorer_spec.rb @@ -4,17 +4,11 @@ describe Projects::ImportExport::ProjectTreeRestorer, services: true do describe :restore do let(:user) { create(:user) } - let(:project_tree_restorer) { Projects::ImportExport::ProjectTreeRestorer.new(path: "fixtures/import_export/project.json") } - - before(:each) do - #allow(project_tree_restorer) - # .to receive(:full_path).and_return("fixtures/import_export/project.json") - end + let(:project_tree_restorer) { Projects::ImportExport::ProjectTreeRestorer.new(path: "fixtures/import_export/project.json", user: user) } context 'JSON' do let(:restored_project_json) do project_tree_restorer.restore - #project_json(project_tree_restorer.full_path) end it 'restores models based on JSON' do @@ -22,8 +16,4 @@ describe Projects::ImportExport::ProjectTreeRestorer, services: true do end end end - - def project_json - JSON.parse(IO.read("fixtures/import_export/project.json")) - end end From f0ce83b1902e78b8adc819db49022ed98d12342e Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 10 Mar 2016 13:04:11 +0100 Subject: [PATCH 011/730] modify model creation to use services when they are available --- .../import_export/project_tree_restorer.rb | 6 +-- .../import_export/relation_factory.rb | 39 ++++++++++++++----- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/app/services/projects/import_export/project_tree_restorer.rb b/app/services/projects/import_export/project_tree_restorer.rb index e30cb25ea6..161081bd75 100644 --- a/app/services/projects/import_export/project_tree_restorer.rb +++ b/app/services/projects/import_export/project_tree_restorer.rb @@ -14,12 +14,12 @@ module Projects json = IO.read(@path) tree_hash = ActiveSupport::JSON.decode(json) relation_hash = {} + project_params = tree_hash.reject { |_key, value | value.is_a?(Array)} + @project = ::Projects::CreateService.new(@user, project_params.except('id')).execute ImportExport.project_tree.each do |relation| next if tree_hash[relation.to_s].empty? relation_hash[relation.to_s] = create_relation(relation, tree_hash[relation.to_s]) end - project_params = tree_hash.delete_if { |_key, value | value.is_a?(Array)} - @project = ::Projects::CreateService.new(@user, project_params).execute @project.saved? end @@ -28,7 +28,7 @@ module Projects def create_relation(relation, relation_hash_list) relation_hash_list.map do |relation_hash| Projects::ImportExport::RelationFactory.create( - relation_sym: relation, relation_hash: relation_hash) + relation_sym: relation, relation_hash: relation_hash, project: @project, user: @user) end end end diff --git a/app/services/projects/import_export/relation_factory.rb b/app/services/projects/import_export/relation_factory.rb index 9f4bc7b99e..f27903ef10 100644 --- a/app/services/projects/import_export/relation_factory.rb +++ b/app/services/projects/import_export/relation_factory.rb @@ -1,24 +1,43 @@ module Projects module ImportExport - module RelationFactory - extend self + class RelationFactory OVERRIDES = { snippets: :project_snippets } - def create(relation_sym:, relation_hash:) - relation_sym = parse_relation_sym(relation_sym) - klass = relation_class(relation_sym) - relation_hash.delete('id') #screw IDs for now - klass.new(relation_hash) + def self.create(*args) + new(*args).create + end + + def initialize(relation_sym:, relation_hash:, project:, user:) + @relation_sym = parsed_relation_sym(relation_sym) + @relation_hash = relation_hash + @project = project + @user = user + end + + def create + @relation_hash.delete('id') + init_service_or_class end private - def relation_class(relation_sym) - relation_sym.to_s.classify.constantize + def init_service_or_class + # Attempt service first + relation_service.new(@project, @user, @relation_hash).execute + rescue NameError + relation_class.new(@relation_hash) end - def parse_relation_sym(relation_sym) + def relation_service + "#{@relation_sym.to_s.classify}::CreateService".constantize + end + + def relation_class + @relation_sym.to_s.classify.constantize + end + + def parsed_relation_sym(relation_sym) OVERRIDES[relation_sym] || relation_sym end end From 40de1b46342ce11668498d725571d253ff99172e Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 9 Mar 2016 18:42:04 +0100 Subject: [PATCH 012/730] revert back services changes (cherry picked from commit 2cc6aae) --- .../import_export/project_tree_restorer.rb | 6 +-- .../import_export/relation_factory.rb | 39 +++++-------------- 2 files changed, 13 insertions(+), 32 deletions(-) diff --git a/app/services/projects/import_export/project_tree_restorer.rb b/app/services/projects/import_export/project_tree_restorer.rb index 161081bd75..e30cb25ea6 100644 --- a/app/services/projects/import_export/project_tree_restorer.rb +++ b/app/services/projects/import_export/project_tree_restorer.rb @@ -14,12 +14,12 @@ module Projects json = IO.read(@path) tree_hash = ActiveSupport::JSON.decode(json) relation_hash = {} - project_params = tree_hash.reject { |_key, value | value.is_a?(Array)} - @project = ::Projects::CreateService.new(@user, project_params.except('id')).execute ImportExport.project_tree.each do |relation| next if tree_hash[relation.to_s].empty? relation_hash[relation.to_s] = create_relation(relation, tree_hash[relation.to_s]) end + project_params = tree_hash.delete_if { |_key, value | value.is_a?(Array)} + @project = ::Projects::CreateService.new(@user, project_params).execute @project.saved? end @@ -28,7 +28,7 @@ module Projects def create_relation(relation, relation_hash_list) relation_hash_list.map do |relation_hash| Projects::ImportExport::RelationFactory.create( - relation_sym: relation, relation_hash: relation_hash, project: @project, user: @user) + relation_sym: relation, relation_hash: relation_hash) end end end diff --git a/app/services/projects/import_export/relation_factory.rb b/app/services/projects/import_export/relation_factory.rb index f27903ef10..9f4bc7b99e 100644 --- a/app/services/projects/import_export/relation_factory.rb +++ b/app/services/projects/import_export/relation_factory.rb @@ -1,43 +1,24 @@ module Projects module ImportExport - class RelationFactory + module RelationFactory + extend self OVERRIDES = { snippets: :project_snippets } - def self.create(*args) - new(*args).create - end - - def initialize(relation_sym:, relation_hash:, project:, user:) - @relation_sym = parsed_relation_sym(relation_sym) - @relation_hash = relation_hash - @project = project - @user = user - end - - def create - @relation_hash.delete('id') - init_service_or_class + def create(relation_sym:, relation_hash:) + relation_sym = parse_relation_sym(relation_sym) + klass = relation_class(relation_sym) + relation_hash.delete('id') #screw IDs for now + klass.new(relation_hash) end private - def init_service_or_class - # Attempt service first - relation_service.new(@project, @user, @relation_hash).execute - rescue NameError - relation_class.new(@relation_hash) + def relation_class(relation_sym) + relation_sym.to_s.classify.constantize end - def relation_service - "#{@relation_sym.to_s.classify}::CreateService".constantize - end - - def relation_class - @relation_sym.to_s.classify.constantize - end - - def parsed_relation_sym(relation_sym) + def parse_relation_sym(relation_sym) OVERRIDES[relation_sym] || relation_sym end end From e90b1e147e69fb05bd10c2a9b4198af7ee386eb1 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 10 Mar 2016 15:35:44 +0100 Subject: [PATCH 013/730] refactored project creation to create the associations as well --- .../projects/import_export/project_factory.rb | 40 +++++++++++++++++++ .../import_export/project_tree_restorer.rb | 15 +++---- 2 files changed, 48 insertions(+), 7 deletions(-) create mode 100644 app/services/projects/import_export/project_factory.rb diff --git a/app/services/projects/import_export/project_factory.rb b/app/services/projects/import_export/project_factory.rb new file mode 100644 index 0000000000..1ca0cfb867 --- /dev/null +++ b/app/services/projects/import_export/project_factory.rb @@ -0,0 +1,40 @@ +module Projects + module ImportExport + module ProjectFactory + extend self + + def create(project_params:, user:) + project = Project.new(project_params.except('id')) + project.creator = user + check_namespace(project_params['namespace_id'], project, user) + end + + def check_namespace(namespace_id, project, user) + if namespace_id + # Find matching namespace and check if it allowed + # for current user if namespace_id passed. + unless allowed_namespace?(user, namespace_id) + project.namespace_id = nil + deny_namespace(project) + end + else + # Set current user namespace if namespace_id is nil + project.namespace_id = user.namespace_id + end + project + end + + private + + def allowed_namespace?(user, namespace_id) + namespace = Namespace.find_by(id: namespace_id) + user.can?(:create_projects, namespace) + end + + def deny_namespace(project) + project.errors.add(:namespace, "is not valid") + end + + end + end +end diff --git a/app/services/projects/import_export/project_tree_restorer.rb b/app/services/projects/import_export/project_tree_restorer.rb index e30cb25ea6..980a376be1 100644 --- a/app/services/projects/import_export/project_tree_restorer.rb +++ b/app/services/projects/import_export/project_tree_restorer.rb @@ -3,7 +3,7 @@ module Projects class ProjectTreeRestorer attr_reader :project - def initialize(path: , user: user) + def initialize(path:, user:) @path = path @user = user end @@ -13,22 +13,23 @@ module Projects def restore json = IO.read(@path) tree_hash = ActiveSupport::JSON.decode(json) + project_params = tree_hash.reject { |_key, value| value.is_a?(Array) } + project = Projects::ImportExport::ProjectFactory.create(project_params: project_params, user: @user) + project.save relation_hash = {} ImportExport.project_tree.each do |relation| next if tree_hash[relation.to_s].empty? - relation_hash[relation.to_s] = create_relation(relation, tree_hash[relation.to_s]) + relation_hash[relation.to_s] = create_relation(relation, tree_hash[relation.to_s], project.id) + project.update_attribute(relation, relation_hash[relation.to_s]) end - project_params = tree_hash.delete_if { |_key, value | value.is_a?(Array)} - @project = ::Projects::CreateService.new(@user, project_params).execute - @project.saved? end private - def create_relation(relation, relation_hash_list) + def create_relation(relation, relation_hash_list, project_id) relation_hash_list.map do |relation_hash| Projects::ImportExport::RelationFactory.create( - relation_sym: relation, relation_hash: relation_hash) + relation_sym: relation, relation_hash: relation_hash.merge(project_id: project_id)) end end end From 2a7a1bcc3aa606a0aab46620c2b262a33c276c7f Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 10 Mar 2016 16:21:17 +0100 Subject: [PATCH 014/730] refactored methods in project tree restorer --- .../import_export/project_tree_restorer.rb | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/app/services/projects/import_export/project_tree_restorer.rb b/app/services/projects/import_export/project_tree_restorer.rb index 980a376be1..3ad42f4145 100644 --- a/app/services/projects/import_export/project_tree_restorer.rb +++ b/app/services/projects/import_export/project_tree_restorer.rb @@ -13,19 +13,23 @@ module Projects def restore json = IO.read(@path) tree_hash = ActiveSupport::JSON.decode(json) - project_params = tree_hash.reject { |_key, value| value.is_a?(Array) } - project = Projects::ImportExport::ProjectFactory.create(project_params: project_params, user: @user) - project.save - relation_hash = {} + project = create_project(tree_hash) ImportExport.project_tree.each do |relation| next if tree_hash[relation.to_s].empty? - relation_hash[relation.to_s] = create_relation(relation, tree_hash[relation.to_s], project.id) - project.update_attribute(relation, relation_hash[relation.to_s]) + relation_hash = create_relation(relation, tree_hash[relation.to_s], project.id) + project.update_attribute(relation, relation_hash) end end private + def create_project(tree_hash) + project_params = tree_hash.reject { |_key, value| value.is_a?(Array) } + project = Projects::ImportExport::ProjectFactory.create(project_params: project_params, user: @user) + project.save + project + end + def create_relation(relation, relation_hash_list, project_id) relation_hash_list.map do |relation_hash| Projects::ImportExport::RelationFactory.create( From a7acfa6614c0645f61a070814e0250b8fbe0cf78 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 10 Mar 2016 16:29:38 +0100 Subject: [PATCH 015/730] add project members to export --- app/services/projects/import_export.rb | 2 +- .../projects/import_export/project_tree_saver_spec.rb | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/services/projects/import_export.rb b/app/services/projects/import_export.rb index 2fc0d5dd7f..601762e00e 100644 --- a/app/services/projects/import_export.rb +++ b/app/services/projects/import_export.rb @@ -7,7 +7,7 @@ module Projects end def project_atts - %i(id name path description issues_enabled wall_enabled merge_requests_enabled wiki_enabled snippets_enabled visibility_level archived) + %i(project_members name path description issues_enabled wall_enabled merge_requests_enabled wiki_enabled snippets_enabled visibility_level archived) end def project_tree diff --git a/spec/services/projects/import_export/project_tree_saver_spec.rb b/spec/services/projects/import_export/project_tree_saver_spec.rb index 1b3568bb7a..839e1b7669 100644 --- a/spec/services/projects/import_export/project_tree_saver_spec.rb +++ b/spec/services/projects/import_export/project_tree_saver_spec.rb @@ -81,6 +81,10 @@ describe Projects::ImportExport::ProjectTreeSaver, services: true do it 'has commit statuses' do expect(saved_project_json['commit_statuses']).not_to be_empty end + + it 'has project members' do + expect(saved_project_json['commit_statuses']).not_to be_empty + end end end From cc8aafeded77cf09580fe3a9f4718dd1b7d33c19 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 10 Mar 2016 18:41:57 +0100 Subject: [PATCH 016/730] typo --- spec/services/projects/import_export/project_tree_saver_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/services/projects/import_export/project_tree_saver_spec.rb b/spec/services/projects/import_export/project_tree_saver_spec.rb index 839e1b7669..383b3e4ce8 100644 --- a/spec/services/projects/import_export/project_tree_saver_spec.rb +++ b/spec/services/projects/import_export/project_tree_saver_spec.rb @@ -83,7 +83,7 @@ describe Projects::ImportExport::ProjectTreeSaver, services: true do end it 'has project members' do - expect(saved_project_json['commit_statuses']).not_to be_empty + expect(saved_project_json['project_members']).not_to be_empty end end end From febff153cc850ef662301dd2a6b19df91186477f Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 10 Mar 2016 18:43:57 +0100 Subject: [PATCH 017/730] started mapping members --- .../projects/import_export/members_mapper.rb | 18 +++++++++ .../projects/import_export/project_factory.rb | 2 +- .../import_export/project_tree_restorer.rb | 38 ++++++++++++------- fixtures/import_export/project.json | 2 +- 4 files changed, 44 insertions(+), 16 deletions(-) create mode 100644 app/services/projects/import_export/members_mapper.rb diff --git a/app/services/projects/import_export/members_mapper.rb b/app/services/projects/import_export/members_mapper.rb new file mode 100644 index 0000000000..ebb50c30b8 --- /dev/null +++ b/app/services/projects/import_export/members_mapper.rb @@ -0,0 +1,18 @@ +module Projects + module ImportExport + class MembersMapper + + def self.map(*args) + new(*args).map + end + + def initialize(exported_members:) + @exported_members = exported_members + end + + def map + #TODO + end + end + end +end diff --git a/app/services/projects/import_export/project_factory.rb b/app/services/projects/import_export/project_factory.rb index 1ca0cfb867..2df38bff1f 100644 --- a/app/services/projects/import_export/project_factory.rb +++ b/app/services/projects/import_export/project_factory.rb @@ -3,7 +3,7 @@ module Projects module ProjectFactory extend self - def create(project_params:, user:) + def create(project_params:, user:, members:) project = Project.new(project_params.except('id')) project.creator = user check_namespace(project_params['namespace_id'], project, user) diff --git a/app/services/projects/import_export/project_tree_restorer.rb b/app/services/projects/import_export/project_tree_restorer.rb index 3ad42f4145..8785c80e24 100644 --- a/app/services/projects/import_export/project_tree_restorer.rb +++ b/app/services/projects/import_export/project_tree_restorer.rb @@ -8,32 +8,42 @@ module Projects @user = user end - #TODO deal with ID issues. - #TODO refactor this method def restore json = IO.read(@path) - tree_hash = ActiveSupport::JSON.decode(json) - project = create_project(tree_hash) - ImportExport.project_tree.each do |relation| - next if tree_hash[relation.to_s].empty? - relation_hash = create_relation(relation, tree_hash[relation.to_s], project.id) - project.update_attribute(relation, relation_hash) - end + @tree_hash = ActiveSupport::JSON.decode(json) + create_relations end private - def create_project(tree_hash) - project_params = tree_hash.reject { |_key, value| value.is_a?(Array) } - project = Projects::ImportExport::ProjectFactory.create(project_params: project_params, user: @user) + def members + @members ||= Projects::ImportExport::MembersMapper.map(exported_members: @tree_hash.delete('project_members')) + end + + def create_relations + (ImportExport.project_tree - [:project_members]).each do |relation| + next if @tree_hash[relation.to_s].empty? + relation_hash = create_relation(relation, @tree_hash[relation.to_s]) + project.update_attribute(relation, relation_hash) + end + end + + def project + @project ||= create_project + end + + def create_project + project_params = @tree_hash.reject { |_key, value| value.is_a?(Array) } + project = Projects::ImportExport::ProjectFactory.create( + project_params: project_params, user: @user, members: members) project.save project end - def create_relation(relation, relation_hash_list, project_id) + def create_relation(relation, relation_hash_list) relation_hash_list.map do |relation_hash| Projects::ImportExport::RelationFactory.create( - relation_sym: relation, relation_hash: relation_hash.merge(project_id: project_id)) + relation_sym: relation, relation_hash: relation_hash.merge(project_id: project.id), members: members) end end end diff --git a/fixtures/import_export/project.json b/fixtures/import_export/project.json index 8ea17e4d99..fe8bb17e6c 100644 --- a/fixtures/import_export/project.json +++ b/fixtures/import_export/project.json @@ -1 +1 @@ -{"id":14,"name":"searchable_project","path":"gitlabhq","description":null,"issues_enabled":true,"wall_enabled":false,"merge_requests_enabled":true,"wiki_enabled":true,"snippets_enabled":true,"visibility_level":20,"archived":false,"issues":[{"id":2,"title":"Eos ut accusamus provident quis qui.","assignee_id":19,"author_id":20,"project_id":14,"created_at":"2016-03-09T11:41:00.754Z","updated_at":"2016-03-09T11:41:05.728Z","position":0,"branch_name":null,"description":null,"milestone_id":null,"state":"opened","iid":1,"updated_by_id":null}],"merge_requests":[{"id":2,"target_branch":"feature","source_branch":"master","source_project_id":9,"author_id":23,"assignee_id":null,"title":"Eos dolores molestias eum magni ut consequatur deleniti distinctio.","created_at":"2016-03-09T11:41:01.820Z","updated_at":"2016-03-09T11:41:01.820Z","milestone_id":null,"state":"opened","merge_status":"can_be_merged","target_project_id":14,"iid":1,"description":null,"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}],"labels":[{"id":2,"title":"Bug","color":"#990000","project_id":14,"created_at":"2016-03-09T11:41:02.959Z","updated_at":"2016-03-09T11:41:05.750Z","template":false,"description":null}],"milestones":[{"id":2,"title":"Milestone v1.2","project_id":14,"description":null,"due_date":null,"created_at":"2016-03-09T11:41:05.846Z","updated_at":"2016-03-09T11:41:05.846Z","state":"active","iid":1}],"snippets":[{"id":2,"title":"Unde adipisci molestiae modi quisquam qui itaque ut aut.","content":"Temporibus qui nisi ipsam maiores voluptatum.","author_id":30,"project_id":14,"created_at":"2016-03-09T11:41:03.720Z","updated_at":"2016-03-09T11:41:05.763Z","file_name":"sarah","expires_at":null,"visibility_level":0}],"releases":[{"id":2,"tag":"v1.1.0","description":"Awesome release","project_id":14,"created_at":"2016-03-09T11:41:04.342Z","updated_at":"2016-03-09T11:41:05.776Z"}],"events":[{"id":2,"target_type":null,"target_id":null,"title":null,"data":null,"project_id":14,"created_at":"2016-03-09T11:41:05.998Z","updated_at":"2016-03-09T11:41:05.998Z","action":8,"author_id":19}],"commit_statuses":[{"id":2,"project_id":null,"status":"success","finished_at":"2016-01-26T07:23:42.000Z","trace":null,"created_at":"2016-03-09T11:41:05.011Z","updated_at":"2016-03-09T11:41:05.801Z","started_at":"2016-01-26T07:21:42.000Z","runner_id":null,"coverage":null,"commit_id":2,"commands":null,"job_id":null,"name":"default","deploy":false,"options":null,"allow_failure":false,"stage":null,"trigger_request_id":null,"stage_idx":null,"tag":null,"ref":null,"user_id":null,"target_url":null,"description":"commit status","artifacts_file":null,"gl_project_id":14,"artifacts_metadata":null,"erased_by_id":null,"erased_at":null}]} \ No newline at end of file +{"name":"searchable_project","path":"gitlabhq","description":null,"issues_enabled":true,"wall_enabled":false,"merge_requests_enabled":true,"wiki_enabled":true,"snippets_enabled":true,"visibility_level":20,"archived":false,"issues":[{"id":2,"title":"Culpa dolores et nostrum magni quo.","assignee_id":19,"author_id":20,"project_id":14,"created_at":"2016-03-10T15:54:30.960Z","updated_at":"2016-03-10T15:54:36.624Z","position":0,"branch_name":null,"description":null,"milestone_id":null,"state":"opened","iid":1,"updated_by_id":null}],"merge_requests":[{"id":2,"target_branch":"feature","source_branch":"master","source_project_id":9,"author_id":23,"assignee_id":null,"title":"Distinctio voluptas qui suscipit asperiores.","created_at":"2016-03-10T15:54:31.921Z","updated_at":"2016-03-10T15:54:31.921Z","milestone_id":null,"state":"opened","merge_status":"can_be_merged","target_project_id":14,"iid":1,"description":null,"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}],"labels":[{"id":2,"title":"Bug","color":"#990000","project_id":14,"created_at":"2016-03-10T15:54:33.128Z","updated_at":"2016-03-10T15:54:36.645Z","template":false,"description":null}],"milestones":[{"id":2,"title":"Milestone v1.2","project_id":14,"description":null,"due_date":null,"created_at":"2016-03-10T15:54:36.756Z","updated_at":"2016-03-10T15:54:36.756Z","state":"active","iid":1}],"snippets":[{"id":2,"title":"In voluptatibus possimus fugiat qui.","content":"Qui exercitationem culpa in dolore ab.","author_id":30,"project_id":14,"created_at":"2016-03-10T15:54:34.253Z","updated_at":"2016-03-10T15:54:36.658Z","file_name":"patrick","expires_at":null,"visibility_level":0}],"releases":[{"id":2,"tag":"v1.1.0","description":"Awesome release","project_id":14,"created_at":"2016-03-10T15:54:35.211Z","updated_at":"2016-03-10T15:54:36.671Z"}],"events":[{"id":2,"target_type":null,"target_id":null,"title":null,"data":null,"project_id":14,"created_at":"2016-03-10T15:54:36.906Z","updated_at":"2016-03-10T15:54:36.906Z","action":8,"author_id":19}],"commit_statuses":[{"id":2,"project_id":null,"status":"success","finished_at":"2016-01-26T07:23:42.000Z","trace":null,"created_at":"2016-03-10T15:54:35.937Z","updated_at":"2016-03-10T15:54:36.699Z","started_at":"2016-01-26T07:21:42.000Z","runner_id":null,"coverage":null,"commit_id":2,"commands":null,"job_id":null,"name":"default","deploy":false,"options":null,"allow_failure":false,"stage":null,"trigger_request_id":null,"stage_idx":null,"tag":null,"ref":null,"user_id":null,"target_url":null,"description":"commit status","artifacts_file":null,"gl_project_id":14,"artifacts_metadata":null,"erased_by_id":null,"erased_at":null}]} \ No newline at end of file From 2fd30231867226d8c921ec74f388e6f30769e2a8 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 11 Mar 2016 09:46:00 +0100 Subject: [PATCH 018/730] fix project members export --- app/services/projects/import_export.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/services/projects/import_export.rb b/app/services/projects/import_export.rb index 601762e00e..99336487eb 100644 --- a/app/services/projects/import_export.rb +++ b/app/services/projects/import_export.rb @@ -7,11 +7,11 @@ module Projects end def project_atts - %i(project_members name path description issues_enabled wall_enabled merge_requests_enabled wiki_enabled snippets_enabled visibility_level archived) + %i(name path description issues_enabled wall_enabled merge_requests_enabled wiki_enabled snippets_enabled visibility_level archived) end def project_tree - %i(issues merge_requests labels milestones snippets releases events commit_statuses) + %i(project_members issues merge_requests labels milestones snippets releases events commit_statuses) end private From b7149266eac2277108757d34cce05eb372d562ab Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 11 Mar 2016 10:25:34 +0100 Subject: [PATCH 019/730] WIP project members - json not quite right yet --- app/services/projects/import_export/project_factory.rb | 2 +- .../projects/import_export/project_tree_restorer.rb | 6 +++--- app/services/projects/import_export/relation_factory.rb | 2 +- fixtures/import_export/project.json | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/services/projects/import_export/project_factory.rb b/app/services/projects/import_export/project_factory.rb index 2df38bff1f..825907df53 100644 --- a/app/services/projects/import_export/project_factory.rb +++ b/app/services/projects/import_export/project_factory.rb @@ -3,7 +3,7 @@ module Projects module ProjectFactory extend self - def create(project_params:, user:, members:) + def create(project_params:, user:, members_map:) project = Project.new(project_params.except('id')) project.creator = user check_namespace(project_params['namespace_id'], project, user) diff --git a/app/services/projects/import_export/project_tree_restorer.rb b/app/services/projects/import_export/project_tree_restorer.rb index 8785c80e24..64ac3a534e 100644 --- a/app/services/projects/import_export/project_tree_restorer.rb +++ b/app/services/projects/import_export/project_tree_restorer.rb @@ -16,7 +16,7 @@ module Projects private - def members + def members_map @members ||= Projects::ImportExport::MembersMapper.map(exported_members: @tree_hash.delete('project_members')) end @@ -35,7 +35,7 @@ module Projects def create_project project_params = @tree_hash.reject { |_key, value| value.is_a?(Array) } project = Projects::ImportExport::ProjectFactory.create( - project_params: project_params, user: @user, members: members) + project_params: project_params, user: @user, members_map: members_map) project.save project end @@ -43,7 +43,7 @@ module Projects def create_relation(relation, relation_hash_list) relation_hash_list.map do |relation_hash| Projects::ImportExport::RelationFactory.create( - relation_sym: relation, relation_hash: relation_hash.merge(project_id: project.id), members: members) + relation_sym: relation, relation_hash: relation_hash.merge(project_id: project.id), members_map: members_map) end end end diff --git a/app/services/projects/import_export/relation_factory.rb b/app/services/projects/import_export/relation_factory.rb index 9f4bc7b99e..624453a6ad 100644 --- a/app/services/projects/import_export/relation_factory.rb +++ b/app/services/projects/import_export/relation_factory.rb @@ -5,7 +5,7 @@ module Projects OVERRIDES = { snippets: :project_snippets } - def create(relation_sym:, relation_hash:) + def create(relation_sym:, relation_hash:, members_map:) relation_sym = parse_relation_sym(relation_sym) klass = relation_class(relation_sym) relation_hash.delete('id') #screw IDs for now diff --git a/fixtures/import_export/project.json b/fixtures/import_export/project.json index fe8bb17e6c..5eaaf1cd8a 100644 --- a/fixtures/import_export/project.json +++ b/fixtures/import_export/project.json @@ -1 +1 @@ -{"name":"searchable_project","path":"gitlabhq","description":null,"issues_enabled":true,"wall_enabled":false,"merge_requests_enabled":true,"wiki_enabled":true,"snippets_enabled":true,"visibility_level":20,"archived":false,"issues":[{"id":2,"title":"Culpa dolores et nostrum magni quo.","assignee_id":19,"author_id":20,"project_id":14,"created_at":"2016-03-10T15:54:30.960Z","updated_at":"2016-03-10T15:54:36.624Z","position":0,"branch_name":null,"description":null,"milestone_id":null,"state":"opened","iid":1,"updated_by_id":null}],"merge_requests":[{"id":2,"target_branch":"feature","source_branch":"master","source_project_id":9,"author_id":23,"assignee_id":null,"title":"Distinctio voluptas qui suscipit asperiores.","created_at":"2016-03-10T15:54:31.921Z","updated_at":"2016-03-10T15:54:31.921Z","milestone_id":null,"state":"opened","merge_status":"can_be_merged","target_project_id":14,"iid":1,"description":null,"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}],"labels":[{"id":2,"title":"Bug","color":"#990000","project_id":14,"created_at":"2016-03-10T15:54:33.128Z","updated_at":"2016-03-10T15:54:36.645Z","template":false,"description":null}],"milestones":[{"id":2,"title":"Milestone v1.2","project_id":14,"description":null,"due_date":null,"created_at":"2016-03-10T15:54:36.756Z","updated_at":"2016-03-10T15:54:36.756Z","state":"active","iid":1}],"snippets":[{"id":2,"title":"In voluptatibus possimus fugiat qui.","content":"Qui exercitationem culpa in dolore ab.","author_id":30,"project_id":14,"created_at":"2016-03-10T15:54:34.253Z","updated_at":"2016-03-10T15:54:36.658Z","file_name":"patrick","expires_at":null,"visibility_level":0}],"releases":[{"id":2,"tag":"v1.1.0","description":"Awesome release","project_id":14,"created_at":"2016-03-10T15:54:35.211Z","updated_at":"2016-03-10T15:54:36.671Z"}],"events":[{"id":2,"target_type":null,"target_id":null,"title":null,"data":null,"project_id":14,"created_at":"2016-03-10T15:54:36.906Z","updated_at":"2016-03-10T15:54:36.906Z","action":8,"author_id":19}],"commit_statuses":[{"id":2,"project_id":null,"status":"success","finished_at":"2016-01-26T07:23:42.000Z","trace":null,"created_at":"2016-03-10T15:54:35.937Z","updated_at":"2016-03-10T15:54:36.699Z","started_at":"2016-01-26T07:21:42.000Z","runner_id":null,"coverage":null,"commit_id":2,"commands":null,"job_id":null,"name":"default","deploy":false,"options":null,"allow_failure":false,"stage":null,"trigger_request_id":null,"stage_idx":null,"tag":null,"ref":null,"user_id":null,"target_url":null,"description":"commit status","artifacts_file":null,"gl_project_id":14,"artifacts_metadata":null,"erased_by_id":null,"erased_at":null}]} \ No newline at end of file +{"name":"searchable_project","path":"gitlabhq","description":null,"issues_enabled":true,"wall_enabled":false,"merge_requests_enabled":true,"wiki_enabled":true,"snippets_enabled":true,"visibility_level":20,"archived":false,"project_members":[{"id":11,"access_level":40,"source_id":77,"source_type":"Project","user_id":181,"notification_level":3,"created_at":"2016-03-11T09:02:34.007Z","updated_at":"2016-03-11T09:02:34.007Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null}],"issues":[{"id":11,"title":"Voluptatibus eius eaque qui officiis fugit.","assignee_id":181,"author_id":182,"project_id":77,"created_at":"2016-03-11T09:02:27.677Z","updated_at":"2016-03-11T09:02:33.728Z","position":0,"branch_name":null,"description":null,"milestone_id":null,"state":"opened","iid":1,"updated_by_id":null}],"merge_requests":[{"id":11,"target_branch":"feature","source_branch":"master","source_project_id":72,"author_id":185,"assignee_id":null,"title":"Dolorum similique voluptate odio id unde a maxime officiis.","created_at":"2016-03-11T09:02:28.616Z","updated_at":"2016-03-11T09:02:28.616Z","milestone_id":null,"state":"opened","merge_status":"can_be_merged","target_project_id":77,"iid":1,"description":null,"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}],"labels":[{"id":11,"title":"Bug","color":"#990000","project_id":77,"created_at":"2016-03-11T09:02:29.974Z","updated_at":"2016-03-11T09:02:33.752Z","template":false,"description":null}],"milestones":[{"id":11,"title":"Milestone v1.2","project_id":77,"description":null,"due_date":null,"created_at":"2016-03-11T09:02:33.882Z","updated_at":"2016-03-11T09:02:33.882Z","state":"active","iid":1}],"snippets":[{"id":11,"title":"Voluptas et expedita autem quia totam voluptate culpa quis.","content":"Veritatis esse fugiat sint eos.","author_id":192,"project_id":77,"created_at":"2016-03-11T09:02:31.022Z","updated_at":"2016-03-11T09:02:33.768Z","file_name":"dexter.hessel","expires_at":null,"visibility_level":0}],"releases":[{"id":11,"tag":"v1.1.0","description":"Awesome release","project_id":77,"created_at":"2016-03-11T09:02:32.099Z","updated_at":"2016-03-11T09:02:33.787Z"}],"events":[{"id":11,"target_type":null,"target_id":null,"title":null,"data":null,"project_id":77,"created_at":"2016-03-11T09:02:34.069Z","updated_at":"2016-03-11T09:02:34.069Z","action":8,"author_id":181}],"commit_statuses":[{"id":11,"project_id":null,"status":"success","finished_at":"2016-01-26T07:23:42.000Z","trace":null,"created_at":"2016-03-11T09:02:32.916Z","updated_at":"2016-03-11T09:02:33.825Z","started_at":"2016-01-26T07:21:42.000Z","runner_id":null,"coverage":null,"commit_id":11,"commands":null,"job_id":null,"name":"default","deploy":false,"options":null,"allow_failure":false,"stage":null,"trigger_request_id":null,"stage_idx":null,"tag":null,"ref":null,"user_id":null,"target_url":null,"description":"commit status","artifacts_file":null,"gl_project_id":77,"artifacts_metadata":null,"erased_by_id":null,"erased_at":null}]} \ No newline at end of file From eb2b9e3efc335b07ade0a44b22af6214089c528b Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 11 Mar 2016 11:23:59 +0100 Subject: [PATCH 020/730] fix project members json to include user --- app/services/projects/import_export.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/services/projects/import_export.rb b/app/services/projects/import_export.rb index 99336487eb..e281925fe9 100644 --- a/app/services/projects/import_export.rb +++ b/app/services/projects/import_export.rb @@ -11,11 +11,15 @@ module Projects end def project_tree - %i(project_members issues merge_requests labels milestones snippets releases events commit_statuses) + %i(issues merge_requests labels milestones snippets releases events commit_statuses) + members end private + def members + [{ project_members: { include: [user: { only: [:email, :username] }] } }] + end + def storage_path File.join(Settings.shared['path'], 'tmp/project_exports') end From cbae4038acc2ac1d4644aa719d11ecbf368ce06c Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 11 Mar 2016 11:37:42 +0100 Subject: [PATCH 021/730] updated test json --- fixtures/import_export/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fixtures/import_export/project.json b/fixtures/import_export/project.json index 5eaaf1cd8a..38c999e8fb 100644 --- a/fixtures/import_export/project.json +++ b/fixtures/import_export/project.json @@ -1 +1 @@ -{"name":"searchable_project","path":"gitlabhq","description":null,"issues_enabled":true,"wall_enabled":false,"merge_requests_enabled":true,"wiki_enabled":true,"snippets_enabled":true,"visibility_level":20,"archived":false,"project_members":[{"id":11,"access_level":40,"source_id":77,"source_type":"Project","user_id":181,"notification_level":3,"created_at":"2016-03-11T09:02:34.007Z","updated_at":"2016-03-11T09:02:34.007Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null}],"issues":[{"id":11,"title":"Voluptatibus eius eaque qui officiis fugit.","assignee_id":181,"author_id":182,"project_id":77,"created_at":"2016-03-11T09:02:27.677Z","updated_at":"2016-03-11T09:02:33.728Z","position":0,"branch_name":null,"description":null,"milestone_id":null,"state":"opened","iid":1,"updated_by_id":null}],"merge_requests":[{"id":11,"target_branch":"feature","source_branch":"master","source_project_id":72,"author_id":185,"assignee_id":null,"title":"Dolorum similique voluptate odio id unde a maxime officiis.","created_at":"2016-03-11T09:02:28.616Z","updated_at":"2016-03-11T09:02:28.616Z","milestone_id":null,"state":"opened","merge_status":"can_be_merged","target_project_id":77,"iid":1,"description":null,"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}],"labels":[{"id":11,"title":"Bug","color":"#990000","project_id":77,"created_at":"2016-03-11T09:02:29.974Z","updated_at":"2016-03-11T09:02:33.752Z","template":false,"description":null}],"milestones":[{"id":11,"title":"Milestone v1.2","project_id":77,"description":null,"due_date":null,"created_at":"2016-03-11T09:02:33.882Z","updated_at":"2016-03-11T09:02:33.882Z","state":"active","iid":1}],"snippets":[{"id":11,"title":"Voluptas et expedita autem quia totam voluptate culpa quis.","content":"Veritatis esse fugiat sint eos.","author_id":192,"project_id":77,"created_at":"2016-03-11T09:02:31.022Z","updated_at":"2016-03-11T09:02:33.768Z","file_name":"dexter.hessel","expires_at":null,"visibility_level":0}],"releases":[{"id":11,"tag":"v1.1.0","description":"Awesome release","project_id":77,"created_at":"2016-03-11T09:02:32.099Z","updated_at":"2016-03-11T09:02:33.787Z"}],"events":[{"id":11,"target_type":null,"target_id":null,"title":null,"data":null,"project_id":77,"created_at":"2016-03-11T09:02:34.069Z","updated_at":"2016-03-11T09:02:34.069Z","action":8,"author_id":181}],"commit_statuses":[{"id":11,"project_id":null,"status":"success","finished_at":"2016-01-26T07:23:42.000Z","trace":null,"created_at":"2016-03-11T09:02:32.916Z","updated_at":"2016-03-11T09:02:33.825Z","started_at":"2016-01-26T07:21:42.000Z","runner_id":null,"coverage":null,"commit_id":11,"commands":null,"job_id":null,"name":"default","deploy":false,"options":null,"allow_failure":false,"stage":null,"trigger_request_id":null,"stage_idx":null,"tag":null,"ref":null,"user_id":null,"target_url":null,"description":"commit status","artifacts_file":null,"gl_project_id":77,"artifacts_metadata":null,"erased_by_id":null,"erased_at":null}]} \ No newline at end of file +{"name":"searchable_project","path":"gitlabhq","description":null,"issues_enabled":true,"wall_enabled":false,"merge_requests_enabled":true,"wiki_enabled":true,"snippets_enabled":true,"visibility_level":20,"archived":false,"issues":[{"id":2,"title":"Voluptatem quia repudiandae id rem ducimus.","assignee_id":19,"author_id":20,"project_id":14,"created_at":"2016-03-11T10:21:37.525Z","updated_at":"2016-03-11T10:21:44.516Z","position":0,"branch_name":null,"description":null,"milestone_id":null,"state":"opened","iid":1,"updated_by_id":null}],"merge_requests":[{"id":2,"target_branch":"feature","source_branch":"master","source_project_id":9,"author_id":23,"assignee_id":null,"title":"Enim dolor veritatis suscipit sed laboriosam consequatur doloremque.","created_at":"2016-03-11T10:21:38.628Z","updated_at":"2016-03-11T10:21:38.628Z","milestone_id":null,"state":"opened","merge_status":"can_be_merged","target_project_id":14,"iid":1,"description":null,"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}],"labels":[{"id":2,"title":"Bug","color":"#990000","project_id":14,"created_at":"2016-03-11T10:21:39.964Z","updated_at":"2016-03-11T10:21:44.539Z","template":false,"description":null}],"milestones":[{"id":2,"title":"Milestone v1.2","project_id":14,"description":null,"due_date":null,"created_at":"2016-03-11T10:21:44.688Z","updated_at":"2016-03-11T10:21:44.688Z","state":"active","iid":1}],"snippets":[{"id":2,"title":"Dolorem perspiciatis unde aut similique aperiam totam qui iste.","content":"Sed similique praesentium tempora et ad dolor quis ut.","author_id":30,"project_id":14,"created_at":"2016-03-11T10:21:41.034Z","updated_at":"2016-03-11T10:21:44.557Z","file_name":"dee","expires_at":null,"visibility_level":0}],"releases":[{"id":2,"tag":"v1.1.0","description":"Awesome release","project_id":14,"created_at":"2016-03-11T10:21:42.531Z","updated_at":"2016-03-11T10:21:44.576Z"}],"events":[{"id":2,"target_type":null,"target_id":null,"title":null,"data":null,"project_id":14,"created_at":"2016-03-11T10:21:44.892Z","updated_at":"2016-03-11T10:21:44.892Z","action":8,"author_id":19}],"commit_statuses":[{"id":2,"project_id":null,"status":"success","finished_at":"2016-01-26T07:23:42.000Z","trace":null,"created_at":"2016-03-11T10:21:43.493Z","updated_at":"2016-03-11T10:21:44.620Z","started_at":"2016-01-26T07:21:42.000Z","runner_id":null,"coverage":null,"commit_id":2,"commands":null,"job_id":null,"name":"default","deploy":false,"options":null,"allow_failure":false,"stage":null,"trigger_request_id":null,"stage_idx":null,"tag":null,"ref":null,"user_id":null,"target_url":null,"description":"commit status","artifacts_file":null,"gl_project_id":14,"artifacts_metadata":null,"erased_by_id":null,"erased_at":null}],"project_members":[{"id":2,"access_level":40,"source_id":14,"source_type":"Project","user_id":19,"notification_level":3,"created_at":"2016-03-11T10:21:44.822Z","updated_at":"2016-03-11T10:21:44.822Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"user":{"email":"claudie.lemke@prohaskamarquardt.co.uk","username":"hiram_conroy19"}}]} \ No newline at end of file From 7b855b75f2699f3189610886d8b2acf7912bf7ef Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 11 Mar 2016 12:55:50 +0100 Subject: [PATCH 022/730] project members import stuff --- .../projects/import_export/members_mapper.rb | 47 ++++++++++++++++++- .../projects/import_export/project_factory.rb | 2 +- .../import_export/project_tree_restorer.rb | 5 +- .../import_export/members_mapper_spec.rb | 42 +++++++++++++++++ 4 files changed, 91 insertions(+), 5 deletions(-) create mode 100644 spec/services/projects/import_export/members_mapper_spec.rb diff --git a/app/services/projects/import_export/members_mapper.rb b/app/services/projects/import_export/members_mapper.rb index ebb50c30b8..56abc131b1 100644 --- a/app/services/projects/import_export/members_mapper.rb +++ b/app/services/projects/import_export/members_mapper.rb @@ -6,12 +6,55 @@ module Projects new(*args).map end - def initialize(exported_members:) + def initialize(exported_members:, user:, project_id:) @exported_members = exported_members + @user = user + @project_id = project_id end def map - #TODO + @project_member_map ||= project_member_map + end + + private + + def project_member_map + @project_member_map = Hash.new(default_project_member) + @exported_members.each do |member| + existing_user = User.where(find_project_user_query(member)).first + assign_member(existing_user, member) if existing_user + end + @project_member_map + end + + def assign_member(existing_user, member) + member['user'] = existing_user + project_member = ProjectMember.new(member_hash(member)) + @project_member_map[member['id']] = project_member if project_member.save + end + + def member_hash(member) + member.except('id').merge(source_id: @project_id) + end + + def default_project_member + @default_project_member ||= + begin + default_member = ProjectMember.new(default_project_member_hash) + default_member if default_member.save + end + end + + def default_project_member_hash + { user: @user, access_level: ProjectMember::MASTER, source_id: @project_id } + end + + def find_project_user_query(member) + user_arel[:username].eq(member['user']['username']).or(user_arel[:email].eq(member['user']['email'])) + end + + def user_arel + @user_arel ||= User.arel_table end end end diff --git a/app/services/projects/import_export/project_factory.rb b/app/services/projects/import_export/project_factory.rb index 825907df53..1ca0cfb867 100644 --- a/app/services/projects/import_export/project_factory.rb +++ b/app/services/projects/import_export/project_factory.rb @@ -3,7 +3,7 @@ module Projects module ProjectFactory extend self - def create(project_params:, user:, members_map:) + def create(project_params:, user:) project = Project.new(project_params.except('id')) project.creator = user check_namespace(project_params['namespace_id'], project, user) diff --git a/app/services/projects/import_export/project_tree_restorer.rb b/app/services/projects/import_export/project_tree_restorer.rb index 64ac3a534e..87b78197cd 100644 --- a/app/services/projects/import_export/project_tree_restorer.rb +++ b/app/services/projects/import_export/project_tree_restorer.rb @@ -17,7 +17,8 @@ module Projects private def members_map - @members ||= Projects::ImportExport::MembersMapper.map(exported_members: @tree_hash.delete('project_members')) + @members ||= Projects::ImportExport::MembersMapper.map( + exported_members: @tree_hash.delete('project_members'), user: @user, project_id: project.id) end def create_relations @@ -35,7 +36,7 @@ module Projects def create_project project_params = @tree_hash.reject { |_key, value| value.is_a?(Array) } project = Projects::ImportExport::ProjectFactory.create( - project_params: project_params, user: @user, members_map: members_map) + project_params: project_params, user: @user) project.save project end diff --git a/spec/services/projects/import_export/members_mapper_spec.rb b/spec/services/projects/import_export/members_mapper_spec.rb new file mode 100644 index 0000000000..431626d5e7 --- /dev/null +++ b/spec/services/projects/import_export/members_mapper_spec.rb @@ -0,0 +1,42 @@ +require 'spec_helper' + +describe Projects::ImportExport::MembersMapper, services: true do + describe :map do + + let(:user) { create(:user) } + let(:project) { create(:project, :public, name: 'searchable_project') } + let(:user2) { create(:user) } + let(:exported_members) { [ + { + "id" => 2, + "access_level" => 40, + "source_id" => 14, + "source_type" => "Project", + "user_id" => 19, + "notification_level" => 3, + "created_at" => "2016-03-11T10:21:44.822Z", + "updated_at" => "2016-03-11T10:21:44.822Z", + "created_by_id" => nil, + "invite_email" => nil, + "invite_token" => nil, + "invite_accepted_at" => nil, + "user" => { "email" => user2.email, "username" => user2.username } }] } + + let(:members_mapper) do + Projects::ImportExport::MembersMapper.new( + exported_members: exported_members, user: user, project_id: project.id) + end + + it 'maps a project member' do + expect(project_member_map_id(user2.id)).to eq(user2.id) + end + + it 'defaults to importer project member if it does not exist' do + expect(project_member_map_id(-1)).to eq(user.id) + end + end + + def project_member_map_id(id) + members_mapper.map[id]['id'] + end +end From 18d3b38e464e3b8c759401b8a8fe643313931152 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 11 Mar 2016 15:14:30 +0100 Subject: [PATCH 023/730] project members: fixed a few issues. Specs now passing --- .../projects/import_export/members_mapper.rb | 3 +- .../import_export/members_mapper_spec.rb | 44 +++++++++++-------- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/app/services/projects/import_export/members_mapper.rb b/app/services/projects/import_export/members_mapper.rb index 56abc131b1..634683da5c 100644 --- a/app/services/projects/import_export/members_mapper.rb +++ b/app/services/projects/import_export/members_mapper.rb @@ -30,13 +30,14 @@ module Projects def assign_member(existing_user, member) member['user'] = existing_user project_member = ProjectMember.new(member_hash(member)) - @project_member_map[member['id']] = project_member if project_member.save + @project_member_map[existing_user.id] = project_member if project_member.save end def member_hash(member) member.except('id').merge(source_id: @project_id) end + #TODO: If default, then we need to leave a comment 'Comment by ' on comments def default_project_member @default_project_member ||= begin diff --git a/spec/services/projects/import_export/members_mapper_spec.rb b/spec/services/projects/import_export/members_mapper_spec.rb index 431626d5e7..dc6ccb5012 100644 --- a/spec/services/projects/import_export/members_mapper_spec.rb +++ b/spec/services/projects/import_export/members_mapper_spec.rb @@ -6,21 +6,27 @@ describe Projects::ImportExport::MembersMapper, services: true do let(:user) { create(:user) } let(:project) { create(:project, :public, name: 'searchable_project') } let(:user2) { create(:user) } - let(:exported_members) { [ - { - "id" => 2, - "access_level" => 40, - "source_id" => 14, - "source_type" => "Project", - "user_id" => 19, - "notification_level" => 3, - "created_at" => "2016-03-11T10:21:44.822Z", - "updated_at" => "2016-03-11T10:21:44.822Z", - "created_by_id" => nil, - "invite_email" => nil, - "invite_token" => nil, - "invite_accepted_at" => nil, - "user" => { "email" => user2.email, "username" => user2.username } }] } + let(:exported_members) do + [{ + "id" => 2, + "access_level" => 40, + "source_id" => 14, + "source_type" => "Project", + "user_id" => 19, + "notification_level" => 3, + "created_at" => "2016-03-11T10:21:44.822Z", + "updated_at" => "2016-03-11T10:21:44.822Z", + "created_by_id" => nil, + "invite_email" => nil, + "invite_token" => nil, + "invite_accepted_at" => nil, + "user" => + { + "email" => user2.email, + "username" => user2.username + } + }] + end let(:members_mapper) do Projects::ImportExport::MembersMapper.new( @@ -28,15 +34,15 @@ describe Projects::ImportExport::MembersMapper, services: true do end it 'maps a project member' do - expect(project_member_map_id(user2.id)).to eq(user2.id) + expect(project_member_user_id(user2.id)).to eq(user2.id) end it 'defaults to importer project member if it does not exist' do - expect(project_member_map_id(-1)).to eq(user.id) + expect(project_member_user_id(-1)).to eq(user.id) end end - def project_member_map_id(id) - members_mapper.map[id]['id'] + def project_member_user_id(id) + members_mapper.map[id].user.id end end From 66d3f98582e2a9fbdff93402de1075b4f7f01eb3 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 11 Mar 2016 17:06:12 +0100 Subject: [PATCH 024/730] add id to project member user json --- app/services/projects/import_export.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/projects/import_export.rb b/app/services/projects/import_export.rb index e281925fe9..b0c0891edb 100644 --- a/app/services/projects/import_export.rb +++ b/app/services/projects/import_export.rb @@ -17,7 +17,7 @@ module Projects private def members - [{ project_members: { include: [user: { only: [:email, :username] }] } }] + [{ project_members: { include: [user: { only: [:id, :email, :username] }] } }] end def storage_path From 1d8e02c4ceba34addae175ac7797535eac2c7457 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 11 Mar 2016 17:33:45 +0100 Subject: [PATCH 025/730] solved a bunch of issues with mapping members/users --- .../projects/import_export/members_mapper.rb | 5 +++-- .../projects/import_export/relation_factory.rb | 13 ++++++++++++- .../projects/import_export/members_mapper_spec.rb | 8 +++++--- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/app/services/projects/import_export/members_mapper.rb b/app/services/projects/import_export/members_mapper.rb index 634683da5c..8d47422b10 100644 --- a/app/services/projects/import_export/members_mapper.rb +++ b/app/services/projects/import_export/members_mapper.rb @@ -28,9 +28,10 @@ module Projects end def assign_member(existing_user, member) + old_user_id = member['user']['id'] member['user'] = existing_user project_member = ProjectMember.new(member_hash(member)) - @project_member_map[existing_user.id] = project_member if project_member.save + @project_member_map[old_user_id] = project_member.user.id if project_member.save end def member_hash(member) @@ -42,7 +43,7 @@ module Projects @default_project_member ||= begin default_member = ProjectMember.new(default_project_member_hash) - default_member if default_member.save + default_member.user.id if default_member.save end end diff --git a/app/services/projects/import_export/relation_factory.rb b/app/services/projects/import_export/relation_factory.rb index 624453a6ad..39ac29e3f8 100644 --- a/app/services/projects/import_export/relation_factory.rb +++ b/app/services/projects/import_export/relation_factory.rb @@ -3,17 +3,28 @@ module Projects module RelationFactory extend self - OVERRIDES = { snippets: :project_snippets } + OVERRIDES = { snippets: :project_snippets }.freeze + USER_REFERENCES = %w(author_id assignee_id updated_by_id).freeze def create(relation_sym:, relation_hash:, members_map:) relation_sym = parse_relation_sym(relation_sym) klass = relation_class(relation_sym) relation_hash.delete('id') #screw IDs for now + update_user_references(relation_hash, members_map) klass.new(relation_hash) end private + #TODO nice to have, optimize this to only get called for specific models + def update_user_references(relation_hash, members_map) + USER_REFERENCES.each do |reference| + if relation_hash[reference] + relation_hash[reference] = members_map[relation_hash[reference]] + end + end + end + def relation_class(relation_sym) relation_sym.to_s.classify.constantize end diff --git a/spec/services/projects/import_export/members_mapper_spec.rb b/spec/services/projects/import_export/members_mapper_spec.rb index dc6ccb5012..e222dd4205 100644 --- a/spec/services/projects/import_export/members_mapper_spec.rb +++ b/spec/services/projects/import_export/members_mapper_spec.rb @@ -6,6 +6,7 @@ describe Projects::ImportExport::MembersMapper, services: true do let(:user) { create(:user) } let(:project) { create(:project, :public, name: 'searchable_project') } let(:user2) { create(:user) } + let(:exported_user_id) { 99 } let(:exported_members) do [{ "id" => 2, @@ -22,6 +23,7 @@ describe Projects::ImportExport::MembersMapper, services: true do "invite_accepted_at" => nil, "user" => { + "id" => exported_user_id, "email" => user2.email, "username" => user2.username } @@ -34,15 +36,15 @@ describe Projects::ImportExport::MembersMapper, services: true do end it 'maps a project member' do - expect(project_member_user_id(user2.id)).to eq(user2.id) + expect(members_mapper.map[exported_user_id]).to eq(user2.id) end it 'defaults to importer project member if it does not exist' do - expect(project_member_user_id(-1)).to eq(user.id) + expect(members_mapper.map[-1]).to eq(user.id) end end def project_member_user_id(id) - members_mapper.map[id].user.id + members_mapper.map[id] end end From 76efdea78839af27127cc81358ea1ffd911191f4 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 11 Mar 2016 18:17:57 +0100 Subject: [PATCH 026/730] fixing MR issues with import --- app/models/merge_request.rb | 4 +++- .../projects/import_export/project_tree_restorer.rb | 2 +- app/services/projects/import_export/relation_factory.rb | 6 ++++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 8271dc8311..714d55323d 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -50,6 +50,8 @@ class MergeRequest < ActiveRecord::Base delegate :commits, :diffs, :real_size, to: :merge_request_diff, prefix: nil + attr_accessor :importing + # When this attribute is true some MR validation is ignored # It allows us to close or modify broken merge requests attr_accessor :allow_broken @@ -128,7 +130,7 @@ class MergeRequest < ActiveRecord::Base validates :target_project, presence: true validates :target_branch, presence: true validates :merge_user, presence: true, if: :merge_when_build_succeeds? - validate :validate_branches + validate :validate_branches, unless: :importing validate :validate_fork scope :of_group, ->(group) { where("source_project_id in (:group_project_ids) OR target_project_id in (:group_project_ids)", group_project_ids: group.projects.select(:id).reorder(nil)) } diff --git a/app/services/projects/import_export/project_tree_restorer.rb b/app/services/projects/import_export/project_tree_restorer.rb index 87b78197cd..ac9b713200 100644 --- a/app/services/projects/import_export/project_tree_restorer.rb +++ b/app/services/projects/import_export/project_tree_restorer.rb @@ -44,7 +44,7 @@ module Projects def create_relation(relation, relation_hash_list) relation_hash_list.map do |relation_hash| Projects::ImportExport::RelationFactory.create( - relation_sym: relation, relation_hash: relation_hash.merge(project_id: project.id), members_map: members_map) + relation_sym: relation, relation_hash: relation_hash.merge('project_id' => project.id), members_map: members_map) end end end diff --git a/app/services/projects/import_export/relation_factory.rb b/app/services/projects/import_export/relation_factory.rb index 39ac29e3f8..1b9bd234a4 100644 --- a/app/services/projects/import_export/relation_factory.rb +++ b/app/services/projects/import_export/relation_factory.rb @@ -10,6 +10,12 @@ module Projects relation_sym = parse_relation_sym(relation_sym) klass = relation_class(relation_sym) relation_hash.delete('id') #screw IDs for now + #TODO refactor this... + if relation_sym == :merge_requests + relation_hash['target_project_id'] = relation_hash.delete('project_id') + relation_hash['source_project_id'] = -1 + relation_hash['importing'] = true + end update_user_references(relation_hash, members_map) klass.new(relation_hash) end From 3a131383b68dcb14abd9d31a2a462ffa57841095 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 14 Mar 2016 10:35:41 +0100 Subject: [PATCH 027/730] fixed MR issue and refactored some stuff --- app/models/merge_request.rb | 2 +- .../projects/import_export/members_mapper.rb | 8 ++------ .../projects/import_export/relation_factory.rb | 13 +++++++------ 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 714d55323d..de6189b2dc 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -125,7 +125,7 @@ class MergeRequest < ActiveRecord::Base end end - validates :source_project, presence: true, unless: :allow_broken + validates :source_project, presence: true, unless: [:allow_broken, :importing] validates :source_branch, presence: true validates :target_project, presence: true validates :target_branch, presence: true diff --git a/app/services/projects/import_export/members_mapper.rb b/app/services/projects/import_export/members_mapper.rb index 8d47422b10..6d49d901bf 100644 --- a/app/services/projects/import_export/members_mapper.rb +++ b/app/services/projects/import_export/members_mapper.rb @@ -13,12 +13,6 @@ module Projects end def map - @project_member_map ||= project_member_map - end - - private - - def project_member_map @project_member_map = Hash.new(default_project_member) @exported_members.each do |member| existing_user = User.where(find_project_user_query(member)).first @@ -27,6 +21,8 @@ module Projects @project_member_map end + private + def assign_member(existing_user, member) old_user_id = member['user']['id'] member['user'] = existing_user diff --git a/app/services/projects/import_export/relation_factory.rb b/app/services/projects/import_export/relation_factory.rb index 1b9bd234a4..6ccaa409ce 100644 --- a/app/services/projects/import_export/relation_factory.rb +++ b/app/services/projects/import_export/relation_factory.rb @@ -10,18 +10,19 @@ module Projects relation_sym = parse_relation_sym(relation_sym) klass = relation_class(relation_sym) relation_hash.delete('id') #screw IDs for now - #TODO refactor this... - if relation_sym == :merge_requests - relation_hash['target_project_id'] = relation_hash.delete('project_id') - relation_hash['source_project_id'] = -1 - relation_hash['importing'] = true - end + handle_merge_requests(relation_hash) if relation_sym == :merge_requests update_user_references(relation_hash, members_map) klass.new(relation_hash) end private + def handle_merge_requests(relation_hash) + relation_hash['target_project_id'] = relation_hash.delete('project_id') + relation_hash['source_project_id'] = -1 + relation_hash['importing'] = true + end + #TODO nice to have, optimize this to only get called for specific models def update_user_references(relation_hash, members_map) USER_REFERENCES.each do |reference| From 37c68fe025b3b4dd4ac3b510cbb32d42cbe6b23b Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 14 Mar 2016 11:12:00 +0100 Subject: [PATCH 028/730] don't create MR diff as this can be imported presumably --- app/models/merge_request.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index de6189b2dc..d9fbbb8500 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -45,7 +45,7 @@ class MergeRequest < ActiveRecord::Base serialize :merge_params, Hash - after_create :create_merge_request_diff + after_create :create_merge_request_diff, unless: :importing after_update :update_merge_request_diff delegate :commits, :diffs, :real_size, to: :merge_request_diff, prefix: nil From ba1fcf36197b86049b5e6a0f2da8842b236bcf62 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 14 Mar 2016 12:29:46 +0100 Subject: [PATCH 029/730] added commits and merge request diffs to export --- app/services/projects/import_export.rb | 12 ++++++++++-- .../import_export/project_tree_saver_spec.rb | 8 ++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/app/services/projects/import_export.rb b/app/services/projects/import_export.rb index b0c0891edb..373916a0c4 100644 --- a/app/services/projects/import_export.rb +++ b/app/services/projects/import_export.rb @@ -11,13 +11,21 @@ module Projects end def project_tree - %i(issues merge_requests labels milestones snippets releases events commit_statuses) + members + %i(issues labels milestones snippets releases events) + [members, merge_requests, commit_statuses] end private + def merge_requests + { merge_requests: { include: :merge_request_diff } } + end + + def commit_statuses + { commit_statuses: { include: :commit } } + end + def members - [{ project_members: { include: [user: { only: [:id, :email, :username] }] } }] + { project_members: { include: [user: { only: [:id, :email, :username] }] } } end def storage_path diff --git a/spec/services/projects/import_export/project_tree_saver_spec.rb b/spec/services/projects/import_export/project_tree_saver_spec.rb index 383b3e4ce8..960109e0c8 100644 --- a/spec/services/projects/import_export/project_tree_saver_spec.rb +++ b/spec/services/projects/import_export/project_tree_saver_spec.rb @@ -85,6 +85,14 @@ describe Projects::ImportExport::ProjectTreeSaver, services: true do it 'has project members' do expect(saved_project_json['project_members']).not_to be_empty end + + it 'has merge requests diffs' do + expect(saved_project_json['merge_requests'].first['merge_request_diff']).not_to be_empty + end + + it 'has ci commits' do + expect(saved_project_json['commit_statuses'].first['commit']).not_to be_empty + end end end From e05bc6114491f4c1f84505b4c4746faa8c269420 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 14 Mar 2016 12:58:01 +0100 Subject: [PATCH 030/730] fix project snippets json issue --- app/services/projects/import_export.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/services/projects/import_export.rb b/app/services/projects/import_export.rb index 373916a0c4..e1d7458a13 100644 --- a/app/services/projects/import_export.rb +++ b/app/services/projects/import_export.rb @@ -11,11 +11,15 @@ module Projects end def project_tree - %i(issues labels milestones snippets releases events) + [members, merge_requests, commit_statuses] + %i(issues labels milestones releases events) + [snippets, members, merge_requests, commit_statuses] end private + def snippets + { snippets: { except: :expired_at } } + end + def merge_requests { merge_requests: { include: :merge_request_diff } } end From a59ba217ae6796d4589575e97913aa80add75b43 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 14 Mar 2016 18:32:56 +0100 Subject: [PATCH 031/730] WIP - building up import tree with sub relations, etc --- app/services/projects/import_export.rb | 4 +++ .../import_export/project_tree_restorer.rb | 35 +++++++++++++++---- fixtures/import_export/project.json | 2 +- 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/app/services/projects/import_export.rb b/app/services/projects/import_export.rb index 373916a0c4..51a1732a67 100644 --- a/app/services/projects/import_export.rb +++ b/app/services/projects/import_export.rb @@ -10,6 +10,10 @@ module Projects %i(name path description issues_enabled wall_enabled merge_requests_enabled wiki_enabled snippets_enabled visibility_level archived) end + def project_tree_list + project_tree.map {|r| r.is_a?(Hash) ? r.keys.first : r } + end + def project_tree %i(issues labels milestones snippets releases events) + [members, merge_requests, commit_statuses] end diff --git a/app/services/projects/import_export/project_tree_restorer.rb b/app/services/projects/import_export/project_tree_restorer.rb index ac9b713200..ae1d0506c0 100644 --- a/app/services/projects/import_export/project_tree_restorer.rb +++ b/app/services/projects/import_export/project_tree_restorer.rb @@ -12,6 +12,7 @@ module Projects json = IO.read(@path) @tree_hash = ActiveSupport::JSON.decode(json) create_relations + puts project.inspect end private @@ -21,11 +22,33 @@ module Projects exported_members: @tree_hash.delete('project_members'), user: @user, project_id: project.id) end - def create_relations - (ImportExport.project_tree - [:project_members]).each do |relation| - next if @tree_hash[relation.to_s].empty? - relation_hash = create_relation(relation, @tree_hash[relation.to_s]) - project.update_attribute(relation, relation_hash) + #TODO Definitely refactor this method! + def create_relations(relation_list = default_relation_list, tree_hash = @tree_hash) + relation_list.each do |relation| + relation_hash = nil + # FIXME + # next if tree_hash[relation.to_s].blank? + if (relation.is_a?(Hash) && relation.values.first[:include]) + #TODO name stuff properly + relation_sym = relation.keys.first + #TODO remove sub-relation hashes from here so we can save the parent relation first + relation_hash = create_relation(relation_sym, tree_hash[relation_sym.to_s]) + sub_relations = [] + sub_relation = relation.values.first[:include] + sub_relation_hash_list = tree_hash[relation.keys.first.to_s] + sub_relation_hash_list.each do |sub_relation_hash| + sub_relations << create_relation(relation, sub_relation_hash[relation.to_s]) + end + relation_hash.update_attribute(sub_relation, sub_relations) + end + relation_hash ||= create_relation(relation, tree_hash[relation.to_s]) + project.update_attribute(relation, relation_hash) + end + end + + def default_relation_list + ImportExport.project_tree.reject do |rel| + rel.is_a?(Hash) && !rel[:project_members].blank? end end @@ -42,7 +65,7 @@ module Projects end def create_relation(relation, relation_hash_list) - relation_hash_list.map do |relation_hash| + [relation_hash_list].flatten.map do |relation_hash| Projects::ImportExport::RelationFactory.create( relation_sym: relation, relation_hash: relation_hash.merge('project_id' => project.id), members_map: members_map) end diff --git a/fixtures/import_export/project.json b/fixtures/import_export/project.json index 38c999e8fb..d21e754ce3 100644 --- a/fixtures/import_export/project.json +++ b/fixtures/import_export/project.json @@ -1 +1 @@ -{"name":"searchable_project","path":"gitlabhq","description":null,"issues_enabled":true,"wall_enabled":false,"merge_requests_enabled":true,"wiki_enabled":true,"snippets_enabled":true,"visibility_level":20,"archived":false,"issues":[{"id":2,"title":"Voluptatem quia repudiandae id rem ducimus.","assignee_id":19,"author_id":20,"project_id":14,"created_at":"2016-03-11T10:21:37.525Z","updated_at":"2016-03-11T10:21:44.516Z","position":0,"branch_name":null,"description":null,"milestone_id":null,"state":"opened","iid":1,"updated_by_id":null}],"merge_requests":[{"id":2,"target_branch":"feature","source_branch":"master","source_project_id":9,"author_id":23,"assignee_id":null,"title":"Enim dolor veritatis suscipit sed laboriosam consequatur doloremque.","created_at":"2016-03-11T10:21:38.628Z","updated_at":"2016-03-11T10:21:38.628Z","milestone_id":null,"state":"opened","merge_status":"can_be_merged","target_project_id":14,"iid":1,"description":null,"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}],"labels":[{"id":2,"title":"Bug","color":"#990000","project_id":14,"created_at":"2016-03-11T10:21:39.964Z","updated_at":"2016-03-11T10:21:44.539Z","template":false,"description":null}],"milestones":[{"id":2,"title":"Milestone v1.2","project_id":14,"description":null,"due_date":null,"created_at":"2016-03-11T10:21:44.688Z","updated_at":"2016-03-11T10:21:44.688Z","state":"active","iid":1}],"snippets":[{"id":2,"title":"Dolorem perspiciatis unde aut similique aperiam totam qui iste.","content":"Sed similique praesentium tempora et ad dolor quis ut.","author_id":30,"project_id":14,"created_at":"2016-03-11T10:21:41.034Z","updated_at":"2016-03-11T10:21:44.557Z","file_name":"dee","expires_at":null,"visibility_level":0}],"releases":[{"id":2,"tag":"v1.1.0","description":"Awesome release","project_id":14,"created_at":"2016-03-11T10:21:42.531Z","updated_at":"2016-03-11T10:21:44.576Z"}],"events":[{"id":2,"target_type":null,"target_id":null,"title":null,"data":null,"project_id":14,"created_at":"2016-03-11T10:21:44.892Z","updated_at":"2016-03-11T10:21:44.892Z","action":8,"author_id":19}],"commit_statuses":[{"id":2,"project_id":null,"status":"success","finished_at":"2016-01-26T07:23:42.000Z","trace":null,"created_at":"2016-03-11T10:21:43.493Z","updated_at":"2016-03-11T10:21:44.620Z","started_at":"2016-01-26T07:21:42.000Z","runner_id":null,"coverage":null,"commit_id":2,"commands":null,"job_id":null,"name":"default","deploy":false,"options":null,"allow_failure":false,"stage":null,"trigger_request_id":null,"stage_idx":null,"tag":null,"ref":null,"user_id":null,"target_url":null,"description":"commit status","artifacts_file":null,"gl_project_id":14,"artifacts_metadata":null,"erased_by_id":null,"erased_at":null}],"project_members":[{"id":2,"access_level":40,"source_id":14,"source_type":"Project","user_id":19,"notification_level":3,"created_at":"2016-03-11T10:21:44.822Z","updated_at":"2016-03-11T10:21:44.822Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"user":{"email":"claudie.lemke@prohaskamarquardt.co.uk","username":"hiram_conroy19"}}]} \ No newline at end of file +{"name":"searchable_project","path":"gitlabhq","description":null,"issues_enabled":true,"wall_enabled":false,"merge_requests_enabled":true,"wiki_enabled":true,"snippets_enabled":true,"visibility_level":20,"archived":false,"issues":[{"id":2,"title":"Libero explicabo dolores atque quae debitis sit ipsam unde.","assignee_id":19,"author_id":20,"project_id":14,"created_at":"2016-03-14T11:56:57.324Z","updated_at":"2016-03-14T11:57:02.118Z","position":0,"branch_name":null,"description":null,"milestone_id":null,"state":"opened","iid":1,"updated_by_id":null}],"labels":[{"id":2,"title":"Bug","color":"#990000","project_id":14,"created_at":"2016-03-14T11:56:59.538Z","updated_at":"2016-03-14T11:57:02.132Z","template":false,"description":null}],"milestones":[{"id":2,"title":"Milestone v1.2","project_id":14,"description":null,"due_date":null,"created_at":"2016-03-14T11:57:02.241Z","updated_at":"2016-03-14T11:57:02.241Z","state":"active","iid":1}],"releases":[{"id":2,"tag":"v1.1.0","description":"Awesome release","project_id":14,"created_at":"2016-03-14T11:57:00.950Z","updated_at":"2016-03-14T11:57:02.159Z"}],"events":[{"id":2,"target_type":null,"target_id":null,"title":null,"data":null,"project_id":14,"created_at":"2016-03-14T11:57:02.392Z","updated_at":"2016-03-14T11:57:02.392Z","action":8,"author_id":19}],"snippets":[{"id":2,"title":"Et qui optio blanditiis non.","content":"Repudiandae hic id vero adipisci.","author_id":28,"project_id":14,"created_at":"2016-03-14T11:57:00.372Z","updated_at":"2016-03-14T11:57:02.144Z","file_name":"krystina","visibility_level":0}],"project_members":[{"id":2,"access_level":40,"source_id":14,"source_type":"Project","user_id":19,"notification_level":3,"created_at":"2016-03-14T11:57:02.335Z","updated_at":"2016-03-14T11:57:02.335Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"user":{"id":19,"email":"braxton@greenholttromp.ca","username":"elena19"}}],"merge_requests":[{"id":2,"target_branch":"feature","source_branch":"master","source_project_id":9,"author_id":23,"assignee_id":null,"title":"Cum est in est et.","created_at":"2016-03-14T11:56:58.333Z","updated_at":"2016-03-14T11:56:58.333Z","milestone_id":null,"state":"opened","merge_status":"can_be_merged","target_project_id":14,"iid":1,"description":null,"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,"merge_request_diff":{"id":2,"state":"collected","st_commits":[{"id":"5937ac0a7beb003549fc5fd26fc247adbce4a52e","message":"Add submodule from gitlab.com\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n","parent_ids":["570e7b2abdd848b95f2f578043fc23bd6f6fd24d"],"authored_date":"2014-02-27T10:01:38.000+01:00","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","committed_date":"2014-02-27T10:01:38.000+01:00","committer_name":"Dmitriy Zaporozhets","committer_email":"dmitriy.zaporozhets@gmail.com"},{"id":"570e7b2abdd848b95f2f578043fc23bd6f6fd24d","message":"Change some files\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n","parent_ids":["6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9"],"authored_date":"2014-02-27T09:57:31.000+01:00","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","committed_date":"2014-02-27T09:57:31.000+01:00","committer_name":"Dmitriy Zaporozhets","committer_email":"dmitriy.zaporozhets@gmail.com"},{"id":"6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9","message":"More submodules\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n","parent_ids":["d14d6c0abdd253381df51a723d58691b2ee1ab08"],"authored_date":"2014-02-27T09:54:21.000+01:00","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","committed_date":"2014-02-27T09:54:21.000+01:00","committer_name":"Dmitriy Zaporozhets","committer_email":"dmitriy.zaporozhets@gmail.com"},{"id":"d14d6c0abdd253381df51a723d58691b2ee1ab08","message":"Remove ds_store files\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n","parent_ids":["c1acaa58bbcbc3eafe538cb8274ba387047b69f8"],"authored_date":"2014-02-27T09:49:50.000+01:00","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","committed_date":"2014-02-27T09:49:50.000+01:00","committer_name":"Dmitriy Zaporozhets","committer_email":"dmitriy.zaporozhets@gmail.com"},{"id":"c1acaa58bbcbc3eafe538cb8274ba387047b69f8","message":"Ignore DS files\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n","parent_ids":["ae73cb07c9eeaf35924a10f713b364d32b2dd34f"],"authored_date":"2014-02-27T09:48:32.000+01:00","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","committed_date":"2014-02-27T09:48:32.000+01:00","committer_name":"Dmitriy Zaporozhets","committer_email":"dmitriy.zaporozhets@gmail.com"}],"st_diffs":[{"diff":"Binary files a/.DS_Store and /dev/null differ\n","new_path":".DS_Store","old_path":".DS_Store","a_mode":"100644","b_mode":"0","new_file":false,"renamed_file":false,"deleted_file":true},{"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},{"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},{"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},{"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},{"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},{"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},{"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}],"merge_request_id":2,"created_at":"2016-03-14T11:56:58.353Z","updated_at":"2016-03-14T11:56:58.635Z","base_commit_sha":"ae73cb07c9eeaf35924a10f713b364d32b2dd34f","real_size":"8"}}],"commit_statuses":[{"id":2,"project_id":null,"status":"success","finished_at":"2016-01-26T07:23:42.000Z","trace":null,"created_at":"2016-03-14T11:57:01.483Z","updated_at":"2016-03-14T11:57:02.190Z","started_at":"2016-01-26T07:21:42.000Z","runner_id":null,"coverage":null,"commit_id":2,"commands":null,"job_id":null,"name":"default","deploy":false,"options":null,"allow_failure":false,"stage":null,"trigger_request_id":null,"stage_idx":null,"tag":null,"ref":null,"user_id":null,"target_url":null,"description":"commit status","artifacts_file":null,"gl_project_id":14,"artifacts_metadata":null,"erased_by_id":null,"erased_at":null,"commit":{"id":2,"project_id":13,"ref":null,"sha":"97de212e80737a608d939f648d959671fb0a0142","before_sha":null,"push_data":null,"created_at":"2016-03-14T11:57:01.468Z","updated_at":"2016-03-14T11:57:01.468Z","tag":false,"yaml_errors":null,"committed_at":null,"gl_project_id":13}}]} \ No newline at end of file From e17c7f41fc9fc95399896622eac053fb276888df Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 15 Mar 2016 09:17:44 +0100 Subject: [PATCH 032/730] add TODO --- app/services/projects/import_export/project_tree_restorer.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/services/projects/import_export/project_tree_restorer.rb b/app/services/projects/import_export/project_tree_restorer.rb index ae1d0506c0..3a767c1980 100644 --- a/app/services/projects/import_export/project_tree_restorer.rb +++ b/app/services/projects/import_export/project_tree_restorer.rb @@ -23,6 +23,7 @@ module Projects end #TODO Definitely refactor this method! + #TODO Think about having a yaml file to describe the tree instead of just hashes? def create_relations(relation_list = default_relation_list, tree_hash = @tree_hash) relation_list.each do |relation| relation_hash = nil From ac4d753863e32a3f1da2d073983e418d88401e67 Mon Sep 17 00:00:00 2001 From: Jasper Denkers Date: Fri, 26 Feb 2016 12:31:35 +0100 Subject: [PATCH 033/730] Added CI example for Scala and SBT Added CI test coverage parse regex for scoverage --- doc/ci/examples/README.md | 1 + doc/ci/examples/test-scala-application.md | 28 +++++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 doc/ci/examples/test-scala-application.md diff --git a/doc/ci/examples/README.md b/doc/ci/examples/README.md index cc059dc437..20eeaad3fa 100644 --- a/doc/ci/examples/README.md +++ b/doc/ci/examples/README.md @@ -4,6 +4,7 @@ - [Test and deploy a Ruby application to Heroku](test-and-deploy-ruby-application-to-heroku.md) - [Test and deploy a Python application to Heroku](test-and-deploy-python-application-to-heroku.md) - [Test a Clojure application](test-clojure-application.md) +- [Test a Scala application](test-scala-application.md) - [Using `dpl` as deployment tool](deployment/README.md) - Help your favorite programming language and GitLab by sending a merge request with a guide for that language. diff --git a/doc/ci/examples/test-scala-application.md b/doc/ci/examples/test-scala-application.md new file mode 100644 index 0000000000..2df60321cf --- /dev/null +++ b/doc/ci/examples/test-scala-application.md @@ -0,0 +1,28 @@ +## Test a Scala application + +This example demonstrates the integration of Gitlab CI with Scala applications using SBT. Checkout the example [project](https://gitlab.com/jasperdenkers/scala-sbt-sample-app) and [build status](https://gitlab.com/jasperdenkers/scala-sbt-sample-app/builds). + +### Add `.gitlab-ci.yml` file to project + +The following `.gitlab-ci.yml` should be added in the root of your repository to trigger CI: + +```yaml +before_script: + # Install SBT + - echo "deb http://dl.bintray.com/sbt/debian /" | tee -a /etc/apt/sources.list.d/sbt.list + - apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 642AC823 + - apt-get update -y + - apt-get install sbt -y + - sbt sbt-version + +test: + script: + - sbt clean coverage test coverageReport +``` + +The `before_script` installs [SBT](http://www.scala-sbt.org/) and displays the version that is being used. The `test` stage executes SBT to compile and test the project. [scoverage](https://github.com/scoverage/sbt-scoverage) is used as a SBT plugin to measure test coverage. + +You can use other versions of Scala and SBT by defining them in `build.sbt`. + +### Display test coverage in build +Add the `Coverage was \[\d+.\d+\%\]` regular expression in the `Continuous Integration > Test coverage parsing` project setting to retrieve the test coverage rate from the build trace and have it displayed with your builds. From 707ca4bb91a29baf43908d025be356b6e00353fe Mon Sep 17 00:00:00 2001 From: Jasper Denkers Date: Thu, 10 Mar 2016 17:06:20 +0100 Subject: [PATCH 034/730] Refer to example project in gitlab-examples group --- doc/ci/examples/test-scala-application.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ci/examples/test-scala-application.md b/doc/ci/examples/test-scala-application.md index 2df60321cf..f1753157e9 100644 --- a/doc/ci/examples/test-scala-application.md +++ b/doc/ci/examples/test-scala-application.md @@ -1,6 +1,6 @@ ## Test a Scala application -This example demonstrates the integration of Gitlab CI with Scala applications using SBT. Checkout the example [project](https://gitlab.com/jasperdenkers/scala-sbt-sample-app) and [build status](https://gitlab.com/jasperdenkers/scala-sbt-sample-app/builds). +This example demonstrates the integration of Gitlab CI with Scala applications using SBT. Checkout the example [project](https://gitlab.com/gitlab-examples/scala-sbt) and [build status](https://gitlab.com/gitlab-examples/scala-sbt/builds). ### Add `.gitlab-ci.yml` file to project From 9169c7e81fb906cf9f419d195d73a585b19dafbc Mon Sep 17 00:00:00 2001 From: Jasper Denkers Date: Thu, 10 Mar 2016 17:32:37 +0100 Subject: [PATCH 035/730] Add Java 8 image to Scala CI instructions --- doc/ci/examples/test-scala-application.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/ci/examples/test-scala-application.md b/doc/ci/examples/test-scala-application.md index f1753157e9..58947f0f9f 100644 --- a/doc/ci/examples/test-scala-application.md +++ b/doc/ci/examples/test-scala-application.md @@ -7,6 +7,8 @@ This example demonstrates the integration of Gitlab CI with Scala applications u The following `.gitlab-ci.yml` should be added in the root of your repository to trigger CI: ```yaml +image: java:8 + before_script: # Install SBT - echo "deb http://dl.bintray.com/sbt/debian /" | tee -a /etc/apt/sources.list.d/sbt.list From efde96e9cd4b0096c19ecfa46237b7eda28038aa Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 6 Apr 2016 18:12:41 +0200 Subject: [PATCH 036/730] started refactored the dynamic rules to be defined in a yml file --- .../projects/import_export/import_export.yml | 31 ++++++++++++ .../import_export/import_export_reader.rb | 47 +++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 app/services/projects/import_export/import_export.yml create mode 100644 app/services/projects/import_export/import_export_reader.rb diff --git a/app/services/projects/import_export/import_export.yml b/app/services/projects/import_export/import_export.yml new file mode 100644 index 0000000000..d02ec5df2f --- /dev/null +++ b/app/services/projects/import_export/import_export.yml @@ -0,0 +1,31 @@ +# Class relationships to be included in the import/export +:project_tree: + - :issues + - :labels + - :milestones + - :snippets + - :releases + - :events + - :project_members: + - :user + - :merge_requests: + - :merge_request_diff + - :commit_statuses: + - :commit + +:attributes_only: + :project: + - :name + - :path + - :description + - :issues_enabled + - :wall_enabled + - :merge_requests_enabled + - :wiki_enabled + - :snippets_enabled + - :visibility_level + - :archived + :user: + - :id + - :email + - :username \ No newline at end of file diff --git a/app/services/projects/import_export/import_export_reader.rb b/app/services/projects/import_export/import_export_reader.rb new file mode 100644 index 0000000000..af8c8c3c25 --- /dev/null +++ b/app/services/projects/import_export/import_export_reader.rb @@ -0,0 +1,47 @@ +module Projects + module ImportExport + module ImportExportReader + extend self + + def project_tree + { only: atts_only[:project], include: build_hash(tree) } + end + + def config + @config ||= YAML.load_file('app/services/projects/import_export/import_export.yml') + end + + def atts_only + config[:attributes_only] + end + + def atts_except + config[:attributes_except] + end + + def tree + config[:project_tree] + end + + def build_hash(array) + array.map { |el| el.is_a?(Hash) ? process_include(el) : el } + end + + def process_include(hash) + included_classes_hash = {} + hash.values.flatten.each do |value| + value = value.is_a?(Hash) ? process_include(hash) : value + new_hash = { :include => value } + new_hash.merge!(check_only(value)) + included_classes_hash[hash.keys.first] = new_hash + end + included_classes_hash + end + + def check_only(value) + key = value.is_a?(Hash) ? value.keys.first : value + atts_only[key].nil? ? {} : { only: atts_only[key] } + end + end + end +end \ No newline at end of file From acfa0b69d5370749cee9768bf79b58daf6d916a4 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 7 Apr 2016 13:19:57 +0200 Subject: [PATCH 037/730] continuing to refactor config, added spec and fixed a few problems --- .../projects/import_export/import_export.yml | 2 +- .../import_export/import_export_reader.rb | 51 ++++++++++++++++--- .../import_export_reader_spec.rb | 24 +++++++++ spec/support/import_export/import_export.yml | 20 ++++++++ 4 files changed, 89 insertions(+), 8 deletions(-) create mode 100644 spec/services/projects/import_export/import_export_reader_spec.rb create mode 100644 spec/support/import_export/import_export.yml diff --git a/app/services/projects/import_export/import_export.yml b/app/services/projects/import_export/import_export.yml index d02ec5df2f..40fd98b809 100644 --- a/app/services/projects/import_export/import_export.yml +++ b/app/services/projects/import_export/import_export.yml @@ -1,4 +1,4 @@ -# Class relationships to be included in the import/export +# Class relationships to be included in the project import/export :project_tree: - :issues - :labels diff --git a/app/services/projects/import_export/import_export_reader.rb b/app/services/projects/import_export/import_export_reader.rb index af8c8c3c25..77a1abb851 100644 --- a/app/services/projects/import_export/import_export_reader.rb +++ b/app/services/projects/import_export/import_export_reader.rb @@ -7,6 +7,8 @@ module Projects { only: atts_only[:project], include: build_hash(tree) } end + private + def config @config ||= YAML.load_file('app/services/projects/import_export/import_export.yml') end @@ -27,21 +29,56 @@ module Projects array.map { |el| el.is_a?(Hash) ? process_include(el) : el } end - def process_include(hash) - included_classes_hash = {} + def process_include(hash, included_classes_hash = {}) hash.values.flatten.each do |value| - value = value.is_a?(Hash) ? process_include(hash) : value - new_hash = { :include => value } - new_hash.merge!(check_only(value)) - included_classes_hash[hash.keys.first] = new_hash + current_key, value = process_current_class(hash, included_classes_hash, value) + if included_classes_hash[current_key] + add_class(current_key, included_classes_hash, value) + else + add_new_class(current_key, included_classes_hash, value) + end end included_classes_hash end + def process_current_class(hash, included_classes_hash, value) + value = value.is_a?(Hash) ? process_include(hash, included_classes_hash) : value + current_key = hash.keys.first + current_key_only = check_only_and_except(current_key) + included_classes_hash[current_key] ||= current_key_only unless current_key_only.empty? + return current_key, value + end + + def add_new_class(current_key, included_classes_hash, value) + new_hash = { :include => value } + new_hash.merge!(check_only_and_except(value)) + included_classes_hash[current_key] = new_hash + end + + def add_class(current_key, included_classes_hash, value) + check_only_hash = check_only_and_except(value) + value = { value => check_only_hash } unless check_only_hash.empty? + old_values = included_classes_hash[current_key][:include] + included_classes_hash[current_key][:include] = ([old_values] + [value]).compact.flatten + end + + def check_only_and_except(value) + check_only(value).merge(check_except(value)) + end + def check_only(value) - key = value.is_a?(Hash) ? value.keys.first : value + key = key_from_hash(value) atts_only[key].nil? ? {} : { only: atts_only[key] } end + + def check_except(value) + key = key_from_hash(value) + atts_except[key].nil? ? {} : { except: atts_except[key] } + end + + def key_from_hash(value) + value.is_a?(Hash) ? value.keys.first : value + end end end end \ No newline at end of file diff --git a/spec/services/projects/import_export/import_export_reader_spec.rb b/spec/services/projects/import_export/import_export_reader_spec.rb new file mode 100644 index 0000000000..73e043e52c --- /dev/null +++ b/spec/services/projects/import_export/import_export_reader_spec.rb @@ -0,0 +1,24 @@ +require 'rspec' + +describe Projects::ImportExport::ImportExportReader do + + let(:test_config) { 'spec/support/import_export/import_export.yml' } + let(:project_tree_hash) do + { + :only => [:name, :path], + :include => [:issues, :labels, + { :merge_requests => { + :only => [:id], + :except => [:iid], + :include => [:merge_request_diff, :merge_request_test] + } }, + { :commit_statuses => { :include => :commit } }] + } + end + + it 'should generate hash from project tree config' do + allow(described_class).to receive(:config).and_return(YAML.load_file(test_config)) + + expect(described_class.project_tree).to eq(project_tree_hash) + end +end \ No newline at end of file diff --git a/spec/support/import_export/import_export.yml b/spec/support/import_export/import_export.yml new file mode 100644 index 0000000000..e6985d6413 --- /dev/null +++ b/spec/support/import_export/import_export.yml @@ -0,0 +1,20 @@ +# Class relationships to be included in the project import/export +:project_tree: + - :issues + - :labels + - :merge_requests: + - :merge_request_diff + - :merge_request_test + - :commit_statuses: + - :commit + +:attributes_only: + :project: + - :name + - :path + :merge_requests: + - :id + +:attributes_except: + :merge_requests: + - :iid \ No newline at end of file From de6c44e983a788262b72355b85d085a675c9fccc Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 7 Apr 2016 18:14:42 +0200 Subject: [PATCH 038/730] using new config --- app/services/projects/import_export.rb | 18 +----------------- .../projects/import_export/import_export.yml | 6 +++++- .../import_export/import_export_reader.rb | 17 ++++++++++++----- .../import_export/project_tree_saver.rb | 2 +- 4 files changed, 19 insertions(+), 24 deletions(-) diff --git a/app/services/projects/import_export.rb b/app/services/projects/import_export.rb index e1d7458a13..c74f1d3149 100644 --- a/app/services/projects/import_export.rb +++ b/app/services/projects/import_export.rb @@ -11,27 +11,11 @@ module Projects end def project_tree - %i(issues labels milestones releases events) + [snippets, members, merge_requests, commit_statuses] + Projects::ImportExport::ImportExportReader.project_tree end private - def snippets - { snippets: { except: :expired_at } } - end - - def merge_requests - { merge_requests: { include: :merge_request_diff } } - end - - def commit_statuses - { commit_statuses: { include: :commit } } - end - - def members - { project_members: { include: [user: { only: [:id, :email, :username] }] } } - end - def storage_path File.join(Settings.shared['path'], 'tmp/project_exports') end diff --git a/app/services/projects/import_export/import_export.yml b/app/services/projects/import_export/import_export.yml index 40fd98b809..be7680775b 100644 --- a/app/services/projects/import_export/import_export.yml +++ b/app/services/projects/import_export/import_export.yml @@ -28,4 +28,8 @@ :user: - :id - :email - - :username \ No newline at end of file + - :username + +:attributes_except: + :snippets: + - :expired_at \ No newline at end of file diff --git a/app/services/projects/import_export/import_export_reader.rb b/app/services/projects/import_export/import_export_reader.rb index 77a1abb851..981f19c0ac 100644 --- a/app/services/projects/import_export/import_export_reader.rb +++ b/app/services/projects/import_export/import_export_reader.rb @@ -26,7 +26,14 @@ module Projects end def build_hash(array) - array.map { |el| el.is_a?(Hash) ? process_include(el) : el } + array.map do |el| + if el.is_a?(Hash) + process_include(el) + else + only_except_hash = check_only_and_except(el) + only_except_hash.empty? ? el : { el => only_except_hash } + end + end end def process_include(hash, included_classes_hash = {}) @@ -44,8 +51,8 @@ module Projects def process_current_class(hash, included_classes_hash, value) value = value.is_a?(Hash) ? process_include(hash, included_classes_hash) : value current_key = hash.keys.first - current_key_only = check_only_and_except(current_key) - included_classes_hash[current_key] ||= current_key_only unless current_key_only.empty? + only_except_hash = check_only_and_except(current_key) + included_classes_hash[current_key] ||= only_except_hash unless only_except_hash.empty? return current_key, value end @@ -56,8 +63,8 @@ module Projects end def add_class(current_key, included_classes_hash, value) - check_only_hash = check_only_and_except(value) - value = { value => check_only_hash } unless check_only_hash.empty? + only_except_hash = check_only_and_except(value) + value = { value => only_except_hash } unless only_except_hash.empty? old_values = included_classes_hash[current_key][:include] included_classes_hash[current_key][:include] = ([old_values] + [value]).compact.flatten end diff --git a/app/services/projects/import_export/project_tree_saver.rb b/app/services/projects/import_export/project_tree_saver.rb index 3ca90d1f79..44d100acd1 100644 --- a/app/services/projects/import_export/project_tree_saver.rb +++ b/app/services/projects/import_export/project_tree_saver.rb @@ -32,7 +32,7 @@ module Projects def project_json_tree # TODO confirm children, also add subchildren (i.e comments) # TODO confirm atts for children - @project.to_json(only: ImportExport.project_atts, include: ImportExport.project_tree) + @project.to_json(Projects::ImportExport.project_tree) end end end From 5d642fb7aa666063d5e1761833463bc95241889a Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 8 Apr 2016 15:07:12 +0200 Subject: [PATCH 039/730] fix rubocop warnings --- .../import_export/import_export_reader.rb | 14 +++++++------- .../import_export/import_export_reader_spec.rb | 18 +++++++++--------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/app/services/projects/import_export/import_export_reader.rb b/app/services/projects/import_export/import_export_reader.rb index 981f19c0ac..e0617ce851 100644 --- a/app/services/projects/import_export/import_export_reader.rb +++ b/app/services/projects/import_export/import_export_reader.rb @@ -38,7 +38,8 @@ module Projects def process_include(hash, included_classes_hash = {}) hash.values.flatten.each do |value| - current_key, value = process_current_class(hash, included_classes_hash, value) + current_key = hash.keys.first + value = process_current_class(hash, included_classes_hash, value) if included_classes_hash[current_key] add_class(current_key, included_classes_hash, value) else @@ -50,14 +51,13 @@ module Projects def process_current_class(hash, included_classes_hash, value) value = value.is_a?(Hash) ? process_include(hash, included_classes_hash) : value - current_key = hash.keys.first - only_except_hash = check_only_and_except(current_key) - included_classes_hash[current_key] ||= only_except_hash unless only_except_hash.empty? - return current_key, value + only_except_hash = check_only_and_except(hash.keys.first) + included_classes_hash[hash.keys.first] ||= only_except_hash unless only_except_hash.empty? + value end def add_new_class(current_key, included_classes_hash, value) - new_hash = { :include => value } + new_hash = { include: value } new_hash.merge!(check_only_and_except(value)) included_classes_hash[current_key] = new_hash end @@ -88,4 +88,4 @@ module Projects end end end -end \ No newline at end of file +end diff --git a/spec/services/projects/import_export/import_export_reader_spec.rb b/spec/services/projects/import_export/import_export_reader_spec.rb index 73e043e52c..f825292ce7 100644 --- a/spec/services/projects/import_export/import_export_reader_spec.rb +++ b/spec/services/projects/import_export/import_export_reader_spec.rb @@ -5,14 +5,14 @@ describe Projects::ImportExport::ImportExportReader do let(:test_config) { 'spec/support/import_export/import_export.yml' } let(:project_tree_hash) do { - :only => [:name, :path], - :include => [:issues, :labels, - { :merge_requests => { - :only => [:id], - :except => [:iid], - :include => [:merge_request_diff, :merge_request_test] - } }, - { :commit_statuses => { :include => :commit } }] + only: [:name, :path], + include: [:issues, :labels, + { merge_requests: { + only: [:id], + except: [:iid], + include: [:merge_request_diff, :merge_request_test] + } }, + { commit_statuses: { include: :commit } }] } end @@ -21,4 +21,4 @@ describe Projects::ImportExport::ImportExportReader do expect(described_class.project_tree).to eq(project_tree_hash) end -end \ No newline at end of file +end From a28be02e88f1d213649ef2c25858313caeb83b59 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 8 Apr 2016 18:13:19 +0200 Subject: [PATCH 040/730] starting to use the new dynamic stuff on the import --- .../import_export/import_export_reader.rb | 8 ++-- .../import_export/project_tree_restorer.rb | 47 +++++++++++-------- 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/app/services/projects/import_export/import_export_reader.rb b/app/services/projects/import_export/import_export_reader.rb index e0617ce851..001d24af60 100644 --- a/app/services/projects/import_export/import_export_reader.rb +++ b/app/services/projects/import_export/import_export_reader.rb @@ -7,6 +7,10 @@ module Projects { only: atts_only[:project], include: build_hash(tree) } end + def tree + config[:project_tree] + end + private def config @@ -21,10 +25,6 @@ module Projects config[:attributes_except] end - def tree - config[:project_tree] - end - def build_hash(array) array.map do |el| if el.is_a?(Hash) diff --git a/app/services/projects/import_export/project_tree_restorer.rb b/app/services/projects/import_export/project_tree_restorer.rb index 3a767c1980..ca68840e98 100644 --- a/app/services/projects/import_export/project_tree_restorer.rb +++ b/app/services/projects/import_export/project_tree_restorer.rb @@ -25,32 +25,41 @@ module Projects #TODO Definitely refactor this method! #TODO Think about having a yaml file to describe the tree instead of just hashes? def create_relations(relation_list = default_relation_list, tree_hash = @tree_hash) + members_map # TODO remove this and fix project_members relation_list.each do |relation| - relation_hash = nil - # FIXME - # next if tree_hash[relation.to_s].blank? - if (relation.is_a?(Hash) && relation.values.first[:include]) - #TODO name stuff properly - relation_sym = relation.keys.first - #TODO remove sub-relation hashes from here so we can save the parent relation first - relation_hash = create_relation(relation_sym, tree_hash[relation_sym.to_s]) - sub_relations = [] - sub_relation = relation.values.first[:include] - sub_relation_hash_list = tree_hash[relation.keys.first.to_s] - sub_relation_hash_list.each do |sub_relation_hash| - sub_relations << create_relation(relation, sub_relation_hash[relation.to_s]) + if relation.is_a?(Hash) + relation.values.each do |value| + create_relations(value, @tree_hash[relation.to_s]) end - relation_hash.update_attribute(sub_relation, sub_relations) end - relation_hash ||= create_relation(relation, tree_hash[relation.to_s]) - project.update_attribute(relation, relation_hash) + relation_hash = create_relation(relation, tree_hash[relation.to_s]) + project.update_attribute(relation, relation_hash) + # relation_hash = nil + # # FIXME + # # next if tree_hash[relation.to_s].blank? + # if (relation.is_a?(Hash) && relation.values.first[:include]) + # #TODO name stuff properly + # relation_sym = relation.keys.first + # #TODO remove sub-relation hashes from here so we can save the parent relation first + # relation_hash = create_relation(relation_sym, tree_hash[relation_sym.to_s]) + # sub_relations = [] + # sub_relation = relation.values.first[:include] + # sub_relation_hash_list = tree_hash[relation.keys.first.to_s] + # sub_relation_hash_list.each do |sub_relation_hash| + # sub_relations << create_relation(relation, sub_relation_hash[relation.to_s]) + # end + # relation_hash.update_attribute(sub_relation, sub_relations) + # end + # relation_hash ||= create_relation(relation, tree_hash[relation.to_s]) + # project.update_attribute(relation, relation_hash) end end def default_relation_list - ImportExport.project_tree.reject do |rel| - rel.is_a?(Hash) && !rel[:project_members].blank? - end + Projects::ImportExport::ImportExportReader.tree + # ImportExport.project_tree.reject do |rel| + # rel.is_a?(Hash) && !rel[:project_members].blank? + # end end def project From 56fc58930cec501bd63046781c06be510feee029 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 11 Apr 2016 18:30:54 +0200 Subject: [PATCH 041/730] more refactoring to use dynamic import --- .../projects/import_export/import_export.yml | 4 ++- .../import_export/project_tree_restorer.rb | 35 +++++++++++-------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/app/services/projects/import_export/import_export.yml b/app/services/projects/import_export/import_export.yml index be7680775b..16a212d4c3 100644 --- a/app/services/projects/import_export/import_export.yml +++ b/app/services/projects/import_export/import_export.yml @@ -1,4 +1,4 @@ -# Class relationships to be included in the project import/export +# Model relationships to be included in the project import/export :project_tree: - :issues - :labels @@ -13,6 +13,7 @@ - :commit_statuses: - :commit +# Only include the following attributes for the models specified. :attributes_only: :project: - :name @@ -30,6 +31,7 @@ - :email - :username +# Do not include the following attributes for the models specified. :attributes_except: :snippets: - :expired_at \ No newline at end of file diff --git a/app/services/projects/import_export/project_tree_restorer.rb b/app/services/projects/import_export/project_tree_restorer.rb index ca68840e98..9512fcb2a1 100644 --- a/app/services/projects/import_export/project_tree_restorer.rb +++ b/app/services/projects/import_export/project_tree_restorer.rb @@ -11,29 +11,25 @@ module Projects def restore json = IO.read(@path) @tree_hash = ActiveSupport::JSON.decode(json) + @project_members = @tree_hash.delete('project_members') create_relations - puts project.inspect end private def members_map @members ||= Projects::ImportExport::MembersMapper.map( - exported_members: @tree_hash.delete('project_members'), user: @user, project_id: project.id) + exported_members: @project_members, user: @user, project_id: project.id) end - #TODO Definitely refactor this method! - #TODO Think about having a yaml file to describe the tree instead of just hashes? def create_relations(relation_list = default_relation_list, tree_hash = @tree_hash) - members_map # TODO remove this and fix project_members relation_list.each do |relation| if relation.is_a?(Hash) - relation.values.each do |value| - create_relations(value, @tree_hash[relation.to_s]) - end + create_sub_relations(relation, tree_hash) end - relation_hash = create_relation(relation, tree_hash[relation.to_s]) - project.update_attribute(relation, relation_hash) + relation_key = relation.is_a?(Hash) ? relation.keys.first : relation + relation_hash = create_relation(relation_key, tree_hash[relation_key.to_s]) + project.update_attribute(relation_key, relation_hash) # relation_hash = nil # # FIXME # # next if tree_hash[relation.to_s].blank? @@ -56,10 +52,7 @@ module Projects end def default_relation_list - Projects::ImportExport::ImportExportReader.tree - # ImportExport.project_tree.reject do |rel| - # rel.is_a?(Hash) && !rel[:project_members].blank? - # end + Projects::ImportExport::ImportExportReader.tree.reject { |model| model.is_a?(Hash) && model[:project_members] } end def project @@ -74,6 +67,20 @@ module Projects project end + def create_sub_relations(relation, tree_hash) + # TODO refactor this + relation_key = relation.keys.first + tree_hash[relation_key.to_s].each do |relation_item| + relation.values.each do |sub_relation| + relation_hash = relation_item[sub_relation.to_s] + next if relation_hash.blank? + sub_relation_object = Projects::ImportExport::RelationFactory.create( + relation_sym: sub_relation, relation_hash: relation_hash, members_map: members_map) + relation_item[sub_relation.to_s] = sub_relation_object + end + end + end + def create_relation(relation, relation_hash_list) [relation_hash_list].flatten.map do |relation_hash| Projects::ImportExport::RelationFactory.create( From da60baf2a5fc5e2f7e84ea592b8ba6747a63abb3 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 12 Apr 2016 10:36:18 +0200 Subject: [PATCH 042/730] fixing more importing issues --- app/models/merge_request_diff.rb | 4 +++- app/services/projects/import_export/project_tree_restorer.rb | 3 ++- app/services/projects/import_export/relation_factory.rb | 5 +++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index 3388411859..03daac2822 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -37,7 +37,9 @@ class MergeRequestDiff < ActiveRecord::Base serialize :st_commits serialize :st_diffs - after_create :reload_content + after_create :reload_content, unless: :importing + + attr_accessor :importing def reload_content reload_commits diff --git a/app/services/projects/import_export/project_tree_restorer.rb b/app/services/projects/import_export/project_tree_restorer.rb index 9512fcb2a1..c498d7bd9b 100644 --- a/app/services/projects/import_export/project_tree_restorer.rb +++ b/app/services/projects/import_export/project_tree_restorer.rb @@ -71,9 +71,10 @@ module Projects # TODO refactor this relation_key = relation.keys.first tree_hash[relation_key.to_s].each do |relation_item| - relation.values.each do |sub_relation| + relation.values.flatten.each do |sub_relation| relation_hash = relation_item[sub_relation.to_s] next if relation_hash.blank? + relation_hash.merge!('project_id' => project.id) if sub_relation == :merge_requests sub_relation_object = Projects::ImportExport::RelationFactory.create( relation_sym: sub_relation, relation_hash: relation_hash, members_map: members_map) relation_item[sub_relation.to_s] = sub_relation_object diff --git a/app/services/projects/import_export/relation_factory.rb b/app/services/projects/import_export/relation_factory.rb index 6ccaa409ce..4f1c753ac6 100644 --- a/app/services/projects/import_export/relation_factory.rb +++ b/app/services/projects/import_export/relation_factory.rb @@ -7,12 +7,14 @@ module Projects USER_REFERENCES = %w(author_id assignee_id updated_by_id).freeze def create(relation_sym:, relation_hash:, members_map:) + #TODO refactor this relation_sym = parse_relation_sym(relation_sym) klass = relation_class(relation_sym) relation_hash.delete('id') #screw IDs for now handle_merge_requests(relation_hash) if relation_sym == :merge_requests update_user_references(relation_hash, members_map) - klass.new(relation_hash) + imported_object = klass.new(relation_hash) + imported_object.importing = true if imported_object.respond_to?(:importing) end private @@ -20,7 +22,6 @@ module Projects def handle_merge_requests(relation_hash) relation_hash['target_project_id'] = relation_hash.delete('project_id') relation_hash['source_project_id'] = -1 - relation_hash['importing'] = true end #TODO nice to have, optimize this to only get called for specific models From dbf755ae56f17d9b62a95a1f631ff583b6a50fb3 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 12 Apr 2016 11:34:58 +0200 Subject: [PATCH 043/730] small fix --- app/services/projects/import_export/relation_factory.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/services/projects/import_export/relation_factory.rb b/app/services/projects/import_export/relation_factory.rb index 4f1c753ac6..123dd43dad 100644 --- a/app/services/projects/import_export/relation_factory.rb +++ b/app/services/projects/import_export/relation_factory.rb @@ -15,6 +15,7 @@ module Projects update_user_references(relation_hash, members_map) imported_object = klass.new(relation_hash) imported_object.importing = true if imported_object.respond_to?(:importing) + imported_object end private From 4ffcd427800b9d252b6b6a8cd9dafe03d203229a Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 12 Apr 2016 11:42:37 +0200 Subject: [PATCH 044/730] import working! --- app/services/projects/import_export/project_tree_restorer.rb | 3 +-- app/services/projects/import_export/relation_factory.rb | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/services/projects/import_export/project_tree_restorer.rb b/app/services/projects/import_export/project_tree_restorer.rb index c498d7bd9b..be0c706609 100644 --- a/app/services/projects/import_export/project_tree_restorer.rb +++ b/app/services/projects/import_export/project_tree_restorer.rb @@ -74,9 +74,8 @@ module Projects relation.values.flatten.each do |sub_relation| relation_hash = relation_item[sub_relation.to_s] next if relation_hash.blank? - relation_hash.merge!('project_id' => project.id) if sub_relation == :merge_requests sub_relation_object = Projects::ImportExport::RelationFactory.create( - relation_sym: sub_relation, relation_hash: relation_hash, members_map: members_map) + relation_sym: sub_relation, relation_hash: relation_hash.merge!('project_id' => project.id), members_map: members_map) relation_item[sub_relation.to_s] = sub_relation_object end end diff --git a/app/services/projects/import_export/relation_factory.rb b/app/services/projects/import_export/relation_factory.rb index 123dd43dad..0eb7a03b6e 100644 --- a/app/services/projects/import_export/relation_factory.rb +++ b/app/services/projects/import_export/relation_factory.rb @@ -3,7 +3,7 @@ module Projects module RelationFactory extend self - OVERRIDES = { snippets: :project_snippets }.freeze + OVERRIDES = { snippets: :project_snippets, commit: 'Ci::Commit' }.freeze USER_REFERENCES = %w(author_id assignee_id updated_by_id).freeze def create(relation_sym:, relation_hash:, members_map:) @@ -11,6 +11,7 @@ module Projects relation_sym = parse_relation_sym(relation_sym) klass = relation_class(relation_sym) relation_hash.delete('id') #screw IDs for now + relation_hash.delete('project_id') unless klass.column_names.include?(:project_id) handle_merge_requests(relation_hash) if relation_sym == :merge_requests update_user_references(relation_hash, members_map) imported_object = klass.new(relation_hash) From eb55cb927b668e7e4e507ad87e65895c6a96f14d Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 12 Apr 2016 12:24:40 +0200 Subject: [PATCH 045/730] more refactoring --- .../import_export/project_tree_restorer.rb | 35 ++++++------------- .../import_export/relation_factory.rb | 24 +++++++++---- 2 files changed, 27 insertions(+), 32 deletions(-) diff --git a/app/services/projects/import_export/project_tree_restorer.rb b/app/services/projects/import_export/project_tree_restorer.rb index be0c706609..df0363e0ec 100644 --- a/app/services/projects/import_export/project_tree_restorer.rb +++ b/app/services/projects/import_export/project_tree_restorer.rb @@ -30,24 +30,8 @@ module Projects relation_key = relation.is_a?(Hash) ? relation.keys.first : relation relation_hash = create_relation(relation_key, tree_hash[relation_key.to_s]) project.update_attribute(relation_key, relation_hash) - # relation_hash = nil - # # FIXME - # # next if tree_hash[relation.to_s].blank? - # if (relation.is_a?(Hash) && relation.values.first[:include]) - # #TODO name stuff properly - # relation_sym = relation.keys.first - # #TODO remove sub-relation hashes from here so we can save the parent relation first - # relation_hash = create_relation(relation_sym, tree_hash[relation_sym.to_s]) - # sub_relations = [] - # sub_relation = relation.values.first[:include] - # sub_relation_hash_list = tree_hash[relation.keys.first.to_s] - # sub_relation_hash_list.each do |sub_relation_hash| - # sub_relations << create_relation(relation, sub_relation_hash[relation.to_s]) - # end - # relation_hash.update_attribute(sub_relation, sub_relations) - # end - # relation_hash ||= create_relation(relation, tree_hash[relation.to_s]) - # project.update_attribute(relation, relation_hash) + # FIXME + # next if tree_hash[relation.to_s].blank? end end @@ -68,14 +52,11 @@ module Projects end def create_sub_relations(relation, tree_hash) - # TODO refactor this - relation_key = relation.keys.first - tree_hash[relation_key.to_s].each do |relation_item| + tree_hash[relation.keys.first.to_s].each do |relation_item| relation.values.flatten.each do |sub_relation| relation_hash = relation_item[sub_relation.to_s] next if relation_hash.blank? - sub_relation_object = Projects::ImportExport::RelationFactory.create( - relation_sym: sub_relation, relation_hash: relation_hash.merge!('project_id' => project.id), members_map: members_map) + sub_relation_object = relation_from_factory(relation, relation_hash) relation_item[sub_relation.to_s] = sub_relation_object end end @@ -83,10 +64,14 @@ module Projects def create_relation(relation, relation_hash_list) [relation_hash_list].flatten.map do |relation_hash| - Projects::ImportExport::RelationFactory.create( - relation_sym: relation, relation_hash: relation_hash.merge('project_id' => project.id), members_map: members_map) + relation_from_factory(relation, relation_hash) end end + + def relation_from_factory(relation, relation_hash) + Projects::ImportExport::RelationFactory.create( + relation_sym: relation, relation_hash: relation_hash.merge('project_id' => project.id), members_map: members_map) + end end end end diff --git a/app/services/projects/import_export/relation_factory.rb b/app/services/projects/import_export/relation_factory.rb index 0eb7a03b6e..31d8120364 100644 --- a/app/services/projects/import_export/relation_factory.rb +++ b/app/services/projects/import_export/relation_factory.rb @@ -7,16 +7,13 @@ module Projects USER_REFERENCES = %w(author_id assignee_id updated_by_id).freeze def create(relation_sym:, relation_hash:, members_map:) - #TODO refactor this relation_sym = parse_relation_sym(relation_sym) - klass = relation_class(relation_sym) - relation_hash.delete('id') #screw IDs for now - relation_hash.delete('project_id') unless klass.column_names.include?(:project_id) + klass = parse_relation(relation_hash, relation_sym) + handle_merge_requests(relation_hash) if relation_sym == :merge_requests update_user_references(relation_hash, members_map) - imported_object = klass.new(relation_hash) - imported_object.importing = true if imported_object.respond_to?(:importing) - imported_object + + imported_object(klass, relation_hash) end private @@ -42,6 +39,19 @@ module Projects def parse_relation_sym(relation_sym) OVERRIDES[relation_sym] || relation_sym end + + def imported_object(klass, relation_hash) + imported_object = klass.new(relation_hash) + imported_object.importing = true if imported_object.respond_to?(:importing) + imported_object + end + + def parse_relation(relation_hash, relation_sym) + klass = relation_class(relation_sym) + relation_hash.delete('id') #screw IDs for now + relation_hash.delete('project_id') unless klass.column_names.include?(:project_id) + klass + end end end end From 495397793e1530bb1ec453d1ae5ea9b77cd22c54 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 12 Apr 2016 12:57:00 +0200 Subject: [PATCH 046/730] fix spec --- .../projects/import_export/project_tree_restorer.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/services/projects/import_export/project_tree_restorer.rb b/app/services/projects/import_export/project_tree_restorer.rb index df0363e0ec..251221c2a6 100644 --- a/app/services/projects/import_export/project_tree_restorer.rb +++ b/app/services/projects/import_export/project_tree_restorer.rb @@ -23,16 +23,18 @@ module Projects end def create_relations(relation_list = default_relation_list, tree_hash = @tree_hash) + saved = [] relation_list.each do |relation| if relation.is_a?(Hash) create_sub_relations(relation, tree_hash) end relation_key = relation.is_a?(Hash) ? relation.keys.first : relation relation_hash = create_relation(relation_key, tree_hash[relation_key.to_s]) - project.update_attribute(relation_key, relation_hash) + saved << project.update_attribute(relation_key, relation_hash) # FIXME # next if tree_hash[relation.to_s].blank? end + saved.all? end def default_relation_list @@ -56,7 +58,7 @@ module Projects relation.values.flatten.each do |sub_relation| relation_hash = relation_item[sub_relation.to_s] next if relation_hash.blank? - sub_relation_object = relation_from_factory(relation, relation_hash) + sub_relation_object = relation_from_factory(sub_relation, relation_hash) relation_item[sub_relation.to_s] = sub_relation_object end end From 3b99e4ae5bc9e4d1bf54c65bf633ad449361b9df Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 12 Apr 2016 15:32:25 +0200 Subject: [PATCH 047/730] add issue and MR comments to default export. Fix spec --- .../projects/import_export/import_export.yml | 4 +- .../import_export/import_export_reader.rb | 8 +- .../import_export/project_tree_saver.rb | 2 - .../import_export/project_tree_saver_spec.rb | 171 ++---------------- 4 files changed, 19 insertions(+), 166 deletions(-) diff --git a/app/services/projects/import_export/import_export.yml b/app/services/projects/import_export/import_export.yml index be7680775b..c622447ef0 100644 --- a/app/services/projects/import_export/import_export.yml +++ b/app/services/projects/import_export/import_export.yml @@ -1,6 +1,7 @@ # Class relationships to be included in the project import/export :project_tree: - - :issues + - :issues: + - :notes - :labels - :milestones - :snippets @@ -10,6 +11,7 @@ - :user - :merge_requests: - :merge_request_diff + - :notes - :commit_statuses: - :commit diff --git a/app/services/projects/import_export/import_export_reader.rb b/app/services/projects/import_export/import_export_reader.rb index e0617ce851..001d24af60 100644 --- a/app/services/projects/import_export/import_export_reader.rb +++ b/app/services/projects/import_export/import_export_reader.rb @@ -7,6 +7,10 @@ module Projects { only: atts_only[:project], include: build_hash(tree) } end + def tree + config[:project_tree] + end + private def config @@ -21,10 +25,6 @@ module Projects config[:attributes_except] end - def tree - config[:project_tree] - end - def build_hash(array) array.map do |el| if el.is_a?(Hash) diff --git a/app/services/projects/import_export/project_tree_saver.rb b/app/services/projects/import_export/project_tree_saver.rb index 44d100acd1..b2ca85bd7c 100644 --- a/app/services/projects/import_export/project_tree_saver.rb +++ b/app/services/projects/import_export/project_tree_saver.rb @@ -30,8 +30,6 @@ module Projects end def project_json_tree - # TODO confirm children, also add subchildren (i.e comments) - # TODO confirm atts for children @project.to_json(Projects::ImportExport.project_tree) end end diff --git a/spec/services/projects/import_export/project_tree_saver_spec.rb b/spec/services/projects/import_export/project_tree_saver_spec.rb index 960109e0c8..eda9e08cdc 100644 --- a/spec/services/projects/import_export/project_tree_saver_spec.rb +++ b/spec/services/projects/import_export/project_tree_saver_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' describe Projects::ImportExport::ProjectTreeSaver, services: true do describe :save do + # TODO refactor this into a setup method + let(:user) { create(:user) } let(:issue) { create(:issue, assignee: user) } let(:merge_request) { create(:merge_request) } @@ -25,6 +27,8 @@ describe Projects::ImportExport::ProjectTreeSaver, services: true do let(:export_path) { "#{Dir::tmpdir}/project_tree_saver_spec" } let(:shared) { Projects::ImportExport::Shared.new(relative_path: project.path_with_namespace) } let(:project_tree_saver) { Projects::ImportExport::ProjectTreeSaver.new(project: project, shared: shared) } + let!(:issue_note) { create(:note, note: ":+1: issue", noteable: issue) } + let!(:merge_request_note) { create(:note, note: ":+1: merge_request", noteable: merge_request) } before(:each) do project.team << [user, :master] @@ -78,6 +82,10 @@ describe Projects::ImportExport::ProjectTreeSaver, services: true do expect(saved_project_json['issues']).not_to be_empty end + it 'has issue comments' do + expect(saved_project_json['issues'].first['notes']).not_to be_empty + end + it 'has commit statuses' do expect(saved_project_json['commit_statuses']).not_to be_empty end @@ -90,6 +98,10 @@ describe Projects::ImportExport::ProjectTreeSaver, services: true do expect(saved_project_json['merge_requests'].first['merge_request_diff']).not_to be_empty end + it 'has merge requests comments' do + expect(saved_project_json['merge_requests'].first['notes']).not_to be_empty + end + it 'has ci commits' do expect(saved_project_json['commit_statuses'].first['commit']).not_to be_empty end @@ -99,163 +111,4 @@ describe Projects::ImportExport::ProjectTreeSaver, services: true do def project_json(filename) JSON.parse(IO.read(filename)) end - - # TODO: Remove this. Current JSON pretty printed: - # { - # "id":7, - # "name":"searchable_project", - # "path":"gitlabhq", - # "description":null, - # "issues_enabled":true, - # "wall_enabled":false, - # "merge_requests_enabled":true, - # "wiki_enabled":true, - # "snippets_enabled":true, - # "visibility_level":20, - # "archived":false, - # "issues":[ - # { - # "id":1, - # "title":"Voluptas dolores molestias iste excepturi quia atque sint et.", - # "assignee_id":1, - # "author_id":2, - # "project_id":7, - # "created_at":"2016-03-08T09:14:31.726Z", - # "updated_at":"2016-03-08T09:14:36.293Z", - # "position":0, - # "branch_name":null, - # "description":null, - # "milestone_id":null, - # "state":"opened", - # "iid":1, - # "updated_by_id":null - # } - # ], - # "merge_requests":[ - # { - # "id":1, - # "target_branch":"feature", - # "source_branch":"master", - # "source_project_id":2, - # "author_id":5, - # "assignee_id":null, - # "title":"Quam velit cupiditate culpa perspiciatis esse maiores quaerat.", - # "created_at":"2016-03-08T09:14:32.597Z", - # "updated_at":"2016-03-08T09:14:32.597Z", - # "milestone_id":null, - # "state":"opened", - # "merge_status":"can_be_merged", - # "target_project_id":7, - # "iid":1, - # "description":null, - # "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 - # } - # ], - # "labels":[ - # { - # "id":1, - # "title":"Bug", - # "color":"#990000", - # "project_id":7, - # "created_at":"2016-03-08T09:14:33.774Z", - # "updated_at":"2016-03-08T09:14:36.314Z", - # "template":false, - # "description":null - # } - # ], - # "milestones":[ - # { - # "id":1, - # "title":"Milestone v1.2", - # "project_id":7, - # "description":null, - # "due_date":null, - # "created_at":"2016-03-08T09:14:36.526Z", - # "updated_at":"2016-03-08T09:14:36.526Z", - # "state":"active", - # "iid":1 - # } - # ], - # "snippets":[ - # { - # "id":1, - # "title":"Voluptatem qui officiis modi ut fugit distinctio dolor qui.", - # "content":"Quaerat sunt eligendi voluptatum magnam.", - # "author_id":12, - # "project_id":7, - # "created_at":"2016-03-08T09:14:34.539Z", - # "updated_at":"2016-03-08T09:14:36.332Z", - # "file_name":"rowland.tremblay", - # "expires_at":null, - # "visibility_level":0 - # } - # ], - # "releases":[ - # { - # "id":1, - # "tag":"v1.1.0", - # "description":"Awesome release", - # "project_id":7, - # "created_at":"2016-03-08T09:14:35.023Z", - # "updated_at":"2016-03-08T09:14:36.351Z" - # } - # ], - # "events":[ - # { - # "id":1, - # "target_type":null, - # "target_id":null, - # "title":null, - # "data":null, - # "project_id":7, - # "created_at":"2016-03-08T09:14:36.806Z", - # "updated_at":"2016-03-08T09:14:36.806Z", - # "action":8, - # "author_id":1 - # } - # ], - # "commit_statuses":[ - # { - # "id":1, - # "project_id":null, - # "status":"success", - # "finished_at":"2016-01-26T07:23:42.000Z", - # "trace":null, - # "created_at":"2016-03-08T09:14:35.633Z", - # "updated_at":"2016-03-08T09:14:36.385Z", - # "started_at":"2016-01-26T07:21:42.000Z", - # "runner_id":null, - # "coverage":null, - # "commit_id":1, - # "commands":null, - # "job_id":null, - # "name":"default", - # "deploy":false, - # "options":null, - # "allow_failure":false, - # "stage":null, - # "trigger_request_id":null, - # "stage_idx":null, - # "tag":null, - # "ref":null, - # "user_id":null, - # "target_url":null, - # "description":"commit status", - # "artifacts_file":null, - # "gl_project_id":7, - # "artifacts_metadata":null, - # "erased_by_id":null, - # "erased_at":null - # } - # ] - # } end From 0d8a97dcef64967e3a8912e53ec8c91b54ccfe2e Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 12 Apr 2016 17:10:30 +0200 Subject: [PATCH 048/730] some more fixes to import projects --- .../import_export/project_tree_restorer.rb | 13 +- .../import_export/relation_factory.rb | 4 +- fixtures/import_export/project.json | 433 +++++++++++++++++- 3 files changed, 445 insertions(+), 5 deletions(-) diff --git a/app/services/projects/import_export/project_tree_restorer.rb b/app/services/projects/import_export/project_tree_restorer.rb index 251221c2a6..2d9dee1031 100644 --- a/app/services/projects/import_export/project_tree_restorer.rb +++ b/app/services/projects/import_export/project_tree_restorer.rb @@ -58,12 +58,21 @@ module Projects relation.values.flatten.each do |sub_relation| relation_hash = relation_item[sub_relation.to_s] next if relation_hash.blank? - sub_relation_object = relation_from_factory(sub_relation, relation_hash) - relation_item[sub_relation.to_s] = sub_relation_object + process_sub_relation(relation_hash, relation_item, sub_relation) end end end + def process_sub_relation(relation_hash, relation_item, sub_relation) + sub_relation_object = nil + if relation_hash.is_a?(Array) + sub_relation_object = create_relation(sub_relation, relation_hash) + else + sub_relation_object = relation_from_factory(sub_relation, relation_hash) + end + relation_item[sub_relation.to_s] = sub_relation_object + end + def create_relation(relation, relation_hash_list) [relation_hash_list].flatten.map do |relation_hash| relation_from_factory(relation, relation_hash) diff --git a/app/services/projects/import_export/relation_factory.rb b/app/services/projects/import_export/relation_factory.rb index 31d8120364..29917fce2b 100644 --- a/app/services/projects/import_export/relation_factory.rb +++ b/app/services/projects/import_export/relation_factory.rb @@ -48,8 +48,8 @@ module Projects def parse_relation(relation_hash, relation_sym) klass = relation_class(relation_sym) - relation_hash.delete('id') #screw IDs for now - relation_hash.delete('project_id') unless klass.column_names.include?(:project_id) + relation_hash.delete('id') + relation_hash.delete('project_id') unless klass.column_names.include?('project_id') klass end end diff --git a/fixtures/import_export/project.json b/fixtures/import_export/project.json index d21e754ce3..a2fed10b85 100644 --- a/fixtures/import_export/project.json +++ b/fixtures/import_export/project.json @@ -1 +1,432 @@ -{"name":"searchable_project","path":"gitlabhq","description":null,"issues_enabled":true,"wall_enabled":false,"merge_requests_enabled":true,"wiki_enabled":true,"snippets_enabled":true,"visibility_level":20,"archived":false,"issues":[{"id":2,"title":"Libero explicabo dolores atque quae debitis sit ipsam unde.","assignee_id":19,"author_id":20,"project_id":14,"created_at":"2016-03-14T11:56:57.324Z","updated_at":"2016-03-14T11:57:02.118Z","position":0,"branch_name":null,"description":null,"milestone_id":null,"state":"opened","iid":1,"updated_by_id":null}],"labels":[{"id":2,"title":"Bug","color":"#990000","project_id":14,"created_at":"2016-03-14T11:56:59.538Z","updated_at":"2016-03-14T11:57:02.132Z","template":false,"description":null}],"milestones":[{"id":2,"title":"Milestone v1.2","project_id":14,"description":null,"due_date":null,"created_at":"2016-03-14T11:57:02.241Z","updated_at":"2016-03-14T11:57:02.241Z","state":"active","iid":1}],"releases":[{"id":2,"tag":"v1.1.0","description":"Awesome release","project_id":14,"created_at":"2016-03-14T11:57:00.950Z","updated_at":"2016-03-14T11:57:02.159Z"}],"events":[{"id":2,"target_type":null,"target_id":null,"title":null,"data":null,"project_id":14,"created_at":"2016-03-14T11:57:02.392Z","updated_at":"2016-03-14T11:57:02.392Z","action":8,"author_id":19}],"snippets":[{"id":2,"title":"Et qui optio blanditiis non.","content":"Repudiandae hic id vero adipisci.","author_id":28,"project_id":14,"created_at":"2016-03-14T11:57:00.372Z","updated_at":"2016-03-14T11:57:02.144Z","file_name":"krystina","visibility_level":0}],"project_members":[{"id":2,"access_level":40,"source_id":14,"source_type":"Project","user_id":19,"notification_level":3,"created_at":"2016-03-14T11:57:02.335Z","updated_at":"2016-03-14T11:57:02.335Z","created_by_id":null,"invite_email":null,"invite_token":null,"invite_accepted_at":null,"user":{"id":19,"email":"braxton@greenholttromp.ca","username":"elena19"}}],"merge_requests":[{"id":2,"target_branch":"feature","source_branch":"master","source_project_id":9,"author_id":23,"assignee_id":null,"title":"Cum est in est et.","created_at":"2016-03-14T11:56:58.333Z","updated_at":"2016-03-14T11:56:58.333Z","milestone_id":null,"state":"opened","merge_status":"can_be_merged","target_project_id":14,"iid":1,"description":null,"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,"merge_request_diff":{"id":2,"state":"collected","st_commits":[{"id":"5937ac0a7beb003549fc5fd26fc247adbce4a52e","message":"Add submodule from gitlab.com\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n","parent_ids":["570e7b2abdd848b95f2f578043fc23bd6f6fd24d"],"authored_date":"2014-02-27T10:01:38.000+01:00","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","committed_date":"2014-02-27T10:01:38.000+01:00","committer_name":"Dmitriy Zaporozhets","committer_email":"dmitriy.zaporozhets@gmail.com"},{"id":"570e7b2abdd848b95f2f578043fc23bd6f6fd24d","message":"Change some files\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n","parent_ids":["6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9"],"authored_date":"2014-02-27T09:57:31.000+01:00","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","committed_date":"2014-02-27T09:57:31.000+01:00","committer_name":"Dmitriy Zaporozhets","committer_email":"dmitriy.zaporozhets@gmail.com"},{"id":"6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9","message":"More submodules\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n","parent_ids":["d14d6c0abdd253381df51a723d58691b2ee1ab08"],"authored_date":"2014-02-27T09:54:21.000+01:00","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","committed_date":"2014-02-27T09:54:21.000+01:00","committer_name":"Dmitriy Zaporozhets","committer_email":"dmitriy.zaporozhets@gmail.com"},{"id":"d14d6c0abdd253381df51a723d58691b2ee1ab08","message":"Remove ds_store files\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n","parent_ids":["c1acaa58bbcbc3eafe538cb8274ba387047b69f8"],"authored_date":"2014-02-27T09:49:50.000+01:00","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","committed_date":"2014-02-27T09:49:50.000+01:00","committer_name":"Dmitriy Zaporozhets","committer_email":"dmitriy.zaporozhets@gmail.com"},{"id":"c1acaa58bbcbc3eafe538cb8274ba387047b69f8","message":"Ignore DS files\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n","parent_ids":["ae73cb07c9eeaf35924a10f713b364d32b2dd34f"],"authored_date":"2014-02-27T09:48:32.000+01:00","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","committed_date":"2014-02-27T09:48:32.000+01:00","committer_name":"Dmitriy Zaporozhets","committer_email":"dmitriy.zaporozhets@gmail.com"}],"st_diffs":[{"diff":"Binary files a/.DS_Store and /dev/null differ\n","new_path":".DS_Store","old_path":".DS_Store","a_mode":"100644","b_mode":"0","new_file":false,"renamed_file":false,"deleted_file":true},{"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},{"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},{"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},{"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},{"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},{"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},{"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}],"merge_request_id":2,"created_at":"2016-03-14T11:56:58.353Z","updated_at":"2016-03-14T11:56:58.635Z","base_commit_sha":"ae73cb07c9eeaf35924a10f713b364d32b2dd34f","real_size":"8"}}],"commit_statuses":[{"id":2,"project_id":null,"status":"success","finished_at":"2016-01-26T07:23:42.000Z","trace":null,"created_at":"2016-03-14T11:57:01.483Z","updated_at":"2016-03-14T11:57:02.190Z","started_at":"2016-01-26T07:21:42.000Z","runner_id":null,"coverage":null,"commit_id":2,"commands":null,"job_id":null,"name":"default","deploy":false,"options":null,"allow_failure":false,"stage":null,"trigger_request_id":null,"stage_idx":null,"tag":null,"ref":null,"user_id":null,"target_url":null,"description":"commit status","artifacts_file":null,"gl_project_id":14,"artifacts_metadata":null,"erased_by_id":null,"erased_at":null,"commit":{"id":2,"project_id":13,"ref":null,"sha":"97de212e80737a608d939f648d959671fb0a0142","before_sha":null,"push_data":null,"created_at":"2016-03-14T11:57:01.468Z","updated_at":"2016-03-14T11:57:01.468Z","tag":false,"yaml_errors":null,"committed_at":null,"gl_project_id":13}}]} \ No newline at end of file +{ + "name": "searchable_project", + "path": "gitlabhq", + "description": null, + "issues_enabled": true, + "wall_enabled": false, + "merge_requests_enabled": true, + "wiki_enabled": true, + "snippets_enabled": true, + "visibility_level": 20, + "archived": false, + "issues": [ + { + "id": 1, + "title": "Ad est est quia inventore eius suscipit molestiae.", + "assignee_id": 1, + "author_id": 2, + "project_id": 7, + "created_at": "2016-04-12T13:26:48.974Z", + "updated_at": "2016-04-12T13:26:55.496Z", + "position": 0, + "branch_name": null, + "description": null, + "milestone_id": null, + "state": "opened", + "iid": 1, + "updated_by_id": null, + "confidential": false, + "deleted_at": null, + "moved_to_id": null, + "notes": [ + { + "id": 1, + "note": ":+1: issue", + "noteable_type": "Issue", + "author_id": 21, + "created_at": "2016-04-12T13:26:55.480Z", + "updated_at": "2016-04-12T13:26:55.480Z", + "project_id": 8, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 1, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false + } + ] + } + ], + "labels": [ + { + "id": 1, + "title": "label1", + "color": "#990000", + "project_id": 7, + "created_at": "2016-04-12T13:26:51.027Z", + "updated_at": "2016-04-12T13:26:53.799Z", + "template": false, + "description": null + } + ], + "milestones": [ + { + "id": 1, + "title": "Milestone v1.2", + "project_id": 7, + "description": null, + "due_date": null, + "created_at": "2016-04-12T13:26:53.993Z", + "updated_at": "2016-04-12T13:26:53.993Z", + "state": "active", + "iid": 1 + } + ], + "snippets": [ + { + "id": 1, + "title": "Possimus harum est mollitia fugiat in.", + "content": "Itaque ipsum culpa quibusdam mollitia.", + "author_id": 10, + "project_id": 7, + "created_at": "2016-04-12T13:26:51.821Z", + "updated_at": "2016-04-12T13:26:53.811Z", + "file_name": "thomas_marquardt", + "visibility_level": 0 + } + ], + "releases": [ + { + "id": 1, + "tag": "v1.1.0", + "description": "Awesome release", + "project_id": 7, + "created_at": "2016-04-12T13:26:52.353Z", + "updated_at": "2016-04-12T13:26:53.823Z" + } + ], + "events": [ + { + "id": 1, + "target_type": null, + "target_id": null, + "title": null, + "data": null, + "project_id": 7, + "created_at": "2016-04-12T13:26:57.139Z", + "updated_at": "2016-04-12T13:26:57.139Z", + "action": 8, + "author_id": 1 + } + ], + "project_members": [ + { + "id": 1, + "user": { + "id": 1, + "email": "maybell_auer@gleasonolson.com", + "created_at": "2016-04-12T13:26:47.499Z", + "updated_at": "2016-04-12T13:26:47.499Z", + "name": "Charles Nitzsche", + "admin": false, + "projects_limit": 42, + "skype": "", + "linkedin": "", + "twitter": "", + "authentication_token": "nCBdoTPWP-5adipsFwEq", + "theme_id": 2, + "bio": null, + "username": "koby.zieme1", + "can_create_group": true, + "can_create_team": false, + "state": "active", + "color_scheme_id": 1, + "notification_level": 1, + "password_expires_at": null, + "created_by_id": null, + "last_credential_check_at": null, + "avatar": { + "url": null + }, + "hide_no_ssh_key": false, + "website_url": "", + "notification_email": "maybell_auer@gleasonolson.com", + "hide_no_password": false, + "password_automatically_set": false, + "location": null, + "encrypted_otp_secret": null, + "encrypted_otp_secret_iv": null, + "encrypted_otp_secret_salt": null, + "otp_required_for_login": false, + "otp_backup_codes": null, + "public_email": "", + "dashboard": "projects", + "project_view": "readme", + "consumed_timestep": null, + "layout": "fixed", + "hide_project_limit": false, + "otp_grace_period_started_at": null, + "ldap_email": false, + "external": false + } + } + ], + "merge_requests": [ + { + "id": 1, + "target_branch": "feature", + "source_branch": "master", + "source_project_id": 2, + "author_id": 5, + "assignee_id": null, + "title": "Natus vel molestiae ab et dolorem odit ut.", + "created_at": "2016-04-12T13:26:49.813Z", + "updated_at": "2016-04-12T13:26:56.806Z", + "milestone_id": null, + "state": "opened", + "merge_status": "can_be_merged", + "target_project_id": 7, + "iid": 1, + "description": null, + "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, + "merge_request_diff": { + "id": 1, + "state": "collected", + "st_commits": [ + { + "id": "5937ac0a7beb003549fc5fd26fc247adbce4a52e", + "message": "Add submodule from gitlab.com\n\nSigned-off-by: Dmitriy Zaporozhets \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 \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 \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 \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 \n", + "parent_ids": [ + "ae73cb07c9eeaf35924a10f713b364d32b2dd34f" + ], + "authored_date": "2014-02-27T09:48:32.000+01:00", + "author_name": "Dmitriy Zaporozhets", + "author_email": "dmitriy.zaporozhets@gmail.com", + "committed_date": "2014-02-27T09:48:32.000+01:00", + "committer_name": "Dmitriy Zaporozhets", + "committer_email": "dmitriy.zaporozhets@gmail.com" + } + ], + "st_diffs": [ + { + "diff": "Binary files a/.DS_Store and /dev/null differ\n", + "new_path": ".DS_Store", + "old_path": ".DS_Store", + "a_mode": "100644", + "b_mode": "0", + "new_file": false, + "renamed_file": false, + "deleted_file": true, + "too_large": false + }, + { + "diff": "--- a/.gitignore\n+++ b/.gitignore\n@@ -17,3 +17,4 @@ rerun.txt\n pickle-email-*.html\n .project\n config/initializers/secret_token.rb\n+.DS_Store\n", + "new_path": ".gitignore", + "old_path": ".gitignore", + "a_mode": "100644", + "b_mode": "100644", + "new_file": false, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- a/.gitmodules\n+++ b/.gitmodules\n@@ -1,3 +1,9 @@\n [submodule \"six\"]\n \tpath = six\n \turl = git://github.com/randx/six.git\n+[submodule \"gitlab-shell\"]\n+\tpath = gitlab-shell\n+\turl = https://github.com/gitlabhq/gitlab-shell.git\n+[submodule \"gitlab-grack\"]\n+\tpath = gitlab-grack\n+\turl = https://gitlab.com/gitlab-org/gitlab-grack.git\n", + "new_path": ".gitmodules", + "old_path": ".gitmodules", + "a_mode": "100644", + "b_mode": "100644", + "new_file": false, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "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": "--- 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\" => path }\n- options = { chdir: path }\n+\n+ vars = {\n+ \"PWD\" => 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 << stdout.read\n @cmd_output << 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/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 + } + ], + "merge_request_id": 1, + "created_at": "2016-04-12T13:26:49.896Z", + "updated_at": "2016-04-12T13:26:50.189Z", + "base_commit_sha": "ae73cb07c9eeaf35924a10f713b364d32b2dd34f", + "real_size": "8" + }, + "notes": [ + { + "id": 2, + "note": ":+1: merge_request", + "noteable_type": "MergeRequest", + "author_id": 24, + "created_at": "2016-04-12T13:26:56.790Z", + "updated_at": "2016-04-12T13:26:56.790Z", + "project_id": 9, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 1, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false + } + ] + } + ], + "commit_statuses": [ + { + "id": 1, + "project_id": null, + "status": "success", + "finished_at": "2016-01-26T07:23:42.000Z", + "trace": null, + "created_at": "2016-04-12T13:26:53.034Z", + "updated_at": "2016-04-12T13:26:53.850Z", + "started_at": "2016-01-26T07:21:42.000Z", + "runner_id": null, + "coverage": null, + "commit_id": 1, + "commands": null, + "job_id": null, + "name": "default", + "deploy": false, + "options": null, + "allow_failure": false, + "stage": null, + "trigger_request_id": null, + "stage_idx": null, + "tag": null, + "ref": null, + "user_id": null, + "target_url": null, + "description": "commit status", + "artifacts_file": null, + "gl_project_id": 7, + "artifacts_metadata": null, + "erased_by_id": null, + "erased_at": null, + "commit": { + "id": 1, + "project_id": 6, + "ref": null, + "sha": "97de212e80737a608d939f648d959671fb0a0142", + "before_sha": null, + "push_data": null, + "created_at": "2016-04-12T13:26:53.010Z", + "updated_at": "2016-04-12T13:26:53.010Z", + "tag": false, + "yaml_errors": null, + "committed_at": null, + "gl_project_id": 6 + } + } + ] +} \ No newline at end of file From 6f74c7d4827955d44f53eeef0701e4e3c0f718a1 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 12 Apr 2016 18:06:57 +0200 Subject: [PATCH 049/730] fix export commits stuff --- .../projects/import_export/import_export.yml | 4 ++-- .../projects/import_export/project_tree_saver.rb | 2 +- .../import_export/project_tree_saver_spec.rb | 15 ++++++++------- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/app/services/projects/import_export/import_export.yml b/app/services/projects/import_export/import_export.yml index c622447ef0..92f492e901 100644 --- a/app/services/projects/import_export/import_export.yml +++ b/app/services/projects/import_export/import_export.yml @@ -12,8 +12,8 @@ - :merge_requests: - :merge_request_diff - :notes - - :commit_statuses: - - :commit + - :ci_commits: + - :statuses :attributes_only: :project: diff --git a/app/services/projects/import_export/project_tree_saver.rb b/app/services/projects/import_export/project_tree_saver.rb index b2ca85bd7c..37bf3e8e54 100644 --- a/app/services/projects/import_export/project_tree_saver.rb +++ b/app/services/projects/import_export/project_tree_saver.rb @@ -20,7 +20,7 @@ module Projects File.write(full_path, project_json_tree) true rescue - #TODO: handle error + # TODO: handle error false end diff --git a/spec/services/projects/import_export/project_tree_saver_spec.rb b/spec/services/projects/import_export/project_tree_saver_spec.rb index eda9e08cdc..05ece41341 100644 --- a/spec/services/projects/import_export/project_tree_saver_spec.rb +++ b/spec/services/projects/import_export/project_tree_saver_spec.rb @@ -20,9 +20,10 @@ describe Projects::ImportExport::ProjectTreeSaver, services: true do merge_requests: [merge_request], labels: [label], snippets: [snippet], - releases: [release], - commit_statuses: [commit_status]) + releases: [release] + ) end + let!(:ci_commit) { create(:ci_commit, project: project, sha: merge_request.last_commit.id, ref: merge_request.source_branch, statuses: [commit_status]) } let!(:milestone) { create(:milestone, title: "Milestone v1.2", project: project) } let(:export_path) { "#{Dir::tmpdir}/project_tree_saver_spec" } let(:shared) { Projects::ImportExport::Shared.new(relative_path: project.path_with_namespace) } @@ -86,10 +87,6 @@ describe Projects::ImportExport::ProjectTreeSaver, services: true do expect(saved_project_json['issues'].first['notes']).not_to be_empty end - it 'has commit statuses' do - expect(saved_project_json['commit_statuses']).not_to be_empty - end - it 'has project members' do expect(saved_project_json['project_members']).not_to be_empty end @@ -102,8 +99,12 @@ describe Projects::ImportExport::ProjectTreeSaver, services: true do expect(saved_project_json['merge_requests'].first['notes']).not_to be_empty end + it 'has commit statuses' do + expect(saved_project_json['ci_commits'].first['statuses']).not_to be_empty + end + it 'has ci commits' do - expect(saved_project_json['commit_statuses'].first['commit']).not_to be_empty + expect(saved_project_json['ci_commits']).not_to be_empty end end end From 267fd01ce8fa1620d5fd597825c653630909d415 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 13 Apr 2016 17:47:14 +0200 Subject: [PATCH 050/730] fixed import and spec is now passing! --- .../import_export/project_tree_restorer.rb | 3 +- .../import_export/relation_factory.rb | 21 ++- fixtures/import_export/project.json | 170 +++++++++--------- 3 files changed, 99 insertions(+), 95 deletions(-) diff --git a/app/services/projects/import_export/project_tree_restorer.rb b/app/services/projects/import_export/project_tree_restorer.rb index 2d9dee1031..62d3e06fdc 100644 --- a/app/services/projects/import_export/project_tree_restorer.rb +++ b/app/services/projects/import_export/project_tree_restorer.rb @@ -25,14 +25,13 @@ module Projects def create_relations(relation_list = default_relation_list, tree_hash = @tree_hash) saved = [] relation_list.each do |relation| + next if !relation.is_a?(Hash) && tree_hash[relation.to_s].blank? if relation.is_a?(Hash) create_sub_relations(relation, tree_hash) end relation_key = relation.is_a?(Hash) ? relation.keys.first : relation relation_hash = create_relation(relation_key, tree_hash[relation_key.to_s]) saved << project.update_attribute(relation_key, relation_hash) - # FIXME - # next if tree_hash[relation.to_s].blank? end saved.all? end diff --git a/app/services/projects/import_export/relation_factory.rb b/app/services/projects/import_export/relation_factory.rb index 29917fce2b..8fce875722 100644 --- a/app/services/projects/import_export/relation_factory.rb +++ b/app/services/projects/import_export/relation_factory.rb @@ -3,27 +3,21 @@ module Projects module RelationFactory extend self - OVERRIDES = { snippets: :project_snippets, commit: 'Ci::Commit' }.freeze + OVERRIDES = { snippets: :project_snippets, ci_commits: 'Ci::Commit', statuses: 'commit_status' }.freeze USER_REFERENCES = %w(author_id assignee_id updated_by_id).freeze def create(relation_sym:, relation_hash:, members_map:) relation_sym = parse_relation_sym(relation_sym) klass = parse_relation(relation_hash, relation_sym) - handle_merge_requests(relation_hash) if relation_sym == :merge_requests update_user_references(relation_hash, members_map) + update_project_references(relation_hash, klass) imported_object(klass, relation_hash) end private - def handle_merge_requests(relation_hash) - relation_hash['target_project_id'] = relation_hash.delete('project_id') - relation_hash['source_project_id'] = -1 - end - - #TODO nice to have, optimize this to only get called for specific models def update_user_references(relation_hash, members_map) USER_REFERENCES.each do |reference| if relation_hash[reference] @@ -32,6 +26,16 @@ module Projects end end + def update_project_references(relation_hash, klass) + project_id = relation_hash.delete('project_id') + + # project_id may not be part of the export, but we always need to populate it if required. + relation_hash['project_id'] = project_id if klass.column_names.include?('project_id') + relation_hash['gl_project_id'] = project_id if relation_hash ['gl_project_id'] + relation_hash['target_project_id'] = project_id if relation_hash['target_project_id'] + relation_hash['source_project_id'] = -1 if relation_hash['source_project_id'] + end + def relation_class(relation_sym) relation_sym.to_s.classify.constantize end @@ -49,7 +53,6 @@ module Projects def parse_relation(relation_hash, relation_sym) klass = relation_class(relation_sym) relation_hash.delete('id') - relation_hash.delete('project_id') unless klass.column_names.include?('project_id') klass end end diff --git a/fixtures/import_export/project.json b/fixtures/import_export/project.json index a2fed10b85..4a12c951dc 100644 --- a/fixtures/import_export/project.json +++ b/fixtures/import_export/project.json @@ -12,12 +12,12 @@ "issues": [ { "id": 1, - "title": "Ad est est quia inventore eius suscipit molestiae.", + "title": "Debitis vero omnis cum accusamus nihil rerum cupiditate.", "assignee_id": 1, "author_id": 2, - "project_id": 7, - "created_at": "2016-04-12T13:26:48.974Z", - "updated_at": "2016-04-12T13:26:55.496Z", + "project_id": 6, + "created_at": "2016-04-13T14:40:32.471Z", + "updated_at": "2016-04-13T14:40:38.956Z", "position": 0, "branch_name": null, "description": null, @@ -34,8 +34,8 @@ "note": ":+1: issue", "noteable_type": "Issue", "author_id": 21, - "created_at": "2016-04-12T13:26:55.480Z", - "updated_at": "2016-04-12T13:26:55.480Z", + "created_at": "2016-04-13T14:40:38.944Z", + "updated_at": "2016-04-13T14:40:38.944Z", "project_id": 8, "attachment": { "url": null @@ -56,9 +56,9 @@ "id": 1, "title": "label1", "color": "#990000", - "project_id": 7, - "created_at": "2016-04-12T13:26:51.027Z", - "updated_at": "2016-04-12T13:26:53.799Z", + "project_id": 6, + "created_at": "2016-04-13T14:40:34.704Z", + "updated_at": "2016-04-13T14:40:36.891Z", "template": false, "description": null } @@ -67,11 +67,11 @@ { "id": 1, "title": "Milestone v1.2", - "project_id": 7, + "project_id": 6, "description": null, "due_date": null, - "created_at": "2016-04-12T13:26:53.993Z", - "updated_at": "2016-04-12T13:26:53.993Z", + "created_at": "2016-04-13T14:40:37.901Z", + "updated_at": "2016-04-13T14:40:37.901Z", "state": "active", "iid": 1 } @@ -79,13 +79,13 @@ "snippets": [ { "id": 1, - "title": "Possimus harum est mollitia fugiat in.", - "content": "Itaque ipsum culpa quibusdam mollitia.", + "title": "Illo ipsa maxime magni aut.", + "content": "Excepturi delectus ut harum est molestiae dolor.", "author_id": 10, - "project_id": 7, - "created_at": "2016-04-12T13:26:51.821Z", - "updated_at": "2016-04-12T13:26:53.811Z", - "file_name": "thomas_marquardt", + "project_id": 6, + "created_at": "2016-04-13T14:40:35.603Z", + "updated_at": "2016-04-13T14:40:36.903Z", + "file_name": "daphne.mraz", "visibility_level": 0 } ], @@ -94,9 +94,9 @@ "id": 1, "tag": "v1.1.0", "description": "Awesome release", - "project_id": 7, - "created_at": "2016-04-12T13:26:52.353Z", - "updated_at": "2016-04-12T13:26:53.823Z" + "project_id": 6, + "created_at": "2016-04-13T14:40:36.223Z", + "updated_at": "2016-04-13T14:40:36.913Z" } ], "events": [ @@ -106,9 +106,9 @@ "target_id": null, "title": null, "data": null, - "project_id": 7, - "created_at": "2016-04-12T13:26:57.139Z", - "updated_at": "2016-04-12T13:26:57.139Z", + "project_id": 6, + "created_at": "2016-04-13T14:40:40.122Z", + "updated_at": "2016-04-13T14:40:40.122Z", "action": 8, "author_id": 1 } @@ -118,19 +118,19 @@ "id": 1, "user": { "id": 1, - "email": "maybell_auer@gleasonolson.com", - "created_at": "2016-04-12T13:26:47.499Z", - "updated_at": "2016-04-12T13:26:47.499Z", - "name": "Charles Nitzsche", + "email": "norval.gulgowski@schambergerboyle.co.uk", + "created_at": "2016-04-13T14:40:30.963Z", + "updated_at": "2016-04-13T14:40:30.963Z", + "name": "Jalon Cormier DVM", "admin": false, "projects_limit": 42, "skype": "", "linkedin": "", "twitter": "", - "authentication_token": "nCBdoTPWP-5adipsFwEq", + "authentication_token": "tt-mPSZFvRBu8QzkW1Ss", "theme_id": 2, "bio": null, - "username": "koby.zieme1", + "username": "vance.turner1", "can_create_group": true, "can_create_team": false, "state": "active", @@ -144,7 +144,7 @@ }, "hide_no_ssh_key": false, "website_url": "", - "notification_email": "maybell_auer@gleasonolson.com", + "notification_email": "norval.gulgowski@schambergerboyle.co.uk", "hide_no_password": false, "password_automatically_set": false, "location": null, @@ -173,13 +173,13 @@ "source_project_id": 2, "author_id": 5, "assignee_id": null, - "title": "Natus vel molestiae ab et dolorem odit ut.", - "created_at": "2016-04-12T13:26:49.813Z", - "updated_at": "2016-04-12T13:26:56.806Z", + "title": "Dignissimos officia sit aut id dolor iure voluptatem expedita.", + "created_at": "2016-04-13T14:40:33.381Z", + "updated_at": "2016-04-13T14:40:39.850Z", "milestone_id": null, "state": "opened", "merge_status": "can_be_merged", - "target_project_id": 7, + "target_project_id": 6, "iid": 1, "description": null, "position": 0, @@ -353,8 +353,8 @@ } ], "merge_request_id": 1, - "created_at": "2016-04-12T13:26:49.896Z", - "updated_at": "2016-04-12T13:26:50.189Z", + "created_at": "2016-04-13T14:40:33.474Z", + "updated_at": "2016-04-13T14:40:33.834Z", "base_commit_sha": "ae73cb07c9eeaf35924a10f713b364d32b2dd34f", "real_size": "8" }, @@ -364,8 +364,8 @@ "note": ":+1: merge_request", "noteable_type": "MergeRequest", "author_id": 24, - "created_at": "2016-04-12T13:26:56.790Z", - "updated_at": "2016-04-12T13:26:56.790Z", + "created_at": "2016-04-13T14:40:39.832Z", + "updated_at": "2016-04-13T14:40:39.832Z", "project_id": 9, "attachment": { "url": null @@ -381,52 +381,54 @@ ] } ], - "commit_statuses": [ + "ci_commits": [ { - "id": 1, - "project_id": null, - "status": "success", - "finished_at": "2016-01-26T07:23:42.000Z", - "trace": null, - "created_at": "2016-04-12T13:26:53.034Z", - "updated_at": "2016-04-12T13:26:53.850Z", - "started_at": "2016-01-26T07:21:42.000Z", - "runner_id": null, - "coverage": null, - "commit_id": 1, - "commands": null, - "job_id": null, - "name": "default", - "deploy": false, - "options": null, - "allow_failure": false, - "stage": null, - "trigger_request_id": null, - "stage_idx": null, - "tag": null, - "ref": null, - "user_id": null, - "target_url": null, - "description": "commit status", - "artifacts_file": null, - "gl_project_id": 7, - "artifacts_metadata": null, - "erased_by_id": null, - "erased_at": null, - "commit": { - "id": 1, - "project_id": 6, - "ref": null, - "sha": "97de212e80737a608d939f648d959671fb0a0142", - "before_sha": null, - "push_data": null, - "created_at": "2016-04-12T13:26:53.010Z", - "updated_at": "2016-04-12T13:26:53.010Z", - "tag": false, - "yaml_errors": null, - "committed_at": null, - "gl_project_id": 6 - } + "id": 2, + "project_id": 6, + "ref": "master", + "sha": "5937ac0a7beb003549fc5fd26fc247adbce4a52e", + "before_sha": null, + "push_data": null, + "created_at": "2016-04-13T14:40:37.759Z", + "updated_at": "2016-04-13T14:40:37.759Z", + "tag": false, + "yaml_errors": null, + "committed_at": null, + "gl_project_id": 6, + "statuses": [ + { + "id": 1, + "project_id": null, + "status": "success", + "finished_at": "2016-01-26T07:23:42.000Z", + "trace": null, + "created_at": "2016-04-13T14:40:37.717Z", + "updated_at": "2016-04-13T14:40:37.771Z", + "started_at": "2016-01-26T07:21:42.000Z", + "runner_id": null, + "coverage": null, + "commit_id": 2, + "commands": null, + "job_id": null, + "name": "default", + "deploy": false, + "options": null, + "allow_failure": false, + "stage": null, + "trigger_request_id": null, + "stage_idx": null, + "tag": null, + "ref": null, + "user_id": null, + "target_url": null, + "description": "commit status", + "artifacts_file": null, + "gl_project_id": 7, + "artifacts_metadata": null, + "erased_by_id": null, + "erased_at": null + } + ] } ] } \ No newline at end of file From 0852f539aa389c66ef377b7d567c931f928e147f Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 14 Apr 2016 16:57:25 +0200 Subject: [PATCH 051/730] refactored stuff, added a save and compress all class and moved mostly everything to lib --- .../projects/import_export/export_service.rb | 11 ++++-- .../projects => lib/gitlab}/import_export.rb | 6 +-- .../import_export/command_line_util.rb | 16 ++++++-- .../gitlab}/import_export/import_export.yml | 0 .../import_export/import_export_reader.rb | 4 +- .../import_export/project_tree_saver.rb | 5 +-- .../gitlab}/import_export/repo_bundler.rb | 4 +- lib/gitlab/import_export/saver.rb | 38 +++++++++++++++++++ .../gitlab}/import_export/shared.rb | 4 +- .../import_export/wiki_repo_bundler.rb | 2 +- .../import_export_reader_spec.rb | 2 +- .../import_export/project_tree_saver_spec.rb | 8 ++-- .../import_export/repo_bundler_spec.rb | 8 ++-- .../import_export/wiki_repo_bundler_spec.rb | 8 ++-- 14 files changed, 83 insertions(+), 33 deletions(-) rename {app/services/projects => lib/gitlab}/import_export.rb (68%) rename {app/services/projects => lib/gitlab}/import_export/command_line_util.rb (58%) rename {app/services/projects => lib/gitlab}/import_export/import_export.yml (100%) rename {app/services/projects => lib/gitlab}/import_export/import_export_reader.rb (96%) rename {app/services/projects => lib/gitlab}/import_export/project_tree_saver.rb (85%) rename {app/services/projects => lib/gitlab}/import_export/repo_bundler.rb (91%) create mode 100644 lib/gitlab/import_export/saver.rb rename {app/services/projects => lib/gitlab}/import_export/shared.rb (56%) rename {app/services/projects => lib/gitlab}/import_export/wiki_repo_bundler.rb (97%) rename spec/{services/projects => lib/gitlab}/import_export/import_export_reader_spec.rb (92%) rename spec/{services/projects => lib/gitlab}/import_export/project_tree_saver_spec.rb (89%) rename spec/{services/projects => lib/gitlab}/import_export/repo_bundler_spec.rb (55%) rename spec/{services/projects => lib/gitlab}/import_export/wiki_repo_bundler_spec.rb (61%) diff --git a/app/services/projects/import_export/export_service.rb b/app/services/projects/import_export/export_service.rb index 99aa8489f6..ce13942c5d 100644 --- a/app/services/projects/import_export/export_service.rb +++ b/app/services/projects/import_export/export_service.rb @@ -2,19 +2,24 @@ module Projects module ImportExport class ExportService < BaseService def execute(options = {}) - @shared = Projects::ImportExport::Shared.new(relative_path: project.path_with_namespace) + @shared = Gitlab::ImportExport::Shared.new(relative_path: project.path_with_namespace) save_project_tree bundle_repo + save_all end private def save_project_tree - Projects::ImportExport::ProjectTreeSaver.new(project: project, shared: @shared).save + Gitlab::ImportExport::ProjectTreeSaver.new(project: project, shared: @shared).save end def bundle_repo - Projects::ImportExport::RepoBundler.new(project: project, shared: @shared).bundle + Gitlab::ImportExport::RepoBundler.new(project: project, shared: @shared).bundle + end + + def save_all + Gitlab::ImportExport::Saver.save(storage_path: @shared.export_path) end end end diff --git a/app/services/projects/import_export.rb b/lib/gitlab/import_export.rb similarity index 68% rename from app/services/projects/import_export.rb rename to lib/gitlab/import_export.rb index c74f1d3149..fe88850c33 100644 --- a/app/services/projects/import_export.rb +++ b/lib/gitlab/import_export.rb @@ -1,9 +1,9 @@ -module Projects +module Gitlab module ImportExport extend self def export_path(relative_path:) - File.join(storage_path, "#{Time.now.strftime('%Y-%m-%d_%H-%M-%3N')}_gitlab_export/#{relative_path}") + File.join(storage_path, relative_path, "#{Time.now.strftime('%Y-%m-%d_%H-%M-%3N')}_gitlab_export") end def project_atts @@ -11,7 +11,7 @@ module Projects end def project_tree - Projects::ImportExport::ImportExportReader.project_tree + Gitlab::ImportExport::ImportExportReader.project_tree end private diff --git a/app/services/projects/import_export/command_line_util.rb b/lib/gitlab/import_export/command_line_util.rb similarity index 58% rename from app/services/projects/import_export/command_line_util.rb rename to lib/gitlab/import_export/command_line_util.rb index 3ca49e76c7..7bf4b476b6 100644 --- a/app/services/projects/import_export/command_line_util.rb +++ b/lib/gitlab/import_export/command_line_util.rb @@ -1,10 +1,12 @@ -module Projects +module Gitlab module ImportExport module CommandLineUtil def tar_cf(archive:, dir:) - cmd = %W(tar -cf #{archive} -C #{dir} .) - _output, status = Gitlab::Popen.popen(cmd) - status.zero? + tar_with_options(archive: archive, dir: dir, options: 'cf') + end + + def tar_czf(archive:, dir:) + tar_with_options(archive: archive, dir: dir, options: 'czf') end def git_bundle(git_bin_path: Gitlab.config.git.bin_path, repo_path:, bundle_path:) @@ -12,6 +14,12 @@ module Projects _output, status = Gitlab::Popen.popen(cmd) status.zero? end + + def tar_with_options(archive:, dir:, options:) + cmd = %W(tar -#{options} #{archive} -C #{dir} .) + _output, status = Gitlab::Popen.popen(cmd) + status.zero? + end end end end diff --git a/app/services/projects/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml similarity index 100% rename from app/services/projects/import_export/import_export.yml rename to lib/gitlab/import_export/import_export.yml diff --git a/app/services/projects/import_export/import_export_reader.rb b/lib/gitlab/import_export/import_export_reader.rb similarity index 96% rename from app/services/projects/import_export/import_export_reader.rb rename to lib/gitlab/import_export/import_export_reader.rb index 001d24af60..717d3026f9 100644 --- a/app/services/projects/import_export/import_export_reader.rb +++ b/lib/gitlab/import_export/import_export_reader.rb @@ -1,4 +1,4 @@ -module Projects +module Gitlab module ImportExport module ImportExportReader extend self @@ -14,7 +14,7 @@ module Projects private def config - @config ||= YAML.load_file('app/services/projects/import_export/import_export.yml') + @config ||= YAML.load_file('lib/gitlab/import_export/import_export.yml') end def atts_only diff --git a/app/services/projects/import_export/project_tree_saver.rb b/lib/gitlab/import_export/project_tree_saver.rb similarity index 85% rename from app/services/projects/import_export/project_tree_saver.rb rename to lib/gitlab/import_export/project_tree_saver.rb index 37bf3e8e54..b2615f8273 100644 --- a/app/services/projects/import_export/project_tree_saver.rb +++ b/lib/gitlab/import_export/project_tree_saver.rb @@ -1,4 +1,4 @@ -module Projects +module Gitlab module ImportExport class ProjectTreeSaver attr_reader :full_path @@ -25,12 +25,11 @@ module Projects end def project_filename - # TODO sanitize name "#{@project.name}.json" end def project_json_tree - @project.to_json(Projects::ImportExport.project_tree) + @project.to_json(Gitlab::ImportExport.project_tree) end end end diff --git a/app/services/projects/import_export/repo_bundler.rb b/lib/gitlab/import_export/repo_bundler.rb similarity index 91% rename from app/services/projects/import_export/repo_bundler.rb rename to lib/gitlab/import_export/repo_bundler.rb index d43fb4ea09..7a1c2a12a5 100644 --- a/app/services/projects/import_export/repo_bundler.rb +++ b/lib/gitlab/import_export/repo_bundler.rb @@ -1,7 +1,7 @@ -module Projects +module Gitlab module ImportExport class RepoBundler - include Projects::ImportExport::CommandLineUtil + include Gitlab::ImportExport::CommandLineUtil attr_reader :full_path diff --git a/lib/gitlab/import_export/saver.rb b/lib/gitlab/import_export/saver.rb new file mode 100644 index 0000000000..f26804d240 --- /dev/null +++ b/lib/gitlab/import_export/saver.rb @@ -0,0 +1,38 @@ +module Gitlab + module ImportExport + class Saver + include Gitlab::ImportExport::CommandLineUtil + + def self.save(*args) + new(*args).save + end + + def initialize(storage_path:) + @storage_path = storage_path + end + + def save + if compress_and_save + remove_storage_path + archive_file + else + false + end + end + + private + + def compress_and_save + tar_czf(archive: archive_file, dir: @storage_path) + end + + def remove_storage_path + FileUtils.rm_rf(@storage_path) + end + + def archive_file + @archive_file ||= File.join(@storage_path, '..', 'project.tar.gz') + end + end + end +end diff --git a/app/services/projects/import_export/shared.rb b/lib/gitlab/import_export/shared.rb similarity index 56% rename from app/services/projects/import_export/shared.rb rename to lib/gitlab/import_export/shared.rb index 04fe01c0d6..a4ec33a6cf 100644 --- a/app/services/projects/import_export/shared.rb +++ b/lib/gitlab/import_export/shared.rb @@ -1,4 +1,4 @@ -module Projects +module Gitlab module ImportExport class Shared def initialize(opts) @@ -6,7 +6,7 @@ module Projects end def export_path - @export_path ||= Projects::ImportExport.export_path(relative_path: @opts[:relative_path]) + @export_path ||= Gitlab::ImportExport.export_path(relative_path: @opts[:relative_path]) end end end diff --git a/app/services/projects/import_export/wiki_repo_bundler.rb b/lib/gitlab/import_export/wiki_repo_bundler.rb similarity index 97% rename from app/services/projects/import_export/wiki_repo_bundler.rb rename to lib/gitlab/import_export/wiki_repo_bundler.rb index bf69936503..9ef0febee5 100644 --- a/app/services/projects/import_export/wiki_repo_bundler.rb +++ b/lib/gitlab/import_export/wiki_repo_bundler.rb @@ -1,4 +1,4 @@ -module Projects +module Gitlab module ImportExport class WikiRepoBundler < RepoBundler def bundle diff --git a/spec/services/projects/import_export/import_export_reader_spec.rb b/spec/lib/gitlab/import_export/import_export_reader_spec.rb similarity index 92% rename from spec/services/projects/import_export/import_export_reader_spec.rb rename to spec/lib/gitlab/import_export/import_export_reader_spec.rb index f825292ce7..e71c7b60b8 100644 --- a/spec/services/projects/import_export/import_export_reader_spec.rb +++ b/spec/lib/gitlab/import_export/import_export_reader_spec.rb @@ -1,6 +1,6 @@ require 'rspec' -describe Projects::ImportExport::ImportExportReader do +describe Gitlab::ImportExport::ImportExportReader do let(:test_config) { 'spec/support/import_export/import_export.yml' } let(:project_tree_hash) do diff --git a/spec/services/projects/import_export/project_tree_saver_spec.rb b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb similarity index 89% rename from spec/services/projects/import_export/project_tree_saver_spec.rb rename to spec/lib/gitlab/import_export/project_tree_saver_spec.rb index 05ece41341..8a923dde46 100644 --- a/spec/services/projects/import_export/project_tree_saver_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Projects::ImportExport::ProjectTreeSaver, services: true do +describe Gitlab::ImportExport::ProjectTreeSaver, services: true do describe :save do # TODO refactor this into a setup method @@ -26,14 +26,14 @@ describe Projects::ImportExport::ProjectTreeSaver, services: true do let!(:ci_commit) { create(:ci_commit, project: project, sha: merge_request.last_commit.id, ref: merge_request.source_branch, statuses: [commit_status]) } let!(:milestone) { create(:milestone, title: "Milestone v1.2", project: project) } let(:export_path) { "#{Dir::tmpdir}/project_tree_saver_spec" } - let(:shared) { Projects::ImportExport::Shared.new(relative_path: project.path_with_namespace) } - let(:project_tree_saver) { Projects::ImportExport::ProjectTreeSaver.new(project: project, shared: shared) } + let(:shared) { Gitlab::ImportExport::Shared.new(relative_path: project.path_with_namespace) } + let(:project_tree_saver) { Gitlab::ImportExport::ProjectTreeSaver.new(project: project, shared: shared) } let!(:issue_note) { create(:note, note: ":+1: issue", noteable: issue) } let!(:merge_request_note) { create(:note, note: ":+1: merge_request", noteable: merge_request) } before(:each) do project.team << [user, :master] - allow_any_instance_of(Projects::ImportExport).to receive(:storage_path).and_return(export_path) + allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path) end after(:each) do diff --git a/spec/services/projects/import_export/repo_bundler_spec.rb b/spec/lib/gitlab/import_export/repo_bundler_spec.rb similarity index 55% rename from spec/services/projects/import_export/repo_bundler_spec.rb rename to spec/lib/gitlab/import_export/repo_bundler_spec.rb index 1f8ed41718..23447d878a 100644 --- a/spec/services/projects/import_export/repo_bundler_spec.rb +++ b/spec/lib/gitlab/import_export/repo_bundler_spec.rb @@ -1,17 +1,17 @@ require 'spec_helper' -describe Projects::ImportExport::RepoBundler, services: true do +describe Gitlab::ImportExport::RepoBundler, services: true do describe :bundle do let(:user) { create(:user) } let!(:project) { create(:project, :public, name: 'searchable_project') } let(:export_path) { "#{Dir::tmpdir}/project_tree_saver_spec" } - let(:shared) { Projects::ImportExport::Shared.new(relative_path: project.path_with_namespace) } - let(:bundler) { Projects::ImportExport::RepoBundler.new(project: project, shared: shared) } + let(:shared) { Gitlab::ImportExport::Shared.new(relative_path: project.path_with_namespace) } + let(:bundler) { Gitlab::ImportExport::RepoBundler.new(project: project, shared: shared) } before(:each) do project.team << [user, :master] - allow_any_instance_of(Projects::ImportExport).to receive(:storage_path).and_return(export_path) + allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path) end after(:each) do diff --git a/spec/services/projects/import_export/wiki_repo_bundler_spec.rb b/spec/lib/gitlab/import_export/wiki_repo_bundler_spec.rb similarity index 61% rename from spec/services/projects/import_export/wiki_repo_bundler_spec.rb rename to spec/lib/gitlab/import_export/wiki_repo_bundler_spec.rb index a589f81c5f..6cc95edc21 100644 --- a/spec/services/projects/import_export/wiki_repo_bundler_spec.rb +++ b/spec/lib/gitlab/import_export/wiki_repo_bundler_spec.rb @@ -1,18 +1,18 @@ require 'spec_helper' -describe Projects::ImportExport::WikiRepoBundler, services: true do +describe Gitlab::ImportExport::WikiRepoBundler, services: true do describe :bundle do let(:user) { create(:user) } let!(:project) { create(:project, :public, name: 'searchable_project') } let(:export_path) { "#{Dir::tmpdir}/project_tree_saver_spec" } - let(:shared) { Projects::ImportExport::Shared.new(relative_path: project.path_with_namespace) } - let(:wiki_bundler) { Projects::ImportExport::WikiRepoBundler.new(project: project, shared: shared) } + let(:shared) { Gitlab::ImportExport::Shared.new(relative_path: project.path_with_namespace) } + let(:wiki_bundler) { Gitlab::ImportExport::WikiRepoBundler.new(project: project, shared: shared) } let!(:project_wiki) { ProjectWiki.new(project, user) } before(:each) do project.team << [user, :master] - allow_any_instance_of(Projects::ImportExport).to receive(:storage_path).and_return(export_path) + allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path) project_wiki.wiki project_wiki.create_page("index", "test content") end From 97c3aff16fa94cee622cd00ffaa2e3a6469c1439 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 14 Apr 2016 17:10:57 +0200 Subject: [PATCH 052/730] refactored import stuff, moved to lib --- app/services/projects/import_export/import_service.rb | 2 +- .../gitlab}/import_export/members_mapper.rb | 2 +- .../gitlab}/import_export/project_factory.rb | 2 +- .../gitlab}/import_export/project_tree_restorer.rb | 10 +++++----- .../gitlab}/import_export/relation_factory.rb | 2 +- .../gitlab}/import_export/members_mapper_spec.rb | 4 ++-- .../import_export/project_tree_restorer_spec.rb | 4 ++-- 7 files changed, 13 insertions(+), 13 deletions(-) rename {app/services/projects => lib/gitlab}/import_export/members_mapper.rb (99%) rename {app/services/projects => lib/gitlab}/import_export/project_factory.rb (98%) rename {app/services/projects => lib/gitlab}/import_export/project_tree_restorer.rb (89%) rename {app/services/projects => lib/gitlab}/import_export/relation_factory.rb (99%) rename spec/{services/projects => lib/gitlab}/import_export/members_mapper_spec.rb (91%) rename spec/{services/projects => lib/gitlab}/import_export/project_tree_restorer_spec.rb (59%) diff --git a/app/services/projects/import_export/import_service.rb b/app/services/projects/import_export/import_service.rb index 3efddf75e4..d188b2dc83 100644 --- a/app/services/projects/import_export/import_service.rb +++ b/app/services/projects/import_export/import_service.rb @@ -8,7 +8,7 @@ module Projects private def restore_project_tree - Projects::ImportExport::ProjectTreeRestorer.new(path: @import_path).restore + Gitlab::ImportExport::ProjectTreeRestorer.new(path: @import_path).restore end def restore_repo diff --git a/app/services/projects/import_export/members_mapper.rb b/lib/gitlab/import_export/members_mapper.rb similarity index 99% rename from app/services/projects/import_export/members_mapper.rb rename to lib/gitlab/import_export/members_mapper.rb index 6d49d901bf..d6124106f5 100644 --- a/app/services/projects/import_export/members_mapper.rb +++ b/lib/gitlab/import_export/members_mapper.rb @@ -1,4 +1,4 @@ -module Projects +module Gitlab module ImportExport class MembersMapper diff --git a/app/services/projects/import_export/project_factory.rb b/lib/gitlab/import_export/project_factory.rb similarity index 98% rename from app/services/projects/import_export/project_factory.rb rename to lib/gitlab/import_export/project_factory.rb index 1ca0cfb867..c7137844a0 100644 --- a/app/services/projects/import_export/project_factory.rb +++ b/lib/gitlab/import_export/project_factory.rb @@ -1,4 +1,4 @@ -module Projects +module Gitlab module ImportExport module ProjectFactory extend self diff --git a/app/services/projects/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb similarity index 89% rename from app/services/projects/import_export/project_tree_restorer.rb rename to lib/gitlab/import_export/project_tree_restorer.rb index 62d3e06fdc..4c0f6a2267 100644 --- a/app/services/projects/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -1,4 +1,4 @@ -module Projects +module Gitlab module ImportExport class ProjectTreeRestorer attr_reader :project @@ -18,7 +18,7 @@ module Projects private def members_map - @members ||= Projects::ImportExport::MembersMapper.map( + @members ||= Gitlab::ImportExport::MembersMapper.map( exported_members: @project_members, user: @user, project_id: project.id) end @@ -37,7 +37,7 @@ module Projects end def default_relation_list - Projects::ImportExport::ImportExportReader.tree.reject { |model| model.is_a?(Hash) && model[:project_members] } + Gitlab::ImportExport::ImportExportReader.tree.reject { |model| model.is_a?(Hash) && model[:project_members] } end def project @@ -46,7 +46,7 @@ module Projects def create_project project_params = @tree_hash.reject { |_key, value| value.is_a?(Array) } - project = Projects::ImportExport::ProjectFactory.create( + project = Gitlab::ImportExport::ProjectFactory.create( project_params: project_params, user: @user) project.save project @@ -79,7 +79,7 @@ module Projects end def relation_from_factory(relation, relation_hash) - Projects::ImportExport::RelationFactory.create( + Gitlab::ImportExport::RelationFactory.create( relation_sym: relation, relation_hash: relation_hash.merge('project_id' => project.id), members_map: members_map) end end diff --git a/app/services/projects/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb similarity index 99% rename from app/services/projects/import_export/relation_factory.rb rename to lib/gitlab/import_export/relation_factory.rb index 8fce875722..dd992ef443 100644 --- a/app/services/projects/import_export/relation_factory.rb +++ b/lib/gitlab/import_export/relation_factory.rb @@ -1,4 +1,4 @@ -module Projects +module Gitlab module ImportExport module RelationFactory extend self diff --git a/spec/services/projects/import_export/members_mapper_spec.rb b/spec/lib/gitlab/import_export/members_mapper_spec.rb similarity index 91% rename from spec/services/projects/import_export/members_mapper_spec.rb rename to spec/lib/gitlab/import_export/members_mapper_spec.rb index e222dd4205..9175356c64 100644 --- a/spec/services/projects/import_export/members_mapper_spec.rb +++ b/spec/lib/gitlab/import_export/members_mapper_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Projects::ImportExport::MembersMapper, services: true do +describe Gitlab::ImportExport::MembersMapper, services: true do describe :map do let(:user) { create(:user) } @@ -31,7 +31,7 @@ describe Projects::ImportExport::MembersMapper, services: true do end let(:members_mapper) do - Projects::ImportExport::MembersMapper.new( + Gitlab::ImportExport::MembersMapper.new( exported_members: exported_members, user: user, project_id: project.id) end diff --git a/spec/services/projects/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb similarity index 59% rename from spec/services/projects/import_export/project_tree_restorer_spec.rb rename to spec/lib/gitlab/import_export/project_tree_restorer_spec.rb index 4c8d182a21..f3d3a57ddd 100644 --- a/spec/services/projects/import_export/project_tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb @@ -1,10 +1,10 @@ require 'spec_helper' -describe Projects::ImportExport::ProjectTreeRestorer, services: true do +describe Gitlab::ImportExport::ProjectTreeRestorer, services: true do describe :restore do let(:user) { create(:user) } - let(:project_tree_restorer) { Projects::ImportExport::ProjectTreeRestorer.new(path: "fixtures/import_export/project.json", user: user) } + let(:project_tree_restorer) { Gitlab::ImportExport::ProjectTreeRestorer.new(path: "fixtures/import_export/project.json", user: user) } context 'JSON' do let(:restored_project_json) do From 41163fd55251edbfa0d0dd341e34c878563e4981 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 14 Apr 2016 18:01:21 +0200 Subject: [PATCH 053/730] some experimental UI stuff to test export --- app/controllers/projects_controller.rb | 9 +++++++++ .../projects/import_export/export_service.rb | 1 + app/views/projects/edit.html.haml | 13 +++++++++++++ config/routes.rb | 1 + 4 files changed, 24 insertions(+) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 3cc37e5985..39ae3659a8 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -186,6 +186,15 @@ class ProjectsController < Projects::ApplicationController ) end + def export + ::Projects::ImportExport::ExportService.new(@project, current_user).execute + + redirect_to( + project_path(@project), + notice: "Project export successfully started" + ) + end + def toggle_star current_user.toggle_star(@project) @project.reload diff --git a/app/services/projects/import_export/export_service.rb b/app/services/projects/import_export/export_service.rb index ce13942c5d..8b641008a8 100644 --- a/app/services/projects/import_export/export_service.rb +++ b/app/services/projects/import_export/export_service.rb @@ -1,6 +1,7 @@ module Projects module ImportExport class ExportService < BaseService + def execute(options = {}) @shared = Gitlab::ImportExport::Shared.new(relative_path: project.path_with_namespace) save_project_tree diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 6d872cd0b2..8097ef5d88 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -132,6 +132,19 @@ = link_to 'Housekeeping', housekeeping_namespace_project_path(@project.namespace, @project), method: :post, class: "btn btn-default" + .panel.panel-default + .panel-heading Export + .errors-holder + .panel-body + %p + Downloads a compressed version of the project that can be imported. + %br + + .form-actions + = link_to 'Export', export_namespace_project_path(@project.namespace, @project), + method: :post, class: "btn btn-default" + + - if can? current_user, :archive_project, @project - if @project.archived? .panel.panel-success diff --git a/config/routes.rb b/config/routes.rb index 842fbb9984..55d3084ed6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -433,6 +433,7 @@ Rails.application.routes.draw do post :housekeeping post :toggle_star post :markdown_preview + post :export get :autocomplete_sources get :activity end From 05edd5e6dc169e4987e5e98e9243fa85c5b6e4b8 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 15 Apr 2016 15:38:34 +0200 Subject: [PATCH 054/730] download export now working --- app/controllers/projects_controller.rb | 11 ++++++++++- app/views/projects/edit.html.haml | 7 +++++-- config/routes.rb | 1 + 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 39ae3659a8..9fb4370ef9 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -190,11 +190,15 @@ class ProjectsController < Projects::ApplicationController ::Projects::ImportExport::ExportService.new(@project, current_user).execute redirect_to( - project_path(@project), + edit_project_path(@project), notice: "Project export successfully started" ) end + def download_export + send_file export_project_path, disposition: 'attachment' + end + def toggle_star current_user.toggle_star(@project) @project.reload @@ -256,4 +260,9 @@ class ProjectsController < Projects::ApplicationController def get_id project.repository.root_ref end + + def export_project_path + # TODO: move this, probably to ImportExport and refactor + File.join(Settings.shared['path'], 'tmp/project_exports', @project.path_with_namespace, 'project.tar.gz') + end end diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 8097ef5d88..37ac0aa1f5 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -133,7 +133,7 @@ method: :post, class: "btn btn-default" .panel.panel-default - .panel-heading Export + .panel-heading Export project .errors-holder .panel-body %p @@ -141,9 +141,12 @@ %br .form-actions - = link_to 'Export', export_namespace_project_path(@project.namespace, @project), + = link_to 'Generate new export', export_namespace_project_path(@project.namespace, @project), method: :post, class: "btn btn-default" + = link_to 'Download export', download_export_namespace_project_path(@project.namespace, @project), + method: :post, class: "btn btn-default" + - if can? current_user, :archive_project, @project - if @project.archived? diff --git a/config/routes.rb b/config/routes.rb index 55d3084ed6..21164ba0ed 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -434,6 +434,7 @@ Rails.application.routes.draw do post :toggle_star post :markdown_preview post :export + post :download_export get :autocomplete_sources get :activity end From ae777ea0618e8db8a552a831dc331fe7a7b1fe7a Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 15 Apr 2016 18:14:28 +0200 Subject: [PATCH 055/730] WIP - importing file and repo --- .../projects/import_export/import_service.rb | 11 +++++-- lib/gitlab/import_export/command_line_util.rb | 14 +++++++++ lib/gitlab/import_export/importer.rb | 26 ++++++++++++++++ lib/gitlab/import_export/repo_restorer.rb | 31 +++++++++++++++++++ 4 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 lib/gitlab/import_export/importer.rb create mode 100644 lib/gitlab/import_export/repo_restorer.rb diff --git a/app/services/projects/import_export/import_service.rb b/app/services/projects/import_export/import_service.rb index d188b2dc83..b252692cd7 100644 --- a/app/services/projects/import_export/import_service.rb +++ b/app/services/projects/import_export/import_service.rb @@ -2,17 +2,24 @@ module Projects module ImportExport class ExportService < BaseService def execute(options = {}) + @import_path = options[:import_path] + restore_project_tree + restore_repo(project_tree.project) end private def restore_project_tree - Gitlab::ImportExport::ProjectTreeRestorer.new(path: @import_path).restore + project_tree.restore end - def restore_repo + def project_tree + @project_tree ||= Gitlab::ImportExport::ProjectTreeRestorer.new(path: @import_path, user: @current_user) + end + def restore_repo(project) + Gitlab::ImportExport::RepoRestorer.new(path: @import_path, project: project).restore end end end diff --git a/lib/gitlab/import_export/command_line_util.rb b/lib/gitlab/import_export/command_line_util.rb index 7bf4b476b6..f9041e9f4e 100644 --- a/lib/gitlab/import_export/command_line_util.rb +++ b/lib/gitlab/import_export/command_line_util.rb @@ -5,6 +5,14 @@ module Gitlab tar_with_options(archive: archive, dir: dir, options: 'cf') end + def untar_czf(archive:, dir:) + untar_with_options(archive: archive, dir: dir, options: 'czf') + end + + def untar_cf(archive:, dir:) + untar_with_options(archive: archive, dir: dir, options: 'cf') + end + def tar_czf(archive:, dir:) tar_with_options(archive: archive, dir: dir, options: 'czf') end @@ -20,6 +28,12 @@ module Gitlab _output, status = Gitlab::Popen.popen(cmd) status.zero? end + + def untar_with_options(archive:, dir:, options:) + cmd = %W(tar -#{options} #{archive)} -C #{dir}) + _output, status = Gitlab::Popen.popen(cmd) + status.zero? + end end end end diff --git a/lib/gitlab/import_export/importer.rb b/lib/gitlab/import_export/importer.rb new file mode 100644 index 0000000000..79f54000bb --- /dev/null +++ b/lib/gitlab/import_export/importer.rb @@ -0,0 +1,26 @@ +module Gitlab + module ImportExport + class Importer + include Gitlab::ImportExport::CommandLineUtil + + def self.import(*args) + new(*args).import + end + + def initialize(archive_file:, storage_path:) + @archive_file = archive_file + @storage_path = storage_path + end + + def import + decompress_export + end + + private + + def decompress + untar_czf(archive: archive_file, dir: @storage_path) + end + end + end +end diff --git a/lib/gitlab/import_export/repo_restorer.rb b/lib/gitlab/import_export/repo_restorer.rb new file mode 100644 index 0000000000..42126cabd9 --- /dev/null +++ b/lib/gitlab/import_export/repo_restorer.rb @@ -0,0 +1,31 @@ +module Gitlab + module ImportExport + class RepoRestorer + include Gitlab::ImportExport::CommandLineUtil + + def initialize(project: , path: ) + @project = project + @path = path + end + + def restore + return false unless File.exists?(@path) + # Move repos dir to 'repositories.old' dir + + FileUtils.mkdir_p(repos_path) + FileUtils.mkdir_p(path_to_repo) + untar_cf(archive: @path, dir: path_to_repo) + end + + private + + def repos_path + Gitlab.config.gitlab_shell.repos_path + end + + def path_to_repo + @project.repository.path_to_repo + end + end + end +end From 42567436863c96b7f184cc7a728b2da3d18852c8 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 22 Apr 2016 12:18:11 +0200 Subject: [PATCH 056/730] refactored path stuff --- lib/gitlab/import_export.rb | 4 +--- lib/gitlab/import_export/saver.rb | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/gitlab/import_export.rb b/lib/gitlab/import_export.rb index fe88850c33..539eae13f3 100644 --- a/lib/gitlab/import_export.rb +++ b/lib/gitlab/import_export.rb @@ -3,7 +3,7 @@ module Gitlab extend self def export_path(relative_path:) - File.join(storage_path, relative_path, "#{Time.now.strftime('%Y-%m-%d_%H-%M-%3N')}_gitlab_export") + File.join(storage_path, relative_path) end def project_atts @@ -14,8 +14,6 @@ module Gitlab Gitlab::ImportExport::ImportExportReader.project_tree end - private - def storage_path File.join(Settings.shared['path'], 'tmp/project_exports') end diff --git a/lib/gitlab/import_export/saver.rb b/lib/gitlab/import_export/saver.rb index f26804d240..f87e0fdc7e 100644 --- a/lib/gitlab/import_export/saver.rb +++ b/lib/gitlab/import_export/saver.rb @@ -31,7 +31,7 @@ module Gitlab end def archive_file - @archive_file ||= File.join(@storage_path, '..', 'project.tar.gz') + @archive_file ||= File.join(@storage_path, '..', "#{Time.now.strftime('%Y-%m-%d_%H-%M-%3N')}_project_export.tar.gz") end end end From 8f973b8f6887da082c4e4c777dc3961fae32ab16 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 22 Apr 2016 12:45:20 +0200 Subject: [PATCH 057/730] more refactoring - easier guessing path changes --- .../projects/import_export/import_service.rb | 12 ++++++++---- lib/gitlab/import_export/command_line_util.rb | 4 ++-- lib/gitlab/import_export/importer.rb | 8 ++++---- lib/gitlab/import_export/project_tree_restorer.rb | 2 +- lib/gitlab/import_export/repo_restorer.rb | 4 ++-- 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/app/services/projects/import_export/import_service.rb b/app/services/projects/import_export/import_service.rb index b252692cd7..20eda2f228 100644 --- a/app/services/projects/import_export/import_service.rb +++ b/app/services/projects/import_export/import_service.rb @@ -2,8 +2,8 @@ module Projects module ImportExport class ExportService < BaseService def execute(options = {}) - - @import_path = options[:import_path] + archive_file = options[:archive_file] + Gitlab::ImportExport::Importer.import(archive_file: archive_file, storage_path: storage_path) restore_project_tree restore_repo(project_tree.project) end @@ -15,11 +15,15 @@ module Projects end def project_tree - @project_tree ||= Gitlab::ImportExport::ProjectTreeRestorer.new(path: @import_path, user: @current_user) + @project_tree ||= Gitlab::ImportExport::ProjectTreeRestorer.new(path: storage_path, user: @current_user) end def restore_repo(project) - Gitlab::ImportExport::RepoRestorer.new(path: @import_path, project: project).restore + Gitlab::ImportExport::RepoRestorer.new(path: storage_path, project: project).restore + end + + def storage_path + @storage_path ||= Gitlab::ImportExport.export_path(relative_path: project.path_with_namespace) end end end diff --git a/lib/gitlab/import_export/command_line_util.rb b/lib/gitlab/import_export/command_line_util.rb index f9041e9f4e..3665e2edb7 100644 --- a/lib/gitlab/import_export/command_line_util.rb +++ b/lib/gitlab/import_export/command_line_util.rb @@ -24,13 +24,13 @@ module Gitlab end def tar_with_options(archive:, dir:, options:) - cmd = %W(tar -#{options} #{archive} -C #{dir} .) + cmd = %W(tar -#{options} #{archive} -C #{dir}) _output, status = Gitlab::Popen.popen(cmd) status.zero? end def untar_with_options(archive:, dir:, options:) - cmd = %W(tar -#{options} #{archive)} -C #{dir}) + cmd = %W(tar -#{options} #{archive} -C #{dir}) _output, status = Gitlab::Popen.popen(cmd) status.zero? end diff --git a/lib/gitlab/import_export/importer.rb b/lib/gitlab/import_export/importer.rb index 79f54000bb..9f39984543 100644 --- a/lib/gitlab/import_export/importer.rb +++ b/lib/gitlab/import_export/importer.rb @@ -7,19 +7,19 @@ module Gitlab new(*args).import end - def initialize(archive_file:, storage_path:) + def initialize(archive_file: , storage_path:) @archive_file = archive_file @storage_path = storage_path end def import - decompress_export + decompress_archive end private - def decompress - untar_czf(archive: archive_file, dir: @storage_path) + def decompress_archive + untar_czf(archive: @archive_file, dir: @storage_path) end end end diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index 4c0f6a2267..4e0f555afe 100644 --- a/lib/gitlab/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -4,7 +4,7 @@ module Gitlab attr_reader :project def initialize(path:, user:) - @path = path + @path = File.join(path, 'project.json') @user = user end diff --git a/lib/gitlab/import_export/repo_restorer.rb b/lib/gitlab/import_export/repo_restorer.rb index 42126cabd9..47be303e22 100644 --- a/lib/gitlab/import_export/repo_restorer.rb +++ b/lib/gitlab/import_export/repo_restorer.rb @@ -3,9 +3,9 @@ module Gitlab class RepoRestorer include Gitlab::ImportExport::CommandLineUtil - def initialize(project: , path: ) + def initialize(project: , path:, bundler_file: ) @project = project - @path = path + @path = File.join(path, bundler_file) end def restore From fedfba55194ed51c6a7510c01fa94091e92c71cf Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 22 Apr 2016 12:49:37 +0200 Subject: [PATCH 058/730] more refactoring - easier guessing path changes --- lib/gitlab/import_export/project_tree_saver.rb | 2 +- lib/gitlab/import_export/repo_bundler.rb | 2 +- lib/gitlab/import_export/wiki_repo_bundler.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/gitlab/import_export/project_tree_saver.rb b/lib/gitlab/import_export/project_tree_saver.rb index b2615f8273..f6fab0fe22 100644 --- a/lib/gitlab/import_export/project_tree_saver.rb +++ b/lib/gitlab/import_export/project_tree_saver.rb @@ -25,7 +25,7 @@ module Gitlab end def project_filename - "#{@project.name}.json" + "project.json" end def project_json_tree diff --git a/lib/gitlab/import_export/repo_bundler.rb b/lib/gitlab/import_export/repo_bundler.rb index 7a1c2a12a5..86c9501b70 100644 --- a/lib/gitlab/import_export/repo_bundler.rb +++ b/lib/gitlab/import_export/repo_bundler.rb @@ -27,7 +27,7 @@ module Gitlab end def project_filename - "#{@project.name}.bundle" + "project.bundle" end def path_to_repo diff --git a/lib/gitlab/import_export/wiki_repo_bundler.rb b/lib/gitlab/import_export/wiki_repo_bundler.rb index 9ef0febee5..7821c67162 100644 --- a/lib/gitlab/import_export/wiki_repo_bundler.rb +++ b/lib/gitlab/import_export/wiki_repo_bundler.rb @@ -19,7 +19,7 @@ module Gitlab private def project_filename - "#{@project.name}.wiki.bundle" + "project.wiki.bundle" end def path_to_repo From acf297955a5546161ac5e52589ba4740f234a0ae Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 22 Apr 2016 17:44:59 +0200 Subject: [PATCH 059/730] gitlab import UI - icon, file selector, etc... Also updated font-awesome and modified import source settings. --- Gemfile | 2 +- Gemfile.lock | 4 ++-- app/assets/javascripts/behaviors/toggler_behavior.coffee | 1 + app/controllers/application_controller.rb | 6 +++++- app/models/application_setting.rb | 2 +- app/views/projects/_project_import_form.html.haml | 8 ++++++++ app/views/projects/new.html.haml | 9 ++++++++- db/schema.rb | 4 ++-- lib/gitlab/current_settings.rb | 2 +- lib/gitlab/import_sources.rb | 1 + 10 files changed, 30 insertions(+), 9 deletions(-) create mode 100644 app/views/projects/_project_import_form.html.haml diff --git a/Gemfile b/Gemfile index 67cc3f34b8..f8bd26f36f 100644 --- a/Gemfile +++ b/Gemfile @@ -213,7 +213,7 @@ gem 'jquery-turbolinks', '~> 2.1.0' gem 'addressable', '~> 2.3.8' gem 'bootstrap-sass', '~> 3.3.0' -gem 'font-awesome-rails', '~> 4.2' +gem 'font-awesome-rails', '~> 4.6.1' gem 'gitlab_emoji', '~> 0.3.0' gem 'gon', '~> 6.0.1' gem 'jquery-atwho-rails', '~> 1.3.2' diff --git a/Gemfile.lock b/Gemfile.lock index b00d7b35c8..7ce19ba7b7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -322,7 +322,7 @@ GEM fog-xml (0.1.2) fog-core nokogiri (~> 1.5, >= 1.5.11) - font-awesome-rails (4.5.0.1) + font-awesome-rails (4.6.1.0) railties (>= 3.2, < 5.1) foreman (0.78.0) thor (~> 0.19.1) @@ -931,7 +931,7 @@ DEPENDENCIES flay flog fog (~> 1.36.0) - font-awesome-rails (~> 4.2) + font-awesome-rails (~> 4.6.1) foreman fuubar (~> 2.0.0) gemnasium-gitlab-service (~> 0.2) diff --git a/app/assets/javascripts/behaviors/toggler_behavior.coffee b/app/assets/javascripts/behaviors/toggler_behavior.coffee index 177b691827..640cdfe15f 100644 --- a/app/assets/javascripts/behaviors/toggler_behavior.coffee +++ b/app/assets/javascripts/behaviors/toggler_behavior.coffee @@ -7,6 +7,7 @@ $ -> # %div.js-toggle-content # $("body").on "click", ".js-toggle-button", (e) -> + console.log(e); $(@).find('i'). toggleClass('fa fa-chevron-down'). toggleClass('fa fa-chevron-up') diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 1c53b0b21a..7afde111a3 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -23,7 +23,7 @@ class ApplicationController < ActionController::Base protect_from_forgery with: :exception helper_method :abilities, :can?, :current_application_settings - helper_method :import_sources_enabled?, :github_import_enabled?, :github_import_configured?, :gitlab_import_enabled?, :gitlab_import_configured?, :bitbucket_import_enabled?, :bitbucket_import_configured?, :gitorious_import_enabled?, :google_code_import_enabled?, :fogbugz_import_enabled?, :git_import_enabled? + helper_method :import_sources_enabled?, :github_import_enabled?, :github_import_configured?, :gitlab_import_enabled?, :gitlab_import_configured?, :bitbucket_import_enabled?, :bitbucket_import_configured?, :gitorious_import_enabled?, :google_code_import_enabled?, :fogbugz_import_enabled?, :git_import_enabled?, :gitlab_project_import_enabled? rescue_from Encoding::CompatibilityError do |exception| log_exception(exception) @@ -325,6 +325,10 @@ class ApplicationController < ActionController::Base current_application_settings.import_sources.include?('git') end + def gitlab_project_import_enabled? + current_application_settings.import_sources.include?('gitlab_project') + end + def two_factor_authentication_required? current_application_settings.require_two_factor_authentication end diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 36f8815423..4e2c7c8240 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -147,7 +147,7 @@ class ApplicationSetting < ActiveRecord::Base default_project_visibility: Settings.gitlab.default_projects_features['visibility_level'], default_snippet_visibility: Settings.gitlab.default_projects_features['visibility_level'], restricted_signup_domains: Settings.gitlab['restricted_signup_domains'], - import_sources: ['github','bitbucket','gitlab','gitorious','google_code','fogbugz','git'], + import_sources: ['github','bitbucket','gitlab','gitorious','google_code','fogbugz','git', 'gitlab_project'], shared_runners_enabled: Settings.gitlab_ci['shared_runners_enabled'], max_artifacts_size: Settings.artifacts['max_size'], require_two_factor_authentication: false, diff --git a/app/views/projects/_project_import_form.html.haml b/app/views/projects/_project_import_form.html.haml new file mode 100644 index 0000000000..62d4b55424 --- /dev/null +++ b/app/views/projects/_project_import_form.html.haml @@ -0,0 +1,8 @@ +.form-group.import-url-data + = f.label :import_url, class: 'control-label' do + %span GitLab export file + .col-sm-10 + = f.file_field :file, class: '' + + .well.prepend-top-20 + The project must have a valid Gitlab export format \ No newline at end of file diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index a4c6094c69..cf24c4cacf 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -88,10 +88,17 @@ - if git_import_enabled? = link_to "#", class: 'btn js-toggle-button import_git' do %i.fa.fa-git - %span Any repo by URL + %span Repo by URL + + - if gitlab_project_import_enabled? + = link_to "#", class: 'btn import_gitlab_project', onclick: '$(".js-toggle-content2").toggle();' do + %i.fa.fa-gitlab + %span GitLab project .js-toggle-content.hide = render "shared/import_form", f: f + .js-toggle-content2.hide + = render "project_import_form", f: f .prepend-botton-10 diff --git a/db/schema.rb b/db/schema.rb index 42457d9235..f7dfd296ae 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -78,8 +78,8 @@ ActiveRecord::Schema.define(version: 20160421130527) do t.boolean "email_author_in_body", default: false t.integer "default_group_visibility" t.boolean "repository_checks_enabled", default: false - t.integer "metrics_packet_size", default: 1 t.text "shared_runners_text" + t.integer "metrics_packet_size", default: 1 end create_table "audit_events", force: :cascade do |t| @@ -426,9 +426,9 @@ ActiveRecord::Schema.define(version: 20160421130527) do t.string "state" t.integer "iid" t.integer "updated_by_id" - t.integer "moved_to_id" t.boolean "confidential", default: false t.datetime "deleted_at" + t.integer "moved_to_id" t.date "due_date" end diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb index f44d1b3a44..688e780c13 100644 --- a/lib/gitlab/current_settings.rb +++ b/lib/gitlab/current_settings.rb @@ -29,7 +29,7 @@ module Gitlab default_project_visibility: Settings.gitlab.default_projects_features['visibility_level'], default_snippet_visibility: Settings.gitlab.default_projects_features['visibility_level'], restricted_signup_domains: Settings.gitlab['restricted_signup_domains'], - import_sources: ['github','bitbucket','gitlab','gitorious','google_code','fogbugz','git'], + import_sources: ['github','bitbucket','gitlab','gitorious','google_code','fogbugz','git', 'gitlab_project'], shared_runners_enabled: Settings.gitlab_ci['shared_runners_enabled'], max_artifacts_size: Settings.artifacts['max_size'], require_two_factor_authentication: false, diff --git a/lib/gitlab/import_sources.rb b/lib/gitlab/import_sources.rb index ccfdfbe73e..2b5658a8b6 100644 --- a/lib/gitlab/import_sources.rb +++ b/lib/gitlab/import_sources.rb @@ -21,6 +21,7 @@ module Gitlab 'Google Code' => 'google_code', 'FogBugz' => 'fogbugz', 'Any repo by URL' => 'git', + 'GitLab project' => 'gitlab_project' } end From e5a59331cf5221d39f9430480d449f30bbe8e63f Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 22 Apr 2016 17:56:20 +0200 Subject: [PATCH 060/730] remove debug statement --- app/assets/javascripts/behaviors/toggler_behavior.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/app/assets/javascripts/behaviors/toggler_behavior.coffee b/app/assets/javascripts/behaviors/toggler_behavior.coffee index 640cdfe15f..177b691827 100644 --- a/app/assets/javascripts/behaviors/toggler_behavior.coffee +++ b/app/assets/javascripts/behaviors/toggler_behavior.coffee @@ -7,7 +7,6 @@ $ -> # %div.js-toggle-content # $("body").on "click", ".js-toggle-button", (e) -> - console.log(e); $(@).find('i'). toggleClass('fa fa-chevron-down'). toggleClass('fa fa-chevron-up') From 10f1609535742173d8747d3a1097ed7e919fb9e2 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 25 Apr 2016 18:00:15 +0200 Subject: [PATCH 061/730] changes to be picked by the UI branch --- .../import/gitlab_project_controller.rb | 46 +++++++++++++++++++ config/routes.rb | 6 +++ .../gitlab}/import_export/import_service.rb | 19 ++++++-- 3 files changed, 66 insertions(+), 5 deletions(-) create mode 100644 app/controllers/import/gitlab_project_controller.rb rename {app/services/projects => lib/gitlab}/import_export/import_service.rb (63%) diff --git a/app/controllers/import/gitlab_project_controller.rb b/app/controllers/import/gitlab_project_controller.rb new file mode 100644 index 0000000000..fa3e0c7876 --- /dev/null +++ b/app/controllers/import/gitlab_project_controller.rb @@ -0,0 +1,46 @@ +class Import::GitlabProjectController < Import::BaseController + before_action :verify_gitlab_project_import_enabled + before_action :gitlab_project_auth, except: :callback + + rescue_from OAuth::Error, with: :gitlab_project_unauthorized + + #TODO permissions stuff + + def callback + + redirect_to status_import_gitlab_project_url + end + + def status + @repos = client.projects + @incompatible_repos = client.incompatible_projects + + @already_added_projects = current_user.created_projects.where(import_type: "gitlab_project") + already_added_projects_names = @already_added_projects.pluck(:import_source) + + @repos.to_a.reject!{ |repo| already_added_projects_names.include? "#{repo["owner"]}/#{repo["slug"]}" } + end + + def jobs + jobs = current_user.created_projects.where(import_type: "gitlab_project").to_json(only: [:id, :import_status]) + render json: jobs + end + + def create + @file = params[:file] + # @project_name = + + repo_owner = current_user.username + @target_namespace = params[:new_namespace].presence || repo_owner + + namespace = get_or_create_namespace || (render and return) + + @project = Gitlab::ImportExport::ImportService.execute(archive_file: file, owner: repo_owner) + end + + private + + def verify_gitlab_project_import_enabled + render_404 unless gitlab_project_import_enabled? + end +end diff --git a/config/routes.rb b/config/routes.rb index 79b62a0b1b..df6116b6ea 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -156,6 +156,12 @@ Rails.application.routes.draw do get :new_user_map, path: :user_map post :create_user_map, path: :user_map end + + resource :gitlab_project, only: [:create, :new], controller: :gitlab_projects do + get :status + get :callback + get :jobs + end end # diff --git a/app/services/projects/import_export/import_service.rb b/lib/gitlab/import_export/import_service.rb similarity index 63% rename from app/services/projects/import_export/import_service.rb rename to lib/gitlab/import_export/import_service.rb index 20eda2f228..978a581f57 100644 --- a/app/services/projects/import_export/import_service.rb +++ b/lib/gitlab/import_export/import_service.rb @@ -1,9 +1,18 @@ -module Projects +module Gitlab module ImportExport - class ExportService < BaseService - def execute(options = {}) - archive_file = options[:archive_file] - Gitlab::ImportExport::Importer.import(archive_file: archive_file, storage_path: storage_path) + class ImportService + + def self.execute(*args) + new(args).execute + end + + def initialize(options = {}) + @archive_file = options[:archive_file] + @current_user = options[:owner] + end + + def execute + Gitlab::ImportExport::Importer.import(archive_file: @archive_file, storage_path: storage_path) restore_project_tree restore_repo(project_tree.project) end From 28b0208e93cbc949e1c733c60ec577740d824623 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 26 Apr 2016 10:59:00 +0200 Subject: [PATCH 062/730] refactoring, mainly UI stuff to follow other import actions --- ...oller.rb => gitlab_projects_controller.rb} | 7 +-- .../import/gitlab_projects/new.html.haml | 17 ++++++ .../import/gitlab_projects/status.html.haml | 55 +++++++++++++++++++ .../projects/_project_import_form.html.haml | 8 --- app/views/projects/new.html.haml | 4 +- config/routes.rb | 1 - 6 files changed, 76 insertions(+), 16 deletions(-) rename app/controllers/import/{gitlab_project_controller.rb => gitlab_projects_controller.rb} (86%) create mode 100644 app/views/import/gitlab_projects/new.html.haml create mode 100644 app/views/import/gitlab_projects/status.html.haml delete mode 100644 app/views/projects/_project_import_form.html.haml diff --git a/app/controllers/import/gitlab_project_controller.rb b/app/controllers/import/gitlab_projects_controller.rb similarity index 86% rename from app/controllers/import/gitlab_project_controller.rb rename to app/controllers/import/gitlab_projects_controller.rb index fa3e0c7876..c99c97893a 100644 --- a/app/controllers/import/gitlab_project_controller.rb +++ b/app/controllers/import/gitlab_projects_controller.rb @@ -1,14 +1,13 @@ -class Import::GitlabProjectController < Import::BaseController +class Import::GitlabProjectsController < Import::BaseController before_action :verify_gitlab_project_import_enabled - before_action :gitlab_project_auth, except: :callback + #before_action :gitlab_project_auth, except: :callback rescue_from OAuth::Error, with: :gitlab_project_unauthorized #TODO permissions stuff - def callback + def new - redirect_to status_import_gitlab_project_url end def status diff --git a/app/views/import/gitlab_projects/new.html.haml b/app/views/import/gitlab_projects/new.html.haml new file mode 100644 index 0000000000..64ea536698 --- /dev/null +++ b/app/views/import/gitlab_projects/new.html.haml @@ -0,0 +1,17 @@ +- page_title "FogBugz Import" +- header_title "Projects", root_path +%h3.page-title + %i.fa.fa-bug + Import projects from FogBugz +%hr + += form_tag status_import_gitlab_project_url, class: 'form-horizontal' do + %p + To get started you add your project export file below. + .form-group + = label_tag :file, class: 'control-label' do + %span GitLab export file + .col-sm-10 + = file_field_tag :file, class: '' + .form-actions + = submit_tag 'Continue to the next step', class: 'btn btn-create' diff --git a/app/views/import/gitlab_projects/status.html.haml b/app/views/import/gitlab_projects/status.html.haml new file mode 100644 index 0000000000..2b879f0c59 --- /dev/null +++ b/app/views/import/gitlab_projects/status.html.haml @@ -0,0 +1,55 @@ +- page_title "Gitlab_project import" +- header_title "Projects", root_path +%h3.page-title + %i.icon-gitlab.icon-gitlab-big + Import Gitlab projects + +%p.light + Select projects you want to import. +%hr +%p + = button_tag class: "btn btn-import btn-success js-import-all" do + Import all projects + = icon("spinner spin", class: "loading-icon") + +.table-responsive + %table.table.import-jobs + %colgroup.import-jobs-from-col + %colgroup.import-jobs-to-col + %colgroup.import-jobs-status-col + %thead + %tr + %th From Gitlab_project.org + %th To GitLab + %th Status + %tbody + - @already_added_projects.each do |project| + %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"} + %td + = link_to project.import_source, "https://gitlab_project.org/#{project.import_source}", target: "_blank" + %td + = link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project] + %td.job-status + - if project.import_status == 'finished' + %span + %i.fa.fa-check + done + - elsif project.import_status == 'started' + %i.fa.fa-spinner.fa-spin + started + - else + = project.human_import_status_name + + - @repos.each do |repo| + %tr{id: "repo_#{repo.id}"} + %td + = link_to repo.full_name, "https://gitlab_project.org/#{repo.full_name}", target: "_blank" + %td.import-target + = repo.full_name + %td.import-actions.job-status + = button_tag class: "btn btn-import js-add-to-import" do + Import + = icon("spinner spin", class: "loading-icon") + +:javascript + new ImporterStatus("#{jobs_import_gitlab_project_path}", "#{import_gitlab_project_path}"); diff --git a/app/views/projects/_project_import_form.html.haml b/app/views/projects/_project_import_form.html.haml deleted file mode 100644 index 62d4b55424..0000000000 --- a/app/views/projects/_project_import_form.html.haml +++ /dev/null @@ -1,8 +0,0 @@ -.form-group.import-url-data - = f.label :import_url, class: 'control-label' do - %span GitLab export file - .col-sm-10 - = f.file_field :file, class: '' - - .well.prepend-top-20 - The project must have a valid Gitlab export format \ No newline at end of file diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index cf24c4cacf..d4bb57aafc 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -91,14 +91,12 @@ %span Repo by URL - if gitlab_project_import_enabled? - = link_to "#", class: 'btn import_gitlab_project', onclick: '$(".js-toggle-content2").toggle();' do + = link_to new_import_gitlab_project_path, class: 'btn import_gitlab_project' do %i.fa.fa-gitlab %span GitLab project .js-toggle-content.hide = render "shared/import_form", f: f - .js-toggle-content2.hide - = render "project_import_form", f: f .prepend-botton-10 diff --git a/config/routes.rb b/config/routes.rb index b4e1abd276..05e89e8150 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -159,7 +159,6 @@ Rails.application.routes.draw do resource :gitlab_project, only: [:create, :new], controller: :gitlab_projects do get :status - get :callback get :jobs end end From 1d4c3fa1507fdfdecdc15091ac8ef8d9f5fb63d9 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 26 Apr 2016 13:01:51 +0200 Subject: [PATCH 063/730] more refactoring, now using custom job for processing project imports --- .../import/gitlab_projects_controller.rb | 4 ++-- app/models/project.rb | 10 +++++++++ .../import/gitlab_projects/new.html.haml | 2 +- app/workers/project_import_worker.rb | 22 +++++++++++++++++++ config/routes.rb | 1 + 5 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 app/workers/project_import_worker.rb diff --git a/app/controllers/import/gitlab_projects_controller.rb b/app/controllers/import/gitlab_projects_controller.rb index c99c97893a..0e94915765 100644 --- a/app/controllers/import/gitlab_projects_controller.rb +++ b/app/controllers/import/gitlab_projects_controller.rb @@ -26,7 +26,7 @@ class Import::GitlabProjectsController < Import::BaseController end def create - @file = params[:file] + file = params[:file] # @project_name = repo_owner = current_user.username @@ -34,7 +34,7 @@ class Import::GitlabProjectsController < Import::BaseController namespace = get_or_create_namespace || (render and return) - @project = Gitlab::ImportExport::ImportService.execute(archive_file: file, owner: repo_owner) + @project = Project.create_from_import_job(current_user.id, File.expand_path(file.path)) end private diff --git a/app/models/project.rb b/app/models/project.rb index 0420c6a61a..18e647045c 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -359,6 +359,16 @@ class Project < ActiveRecord::Base def visible_to_user(user) where(id: user.authorized_projects.select(:id).reorder(nil)) end + + def create_from_import_job(current_user_id:, tmp_file:) + job_id = ProjectImportWorker.perform_async(current_user_id, tmp_file) + + if job_id + Rails.logger.info "Import job started for #{path_with_namespace} with job ID #{job_id}" + else + Rails.logger.error "Import job failed to start for #{path_with_namespace}" + end + end end def team diff --git a/app/views/import/gitlab_projects/new.html.haml b/app/views/import/gitlab_projects/new.html.haml index 64ea536698..9e798b8a63 100644 --- a/app/views/import/gitlab_projects/new.html.haml +++ b/app/views/import/gitlab_projects/new.html.haml @@ -5,7 +5,7 @@ Import projects from FogBugz %hr -= form_tag status_import_gitlab_project_url, class: 'form-horizontal' do += form_tag import_gitlab_project_path, class: 'form-horizontal' do %p To get started you add your project export file below. .form-group diff --git a/app/workers/project_import_worker.rb b/app/workers/project_import_worker.rb new file mode 100644 index 0000000000..6dd514b56a --- /dev/null +++ b/app/workers/project_import_worker.rb @@ -0,0 +1,22 @@ +class ProjectImportWorker + include Sidekiq::Worker + include Gitlab::ShellAdapter + + sidekiq_options queue: :gitlab_shell + + def perform(current_user_id, tmp_file) + current_user = User.find(current_user_id) + + project = Gitlab::ImportExport::ImportService.execute(archive_file: tmp_file, owner: current_user) + + # TODO: Move this to import service + # if result[:status] == :error + # project.update(import_error: result[:message]) + # project.import_fail + # return + # end + + project.repository.after_import + project.import_finish + end +end diff --git a/config/routes.rb b/config/routes.rb index 05e89e8150..99ce011810 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -159,6 +159,7 @@ Rails.application.routes.draw do resource :gitlab_project, only: [:create, :new], controller: :gitlab_projects do get :status + post :create get :jobs end end From cbbc42e0c4e5888413a690a4e0760e3cadd55a63 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 26 Apr 2016 17:12:50 +0200 Subject: [PATCH 064/730] adding more UI changes, updated controller, worker and refactored import service --- .../import/gitlab_projects_controller.rb | 17 +++++++++++----- app/models/project.rb | 8 ++++---- .../import/gitlab_projects/new.html.haml | 2 +- app/workers/project_import_worker.rb | 9 ++++++--- lib/gitlab/import_export/import_service.rb | 20 ++++++++++++------- .../import_export/project_tree_restorer.rb | 1 + 6 files changed, 37 insertions(+), 20 deletions(-) diff --git a/app/controllers/import/gitlab_projects_controller.rb b/app/controllers/import/gitlab_projects_controller.rb index 0e94915765..36be79a39c 100644 --- a/app/controllers/import/gitlab_projects_controller.rb +++ b/app/controllers/import/gitlab_projects_controller.rb @@ -7,7 +7,8 @@ class Import::GitlabProjectsController < Import::BaseController #TODO permissions stuff def new - + @namespace_id = project_params[:namespace_id] + @path = project_params[:path] end def status @@ -27,14 +28,14 @@ class Import::GitlabProjectsController < Import::BaseController def create file = params[:file] - # @project_name = repo_owner = current_user.username @target_namespace = params[:new_namespace].presence || repo_owner - namespace = get_or_create_namespace || (render and return) - - @project = Project.create_from_import_job(current_user.id, File.expand_path(file.path)) + @project = Project.create_from_import_job(current_user_id: current_user.id, + tmp_file: File.expand_path(file.path), + namespace_id: @namespace_id, + project_path: @path) end private @@ -42,4 +43,10 @@ class Import::GitlabProjectsController < Import::BaseController def verify_gitlab_project_import_enabled render_404 unless gitlab_project_import_enabled? end + + def project_params + params.require(:project).permit( + :path, :namespace_id, + ) + end end diff --git a/app/models/project.rb b/app/models/project.rb index 18e647045c..70921e0275 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -360,13 +360,13 @@ class Project < ActiveRecord::Base where(id: user.authorized_projects.select(:id).reorder(nil)) end - def create_from_import_job(current_user_id:, tmp_file:) - job_id = ProjectImportWorker.perform_async(current_user_id, tmp_file) + def create_from_import_job(current_user_id:, tmp_file:, namespace_id:, project_path:) + job_id = ProjectImportWorker.perform_async(current_user_id, tmp_file, namespace_id, project_path) if job_id - Rails.logger.info "Import job started for #{path_with_namespace} with job ID #{job_id}" + Rails.logger.info "Import job started for export #{tmp_file} with job ID #{job_id}" else - Rails.logger.error "Import job failed to start for #{path_with_namespace}" + Rails.logger.error "Import job failed to start for #{tmp_file}" end end end diff --git a/app/views/import/gitlab_projects/new.html.haml b/app/views/import/gitlab_projects/new.html.haml index 9e798b8a63..323b7810c5 100644 --- a/app/views/import/gitlab_projects/new.html.haml +++ b/app/views/import/gitlab_projects/new.html.haml @@ -5,7 +5,7 @@ Import projects from FogBugz %hr -= form_tag import_gitlab_project_path, class: 'form-horizontal' do += form_tag import_gitlab_project_path, class: 'form-horizontal', multipart: true do %p To get started you add your project export file below. .form-group diff --git a/app/workers/project_import_worker.rb b/app/workers/project_import_worker.rb index 6dd514b56a..0e8b955244 100644 --- a/app/workers/project_import_worker.rb +++ b/app/workers/project_import_worker.rb @@ -2,12 +2,15 @@ class ProjectImportWorker include Sidekiq::Worker include Gitlab::ShellAdapter - sidekiq_options queue: :gitlab_shell + sidekiq_options queue: :gitlab_shell, retry: false - def perform(current_user_id, tmp_file) + def perform(current_user_id, tmp_file, namespace_id, path) current_user = User.find(current_user_id) - project = Gitlab::ImportExport::ImportService.execute(archive_file: tmp_file, owner: current_user) + project = Gitlab::ImportExport::ImportService.execute(archive_file: tmp_file, + owner: current_user, + namespace_id: namespace_id, + project_path: path) # TODO: Move this to import service # if result[:status] == :error diff --git a/lib/gitlab/import_export/import_service.rb b/lib/gitlab/import_export/import_service.rb index 978a581f57..5152d6ac18 100644 --- a/lib/gitlab/import_export/import_service.rb +++ b/lib/gitlab/import_export/import_service.rb @@ -6,15 +6,17 @@ module Gitlab new(args).execute end - def initialize(options = {}) - @archive_file = options[:archive_file] - @current_user = options[:owner] + def initialize(archive_file:, owner:, namespace_id:, project_path:) + @archive_file = archive_file + @current_user = owner + @namespace_path = Namespace.find(namespace_id).path + @project_path = project_path end def execute Gitlab::ImportExport::Importer.import(archive_file: @archive_file, storage_path: storage_path) restore_project_tree - restore_repo(project_tree.project) + restore_repo end private @@ -27,12 +29,16 @@ module Gitlab @project_tree ||= Gitlab::ImportExport::ProjectTreeRestorer.new(path: storage_path, user: @current_user) end - def restore_repo(project) - Gitlab::ImportExport::RepoRestorer.new(path: storage_path, project: project).restore + def restore_repo + Gitlab::ImportExport::RepoRestorer.new(path: storage_path, project: project_tree.project).restore end def storage_path - @storage_path ||= Gitlab::ImportExport.export_path(relative_path: project.path_with_namespace) + @storage_path ||= Gitlab::ImportExport.export_path(relative_path: path_with_namespace) + end + + def path_with_namespace + File.join(@namespace_path, @project_path) end end end diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index 4e0f555afe..445f1d884d 100644 --- a/lib/gitlab/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -49,6 +49,7 @@ module Gitlab project = Gitlab::ImportExport::ProjectFactory.create( project_params: project_params, user: @user) project.save + project.import_start project end From 34c826a3110700f401fac4242f6a5dd15884f33d Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 27 Apr 2016 15:01:55 +0200 Subject: [PATCH 065/730] some JS magic to pass namespace and path importing projects --- app/controllers/import/gitlab_projects_controller.rb | 9 ++++++--- app/views/import/gitlab_projects/new.html.haml | 3 +++ app/views/projects/new.html.haml | 6 +++++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/app/controllers/import/gitlab_projects_controller.rb b/app/controllers/import/gitlab_projects_controller.rb index 36be79a39c..b141b5f472 100644 --- a/app/controllers/import/gitlab_projects_controller.rb +++ b/app/controllers/import/gitlab_projects_controller.rb @@ -27,15 +27,18 @@ class Import::GitlabProjectsController < Import::BaseController end def create + # TODO verify access to namespace and path file = params[:file] + namespace_id = project_params[:namespace_id] + path = project_params[:path] repo_owner = current_user.username @target_namespace = params[:new_namespace].presence || repo_owner @project = Project.create_from_import_job(current_user_id: current_user.id, tmp_file: File.expand_path(file.path), - namespace_id: @namespace_id, - project_path: @path) + namespace_id: namespace_id, + project_path: path) end private @@ -45,7 +48,7 @@ class Import::GitlabProjectsController < Import::BaseController end def project_params - params.require(:project).permit( + params.permit( :path, :namespace_id, ) end diff --git a/app/views/import/gitlab_projects/new.html.haml b/app/views/import/gitlab_projects/new.html.haml index 323b7810c5..1158a04ea4 100644 --- a/app/views/import/gitlab_projects/new.html.haml +++ b/app/views/import/gitlab_projects/new.html.haml @@ -9,9 +9,12 @@ %p To get started you add your project export file below. .form-group + = hidden_field_tag :namespace_id, @namespace_id + = hidden_field_tag :path, @path = label_tag :file, class: 'control-label' do %span GitLab export file .col-sm-10 = file_field_tag :file, class: '' + .form-actions = submit_tag 'Continue to the next step', class: 'btn btn-create' diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index d4bb57aafc..b3d755b379 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -91,7 +91,7 @@ %span Repo by URL - if gitlab_project_import_enabled? - = link_to new_import_gitlab_project_path, class: 'btn import_gitlab_project' do + = link_to new_import_gitlab_project_path, class: 'btn import_gitlab_project project-submit' do %i.fa.fa-gitlab %span GitLab project @@ -127,3 +127,7 @@ $('.modal-header .close').bind('click', function() { $(".modal").hide(); }); + $('.import_gitlab_project').bind('click', function() { + var _href = $("a.import_gitlab_project").attr("href"); + $(".import_gitlab_project").attr("href", _href + '?namespace_id=' + $("#project_namespace_id").val() + '&path=' + $("#project_path").val()); + }); From cec4ae55b728c76f797ada20125d5bbf2af0adb9 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 27 Apr 2016 18:07:40 +0200 Subject: [PATCH 066/730] quite a few fixes - import service --- lib/gitlab/import_export/command_line_util.rb | 12 +++--------- lib/gitlab/import_export/import_service.rb | 4 ++-- lib/gitlab/import_export/importer.rb | 1 + lib/gitlab/import_export/project_tree_restorer.rb | 4 +++- 4 files changed, 9 insertions(+), 12 deletions(-) diff --git a/lib/gitlab/import_export/command_line_util.rb b/lib/gitlab/import_export/command_line_util.rb index 3665e2edb7..e8d41a6bd3 100644 --- a/lib/gitlab/import_export/command_line_util.rb +++ b/lib/gitlab/import_export/command_line_util.rb @@ -6,11 +6,11 @@ module Gitlab end def untar_czf(archive:, dir:) - untar_with_options(archive: archive, dir: dir, options: 'czf') + tar_with_options(archive: archive, dir: dir, options: 'czf') end def untar_cf(archive:, dir:) - untar_with_options(archive: archive, dir: dir, options: 'cf') + tar_with_options(archive: archive, dir: dir, options: 'cf') end def tar_czf(archive:, dir:) @@ -24,13 +24,7 @@ module Gitlab end def tar_with_options(archive:, dir:, options:) - cmd = %W(tar -#{options} #{archive} -C #{dir}) - _output, status = Gitlab::Popen.popen(cmd) - status.zero? - end - - def untar_with_options(archive:, dir:, options:) - cmd = %W(tar -#{options} #{archive} -C #{dir}) + cmd = %W(tar -#{options} #{archive} #{dir}) _output, status = Gitlab::Popen.popen(cmd) status.zero? end diff --git a/lib/gitlab/import_export/import_service.rb b/lib/gitlab/import_export/import_service.rb index 5152d6ac18..226499030a 100644 --- a/lib/gitlab/import_export/import_service.rb +++ b/lib/gitlab/import_export/import_service.rb @@ -3,7 +3,7 @@ module Gitlab class ImportService def self.execute(*args) - new(args).execute + new(*args).execute end def initialize(archive_file:, owner:, namespace_id:, project_path:) @@ -26,7 +26,7 @@ module Gitlab end def project_tree - @project_tree ||= Gitlab::ImportExport::ProjectTreeRestorer.new(path: storage_path, user: @current_user) + @project_tree ||= Gitlab::ImportExport::ProjectTreeRestorer.new(path: storage_path, user: @current_user, project_path: @project_path) end def restore_repo diff --git a/lib/gitlab/import_export/importer.rb b/lib/gitlab/import_export/importer.rb index 9f39984543..225e6f3499 100644 --- a/lib/gitlab/import_export/importer.rb +++ b/lib/gitlab/import_export/importer.rb @@ -13,6 +13,7 @@ module Gitlab end def import + FileUtils.mkdir_p(@storage_path) decompress_archive end diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index 445f1d884d..7b41ba0685 100644 --- a/lib/gitlab/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -3,9 +3,10 @@ module Gitlab class ProjectTreeRestorer attr_reader :project - def initialize(path:, user:) + def initialize(path:, user:, project_path:) @path = File.join(path, 'project.json') @user = user + @project_path = project_path end def restore @@ -48,6 +49,7 @@ module Gitlab project_params = @tree_hash.reject { |_key, value| value.is_a?(Array) } project = Gitlab::ImportExport::ProjectFactory.create( project_params: project_params, user: @user) + project.path = @project_path project.save project.import_start project From 5908bdf3edb6f59674789e3d210999406d455f67 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 28 Apr 2016 13:53:16 +0200 Subject: [PATCH 067/730] fixing a few tar issues - and using gnu tar only --- lib/gitlab/import_export/command_line_util.rb | 14 ++++++++++---- lib/gitlab/import_export/importer.rb | 2 +- lib/gitlab/import_export/repo_restorer.rb | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/gitlab/import_export/command_line_util.rb b/lib/gitlab/import_export/command_line_util.rb index e8d41a6bd3..1140e7beb9 100644 --- a/lib/gitlab/import_export/command_line_util.rb +++ b/lib/gitlab/import_export/command_line_util.rb @@ -5,12 +5,12 @@ module Gitlab tar_with_options(archive: archive, dir: dir, options: 'cf') end - def untar_czf(archive:, dir:) - tar_with_options(archive: archive, dir: dir, options: 'czf') + def untar_zxf(archive:, dir:) + untar_with_options(archive: archive, dir: dir, options: 'zxf') end - def untar_cf(archive:, dir:) - tar_with_options(archive: archive, dir: dir, options: 'cf') + def untar_czf(archive:, dir:) + untar_with_options(archive: archive, dir: dir, options: 'xf') end def tar_czf(archive:, dir:) @@ -28,6 +28,12 @@ module Gitlab _output, status = Gitlab::Popen.popen(cmd) status.zero? end + + def untar_with_options(archive:, dir:, options:) + cmd = %W(tar -#{options} #{archive} -C #{dir}) + _output, status = Gitlab::Popen.popen(cmd) + status.zero? + end end end end diff --git a/lib/gitlab/import_export/importer.rb b/lib/gitlab/import_export/importer.rb index 225e6f3499..8f838287f9 100644 --- a/lib/gitlab/import_export/importer.rb +++ b/lib/gitlab/import_export/importer.rb @@ -20,7 +20,7 @@ module Gitlab private def decompress_archive - untar_czf(archive: @archive_file, dir: @storage_path) + untar_zxf(archive: @archive_file, dir: @storage_path) end end end diff --git a/lib/gitlab/import_export/repo_restorer.rb b/lib/gitlab/import_export/repo_restorer.rb index 47be303e22..aa90f05368 100644 --- a/lib/gitlab/import_export/repo_restorer.rb +++ b/lib/gitlab/import_export/repo_restorer.rb @@ -14,7 +14,7 @@ module Gitlab FileUtils.mkdir_p(repos_path) FileUtils.mkdir_p(path_to_repo) - untar_cf(archive: @path, dir: path_to_repo) + untar_czf(archive: @path, dir: path_to_repo) end private From c5bc262981a9fbfe748dfb0b527e4fb0fa597ccf Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 28 Apr 2016 18:00:30 +0200 Subject: [PATCH 068/730] few fixes - import from UI working --- app/controllers/projects_controller.rb | 4 +++- app/services/projects/import_export/export_service.rb | 2 +- lib/gitlab/import_export/command_line_util.rb | 2 +- lib/gitlab/import_export/saver.rb | 1 + 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 1d4684ca22..62f8b376c1 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -191,6 +191,7 @@ class ProjectsController < Projects::ApplicationController end def export + #TODO: Move to worker ::Projects::ImportExport::ExportService.new(@project, current_user).execute redirect_to( @@ -267,6 +268,7 @@ class ProjectsController < Projects::ApplicationController def export_project_path # TODO: move this, probably to ImportExport and refactor - File.join(Settings.shared['path'], 'tmp/project_exports', @project.path_with_namespace, 'project.tar.gz') + folder = File.join(Settings.shared['path'], 'tmp/project_exports', @project.path_with_namespace) + Dir.glob("#{folder}/*export.tar.gz").max_by {|f| File.ctime(f)} end end diff --git a/app/services/projects/import_export/export_service.rb b/app/services/projects/import_export/export_service.rb index 8b641008a8..5d5573cba5 100644 --- a/app/services/projects/import_export/export_service.rb +++ b/app/services/projects/import_export/export_service.rb @@ -3,7 +3,7 @@ module Projects class ExportService < BaseService def execute(options = {}) - @shared = Gitlab::ImportExport::Shared.new(relative_path: project.path_with_namespace) + @shared = Gitlab::ImportExport::Shared.new(relative_path: File.join(project.path_with_namespace, 'work')) save_project_tree bundle_repo save_all diff --git a/lib/gitlab/import_export/command_line_util.rb b/lib/gitlab/import_export/command_line_util.rb index 1140e7beb9..9fc83afc4f 100644 --- a/lib/gitlab/import_export/command_line_util.rb +++ b/lib/gitlab/import_export/command_line_util.rb @@ -24,7 +24,7 @@ module Gitlab end def tar_with_options(archive:, dir:, options:) - cmd = %W(tar -#{options} #{archive} #{dir}) + cmd = %W(tar -#{options} #{archive} -C #{dir} .) _output, status = Gitlab::Popen.popen(cmd) status.zero? end diff --git a/lib/gitlab/import_export/saver.rb b/lib/gitlab/import_export/saver.rb index f87e0fdc7e..634e58e603 100644 --- a/lib/gitlab/import_export/saver.rb +++ b/lib/gitlab/import_export/saver.rb @@ -14,6 +14,7 @@ module Gitlab def save if compress_and_save remove_storage_path + Rails.logger.info("Saved project export #{archive_file}") archive_file else false From 3a609038748055a27c7e01cf4b55d8249709c9cc Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Fri, 15 Apr 2016 13:06:44 +0530 Subject: [PATCH 069/730] Allow creating Personal Access Tokens through the website. --- .../personal_access_tokens_controller.rb | 22 ++++++++++ app/models/personal_access_token.rb | 9 ++++ app/models/user.rb | 1 + .../personal_access_tokens/create.html.haml | 2 + .../personal_access_tokens/index.html.haml | 44 +++++++++++++++++++ config/routes.rb | 1 + ...415062917_create_personal_access_tokens.rb | 11 +++++ db/schema.rb | 14 ++++++ 8 files changed, 104 insertions(+) create mode 100644 app/controllers/profiles/personal_access_tokens_controller.rb create mode 100644 app/models/personal_access_token.rb create mode 100644 app/views/profiles/personal_access_tokens/create.html.haml create mode 100644 app/views/profiles/personal_access_tokens/index.html.haml create mode 100644 db/migrate/20160415062917_create_personal_access_tokens.rb diff --git a/app/controllers/profiles/personal_access_tokens_controller.rb b/app/controllers/profiles/personal_access_tokens_controller.rb new file mode 100644 index 0000000000..dbf06cb4c6 --- /dev/null +++ b/app/controllers/profiles/personal_access_tokens_controller.rb @@ -0,0 +1,22 @@ +class Profiles::PersonalAccessTokensController < ApplicationController + def index + @user = current_user + @personal_access_token = current_user.personal_access_tokens.new + end + + def create + @personal_access_token = current_user.personal_access_tokens.generate(personal_access_token_params) + + if @personal_access_token.save + redirect_to profile_personal_access_tokens_path, notice: "Created personal access token!" + else + render :index + end + end + + private + + def personal_access_token_params + params.require(:personal_access_token).permit(:name) + end +end diff --git a/app/models/personal_access_token.rb b/app/models/personal_access_token.rb new file mode 100644 index 0000000000..29f2275475 --- /dev/null +++ b/app/models/personal_access_token.rb @@ -0,0 +1,9 @@ +class PersonalAccessToken < ActiveRecord::Base + belongs_to :user + + def self.generate(params) + personal_access_token = self.new(params) + personal_access_token.token = Devise.friendly_token(50) + personal_access_token + end +end diff --git a/app/models/user.rb b/app/models/user.rb index b6f405c698..7ac30d21cb 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -109,6 +109,7 @@ class User < ActiveRecord::Base # Profile has_many :keys, dependent: :destroy has_many :emails, dependent: :destroy + has_many :personal_access_tokens, dependent: :destroy has_many :identities, dependent: :destroy, autosave: true # Groups diff --git a/app/views/profiles/personal_access_tokens/create.html.haml b/app/views/profiles/personal_access_tokens/create.html.haml new file mode 100644 index 0000000000..89da41a75e --- /dev/null +++ b/app/views/profiles/personal_access_tokens/create.html.haml @@ -0,0 +1,2 @@ +%h1 Profiles::PersonalAccessTokens#create +%p Find me in app/views/profiles/personal_access_tokens/create.html.haml diff --git a/app/views/profiles/personal_access_tokens/index.html.haml b/app/views/profiles/personal_access_tokens/index.html.haml new file mode 100644 index 0000000000..05eed3c5c3 --- /dev/null +++ b/app/views/profiles/personal_access_tokens/index.html.haml @@ -0,0 +1,44 @@ +- page_title "Personal Access Tokens" +- header_title page_title, profile_personal_access_tokens_path + +.row.prepend-top-default + .col-lg-3.profile-settings-sidebar + %h4.prepend-top-0 + = page_title + %p + You can generate a personal access token for each application you use that needs access to GitLab. + .col-lg-9 + %h5.prepend-top-0 + Add a Personal Access Token + %p.profile-settings-content + Pick a name for the application, and we'll give you a unique token. + = form_for [:profile, @personal_access_token], method: :post, html: { class: 'js-requires-input' } do |f| + + .form-group + = f.label :name, class: 'label-light' + = f.text_field :name, class: "form-control", required: true + + .prepend-top-default + = f.submit 'Add Personal Access Token', class: "btn btn-create" + + %hr + + %h5 + Active Personal Access Tokens + + - if @user.personal_access_tokens.exists? + .table-responsive + %table.table.table-striped + %thead + %tr + %th Name + %th Token + %th Created At + %tbody + - @user.personal_access_tokens.each do |token| + %tr + %td= token.name + %td= token.token + %td= token.created_at + - else + %span You don't have any tokens yet. \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index d664434e1a..d1be826d2a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -333,6 +333,7 @@ Rails.application.routes.draw do resources :keys resources :emails, only: [:index, :create, :destroy] resource :avatar, only: [:destroy] + resources :personal_access_tokens, only: [:index, :create] resource :two_factor_auth, only: [:new, :create, :destroy] do member do post :codes diff --git a/db/migrate/20160415062917_create_personal_access_tokens.rb b/db/migrate/20160415062917_create_personal_access_tokens.rb new file mode 100644 index 0000000000..42a41349a0 --- /dev/null +++ b/db/migrate/20160415062917_create_personal_access_tokens.rb @@ -0,0 +1,11 @@ +class CreatePersonalAccessTokens < ActiveRecord::Migration + def change + create_table :personal_access_tokens do |t| + t.references :user, index: true, foreign_key: true, null: false + t.string :token, index: {unique: true}, null: false + t.string :name, null: false + + t.timestamps null: false + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 42457d9235..05c9700397 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -704,6 +704,19 @@ ActiveRecord::Schema.define(version: 20160421130527) do add_index "oauth_applications", ["owner_id", "owner_type"], name: "index_oauth_applications_on_owner_id_and_owner_type", using: :btree add_index "oauth_applications", ["uid"], name: "index_oauth_applications_on_uid", unique: true, using: :btree + create_table "personal_access_tokens", force: :cascade do |t| + t.integer "user_id", null: false + t.string "token", null: false + t.string "name", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.boolean "revoked", default: false + t.datetime "expires_at" + end + + add_index "personal_access_tokens", ["token"], name: "index_personal_access_tokens_on_token", unique: true, using: :btree + add_index "personal_access_tokens", ["user_id"], name: "index_personal_access_tokens_on_user_id", using: :btree + create_table "project_group_links", force: :cascade do |t| t.integer "project_id", null: false t.integer "group_id", null: false @@ -1030,4 +1043,5 @@ ActiveRecord::Schema.define(version: 20160421130527) do add_index "web_hooks", ["created_at", "id"], name: "index_web_hooks_on_created_at_and_id", using: :btree add_index "web_hooks", ["project_id"], name: "index_web_hooks_on_project_id", using: :btree + add_foreign_key "personal_access_tokens", "users" end From e8314ccca5ff1cd9cf2b1d1aeccd699598b384a5 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Fri, 15 Apr 2016 19:37:21 +0530 Subject: [PATCH 070/730] Refactor `API::Helpers` into `API::Helpers::Core` and `API::Helpers::Authentication` --- lib/api/api.rb | 4 +- lib/api/helpers.rb | 385 ------------------------------ lib/api/helpers/authentication.rb | 41 ++++ lib/api/helpers/core.rb | 351 +++++++++++++++++++++++++++ lib/ci/api/api.rb | 3 +- spec/requests/api/users_spec.rb | 2 +- 6 files changed, 398 insertions(+), 388 deletions(-) delete mode 100644 lib/api/helpers.rb create mode 100644 lib/api/helpers/authentication.rb create mode 100644 lib/api/helpers/core.rb diff --git a/lib/api/api.rb b/lib/api/api.rb index cc1004f800..537678863c 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -1,4 +1,5 @@ Dir["#{Rails.root}/lib/api/*.rb"].each {|file| require file} +Dir["#{Rails.root}/lib/api/helpers/*.rb"].each {|file| require file} module API class API < Grape::API @@ -25,7 +26,8 @@ module API format :json content_type :txt, "text/plain" - helpers Helpers + helpers Helpers::Core + helpers Helpers::Authentication mount Groups mount GroupMembers diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb deleted file mode 100644 index 5bbf721321..0000000000 --- a/lib/api/helpers.rb +++ /dev/null @@ -1,385 +0,0 @@ -module API - module Helpers - PRIVATE_TOKEN_HEADER = "HTTP_PRIVATE_TOKEN" - PRIVATE_TOKEN_PARAM = :private_token - SUDO_HEADER ="HTTP_SUDO" - SUDO_PARAM = :sudo - - def parse_boolean(value) - [ true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON' ].include?(value) - end - - def current_user - private_token = (params[PRIVATE_TOKEN_PARAM] || env[PRIVATE_TOKEN_HEADER]).to_s - @current_user ||= (User.find_by(authentication_token: private_token) || doorkeeper_guard) - - unless @current_user && Gitlab::UserAccess.allowed?(@current_user) - return nil - end - - identifier = sudo_identifier() - - # If the sudo is the current user do nothing - if identifier && !(@current_user.id == identifier || @current_user.username == identifier) - render_api_error!('403 Forbidden: Must be admin to use sudo', 403) unless @current_user.is_admin? - @current_user = User.by_username_or_id(identifier) - not_found!("No user id or username for: #{identifier}") if @current_user.nil? - end - - @current_user - end - - def sudo_identifier() - identifier ||= params[SUDO_PARAM] || env[SUDO_HEADER] - - # Regex for integers - if !!(identifier =~ /^[0-9]+$/) - identifier.to_i - else - identifier - end - end - - def user_project - @project ||= find_project(params[:id]) - @project || not_found!("Project") - end - - def find_project(id) - project = Project.find_with_namespace(id) || Project.find_by(id: id) - - if project && can?(current_user, :read_project, project) - project - else - nil - end - end - - def project_service - @project_service ||= begin - underscored_service = params[:service_slug].underscore - - if Service.available_services_names.include?(underscored_service) - user_project.build_missing_services - - service_method = "#{underscored_service}_service" - - send_service(service_method) - end - end - - @project_service || not_found!("Service") - end - - def send_service(service_method) - user_project.send(service_method) - end - - def service_attributes - @service_attributes ||= project_service.fields.inject([]) do |arr, hash| - arr << hash[:name].to_sym - end - end - - def find_group(id) - begin - group = Group.find(id) - rescue ActiveRecord::RecordNotFound - group = Group.find_by!(path: id) - end - - if can?(current_user, :read_group, group) - group - else - not_found!('Group') - end - end - - def paginate(relation) - relation.page(params[:page]).per(params[:per_page].to_i).tap do |data| - add_pagination_headers(data) - end - end - - def authenticate! - unauthorized! unless current_user - end - - def authenticate_by_gitlab_shell_token! - input = params['secret_token'].try(:chomp) - unless Devise.secure_compare(secret_token, input) - unauthorized! - end - end - - def authenticated_as_admin! - forbidden! unless current_user.is_admin? - end - - def authorize!(action, subject) - forbidden! unless abilities.allowed?(current_user, action, subject) - end - - def authorize_push_project - authorize! :push_code, user_project - end - - def authorize_admin_project - authorize! :admin_project, user_project - end - - def require_gitlab_workhorse! - unless env['HTTP_GITLAB_WORKHORSE'].present? - forbidden!('Request should be executed via GitLab Workhorse') - end - end - - def can?(object, action, subject) - abilities.allowed?(object, action, subject) - end - - # Checks the occurrences of required attributes, each attribute must be present in the params hash - # or a Bad Request error is invoked. - # - # Parameters: - # keys (required) - A hash consisting of keys that must be present - def required_attributes!(keys) - keys.each do |key| - bad_request!(key) unless params[key].present? - end - end - - def attributes_for_keys(keys, custom_params = nil) - params_hash = custom_params || params - attrs = {} - keys.each do |key| - if params_hash[key].present? or (params_hash.has_key?(key) and params_hash[key] == false) - attrs[key] = params_hash[key] - end - end - ActionController::Parameters.new(attrs).permit! - end - - # Helper method for validating all labels against its names - def validate_label_params(params) - errors = {} - - if params[:labels].present? - params[:labels].split(',').each do |label_name| - label = user_project.labels.create_with( - color: Label::DEFAULT_COLOR).find_or_initialize_by( - title: label_name.strip) - - if label.invalid? - errors[label.title] = label.errors - end - end - end - - errors - end - - def validate_access_level?(level) - Gitlab::Access.options_with_owner.values.include? level.to_i - end - - def issuable_order_by - if params["order_by"] == 'updated_at' - 'updated_at' - else - 'created_at' - end - end - - def issuable_sort - if params["sort"] == 'asc' - :asc - else - :desc - end - end - - def filter_by_iid(items, iid) - items.where(iid: iid) - end - - # error helpers - - def forbidden!(reason = nil) - message = ['403 Forbidden'] - message << " - #{reason}" if reason - render_api_error!(message.join(' '), 403) - end - - def bad_request!(attribute) - message = ["400 (Bad request)"] - message << "\"" + attribute.to_s + "\" not given" - render_api_error!(message.join(' '), 400) - end - - def not_found!(resource = nil) - message = ["404"] - message << resource if resource - message << "Not Found" - render_api_error!(message.join(' '), 404) - end - - def unauthorized! - render_api_error!('401 Unauthorized', 401) - end - - def not_allowed! - render_api_error!('405 Method Not Allowed', 405) - end - - def conflict!(message = nil) - render_api_error!(message || '409 Conflict', 409) - end - - def file_to_large! - render_api_error!('413 Request Entity Too Large', 413) - end - - def not_modified! - render_api_error!('304 Not Modified', 304) - end - - def render_validation_error!(model) - if model.errors.any? - render_api_error!(model.errors.messages || '400 Bad Request', 400) - end - end - - def render_api_error!(message, status) - error!({ 'message' => message }, status) - end - - # Projects helpers - - def filter_projects(projects) - # If the archived parameter is passed, limit results accordingly - if params[:archived].present? - projects = projects.where(archived: parse_boolean(params[:archived])) - end - - if params[:search].present? - projects = projects.search(params[:search]) - end - - if params[:visibility].present? - projects = projects.search_by_visibility(params[:visibility]) - end - - projects.reorder(project_order_by => project_sort) - end - - def project_order_by - order_fields = %w(id name path created_at updated_at last_activity_at) - - if order_fields.include?(params['order_by']) - params['order_by'] - else - 'created_at' - end - end - - def project_sort - if params["sort"] == 'asc' - :asc - else - :desc - end - end - - # file helpers - - def uploaded_file(field, uploads_path) - if params[field] - bad_request!("#{field} is not a file") unless params[field].respond_to?(:filename) - return params[field] - end - - return nil unless params["#{field}.path"] && params["#{field}.name"] - - # sanitize file paths - # this requires all paths to exist - required_attributes! %W(#{field}.path) - uploads_path = File.realpath(uploads_path) - file_path = File.realpath(params["#{field}.path"]) - bad_request!('Bad file path') unless file_path.start_with?(uploads_path) - - UploadedFile.new( - file_path, - params["#{field}.name"], - params["#{field}.type"] || 'application/octet-stream', - ) - end - - def present_file!(path, filename, content_type = 'application/octet-stream') - filename ||= File.basename(path) - header['Content-Disposition'] = "attachment; filename=#{filename}" - header['Content-Transfer-Encoding'] = 'binary' - content_type content_type - - # Support download acceleration - case headers['X-Sendfile-Type'] - when 'X-Sendfile' - header['X-Sendfile'] = path - body - else - file FileStreamer.new(path) - end - end - - private - - def add_pagination_headers(paginated_data) - header 'X-Total', paginated_data.total_count.to_s - header 'X-Total-Pages', paginated_data.total_pages.to_s - header 'X-Per-Page', paginated_data.limit_value.to_s - header 'X-Page', paginated_data.current_page.to_s - header 'X-Next-Page', paginated_data.next_page.to_s - header 'X-Prev-Page', paginated_data.prev_page.to_s - header 'Link', pagination_links(paginated_data) - end - - def pagination_links(paginated_data) - request_url = request.url.split('?').first - request_params = params.clone - request_params[:per_page] = paginated_data.limit_value - - links = [] - - request_params[:page] = paginated_data.current_page - 1 - links << %(<#{request_url}?#{request_params.to_query}>; rel="prev") unless paginated_data.first_page? - - request_params[:page] = paginated_data.current_page + 1 - links << %(<#{request_url}?#{request_params.to_query}>; rel="next") unless paginated_data.last_page? - - request_params[:page] = 1 - links << %(<#{request_url}?#{request_params.to_query}>; rel="first") - - request_params[:page] = paginated_data.total_pages - links << %(<#{request_url}?#{request_params.to_query}>; rel="last") - - links.join(', ') - end - - def abilities - @abilities ||= begin - abilities = Six.new - abilities << Ability - abilities - end - end - - def secret_token - File.read(Gitlab.config.gitlab_shell.secret_file).chomp - end - - def handle_member_errors(errors) - error!(errors[:access_level], 422) if errors[:access_level].any? - not_found!(errors) - end - end -end diff --git a/lib/api/helpers/authentication.rb b/lib/api/helpers/authentication.rb new file mode 100644 index 0000000000..8c7bb2c8cd --- /dev/null +++ b/lib/api/helpers/authentication.rb @@ -0,0 +1,41 @@ +module API + module Helpers + module Authentication + PRIVATE_TOKEN_HEADER = "HTTP_PRIVATE_TOKEN" + PRIVATE_TOKEN_PARAM = :private_token + SUDO_HEADER ="HTTP_SUDO" + SUDO_PARAM = :sudo + + def current_user + private_token = (params[PRIVATE_TOKEN_PARAM] || env[PRIVATE_TOKEN_HEADER]).to_s + @current_user ||= (User.find_by(authentication_token: private_token) || doorkeeper_guard) + + unless @current_user && Gitlab::UserAccess.allowed?(@current_user) + return nil + end + + identifier = sudo_identifier() + + # If the sudo is the current user do nothing + if identifier && !(@current_user.id == identifier || @current_user.username == identifier) + render_api_error!('403 Forbidden: Must be admin to use sudo', 403) unless @current_user.is_admin? + @current_user = User.by_username_or_id(identifier) + not_found!("No user id or username for: #{identifier}") if @current_user.nil? + end + + @current_user + end + + def sudo_identifier() + identifier ||= params[SUDO_PARAM] || env[SUDO_HEADER] + + # Regex for integers + if !!(identifier =~ /^[0-9]+$/) + identifier.to_i + else + identifier + end + end + end + end +end \ No newline at end of file diff --git a/lib/api/helpers/core.rb b/lib/api/helpers/core.rb new file mode 100644 index 0000000000..c37064d49a --- /dev/null +++ b/lib/api/helpers/core.rb @@ -0,0 +1,351 @@ +module API + module Helpers + module Core + def parse_boolean(value) + [ true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON' ].include?(value) + end + + def user_project + @project ||= find_project(params[:id]) + @project || not_found!("Project") + end + + def find_project(id) + project = Project.find_with_namespace(id) || Project.find_by(id: id) + + if project && can?(current_user, :read_project, project) + project + else + nil + end + end + + def project_service + @project_service ||= begin + underscored_service = params[:service_slug].underscore + + if Service.available_services_names.include?(underscored_service) + user_project.build_missing_services + + service_method = "#{underscored_service}_service" + + send_service(service_method) + end + end + + @project_service || not_found!("Service") + end + + def send_service(service_method) + user_project.send(service_method) + end + + def service_attributes + @service_attributes ||= project_service.fields.inject([]) do |arr, hash| + arr << hash[:name].to_sym + end + end + + def find_group(id) + begin + group = Group.find(id) + rescue ActiveRecord::RecordNotFound + group = Group.find_by!(path: id) + end + + if can?(current_user, :read_group, group) + group + else + not_found!('Group') + end + end + + def paginate(relation) + relation.page(params[:page]).per(params[:per_page].to_i).tap do |data| + add_pagination_headers(data) + end + end + + def authenticate! + unauthorized! unless current_user + end + + def authenticate_by_gitlab_shell_token! + input = params['secret_token'].try(:chomp) + unless Devise.secure_compare(secret_token, input) + unauthorized! + end + end + + def authenticated_as_admin! + forbidden! unless current_user.is_admin? + end + + def authorize!(action, subject) + forbidden! unless abilities.allowed?(current_user, action, subject) + end + + def authorize_push_project + authorize! :push_code, user_project + end + + def authorize_admin_project + authorize! :admin_project, user_project + end + + def require_gitlab_workhorse! + unless env['HTTP_GITLAB_WORKHORSE'].present? + forbidden!('Request should be executed via GitLab Workhorse') + end + end + + def can?(object, action, subject) + abilities.allowed?(object, action, subject) + end + + # Checks the occurrences of required attributes, each attribute must be present in the params hash + # or a Bad Request error is invoked. + # + # Parameters: + # keys (required) - A hash consisting of keys that must be present + def required_attributes!(keys) + keys.each do |key| + bad_request!(key) unless params[key].present? + end + end + + def attributes_for_keys(keys, custom_params = nil) + params_hash = custom_params || params + attrs = {} + keys.each do |key| + if params_hash[key].present? or (params_hash.has_key?(key) and params_hash[key] == false) + attrs[key] = params_hash[key] + end + end + ActionController::Parameters.new(attrs).permit! + end + + # Helper method for validating all labels against its names + def validate_label_params(params) + errors = {} + + if params[:labels].present? + params[:labels].split(',').each do |label_name| + label = user_project.labels.create_with( + color: Label::DEFAULT_COLOR).find_or_initialize_by( + title: label_name.strip) + + if label.invalid? + errors[label.title] = label.errors + end + end + end + + errors + end + + def validate_access_level?(level) + Gitlab::Access.options_with_owner.values.include? level.to_i + end + + def issuable_order_by + if params["order_by"] == 'updated_at' + 'updated_at' + else + 'created_at' + end + end + + def issuable_sort + if params["sort"] == 'asc' + :asc + else + :desc + end + end + + def filter_by_iid(items, iid) + items.where(iid: iid) + end + + # error helpers + + def forbidden!(reason = nil) + message = ['403 Forbidden'] + message << " - #{reason}" if reason + render_api_error!(message.join(' '), 403) + end + + def bad_request!(attribute) + message = ["400 (Bad request)"] + message << "\"" + attribute.to_s + "\" not given" + render_api_error!(message.join(' '), 400) + end + + def not_found!(resource = nil) + message = ["404"] + message << resource if resource + message << "Not Found" + render_api_error!(message.join(' '), 404) + end + + def unauthorized! + render_api_error!('401 Unauthorized', 401) + end + + def not_allowed! + render_api_error!('405 Method Not Allowed', 405) + end + + def conflict!(message = nil) + render_api_error!(message || '409 Conflict', 409) + end + + def file_to_large! + render_api_error!('413 Request Entity Too Large', 413) + end + + def not_modified! + render_api_error!('304 Not Modified', 304) + end + + def render_validation_error!(model) + if model.errors.any? + render_api_error!(model.errors.messages || '400 Bad Request', 400) + end + end + + def render_api_error!(message, status) + error!({ 'message' => message }, status) + end + + # Projects helpers + + def filter_projects(projects) + # If the archived parameter is passed, limit results accordingly + if params[:archived].present? + projects = projects.where(archived: parse_boolean(params[:archived])) + end + + if params[:search].present? + projects = projects.search(params[:search]) + end + + if params[:visibility].present? + projects = projects.search_by_visibility(params[:visibility]) + end + + projects.reorder(project_order_by => project_sort) + end + + def project_order_by + order_fields = %w(id name path created_at updated_at last_activity_at) + + if order_fields.include?(params['order_by']) + params['order_by'] + else + 'created_at' + end + end + + def project_sort + if params["sort"] == 'asc' + :asc + else + :desc + end + end + + # file helpers + + def uploaded_file(field, uploads_path) + if params[field] + bad_request!("#{field} is not a file") unless params[field].respond_to?(:filename) + return params[field] + end + + return nil unless params["#{field}.path"] && params["#{field}.name"] + + # sanitize file paths + # this requires all paths to exist + required_attributes! %W(#{field}.path) + uploads_path = File.realpath(uploads_path) + file_path = File.realpath(params["#{field}.path"]) + bad_request!('Bad file path') unless file_path.start_with?(uploads_path) + + UploadedFile.new( + file_path, + params["#{field}.name"], + params["#{field}.type"] || 'application/octet-stream', + ) + end + + def present_file!(path, filename, content_type = 'application/octet-stream') + filename ||= File.basename(path) + header['Content-Disposition'] = "attachment; filename=#{filename}" + header['Content-Transfer-Encoding'] = 'binary' + content_type content_type + + # Support download acceleration + case headers['X-Sendfile-Type'] + when 'X-Sendfile' + header['X-Sendfile'] = path + body + else + file FileStreamer.new(path) + end + end + + private + + def add_pagination_headers(paginated_data) + header 'X-Total', paginated_data.total_count.to_s + header 'X-Total-Pages', paginated_data.total_pages.to_s + header 'X-Per-Page', paginated_data.limit_value.to_s + header 'X-Page', paginated_data.current_page.to_s + header 'X-Next-Page', paginated_data.next_page.to_s + header 'X-Prev-Page', paginated_data.prev_page.to_s + header 'Link', pagination_links(paginated_data) + end + + def pagination_links(paginated_data) + request_url = request.url.split('?').first + request_params = params.clone + request_params[:per_page] = paginated_data.limit_value + + links = [] + + request_params[:page] = paginated_data.current_page - 1 + links << %(<#{request_url}?#{request_params.to_query}>; rel="prev") unless paginated_data.first_page? + + request_params[:page] = paginated_data.current_page + 1 + links << %(<#{request_url}?#{request_params.to_query}>; rel="next") unless paginated_data.last_page? + + request_params[:page] = 1 + links << %(<#{request_url}?#{request_params.to_query}>; rel="first") + + request_params[:page] = paginated_data.total_pages + links << %(<#{request_url}?#{request_params.to_query}>; rel="last") + + links.join(', ') + end + + def abilities + @abilities ||= begin + abilities = Six.new + abilities << Ability + abilities + end + end + + def secret_token + File.read(Gitlab.config.gitlab_shell.secret_file).chomp + end + + def handle_member_errors(errors) + error!(errors[:access_level], 422) if errors[:access_level].any? + not_found!(errors) + end + end + end +end \ No newline at end of file diff --git a/lib/ci/api/api.rb b/lib/ci/api/api.rb index 353c4ddebf..495f5792b0 100644 --- a/lib/ci/api/api.rb +++ b/lib/ci/api/api.rb @@ -28,7 +28,8 @@ module Ci format :json helpers ::Ci::API::Helpers - helpers ::API::Helpers + helpers ::API::Helpers::Core + helpers ::API::Helpers::Authentication helpers Gitlab::CurrentSettings mount Builds diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index 40b24c125b..628569d3e0 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -24,7 +24,7 @@ describe API::API, api: true do context "when public level is restricted" do before do stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC]) - allow_any_instance_of(API::Helpers).to receive(:authenticate!).and_return(true) + allow_any_instance_of(API::Helpers::Authentication).to receive(:authenticate!).and_return(true) end it "renders 403" do From 5fb44192964c962000f8c8708d823931ee6a6d8e Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Fri, 15 Apr 2016 19:48:47 +0530 Subject: [PATCH 071/730] Allow personal access tokens to be used for API authentication. --- lib/api/helpers/authentication.rb | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/api/helpers/authentication.rb b/lib/api/helpers/authentication.rb index 8c7bb2c8cd..f11c9725f3 100644 --- a/lib/api/helpers/authentication.rb +++ b/lib/api/helpers/authentication.rb @@ -5,10 +5,22 @@ module API PRIVATE_TOKEN_PARAM = :private_token SUDO_HEADER ="HTTP_SUDO" SUDO_PARAM = :sudo + PERSONAL_ACCESS_TOKEN_PARAM = :personal_access_token + + def find_user_by_private_token + private_token = (params[PRIVATE_TOKEN_PARAM] || env[PRIVATE_TOKEN_HEADER]).to_s + User.find_by_authentication_token(private_token) + end + + def find_user_by_personal_access_token + personal_access_token = PersonalAccessToken.find_by_token(params[PERSONAL_ACCESS_TOKEN_PARAM]) + if personal_access_token + personal_access_token.user + end + end def current_user - private_token = (params[PRIVATE_TOKEN_PARAM] || env[PRIVATE_TOKEN_HEADER]).to_s - @current_user ||= (User.find_by(authentication_token: private_token) || doorkeeper_guard) + @current_user ||= (find_user_by_private_token || find_user_by_personal_access_token || doorkeeper_guard) unless @current_user && Gitlab::UserAccess.allowed?(@current_user) return nil From e2a4051cc3f4192849d7571bf83b0d9a7b2cbd4e Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Fri, 15 Apr 2016 19:55:38 +0530 Subject: [PATCH 072/730] Allow personal access tokens to be specified in a header. - In addition to a param. --- lib/api/helpers/authentication.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/api/helpers/authentication.rb b/lib/api/helpers/authentication.rb index f11c9725f3..e1d7ac83ff 100644 --- a/lib/api/helpers/authentication.rb +++ b/lib/api/helpers/authentication.rb @@ -6,6 +6,7 @@ module API SUDO_HEADER ="HTTP_SUDO" SUDO_PARAM = :sudo PERSONAL_ACCESS_TOKEN_PARAM = :personal_access_token + PERSONAL_ACCESS_TOKEN_HEADER = "HTTP_PERSONAL_ACCESS_TOKEN" def find_user_by_private_token private_token = (params[PRIVATE_TOKEN_PARAM] || env[PRIVATE_TOKEN_HEADER]).to_s @@ -13,10 +14,9 @@ module API end def find_user_by_personal_access_token - personal_access_token = PersonalAccessToken.find_by_token(params[PERSONAL_ACCESS_TOKEN_PARAM]) - if personal_access_token - personal_access_token.user - end + personal_access_token_string = (params[PERSONAL_ACCESS_TOKEN_PARAM] || env[PERSONAL_ACCESS_TOKEN_HEADER]).to_s + personal_access_token = PersonalAccessToken.find_by_token(personal_access_token_string) + personal_access_token.user if personal_access_token end def current_user From 6d76f14f54eb1af0e5c29eff1b8f5e70d2264ffd Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Fri, 15 Apr 2016 20:54:20 +0530 Subject: [PATCH 073/730] Allow revoking personal access tokens. --- app/assets/stylesheets/pages/profile.scss | 3 +++ .../personal_access_tokens_controller.rb | 16 +++++++++++++++- app/models/personal_access_token.rb | 7 +++++++ .../personal_access_tokens/index.html.haml | 9 ++++++++- config/locales/en.yml | 4 ++++ config/routes.rb | 6 +++++- ...d_column_revoked_to_personal_access_tokens.rb | 5 +++++ lib/api/helpers/authentication.rb | 2 +- 8 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 db/migrate/20160415144643_add_column_revoked_to_personal_access_tokens.rb diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss index 01f9847962..5a4d0a5c8b 100644 --- a/app/assets/stylesheets/pages/profile.scss +++ b/app/assets/stylesheets/pages/profile.scss @@ -205,3 +205,6 @@ text-align: center; } } +.personal-access-tokens-revoked-label { + color: #bbb; +} \ No newline at end of file diff --git a/app/controllers/profiles/personal_access_tokens_controller.rb b/app/controllers/profiles/personal_access_tokens_controller.rb index dbf06cb4c6..59de0b26ee 100644 --- a/app/controllers/profiles/personal_access_tokens_controller.rb +++ b/app/controllers/profiles/personal_access_tokens_controller.rb @@ -1,7 +1,11 @@ class Profiles::PersonalAccessTokensController < ApplicationController def index @user = current_user - @personal_access_token = current_user.personal_access_tokens.new + + # Prefer this to `@user.personal_access_tokens.new`, because it + # litters the view's call to `@user.personal_access_tokens` with + # this stub personal access token. + @personal_access_token = PersonalAccessToken.new(user: @user) end def create @@ -14,6 +18,16 @@ class Profiles::PersonalAccessTokensController < ApplicationController end end + def revoke + @personal_access_token = current_user.personal_access_tokens.find(params[:id]) + + if @personal_access_token.revoke! + redirect_to profile_personal_access_tokens_path, notice: "Revoked personal access token #{@personal_access_token.name}!" + else + render :index + end + end + private def personal_access_token_params diff --git a/app/models/personal_access_token.rb b/app/models/personal_access_token.rb index 29f2275475..e5f1f9749f 100644 --- a/app/models/personal_access_token.rb +++ b/app/models/personal_access_token.rb @@ -1,9 +1,16 @@ class PersonalAccessToken < ActiveRecord::Base belongs_to :user + scope :active, -> { where.not(revoked: true) } + def self.generate(params) personal_access_token = self.new(params) personal_access_token.token = Devise.friendly_token(50) personal_access_token end + + def revoke! + self.revoked = true + self.save + end end diff --git a/app/views/profiles/personal_access_tokens/index.html.haml b/app/views/profiles/personal_access_tokens/index.html.haml index 05eed3c5c3..02d15269c8 100644 --- a/app/views/profiles/personal_access_tokens/index.html.haml +++ b/app/views/profiles/personal_access_tokens/index.html.haml @@ -34,11 +34,18 @@ %th Name %th Token %th Created At + %th Actions %tbody - - @user.personal_access_tokens.each do |token| + - @user.personal_access_tokens.order(:revoked).each do |token| %tr %td= token.name %td= token.token %td= token.created_at + - if token.revoked? + %td + %span.personal-access-tokens-revoked-label Revoked + - else + %td= link_to "Revoke", revoke_profile_personal_access_token_path(token), method: :put, class: "btn btn-danger", data: {confirm: t('profile.personal_access_tokens.revoke.confirmation')} + - else %span You don't have any tokens yet. \ No newline at end of file diff --git a/config/locales/en.yml b/config/locales/en.yml index cedb5e207b..b5b8c4467b 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -12,3 +12,7 @@ en: pagination: previous: "Prev" next: "Next" + profile: + personal_access_tokens: + revoke: + confirmation: "Are you sure? This cannot be undone." diff --git a/config/routes.rb b/config/routes.rb index d1be826d2a..4e4666762f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -333,7 +333,11 @@ Rails.application.routes.draw do resources :keys resources :emails, only: [:index, :create, :destroy] resource :avatar, only: [:destroy] - resources :personal_access_tokens, only: [:index, :create] + resources :personal_access_tokens, only: [:index, :create] do + member do + put :revoke + end + end resource :two_factor_auth, only: [:new, :create, :destroy] do member do post :codes diff --git a/db/migrate/20160415144643_add_column_revoked_to_personal_access_tokens.rb b/db/migrate/20160415144643_add_column_revoked_to_personal_access_tokens.rb new file mode 100644 index 0000000000..8eecdfc5a1 --- /dev/null +++ b/db/migrate/20160415144643_add_column_revoked_to_personal_access_tokens.rb @@ -0,0 +1,5 @@ +class AddColumnRevokedToPersonalAccessTokens < ActiveRecord::Migration + def change + add_column :personal_access_tokens, :revoked, :boolean, default: false + end +end diff --git a/lib/api/helpers/authentication.rb b/lib/api/helpers/authentication.rb index e1d7ac83ff..666bf3ffa1 100644 --- a/lib/api/helpers/authentication.rb +++ b/lib/api/helpers/authentication.rb @@ -15,7 +15,7 @@ module API def find_user_by_personal_access_token personal_access_token_string = (params[PERSONAL_ACCESS_TOKEN_PARAM] || env[PERSONAL_ACCESS_TOKEN_HEADER]).to_s - personal_access_token = PersonalAccessToken.find_by_token(personal_access_token_string) + personal_access_token = PersonalAccessToken.active.find_by_token(personal_access_token_string) personal_access_token.user if personal_access_token end From 1541d1de18c3e7707ce1289f882b4c1262ec8c71 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Mon, 18 Apr 2016 14:47:38 +0530 Subject: [PATCH 074/730] Rename `api_helpers_spec` to `api_authentication_spec` - And fix all tests. --- ...ers_spec.rb => api_authentication_spec.rb} | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) rename spec/requests/api/{api_helpers_spec.rb => api_authentication_spec.rb} (82%) diff --git a/spec/requests/api/api_helpers_spec.rb b/spec/requests/api/api_authentication_spec.rb similarity index 82% rename from spec/requests/api/api_helpers_spec.rb rename to spec/requests/api/api_authentication_spec.rb index 0c19094ec5..8bed3bb119 100644 --- a/spec/requests/api/api_helpers_spec.rb +++ b/spec/requests/api/api_authentication_spec.rb @@ -1,8 +1,10 @@ require 'spec_helper' -describe API, api: true do - include API::Helpers +describe API::Helpers::Authentication, api: true do + + include API::Helpers::Authentication include ApiHelpers + let(:user) { create(:user) } let(:admin) { create(:admin) } let(:key) { create(:key, user: user) } @@ -13,25 +15,25 @@ describe API, api: true do def set_env(token_usr, identifier) clear_env clear_param - env[API::Helpers::PRIVATE_TOKEN_HEADER] = token_usr.private_token - env[API::Helpers::SUDO_HEADER] = identifier + env[API::Helpers::Authentication::PRIVATE_TOKEN_HEADER] = token_usr.private_token + env[API::Helpers::Authentication::SUDO_HEADER] = identifier end def set_param(token_usr, identifier) clear_env clear_param - params[API::Helpers::PRIVATE_TOKEN_PARAM] = token_usr.private_token - params[API::Helpers::SUDO_PARAM] = identifier + params[API::Helpers::Authentication::PRIVATE_TOKEN_PARAM] = token_usr.private_token + params[API::Helpers::Authentication::SUDO_PARAM] = identifier end def clear_env - env.delete(API::Helpers::PRIVATE_TOKEN_HEADER) - env.delete(API::Helpers::SUDO_HEADER) + env.delete(API::Helpers::Authentication::PRIVATE_TOKEN_HEADER) + env.delete(API::Helpers::Authentication::SUDO_HEADER) end def clear_param - params.delete(API::Helpers::PRIVATE_TOKEN_PARAM) - params.delete(API::Helpers::SUDO_PARAM) + params.delete(API::Helpers::Authentication::PRIVATE_TOKEN_PARAM) + params.delete(API::Helpers::Authentication::SUDO_PARAM) end def error!(message, status) @@ -40,22 +42,22 @@ describe API, api: true do describe ".current_user" do it "should return nil for an invalid token" do - env[API::Helpers::PRIVATE_TOKEN_HEADER] = 'invalid token' + env[API::Helpers::Authentication::PRIVATE_TOKEN_HEADER] = 'invalid token' allow_any_instance_of(self.class).to receive(:doorkeeper_guard){ false } expect(current_user).to be_nil end it "should return nil for a user without access" do - env[API::Helpers::PRIVATE_TOKEN_HEADER] = user.private_token + env[API::Helpers::Authentication::PRIVATE_TOKEN_HEADER] = user.private_token allow(Gitlab::UserAccess).to receive(:allowed?).and_return(false) expect(current_user).to be_nil end it "should leave user as is when sudo not specified" do - env[API::Helpers::PRIVATE_TOKEN_HEADER] = user.private_token + env[API::Helpers::Authentication::PRIVATE_TOKEN_HEADER] = user.private_token expect(current_user).to eq(user) clear_env - params[API::Helpers::PRIVATE_TOKEN_PARAM] = user.private_token + params[API::Helpers::Authentication::PRIVATE_TOKEN_PARAM] = user.private_token expect(current_user).to eq(user) end From e5cf527f279964a8952de544526e8def226b98d7 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Mon, 18 Apr 2016 15:48:54 +0530 Subject: [PATCH 075/730] Allow expiration of personal access tokens. --- app/assets/stylesheets/pages/profile.scss | 4 ++ .../personal_access_tokens_controller.rb | 2 +- app/models/personal_access_token.rb | 2 +- .../personal_access_tokens/index.html.haml | 20 +++++- ...mn_expires_at_to_personal_access_tokens.rb | 5 ++ spec/factories/personal_access_tokens.rb | 9 +++ spec/requests/api/api_authentication_spec.rb | 70 +++++++++++++++---- 7 files changed, 93 insertions(+), 19 deletions(-) create mode 100644 db/migrate/20160418085954_add_column_expires_at_to_personal_access_tokens.rb create mode 100644 spec/factories/personal_access_tokens.rb diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss index 5a4d0a5c8b..8c62c97215 100644 --- a/app/assets/stylesheets/pages/profile.scss +++ b/app/assets/stylesheets/pages/profile.scss @@ -207,4 +207,8 @@ } .personal-access-tokens-revoked-label { color: #bbb; +} + +.personal-access-tokens-never-expires-label { + color: #bbb; } \ No newline at end of file diff --git a/app/controllers/profiles/personal_access_tokens_controller.rb b/app/controllers/profiles/personal_access_tokens_controller.rb index 59de0b26ee..d01afbfe11 100644 --- a/app/controllers/profiles/personal_access_tokens_controller.rb +++ b/app/controllers/profiles/personal_access_tokens_controller.rb @@ -31,6 +31,6 @@ class Profiles::PersonalAccessTokensController < ApplicationController private def personal_access_token_params - params.require(:personal_access_token).permit(:name) + params.require(:personal_access_token).permit(:name, :expires_at) end end diff --git a/app/models/personal_access_token.rb b/app/models/personal_access_token.rb index e5f1f9749f..dd64374481 100644 --- a/app/models/personal_access_token.rb +++ b/app/models/personal_access_token.rb @@ -1,7 +1,7 @@ class PersonalAccessToken < ActiveRecord::Base belongs_to :user - scope :active, -> { where.not(revoked: true) } + scope :active, -> { where.not(revoked: true).where("expires_at >= :current", current: Time.current) } def self.generate(params) personal_access_token = self.new(params) diff --git a/app/views/profiles/personal_access_tokens/index.html.haml b/app/views/profiles/personal_access_tokens/index.html.haml index 02d15269c8..f3d5f07cdd 100644 --- a/app/views/profiles/personal_access_tokens/index.html.haml +++ b/app/views/profiles/personal_access_tokens/index.html.haml @@ -18,6 +18,10 @@ = f.label :name, class: 'label-light' = f.text_field :name, class: "form-control", required: true + .form-group + = f.label :expires_at, class: 'label-light' + = f.text_field :expires_at, class: "form-control datepicker", required: false + .prepend-top-default = f.submit 'Add Personal Access Token', class: "btn btn-create" @@ -34,13 +38,19 @@ %th Name %th Token %th Created At + %th Expires At %th Actions %tbody - - @user.personal_access_tokens.order(:revoked).each do |token| + - @user.personal_access_tokens.order("revoked, expires_at").each do |token| %tr %td= token.name %td= token.token %td= token.created_at + - if token.expires_at.present? + %td= token.expires_at.to_date + - else + %td + %span.personal-access-tokens-never-expires-label Never - if token.revoked? %td %span.personal-access-tokens-revoked-label Revoked @@ -48,4 +58,10 @@ %td= link_to "Revoke", revoke_profile_personal_access_token_path(token), method: :put, class: "btn btn-danger", data: {confirm: t('profile.personal_access_tokens.revoke.confirmation')} - else - %span You don't have any tokens yet. \ No newline at end of file + %span You don't have any tokens yet. + +:javascript + $(".datepicker").datepicker({ + dateFormat: "yy-mm-dd", + onSelect: function(dateText, inst) { $("#personal_access_token_expires_at").val(dateText) } + }).datepicker("setDate", $.datepicker.parseDate('yy-mm-dd', $('#personal_access_token_expires_at').val())); \ No newline at end of file diff --git a/db/migrate/20160418085954_add_column_expires_at_to_personal_access_tokens.rb b/db/migrate/20160418085954_add_column_expires_at_to_personal_access_tokens.rb new file mode 100644 index 0000000000..9d99ebeadf --- /dev/null +++ b/db/migrate/20160418085954_add_column_expires_at_to_personal_access_tokens.rb @@ -0,0 +1,5 @@ +class AddColumnExpiresAtToPersonalAccessTokens < ActiveRecord::Migration + def change + add_column :personal_access_tokens, :expires_at, :datetime + end +end diff --git a/spec/factories/personal_access_tokens.rb b/spec/factories/personal_access_tokens.rb new file mode 100644 index 0000000000..da4c72bcb5 --- /dev/null +++ b/spec/factories/personal_access_tokens.rb @@ -0,0 +1,9 @@ +FactoryGirl.define do + factory :personal_access_token do + user + token { SecureRandom.hex(50) } + name { FFaker::Product.brand } + revoked false + expires_at { 5.days.from_now } + end +end diff --git a/spec/requests/api/api_authentication_spec.rb b/spec/requests/api/api_authentication_spec.rb index 8bed3bb119..0416e57c68 100644 --- a/spec/requests/api/api_authentication_spec.rb +++ b/spec/requests/api/api_authentication_spec.rb @@ -41,24 +41,64 @@ describe API::Helpers::Authentication, api: true do end describe ".current_user" do - it "should return nil for an invalid token" do - env[API::Helpers::Authentication::PRIVATE_TOKEN_HEADER] = 'invalid token' - allow_any_instance_of(self.class).to receive(:doorkeeper_guard){ false } - expect(current_user).to be_nil + describe "when authenticating using a user's private token" do + it "should return nil for an invalid token" do + env[API::Helpers::Authentication::PRIVATE_TOKEN_HEADER] = 'invalid token' + allow_any_instance_of(self.class).to receive(:doorkeeper_guard){ false } + expect(current_user).to be_nil + end + + it "should return nil for a user without access" do + env[API::Helpers::Authentication::PRIVATE_TOKEN_HEADER] = user.private_token + allow(Gitlab::UserAccess).to receive(:allowed?).and_return(false) + expect(current_user).to be_nil + end + + it "should leave user as is when sudo not specified" do + env[API::Helpers::Authentication::PRIVATE_TOKEN_HEADER] = user.private_token + expect(current_user).to eq(user) + clear_env + params[API::Helpers::Authentication::PRIVATE_TOKEN_PARAM] = user.private_token + expect(current_user).to eq(user) + end end - it "should return nil for a user without access" do - env[API::Helpers::Authentication::PRIVATE_TOKEN_HEADER] = user.private_token - allow(Gitlab::UserAccess).to receive(:allowed?).and_return(false) - expect(current_user).to be_nil - end + describe "when authenticating using a user's personal access tokens" do + let(:personal_access_token) { create(:personal_access_token, user: user) } - it "should leave user as is when sudo not specified" do - env[API::Helpers::Authentication::PRIVATE_TOKEN_HEADER] = user.private_token - expect(current_user).to eq(user) - clear_env - params[API::Helpers::Authentication::PRIVATE_TOKEN_PARAM] = user.private_token - expect(current_user).to eq(user) + it "should return nil for an invalid token" do + env[API::Helpers::Authentication::PERSONAL_ACCESS_TOKEN_HEADER] = 'invalid token' + allow_any_instance_of(self.class).to receive(:doorkeeper_guard){ false } + expect(current_user).to be_nil + end + + it "should return nil for a user without access" do + env[API::Helpers::Authentication::PERSONAL_ACCESS_TOKEN_HEADER] = personal_access_token.token + allow(Gitlab::UserAccess).to receive(:allowed?).and_return(false) + expect(current_user).to be_nil + end + + it "should leave user as is when sudo not specified" do + env[API::Helpers::Authentication::PERSONAL_ACCESS_TOKEN_HEADER] = personal_access_token.token + expect(current_user).to eq(user) + clear_env + params[API::Helpers::Authentication::PERSONAL_ACCESS_TOKEN_PARAM] = personal_access_token.token + expect(current_user).to eq(user) + end + + it 'does not allow revoked tokens' do + personal_access_token.revoke! + env[API::Helpers::Authentication::PERSONAL_ACCESS_TOKEN_HEADER] = personal_access_token.token + allow_any_instance_of(self.class).to receive(:doorkeeper_guard){ false } + expect(current_user).to be_nil + end + + it 'does not allow expired tokens' do + personal_access_token.update_attributes!(expires_at: 1.day.ago) + env[API::Helpers::Authentication::PERSONAL_ACCESS_TOKEN_HEADER] = personal_access_token.token + allow_any_instance_of(self.class).to receive(:doorkeeper_guard){ false } + expect(current_user).to be_nil + end end it "should change current user to sudo when admin" do From 41b4e119e9b076cc0f36bd31cbb42f87e5ecb08f Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Tue, 19 Apr 2016 14:01:21 +0530 Subject: [PATCH 076/730] Add an entry for Personal Access Tokens in the sidebar. --- .../profiles/personal_access_tokens_controller.rb | 2 +- app/views/layouts/nav/_profile.html.haml | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/controllers/profiles/personal_access_tokens_controller.rb b/app/controllers/profiles/personal_access_tokens_controller.rb index d01afbfe11..a5804cc0d7 100644 --- a/app/controllers/profiles/personal_access_tokens_controller.rb +++ b/app/controllers/profiles/personal_access_tokens_controller.rb @@ -1,4 +1,4 @@ -class Profiles::PersonalAccessTokensController < ApplicationController +class Profiles::PersonalAccessTokensController < Profiles::ApplicationController def index @user = current_user diff --git a/app/views/layouts/nav/_profile.html.haml b/app/views/layouts/nav/_profile.html.haml index d730840d63..297f3e4063 100644 --- a/app/views/layouts/nav/_profile.html.haml +++ b/app/views/layouts/nav/_profile.html.haml @@ -14,6 +14,11 @@ = icon('cloud fw') %span Applications + = nav_link(controller: :personal_access_tokens) do + = link_to profile_personal_access_tokens_path, title: 'Personal Access Tokens' do + = icon('ticket fw') + %span + Personal Access Tokens = nav_link(controller: :emails) do = link_to profile_emails_path, title: 'Emails' do = icon('envelope-o fw') From fb2da6795c8503db5fed0f856760289e87ea9419 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Tue, 19 Apr 2016 15:28:35 +0530 Subject: [PATCH 077/730] Add an "Inactive Personal Access Tokens" section. - Show the count for each section in parens - Remove the `revoked?` check, because everything in the active section is guaranteed to not be revoked. --- app/assets/stylesheets/pages/profile.scss | 4 ++ .../personal_access_tokens_controller.rb | 3 +- app/models/personal_access_token.rb | 3 +- .../personal_access_tokens/index.html.haml | 56 ++++++++++++++----- 4 files changed, 49 insertions(+), 17 deletions(-) diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss index 8c62c97215..85d9173afb 100644 --- a/app/assets/stylesheets/pages/profile.scss +++ b/app/assets/stylesheets/pages/profile.scss @@ -211,4 +211,8 @@ .personal-access-tokens-never-expires-label { color: #bbb; +} + +.personal-access-tokens-token-column { + max-width: 500px } \ No newline at end of file diff --git a/app/controllers/profiles/personal_access_tokens_controller.rb b/app/controllers/profiles/personal_access_tokens_controller.rb index a5804cc0d7..5a6026f58c 100644 --- a/app/controllers/profiles/personal_access_tokens_controller.rb +++ b/app/controllers/profiles/personal_access_tokens_controller.rb @@ -1,6 +1,7 @@ class Profiles::PersonalAccessTokensController < Profiles::ApplicationController def index - @user = current_user + @active_personal_access_tokens = current_user.personal_access_tokens.active.order(:expires_at) + @inactive_personal_access_tokens = current_user.personal_access_tokens.inactive # Prefer this to `@user.personal_access_tokens.new`, because it # litters the view's call to `@user.personal_access_tokens` with diff --git a/app/models/personal_access_token.rb b/app/models/personal_access_token.rb index dd64374481..fff3f76fb9 100644 --- a/app/models/personal_access_token.rb +++ b/app/models/personal_access_token.rb @@ -1,7 +1,8 @@ class PersonalAccessToken < ActiveRecord::Base belongs_to :user - scope :active, -> { where.not(revoked: true).where("expires_at >= :current", current: Time.current) } + scope :active, -> { where(revoked: false).where("expires_at >= :current OR expires_at IS NULL", current: Time.current) } + scope :inactive, -> { where("revoked = true OR expires_at < :current", current: Time.current) } def self.generate(params) personal_access_token = self.new(params) diff --git a/app/views/profiles/personal_access_tokens/index.html.haml b/app/views/profiles/personal_access_tokens/index.html.haml index f3d5f07cdd..77726d34fb 100644 --- a/app/views/profiles/personal_access_tokens/index.html.haml +++ b/app/views/profiles/personal_access_tokens/index.html.haml @@ -27,38 +27,64 @@ %hr - %h5 - Active Personal Access Tokens + %h5= "Active Personal Access Tokens (#{@active_personal_access_tokens.count})" - - if @user.personal_access_tokens.exists? + - if @active_personal_access_tokens.exists? .table-responsive - %table.table.table-striped + %table.table.table-striped.table-hover %thead %tr %th Name %th Token - %th Created At - %th Expires At + %th Created + %th Expires %th Actions %tbody - - @user.personal_access_tokens.order("revoked, expires_at").each do |token| + - @active_personal_access_tokens.active.each do |token| %tr %td= token.name - %td= token.token - %td= token.created_at + %td.input-group.personal-access-tokens-token-column + %input.form-control{type: "text", value: token.token, readonly: true} + %div.input-group-btn + %button.btn.btn-default{type: "button", data: {clipboard_text: token.token}} + %i.fa.fa-clipboard + %td= token.created_at.to_date - if token.expires_at.present? %td= token.expires_at.to_date - else %td %span.personal-access-tokens-never-expires-label Never - - if token.revoked? - %td - %span.personal-access-tokens-revoked-label Revoked - - else - %td= link_to "Revoke", revoke_profile_personal_access_token_path(token), method: :put, class: "btn btn-danger", data: {confirm: t('profile.personal_access_tokens.revoke.confirmation')} + %td= link_to "Revoke", revoke_profile_personal_access_token_path(token), method: :put, class: "btn btn-danger", data: {confirm: t('profile.personal_access_tokens.revoke.confirmation')} - else - %span You don't have any tokens yet. + %span You don't have any active tokens yet. + + %hr + + %h5= "Inactive Personal Access Tokens (#{@inactive_personal_access_tokens.count})" + + - if @inactive_personal_access_tokens.exists? + .table-responsive + %table.table.table-striped.table-hover + %thead + %tr + %th Name + %th Token + %th Created + %tbody + - @inactive_personal_access_tokens.order("revoked, expires_at").each do |token| + %tr + %td= token.name + %td.input-group.personal-access-tokens-token-column + %input.form-control{type: "text", value: token.token, readonly: true} + %div.input-group-btn + %button.btn.btn-default{type: "button", data: {clipboard_text: token.token}} + %i.fa.fa-clipboard + %td= token.created_at.to_date + + - else + %span No inactive tokens. + :javascript $(".datepicker").datepicker({ From ade40fdcd2a4ee879bd2aba939cffaff39c65228 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Tue, 19 Apr 2016 16:22:15 +0530 Subject: [PATCH 078/730] Authenticate non-API requests with personal access tokens. - Rename the `authenticate_user_from_token!` filter to `authenticate_user_from_private_token!` - Add a new `authenticate_user_from_personal_access_token!` filter - Add tests for both. --- app/controllers/application_controller.rb | 19 +++++- .../application_controller_spec.rb | 66 +++++++++++++++++++ 2 files changed, 83 insertions(+), 2 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 1c53b0b21a..590f9383f7 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -7,7 +7,8 @@ class ApplicationController < ActionController::Base include GitlabRoutingHelper include PageLayoutHelper - before_action :authenticate_user_from_token! + before_action :authenticate_user_from_private_token! + before_action :authenticate_user_from_personal_access_token! before_action :authenticate_user! before_action :validate_user_service_ticket! before_action :reject_blocked! @@ -65,7 +66,7 @@ class ApplicationController < ActionController::Base # From https://github.com/plataformatec/devise/wiki/How-To:-Simple-Token-Authentication-Example # https://gist.github.com/josevalim/fb706b1e933ef01e4fb6 - def authenticate_user_from_token! + def authenticate_user_from_private_token! user_token = if params[:authenticity_token].presence params[:authenticity_token].presence elsif params[:private_token].presence @@ -84,6 +85,20 @@ class ApplicationController < ActionController::Base end end + def authenticate_user_from_personal_access_token! + token_string = params[:personal_access_token].presence || request.headers['PERSONAL_ACCESS_TOKEN'].presence + personal_access_token = PersonalAccessToken.active.find_by_token(token_string) + user = personal_access_token && personal_access_token.user + + if user + # Notice we are passing store false, so the user is not + # actually stored in the session and a token is needed + # for every request. If you want the token to work as a + # sign in token, you can simply remove store: false. + sign_in user, store: false + end + end + def authenticate_user!(*args) if redirect_to_home_page_url? redirect_to current_application_settings.home_page_url and return diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index 186239d309..1ec51465cd 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -30,4 +30,70 @@ describe ApplicationController do controller.send(:check_password_expiration) end end + + describe "#authenticate_user_from_private_token!" do + controller(ApplicationController) do + def index + render text: "authenticated" + end + end + + let(:user) { create(:user) } + + it "logs the user in when the 'authenticity_token' param is populated with the private token" do + get :index, authenticity_token: user.private_token + expect(response.status).to eq(200) + expect(response.body).to eq("authenticated") + end + + it "logs the user in when the 'private_token' param is populated with the private token" do + get :index, private_token: user.private_token + expect(response.status).to eq(200) + expect(response.body).to eq("authenticated") + end + + it "logs the user in when the 'PRIVATE-TOKEN' header is populated with the private token" do + @request.headers['PRIVATE-TOKEN'] = user.private_token + get :index + expect(response.status).to eq(200) + expect(response.body).to eq("authenticated") + end + + it "doesn't log the user in otherwise" do + @request.headers['PRIVATE-TOKEN'] = "token" + get :index, private_token: "token", authenticity_token: "token" + expect(response.status).to_not eq(200) + expect(response.body).to_not eq("authenticated") + end + end + + describe "#authenticate_user_from_personal_access_token!" do + controller(ApplicationController) do + def index + render text: 'authenticated' + end + end + + let(:user) { create(:user) } + let(:personal_access_token) { create(:personal_access_token, user: user) } + + it "logs the user in when the 'personal_access_token' param is populated with the personal access token" do + get :index, personal_access_token: personal_access_token.token + expect(response.status).to eq(200) + expect(response.body).to eq('authenticated') + end + + it "logs the user in when the 'PERSONAL_ACCESS_TOKEN' header is populated with the personal access token" do + @request.headers["PERSONAL_ACCESS_TOKEN"] = personal_access_token.token + get :index + expect(response.status).to eq(200) + expect(response.body).to eq('authenticated') + end + + it "doesn't log the user in otherwise" do + get :index, personal_access_token: "token" + expect(response.status).to_not eq(200) + expect(response.body).to_not eq('authenticated') + end + end end From 051324e12a7384b15aaa68f53dd43ad0b3c67812 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Tue, 19 Apr 2016 16:24:33 +0530 Subject: [PATCH 079/730] Refactor `authenticate_user_from_private_token!` - No need to use `if`s when we have a `presence` check already. --- app/controllers/application_controller.rb | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 590f9383f7..2b2726c048 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -67,13 +67,7 @@ class ApplicationController < ActionController::Base # From https://github.com/plataformatec/devise/wiki/How-To:-Simple-Token-Authentication-Example # https://gist.github.com/josevalim/fb706b1e933ef01e4fb6 def authenticate_user_from_private_token! - user_token = if params[:authenticity_token].presence - params[:authenticity_token].presence - elsif params[:private_token].presence - params[:private_token].presence - elsif request.headers['PRIVATE-TOKEN'].present? - request.headers['PRIVATE-TOKEN'] - end + user_token = params[:authenticity_token].presence || params[:private_token].presence || request.headers['PRIVATE-TOKEN'].presence user = user_token && User.find_by_authentication_token(user_token.to_s) if user From abd8eccae7d0566ed6966c5f681d4f7c07bfb016 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Tue, 19 Apr 2016 16:46:03 +0530 Subject: [PATCH 080/730] Remove an unused view file. --- app/views/profiles/personal_access_tokens/create.html.haml | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 app/views/profiles/personal_access_tokens/create.html.haml diff --git a/app/views/profiles/personal_access_tokens/create.html.haml b/app/views/profiles/personal_access_tokens/create.html.haml deleted file mode 100644 index 89da41a75e..0000000000 --- a/app/views/profiles/personal_access_tokens/create.html.haml +++ /dev/null @@ -1,2 +0,0 @@ -%h1 Profiles::PersonalAccessTokens#create -%p Find me in app/views/profiles/personal_access_tokens/create.html.haml From 611f3ad2683a1103ef3c2af244a10ac9f3ae6734 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Wed, 20 Apr 2016 11:14:08 +0530 Subject: [PATCH 081/730] Fix rubocop complaints. --- lib/api/helpers/authentication.rb | 2 +- lib/api/helpers/core.rb | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/api/helpers/authentication.rb b/lib/api/helpers/authentication.rb index 666bf3ffa1..4109c97ed0 100644 --- a/lib/api/helpers/authentication.rb +++ b/lib/api/helpers/authentication.rb @@ -50,4 +50,4 @@ module API end end end -end \ No newline at end of file +end diff --git a/lib/api/helpers/core.rb b/lib/api/helpers/core.rb index c37064d49a..05cda8b84b 100644 --- a/lib/api/helpers/core.rb +++ b/lib/api/helpers/core.rb @@ -132,7 +132,7 @@ module API if params[:labels].present? params[:labels].split(',').each do |label_name| label = user_project.labels.create_with( - color: Label::DEFAULT_COLOR).find_or_initialize_by( + color: Label::DEFAULT_COLOR).find_or_initialize_by( title: label_name.strip) if label.invalid? @@ -274,9 +274,9 @@ module API bad_request!('Bad file path') unless file_path.start_with?(uploads_path) UploadedFile.new( - file_path, - params["#{field}.name"], - params["#{field}.type"] || 'application/octet-stream', + file_path, + params["#{field}.name"], + params["#{field}.type"] || 'application/octet-stream', ) end @@ -288,11 +288,11 @@ module API # Support download acceleration case headers['X-Sendfile-Type'] - when 'X-Sendfile' - header['X-Sendfile'] = path - body - else - file FileStreamer.new(path) + when 'X-Sendfile' + header['X-Sendfile'] = path + body + else + file FileStreamer.new(path) end end @@ -348,4 +348,4 @@ module API end end end -end \ No newline at end of file +end From 17f2fc10e6765d328b9c34a45815e183cca50466 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Wed, 20 Apr 2016 11:57:45 +0530 Subject: [PATCH 082/730] Change the root param while creating personal access tokens. - Can't use `personal_access_token` anymore, because the contents of that param are assumed to be a token string, and authenticated against. --- app/controllers/profiles/personal_access_tokens_controller.rb | 4 +++- app/views/profiles/personal_access_tokens/index.html.haml | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/controllers/profiles/personal_access_tokens_controller.rb b/app/controllers/profiles/personal_access_tokens_controller.rb index 5a6026f58c..7fbf343edb 100644 --- a/app/controllers/profiles/personal_access_tokens_controller.rb +++ b/app/controllers/profiles/personal_access_tokens_controller.rb @@ -32,6 +32,8 @@ class Profiles::PersonalAccessTokensController < Profiles::ApplicationController private def personal_access_token_params - params.require(:personal_access_token).permit(:name, :expires_at) + # We aren't using `personal_access_token` as the root param because the authentication + # system expects to find a token string there - it's off-limits to us. + params.require(:personal_access_token_params).permit(:name, :expires_at) end end diff --git a/app/views/profiles/personal_access_tokens/index.html.haml b/app/views/profiles/personal_access_tokens/index.html.haml index 77726d34fb..72e67df433 100644 --- a/app/views/profiles/personal_access_tokens/index.html.haml +++ b/app/views/profiles/personal_access_tokens/index.html.haml @@ -12,7 +12,8 @@ Add a Personal Access Token %p.profile-settings-content Pick a name for the application, and we'll give you a unique token. - = form_for [:profile, @personal_access_token], method: :post, html: { class: 'js-requires-input' } do |f| + = form_for [:profile, @personal_access_token], as: "personal_access_token_params", + method: :post, html: { class: 'js-requires-input' } do |f| .form-group = f.label :name, class: 'label-light' From 25aefde62b0ac57d93ff3a6ddeef3277e40cc7bd Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Wed, 20 Apr 2016 11:58:48 +0530 Subject: [PATCH 083/730] Add feature specs for personal access token management. --- .../personal_access_tokens/index.html.haml | 4 +- .../profiles/personal_access_tokens_spec.rb | 52 +++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 spec/features/profiles/personal_access_tokens_spec.rb diff --git a/app/views/profiles/personal_access_tokens/index.html.haml b/app/views/profiles/personal_access_tokens/index.html.haml index 72e67df433..e61fa69af5 100644 --- a/app/views/profiles/personal_access_tokens/index.html.haml +++ b/app/views/profiles/personal_access_tokens/index.html.haml @@ -32,7 +32,7 @@ - if @active_personal_access_tokens.exists? .table-responsive - %table.table.table-striped.table-hover + %table.table.table-striped.table-hover.active-personal-access-tokens %thead %tr %th Name @@ -66,7 +66,7 @@ - if @inactive_personal_access_tokens.exists? .table-responsive - %table.table.table-striped.table-hover + %table.table.table-striped.table-hover.inactive-personal-access-tokens %thead %tr %th Name diff --git a/spec/features/profiles/personal_access_tokens_spec.rb b/spec/features/profiles/personal_access_tokens_spec.rb new file mode 100644 index 0000000000..ce972776ff --- /dev/null +++ b/spec/features/profiles/personal_access_tokens_spec.rb @@ -0,0 +1,52 @@ +require 'spec_helper' + +describe 'Profile > Personal Access Tokens', feature: true do + let(:user) { create(:user) } + + before do + login_as(user) + end + + describe "token creation" do + it "allows creation of a token with an optional expiry date" do + visit profile_personal_access_tokens_path + fill_in "Name", with: FFaker::Product.brand + expect {click_on "Add Personal Access Token"}.to change { PersonalAccessToken.count }.by(1) + + active_personal_access_tokens = find(".table.active-personal-access-tokens").native.inner_html + expect(active_personal_access_tokens).to match(PersonalAccessToken.last.name) + expect(active_personal_access_tokens).to match("Never") + expect(active_personal_access_tokens).to match(PersonalAccessToken.last.token) + + fill_in "Name", with: FFaker::Product.brand + fill_in "Expires at", with: 5.days.from_now + expect {click_on "Add Personal Access Token"}.to change { PersonalAccessToken.count }.by(1) + + active_personal_access_tokens = find(".table.active-personal-access-tokens").native.inner_html + expect(active_personal_access_tokens).to match(PersonalAccessToken.last.name) + expect(active_personal_access_tokens).to match(5.days.from_now.to_date.to_s) + expect(active_personal_access_tokens).to match(PersonalAccessToken.last.token) + end + end + + describe "inactive tokens" do + it "allows revocation of an active token" do + personal_access_token = create(:personal_access_token, user: user) + visit profile_personal_access_tokens_path + click_on "Revoke" + + inactive_personal_access_tokens = find(".table.inactive-personal-access-tokens").native.inner_html + expect(inactive_personal_access_tokens).to match(personal_access_token.name) + expect(inactive_personal_access_tokens).to match(personal_access_token.token) + end + + it "moves expired tokens to the 'inactive' section" do + personal_access_token = create(:personal_access_token, expires_at: 5.days.ago, user: user) + visit profile_personal_access_tokens_path + + inactive_personal_access_tokens = find(".table.inactive-personal-access-tokens").native.inner_html + expect(inactive_personal_access_tokens).to match(personal_access_token.name) + expect(inactive_personal_access_tokens).to match(personal_access_token.token) + end + end +end From 4e7acd88dc02e545ba696a2b4fd8c16bd6df31d5 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Wed, 20 Apr 2016 12:21:14 +0530 Subject: [PATCH 084/730] Remove unnecessary javascript from the datepicker initialization. - In the personal access tokens page. - Also fix the z-index so it doesn't appear below the token text fields. --- .../personal_access_tokens/index.html.haml | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/app/views/profiles/personal_access_tokens/index.html.haml b/app/views/profiles/personal_access_tokens/index.html.haml index e61fa69af5..af34eb389d 100644 --- a/app/views/profiles/personal_access_tokens/index.html.haml +++ b/app/views/profiles/personal_access_tokens/index.html.haml @@ -90,5 +90,16 @@ :javascript $(".datepicker").datepicker({ dateFormat: "yy-mm-dd", - onSelect: function(dateText, inst) { $("#personal_access_token_expires_at").val(dateText) } - }).datepicker("setDate", $.datepicker.parseDate('yy-mm-dd', $('#personal_access_token_expires_at').val())); \ No newline at end of file + beforeShow: function() { + //////////////////////////////////////////////////////////////// + // 1. Need the setTimeout because the datepicker doesn't have // + // an `afterShow` callback. // + // 2. Need to set the z-index like this because we don't want // + // to target datepickers outside the current page, which // + // will happen if we set this in CSS directly. // + //////////////////////////////////////////////////////////////// + setTimeout(function(){ + $('.ui-datepicker').css('z-index', 3); + }, 0); + } + }); From c382bd266d256cdbd732be928ecb6a532bfa8ddd Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Wed, 20 Apr 2016 14:20:24 +0530 Subject: [PATCH 085/730] Improve performance of the personal access tokens page. --- .../profiles/personal_access_tokens/index.html.haml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/views/profiles/personal_access_tokens/index.html.haml b/app/views/profiles/personal_access_tokens/index.html.haml index af34eb389d..02800c3791 100644 --- a/app/views/profiles/personal_access_tokens/index.html.haml +++ b/app/views/profiles/personal_access_tokens/index.html.haml @@ -28,9 +28,9 @@ %hr - %h5= "Active Personal Access Tokens (#{@active_personal_access_tokens.count})" + %h5= "Active Personal Access Tokens (#{@active_personal_access_tokens.length})" - - if @active_personal_access_tokens.exists? + - if @active_personal_access_tokens.present? .table-responsive %table.table.table-striped.table-hover.active-personal-access-tokens %thead @@ -41,7 +41,7 @@ %th Expires %th Actions %tbody - - @active_personal_access_tokens.active.each do |token| + - @active_personal_access_tokens.each do |token| %tr %td= token.name %td.input-group.personal-access-tokens-token-column @@ -62,9 +62,9 @@ %hr - %h5= "Inactive Personal Access Tokens (#{@inactive_personal_access_tokens.count})" + %h5= "Inactive Personal Access Tokens (#{@inactive_personal_access_tokens.length})" - - if @inactive_personal_access_tokens.exists? + - if @inactive_personal_access_tokens.present? .table-responsive %table.table.table-striped.table-hover.inactive-personal-access-tokens %thead @@ -73,7 +73,7 @@ %th Token %th Created %tbody - - @inactive_personal_access_tokens.order("revoked, expires_at").each do |token| + - @inactive_personal_access_tokens.each do |token| %tr %td= token.name %td.input-group.personal-access-tokens-token-column From 4076bce5d52b8a11eda48c36011666ea344ba3b7 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Fri, 22 Apr 2016 12:36:56 +0530 Subject: [PATCH 086/730] Merge the "personal access token"-related migrations. --- db/migrate/20160415062917_create_personal_access_tokens.rb | 2 ++ ...415144643_add_column_revoked_to_personal_access_tokens.rb | 5 ----- ...085954_add_column_expires_at_to_personal_access_tokens.rb | 5 ----- 3 files changed, 2 insertions(+), 10 deletions(-) delete mode 100644 db/migrate/20160415144643_add_column_revoked_to_personal_access_tokens.rb delete mode 100644 db/migrate/20160418085954_add_column_expires_at_to_personal_access_tokens.rb diff --git a/db/migrate/20160415062917_create_personal_access_tokens.rb b/db/migrate/20160415062917_create_personal_access_tokens.rb index 42a41349a0..2c9f773e30 100644 --- a/db/migrate/20160415062917_create_personal_access_tokens.rb +++ b/db/migrate/20160415062917_create_personal_access_tokens.rb @@ -4,6 +4,8 @@ class CreatePersonalAccessTokens < ActiveRecord::Migration t.references :user, index: true, foreign_key: true, null: false t.string :token, index: {unique: true}, null: false t.string :name, null: false + t.boolean :revoked, default: false + t.datetime :expires_at t.timestamps null: false end diff --git a/db/migrate/20160415144643_add_column_revoked_to_personal_access_tokens.rb b/db/migrate/20160415144643_add_column_revoked_to_personal_access_tokens.rb deleted file mode 100644 index 8eecdfc5a1..0000000000 --- a/db/migrate/20160415144643_add_column_revoked_to_personal_access_tokens.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddColumnRevokedToPersonalAccessTokens < ActiveRecord::Migration - def change - add_column :personal_access_tokens, :revoked, :boolean, default: false - end -end diff --git a/db/migrate/20160418085954_add_column_expires_at_to_personal_access_tokens.rb b/db/migrate/20160418085954_add_column_expires_at_to_personal_access_tokens.rb deleted file mode 100644 index 9d99ebeadf..0000000000 --- a/db/migrate/20160418085954_add_column_expires_at_to_personal_access_tokens.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddColumnExpiresAtToPersonalAccessTokens < ActiveRecord::Migration - def change - add_column :personal_access_tokens, :expires_at, :datetime - end -end From fc4bce755d19d570c4a00241048517c38aa839b3 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Fri, 22 Apr 2016 14:03:11 +0530 Subject: [PATCH 087/730] Make fixes based on @vsizov's comments on MR !3749 --- app/controllers/profiles/personal_access_tokens_controller.rb | 4 ---- app/models/personal_access_token.rb | 4 ++-- lib/api/helpers/authentication.rb | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/app/controllers/profiles/personal_access_tokens_controller.rb b/app/controllers/profiles/personal_access_tokens_controller.rb index 7fbf343edb..af6def25e7 100644 --- a/app/controllers/profiles/personal_access_tokens_controller.rb +++ b/app/controllers/profiles/personal_access_tokens_controller.rb @@ -2,10 +2,6 @@ class Profiles::PersonalAccessTokensController < Profiles::ApplicationController def index @active_personal_access_tokens = current_user.personal_access_tokens.active.order(:expires_at) @inactive_personal_access_tokens = current_user.personal_access_tokens.inactive - - # Prefer this to `@user.personal_access_tokens.new`, because it - # litters the view's call to `@user.personal_access_tokens` with - # this stub personal access token. @personal_access_token = PersonalAccessToken.new(user: @user) end diff --git a/app/models/personal_access_token.rb b/app/models/personal_access_token.rb index fff3f76fb9..c7c3932ba4 100644 --- a/app/models/personal_access_token.rb +++ b/app/models/personal_access_token.rb @@ -1,8 +1,8 @@ class PersonalAccessToken < ActiveRecord::Base belongs_to :user - scope :active, -> { where(revoked: false).where("expires_at >= :current OR expires_at IS NULL", current: Time.current) } - scope :inactive, -> { where("revoked = true OR expires_at < :current", current: Time.current) } + scope :active, -> { where(revoked: false).where("expires_at >= NOW() OR expires_at IS NULL") } + scope :inactive, -> { where("revoked = true OR expires_at < NOW()") } def self.generate(params) personal_access_token = self.new(params) diff --git a/lib/api/helpers/authentication.rb b/lib/api/helpers/authentication.rb index 4109c97ed0..4330c58027 100644 --- a/lib/api/helpers/authentication.rb +++ b/lib/api/helpers/authentication.rb @@ -42,7 +42,7 @@ module API identifier ||= params[SUDO_PARAM] || env[SUDO_HEADER] # Regex for integers - if !!(identifier =~ /^[0-9]+$/) + if !!(identifier =~ /\A[0-9]+\z/) identifier.to_i else identifier From b22a47c62e076acddd254e2d659f38261085bf01 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Mon, 25 Apr 2016 09:00:20 +0530 Subject: [PATCH 088/730] Combine `API::Helpers::Core` and `API::Helpers::Authentication` back into `API::Helpers` - Makes the MR easier to read; this can go in a separate MR - This is a (sort of) revert of 99bea01 --- lib/api/api.rb | 4 +- lib/api/helpers.rb | 397 ++++++++++++++++++ lib/api/helpers/authentication.rb | 53 --- lib/api/helpers/core.rb | 351 ---------------- lib/ci/api/api.rb | 3 +- ...entication_spec.rb => api_helpers_spec.rb} | 40 +- spec/requests/api/users_spec.rb | 2 +- 7 files changed, 420 insertions(+), 430 deletions(-) create mode 100644 lib/api/helpers.rb delete mode 100644 lib/api/helpers/authentication.rb delete mode 100644 lib/api/helpers/core.rb rename spec/requests/api/{api_authentication_spec.rb => api_helpers_spec.rb} (79%) diff --git a/lib/api/api.rb b/lib/api/api.rb index 537678863c..cc1004f800 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -1,5 +1,4 @@ Dir["#{Rails.root}/lib/api/*.rb"].each {|file| require file} -Dir["#{Rails.root}/lib/api/helpers/*.rb"].each {|file| require file} module API class API < Grape::API @@ -26,8 +25,7 @@ module API format :json content_type :txt, "text/plain" - helpers Helpers::Core - helpers Helpers::Authentication + helpers Helpers mount Groups mount GroupMembers diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb new file mode 100644 index 0000000000..fb30ef3e25 --- /dev/null +++ b/lib/api/helpers.rb @@ -0,0 +1,397 @@ +module API + module Helpers + PRIVATE_TOKEN_HEADER = "HTTP_PRIVATE_TOKEN" + PRIVATE_TOKEN_PARAM = :private_token + SUDO_HEADER ="HTTP_SUDO" + SUDO_PARAM = :sudo + PERSONAL_ACCESS_TOKEN_PARAM = :personal_access_token + PERSONAL_ACCESS_TOKEN_HEADER = "HTTP_PERSONAL_ACCESS_TOKEN" + + def parse_boolean(value) + [ true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON' ].include?(value) + end + + def find_user_by_private_token + private_token = (params[PRIVATE_TOKEN_PARAM] || env[PRIVATE_TOKEN_HEADER]).to_s + User.find_by_authentication_token(private_token) + end + + def find_user_by_personal_access_token + personal_access_token_string = (params[PERSONAL_ACCESS_TOKEN_PARAM] || env[PERSONAL_ACCESS_TOKEN_HEADER]).to_s + personal_access_token = PersonalAccessToken.active.find_by_token(personal_access_token_string) + personal_access_token.user if personal_access_token + end + + def current_user + @current_user ||= (find_user_by_private_token || find_user_by_personal_access_token || doorkeeper_guard) + + unless @current_user && Gitlab::UserAccess.allowed?(@current_user) + return nil + end + + identifier = sudo_identifier() + + # If the sudo is the current user do nothing + if identifier && !(@current_user.id == identifier || @current_user.username == identifier) + render_api_error!('403 Forbidden: Must be admin to use sudo', 403) unless @current_user.is_admin? + @current_user = User.by_username_or_id(identifier) + not_found!("No user id or username for: #{identifier}") if @current_user.nil? + end + + @current_user + end + + def sudo_identifier() + identifier ||= params[SUDO_PARAM] || env[SUDO_HEADER] + + # Regex for integers + if !!(identifier =~ /\A[0-9]+\z/) + identifier.to_i + else + identifier + end + end + + def user_project + @project ||= find_project(params[:id]) + @project || not_found!("Project") + end + + def find_project(id) + project = Project.find_with_namespace(id) || Project.find_by(id: id) + + if project && can?(current_user, :read_project, project) + project + else + nil + end + end + + def project_service + @project_service ||= begin + underscored_service = params[:service_slug].underscore + + if Service.available_services_names.include?(underscored_service) + user_project.build_missing_services + + service_method = "#{underscored_service}_service" + + send_service(service_method) + end + end + + @project_service || not_found!("Service") + end + + def send_service(service_method) + user_project.send(service_method) + end + + def service_attributes + @service_attributes ||= project_service.fields.inject([]) do |arr, hash| + arr << hash[:name].to_sym + end + end + + def find_group(id) + begin + group = Group.find(id) + rescue ActiveRecord::RecordNotFound + group = Group.find_by!(path: id) + end + + if can?(current_user, :read_group, group) + group + else + not_found!('Group') + end + end + + def paginate(relation) + relation.page(params[:page]).per(params[:per_page].to_i).tap do |data| + add_pagination_headers(data) + end + end + + def authenticate! + unauthorized! unless current_user + end + + def authenticate_by_gitlab_shell_token! + input = params['secret_token'].try(:chomp) + unless Devise.secure_compare(secret_token, input) + unauthorized! + end + end + + def authenticated_as_admin! + forbidden! unless current_user.is_admin? + end + + def authorize!(action, subject) + forbidden! unless abilities.allowed?(current_user, action, subject) + end + + def authorize_push_project + authorize! :push_code, user_project + end + + def authorize_admin_project + authorize! :admin_project, user_project + end + + def require_gitlab_workhorse! + unless env['HTTP_GITLAB_WORKHORSE'].present? + forbidden!('Request should be executed via GitLab Workhorse') + end + end + + def can?(object, action, subject) + abilities.allowed?(object, action, subject) + end + + # Checks the occurrences of required attributes, each attribute must be present in the params hash + # or a Bad Request error is invoked. + # + # Parameters: + # keys (required) - A hash consisting of keys that must be present + def required_attributes!(keys) + keys.each do |key| + bad_request!(key) unless params[key].present? + end + end + + def attributes_for_keys(keys, custom_params = nil) + params_hash = custom_params || params + attrs = {} + keys.each do |key| + if params_hash[key].present? or (params_hash.has_key?(key) and params_hash[key] == false) + attrs[key] = params_hash[key] + end + end + ActionController::Parameters.new(attrs).permit! + end + + # Helper method for validating all labels against its names + def validate_label_params(params) + errors = {} + + if params[:labels].present? + params[:labels].split(',').each do |label_name| + label = user_project.labels.create_with( + color: Label::DEFAULT_COLOR).find_or_initialize_by( + title: label_name.strip) + + if label.invalid? + errors[label.title] = label.errors + end + end + end + + errors + end + + def validate_access_level?(level) + Gitlab::Access.options_with_owner.values.include? level.to_i + end + + def issuable_order_by + if params["order_by"] == 'updated_at' + 'updated_at' + else + 'created_at' + end + end + + def issuable_sort + if params["sort"] == 'asc' + :asc + else + :desc + end + end + + def filter_by_iid(items, iid) + items.where(iid: iid) + end + + # error helpers + + def forbidden!(reason = nil) + message = ['403 Forbidden'] + message << " - #{reason}" if reason + render_api_error!(message.join(' '), 403) + end + + def bad_request!(attribute) + message = ["400 (Bad request)"] + message << "\"" + attribute.to_s + "\" not given" + render_api_error!(message.join(' '), 400) + end + + def not_found!(resource = nil) + message = ["404"] + message << resource if resource + message << "Not Found" + render_api_error!(message.join(' '), 404) + end + + def unauthorized! + render_api_error!('401 Unauthorized', 401) + end + + def not_allowed! + render_api_error!('405 Method Not Allowed', 405) + end + + def conflict!(message = nil) + render_api_error!(message || '409 Conflict', 409) + end + + def file_to_large! + render_api_error!('413 Request Entity Too Large', 413) + end + + def not_modified! + render_api_error!('304 Not Modified', 304) + end + + def render_validation_error!(model) + if model.errors.any? + render_api_error!(model.errors.messages || '400 Bad Request', 400) + end + end + + def render_api_error!(message, status) + error!({ 'message' => message }, status) + end + + # Projects helpers + + def filter_projects(projects) + # If the archived parameter is passed, limit results accordingly + if params[:archived].present? + projects = projects.where(archived: parse_boolean(params[:archived])) + end + + if params[:search].present? + projects = projects.search(params[:search]) + end + + if params[:visibility].present? + projects = projects.search_by_visibility(params[:visibility]) + end + + projects.reorder(project_order_by => project_sort) + end + + def project_order_by + order_fields = %w(id name path created_at updated_at last_activity_at) + + if order_fields.include?(params['order_by']) + params['order_by'] + else + 'created_at' + end + end + + def project_sort + if params["sort"] == 'asc' + :asc + else + :desc + end + end + + # file helpers + + def uploaded_file(field, uploads_path) + if params[field] + bad_request!("#{field} is not a file") unless params[field].respond_to?(:filename) + return params[field] + end + + return nil unless params["#{field}.path"] && params["#{field}.name"] + + # sanitize file paths + # this requires all paths to exist + required_attributes! %W(#{field}.path) + uploads_path = File.realpath(uploads_path) + file_path = File.realpath(params["#{field}.path"]) + bad_request!('Bad file path') unless file_path.start_with?(uploads_path) + + UploadedFile.new( + file_path, + params["#{field}.name"], + params["#{field}.type"] || 'application/octet-stream', + ) + end + + def present_file!(path, filename, content_type = 'application/octet-stream') + filename ||= File.basename(path) + header['Content-Disposition'] = "attachment; filename=#{filename}" + header['Content-Transfer-Encoding'] = 'binary' + content_type content_type + + # Support download acceleration + case headers['X-Sendfile-Type'] + when 'X-Sendfile' + header['X-Sendfile'] = path + body + else + file FileStreamer.new(path) + end + end + + private + + def add_pagination_headers(paginated_data) + header 'X-Total', paginated_data.total_count.to_s + header 'X-Total-Pages', paginated_data.total_pages.to_s + header 'X-Per-Page', paginated_data.limit_value.to_s + header 'X-Page', paginated_data.current_page.to_s + header 'X-Next-Page', paginated_data.next_page.to_s + header 'X-Prev-Page', paginated_data.prev_page.to_s + header 'Link', pagination_links(paginated_data) + end + + def pagination_links(paginated_data) + request_url = request.url.split('?').first + request_params = params.clone + request_params[:per_page] = paginated_data.limit_value + + links = [] + + request_params[:page] = paginated_data.current_page - 1 + links << %(<#{request_url}?#{request_params.to_query}>; rel="prev") unless paginated_data.first_page? + + request_params[:page] = paginated_data.current_page + 1 + links << %(<#{request_url}?#{request_params.to_query}>; rel="next") unless paginated_data.last_page? + + request_params[:page] = 1 + links << %(<#{request_url}?#{request_params.to_query}>; rel="first") + + request_params[:page] = paginated_data.total_pages + links << %(<#{request_url}?#{request_params.to_query}>; rel="last") + + links.join(', ') + end + + def abilities + @abilities ||= begin + abilities = Six.new + abilities << Ability + abilities + end + end + + def secret_token + File.read(Gitlab.config.gitlab_shell.secret_file).chomp + end + + def handle_member_errors(errors) + error!(errors[:access_level], 422) if errors[:access_level].any? + not_found!(errors) + end + end +end diff --git a/lib/api/helpers/authentication.rb b/lib/api/helpers/authentication.rb deleted file mode 100644 index 4330c58027..0000000000 --- a/lib/api/helpers/authentication.rb +++ /dev/null @@ -1,53 +0,0 @@ -module API - module Helpers - module Authentication - PRIVATE_TOKEN_HEADER = "HTTP_PRIVATE_TOKEN" - PRIVATE_TOKEN_PARAM = :private_token - SUDO_HEADER ="HTTP_SUDO" - SUDO_PARAM = :sudo - PERSONAL_ACCESS_TOKEN_PARAM = :personal_access_token - PERSONAL_ACCESS_TOKEN_HEADER = "HTTP_PERSONAL_ACCESS_TOKEN" - - def find_user_by_private_token - private_token = (params[PRIVATE_TOKEN_PARAM] || env[PRIVATE_TOKEN_HEADER]).to_s - User.find_by_authentication_token(private_token) - end - - def find_user_by_personal_access_token - personal_access_token_string = (params[PERSONAL_ACCESS_TOKEN_PARAM] || env[PERSONAL_ACCESS_TOKEN_HEADER]).to_s - personal_access_token = PersonalAccessToken.active.find_by_token(personal_access_token_string) - personal_access_token.user if personal_access_token - end - - def current_user - @current_user ||= (find_user_by_private_token || find_user_by_personal_access_token || doorkeeper_guard) - - unless @current_user && Gitlab::UserAccess.allowed?(@current_user) - return nil - end - - identifier = sudo_identifier() - - # If the sudo is the current user do nothing - if identifier && !(@current_user.id == identifier || @current_user.username == identifier) - render_api_error!('403 Forbidden: Must be admin to use sudo', 403) unless @current_user.is_admin? - @current_user = User.by_username_or_id(identifier) - not_found!("No user id or username for: #{identifier}") if @current_user.nil? - end - - @current_user - end - - def sudo_identifier() - identifier ||= params[SUDO_PARAM] || env[SUDO_HEADER] - - # Regex for integers - if !!(identifier =~ /\A[0-9]+\z/) - identifier.to_i - else - identifier - end - end - end - end -end diff --git a/lib/api/helpers/core.rb b/lib/api/helpers/core.rb deleted file mode 100644 index 05cda8b84b..0000000000 --- a/lib/api/helpers/core.rb +++ /dev/null @@ -1,351 +0,0 @@ -module API - module Helpers - module Core - def parse_boolean(value) - [ true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON' ].include?(value) - end - - def user_project - @project ||= find_project(params[:id]) - @project || not_found!("Project") - end - - def find_project(id) - project = Project.find_with_namespace(id) || Project.find_by(id: id) - - if project && can?(current_user, :read_project, project) - project - else - nil - end - end - - def project_service - @project_service ||= begin - underscored_service = params[:service_slug].underscore - - if Service.available_services_names.include?(underscored_service) - user_project.build_missing_services - - service_method = "#{underscored_service}_service" - - send_service(service_method) - end - end - - @project_service || not_found!("Service") - end - - def send_service(service_method) - user_project.send(service_method) - end - - def service_attributes - @service_attributes ||= project_service.fields.inject([]) do |arr, hash| - arr << hash[:name].to_sym - end - end - - def find_group(id) - begin - group = Group.find(id) - rescue ActiveRecord::RecordNotFound - group = Group.find_by!(path: id) - end - - if can?(current_user, :read_group, group) - group - else - not_found!('Group') - end - end - - def paginate(relation) - relation.page(params[:page]).per(params[:per_page].to_i).tap do |data| - add_pagination_headers(data) - end - end - - def authenticate! - unauthorized! unless current_user - end - - def authenticate_by_gitlab_shell_token! - input = params['secret_token'].try(:chomp) - unless Devise.secure_compare(secret_token, input) - unauthorized! - end - end - - def authenticated_as_admin! - forbidden! unless current_user.is_admin? - end - - def authorize!(action, subject) - forbidden! unless abilities.allowed?(current_user, action, subject) - end - - def authorize_push_project - authorize! :push_code, user_project - end - - def authorize_admin_project - authorize! :admin_project, user_project - end - - def require_gitlab_workhorse! - unless env['HTTP_GITLAB_WORKHORSE'].present? - forbidden!('Request should be executed via GitLab Workhorse') - end - end - - def can?(object, action, subject) - abilities.allowed?(object, action, subject) - end - - # Checks the occurrences of required attributes, each attribute must be present in the params hash - # or a Bad Request error is invoked. - # - # Parameters: - # keys (required) - A hash consisting of keys that must be present - def required_attributes!(keys) - keys.each do |key| - bad_request!(key) unless params[key].present? - end - end - - def attributes_for_keys(keys, custom_params = nil) - params_hash = custom_params || params - attrs = {} - keys.each do |key| - if params_hash[key].present? or (params_hash.has_key?(key) and params_hash[key] == false) - attrs[key] = params_hash[key] - end - end - ActionController::Parameters.new(attrs).permit! - end - - # Helper method for validating all labels against its names - def validate_label_params(params) - errors = {} - - if params[:labels].present? - params[:labels].split(',').each do |label_name| - label = user_project.labels.create_with( - color: Label::DEFAULT_COLOR).find_or_initialize_by( - title: label_name.strip) - - if label.invalid? - errors[label.title] = label.errors - end - end - end - - errors - end - - def validate_access_level?(level) - Gitlab::Access.options_with_owner.values.include? level.to_i - end - - def issuable_order_by - if params["order_by"] == 'updated_at' - 'updated_at' - else - 'created_at' - end - end - - def issuable_sort - if params["sort"] == 'asc' - :asc - else - :desc - end - end - - def filter_by_iid(items, iid) - items.where(iid: iid) - end - - # error helpers - - def forbidden!(reason = nil) - message = ['403 Forbidden'] - message << " - #{reason}" if reason - render_api_error!(message.join(' '), 403) - end - - def bad_request!(attribute) - message = ["400 (Bad request)"] - message << "\"" + attribute.to_s + "\" not given" - render_api_error!(message.join(' '), 400) - end - - def not_found!(resource = nil) - message = ["404"] - message << resource if resource - message << "Not Found" - render_api_error!(message.join(' '), 404) - end - - def unauthorized! - render_api_error!('401 Unauthorized', 401) - end - - def not_allowed! - render_api_error!('405 Method Not Allowed', 405) - end - - def conflict!(message = nil) - render_api_error!(message || '409 Conflict', 409) - end - - def file_to_large! - render_api_error!('413 Request Entity Too Large', 413) - end - - def not_modified! - render_api_error!('304 Not Modified', 304) - end - - def render_validation_error!(model) - if model.errors.any? - render_api_error!(model.errors.messages || '400 Bad Request', 400) - end - end - - def render_api_error!(message, status) - error!({ 'message' => message }, status) - end - - # Projects helpers - - def filter_projects(projects) - # If the archived parameter is passed, limit results accordingly - if params[:archived].present? - projects = projects.where(archived: parse_boolean(params[:archived])) - end - - if params[:search].present? - projects = projects.search(params[:search]) - end - - if params[:visibility].present? - projects = projects.search_by_visibility(params[:visibility]) - end - - projects.reorder(project_order_by => project_sort) - end - - def project_order_by - order_fields = %w(id name path created_at updated_at last_activity_at) - - if order_fields.include?(params['order_by']) - params['order_by'] - else - 'created_at' - end - end - - def project_sort - if params["sort"] == 'asc' - :asc - else - :desc - end - end - - # file helpers - - def uploaded_file(field, uploads_path) - if params[field] - bad_request!("#{field} is not a file") unless params[field].respond_to?(:filename) - return params[field] - end - - return nil unless params["#{field}.path"] && params["#{field}.name"] - - # sanitize file paths - # this requires all paths to exist - required_attributes! %W(#{field}.path) - uploads_path = File.realpath(uploads_path) - file_path = File.realpath(params["#{field}.path"]) - bad_request!('Bad file path') unless file_path.start_with?(uploads_path) - - UploadedFile.new( - file_path, - params["#{field}.name"], - params["#{field}.type"] || 'application/octet-stream', - ) - end - - def present_file!(path, filename, content_type = 'application/octet-stream') - filename ||= File.basename(path) - header['Content-Disposition'] = "attachment; filename=#{filename}" - header['Content-Transfer-Encoding'] = 'binary' - content_type content_type - - # Support download acceleration - case headers['X-Sendfile-Type'] - when 'X-Sendfile' - header['X-Sendfile'] = path - body - else - file FileStreamer.new(path) - end - end - - private - - def add_pagination_headers(paginated_data) - header 'X-Total', paginated_data.total_count.to_s - header 'X-Total-Pages', paginated_data.total_pages.to_s - header 'X-Per-Page', paginated_data.limit_value.to_s - header 'X-Page', paginated_data.current_page.to_s - header 'X-Next-Page', paginated_data.next_page.to_s - header 'X-Prev-Page', paginated_data.prev_page.to_s - header 'Link', pagination_links(paginated_data) - end - - def pagination_links(paginated_data) - request_url = request.url.split('?').first - request_params = params.clone - request_params[:per_page] = paginated_data.limit_value - - links = [] - - request_params[:page] = paginated_data.current_page - 1 - links << %(<#{request_url}?#{request_params.to_query}>; rel="prev") unless paginated_data.first_page? - - request_params[:page] = paginated_data.current_page + 1 - links << %(<#{request_url}?#{request_params.to_query}>; rel="next") unless paginated_data.last_page? - - request_params[:page] = 1 - links << %(<#{request_url}?#{request_params.to_query}>; rel="first") - - request_params[:page] = paginated_data.total_pages - links << %(<#{request_url}?#{request_params.to_query}>; rel="last") - - links.join(', ') - end - - def abilities - @abilities ||= begin - abilities = Six.new - abilities << Ability - abilities - end - end - - def secret_token - File.read(Gitlab.config.gitlab_shell.secret_file).chomp - end - - def handle_member_errors(errors) - error!(errors[:access_level], 422) if errors[:access_level].any? - not_found!(errors) - end - end - end -end diff --git a/lib/ci/api/api.rb b/lib/ci/api/api.rb index 495f5792b0..353c4ddebf 100644 --- a/lib/ci/api/api.rb +++ b/lib/ci/api/api.rb @@ -28,8 +28,7 @@ module Ci format :json helpers ::Ci::API::Helpers - helpers ::API::Helpers::Core - helpers ::API::Helpers::Authentication + helpers ::API::Helpers helpers Gitlab::CurrentSettings mount Builds diff --git a/spec/requests/api/api_authentication_spec.rb b/spec/requests/api/api_helpers_spec.rb similarity index 79% rename from spec/requests/api/api_authentication_spec.rb rename to spec/requests/api/api_helpers_spec.rb index 0416e57c68..06997147b0 100644 --- a/spec/requests/api/api_authentication_spec.rb +++ b/spec/requests/api/api_helpers_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' -describe API::Helpers::Authentication, api: true do +describe API::Helpers, api: true do - include API::Helpers::Authentication + include API::Helpers include ApiHelpers let(:user) { create(:user) } @@ -15,25 +15,25 @@ describe API::Helpers::Authentication, api: true do def set_env(token_usr, identifier) clear_env clear_param - env[API::Helpers::Authentication::PRIVATE_TOKEN_HEADER] = token_usr.private_token - env[API::Helpers::Authentication::SUDO_HEADER] = identifier + env[API::Helpers::PRIVATE_TOKEN_HEADER] = token_usr.private_token + env[API::Helpers::SUDO_HEADER] = identifier end def set_param(token_usr, identifier) clear_env clear_param - params[API::Helpers::Authentication::PRIVATE_TOKEN_PARAM] = token_usr.private_token - params[API::Helpers::Authentication::SUDO_PARAM] = identifier + params[API::Helpers::PRIVATE_TOKEN_PARAM] = token_usr.private_token + params[API::Helpers::SUDO_PARAM] = identifier end def clear_env - env.delete(API::Helpers::Authentication::PRIVATE_TOKEN_HEADER) - env.delete(API::Helpers::Authentication::SUDO_HEADER) + env.delete(API::Helpers::PRIVATE_TOKEN_HEADER) + env.delete(API::Helpers::SUDO_HEADER) end def clear_param - params.delete(API::Helpers::Authentication::PRIVATE_TOKEN_PARAM) - params.delete(API::Helpers::Authentication::SUDO_PARAM) + params.delete(API::Helpers::PRIVATE_TOKEN_PARAM) + params.delete(API::Helpers::SUDO_PARAM) end def error!(message, status) @@ -43,22 +43,22 @@ describe API::Helpers::Authentication, api: true do describe ".current_user" do describe "when authenticating using a user's private token" do it "should return nil for an invalid token" do - env[API::Helpers::Authentication::PRIVATE_TOKEN_HEADER] = 'invalid token' + env[API::Helpers::PRIVATE_TOKEN_HEADER] = 'invalid token' allow_any_instance_of(self.class).to receive(:doorkeeper_guard){ false } expect(current_user).to be_nil end it "should return nil for a user without access" do - env[API::Helpers::Authentication::PRIVATE_TOKEN_HEADER] = user.private_token + env[API::Helpers::PRIVATE_TOKEN_HEADER] = user.private_token allow(Gitlab::UserAccess).to receive(:allowed?).and_return(false) expect(current_user).to be_nil end it "should leave user as is when sudo not specified" do - env[API::Helpers::Authentication::PRIVATE_TOKEN_HEADER] = user.private_token + env[API::Helpers::PRIVATE_TOKEN_HEADER] = user.private_token expect(current_user).to eq(user) clear_env - params[API::Helpers::Authentication::PRIVATE_TOKEN_PARAM] = user.private_token + params[API::Helpers::PRIVATE_TOKEN_PARAM] = user.private_token expect(current_user).to eq(user) end end @@ -67,35 +67,35 @@ describe API::Helpers::Authentication, api: true do let(:personal_access_token) { create(:personal_access_token, user: user) } it "should return nil for an invalid token" do - env[API::Helpers::Authentication::PERSONAL_ACCESS_TOKEN_HEADER] = 'invalid token' + env[API::Helpers::PERSONAL_ACCESS_TOKEN_HEADER] = 'invalid token' allow_any_instance_of(self.class).to receive(:doorkeeper_guard){ false } expect(current_user).to be_nil end it "should return nil for a user without access" do - env[API::Helpers::Authentication::PERSONAL_ACCESS_TOKEN_HEADER] = personal_access_token.token + env[API::Helpers::PERSONAL_ACCESS_TOKEN_HEADER] = personal_access_token.token allow(Gitlab::UserAccess).to receive(:allowed?).and_return(false) expect(current_user).to be_nil end it "should leave user as is when sudo not specified" do - env[API::Helpers::Authentication::PERSONAL_ACCESS_TOKEN_HEADER] = personal_access_token.token + env[API::Helpers::PERSONAL_ACCESS_TOKEN_HEADER] = personal_access_token.token expect(current_user).to eq(user) clear_env - params[API::Helpers::Authentication::PERSONAL_ACCESS_TOKEN_PARAM] = personal_access_token.token + params[API::Helpers::PERSONAL_ACCESS_TOKEN_PARAM] = personal_access_token.token expect(current_user).to eq(user) end it 'does not allow revoked tokens' do personal_access_token.revoke! - env[API::Helpers::Authentication::PERSONAL_ACCESS_TOKEN_HEADER] = personal_access_token.token + env[API::Helpers::PERSONAL_ACCESS_TOKEN_HEADER] = personal_access_token.token allow_any_instance_of(self.class).to receive(:doorkeeper_guard){ false } expect(current_user).to be_nil end it 'does not allow expired tokens' do personal_access_token.update_attributes!(expires_at: 1.day.ago) - env[API::Helpers::Authentication::PERSONAL_ACCESS_TOKEN_HEADER] = personal_access_token.token + env[API::Helpers::PERSONAL_ACCESS_TOKEN_HEADER] = personal_access_token.token allow_any_instance_of(self.class).to receive(:doorkeeper_guard){ false } expect(current_user).to be_nil end diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index 628569d3e0..40b24c125b 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -24,7 +24,7 @@ describe API::API, api: true do context "when public level is restricted" do before do stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC]) - allow_any_instance_of(API::Helpers::Authentication).to receive(:authenticate!).and_return(true) + allow_any_instance_of(API::Helpers).to receive(:authenticate!).and_return(true) end it "renders 403" do From fe5eca8b38e28ad3c77d3d71297cca110306cab9 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Mon, 25 Apr 2016 09:19:25 +0530 Subject: [PATCH 089/730] Update CHANGELOG. --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 91fdfe6216..b3ea047475 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.8.0 (unreleased) - Make build status canceled if any of the jobs was canceled and none failed + - Allow authentication using personal acces tokens - Remove future dates from contribution calendar graph. - Use ActionDispatch Remote IP for Akismet checking - Fix error when visiting commit builds page before build was updated From bafbf22c6ab613d25287d7119d7e30770c531fdb Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Mon, 25 Apr 2016 14:30:59 +0530 Subject: [PATCH 090/730] Address @DouweM's feedback on !3749. - Use `TokenAuthenticatable` to generate the personal access token - Remove a check for `authenticity_token` in application controller; this should've been `authentication_token`, maybe, and doesn't make any sense now. - Have the datepicker appear inline --- app/controllers/application_controller.rb | 2 +- app/models/personal_access_token.rb | 5 ++++- .../personal_access_tokens/index.html.haml | 18 ++++-------------- .../controllers/application_controller_spec.rb | 6 ------ .../profiles/personal_access_tokens_spec.rb | 18 +++++++++++------- spec/models/personal_access_token_spec.rb | 15 +++++++++++++++ 6 files changed, 35 insertions(+), 29 deletions(-) create mode 100644 spec/models/personal_access_token_spec.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 2b2726c048..eb5ffc44c3 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -67,7 +67,7 @@ class ApplicationController < ActionController::Base # From https://github.com/plataformatec/devise/wiki/How-To:-Simple-Token-Authentication-Example # https://gist.github.com/josevalim/fb706b1e933ef01e4fb6 def authenticate_user_from_private_token! - user_token = params[:authenticity_token].presence || params[:private_token].presence || request.headers['PRIVATE-TOKEN'].presence + user_token = params[:private_token].presence || request.headers['PRIVATE-TOKEN'].presence user = user_token && User.find_by_authentication_token(user_token.to_s) if user diff --git a/app/models/personal_access_token.rb b/app/models/personal_access_token.rb index c7c3932ba4..c4b095e0c0 100644 --- a/app/models/personal_access_token.rb +++ b/app/models/personal_access_token.rb @@ -1,4 +1,7 @@ class PersonalAccessToken < ActiveRecord::Base + include TokenAuthenticatable + add_authentication_token_field :token + belongs_to :user scope :active, -> { where(revoked: false).where("expires_at >= NOW() OR expires_at IS NULL") } @@ -6,7 +9,7 @@ class PersonalAccessToken < ActiveRecord::Base def self.generate(params) personal_access_token = self.new(params) - personal_access_token.token = Devise.friendly_token(50) + personal_access_token.ensure_token personal_access_token end diff --git a/app/views/profiles/personal_access_tokens/index.html.haml b/app/views/profiles/personal_access_tokens/index.html.haml index 02800c3791..f7482d2c87 100644 --- a/app/views/profiles/personal_access_tokens/index.html.haml +++ b/app/views/profiles/personal_access_tokens/index.html.haml @@ -21,7 +21,8 @@ .form-group = f.label :expires_at, class: 'label-light' - = f.text_field :expires_at, class: "form-control datepicker", required: false + = f.hidden_field :expires_at, class: "form-control", required: false + .datepicker .prepend-top-default = f.submit 'Add Personal Access Token', class: "btn btn-create" @@ -90,16 +91,5 @@ :javascript $(".datepicker").datepicker({ dateFormat: "yy-mm-dd", - beforeShow: function() { - //////////////////////////////////////////////////////////////// - // 1. Need the setTimeout because the datepicker doesn't have // - // an `afterShow` callback. // - // 2. Need to set the z-index like this because we don't want // - // to target datepickers outside the current page, which // - // will happen if we set this in CSS directly. // - //////////////////////////////////////////////////////////////// - setTimeout(function(){ - $('.ui-datepicker').css('z-index', 3); - }, 0); - } - }); + onSelect: function(dateText, inst) { $("#personal_access_token_params_expires_at").val(dateText) } + }).datepicker("setDate", $.datepicker.parseDate('yy-mm-dd', $('#personal_access_token_params_expires_at').val())); diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index 1ec51465cd..e8bdbf1afb 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -40,12 +40,6 @@ describe ApplicationController do let(:user) { create(:user) } - it "logs the user in when the 'authenticity_token' param is populated with the private token" do - get :index, authenticity_token: user.private_token - expect(response.status).to eq(200) - expect(response.body).to eq("authenticated") - end - it "logs the user in when the 'private_token' param is populated with the private token" do get :index, private_token: user.private_token expect(response.status).to eq(200) diff --git a/spec/features/profiles/personal_access_tokens_spec.rb b/spec/features/profiles/personal_access_tokens_spec.rb index ce972776ff..e9fbeefae7 100644 --- a/spec/features/profiles/personal_access_tokens_spec.rb +++ b/spec/features/profiles/personal_access_tokens_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe 'Profile > Personal Access Tokens', feature: true do +describe 'Profile > Personal Access Tokens', feature: true, js: true do let(:user) { create(:user) } before do @@ -13,18 +13,22 @@ describe 'Profile > Personal Access Tokens', feature: true do fill_in "Name", with: FFaker::Product.brand expect {click_on "Add Personal Access Token"}.to change { PersonalAccessToken.count }.by(1) - active_personal_access_tokens = find(".table.active-personal-access-tokens").native.inner_html + active_personal_access_tokens = find(".table.active-personal-access-tokens").native['innerHTML'] expect(active_personal_access_tokens).to match(PersonalAccessToken.last.name) expect(active_personal_access_tokens).to match("Never") expect(active_personal_access_tokens).to match(PersonalAccessToken.last.token) fill_in "Name", with: FFaker::Product.brand - fill_in "Expires at", with: 5.days.from_now + + # Set date to 1st of next month + find("a[title='Next']").click + click_on "1" + expect {click_on "Add Personal Access Token"}.to change { PersonalAccessToken.count }.by(1) - active_personal_access_tokens = find(".table.active-personal-access-tokens").native.inner_html + active_personal_access_tokens = find(".table.active-personal-access-tokens").native['innerHTML'] expect(active_personal_access_tokens).to match(PersonalAccessToken.last.name) - expect(active_personal_access_tokens).to match(5.days.from_now.to_date.to_s) + expect(active_personal_access_tokens).to match(Date.today.next_month.at_beginning_of_month.to_s) expect(active_personal_access_tokens).to match(PersonalAccessToken.last.token) end end @@ -35,7 +39,7 @@ describe 'Profile > Personal Access Tokens', feature: true do visit profile_personal_access_tokens_path click_on "Revoke" - inactive_personal_access_tokens = find(".table.inactive-personal-access-tokens").native.inner_html + inactive_personal_access_tokens = find(".table.inactive-personal-access-tokens").native['innerHTML'] expect(inactive_personal_access_tokens).to match(personal_access_token.name) expect(inactive_personal_access_tokens).to match(personal_access_token.token) end @@ -44,7 +48,7 @@ describe 'Profile > Personal Access Tokens', feature: true do personal_access_token = create(:personal_access_token, expires_at: 5.days.ago, user: user) visit profile_personal_access_tokens_path - inactive_personal_access_tokens = find(".table.inactive-personal-access-tokens").native.inner_html + inactive_personal_access_tokens = find(".table.inactive-personal-access-tokens").native['innerHTML'] expect(inactive_personal_access_tokens).to match(personal_access_token.name) expect(inactive_personal_access_tokens).to match(personal_access_token.token) end diff --git a/spec/models/personal_access_token_spec.rb b/spec/models/personal_access_token_spec.rb new file mode 100644 index 0000000000..3e80a48175 --- /dev/null +++ b/spec/models/personal_access_token_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +describe PersonalAccessToken, models: true do + describe ".generate" do + it "generates a random token" do + personal_access_token = PersonalAccessToken.generate({}) + expect(personal_access_token.token).to be_present + end + + it "doesn't save the record" do + personal_access_token = PersonalAccessToken.generate({}) + expect(personal_access_token).to_not be_persisted + end + end +end From 2768e99ac386598480a7ac5490deee644125dfa1 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Thu, 28 Apr 2016 17:18:49 +0530 Subject: [PATCH 091/730] Add documentation for personal access tokens. --- doc/api/README.md | 63 ++++++++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/doc/api/README.md b/doc/api/README.md index ff039f1886..0e9dc7acfe 100644 --- a/doc/api/README.md +++ b/doc/api/README.md @@ -37,13 +37,11 @@ following locations: ## Authentication -All API requests require authentication. You need to pass a `private_token` -parameter via query string or header. If passed as a header, the header name -must be `PRIVATE-TOKEN` (uppercase and with a dash instead of an underscore). -You can find or reset your private token in your account page (`/profile/account`). +All API requests require authentication via a token. There are three types of tokens +available: private tokens, OAuth 2 tokens, and personal access tokens. -If `private_token` is invalid or omitted, then an error message will be -returned with status code `401`: +If a token is invalid or omitted, an error message will be returned with +status code `401`: ```json { @@ -51,6 +49,39 @@ returned with status code `401`: } ``` +### Private Tokens + +You need to pass a `private_token` parameter via query string or header. If passed as a +header, the header name must be `PRIVATE-TOKEN` (uppercase and with a dash instead of +an underscore). You can find or reset your private token in your account page +(`/profile/account`). + +### OAuth 2 Tokens + +You can use an OAuth 2 token to authenticate with the API by passing it either in the +`access_token` parameter or in the `Authorization` header. + +Example of using the OAuth2 token in the header: + +```shell +curl -H "Authorization: Bearer OAUTH-TOKEN" https://gitlab.example.com/api/v3/projects +``` + +Read more about [GitLab as an OAuth2 client](oauth2.md). + +### Personal Access Tokens + +> **Note:** This feature was [introduced][ce-3749] in GitLab 8.8 + +You can create as many personal access tokens as you like from your GitLab +profile (`/profile/personal_access_tokens`); perhaps one for each application +that needs access to the GitLab API. + +Once you have your token, pass it to the API using either the `personal_access_token` +parameter or the `PERSONAL-ACCESS-TOKEN` header. + +## Basic Usage + API requests should be prefixed with `api` and the API version. The API version is defined in [`lib/api.rb`][lib-api-url]. @@ -69,25 +100,6 @@ curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/ The API uses JSON to serialize data. You don't need to specify `.json` at the end of an API URL. -## Authentication with OAuth2 token - -Instead of the `private_token` you can transmit the OAuth2 access token as a -header or as a parameter. - -Example of OAuth2 token as a parameter: - -```shell -curl https://gitlab.example.com/api/v3/user?access_token=OAUTH-TOKEN -``` - -Example of OAuth2 token as a header: - -```shell -curl -H "Authorization: Bearer OAUTH-TOKEN" https://example.com/api/v3/user -``` - -Read more about [GitLab as an OAuth2 client](oauth2.md). - ## Status codes The API is designed to return different status codes according to context and @@ -323,3 +335,4 @@ programming languages. Visit the [GitLab website] for a complete list. [GitLab website]: https://about.gitlab.com/applications/#api-clients "Clients using the GitLab API" [lib-api-url]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/lib/api/api.rb +[ce-3749]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3749 From c46f3bcb5184f93f6424efbd4a2117caa6b6193f Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 29 Apr 2016 13:11:07 +0200 Subject: [PATCH 092/730] few fixes and new integration spec -WIP --- .../import_export/project_tree_restorer.rb | 1 - lib/gitlab/import_export/repo_restorer.rb | 2 +- .../import_export/import_file_spec.rb | 22 ++++++++++++++++++ .../import_export/test_project_export.tar.gz | Bin 0 -> 353039 bytes 4 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 spec/features/projects/import_export/import_file_spec.rb create mode 100644 spec/features/projects/import_export/test_project_export.tar.gz diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index 7b41ba0685..a5dc3a7c9c 100644 --- a/lib/gitlab/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -66,7 +66,6 @@ module Gitlab end def process_sub_relation(relation_hash, relation_item, sub_relation) - sub_relation_object = nil if relation_hash.is_a?(Array) sub_relation_object = create_relation(sub_relation, relation_hash) else diff --git a/lib/gitlab/import_export/repo_restorer.rb b/lib/gitlab/import_export/repo_restorer.rb index aa90f05368..aae65f6adc 100644 --- a/lib/gitlab/import_export/repo_restorer.rb +++ b/lib/gitlab/import_export/repo_restorer.rb @@ -14,7 +14,7 @@ module Gitlab FileUtils.mkdir_p(repos_path) FileUtils.mkdir_p(path_to_repo) - untar_czf(archive: @path, dir: path_to_repo) + untar_zxf(archive: @path, dir: path_to_repo) end private diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb new file mode 100644 index 0000000000..e40ed9a683 --- /dev/null +++ b/spec/features/projects/import_export/import_file_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +feature 'project import', feature: true, js: true do + include Select2Helper + + let(:user) { create(:user) } + let!(:namespace) { create(:namespace, name: "asd", owner: user) } + background do + login_as(user) + end + + scenario 'user imports an exported project successfully' do + visit new_project_path + + select2('asd', from: '#project_namespace_id') + fill_in :project_path, with:'test-project-path', visible: true + click_link 'GitLab project' + + expect(page).to have_content('GitLab export file') + expect(URI.parse(current_url).query).to eq('namespace_id=asd&path=test-project-path') + end +end diff --git a/spec/features/projects/import_export/test_project_export.tar.gz b/spec/features/projects/import_export/test_project_export.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..bc447b4a62a2094563ca643e680321ba8f99549c GIT binary patch literal 353039 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

2Fm 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⩔mjFqEc(6R~1t7XQh#X>7L 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 v3}Yww-HieN{C@j^zkBqa|M+81cx%VuzvA9L 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 P4gdT<((kwK07wV`Uk1M* literal 0 HcmV?d00001 From 7ebf22e0024f457238090c3545b8acafae0e1a6f Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 29 Apr 2016 15:15:27 +0200 Subject: [PATCH 093/730] more refactoring and fixes - fixing spec as well --- .../import_export/project_tree_restorer.rb | 10 +++--- lib/gitlab/import_export/repo_bundler.rb | 1 + lib/gitlab/import_export/repo_restorer.rb | 5 +-- .../import_export/import_file_spec.rb | 35 +++++++++++++++++-- 4 files changed, 40 insertions(+), 11 deletions(-) diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index a5dc3a7c9c..d283410175 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 - attr_reader :project def initialize(path:, user:, project_path:) @path = File.join(path, 'project.json') @@ -16,6 +15,10 @@ module Gitlab create_relations end + def project + @project ||= create_project + end + private def members_map @@ -41,17 +44,12 @@ module Gitlab Gitlab::ImportExport::ImportExportReader.tree.reject { |model| model.is_a?(Hash) && model[:project_members] } end - def project - @project ||= create_project - end - def create_project project_params = @tree_hash.reject { |_key, value| value.is_a?(Array) } project = Gitlab::ImportExport::ProjectFactory.create( project_params: project_params, user: @user) project.path = @project_path project.save - project.import_start project end diff --git a/lib/gitlab/import_export/repo_bundler.rb b/lib/gitlab/import_export/repo_bundler.rb index 86c9501b70..e719ee2e9e 100644 --- a/lib/gitlab/import_export/repo_bundler.rb +++ b/lib/gitlab/import_export/repo_bundler.rb @@ -26,6 +26,7 @@ module Gitlab false end + # TODO remove magic keyword and move it to a shared config def project_filename "project.bundle" end diff --git a/lib/gitlab/import_export/repo_restorer.rb b/lib/gitlab/import_export/repo_restorer.rb index aae65f6adc..2c67bd5a84 100644 --- a/lib/gitlab/import_export/repo_restorer.rb +++ b/lib/gitlab/import_export/repo_restorer.rb @@ -3,9 +3,10 @@ module Gitlab class RepoRestorer include Gitlab::ImportExport::CommandLineUtil - def initialize(project: , path:, bundler_file: ) + def initialize(project: , path: ) @project = project - @path = File.join(path, bundler_file) + # TODO remove magic keyword and move it to a shared config + @path = File.join(path, 'project.bundle') end def restore diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb index e40ed9a683..32e131d704 100644 --- a/spec/features/projects/import_export/import_file_spec.rb +++ b/spec/features/projects/import_export/import_file_spec.rb @@ -3,8 +3,10 @@ require 'spec_helper' feature 'project import', feature: true, js: true do include Select2Helper - let(:user) { create(:user) } + let(:user) { create(:admin) } let!(:namespace) { create(:namespace, name: "asd", owner: user) } + let(:file) { File.join(Rails.root, 'spec', 'features', 'projects', 'import_export', 'test_project_export.tar.gz') } + background do login_as(user) end @@ -12,11 +14,38 @@ feature 'project import', feature: true, js: true do scenario 'user imports an exported project successfully' do visit new_project_path - select2('asd', from: '#project_namespace_id') + select2('2', from: '#project_namespace_id') fill_in :project_path, with:'test-project-path', visible: true click_link 'GitLab project' expect(page).to have_content('GitLab export file') - expect(URI.parse(current_url).query).to eq('namespace_id=asd&path=test-project-path') + expect(URI.parse(current_url).query).to eq('namespace_id=2&path=test-project-path') + attach_file('file', file) + + #TODO check timings + + sleep 1 + + click_on 'Continue to the next step' + + sleep 1 + + end + + def drop_in_dropzone(file_path) + # Generate a fake input selector + page.execute_script <<-JS + var fakeFileInput = window.$('').attr( + {id: 'fakeFileInput', type: 'file'} + ).appendTo('body'); + JS + # Attach the file to the fake input selector with Capybara + attach_file("fakeFileInput", file_path) + # Add the file to a fileList array and trigger the fake drop event + page.execute_script <<-JS + var fileList = [$('#fakeFileInput')[0].files[0]]; + var e = jQuery.Event('drop', { dataTransfer : { files : fileList } }); + $('.div-dropzone')[0].dropzone.listeners[0].events.drop(e); + JS end end From 07ab6c2e26a36734ad29ae037810c14d2be7ec8b Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 2 May 2016 11:29:21 +0200 Subject: [PATCH 094/730] refactoring and fixing a bunch of stuff --- .../import/gitlab_projects_controller.rb | 8 +-- .../import/gitlab_projects/status.html.haml | 55 ------------------- lib/gitlab/import_export/command_line_util.rb | 2 +- lib/gitlab/import_export/import_service.rb | 3 +- lib/gitlab/import_export/repo_restorer.rb | 2 +- .../import_export/import_file_spec.rb | 5 +- 6 files changed, 7 insertions(+), 68 deletions(-) diff --git a/app/controllers/import/gitlab_projects_controller.rb b/app/controllers/import/gitlab_projects_controller.rb index b141b5f472..f8d4bcff55 100644 --- a/app/controllers/import/gitlab_projects_controller.rb +++ b/app/controllers/import/gitlab_projects_controller.rb @@ -12,13 +12,7 @@ class Import::GitlabProjectsController < Import::BaseController end def status - @repos = client.projects - @incompatible_repos = client.incompatible_projects - @already_added_projects = current_user.created_projects.where(import_type: "gitlab_project") - already_added_projects_names = @already_added_projects.pluck(:import_source) - - @repos.to_a.reject!{ |repo| already_added_projects_names.include? "#{repo["owner"]}/#{repo["slug"]}" } end def jobs @@ -39,6 +33,8 @@ class Import::GitlabProjectsController < Import::BaseController tmp_file: File.expand_path(file.path), namespace_id: namespace_id, project_path: path) + + redirect_to status_import_gitlab_project_path end private diff --git a/app/views/import/gitlab_projects/status.html.haml b/app/views/import/gitlab_projects/status.html.haml index 2b879f0c59..e69de29bb2 100644 --- a/app/views/import/gitlab_projects/status.html.haml +++ b/app/views/import/gitlab_projects/status.html.haml @@ -1,55 +0,0 @@ -- page_title "Gitlab_project import" -- header_title "Projects", root_path -%h3.page-title - %i.icon-gitlab.icon-gitlab-big - Import Gitlab projects - -%p.light - Select projects you want to import. -%hr -%p - = button_tag class: "btn btn-import btn-success js-import-all" do - Import all projects - = icon("spinner spin", class: "loading-icon") - -.table-responsive - %table.table.import-jobs - %colgroup.import-jobs-from-col - %colgroup.import-jobs-to-col - %colgroup.import-jobs-status-col - %thead - %tr - %th From Gitlab_project.org - %th To GitLab - %th Status - %tbody - - @already_added_projects.each do |project| - %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"} - %td - = link_to project.import_source, "https://gitlab_project.org/#{project.import_source}", target: "_blank" - %td - = link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project] - %td.job-status - - if project.import_status == 'finished' - %span - %i.fa.fa-check - done - - elsif project.import_status == 'started' - %i.fa.fa-spinner.fa-spin - started - - else - = project.human_import_status_name - - - @repos.each do |repo| - %tr{id: "repo_#{repo.id}"} - %td - = link_to repo.full_name, "https://gitlab_project.org/#{repo.full_name}", target: "_blank" - %td.import-target - = repo.full_name - %td.import-actions.job-status - = button_tag class: "btn btn-import js-add-to-import" do - Import - = icon("spinner spin", class: "loading-icon") - -:javascript - new ImporterStatus("#{jobs_import_gitlab_project_path}", "#{import_gitlab_project_path}"); diff --git a/lib/gitlab/import_export/command_line_util.rb b/lib/gitlab/import_export/command_line_util.rb index 9fc83afc4f..5ff72f5ff8 100644 --- a/lib/gitlab/import_export/command_line_util.rb +++ b/lib/gitlab/import_export/command_line_util.rb @@ -9,7 +9,7 @@ module Gitlab untar_with_options(archive: archive, dir: dir, options: 'zxf') end - def untar_czf(archive:, dir:) + def untar_xf(archive:, dir:) untar_with_options(archive: archive, dir: dir, options: 'xf') end diff --git a/lib/gitlab/import_export/import_service.rb b/lib/gitlab/import_export/import_service.rb index 226499030a..227053481c 100644 --- a/lib/gitlab/import_export/import_service.rb +++ b/lib/gitlab/import_export/import_service.rb @@ -15,8 +15,7 @@ module Gitlab def execute Gitlab::ImportExport::Importer.import(archive_file: @archive_file, storage_path: storage_path) - restore_project_tree - restore_repo + project_tree.project if [restore_project_tree, restore_repo].all? end private diff --git a/lib/gitlab/import_export/repo_restorer.rb b/lib/gitlab/import_export/repo_restorer.rb index 2c67bd5a84..994fc4bea5 100644 --- a/lib/gitlab/import_export/repo_restorer.rb +++ b/lib/gitlab/import_export/repo_restorer.rb @@ -15,7 +15,7 @@ module Gitlab FileUtils.mkdir_p(repos_path) FileUtils.mkdir_p(path_to_repo) - untar_zxf(archive: @path, dir: path_to_repo) + untar_xf(archive: @path, dir: path_to_repo) end private diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb index 32e131d704..0bc2b85edb 100644 --- a/spec/features/projects/import_export/import_file_spec.rb +++ b/spec/features/projects/import_export/import_file_spec.rb @@ -8,6 +8,8 @@ feature 'project import', feature: true, js: true do let(:file) { File.join(Rails.root, 'spec', 'features', 'projects', 'import_export', 'test_project_export.tar.gz') } background do + export_path = "#{Dir::tmpdir}/import_file_spec" + allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path) login_as(user) end @@ -27,9 +29,6 @@ feature 'project import', feature: true, js: true do sleep 1 click_on 'Continue to the next step' - - sleep 1 - end def drop_in_dropzone(file_path) From b5f2a7e139f0c1803afb68c26042ce4f8cec9148 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 2 May 2016 11:58:35 +0200 Subject: [PATCH 095/730] fixed integration test --- .../import_export/import_file_spec.rb | 35 +++++++------------ 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb index 0bc2b85edb..05f6e28984 100644 --- a/spec/features/projects/import_export/import_file_spec.rb +++ b/spec/features/projects/import_export/import_file_spec.rb @@ -6,14 +6,19 @@ feature 'project import', feature: true, js: true do let(:user) { create(:admin) } let!(:namespace) { create(:namespace, name: "asd", owner: user) } let(:file) { File.join(Rails.root, 'spec', 'features', 'projects', 'import_export', 'test_project_export.tar.gz') } - + let(:export_path) { "#{Dir::tmpdir}/import_file_spec" } background do - export_path = "#{Dir::tmpdir}/import_file_spec" allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path) login_as(user) end + after(:each) do + FileUtils.rm_rf(export_path, secure: true) + end + scenario 'user imports an exported project successfully' do + expect(Project.all.count).to be_zero + visit new_project_path select2('2', from: '#project_namespace_id') @@ -22,29 +27,13 @@ feature 'project import', feature: true, js: true do expect(page).to have_content('GitLab export file') expect(URI.parse(current_url).query).to eq('namespace_id=2&path=test-project-path') + attach_file('file', file) - #TODO check timings + click_on 'Continue to the next step' # import starts - sleep 1 - - click_on 'Continue to the next step' - end - - def drop_in_dropzone(file_path) - # Generate a fake input selector - page.execute_script <<-JS - var fakeFileInput = window.$('').attr( - {id: 'fakeFileInput', type: 'file'} - ).appendTo('body'); - JS - # Attach the file to the fake input selector with Capybara - attach_file("fakeFileInput", file_path) - # Add the file to a fileList array and trigger the fake drop event - page.execute_script <<-JS - var fileList = [$('#fakeFileInput')[0].files[0]]; - var e = jQuery.Event('drop', { dataTransfer : { files : fileList } }); - $('.div-dropzone')[0].dropzone.listeners[0].events.drop(e); - JS + expect(Project.last).not_to be_nil + expect(Project.last.issues).not_to be_empty + expect(Project.last.repo_exists?).to be true end end From 5a4f576359a71a57c70544568d9291cba53a2d39 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 2 May 2016 18:22:18 +0200 Subject: [PATCH 096/730] fixing issues with project members mapping. Also added some more JS magic to the import page --- app/views/projects/new.html.haml | 11 +++++++++++ lib/gitlab/import_export/import_export_reader.rb | 4 +++- lib/gitlab/import_export/project_tree_restorer.rb | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index b3d755b379..f9d9216f62 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -131,3 +131,14 @@ var _href = $("a.import_gitlab_project").attr("href"); $(".import_gitlab_project").attr("href", _href + '?namespace_id=' + $("#project_namespace_id").val() + '&path=' + $("#project_path").val()); }); + $('.import_gitlab_project').attr('disabled',true) + $('.import_gitlab_project').attr('title', 'Project path required.'); + $('#project_path').keyup(function(){ + if($(this).val().length !=0) { + $('.import_gitlab_project').attr('disabled', false); + $('.import_gitlab_project').attr('title',''); + } else { + $('.import_gitlab_project').attr('disabled',true); + $('.import_gitlab_project').attr('title', 'Project path required.'); + } + }) diff --git a/lib/gitlab/import_export/import_export_reader.rb b/lib/gitlab/import_export/import_export_reader.rb index 717d3026f9..4e46899ec7 100644 --- a/lib/gitlab/import_export/import_export_reader.rb +++ b/lib/gitlab/import_export/import_export_reader.rb @@ -57,8 +57,10 @@ module Gitlab end def add_new_class(current_key, included_classes_hash, value) + only_except_hash = check_only_and_except(value) + # TODO: refactor this + value = (value.is_a?(Hash) ? value.merge(only_except_hash) : { value => only_except_hash }) if only_except_hash new_hash = { include: value } - new_hash.merge!(check_only_and_except(value)) included_classes_hash[current_key] = new_hash end diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index d283410175..0f2e371677 100644 --- a/lib/gitlab/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -49,6 +49,7 @@ module Gitlab project = Gitlab::ImportExport::ProjectFactory.create( project_params: project_params, user: @user) project.path = @project_path + project.name = @project_path project.save project end From 58b0b1a6615958d2ca7628a06898f81b316e6637 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 3 May 2016 11:13:10 +0200 Subject: [PATCH 097/730] picking export stuff from the UI branch --- .../projects/import_export/export_service.rb | 3 ++- lib/gitlab/import_export/command_line_util.rb | 14 ++++++++++++++ lib/gitlab/import_export/import_export_reader.rb | 4 +++- lib/gitlab/import_export/project_tree_saver.rb | 1 + lib/gitlab/import_export/repo_bundler.rb | 1 + lib/gitlab/import_export/saver.rb | 1 + 6 files changed, 22 insertions(+), 2 deletions(-) diff --git a/app/services/projects/import_export/export_service.rb b/app/services/projects/import_export/export_service.rb index ce13942c5d..5d5573cba5 100644 --- a/app/services/projects/import_export/export_service.rb +++ b/app/services/projects/import_export/export_service.rb @@ -1,8 +1,9 @@ module Projects module ImportExport class ExportService < BaseService + def execute(options = {}) - @shared = Gitlab::ImportExport::Shared.new(relative_path: project.path_with_namespace) + @shared = Gitlab::ImportExport::Shared.new(relative_path: File.join(project.path_with_namespace, 'work')) save_project_tree bundle_repo save_all diff --git a/lib/gitlab/import_export/command_line_util.rb b/lib/gitlab/import_export/command_line_util.rb index 7bf4b476b6..5ff72f5ff8 100644 --- a/lib/gitlab/import_export/command_line_util.rb +++ b/lib/gitlab/import_export/command_line_util.rb @@ -5,6 +5,14 @@ module Gitlab tar_with_options(archive: archive, dir: dir, options: 'cf') end + def untar_zxf(archive:, dir:) + untar_with_options(archive: archive, dir: dir, options: 'zxf') + end + + def untar_xf(archive:, dir:) + untar_with_options(archive: archive, dir: dir, options: 'xf') + end + def tar_czf(archive:, dir:) tar_with_options(archive: archive, dir: dir, options: 'czf') end @@ -20,6 +28,12 @@ module Gitlab _output, status = Gitlab::Popen.popen(cmd) status.zero? end + + def untar_with_options(archive:, dir:, options:) + cmd = %W(tar -#{options} #{archive} -C #{dir}) + _output, status = Gitlab::Popen.popen(cmd) + status.zero? + end end end end diff --git a/lib/gitlab/import_export/import_export_reader.rb b/lib/gitlab/import_export/import_export_reader.rb index 717d3026f9..4e46899ec7 100644 --- a/lib/gitlab/import_export/import_export_reader.rb +++ b/lib/gitlab/import_export/import_export_reader.rb @@ -57,8 +57,10 @@ module Gitlab end def add_new_class(current_key, included_classes_hash, value) + only_except_hash = check_only_and_except(value) + # TODO: refactor this + value = (value.is_a?(Hash) ? value.merge(only_except_hash) : { value => only_except_hash }) if only_except_hash new_hash = { include: value } - new_hash.merge!(check_only_and_except(value)) included_classes_hash[current_key] = new_hash end diff --git a/lib/gitlab/import_export/project_tree_saver.rb b/lib/gitlab/import_export/project_tree_saver.rb index f6fab0fe22..394411a56c 100644 --- a/lib/gitlab/import_export/project_tree_saver.rb +++ b/lib/gitlab/import_export/project_tree_saver.rb @@ -24,6 +24,7 @@ module Gitlab false end + # TODO remove magic keyword and move it to a shared config def project_filename "project.json" end diff --git a/lib/gitlab/import_export/repo_bundler.rb b/lib/gitlab/import_export/repo_bundler.rb index 86c9501b70..e719ee2e9e 100644 --- a/lib/gitlab/import_export/repo_bundler.rb +++ b/lib/gitlab/import_export/repo_bundler.rb @@ -26,6 +26,7 @@ module Gitlab false end + # TODO remove magic keyword and move it to a shared config def project_filename "project.bundle" end diff --git a/lib/gitlab/import_export/saver.rb b/lib/gitlab/import_export/saver.rb index f87e0fdc7e..634e58e603 100644 --- a/lib/gitlab/import_export/saver.rb +++ b/lib/gitlab/import_export/saver.rb @@ -14,6 +14,7 @@ module Gitlab def save if compress_and_save remove_storage_path + Rails.logger.info("Saved project export #{archive_file}") archive_file else false From 9d306eb132bf153a0c93dd870d3a098028f12384 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 3 May 2016 12:41:23 +0200 Subject: [PATCH 098/730] picking stuff from ui related to import --- app/models/project.rb | 10 ++++++++ app/workers/project_impor_worker.rb | 25 +++++++++++++++++++ lib/gitlab/import_export/import_service.rb | 25 +++++++++++-------- lib/gitlab/import_export/importer.rb | 3 ++- .../import_export/project_tree_restorer.rb | 15 +++++------ lib/gitlab/import_export/repo_restorer.rb | 9 ++++--- 6 files changed, 65 insertions(+), 22 deletions(-) create mode 100644 app/workers/project_impor_worker.rb diff --git a/app/models/project.rb b/app/models/project.rb index af62e8ecd9..3e782be637 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -359,6 +359,16 @@ class Project < ActiveRecord::Base def visible_to_user(user) where(id: user.authorized_projects.select(:id).reorder(nil)) end + + def create_from_import_job(current_user_id:, tmp_file:, namespace_id:, project_path:) + job_id = ProjectImportWorker.perform_async(current_user_id, tmp_file, namespace_id, project_path) + + if job_id + Rails.logger.info "Import job started for export #{tmp_file} with job ID #{job_id}" + else + Rails.logger.error "Import job failed to start for #{tmp_file}" + end + end end def team diff --git a/app/workers/project_impor_worker.rb b/app/workers/project_impor_worker.rb new file mode 100644 index 0000000000..0ef353fa44 --- /dev/null +++ b/app/workers/project_impor_worker.rb @@ -0,0 +1,25 @@ +class ProjectImportWorker + include Sidekiq::Worker + include Gitlab::ShellAdapter + + sidekiq_options queue: :gitlab_shell, retry: false + + def perform(current_user_id, tmp_file, namespace_id, path) + current_user = User.find(current_user_id) + + project = Gitlab::ImportExport::ImportService.execute(archive_file: tmp_file, + owner: current_user, + namespace_id: namespace_id, + project_path: path) + + # TODO: Move this to import service + # if result[:status] == :error + # project.update(import_error: result[:message]) + # project.import_fail + # return + # end + + project.repository.after_import + project.import_finish + end +end \ No newline at end of file diff --git a/lib/gitlab/import_export/import_service.rb b/lib/gitlab/import_export/import_service.rb index 978a581f57..227053481c 100644 --- a/lib/gitlab/import_export/import_service.rb +++ b/lib/gitlab/import_export/import_service.rb @@ -3,18 +3,19 @@ module Gitlab class ImportService def self.execute(*args) - new(args).execute + new(*args).execute end - def initialize(options = {}) - @archive_file = options[:archive_file] - @current_user = options[:owner] + def initialize(archive_file:, owner:, namespace_id:, project_path:) + @archive_file = archive_file + @current_user = owner + @namespace_path = Namespace.find(namespace_id).path + @project_path = project_path end def execute Gitlab::ImportExport::Importer.import(archive_file: @archive_file, storage_path: storage_path) - restore_project_tree - restore_repo(project_tree.project) + project_tree.project if [restore_project_tree, restore_repo].all? end private @@ -24,15 +25,19 @@ module Gitlab end def project_tree - @project_tree ||= Gitlab::ImportExport::ProjectTreeRestorer.new(path: storage_path, user: @current_user) + @project_tree ||= Gitlab::ImportExport::ProjectTreeRestorer.new(path: storage_path, user: @current_user, project_path: @project_path) end - def restore_repo(project) - Gitlab::ImportExport::RepoRestorer.new(path: storage_path, project: project).restore + def restore_repo + Gitlab::ImportExport::RepoRestorer.new(path: storage_path, project: project_tree.project).restore end def storage_path - @storage_path ||= Gitlab::ImportExport.export_path(relative_path: project.path_with_namespace) + @storage_path ||= Gitlab::ImportExport.export_path(relative_path: path_with_namespace) + end + + def path_with_namespace + File.join(@namespace_path, @project_path) end end end diff --git a/lib/gitlab/import_export/importer.rb b/lib/gitlab/import_export/importer.rb index 9f39984543..8f838287f9 100644 --- a/lib/gitlab/import_export/importer.rb +++ b/lib/gitlab/import_export/importer.rb @@ -13,13 +13,14 @@ module Gitlab end def import + FileUtils.mkdir_p(@storage_path) decompress_archive end private def decompress_archive - untar_czf(archive: @archive_file, dir: @storage_path) + untar_zxf(archive: @archive_file, dir: @storage_path) end end end diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index 4e0f555afe..0f2e371677 100644 --- a/lib/gitlab/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -1,11 +1,11 @@ module Gitlab module ImportExport class ProjectTreeRestorer - attr_reader :project - def initialize(path:, user:) + def initialize(path:, user:, project_path:) @path = File.join(path, 'project.json') @user = user + @project_path = project_path end def restore @@ -15,6 +15,10 @@ module Gitlab create_relations end + def project + @project ||= create_project + end + private def members_map @@ -40,14 +44,12 @@ module Gitlab Gitlab::ImportExport::ImportExportReader.tree.reject { |model| model.is_a?(Hash) && model[:project_members] } end - def project - @project ||= create_project - end - def create_project project_params = @tree_hash.reject { |_key, value| value.is_a?(Array) } project = Gitlab::ImportExport::ProjectFactory.create( project_params: project_params, user: @user) + project.path = @project_path + project.name = @project_path project.save project end @@ -63,7 +65,6 @@ module Gitlab end def process_sub_relation(relation_hash, relation_item, sub_relation) - sub_relation_object = nil if relation_hash.is_a?(Array) sub_relation_object = create_relation(sub_relation, relation_hash) else diff --git a/lib/gitlab/import_export/repo_restorer.rb b/lib/gitlab/import_export/repo_restorer.rb index 47be303e22..315ad88ee0 100644 --- a/lib/gitlab/import_export/repo_restorer.rb +++ b/lib/gitlab/import_export/repo_restorer.rb @@ -3,18 +3,19 @@ module Gitlab class RepoRestorer include Gitlab::ImportExport::CommandLineUtil - def initialize(project: , path:, bundler_file: ) + def initialize(project: , path: ) @project = project - @path = File.join(path, bundler_file) + # TODO remove magic keyword and move it to a shared config + @path = File.join(path, 'project.bundle') end def restore return false unless File.exists?(@path) - # Move repos dir to 'repositories.old' dir + # Move repos dir to 'repositories.old' dir FileUtils.mkdir_p(repos_path) FileUtils.mkdir_p(path_to_repo) - untar_cf(archive: @path, dir: path_to_repo) + untar_xf(archive: @path, dir: path_to_repo) end private From 6139e1433c7f1925a7fc599106656990410a4184 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 3 May 2016 12:46:00 +0200 Subject: [PATCH 099/730] fixing some rubucop warnings --- app/controllers/import/gitlab_project_controller.rb | 3 +-- .../{project_impor_worker.rb => project_import_worker.rb} | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) rename app/workers/{project_impor_worker.rb => project_import_worker.rb} (99%) diff --git a/app/controllers/import/gitlab_project_controller.rb b/app/controllers/import/gitlab_project_controller.rb index fa3e0c7876..ab0da196ac 100644 --- a/app/controllers/import/gitlab_project_controller.rb +++ b/app/controllers/import/gitlab_project_controller.rb @@ -28,12 +28,11 @@ class Import::GitlabProjectController < Import::BaseController def create @file = params[:file] - # @project_name = repo_owner = current_user.username @target_namespace = params[:new_namespace].presence || repo_owner - namespace = get_or_create_namespace || (render and return) + # namespace = get_or_create_namespace || (render and return) @project = Gitlab::ImportExport::ImportService.execute(archive_file: file, owner: repo_owner) end diff --git a/app/workers/project_impor_worker.rb b/app/workers/project_import_worker.rb similarity index 99% rename from app/workers/project_impor_worker.rb rename to app/workers/project_import_worker.rb index 0ef353fa44..0e8b955244 100644 --- a/app/workers/project_impor_worker.rb +++ b/app/workers/project_import_worker.rb @@ -22,4 +22,4 @@ class ProjectImportWorker project.repository.after_import project.import_finish end -end \ No newline at end of file +end From 1990616a21a38e8d0496c066e753282d9a061162 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 3 May 2016 13:06:00 +0200 Subject: [PATCH 100/730] fixed warning --- spec/lib/gitlab/import_export/project_tree_saver_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 8a923dde46..5c1b9af2c1 100644 --- a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb @@ -21,7 +21,7 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do labels: [label], snippets: [snippet], releases: [release] - ) + ) end let!(:ci_commit) { create(:ci_commit, project: project, sha: merge_request.last_commit.id, ref: merge_request.source_branch, statuses: [commit_status]) } let!(:milestone) { create(:milestone, title: "Milestone v1.2", project: project) } From 14964308dc4ca0d62dd12231529abbcfe940f603 Mon Sep 17 00:00:00 2001 From: Arinde Eniola Date: Tue, 3 May 2016 12:07:06 +0100 Subject: [PATCH 101/730] add gfm autocomplete for labels --- .../javascripts/gfm_auto_complete.js.coffee | 25 +++++++++++++++++++ app/controllers/projects_controller.rb | 1 + app/services/projects/autocomplete_service.rb | 4 +++ 3 files changed, 30 insertions(+) diff --git a/app/assets/javascripts/gfm_auto_complete.js.coffee b/app/assets/javascripts/gfm_auto_complete.js.coffee index 61e3f811e7..6d3f4ec975 100644 --- a/app/assets/javascripts/gfm_auto_complete.js.coffee +++ b/app/assets/javascripts/gfm_auto_complete.js.coffee @@ -14,6 +14,10 @@ GitLab.GfmAutoComplete = Members: template: '

  • ${username} ${title}
  • ' + Labels: + template: '
  • ${title}
    +
  • ' + # Issues and MergeRequests Issues: template: '
  • ${id} ${title}
  • ' @@ -94,6 +98,25 @@ GitLab.GfmAutoComplete = title: sanitize(m.title) search: "#{m.iid} #{m.title}" + @input.atwho + at: '~' + alias: 'labels' + searchKey: 'search' + displayTpl: @Labels.template + insertTpl: '${atwho-at}${title}' + callbacks: + beforeSave: (merges) -> + sanitizeLabelTitle = (title)-> + if /\w+\s+\w+/g.test(title) + "\"#{sanitize(title)}\"" + else + sanitize(title) + + $.map merges, (m) -> + title: sanitizeLabelTitle(m.title) + color: m.color + search: "#{m.title}" + destroyAtWho: -> @input.atwho('destroy') @@ -109,3 +132,5 @@ GitLab.GfmAutoComplete = @input.atwho 'load', 'mergerequests', data.mergerequests # load emojis @input.atwho 'load', ':', data.emojis + # load labels + @input.atwho 'load', '~', data.labels diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 3768efe142..4d7a3bfe64 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -148,6 +148,7 @@ class ProjectsController < Projects::ApplicationController emojis: AwardEmoji.urls, issues: autocomplete.issues, mergerequests: autocomplete.merge_requests, + labels: autocomplete.labels, members: participants } diff --git a/app/services/projects/autocomplete_service.rb b/app/services/projects/autocomplete_service.rb index ba50305dbd..826b10899d 100644 --- a/app/services/projects/autocomplete_service.rb +++ b/app/services/projects/autocomplete_service.rb @@ -7,5 +7,9 @@ module Projects def merge_requests @project.merge_requests.opened.select([:iid, :title]) end + + def labels + @project.labels.select([:title, :color]) + end end end From 68da2ac9a0fa6f33b46f0bfbc849043605c2d878 Mon Sep 17 00:00:00 2001 From: Arinde Eniola Date: Tue, 3 May 2016 12:09:13 +0100 Subject: [PATCH 102/730] add entry to CHANGELOG --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index b6527780bb..670f7fa3ab 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -12,6 +12,7 @@ v 8.8.0 (unreleased) - Display informative message when new milestone is created - Replace Devise Async with Devise ActiveJob integration. !3902 (Connor Shea) - Allow "NEWS" and "CHANGES" as alternative names for CHANGELOG. !3768 (Connor Shea) + - Added Gfm autocomplete for labels - Added button to toggle whitespaces changes on diff view - Backport GitLab Enterprise support from EE - Files over 5MB can only be viewed in their raw form, files over 1MB without highlighting !3718 From 315195fe56743db7f0546d3705b4c82fb3462d63 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 3 May 2016 13:18:39 +0200 Subject: [PATCH 103/730] fix schema file --- db/schema.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index 40a295ca63..04aee737e4 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -78,8 +78,8 @@ ActiveRecord::Schema.define(version: 20160421130527) do t.boolean "email_author_in_body", default: false t.integer "default_group_visibility" t.boolean "repository_checks_enabled", default: false - t.text "shared_runners_text" t.integer "metrics_packet_size", default: 1 + t.text "shared_runners_text" end create_table "audit_events", force: :cascade do |t| @@ -426,9 +426,9 @@ ActiveRecord::Schema.define(version: 20160421130527) do t.string "state" t.integer "iid" t.integer "updated_by_id" + t.integer "moved_to_id" t.boolean "confidential", default: false t.datetime "deleted_at" - t.integer "moved_to_id" t.date "due_date" end From fc329696e269044a9b366dbd5135aedca93bccd4 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 3 May 2016 13:40:49 +0200 Subject: [PATCH 104/730] typo --- app/views/import/gitlab_projects/new.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/import/gitlab_projects/new.html.haml b/app/views/import/gitlab_projects/new.html.haml index 1158a04ea4..d01f0190f3 100644 --- a/app/views/import/gitlab_projects/new.html.haml +++ b/app/views/import/gitlab_projects/new.html.haml @@ -2,7 +2,7 @@ - header_title "Projects", root_path %h3.page-title %i.fa.fa-bug - Import projects from FogBugz + Import projects from Gitlab %hr = form_tag import_gitlab_project_path, class: 'form-horizontal', multipart: true do From b69c8c280c029781e87834610a89704210f1a5c4 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 3 May 2016 15:07:05 +0200 Subject: [PATCH 105/730] fixing some export issues in spec --- .../import_export/test_project_export.tar.gz | Bin 353039 -> 352529 bytes 1 file changed, 0 insertions(+), 0 deletions(-) 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 bc447b4a62a2094563ca643e680321ba8f99549c..0c20898086d8766d77ac9ce2216d194532abd72c 100644 GIT binary patch delta 90020 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�z(<+&BDYw|4MO&{!_!`#i%-|2dGYHYLQ*tR|%aamMfxk4Z z4Y?s&N!dQrb!{u+!thJ&h%kmK2V85CT%FSHW=DU9@RkOSoVL0b@+Z?$Dk(2wi<7Z~ zgEZlL^Rpk2!NIumgPnXK^0AN5LZAxBi9_7H2_s7B`|f82)&(G9=%Svs<=B8U8OGw! z+d`bB$MUWVdZ;B9G#kN_qO^?Qx~V(Va$9C)%aEBAO|c=LObRGc=4#jaP1(f>1(otkv01n@38^ zbJbnQyn!kEXxk%w|4r!OuhY!3DJWL3FhbYV=61Wb%ma!OKOt;l`4%D0~RO+wc8fP-r z2nW6JqJ)6>>E8}>)~coy2j3i-k@MP6P)6hs_1m>?6k10=JQ6UNvu`{(>;QzcPyT<6 zOZjaQC@3a`o(CSTac{%iE*xSm>NCjPhauSws3unLt7$t_UD^>d+l%JpOR2qGd`GcU zX{Q5-4tOcAJ>!Mt54ko>XFEE!z0lmPXnQzz8!W5D!bWy?2t8)xRo;E#c~*f7M$+L~ zzNg_dO1&%`U>oSXxB;Eas4)s-`SyQ_v3%^-OPqNdx=@w;9F@H+w0ncQBM!ei65XNa zuNo+vpLRp8T7aJ%h>wswR5ozEhEB(!tG)AxnAk==2IG$N1G4CY;6d*?Xj3{SRTS3# z8Kjvh+s<0|WFtN$G)B4UdZmOD_uKa=os6z{{i2KV_IIsr_Pk87DNoxhKgxeHlUA-A zcqGHC>y($zwELYwSQbs}!tljHOx0;yJ>DI;Sp`J|N1nPyki`_e5+~KERVA}sPct$b zeKyhnB;*+Z5QSNhr<6K~q-y}-pvKlNGwtHqUAwoO=WJ7|EoHBv=fu=WFs0j^N{f<7 zz~OFcRn6bM`ur$%=Pyw}1F1CK6L;qonGl z`OqQDZxUeKS$Nkh+)w_DPw8|sD@`3sZ57A0BastaHx%W?;x=ARICtd?yWrJ#0V*J| z2^OP$^+rvz#;C``gjxrus;sx=$)LtkH1 z1fP8(^cjS)tS+lrP^JsoqOQSK(4Xa&Ffx4}*Rk`yL}rP|JXXM|%4pz!_AZ0!My)2D zOC95B^;TtK-7Gg~Ys{28#uKJ`aR}A_kuOXnuyabn zx|8EGC=>b!uI1Bdc=2U_KA8yc9wr9GRuI5jYrx!ghpNZ4UhuPjICd}oaN+&PibHr} z$c~3fdZt2-n{7&MLpDG^9`{B>Wr}1~Swe$N5(&e)44!7y*cz^k@j_(7Xe7G=V~Tl{ zbBn?aNIG|z#*DBKmVT%+{f&LQ?OSf+#o6xA1Z6J6!nSapJ?jI1D{p_~v2z{Y%LAIL zzj`iIB+WtFNk{lp^xfP2^lDn-*^e`oGJVcEP8Cqq)8aO$i6I_aZN zTS`@ll}1;Uy05W?l1ZTTg03HvLk-f}ja%ZTPqjt~-A{|(m}`0=^sSGgkR-~NfZM8PP`*2m?>6+8Iul4(7 zP2_vE&Rq|bN`zc19{xd)28r>H4Mc3jd;53t^M5JGZ!X~VA7DJEAVt+G&T zrKG&^GiYOfNbGg1sZSBC%<%DzA39vtbsdysPCJ}?w7Kuo(d@xtY+9DeS@q_e z197pTM*FxIP*%D6!XYL(ebCA4d6y(FMe>-v%s)|;?5tZc=fs}wCYEV2xMeY%d0u2; zeV`CqjqP47n9}x>0~=cXXSvk0=Eg0>*atbZ*v{pD@*Wt8;qD!bi`}51F8o*uDjs0* z39NCw&Dr&hPGm#yc*Gg`na)VH#_dO++uRJBVTq)FqMw>-PMJ^9ex9JJaj!!lK+pK& zJ^aDrVfuzF8U8dz>9qVDskps#=T8l%jkV{U%{h=~o|2en?*BpJ(Ynk9;r)&Z+TfFe zruV9Uj>MMB$`?FGgwof#IGDS3n?z3;-A_p%NbbOjUSJpuv8|~`#@bl8D~i5ub$kc! z%5G8>p{QpF$X%y(136;4=PhEeU3pSFB_;zu9vr~#p6WRxrD!(Cu8GZrT}}umU(>48 zs#x!L{MhS3csPb1%X6Y5_(1t|dJs}}Jy-gF#wv$74nFqQqY8JLjC)dE4uWp)fzWu2 zI(n&qOrwV^tfH#WHmT2>UERa(kcZfv!;*44RgQHg9s~>C(+gMR9bh&rKg}Q`Fsj>d zYUkt`NA4!{NG}_N+-%eZK-~A-p6WbH0LZ(9>EQ{bNlXJW;Ys%DtwgS`mRK4Po^?i3g&o4)u-MK|tL%unK zX$xa@X>qpB$s=P7mu@j};1y_>i{b<(e{Fa+uM~V<>$pD_bK+WWtLaoq{|WDbal5(R z(LCPm7t3>H+jm+xh8tGSyoM$y^5R5`_#&z5XBo0l-~%daYCv<|?>5?R!rpD%L?K7i zd@-3lmd&pwI}*)#{^pC+-NGD%5BGXy^n<)wMH9`as@Ym9+$E`>`z$BbsiLuFe`jfQ zT+-dgOx`CBg!D+h*iczpfWd{!BW`~vWFC9=)+8jlwZbGIZfo|ua-RuH_X{2Zu$WVk zd7jw3JK(?zK_OJ7s=uR_GY!n{aH!;zQ>pB(+(PNfg2k(SipeSrg*hRks7NL3V($T? zilF1grhDnex%}L85-8KUb7$v)f5ds+zCAhDop&dA5< z7H1_E931a^I+N8|Y1$J!-%}Y~)uHnuDVZW#ksDcS)en1F)R4cW;a%A)^yUwBV%cf4 zyJgficRX}#e^2^&T=*n|h~ZlW zy1e}@2Gb5&b3AS#qHil6f0}peZ{ng)`v{h3vW@3cb@+&dGBri#H~cf6i!6O`Hd=IiIBS zZyXUVdRFDQ)ik2PYe9tuvT2-d7#wp-oyBzCDF0Dvy~mVn`Q+IXkgTR+aC|m-PPa7B z+;A~hEYV6w$J@VOX(K4^EPp_crP#!0(1|ljQ}51-A-lFK&E1c@@ebcsCUh&E+t+6z z!AA0s6jPknNBx9Pf33UN974D28IMJ&-W|C!CfRP(A);_7-X4fP)M|H4tfYLlo^z3T z%KF^h*+q$VH5TpM691NN(Ru*3ctz!echyN6T6*v1<4r+((wW!q>7R9iAWWFZWsPrC zTgGoTo!p;v^Dd0*TGYmw@TNU_VKHo0G@O{hm{jw_Q=dT(e>b#9ot~!ezdMpx3xj@e z6&4V4ylY#L0Di1s$+e*$f_>y_e!Aje858M1_W+s0{hF1M3Yh3LUVqcm!L!4J1EI0? zqfw&_&#U{s_ag)Q&Z`wCn{O5qh#OMk8{SG3mbmU*3F+{Sd3z)KxuD~gz$F0)UtuVF`+~X4tw$Dz zE7_Yg&0%*uttFoZtHN)CEW7eX>fH1Cc07{xe)e?lr&SrPR|hYp8~SIfGb=aB#jUyav) zZk3wQbbYE~PV}l-@Kb~EqO4w)XdV8imNA35s_s?!dnz2;?fbm58#ND%vqt7(Y*@Ov zG?{o^oodnMovbp-an*+|o_D|eF-Liu+Kl8n*kGFn<*alCwRsao5Np<)~i ze{!6YrWxSq)fvixD+5fH+kIg2_+5MlrRksAV0ke7$v1(H(T&5%vmH|BlB(SmAL#3L zuG5XEw9%jk4@SQxc`)+pKTmY&&A-<)e*JW;ujXd`YLRu`d7!urP%rwuoR#{XPaF-Z zT_*XrT*qJqeDa6sC*GWCW^$gqkLSvc36R>060Yk%ANLOy; zfjy^04#QAYA!qXr^3ZdCAY3bMu(o=;D9zeaW5$-)!@alGvPxFc0rP4Dym}xBfBWGH zefaaX6AT9|{lew+hitG$;!=YH7;av9j{O$`TV}{l1YkG(Od{sIqjWgSx|P!&VtKG^ zS5MPEbw)@@$1ZLS5M)dAB0-zaT9_Da^VJd z0dvPDt2AFSH~wG+3Qu*8v$CD}@g?DB)zqXSc47$qvBDxLnA>SvP&n!W0@Bq&yq8H6r1l^f1?>D=y zKe->J-<+nc`Ji}5e-!vKeRLVBmz5)Co%-`#=T1-_shT_78F?0KdgM^;*~`!RNW69! zEjb&P;h0@Vy;W_k>2~lfWDmw^NL#&7gLXlnyaQ554pzZa+hpPZ{PwGc@) zCryp*9R_8Ck}3HM2Lidxj2Cn;Tv7WH9G!(IHEc+)_=lyVE$XBlP>#t8n@I*EOAuNy zLO7HXMAT*Df2kqKnmu^KJLqyZNv%#VPUSPmnlUW2>RyULVk-*%NQBQMtA5Aj(#MY= zcjWi(<*bsO5}8G;56t@{cu~FCJ$y=iPv}#8JVdEd!5TYg$>{xdC}lJ%PqPPETN_Zc zPU%8%AME2;4}Un#06%A)kYoyjczbtW|GBP186u}Le`cN@k}PSL-Ctd~L9)q;FT6s! zs3EhxBb)~{uIa=+__mIQ_SHUH9p-?!i-rr0r*xqYvMV9g*WeRsrQDM*qk?EUxG$a{ z^m7#H@3}{8cr6aj3)!QM2_>!^_Jl2nEt~mOXr_NLvVg%dn&PAfZZvgL(WxzwxR4b|JTh-54sH>UQ{S=c$O{ zMs>TscRFt&mfcaPkwIpEGg5412|qG@=T`fHf4b7xI!NF7g{ut7*9K~eJg$-7^JeXx z^Sqy7SWjTO(LK>HxH8#G~&sgpJAS2_#x2HKj?PeeGORmO9qjQ%E4SgCQYx> zf0M!&D*6ny4?Z71!I2$&c!E>(bziuoofUM8SR3?X$v!8#3$^d=(La`Ft2f^^e@eMP zhC8>&$4x(PL53nFqd`libLeyyFb%6k+@~c42e$e?6TZje^&RpttnK@8-w6(2MbB3|H_uMvSRo zcVZOoA%~Rm(twx_>-Pkg-$d0f9u=W z@+52yv%520j6YU5PwrKN*R(m%DkhaiCM#$8sx979%fiK}*rHz5blMbh*^Re5ZJjC3 z>EB?;<#Cu}+*j62xIhrr*Py-G_tpZ#SWHA`ske7rz(7Uo`v>O>n}~6Y`PYJtYWKI7 z4ia-2w>$|8@%59{jzD-94`Y7pE40Sy<36}#nLo^Pj@E2v|D3EoVN%v#K>HQ!G%e>`{XgJR{_ zCV$|x$hrhaC!D9|U534P23th})n9#(?b{VR8?5-K;njWdv#+zoH!GgPu}8tP^Ju)d zk{G!?56{p~%z4MY)(hIuD2s7e_kB~=XRRhvvzt{M3{$M5`}ktGe==esH`Z{sOsPWYj>{2ST`V)xV3k+;`#JUQ368f4*d&yXn?Nhh+A4 z)!*)1D6zipd_1C`$tFooh0$;QJ(Yphq$+Pu9n^DwnJL|t39tKxV8>R|*)dgW<7AU>BZoVj zD%_!vAPX;hE6YIEe`)W&o~}REo|`9~c!D^0KjfAHmf-vt#%K{H6o294g2Hk6y+fzo z7xr0Jm5VZJGz{`?n@S2ieXE1<+@oM$zP>BlO+~_Pt!ISnf|ibyJ#s$lyQ>1y*40+u zcedF<+lpvu`dTMUnF8OUU=eB&j!}SL(rdm(S1>rMs}pACe;DTMUv;FUIepx?=$z{z z8d(V;rB5b%ubr&e!XORe8&EyQOqp;)T|%%hlvDQlyfrt!I@YGv9ByoMqzPg1x(cTL zsD~@Yj|n6qcbvObuzzU&%(QU%{hJXbf${3$u#BYG#P!O6mbq40XZR$?Y-i9uqHe zf|VHCEME6(`pI1x;M3SQbGU>_VZw=%zENspFQHeQf2Dndy;$J+Brd$8CNDQq10`TF z39Bp}FdGb74`Q{^K<=nmlzFFgFV|8?m0A5&*ADimcQC)pvg@Cv@LS6VCrWr1WGX2# z?U;7*vvL=;Om8qFY|?+p}%fWn9eK zQ)ZM>zkckhhqz|r@j;z~v@!;D4MhU%bRe6}HXGBAP7&V=);2AsSD;S_9=ToM&q$(m zeEqS?5ktqyKtH)f=+pJot`UQV%&F67XE`hOe>GmM2tc>%?Z<2dADYgQ1A%Ox#hJ&) ziBf7jdZw7M2JW{~Z@=2L`EB~PHgd^!8SatjTjBNf7mYno^{;P@#H8?DL^YMsb1Bn; z26xFf7pd;@E!xEvS{{o&5+b={tKo|(tCp6UZ78R8cN7NVFVTjxDAwA3+C8=FoV#_h ze@F4IJ+yY)>#g2-D$r@(j3&`NcBc1LtgoGk**S>l**1TElAT#uwWP_uP>-1B5|Dl8 zk*8+EEv%-37sr%K=SB;iw7fk}?6z-{HYqRRv~*BOZYokGTE1j|R@l|CeMT@Wq~%bh zYOpWMl~Sp#}`fv!3Y?6HQlZNX|=7 z#-@*S?`OuMk+HMmola`|#rYMlK3VTr0&(PFISNe!rCf64^O z;59d3xQQVi&UX}zpE*?P>YyD{x5L@|N4p{w!#yq2HV<-xY~-b}bh@?CRw?O6-tCY` zF*lHozHTNM&M)HUP0OX(OSF@=EtP6Do*L6?;BOO)wsPRYKONtC)S9z&Ay)Ha9Svjb zwXm4Cg9mKYt)n8#?JwyJC%S7ke~VALZ}nggGhP3>>Jk%&Kek%x-b}UBFnx6TREoS| zJTtTEqsVQsCr0KvE8pFHb=>o~5$lFViFE#CBb|uKD@omL!3uRFcW>k=F>@gT2#&@# ztAX`iPjDg1icOfuQ}O3=7*h^qFG5)-`Z?n3F#7C(j*z~}hmMT#cOeXqe=L)w+hj@A zld+#cna4!4%`F6uSAc~?$T9omgVxDaVm=*Lnj4eD~u>BYG`@<8s{`mFm-_TGS5=7u?buzDgJe`7U2$5>QOyzPsT zjybt`$FZHKAFB12hHW{nGts$OVx3gT!J|=gd*_eK$TXzSr)fz<7UnG!m*jssk(4VACSLp;lThj!DpvhW(VxT`0LpFyhoX8eLgEYNTl(HbUIh$ghjsh=f;8eg9E z(T=y%Pzg8YFKQNqf7Fo}=At&$2*Q-*R4DUq!@|>7yz5-foO$~Q-5Vb&b=0y~mN(W- ztFYO@nn|S9eC~sPY=p14Z>Nf+lY%oncZ@@tsmjHHu&LbOe`$*1v`%3^=dADot1&x+ zU>x$iadSqnie_S^GDD%0*k%p-?0B0@333TO-hYQ~&8;ry_(wBOgYFg-@OYM_ZbxW#Pdwv z`+&E$F6k#moILj#TbUKtW8|$0UMT72+E(^8bN4pRf5#g(Hx8@k`^=cRk8zk1LzIq- zsBSAoxT!cX^7|An2FkE^-%%E)QhYCYoj_q8V^hfl%rkK)(u6u6w-sqAp6=(Ou-;+W z<7Rt7nzC`P^qZE#Nsh6+grj~U;>kWxtB?a)5j7TZHXcx8@xWPh6GDF{=O#5cLjr)| zmkO5!f0@l)oM2ZD+4Ul?&rMy7IK3lKAWU_;>HS>%6^;Rj{rll-<409KYdZDr8fY^c*xq+xrbeY8>UkvYQ!ju|xTjx+{oJr7VqyGFh~ue|Mt ze~s?o`xjJE5Bgg?%Fgd_EEh24W^{K-Vg9hyUC3#h>^XP6#x#Y3`#Fz&AfR7L6)xXYEqcRLa088X zVbe8}rw!wRog$&gyu}ciogJ3Y`Ortcf7f;Bx(%m}fuJ8kWL}Mo95#m-p=c>@QCCrsaNt`O5Xk*S}WU{u{wiu?xmgUVUm zMOhQa`mH&H6WwTbpctnM^@puW+TW8H?{b&?F&s-rQp z$XEC`CmuAWebhu2-1s2XxBmVxY2%5uDz3AdlrsjdexGiqjP6v5u=bo2b~B5DsjySR z?`kNpOijTg8tTQUQ;NKJ{uA566PWoYA%%R9M^f7-%|geI&$b28EU+9_fBeAuQRMNZ z>0N=^xX0cO77B5;WqDPck6f$H<}gzpKewOd*DPpyxwV3LLF_Z=iuV)f$jrr>`ctV% z=B@$G%158?d^wnJ7=EkH$)f9?ZCtr6*ghf7_z}@XwCXkglLy7%&~tenN^W-DYm7grEU;M23*e@>orA`7Sm66TXg zh&rg&!|9;dG0Ch!jV;v6L1jSBQ9~uuvLTIH*A4Wn??znZEaQKjXd15`W1no+Gj$}? z%V1mL`_t!(Z1SLkH_MG*T-hF%xGU4PBP7N?JHPDA zFuNYoYe&C-AAqC0tfUg=;LaRzaa`hE&`>a8tCX6DMT(HO7Z;E(<+iocUf>w)bQ#8z zPSrIpHQl*sU)uQ{9pkw|_aktjS%bp@GwPe6UZC_lW{Hh%e}4551Iw2K`?t7BTJwIC z55PX>=P1sgaGNpcH9xq%VBTjXvEv}SN~e>l-z#dCVsbXS<950OOF++-+1p7XWjTybShrpYWM3zIfbQk_ zC$w=3Y@YRVe+E;Y@f-7+K9UE7kBOFS>5)6*MDgCtBH!$o4&1nn%3&YA{HiDGoo}|e zYRZ8YhmedPE9<-S(`9O3;UCpLmr zE+~!D=(Sy9qPZYJ2u)^dYLMerPne27@VtVc^?X+K%oZ-rPxTMfJ?B1ygdHc^>Q3{L zlY2jdp0~L1HwDsqO^fe;m!Tj=c>ErD3NNTc!Ls?^G`NTpS)jSqBg1ZAetRVHp}bu5Pjt3-O5q0 z9evsR0{N~ITh!I{_q1;+#Cc90Iv;7zFw=hQ1a_CgLxOD+c0b=t@8hDmJ^QDf>ucXn zC0N_{+j>y0q_q22ZQ_J&<1gx+?`qg>e8%u~e@mEOi^^k+R$kslhfF=+=z4dpf{mWK zr=c$orcjXByLnp^j4GZF4%p2Unz!$M7CFfF>N$sRySUQ;S28O{%AVv~zG|H_wf8AG z*N;uauOo_lKFiKzpY5Dm%lvpB{LXa2K*IZQ`+>o@8H2oY^gLC#V!^IYe)#qIdFvoXg-fxkc0+j&Dl0&k}9h}8}zkKzBCHy-^1JYzI%_EBB$@}o6}FT;?gensvLj^ zFKWd)-oL5hp$L|=ujt^o-(EL8L4(^He>+;lT>W%?Ra6~Kur9K3cXxMpf)m_>6FfnJ z2G_ye-Q9u*5AGTyxVyVM?8|@7UH9$2&6=66t}f}B>hAig#Om2!Ip>x;7e1; zO+M?p={vE;?s-(j!cGWwOQ2nB8#_U7O{+?0X#f6`Bd|YivhK!n5WMglqkbUH^nB2} z^G^GXI5)zmji{5#)7eraKE*2EXQ|fkEnKy=b)tu_nw0oN=}+ANTDy#3n^vj~!MYx; zz9#Si`gd<5wL1WEw9xez9JkTZ3Du@ZRD)vf$6H z$KQiO_XfcwkTV2k1T18>r~1n+(NPRRzYd8?$1A5}$=Y1!%xc6H-?DIGi=~h%+zQ7;B=T$t0j(J+M63AdT%K98Q8rUpYULa+e@T{?s{i&< z&FPU366d%KIIFJh+~g(Q!$3!eboSw>Hjt=!m` z&40I^i$-&#xvaOT%I(UIcda!Fq4NaRliodC_ez|mVWpkki7qu3s>`w6hABR^WF_j0 z2Mpj;_wL8G+4tPW_)cux%O4+VTuC=&S_Q1~Md&WLAr87}b6N7H@!#p7-hBGGLDj${ zrT&8zccI|T8aAfMXSQbGDQMzH{bux8xBIkKj0{cW(Xhr$?@B@w2LXdE&*~j;srgeY z=OL)gy+2KZ<_G%MSbM^BC1-df{pNF&p^))`L-3!83I~tf(e9n~xvWqe94zIdc zQk;KthxPb}dIYSRh$f&qvf#DP2s@$g3j^yr--)xUD~-mBKauzDaa3&sToSRfsH?T! zG!GFpzv_DR6X^Dn;zydG_@1x?T22Uhi}(aDW1m{>I|M(6z#{)!9>p^AQCyfjtvDa` z!8iIXTbkQ5qC@r@bBfV9>F~ReH%gDf3uAE+aH_6mY|8 z2>p%m1!eMV?1}oSNt&q_NHK{oQM%~+0PH5rERliJdt32jewCN${=YE#l;OOEi2fa0|;H05%BAStieI;&GKUd<-6mptHgsG|+|^00dGCu}x7G8YCm zAw<+I`hL~>^U=vVh@&Oe(zSzP zp$M1Fep*y13~z_N@!+DSI?un@5E~wxF $`A&K%U5eAp+p0|bwzq@d)c_b|J6Y2v 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 delta 90510 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
    Bh*qpn6MGbWf8I4@$49y9&_ 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 y&+vc$<>SxCpN~Hue?I Date: Tue, 3 May 2016 15:09:28 +0200 Subject: [PATCH 106/730] typo --- app/views/import/gitlab_projects/new.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/import/gitlab_projects/new.html.haml b/app/views/import/gitlab_projects/new.html.haml index d01f0190f3..e8e1c02d44 100644 --- a/app/views/import/gitlab_projects/new.html.haml +++ b/app/views/import/gitlab_projects/new.html.haml @@ -1,8 +1,8 @@ -- page_title "FogBugz Import" +- page_title "GitLab Import" - header_title "Projects", root_path %h3.page-title %i.fa.fa-bug - Import projects from Gitlab + Import projects from GitLab %hr = form_tag import_gitlab_project_path, class: 'form-horizontal', multipart: true do From bd2ebf37e6c5aa07f8d29f4ac8c88fc8333a2297 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 4 May 2016 10:57:09 +0200 Subject: [PATCH 107/730] use worker in controller --- app/controllers/projects_controller.rb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 62f8b376c1..f15f20dcf5 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -191,8 +191,7 @@ class ProjectsController < Projects::ApplicationController end def export - #TODO: Move to worker - ::Projects::ImportExport::ExportService.new(@project, current_user).execute + @project.add_export_job(current_user_id: current_user.id) redirect_to( edit_project_path(@project), @@ -201,7 +200,11 @@ class ProjectsController < Projects::ApplicationController end def download_export - send_file export_project_path, disposition: 'attachment' + if export_project_path + send_file export_project_path, disposition: 'attachment' + else + render_404 + end end def toggle_star From bc8eebf04a32d893d5b536deb2e7ffc205d9fcda Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 4 May 2016 10:59:33 +0200 Subject: [PATCH 108/730] add export worker to process project export async --- app/models/project.rb | 10 ++++++++++ app/workers/project_export_worker.rb | 13 +++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 app/workers/project_export_worker.rb diff --git a/app/models/project.rb b/app/models/project.rb index af62e8ecd9..8781a3cf7a 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1034,4 +1034,14 @@ class Project < ActiveRecord::Base def wiki @wiki ||= ProjectWiki.new(self, self.owner) end + + def add_export_job(current_user_id:) + job_id = ProjectExportWorker.perform_async(current_user_id, self.id) + + if job_id + Rails.logger.info "Export job started for project ID #{self.id} with job ID #{job_id}" + else + Rails.logger.error "Export job failed to start for project ID #{self.id}" + end + end end diff --git a/app/workers/project_export_worker.rb b/app/workers/project_export_worker.rb new file mode 100644 index 0000000000..a1add5395b --- /dev/null +++ b/app/workers/project_export_worker.rb @@ -0,0 +1,13 @@ +class ProjectExportWorker + include Sidekiq::Worker + + # TODO: enabled retry - disabled for QA purposes + sidekiq_options queue: :gitlab_shell, retry: false + + def perform(current_user_id, project_id) + current_user = User.find(current_user_id) + project = Project.find(project_id) + ::Projects::ImportExport::ExportService.new(project, current_user).execute + # TODO : Handle errors + end +end From 9b21207305f7516b132211b5ead584beb37b8948 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 4 May 2016 11:01:55 +0200 Subject: [PATCH 109/730] updated import worker --- app/workers/project_import_worker.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/workers/project_import_worker.rb b/app/workers/project_import_worker.rb index 0e8b955244..aaa59f79d7 100644 --- a/app/workers/project_import_worker.rb +++ b/app/workers/project_import_worker.rb @@ -1,7 +1,7 @@ class ProjectImportWorker include Sidekiq::Worker - include Gitlab::ShellAdapter + # TODO: enabled retry - disabled for QA purposes sidekiq_options queue: :gitlab_shell, retry: false def perform(current_user_id, tmp_file, namespace_id, path) From e5ee7e8692b8c9530cef61f3b4ce14f8bf278452 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 4 May 2016 11:10:25 +0200 Subject: [PATCH 110/730] typos in export page --- app/views/import/gitlab_projects/new.html.haml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/import/gitlab_projects/new.html.haml b/app/views/import/gitlab_projects/new.html.haml index e8e1c02d44..d93ae42c1b 100644 --- a/app/views/import/gitlab_projects/new.html.haml +++ b/app/views/import/gitlab_projects/new.html.haml @@ -1,18 +1,18 @@ - page_title "GitLab Import" - header_title "Projects", root_path %h3.page-title - %i.fa.fa-bug + %i.fa.fa-gitlab Import projects from GitLab %hr = form_tag import_gitlab_project_path, class: 'form-horizontal', multipart: true do %p - To get started you add your project export file below. + To get started add your exported project file below: .form-group = hidden_field_tag :namespace_id, @namespace_id = hidden_field_tag :path, @path = label_tag :file, class: 'control-label' do - %span GitLab export file + %span GitLab project export .col-sm-10 = file_field_tag :file, class: '' From 14dd2d4ad0be905385ec524a3022b9b81cb4671b Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 4 May 2016 15:05:28 +0200 Subject: [PATCH 111/730] fixed import file spec --- spec/features/projects/import_export/import_file_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb index 05f6e28984..b9173e4455 100644 --- a/spec/features/projects/import_export/import_file_spec.rb +++ b/spec/features/projects/import_export/import_file_spec.rb @@ -25,7 +25,7 @@ feature 'project import', feature: true, js: true do fill_in :project_path, with:'test-project-path', visible: true click_link 'GitLab project' - expect(page).to have_content('GitLab export file') + expect(page).to have_content('GitLab project export') expect(URI.parse(current_url).query).to eq('namespace_id=2&path=test-project-path') attach_file('file', file) From 773c39cca3cc6c4f9edd9387e99d3a85924ac5af Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 4 May 2016 15:13:44 +0200 Subject: [PATCH 112/730] fixed import export reader spec --- .../import_export/import_export_reader.rb | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/gitlab/import_export/import_export_reader.rb b/lib/gitlab/import_export/import_export_reader.rb index 4e46899ec7..14049cb1bd 100644 --- a/lib/gitlab/import_export/import_export_reader.rb +++ b/lib/gitlab/import_export/import_export_reader.rb @@ -41,7 +41,7 @@ module Gitlab current_key = hash.keys.first value = process_current_class(hash, included_classes_hash, value) if included_classes_hash[current_key] - add_class(current_key, included_classes_hash, value) + add_to_class(current_key, included_classes_hash, value) else add_new_class(current_key, included_classes_hash, value) end @@ -58,13 +58,18 @@ module Gitlab def add_new_class(current_key, included_classes_hash, value) only_except_hash = check_only_and_except(value) - # TODO: refactor this - value = (value.is_a?(Hash) ? value.merge(only_except_hash) : { value => only_except_hash }) if only_except_hash - new_hash = { include: value } - included_classes_hash[current_key] = new_hash + parsed_hash = { include: value } + unless only_except_hash.empty? + if value.is_a?(Hash) + parsed_hash = { include: value.merge(only_except_hash) } + else + parsed_hash = { include: { value => only_except_hash } } + end + end + included_classes_hash[current_key] = parsed_hash end - def add_class(current_key, included_classes_hash, value) + def add_to_class(current_key, included_classes_hash, value) only_except_hash = check_only_and_except(value) value = { value => only_except_hash } unless only_except_hash.empty? old_values = included_classes_hash[current_key][:include] From a4d242b887f214493e73e2d44110974a417f3418 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 4 May 2016 17:42:02 +0200 Subject: [PATCH 113/730] refactored some namespace stuff and fixed project tree restorer spec. also removing controller so that it belongs to the UI MR --- .../import/gitlab_project_controller.rb | 45 ------------------- lib/gitlab/import_export/import_service.rb | 6 +-- .../gitlab}/import_export/project.json | 0 lib/gitlab/import_export/project_factory.rb | 9 ++-- .../import_export/project_tree_restorer.rb | 10 ++--- lib/gitlab/import_export/repo_restorer.rb | 2 +- .../project_tree_restorer_spec.rb | 3 +- spec/spec_helper.rb | 4 ++ 8 files changed, 20 insertions(+), 59 deletions(-) delete mode 100644 app/controllers/import/gitlab_project_controller.rb rename {fixtures => lib/gitlab}/import_export/project.json (100%) diff --git a/app/controllers/import/gitlab_project_controller.rb b/app/controllers/import/gitlab_project_controller.rb deleted file mode 100644 index ab0da196ac..0000000000 --- a/app/controllers/import/gitlab_project_controller.rb +++ /dev/null @@ -1,45 +0,0 @@ -class Import::GitlabProjectController < Import::BaseController - before_action :verify_gitlab_project_import_enabled - before_action :gitlab_project_auth, except: :callback - - rescue_from OAuth::Error, with: :gitlab_project_unauthorized - - #TODO permissions stuff - - def callback - - redirect_to status_import_gitlab_project_url - end - - def status - @repos = client.projects - @incompatible_repos = client.incompatible_projects - - @already_added_projects = current_user.created_projects.where(import_type: "gitlab_project") - already_added_projects_names = @already_added_projects.pluck(:import_source) - - @repos.to_a.reject!{ |repo| already_added_projects_names.include? "#{repo["owner"]}/#{repo["slug"]}" } - end - - def jobs - jobs = current_user.created_projects.where(import_type: "gitlab_project").to_json(only: [:id, :import_status]) - render json: jobs - end - - def create - @file = params[:file] - - repo_owner = current_user.username - @target_namespace = params[:new_namespace].presence || repo_owner - - # namespace = get_or_create_namespace || (render and return) - - @project = Gitlab::ImportExport::ImportService.execute(archive_file: file, owner: repo_owner) - end - - private - - def verify_gitlab_project_import_enabled - render_404 unless gitlab_project_import_enabled? - end -end diff --git a/lib/gitlab/import_export/import_service.rb b/lib/gitlab/import_export/import_service.rb index 227053481c..97ee8a7fc9 100644 --- a/lib/gitlab/import_export/import_service.rb +++ b/lib/gitlab/import_export/import_service.rb @@ -9,7 +9,7 @@ module Gitlab def initialize(archive_file:, owner:, namespace_id:, project_path:) @archive_file = archive_file @current_user = owner - @namespace_path = Namespace.find(namespace_id).path + @namespace = Namespace.find(namespace_id) @project_path = project_path end @@ -25,7 +25,7 @@ module Gitlab end def project_tree - @project_tree ||= Gitlab::ImportExport::ProjectTreeRestorer.new(path: storage_path, user: @current_user, project_path: @project_path) + @project_tree ||= Gitlab::ImportExport::ProjectTreeRestorer.new(path: storage_path, user: @current_user, project_path: @project_path, namespace_id: @namespace.id) end def restore_repo @@ -37,7 +37,7 @@ module Gitlab end def path_with_namespace - File.join(@namespace_path, @project_path) + File.join(@namespace.path, @project_path) end end end diff --git a/fixtures/import_export/project.json b/lib/gitlab/import_export/project.json similarity index 100% rename from fixtures/import_export/project.json rename to lib/gitlab/import_export/project.json diff --git a/lib/gitlab/import_export/project_factory.rb b/lib/gitlab/import_export/project_factory.rb index c7137844a0..6cd4736649 100644 --- a/lib/gitlab/import_export/project_factory.rb +++ b/lib/gitlab/import_export/project_factory.rb @@ -3,17 +3,19 @@ module Gitlab module ProjectFactory extend self - def create(project_params:, user:) + def create(project_params:, user:, namespace_id:) project = Project.new(project_params.except('id')) project.creator = user - check_namespace(project_params['namespace_id'], project, user) + check_namespace(namespace_id, project, user) end def check_namespace(namespace_id, project, user) if namespace_id # Find matching namespace and check if it allowed # for current user if namespace_id passed. - unless allowed_namespace?(user, namespace_id) + if allowed_namespace?(user, namespace_id) + project.namespace_id = namespace_id + else project.namespace_id = nil deny_namespace(project) end @@ -34,7 +36,6 @@ module Gitlab def deny_namespace(project) project.errors.add(:namespace, "is not valid") end - end end end diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index 0f2e371677..0bc23dfaa2 100644 --- a/lib/gitlab/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -2,10 +2,11 @@ module Gitlab module ImportExport class ProjectTreeRestorer - def initialize(path:, user:, project_path:) + def initialize(path:, user:, project_path:, namespace_id:) @path = File.join(path, 'project.json') @user = user @project_path = project_path + @namespace_id = namespace_id end def restore @@ -30,9 +31,8 @@ module Gitlab saved = [] relation_list.each do |relation| next if !relation.is_a?(Hash) && tree_hash[relation.to_s].blank? - if relation.is_a?(Hash) - create_sub_relations(relation, tree_hash) - end + create_sub_relations(relation, tree_hash) if relation.is_a?(Hash) + relation_key = relation.is_a?(Hash) ? relation.keys.first : relation relation_hash = create_relation(relation_key, tree_hash[relation_key.to_s]) saved << project.update_attribute(relation_key, relation_hash) @@ -47,7 +47,7 @@ module Gitlab def create_project project_params = @tree_hash.reject { |_key, value| value.is_a?(Array) } project = Gitlab::ImportExport::ProjectFactory.create( - project_params: project_params, user: @user) + project_params: project_params, user: @user, namespace_id: @namespace_id) project.path = @project_path project.name = @project_path project.save diff --git a/lib/gitlab/import_export/repo_restorer.rb b/lib/gitlab/import_export/repo_restorer.rb index 315ad88ee0..b34581deeb 100644 --- a/lib/gitlab/import_export/repo_restorer.rb +++ b/lib/gitlab/import_export/repo_restorer.rb @@ -3,7 +3,7 @@ module Gitlab class RepoRestorer include Gitlab::ImportExport::CommandLineUtil - def initialize(project: , path: ) + def initialize(project:, path:) @project = project # TODO remove magic keyword and move it to a shared config @path = File.join(path, 'project.bundle') 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 f3d3a57ddd..aa8a12c4ca 100644 --- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb @@ -4,7 +4,8 @@ describe Gitlab::ImportExport::ProjectTreeRestorer, services: true do describe :restore do let(:user) { create(:user) } - let(:project_tree_restorer) { Gitlab::ImportExport::ProjectTreeRestorer.new(path: "fixtures/import_export/project.json", user: user) } + let(:namespace) { create(:namespace, owner: user) } + let(:project_tree_restorer) { Gitlab::ImportExport::ProjectTreeRestorer.new(path: "lib/gitlab/import_export/", user: user, project_path: 'project', namespace_id: namespace.id) } context 'JSON' do let(:restored_project_json) do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 596d607f2a..b48e54b78f 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -58,3 +58,7 @@ RSpec::Rails::ViewRendering::EmptyTemplatePathSetDecorator.class_eval do end ActiveRecord::Migration.maintain_test_schema! + +Capybara.register_driver :poltergeist do |app| + Capybara::Poltergeist::Driver.new(app, timeout: 1.minute) +end \ No newline at end of file From 48fcf54040bf049d7f7d959b1033ad28b3966770 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 4 May 2016 18:01:41 +0200 Subject: [PATCH 114/730] add gitlab project controller - still WIP --- .../import/gitlab_project_controller.rb | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 app/controllers/import/gitlab_project_controller.rb diff --git a/app/controllers/import/gitlab_project_controller.rb b/app/controllers/import/gitlab_project_controller.rb new file mode 100644 index 0000000000..ab0da196ac --- /dev/null +++ b/app/controllers/import/gitlab_project_controller.rb @@ -0,0 +1,45 @@ +class Import::GitlabProjectController < Import::BaseController + before_action :verify_gitlab_project_import_enabled + before_action :gitlab_project_auth, except: :callback + + rescue_from OAuth::Error, with: :gitlab_project_unauthorized + + #TODO permissions stuff + + def callback + + redirect_to status_import_gitlab_project_url + end + + def status + @repos = client.projects + @incompatible_repos = client.incompatible_projects + + @already_added_projects = current_user.created_projects.where(import_type: "gitlab_project") + already_added_projects_names = @already_added_projects.pluck(:import_source) + + @repos.to_a.reject!{ |repo| already_added_projects_names.include? "#{repo["owner"]}/#{repo["slug"]}" } + end + + def jobs + jobs = current_user.created_projects.where(import_type: "gitlab_project").to_json(only: [:id, :import_status]) + render json: jobs + end + + def create + @file = params[:file] + + repo_owner = current_user.username + @target_namespace = params[:new_namespace].presence || repo_owner + + # namespace = get_or_create_namespace || (render and return) + + @project = Gitlab::ImportExport::ImportService.execute(archive_file: file, owner: repo_owner) + end + + private + + def verify_gitlab_project_import_enabled + render_404 unless gitlab_project_import_enabled? + end +end From c1858da9e154d4ac0b18dc93ec13464700c1f11b Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 5 May 2016 09:35:27 +0200 Subject: [PATCH 115/730] remove spec helper conf --- spec/spec_helper.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index b48e54b78f..596d607f2a 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -58,7 +58,3 @@ RSpec::Rails::ViewRendering::EmptyTemplatePathSetDecorator.class_eval do end ActiveRecord::Migration.maintain_test_schema! - -Capybara.register_driver :poltergeist do |app| - Capybara::Poltergeist::Driver.new(app, timeout: 1.minute) -end \ No newline at end of file From a9ac9ed105a710194099a4e07a2e87712d59a59a Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 5 May 2016 10:05:42 +0200 Subject: [PATCH 116/730] fix import feature --- features/steps/dashboard/new_project.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/features/steps/dashboard/new_project.rb b/features/steps/dashboard/new_project.rb index a0aad66184..ad20201c2c 100644 --- a/features/steps/dashboard/new_project.rb +++ b/features/steps/dashboard/new_project.rb @@ -19,7 +19,8 @@ class Spinach::Features::NewProject < Spinach::FeatureSteps expect(page).to have_link('GitLab.com') expect(page).to have_link('Gitorious.org') expect(page).to have_link('Google Code') - expect(page).to have_link('Any repo by URL') + expect(page).to have_link('Repo by URL') + expect(page).to have_link('GitLab project') end step 'I click on "Import project from GitHub"' do @@ -36,7 +37,7 @@ class Spinach::Features::NewProject < Spinach::FeatureSteps end end - step 'I click on "Any repo by URL"' do + step 'I click on "Repo by URL"' do first('.import_git').click end From e14d1051d2c04bad514d840e1eff35ce24b05922 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 5 May 2016 11:02:22 +0200 Subject: [PATCH 117/730] fix import feature v2 --- features/dashboard/new_project.feature | 2 +- lib/gitlab/import_sources.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/features/dashboard/new_project.feature b/features/dashboard/new_project.feature index 7639206835..56b4a639c0 100644 --- a/features/dashboard/new_project.feature +++ b/features/dashboard/new_project.feature @@ -14,7 +14,7 @@ Background: @javascript Scenario: I should see instructions on how to import from Git URL Given I see "New Project" page - When I click on "Any repo by URL" + When I click on "Repo by URL" Then I see instructions on how to import from Git URL @javascript diff --git a/lib/gitlab/import_sources.rb b/lib/gitlab/import_sources.rb index 2b5658a8b6..4cae819d35 100644 --- a/lib/gitlab/import_sources.rb +++ b/lib/gitlab/import_sources.rb @@ -20,7 +20,7 @@ module Gitlab 'Gitorious.org' => 'gitorious', 'Google Code' => 'google_code', 'FogBugz' => 'fogbugz', - 'Any repo by URL' => 'git', + 'Repo by URL' => 'git', 'GitLab project' => 'gitlab_project' } end From 6612ca096a496caaa0d30724190964df8aac2f46 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 5 May 2016 12:01:18 +0200 Subject: [PATCH 118/730] update repo and wiki repo bundler to use git bundle instead of compressing via tar --- app/services/projects/import_export/export_service.rb | 6 ++++++ lib/gitlab/import_export/repo_bundler.rb | 3 +-- lib/gitlab/import_export/wiki_repo_bundler.rb | 3 +-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/services/projects/import_export/export_service.rb b/app/services/projects/import_export/export_service.rb index 5d5573cba5..47ceff18af 100644 --- a/app/services/projects/import_export/export_service.rb +++ b/app/services/projects/import_export/export_service.rb @@ -4,8 +4,10 @@ module Projects def execute(options = {}) @shared = Gitlab::ImportExport::Shared.new(relative_path: File.join(project.path_with_namespace, 'work')) + # TODO handle errors save_project_tree bundle_repo + bundle_wiki_repo save_all end @@ -19,6 +21,10 @@ module Projects Gitlab::ImportExport::RepoBundler.new(project: project, shared: @shared).bundle end + def bundle_wiki_repo + Gitlab::ImportExport::WikiRepoBundler.new(project: project, shared: @shared).bundle + end + def save_all Gitlab::ImportExport::Saver.save(storage_path: @shared.export_path) end diff --git a/lib/gitlab/import_export/repo_bundler.rb b/lib/gitlab/import_export/repo_bundler.rb index e719ee2e9e..cd871687d7 100644 --- a/lib/gitlab/import_export/repo_bundler.rb +++ b/lib/gitlab/import_export/repo_bundler.rb @@ -20,9 +20,8 @@ module Gitlab def bundle_to_disk FileUtils.mkdir_p(@export_path) - tar_cf(archive: full_path, dir: path_to_repo) + git_bundle(repo_path: path_to_repo, bundle_path: @full_path) rescue - #TODO: handle error false end diff --git a/lib/gitlab/import_export/wiki_repo_bundler.rb b/lib/gitlab/import_export/wiki_repo_bundler.rb index 7821c67162..17f1530d5a 100644 --- a/lib/gitlab/import_export/wiki_repo_bundler.rb +++ b/lib/gitlab/import_export/wiki_repo_bundler.rb @@ -3,7 +3,7 @@ module Gitlab class WikiRepoBundler < RepoBundler def bundle @wiki = ProjectWiki.new(@project) - return false if !wiki? + return true if !wiki? # it's okay to have no Wiki @full_path = File.join(@export_path, project_filename) bundle_to_disk end @@ -12,7 +12,6 @@ module Gitlab FileUtils.mkdir_p(@export_path) git_bundle(repo_path: path_to_repo, bundle_path: @full_path) rescue - #TODO: handle error false end From 92f4bde427652a33ccb42e93de1cc781289a6c8a Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 5 May 2016 12:39:18 +0200 Subject: [PATCH 119/730] use git bundle in import and add wiki repo to import --- lib/gitlab/import_export/command_line_util.rb | 6 ++++++ lib/gitlab/import_export/import_service.rb | 16 ++++++++++++++-- lib/gitlab/import_export/repo_restorer.rb | 11 +++++------ 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/lib/gitlab/import_export/command_line_util.rb b/lib/gitlab/import_export/command_line_util.rb index 5ff72f5ff8..f32e271599 100644 --- a/lib/gitlab/import_export/command_line_util.rb +++ b/lib/gitlab/import_export/command_line_util.rb @@ -23,6 +23,12 @@ module Gitlab status.zero? end + def git_unbundle(git_bin_path: Gitlab.config.git.bin_path, repo_path:, bundle_path:) + cmd = %W(#{git_bin_path} clone --bare #{bundle_path} #{repo_path}) + _output, status = Gitlab::Popen.popen(cmd) + status.zero? + end + def tar_with_options(archive:, dir:, options:) cmd = %W(tar -#{options} #{archive} -C #{dir} .) _output, status = Gitlab::Popen.popen(cmd) diff --git a/lib/gitlab/import_export/import_service.rb b/lib/gitlab/import_export/import_service.rb index 97ee8a7fc9..6878f4bbc8 100644 --- a/lib/gitlab/import_export/import_service.rb +++ b/lib/gitlab/import_export/import_service.rb @@ -15,7 +15,7 @@ module Gitlab def execute Gitlab::ImportExport::Importer.import(archive_file: @archive_file, storage_path: storage_path) - project_tree.project if [restore_project_tree, restore_repo].all? + project_tree.project if [restore_project_tree, restore_repo, restore_wiki_repo].all? end private @@ -29,7 +29,11 @@ module Gitlab end def restore_repo - Gitlab::ImportExport::RepoRestorer.new(path: storage_path, project: project_tree.project).restore + Gitlab::ImportExport::RepoRestorer.new(path: repo_path, project: project_tree.project).restore + end + + def restore_wiki_repo + Gitlab::ImportExport::RepoRestorer.new(path: wiki_repo_path, project: project_tree.project).restore end def storage_path @@ -39,6 +43,14 @@ module Gitlab def path_with_namespace File.join(@namespace.path, @project_path) end + + def repo_path + File.join('storage_path', 'project.bundle') + end + + def wiki_repo_path + File.join('storage_path', 'project.wiki.bundle') + end end end end diff --git a/lib/gitlab/import_export/repo_restorer.rb b/lib/gitlab/import_export/repo_restorer.rb index b34581deeb..dc45238bf2 100644 --- a/lib/gitlab/import_export/repo_restorer.rb +++ b/lib/gitlab/import_export/repo_restorer.rb @@ -3,19 +3,18 @@ module Gitlab class RepoRestorer include Gitlab::ImportExport::CommandLineUtil - def initialize(project:, path:) + def initialize(project:, path_to_bundle: ) @project = project - # TODO remove magic keyword and move it to a shared config - @path = File.join(path, 'project.bundle') + @path_to_bundle = path_to_bundle end def restore - return false unless File.exists?(@path) - # Move repos dir to 'repositories.old' dir + return true unless File.exists?(@path) FileUtils.mkdir_p(repos_path) FileUtils.mkdir_p(path_to_repo) - untar_xf(archive: @path, dir: path_to_repo) + + git_unbundle(git_bin_path: Gitlab.config.git.bin_path, repo_path: path_to_repo, bundle_path: @path_to_bundle) end private From 7204018a36e79a4b26b954965387495f50115541 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 5 May 2016 12:54:12 +0200 Subject: [PATCH 120/730] fix path to bundle --- lib/gitlab/import_export/import_service.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/import_export/import_service.rb b/lib/gitlab/import_export/import_service.rb index 6878f4bbc8..a4555699ff 100644 --- a/lib/gitlab/import_export/import_service.rb +++ b/lib/gitlab/import_export/import_service.rb @@ -29,11 +29,11 @@ module Gitlab end def restore_repo - Gitlab::ImportExport::RepoRestorer.new(path: repo_path, project: project_tree.project).restore + Gitlab::ImportExport::RepoRestorer.new(path_to_bundle: repo_path, project: project_tree.project).restore end def restore_wiki_repo - Gitlab::ImportExport::RepoRestorer.new(path: wiki_repo_path, project: project_tree.project).restore + Gitlab::ImportExport::RepoRestorer.new(path_to_bundle: wiki_repo_path, project: project_tree.project).restore end def storage_path From 4b1fdfd6eb013f3549dc9198ffab46f7ef0de87c Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 5 May 2016 13:14:43 +0200 Subject: [PATCH 121/730] updated export file for testing --- .../import_export/test_project_export.tar.gz | Bin 352529 -> 338759 bytes 1 file changed, 0 insertions(+), 0 deletions(-) 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 0c20898086d8766d77ac9ce2216d194532abd72c..87f118b6e230a19317e7070bf04c7ad072f0eb9c 100644 GIT binary patch delta 109939 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 AbuIX2t%UiZ0RVNgMg(3Ls8gb6^stm z5Jl`^O5z zGOlwG<{D@X1A!Kd38-h{h^@g)0|gNkYoNd-9yEawE7n!`QI!qQxu~EObS4A^0SiLW zVC`}eT2dO!e^sU3fW@rl>(25iX|bX2$G_sBG6F(0j4xqQPh{)1X+Qe3W_SyiEpSN3W=y&&|(U& zvZah9z-k071^bE7ODQWh0n=&WdWKS+XbcJVB!R>)e}k<>A-Wm%DUAn3!WKiRCJ4L) zdZ?-#^@pLN^wpFKk~2VYaHC*r1J$WYywQ%ZL_pvRnc$6mKOf@7>GHf~Ma6`e(L2rjyCF+KtiV9l_;|b4_c>{G!RBTAFBg>K@>zpP5 z+7~rZf7V&4)*S&>mq>ie=n_dBAYG#1b!3?KvWB_@BxcBl(yP6jRF}Y3t4g>gV2Z-l z!mARF9V~1?2W((4rLeC{vVa>Y6vBw=JbaIXsR=*AT!iTfiweDKbe#IIMXIVnv<~J4 z5Df{Y;V77nxJF@vBW9T{;N;`*b-acs^6$4GW1W9EGPKBEl_|DaEA) zI}vhU&@@4w?X#+;phyC(#FmcI z5ndr)h*dTa;=rB?OAmHO^w8B{#v>?$9Tp#a68XeXdF4TB2`~*WQw2J~>rxHX|BsxMf zQPFS?82D@u4Xj^KtRjr7Krp!u9Rw82sai?_t*u3;lfHVkzOxT-r zBQOAotu1>_C88fu~FxhjSigq;rdaA>dwe>;x^ zswssA0>W?(A0|mK_cgY36yO;dtO!Fl*kT#8!o&K;Z47oi5H$cLw0U_RUoFFq3~)+S z3}m{PVn76%Ap(?Ah=~Bp66`#Mz%^_Uui*wML-S=?DiG)*b21Dkt~zW*R60roD?&x% zlr4o(0&EC~0RSJ!QW0QJ7unL7f7qg8R>n+|dnt~MUi6Tv;=0qNZgI?@APaisUc$`2 zD#Lau;9`S`jx;Tp-C#GVpm_~2atS1?TMQcnOizG7_XKkh;Y&5y~qZN7a>x z2vY{Mz9Gx;uJ=+5PynU|z>T;>dMRcfQnxrR5phLJBvAA6K=FJ4YE;;Gf5~wJVs~C$ zUKKBkXk{5h-QkIu09XJpjLZWH6%}3qBqgJnDH3QSf%T=Jts{U^;W5Cdp@3$SkUkTk zjt<2d+CW$=VSpmAhP0|u0qIFzi#=jIK;D!jffb|1UMRrY;K91k;_UznM3!^|VI|uR z05*oMX}Tb?Z$u^v)(hyXe^@DC5l~>NtjF5{{pJ-z26P*12eaixVj9&UAZ?|?Tm=QG zN`PGe^nfXemYqUtgJ=NQgSO{1fNr8H7|6oFlvQ|1My?PbYD&cUiBW$&hDes(S+Gqf2s6txTXe*$Poam z%1AaV0G(0*k-_>{-c_aZMD7MTn~wbgn3m9%n8@xZ3{{ z*k;LT;7}5;X^0KbDMOS*ez~VO(%}eM2`Z2YaU@6tEYvH8&05wG&m%j6N?Yf_EF9GV zm<=5uR8Pr%!1>$;Q=mOdPe+@|@baQ)yZye^3fIT{vtBuiwrRMt|eBB{h5 zA$kP$ljEy*e;19V5La#lr41M|Xxi>lHME)mIt>u7UbFG@XmcrXoKSy!T4(py2X6Pr zBSJipXx_fY;H}sOR=*fqpySb`9^2PM42%Kw^w_S3m2vf9DJ}dP4VcidE z3jG4SEa4YTpUzDzV2Bco!N{3qjL430g~A)CH8I&^7fIUcL}ah7u##Pb$!5s^Gim6u zl#ilDJJ#+-k|H8BS7VXYja+YDJp80Avl?grkJuJnv!GlcE(C8 zvTSP^P;{c2wq#zAEnQLY6x|XGF=GpktlP3}ix#L)cp8Rk=LF0$2)ifV6RS50wY{h} z6m@H@WaANC_piN>MJ_{g^(7E}uU^k%pRPPTe=Za{(`JdJx}W7Z#hRW~eO}eG+E2gZ zTn9pftdTVIsL?3L3$3T~di`7n{kT%h<~mSoa~%kxD96La;{>BQ48w$4QJm;zCpnN1 zdnE{=8`T@A5V}HBvpIoSqiE36qKt)3l$evmjn5bGJ~B;4#-%}0ro&`3>vydFhQYT{ ze~t;`-iia8RHEtfjsilDF-fd`Cb~I_oegkH)1Z>jw0=O{W+z1e0ZKwLLHqSuM$lUA z#EufeMTrnFdOwD7Fr6TVa5K{)pxl%MnX;mKEhAqh4;%?`&4?53$8K^81dJ-4 zB(H2#uT{h;@eG(SJ(nxkB;$RtV!L=d-XSTIGa1*y30x^NsUn-4`2b}n%gJO+>$QxG zqx?QJT{4Mz&!m=!V#61M>{TQhyjAIMcA6wY))G!+traG6lmVem?ntz~I)t{`fBXmZ z1HLUm0tD2xu?z@8lmTI?pBXsFQ;T^kz&I(>MT9uT!i-}TuUv?yYBs^}F1bPakcQ@m zEGHW>O;QFl^MP8O`C#t~&87tZ(d-VM=@e0Aq_{EAb1TRe7Nk%{aZqKQ;wFS>Bg|gF zY@Af(nAK?{{6r!Ds|gPJk=GI|e@26Zg*EhyB4kX(HUwT29MzK1ZOoJuQ{x3Q9;Pkh z&Vy}ou)x;|o0K?XLjABwDhXs{;AE8fF21j5gnPn29ycB)w|3GS$!w0pgc@*Q7^-1dqPfX|x;rfAw^=KIzeq z92^Z2Ji;CtrFNT05C~d`4v8!UDk4vfL{z;wH(&8+M)5FJA=r_yk_I5J8X-+SF`KAnz#I8%b|N_OTM7*NFlTF?YU_BX%U&>a+Gh(DR=?%F#rUI$|swve!Z3vX~fj+ zUg>rNxCd|-kfuvgzh<*E*&`}q%wk2b?ZEIFs+3IO`t@2y$Pr67hUC!&X<{}oP_2~Q z$Gp0M(gi@*PnD2F)v9Vj$*Qd-S-r~qM&N`gXShNx?*{2h{e;HNeFdqjx?-OvGnY(HRJG13qI~ zaL`3Tw1@OGlRBMnQY0B6F~l)BEtutHH*X=GMbm#L;xhy_8P8`JaveTHXd0iPRPz~Q zNY}{O9%D6dp;fBZ;NMj{-$ViC5kSTY^Yp~QaHO(Q2A5E#K;7#<>82$3@~ykdpHprtBzo#z|*n(UD}uP!&-%t+cKRLfXmRf6ik@0WJZR;rfYk%b@B| z8HI;2C7MB&0fm%v2F*MGJcp(w+-J3c-Djod!Wda#>rS>mhPxe?Z$Dw@eRl2Z-~~)nsl4e!Z3vb;Qq2^cl_!;XdfJ%@NiE2~p4tg@GYD zjD$+TXfdUrFy?r%V}Kn)nG<3Ra%083y+m>dowsC>+Y zLA_03388OC#gXTHl49eeeqZqH;&|4{RCe1q**x+v9<`NREl)*+V2jG-E;BbrV+Bk-0aq$QX_8JQOa+2I{M0|;@2 z^B^+jBou`e$b-~-umK=>a z^B7T!*>qL}BXA{wk72z5+k(X=qnqe(XQGoUP|rIe zO(!C~smC9Tg-<{=ofiSIX-SOBuwJW(SBXfzDZzmmh3KZuIzifiRb1R+3m)slK>eKj ze+7U}*-d9qgp|N1!z+HhmXUl!_lz7alDL`LK(l^YR~ zb0ZnU&`nF%Ov?~uIU^{JVF`-B8>X6(9aS_H8SGAD#ovXIyJV?LlvXG=Qv1g5xsg7( zk-oQpK*=QW5s@)T)xdKjipp>!e^f1m6bL;#qpk{ect#vrHGwl`e-GW0a3P|Rj0^GW z4cIm*G#QiBhEJfL3^`0N4+xvfqsVYm8vq7GN_0LM)@vD|>MYRn4;La&rtp~E_q-tj zrhbv(q#gj$LrUbA8rEwWVMlDcF-UN#Iz$o+sD&PrXJ^+2lnTF;HMS%lAamZpaio>thGE$BhypdU#5OuEQ zh8M&^We_tQc@Ebv$RmY~emc!(IbUq;BUihKN{ARF_zet}OmGSi1nZ--S=gP?s^3GY5awRL?XqI4b2gO zPck%OiZ|+U9?iQzBUW=B<0DH1H#(NvXD;fKjw4>C1V;?<`TU+gf3w4xPk|ueKb#ad z4l6`abHcM4>W1Yo&TRjS%m|;H8A;1xI<2dgW6DO_ww#P1OO7H6iY}+Y02MS_w{2Vc zE~13+QWtNm(AzV$Z~UGa>601h8)gQoC>b*%82rF9BWiRyGln|ChljUB=lB8Q{9{J+ z-yQ%S#7GoIGORaXfBPoiWVoWRn6N6K6)Jn`3Ey94DGACp62*lJ>$QwT86MBS%f$qX zbTHJFQ)c}^g5a~hJ7s9gyZOi;Y5-^vLrplL)z+HO5wSNRbf&?x7Gmt+4}l*7dv4A+ zb<=a+0U$^WBN_7c>$Qx)BhqgYIWP~S1rXH{x%AnQYmVvLfAA>leg)w$PNb~E zdMzXBi1M2jMPi69e^7@7c3wNa3tF=|5)hr7gd+*-wTg%}#)%Isw^%&idBv=2fvrM( z7a~uxP?I;CBf$*dNjQ?QUdsqMV*B>46wp4VR~cQ8+&7^2NkdOE{I}UW2pZ8zjqO&@ z#vu=4^g@H^f4$KlMj{%d`jU+l(I8Vua8R_)9Y4SkxnYtoq-o#_=GLkY)R7#?xp_Bd zCZI(m%m$Qbq$J)LP*)J4niipP!O69u;HnIzGU$c<;B>YU(-9bD#0p{nkn2ZC_yuQV zCLzD$v1Q4ZLR5$@Q$*s?SpyY(6tv}klp!&a6C{o(e;H|0w+t<<^J!7nWJNQ;_Ebg1 zF%4DJGqR;;GRk*AkVtwLudYynr1p*96C`~RBt{~glq8C(l+xuDaH~d(&UL6t!jOH1 zd_agq2%MZ;68Ig48~L^e?~N%FF(rt}P`F=jpte|}$>1eA;F&`1xBI6%k(hnoz$l~( zjr140e?{4JJ_W?6Bow#OQsR!tze(gW4PwG5HxIqN!A9!x`g`u4fGq)`=}7|Rg!NiQ zxU6S(!DDHVz*7Xx9=zLYGDkg4Cr8ATnCNCwSg%#&8*zct!i#p%i5PlJWB7*X49#~Q z_HR7)JLO3tazvDp8I^v$RuOf?`;80|rZFVze{A2*3`AREuAc@M+M7?3h)R;{GGV<| z5w%_`YLnXVEVCU15pO;%A|_PEVrwa5CiZG%B8GZ6yiw5K!h$ zf6ZK$8th(NzHyVfJ6p|Xgw#g{>^t9zHcRnuWn3^9dSXR(g+?a~ey5LNY!M{(8ony_ z;Ham@R9@{8byx@~mF_&{5@tzFEXKYvAjKX|Ot;z&mn!*ujI^){bDR?425ROmP9^-+ z%p*V0wjD>v5Y8`x#~)lsvy+^f*(7T$f31n}er>0iEzA$6Iw9)w;Yga_8lV3P*Kif*&+&)*2362WJNyR76wTC#>P)#vyp=TuPCy)Os=MPuyK zDaWK4Ee8>`v0Y(hdgp`8Cz|UucsF(G4%(LD_O7_~M;a3YvC-F{DH8*9L}wi$P%{c( z<%FTFe1ZERWWp0_CNg2@e?Jr#cDX9+a)NCr36cuyeaG97_&>M}wRP?b5A!++sogo+ z0h_u|L~z;(DhTFWhaDAl%yNU`P5^Nw$L7(z2yUf2JYmYMPfNi5E24 zX&z8cxU^`!l^Q6^%L!se+Vsf0V8`OA(yb{<Y)=gUw-S8f+Ck z&>)+lLl2ZObYtLgf1V4W7DnozJ632mvmCK$hxwvlf1nQh?v*%x-i9d z1m?1ScvUp;+>3S4j~BveQjs!CY z#2WBgO53e0WKk75XDZ-@y*i zOA;|6j%>jM#ROS2d{OyXKshFyP%xe*dx%aD9RU*I6b=sCv7Hq9npMFk$hi4IC<50K z#&s&XZw6xZk!%FfnM>FH3ZUSN%$e{`CCQFTqhL^fPL^V%zHijE1v?*1a@yDkfI>0`EBSd`U4K+2`9=iIK@j3bMjqjHmT0Y$ z0A+~(ruq()s33y8cC^b>I4pQ$MgaRo5ZT^10|SZBs4xDk2;3+lgN0yERvKuQB*9^N zBLB3o-g4qF?Ry-yLU5S8GUKp%jr%q@EFe0h-Z6q@f95Tx4xJVQ2?=49o+uA>SnoSt zDc=)k{U**LT(2j?^-9JNC0$i)+mU2R)fL$>EGKPPc3RT~MHO^gc68Zj8m>>`xDeJ` zsd0Vn5kvoQ{g?nf&?~^EpI9tRV3sfBLwbp#Vaj|kTX&eJGXQtt`6d@!NC~2xQ##A` zu}FdDf4UFh0J*w~JX*9JQ-~J1>e4U=05bi^RTgczALA{o=Ho`hDIqySdNP$^7AgG_ zK!6BGF-Zq0dYM4sB1H}kjW{0OpY{WP($MaqC@R$P(u8KXJ~|@AD9vuiMR`|fH^LC- z)QdG1#H{Rx^kU#G!CWlkNiCG%YH%n}H)gEGe+joB?-Pr4LY^uJQBN=IS14geiBZaz zkzt}1To}%t@X-zfPXoDmK7=NHV@N~a<{8P_3M9V-!~YV$vOMYgMAvh}AwstWLUh^` z6eHARuw&c`3ScjxWWxha+WeqBDQ+?|Q`jq10g{KtdCVX%;gWnmV>;S|$0k>c$z-Qw zeFBQLU4n%x2T1O169y*ByQ8^oL z%6h_0S#QRstbY$*R|tGnS7!KHuW`!*UzPrz1;=+nJkfFd!xm=c(bJ&l*lh|fE9y2+ zk0boB3q<2#Vrw%XxF{bK3tr%}3(;{1f8(4*PVUg$rAf~GuqeTvN_J4H{3>w+l_7`% zj)`bXa@ONVgQU(f<&X>_IXD8dnzoi&?DXew&k64d(A3zw8W9|X&;!-X`Jr^Ne^sb2 z>9vJeoO!~vm{r6>jQL>rJAXT%Y$Pgw|7 z_=^ZtGwIRz>hOewAM%rL`)p)556w#K;CW;S?yAH85=NVdorVbqTobJE3d=H*9!H73 z@eG|sis6e{);FM+W4Ox?DP;#hn}%c!C~*=8u-b3C@#dW<;#^qoJKntie-|z4f!H6F zm3i~7*SO_712mFx1-59*60d5irb(7*>bhl{8O>4@Lza0>N{bm=QB=Wf7FVDqas3SI zt<+pWEgRE6t{^z{3Qs|Z%A~{r37LdvYG}e)bf-#j6ofDvN1*fqSmV3w`kM)EYSBl2 zn2K;Cirq8!So4VN52GsCf1=6SZQ-d%l>L$Jfy_O}X=MMVMjAe|La<2eXfZU^eZ?Op z_>FS0vq|2`*%ToyXlzW9e}cAf4Bb?yu}*CG&=w7?;xHjgWVNDwSDO_LcM(6C+Qs3Po=|G^6;4 z$Yyu??Er5QMkTzYO7RfQGZ9P+`k)>PWyeHu%_(I@QuT<@Bt|Ws_c;_F%p6R6ciQ_n2(r*5;RN%d#5^TAMLus z+*T(Zag2ajm=jF|e54H9i#fiY3vga2E?nQIjv}D^fsa;HHRo|PL@(^LHk|>-BWzC})yG#aQ-`ovTQFzg|NC;bIdkq|aNr)xS z@pTE=aspjkt<}MjB*b&v*EcZDiBn9VZ^G9G8xLOX1c*SCV`$+8%D+Zcv)KfxDNKAM zMiQS-+R{M0e++jV)3by-W-}EAp0y6c2LucS#S}FjH9l8E$Z;Yma_}*sz;@6~GcF*( zwn+{5*p3(mw2FADkk%)bb0BpZk2>^U4?{)7Vo@-gPdG6HS0f6%2rlrqykJxUnfWe6 zF@P8P(D;t&6jga{G=%<0gaJ!K9&EC~ji`hY%2bFiY|9 zia0|>fQRmv!2wg%zK$*4E$Ryeh2*Fun49$B0Z|fq`Lp{yom&1FP*x-cwsF_Sal$3; zuij7%_%1LZK@^c0coae4`#5@V6?lV@r5`|Ak8*MVpabMbl>#$9p~hewgHTMtVALGa z1knNlf6kS09t^-VJDZTHb=kf-0n0~UGik+gWK+^LRdKAeVoMoKY8r=8o? zYFVmpb>WbvD`bzJsIvB*lLK3tn8~=eVzQmIe}Blp=5UQAvu3gMraFU!J>2h5I3R`?i;Wuu0n7i0b|d)a+tC6p7>Bw{8u3m#P_x!7lsI@Mj)6Q zV#bg_qeo6r)*C0sNQ^*dav5uk$-q5oZHJN3gYWstn}hJ^4*gol*hPLPxHA*jN$ysW zZxNz_PG|y9nW*h3)ClJI7DI@9!*C$Ef8b(Wcq9}t1rd6S;b|X2F%)3rq!flPBO~L3 zoPZWFE3v>COl4e#6MYUUOnVa}86$TV#|*tfZs#xWE_;60H-zE8HSbC*<)|7ZnuQ1uDT&HnXVx>k8C|F+4}0 znOA&%Ii%C+$$X#%Bcsx^!@I&0f62DQ_^Pm%RbzKc8FGTsB~_c89XA`pr}*@G>;`lE z#&?H3g~(Of7ol2+4hZ5d$dCrwI0md}dk)9m1dYqU>pb}8ZrEO$64=^AaAlMNJ~|Ci zEkde(*b*d25JGpIgRAm!g?bTnA`>?KhBzw~6l1XEu;8XSc&iv}BoH=6g>9 z&!Pp>=4Pf~+Q10H2LV%KBL>hZ=SF5m#^$C53#p#5|X2Qd+WQT3TX?sj-={sX?N#g{ip(Fp5mfQ<76m zO^waXEi5e)jgo*Rb6T-}MrvY8u|A|oAYQA7tD_4SSAe6lH_!o0K+HU!yJF7V)7E^4 z40sqW>|Oq$ujP}zqiECO9etU~6L)#t{e4(c;{Jy%#?1FJe_XW8j4xVG=)QP6$+zs@ znWO6coSlnKGtb-Q)gGQ%y1KpW%KT-%eX_TU|IOLsu`_QC{|3dK0+TqEV|t9!6f)PY z`cz;2LW%2&ne6X$)ep7u@bc++bkd-3Rt z1Ibh7T$#5&Tjin5&I8&E`{Q{WEi2||d+O>1YMeiFj)g%;f_bXKs&uQV=`k*in;EaU z@0zVq_3GWTfsWZxFbYP&C>RB!U=)mkQ7{Td!6+C7qhJ(_0tf&A;hN&o0N@4yJ-UTq delta 123803 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 Date: Thu, 5 May 2016 13:19:41 +0200 Subject: [PATCH 122/730] fix issue restoring repo --- lib/gitlab/import_export/repo_restorer.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/import_export/repo_restorer.rb b/lib/gitlab/import_export/repo_restorer.rb index dc45238bf2..9417393ecd 100644 --- a/lib/gitlab/import_export/repo_restorer.rb +++ b/lib/gitlab/import_export/repo_restorer.rb @@ -3,18 +3,20 @@ module Gitlab class RepoRestorer include Gitlab::ImportExport::CommandLineUtil - def initialize(project:, path_to_bundle: ) + def initialize(project:, path_to_bundle:) @project = project @path_to_bundle = path_to_bundle end def restore - return true unless File.exists?(@path) + return true unless File.exists?(@path_to_bundle) FileUtils.mkdir_p(repos_path) FileUtils.mkdir_p(path_to_repo) git_unbundle(git_bin_path: Gitlab.config.git.bin_path, repo_path: path_to_repo, bundle_path: @path_to_bundle) + rescue + false end private From f11920e21d35d8b34b9206a7ddf37422ca1914fa Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 5 May 2016 14:21:27 +0200 Subject: [PATCH 123/730] more fixes - restoring repo --- lib/gitlab/import_export/import_service.rb | 4 ++-- lib/gitlab/import_export/repo_restorer.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/gitlab/import_export/import_service.rb b/lib/gitlab/import_export/import_service.rb index a4555699ff..ae5a878d63 100644 --- a/lib/gitlab/import_export/import_service.rb +++ b/lib/gitlab/import_export/import_service.rb @@ -45,11 +45,11 @@ module Gitlab end def repo_path - File.join('storage_path', 'project.bundle') + File.join(storage_path, 'project.bundle') end def wiki_repo_path - File.join('storage_path', 'project.wiki.bundle') + File.join(storage_path, 'project.wiki.bundle') end end end diff --git a/lib/gitlab/import_export/repo_restorer.rb b/lib/gitlab/import_export/repo_restorer.rb index 9417393ecd..7a4cda828b 100644 --- a/lib/gitlab/import_export/repo_restorer.rb +++ b/lib/gitlab/import_export/repo_restorer.rb @@ -14,7 +14,7 @@ module Gitlab FileUtils.mkdir_p(repos_path) FileUtils.mkdir_p(path_to_repo) - git_unbundle(git_bin_path: Gitlab.config.git.bin_path, repo_path: path_to_repo, bundle_path: @path_to_bundle) + git_unbundle(repo_path: path_to_repo, bundle_path: @path_to_bundle) rescue false end From 9c60eca87fe30d34e29d26d667a9235912dcbe7e Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 5 May 2016 15:23:59 +0200 Subject: [PATCH 124/730] fix wiki import --- lib/gitlab/import_export/import_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gitlab/import_export/import_service.rb b/lib/gitlab/import_export/import_service.rb index ae5a878d63..31b77981ba 100644 --- a/lib/gitlab/import_export/import_service.rb +++ b/lib/gitlab/import_export/import_service.rb @@ -33,7 +33,7 @@ module Gitlab end def restore_wiki_repo - Gitlab::ImportExport::RepoRestorer.new(path_to_bundle: wiki_repo_path, project: project_tree.project).restore + Gitlab::ImportExport::RepoRestorer.new(path_to_bundle: wiki_repo_path, project: ProjectWiki.new(project_tree.project)).restore end def storage_path From 2a135866a24170e1db106885d4134e33141c07dd Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 5 May 2016 16:24:09 +0200 Subject: [PATCH 125/730] added more tests to integration spec --- .../projects/import_export/import_file_spec.rb | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb index b9173e4455..a7da7a21ea 100644 --- a/spec/features/projects/import_export/import_file_spec.rb +++ b/spec/features/projects/import_export/import_file_spec.rb @@ -7,6 +7,7 @@ feature 'project import', feature: true, js: true do let!(:namespace) { create(:namespace, name: "asd", owner: user) } let(:file) { File.join(Rails.root, 'spec', 'features', 'projects', 'import_export', 'test_project_export.tar.gz') } let(:export_path) { "#{Dir::tmpdir}/import_file_spec" } + let(:project) { Project.last } background do allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path) login_as(user) @@ -32,8 +33,15 @@ feature 'project import', feature: true, js: true do click_on 'Continue to the next step' # import starts - expect(Project.last).not_to be_nil - expect(Project.last.issues).not_to be_empty - expect(Project.last.repo_exists?).to be true + expect(project).not_to be_nil + expect(project.issues).not_to be_empty + expect(project.merge_requests).not_to be_empty + expect(project.repo_exists?).to be true + expect(wiki_exists?).to be true + end + + def wiki_exists? + wiki = ProjectWiki.new(project) + File.exists?(wiki.repository.path_to_repo) && !wiki.repository.empty? end end From 9f5dd2de4e85eba70cd469b36db1c19988c3603f Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 5 May 2016 18:12:24 +0200 Subject: [PATCH 126/730] handling errors a bit better on import failure --- app/workers/project_import_worker.rb | 18 +++++++++--------- lib/gitlab/import_export/import_service.rb | 14 ++++++++++---- .../import_export/project_tree_restorer.rb | 4 +++- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/app/workers/project_import_worker.rb b/app/workers/project_import_worker.rb index aaa59f79d7..cc75da704f 100644 --- a/app/workers/project_import_worker.rb +++ b/app/workers/project_import_worker.rb @@ -11,15 +11,15 @@ class ProjectImportWorker owner: current_user, namespace_id: namespace_id, project_path: path) + if project + project.repository.after_import + project.import_finish + else + logger.error("There was an error during the import: #{tmpfile}") + end + end - # TODO: Move this to import service - # if result[:status] == :error - # project.update(import_error: result[:message]) - # project.import_fail - # return - # end - - project.repository.after_import - project.import_finish + def logger + Sidekiq.logger end end diff --git a/lib/gitlab/import_export/import_service.rb b/lib/gitlab/import_export/import_service.rb index 31b77981ba..99fb9bad78 100644 --- a/lib/gitlab/import_export/import_service.rb +++ b/lib/gitlab/import_export/import_service.rb @@ -14,7 +14,8 @@ module Gitlab end def execute - Gitlab::ImportExport::Importer.import(archive_file: @archive_file, storage_path: storage_path) + Gitlab::ImportExport::Importer.import(archive_file: @archive_file, + storage_path: storage_path) project_tree.project if [restore_project_tree, restore_repo, restore_wiki_repo].all? end @@ -25,15 +26,20 @@ module Gitlab end def project_tree - @project_tree ||= Gitlab::ImportExport::ProjectTreeRestorer.new(path: storage_path, user: @current_user, project_path: @project_path, namespace_id: @namespace.id) + @project_tree ||= Gitlab::ImportExport::ProjectTreeRestorer.new(path: storage_path, + user: @current_user, + project_path: @project_path, + namespace_id: @namespace.id) end def restore_repo - Gitlab::ImportExport::RepoRestorer.new(path_to_bundle: repo_path, project: project_tree.project).restore + Gitlab::ImportExport::RepoRestorer.new(path_to_bundle: repo_path, + project: project_tree.project).restore end def restore_wiki_repo - Gitlab::ImportExport::RepoRestorer.new(path_to_bundle: wiki_repo_path, project: ProjectWiki.new(project_tree.project)).restore + Gitlab::ImportExport::RepoRestorer.new(path_to_bundle: wiki_repo_path, + project: ProjectWiki.new(project_tree.project)).restore end def storage_path diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index 0bc23dfaa2..7aa0ff46cd 100644 --- a/lib/gitlab/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -14,6 +14,8 @@ module Gitlab @tree_hash = ActiveSupport::JSON.decode(json) @project_members = @tree_hash.delete('project_members') create_relations + rescue + false end def project @@ -50,7 +52,7 @@ module Gitlab project_params: project_params, user: @user, namespace_id: @namespace_id) project.path = @project_path project.name = @project_path - project.save + project.save! project end From ce598b05414d52b31437dbe19412eb6a9a16f1b5 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 6 May 2016 13:40:02 +0200 Subject: [PATCH 127/730] fixed and refactored a few things based on MR feedback --- .../projects/import_export/export_service.rb | 5 +- lib/gitlab/import_export.rb | 2 +- lib/gitlab/import_export/command_line_util.rb | 29 ++++----- lib/gitlab/import_export/import_export.yml | 24 ++++---- .../import_export/import_export_reader.rb | 26 ++++---- .../import_export/project_tree_saver.rb | 12 ++-- .../import_export_reader_spec.rb | 4 +- .../import_export/project_tree_saver_spec.rb | 60 ++++++++++--------- .../gitlab/import_export/repo_bundler_spec.rb | 8 +-- .../import_export/wiki_repo_bundler_spec.rb | 8 +-- spec/support/import_export/import_export.yml | 16 ++--- 11 files changed, 93 insertions(+), 101 deletions(-) diff --git a/app/services/projects/import_export/export_service.rb b/app/services/projects/import_export/export_service.rb index 47ceff18af..fd569e1c9a 100644 --- a/app/services/projects/import_export/export_service.rb +++ b/app/services/projects/import_export/export_service.rb @@ -5,10 +5,7 @@ module Projects def execute(options = {}) @shared = Gitlab::ImportExport::Shared.new(relative_path: File.join(project.path_with_namespace, 'work')) # TODO handle errors - save_project_tree - bundle_repo - bundle_wiki_repo - save_all + save_all if [save_project_tree, bundle_repo, bundle_wiki_repo].all? end private diff --git a/lib/gitlab/import_export.rb b/lib/gitlab/import_export.rb index 539eae13f3..aa69f7c44a 100644 --- a/lib/gitlab/import_export.rb +++ b/lib/gitlab/import_export.rb @@ -6,7 +6,7 @@ module Gitlab File.join(storage_path, relative_path) end - def project_atts + def project_attributes %i(name path description issues_enabled wall_enabled merge_requests_enabled wiki_enabled snippets_enabled visibility_level archived) end diff --git a/lib/gitlab/import_export/command_line_util.rb b/lib/gitlab/import_export/command_line_util.rb index 5ff72f5ff8..4a1018072c 100644 --- a/lib/gitlab/import_export/command_line_util.rb +++ b/lib/gitlab/import_export/command_line_util.rb @@ -1,36 +1,31 @@ module Gitlab module ImportExport module CommandLineUtil - def tar_cf(archive:, dir:) - tar_with_options(archive: archive, dir: dir, options: 'cf') + def tar_czf(archive:, dir:) + tar_with_options(archive: archive, dir: dir, options: 'czf') end def untar_zxf(archive:, dir:) untar_with_options(archive: archive, dir: dir, options: 'zxf') end - def untar_xf(archive:, dir:) - untar_with_options(archive: archive, dir: dir, options: 'xf') - end - - def tar_czf(archive:, dir:) - tar_with_options(archive: archive, dir: dir, options: 'czf') - end - def git_bundle(git_bin_path: Gitlab.config.git.bin_path, repo_path:, bundle_path:) - cmd = %W(#{git_bin_path} --git-dir=#{repo_path} bundle create #{bundle_path} --all) - _output, status = Gitlab::Popen.popen(cmd) - status.zero? + execute(%W(#{git_bin_path} --git-dir=#{repo_path} bundle create #{bundle_path} --all)) + end + + def git_unbundle(git_bin_path: Gitlab.config.git.bin_path, repo_path:, bundle_path:) + execute(%W(#{git_bin_path} clone --bare #{bundle_path} #{repo_path})) end def tar_with_options(archive:, dir:, options:) - cmd = %W(tar -#{options} #{archive} -C #{dir} .) - _output, status = Gitlab::Popen.popen(cmd) - status.zero? + execute(%W(tar -#{options} #{archive} -C #{dir} .)) end def untar_with_options(archive:, dir:, options:) - cmd = %W(tar -#{options} #{archive} -C #{dir}) + execute(%W(tar -#{options} #{archive} -C #{dir})) + end + + def execute(cmd) _output, status = Gitlab::Popen.popen(cmd) status.zero? end diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml index 92f492e901..ca433e72d5 100644 --- a/lib/gitlab/import_export/import_export.yml +++ b/lib/gitlab/import_export/import_export.yml @@ -1,22 +1,23 @@ -# Class relationships to be included in the project import/export -:project_tree: - - :issues: +# Model relationships to be included in the project import/export +project_tree: + - issues: - :notes - :labels - :milestones - :snippets - :releases - :events - - :project_members: + - project_members: - :user - - :merge_requests: + - merge_requests: - :merge_request_diff - :notes - - :ci_commits: + - ci_commits: - :statuses -:attributes_only: - :project: +# Only include the following attributes for the models specified. +included_attributes: + project: - :name - :path - :description @@ -27,11 +28,12 @@ - :snippets_enabled - :visibility_level - :archived - :user: + user: - :id - :email - :username -:attributes_except: - :snippets: +# Do not include the following attributes for the models specified. +excluded_attributes: + snippets: - :expired_at \ No newline at end of file diff --git a/lib/gitlab/import_export/import_export_reader.rb b/lib/gitlab/import_export/import_export_reader.rb index 14049cb1bd..77db6cabe3 100644 --- a/lib/gitlab/import_export/import_export_reader.rb +++ b/lib/gitlab/import_export/import_export_reader.rb @@ -4,7 +4,7 @@ module Gitlab extend self def project_tree - { only: atts_only[:project], include: build_hash(tree) } + { only: included_attributes[:project], include: build_hash(tree) } end def tree @@ -14,24 +14,24 @@ module Gitlab private def config - @config ||= YAML.load_file('lib/gitlab/import_export/import_export.yml') + @config ||= YAML.load_file('lib/gitlab/import_export/import_export.yml').with_indifferent_access end - def atts_only - config[:attributes_only] + def included_attributes + config[:included_attributes] || {} end - def atts_except - config[:attributes_except] + def excluded_attributes + config[:excluded_attributes] || {} end def build_hash(array) - array.map do |el| - if el.is_a?(Hash) - process_include(el) + array.map do |model_object| + if model_object.is_a?(Hash) + process_include(model_object) else - only_except_hash = check_only_and_except(el) - only_except_hash.empty? ? el : { el => only_except_hash } + only_except_hash = check_only_and_except(model_object) + only_except_hash.empty? ? model_object : { model_object => only_except_hash } end end end @@ -82,12 +82,12 @@ module Gitlab def check_only(value) key = key_from_hash(value) - atts_only[key].nil? ? {} : { only: atts_only[key] } + included_attributes[key].nil? ? {} : { only: included_attributes[key] } end def check_except(value) key = key_from_hash(value) - atts_except[key].nil? ? {} : { except: atts_except[key] } + excluded_attributes[key].nil? ? {} : { except: excluded_attributes[key] } end def key_from_hash(value) diff --git a/lib/gitlab/import_export/project_tree_saver.rb b/lib/gitlab/import_export/project_tree_saver.rb index 394411a56c..29d715c16d 100644 --- a/lib/gitlab/import_export/project_tree_saver.rb +++ b/lib/gitlab/import_export/project_tree_saver.rb @@ -3,19 +3,13 @@ module Gitlab class ProjectTreeSaver attr_reader :full_path - def initialize(project: , shared: ) + def initialize(project:, shared:) @project = project @export_path = shared.export_path + @full_path = File.join(@export_path, project_filename) end def save - @full_path = File.join(@export_path, project_filename) - save_to_disk - end - - private - - def save_to_disk FileUtils.mkdir_p(@export_path) File.write(full_path, project_json_tree) true @@ -24,6 +18,8 @@ module Gitlab false end + private + # TODO remove magic keyword and move it to a shared config def project_filename "project.json" diff --git a/spec/lib/gitlab/import_export/import_export_reader_spec.rb b/spec/lib/gitlab/import_export/import_export_reader_spec.rb index e71c7b60b8..0b2da73a22 100644 --- a/spec/lib/gitlab/import_export/import_export_reader_spec.rb +++ b/spec/lib/gitlab/import_export/import_export_reader_spec.rb @@ -1,4 +1,4 @@ -require 'rspec' +require 'spec_helper' describe Gitlab::ImportExport::ImportExportReader do @@ -17,7 +17,7 @@ describe Gitlab::ImportExport::ImportExportReader do end it 'should generate hash from project tree config' do - allow(described_class).to receive(:config).and_return(YAML.load_file(test_config)) + allow(described_class).to receive(:config).and_return(YAML.load_file(test_config).deep_symbolize_keys) expect(described_class.project_tree).to eq(project_tree_hash) 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 5c1b9af2c1..67e6267b74 100644 --- a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb @@ -1,42 +1,20 @@ require 'spec_helper' describe Gitlab::ImportExport::ProjectTreeSaver, services: true do - describe :save do + describe 'saves the project tree into a json object' do - # TODO refactor this into a setup method - - let(:user) { create(:user) } - let(:issue) { create(:issue, assignee: user) } - let(:merge_request) { create(:merge_request) } - let(:label) { create(:label) } - let(:snippet) { create(:project_snippet) } - let(:commit_status) { create(:commit_status) } - let(:release) { create(:release) } - let!(:project) do - create(:project, - :public, - name: 'searchable_project', - issues: [issue], - merge_requests: [merge_request], - labels: [label], - snippets: [snippet], - releases: [release] - ) - end - let!(:ci_commit) { create(:ci_commit, project: project, sha: merge_request.last_commit.id, ref: merge_request.source_branch, statuses: [commit_status]) } - let!(:milestone) { create(:milestone, title: "Milestone v1.2", project: project) } - let(:export_path) { "#{Dir::tmpdir}/project_tree_saver_spec" } let(:shared) { Gitlab::ImportExport::Shared.new(relative_path: project.path_with_namespace) } - let(:project_tree_saver) { Gitlab::ImportExport::ProjectTreeSaver.new(project: project, shared: shared) } - let!(:issue_note) { create(:note, note: ":+1: issue", noteable: issue) } - let!(:merge_request_note) { create(:note, note: ":+1: merge_request", noteable: merge_request) } + let(:project_tree_saver) { described_class.new(project: project, shared: shared) } + let(:export_path) { "#{Dir::tmpdir}/project_tree_saver_spec" } + let(:user) { create(:user) } + let(:project) { setup_project } - before(:each) do + before do project.team << [user, :master] allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path) end - after(:each) do + after do FileUtils.rm_rf(export_path) end @@ -109,6 +87,30 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do end end + def setup_project + issue = create(:issue, assignee: user) + merge_request = create(:merge_request) + label = create(:label) + snippet = create(:project_snippet) + commit_status = create(:commit_status) + release = create(:release) + + project = create(:project, + :public, + issues: [issue], + merge_requests: [merge_request], + labels: [label], + snippets: [snippet], + releases: [release] + ) + + create(:ci_commit, project: project, sha: merge_request.last_commit.id, ref: merge_request.source_branch, statuses: [commit_status]) + create(:milestone, project: project) + create(:note, noteable: issue) + create(:note, noteable: merge_request) + project + end + def project_json(filename) JSON.parse(IO.read(filename)) end diff --git a/spec/lib/gitlab/import_export/repo_bundler_spec.rb b/spec/lib/gitlab/import_export/repo_bundler_spec.rb index 23447d878a..fa926bab82 100644 --- a/spec/lib/gitlab/import_export/repo_bundler_spec.rb +++ b/spec/lib/gitlab/import_export/repo_bundler_spec.rb @@ -1,20 +1,20 @@ require 'spec_helper' describe Gitlab::ImportExport::RepoBundler, services: true do - describe :bundle 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" } let(:shared) { Gitlab::ImportExport::Shared.new(relative_path: project.path_with_namespace) } - let(:bundler) { Gitlab::ImportExport::RepoBundler.new(project: project, shared: shared) } + let(:bundler) { described_class.new(project: project, shared: shared) } - before(:each) do + before do project.team << [user, :master] allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path) end - after(:each) do + after do FileUtils.rm_rf(export_path) end 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 6cc95edc21..60a0145c1a 100644 --- a/spec/lib/gitlab/import_export/wiki_repo_bundler_spec.rb +++ b/spec/lib/gitlab/import_export/wiki_repo_bundler_spec.rb @@ -1,23 +1,23 @@ require 'spec_helper' describe Gitlab::ImportExport::WikiRepoBundler, services: true do - describe :bundle 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" } let(:shared) { Gitlab::ImportExport::Shared.new(relative_path: project.path_with_namespace) } - let(:wiki_bundler) { Gitlab::ImportExport::WikiRepoBundler.new(project: project, shared: shared) } + let(:wiki_bundler) { described_class.new(project: project, shared: shared) } let!(:project_wiki) { ProjectWiki.new(project, user) } - before(:each) do + before do project.team << [user, :master] allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path) project_wiki.wiki project_wiki.create_page("index", "test content") end - after(:each) do + after do FileUtils.rm_rf(export_path) end diff --git a/spec/support/import_export/import_export.yml b/spec/support/import_export/import_export.yml index e6985d6413..3ceec50640 100644 --- a/spec/support/import_export/import_export.yml +++ b/spec/support/import_export/import_export.yml @@ -1,20 +1,20 @@ # Class relationships to be included in the project import/export -:project_tree: +project_tree: - :issues - :labels - - :merge_requests: + - merge_requests: - :merge_request_diff - :merge_request_test - - :commit_statuses: + - commit_statuses: - :commit -:attributes_only: - :project: +included_attributes: + project: - :name - :path - :merge_requests: + merge_requests: - :id -:attributes_except: - :merge_requests: +excluded_attributes: + merge_requests: - :iid \ No newline at end of file From b6ab4a311396d12cdb686df885fe48c58ea31218 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 6 May 2016 14:39:57 +0200 Subject: [PATCH 128/730] missing private keyword --- lib/gitlab/import_export/command_line_util.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/gitlab/import_export/command_line_util.rb b/lib/gitlab/import_export/command_line_util.rb index 4a1018072c..c99b0d83b4 100644 --- a/lib/gitlab/import_export/command_line_util.rb +++ b/lib/gitlab/import_export/command_line_util.rb @@ -17,6 +17,8 @@ module Gitlab execute(%W(#{git_bin_path} clone --bare #{bundle_path} #{repo_path})) end + private + def tar_with_options(archive:, dir:, options:) execute(%W(tar -#{options} #{archive} -C #{dir} .)) end From 49cdb778a17b25014c9439eb1a719e1fac9d04d0 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 6 May 2016 15:18:25 +0200 Subject: [PATCH 129/730] few fixes to import specs and code --- lib/gitlab/import_export/project_tree_restorer.rb | 5 +++-- spec/lib/gitlab/import_export/members_mapper_spec.rb | 4 ++-- {lib => spec/lib}/gitlab/import_export/project.json | 0 spec/lib/gitlab/import_export/project_tree_restorer_spec.rb | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) rename {lib => spec/lib}/gitlab/import_export/project.json (100%) diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index 7aa0ff46cd..ad77f7f69b 100644 --- a/lib/gitlab/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -14,7 +14,8 @@ module Gitlab @tree_hash = ActiveSupport::JSON.decode(json) @project_members = @tree_hash.delete('project_members') create_relations - rescue + rescue => e + # TODO: handle errors better, move them to a shared thing false end @@ -83,7 +84,7 @@ module Gitlab def relation_from_factory(relation, relation_hash) Gitlab::ImportExport::RelationFactory.create( - relation_sym: relation, relation_hash: relation_hash.merge('project_id' => project.id), members_map: members_map) + relation_sym: relation.to_sym, relation_hash: relation_hash.merge('project_id' => project.id), members_map: members_map) end end end diff --git a/spec/lib/gitlab/import_export/members_mapper_spec.rb b/spec/lib/gitlab/import_export/members_mapper_spec.rb index 9175356c64..a4d3d6d122 100644 --- a/spec/lib/gitlab/import_export/members_mapper_spec.rb +++ b/spec/lib/gitlab/import_export/members_mapper_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe Gitlab::ImportExport::MembersMapper, services: true do - describe :map do + describe 'map members' do let(:user) { create(:user) } let(:project) { create(:project, :public, name: 'searchable_project') } @@ -31,7 +31,7 @@ describe Gitlab::ImportExport::MembersMapper, services: true do end let(:members_mapper) do - Gitlab::ImportExport::MembersMapper.new( + described_class.new( exported_members: exported_members, user: user, project_id: project.id) end diff --git a/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json similarity index 100% rename from lib/gitlab/import_export/project.json rename to spec/lib/gitlab/import_export/project.json 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 aa8a12c4ca..0958365ff9 100644 --- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb @@ -1,11 +1,11 @@ require 'spec_helper' describe Gitlab::ImportExport::ProjectTreeRestorer, services: true do - describe :restore do + describe 'restore project tree' do let(:user) { create(:user) } let(:namespace) { create(:namespace, owner: user) } - let(:project_tree_restorer) { Gitlab::ImportExport::ProjectTreeRestorer.new(path: "lib/gitlab/import_export/", user: user, project_path: 'project', namespace_id: namespace.id) } + let(:project_tree_restorer) { described_class.new(path: Rails.root.join("spec/lib/gitlab/import_export/"), user: user, project_path: 'project', namespace_id: namespace.id) } context 'JSON' do let(:restored_project_json) do From 8ac53eb5d0dcc6d0248a8b178a3c1b5f2d2284e1 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 6 May 2016 17:55:06 +0200 Subject: [PATCH 130/730] started refactoring import export reader - WIP --- lib/gitlab/import_export.rb | 2 +- lib/gitlab/import_export/attributes_finder.rb | 35 ++++++++++ .../import_export/import_export_reader.rb | 68 ++++++------------- .../import_export_reader_spec.rb | 4 +- 4 files changed, 57 insertions(+), 52 deletions(-) create mode 100644 lib/gitlab/import_export/attributes_finder.rb diff --git a/lib/gitlab/import_export.rb b/lib/gitlab/import_export.rb index aa69f7c44a..84860b43cb 100644 --- a/lib/gitlab/import_export.rb +++ b/lib/gitlab/import_export.rb @@ -11,7 +11,7 @@ module Gitlab end def project_tree - Gitlab::ImportExport::ImportExportReader.project_tree + Gitlab::ImportExport::ImportExportReader.new.project_tree end def storage_path diff --git a/lib/gitlab/import_export/attributes_finder.rb b/lib/gitlab/import_export/attributes_finder.rb new file mode 100644 index 0000000000..12ae79a877 --- /dev/null +++ b/lib/gitlab/import_export/attributes_finder.rb @@ -0,0 +1,35 @@ +module Gitlab + module ImportExport + class AttributesFinder + def initialize(included_attributes:, excluded_attributes:) + @included_attributes = included_attributes || {} + @excluded_attributes = excluded_attributes || {} + end + + def find(model_object) + parsed_hash = find_attributes_only(model_object) + parsed_hash.empty? ? model_object : { model_object => parsed_hash } + end + + def find_attributes_only(value) + find_included(value).merge(find_excluded(value)) + end + + def find_included(value) + key = key_from_hash(value) + @included_attributes[key].nil? ? {} : { only: @included_attributes[key] } + end + + def find_excluded(value) + key = key_from_hash(value) + @excluded_attributes[key].nil? ? {} : { except: @excluded_attributes[key] } + end + + private + + def key_from_hash(value) + value.is_a?(Hash) ? value.keys.first : value + end + end + end +end \ No newline at end of file diff --git a/lib/gitlab/import_export/import_export_reader.rb b/lib/gitlab/import_export/import_export_reader.rb index 77db6cabe3..a6cf191010 100644 --- a/lib/gitlab/import_export/import_export_reader.rb +++ b/lib/gitlab/import_export/import_export_reader.rb @@ -1,37 +1,27 @@ module Gitlab module ImportExport - module ImportExportReader - extend self + class ImportExportReader + #FIXME - def project_tree - { only: included_attributes[:project], include: build_hash(tree) } + def initialize(config: 'lib/gitlab/import_export/import_export.yml') + config = YAML.load_file('lib/gitlab/import_export/import_export.yml').with_indifferent_access + @tree = config[:project_tree] + @attributes_parser = Gitlab::ImportExport::AttributesFinder.new(included_attributes: config[:included_attributes], + excluded_attributes: config[:excluded_attributes]) end - def tree - config[:project_tree] + def project_tree + { only: @attributes_parser.find_included(:project), include: build_hash(@tree) } end private - def config - @config ||= YAML.load_file('lib/gitlab/import_export/import_export.yml').with_indifferent_access - end - - def included_attributes - config[:included_attributes] || {} - end - - def excluded_attributes - config[:excluded_attributes] || {} - end - - def build_hash(array) - array.map do |model_object| + def build_hash(model_list) + model_list.map do |model_object| if model_object.is_a?(Hash) process_include(model_object) else - only_except_hash = check_only_and_except(model_object) - only_except_hash.empty? ? model_object : { model_object => only_except_hash } + @attributes_parser.find(model_object) end end end @@ -51,48 +41,30 @@ module Gitlab def process_current_class(hash, included_classes_hash, value) value = value.is_a?(Hash) ? process_include(hash, included_classes_hash) : value - only_except_hash = check_only_and_except(hash.keys.first) - included_classes_hash[hash.keys.first] ||= only_except_hash unless only_except_hash.empty? + attributes_hash = @attributes_parser.find_attributes_only(hash.keys.first) + included_classes_hash[hash.keys.first] ||= attributes_hash unless attributes_hash.empty? value end def add_new_class(current_key, included_classes_hash, value) - only_except_hash = check_only_and_except(value) + attributes_hash = @attributes_parser.find_attributes_only(value) parsed_hash = { include: value } - unless only_except_hash.empty? + unless attributes_hash.empty? if value.is_a?(Hash) - parsed_hash = { include: value.merge(only_except_hash) } + parsed_hash = { include: value.merge(attributes_hash) } else - parsed_hash = { include: { value => only_except_hash } } + parsed_hash = { include: { value => attributes_hash } } end end included_classes_hash[current_key] = parsed_hash end def add_to_class(current_key, included_classes_hash, value) - only_except_hash = check_only_and_except(value) - value = { value => only_except_hash } unless only_except_hash.empty? + attributes_hash = @attributes_parser.find_attributes_only(value) + value = { value => attributes_hash } unless attributes_hash.empty? old_values = included_classes_hash[current_key][:include] included_classes_hash[current_key][:include] = ([old_values] + [value]).compact.flatten end - - def check_only_and_except(value) - check_only(value).merge(check_except(value)) - end - - def check_only(value) - key = key_from_hash(value) - included_attributes[key].nil? ? {} : { only: included_attributes[key] } - end - - def check_except(value) - key = key_from_hash(value) - excluded_attributes[key].nil? ? {} : { except: excluded_attributes[key] } - end - - def key_from_hash(value) - value.is_a?(Hash) ? value.keys.first : value - end end end end diff --git a/spec/lib/gitlab/import_export/import_export_reader_spec.rb b/spec/lib/gitlab/import_export/import_export_reader_spec.rb index 0b2da73a22..6be2289b5a 100644 --- a/spec/lib/gitlab/import_export/import_export_reader_spec.rb +++ b/spec/lib/gitlab/import_export/import_export_reader_spec.rb @@ -17,8 +17,6 @@ describe Gitlab::ImportExport::ImportExportReader do end it 'should generate hash from project tree config' do - allow(described_class).to receive(:config).and_return(YAML.load_file(test_config).deep_symbolize_keys) - - expect(described_class.project_tree).to eq(project_tree_hash) + expect(described_class.new(config: test_config).project_tree).to eq(project_tree_hash) end end From 3aee167dcc26e6b9b92d6f67b316280675f5cde8 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 9 May 2016 11:10:12 +0200 Subject: [PATCH 131/730] fixed issues after refactor, spec passing --- lib/gitlab/import_export/import_export_reader.rb | 10 +++++----- .../gitlab/import_export/import_export_reader_spec.rb | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/gitlab/import_export/import_export_reader.rb b/lib/gitlab/import_export/import_export_reader.rb index a6cf191010..3f45de209c 100644 --- a/lib/gitlab/import_export/import_export_reader.rb +++ b/lib/gitlab/import_export/import_export_reader.rb @@ -4,14 +4,14 @@ module Gitlab #FIXME def initialize(config: 'lib/gitlab/import_export/import_export.yml') - config = YAML.load_file('lib/gitlab/import_export/import_export.yml').with_indifferent_access - @tree = config[:project_tree] - @attributes_parser = Gitlab::ImportExport::AttributesFinder.new(included_attributes: config[:included_attributes], - excluded_attributes: config[:excluded_attributes]) + config_hash = YAML.load_file(config).with_indifferent_access + @tree = config_hash[:project_tree] + @attributes_parser = Gitlab::ImportExport::AttributesFinder.new(included_attributes: config_hash[:included_attributes], + excluded_attributes: config_hash[:excluded_attributes]) end def project_tree - { only: @attributes_parser.find_included(:project), include: build_hash(@tree) } + @attributes_parser.find_included(:project).merge(include: build_hash(@tree)) end private diff --git a/spec/lib/gitlab/import_export/import_export_reader_spec.rb b/spec/lib/gitlab/import_export/import_export_reader_spec.rb index 6be2289b5a..f826c5ec8e 100644 --- a/spec/lib/gitlab/import_export/import_export_reader_spec.rb +++ b/spec/lib/gitlab/import_export/import_export_reader_spec.rb @@ -17,6 +17,6 @@ describe Gitlab::ImportExport::ImportExportReader do end it 'should generate hash from project tree config' do - expect(described_class.new(config: test_config).project_tree).to eq(project_tree_hash) + expect(described_class.new(config: test_config).project_tree) =~ (project_tree_hash) end end From 9c639041fe312f8edf1613809ac665cb8755ffb7 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 9 May 2016 12:15:50 +0200 Subject: [PATCH 132/730] bit more refactoring of import export reader, fixed rubocop warning --- lib/gitlab/import_export/attributes_finder.rb | 2 +- .../import_export/import_export_reader.rb | 22 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/gitlab/import_export/attributes_finder.rb b/lib/gitlab/import_export/attributes_finder.rb index 12ae79a877..8a599ad526 100644 --- a/lib/gitlab/import_export/attributes_finder.rb +++ b/lib/gitlab/import_export/attributes_finder.rb @@ -32,4 +32,4 @@ module Gitlab end end end -end \ No newline at end of file +end diff --git a/lib/gitlab/import_export/import_export_reader.rb b/lib/gitlab/import_export/import_export_reader.rb index 3f45de209c..35ff05350d 100644 --- a/lib/gitlab/import_export/import_export_reader.rb +++ b/lib/gitlab/import_export/import_export_reader.rb @@ -17,30 +17,30 @@ module Gitlab private def build_hash(model_list) - model_list.map do |model_object| - if model_object.is_a?(Hash) - process_include(model_object) + model_list.map do |model_object_hash| + if model_object_hash.is_a?(Hash) + process_model_object(model_object_hash) else - @attributes_parser.find(model_object) + @attributes_parser.find(model_object_hash) end end end - def process_include(hash, included_classes_hash = {}) - hash.values.flatten.each do |value| - current_key = hash.keys.first - value = process_current_class(hash, included_classes_hash, value) + def process_model_object(model_object_hash, included_classes_hash = {}) + model_object_hash.values.flatten.each do |model_object| + current_key = model_object_hash.keys.first + model_object = process_current_class(model_object_hash, included_classes_hash, model_object) if included_classes_hash[current_key] - add_to_class(current_key, included_classes_hash, value) + add_to_class(current_key, included_classes_hash, model_object) else - add_new_class(current_key, included_classes_hash, value) + add_new_class(current_key, included_classes_hash, model_object) end end included_classes_hash end def process_current_class(hash, included_classes_hash, value) - value = value.is_a?(Hash) ? process_include(hash, included_classes_hash) : value + value = value.is_a?(Hash) ? process_model_object(hash, included_classes_hash) : value attributes_hash = @attributes_parser.find_attributes_only(hash.keys.first) included_classes_hash[hash.keys.first] ||= attributes_hash unless attributes_hash.empty? value From 7ff2a51eb24032895e6199c62de44e17de65af7b Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 9 May 2016 17:58:43 +0200 Subject: [PATCH 133/730] more refactoring to import export reader --- lib/gitlab/import_export/attributes_finder.rb | 9 ++- .../import_export/import_export_reader.rb | 56 +++++++++---------- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/lib/gitlab/import_export/attributes_finder.rb b/lib/gitlab/import_export/attributes_finder.rb index 8a599ad526..cfb9f0eef1 100644 --- a/lib/gitlab/import_export/attributes_finder.rb +++ b/lib/gitlab/import_export/attributes_finder.rb @@ -11,8 +11,9 @@ module Gitlab parsed_hash.empty? ? model_object : { model_object => parsed_hash } end - def find_attributes_only(value) - find_included(value).merge(find_excluded(value)) + def parse(model_object) + parsed_hash = find_attributes_only(model_object) + yield parsed_hash unless parsed_hash.empty? end def find_included(value) @@ -27,6 +28,10 @@ module Gitlab private + def find_attributes_only(value) + find_included(value).merge(find_excluded(value)) + end + def key_from_hash(value) value.is_a?(Hash) ? value.keys.first : value end diff --git a/lib/gitlab/import_export/import_export_reader.rb b/lib/gitlab/import_export/import_export_reader.rb index 35ff05350d..84c3f3e972 100644 --- a/lib/gitlab/import_export/import_export_reader.rb +++ b/lib/gitlab/import_export/import_export_reader.rb @@ -1,13 +1,13 @@ module Gitlab module ImportExport class ImportExportReader - #FIXME def initialize(config: 'lib/gitlab/import_export/import_export.yml') config_hash = YAML.load_file(config).with_indifferent_access @tree = config_hash[:project_tree] @attributes_parser = Gitlab::ImportExport::AttributesFinder.new(included_attributes: config_hash[:included_attributes], excluded_attributes: config_hash[:excluded_attributes]) + @json_config_hash = {} end def project_tree @@ -19,51 +19,49 @@ module Gitlab def build_hash(model_list) model_list.map do |model_object_hash| if model_object_hash.is_a?(Hash) - process_model_object(model_object_hash) + build_json_config_hash(model_object_hash) else @attributes_parser.find(model_object_hash) end end end - def process_model_object(model_object_hash, included_classes_hash = {}) + def build_json_config_hash(model_object_hash) model_object_hash.values.flatten.each do |model_object| current_key = model_object_hash.keys.first - model_object = process_current_class(model_object_hash, included_classes_hash, model_object) - if included_classes_hash[current_key] - add_to_class(current_key, included_classes_hash, model_object) - else - add_new_class(current_key, included_classes_hash, model_object) - end + + @attributes_parser.parse(current_key) { |hash| @json_config_hash[current_key] ||= hash } + + handle_model_object(current_key, model_object) end - included_classes_hash + @json_config_hash end - def process_current_class(hash, included_classes_hash, value) - value = value.is_a?(Hash) ? process_model_object(hash, included_classes_hash) : value - attributes_hash = @attributes_parser.find_attributes_only(hash.keys.first) - included_classes_hash[hash.keys.first] ||= attributes_hash unless attributes_hash.empty? - value + def handle_model_object(current_key, model_object) + if @json_config_hash[current_key] + add_model_value(current_key, model_object) + else + create_model_value(current_key, model_object) + end end - def add_new_class(current_key, included_classes_hash, value) - attributes_hash = @attributes_parser.find_attributes_only(value) + def create_model_value(current_key, value) parsed_hash = { include: value } - unless attributes_hash.empty? - if value.is_a?(Hash) - parsed_hash = { include: value.merge(attributes_hash) } - else - parsed_hash = { include: { value => attributes_hash } } - end + + @attributes_parser.parse(value) do |hash| + parsed_hash = { include: hash_or_merge(value, hash) } end - included_classes_hash[current_key] = parsed_hash + @json_config_hash[current_key] = parsed_hash end - def add_to_class(current_key, included_classes_hash, value) - attributes_hash = @attributes_parser.find_attributes_only(value) - value = { value => attributes_hash } unless attributes_hash.empty? - old_values = included_classes_hash[current_key][:include] - included_classes_hash[current_key][:include] = ([old_values] + [value]).compact.flatten + def add_model_value(current_key, value) + @attributes_parser.parse(value) { |hash| value = { value => hash } } + old_values = @json_config_hash[current_key][:include] + @json_config_hash[current_key][:include] = ([old_values] + [value]).compact.flatten + end + + def hash_or_merge(value, hash) + value.is_a?(Hash) ? value.merge(hash) : hash end end end From bd0c8ce40542dd3c05526c4c80df4ad4c151b4b6 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 9 May 2016 18:07:29 +0200 Subject: [PATCH 134/730] fixed space --- spec/features/projects/import_export/import_file_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb index a7da7a21ea..03298149b6 100644 --- a/spec/features/projects/import_export/import_file_spec.rb +++ b/spec/features/projects/import_export/import_file_spec.rb @@ -8,6 +8,7 @@ feature 'project import', feature: true, js: true do let(:file) { File.join(Rails.root, 'spec', 'features', 'projects', 'import_export', 'test_project_export.tar.gz') } let(:export_path) { "#{Dir::tmpdir}/import_file_spec" } let(:project) { Project.last } + background do allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path) login_as(user) From 5dad9f1fcbd432f1c2cc2e861983e4c49cfce140 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 9 May 2016 16:19:07 +0000 Subject: [PATCH 135/730] new line missing --- lib/gitlab/import_export/attributes_finder.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/gitlab/import_export/attributes_finder.rb b/lib/gitlab/import_export/attributes_finder.rb index cfb9f0eef1..3439ef1006 100644 --- a/lib/gitlab/import_export/attributes_finder.rb +++ b/lib/gitlab/import_export/attributes_finder.rb @@ -1,6 +1,7 @@ module Gitlab module ImportExport class AttributesFinder + def initialize(included_attributes:, excluded_attributes:) @included_attributes = included_attributes || {} @excluded_attributes = excluded_attributes || {} From 21be0cae62af3ba5e0e71758d260287b164fe504 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 9 May 2016 18:33:48 +0200 Subject: [PATCH 136/730] fixing merge issues --- lib/gitlab/import_export.rb | 4 ---- lib/gitlab/import_export/import_export.yml | 1 - 2 files changed, 5 deletions(-) diff --git a/lib/gitlab/import_export.rb b/lib/gitlab/import_export.rb index 84860b43cb..655373c03a 100644 --- a/lib/gitlab/import_export.rb +++ b/lib/gitlab/import_export.rb @@ -6,10 +6,6 @@ module Gitlab File.join(storage_path, relative_path) end - def project_attributes - %i(name path description issues_enabled wall_enabled merge_requests_enabled wiki_enabled snippets_enabled visibility_level archived) - end - def project_tree Gitlab::ImportExport::ImportExportReader.new.project_tree end diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml index ca433e72d5..36128909df 100644 --- a/lib/gitlab/import_export/import_export.yml +++ b/lib/gitlab/import_export/import_export.yml @@ -22,7 +22,6 @@ included_attributes: - :path - :description - :issues_enabled - - :wall_enabled - :merge_requests_enabled - :wiki_enabled - :snippets_enabled From 6a12ff6345e517af9cf07cb61f3a0ea85562f399 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 9 May 2016 18:40:31 +0200 Subject: [PATCH 137/730] renaming variable --- lib/gitlab/import_export/import_export_reader.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/gitlab/import_export/import_export_reader.rb b/lib/gitlab/import_export/import_export_reader.rb index 84c3f3e972..37093ff58e 100644 --- a/lib/gitlab/import_export/import_export_reader.rb +++ b/lib/gitlab/import_export/import_export_reader.rb @@ -17,11 +17,11 @@ module Gitlab private def build_hash(model_list) - model_list.map do |model_object_hash| - if model_object_hash.is_a?(Hash) - build_json_config_hash(model_object_hash) + model_list.map do |model_objects| + if model_objects.is_a?(Hash) + build_json_config_hash(model_objects) else - @attributes_parser.find(model_object_hash) + @attributes_parser.find(model_objects) end end end From 5b51d13c5e432cb76dc911047cc8c5932ecfe421 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 10 May 2016 12:01:10 +0200 Subject: [PATCH 138/730] removed method no longer needed --- lib/gitlab/import_export.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/gitlab/import_export.rb b/lib/gitlab/import_export.rb index 22973ff3b6..655373c03a 100644 --- a/lib/gitlab/import_export.rb +++ b/lib/gitlab/import_export.rb @@ -6,10 +6,6 @@ module Gitlab File.join(storage_path, relative_path) end - def project_tree_list - project_tree.map {|r| r.is_a?(Hash) ? r.keys.first : r } - end - def project_tree Gitlab::ImportExport::ImportExportReader.new.project_tree end From e6fcd6d5bd8580f992f557c05aef3cc335b7ee8b Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 10 May 2016 12:30:45 +0200 Subject: [PATCH 139/730] fixed more import merging issues --- spec/lib/gitlab/import_export/project.json | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json index 4a12c951dc..8b6a16c049 100644 --- a/spec/lib/gitlab/import_export/project.json +++ b/spec/lib/gitlab/import_export/project.json @@ -3,7 +3,6 @@ "path": "gitlabhq", "description": null, "issues_enabled": true, - "wall_enabled": false, "merge_requests_enabled": true, "wiki_enabled": true, "snippets_enabled": true, From 17ce63a5e19f03fb1fec04724ca6d41e463a32b6 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 10 May 2016 13:11:21 +0200 Subject: [PATCH 140/730] updated spec export file --- .../import_export/test_project_export.tar.gz | Bin 338759 -> 322702 bytes 1 file changed, 0 insertions(+), 0 deletions(-) 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 87f118b6e230a19317e7070bf04c7ad072f0eb9c..8147c289b8e763d509d35f0293814d92489772f3 100644 GIT binary patch delta 60492 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 W2l98i54EumNVDWoYp`5su>S!Q?;8LB delta 76674 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 From a5d59f075a4a9a301ef985eb7cc6cdfdf3e73955 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 10 May 2016 17:15:20 +0200 Subject: [PATCH 141/730] added better error handling. Also refactored some of the code and fixed a few issues in project_tree_saver --- .../projects/import_export/export_service.rb | 8 ++++++-- lib/gitlab/import_export.rb | 4 ---- lib/gitlab/import_export/error.rb | 5 +++++ .../import_export/import_export_reader.rb | 12 ++++++++---- lib/gitlab/import_export/project_tree_saver.rb | 12 ++++++------ lib/gitlab/import_export/repo_bundler.rb | 9 +++++---- lib/gitlab/import_export/saver.rb | 17 ++++++++++------- lib/gitlab/import_export/shared.rb | 15 +++++++++++++++ lib/gitlab/import_export/wiki_repo_bundler.rb | 7 ++++--- .../import_export/import_export_reader_spec.rb | 4 ++-- 10 files changed, 61 insertions(+), 32 deletions(-) create mode 100644 lib/gitlab/import_export/error.rb diff --git a/app/services/projects/import_export/export_service.rb b/app/services/projects/import_export/export_service.rb index fd569e1c9a..87a259ed15 100644 --- a/app/services/projects/import_export/export_service.rb +++ b/app/services/projects/import_export/export_service.rb @@ -4,8 +4,8 @@ module Projects def execute(options = {}) @shared = Gitlab::ImportExport::Shared.new(relative_path: File.join(project.path_with_namespace, 'work')) - # TODO handle errors save_all if [save_project_tree, bundle_repo, bundle_wiki_repo].all? + notify_worker if @shared.errors.any? end private @@ -23,7 +23,11 @@ module Projects end def save_all - Gitlab::ImportExport::Saver.save(storage_path: @shared.export_path) + Gitlab::ImportExport::Saver.save(shared: @shared) + end + + def notify_worker + raise Gitlab::ImportExport::Error @shared.errors.join(', ') end end end diff --git a/lib/gitlab/import_export.rb b/lib/gitlab/import_export.rb index 655373c03a..6835411ba7 100644 --- a/lib/gitlab/import_export.rb +++ b/lib/gitlab/import_export.rb @@ -6,10 +6,6 @@ module Gitlab File.join(storage_path, relative_path) end - def project_tree - Gitlab::ImportExport::ImportExportReader.new.project_tree - end - def storage_path File.join(Settings.shared['path'], 'tmp/project_exports') end diff --git a/lib/gitlab/import_export/error.rb b/lib/gitlab/import_export/error.rb new file mode 100644 index 0000000000..b47a646c0b --- /dev/null +++ b/lib/gitlab/import_export/error.rb @@ -0,0 +1,5 @@ +module Gitlab + module ImportExport + class Error < StandardError; end + end +end \ No newline at end of file diff --git a/lib/gitlab/import_export/import_export_reader.rb b/lib/gitlab/import_export/import_export_reader.rb index 37093ff58e..b7204d5a87 100644 --- a/lib/gitlab/import_export/import_export_reader.rb +++ b/lib/gitlab/import_export/import_export_reader.rb @@ -2,16 +2,18 @@ module Gitlab module ImportExport class ImportExportReader - def initialize(config: 'lib/gitlab/import_export/import_export.yml') - config_hash = YAML.load_file(config).with_indifferent_access + def initialize(config: 'lib/gitlab/import_export/import_export.yml', shared:) + @shared = shared + config_hash = YAML.load_file(config).deep_symbolize_keys @tree = config_hash[:project_tree] @attributes_parser = Gitlab::ImportExport::AttributesFinder.new(included_attributes: config_hash[:included_attributes], excluded_attributes: config_hash[:excluded_attributes]) - @json_config_hash = {} end def project_tree @attributes_parser.find_included(:project).merge(include: build_hash(@tree)) + rescue => e + @shared.error(e.message) end private @@ -27,6 +29,8 @@ module Gitlab end def build_json_config_hash(model_object_hash) + @json_config_hash = {} + model_object_hash.values.flatten.each do |model_object| current_key = model_object_hash.keys.first @@ -61,7 +65,7 @@ module Gitlab end def hash_or_merge(value, hash) - value.is_a?(Hash) ? value.merge(hash) : hash + value.is_a?(Hash) ? value.merge(hash) : { value => hash } end end end diff --git a/lib/gitlab/import_export/project_tree_saver.rb b/lib/gitlab/import_export/project_tree_saver.rb index 29d715c16d..2287524c8a 100644 --- a/lib/gitlab/import_export/project_tree_saver.rb +++ b/lib/gitlab/import_export/project_tree_saver.rb @@ -5,16 +5,16 @@ module Gitlab def initialize(project:, shared:) @project = project - @export_path = shared.export_path - @full_path = File.join(@export_path, project_filename) + @shared = shared + @full_path = File.join(@shared.export_path, project_filename) end def save - FileUtils.mkdir_p(@export_path) + FileUtils.mkdir_p(@shared.export_path) File.write(full_path, project_json_tree) true - rescue - # TODO: handle error + rescue => e + @shared.error(e.message) false end @@ -26,7 +26,7 @@ module Gitlab end def project_json_tree - @project.to_json(Gitlab::ImportExport.project_tree) + @project.to_json(Gitlab::ImportExport::ImportExportReader.new(shared: @shared).project_tree) end end end diff --git a/lib/gitlab/import_export/repo_bundler.rb b/lib/gitlab/import_export/repo_bundler.rb index cd871687d7..bcf976fb62 100644 --- a/lib/gitlab/import_export/repo_bundler.rb +++ b/lib/gitlab/import_export/repo_bundler.rb @@ -7,21 +7,22 @@ module Gitlab def initialize(project: , shared: ) @project = project - @export_path = shared.export_path + @shared = shared end def bundle return false if @project.empty_repo? - @full_path = File.join(@export_path, project_filename) + @full_path = File.join(@shared.export_path, project_filename) bundle_to_disk end private def bundle_to_disk - FileUtils.mkdir_p(@export_path) + FileUtils.mkdir_p(@shared.export_path) git_bundle(repo_path: path_to_repo, bundle_path: @full_path) - rescue + rescue => e + @shared.error(e.message) false end diff --git a/lib/gitlab/import_export/saver.rb b/lib/gitlab/import_export/saver.rb index 634e58e603..024a0e1e78 100644 --- a/lib/gitlab/import_export/saver.rb +++ b/lib/gitlab/import_export/saver.rb @@ -7,32 +7,35 @@ module Gitlab new(*args).save end - def initialize(storage_path:) - @storage_path = storage_path + def initialize(shared:) + @shared = shared end def save if compress_and_save - remove_storage_path + remove_@shared.storage_path Rails.logger.info("Saved project export #{archive_file}") archive_file else false end + rescue => e + @shared.error(e.message) + false end private def compress_and_save - tar_czf(archive: archive_file, dir: @storage_path) + tar_czf(archive: archive_file, dir: @shared.storage_path) end - def remove_storage_path - FileUtils.rm_rf(@storage_path) + def remove_shared.storage_path + FileUtils.rm_rf(@shared.storage_path) end def archive_file - @archive_file ||= File.join(@storage_path, '..', "#{Time.now.strftime('%Y-%m-%d_%H-%M-%3N')}_project_export.tar.gz") + @archive_file ||= File.join(@shared.storage_path, '..', "#{Time.now.strftime('%Y-%m-%d_%H-%M-%3N')}_project_export.tar.gz") end end end diff --git a/lib/gitlab/import_export/shared.rb b/lib/gitlab/import_export/shared.rb index a4ec33a6cf..4246f73af9 100644 --- a/lib/gitlab/import_export/shared.rb +++ b/lib/gitlab/import_export/shared.rb @@ -1,13 +1,28 @@ module Gitlab module ImportExport class Shared + + attr_reader :errors + def initialize(opts) @opts = opts + @errors = [] end def export_path @export_path ||= Gitlab::ImportExport.export_path(relative_path: @opts[:relative_path]) end + + def error(message) + error_out(message, caller[0].dup) + @errors << message + end + + private + + def error_out(message, caller) + Rails.logger.error("Import/Export error raised on #{caller}: #{message}") + end end end end diff --git a/lib/gitlab/import_export/wiki_repo_bundler.rb b/lib/gitlab/import_export/wiki_repo_bundler.rb index 17f1530d5a..a0000176bb 100644 --- a/lib/gitlab/import_export/wiki_repo_bundler.rb +++ b/lib/gitlab/import_export/wiki_repo_bundler.rb @@ -4,14 +4,15 @@ module Gitlab def bundle @wiki = ProjectWiki.new(@project) return true if !wiki? # it's okay to have no Wiki - @full_path = File.join(@export_path, project_filename) + @full_path = File.join(@shared.export_path, project_filename) bundle_to_disk end def bundle_to_disk - FileUtils.mkdir_p(@export_path) + FileUtils.mkdir_p(@shared.export_path) git_bundle(repo_path: path_to_repo, bundle_path: @full_path) - rescue + rescue => e + @shared.error(e.message) false end diff --git a/spec/lib/gitlab/import_export/import_export_reader_spec.rb b/spec/lib/gitlab/import_export/import_export_reader_spec.rb index f826c5ec8e..2fc9a39c68 100644 --- a/spec/lib/gitlab/import_export/import_export_reader_spec.rb +++ b/spec/lib/gitlab/import_export/import_export_reader_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe Gitlab::ImportExport::ImportExportReader do - + let(:shared) { Gitlab::ImportExport::Shared.new(relative_path:'') } let(:test_config) { 'spec/support/import_export/import_export.yml' } let(:project_tree_hash) do { @@ -17,6 +17,6 @@ describe Gitlab::ImportExport::ImportExportReader do end it 'should generate hash from project tree config' do - expect(described_class.new(config: test_config).project_tree) =~ (project_tree_hash) + expect(described_class.new(config: test_config, shared: shared).project_tree) =~ (project_tree_hash) end end From d915e7d5cad99b8971e65d30accc8bc7a05fecbc Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Wed, 11 May 2016 10:16:23 +0530 Subject: [PATCH 142/730] Reuse the private token param and header for personal access tokens. - https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3749#note_11626427 - Personal access tokens are still a separate entity as far as the codebase is concerned - they just happen to use the same entry point as private tokens. - Update tests and documentation to reflect this change --- app/controllers/application_controller.rb | 2 +- doc/api/README.md | 4 ++-- lib/api/helpers.rb | 4 ++-- spec/controllers/application_controller_spec.rb | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 72ba1a85cf..b26afb42e7 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -80,7 +80,7 @@ class ApplicationController < ActionController::Base end def authenticate_user_from_personal_access_token! - token_string = params[:personal_access_token].presence || request.headers['PERSONAL_ACCESS_TOKEN'].presence + token_string = params[:private_token].presence || request.headers['PRIVATE-TOKEN'].presence personal_access_token = PersonalAccessToken.active.find_by_token(token_string) user = personal_access_token && personal_access_token.user diff --git a/doc/api/README.md b/doc/api/README.md index 0e9dc7acfe..276816b280 100644 --- a/doc/api/README.md +++ b/doc/api/README.md @@ -77,8 +77,8 @@ You can create as many personal access tokens as you like from your GitLab profile (`/profile/personal_access_tokens`); perhaps one for each application that needs access to the GitLab API. -Once you have your token, pass it to the API using either the `personal_access_token` -parameter or the `PERSONAL-ACCESS-TOKEN` header. +Once you have your token, pass it to the API using either the `private_token` +parameter or the `PRIVATE-TOKEN` header. ## Basic Usage diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index de9a1b0eb9..68642e2d8a 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -4,8 +4,8 @@ module API PRIVATE_TOKEN_PARAM = :private_token SUDO_HEADER ="HTTP_SUDO" SUDO_PARAM = :sudo - PERSONAL_ACCESS_TOKEN_PARAM = :personal_access_token - PERSONAL_ACCESS_TOKEN_HEADER = "HTTP_PERSONAL_ACCESS_TOKEN" + PERSONAL_ACCESS_TOKEN_PARAM = PRIVATE_TOKEN_PARAM + PERSONAL_ACCESS_TOKEN_HEADER = PRIVATE_TOKEN_HEADER def parse_boolean(value) [ true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON' ].include?(value) diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index e8bdbf1afb..d7835dc6e2 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -72,20 +72,20 @@ describe ApplicationController do let(:personal_access_token) { create(:personal_access_token, user: user) } it "logs the user in when the 'personal_access_token' param is populated with the personal access token" do - get :index, personal_access_token: personal_access_token.token + get :index, private_token: personal_access_token.token expect(response.status).to eq(200) expect(response.body).to eq('authenticated') end it "logs the user in when the 'PERSONAL_ACCESS_TOKEN' header is populated with the personal access token" do - @request.headers["PERSONAL_ACCESS_TOKEN"] = personal_access_token.token + @request.headers["PRIVATE-TOKEN"] = personal_access_token.token get :index expect(response.status).to eq(200) expect(response.body).to eq('authenticated') end it "doesn't log the user in otherwise" do - get :index, personal_access_token: "token" + get :index, private_token: "token" expect(response.status).to_not eq(200) expect(response.body).to_not eq('authenticated') end From 70add1388f514b353d92d2e6a1db0dc173290946 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Wed, 11 May 2016 10:25:21 +0530 Subject: [PATCH 143/730] Minor fixes after a final look at the diff. - Spaces around `{` and `}` in HAML. - Typo in CHANGELOG. - Remove i18n. --- CHANGELOG | 2 +- .../profiles/personal_access_tokens/index.html.haml | 10 +++++----- config/locales/en.yml | 4 ---- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 5b52977a9b..d8d8a36e4b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -12,7 +12,7 @@ v 8.8.0 (unreleased) - GitAccess#protected_tag? no longer loads all tags just to check if a single one exists - Reduce delay in destroying a project from 1-minute to immediately - Make build status canceled if any of the jobs was canceled and none failed - - Allow authentication using personal acces tokens + - Allow authentication using personal access tokens - Upgrade Sidekiq to 4.1.2 - Sanitize repo paths in new project error message - Bump mail_room to 0.7.0 to fix stuck IDLE connections diff --git a/app/views/profiles/personal_access_tokens/index.html.haml b/app/views/profiles/personal_access_tokens/index.html.haml index f7482d2c87..0f51e8cd8b 100644 --- a/app/views/profiles/personal_access_tokens/index.html.haml +++ b/app/views/profiles/personal_access_tokens/index.html.haml @@ -46,9 +46,9 @@ %tr %td= token.name %td.input-group.personal-access-tokens-token-column - %input.form-control{type: "text", value: token.token, readonly: true} + %input.form-control{ type: "text", value: token.token, readonly: true } %div.input-group-btn - %button.btn.btn-default{type: "button", data: {clipboard_text: token.token}} + %button.btn.btn-default{ type: "button", data: { clipboard_text: token.token } } %i.fa.fa-clipboard %td= token.created_at.to_date - if token.expires_at.present? @@ -56,7 +56,7 @@ - else %td %span.personal-access-tokens-never-expires-label Never - %td= link_to "Revoke", revoke_profile_personal_access_token_path(token), method: :put, class: "btn btn-danger", data: {confirm: t('profile.personal_access_tokens.revoke.confirmation')} + %td= link_to "Revoke", revoke_profile_personal_access_token_path(token), method: :put, class: "btn btn-danger", data: { confirm: "Are you sure? This cannot be undone." } - else %span You don't have any active tokens yet. @@ -78,9 +78,9 @@ %tr %td= token.name %td.input-group.personal-access-tokens-token-column - %input.form-control{type: "text", value: token.token, readonly: true} + %input.form-control{ type: "text", value: token.token, readonly: true } %div.input-group-btn - %button.btn.btn-default{type: "button", data: {clipboard_text: token.token}} + %button.btn.btn-default{ type: "button", data: { clipboard_text: token.token } } %i.fa.fa-clipboard %td= token.created_at.to_date diff --git a/config/locales/en.yml b/config/locales/en.yml index b5b8c4467b..cedb5e207b 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -12,7 +12,3 @@ en: pagination: previous: "Prev" next: "Next" - profile: - personal_access_tokens: - revoke: - confirmation: "Are you sure? This cannot be undone." From 49e6fc40b9d23b4081139a3ad141722a6b1f7cfc Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 11 May 2016 13:17:49 +0200 Subject: [PATCH 144/730] fix bad refactor --- lib/gitlab/import_export/saver.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/import_export/saver.rb b/lib/gitlab/import_export/saver.rb index 024a0e1e78..7532c977fc 100644 --- a/lib/gitlab/import_export/saver.rb +++ b/lib/gitlab/import_export/saver.rb @@ -13,7 +13,7 @@ module Gitlab def save if compress_and_save - remove_@shared.storage_path + remove_storage_path Rails.logger.info("Saved project export #{archive_file}") archive_file else @@ -30,7 +30,7 @@ module Gitlab tar_czf(archive: archive_file, dir: @shared.storage_path) end - def remove_shared.storage_path + def remove_storage_path FileUtils.rm_rf(@shared.storage_path) end From 5086e899fe26447e6e24064c9a05d3989c1e8448 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 11 May 2016 13:21:00 +0200 Subject: [PATCH 145/730] fix log statement --- app/workers/project_import_worker.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/workers/project_import_worker.rb b/app/workers/project_import_worker.rb index cc75da704f..c6a6d24b4e 100644 --- a/app/workers/project_import_worker.rb +++ b/app/workers/project_import_worker.rb @@ -15,7 +15,7 @@ class ProjectImportWorker project.repository.after_import project.import_finish else - logger.error("There was an error during the import: #{tmpfile}") + logger.error("There was an error during the import: #{tmp_file}") end end From cffae0d22ee159b78f66eb68cae9df4bcb9e83e5 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 11 May 2016 14:51:25 +0200 Subject: [PATCH 146/730] fixing more export problems --- app/services/projects/import_export/export_service.rb | 2 +- app/workers/project_export_worker.rb | 3 +-- lib/gitlab/import_export/saver.rb | 10 +++++----- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/app/services/projects/import_export/export_service.rb b/app/services/projects/import_export/export_service.rb index 87a259ed15..e6eb6f915b 100644 --- a/app/services/projects/import_export/export_service.rb +++ b/app/services/projects/import_export/export_service.rb @@ -27,7 +27,7 @@ module Projects end def notify_worker - raise Gitlab::ImportExport::Error @shared.errors.join(', ') + raise Gitlab::ImportExport::Error.new(@shared.errors.join(', ')) end end end diff --git a/app/workers/project_export_worker.rb b/app/workers/project_export_worker.rb index a1add5395b..3616b37d2a 100644 --- a/app/workers/project_export_worker.rb +++ b/app/workers/project_export_worker.rb @@ -1,13 +1,12 @@ class ProjectExportWorker include Sidekiq::Worker - # TODO: enabled retry - disabled for QA purposes + # TODO: enable retry - disabled for QA purposes sidekiq_options queue: :gitlab_shell, retry: false def perform(current_user_id, project_id) current_user = User.find(current_user_id) project = Project.find(project_id) ::Projects::ImportExport::ExportService.new(project, current_user).execute - # TODO : Handle errors end end diff --git a/lib/gitlab/import_export/saver.rb b/lib/gitlab/import_export/saver.rb index 7532c977fc..a2ff43a3ce 100644 --- a/lib/gitlab/import_export/saver.rb +++ b/lib/gitlab/import_export/saver.rb @@ -13,7 +13,7 @@ module Gitlab def save if compress_and_save - remove_storage_path + remove_export_path Rails.logger.info("Saved project export #{archive_file}") archive_file else @@ -27,15 +27,15 @@ module Gitlab private def compress_and_save - tar_czf(archive: archive_file, dir: @shared.storage_path) + tar_czf(archive: archive_file, dir: @shared.export_path) end - def remove_storage_path - FileUtils.rm_rf(@shared.storage_path) + def remove_export_path + FileUtils.rm_rf(@shared.export_path) end def archive_file - @archive_file ||= File.join(@shared.storage_path, '..', "#{Time.now.strftime('%Y-%m-%d_%H-%M-%3N')}_project_export.tar.gz") + @archive_file ||= File.join(@shared.export_path, '..', "#{Time.now.strftime('%Y-%m-%d_%H-%M-%3N')}_project_export.tar.gz") end end end From ae53840723208d34b78dd67f7aedf9c627af4ed1 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 11 May 2016 15:02:55 +0200 Subject: [PATCH 147/730] updated export file for spec --- .../import_export/test_project_export.tar.gz | Bin 322702 -> 338822 bytes 1 file changed, 0 insertions(+), 0 deletions(-) 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 8147c289b8e763d509d35f0293814d92489772f3..f2c3c3cd2dc67ba456501a8ba754edf74cdaba9a 100644 GIT binary patch delta 27434 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 U7zLwX6d(Wq#FC}I0N?@!0IQ$I;s5{u delta 11188 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 Date: Wed, 11 May 2016 17:22:45 +0200 Subject: [PATCH 148/730] refactored import to use shared error stuff and fixed a few issues with recent refactorings --- app/workers/project_import_worker.rb | 1 - .../import_export/import_export_reader.rb | 2 ++ lib/gitlab/import_export/import_service.rb | 19 ++++++++----------- lib/gitlab/import_export/importer.rb | 11 +++++++---- .../import_export/project_tree_restorer.rb | 13 ++++++++----- lib/gitlab/import_export/repo_restorer.rb | 6 ++++-- lib/gitlab/import_export/shared.rb | 2 +- .../project_tree_restorer_spec.rb | 3 ++- 8 files changed, 32 insertions(+), 25 deletions(-) diff --git a/app/workers/project_import_worker.rb b/app/workers/project_import_worker.rb index c6a6d24b4e..b2902c3278 100644 --- a/app/workers/project_import_worker.rb +++ b/app/workers/project_import_worker.rb @@ -13,7 +13,6 @@ class ProjectImportWorker project_path: path) if project project.repository.after_import - project.import_finish else logger.error("There was an error during the import: #{tmp_file}") end diff --git a/lib/gitlab/import_export/import_export_reader.rb b/lib/gitlab/import_export/import_export_reader.rb index b7204d5a87..f637756b35 100644 --- a/lib/gitlab/import_export/import_export_reader.rb +++ b/lib/gitlab/import_export/import_export_reader.rb @@ -2,6 +2,8 @@ module Gitlab module ImportExport class ImportExportReader + attr_reader :tree + def initialize(config: 'lib/gitlab/import_export/import_export.yml', shared:) @shared = shared config_hash = YAML.load_file(config).deep_symbolize_keys diff --git a/lib/gitlab/import_export/import_service.rb b/lib/gitlab/import_export/import_service.rb index 99fb9bad78..f7b66448ab 100644 --- a/lib/gitlab/import_export/import_service.rb +++ b/lib/gitlab/import_export/import_service.rb @@ -10,12 +10,12 @@ module Gitlab @archive_file = archive_file @current_user = owner @namespace = Namespace.find(namespace_id) - @project_path = project_path + @shared = Gitlab::ImportExport::Shared.new(relative_path: path_with_namespace, project_path: project_path) end def execute Gitlab::ImportExport::Importer.import(archive_file: @archive_file, - storage_path: storage_path) + shared: @shared) project_tree.project if [restore_project_tree, restore_repo, restore_wiki_repo].all? end @@ -26,36 +26,33 @@ module Gitlab end def project_tree - @project_tree ||= Gitlab::ImportExport::ProjectTreeRestorer.new(path: storage_path, - user: @current_user, - project_path: @project_path, + @project_tree ||= Gitlab::ImportExport::ProjectTreeRestorer.new(user: @current_user, + shared: @shared, namespace_id: @namespace.id) end def restore_repo Gitlab::ImportExport::RepoRestorer.new(path_to_bundle: repo_path, + shared: @shared, project: project_tree.project).restore end def restore_wiki_repo Gitlab::ImportExport::RepoRestorer.new(path_to_bundle: wiki_repo_path, + shared: @shared, project: ProjectWiki.new(project_tree.project)).restore end - def storage_path - @storage_path ||= Gitlab::ImportExport.export_path(relative_path: path_with_namespace) - end - def path_with_namespace File.join(@namespace.path, @project_path) end def repo_path - File.join(storage_path, 'project.bundle') + File.join(@shared.export_path, 'project.bundle') end def wiki_repo_path - File.join(storage_path, 'project.wiki.bundle') + File.join(@shared.export_path, 'project.wiki.bundle') end end end diff --git a/lib/gitlab/import_export/importer.rb b/lib/gitlab/import_export/importer.rb index 8f838287f9..19c5aafad2 100644 --- a/lib/gitlab/import_export/importer.rb +++ b/lib/gitlab/import_export/importer.rb @@ -7,20 +7,23 @@ module Gitlab new(*args).import end - def initialize(archive_file: , storage_path:) + def initialize(archive_file: , shared:) @archive_file = archive_file - @storage_path = storage_path + @shared = shared end def import - FileUtils.mkdir_p(@storage_path) + FileUtils.mkdir_p(@shared.storage_path) decompress_archive + rescue => e + @shared.error(e.message) + false end private def decompress_archive - untar_zxf(archive: @archive_file, dir: @storage_path) + untar_zxf(archive: @archive_file, dir: @shared.storage_path) end end end diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index ad77f7f69b..06bf86a178 100644 --- a/lib/gitlab/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -2,11 +2,12 @@ module Gitlab module ImportExport class ProjectTreeRestorer - def initialize(path:, user:, project_path:, namespace_id:) - @path = File.join(path, 'project.json') + def initialize(user:, shared:, namespace_id:) + @path = File.join(shared.export_path, 'project.json') @user = user - @project_path = project_path + @project_path = shared.opts[:project_path] @namespace_id = namespace_id + @shared = shared end def restore @@ -15,7 +16,7 @@ module Gitlab @project_members = @tree_hash.delete('project_members') create_relations rescue => e - # TODO: handle errors better, move them to a shared thing + @shared.error(e.message) false end @@ -44,7 +45,9 @@ module Gitlab end def default_relation_list - Gitlab::ImportExport::ImportExportReader.tree.reject { |model| model.is_a?(Hash) && model[:project_members] } + Gitlab::ImportExport::ImportExportReader.new(shared: @shared).tree.reject do |model| + model.is_a?(Hash) && model[:project_members] + end end def create_project diff --git a/lib/gitlab/import_export/repo_restorer.rb b/lib/gitlab/import_export/repo_restorer.rb index 7a4cda828b..3909d44744 100644 --- a/lib/gitlab/import_export/repo_restorer.rb +++ b/lib/gitlab/import_export/repo_restorer.rb @@ -3,9 +3,10 @@ module Gitlab class RepoRestorer include Gitlab::ImportExport::CommandLineUtil - def initialize(project:, path_to_bundle:) + def initialize(project:, shared:, path_to_bundle:) @project = project @path_to_bundle = path_to_bundle + @shared = shared end def restore @@ -15,7 +16,8 @@ module Gitlab FileUtils.mkdir_p(path_to_repo) git_unbundle(repo_path: path_to_repo, bundle_path: @path_to_bundle) - rescue + rescue => e + @shared.error(e.message) false end diff --git a/lib/gitlab/import_export/shared.rb b/lib/gitlab/import_export/shared.rb index 4246f73af9..050b0428f4 100644 --- a/lib/gitlab/import_export/shared.rb +++ b/lib/gitlab/import_export/shared.rb @@ -2,7 +2,7 @@ module Gitlab module ImportExport class Shared - attr_reader :errors + attr_reader :errors, :opts def initialize(opts) @opts = opts 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 0958365ff9..7c6a14fc8a 100644 --- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb @@ -5,7 +5,8 @@ describe Gitlab::ImportExport::ProjectTreeRestorer, services: true do let(:user) { create(:user) } let(:namespace) { create(:namespace, owner: user) } - let(:project_tree_restorer) { described_class.new(path: Rails.root.join("spec/lib/gitlab/import_export/"), user: user, project_path: 'project', namespace_id: namespace.id) } + let(:shared) { Gitlab::ImportExport::Shared.new(relative_path: "../../../spec/lib/gitlab/import_export/", project_path: 'path') } + let(:project_tree_restorer) { described_class.new(user: user, shared: shared, namespace_id: namespace.id) } context 'JSON' do let(:restored_project_json) do From 385d6df20c7f3a40b40016d5413b50690ce9a48b Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 12 May 2016 10:39:59 +0200 Subject: [PATCH 149/730] typo --- lib/gitlab/import_export/import_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gitlab/import_export/import_service.rb b/lib/gitlab/import_export/import_service.rb index f7b66448ab..ea9ba9e7b4 100644 --- a/lib/gitlab/import_export/import_service.rb +++ b/lib/gitlab/import_export/import_service.rb @@ -44,7 +44,7 @@ module Gitlab end def path_with_namespace - File.join(@namespace.path, @project_path) + File.join(@namespace.path, @shared.opts[:project_path]) end def repo_path From f06c5516db2c4b1df480545d11f177838abeb00d Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 12 May 2016 10:57:28 +0200 Subject: [PATCH 150/730] fix issue in import_service --- lib/gitlab/import_export/import_service.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/gitlab/import_export/import_service.rb b/lib/gitlab/import_export/import_service.rb index ea9ba9e7b4..670f1ebece 100644 --- a/lib/gitlab/import_export/import_service.rb +++ b/lib/gitlab/import_export/import_service.rb @@ -10,7 +10,7 @@ module Gitlab @archive_file = archive_file @current_user = owner @namespace = Namespace.find(namespace_id) - @shared = Gitlab::ImportExport::Shared.new(relative_path: path_with_namespace, project_path: project_path) + @shared = Gitlab::ImportExport::Shared.new(relative_path: path_with_namespace(project_path), project_path: project_path) end def execute @@ -43,8 +43,8 @@ module Gitlab project: ProjectWiki.new(project_tree.project)).restore end - def path_with_namespace - File.join(@namespace.path, @shared.opts[:project_path]) + def path_with_namespace(project_path) + File.join(@namespace.path, project_path) end def repo_path From ff56f7be62a94f336e4cb3382ca983cf5e2c5e54 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 12 May 2016 11:03:55 +0200 Subject: [PATCH 151/730] fix importer issue --- lib/gitlab/import_export/importer.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/import_export/importer.rb b/lib/gitlab/import_export/importer.rb index 19c5aafad2..20a93f7f6d 100644 --- a/lib/gitlab/import_export/importer.rb +++ b/lib/gitlab/import_export/importer.rb @@ -13,7 +13,7 @@ module Gitlab end def import - FileUtils.mkdir_p(@shared.storage_path) + FileUtils.mkdir_p(@shared.export_path) decompress_archive rescue => e @shared.error(e.message) @@ -23,7 +23,7 @@ module Gitlab private def decompress_archive - untar_zxf(archive: @archive_file, dir: @shared.storage_path) + untar_zxf(archive: @archive_file, dir: @shared.export_path) end end end From b2b7b38c944436af5257b1b38d612aeb3d2f237e Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 12 May 2016 11:29:06 +0200 Subject: [PATCH 152/730] fix rubocop warnings --- lib/gitlab/import_export/error.rb | 2 +- lib/gitlab/import_export/import_export_reader.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/import_export/error.rb b/lib/gitlab/import_export/error.rb index b47a646c0b..e341c4d9cf 100644 --- a/lib/gitlab/import_export/error.rb +++ b/lib/gitlab/import_export/error.rb @@ -2,4 +2,4 @@ module Gitlab module ImportExport class Error < StandardError; end end -end \ No newline at end of file +end diff --git a/lib/gitlab/import_export/import_export_reader.rb b/lib/gitlab/import_export/import_export_reader.rb index b7204d5a87..a8b6294662 100644 --- a/lib/gitlab/import_export/import_export_reader.rb +++ b/lib/gitlab/import_export/import_export_reader.rb @@ -53,7 +53,7 @@ module Gitlab parsed_hash = { include: value } @attributes_parser.parse(value) do |hash| - parsed_hash = { include: hash_or_merge(value, hash) } + parsed_hash = { include: hash_or_merge(value, hash) } end @json_config_hash[current_key] = parsed_hash end From 8165e52045711958abbb94ee9ea2c00056ccadda Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 12 May 2016 14:27:41 +0200 Subject: [PATCH 153/730] add author on notes to export - so we can add to a note if project member is not found --- lib/gitlab/import_export/import_export.yml | 8 ++++++-- lib/gitlab/import_export/import_export_reader.rb | 12 ++++++++++++ .../gitlab/import_export/project_tree_saver_spec.rb | 7 +++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml index 36128909df..66e6ae86cf 100644 --- a/lib/gitlab/import_export/import_export.yml +++ b/lib/gitlab/import_export/import_export.yml @@ -1,7 +1,8 @@ # Model relationships to be included in the project import/export project_tree: - issues: - - :notes + - notes: + :author - :labels - :milestones - :snippets @@ -10,8 +11,9 @@ project_tree: - project_members: - :user - merge_requests: + - notes: + :author - :merge_request_diff - - :notes - ci_commits: - :statuses @@ -31,6 +33,8 @@ included_attributes: - :id - :email - :username + author: + - :name # Do not include the following attributes for the models specified. excluded_attributes: diff --git a/lib/gitlab/import_export/import_export_reader.rb b/lib/gitlab/import_export/import_export_reader.rb index a8b6294662..9aac0eae79 100644 --- a/lib/gitlab/import_export/import_export_reader.rb +++ b/lib/gitlab/import_export/import_export_reader.rb @@ -37,10 +37,22 @@ module Gitlab @attributes_parser.parse(current_key) { |hash| @json_config_hash[current_key] ||= hash } handle_model_object(current_key, model_object) + process_sub_model(current_key, model_object) if model_object.is_a?(Hash) end @json_config_hash end + def process_sub_model(current_key, model_object) + sub_model_json = build_json_config_hash(model_object).dup + @json_config_hash.slice!(current_key) + + if @json_config_hash[current_key] && @json_config_hash[current_key][:include] + @json_config_hash[current_key][:include] << sub_model_json + else + @json_config_hash[current_key] = { include: sub_model_json } + end + end + def handle_model_object(current_key, model_object) if @json_config_hash[current_key] add_model_value(current_key, model_object) 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 67e6267b74..b9cf88d3f7 100644 --- a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb @@ -65,6 +65,10 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do expect(saved_project_json['issues'].first['notes']).not_to be_empty end + it 'has author on issue comments' do + expect(saved_project_json['issues'].first['notes'].first['author']).not_to be_empty + end + it 'has project members' do expect(saved_project_json['project_members']).not_to be_empty end @@ -77,6 +81,9 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do expect(saved_project_json['merge_requests'].first['notes']).not_to be_empty end + it 'has author on merge requests comments' do + expect(saved_project_json['merge_requests'].first['notes'].first['author']).not_to be_empty + end it 'has commit statuses' do expect(saved_project_json['ci_commits'].first['statuses']).not_to be_empty end From 25a1c6541aa3dfb41ef006d42ba280d5a1d4103d Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 13 May 2016 12:33:13 +0200 Subject: [PATCH 154/730] add message to notes about missing author on import --- .../import_export/import_export_reader.rb | 2 +- lib/gitlab/import_export/importer.rb | 2 +- lib/gitlab/import_export/members_mapper.rb | 19 +++++++++----- .../import_export/project_tree_restorer.rb | 26 ++++++++++++------- .../import_export/project_tree_saver.rb | 2 +- lib/gitlab/import_export/relation_factory.rb | 20 ++++++++++++-- lib/gitlab/import_export/repo_bundler.rb | 2 +- lib/gitlab/import_export/repo_restorer.rb | 2 +- lib/gitlab/import_export/saver.rb | 2 +- lib/gitlab/import_export/shared.rb | 8 +++--- lib/gitlab/import_export/wiki_repo_bundler.rb | 2 +- .../import_export/members_mapper_spec.rb | 8 +++--- .../project_tree_restorer_spec.rb | 5 +--- 13 files changed, 65 insertions(+), 35 deletions(-) diff --git a/lib/gitlab/import_export/import_export_reader.rb b/lib/gitlab/import_export/import_export_reader.rb index 5d218320e2..11a736ecab 100644 --- a/lib/gitlab/import_export/import_export_reader.rb +++ b/lib/gitlab/import_export/import_export_reader.rb @@ -15,7 +15,7 @@ module Gitlab def project_tree @attributes_parser.find_included(:project).merge(include: build_hash(@tree)) rescue => e - @shared.error(e.message) + @shared.error(e) end private diff --git a/lib/gitlab/import_export/importer.rb b/lib/gitlab/import_export/importer.rb index 20a93f7f6d..d73ce43b49 100644 --- a/lib/gitlab/import_export/importer.rb +++ b/lib/gitlab/import_export/importer.rb @@ -16,7 +16,7 @@ module Gitlab FileUtils.mkdir_p(@shared.export_path) decompress_archive rescue => e - @shared.error(e.message) + @shared.error(e) false end diff --git a/lib/gitlab/import_export/members_mapper.rb b/lib/gitlab/import_export/members_mapper.rb index d6124106f5..da8aa47565 100644 --- a/lib/gitlab/import_export/members_mapper.rb +++ b/lib/gitlab/import_export/members_mapper.rb @@ -2,18 +2,25 @@ module Gitlab module ImportExport class MembersMapper - def self.map(*args) - new(*args).map - end + attr_reader :map, :note_member_list def initialize(exported_members:, user:, project_id:) @exported_members = exported_members @user = user @project_id = project_id + @note_member_list = [] + + @project_member_map = Hash.new do |_, key| + @note_member_list << key + default_project_member + end + + @map = generate_map end - def map - @project_member_map = Hash.new(default_project_member) + private + + def generate_map @exported_members.each do |member| existing_user = User.where(find_project_user_query(member)).first assign_member(existing_user, member) if existing_user @@ -21,8 +28,6 @@ module Gitlab @project_member_map end - private - def assign_member(existing_user, member) old_user_id = member['user']['id'] member['user'] = existing_user diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index 06bf86a178..a840c9f947 100644 --- a/lib/gitlab/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -16,7 +16,7 @@ module Gitlab @project_members = @tree_hash.delete('project_members') create_relations rescue => e - @shared.error(e.message) + @shared.error(e) false end @@ -26,9 +26,10 @@ module Gitlab private - def members_map - @members ||= Gitlab::ImportExport::MembersMapper.map( - exported_members: @project_members, user: @user, project_id: project.id) + def members_mapper + @members_mapper ||= Gitlab::ImportExport::MembersMapper.new(exported_members: @project_members, + user: @user, + project_id: project.id) end def create_relations(relation_list = default_relation_list, tree_hash = @tree_hash) @@ -61,11 +62,18 @@ module Gitlab end def create_sub_relations(relation, tree_hash) - tree_hash[relation.keys.first.to_s].each do |relation_item| + relation_key = relation.keys.first.to_s + tree_hash[relation_key].each do |relation_item| relation.values.flatten.each do |sub_relation| - relation_hash = relation_item[sub_relation.to_s] - next if relation_hash.blank? - process_sub_relation(relation_hash, relation_item, sub_relation) + + if sub_relation.is_a?(Hash) + relation_hash = relation_item[sub_relation.keys.first.to_s] + sub_relation = sub_relation.keys.first + else + relation_hash = relation_item[sub_relation.to_s] + end + + process_sub_relation(relation_hash, relation_item, sub_relation) unless relation_hash.blank? end end end @@ -87,7 +95,7 @@ module Gitlab def relation_from_factory(relation, relation_hash) Gitlab::ImportExport::RelationFactory.create( - relation_sym: relation.to_sym, relation_hash: relation_hash.merge('project_id' => project.id), members_map: members_map) + relation_sym: relation.to_sym, relation_hash: relation_hash.merge('project_id' => project.id), members_mapper: members_mapper) end end end diff --git a/lib/gitlab/import_export/project_tree_saver.rb b/lib/gitlab/import_export/project_tree_saver.rb index 2287524c8a..ed8ca31d93 100644 --- a/lib/gitlab/import_export/project_tree_saver.rb +++ b/lib/gitlab/import_export/project_tree_saver.rb @@ -14,7 +14,7 @@ module Gitlab File.write(full_path, project_json_tree) true rescue => e - @shared.error(e.message) + @shared.error(e) false end diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb index dd992ef443..65e2a935fa 100644 --- a/lib/gitlab/import_export/relation_factory.rb +++ b/lib/gitlab/import_export/relation_factory.rb @@ -6,11 +6,12 @@ module Gitlab OVERRIDES = { snippets: :project_snippets, ci_commits: 'Ci::Commit', statuses: 'commit_status' }.freeze USER_REFERENCES = %w(author_id assignee_id updated_by_id).freeze - def create(relation_sym:, relation_hash:, members_map:) + def create(relation_sym:, relation_hash:, members_mapper:) relation_sym = parse_relation_sym(relation_sym) klass = parse_relation(relation_hash, relation_sym) - update_user_references(relation_hash, members_map) + update_missing_author(relation_hash, members_mapper) if relation_sym == :notes + update_user_references(relation_hash, members_mapper.map) update_project_references(relation_hash, klass) imported_object(klass, relation_hash) @@ -26,6 +27,21 @@ module Gitlab end end + def update_missing_author(relation_hash, members_map) + old_author_id = relation_hash['author_id'].dup + relation_hash['author_id'] = members_map.map[old_author_id] + return unless members_map.note_member_list.include?(old_author_id) + + relation_hash['note'] = ('*Blank note*') if relation_hash['note'].blank? + relation_hash['note'].join(missing_author_note(relation_hash['updated_at'], + relation_hash['author']['name'])) + relation_hash.delete('author') + end + + def missing_author_note(updated_at, author_name) + "\n\n *By #{author_name} on #{updated_at} (imported from GitLab project)*" + end + def update_project_references(relation_hash, klass) project_id = relation_hash.delete('project_id') diff --git a/lib/gitlab/import_export/repo_bundler.rb b/lib/gitlab/import_export/repo_bundler.rb index bcf976fb62..af809f4c38 100644 --- a/lib/gitlab/import_export/repo_bundler.rb +++ b/lib/gitlab/import_export/repo_bundler.rb @@ -22,7 +22,7 @@ module Gitlab FileUtils.mkdir_p(@shared.export_path) git_bundle(repo_path: path_to_repo, bundle_path: @full_path) rescue => e - @shared.error(e.message) + @shared.error(e) false end diff --git a/lib/gitlab/import_export/repo_restorer.rb b/lib/gitlab/import_export/repo_restorer.rb index 3909d44744..36094b95aa 100644 --- a/lib/gitlab/import_export/repo_restorer.rb +++ b/lib/gitlab/import_export/repo_restorer.rb @@ -17,7 +17,7 @@ module Gitlab git_unbundle(repo_path: path_to_repo, bundle_path: @path_to_bundle) rescue => e - @shared.error(e.message) + @shared.error(e) false end diff --git a/lib/gitlab/import_export/saver.rb b/lib/gitlab/import_export/saver.rb index a2ff43a3ce..f38229c6c5 100644 --- a/lib/gitlab/import_export/saver.rb +++ b/lib/gitlab/import_export/saver.rb @@ -20,7 +20,7 @@ module Gitlab false end rescue => e - @shared.error(e.message) + @shared.error(e) false end diff --git a/lib/gitlab/import_export/shared.rb b/lib/gitlab/import_export/shared.rb index 050b0428f4..01ac332981 100644 --- a/lib/gitlab/import_export/shared.rb +++ b/lib/gitlab/import_export/shared.rb @@ -13,9 +13,11 @@ module Gitlab @export_path ||= Gitlab::ImportExport.export_path(relative_path: @opts[:relative_path]) end - def error(message) - error_out(message, caller[0].dup) - @errors << message + def error(error) + error_out(error.message, caller[0].dup) + @errors << error.message + # Debug: + Rails.logger.error(error.backtrace) end private diff --git a/lib/gitlab/import_export/wiki_repo_bundler.rb b/lib/gitlab/import_export/wiki_repo_bundler.rb index a0000176bb..e1e7f75372 100644 --- a/lib/gitlab/import_export/wiki_repo_bundler.rb +++ b/lib/gitlab/import_export/wiki_repo_bundler.rb @@ -12,7 +12,7 @@ module Gitlab FileUtils.mkdir_p(@shared.export_path) git_bundle(repo_path: path_to_repo, bundle_path: @full_path) rescue => e - @shared.error(e.message) + @shared.error(e) false end diff --git a/spec/lib/gitlab/import_export/members_mapper_spec.rb b/spec/lib/gitlab/import_export/members_mapper_spec.rb index a4d3d6d122..78706f64fb 100644 --- a/spec/lib/gitlab/import_export/members_mapper_spec.rb +++ b/spec/lib/gitlab/import_export/members_mapper_spec.rb @@ -42,9 +42,11 @@ describe Gitlab::ImportExport::MembersMapper, services: true do it 'defaults to importer project member if it does not exist' do expect(members_mapper.map[-1]).to eq(user.id) end - end - def project_member_user_id(id) - members_mapper.map[id] + it 'updates missing author IDs on missing project member' do + members_mapper.map[-1] + + expect(members_mapper.note_member_list.first).to eq(-1) + end end end 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 7c6a14fc8a..6464b0141f 100644 --- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb @@ -7,12 +7,9 @@ describe Gitlab::ImportExport::ProjectTreeRestorer, services: true do let(:namespace) { create(:namespace, owner: user) } let(:shared) { Gitlab::ImportExport::Shared.new(relative_path: "../../../spec/lib/gitlab/import_export/", project_path: 'path') } let(:project_tree_restorer) { described_class.new(user: user, shared: shared, namespace_id: namespace.id) } + let!(:restored_project_json) { project_tree_restorer.restore } context 'JSON' do - let(:restored_project_json) do - project_tree_restorer.restore - end - it 'restores models based on JSON' do expect(restored_project_json).to be true end From a86825826915f78a0728becd91f6a31df90543ea Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 13 May 2016 14:17:10 +0200 Subject: [PATCH 155/730] update json and fix notes issue --- lib/gitlab/import_export/relation_factory.rb | 4 +- spec/lib/gitlab/import_export/project.json | 5375 +++++++++++++++++- 2 files changed, 5220 insertions(+), 159 deletions(-) diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb index 65e2a935fa..0adcd0d5e6 100644 --- a/lib/gitlab/import_export/relation_factory.rb +++ b/lib/gitlab/import_export/relation_factory.rb @@ -28,12 +28,12 @@ module Gitlab end def update_missing_author(relation_hash, members_map) - old_author_id = relation_hash['author_id'].dup + old_author_id = relation_hash['author_id'] relation_hash['author_id'] = members_map.map[old_author_id] return unless members_map.note_member_list.include?(old_author_id) relation_hash['note'] = ('*Blank note*') if relation_hash['note'].blank? - relation_hash['note'].join(missing_author_note(relation_hash['updated_at'], + relation_hash['note'] += (missing_author_note(relation_hash['updated_at'], relation_hash['author']['name'])) relation_hash.delete('author') end diff --git a/spec/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json index 8b6a16c049..31851c4c64 100644 --- a/spec/lib/gitlab/import_export/project.json +++ b/spec/lib/gitlab/import_export/project.json @@ -1,203 +1,2689 @@ { - "name": "searchable_project", - "path": "gitlabhq", - "description": null, + "name": "Gitlab Test", + "path": "gitlab-test", + "description": "Aut saepe in eos dolorem aliquam hic.", "issues_enabled": true, "merge_requests_enabled": true, "wiki_enabled": true, - "snippets_enabled": true, + "snippets_enabled": false, "visibility_level": 20, "archived": false, "issues": [ { - "id": 1, - "title": "Debitis vero omnis cum accusamus nihil rerum cupiditate.", + "id": 40, + "title": "Voluptatem modi rerum ipsum vero voluptas repudiandae veniam quibusdam.", "assignee_id": 1, - "author_id": 2, - "project_id": 6, - "created_at": "2016-04-13T14:40:32.471Z", - "updated_at": "2016-04-13T14:40:38.956Z", + "author_id": 4, + "project_id": 5, + "created_at": "2016-03-22T15:13:28.411Z", + "updated_at": "2016-04-12T13:08:26.029Z", "position": 0, "branch_name": null, - "description": null, - "milestone_id": null, + "description": "Aut minima non sit qui nulla rerum laborum.", + "milestone_id": 10, "state": "opened", - "iid": 1, + "iid": 10, "updated_by_id": null, "confidential": false, "deleted_at": null, "moved_to_id": null, + "due_date": null, "notes": [ { - "id": 1, - "note": ":+1: issue", + "id": 1357, + "note": "test", "noteable_type": "Issue", - "author_id": 21, - "created_at": "2016-04-13T14:40:38.944Z", - "updated_at": "2016-04-13T14:40:38.944Z", - "project_id": 8, + "author_id": 1, + "created_at": "2016-04-12T13:08:26.006Z", + "updated_at": "2016-04-12T13:08:26.006Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": "", + "noteable_id": 40, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Administrator" + } + }, + { + "id": 338, + "note": "Fugit in aliquid voluptas dolor.", + "noteable_type": "Issue", + "author_id": 1, + "created_at": "2016-03-22T15:19:59.213Z", + "updated_at": "2016-03-22T15:19:59.213Z", + "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 1, + "noteable_id": 40, "system": false, "st_diff": null, "updated_by_id": null, - "is_award": false + "is_award": false, + "author": { + "name": "Administrator" + } + }, + { + "id": 337, + "note": "Occaecati consequatur facilis doloribus omnis hic placeat nihil.", + "noteable_type": "Issue", + "author_id": 3, + "created_at": "2016-03-22T15:19:59.186Z", + "updated_at": "2016-03-22T15:19:59.186Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 40, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Alexie Trantow" + } + }, + { + "id": 336, + "note": "Nostrum et et est repudiandae non dolores voluptatem.", + "noteable_type": "Issue", + "author_id": 4, + "created_at": "2016-03-22T15:19:59.156Z", + "updated_at": "2016-03-22T15:19:59.156Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 40, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Julius Moore" + } + }, + { + "id": 335, + "note": "Nihil et aut dolorum aut sit maxime.", + "noteable_type": "Issue", + "author_id": 10, + "created_at": "2016-03-22T15:19:59.130Z", + "updated_at": "2016-03-22T15:19:59.130Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 40, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Robyn McCullough Jr." + } + }, + { + "id": 334, + "note": "Non blanditiis voluptatem sit earum accusantium distinctio voluptas officiis.", + "noteable_type": "Issue", + "author_id": 12, + "created_at": "2016-03-22T15:19:59.101Z", + "updated_at": "2016-03-22T15:19:59.101Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 40, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Vladimir McCullough" + } + }, + { + "id": 333, + "note": "Nesciunt non dolorem similique nam ipsa et.", + "noteable_type": "Issue", + "author_id": 22, + "created_at": "2016-03-22T15:19:59.075Z", + "updated_at": "2016-03-22T15:19:59.075Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 40, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 0" + } + }, + { + "id": 332, + "note": "Sed aut fugit et officiis dolor.", + "noteable_type": "Issue", + "author_id": 24, + "created_at": "2016-03-22T15:19:59.047Z", + "updated_at": "2016-03-22T15:19:59.047Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 40, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 2" + } + }, + { + "id": 331, + "note": "Officiis iste eum recusandae suscipit consequatur consequatur.", + "noteable_type": "Issue", + "author_id": 26, + "created_at": "2016-03-22T15:19:59.015Z", + "updated_at": "2016-03-22T15:19:59.015Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 40, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 4" + } + } + ] + }, + { + "id": 39, + "title": "Sit ut adipisci sint temporibus velit quis.", + "assignee_id": 1, + "author_id": 12, + "project_id": 5, + "created_at": "2016-03-22T15:13:28.278Z", + "updated_at": "2016-03-22T15:19:59.473Z", + "position": 0, + "branch_name": null, + "description": "Ab sint nostrum aliquam laudantium magni recusandae qui.", + "milestone_id": 10, + "state": "closed", + "iid": 9, + "updated_by_id": null, + "confidential": false, + "deleted_at": null, + "moved_to_id": null, + "due_date": null, + "notes": [ + { + "id": 346, + "note": "Natus rerum qui dolorem dolorum voluptas.", + "noteable_type": "Issue", + "author_id": 1, + "created_at": "2016-03-22T15:19:59.469Z", + "updated_at": "2016-03-22T15:19:59.469Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 39, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Administrator" + } + }, + { + "id": 345, + "note": "Voluptatibus et qui quis id sed necessitatibus quos.", + "noteable_type": "Issue", + "author_id": 3, + "created_at": "2016-03-22T15:19:59.438Z", + "updated_at": "2016-03-22T15:19:59.438Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 39, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Alexie Trantow" + } + }, + { + "id": 344, + "note": "Aperiam possimus ipsam quibusdam in.", + "noteable_type": "Issue", + "author_id": 4, + "created_at": "2016-03-22T15:19:59.410Z", + "updated_at": "2016-03-22T15:19:59.410Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 39, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Julius Moore" + } + }, + { + "id": 343, + "note": "Ad vel hic molestiae tempora.", + "noteable_type": "Issue", + "author_id": 10, + "created_at": "2016-03-22T15:19:59.379Z", + "updated_at": "2016-03-22T15:19:59.379Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 39, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Robyn McCullough Jr." + } + }, + { + "id": 342, + "note": "Vel magnam sed quidem aut molestiae facilis alias.", + "noteable_type": "Issue", + "author_id": 12, + "created_at": "2016-03-22T15:19:59.348Z", + "updated_at": "2016-03-22T15:19:59.348Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 39, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Vladimir McCullough" + } + }, + { + "id": 341, + "note": "Veritatis dolorum aut qui quod.", + "noteable_type": "Issue", + "author_id": 22, + "created_at": "2016-03-22T15:19:59.319Z", + "updated_at": "2016-03-22T15:19:59.319Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 39, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 0" + } + }, + { + "id": 340, + "note": "Illum at cumque dolorum et quia.", + "noteable_type": "Issue", + "author_id": 24, + "created_at": "2016-03-22T15:19:59.289Z", + "updated_at": "2016-03-22T15:19:59.289Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 39, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 2" + } + }, + { + "id": 339, + "note": "Fugiat et error molestiae cumque quos aperiam.", + "noteable_type": "Issue", + "author_id": 26, + "created_at": "2016-03-22T15:19:59.255Z", + "updated_at": "2016-03-22T15:19:59.255Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 39, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 4" + } + } + ] + }, + { + "id": 38, + "title": "Quod quo est quis vel natus nulla eos reiciendis.", + "assignee_id": 12, + "author_id": 3, + "project_id": 5, + "created_at": "2016-03-22T15:13:28.137Z", + "updated_at": "2016-03-22T15:19:59.712Z", + "position": 0, + "branch_name": null, + "description": "Fugit dolor accusantium suscipit facere voluptate.", + "milestone_id": 10, + "state": "opened", + "iid": 8, + "updated_by_id": null, + "confidential": false, + "deleted_at": null, + "moved_to_id": null, + "due_date": null, + "notes": [ + { + "id": 354, + "note": "Id commodi natus vel corrupti ea placeat cum nihil.", + "noteable_type": "Issue", + "author_id": 1, + "created_at": "2016-03-22T15:19:59.708Z", + "updated_at": "2016-03-22T15:19:59.708Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 38, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Administrator" + } + }, + { + "id": 353, + "note": "Quia hic sed ratione eos voluptate dolor occaecati dolorem.", + "noteable_type": "Issue", + "author_id": 3, + "created_at": "2016-03-22T15:19:59.680Z", + "updated_at": "2016-03-22T15:19:59.680Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 38, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Alexie Trantow" + } + }, + { + "id": 352, + "note": "Commodi sint voluptatem est aut.", + "noteable_type": "Issue", + "author_id": 4, + "created_at": "2016-03-22T15:19:59.650Z", + "updated_at": "2016-03-22T15:19:59.650Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 38, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Julius Moore" + } + }, + { + "id": 351, + "note": "Et quibusdam voluptatibus dolores aut quam architecto optio.", + "noteable_type": "Issue", + "author_id": 10, + "created_at": "2016-03-22T15:19:59.622Z", + "updated_at": "2016-03-22T15:19:59.622Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 38, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Robyn McCullough Jr." + } + }, + { + "id": 350, + "note": "Fugit natus explicabo sed pariatur et quasi autem.", + "noteable_type": "Issue", + "author_id": 12, + "created_at": "2016-03-22T15:19:59.590Z", + "updated_at": "2016-03-22T15:19:59.590Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 38, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Vladimir McCullough" + } + }, + { + "id": 349, + "note": "Corporis commodi eos quia optio sunt corrupti.", + "noteable_type": "Issue", + "author_id": 22, + "created_at": "2016-03-22T15:19:59.562Z", + "updated_at": "2016-03-22T15:19:59.562Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 38, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 0" + } + }, + { + "id": 348, + "note": "Occaecati nostrum hic dolor tenetur aliquid maxime animi.", + "noteable_type": "Issue", + "author_id": 24, + "created_at": "2016-03-22T15:19:59.536Z", + "updated_at": "2016-03-22T15:19:59.536Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 38, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 2" + } + }, + { + "id": 347, + "note": "Inventore ullam sed repellendus laudantium itaque et quia.", + "noteable_type": "Issue", + "author_id": 26, + "created_at": "2016-03-22T15:19:59.506Z", + "updated_at": "2016-03-22T15:19:59.506Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 38, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 4" + } + } + ] + }, + { + "id": 37, + "title": "Animi suscipit quia ut hic asperiores perferendis nisi ut.", + "assignee_id": 22, + "author_id": 10, + "project_id": 5, + "created_at": "2016-03-22T15:13:27.994Z", + "updated_at": "2016-03-22T15:19:59.972Z", + "position": 0, + "branch_name": null, + "description": "Non quibusdam in maxime earum eveniet itaque culpa.", + "milestone_id": 11, + "state": "closed", + "iid": 7, + "updated_by_id": null, + "confidential": false, + "deleted_at": null, + "moved_to_id": null, + "due_date": null, + "notes": [ + { + "id": 362, + "note": "Quia qui quis molestiae in praesentium.", + "noteable_type": "Issue", + "author_id": 1, + "created_at": "2016-03-22T15:19:59.966Z", + "updated_at": "2016-03-22T15:19:59.966Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 37, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Administrator" + } + }, + { + "id": 361, + "note": "Maxime sed eius qui consequatur beatae.", + "noteable_type": "Issue", + "author_id": 3, + "created_at": "2016-03-22T15:19:59.924Z", + "updated_at": "2016-03-22T15:19:59.924Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 37, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Alexie Trantow" + } + }, + { + "id": 360, + "note": "Voluptatum quasi corrupti eveniet sed ut quis quibusdam.", + "noteable_type": "Issue", + "author_id": 4, + "created_at": "2016-03-22T15:19:59.897Z", + "updated_at": "2016-03-22T15:19:59.897Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 37, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Julius Moore" + } + }, + { + "id": 359, + "note": "Molestias quia eius ipsum non.", + "noteable_type": "Issue", + "author_id": 10, + "created_at": "2016-03-22T15:19:59.866Z", + "updated_at": "2016-03-22T15:19:59.866Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 37, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Robyn McCullough Jr." + } + }, + { + "id": 358, + "note": "Aut non est accusantium aliquam.", + "noteable_type": "Issue", + "author_id": 12, + "created_at": "2016-03-22T15:19:59.834Z", + "updated_at": "2016-03-22T15:19:59.834Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 37, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Vladimir McCullough" + } + }, + { + "id": 357, + "note": "Aspernatur voluptas id voluptas vel cum ipsam.", + "noteable_type": "Issue", + "author_id": 22, + "created_at": "2016-03-22T15:19:59.805Z", + "updated_at": "2016-03-22T15:19:59.805Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 37, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 0" + } + }, + { + "id": 356, + "note": "Harum dignissimos provident tempora sit numquam est qui.", + "noteable_type": "Issue", + "author_id": 24, + "created_at": "2016-03-22T15:19:59.773Z", + "updated_at": "2016-03-22T15:19:59.773Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 37, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 2" + } + }, + { + "id": 355, + "note": "Sint dignissimos molestiae recusandae delectus.", + "noteable_type": "Issue", + "author_id": 26, + "created_at": "2016-03-22T15:19:59.746Z", + "updated_at": "2016-03-22T15:19:59.746Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 37, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 4" + } + } + ] + }, + { + "id": 36, + "title": "Quia dolores commodi eligendi ut nemo totam.", + "assignee_id": 3, + "author_id": 4, + "project_id": 5, + "created_at": "2016-03-22T15:13:27.814Z", + "updated_at": "2016-03-22T15:20:00.371Z", + "position": 0, + "branch_name": null, + "description": "Molestiae veniam laudantium autem et natus.", + "milestone_id": 11, + "state": "opened", + "iid": 6, + "updated_by_id": null, + "confidential": false, + "deleted_at": null, + "moved_to_id": null, + "due_date": null, + "notes": [ + { + "id": 370, + "note": "Occaecati temporibus tempore harum vero incidunt veniam iste.", + "noteable_type": "Issue", + "author_id": 1, + "created_at": "2016-03-22T15:20:00.365Z", + "updated_at": "2016-03-22T15:20:00.365Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 36, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Administrator" + } + }, + { + "id": 369, + "note": "Modi architecto officiis quia iste voluptas libero nihil quo.", + "noteable_type": "Issue", + "author_id": 3, + "created_at": "2016-03-22T15:20:00.331Z", + "updated_at": "2016-03-22T15:20:00.331Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 36, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Alexie Trantow" + } + }, + { + "id": 368, + "note": "Eaque est tenetur ex est molestiae nobis.", + "noteable_type": "Issue", + "author_id": 4, + "created_at": "2016-03-22T15:20:00.296Z", + "updated_at": "2016-03-22T15:20:00.296Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 36, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Julius Moore" + } + }, + { + "id": 367, + "note": "Odit enim ut a quo qui.", + "noteable_type": "Issue", + "author_id": 10, + "created_at": "2016-03-22T15:20:00.261Z", + "updated_at": "2016-03-22T15:20:00.261Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 36, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Robyn McCullough Jr." + } + }, + { + "id": 366, + "note": "Omnis unde cum officiis est.", + "noteable_type": "Issue", + "author_id": 12, + "created_at": "2016-03-22T15:20:00.223Z", + "updated_at": "2016-03-22T15:20:00.223Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 36, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Vladimir McCullough" + } + }, + { + "id": 365, + "note": "Ab consequuntur aliquam illo voluptatum.", + "noteable_type": "Issue", + "author_id": 22, + "created_at": "2016-03-22T15:20:00.178Z", + "updated_at": "2016-03-22T15:20:00.178Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 36, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 0" + } + }, + { + "id": 364, + "note": "Molestiae dolorem est eos dolores aut.", + "noteable_type": "Issue", + "author_id": 24, + "created_at": "2016-03-22T15:20:00.127Z", + "updated_at": "2016-03-22T15:20:00.127Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 36, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 2" + } + }, + { + "id": 363, + "note": "Nemo velit nam quod veniam.", + "noteable_type": "Issue", + "author_id": 26, + "created_at": "2016-03-22T15:20:00.083Z", + "updated_at": "2016-03-22T15:20:00.083Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 36, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 4" + } + } + ] + }, + { + "id": 35, + "title": "Rerum tenetur harum molestiae quam aut praesentium quaerat doloremque.", + "assignee_id": 4, + "author_id": 1, + "project_id": 5, + "created_at": "2016-03-22T15:13:27.660Z", + "updated_at": "2016-03-22T15:20:00.665Z", + "position": 0, + "branch_name": null, + "description": "Omnis et voluptatibus expedita qui et explicabo rem ut.", + "milestone_id": 11, + "state": "opened", + "iid": 5, + "updated_by_id": null, + "confidential": false, + "deleted_at": null, + "moved_to_id": null, + "due_date": null, + "notes": [ + { + "id": 378, + "note": "Molestiae atque exercitationem culpa harum nemo.", + "noteable_type": "Issue", + "author_id": 1, + "created_at": "2016-03-22T15:20:00.660Z", + "updated_at": "2016-03-22T15:20:00.660Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 35, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Administrator" + } + }, + { + "id": 377, + "note": "Porro sed nobis neque amet velit velit.", + "noteable_type": "Issue", + "author_id": 3, + "created_at": "2016-03-22T15:20:00.625Z", + "updated_at": "2016-03-22T15:20:00.625Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 35, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Alexie Trantow" + } + }, + { + "id": 376, + "note": "Dicta officiis doloremque voluptatum qui omnis.", + "noteable_type": "Issue", + "author_id": 4, + "created_at": "2016-03-22T15:20:00.589Z", + "updated_at": "2016-03-22T15:20:00.589Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 35, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Julius Moore" + } + }, + { + "id": 375, + "note": "Incidunt rerum omnis cum laudantium aut impedit.", + "noteable_type": "Issue", + "author_id": 10, + "created_at": "2016-03-22T15:20:00.553Z", + "updated_at": "2016-03-22T15:20:00.553Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 35, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Robyn McCullough Jr." + } + }, + { + "id": 374, + "note": "Et suscipit omnis dolorum officia vero.", + "noteable_type": "Issue", + "author_id": 12, + "created_at": "2016-03-22T15:20:00.517Z", + "updated_at": "2016-03-22T15:20:00.517Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 35, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Vladimir McCullough" + } + }, + { + "id": 373, + "note": "Doloremque adipisci et cumque inventore beatae consectetur.", + "noteable_type": "Issue", + "author_id": 22, + "created_at": "2016-03-22T15:20:00.485Z", + "updated_at": "2016-03-22T15:20:00.485Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 35, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 0" + } + }, + { + "id": 372, + "note": "Dolores sapiente ea dolorum et quae adipisci id.", + "noteable_type": "Issue", + "author_id": 24, + "created_at": "2016-03-22T15:20:00.455Z", + "updated_at": "2016-03-22T15:20:00.455Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 35, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 2" + } + }, + { + "id": 371, + "note": "Accusantium repellat tenetur natus dicta ullam saepe facere.", + "noteable_type": "Issue", + "author_id": 26, + "created_at": "2016-03-22T15:20:00.420Z", + "updated_at": "2016-03-22T15:20:00.420Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 35, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 4" + } + } + ] + }, + { + "id": 34, + "title": "Enim occaecati aut sed quia mollitia eligendi atque dolores voluptatem.", + "assignee_id": 24, + "author_id": 1, + "project_id": 5, + "created_at": "2016-03-22T15:13:27.506Z", + "updated_at": "2016-03-22T15:20:00.961Z", + "position": 0, + "branch_name": null, + "description": "Voluptatem totam magnam fugit assumenda consequatur illo qui.", + "milestone_id": 10, + "state": "opened", + "iid": 4, + "updated_by_id": null, + "confidential": false, + "deleted_at": null, + "moved_to_id": null, + "due_date": null, + "notes": [ + { + "id": 379, + "note": "Praesentium odio quia fugit consequuntur repudiandae ducimus.", + "noteable_type": "Issue", + "author_id": 26, + "created_at": "2016-03-22T15:20:00.717Z", + "updated_at": "2016-03-22T15:20:00.717Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 34, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 4" + } + }, + { + "id": 380, + "note": "Dolores aut dolorem quia soluta incidunt commodi quia.", + "noteable_type": "Issue", + "author_id": 24, + "created_at": "2016-03-22T15:20:00.754Z", + "updated_at": "2016-03-22T15:20:00.754Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 34, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 2" + } + }, + { + "id": 381, + "note": "Enim et velit iure ad.", + "noteable_type": "Issue", + "author_id": 22, + "created_at": "2016-03-22T15:20:00.787Z", + "updated_at": "2016-03-22T15:20:00.787Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 34, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 0" + } + }, + { + "id": 382, + "note": "Impedit nobis quis laudantium ad assumenda.", + "noteable_type": "Issue", + "author_id": 12, + "created_at": "2016-03-22T15:20:00.822Z", + "updated_at": "2016-03-22T15:20:00.822Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 34, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Vladimir McCullough" + } + }, + { + "id": 383, + "note": "Facere sed numquam quos quas.", + "noteable_type": "Issue", + "author_id": 10, + "created_at": "2016-03-22T15:20:00.855Z", + "updated_at": "2016-03-22T15:20:00.855Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 34, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Robyn McCullough Jr." + } + }, + { + "id": 384, + "note": "Ex voluptatem sit provident error.", + "noteable_type": "Issue", + "author_id": 4, + "created_at": "2016-03-22T15:20:00.889Z", + "updated_at": "2016-03-22T15:20:00.889Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 34, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Julius Moore" + } + }, + { + "id": 385, + "note": "Soluta laboriosam recusandae est cupiditate.", + "noteable_type": "Issue", + "author_id": 3, + "created_at": "2016-03-22T15:20:00.925Z", + "updated_at": "2016-03-22T15:20:00.925Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 34, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Alexie Trantow" + } + }, + { + "id": 386, + "note": "Similique dolorem rerum iusto animi perferendis aut inventore.", + "noteable_type": "Issue", + "author_id": 1, + "created_at": "2016-03-22T15:20:00.957Z", + "updated_at": "2016-03-22T15:20:00.957Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 34, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Administrator" + } + } + ] + }, + { + "id": 33, + "title": "Rem fugiat fugit occaecati quibusdam enim consectetur numquam.", + "assignee_id": 22, + "author_id": 22, + "project_id": 5, + "created_at": "2016-03-22T15:13:27.364Z", + "updated_at": "2016-03-22T15:20:01.227Z", + "position": 0, + "branch_name": null, + "description": "Provident nulla architecto neque beatae fuga alias repudiandae.", + "milestone_id": 10, + "state": "closed", + "iid": 3, + "updated_by_id": null, + "confidential": false, + "deleted_at": null, + "moved_to_id": null, + "due_date": null, + "notes": [ + { + "id": 394, + "note": "Suscipit numquam voluptatibus ipsam libero dolorum dolore totam.", + "noteable_type": "Issue", + "author_id": 1, + "created_at": "2016-03-22T15:20:01.223Z", + "updated_at": "2016-03-22T15:20:01.223Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 33, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Administrator" + } + }, + { + "id": 393, + "note": "Et et sed sit sint.", + "noteable_type": "Issue", + "author_id": 3, + "created_at": "2016-03-22T15:20:01.194Z", + "updated_at": "2016-03-22T15:20:01.194Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 33, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Alexie Trantow" + } + }, + { + "id": 392, + "note": "Corrupti perferendis voluptas et iure omnis officia.", + "noteable_type": "Issue", + "author_id": 4, + "created_at": "2016-03-22T15:20:01.160Z", + "updated_at": "2016-03-22T15:20:01.160Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 33, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Julius Moore" + } + }, + { + "id": 391, + "note": "Autem quo fugit in iste nesciunt tempora.", + "noteable_type": "Issue", + "author_id": 10, + "created_at": "2016-03-22T15:20:01.131Z", + "updated_at": "2016-03-22T15:20:01.131Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 33, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Robyn McCullough Jr." + } + }, + { + "id": 390, + "note": "Magni porro ut soluta quis et eveniet maiores.", + "noteable_type": "Issue", + "author_id": 12, + "created_at": "2016-03-22T15:20:01.101Z", + "updated_at": "2016-03-22T15:20:01.101Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 33, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Vladimir McCullough" + } + }, + { + "id": 389, + "note": "Sed consequuntur debitis nisi veniam exercitationem recusandae a quisquam.", + "noteable_type": "Issue", + "author_id": 22, + "created_at": "2016-03-22T15:20:01.070Z", + "updated_at": "2016-03-22T15:20:01.070Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 33, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 0" + } + }, + { + "id": 388, + "note": "Aut impedit qui consectetur dicta temporibus.", + "noteable_type": "Issue", + "author_id": 24, + "created_at": "2016-03-22T15:20:01.042Z", + "updated_at": "2016-03-22T15:20:01.042Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 33, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 2" + } + }, + { + "id": 387, + "note": "Officia repudiandae ut culpa ipsa reiciendis.", + "noteable_type": "Issue", + "author_id": 26, + "created_at": "2016-03-22T15:20:01.005Z", + "updated_at": "2016-03-22T15:20:01.005Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 33, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 4" + } + } + ] + }, + { + "id": 32, + "title": "Velit nihil est alias blanditiis eius earum autem hic.", + "assignee_id": 22, + "author_id": 26, + "project_id": 5, + "created_at": "2016-03-22T15:13:27.225Z", + "updated_at": "2016-03-22T15:20:01.495Z", + "position": 0, + "branch_name": null, + "description": "Id voluptas ut sint aut laborum nobis commodi.", + "milestone_id": 11, + "state": "opened", + "iid": 2, + "updated_by_id": null, + "confidential": false, + "deleted_at": null, + "moved_to_id": null, + "due_date": null, + "notes": [ + { + "id": 402, + "note": "Magni ut eligendi sit sint recusandae voluptas tempore necessitatibus.", + "noteable_type": "Issue", + "author_id": 1, + "created_at": "2016-03-22T15:20:01.489Z", + "updated_at": "2016-03-22T15:20:01.489Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 32, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Administrator" + } + }, + { + "id": 401, + "note": "Est repellat commodi incidunt tempore earum optio unde sint.", + "noteable_type": "Issue", + "author_id": 3, + "created_at": "2016-03-22T15:20:01.455Z", + "updated_at": "2016-03-22T15:20:01.455Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 32, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Alexie Trantow" + } + }, + { + "id": 400, + "note": "Vero unde debitis tempore est laboriosam ut esse.", + "noteable_type": "Issue", + "author_id": 4, + "created_at": "2016-03-22T15:20:01.421Z", + "updated_at": "2016-03-22T15:20:01.421Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 32, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Julius Moore" + } + }, + { + "id": 399, + "note": "Omnis qui asperiores expedita harum voluptatem eius.", + "noteable_type": "Issue", + "author_id": 10, + "created_at": "2016-03-22T15:20:01.391Z", + "updated_at": "2016-03-22T15:20:01.391Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 32, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Robyn McCullough Jr." + } + }, + { + "id": 398, + "note": "Dolorem doloribus delectus quo ratione esse veritatis.", + "noteable_type": "Issue", + "author_id": 12, + "created_at": "2016-03-22T15:20:01.358Z", + "updated_at": "2016-03-22T15:20:01.358Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 32, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Vladimir McCullough" + } + }, + { + "id": 397, + "note": "Quia esse et odit id est omnis dolorum quia.", + "noteable_type": "Issue", + "author_id": 22, + "created_at": "2016-03-22T15:20:01.329Z", + "updated_at": "2016-03-22T15:20:01.329Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 32, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 0" + } + }, + { + "id": 396, + "note": "Exercitationem suscipit non rerum tempore sit.", + "noteable_type": "Issue", + "author_id": 24, + "created_at": "2016-03-22T15:20:01.297Z", + "updated_at": "2016-03-22T15:20:01.297Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 32, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 2" + } + }, + { + "id": 395, + "note": "Nihil veniam magni sit officiis.", + "noteable_type": "Issue", + "author_id": 26, + "created_at": "2016-03-22T15:20:01.268Z", + "updated_at": "2016-03-22T15:20:01.268Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 32, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 4" + } + } + ] + }, + { + "id": 31, + "title": "Asperiores recusandae praesentium voluptas pariatur provident qui exercitationem quis.", + "assignee_id": 26, + "author_id": 24, + "project_id": 5, + "created_at": "2016-03-22T15:13:26.889Z", + "updated_at": "2016-03-22T15:20:01.834Z", + "position": 0, + "branch_name": null, + "description": "Ex voluptates qui excepturi cupiditate.", + "milestone_id": 11, + "state": "closed", + "iid": 1, + "updated_by_id": null, + "confidential": false, + "deleted_at": null, + "moved_to_id": null, + "due_date": null, + "notes": [ + { + "id": 410, + "note": "Sit itaque non nihil nisi qui voluptatem dolorem error.", + "noteable_type": "Issue", + "author_id": 1, + "created_at": "2016-03-22T15:20:01.828Z", + "updated_at": "2016-03-22T15:20:01.828Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 31, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Administrator" + } + }, + { + "id": 409, + "note": "Omnis rem nihil molestiae enim laudantium doloremque.", + "noteable_type": "Issue", + "author_id": 3, + "created_at": "2016-03-22T15:20:01.783Z", + "updated_at": "2016-03-22T15:20:01.783Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 31, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Alexie Trantow" + } + }, + { + "id": 408, + "note": "Ullam harum sit et optio incidunt.", + "noteable_type": "Issue", + "author_id": 4, + "created_at": "2016-03-22T15:20:01.746Z", + "updated_at": "2016-03-22T15:20:01.746Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 31, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Julius Moore" + } + }, + { + "id": 407, + "note": "Fugit distinctio ab quo ipsam.", + "noteable_type": "Issue", + "author_id": 10, + "created_at": "2016-03-22T15:20:01.716Z", + "updated_at": "2016-03-22T15:20:01.716Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 31, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Robyn McCullough Jr." + } + }, + { + "id": 406, + "note": "Impedit iste possimus ad ea.", + "noteable_type": "Issue", + "author_id": 12, + "created_at": "2016-03-22T15:20:01.676Z", + "updated_at": "2016-03-22T15:20:01.676Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 31, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Vladimir McCullough" + } + }, + { + "id": 405, + "note": "Nemo recusandae dolore distinctio quam consequuntur ut et aut.", + "noteable_type": "Issue", + "author_id": 22, + "created_at": "2016-03-22T15:20:01.641Z", + "updated_at": "2016-03-22T15:20:01.641Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 31, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 0" + } + }, + { + "id": 404, + "note": "Nisi repudiandae repellat nulla culpa quasi expedita quod velit.", + "noteable_type": "Issue", + "author_id": 24, + "created_at": "2016-03-22T15:20:01.601Z", + "updated_at": "2016-03-22T15:20:01.601Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 31, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 2" + } + }, + { + "id": 403, + "note": "Quibusdam odio temporibus nemo voluptatibus accusamus.", + "noteable_type": "Issue", + "author_id": 26, + "created_at": "2016-03-22T15:20:01.552Z", + "updated_at": "2016-03-22T15:20:01.552Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 31, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 4" + } } ] } ], "labels": [ { - "id": 1, - "title": "label1", - "color": "#990000", - "project_id": 6, - "created_at": "2016-04-13T14:40:34.704Z", - "updated_at": "2016-04-13T14:40:36.891Z", + "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": null + "description": "test label" } ], "milestones": [ { - "id": 1, - "title": "Milestone v1.2", - "project_id": 6, - "description": null, + "id": 11, + "title": "v2.0", + "project_id": 5, + "description": "Sapiente facilis architecto reprehenderit aut sed enim.", "due_date": null, - "created_at": "2016-04-13T14:40:37.901Z", - "updated_at": "2016-04-13T14:40:37.901Z", - "state": "active", + "created_at": "2016-03-22T15:13:21.631Z", + "updated_at": "2016-03-22T15:13:21.631Z", + "state": "closed", + "iid": 2 + }, + { + "id": 10, + "title": "v1.0", + "project_id": 5, + "description": "Est sed eos minima veniam culpa aut non.", + "due_date": null, + "created_at": "2016-03-22T15:13:21.622Z", + "updated_at": "2016-03-22T15:13:21.622Z", + "state": "closed", "iid": 1 } ], "snippets": [ - { - "id": 1, - "title": "Illo ipsa maxime magni aut.", - "content": "Excepturi delectus ut harum est molestiae dolor.", - "author_id": 10, - "project_id": 6, - "created_at": "2016-04-13T14:40:35.603Z", - "updated_at": "2016-04-13T14:40:36.903Z", - "file_name": "daphne.mraz", - "visibility_level": 0 - } + ], "releases": [ - { - "id": 1, - "tag": "v1.1.0", - "description": "Awesome release", - "project_id": 6, - "created_at": "2016-04-13T14:40:36.223Z", - "updated_at": "2016-04-13T14:40:36.913Z" - } + ], "events": [ { - "id": 1, + "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": 6, - "created_at": "2016-04-13T14:40:40.122Z", - "updated_at": "2016-04-13T14:40:40.122Z", + "project_id": 5, + "created_at": "2016-03-22T15:13:20.750Z", + "updated_at": "2016-03-22T15:13:20.750Z", "action": 8, + "author_id": 12 + }, + { + "id": 23, + "target_type": null, + "target_id": null, + "title": null, + "data": null, + "project_id": 5, + "created_at": "2016-03-22T15:13:20.711Z", + "updated_at": "2016-03-22T15:13:20.711Z", + "action": 8, + "author_id": 22 + }, + { + "id": 22, + "target_type": null, + "target_id": null, + "title": null, + "data": null, + "project_id": 5, + "created_at": "2016-03-22T15:13:20.667Z", + "updated_at": "2016-03-22T15:13:20.667Z", + "action": 8, + "author_id": 26 + }, + { + "id": 21, + "target_type": null, + "target_id": null, + "title": null, + "data": null, + "project_id": 5, + "created_at": "2016-03-22T15:13:20.646Z", + "updated_at": "2016-03-22T15:13:20.646Z", + "action": 8, + "author_id": 1 + }, + { + "id": 5, + "target_type": null, + "target_id": null, + "title": null, + "data": null, + "project_id": 5, + "created_at": "2016-03-22T15:13:10.369Z", + "updated_at": "2016-03-22T15:13:10.369Z", + "action": 1, "author_id": 1 } ], "project_members": [ { - "id": 1, + "id": 35, + "access_level": 40, + "source_id": 5, + "source_type": "Project", + "user_id": 12, + "notification_level": 3, + "created_at": "2016-03-22T15:13:20.743Z", + "updated_at": "2016-03-22T15:13:20.743Z", + "created_by_id": null, + "invite_email": null, + "invite_token": null, + "invite_accepted_at": null, + "user": { + "id": 12, + "email": "maureen.bogisich@russelkessler.com", + "username": "evans" + } + }, + { + "id": 34, + "access_level": 40, + "source_id": 5, + "source_type": "Project", + "user_id": 22, + "notification_level": 3, + "created_at": "2016-03-22T15:13:20.708Z", + "updated_at": "2016-03-22T15:13:20.708Z", + "created_by_id": null, + "invite_email": null, + "invite_token": null, + "invite_accepted_at": null, + "user": { + "id": 22, + "email": "user0@example.com", + "username": "user0" + } + }, + { + "id": 33, + "access_level": 40, + "source_id": 5, + "source_type": "Project", + "user_id": 26, + "notification_level": 3, + "created_at": "2016-03-22T15:13:20.664Z", + "updated_at": "2016-03-22T15:13:20.664Z", + "created_by_id": null, + "invite_email": null, + "invite_token": null, + "invite_accepted_at": null, + "user": { + "id": 26, + "email": "user4@example.com", + "username": "user4" + } + }, + { + "id": 32, + "access_level": 20, + "source_id": 5, + "source_type": "Project", + "user_id": 1, + "notification_level": 3, + "created_at": "2016-03-22T15:13:20.643Z", + "updated_at": "2016-03-22T15:13:20.643Z", + "created_by_id": null, + "invite_email": null, + "invite_token": null, + "invite_accepted_at": null, "user": { "id": 1, - "email": "norval.gulgowski@schambergerboyle.co.uk", - "created_at": "2016-04-13T14:40:30.963Z", - "updated_at": "2016-04-13T14:40:30.963Z", - "name": "Jalon Cormier DVM", - "admin": false, - "projects_limit": 42, - "skype": "", - "linkedin": "", - "twitter": "", - "authentication_token": "tt-mPSZFvRBu8QzkW1Ss", - "theme_id": 2, - "bio": null, - "username": "vance.turner1", - "can_create_group": true, - "can_create_team": false, - "state": "active", - "color_scheme_id": 1, - "notification_level": 1, - "password_expires_at": null, - "created_by_id": null, - "last_credential_check_at": null, - "avatar": { - "url": null - }, - "hide_no_ssh_key": false, - "website_url": "", - "notification_email": "norval.gulgowski@schambergerboyle.co.uk", - "hide_no_password": false, - "password_automatically_set": false, - "location": null, - "encrypted_otp_secret": null, - "encrypted_otp_secret_iv": null, - "encrypted_otp_secret_salt": null, - "otp_required_for_login": false, - "otp_backup_codes": null, - "public_email": "", - "dashboard": "projects", - "project_view": "readme", - "consumed_timestep": null, - "layout": "fixed", - "hide_project_limit": false, - "otp_grace_period_started_at": null, - "ldap_email": false, - "external": false + "email": "nospam@bluegod.net", + "username": "root" } } ], "merge_requests": [ { - "id": 1, + "id": 85, "target_branch": "feature", - "source_branch": "master", - "source_project_id": 2, - "author_id": 5, + "source_branch": "feature_conflict", + "source_project_id": 5, + "author_id": 1, "assignee_id": null, - "title": "Dignissimos officia sit aut id dolor iure voluptatem expedita.", - "created_at": "2016-04-13T14:40:33.381Z", - "updated_at": "2016-04-13T14:40:39.850Z", + "title": "Cannot be automatically merged", + "created_at": "2016-03-22T15:19:44.807Z", + "updated_at": "2016-03-22T15:20:09.557Z", "milestone_id": null, "state": "opened", - "merge_status": "can_be_merged", - "target_project_id": 6, - "iid": 1, + "merge_status": "unchecked", + "target_project_id": 5, + "iid": 9, "description": null, "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": 638, + "note": "Ab velit ducimus totam sunt ut.", + "noteable_type": "MergeRequest", + "author_id": 1, + "created_at": "2016-03-22T15:20:09.553Z", + "updated_at": "2016-03-22T15:20:09.553Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 85, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Administrator" + } + }, + { + "id": 637, + "note": "Ipsum aliquam est in unde similique nihil illo ea.", + "noteable_type": "MergeRequest", + "author_id": 3, + "created_at": "2016-03-22T15:20:09.528Z", + "updated_at": "2016-03-22T15:20:09.528Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 85, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Alexie Trantow" + } + }, + { + "id": 636, + "note": "Soluta inventore adipisci et consequatur expedita aliquid earum modi.", + "noteable_type": "MergeRequest", + "author_id": 4, + "created_at": "2016-03-22T15:20:09.496Z", + "updated_at": "2016-03-22T15:20:09.496Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 85, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Julius Moore" + } + }, + { + "id": 635, + "note": "Corporis incidunt tempore est deleniti.", + "noteable_type": "MergeRequest", + "author_id": 10, + "created_at": "2016-03-22T15:20:09.469Z", + "updated_at": "2016-03-22T15:20:09.469Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 85, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Robyn McCullough Jr." + } + }, + { + "id": 634, + "note": "Hic dolores voluptatibus qui necessitatibus.", + "noteable_type": "MergeRequest", + "author_id": 12, + "created_at": "2016-03-22T15:20:09.440Z", + "updated_at": "2016-03-22T15:20:09.440Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 85, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Vladimir McCullough" + } + }, + { + "id": 633, + "note": "Rerum architecto placeat doloribus voluptates consequuntur quo.", + "noteable_type": "MergeRequest", + "author_id": 22, + "created_at": "2016-03-22T15:20:09.412Z", + "updated_at": "2016-03-22T15:20:09.412Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 85, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 0" + } + }, + { + "id": 632, + "note": "Vel earum aut ut occaecati aut ut rerum qui.", + "noteable_type": "MergeRequest", + "author_id": 24, + "created_at": "2016-03-22T15:20:09.389Z", + "updated_at": "2016-03-22T15:20:09.389Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 85, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 2" + } + }, + { + "id": 631, + "note": "Est voluptatibus dolores animi numquam.", + "noteable_type": "MergeRequest", + "author_id": 26, + "created_at": "2016-03-22T15:20:09.361Z", + "updated_at": "2016-03-22T15:20:09.361Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 85, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 4" + } + } + ], "merge_request_diff": { - "id": 1, + "id": 85, "state": "collected", "st_commits": [ + { + "id": "bb5206fee213d983da88c47f9cf4cc6caf9c66dc", + "message": "Feature conflcit added\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n", + "parent_ids": [ + "5937ac0a7beb003549fc5fd26fc247adbce4a52e" + ], + "authored_date": "2014-08-06T08:35:52.000+02:00", + "author_name": "Dmitriy Zaporozhets", + "author_email": "dmitriy.zaporozhets@gmail.com", + "committed_date": "2014-08-06T08:35:52.000+02:00", + "committer_name": "Dmitriy Zaporozhets", + "committer_email": "dmitriy.zaporozhets@gmail.com" + }, { "id": "5937ac0a7beb003549fc5fd26fc247adbce4a52e", - "message": "Add submodule from gitlab.com\n\nSigned-off-by: Dmitriy Zaporozhets \n", + "message": "Add submodule from gitlab.com\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n", "parent_ids": [ "570e7b2abdd848b95f2f578043fc23bd6f6fd24d" ], @@ -210,7 +2696,7 @@ }, { "id": "570e7b2abdd848b95f2f578043fc23bd6f6fd24d", - "message": "Change some files\n\nSigned-off-by: Dmitriy Zaporozhets \n", + "message": "Change some files\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n", "parent_ids": [ "6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9" ], @@ -223,7 +2709,7 @@ }, { "id": "6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9", - "message": "More submodules\n\nSigned-off-by: Dmitriy Zaporozhets \n", + "message": "More submodules\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n", "parent_ids": [ "d14d6c0abdd253381df51a723d58691b2ee1ab08" ], @@ -236,7 +2722,7 @@ }, { "id": "d14d6c0abdd253381df51a723d58691b2ee1ab08", - "message": "Remove ds_store files\n\nSigned-off-by: Dmitriy Zaporozhets \n", + "message": "Remove ds_store files\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n", "parent_ids": [ "c1acaa58bbcbc3eafe538cb8274ba387047b69f8" ], @@ -249,7 +2735,7 @@ }, { "id": "c1acaa58bbcbc3eafe538cb8274ba387047b69f8", - "message": "Ignore DS files\n\nSigned-off-by: Dmitriy Zaporozhets \n", + "message": "Ignore DS files\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n", "parent_ids": [ "ae73cb07c9eeaf35924a10f713b364d32b2dd34f" ], @@ -307,7 +2793,18 @@ "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\" => path }\n- options = { chdir: path }\n+\n+ vars = {\n+ \"PWD\" => 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 << stdout.read\n @cmd_output << stderr.read\n", + "diff": "--- /dev/null\n+++ b/files/ruby/feature.rb\n@@ -0,0 +1,4 @@\n+# This file was changed in feature branch\n+# We put different code here to make merge conflict\n+class Conflict\n+end\n", + "new_path": "files/ruby/feature.rb", + "old_path": "files/ruby/feature.rb", + "a_mode": "0", + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + }, + { + "diff": "--- a/files/ruby/popen.rb\n+++ b/files/ruby/popen.rb\n@@ -6,12 +6,18 @@ module Popen\n \n def popen(cmd, path=nil)\n unless cmd.is_a?(Array)\n- raise \"System commands must be given as an array of strings\"\n+ raise RuntimeError, \"System commands must be given as an array of strings\"\n end\n \n path ||= Dir.pwd\n- vars = { \"PWD\" =\u003e path }\n- options = { chdir: path }\n+\n+ vars = {\n+ \"PWD\" =\u003e path\n+ }\n+\n+ options = {\n+ chdir: path\n+ }\n \n unless File.directory?(path)\n FileUtils.mkdir_p(path)\n@@ -19,6 +25,7 @@ module Popen\n \n @cmd_output = \"\"\n @cmd_status = 0\n+\n Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr|\n @cmd_output \u003c\u003c stdout.read\n @cmd_output \u003c\u003c stderr.read\n", "new_path": "files/ruby/popen.rb", "old_path": "files/ruby/popen.rb", "a_mode": "100644", @@ -351,79 +2848,2643 @@ "too_large": false } ], - "merge_request_id": 1, - "created_at": "2016-04-13T14:40:33.474Z", - "updated_at": "2016-04-13T14:40:33.834Z", + "merge_request_id": 85, + "created_at": "2016-03-22T15:19:44.810Z", + "updated_at": "2016-03-22T15:19:44.901Z", "base_commit_sha": "ae73cb07c9eeaf35924a10f713b364d32b2dd34f", - "real_size": "8" + "real_size": "9" + } + }, + { + "id": 84, + "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", + "milestone_id": null, + "state": "opened", + "merge_status": "unchecked", + "target_project_id": 5, + "iid": 8, + "description": null, + "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": 2, - "note": ":+1: merge_request", + "id": 646, + "note": "Temporibus debitis veniam est ut sit nihil.", "noteable_type": "MergeRequest", - "author_id": 24, - "created_at": "2016-04-13T14:40:39.832Z", - "updated_at": "2016-04-13T14:40:39.832Z", - "project_id": 9, + "author_id": 1, + "created_at": "2016-03-22T15:20:09.770Z", + "updated_at": "2016-03-22T15:20:09.770Z", + "project_id": 5, "attachment": { "url": null }, "line_code": null, "commit_id": null, - "noteable_id": 1, + "noteable_id": 84, "system": false, "st_diff": null, "updated_by_id": null, - "is_award": false + "is_award": false, + "author": { + "name": "Administrator" + } + }, + { + "id": 645, + "note": "Ut assumenda dignissimos quibusdam veritatis sequi dolores.", + "noteable_type": "MergeRequest", + "author_id": 3, + "created_at": "2016-03-22T15:20:09.740Z", + "updated_at": "2016-03-22T15:20:09.740Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 84, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Alexie Trantow" + } + }, + { + "id": 644, + "note": "Velit quae quidem cupiditate laudantium nihil ut eveniet.", + "noteable_type": "MergeRequest", + "author_id": 4, + "created_at": "2016-03-22T15:20:09.717Z", + "updated_at": "2016-03-22T15:20:09.717Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 84, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Julius Moore" + } + }, + { + "id": 643, + "note": "Repellat quas porro sed mollitia laborum ut fugiat.", + "noteable_type": "MergeRequest", + "author_id": 10, + "created_at": "2016-03-22T15:20:09.690Z", + "updated_at": "2016-03-22T15:20:09.690Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 84, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Robyn McCullough Jr." + } + }, + { + "id": 642, + "note": "Qui aut debitis perspiciatis et voluptatem.", + "noteable_type": "MergeRequest", + "author_id": 12, + "created_at": "2016-03-22T15:20:09.665Z", + "updated_at": "2016-03-22T15:20:09.665Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 84, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Vladimir McCullough" + } + }, + { + "id": 641, + "note": "Quia id quia velit et.", + "noteable_type": "MergeRequest", + "author_id": 22, + "created_at": "2016-03-22T15:20:09.639Z", + "updated_at": "2016-03-22T15:20:09.639Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 84, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 0" + } + }, + { + "id": 640, + "note": "Corporis commodi doloremque itaque non animi.", + "noteable_type": "MergeRequest", + "author_id": 24, + "created_at": "2016-03-22T15:20:09.617Z", + "updated_at": "2016-03-22T15:20:09.617Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 84, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 2" + } + }, + { + "id": 639, + "note": "Possimus dignissimos voluptatum in tenetur.", + "noteable_type": "MergeRequest", + "author_id": 26, + "created_at": "2016-03-22T15:20:09.589Z", + "updated_at": "2016-03-22T15:20:09.589Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 84, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 4" + } } - ] + ], + "merge_request_diff": { + "id": 84, + "state": "collected", + "st_commits": [ + { + "id": "0b4bc9a49b562e85de7cc9e834518ea6828729b9", + "message": "Feature added\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n", + "parent_ids": [ + "ae73cb07c9eeaf35924a10f713b364d32b2dd34f" + ], + "authored_date": "2014-02-27T09:26:01.000+01:00", + "author_name": "Dmitriy Zaporozhets", + "author_email": "dmitriy.zaporozhets@gmail.com", + "committed_date": "2014-02-27T09:26:01.000+01:00", + "committer_name": "Dmitriy Zaporozhets", + "committer_email": "dmitriy.zaporozhets@gmail.com" + } + ], + "st_diffs": [ + { + "diff": "--- /dev/null\n+++ b/files/ruby/feature.rb\n@@ -0,0 +1,5 @@\n+class Feature\n+ def foo\n+ puts 'bar'\n+ end\n+end\n", + "new_path": "files/ruby/feature.rb", + "old_path": "files/ruby/feature.rb", + "a_mode": "0", + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + } + ], + "merge_request_id": 84, + "created_at": "2016-03-22T15:19:44.485Z", + "updated_at": "2016-03-22T15:19:44.577Z", + "base_commit_sha": "ae73cb07c9eeaf35924a10f713b364d32b2dd34f", + "real_size": "1" + } + }, + { + "id": 15, + "target_branch": "markdown", + "source_branch": "master", + "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, + "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.", + "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": 1231, + "note": "Rerum optio quibusdam provident possimus quis cum.", + "noteable_type": "MergeRequest", + "author_id": 1, + "created_at": "2016-03-22T15:20:30.472Z", + "updated_at": "2016-03-22T15:20:30.472Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 15, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Administrator" + } + }, + { + "id": 1230, + "note": "Quasi odit repudiandae ut officiis ut nihil illo.", + "noteable_type": "MergeRequest", + "author_id": 3, + "created_at": "2016-03-22T15:20:30.444Z", + "updated_at": "2016-03-22T15:20:30.444Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 15, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Alexie Trantow" + } + }, + { + "id": 1229, + "note": "Aut vero dolores facere sed.", + "noteable_type": "MergeRequest", + "author_id": 4, + "created_at": "2016-03-22T15:20:30.412Z", + "updated_at": "2016-03-22T15:20:30.412Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 15, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Julius Moore" + } + }, + { + "id": 1228, + "note": "Autem voluptatem et blanditiis accusantium deserunt et et.", + "noteable_type": "MergeRequest", + "author_id": 10, + "created_at": "2016-03-22T15:20:30.383Z", + "updated_at": "2016-03-22T15:20:30.383Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 15, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Robyn McCullough Jr." + } + }, + { + "id": 1227, + "note": "Voluptatem aliquam voluptatem molestiae est.", + "noteable_type": "MergeRequest", + "author_id": 12, + "created_at": "2016-03-22T15:20:30.352Z", + "updated_at": "2016-03-22T15:20:30.352Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 15, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Vladimir McCullough" + } + }, + { + "id": 1226, + "note": "Ea aut cupiditate est consequatur animi error qui et.", + "noteable_type": "MergeRequest", + "author_id": 22, + "created_at": "2016-03-22T15:20:30.319Z", + "updated_at": "2016-03-22T15:20:30.319Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 15, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 0" + } + }, + { + "id": 1225, + "note": "Voluptates est voluptas et nostrum modi beatae inventore et.", + "noteable_type": "MergeRequest", + "author_id": 24, + "created_at": "2016-03-22T15:20:30.289Z", + "updated_at": "2016-03-22T15:20:30.289Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 15, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 2" + } + }, + { + "id": 1224, + "note": "Quia est rerum adipisci cupiditate.", + "noteable_type": "MergeRequest", + "author_id": 26, + "created_at": "2016-03-22T15:20:30.260Z", + "updated_at": "2016-03-22T15:20:30.260Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 15, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 4" + } + } + ], + "merge_request_diff": { + "id": 15, + "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", + "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 + } + ], + "merge_request_id": 15, + "created_at": "2016-03-22T15:13:45.692Z", + "updated_at": "2016-03-22T15:13:45.808Z", + "base_commit_sha": "5937ac0a7beb003549fc5fd26fc247adbce4a52e", + "real_size": "6" + } + }, + { + "id": 14, + "target_branch": "test-1", + "source_branch": "test-10", + "source_project_id": 5, + "author_id": 10, + "assignee_id": 1, + "title": "Tempore aliquid sit amet odit qui cum iusto voluptatibus asperiores.", + "created_at": "2016-03-22T15:13:45.442Z", + "updated_at": "2016-03-22T15:20:30.735Z", + "milestone_id": 10, + "state": "opened", + "merge_status": "unchecked", + "target_project_id": 5, + "iid": 6, + "description": "Quis et et autem saepe ut. Eum corporis tempore cum dolore. Molestiae pariatur voluptatem officia perferendis aut veniam.", + "position": 0, + "locked_at": null, + "updated_by_id": null, + "merge_error": null, + "merge_params": { + + }, + "merge_when_build_succeeds": false, + "merge_user_id": null, + "merge_commit_sha": null, + "deleted_at": null, + "notes": [ + { + "id": 1239, + "note": "Aspernatur suscipit veritatis aliquid rerum.", + "noteable_type": "MergeRequest", + "author_id": 1, + "created_at": "2016-03-22T15:20:30.731Z", + "updated_at": "2016-03-22T15:20:30.731Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 14, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Administrator" + } + }, + { + "id": 1238, + "note": "Rerum deleniti omnis porro commodi.", + "noteable_type": "MergeRequest", + "author_id": 3, + "created_at": "2016-03-22T15:20:30.701Z", + "updated_at": "2016-03-22T15:20:30.701Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 14, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Alexie Trantow" + } + }, + { + "id": 1237, + "note": "Eaque ut magnam rerum non dolores esse.", + "noteable_type": "MergeRequest", + "author_id": 4, + "created_at": "2016-03-22T15:20:30.667Z", + "updated_at": "2016-03-22T15:20:30.667Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 14, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Julius Moore" + } + }, + { + "id": 1236, + "note": "Fugit et aut similique illum ut natus maiores et.", + "noteable_type": "MergeRequest", + "author_id": 10, + "created_at": "2016-03-22T15:20:30.637Z", + "updated_at": "2016-03-22T15:20:30.637Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 14, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Robyn McCullough Jr." + } + }, + { + "id": 1235, + "note": "Qui qui temporibus eos aliquam.", + "noteable_type": "MergeRequest", + "author_id": 12, + "created_at": "2016-03-22T15:20:30.608Z", + "updated_at": "2016-03-22T15:20:30.608Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 14, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Vladimir McCullough" + } + }, + { + "id": 1234, + "note": "Voluptates hic dolorum aut inventore.", + "noteable_type": "MergeRequest", + "author_id": 22, + "created_at": "2016-03-22T15:20:30.575Z", + "updated_at": "2016-03-22T15:20:30.575Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 14, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 0" + } + }, + { + "id": 1233, + "note": "Dolorum iure at dolor dolores numquam iusto.", + "noteable_type": "MergeRequest", + "author_id": 24, + "created_at": "2016-03-22T15:20:30.548Z", + "updated_at": "2016-03-22T15:20:30.548Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 14, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 2" + } + }, + { + "id": 1232, + "note": "Nihil est eum aspernatur amet minus et corporis consectetur.", + "noteable_type": "MergeRequest", + "author_id": 26, + "created_at": "2016-03-22T15:20:30.517Z", + "updated_at": "2016-03-22T15:20:30.517Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 14, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 4" + } + } + ], + "merge_request_diff": { + "id": 14, + "state": "collected", + "st_commits": [ + { + "id": "bce96ecee98f51fa5d91021e6c42859a35a701ad", + "message": "fixes #10\n", + "parent_ids": [ + "be93687618e4b132087f430a4d8fc3a609c9b77c" + ], + "authored_date": "2016-01-19T15:40:05.000+01:00", + "author_name": "Test Lopez", + "author_email": "Test@Testlopez.es", + "committed_date": "2016-01-19T15:40:05.000+01:00", + "committer_name": "Test Lopez", + "committer_email": "Test@Testlopez.es" + } + ], + "st_diffs": [ + { + "diff": "--- /dev/null\n+++ b/test\n", + "new_path": "test", + "old_path": "test", + "a_mode": "0", + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + } + ], + "merge_request_id": 14, + "created_at": "2016-03-22T15:13:45.444Z", + "updated_at": "2016-03-22T15:13:45.486Z", + "base_commit_sha": "be93687618e4b132087f430a4d8fc3a609c9b77c", + "real_size": "1" + } + }, + { + "id": 13, + "target_branch": "test-11", + "source_branch": "test-12", + "source_project_id": 5, + "author_id": 1, + "assignee_id": 26, + "title": "Voluptas minus sunt voluptatum quis quia ut velit distinctio itaque.", + "created_at": "2016-03-22T15:13:45.164Z", + "updated_at": "2016-03-22T15:20:30.994Z", + "milestone_id": 11, + "state": "opened", + "merge_status": "unchecked", + "target_project_id": 5, + "iid": 5, + "description": "Ea ut modi consectetur et minus beatae. Et sunt ducimus praesentium libero officia maiores voluptas cumque. Rerum in aut corporis et ullam omnis.", + "position": 0, + "locked_at": null, + "updated_by_id": null, + "merge_error": null, + "merge_params": { + + }, + "merge_when_build_succeeds": false, + "merge_user_id": null, + "merge_commit_sha": null, + "deleted_at": null, + "notes": [ + { + "id": 1247, + "note": "Non error magnam placeat cupiditate eum.", + "noteable_type": "MergeRequest", + "author_id": 1, + "created_at": "2016-03-22T15:20:30.989Z", + "updated_at": "2016-03-22T15:20:30.989Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 13, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Administrator" + } + }, + { + "id": 1246, + "note": "Eos optio et architecto eligendi ea est nihil.", + "noteable_type": "MergeRequest", + "author_id": 3, + "created_at": "2016-03-22T15:20:30.957Z", + "updated_at": "2016-03-22T15:20:30.957Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 13, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Alexie Trantow" + } + }, + { + "id": 1245, + "note": "Reprehenderit in atque dolor et repudiandae a est.", + "noteable_type": "MergeRequest", + "author_id": 4, + "created_at": "2016-03-22T15:20:30.928Z", + "updated_at": "2016-03-22T15:20:30.928Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 13, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Julius Moore" + } + }, + { + "id": 1244, + "note": "Numquam fugit doloremque iure odio et.", + "noteable_type": "MergeRequest", + "author_id": 10, + "created_at": "2016-03-22T15:20:30.902Z", + "updated_at": "2016-03-22T15:20:30.902Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 13, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Robyn McCullough Jr." + } + }, + { + "id": 1243, + "note": "Doloribus laboriosam id harum voluptatum vitae ut quam.", + "noteable_type": "MergeRequest", + "author_id": 12, + "created_at": "2016-03-22T15:20:30.863Z", + "updated_at": "2016-03-22T15:20:30.863Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 13, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Vladimir McCullough" + } + }, + { + "id": 1242, + "note": "Harum et ut ipsum dolore ea.", + "noteable_type": "MergeRequest", + "author_id": 22, + "created_at": "2016-03-22T15:20:30.832Z", + "updated_at": "2016-03-22T15:20:30.832Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 13, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 0" + } + }, + { + "id": 1241, + "note": "Corporis sed soluta ut est modi natus ab.", + "noteable_type": "MergeRequest", + "author_id": 24, + "created_at": "2016-03-22T15:20:30.802Z", + "updated_at": "2016-03-22T15:20:30.802Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 13, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 2" + } + }, + { + "id": 1240, + "note": "Corrupti totam tenetur officiis ratione dolores est qui vel.", + "noteable_type": "MergeRequest", + "author_id": 26, + "created_at": "2016-03-22T15:20:30.771Z", + "updated_at": "2016-03-22T15:20:30.771Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 13, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 4" + } + } + ], + "merge_request_diff": { + "id": 13, + "state": "collected", + "st_commits": [ + { + "id": "a4e5dfebf42e34596526acb8611bc7ed80e4eb3f", + "message": "fixes #10\n", + "parent_ids": [ + "be93687618e4b132087f430a4d8fc3a609c9b77c" + ], + "authored_date": "2016-01-19T15:44:02.000+01:00", + "author_name": "Test Lopez", + "author_email": "Test@Testlopez.es", + "committed_date": "2016-01-19T15:44:02.000+01:00", + "committer_name": "Test Lopez", + "committer_email": "Test@Testlopez.es" + } + ], + "st_diffs": [ + { + "diff": "--- /dev/null\n+++ b/test\n", + "new_path": "test", + "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-03-22T15:13:45.167Z", + "updated_at": "2016-03-22T15:13:45.216Z", + "base_commit_sha": "be93687618e4b132087f430a4d8fc3a609c9b77c", + "real_size": "1" + } + }, + { + "id": 12, + "target_branch": "test-15", + "source_branch": "test-2", + "source_project_id": 5, + "author_id": 24, + "assignee_id": 12, + "title": "In assumenda nam quaerat qui eos sit facilis enim quia quis.", + "created_at": "2016-03-22T15:13:44.837Z", + "updated_at": "2016-03-22T15:20:31.258Z", + "milestone_id": 10, + "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.", + "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": 1255, + "note": "Quibusdam rem aut similique ipsum recusandae ut accusamus.", + "noteable_type": "MergeRequest", + "author_id": 1, + "created_at": "2016-03-22T15:20:31.253Z", + "updated_at": "2016-03-22T15:20:31.253Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 12, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Administrator" + } + }, + { + "id": 1254, + "note": "Cumque sed omnis ipsa et magnam dolorem et.", + "noteable_type": "MergeRequest", + "author_id": 3, + "created_at": "2016-03-22T15:20:31.224Z", + "updated_at": "2016-03-22T15:20:31.224Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 12, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Alexie Trantow" + } + }, + { + "id": 1253, + "note": "Molestiae beatae id consequatur nam minus quia.", + "noteable_type": "MergeRequest", + "author_id": 4, + "created_at": "2016-03-22T15:20:31.195Z", + "updated_at": "2016-03-22T15:20:31.195Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 12, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Julius Moore" + } + }, + { + "id": 1252, + "note": "Voluptatem dolorem dignissimos itaque tempora quas ut.", + "noteable_type": "MergeRequest", + "author_id": 10, + "created_at": "2016-03-22T15:20:31.166Z", + "updated_at": "2016-03-22T15:20:31.166Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 12, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Robyn McCullough Jr." + } + }, + { + "id": 1251, + "note": "Debitis qui quibusdam voluptas repellat veritatis dicta rerum id.", + "noteable_type": "MergeRequest", + "author_id": 12, + "created_at": "2016-03-22T15:20:31.137Z", + "updated_at": "2016-03-22T15:20:31.137Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 12, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Vladimir McCullough" + } + }, + { + "id": 1250, + "note": "Suscipit optio ad voluptatem dignissimos temporibus amet molestias ut.", + "noteable_type": "MergeRequest", + "author_id": 22, + "created_at": "2016-03-22T15:20:31.107Z", + "updated_at": "2016-03-22T15:20:31.107Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 12, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 0" + } + }, + { + "id": 1249, + "note": "Nemo aut vitae et ducimus autem ex dolores.", + "noteable_type": "MergeRequest", + "author_id": 24, + "created_at": "2016-03-22T15:20:31.073Z", + "updated_at": "2016-03-22T15:20:31.073Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 12, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 2" + } + }, + { + "id": 1248, + "note": "Repellendus eaque ex molestiae laudantium placeat quidem vitae recusandae.", + "noteable_type": "MergeRequest", + "author_id": 26, + "created_at": "2016-03-22T15:20:31.038Z", + "updated_at": "2016-03-22T15:20:31.038Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 12, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 4" + } + } + ], + "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" + } + ], + "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" + } + }, + { + "id": 11, + "target_branch": "test-3", + "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, + "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.", + "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": 1263, + "note": "Beatae incidunt exercitationem voluptates recusandae fuga quia enim.", + "noteable_type": "MergeRequest", + "author_id": 1, + "created_at": "2016-03-22T15:20:31.883Z", + "updated_at": "2016-03-22T15:20:31.883Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 11, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Administrator" + } + }, + { + "id": 1262, + "note": "Illum sunt id consequuntur fugit et quo ullam eum.", + "noteable_type": "MergeRequest", + "author_id": 3, + "created_at": "2016-03-22T15:20:31.860Z", + "updated_at": "2016-03-22T15:20:31.860Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 11, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Alexie Trantow" + } + }, + { + "id": 1261, + "note": "Alias reiciendis autem ipsa sequi autem nemo odio.", + "noteable_type": "MergeRequest", + "author_id": 4, + "created_at": "2016-03-22T15:20:31.456Z", + "updated_at": "2016-03-22T15:20:31.456Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 11, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Julius Moore" + } + }, + { + "id": 1260, + "note": "Maxime nisi odit eos nulla vel ex accusamus velit.", + "noteable_type": "MergeRequest", + "author_id": 10, + "created_at": "2016-03-22T15:20:31.426Z", + "updated_at": "2016-03-22T15:20:31.426Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 11, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Robyn McCullough Jr." + } + }, + { + "id": 1259, + "note": "Excepturi et qui sapiente ut ducimus sunt nesciunt.", + "noteable_type": "MergeRequest", + "author_id": 12, + "created_at": "2016-03-22T15:20:31.397Z", + "updated_at": "2016-03-22T15:20:31.397Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 11, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Vladimir McCullough" + } + }, + { + "id": 1258, + "note": "Quis rerum dolores et dolorem modi neque ullam doloribus.", + "noteable_type": "MergeRequest", + "author_id": 22, + "created_at": "2016-03-22T15:20:31.364Z", + "updated_at": "2016-03-22T15:20:31.364Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 11, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 0" + } + }, + { + "id": 1257, + "note": "Voluptatum et mollitia neque aut.", + "noteable_type": "MergeRequest", + "author_id": 24, + "created_at": "2016-03-22T15:20:31.328Z", + "updated_at": "2016-03-22T15:20:31.328Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 11, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 2" + } + }, + { + "id": 1256, + "note": "Rerum laudantium dolor natus doloribus voluptas aliquid a.", + "noteable_type": "MergeRequest", + "author_id": 26, + "created_at": "2016-03-22T15:20:31.298Z", + "updated_at": "2016-03-22T15:20:31.298Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 11, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 4" + } + } + ], + "merge_request_diff": { + "id": 11, + "state": "collected", + "st_commits": [ + { + "id": "f998ac87ac9244f15e9c15109a6f4e62a54b779d", + "message": "fixes #10\n", + "parent_ids": [ + "be93687618e4b132087f430a4d8fc3a609c9b77c" + ], + "authored_date": "2016-01-19T14:43:23.000+01:00", + "author_name": "Test Lopez", + "author_email": "Test@Testlopez.es", + "committed_date": "2016-01-19T14:43:23.000+01:00", + "committer_name": "Test Lopez", + "committer_email": "Test@Testlopez.es" + } + ], + "st_diffs": [ + { + "diff": "--- /dev/null\n+++ b/test\n", + "new_path": "test", + "old_path": "test", + "a_mode": "0", + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + } + ], + "merge_request_id": 11, + "created_at": "2016-03-22T15:13:44.497Z", + "updated_at": "2016-03-22T15:13:44.547Z", + "base_commit_sha": "be93687618e4b132087f430a4d8fc3a609c9b77c", + "real_size": "1" + } + }, + { + "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, + "is_award": false, + "author": { + "name": "Administrator" + } + }, + { + "id": 1270, + "note": "Sed deserunt et explicabo rem repellat voluptatem.", + "noteable_type": "MergeRequest", + "author_id": 3, + "created_at": "2016-03-22T15:20:32.070Z", + "updated_at": "2016-03-22T15:20:32.070Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 10, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Alexie Trantow" + } + }, + { + "id": 1269, + "note": "Veritatis architecto omnis consequatur et optio.", + "noteable_type": "MergeRequest", + "author_id": 4, + "created_at": "2016-03-22T15:20:32.046Z", + "updated_at": "2016-03-22T15:20:32.046Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 10, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Julius Moore" + } + }, + { + "id": 1268, + "note": "Omnis suscipit odio molestiae debitis quia autem magni.", + "noteable_type": "MergeRequest", + "author_id": 10, + "created_at": "2016-03-22T15:20:32.019Z", + "updated_at": "2016-03-22T15:20:32.019Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 10, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Robyn McCullough Jr." + } + }, + { + "id": 1267, + "note": "Molestias est sunt est tempora consequatur cupiditate magnam.", + "noteable_type": "MergeRequest", + "author_id": 12, + "created_at": "2016-03-22T15:20:31.993Z", + "updated_at": "2016-03-22T15:20:31.993Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 10, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Vladimir McCullough" + } + }, + { + "id": 1266, + "note": "Ratione blanditiis eveniet voluptatem nostrum rerum excepturi in molestiae.", + "noteable_type": "MergeRequest", + "author_id": 22, + "created_at": "2016-03-22T15:20:31.969Z", + "updated_at": "2016-03-22T15:20:31.969Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 10, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 0" + } + }, + { + "id": 1265, + "note": "Illo voluptatibus vel odio ea.", + "noteable_type": "MergeRequest", + "author_id": 24, + "created_at": "2016-03-22T15:20:31.944Z", + "updated_at": "2016-03-22T15:20:31.944Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 10, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 2" + } + }, + { + "id": 1264, + "note": "Earum veritatis quis facere itaque iure.", + "noteable_type": "MergeRequest", + "author_id": 26, + "created_at": "2016-03-22T15:20:31.919Z", + "updated_at": "2016-03-22T15:20:31.919Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 10, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "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/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": 10, + "created_at": "2016-03-22T15:13:44.107Z", + "updated_at": "2016-03-22T15:13:44.190Z", + "base_commit_sha": "be93687618e4b132087f430a4d8fc3a609c9b77c", + "real_size": "1" + } + }, + { + "id": 9, + "target_branch": "test-8", + "source_branch": "test-9", + "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, + "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.", + "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": 1279, + "note": "A corrupti nesciunt pariatur ea.", + "noteable_type": "MergeRequest", + "author_id": 1, + "created_at": "2016-03-22T15:20:32.307Z", + "updated_at": "2016-03-22T15:20:32.307Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 9, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Administrator" + } + }, + { + "id": 1278, + "note": "Adipisci aut ut et voluptate numquam.", + "noteable_type": "MergeRequest", + "author_id": 3, + "created_at": "2016-03-22T15:20:32.281Z", + "updated_at": "2016-03-22T15:20:32.281Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 9, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Alexie Trantow" + } + }, + { + "id": 1277, + "note": "Adipisci voluptatem quod ut placeat repellendus deleniti.", + "noteable_type": "MergeRequest", + "author_id": 4, + "created_at": "2016-03-22T15:20:32.255Z", + "updated_at": "2016-03-22T15:20:32.255Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 9, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Julius Moore" + } + }, + { + "id": 1276, + "note": "Vitae et doloremque aut et aspernatur velit placeat sed.", + "noteable_type": "MergeRequest", + "author_id": 10, + "created_at": "2016-03-22T15:20:32.230Z", + "updated_at": "2016-03-22T15:20:32.230Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 9, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Robyn McCullough Jr." + } + }, + { + "id": 1275, + "note": "Quos cupiditate nesciunt expedita aspernatur.", + "noteable_type": "MergeRequest", + "author_id": 12, + "created_at": "2016-03-22T15:20:32.207Z", + "updated_at": "2016-03-22T15:20:32.207Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 9, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "Vladimir McCullough" + } + }, + { + "id": 1274, + "note": "Optio rem inventore dicta praesentium sit.", + "noteable_type": "MergeRequest", + "author_id": 22, + "created_at": "2016-03-22T15:20:32.181Z", + "updated_at": "2016-03-22T15:20:32.181Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 9, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 0" + } + }, + { + "id": 1273, + "note": "Sit incidunt molestiae maxime officiis rerum necessitatibus.", + "noteable_type": "MergeRequest", + "author_id": 24, + "created_at": "2016-03-22T15:20:32.159Z", + "updated_at": "2016-03-22T15:20:32.159Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 9, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 2" + } + }, + { + "id": 1272, + "note": "Autem ut non itaque molestiae nisi quia officiis doloribus.", + "noteable_type": "MergeRequest", + "author_id": 26, + "created_at": "2016-03-22T15:20:32.129Z", + "updated_at": "2016-03-22T15:20:32.129Z", + "project_id": 5, + "attachment": { + "url": null + }, + "line_code": null, + "commit_id": null, + "noteable_id": 9, + "system": false, + "st_diff": null, + "updated_by_id": null, + "is_award": false, + "author": { + "name": "User 4" + } + } + ], + "merge_request_diff": { + "id": 9, + "state": "collected", + "st_commits": [ + { + "id": "e239ba8c97b80b2874579a4d625ea9628f4c8ff5", + "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" + } + ], + "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": 9, + "created_at": "2016-03-22T15:13:43.794Z", + "updated_at": "2016-03-22T15:13:43.848Z", + "base_commit_sha": "be93687618e4b132087f430a4d8fc3a609c9b77c", + "real_size": "1" + } } ], "ci_commits": [ { - "id": 2, - "project_id": 6, + "id": 36, + "project_id": 5, "ref": "master", - "sha": "5937ac0a7beb003549fc5fd26fc247adbce4a52e", + "sha": "be93687618e4b132087f430a4d8fc3a609c9b77c", "before_sha": null, "push_data": null, - "created_at": "2016-04-13T14:40:37.759Z", - "updated_at": "2016-04-13T14:40:37.759Z", - "tag": false, + "created_at": "2016-03-22T15:20:35.755Z", + "updated_at": "2016-03-22T15:20:35.755Z", + "tag": null, "yaml_errors": null, "committed_at": null, - "gl_project_id": 6, + "gl_project_id": 5, + "status": "failed", + "started_at": null, + "finished_at": null, + "duration": null, "statuses": [ { - "id": 1, - "project_id": null, - "status": "success", - "finished_at": "2016-01-26T07:23:42.000Z", + "id": 71, + "project_id": 5, + "status": "failed", + "finished_at": "2016-03-29T06:28:12.630Z", "trace": null, - "created_at": "2016-04-13T14:40:37.717Z", - "updated_at": "2016-04-13T14:40:37.771Z", - "started_at": "2016-01-26T07:21:42.000Z", + "created_at": "2016-03-22T15:20:35.772Z", + "updated_at": "2016-03-29T06:28:12.634Z", + "started_at": null, "runner_id": null, "coverage": null, - "commit_id": 2, - "commands": null, + "commit_id": 36, + "commands": "$ build command", "job_id": null, - "name": "default", + "name": "test build 1", "deploy": false, "options": null, "allow_failure": false, - "stage": null, + "stage": "test", "trigger_request_id": null, - "stage_idx": null, + "stage_idx": 1, "tag": null, - "ref": null, + "ref": "master", "user_id": null, "target_url": null, - "description": "commit status", - "artifacts_file": null, - "gl_project_id": 7, - "artifacts_metadata": null, + "description": null, + "artifacts_file": { + "url": null + }, + "gl_project_id": 5, + "artifacts_metadata": { + "url": null + }, + "erased_by_id": null, + "erased_at": null + }, + { + "id": 72, + "project_id": 5, + "status": "success", + "finished_at": null, + "trace": "Porro ea qui ut dolores. Labore ab nemo explicabo aspernatur quis voluptates corporis. Et quasi delectus est sit aperiam perspiciatis asperiores. Repudiandae cum aut consectetur accusantium officia sunt.\n\nQuidem dolore iusto quaerat ut aut inventore et molestiae. Libero voluptates atque nemo qui. Nulla temporibus ipsa similique facere.\n\nAliquam ipsam perferendis qui fugit accusantium omnis id voluptatum. Dignissimos aliquid dicta eos voluptatem assumenda quia. Sed autem natus unde dolor et non nisi et. Consequuntur nihil consequatur rerum est.\n\nSimilique neque est iste ducimus qui fuga cupiditate. Libero autem est aut fuga. Consectetur natus quis non ducimus ut dolore. Magni voluptatibus eius et maxime aut.\n\nAd officiis tempore voluptate vitae corrupti explicabo labore est. Consequatur expedita et sunt nihil aut. Deleniti porro iusto molestiae et beatae.\n\nDeleniti modi nulla qui et labore sequi corrupti. Qui voluptatem assumenda eum cupiditate et. Nesciunt ipsam ut ea possimus eum. Consectetur quidem suscipit atque dolore itaque voluptatibus et cupiditate.", + "created_at": "2016-03-22T15:20:35.777Z", + "updated_at": "2016-03-22T15:20:35.777Z", + "started_at": null, + "runner_id": null, + "coverage": null, + "commit_id": 36, + "commands": "$ build command", + "job_id": null, + "name": "test build 2", + "deploy": false, + "options": null, + "allow_failure": false, + "stage": "test", + "trigger_request_id": null, + "stage_idx": 1, + "tag": null, + "ref": "master", + "user_id": null, + "target_url": null, + "description": null, + "artifacts_file": { + "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/72/p5_build_artifacts.zip" + }, + "gl_project_id": 5, + "artifacts_metadata": { + "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/72/p5_build_artifacts_metadata.gz" + }, + "erased_by_id": null, + "erased_at": null + } + ] + }, + { + "id": 37, + "project_id": 5, + "ref": "master", + "sha": "048721d90c449b244b7b4c53a9186b04330174ec", + "before_sha": null, + "push_data": null, + "created_at": "2016-03-22T15:20:35.757Z", + "updated_at": "2016-03-22T15:20:35.757Z", + "tag": null, + "yaml_errors": null, + "committed_at": null, + "gl_project_id": 5, + "status": "failed", + "started_at": null, + "finished_at": null, + "duration": null, + "statuses": [ + { + "id": 74, + "project_id": 5, + "status": "success", + "finished_at": null, + "trace": "Ad ut quod repudiandae iste dolor doloribus. Adipisci consequuntur deserunt omnis quasi eveniet et sed fugit. Aut nemo omnis molestiae impedit ex consequatur ducimus. Voluptatum exercitationem quia aut est et hic dolorem.\n\nQuasi repellendus et eaque magni eum facilis. Dolorem aperiam nam nihil pariatur praesentium ad aliquam. Commodi enim et eos tenetur. Odio voluptatibus laboriosam mollitia rerum exercitationem magnam consequuntur. Tenetur ea vel eum corporis.\n\nVoluptatibus optio in aliquid est voluptates. Ad a ut ab placeat vero blanditiis. Earum aspernatur quia beatae expedita voluptatem dignissimos provident. Quis minima id nemo ut aut est veritatis provident.\n\nRerum voluptatem quidem eius maiores magnam veniam. Voluptatem aperiam aut voluptate et nulla deserunt voluptas. Quaerat aut accusantium laborum est dolorem architecto reiciendis. Aliquam asperiores doloribus omnis maxime enim nesciunt. Eum aut rerum repellendus debitis et ut eius.\n\nQuaerat assumenda ea sit consequatur autem in. Cum eligendi voluptatem quo sed. Ut fuga iusto cupiditate autem sint.\n\nOfficia totam officiis architecto corporis molestiae amet ut. Tempora sed dolorum rerum omnis voluptatem accusantium sit eum. Quia debitis ipsum quidem aliquam inventore sunt consequatur qui.", + "created_at": "2016-03-22T15:20:35.846Z", + "updated_at": "2016-03-22T15:20:35.846Z", + "started_at": null, + "runner_id": null, + "coverage": null, + "commit_id": 37, + "commands": "$ build command", + "job_id": null, + "name": "test build 2", + "deploy": false, + "options": null, + "allow_failure": false, + "stage": "test", + "trigger_request_id": null, + "stage_idx": 1, + "tag": null, + "ref": "master", + "user_id": null, + "target_url": null, + "description": null, + "artifacts_file": { + "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/74/p5_build_artifacts.zip" + }, + "gl_project_id": 5, + "artifacts_metadata": { + "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/74/p5_build_artifacts_metadata.gz" + }, + "erased_by_id": null, + "erased_at": null + }, + { + "id": 73, + "project_id": 5, + "status": "canceled", + "finished_at": null, + "trace": null, + "created_at": "2016-03-22T15:20:35.842Z", + "updated_at": "2016-03-22T15:20:35.842Z", + "started_at": null, + "runner_id": null, + "coverage": null, + "commit_id": 37, + "commands": "$ build command", + "job_id": null, + "name": "test build 1", + "deploy": false, + "options": null, + "allow_failure": false, + "stage": "test", + "trigger_request_id": null, + "stage_idx": 1, + "tag": null, + "ref": "master", + "user_id": null, + "target_url": null, + "description": null, + "artifacts_file": { + "url": null + }, + "gl_project_id": 5, + "artifacts_metadata": { + "url": null + }, + "erased_by_id": null, + "erased_at": null + } + ] + }, + { + "id": 38, + "project_id": 5, + "ref": "master", + "sha": "5f923865dde3436854e9ceb9cdb7815618d4e849", + "before_sha": null, + "push_data": null, + "created_at": "2016-03-22T15:20:35.759Z", + "updated_at": "2016-03-22T15:20:35.759Z", + "tag": null, + "yaml_errors": null, + "committed_at": null, + "gl_project_id": 5, + "status": "failed", + "started_at": null, + "finished_at": null, + "duration": null, + "statuses": [ + { + "id": 76, + "project_id": 5, + "status": "success", + "finished_at": null, + "trace": "Et rerum quia ea cumque ut modi non. Libero eaque ipsam architecto maiores expedita deleniti. Ratione quia qui est id.\n\nQuod sit officiis sed unde inventore veniam quisquam velit. Ea harum cum quibusdam quisquam minima quo possimus non. Temporibus itaque aliquam aut rerum veritatis at.\n\nMagnam ipsum eius recusandae qui quis sit maiores eum. Et animi iusto aut itaque. Doloribus harum deleniti nobis accusantium et libero.\n\nRerum fuga perferendis magni commodi officiis id repudiandae. Consequatur ratione consequatur suscipit facilis sunt iure est dicta. Qui unde quasi facilis et quae nesciunt. Magnam iste et nobis officiis tenetur. Aspernatur quo et temporibus non in.\n\nNisi rerum velit est ad enim sint molestiae consequuntur. Quaerat nisi nesciunt quasi officiis. Possimus non blanditiis laborum quos.\n\nRerum laudantium facere animi qui. Ipsa est iusto magnam nihil. Enim omnis occaecati non dignissimos ut recusandae eum quasi. Qui maxime dolor et nemo voluptates incidunt quia.", + "created_at": "2016-03-22T15:20:35.882Z", + "updated_at": "2016-03-22T15:20:35.882Z", + "started_at": null, + "runner_id": null, + "coverage": null, + "commit_id": 38, + "commands": "$ build command", + "job_id": null, + "name": "test build 2", + "deploy": false, + "options": null, + "allow_failure": false, + "stage": "test", + "trigger_request_id": null, + "stage_idx": 1, + "tag": null, + "ref": "master", + "user_id": null, + "target_url": null, + "description": null, + "artifacts_file": { + "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/76/p5_build_artifacts.zip" + }, + "gl_project_id": 5, + "artifacts_metadata": { + "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/76/p5_build_artifacts_metadata.gz" + }, + "erased_by_id": null, + "erased_at": null + }, + { + "id": 75, + "project_id": 5, + "status": "failed", + "finished_at": null, + "trace": "Sed et iste recusandae dicta corporis. Sunt alias porro fugit sunt. Fugiat omnis nihil dignissimos aperiam explicabo doloremque sit aut. Harum fugit expedita quia rerum ut consequatur laboriosam aliquam.\n\nNatus libero ut ut tenetur earum. Tempora omnis autem omnis et libero dolores illum autem. Deleniti eos sunt mollitia ipsam. Cum dolor repellendus dolorum sequi officia. Ullam sunt in aut pariatur excepturi.\n\nDolor nihil debitis et est eos. Cumque eos eum saepe ducimus autem. Alias architecto consequatur aut pariatur possimus. Aut quos aut incidunt quam velit et. Quas voluptatum ad dolorum dignissimos.\n\nUt voluptates consectetur illo et. Est commodi accusantium vel quo. Eos qui fugiat soluta porro.\n\nRatione possimus alias vel maxime sint totam est repellat. Ipsum corporis eos sint voluptatem eos odit. Temporibus libero nulla harum eligendi labore similique ratione magnam. Suscipit sequi in omnis neque.\n\nLaudantium dolor amet omnis placeat mollitia aut molestiae. Aut rerum similique ipsum quod illo quas unde. Sunt aut veritatis eos omnis porro. Rem veritatis mollitia praesentium dolorem. Consequatur sequi ad cumque earum omnis quia necessitatibus.", + "created_at": "2016-03-22T15:20:35.864Z", + "updated_at": "2016-03-22T15:20:35.864Z", + "started_at": null, + "runner_id": null, + "coverage": null, + "commit_id": 38, + "commands": "$ build command", + "job_id": null, + "name": "test build 1", + "deploy": false, + "options": null, + "allow_failure": false, + "stage": "test", + "trigger_request_id": null, + "stage_idx": 1, + "tag": null, + "ref": "master", + "user_id": null, + "target_url": null, + "description": null, + "artifacts_file": { + "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/75/p5_build_artifacts.zip" + }, + "gl_project_id": 5, + "artifacts_metadata": { + "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/75/p5_build_artifacts_metadata.gz" + }, + "erased_by_id": null, + "erased_at": null + } + ] + }, + { + "id": 39, + "project_id": 5, + "ref": "master", + "sha": "d2d430676773caa88cdaf7c55944073b2fd5561a", + "before_sha": null, + "push_data": null, + "created_at": "2016-03-22T15:20:35.761Z", + "updated_at": "2016-03-22T15:20:35.761Z", + "tag": null, + "yaml_errors": null, + "committed_at": null, + "gl_project_id": 5, + "status": "failed", + "started_at": null, + "finished_at": null, + "duration": null, + "statuses": [ + { + "id": 78, + "project_id": 5, + "status": "success", + "finished_at": null, + "trace": "Dolorem deserunt quas quia error hic quo cum vel. Natus voluptatem cumque expedita numquam odit. Eos expedita nostrum corporis consequatur est recusandae.\n\nCulpa blanditiis rerum repudiandae alias voluptatem. Velit iusto est ullam consequatur doloribus porro. Corporis voluptas consectetur est veniam et quia quae.\n\nEt aut magni fuga nesciunt officiis molestias. Quaerat et nam necessitatibus qui rerum. Architecto quia officiis voluptatem laborum est recusandae. Quasi ducimus soluta odit necessitatibus labore numquam dignissimos. Quia facere sint temporibus inventore sunt nihil saepe dolorum.\n\nFacere dolores quis dolores a. Est minus nostrum nihil harum. Earum laborum et ipsum unde neque sit nemo. Corrupti est consequatur minima fugit. Illum voluptatem illo error ducimus officia qui debitis.\n\nDignissimos porro a autem harum aut. Aut id reprehenderit et exercitationem. Est et quisquam ipsa temporibus molestiae. Architecto natus dolore qui fugiat incidunt. Autem odit veniam excepturi et voluptatibus culpa ipsum eos.\n\nAmet quo quisquam dignissimos soluta modi dolores. Sint omnis eius optio corporis dolor. Eligendi animi porro quia placeat ut.", + "created_at": "2016-03-22T15:20:35.927Z", + "updated_at": "2016-03-22T15:20:35.927Z", + "started_at": null, + "runner_id": null, + "coverage": null, + "commit_id": 39, + "commands": "$ build command", + "job_id": null, + "name": "test build 2", + "deploy": false, + "options": null, + "allow_failure": false, + "stage": "test", + "trigger_request_id": null, + "stage_idx": 1, + "tag": null, + "ref": "master", + "user_id": null, + "target_url": null, + "description": null, + "artifacts_file": { + "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/78/p5_build_artifacts.zip" + }, + "gl_project_id": 5, + "artifacts_metadata": { + "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/78/p5_build_artifacts_metadata.gz" + }, + "erased_by_id": null, + "erased_at": null + }, + { + "id": 77, + "project_id": 5, + "status": "failed", + "finished_at": null, + "trace": "Rerum ut et suscipit est perspiciatis. Inventore debitis cum eius vitae. Ex incidunt id velit aut quo nisi. Laboriosam repellat deserunt eius reiciendis architecto et. Est harum quos nesciunt nisi consectetur.\n\nAlias esse omnis sint officia est consequatur in nobis. Dignissimos dolorum vel eligendi nesciunt dolores sit. Veniam mollitia ducimus et exercitationem molestiae libero sed. Atque omnis debitis laudantium voluptatibus qui. Repellendus tempore est commodi pariatur.\n\nExpedita voluptate illum est alias non. Modi nesciunt ab assumenda laborum nulla consequatur molestias doloremque. Magnam quod officia vel explicabo accusamus ut voluptatem incidunt. Rerum ut aliquid ullam saepe. Est eligendi debitis beatae blanditiis reiciendis.\n\nQui fuga sit dolores libero maiores et suscipit. Consectetur asperiores omnis minima impedit eos fugiat. Similique omnis nisi sed vero inventore ipsum aliquam exercitationem.\n\nBlanditiis magni iure dolorum omnis ratione delectus molestiae. Atque officia dolor voluptatem culpa quod. Incidunt suscipit quidem possimus veritatis non vel. Iusto aliquid et id quia quasi.\n\nVel facere velit blanditiis incidunt cupiditate sed maiores consequuntur. Quasi quia dicta consequuntur et quia voluptatem iste id. Incidunt et rerum fuga esse sint.", + "created_at": "2016-03-22T15:20:35.905Z", + "updated_at": "2016-03-22T15:20:35.905Z", + "started_at": null, + "runner_id": null, + "coverage": null, + "commit_id": 39, + "commands": "$ build command", + "job_id": null, + "name": "test build 1", + "deploy": false, + "options": null, + "allow_failure": false, + "stage": "test", + "trigger_request_id": null, + "stage_idx": 1, + "tag": null, + "ref": "master", + "user_id": null, + "target_url": null, + "description": null, + "artifacts_file": { + "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/77/p5_build_artifacts.zip" + }, + "gl_project_id": 5, + "artifacts_metadata": { + "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/77/p5_build_artifacts_metadata.gz" + }, + "erased_by_id": null, + "erased_at": null + } + ] + }, + { + "id": 40, + "project_id": 5, + "ref": "master", + "sha": "2ea1f3dec713d940208fb5ce4a38765ecb5d3f73", + "before_sha": null, + "push_data": null, + "created_at": "2016-03-22T15:20:35.763Z", + "updated_at": "2016-03-22T15:20:35.763Z", + "tag": null, + "yaml_errors": null, + "committed_at": null, + "gl_project_id": 5, + "status": "failed", + "started_at": null, + "finished_at": null, + "duration": null, + "statuses": [ + { + "id": 79, + "project_id": 5, + "status": "failed", + "finished_at": "2016-03-29T06:28:12.695Z", + "trace": "Sed culpa est et facere saepe vel id ab. Quas temporibus aut similique dolorem consequatur corporis aut praesentium. Cum officia molestiae sit earum excepturi.\n\nSint possimus aut ratione quia. Quis nesciunt ratione itaque illo. Tenetur est dolor assumenda possimus voluptatem quia minima. Accusamus reprehenderit ut et itaque non reiciendis incidunt.\n\nRerum suscipit quibusdam dolore nam omnis. Consequatur ipsa nihil ut enim blanditiis delectus. Nulla quis hic occaecati mollitia qui placeat. Quo rerum sed perferendis a accusantium consequatur commodi ut. Sit quae et cumque vel eius tempora nostrum.\n\nUllam dolorem et itaque sint est. Ea molestias quia provident dolorem vitae error et et. Ea expedita officiis iste non. Qui vitae odit saepe illum. Dolores enim ratione deserunt tempore expedita amet non neque.\n\nEligendi asperiores voluptatibus omnis repudiandae expedita distinctio qui aliquid. Autem aut doloremque distinctio ab. Nostrum sapiente repudiandae aspernatur ea et quae voluptas. Officiis perspiciatis nisi laudantium asperiores error eligendi ab. Eius quia amet magni omnis exercitationem voluptatum et.\n\nVoluptatem ullam labore quas dicta est ex voluptas. Pariatur ea modi voluptas consequatur dolores perspiciatis similique. Numquam in distinctio perspiciatis ut qui earum. Quidem omnis mollitia facere aut beatae. Ea est iure et voluptatem.", + "created_at": "2016-03-22T15:20:35.950Z", + "updated_at": "2016-03-29T06:28:12.696Z", + "started_at": null, + "runner_id": null, + "coverage": null, + "commit_id": 40, + "commands": "$ build command", + "job_id": null, + "name": "test build 1", + "deploy": false, + "options": null, + "allow_failure": false, + "stage": "test", + "trigger_request_id": null, + "stage_idx": 1, + "tag": null, + "ref": "master", + "user_id": null, + "target_url": null, + "description": null, + "artifacts_file": { + "url": null + }, + "gl_project_id": 5, + "artifacts_metadata": { + "url": null + }, + "erased_by_id": null, + "erased_at": null + }, + { + "id": 80, + "project_id": 5, + "status": "success", + "finished_at": null, + "trace": "Impedit et optio nemo ipsa. Non ad non quis ut sequi laudantium omnis velit. Corporis a enim illo eos. Quia totam tempore inventore ad est.\n\nNihil recusandae cupiditate eaque voluptatem molestias sint. Consequatur id voluptatem cupiditate harum. Consequuntur iusto quaerat reiciendis aut autem libero est. Quisquam dolores veritatis rerum et sint maxime ullam libero. Id quas porro ut perspiciatis rem amet vitae.\n\nNemo inventore minus blanditiis magnam. Modi consequuntur nostrum aut voluptatem ex. Sunt rerum rem optio mollitia qui aliquam officiis officia. Aliquid eos et id aut minus beatae reiciendis.\n\nDolores non in temporibus dicta. Fugiat voluptatem est aspernatur expedita voluptatum nam qui. Quia et eligendi sit quae sint tempore exercitationem eos. Est sapiente corrupti quidem at. Qui magni odio repudiandae saepe tenetur optio dolore.\n\nEos placeat soluta at dolorem adipisci provident. Quo commodi id reprehenderit possimus quo tenetur. Ipsum et quae eligendi laborum. Et qui nesciunt at quasi quidem voluptatem cum rerum. Excepturi non facilis aut sunt vero sed.\n\nQui explicabo ratione ut eligendi recusandae. Quis quasi quas molestiae consequatur voluptatem et voluptatem. Ex repellat saepe occaecati aperiam ea eveniet dignissimos facilis.", + "created_at": "2016-03-22T15:20:35.966Z", + "updated_at": "2016-03-22T15:20:35.966Z", + "started_at": null, + "runner_id": null, + "coverage": null, + "commit_id": 40, + "commands": "$ build command", + "job_id": null, + "name": "test build 2", + "deploy": false, + "options": null, + "allow_failure": false, + "stage": "test", + "trigger_request_id": null, + "stage_idx": 1, + "tag": null, + "ref": "master", + "user_id": null, + "target_url": null, + "description": null, + "artifacts_file": { + "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/80/p5_build_artifacts.zip" + }, + "gl_project_id": 5, + "artifacts_metadata": { + "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/80/p5_build_artifacts_metadata.gz" + }, "erased_by_id": null, "erased_at": null } From c487e6d311957984da95d19ed8d63b068c6da228 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 13 May 2016 16:24:32 +0200 Subject: [PATCH 156/730] updated spec file --- .../import_export/test_project_export.tar.gz | Bin 338822 -> 339384 bytes 1 file changed, 0 insertions(+), 0 deletions(-) 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 f2c3c3cd2dc67ba456501a8ba754edf74cdaba9a..aef4af6998ee729c2eea80c9d2423fc787083950 100644 GIT binary patch delta 77228 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 delta 74146 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 z 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 Date: Mon, 16 May 2016 15:29:14 +0200 Subject: [PATCH 173/730] fix issue with forked MRs --- lib/gitlab/import_export/relation_factory.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb index 3b27f133ec..082398d1f0 100644 --- a/lib/gitlab/import_export/relation_factory.rb +++ b/lib/gitlab/import_export/relation_factory.rb @@ -53,11 +53,19 @@ module Gitlab def update_project_references(relation_hash, klass) project_id = relation_hash.delete('project_id') + if relation_hash['source_project_id'] && relation_hash['target_project_id'] + # If source and target are the same, populate them with the new project ID. + if relation_hash['target_project_id'] == relation_hash['source_project_id'] + relation_hash['source_project_id'] = project_id + else + relation_hash['source_project_id'] = -1 + end + end + relation_hash['target_project_id'] = project_id if relation_hash['target_project_id'] + # project_id may not be part of the export, but we always need to populate it if required. relation_hash['project_id'] = project_id if klass.column_names.include?('project_id') relation_hash['gl_project_id'] = project_id if relation_hash ['gl_project_id'] - relation_hash['target_project_id'] = project_id if relation_hash['target_project_id'] - relation_hash['source_project_id'] = -1 if relation_hash['source_project_id'] end def relation_class(relation_sym) From 07c642cb1342c82ff04681964754bc654450ec16 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 17 May 2016 09:39:34 +0200 Subject: [PATCH 174/730] updated routes for gitlab_project --- config/routes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/routes.rb b/config/routes.rb index 08598e36fe..a528e0b494 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -159,7 +159,7 @@ Rails.application.routes.draw do post :create_user_map, path: :user_map end - resource :gitlab_project, only: [:create, :new], controller: :gitlab_projects do + resource :gitlab_project, only: [:create, :new] do post :create end end From f48184cbc6d8951156ac5af6821f0a47dbc1c588 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 17 May 2016 09:40:49 +0200 Subject: [PATCH 175/730] updated routes for gitlab_projects --- config/routes.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index 8ad0b4874d..ad44c8f05b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -159,10 +159,8 @@ Rails.application.routes.draw do post :create_user_map, path: :user_map end - resource :gitlab_project, only: [:create, :new], controller: :gitlab_projects do - get :status - get :callback - get :jobs + resource :gitlab_project, only: [:create, :new] do + post :create end end From 7733f56d80f84ada4c4fef8cc4a5ab9357af0dc5 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 17 May 2016 16:28:27 +0200 Subject: [PATCH 176/730] fix specs --- lib/gitlab/import_export/project_tree_saver.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/gitlab/import_export/project_tree_saver.rb b/lib/gitlab/import_export/project_tree_saver.rb index 631746a47f..a2c5df8af2 100644 --- a/lib/gitlab/import_export/project_tree_saver.rb +++ b/lib/gitlab/import_export/project_tree_saver.rb @@ -10,6 +10,8 @@ module Gitlab end def save + FileUtils.mkdir_p(@shared.export_path) + File.write(full_path, project_json_tree) true rescue => e From bcda64c75c15e2fb1343378a9d07e4659ae4acda Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 18 May 2016 10:39:53 +0200 Subject: [PATCH 177/730] added DB configuration --- lib/gitlab/import_export/import_export.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml index 66e6ae86cf..ae2bf677c9 100644 --- a/lib/gitlab/import_export/import_export.yml +++ b/lib/gitlab/import_export/import_export.yml @@ -16,6 +16,13 @@ project_tree: - :merge_request_diff - ci_commits: - :statuses + - :builds + - :variables + - :triggers + - :deploy_keys + - :services + - :hooks + - :protected_branches # Only include the following attributes for the models specified. included_attributes: From ee2993040c207f70bf05a730b9389a54928e5a54 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 18 May 2016 11:20:38 +0200 Subject: [PATCH 178/730] updated test file with DB config --- .../import_export/test_project_export.tar.gz | Bin 339482 -> 340727 bytes 1 file changed, 0 insertions(+), 0 deletions(-) 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 4f2ec49e9b51682a2813d3d310ea899a2ff361f3..380696d5ab5b71539efffb0e221d5a6a80a3e435 100644 GIT binary patch delta 78539 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 T=FFM18*2Xo^f_;h00;*FzGx@D From 4d894a7a953f18d8a71f003677b5f8ea5bbc1779 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 18 May 2016 14:32:30 +0200 Subject: [PATCH 179/730] added commits mapper and DB config import stuff --- lib/gitlab/import_export/commit_mapper.rb | 49 ++++++++++++++ .../import_export/project_tree_restorer.rb | 14 +++- lib/gitlab/import_export/relation_factory.rb | 64 +++++++++++++------ 3 files changed, 105 insertions(+), 22 deletions(-) create mode 100644 lib/gitlab/import_export/commit_mapper.rb diff --git a/lib/gitlab/import_export/commit_mapper.rb b/lib/gitlab/import_export/commit_mapper.rb new file mode 100644 index 0000000000..405149d3cd --- /dev/null +++ b/lib/gitlab/import_export/commit_mapper.rb @@ -0,0 +1,49 @@ +module Gitlab + module ImportExport + class CommitMapper + def initialize(commits:, members_map:, project_id:, relation_factory: Gitlab::ImportExport::RelationFactory, user_admin:) + @commits = commits + @members_map = members_map + @project_id = project_id + @relation_factory = relation_factory + @user_admin = user_admin + end + + def ids_map + @ids_map ||= map_commits + end + + def map_commits + @id_map = Hash.new(-1) + + @commits.each do |commit_hash| + @relation_factory.update_user_references(commit_hash, @members_map) + + commit_hash['project_id'] = @project_id + @relation_factory.update_project_references(commit_hash, Ci::Commit) + create_commit_statuses(commit_hash) + create_commit(commit_hash) + end + @id_map + end + + def create_commit(commit_hash) + old_id = commit_hash.delete('id') + commit = Ci::Commit.new(commit_hash) + commit.save! + @id_map[old_id] = commit.id + end + + def create_commit_statuses(commit_hash) + commit_hash['statuses'].map! do |status_hash| + @relation_factory.create(relation_sym: :statuses, + relation_hash: status_hash.merge('project_id' => @project_id, + 'commit_id' => nil), + members_mapper: @members_map, + commits_mapper: nil, + user_admin: @user_admin) + end + end + end + end +end diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index 911ba06e74..750b69caaf 100644 --- a/lib/gitlab/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -14,6 +14,7 @@ module Gitlab json = IO.read(@path) @tree_hash = ActiveSupport::JSON.decode(json) @project_members = @tree_hash.delete('project_members') + @commits = @tree_hash.delete('ci_commits') create_relations rescue => e @shared.error(e) @@ -32,6 +33,13 @@ module Gitlab project: project) end + def commits_mapper + @commits_mapper ||= Gitlab::ImportExport::CommitMapper.new(commits: @commits, + members_map: members_mapper.map, + project_id: project.id, + user_admin: @user.is_admin?) + end + def create_relations(relation_list = default_relation_list, tree_hash = @tree_hash) saved = [] relation_list.each do |relation| @@ -47,7 +55,7 @@ module Gitlab def default_relation_list Gitlab::ImportExport::ImportExportReader.new(shared: @shared).tree.reject do |model| - model.is_a?(Hash) && model[:project_members] + model.is_a?(Hash) && (model[:project_members] || model[:ci_commits]) end end @@ -65,9 +73,8 @@ module Gitlab relation_key = relation.keys.first.to_s tree_hash[relation_key].each do |relation_item| relation.values.flatten.each do |sub_relation| - if sub_relation.is_a?(Hash) - relation_hash = relation_item[sub_relation.keys.first.to_s] + relation_hash = relation_item[sub_relation.keys.first.to_s] sub_relation = sub_relation.keys.first else relation_hash = relation_item[sub_relation.to_s] @@ -97,6 +104,7 @@ module Gitlab Gitlab::ImportExport::RelationFactory.create(relation_sym: relation.to_sym, relation_hash: relation_hash.merge('project_id' => project.id), members_mapper: members_mapper, + commits_mapper: commits_mapper, user_admin: @user.is_admin?) end end diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb index 082398d1f0..7f0f8f8077 100644 --- a/lib/gitlab/import_export/relation_factory.rb +++ b/lib/gitlab/import_export/relation_factory.rb @@ -3,21 +3,27 @@ module Gitlab module RelationFactory extend self - OVERRIDES = { snippets: :project_snippets, ci_commits: 'Ci::Commit', statuses: 'commit_status' }.freeze - USER_REFERENCES = %w(author_id assignee_id updated_by_id).freeze + OVERRIDES = { snippets: :project_snippets, + ci_commits: 'Ci::Commit', + statuses: 'commit_status', + variables: 'Ci::Variable', + triggers: 'Ci::Trigger', + builds: 'Ci::Build', + hooks: 'ProjectHook' }.freeze + USER_REFERENCES = %w(author_id assignee_id updated_by_id user_id).freeze - def create(relation_sym:, relation_hash:, members_mapper:, user_admin:) + def create(relation_sym:, relation_hash:, members_mapper:, commits_mapper:, user_admin:) relation_sym = parse_relation_sym(relation_sym) klass = parse_relation(relation_hash, relation_sym) update_missing_author(relation_hash, members_mapper, user_admin) if relation_sym == :notes update_user_references(relation_hash, members_mapper.map) update_project_references(relation_hash, klass) + update_commit_references(relation_hash, commits_mapper.ids_map) if commits_mapper - imported_object(klass, relation_hash) + generate_imported_object(klass, relation_hash, relation_sym) end - private def update_user_references(relation_hash, members_map) USER_REFERENCES.each do |reference| @@ -27,6 +33,32 @@ module Gitlab end end + def update_project_references(relation_hash, klass) + project_id = relation_hash.delete('project_id') + + if relation_hash['source_project_id'] && relation_hash['target_project_id'] + # If source and target are the same, populate them with the new project ID. + if relation_hash['target_project_id'] == relation_hash['source_project_id'] + relation_hash['source_project_id'] = project_id + else + relation_hash['source_project_id'] = -1 + end + end + relation_hash['target_project_id'] = project_id if relation_hash['target_project_id'] + + # project_id may not be part of the export, but we always need to populate it if required. + relation_hash['project_id'] = project_id if klass.column_names.include?('project_id') + relation_hash['gl_project_id'] = project_id if relation_hash['gl_project_id'] + end + + private + + def update_commit_references(relation_hash, commit_ids_map) + return unless relation_hash['commit_id'] + old_commit_id = relation_hash['commit_id'] + relation_hash['commit_id'] = commit_ids_map[old_commit_id] + end + def update_missing_author(relation_hash, members_map, user_admin) old_author_id = relation_hash['author_id'] @@ -50,22 +82,15 @@ module Gitlab "\n\n *By #{author_name} on #{timestamp} (imported from GitLab project)*" end - def update_project_references(relation_hash, klass) - project_id = relation_hash.delete('project_id') - - if relation_hash['source_project_id'] && relation_hash['target_project_id'] - # If source and target are the same, populate them with the new project ID. - if relation_hash['target_project_id'] == relation_hash['source_project_id'] - relation_hash['source_project_id'] = project_id - else - relation_hash['source_project_id'] = -1 + def generate_imported_object(klass, relation_hash, relation_sym) + if relation_sym == 'Ci::Build' # call #trace= method after assigning the other attributes + trace = relation_hash.delete('trace') + imported_object(klass, relation_hash) do |imported_object| + imported_object.trace = trace end + else + imported_object(klass, relation_hash) end - relation_hash['target_project_id'] = project_id if relation_hash['target_project_id'] - - # project_id may not be part of the export, but we always need to populate it if required. - relation_hash['project_id'] = project_id if klass.column_names.include?('project_id') - relation_hash['gl_project_id'] = project_id if relation_hash ['gl_project_id'] end def relation_class(relation_sym) @@ -78,6 +103,7 @@ module Gitlab def imported_object(klass, relation_hash) imported_object = klass.new(relation_hash) + yield(imported_object) if block_given? imported_object.importing = true if imported_object.respond_to?(:importing) imported_object end From 0df21ac712d7afd99b0d38a52e7375b11a4fe269 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 18 May 2016 15:15:14 +0200 Subject: [PATCH 180/730] revert changes as builds are related to statuses which are already there --- lib/gitlab/import_export/commit_mapper.rb | 49 -------------- .../import_export/project_tree_restorer.rb | 14 +--- lib/gitlab/import_export/relation_factory.rb | 64 ++++++------------- 3 files changed, 22 insertions(+), 105 deletions(-) delete mode 100644 lib/gitlab/import_export/commit_mapper.rb diff --git a/lib/gitlab/import_export/commit_mapper.rb b/lib/gitlab/import_export/commit_mapper.rb deleted file mode 100644 index 405149d3cd..0000000000 --- a/lib/gitlab/import_export/commit_mapper.rb +++ /dev/null @@ -1,49 +0,0 @@ -module Gitlab - module ImportExport - class CommitMapper - def initialize(commits:, members_map:, project_id:, relation_factory: Gitlab::ImportExport::RelationFactory, user_admin:) - @commits = commits - @members_map = members_map - @project_id = project_id - @relation_factory = relation_factory - @user_admin = user_admin - end - - def ids_map - @ids_map ||= map_commits - end - - def map_commits - @id_map = Hash.new(-1) - - @commits.each do |commit_hash| - @relation_factory.update_user_references(commit_hash, @members_map) - - commit_hash['project_id'] = @project_id - @relation_factory.update_project_references(commit_hash, Ci::Commit) - create_commit_statuses(commit_hash) - create_commit(commit_hash) - end - @id_map - end - - def create_commit(commit_hash) - old_id = commit_hash.delete('id') - commit = Ci::Commit.new(commit_hash) - commit.save! - @id_map[old_id] = commit.id - end - - def create_commit_statuses(commit_hash) - commit_hash['statuses'].map! do |status_hash| - @relation_factory.create(relation_sym: :statuses, - relation_hash: status_hash.merge('project_id' => @project_id, - 'commit_id' => nil), - members_mapper: @members_map, - commits_mapper: nil, - user_admin: @user_admin) - end - end - end - end -end diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index 750b69caaf..911ba06e74 100644 --- a/lib/gitlab/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -14,7 +14,6 @@ module Gitlab json = IO.read(@path) @tree_hash = ActiveSupport::JSON.decode(json) @project_members = @tree_hash.delete('project_members') - @commits = @tree_hash.delete('ci_commits') create_relations rescue => e @shared.error(e) @@ -33,13 +32,6 @@ module Gitlab project: project) end - def commits_mapper - @commits_mapper ||= Gitlab::ImportExport::CommitMapper.new(commits: @commits, - members_map: members_mapper.map, - project_id: project.id, - user_admin: @user.is_admin?) - end - def create_relations(relation_list = default_relation_list, tree_hash = @tree_hash) saved = [] relation_list.each do |relation| @@ -55,7 +47,7 @@ module Gitlab def default_relation_list Gitlab::ImportExport::ImportExportReader.new(shared: @shared).tree.reject do |model| - model.is_a?(Hash) && (model[:project_members] || model[:ci_commits]) + model.is_a?(Hash) && model[:project_members] end end @@ -73,8 +65,9 @@ module Gitlab relation_key = relation.keys.first.to_s tree_hash[relation_key].each do |relation_item| relation.values.flatten.each do |sub_relation| + if sub_relation.is_a?(Hash) - relation_hash = relation_item[sub_relation.keys.first.to_s] + relation_hash = relation_item[sub_relation.keys.first.to_s] sub_relation = sub_relation.keys.first else relation_hash = relation_item[sub_relation.to_s] @@ -104,7 +97,6 @@ module Gitlab Gitlab::ImportExport::RelationFactory.create(relation_sym: relation.to_sym, relation_hash: relation_hash.merge('project_id' => project.id), members_mapper: members_mapper, - commits_mapper: commits_mapper, user_admin: @user.is_admin?) end end diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb index 7f0f8f8077..082398d1f0 100644 --- a/lib/gitlab/import_export/relation_factory.rb +++ b/lib/gitlab/import_export/relation_factory.rb @@ -3,27 +3,21 @@ module Gitlab module RelationFactory extend self - OVERRIDES = { snippets: :project_snippets, - ci_commits: 'Ci::Commit', - statuses: 'commit_status', - variables: 'Ci::Variable', - triggers: 'Ci::Trigger', - builds: 'Ci::Build', - hooks: 'ProjectHook' }.freeze - USER_REFERENCES = %w(author_id assignee_id updated_by_id user_id).freeze + OVERRIDES = { snippets: :project_snippets, ci_commits: 'Ci::Commit', statuses: 'commit_status' }.freeze + USER_REFERENCES = %w(author_id assignee_id updated_by_id).freeze - def create(relation_sym:, relation_hash:, members_mapper:, commits_mapper:, user_admin:) + def create(relation_sym:, relation_hash:, members_mapper:, user_admin:) relation_sym = parse_relation_sym(relation_sym) klass = parse_relation(relation_hash, relation_sym) update_missing_author(relation_hash, members_mapper, user_admin) if relation_sym == :notes update_user_references(relation_hash, members_mapper.map) update_project_references(relation_hash, klass) - update_commit_references(relation_hash, commits_mapper.ids_map) if commits_mapper - generate_imported_object(klass, relation_hash, relation_sym) + imported_object(klass, relation_hash) end + private def update_user_references(relation_hash, members_map) USER_REFERENCES.each do |reference| @@ -33,32 +27,6 @@ module Gitlab end end - def update_project_references(relation_hash, klass) - project_id = relation_hash.delete('project_id') - - if relation_hash['source_project_id'] && relation_hash['target_project_id'] - # If source and target are the same, populate them with the new project ID. - if relation_hash['target_project_id'] == relation_hash['source_project_id'] - relation_hash['source_project_id'] = project_id - else - relation_hash['source_project_id'] = -1 - end - end - relation_hash['target_project_id'] = project_id if relation_hash['target_project_id'] - - # project_id may not be part of the export, but we always need to populate it if required. - relation_hash['project_id'] = project_id if klass.column_names.include?('project_id') - relation_hash['gl_project_id'] = project_id if relation_hash['gl_project_id'] - end - - private - - def update_commit_references(relation_hash, commit_ids_map) - return unless relation_hash['commit_id'] - old_commit_id = relation_hash['commit_id'] - relation_hash['commit_id'] = commit_ids_map[old_commit_id] - end - def update_missing_author(relation_hash, members_map, user_admin) old_author_id = relation_hash['author_id'] @@ -82,15 +50,22 @@ module Gitlab "\n\n *By #{author_name} on #{timestamp} (imported from GitLab project)*" end - def generate_imported_object(klass, relation_hash, relation_sym) - if relation_sym == 'Ci::Build' # call #trace= method after assigning the other attributes - trace = relation_hash.delete('trace') - imported_object(klass, relation_hash) do |imported_object| - imported_object.trace = trace + def update_project_references(relation_hash, klass) + project_id = relation_hash.delete('project_id') + + if relation_hash['source_project_id'] && relation_hash['target_project_id'] + # If source and target are the same, populate them with the new project ID. + if relation_hash['target_project_id'] == relation_hash['source_project_id'] + relation_hash['source_project_id'] = project_id + else + relation_hash['source_project_id'] = -1 end - else - imported_object(klass, relation_hash) end + relation_hash['target_project_id'] = project_id if relation_hash['target_project_id'] + + # project_id may not be part of the export, but we always need to populate it if required. + relation_hash['project_id'] = project_id if klass.column_names.include?('project_id') + relation_hash['gl_project_id'] = project_id if relation_hash ['gl_project_id'] end def relation_class(relation_sym) @@ -103,7 +78,6 @@ module Gitlab def imported_object(klass, relation_hash) imported_object = klass.new(relation_hash) - yield(imported_object) if block_given? imported_object.importing = true if imported_object.respond_to?(:importing) imported_object end From 6956fb6366d78dd979fb1046bcd8b05e6dfd2bf7 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 18 May 2016 15:22:26 +0200 Subject: [PATCH 181/730] update relation factory with new models exceptions --- lib/gitlab/import_export/relation_factory.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb index 082398d1f0..68319441a6 100644 --- a/lib/gitlab/import_export/relation_factory.rb +++ b/lib/gitlab/import_export/relation_factory.rb @@ -3,7 +3,15 @@ module Gitlab module RelationFactory extend self - OVERRIDES = { snippets: :project_snippets, ci_commits: 'Ci::Commit', statuses: 'commit_status' }.freeze + + OVERRIDES = { snippets: :project_snippets, + ci_commits: 'Ci::Commit', + statuses: 'commit_status', + variables: 'Ci::Variable', + triggers: 'Ci::Trigger', + builds: 'Ci::Build', + hooks: 'ProjectHook' }.freeze + USER_REFERENCES = %w(author_id assignee_id updated_by_id).freeze def create(relation_sym:, relation_hash:, members_mapper:, user_admin:) From 301d64b84943f7f91588c330f2d22c172f529d52 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 18 May 2016 15:23:32 +0200 Subject: [PATCH 182/730] updated import export conf --- lib/gitlab/import_export/import_export.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml index ae2bf677c9..947f3030f4 100644 --- a/lib/gitlab/import_export/import_export.yml +++ b/lib/gitlab/import_export/import_export.yml @@ -16,7 +16,6 @@ project_tree: - :merge_request_diff - ci_commits: - :statuses - - :builds - :variables - :triggers - :deploy_keys From a5f04ad48849b94aabeeb7450c6059e76372855c Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 18 May 2016 17:48:15 +0200 Subject: [PATCH 183/730] fixed CI commits on export --- lib/gitlab/import_export/attributes_finder.rb | 10 ++++++++-- lib/gitlab/import_export/import_export.yml | 6 +++++- lib/gitlab/import_export/import_export_reader.rb | 3 ++- .../gitlab/import_export/project_tree_saver_spec.rb | 9 +++++++-- 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/lib/gitlab/import_export/attributes_finder.rb b/lib/gitlab/import_export/attributes_finder.rb index 3439ef1006..d230de781d 100644 --- a/lib/gitlab/import_export/attributes_finder.rb +++ b/lib/gitlab/import_export/attributes_finder.rb @@ -2,9 +2,10 @@ module Gitlab module ImportExport class AttributesFinder - def initialize(included_attributes:, excluded_attributes:) + def initialize(included_attributes:, excluded_attributes:, methods:) @included_attributes = included_attributes || {} @excluded_attributes = excluded_attributes || {} + @methods = methods || {} end def find(model_object) @@ -27,10 +28,15 @@ module Gitlab @excluded_attributes[key].nil? ? {} : { except: @excluded_attributes[key] } end + def find_method(value) + key = key_from_hash(value) + @methods[key].nil? ? {} : { methods: @methods[key] } + end + private def find_attributes_only(value) - find_included(value).merge(find_excluded(value)) + find_included(value).merge(find_excluded(value)).merge(find_method(value)) end def key_from_hash(value) diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml index 947f3030f4..eef4d92bee 100644 --- a/lib/gitlab/import_export/import_export.yml +++ b/lib/gitlab/import_export/import_export.yml @@ -45,4 +45,8 @@ included_attributes: # Do not include the following attributes for the models specified. excluded_attributes: snippets: - - :expired_at \ No newline at end of file + - :expired_at + +methods: + statuses: + - :type \ No newline at end of file diff --git a/lib/gitlab/import_export/import_export_reader.rb b/lib/gitlab/import_export/import_export_reader.rb index 25e13074e9..65d27f4b7a 100644 --- a/lib/gitlab/import_export/import_export_reader.rb +++ b/lib/gitlab/import_export/import_export_reader.rb @@ -7,7 +7,8 @@ module Gitlab config_hash = YAML.load_file(config).deep_symbolize_keys @tree = config_hash[:project_tree] @attributes_parser = Gitlab::ImportExport::AttributesFinder.new(included_attributes: config_hash[:included_attributes], - excluded_attributes: config_hash[:excluded_attributes]) + excluded_attributes: config_hash[:excluded_attributes], + methods: config_hash[:methods]) end def project_tree 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 b9cf88d3f7..1c55d0e33c 100644 --- a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb @@ -84,10 +84,15 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do it 'has author on merge requests comments' do expect(saved_project_json['merge_requests'].first['notes'].first['author']).not_to be_empty end + it 'has commit statuses' do expect(saved_project_json['ci_commits'].first['statuses']).not_to be_empty end + it 'has CI builds' do + expect(saved_project_json['ci_commits'].first['statuses'].first['type']).to eq('Ci::Build') + end + it 'has ci commits' do expect(saved_project_json['ci_commits']).not_to be_empty end @@ -99,7 +104,6 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do merge_request = create(:merge_request) label = create(:label) snippet = create(:project_snippet) - commit_status = create(:commit_status) release = create(:release) project = create(:project, @@ -111,7 +115,8 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do releases: [release] ) - create(:ci_commit, project: project, sha: merge_request.last_commit.id, ref: merge_request.source_branch, statuses: [commit_status]) + ci_commit = create(:ci_commit, project: project, sha: merge_request.last_commit.id, ref: merge_request.source_branch) + create(:ci_build, commit: ci_commit) create(:milestone, project: project) create(:note, noteable: issue) create(:note, noteable: merge_request) From 0de533ed08eb3e918f30c72a46635c256881d8c0 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 18 May 2016 17:54:39 +0200 Subject: [PATCH 184/730] fix rubocop warning --- lib/gitlab/import_export/version_restorer.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/gitlab/import_export/version_restorer.rb b/lib/gitlab/import_export/version_restorer.rb index 2c83bf0899..892352f5ad 100644 --- a/lib/gitlab/import_export/version_restorer.rb +++ b/lib/gitlab/import_export/version_restorer.rb @@ -34,4 +34,3 @@ module Gitlab end end end - From dac1d0d81250ef41e7a0a26edf54100229cbb22c Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 18 May 2016 18:15:28 +0200 Subject: [PATCH 185/730] updated test project file --- .../import_export/test_project_export.tar.gz | Bin 340727 -> 340523 bytes 1 file changed, 0 insertions(+), 0 deletions(-) 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 380696d5ab5b71539efffb0e221d5a6a80a3e435..7eed8a6306a1e3fb2c06b2eb148e765da05de12c 100644 GIT binary patch delta 78124 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 z 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 delta 97287 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νpwZddTH@-KY3#2Nq3Ig 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 Date: Thu, 19 May 2016 17:02:49 +0200 Subject: [PATCH 193/730] fixed small issue mapping members --- lib/gitlab/import_export/members_mapper.rb | 1 - lib/gitlab/import_export/relation_factory.rb | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/gitlab/import_export/members_mapper.rb b/lib/gitlab/import_export/members_mapper.rb index 28e5786715..cd1e174f18 100644 --- a/lib/gitlab/import_export/members_mapper.rb +++ b/lib/gitlab/import_export/members_mapper.rb @@ -25,7 +25,6 @@ module Gitlab def default_project_member @default_project_member ||= begin - return @project.project_members.first.user.id unless @project.project_members.empty? default_member = ProjectMember.new(default_project_member_hash) default_member.save! default_member.user.id diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb index 566777e8fc..d5b80beb31 100644 --- a/lib/gitlab/import_export/relation_factory.rb +++ b/lib/gitlab/import_export/relation_factory.rb @@ -39,11 +39,11 @@ module Gitlab def update_missing_author(relation_hash, members_map, user_admin) old_author_id = relation_hash['author_id'] - # Users with admin access have access to mapping of users + # Users with admin access can map users if user_admin - relation_hash['author_id'] = members_map.default_project_member - else relation_hash['author_id'] = members_map.map[old_author_id] + else + relation_hash['author_id'] = members_map.default_project_member end author = relation_hash.delete('author') From 6782cd3cf6bd298c0c26538db35704bf13fcabb3 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 19 May 2016 17:05:35 +0200 Subject: [PATCH 194/730] fix extra space --- lib/gitlab/import_export/relation_factory.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb index d5b80beb31..0fdf208cfa 100644 --- a/lib/gitlab/import_export/relation_factory.rb +++ b/lib/gitlab/import_export/relation_factory.rb @@ -3,7 +3,6 @@ module Gitlab module RelationFactory extend self - OVERRIDES = { snippets: :project_snippets, ci_commits: 'Ci::Commit', statuses: 'commit_status', From fa1884698db9d462ebff3301d42cbc7d43d62c49 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 20 May 2016 10:57:10 +0200 Subject: [PATCH 195/730] a few nice to have and updated changelog --- CHANGELOG | 1 + app/helpers/todos_helper.rb | 10 ++++++++-- app/models/project.rb | 2 ++ app/models/todo.rb | 5 +++++ app/views/projects/edit.html.haml | 2 +- lib/gitlab/import_export/import_service.rb | 13 +++++++++++++ 6 files changed, 30 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 822fa4be56..992f782f80 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -33,6 +33,7 @@ v 8.8.0 (unreleased) - Fix Gravatar hint in user profile when Gravatar is disabled. !3988 (Artem Sidorenko) - Expire repository exists? and has_visible_content? caches after a push if necessary - Fix unintentional filtering bug in issues sorted by milestone due (Takuya Noguchi) + - GitLab project import and export functionality v 8.7.4 - Fix always showing build notification message when switching between merge requests diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb index 2f06668218..5317b55520 100644 --- a/app/helpers/todos_helper.rb +++ b/app/helpers/todos_helper.rb @@ -9,8 +9,12 @@ module TodosHelper def todo_action_name(todo) case todo.action - when Todo::ASSIGNED then 'assigned you' - when Todo::MENTIONED then 'mentioned you on' + when Todo::ASSIGNED then + 'assigned you' + when Todo::MENTIONED then + 'mentioned you on' + when Todo::IMPORTED then + 'imported successfully' end end @@ -27,6 +31,8 @@ module TodosHelper if todo.for_commit? namespace_project_commit_path(todo.project.namespace.becomes(Namespace), todo.project, todo.target, anchor: anchor) + elsif todo.for_project? + namespace_project_path(todo.project.namespace, todo.project) else polymorphic_path([todo.project.namespace.becomes(Namespace), todo.project, todo.target], anchor: anchor) diff --git a/app/models/project.rb b/app/models/project.rb index 5003324f8f..3bd5d048e1 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -94,6 +94,8 @@ class Project < ActiveRecord::Base attr_accessor :new_default_branch attr_accessor :old_path_with_namespace + alias_attribute :title, :name + # Relations belongs_to :creator, foreign_key: 'creator_id', class_name: 'User' belongs_to :group, -> { where(type: Group) }, foreign_key: 'namespace_id' diff --git a/app/models/todo.rb b/app/models/todo.rb index d85f7bfdf5..3333e56912 100644 --- a/app/models/todo.rb +++ b/app/models/todo.rb @@ -19,6 +19,7 @@ class Todo < ActiveRecord::Base ASSIGNED = 1 MENTIONED = 2 + IMPORTED = 3 belongs_to :author, class_name: "User" belongs_to :note @@ -58,6 +59,10 @@ class Todo < ActiveRecord::Base target_type == "Commit" end + def for_project? + target_type == "Project" + end + # override to return commits, which are not active record def target if for_commit? diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 251fba474a..dcb46ad9d1 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -144,7 +144,7 @@ = link_to 'Generate new export', export_namespace_project_path(@project.namespace, @project), method: :post, class: "btn btn-default" - = link_to 'Download export', download_export_namespace_project_path(@project.namespace, @project), + = link_to 'Download latest export', download_export_namespace_project_path(@project.namespace, @project), method: :post, class: "btn btn-default" diff --git a/lib/gitlab/import_export/import_service.rb b/lib/gitlab/import_export/import_service.rb index acd734f089..79794a4c34 100644 --- a/lib/gitlab/import_export/import_service.rb +++ b/lib/gitlab/import_export/import_service.rb @@ -17,6 +17,7 @@ module Gitlab Gitlab::ImportExport::Importer.import(archive_file: @archive_file, shared: @shared) if [restore_version, restore_project_tree, restore_repo, restore_wiki_repo, restore_uploads].all? + Todo.create(attributes_for_todo) project_tree.project else project_tree.project.destroy if project_tree.project @@ -67,6 +68,18 @@ module Gitlab def wiki_repo_path File.join(@shared.export_path, 'project.wiki.bundle') end + + def attributes_for_todo + { user_id: @current_user.id, + project_id: project_tree.project.id, + target_type: 'Project', + target: project_tree.project, + action: Todo::IMPORTED, + author_id: @current_user.id, + state: :pending, + target_id: project_tree.project.id + } + end end end end From f70c000924c82bc579310fe784a6df159d15618b Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 20 May 2016 11:56:02 +0200 Subject: [PATCH 196/730] fix indentation --- app/helpers/todos_helper.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb index 5317b55520..25b812877e 100644 --- a/app/helpers/todos_helper.rb +++ b/app/helpers/todos_helper.rb @@ -9,12 +9,12 @@ module TodosHelper def todo_action_name(todo) case todo.action - when Todo::ASSIGNED then - 'assigned you' - when Todo::MENTIONED then - 'mentioned you on' - when Todo::IMPORTED then - 'imported successfully' + when Todo::ASSIGNED then + 'assigned you' + when Todo::MENTIONED then + 'mentioned you on' + when Todo::IMPORTED then + 'imported successfully' end end From 05b319b0b45288cbbe0bce15bf7bed7f58f6cf76 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Wed, 1 Jun 2016 14:04:38 +0530 Subject: [PATCH 197/730] Perform private token and personal access token authentication in the same `before_action`. - So that the check for valid personal access tokens happens only if private token auth fails. --- app/controllers/application_controller.rb | 38 +++---- .../application_controller_spec.rb | 100 +++++++++--------- 2 files changed, 67 insertions(+), 71 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index b26afb42e7..9dbaba00ff 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -7,8 +7,7 @@ class ApplicationController < ActionController::Base include GitlabRoutingHelper include PageLayoutHelper - before_action :authenticate_user_from_private_token! - before_action :authenticate_user_from_personal_access_token! + before_action :authenticate_user_from_token! before_action :authenticate_user! before_action :validate_user_service_ticket! before_action :reject_blocked! @@ -64,26 +63,8 @@ class ApplicationController < ActionController::Base end end - # From https://github.com/plataformatec/devise/wiki/How-To:-Simple-Token-Authentication-Example - # https://gist.github.com/josevalim/fb706b1e933ef01e4fb6 - def authenticate_user_from_private_token! - user_token = params[:private_token].presence || request.headers['PRIVATE-TOKEN'].presence - user = user_token && User.find_by_authentication_token(user_token.to_s) - - if user - # Notice we are passing store false, so the user is not - # actually stored in the session and a token is needed - # for every request. If you want the token to work as a - # sign in token, you can simply remove store: false. - sign_in user, store: false - end - end - - def authenticate_user_from_personal_access_token! - token_string = params[:private_token].presence || request.headers['PRIVATE-TOKEN'].presence - personal_access_token = PersonalAccessToken.active.find_by_token(token_string) - user = personal_access_token && personal_access_token.user - + def authenticate_user_from_token! + user = get_user_from_private_token || get_user_from_personal_access_token if user # Notice we are passing store false, so the user is not # actually stored in the session and a token is needed @@ -383,4 +364,17 @@ class ApplicationController < ActionController::Base (controller_name == 'groups' && action_name == page_type) || (controller_name == 'dashboard' && action_name == page_type) end + + # From https://github.com/plataformatec/devise/wiki/How-To:-Simple-Token-Authentication-Example + # https://gist.github.com/josevalim/fb706b1e933ef01e4fb6 + def get_user_from_private_token + user_token = params[:private_token].presence || request.headers['PRIVATE-TOKEN'].presence + User.find_by_authentication_token(user_token.to_s) if user_token + end + + def get_user_from_personal_access_token + token_string = params[:private_token].presence || request.headers['PRIVATE-TOKEN'].presence + personal_access_token = PersonalAccessToken.active.find_by_token(token_string) + personal_access_token.user if personal_access_token + end end diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index d7835dc6e2..90dbd1183e 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -31,63 +31,65 @@ describe ApplicationController do end end - describe "#authenticate_user_from_private_token!" do - controller(ApplicationController) do - def index - render text: "authenticated" + describe "#authenticate_user_from_token!" do + describe "authenticating a user from a private token" do + controller(ApplicationController) do + def index + render text: "authenticated" + end + end + + let(:user) { create(:user) } + + it "logs the user in when the 'private_token' param is populated with the private token" do + get :index, private_token: user.private_token + expect(response.status).to eq(200) + expect(response.body).to eq("authenticated") + end + + it "logs the user in when the 'PRIVATE-TOKEN' header is populated with the private token" do + @request.headers['PRIVATE-TOKEN'] = user.private_token + get :index + expect(response.status).to eq(200) + expect(response.body).to eq("authenticated") + end + + it "doesn't log the user in otherwise" do + @request.headers['PRIVATE-TOKEN'] = "token" + get :index, private_token: "token", authenticity_token: "token" + expect(response.status).to_not eq(200) + expect(response.body).to_not eq("authenticated") end end - let(:user) { create(:user) } - - it "logs the user in when the 'private_token' param is populated with the private token" do - get :index, private_token: user.private_token - expect(response.status).to eq(200) - expect(response.body).to eq("authenticated") - end - - it "logs the user in when the 'PRIVATE-TOKEN' header is populated with the private token" do - @request.headers['PRIVATE-TOKEN'] = user.private_token - get :index - expect(response.status).to eq(200) - expect(response.body).to eq("authenticated") - end - - it "doesn't log the user in otherwise" do - @request.headers['PRIVATE-TOKEN'] = "token" - get :index, private_token: "token", authenticity_token: "token" - expect(response.status).to_not eq(200) - expect(response.body).to_not eq("authenticated") - end - end - - describe "#authenticate_user_from_personal_access_token!" do - controller(ApplicationController) do - def index - render text: 'authenticated' + describe "authenticating a user from a personal access token" do + controller(ApplicationController) do + def index + render text: 'authenticated' + end end - end - let(:user) { create(:user) } - let(:personal_access_token) { create(:personal_access_token, user: user) } + let(:user) { create(:user) } + let(:personal_access_token) { create(:personal_access_token, user: user) } - it "logs the user in when the 'personal_access_token' param is populated with the personal access token" do - get :index, private_token: personal_access_token.token - expect(response.status).to eq(200) - expect(response.body).to eq('authenticated') - end + it "logs the user in when the 'personal_access_token' param is populated with the personal access token" do + get :index, private_token: personal_access_token.token + expect(response.status).to eq(200) + expect(response.body).to eq('authenticated') + end - it "logs the user in when the 'PERSONAL_ACCESS_TOKEN' header is populated with the personal access token" do - @request.headers["PRIVATE-TOKEN"] = personal_access_token.token - get :index - expect(response.status).to eq(200) - expect(response.body).to eq('authenticated') - end + it "logs the user in when the 'PERSONAL_ACCESS_TOKEN' header is populated with the personal access token" do + @request.headers["PRIVATE-TOKEN"] = personal_access_token.token + get :index + expect(response.status).to eq(200) + expect(response.body).to eq('authenticated') + end - it "doesn't log the user in otherwise" do - get :index, private_token: "token" - expect(response.status).to_not eq(200) - expect(response.body).to_not eq('authenticated') + it "doesn't log the user in otherwise" do + get :index, private_token: "token" + expect(response.status).to_not eq(200) + expect(response.body).to_not eq('authenticated') + end end end end From 6d444331764fec1910d15b300d89b6246a1f83ea Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Wed, 1 Jun 2016 14:09:17 +0530 Subject: [PATCH 198/730] Don't look for personal access tokens in the DB when the parameter/header is not passed. --- app/controllers/application_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 9dbaba00ff..17bd980b45 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -374,7 +374,7 @@ class ApplicationController < ActionController::Base def get_user_from_personal_access_token token_string = params[:private_token].presence || request.headers['PRIVATE-TOKEN'].presence - personal_access_token = PersonalAccessToken.active.find_by_token(token_string) + personal_access_token = PersonalAccessToken.active.find_by_token(token_string) if token_string personal_access_token.user if personal_access_token end end From c75aea5e4dc6f4420e7576a5c367a9e035f63646 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Wed, 1 Jun 2016 14:31:16 +0530 Subject: [PATCH 199/730] Fix minor issues with the personal access tokens implementation. - Use the `:personal_access_token` param root instead of `personal_access_token_params`, because we aren't using the `personal_access_token` param for authentication anymore (we're using `private_token` instead). - Use `build` to instantiate a `PersonalAccessToken` - Use better-formatted dates --- .../profiles/personal_access_tokens_controller.rb | 6 ++---- .../profiles/personal_access_tokens/index.html.haml | 12 ++++++------ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/app/controllers/profiles/personal_access_tokens_controller.rb b/app/controllers/profiles/personal_access_tokens_controller.rb index af6def25e7..1ad1c11b73 100644 --- a/app/controllers/profiles/personal_access_tokens_controller.rb +++ b/app/controllers/profiles/personal_access_tokens_controller.rb @@ -2,7 +2,7 @@ class Profiles::PersonalAccessTokensController < Profiles::ApplicationController def index @active_personal_access_tokens = current_user.personal_access_tokens.active.order(:expires_at) @inactive_personal_access_tokens = current_user.personal_access_tokens.inactive - @personal_access_token = PersonalAccessToken.new(user: @user) + @personal_access_token = current_user.personal_access_tokens.build end def create @@ -28,8 +28,6 @@ class Profiles::PersonalAccessTokensController < Profiles::ApplicationController private def personal_access_token_params - # We aren't using `personal_access_token` as the root param because the authentication - # system expects to find a token string there - it's off-limits to us. - params.require(:personal_access_token_params).permit(:name, :expires_at) + params.require(:personal_access_token).permit(:name, :expires_at) end end diff --git a/app/views/profiles/personal_access_tokens/index.html.haml b/app/views/profiles/personal_access_tokens/index.html.haml index 0f51e8cd8b..b4468dd983 100644 --- a/app/views/profiles/personal_access_tokens/index.html.haml +++ b/app/views/profiles/personal_access_tokens/index.html.haml @@ -12,7 +12,7 @@ Add a Personal Access Token %p.profile-settings-content Pick a name for the application, and we'll give you a unique token. - = form_for [:profile, @personal_access_token], as: "personal_access_token_params", + = form_for [:profile, @personal_access_token], method: :post, html: { class: 'js-requires-input' } do |f| .form-group @@ -29,7 +29,7 @@ %hr - %h5= "Active Personal Access Tokens (#{@active_personal_access_tokens.length})" + %h5 Active Personal Access Tokens (#{@active_personal_access_tokens.length}) - if @active_personal_access_tokens.present? .table-responsive @@ -50,9 +50,9 @@ %div.input-group-btn %button.btn.btn-default{ type: "button", data: { clipboard_text: token.token } } %i.fa.fa-clipboard - %td= token.created_at.to_date + %td= token.created_at.to_date.to_s(:medium) - if token.expires_at.present? - %td= token.expires_at.to_date + %td= token.expires_at.to_date.to_s(:medium) - else %td %span.personal-access-tokens-never-expires-label Never @@ -63,7 +63,7 @@ %hr - %h5= "Inactive Personal Access Tokens (#{@inactive_personal_access_tokens.length})" + %h5 Inactive Personal Access Tokens (#{@inactive_personal_access_tokens.length}) - if @inactive_personal_access_tokens.present? .table-responsive @@ -82,7 +82,7 @@ %div.input-group-btn %button.btn.btn-default{ type: "button", data: { clipboard_text: token.token } } %i.fa.fa-clipboard - %td= token.created_at.to_date + %td= token.created_at.to_date.to_s(:medium) - else %span No inactive tokens. From 7c8359b7441c2631ceec3bd3783a9761646a9f99 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 1 Jun 2016 18:03:51 +0200 Subject: [PATCH 200/730] started refactoring some stuff based on MR feedback --- app/models/concerns/importable.rb | 6 ++++ app/models/member.rb | 10 +++--- app/models/merge_request.rb | 7 ++-- app/models/merge_request_diff.rb | 5 ++- db/schema.rb | 16 ++++----- lib/gitlab/import_export/members_mapper.rb | 34 +++++++++++-------- .../import_export/project_tree_restorer.rb | 34 ++++++------------- lib/gitlab/import_export/relation_factory.rb | 17 ++++------ lib/gitlab/import_export/repo_restorer.rb | 1 - 9 files changed, 61 insertions(+), 69 deletions(-) create mode 100644 app/models/concerns/importable.rb diff --git a/app/models/concerns/importable.rb b/app/models/concerns/importable.rb new file mode 100644 index 0000000000..019ef75584 --- /dev/null +++ b/app/models/concerns/importable.rb @@ -0,0 +1,6 @@ +module Importable + extend ActiveSupport::Concern + + attr_accessor :importing + alias_method :importing?, :importing +end diff --git a/app/models/member.rb b/app/models/member.rb index bef0b545c7..9a56d3d218 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -19,10 +19,10 @@ class Member < ActiveRecord::Base include Sortable + include Importable include Gitlab::Access attr_accessor :raw_invite_token - attr_accessor :importing belongs_to :created_by, class_name: "User" belongs_to :user @@ -55,10 +55,10 @@ class Member < ActiveRecord::Base scope :owners, -> { where(access_level: OWNER) } before_validation :generate_invite_token, on: :create, if: -> (member) { member.invite_email.present? } - after_create :send_invite, if: :invite?, unless: :importing - after_create :create_notification_setting, unless: [:invite?, :importing] - after_create :post_create_hook, unless: [:invite?, :importing] - after_update :post_update_hook, unless: [:invite?, :importing] + after_create :send_invite, if: :invite?, unless: :importing? + after_create :create_notification_setting, unless: [:invite?, :importing?] + after_create :post_create_hook, unless: [:invite?, :importing?] + after_update :post_update_hook, unless: [:invite?, :importing?] after_destroy :post_destroy_hook, unless: :invite? delegate :name, :username, :email, to: :user, prefix: true diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 916329e04d..c771968627 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -34,6 +34,7 @@ class MergeRequest < ActiveRecord::Base include Referable include Sortable include Taskable + include Importable belongs_to :target_project, foreign_key: :target_project_id, class_name: "Project" belongs_to :source_project, foreign_key: :source_project_id, class_name: "Project" @@ -48,8 +49,6 @@ class MergeRequest < ActiveRecord::Base delegate :commits, :diffs, :real_size, to: :merge_request_diff, prefix: nil - attr_accessor :importing - # When this attribute is true some MR validation is ignored # It allows us to close or modify broken merge requests attr_accessor :allow_broken @@ -123,12 +122,12 @@ class MergeRequest < ActiveRecord::Base end end - validates :source_project, presence: true, unless: [:allow_broken, :importing] + validates :source_project, presence: true, unless: [:allow_broken, :importing?] validates :source_branch, presence: true validates :target_project, presence: true validates :target_branch, presence: true validates :merge_user, presence: true, if: :merge_when_build_succeeds? - validate :validate_branches, unless: [:allow_broken, :importing] + validate :validate_branches, unless: [:allow_broken, :importing?] validate :validate_fork scope :by_branch, ->(branch_name) { where("(source_branch LIKE :branch) OR (target_branch LIKE :branch)", branch: branch_name) } diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index 4278c7daa4..2c9eaf3849 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -15,6 +15,7 @@ class MergeRequestDiff < ActiveRecord::Base include Sortable + include Importable # Prevent store of diff if commits amount more then 500 COMMITS_SAFE_SIZE = 100 @@ -37,9 +38,7 @@ class MergeRequestDiff < ActiveRecord::Base serialize :st_commits serialize :st_diffs - after_create :reload_content, unless: :importing - - attr_accessor :importing + after_create :reload_content, unless: :importing? def reload_content reload_commits diff --git a/db/schema.rb b/db/schema.rb index 71d953afe3..89dba1318f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -70,11 +70,11 @@ ActiveRecord::Schema.define(version: 20160508194200) do t.string "recaptcha_site_key" t.string "recaptcha_private_key" t.integer "metrics_port", default: 8089 - t.boolean "akismet_enabled", default: false - t.string "akismet_api_key" t.integer "metrics_sample_interval", default: 15 t.boolean "sentry_enabled", default: false t.string "sentry_dsn" + t.boolean "akismet_enabled", default: false + t.string "akismet_api_key" t.boolean "email_author_in_body", default: false t.integer "default_group_visibility" t.boolean "repository_checks_enabled", default: false @@ -428,8 +428,8 @@ ActiveRecord::Schema.define(version: 20160508194200) do t.integer "updated_by_id" t.boolean "confidential", default: false t.datetime "deleted_at" - t.date "due_date" t.integer "moved_to_id" + t.date "due_date" end add_index "issues", ["assignee_id"], name: "index_issues_on_assignee_id", using: :btree @@ -716,8 +716,8 @@ ActiveRecord::Schema.define(version: 20160508194200) do t.integer "project_id" t.text "data" t.text "encrypted_credentials" - t.string "encrypted_credentials_iv" - t.string "encrypted_credentials_salt" + t.text "encrypted_credentials_iv" + t.text "encrypted_credentials_salt" end create_table "projects", force: :cascade do |t| @@ -815,9 +815,9 @@ ActiveRecord::Schema.define(version: 20160508194200) do t.string "type" t.string "title" t.integer "project_id" - t.datetime "created_at" - t.datetime "updated_at" - t.boolean "active", default: false, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.boolean "active", null: false t.text "properties" t.boolean "template", default: false t.boolean "push_events", default: true diff --git a/lib/gitlab/import_export/members_mapper.rb b/lib/gitlab/import_export/members_mapper.rb index cd1e174f18..9c47216eb8 100644 --- a/lib/gitlab/import_export/members_mapper.rb +++ b/lib/gitlab/import_export/members_mapper.rb @@ -2,7 +2,7 @@ module Gitlab module ImportExport class MembersMapper - attr_reader :map, :note_member_list + attr_reader :note_member_list def initialize(exported_members:, user:, project:) @exported_members = exported_members @@ -19,33 +19,37 @@ module Gitlab default_project_member end - @map = generate_map end def default_project_member @default_project_member ||= begin default_member = ProjectMember.new(default_project_member_hash) - default_member.save! + default_member.create! default_member.user.id end end + def map + @map ||= + begin + @exported_members.inject(@project_member_map) do |hash, member| + existing_user = User.where(find_project_user_query(member)).first + if existing_user + old_user_id = member['user']['id'] + add_user_as_team_member(existing_user, member) + hash[old_user_id] = existing_user.id + end + hash + end + end + end + private - def generate_map - @exported_members.each do |member| - existing_user = User.where(find_project_user_query(member)).first - assign_member(existing_user, member) if existing_user - end - @project_member_map - end - - def assign_member(existing_user, member) - old_user_id = member['user']['id'] + def add_user_as_team_member(existing_user, member) member['user'] = existing_user - project_member = ProjectMember.new(member_hash(member)) - @project_member_map[old_user_id] = project_member.user.id if project_member.save + ProjectMember.create!(member_hash(member)) end def member_hash(member) diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index 911ba06e74..e8f5fb8838 100644 --- a/lib/gitlab/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -32,14 +32,15 @@ module Gitlab project: project) end - def create_relations(relation_list = default_relation_list, tree_hash = @tree_hash) + def create_relations saved = [] - relation_list.each do |relation| - next if !relation.is_a?(Hash) && tree_hash[relation.to_s].blank? - create_sub_relations(relation, tree_hash) if relation.is_a?(Hash) + default_relation_list.each do |relation| + next unless relation.is_a?(Hash) || @tree_hash[relation.to_s].present? + + create_sub_relations(relation, @tree_hash) if relation.is_a?(Hash) relation_key = relation.is_a?(Hash) ? relation.keys.first : relation - relation_hash = create_relation(relation_key, tree_hash[relation_key.to_s]) + relation_hash = create_relation(relation_key, @tree_hash[relation_key.to_s]) saved << project.update_attribute(relation_key, relation_hash) end saved.all? @@ -73,32 +74,19 @@ module Gitlab relation_hash = relation_item[sub_relation.to_s] end - process_sub_relation(relation_hash, relation_item, sub_relation) unless relation_hash.blank? + relation_item[sub_relation.to_s] = create_relation(sub_relation, relation_hash) unless relation_hash.blank? end end end - def process_sub_relation(relation_hash, relation_item, sub_relation) - if relation_hash.is_a?(Array) - sub_relation_object = create_relation(sub_relation, relation_hash) - else - sub_relation_object = relation_from_factory(sub_relation, relation_hash) - end - relation_item[sub_relation.to_s] = sub_relation_object - end - def create_relation(relation, relation_hash_list) [relation_hash_list].flatten.map do |relation_hash| - relation_from_factory(relation, relation_hash) + Gitlab::ImportExport::RelationFactory.create(relation_sym: relation.to_sym, + relation_hash: relation_hash.merge('project_id' => project.id), + members_mapper: members_mapper, + user_admin: @user.is_admin?) end end - - def relation_from_factory(relation, relation_hash) - Gitlab::ImportExport::RelationFactory.create(relation_sym: relation.to_sym, - relation_hash: relation_hash.merge('project_id' => project.id), - members_mapper: members_mapper, - user_admin: @user.is_admin?) - end end end end diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb index 0fdf208cfa..2794eafe4b 100644 --- a/lib/gitlab/import_export/relation_factory.rb +++ b/lib/gitlab/import_export/relation_factory.rb @@ -11,11 +11,14 @@ module Gitlab builds: 'Ci::Build', hooks: 'ProjectHook' }.freeze - USER_REFERENCES = %w(author_id assignee_id updated_by_id user_id).freeze + USER_REFERENCES = %w[author_id assignee_id updated_by_id user_id].freeze + # Guesses a model and saves it to the DB given its name `relation_sym` def create(relation_sym:, relation_hash:, members_mapper:, user_admin:) relation_sym = parse_relation_sym(relation_sym) - klass = parse_relation(relation_hash, relation_sym) + + klass = relation_class(relation_sym) + relation_hash.delete('id') update_missing_author(relation_hash, members_mapper, user_admin) if relation_sym == :notes update_user_references(relation_hash, members_mapper.map) @@ -49,8 +52,8 @@ module Gitlab return unless user_admin && members_map.note_member_list.include?(old_author_id) - relation_hash['note'] = ('*Blank note*') if relation_hash['note'].blank? - relation_hash['note'] += (missing_author_note(relation_hash['updated_at'], author['name'])) + relation_hash['note'] = '*Blank note*' if relation_hash['note'].blank? + relation_hash['note'] += missing_author_note(relation_hash['updated_at'], author['name']) end def missing_author_note(updated_at, author_name) @@ -109,12 +112,6 @@ module Gitlab imported_object.importing = true if imported_object.respond_to?(:importing) imported_object end - - def parse_relation(relation_hash, relation_sym) - klass = relation_class(relation_sym) - relation_hash.delete('id') - klass - end end end end diff --git a/lib/gitlab/import_export/repo_restorer.rb b/lib/gitlab/import_export/repo_restorer.rb index 36094b95aa..9fac58e224 100644 --- a/lib/gitlab/import_export/repo_restorer.rb +++ b/lib/gitlab/import_export/repo_restorer.rb @@ -12,7 +12,6 @@ module Gitlab def restore return true unless File.exists?(@path_to_bundle) - FileUtils.mkdir_p(repos_path) FileUtils.mkdir_p(path_to_repo) git_unbundle(repo_path: path_to_repo, bundle_path: @path_to_bundle) From 4d50d8a6e3b8ae1521617df32af4cad18385fb9f Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Thu, 2 Jun 2016 08:27:47 +0530 Subject: [PATCH 201/730] Only show a personal access token right after its creation. --- app/assets/stylesheets/pages/profile.scss | 8 +++++ .../personal_access_tokens_controller.rb | 3 +- .../personal_access_tokens/index.html.haml | 26 +++++++-------- .../profiles/personal_access_tokens_spec.rb | 32 ++++++++++++------- 4 files changed, 42 insertions(+), 27 deletions(-) diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss index 53f16c13ec..69bc74228e 100644 --- a/app/assets/stylesheets/pages/profile.scss +++ b/app/assets/stylesheets/pages/profile.scss @@ -218,6 +218,14 @@ max-width: 500px } +.created-personal-access-token { + margin: 15px 15px 0 0; + pre { + max-width: 400px; + display: inline; + } +} + .user-profile { @media (max-width: $screen-xs-max) { .cover-block { diff --git a/app/controllers/profiles/personal_access_tokens_controller.rb b/app/controllers/profiles/personal_access_tokens_controller.rb index 1ad1c11b73..81f2390a56 100644 --- a/app/controllers/profiles/personal_access_tokens_controller.rb +++ b/app/controllers/profiles/personal_access_tokens_controller.rb @@ -9,7 +9,8 @@ class Profiles::PersonalAccessTokensController < Profiles::ApplicationController @personal_access_token = current_user.personal_access_tokens.generate(personal_access_token_params) if @personal_access_token.save - redirect_to profile_personal_access_tokens_path, notice: "Created personal access token!" + flash[:personal_access_token] = @personal_access_token.token + redirect_to profile_personal_access_tokens_path else render :index end diff --git a/app/views/profiles/personal_access_tokens/index.html.haml b/app/views/profiles/personal_access_tokens/index.html.haml index b4468dd983..503f88efb4 100644 --- a/app/views/profiles/personal_access_tokens/index.html.haml +++ b/app/views/profiles/personal_access_tokens/index.html.haml @@ -8,6 +8,16 @@ %p You can generate a personal access token for each application you use that needs access to GitLab. .col-lg-9 + + - if flash[:personal_access_token] + .panel.panel-success + .panel-heading Success! + .panel-body + Your new personal access token has been created. Make sure to save it - you can't see it again on this page. + .created-personal-access-token + %pre= flash[:personal_access_token] + = clipboard_button(clipboard_text: flash[:personal_access_token]) + %h5.prepend-top-0 Add a Personal Access Token %p.profile-settings-content @@ -37,7 +47,6 @@ %thead %tr %th Name - %th Token %th Created %th Expires %th Actions @@ -45,11 +54,6 @@ - @active_personal_access_tokens.each do |token| %tr %td= token.name - %td.input-group.personal-access-tokens-token-column - %input.form-control{ type: "text", value: token.token, readonly: true } - %div.input-group-btn - %button.btn.btn-default{ type: "button", data: { clipboard_text: token.token } } - %i.fa.fa-clipboard %td= token.created_at.to_date.to_s(:medium) - if token.expires_at.present? %td= token.expires_at.to_date.to_s(:medium) @@ -71,17 +75,11 @@ %thead %tr %th Name - %th Token %th Created %tbody - @inactive_personal_access_tokens.each do |token| %tr %td= token.name - %td.input-group.personal-access-tokens-token-column - %input.form-control{ type: "text", value: token.token, readonly: true } - %div.input-group-btn - %button.btn.btn-default{ type: "button", data: { clipboard_text: token.token } } - %i.fa.fa-clipboard %td= token.created_at.to_date.to_s(:medium) - else @@ -91,5 +89,5 @@ :javascript $(".datepicker").datepicker({ dateFormat: "yy-mm-dd", - onSelect: function(dateText, inst) { $("#personal_access_token_params_expires_at").val(dateText) } - }).datepicker("setDate", $.datepicker.parseDate('yy-mm-dd', $('#personal_access_token_params_expires_at').val())); + onSelect: function(dateText, inst) { $("#personal_access_token_expires_at").val(dateText) } + }).datepicker("setDate", $.datepicker.parseDate('yy-mm-dd', $('#personal_access_token_expires_at').val())); diff --git a/spec/features/profiles/personal_access_tokens_spec.rb b/spec/features/profiles/personal_access_tokens_spec.rb index e9fbeefae7..095c7d60e2 100644 --- a/spec/features/profiles/personal_access_tokens_spec.rb +++ b/spec/features/profiles/personal_access_tokens_spec.rb @@ -3,21 +3,35 @@ require 'spec_helper' describe 'Profile > Personal Access Tokens', feature: true, js: true do let(:user) { create(:user) } + def active_personal_access_tokens + find(".table.active-personal-access-tokens").native['innerHTML'] + end + + def inactive_personal_access_tokens + find(".table.inactive-personal-access-tokens").native['innerHTML'] + end + + def created_personal_access_token + find(".created-personal-access-token pre").native['innerHTML'] + end + before do login_as(user) end describe "token creation" do - it "allows creation of a token with an optional expiry date" do + it "allows creation of a token" do visit profile_personal_access_tokens_path fill_in "Name", with: FFaker::Product.brand - expect {click_on "Add Personal Access Token"}.to change { PersonalAccessToken.count }.by(1) - active_personal_access_tokens = find(".table.active-personal-access-tokens").native['innerHTML'] + expect {click_on "Add Personal Access Token"}.to change { PersonalAccessToken.count }.by(1) + expect(created_personal_access_token).to eq(PersonalAccessToken.last.token) expect(active_personal_access_tokens).to match(PersonalAccessToken.last.name) expect(active_personal_access_tokens).to match("Never") - expect(active_personal_access_tokens).to match(PersonalAccessToken.last.token) + end + it "allows creation of a token with an expiry date" do + visit profile_personal_access_tokens_path fill_in "Name", with: FFaker::Product.brand # Set date to 1st of next month @@ -25,11 +39,9 @@ describe 'Profile > Personal Access Tokens', feature: true, js: true do click_on "1" expect {click_on "Add Personal Access Token"}.to change { PersonalAccessToken.count }.by(1) - - active_personal_access_tokens = find(".table.active-personal-access-tokens").native['innerHTML'] + expect(created_personal_access_token).to eq(PersonalAccessToken.last.token) expect(active_personal_access_tokens).to match(PersonalAccessToken.last.name) - expect(active_personal_access_tokens).to match(Date.today.next_month.at_beginning_of_month.to_s) - expect(active_personal_access_tokens).to match(PersonalAccessToken.last.token) + expect(active_personal_access_tokens).to match(Date.today.next_month.at_beginning_of_month.to_s(:medium)) end end @@ -39,18 +51,14 @@ describe 'Profile > Personal Access Tokens', feature: true, js: true do visit profile_personal_access_tokens_path click_on "Revoke" - inactive_personal_access_tokens = find(".table.inactive-personal-access-tokens").native['innerHTML'] expect(inactive_personal_access_tokens).to match(personal_access_token.name) - expect(inactive_personal_access_tokens).to match(personal_access_token.token) end it "moves expired tokens to the 'inactive' section" do personal_access_token = create(:personal_access_token, expires_at: 5.days.ago, user: user) visit profile_personal_access_tokens_path - inactive_personal_access_tokens = find(".table.inactive-personal-access-tokens").native['innerHTML'] expect(inactive_personal_access_tokens).to match(personal_access_token.name) - expect(inactive_personal_access_tokens).to match(personal_access_token.token) end end end From 102074c80152a0d9b808f3eea78a195234ef80bb Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 2 Jun 2016 10:59:54 +0200 Subject: [PATCH 202/730] more and more refactoring --- lib/gitlab/import_export/import_service.rb | 22 ++++---- lib/gitlab/import_export/members_mapper.rb | 53 ++++++++++--------- .../import_export/project_tree_restorer.rb | 4 +- lib/gitlab/import_export/relation_factory.rb | 2 +- lib/gitlab/import_export/uploads_saver.rb | 4 -- ...version_restorer.rb => version_checker.rb} | 6 +-- 6 files changed, 43 insertions(+), 48 deletions(-) rename lib/gitlab/import_export/{version_restorer.rb => version_checker.rb} (91%) diff --git a/lib/gitlab/import_export/import_service.rb b/lib/gitlab/import_export/import_service.rb index acd734f089..96cb8f4b17 100644 --- a/lib/gitlab/import_export/import_service.rb +++ b/lib/gitlab/import_export/import_service.rb @@ -16,7 +16,7 @@ module Gitlab def execute Gitlab::ImportExport::Importer.import(archive_file: @archive_file, shared: @shared) - if [restore_version, restore_project_tree, restore_repo, restore_wiki_repo, restore_uploads].all? + if check_version! && [project_tree, repo_restorer, wiki_restorer, uploads_restorer].all?(&:restore) project_tree.project else project_tree.project.destroy if project_tree.project @@ -26,12 +26,8 @@ module Gitlab private - def restore_version - Gitlab::ImportExport::VersionRestorer.restore(shared: @shared) - end - - def restore_project_tree - project_tree.restore + def check_version! + Gitlab::ImportExport::VersionChecker.check!(shared: @shared) end def project_tree @@ -40,20 +36,20 @@ module Gitlab namespace_id: @namespace.id) end - def restore_repo + def repo_restorer Gitlab::ImportExport::RepoRestorer.new(path_to_bundle: repo_path, shared: @shared, - project: project_tree.project).restore + project: project_tree.project) end - def restore_wiki_repo + def wiki_restorer Gitlab::ImportExport::RepoRestorer.new(path_to_bundle: wiki_repo_path, shared: @shared, - project: ProjectWiki.new(project_tree.project)).restore + project: ProjectWiki.new(project_tree.project)) end - def restore_uploads - Gitlab::ImportExport::UploadsRestorer.restore(project: project_tree.project, shared: @shared) + def uploads_restorer + Gitlab::ImportExport::UploadsRestorer.new(project: project_tree.project, shared: @shared) end def path_with_namespace(project_path) diff --git a/lib/gitlab/import_export/members_mapper.rb b/lib/gitlab/import_export/members_mapper.rb index 9c47216eb8..13fe68d540 100644 --- a/lib/gitlab/import_export/members_mapper.rb +++ b/lib/gitlab/import_export/members_mapper.rb @@ -12,32 +12,27 @@ module Gitlab # This needs to run first, as second call would be from generate_map # which means project members already exist. - default_project_member - - @project_member_map = Hash.new do |_, key| - @note_member_list << key - default_project_member - end - - end - - def default_project_member - @default_project_member ||= - begin - default_member = ProjectMember.new(default_project_member_hash) - default_member.create! - default_member.user.id - end + ensure_default_member! end def map + @map ||= generate_map + end + + def default_user_id + @user.id + end + + private + + + def generate_map @map ||= begin - @exported_members.inject(@project_member_map) do |hash, member| + @exported_members.inject(missing_keys_tracking_hash) do |hash, member| existing_user = User.where(find_project_user_query(member)).first - if existing_user - old_user_id = member['user']['id'] - add_user_as_team_member(existing_user, member) + old_user_id = member['user']['id'] + if existing_user && add_user_as_team_member(existing_user, member).persisted? hash[old_user_id] = existing_user.id end hash @@ -45,21 +40,27 @@ module Gitlab end end - private + def missing_keys_tracking_hash + Hash.new do |_, key| + @note_member_list << key + @user.id + end + end + + def ensure_default_member! + ProjectMember.create!(user: @user, access_level: ProjectMember::MASTER, source_id: @project.id, importing: true) + end def add_user_as_team_member(existing_user, member) member['user'] = existing_user - ProjectMember.create!(member_hash(member)) + + ProjectMember.create(member_hash(member)) end def member_hash(member) member.except('id').merge(source_id: @project.id, importing: true) end - def default_project_member_hash - { user: @user, access_level: ProjectMember::MASTER, source_id: @project.id, importing: true } - end - def find_project_user_query(member) user_arel[:username].eq(member['user']['username']).or(user_arel[:email].eq(member['user']['email'])) end diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index e8f5fb8838..8d3a016ad7 100644 --- a/lib/gitlab/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -80,12 +80,14 @@ module Gitlab end def create_relation(relation, relation_hash_list) - [relation_hash_list].flatten.map do |relation_hash| + relation_array = [relation_hash_list].flatten.map do |relation_hash| Gitlab::ImportExport::RelationFactory.create(relation_sym: relation.to_sym, relation_hash: relation_hash.merge('project_id' => project.id), members_mapper: members_mapper, user_admin: @user.is_admin?) end + + relation_hash_list.is_a?(Array) ? relation_array : relation_array.first end end end diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb index 2794eafe4b..cecb474782 100644 --- a/lib/gitlab/import_export/relation_factory.rb +++ b/lib/gitlab/import_export/relation_factory.rb @@ -45,7 +45,7 @@ module Gitlab if user_admin relation_hash['author_id'] = members_map.map[old_author_id] else - relation_hash['author_id'] = members_map.default_project_member + relation_hash['author_id'] = members_map.default_user_id end author = relation_hash.delete('author') diff --git a/lib/gitlab/import_export/uploads_saver.rb b/lib/gitlab/import_export/uploads_saver.rb index 93bc626b36..7292e9d971 100644 --- a/lib/gitlab/import_export/uploads_saver.rb +++ b/lib/gitlab/import_export/uploads_saver.rb @@ -2,10 +2,6 @@ module Gitlab module ImportExport class UploadsSaver - def self.save(*args) - new(*args).save - end - def initialize(project:, shared:) @project = project @shared = shared diff --git a/lib/gitlab/import_export/version_restorer.rb b/lib/gitlab/import_export/version_checker.rb similarity index 91% rename from lib/gitlab/import_export/version_restorer.rb rename to lib/gitlab/import_export/version_checker.rb index 892352f5ad..4f46776086 100644 --- a/lib/gitlab/import_export/version_restorer.rb +++ b/lib/gitlab/import_export/version_checker.rb @@ -1,16 +1,16 @@ module Gitlab module ImportExport - class VersionRestorer + class VersionChecker def self.restore(*args) - new(*args).restore + new(*args).check end def initialize(shared:) @shared = shared end - def restore + def check! version = File.open(version_file, &:readline) verify_version!(version) rescue => e From a9fdf62b5797220b7736859a2bc0f34f96a7ed43 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 2 Jun 2016 14:07:09 +0200 Subject: [PATCH 203/730] refactoring relation factory, changed from module to class --- .../import_export/project_tree_restorer.rb | 5 + lib/gitlab/import_export/relation_factory.rb | 127 ++++++++++-------- 2 files changed, 73 insertions(+), 59 deletions(-) diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index 8d3a016ad7..dc1e477a82 100644 --- a/lib/gitlab/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -32,6 +32,11 @@ module Gitlab project: project) end + # Loops through the tree of models defined in import_export.yml and + # finds them in the imported JSON so they can be instantiated and saved + # in the DB. The structure and relationships between models are guessed from + # the configuration yaml file too. + # Finally, it updates each attribute in the newly imported project. def create_relations saved = [] default_relation_list.each do |relation| diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb index cecb474782..3738dbaebd 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 - module RelationFactory - extend self + class RelationFactory OVERRIDES = { snippets: :project_snippets, ci_commits: 'Ci::Commit', @@ -13,47 +12,54 @@ module Gitlab USER_REFERENCES = %w[author_id assignee_id updated_by_id user_id].freeze - # Guesses a model and saves it to the DB given its name `relation_sym` - def create(relation_sym:, relation_hash:, members_mapper:, user_admin:) - relation_sym = parse_relation_sym(relation_sym) + def self.create(*args) + new(*args).create + end - klass = relation_class(relation_sym) - relation_hash.delete('id') + def initialize(relation_sym:, relation_hash:, members_mapper:, user_admin:) + @relation_name = OVERRIDES[relation_sym] || relation_sym + @relation_hash = relation_hash.except('id') + @members_mapper = members_mapper + @user_admin = user_admin + end - update_missing_author(relation_hash, members_mapper, user_admin) if relation_sym == :notes - update_user_references(relation_hash, members_mapper.map) - update_project_references(relation_hash, klass) - reset_tokens(relation_hash) if relation_sym == 'Ci::Trigger' + # Creates an object from an actual model with name "relation_sym" with params from + # the relation_hash, updating references with new object IDs, mapping users using + # the "members_mapper" object, also updating notes if required. + def create + set_note_author if @relation_name == :notes + update_user_references + update_project_references + reset_tokens if @relation_name == 'Ci::Trigger' - generate_imported_object(klass, relation_hash, relation_sym) + generate_imported_object end private - def update_user_references(relation_hash, members_map) + def update_user_references USER_REFERENCES.each do |reference| - if relation_hash[reference] - relation_hash[reference] = members_map[relation_hash[reference]] + if @relation_hash[reference] + @relation_hash[reference] = @members_mapper.map[@relation_hash[reference]] end end end - def update_missing_author(relation_hash, members_map, user_admin) - old_author_id = relation_hash['author_id'] + # Sets the author for a note. If the user importing the project + # has admin access, an actual mapping with new project members + # will be used. Otherwise, a note stating the original author name + # is left. + def set_note_author + old_author_id = @relation_hash['author_id'] # Users with admin access can map users - if user_admin - relation_hash['author_id'] = members_map.map[old_author_id] - else - relation_hash['author_id'] = members_map.default_user_id + @relation_hash['author_id'] = admin_user? ? @members_mapper.map[old_author_id] : @members_mapper.default_user_id + + author = @relation_hash.delete('author') + + if admin_user? && @members_mapper.note_member_list.include?(old_author_id) + update_note_for_missing_author(author['name']) end - - author = relation_hash.delete('author') - - return unless user_admin && members_map.note_member_list.include?(old_author_id) - - relation_hash['note'] = '*Blank note*' if relation_hash['note'].blank? - relation_hash['note'] += missing_author_note(relation_hash['updated_at'], author['name']) end def missing_author_note(updated_at, author_name) @@ -61,57 +67,60 @@ module Gitlab "\n\n *By #{author_name} on #{timestamp} (imported from GitLab project)*" end - def generate_imported_object(klass, relation_hash, relation_sym) - if relation_sym == 'commit_status' # call #trace= method after assigning the other attributes - trace = relation_hash.delete('trace') - imported_object(klass, relation_hash) do |imported_object| - imported_object.trace = trace - imported_object.commit_id = nil + def generate_imported_object + if @relation_sym == 'commit_status' # call #trace= method after assigning the other attributes + trace = @relation_hash.delete('trace') + imported_object do |object| + object.trace = trace + object.commit_id = nil end else - imported_object(klass, relation_hash) + imported_object end end - def update_project_references(relation_hash, klass) - project_id = relation_hash.delete('project_id') - - if relation_hash['source_project_id'] && relation_hash['target_project_id'] - # If source and target are the same, populate them with the new project ID. - if relation_hash['target_project_id'] == relation_hash['source_project_id'] - relation_hash['source_project_id'] = project_id - else - relation_hash['source_project_id'] = -1 - end - end - relation_hash['target_project_id'] = project_id if relation_hash['target_project_id'] + def update_project_references + project_id = @relation_hash.delete('project_id') # project_id may not be part of the export, but we always need to populate it if required. - relation_hash['project_id'] = project_id if klass.column_names.include?('project_id') - relation_hash['gl_project_id'] = project_id if relation_hash ['gl_project_id'] + @relation_hash['project_id'] = project_id if relation_class.column_names.include?('project_id') + @relation_hash['gl_project_id'] = project_id if @relation_hash['gl_project_id'] + @relation_hash['target_project_id'] = project_id if @relation_hash['target_project_id'] + @relation_hash['source_project_id'] = -1 if @relation_hash['source_project_id'] + + # If source and target are the same, populate them with the new project ID. + if @relation_hash['source_project_id'] && @relation_hash['target_project_id'] && + @relation_hash['target_project_id'] == @relation_hash['source_project_id'] + @relation_hash['source_project_id'] = project_id + end end - def reset_tokens(relation_hash) + def reset_tokens return unless Gitlab::ImportExport.reset_tokens? # If we import/export a project to the same instance, tokens will have to be reseated. - relation_hash['token'] = nil + @relation_hash['token'] = nil end - def relation_class(relation_sym) - relation_sym.to_s.classify.constantize + def relation_class + @relation_class ||= @relation_name.to_s.classify.constantize end - def parse_relation_sym(relation_sym) - OVERRIDES[relation_sym] || relation_sym - end - - def imported_object(klass, relation_hash) - imported_object = klass.new(relation_hash) + def imported_object + imported_object = relation_class.new(@relation_hash) yield(imported_object) if block_given? imported_object.importing = true if imported_object.respond_to?(:importing) imported_object end + + def update_note_for_missing_author(author_name) + @relation_hash['note'] = '*Blank note*' if @relation_hash['note'].blank? + @relation_hash['note'] += missing_author_note(@relation_hash['updated_at'], author_name) + end + + def admin_user? + @user_admin + end end end end From 41c06c311b9c5642f6056d0b34030980ebf507b3 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 2 Jun 2016 14:44:59 +0200 Subject: [PATCH 204/730] refactoring more things based on MR feedback --- lib/gitlab/import_export/import_service.rb | 3 ++- lib/gitlab/import_export/relation_factory.rb | 6 +++--- lib/gitlab/import_export/repo_restorer.rb | 9 +++++++-- lib/gitlab/import_export/shared.rb | 2 +- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/lib/gitlab/import_export/import_service.rb b/lib/gitlab/import_export/import_service.rb index 96cb8f4b17..db71f72efe 100644 --- a/lib/gitlab/import_export/import_service.rb +++ b/lib/gitlab/import_export/import_service.rb @@ -45,7 +45,8 @@ module Gitlab def wiki_restorer Gitlab::ImportExport::RepoRestorer.new(path_to_bundle: wiki_repo_path, shared: @shared, - project: ProjectWiki.new(project_tree.project)) + project: ProjectWiki.new(project_tree.project), + wiki: true) end def uploads_restorer diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb index 3738dbaebd..dc86862c2d 100644 --- a/lib/gitlab/import_export/relation_factory.rb +++ b/lib/gitlab/import_export/relation_factory.rb @@ -30,7 +30,7 @@ module Gitlab set_note_author if @relation_name == :notes update_user_references update_project_references - reset_tokens if @relation_name == 'Ci::Trigger' + reset_ci_tokens if @relation_name == 'Ci::Trigger' generate_imported_object end @@ -95,10 +95,10 @@ module Gitlab end end - def reset_tokens + def reset_ci_tokens return unless Gitlab::ImportExport.reset_tokens? - # If we import/export a project to the same instance, tokens will have to be reseated. + # If we import/export a project to the same instance, tokens will have to be reset. @relation_hash['token'] = nil end diff --git a/lib/gitlab/import_export/repo_restorer.rb b/lib/gitlab/import_export/repo_restorer.rb index 9fac58e224..d6dcf5dc11 100644 --- a/lib/gitlab/import_export/repo_restorer.rb +++ b/lib/gitlab/import_export/repo_restorer.rb @@ -3,14 +3,15 @@ module Gitlab class RepoRestorer include Gitlab::ImportExport::CommandLineUtil - def initialize(project:, shared:, path_to_bundle:) + def initialize(project:, shared:, path_to_bundle:, wiki: false) @project = project @path_to_bundle = path_to_bundle @shared = shared + @wiki = wiki end def restore - return true unless File.exists?(@path_to_bundle) + return false unless File.exists?(@path_to_bundle) || wiki? FileUtils.mkdir_p(path_to_repo) @@ -29,6 +30,10 @@ module Gitlab def path_to_repo @project.repository.path_to_repo end + + def wiki? + @wiki + end end end end diff --git a/lib/gitlab/import_export/shared.rb b/lib/gitlab/import_export/shared.rb index 01ac332981..6aff05b886 100644 --- a/lib/gitlab/import_export/shared.rb +++ b/lib/gitlab/import_export/shared.rb @@ -10,7 +10,7 @@ module Gitlab end def export_path - @export_path ||= Gitlab::ImportExport.export_path(relative_path: @opts[:relative_path]) + @export_path ||= Gitlab::ImportExport.export_path(relative_path: opts[:relative_path]) end def error(error) From a1295d8ebef223eb0a87bc9e1660efcb9147599c Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Fri, 3 Jun 2016 08:58:15 +0530 Subject: [PATCH 205/730] Don't use `natve['innerHTML']` in the feature spec. - The `have_text` matcher works fine. --- .../profiles/personal_access_tokens_spec.rb | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/spec/features/profiles/personal_access_tokens_spec.rb b/spec/features/profiles/personal_access_tokens_spec.rb index 095c7d60e2..14f2a7c9a2 100644 --- a/spec/features/profiles/personal_access_tokens_spec.rb +++ b/spec/features/profiles/personal_access_tokens_spec.rb @@ -4,15 +4,15 @@ describe 'Profile > Personal Access Tokens', feature: true, js: true do let(:user) { create(:user) } def active_personal_access_tokens - find(".table.active-personal-access-tokens").native['innerHTML'] + find(".table.active-personal-access-tokens") end def inactive_personal_access_tokens - find(".table.inactive-personal-access-tokens").native['innerHTML'] + find(".table.inactive-personal-access-tokens") end def created_personal_access_token - find(".created-personal-access-token pre").native['innerHTML'] + find(".created-personal-access-token pre") end before do @@ -25,9 +25,9 @@ describe 'Profile > Personal Access Tokens', feature: true, js: true do fill_in "Name", with: FFaker::Product.brand expect {click_on "Add Personal Access Token"}.to change { PersonalAccessToken.count }.by(1) - expect(created_personal_access_token).to eq(PersonalAccessToken.last.token) - expect(active_personal_access_tokens).to match(PersonalAccessToken.last.name) - expect(active_personal_access_tokens).to match("Never") + expect(created_personal_access_token).to have_text(PersonalAccessToken.last.token) + expect(active_personal_access_tokens).to have_text(PersonalAccessToken.last.name) + expect(active_personal_access_tokens).to have_text("Never") end it "allows creation of a token with an expiry date" do @@ -39,9 +39,9 @@ describe 'Profile > Personal Access Tokens', feature: true, js: true do click_on "1" expect {click_on "Add Personal Access Token"}.to change { PersonalAccessToken.count }.by(1) - expect(created_personal_access_token).to eq(PersonalAccessToken.last.token) - expect(active_personal_access_tokens).to match(PersonalAccessToken.last.name) - expect(active_personal_access_tokens).to match(Date.today.next_month.at_beginning_of_month.to_s(:medium)) + expect(created_personal_access_token).to have_text(PersonalAccessToken.last.token) + expect(active_personal_access_tokens).to have_text(PersonalAccessToken.last.name) + expect(active_personal_access_tokens).to have_text(Date.today.next_month.at_beginning_of_month.to_s(:medium)) end end @@ -51,14 +51,14 @@ describe 'Profile > Personal Access Tokens', feature: true, js: true do visit profile_personal_access_tokens_path click_on "Revoke" - expect(inactive_personal_access_tokens).to match(personal_access_token.name) + expect(inactive_personal_access_tokens).to have_text(personal_access_token.name) end it "moves expired tokens to the 'inactive' section" do personal_access_token = create(:personal_access_token, expires_at: 5.days.ago, user: user) visit profile_personal_access_tokens_path - expect(inactive_personal_access_tokens).to match(personal_access_token.name) + expect(inactive_personal_access_tokens).to have_text(personal_access_token.name) end end end From b4b024857783e1fc39424fdf631b722ee1dfd195 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Fri, 3 Jun 2016 09:00:39 +0530 Subject: [PATCH 206/730] Parts of spec names with "when" should be contexts. --- .../application_controller_spec.rb | 45 +++++++++++-------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index 90dbd1183e..ff596e7c2a 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -41,17 +41,22 @@ describe ApplicationController do let(:user) { create(:user) } - it "logs the user in when the 'private_token' param is populated with the private token" do - get :index, private_token: user.private_token - expect(response.status).to eq(200) - expect(response.body).to eq("authenticated") + context "when the 'private_token' param is populated with the private token" do + it "logs the user in" do + get :index, private_token: user.private_token + expect(response.status).to eq(200) + expect(response.body).to eq("authenticated") + end end - it "logs the user in when the 'PRIVATE-TOKEN' header is populated with the private token" do - @request.headers['PRIVATE-TOKEN'] = user.private_token - get :index - expect(response.status).to eq(200) - expect(response.body).to eq("authenticated") + + 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 + get :index + expect(response.status).to eq(200) + expect(response.body).to eq("authenticated") + end end it "doesn't log the user in otherwise" do @@ -72,17 +77,21 @@ describe ApplicationController do let(:user) { create(:user) } let(:personal_access_token) { create(:personal_access_token, user: user) } - it "logs the user in when the 'personal_access_token' param is populated with the personal access token" do - get :index, private_token: personal_access_token.token - expect(response.status).to eq(200) - expect(response.body).to eq('authenticated') + context "when the 'personal_access_token' param is populated with the personal access token" do + it "logs the user in" do + get :index, private_token: personal_access_token.token + expect(response.status).to eq(200) + expect(response.body).to eq('authenticated') + end end - it "logs the user in when the 'PERSONAL_ACCESS_TOKEN' header is populated with the personal access token" do - @request.headers["PRIVATE-TOKEN"] = personal_access_token.token - get :index - expect(response.status).to eq(200) - expect(response.body).to eq('authenticated') + context "when the 'PERSONAL_ACCESS_TOKEN' header is populated with the personal access token" do + it "logs the user in" do + @request.headers["PRIVATE-TOKEN"] = personal_access_token.token + get :index + expect(response.status).to eq(200) + expect(response.body).to eq('authenticated') + end end it "doesn't log the user in otherwise" do From 399a633061577b8a2ca95c29ce1cfe0abeac4779 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Fri, 3 Jun 2016 09:07:37 +0530 Subject: [PATCH 207/730] Fix minor styling issues. - No "Actions" label necessary - `%td` can be moved out of `if/else` - Page header should be "Profile Settings", not "Personal Access Tokens" - "You don't have any tokens" message should be styled consistently --- .../personal_access_tokens/index.html.haml | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/app/views/profiles/personal_access_tokens/index.html.haml b/app/views/profiles/personal_access_tokens/index.html.haml index 503f88efb4..68f2813bc1 100644 --- a/app/views/profiles/personal_access_tokens/index.html.haml +++ b/app/views/profiles/personal_access_tokens/index.html.haml @@ -1,12 +1,11 @@ - page_title "Personal Access Tokens" -- header_title page_title, profile_personal_access_tokens_path .row.prepend-top-default .col-lg-3.profile-settings-sidebar %h4.prepend-top-0 = page_title %p - You can generate a personal access token for each application you use that needs access to GitLab. + You can generate a personal access token for each application you use that needs access to the GitLab API. .col-lg-9 - if flash[:personal_access_token] @@ -49,21 +48,22 @@ %th Name %th Created %th Expires - %th Actions + %th %tbody - @active_personal_access_tokens.each do |token| %tr %td= token.name %td= token.created_at.to_date.to_s(:medium) - - if token.expires_at.present? - %td= token.expires_at.to_date.to_s(:medium) - - else - %td + %td + - if token.expires_at.present? + = token.expires_at.to_date.to_s(:medium) + - else %span.personal-access-tokens-never-expires-label Never %td= link_to "Revoke", revoke_profile_personal_access_token_path(token), method: :put, class: "btn btn-danger", data: { confirm: "Are you sure? This cannot be undone." } - else - %span You don't have any active tokens yet. + .settings-message.text-center + You don't have any active tokens yet. %hr @@ -83,7 +83,8 @@ %td= token.created_at.to_date.to_s(:medium) - else - %span No inactive tokens. + .settings-message.text-center + There are no inactive tokens. :javascript From ffe111c1e22b0cce827c297fea62dfb0bd91326a Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Fri, 3 Jun 2016 09:23:16 +0530 Subject: [PATCH 208/730] Display appropriate errors when personal access token creation/revocation fails. --- .../profiles/personal_access_tokens_controller.rb | 12 +++++++++--- .../profiles/personal_access_tokens/index.html.haml | 2 ++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/app/controllers/profiles/personal_access_tokens_controller.rb b/app/controllers/profiles/personal_access_tokens_controller.rb index 81f2390a56..a1545a5dd0 100644 --- a/app/controllers/profiles/personal_access_tokens_controller.rb +++ b/app/controllers/profiles/personal_access_tokens_controller.rb @@ -1,7 +1,7 @@ class Profiles::PersonalAccessTokensController < Profiles::ApplicationController + before_action :load_personal_access_tokens, only: :index + def index - @active_personal_access_tokens = current_user.personal_access_tokens.active.order(:expires_at) - @inactive_personal_access_tokens = current_user.personal_access_tokens.inactive @personal_access_token = current_user.personal_access_tokens.build end @@ -12,6 +12,7 @@ class Profiles::PersonalAccessTokensController < Profiles::ApplicationController flash[:personal_access_token] = @personal_access_token.token redirect_to profile_personal_access_tokens_path else + load_personal_access_tokens render :index end end @@ -22,7 +23,7 @@ class Profiles::PersonalAccessTokensController < Profiles::ApplicationController if @personal_access_token.revoke! redirect_to profile_personal_access_tokens_path, notice: "Revoked personal access token #{@personal_access_token.name}!" else - render :index + redirect_to profile_personal_access_tokens_path, alert: "Could not revoke personal access token #{@personal_access_token.name}." end end @@ -31,4 +32,9 @@ class Profiles::PersonalAccessTokensController < Profiles::ApplicationController def personal_access_token_params params.require(:personal_access_token).permit(:name, :expires_at) end + + def load_personal_access_tokens + @active_personal_access_tokens = current_user.personal_access_tokens.active.order(:expires_at) + @inactive_personal_access_tokens = current_user.personal_access_tokens.inactive + end end diff --git a/app/views/profiles/personal_access_tokens/index.html.haml b/app/views/profiles/personal_access_tokens/index.html.haml index 68f2813bc1..64e632b20e 100644 --- a/app/views/profiles/personal_access_tokens/index.html.haml +++ b/app/views/profiles/personal_access_tokens/index.html.haml @@ -24,6 +24,8 @@ = form_for [:profile, @personal_access_token], method: :post, html: { class: 'js-requires-input' } do |f| + = form_errors(@personal_access_token) + .form-group = f.label :name, class: 'label-light' = f.text_field :name, class: "form-control", required: true From 1a416720a2261f453ec4ce539fa61c1c32769aea Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Fri, 3 Jun 2016 09:31:56 +0530 Subject: [PATCH 209/730] Update CHANGELOG. --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 547921a077..57a006869c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -23,6 +23,7 @@ v 8.9.0 (unreleased) - Link to blank group icon doesn't throw a 404 anymore - Remove 'main language' feature - Pipelines can be canceled only when there are running builds + - Allow authentication using personal access tokens - Use downcased path to container repository as this is expected path by Docker - Projects pending deletion will render a 404 page - Measure queue duration between gitlab-workhorse and Rails @@ -92,7 +93,6 @@ v 8.8.0 - GitAccess#protected_tag? no longer loads all tags just to check if a single one exists - Reduce delay in destroying a project from 1-minute to immediately - Make build status canceled if any of the jobs was canceled and none failed - - Allow authentication using personal access tokens - Upgrade Sidekiq to 4.1.2 - Added /health_check endpoint for checking service status - Make 'upcoming' filter for milestones work better across projects From 3adf125a155fd04fbba4f0882c739eae1cc73e15 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Fri, 3 Jun 2016 09:53:49 +0530 Subject: [PATCH 210/730] Add tests for errors while creating/revoking personal access tokens. --- .../profiles/personal_access_tokens_spec.rb | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/spec/features/profiles/personal_access_tokens_spec.rb b/spec/features/profiles/personal_access_tokens_spec.rb index 14f2a7c9a2..5bba08d005 100644 --- a/spec/features/profiles/personal_access_tokens_spec.rb +++ b/spec/features/profiles/personal_access_tokens_spec.rb @@ -15,6 +15,12 @@ describe 'Profile > Personal Access Tokens', feature: true, js: true do find(".created-personal-access-token pre") end + def disallow_personal_access_token_saves! + allow_any_instance_of(PersonalAccessToken).to receive(:save).and_return(false) + errors = ActiveModel::Errors.new(PersonalAccessToken.new).tap { |e| e.add(:name, "cannot be nil") } + allow_any_instance_of(PersonalAccessToken).to receive(:errors).and_return(errors) + end + before do login_as(user) end @@ -43,11 +49,23 @@ describe 'Profile > Personal Access Tokens', feature: true, js: true do expect(active_personal_access_tokens).to have_text(PersonalAccessToken.last.name) expect(active_personal_access_tokens).to have_text(Date.today.next_month.at_beginning_of_month.to_s(:medium)) end + + context "when creation fails" do + it "displays an error message" do + disallow_personal_access_token_saves! + visit profile_personal_access_tokens_path + fill_in "Name", with: FFaker::Product.brand + + expect { click_on "Add Personal Access Token" }.not_to change { PersonalAccessToken.count } + expect(page).to have_content("Name cannot be nil") + end + end end describe "inactive tokens" do + let!(:personal_access_token) { create(:personal_access_token, user: user) } + it "allows revocation of an active token" do - personal_access_token = create(:personal_access_token, user: user) visit profile_personal_access_tokens_path click_on "Revoke" @@ -55,10 +73,21 @@ describe 'Profile > Personal Access Tokens', feature: true, js: true do end it "moves expired tokens to the 'inactive' section" do - personal_access_token = create(:personal_access_token, expires_at: 5.days.ago, user: user) + personal_access_token.update(expires_at: 5.days.ago) visit profile_personal_access_tokens_path expect(inactive_personal_access_tokens).to have_text(personal_access_token.name) end + + context "when revocation fails" do + it "displays an error message" do + disallow_personal_access_token_saves! + visit profile_personal_access_tokens_path + + expect { click_on "Revoke" }.not_to change { PersonalAccessToken.inactive.count } + expect(active_personal_access_tokens).to have_text(personal_access_token.name) + expect(page).to have_content("Could not revoke") + end + end end end From 0dff6fd7148957fa94d2626e3912cd929ba150d3 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Fri, 3 Jun 2016 10:10:58 +0530 Subject: [PATCH 211/730] Fix rubocop spec. --- app/controllers/application_controller.rb | 2 +- spec/controllers/application_controller_spec.rb | 8 ++++---- spec/models/personal_access_token_spec.rb | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index c8baea2579..23a0e16ca4 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -368,7 +368,7 @@ class ApplicationController < ActionController::Base # From https://github.com/plataformatec/devise/wiki/How-To:-Simple-Token-Authentication-Example # https://gist.github.com/josevalim/fb706b1e933ef01e4fb6 def get_user_from_private_token - user_token = params[:private_token].presence || request.headers['PRIVATE-TOKEN'].presence + user_token = params[:private_token].presence || request.headers['PRIVATE-TOKEN'].presence User.find_by_authentication_token(user_token.to_s) if user_token end diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index ff596e7c2a..ff5b391627 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -62,8 +62,8 @@ describe ApplicationController do it "doesn't log the user in otherwise" do @request.headers['PRIVATE-TOKEN'] = "token" get :index, private_token: "token", authenticity_token: "token" - expect(response.status).to_not eq(200) - expect(response.body).to_not eq("authenticated") + expect(response.status).not_to eq(200) + expect(response.body).not_to eq("authenticated") end end @@ -96,8 +96,8 @@ describe ApplicationController do it "doesn't log the user in otherwise" do get :index, private_token: "token" - expect(response.status).to_not eq(200) - expect(response.body).to_not eq('authenticated') + expect(response.status).not_to eq(200) + expect(response.body).not_to eq('authenticated') end end end diff --git a/spec/models/personal_access_token_spec.rb b/spec/models/personal_access_token_spec.rb index 3e80a48175..46eb71cef1 100644 --- a/spec/models/personal_access_token_spec.rb +++ b/spec/models/personal_access_token_spec.rb @@ -9,7 +9,7 @@ describe PersonalAccessToken, models: true do it "doesn't save the record" do personal_access_token = PersonalAccessToken.generate({}) - expect(personal_access_token).to_not be_persisted + expect(personal_access_token).not_to be_persisted end end end From 3e99123095b26988de67a94b0e7a5207c1ef5ae2 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 3 Jun 2016 10:57:46 +0200 Subject: [PATCH 212/730] Fix merge conflicts - squashed commit # Conflicts: # app/models/project.rb --- .gitignore | 78 +-- .rubocop.yml | 273 ++++++--- ...t_discussion.html.haml => .vagrant_enabled | 0 CHANGELOG | 154 ++++- CONTRIBUTING.md | 6 +- GITLAB_SHELL_VERSION | 2 +- GITLAB_WORKHORSE_VERSION | 2 +- Gemfile | 39 +- Gemfile.lock | 212 ++----- README.md | 6 +- VERSION | 2 +- app/assets/images/ci/arch.jpg | Bin 25222 -> 0 bytes app/assets/images/ci/favicon.ico | Bin 5430 -> 0 bytes app/assets/images/ci/loader.gif | Bin 4405 -> 0 bytes app/assets/images/ci/no_avatar.png | Bin 1337 -> 0 bytes app/assets/images/ci/rails.png | Bin 6646 -> 0 bytes app/assets/images/ci/service_sample.png | Bin 76024 -> 0 bytes .../images/mailers/gitlab_header_logo.png | Bin 0 -> 7096 bytes .../images/mailers/gitlab_tanuki_2x.png | Bin 0 -> 2545 bytes app/assets/javascripts/api.js.coffee | 35 +- app/assets/javascripts/application.js.coffee | 43 +- .../blob/blob_gitignore_selector.js.coffee | 58 ++ .../javascripts/blob/edit_blob.js.coffee | 1 + app/assets/javascripts/calendar.js.coffee | 34 -- .../javascripts/ci/application.js.coffee | 28 - app/assets/javascripts/ci/build.coffee | 24 +- app/assets/javascripts/dispatcher.js.coffee | 3 +- .../javascripts/due_date_select.js.coffee | 35 +- .../javascripts/gfm_auto_complete.js.coffee | 19 + app/assets/javascripts/gl_dropdown.js.coffee | 82 ++- .../javascripts/graphs/application.js.coffee | 7 + .../{ => graphs}/stat_graph.js.coffee | 0 .../stat_graph_contributors.js.coffee | 1 - .../stat_graph_contributors_graph.js.coffee | 2 - .../stat_graph_contributors_util.js.coffee | 0 app/assets/javascripts/issuable.js.coffee | 48 +- .../javascripts/issuable_form.js.coffee | 26 + app/assets/javascripts/issues.js.coffee | 38 -- app/assets/javascripts/layout_nav.js.coffee | 14 + .../javascripts/lib/type_utility.js.coffee | 9 + .../javascripts/lib/url_utility.js.coffee | 11 +- .../javascripts/merge_request_tabs.js.coffee | 3 + .../merge_request_widget.js.coffee | 15 +- app/assets/javascripts/notes.js.coffee | 12 +- .../javascripts/right_sidebar.js.coffee | 36 +- .../javascripts/search_autocomplete.js.coffee | 22 +- .../shortcuts_dashboard_navigation.js.coffee | 8 +- .../javascripts/shortcuts_issuable.coffee | 4 + app/assets/javascripts/sidebar.js.coffee | 2 +- app/assets/javascripts/user_tabs.js.coffee | 9 +- .../javascripts/users/application.js.coffee | 8 + .../javascripts/users/calendar.js.coffee | 198 +++++++ app/assets/javascripts/users_select.js.coffee | 12 +- app/assets/stylesheets/application.scss | 2 - app/assets/stylesheets/framework.scss | 1 + .../stylesheets/framework/animations.scss | 72 +++ app/assets/stylesheets/framework/avatar.scss | 1 + app/assets/stylesheets/framework/blocks.scss | 11 +- app/assets/stylesheets/framework/buttons.scss | 18 +- .../stylesheets/framework/calendar.scss | 82 +-- app/assets/stylesheets/framework/common.scss | 2 +- .../stylesheets/framework/dropdowns.scss | 6 +- app/assets/stylesheets/framework/files.scss | 31 +- app/assets/stylesheets/framework/forms.scss | 8 +- .../stylesheets/framework/gitlab-theme.scss | 17 +- app/assets/stylesheets/framework/header.scss | 58 +- app/assets/stylesheets/framework/mobile.scss | 4 - app/assets/stylesheets/framework/nav.scss | 122 +++- app/assets/stylesheets/framework/sidebar.scss | 52 +- .../stylesheets/framework/typography.scss | 8 + .../stylesheets/framework/variables.scss | 15 +- app/assets/stylesheets/framework/zen.scss | 2 +- app/assets/stylesheets/mailers/devise.scss | 134 +++++ .../mailers/repository_push_email.scss | 43 ++ app/assets/stylesheets/pages/commit.scss | 24 +- app/assets/stylesheets/pages/detail_page.scss | 2 - app/assets/stylesheets/pages/editor.scss | 21 +- app/assets/stylesheets/pages/issuable.scss | 6 +- app/assets/stylesheets/pages/issues.scss | 10 - .../stylesheets/pages/merge_requests.scss | 31 +- app/assets/stylesheets/pages/notes.scss | 3 +- app/assets/stylesheets/pages/pipelines.scss | 24 + app/assets/stylesheets/pages/profile.scss | 16 +- app/assets/stylesheets/pages/projects.scss | 178 ++++-- app/assets/stylesheets/pages/search.scss | 4 +- app/assets/stylesheets/pages/settings.scss | 8 + app/assets/stylesheets/pages/snippets.scss | 44 +- app/assets/stylesheets/pages/todos.scss | 14 +- app/assets/stylesheets/pages/tree.scss | 15 +- .../admin/abuse_reports_controller.rb | 2 +- .../admin/application_settings_controller.rb | 17 +- .../admin/broadcast_messages_controller.rb | 2 +- .../admin/health_check_controller.rb | 5 + app/controllers/admin/keys_controller.rb | 2 +- app/controllers/admin/runners_controller.rb | 37 +- app/controllers/admin/spam_logs_controller.rb | 2 +- app/controllers/admin/users_controller.rb | 3 +- app/controllers/application_controller.rb | 6 +- app/controllers/autocomplete_controller.rb | 18 + app/controllers/concerns/creates_commit.rb | 2 +- .../concerns/toggle_subscription_action.rb | 2 +- .../dashboard/labels_controller.rb | 2 +- .../dashboard/projects_controller.rb | 2 +- app/controllers/dashboard/todos_controller.rb | 4 +- app/controllers/dashboard_controller.rb | 2 +- .../groups/group_members_controller.rb | 2 +- app/controllers/health_check_controller.rb | 22 + app/controllers/jwt_controller.rb | 87 +++ .../omniauth_callbacks_controller.rb | 2 +- app/controllers/profiles/emails_controller.rb | 2 +- app/controllers/profiles/keys_controller.rb | 2 +- .../projects/application_controller.rb | 2 +- .../projects/branches_controller.rb | 2 +- app/controllers/projects/builds_controller.rb | 8 + app/controllers/projects/commit_controller.rb | 12 +- .../projects/compare_controller.rb | 3 +- .../projects/container_registry_controller.rb | 34 ++ .../projects/find_file_controller.rb | 52 +- app/controllers/projects/hooks_controller.rb | 9 +- .../projects/imports_controller.rb | 1 + .../projects/merge_requests_controller.rb | 16 +- .../projects/milestones_controller.rb | 2 +- app/controllers/projects/notes_controller.rb | 10 +- .../projects/pipelines_controller.rb | 59 ++ .../projects/project_members_controller.rb | 4 +- .../projects/protected_branches_controller.rb | 2 +- .../projects/runners_controller.rb | 4 +- .../projects/variables_controller.rb | 30 +- app/controllers/projects/wikis_controller.rb | 4 +- app/controllers/projects_controller.rb | 16 +- app/controllers/registrations_controller.rb | 4 +- app/controllers/sessions_controller.rb | 2 + app/controllers/snippets_controller.rb | 2 +- app/controllers/users_controller.rb | 24 +- app/finders/group_projects_finder.rb | 2 +- app/finders/issuable_finder.rb | 10 +- app/finders/notes_finder.rb | 2 +- app/finders/pipelines_finder.rb | 38 ++ app/finders/todos_finder.rb | 2 +- app/helpers/application_helper.rb | 20 +- app/helpers/application_settings_helper.rb | 14 + app/helpers/auth_helper.rb | 10 + app/helpers/blob_helper.rb | 10 + app/helpers/button_helper.rb | 2 +- app/helpers/ci_status_helper.rb | 29 +- app/helpers/commits_helper.rb | 19 +- app/helpers/diff_helper.rb | 30 +- app/helpers/emails_helper.rb | 6 - app/helpers/events_helper.rb | 92 +-- app/helpers/gitlab_markdown_helper.rb | 2 +- app/helpers/gitlab_routing_helper.rb | 4 + app/helpers/groups_helper.rb | 2 +- app/helpers/issuables_helper.rb | 10 +- app/helpers/issues_helper.rb | 21 +- app/helpers/javascript_helper.rb | 7 + app/helpers/nav_helper.rb | 8 + app/helpers/notes_helper.rb | 29 +- app/helpers/projects_helper.rb | 21 +- app/helpers/search_helper.rb | 2 +- app/helpers/selects_helper.rb | 2 +- app/helpers/tab_helper.rb | 6 +- app/helpers/todos_helper.rb | 28 +- app/mailers/devise_mailer.rb | 2 + app/mailers/emails/projects.rb | 8 +- app/mailers/notify.rb | 2 + app/models/ability.rb | 54 +- app/models/abuse_report.rb | 12 - app/models/appearance.rb | 13 - app/models/application_setting.rb | 80 +-- app/models/audit_event.rb | 14 - app/models/broadcast_message.rb | 14 - app/models/ci/build.rb | 57 +- app/models/ci/commit.rb | 50 +- app/models/ci/runner.rb | 39 +- app/models/ci/runner_project.rb | 12 - app/models/ci/trigger.rb | 13 - app/models/ci/trigger_request.rb | 12 - app/models/ci/variable.rb | 19 +- app/models/commit.rb | 23 +- app/models/commit_range.rb | 2 +- app/models/commit_status.rb | 54 +- app/models/concerns/issuable.rb | 57 +- app/models/concerns/mentionable.rb | 19 +- app/models/concerns/participable.rb | 94 +-- app/models/concerns/subscribable.rb | 6 + app/models/deploy_key.rb | 15 - app/models/deploy_keys_project.rb | 11 - app/models/email.rb | 11 - app/models/event.rb | 51 +- app/models/forked_project_link.rb | 11 - app/models/generic_commit_status.rb | 37 -- app/models/group.rb | 17 - app/models/hooks/project_hook.rb | 22 - app/models/hooks/service_hook.rb | 22 - app/models/hooks/system_hook.rb | 22 - app/models/hooks/web_hook.rb | 24 +- app/models/identity.rb | 12 - app/models/issue.rb | 47 +- app/models/key.rb | 17 +- app/models/label.rb | 18 +- app/models/label_link.rb | 12 - app/models/legacy_diff_note.rb | 157 +++++ app/models/lfs_object.rb | 12 - app/models/lfs_objects_project.rb | 11 - app/models/member.rb | 19 - app/models/members/group_member.rb | 19 - app/models/members/project_member.rb | 26 +- app/models/merge_request.rb | 59 +- app/models/merge_request_diff.rb | 45 +- app/models/milestone.rb | 91 ++- app/models/namespace.rb | 25 +- app/models/network/graph.rb | 35 +- app/models/note.rb | 283 +++------ app/models/notification_setting.rb | 13 - app/models/oauth_access_token.rb | 15 - app/models/personal_snippet.rb | 16 - app/models/project.rb | 161 +++--- app/models/project_group_link.rb | 12 - app/models/project_import_data.rb | 15 +- app/models/project_services/asana_service.rb | 24 - .../project_services/assembla_service.rb | 24 - app/models/project_services/bamboo_service.rb | 24 - .../project_services/buildkite_service.rb | 24 - .../project_services/builds_email_service.rb | 24 - .../project_services/campfire_service.rb | 24 - app/models/project_services/ci_service.rb | 24 - .../custom_issue_tracker_service.rb | 24 - .../project_services/drone_ci_service.rb | 24 - .../emails_on_push_service.rb | 24 - .../project_services/external_wiki_service.rb | 26 +- .../project_services/flowdock_service.rb | 24 - .../project_services/gemnasium_service.rb | 24 - .../project_services/gitlab_ci_service.rb | 24 - .../gitlab_issue_tracker_service.rb | 24 - .../project_services/hipchat_service.rb | 24 - app/models/project_services/irker_service.rb | 26 +- .../project_services/issue_tracker_service.rb | 24 - app/models/project_services/jira_service.rb | 24 - .../pivotaltracker_service.rb | 24 - .../project_services/pushover_service.rb | 24 - .../project_services/redmine_service.rb | 24 - app/models/project_services/slack_service.rb | 24 - .../slack_service/build_message.rb | 4 +- .../slack_service/issue_message.rb | 19 +- .../project_services/teamcity_service.rb | 24 - app/models/project_snippet.rb | 19 +- app/models/project_wiki.rb | 18 +- app/models/protected_branch.rb | 12 - app/models/release.rb | 12 - app/models/repository.rb | 56 +- app/models/security_event.rb | 14 - app/models/sent_notification.rb | 14 - app/models/service.rb | 24 - app/models/snippet.rb | 23 +- app/models/spam_log.rb | 17 - app/models/subscription.rb | 13 - app/models/todo.rb | 27 +- app/models/user.rb | 110 ++-- app/models/users_star_project.rb | 11 - ...ntainer_registry_authentication_service.rb | 87 +++ app/services/ci/create_pipeline_service.rb | 50 ++ app/services/create_commit_builds_service.rb | 17 +- app/services/git_push_service.rb | 17 - app/services/git_tag_push_service.rb | 2 +- app/services/issues/update_service.rb | 10 + .../add_todo_when_build_fails_service.rb | 17 + app/services/merge_requests/base_service.rb | 25 + app/services/merge_requests/build_service.rb | 2 +- app/services/merge_requests/create_service.rb | 7 +- app/services/merge_requests/merge_service.rb | 8 +- .../merge_when_build_succeeds_service.rb | 23 +- .../merge_requests/refresh_service.rb | 7 + app/services/merge_requests/update_service.rb | 2 + app/services/notes/create_service.rb | 11 - app/services/projects/autocomplete_service.rb | 4 + app/services/projects/create_service.rb | 43 +- app/services/projects/destroy_service.rb | 12 +- app/services/projects/fork_service.rb | 14 +- app/services/projects/housekeeping_service.rb | 2 +- app/services/projects/import_service.rb | 2 +- app/services/projects/transfer_service.rb | 5 + app/services/system_hooks_service.rb | 2 +- app/services/system_note_service.rb | 25 +- app/services/todo_service.rb | 30 + app/services/wiki_pages/base_service.rb | 5 +- .../abuse_reports/_abuse_report.html.haml | 2 +- .../application_settings/_form.html.haml | 21 + app/views/admin/builds/index.html.haml | 3 +- app/views/admin/health_check/show.html.haml | 49 ++ app/views/admin/runners/_runner.html.haml | 12 +- app/views/admin/runners/show.html.haml | 24 +- app/views/dashboard/issues.atom.builder | 5 +- .../dashboard/projects/index.atom.builder | 4 +- app/views/dashboard/todos/_todo.html.haml | 14 +- .../mailer/confirmation_instructions.html.erb | 9 - .../confirmation_instructions.html.haml | 16 + .../mailer/confirmation_instructions.text.erb | 9 + app/views/devise/sessions/new.html.haml | 2 +- .../devise/sessions/two_factor.html.haml | 1 + .../devise/shared/_omniauth_box.html.haml | 2 +- .../doorkeeper/authorizations/new.html.haml | 2 +- app/views/events/_commit.html.haml | 2 +- app/views/events/_event.atom.builder | 20 + app/views/events/_event_issue.atom.haml | 2 +- .../events/_event_merge_request.atom.haml | 2 +- app/views/events/_event_note.atom.haml | 2 +- app/views/events/_event_push.atom.haml | 2 +- app/views/events/event/_common.html.haml | 2 +- app/views/events/event/_push.html.haml | 2 +- app/views/groups/_activities.html.haml | 2 +- app/views/groups/issues.atom.builder | 13 +- app/views/groups/show.atom.builder | 4 +- app/views/import/gitlab/status.html.haml | 2 +- app/views/issues/_issue.atom.builder | 14 + .../kaminari/gitlab/_first_page.html.haml | 2 +- app/views/kaminari/gitlab/_gap.html.haml | 2 +- .../kaminari/gitlab/_last_page.html.haml | 2 +- .../kaminari/gitlab/_next_page.html.haml | 2 +- app/views/kaminari/gitlab/_page.html.haml | 2 +- .../kaminari/gitlab/_paginator.html.haml | 6 +- .../kaminari/gitlab/_prev_page.html.haml | 2 +- app/views/layouts/_head.html.haml | 3 + app/views/layouts/_page.html.haml | 4 +- app/views/layouts/_search.html.haml | 7 +- app/views/layouts/devise_mailer.html.haml | 34 ++ app/views/layouts/header/_default.html.haml | 10 +- app/views/layouts/nav/_admin.html.haml | 5 + app/views/layouts/nav/_dashboard.html.haml | 14 +- app/views/layouts/nav/_group.html.haml | 75 +-- .../layouts/nav/_group_settings.html.haml | 2 +- app/views/layouts/nav/_profile.html.haml | 4 +- app/views/layouts/nav/_project.html.haml | 252 ++++---- .../layouts/nav/_project_settings.html.haml | 102 ++-- app/views/layouts/notify.html.haml | 1 + app/views/layouts/project.html.haml | 2 +- app/views/layouts/project_settings.html.haml | 3 +- app/views/notify/_note_message.html.haml | 2 +- app/views/notify/new_issue_email.html.haml | 2 +- .../notify/new_merge_request_email.html.haml | 2 +- .../notify/note_merge_request_email.html.haml | 4 +- .../notify/repository_push_email.html.haml | 59 +- .../notify/repository_push_email.text.haml | 38 +- app/views/profiles/accounts/show.html.haml | 4 +- app/views/profiles/preferences/show.html.haml | 2 +- app/views/projects/_builds_settings.html.haml | 123 ++-- app/views/projects/_home_panel.html.haml | 76 +-- app/views/projects/_md_preview.html.haml | 2 +- app/views/projects/_zen.html.haml | 2 +- app/views/projects/activity.html.haml | 1 - app/views/projects/artifacts/browse.html.haml | 1 - app/views/projects/badges/index.html.haml | 1 - app/views/projects/blame/show.html.haml | 1 - app/views/projects/blob/_editor.html.haml | 3 + .../projects/blob/_header_title.html.haml | 1 - app/views/projects/blob/edit.html.haml | 1 - app/views/projects/blob/new.html.haml | 1 - app/views/projects/blob/show.html.haml | 1 - app/views/projects/branches/destroy.js.haml | 1 - app/views/projects/branches/index.html.haml | 1 - app/views/projects/branches/new.html.haml | 1 - .../projects/builds/_header_title.html.haml | 1 - app/views/projects/builds/index.html.haml | 5 +- app/views/projects/builds/show.html.haml | 8 +- .../projects/buttons/_dropdown.html.haml | 2 +- app/views/projects/buttons/_fork.html.haml | 5 +- .../projects/buttons/_notifications.html.haml | 6 +- app/views/projects/ci/builds/_build.html.haml | 10 +- .../projects/ci/commits/_commit.html.haml | 71 +++ app/views/projects/commit/_builds.html.haml | 2 +- .../projects/commit/_ci_commit.html.haml | 63 +- app/views/projects/commit/_ci_stage.html.haml | 15 + .../projects/commit/_commit_box.html.haml | 80 +-- app/views/projects/commit/builds.html.haml | 4 +- app/views/projects/commit/show.html.haml | 2 - .../projects/commits/_commit.atom.builder | 14 + app/views/projects/commits/_commit.html.haml | 4 +- app/views/projects/commits/_commits.html.haml | 2 +- app/views/projects/commits/_head.html.haml | 8 +- .../projects/commits/_header_title.html.haml | 1 - app/views/projects/commits/show.atom.builder | 15 +- app/views/projects/commits/show.html.haml | 1 - app/views/projects/compare/index.html.haml | 1 - app/views/projects/compare/show.html.haml | 1 - .../container_registry/_tag.html.haml | 21 + .../container_registry/index.html.haml | 39 ++ .../projects/deploy_keys/index.html.haml | 4 +- app/views/projects/diffs/_file.html.haml | 8 +- app/views/projects/diffs/_line.html.haml | 2 +- .../projects/diffs/_parallel_view.html.haml | 14 +- app/views/projects/diffs/_text_file.html.haml | 9 +- app/views/projects/edit.html.haml | 445 +++++++------- app/views/projects/empty.html.haml | 10 +- app/views/projects/find_file/show.html.haml | 1 - .../_generic_commit_status.html.haml | 15 +- app/views/projects/graphs/_head.html.haml | 1 + .../projects/graphs/_header_title.html.haml | 1 - app/views/projects/graphs/ci.html.haml | 1 - app/views/projects/graphs/commits.html.haml | 1 - app/views/projects/graphs/languages.html.haml | 1 - app/views/projects/graphs/show.html.haml | 3 +- .../projects/hooks/_project_hook.html.haml | 2 +- app/views/projects/hooks/index.html.haml | 9 +- .../projects/issues/_header_title.html.haml | 1 - app/views/projects/issues/_issue.html.haml | 16 +- .../projects/issues/_merge_requests.html.haml | 7 +- .../issues/_related_branches.html.haml | 2 +- app/views/projects/issues/edit.html.haml | 1 - app/views/projects/issues/index.atom.builder | 4 +- app/views/projects/issues/index.html.haml | 1 - app/views/projects/issues/new.html.haml | 1 - app/views/projects/issues/show.html.haml | 5 +- .../projects/labels/_header_title.html.haml | 1 - app/views/projects/labels/edit.html.haml | 1 - app/views/projects/labels/index.html.haml | 3 +- app/views/projects/labels/new.html.haml | 1 - .../merge_requests/_header_title.html.haml | 1 - .../merge_requests/_merge_request.html.haml | 18 +- .../projects/merge_requests/_show.html.haml | 1 - .../dropdowns/_branch.html.haml | 2 +- .../projects/merge_requests/edit.html.haml | 1 - .../projects/merge_requests/index.html.haml | 1 - .../projects/merge_requests/invalid.html.haml | 1 - .../projects/merge_requests/new.html.haml | 1 - .../merge_requests/show/_mr_box.html.haml | 4 +- .../merge_requests/widget/_open.html.haml | 2 +- .../merge_requests/widget/_show.html.haml | 8 +- .../widget/open/_accept.html.haml | 5 +- .../open/_merge_when_build_succeeds.html.haml | 5 +- .../widget/open/_not_allowed.html.haml | 4 +- .../milestones/_header_title.html.haml | 1 - app/views/projects/milestones/edit.html.haml | 1 - app/views/projects/milestones/index.html.haml | 2 - app/views/projects/milestones/new.html.haml | 1 - app/views/projects/milestones/show.html.haml | 2 - app/views/projects/network/show.html.haml | 1 - app/views/projects/new.html.haml | 2 +- .../notes/_diff_notes_with_reply.html.haml | 18 +- .../_diff_notes_with_reply_parallel.html.haml | 20 +- .../projects/notes/_discussion.html.haml | 47 +- app/views/projects/notes/_form.html.haml | 1 + app/views/projects/notes/_note.html.haml | 11 +- app/views/projects/notes/_notes.html.haml | 9 +- .../notes/discussions/_active.html.haml | 16 - .../notes/discussions/_commit.html.haml | 25 - .../notes/discussions/_diff.html.haml | 28 - .../discussions/_diff_with_notes.html.haml | 30 + .../notes/discussions/_notes.html.haml | 7 + .../notes/discussions/_outdated.html.haml | 14 - app/views/projects/pipelines/_head.html.haml | 14 + app/views/projects/pipelines/_info.html.haml | 37 ++ app/views/projects/pipelines/index.html.haml | 58 ++ app/views/projects/pipelines/new.html.haml | 21 + app/views/projects/pipelines/show.html.haml | 8 + .../project_members/_header_title.html.haml | 1 - .../projects/project_members/import.html.haml | 1 - .../projects/project_members/index.html.haml | 1 - .../_branches_list.html.haml | 2 +- app/views/projects/releases/edit.html.haml | 1 - .../projects/repositories/_feed.html.haml | 2 +- app/views/projects/runners/_form.html.haml | 32 + app/views/projects/runners/_runner.html.haml | 2 +- .../runners/_specific_runners.html.haml | 2 +- app/views/projects/runners/edit.html.haml | 27 +- app/views/projects/runners/show.html.haml | 51 +- app/views/projects/services/_form.html.haml | 32 +- app/views/projects/services/index.html.haml | 52 +- app/views/projects/show.atom.builder | 4 +- app/views/projects/show.html.haml | 78 +-- .../projects/snippets/_actions.html.haml | 38 +- .../projects/snippets/_header_title.html.haml | 1 - app/views/projects/snippets/edit.html.haml | 1 - app/views/projects/snippets/index.html.haml | 1 - app/views/projects/snippets/new.html.haml | 1 - app/views/projects/snippets/show.html.haml | 9 +- app/views/projects/tags/destroy.js.haml | 1 - app/views/projects/tags/index.html.haml | 1 - app/views/projects/tags/new.html.haml | 3 +- app/views/projects/tags/show.html.haml | 9 +- app/views/projects/tree/show.html.haml | 2 +- app/views/projects/triggers/index.html.haml | 22 +- .../projects/variables/_content.html.haml | 8 + app/views/projects/variables/_form.html.haml | 10 + app/views/projects/variables/_table.html.haml | 25 + app/views/projects/variables/index.html.haml | 17 + app/views/projects/variables/show.html.haml | 41 +- .../projects/wikis/_header_title.html.haml | 1 - app/views/projects/wikis/edit.html.haml | 1 - app/views/projects/wikis/empty.html.haml | 1 - app/views/projects/wikis/git_access.html.haml | 1 - app/views/projects/wikis/history.html.haml | 1 - app/views/projects/wikis/pages.html.haml | 1 - app/views/projects/wikis/show.html.haml | 1 - app/views/search/results/_issue.html.haml | 2 +- .../search/results/_merge_request.html.haml | 2 +- app/views/search/results/_note.html.haml | 2 +- app/views/shared/_clone_panel.html.haml | 2 +- app/views/shared/_event_filter.html.haml | 4 +- app/views/shared/_sort_dropdown.html.haml | 2 +- app/views/shared/groups/_list.html.haml | 2 +- app/views/shared/issuable/_filter.html.haml | 6 +- app/views/shared/issuable/_form.html.haml | 93 +-- .../shared/issuable/_search_form.html.haml | 6 - app/views/shared/issuable/_sidebar.html.haml | 24 +- .../milestones/_participants_tab.html.haml | 2 +- app/views/shared/projects/_project.html.haml | 5 +- app/views/shared/snippets/_header.html.haml | 23 +- app/views/snippets/_actions.html.haml | 38 +- app/views/snippets/show.html.haml | 7 +- app/views/users/calendar.html.haml | 19 +- app/views/users/calendar_activities.html.haml | 42 +- app/views/users/show.atom.builder | 4 +- app/views/users/show.html.haml | 14 +- app/workers/emails_on_push_worker.rb | 44 +- app/workers/repository_fork_worker.rb | 6 +- app/workers/repository_import_worker.rb | 3 +- config/application.rb | 32 +- config/boot.rb | 2 +- config/environments/development.rb | 1 + config/environments/test.rb | 2 +- config/gitlab.yml.example | 10 + config/initializers/1_settings.rb | 46 +- config/initializers/5_backend.rb | 6 +- config/initializers/carrierwave.rb | 4 +- config/initializers/devise.rb | 2 +- config/initializers/devise_async.rb | 1 - config/initializers/doorkeeper.rb | 4 +- config/initializers/health_check.rb | 3 + config/initializers/metrics.rb | 3 + config/initializers/monkey_patch.rb | 48 -- config/initializers/omniauth.rb | 2 +- config/initializers/premailer.rb | 2 +- config/initializers/session_store.rb | 2 +- config/routes.rb | 63 +- ...8_remove_wrong_import_url_from_projects.rb | 4 +- ...roup_visibility_to_application_settings.rb | 4 +- ...07120251_add_images_enabled_for_project.rb | 5 + ...sign_in_sources_to_application_settings.rb | 5 + ...504112519_add_run_untagged_to_ci_runner.rb | 13 + .../20160508215820_add_type_to_notes.rb | 5 + ...508221410_set_type_on_legacy_diff_notes.rb | 5 + ...ck_access_token_to_application_settings.rb | 5 + ...firmation_email_to_application_settings.rb | 12 + ...5328_remove_main_language_from_projects.rb | 21 + ...ification_settings_for_deleted_projects.rb | 13 + .../20160528043124_add_users_state_index.rb | 9 + ...en_expire_delay_to_application_settings.rb | 9 + db/schema.rb | 55 +- doc/README.md | 3 + doc/administration/container_registry.md | 375 ++++++++++++ doc/administration/environment_variables.md | 2 +- .../high_availability/README.md | 4 + .../high_availability/load_balancer.md | 2 +- doc/administration/high_availability/nfs.md | 6 +- doc/administration/high_availability/redis.md | 2 +- .../active-active-diagram.png | Bin 0 -> 29607 bytes .../active-passive-diagram.png | Bin 0 -> 24246 bytes doc/administration/repository_checks.md | 4 +- doc/administration/troubleshooting/sidekiq.md | 8 + doc/api/README.md | 2 +- doc/api/build_triggers.md | 12 +- doc/api/groups.md | 2 - doc/api/issues.md | 15 +- doc/api/labels.md | 72 ++- doc/api/merge_requests.md | 22 +- doc/api/notes.md | 10 +- doc/api/projects.md | 3 + doc/api/runners.md | 4 +- doc/api/services.md | 8 +- doc/api/settings.md | 7 +- doc/ci/{ => examples}/deployment/README.md | 0 doc/ci/quick_start/README.md | 4 +- doc/ci/runners/README.md | 8 +- doc/ci/triggers/README.md | 2 +- doc/ci/yaml/README.md | 4 +- doc/container_registry/README.md | 113 ++++ .../img/container_registry.png | Bin 0 -> 354050 bytes .../img/project_feature.png | Bin 0 -> 392842 bytes doc/development/doc_styleguide.md | 4 +- doc/development/instrumentation.md | 129 ++++- doc/development/migration_style_guide.md | 48 +- doc/development/testing.md | 2 +- doc/development/ui_guide.md | 48 ++ doc/gitlab-basics/create-issue.md | 2 +- doc/gitlab-basics/create-project.md | 2 +- doc/hooks/custom_hooks.md | 2 +- doc/install/installation.md | 8 +- doc/install/relative_url.md | 2 +- doc/install/requirements.md | 3 +- doc/integration/README.md | 2 +- doc/integration/cas.md | 19 +- doc/integration/google.md | 4 +- .../img/enabled-oauth-sign-in-sources.png | Bin 0 -> 49081 bytes doc/integration/omniauth.md | 15 + doc/intro/README.md | 2 +- doc/logs/logs.md | 8 +- doc/markdown/markdown.md | 49 +- doc/migrate_ci_to_ce/README.md | 2 +- doc/monitoring/health_check.md | 66 +++ doc/monitoring/img/health_check_token.png | Bin 0 -> 10884 bytes doc/operations/moving_repositories.md | 8 +- doc/permissions/permissions.md | 3 + doc/raketasks/README.md | 2 +- doc/security/README.md | 1 + doc/security/user_email_confirmation.md | 7 + doc/update/8.6-to-8.7.md | 8 + doc/update/8.7-to-8.8.md | 162 ++++++ doc/update/README.md | 6 +- doc/update/patch_versions.md | 4 +- doc/web_hooks/web_hooks.md | 68 +++ doc/workflow/gitlab_flow.md | 4 +- doc/workflow/groups.md | 2 +- .../importing/import_projects_from_github.md | 2 +- .../import_projects_from_gitlab_com.md | 2 +- .../lfs/manage_large_binaries_with_git_lfs.md | 6 +- doc/workflow/notifications.md | 2 +- features/project/active_tab.feature | 55 +- features/project/builds/summary.feature | 1 + features/project/commits/tags.feature | 46 -- features/project/create.feature | 16 +- features/project/project.feature | 9 - features/project/shortcuts.feature | 8 +- features/steps/admin/active_tab.rb | 10 +- features/steps/admin/users.rb | 2 +- features/steps/dashboard/active_tab.rb | 6 +- features/steps/dashboard/dashboard.rb | 2 +- features/steps/dashboard/issues.rb | 2 +- features/steps/dashboard/merge_requests.rb | 2 +- features/steps/dashboard/shortcuts.rb | 3 +- features/steps/dashboard/todos.rb | 4 +- features/steps/profile/active_tab.rb | 4 - features/steps/profile/profile.rb | 2 +- features/steps/project/active_tab.rb | 32 +- features/steps/project/builds/summary.rb | 4 + features/steps/project/commits/commits.rb | 6 +- features/steps/project/commits/tags.rb | 90 --- features/steps/project/create.rb | 26 +- features/steps/project/fork.rb | 2 +- features/steps/project/hooks.rb | 2 +- features/steps/project/issues/award_emoji.rb | 4 +- features/steps/project/issues/issues.rb | 6 +- features/steps/project/issues/labels.rb | 4 +- features/steps/project/merge_requests.rb | 10 +- features/steps/project/project.rb | 12 +- features/steps/project/project_find_file.rb | 4 +- features/steps/project/project_milestone.rb | 2 +- features/steps/project/project_shortcuts.rb | 1 + features/steps/project/snippets.rb | 4 +- features/steps/project/source/browse_files.rb | 16 +- features/steps/project/team_management.rb | 2 +- features/steps/shared/active_tab.rb | 28 +- features/steps/shared/diff_note.rb | 12 +- features/steps/shared/issuable.rb | 8 +- features/steps/shared/note.rb | 2 +- features/steps/shared/project.rb | 2 +- features/steps/shared/project_tab.rb | 20 +- features/steps/shared/shortcuts.rb | 2 +- features/steps/shared/sidebar_active_tab.rb | 35 ++ features/steps/snippets/snippets.rb | 4 +- features/steps/user.rb | 2 +- .../migration/create_table_migration.rb | 35 ++ .../active_record/migration/migration.rb | 55 ++ lib/api/api.rb | 69 +-- lib/api/api_guard.rb | 302 +++++----- lib/api/commit_statuses.rb | 2 +- lib/api/commits.rb | 2 + lib/api/entities.rb | 27 +- lib/api/gitignores.rb | 29 + lib/api/groups.rb | 3 +- lib/api/helpers.rb | 15 +- lib/api/issues.rb | 39 +- lib/api/labels.rb | 6 +- lib/api/licenses.rb | 14 +- lib/api/merge_requests.rb | 36 -- lib/api/notes.rb | 45 +- lib/api/projects.rb | 7 +- lib/api/runners.rb | 2 +- lib/api/subscriptions.rb | 60 ++ lib/api/users.rb | 2 +- lib/backup/manager.rb | 17 +- lib/backup/registry.rb | 13 + .../filter/abstract_reference_filter.rb | 12 +- .../filter/commit_range_reference_filter.rb | 20 +- lib/banzai/filter/commit_reference_filter.rb | 20 +- .../filter/external_issue_reference_filter.rb | 14 +- lib/banzai/filter/inline_diff_filter.rb | 26 + lib/banzai/filter/issue_reference_filter.rb | 7 +- lib/banzai/filter/label_reference_filter.rb | 2 + .../filter/merge_request_reference_filter.rb | 2 + .../filter/milestone_reference_filter.rb | 46 +- lib/banzai/filter/redactor_filter.rb | 31 +- lib/banzai/filter/reference_filter.rb | 24 +- .../filter/reference_gatherer_filter.rb | 65 --- lib/banzai/filter/sanitization_filter.rb | 2 +- lib/banzai/filter/snippet_reference_filter.rb | 2 + lib/banzai/filter/upload_link_filter.rb | 8 +- lib/banzai/filter/user_reference_filter.rb | 44 +- lib/banzai/filter/wiki_link_filter.rb | 11 +- lib/banzai/lazy_reference.rb | 25 - lib/banzai/pipeline/gfm_pipeline.rb | 3 +- .../pipeline/reference_extraction_pipeline.rb | 11 - lib/banzai/reference_extractor.rb | 48 +- lib/banzai/reference_parser.rb | 14 + lib/banzai/reference_parser/base_parser.rb | 204 +++++++ lib/banzai/reference_parser/commit_parser.rb | 34 ++ .../reference_parser/commit_range_parser.rb | 38 ++ .../reference_parser/external_issue_parser.rb | 25 + lib/banzai/reference_parser/issue_parser.rb | 40 ++ lib/banzai/reference_parser/label_parser.rb | 11 + .../reference_parser/merge_request_parser.rb | 11 + .../reference_parser/milestone_parser.rb | 11 + lib/banzai/reference_parser/snippet_parser.rb | 11 + lib/banzai/reference_parser/user_parser.rb | 92 +++ lib/ci/ansi2html.rb | 87 ++- lib/ci/api/api.rb | 10 +- lib/ci/api/runners.rb | 18 +- lib/ci/charts.rb | 3 +- lib/ci/gitlab_ci_yaml_processor.rb | 4 +- lib/container_registry/blob.rb | 48 ++ lib/container_registry/client.rb | 61 ++ lib/container_registry/config.rb | 16 + lib/container_registry/registry.rb | 21 + lib/container_registry/repository.rb | 48 ++ lib/container_registry/tag.rb | 77 +++ lib/event_filter.rb | 2 +- lib/gitlab.rb | 2 +- lib/gitlab/backend/shell.rb | 2 +- lib/gitlab/bitbucket_import/client.rb | 2 +- .../bitbucket_import/project_creator.rb | 7 +- lib/gitlab/ci/build/artifacts/metadata.rb | 2 +- lib/gitlab/contributions_calendar.rb | 2 +- lib/gitlab/current_settings.rb | 27 +- lib/gitlab/database.rb | 4 +- lib/gitlab/database/migration_helpers.rb | 142 +++++ lib/gitlab/diff/inline_diff_marker.rb | 36 +- lib/gitlab/diff/parser.rb | 16 +- lib/gitlab/email/message/repository_push.rb | 11 +- lib/gitlab/email/reply_parser.rb | 2 +- lib/gitlab/fogbugz_import/project_creator.rb | 9 +- lib/gitlab/github_import/branch_formatter.rb | 29 + lib/gitlab/github_import/importer.rb | 72 ++- .../github_import/pull_request_formatter.rb | 54 +- lib/gitlab/gitignore.rb | 56 ++ lib/gitlab/gitlab_import/importer.rb | 8 +- .../google_code_import/project_creator.rb | 9 +- lib/gitlab/lazy.rb | 34 ++ lib/gitlab/markup_helper.rb | 2 +- lib/gitlab/metrics/instrumentation.rb | 2 - lib/gitlab/metrics/subscribers/rails_cache.rb | 12 +- lib/gitlab/middleware/go.rb | 2 +- lib/gitlab/middleware/rails_queue_duration.rb | 24 + lib/gitlab/project_search_results.rb | 2 +- lib/gitlab/redis.rb | 8 +- lib/gitlab/reference_extractor.rb | 19 +- lib/gitlab/regex.rb | 4 + lib/gitlab/sanitizers/svg.rb | 8 +- lib/gitlab/sanitizers/svg/whitelist.rb | 170 +++--- lib/gitlab/url_builder.rb | 2 +- .../{import_url.rb => url_sanitizer.rb} | 17 +- lib/gitlab/visibility_level.rb | 7 + lib/json_web_token/rsa_token.rb | 42 ++ lib/json_web_token/token.rb | 46 ++ lib/support/nginx/registry-ssl | 53 ++ lib/tasks/auto_annotate_models.rake | 44 -- lib/tasks/gitlab/backup.rake | 29 + lib/tasks/gitlab/check.rake | 2 +- lib/tasks/gitlab/db.rake | 14 +- lib/tasks/gitlab/update_gitignore.rake | 46 ++ lib/tasks/rubocop.rake | 1 + public/robots.txt | 1 + shared/registry/.gitkeep | 0 spec/config/mail_room_spec.rb | 2 +- .../admin/projects_controller_spec.rb | 2 +- .../admin/users_controller_spec.rb | 76 +++ .../health_check_controller_spec.rb | 105 ++++ .../projects/branches_controller_spec.rb | 4 - .../projects/compare_controller_spec.rb | 4 +- .../projects/group_links_controller_spec.rb | 4 +- .../projects/issues_controller_spec.rb | 2 +- .../merge_requests_controller_spec.rb | 2 +- .../notification_settings_controller_spec.rb | 14 + .../project_members_controller_spec.rb | 2 +- .../projects/raw_controller_spec.rb | 2 +- spec/controllers/projects_controller_spec.rb | 45 ++ .../registrations_controller_spec.rb | 33 ++ spec/controllers/sessions_controller_spec.rb | 29 +- spec/controllers/users_controller_spec.rb | 22 + spec/factories/abuse_reports.rb | 12 - spec/factories/broadcast_messages.rb | 14 - spec/factories/forked_project_links.rb | 11 - spec/factories/label_links.rb | 12 - spec/factories/labels.rb | 13 - spec/factories/lfs_objects.rb | 12 - spec/factories/lfs_objects_projects.rb | 11 - spec/factories/merge_requests.rb | 29 - spec/factories/notes.rb | 45 +- spec/factories/oauth_access_tokens.rb | 15 - spec/factories/projects.rb | 49 +- spec/factories/releases.rb | 12 - spec/factories/todos.rb | 22 +- spec/factories_spec.rb | 4 +- spec/features/admin/admin_builds_spec.rb | 1 + .../features/admin/admin_health_check_spec.rb | 55 ++ spec/features/admin/admin_runners_spec.rb | 2 +- spec/features/admin/admin_users_spec.rb | 5 +- spec/features/builds_spec.rb | 4 +- spec/features/commits_spec.rb | 10 +- spec/features/container_registry_spec.rb | 44 ++ spec/features/issues/filter_issues_spec.rb | 176 ++++++ spec/features/issues/move_spec.rb | 16 +- spec/features/issues/note_polling_spec.rb | 5 +- spec/features/issues/update_issues_spec.rb | 2 +- spec/features/issues_spec.rb | 99 +++- spec/features/login_spec.rb | 10 +- spec/features/markdown_spec.rb | 4 + .../merge_requests/created_from_fork_spec.rb | 58 ++ .../user_lists_merge_requests_spec.rb | 161 ++++++ spec/features/notes_on_merge_requests_spec.rb | 12 +- .../participants_autocomplete_spec.rb | 6 +- spec/features/pipelines_spec.rb | 189 ++++++ spec/features/projects/badges/list_spec.rb | 5 +- ...r_views_empty_project_instructions_spec.rb | 63 ++ .../projects/files/gitignore_dropdown_spec.rb | 30 + ...project_owner_creates_license_file_spec.rb | 8 +- ...eate_license_file_in_empty_project_spec.rb | 4 +- .../{project => projects}/shortcuts_spec.rb | 4 +- spec/features/runners_spec.rb | 37 +- spec/features/signup_spec.rb | 45 +- spec/features/tags/master_creates_tag_spec.rb | 62 ++ spec/features/tags/master_deletes_tag_spec.rb | 41 ++ spec/features/tags/master_updates_tag_spec.rb | 42 ++ spec/features/tags/master_views_tags_spec.rb | 73 +++ spec/features/task_lists_spec.rb | 5 +- spec/features/todos/target_state_spec.rb | 65 +++ spec/features/todos/todos_spec.rb | 21 + spec/features/variables_spec.rb | 59 +- spec/finders/issues_finder_spec.rb | 186 +++--- .../container_registry/config_blob.json | 1 + .../container_registry/tag_manifest.json | 1 + spec/fixtures/markdown.md.erb | 23 +- spec/helpers/auth_helper_spec.rb | 47 +- spec/helpers/diff_helper_spec.rb | 4 +- spec/helpers/events_helper_spec.rb | 95 +-- spec/helpers/merge_requests_helper_spec.rb | 2 +- spec/helpers/projects_helper_spec.rb | 10 +- .../fixtures/right_sidebar.html.haml | 13 + .../stat_graph_contributors_graph_spec.js | 2 +- .../stat_graph_contributors_util_spec.js | 2 +- .../{ => graphs}/stat_graph_spec.js | 2 +- spec/javascripts/project_title_spec.js.coffee | 1 + spec/javascripts/right_sidebar_spec.js.coffee | 69 +++ spec/lib/award_emoji_spec.rb | 2 +- .../commit_range_reference_filter_spec.rb | 15 - .../filter/commit_reference_filter_spec.rb | 15 - .../banzai/filter/inline_diff_filter_spec.rb | 68 +++ .../filter/issue_reference_filter_spec.rb | 25 - .../filter/label_reference_filter_spec.rb | 10 - .../merge_request_reference_filter_spec.rb | 15 - .../filter/milestone_reference_filter_spec.rb | 159 ++++- .../lib/banzai/filter/redactor_filter_spec.rb | 38 +- .../filter/reference_gatherer_filter_spec.rb | 87 --- .../banzai/filter/sanitization_filter_spec.rb | 6 + .../filter/snippet_reference_filter_spec.rb | 15 - .../banzai/filter/upload_link_filter_spec.rb | 18 + .../filter/user_reference_filter_spec.rb | 35 +- .../banzai/filter/wiki_link_filter_spec.rb | 85 +++ .../reference_parser/base_parser_spec.rb | 237 ++++++++ .../reference_parser/commit_parser_spec.rb | 113 ++++ .../commit_range_parser_spec.rb | 120 ++++ .../external_issue_parser_spec.rb | 62 ++ .../reference_parser/issue_parser_spec.rb | 79 +++ .../reference_parser/label_parser_spec.rb | 31 + .../merge_request_parser_spec.rb | 30 + .../reference_parser/milestone_parser_spec.rb | 31 + .../reference_parser/snippet_parser_spec.rb | 31 + .../reference_parser/user_parser_spec.rb | 189 ++++++ spec/lib/ci/ansi2html_spec.rb | 120 ++-- spec/lib/ci/charts_spec.rb | 7 + spec/lib/ci/gitlab_ci_yaml_processor_spec.rb | 10 +- spec/lib/container_registry/blob_spec.rb | 61 ++ spec/lib/container_registry/registry_spec.rb | 28 + .../lib/container_registry/repository_spec.rb | 65 +++ spec/lib/container_registry/tag_spec.rb | 89 +++ spec/lib/gitlab/akismet_helper_spec.rb | 4 +- .../gitlab/bitbucket_import/client_spec.rb | 2 +- .../ci/build/artifacts/metadata/entry_spec.rb | 6 +- .../gitlab/database/migration_helpers_spec.rb | 128 ++++ .../email/message/repository_push_spec.rb | 4 +- .../lib/gitlab/gfm/reference_rewriter_spec.rb | 4 +- spec/lib/gitlab/gfm/uploads_rewriter_spec.rb | 8 +- .../github_import/branch_formatter_spec.rb | 71 +++ .../pull_request_formatter_spec.rb | 46 +- spec/lib/gitlab/gitignore_spec.rb | 40 ++ spec/lib/gitlab/import_url_spec.rb | 21 - spec/lib/gitlab/lazy_spec.rb | 37 ++ spec/lib/gitlab/lfs/lfs_router_spec.rb | 8 +- .../gitlab/metrics/instrumentation_spec.rb | 14 +- spec/lib/gitlab/metrics/sampler_spec.rb | 2 +- .../metrics/subscribers/active_record_spec.rb | 2 +- .../metrics/subscribers/rails_cache_spec.rb | 16 +- .../middleware/rails_queue_duration_spec.rb | 31 + spec/lib/gitlab/note_data_builder_spec.rb | 71 ++- spec/lib/gitlab/sherlock/collection_spec.rb | 6 +- spec/lib/gitlab/sherlock/query_spec.rb | 2 +- spec/lib/gitlab/sherlock/transaction_spec.rb | 4 +- spec/lib/gitlab/url_sanitizer_spec.rb | 68 +++ spec/lib/json_web_token/rsa_token_spec.rb | 43 ++ spec/lib/json_web_token/token_spec.rb | 18 + spec/mailers/notify_spec.rb | 54 +- .../mailers/previews/devise_mailer_preview.rb | 11 + spec/mailers/shared/notify.rb | 4 +- spec/models/ability_spec.rb | 117 ++++ spec/models/abuse_report_spec.rb | 12 - spec/models/application_setting_spec.rb | 55 +- spec/models/broadcast_message_spec.rb | 14 - spec/models/build_spec.rb | 98 ++-- spec/models/ci/commit_spec.rb | 21 +- spec/models/ci/runner_project_spec.rb | 17 - spec/models/ci/runner_spec.rb | 51 +- spec/models/ci/trigger_spec.rb | 13 - spec/models/ci/variable_spec.rb | 16 +- spec/models/commit_range_spec.rb | 34 ++ spec/models/commit_spec.rb | 40 +- spec/models/commit_status_spec.rb | 34 -- spec/models/concerns/issuable_spec.rb | 54 +- spec/models/concerns/participable_spec.rb | 83 +++ spec/models/concerns/subscribable_spec.rb | 10 + .../concerns/token_authenticatable_spec.rb | 6 +- spec/models/deploy_key_spec.rb | 15 - spec/models/deploy_keys_project_spec.rb | 11 - spec/models/email_spec.rb | 11 - spec/models/event_spec.rb | 16 - spec/models/forked_project_link_spec.rb | 11 - spec/models/generic_commit_status_spec.rb | 38 +- spec/models/group_spec.rb | 15 - spec/models/hooks/service_hook_spec.rb | 4 +- spec/models/hooks/system_hook_spec.rb | 20 +- spec/models/hooks/web_hook_spec.rb | 4 +- spec/models/identity_spec.rb | 12 - spec/models/issue_spec.rb | 77 ++- spec/models/key_spec.rb | 15 - spec/models/label_link_spec.rb | 12 - spec/models/label_spec.rb | 21 +- spec/models/legacy_diff_note_spec.rb | 76 +++ spec/models/member_spec.rb | 19 - spec/models/members/project_member_spec.rb | 42 ++ spec/models/merge_request_spec.rb | 99 ++-- spec/models/milestone_spec.rb | 56 +- spec/models/namespace_spec.rb | 29 +- spec/models/note_spec.rb | 187 +++--- .../project_services/hipchat_service_spec.rb | 149 +++-- .../slack_service/build_message_spec.rb | 23 +- .../slack_service/issue_message_spec.rb | 11 +- .../slack_service/note_message_spec.rb | 4 +- .../project_services/slack_service_spec.rb | 68 ++- spec/models/project_snippet_spec.rb | 16 - spec/models/project_spec.rb | 132 +++-- spec/models/project_wiki_spec.rb | 16 +- spec/models/protected_branch_spec.rb | 12 - spec/models/release_spec.rb | 12 - spec/models/repository_spec.rb | 46 +- spec/models/service_spec.rb | 21 - spec/models/snippet_spec.rb | 43 +- spec/models/todo_spec.rb | 18 - spec/models/user_spec.rb | 89 +-- spec/requests/api/builds_spec.rb | 4 +- ...status_spec.rb => commit_statuses_spec.rb} | 2 +- spec/requests/api/gitignores_spec.rb | 29 + spec/requests/api/group_members_spec.rb | 10 +- spec/requests/api/groups_spec.rb | 21 +- spec/requests/api/issues_spec.rb | 33 ++ spec/requests/api/labels_spec.rb | 82 +++ spec/requests/api/licenses_spec.rb | 12 +- spec/requests/api/merge_requests_spec.rb | 28 + spec/requests/api/notes_spec.rb | 71 ++- spec/requests/api/project_members_spec.rb | 2 +- spec/requests/api/projects_spec.rb | 21 +- spec/requests/api/runners_spec.rb | 15 +- spec/requests/api/system_hooks_spec.rb | 2 +- spec/requests/api/users_spec.rb | 2 +- spec/requests/ci/api/builds_spec.rb | 40 +- spec/requests/ci/api/runners_spec.rb | 83 ++- spec/requests/jwt_controller_spec.rb | 72 +++ spec/routing/admin_routing_spec.rb | 7 + spec/routing/routing_spec.rb | 51 +- ...er_registry_authentication_service_spec.rb | 242 ++++++++ .../create_commit_builds_service_spec.rb | 2 +- spec/services/git_push_service_spec.rb | 43 -- spec/services/groups/create_service_spec.rb | 4 +- .../issues/bulk_update_service_spec.rb | 9 +- spec/services/issues/create_service_spec.rb | 6 +- spec/services/issues/move_service_spec.rb | 6 +- spec/services/issues/update_service_spec.rb | 24 +- .../add_todo_when_build_fails_service_spec.rb | 81 +++ .../merge_requests/create_service_spec.rb | 4 +- .../merge_requests/merge_service_spec.rb | 15 + .../merge_when_build_succeeds_service_spec.rb | 16 +- .../merge_requests/refresh_service_spec.rb | 28 + .../merge_requests/update_service_spec.rb | 8 +- spec/services/notification_service_spec.rb | 30 + spec/services/projects/create_service_spec.rb | 4 +- .../services/projects/destroy_service_spec.rb | 31 +- spec/services/projects/fork_service_spec.rb | 27 + spec/services/projects/import_service_spec.rb | 2 +- .../projects/transfer_service_spec.rb | 11 + spec/services/system_note_service_spec.rb | 26 +- spec/services/todo_service_spec.rb | 38 ++ spec/support/filter_spec_helper.rb | 3 +- spec/support/jira_service_helper.rb | 10 +- spec/support/login_helpers.rb | 6 +- spec/support/markdown_feature.rb | 6 +- spec/support/matchers/markdown_matchers.rb | 12 +- spec/support/reference_parser_helpers.rb | 5 + spec/support/stub_gitlab_calls.rb | 37 +- spec/tasks/gitlab/backup_rake_spec.rb | 32 +- spec/tasks/gitlab/db_rake_spec.rb | 62 ++ spec/teaspoon_env.rb | 50 +- spec/workers/emails_on_push_worker_spec.rb | 65 ++- spec/workers/post_receive_spec.rb | 16 + spec/workers/repository_import_worker_spec.rb | 26 +- vendor/assets/javascripts/jquery.scrollTo.js | 210 +++++++ vendor/assets/stylesheets/animate.css | 11 - vendor/gitignore/Actionscript.gitignore | 19 + vendor/gitignore/Ada.gitignore | 5 + vendor/gitignore/Agda.gitignore | 1 + vendor/gitignore/Android.gitignore | 39 ++ vendor/gitignore/AppEngine.gitignore | 2 + .../gitignore/AppceleratorTitanium.gitignore | 3 + vendor/gitignore/ArchLinuxPackages.gitignore | 13 + vendor/gitignore/Autotools.gitignore | 18 + vendor/gitignore/C++.gitignore | 28 + vendor/gitignore/C.gitignore | 33 ++ vendor/gitignore/CFWheels.gitignore | 12 + vendor/gitignore/CMake.gitignore | 6 + vendor/gitignore/CUDA.gitignore | 6 + vendor/gitignore/CakePHP.gitignore | 25 + vendor/gitignore/ChefCookbook.gitignore | 9 + vendor/gitignore/Clojure.gitignore | 1 + vendor/gitignore/CodeIgniter.gitignore | 6 + vendor/gitignore/CommonLisp.gitignore | 3 + vendor/gitignore/Composer.gitignore | 6 + vendor/gitignore/Concrete5.gitignore | 4 + vendor/gitignore/Coq.gitignore | 3 + vendor/gitignore/CraftCMS.gitignore | 3 + vendor/gitignore/D.gitignore | 20 + vendor/gitignore/DM.gitignore | 5 + vendor/gitignore/Dart.gitignore | 27 + vendor/gitignore/Delphi.gitignore | 66 +++ vendor/gitignore/Drupal.gitignore | 36 ++ vendor/gitignore/EPiServer.gitignore | 4 + vendor/gitignore/Eagle.gitignore | 44 ++ vendor/gitignore/Elisp.gitignore | 5 + vendor/gitignore/Elixir.gitignore | 5 + vendor/gitignore/Elm.gitignore | 4 + vendor/gitignore/Erlang.gitignore | 10 + vendor/gitignore/ExpressionEngine.gitignore | 19 + vendor/gitignore/ExtJs.gitignore | 4 + vendor/gitignore/Fancy.gitignore | 2 + vendor/gitignore/Finale.gitignore | 13 + vendor/gitignore/ForceDotCom.gitignore | 4 + vendor/gitignore/Fortran.gitignore | 1 + vendor/gitignore/FuelPHP.gitignore | 21 + vendor/gitignore/GWT.gitignore | 28 + vendor/gitignore/Gcov.gitignore | 5 + vendor/gitignore/GitBook.gitignore | 16 + vendor/gitignore/Global/Anjuta.gitignore | 3 + vendor/gitignore/Global/Archives.gitignore | 27 + vendor/gitignore/Global/BricxCC.gitignore | 4 + vendor/gitignore/Global/CVS.gitignore | 4 + vendor/gitignore/Global/Calabash.gitignore | 10 + vendor/gitignore/Global/Cloud9.gitignore | 3 + vendor/gitignore/Global/CodeKit.gitignore | 3 + vendor/gitignore/Global/DartEditor.gitignore | 2 + vendor/gitignore/Global/Dreamweaver.gitignore | 7 + vendor/gitignore/Global/Dropbox.gitignore | 4 + vendor/gitignore/Global/Eclipse.gitignore | 51 ++ .../gitignore/Global/EiffelStudio.gitignore | 2 + vendor/gitignore/Global/Emacs.gitignore | 42 ++ vendor/gitignore/Global/Ensime.gitignore | 4 + vendor/gitignore/Global/Espresso.gitignore | 1 + vendor/gitignore/Global/FlexBuilder.gitignore | 3 + vendor/gitignore/Global/GPG.gitignore | 2 + .../Global/IPythonNotebook.gitignore | 2 + vendor/gitignore/Global/JDeveloper.gitignore | 13 + vendor/gitignore/Global/JetBrains.gitignore | 44 ++ vendor/gitignore/Global/KDevelop4.gitignore | 2 + vendor/gitignore/Global/Kate.gitignore | 3 + vendor/gitignore/Global/Lazarus.gitignore | 30 + vendor/gitignore/Global/LibreOffice.gitignore | 2 + vendor/gitignore/Global/Linux.gitignore | 10 + vendor/gitignore/Global/LyX.gitignore | 4 + vendor/gitignore/Global/Matlab.gitignore | 19 + vendor/gitignore/Global/Mercurial.gitignore | 6 + .../Global/MicrosoftOffice.gitignore | 16 + vendor/gitignore/Global/ModelSim.gitignore | 23 + vendor/gitignore/Global/Momentics.gitignore | 8 + vendor/gitignore/Global/MonoDevelop.gitignore | 8 + vendor/gitignore/Global/NetBeans.gitignore | 7 + vendor/gitignore/Global/Ninja.gitignore | 2 + vendor/gitignore/Global/NotepadPP.gitignore | 2 + vendor/gitignore/Global/OSX.gitignore | 24 + vendor/gitignore/Global/Otto.gitignore | 1 + vendor/gitignore/Global/Redcar.gitignore | 1 + vendor/gitignore/Global/Redis.gitignore | 3 + vendor/gitignore/Global/SBT.gitignore | 9 + vendor/gitignore/Global/SVN.gitignore | 1 + vendor/gitignore/Global/SlickEdit.gitignore | 11 + vendor/gitignore/Global/SublimeText.gitignore | 14 + vendor/gitignore/Global/SynopsysVCS.gitignore | 36 ++ vendor/gitignore/Global/Tags.gitignore | 16 + vendor/gitignore/Global/TextMate.gitignore | 3 + vendor/gitignore/Global/TortoiseGit.gitignore | 2 + vendor/gitignore/Global/Vagrant.gitignore | 1 + vendor/gitignore/Global/Vim.gitignore | 10 + vendor/gitignore/Global/VirtualEnv.gitignore | 12 + .../Global/VisualStudioCode.gitignore | 2 + vendor/gitignore/Global/WebMethods.gitignore | 14 + vendor/gitignore/Global/Windows.gitignore | 18 + vendor/gitignore/Global/Xcode.gitignore | 23 + vendor/gitignore/Global/XilinxISE.gitignore | 67 +++ vendor/gitignore/Go.gitignore | 24 + vendor/gitignore/Gradle.gitignore | 14 + vendor/gitignore/Grails.gitignore | 33 ++ vendor/gitignore/Haskell.gitignore | 18 + vendor/gitignore/IGORPro.gitignore | 5 + vendor/gitignore/Idris.gitignore | 2 + vendor/gitignore/Java.gitignore | 12 + vendor/gitignore/Jboss.gitignore | 19 + vendor/gitignore/Jekyll.gitignore | 3 + vendor/gitignore/Joomla.gitignore | 546 ++++++++++++++++++ vendor/gitignore/KiCad.gitignore | 20 + vendor/gitignore/Kohana.gitignore | 2 + vendor/gitignore/LabVIEW.gitignore | 16 + vendor/gitignore/Laravel.gitignore | 16 + vendor/gitignore/Leiningen.gitignore | 12 + vendor/gitignore/LemonStand.gitignore | 21 + vendor/gitignore/Lilypond.gitignore | 6 + vendor/gitignore/Lithium.gitignore | 2 + vendor/gitignore/Lua.gitignore | 41 ++ vendor/gitignore/Magento.gitignore | 104 ++++ vendor/gitignore/Maven.gitignore | 9 + vendor/gitignore/Mercury.gitignore | 13 + .../gitignore/MetaProgrammingSystem.gitignore | 16 + vendor/gitignore/Nanoc.gitignore | 10 + vendor/gitignore/Nim.gitignore | 1 + vendor/gitignore/Node.gitignore | 37 ++ vendor/gitignore/OCaml.gitignore | 20 + vendor/gitignore/Objective-C.gitignore | 51 ++ vendor/gitignore/Opa.gitignore | 13 + vendor/gitignore/OpenCart.gitignore | 13 + vendor/gitignore/OracleForms.gitignore | 8 + vendor/gitignore/Packer.gitignore | 5 + vendor/gitignore/Perl.gitignore | 20 + vendor/gitignore/Phalcon.gitignore | 2 + vendor/gitignore/PlayFramework.gitignore | 15 + vendor/gitignore/Plone.gitignore | 18 + vendor/gitignore/Prestashop.gitignore | 32 + vendor/gitignore/Processing.gitignore | 7 + vendor/gitignore/Python.gitignore | 89 +++ vendor/gitignore/Qooxdoo.gitignore | 5 + vendor/gitignore/Qt.gitignore | 38 ++ vendor/gitignore/R.gitignore | 33 ++ vendor/gitignore/README.md | 14 + vendor/gitignore/ROS.gitignore | 47 ++ vendor/gitignore/Rails.gitignore | 38 ++ vendor/gitignore/RhodesRhomobile.gitignore | 9 + vendor/gitignore/Ruby.gitignore | 50 ++ vendor/gitignore/Rust.gitignore | 7 + vendor/gitignore/SCons.gitignore | 2 + vendor/gitignore/Sass.gitignore | 2 + vendor/gitignore/Scala.gitignore | 17 + vendor/gitignore/Scheme.gitignore | 7 + vendor/gitignore/Scrivener.gitignore | 7 + vendor/gitignore/Sdcc.gitignore | 8 + vendor/gitignore/SeamGen.gitignore | 26 + vendor/gitignore/SketchUp.gitignore | 1 + vendor/gitignore/Smalltalk.gitignore | 18 + vendor/gitignore/Stella.gitignore | 12 + vendor/gitignore/SugarCRM.gitignore | 25 + vendor/gitignore/Swift.gitignore | 63 ++ vendor/gitignore/Symfony.gitignore | 48 ++ vendor/gitignore/SymphonyCMS.gitignore | 6 + vendor/gitignore/TeX.gitignore | 180 ++++++ vendor/gitignore/Terraform.gitignore | 3 + vendor/gitignore/Textpattern.gitignore | 11 + vendor/gitignore/TurboGears2.gitignore | 20 + vendor/gitignore/Typo3.gitignore | 20 + vendor/gitignore/Umbraco.gitignore | 19 + vendor/gitignore/Unity.gitignore | 30 + vendor/gitignore/UnrealEngine.gitignore | 62 ++ vendor/gitignore/VVVV.gitignore | 6 + vendor/gitignore/VisualStudio.gitignore | 252 ++++++++ vendor/gitignore/Waf.gitignore | 4 + vendor/gitignore/WordPress.gitignore | 18 + vendor/gitignore/Xojo.gitignore | 11 + vendor/gitignore/Yeoman.gitignore | 6 + vendor/gitignore/Yii.gitignore | 6 + vendor/gitignore/ZendFramework.gitignore | 25 + vendor/gitignore/Zephir.gitignore | 26 + 1198 files changed, 20328 insertions(+), 8300 deletions(-) rename app/views/projects/notes/_commit_discussion.html.haml => .vagrant_enabled (100%) delete mode 100644 app/assets/images/ci/arch.jpg delete mode 100644 app/assets/images/ci/favicon.ico delete mode 100644 app/assets/images/ci/loader.gif delete mode 100644 app/assets/images/ci/no_avatar.png delete mode 100644 app/assets/images/ci/rails.png delete mode 100644 app/assets/images/ci/service_sample.png create mode 100644 app/assets/images/mailers/gitlab_header_logo.png create mode 100644 app/assets/images/mailers/gitlab_tanuki_2x.png create mode 100644 app/assets/javascripts/blob/blob_gitignore_selector.js.coffee delete mode 100644 app/assets/javascripts/calendar.js.coffee create mode 100644 app/assets/javascripts/graphs/application.js.coffee rename app/assets/javascripts/{ => graphs}/stat_graph.js.coffee (100%) rename app/assets/javascripts/{ => graphs}/stat_graph_contributors.js.coffee (98%) rename app/assets/javascripts/{ => graphs}/stat_graph_contributors_graph.js.coffee (99%) rename app/assets/javascripts/{ => graphs}/stat_graph_contributors_util.js.coffee (100%) delete mode 100644 app/assets/javascripts/issues.js.coffee create mode 100644 app/assets/javascripts/layout_nav.js.coffee create mode 100644 app/assets/javascripts/lib/type_utility.js.coffee create mode 100644 app/assets/javascripts/users/application.js.coffee create mode 100644 app/assets/javascripts/users/calendar.js.coffee create mode 100644 app/assets/stylesheets/framework/animations.scss create mode 100644 app/assets/stylesheets/mailers/devise.scss create mode 100644 app/assets/stylesheets/mailers/repository_push_email.scss create mode 100644 app/assets/stylesheets/pages/pipelines.scss create mode 100644 app/controllers/admin/health_check_controller.rb create mode 100644 app/controllers/health_check_controller.rb create mode 100644 app/controllers/jwt_controller.rb create mode 100644 app/controllers/projects/container_registry_controller.rb create mode 100644 app/controllers/projects/pipelines_controller.rb create mode 100644 app/finders/pipelines_finder.rb create mode 100644 app/helpers/javascript_helper.rb create mode 100644 app/models/legacy_diff_note.rb create mode 100644 app/services/auth/container_registry_authentication_service.rb create mode 100644 app/services/ci/create_pipeline_service.rb create mode 100644 app/services/merge_requests/add_todo_when_build_fails_service.rb create mode 100644 app/views/admin/health_check/show.html.haml delete mode 100644 app/views/devise/mailer/confirmation_instructions.html.erb create mode 100644 app/views/devise/mailer/confirmation_instructions.html.haml create mode 100644 app/views/devise/mailer/confirmation_instructions.text.erb create mode 100644 app/views/events/_event.atom.builder create mode 100644 app/views/issues/_issue.atom.builder create mode 100644 app/views/layouts/devise_mailer.html.haml delete mode 100644 app/views/projects/blob/_header_title.html.haml delete mode 100644 app/views/projects/branches/destroy.js.haml delete mode 100644 app/views/projects/builds/_header_title.html.haml create mode 100644 app/views/projects/ci/commits/_commit.html.haml create mode 100644 app/views/projects/commit/_ci_stage.html.haml create mode 100644 app/views/projects/commits/_commit.atom.builder delete mode 100644 app/views/projects/commits/_header_title.html.haml create mode 100644 app/views/projects/container_registry/_tag.html.haml create mode 100644 app/views/projects/container_registry/index.html.haml delete mode 100644 app/views/projects/graphs/_header_title.html.haml delete mode 100644 app/views/projects/issues/_header_title.html.haml delete mode 100644 app/views/projects/labels/_header_title.html.haml delete mode 100644 app/views/projects/merge_requests/_header_title.html.haml delete mode 100644 app/views/projects/milestones/_header_title.html.haml delete mode 100644 app/views/projects/notes/discussions/_active.html.haml delete mode 100644 app/views/projects/notes/discussions/_commit.html.haml delete mode 100644 app/views/projects/notes/discussions/_diff.html.haml create mode 100644 app/views/projects/notes/discussions/_diff_with_notes.html.haml create mode 100644 app/views/projects/notes/discussions/_notes.html.haml delete mode 100644 app/views/projects/notes/discussions/_outdated.html.haml create mode 100644 app/views/projects/pipelines/_head.html.haml create mode 100644 app/views/projects/pipelines/_info.html.haml create mode 100644 app/views/projects/pipelines/index.html.haml create mode 100644 app/views/projects/pipelines/new.html.haml create mode 100644 app/views/projects/pipelines/show.html.haml delete mode 100644 app/views/projects/project_members/_header_title.html.haml create mode 100644 app/views/projects/runners/_form.html.haml delete mode 100644 app/views/projects/snippets/_header_title.html.haml create mode 100644 app/views/projects/variables/_content.html.haml create mode 100644 app/views/projects/variables/_form.html.haml create mode 100644 app/views/projects/variables/_table.html.haml create mode 100644 app/views/projects/variables/index.html.haml delete mode 100644 app/views/projects/wikis/_header_title.html.haml delete mode 100644 config/initializers/devise_async.rb create mode 100644 config/initializers/health_check.rb delete mode 100644 config/initializers/monkey_patch.rb create mode 100644 db/migrate/20160407120251_add_images_enabled_for_project.rb create mode 100644 db/migrate/20160504091942_add_disabled_oauth_sign_in_sources_to_application_settings.rb create mode 100644 db/migrate/20160504112519_add_run_untagged_to_ci_runner.rb create mode 100644 db/migrate/20160508215820_add_type_to_notes.rb create mode 100644 db/migrate/20160508221410_set_type_on_legacy_diff_notes.rb create mode 100644 db/migrate/20160509201028_add_health_check_access_token_to_application_settings.rb create mode 100644 db/migrate/20160516174813_add_send_user_confirmation_email_to_application_settings.rb create mode 100644 db/migrate/20160525205328_remove_main_language_from_projects.rb create mode 100644 db/migrate/20160527020117_remove_notification_settings_for_deleted_projects.rb create mode 100644 db/migrate/20160528043124_add_users_state_index.rb create mode 100644 db/migrate/20160530150109_add_container_registry_token_expire_delay_to_application_settings.rb create mode 100644 doc/administration/container_registry.md create mode 100644 doc/administration/img/high_availability/active-active-diagram.png create mode 100644 doc/administration/img/high_availability/active-passive-diagram.png rename doc/ci/{ => examples}/deployment/README.md (100%) create mode 100644 doc/container_registry/README.md create mode 100644 doc/container_registry/img/container_registry.png create mode 100644 doc/container_registry/img/project_feature.png create mode 100644 doc/integration/img/enabled-oauth-sign-in-sources.png create mode 100644 doc/monitoring/health_check.md create mode 100644 doc/monitoring/img/health_check_token.png create mode 100644 doc/security/user_email_confirmation.md create mode 100644 doc/update/8.7-to-8.8.md delete mode 100644 features/project/commits/tags.feature delete mode 100644 features/steps/project/commits/tags.rb create mode 100644 features/steps/shared/sidebar_active_tab.rb create mode 100644 generator_templates/active_record/migration/create_table_migration.rb create mode 100644 generator_templates/active_record/migration/migration.rb create mode 100644 lib/api/gitignores.rb create mode 100644 lib/api/subscriptions.rb create mode 100644 lib/backup/registry.rb create mode 100644 lib/banzai/filter/inline_diff_filter.rb delete mode 100644 lib/banzai/filter/reference_gatherer_filter.rb delete mode 100644 lib/banzai/lazy_reference.rb delete mode 100644 lib/banzai/pipeline/reference_extraction_pipeline.rb create mode 100644 lib/banzai/reference_parser.rb create mode 100644 lib/banzai/reference_parser/base_parser.rb create mode 100644 lib/banzai/reference_parser/commit_parser.rb create mode 100644 lib/banzai/reference_parser/commit_range_parser.rb create mode 100644 lib/banzai/reference_parser/external_issue_parser.rb create mode 100644 lib/banzai/reference_parser/issue_parser.rb create mode 100644 lib/banzai/reference_parser/label_parser.rb create mode 100644 lib/banzai/reference_parser/merge_request_parser.rb create mode 100644 lib/banzai/reference_parser/milestone_parser.rb create mode 100644 lib/banzai/reference_parser/snippet_parser.rb create mode 100644 lib/banzai/reference_parser/user_parser.rb create mode 100644 lib/container_registry/blob.rb create mode 100644 lib/container_registry/client.rb create mode 100644 lib/container_registry/config.rb create mode 100644 lib/container_registry/registry.rb create mode 100644 lib/container_registry/repository.rb create mode 100644 lib/container_registry/tag.rb create mode 100644 lib/gitlab/database/migration_helpers.rb create mode 100644 lib/gitlab/github_import/branch_formatter.rb create mode 100644 lib/gitlab/gitignore.rb create mode 100644 lib/gitlab/lazy.rb create mode 100644 lib/gitlab/middleware/rails_queue_duration.rb rename lib/gitlab/{import_url.rb => url_sanitizer.rb} (66%) create mode 100644 lib/json_web_token/rsa_token.rb create mode 100644 lib/json_web_token/token.rb create mode 100644 lib/support/nginx/registry-ssl delete mode 100644 lib/tasks/auto_annotate_models.rake create mode 100644 lib/tasks/gitlab/update_gitignore.rake create mode 100644 shared/registry/.gitkeep create mode 100644 spec/controllers/health_check_controller_spec.rb create mode 100644 spec/controllers/registrations_controller_spec.rb create mode 100644 spec/features/admin/admin_health_check_spec.rb create mode 100644 spec/features/container_registry_spec.rb create mode 100644 spec/features/merge_requests/created_from_fork_spec.rb create mode 100644 spec/features/merge_requests/user_lists_merge_requests_spec.rb create mode 100644 spec/features/pipelines_spec.rb create mode 100644 spec/features/projects/developer_views_empty_project_instructions_spec.rb create mode 100644 spec/features/projects/files/gitignore_dropdown_spec.rb rename spec/features/{project => projects}/shortcuts_spec.rb (79%) create mode 100644 spec/features/tags/master_creates_tag_spec.rb create mode 100644 spec/features/tags/master_deletes_tag_spec.rb create mode 100644 spec/features/tags/master_updates_tag_spec.rb create mode 100644 spec/features/tags/master_views_tags_spec.rb create mode 100644 spec/features/todos/target_state_spec.rb create mode 100644 spec/fixtures/container_registry/config_blob.json create mode 100644 spec/fixtures/container_registry/tag_manifest.json create mode 100644 spec/javascripts/fixtures/right_sidebar.html.haml rename spec/javascripts/{ => graphs}/stat_graph_contributors_graph_spec.js (98%) rename spec/javascripts/{ => graphs}/stat_graph_contributors_util_spec.js (99%) rename spec/javascripts/{ => graphs}/stat_graph_spec.js (92%) create mode 100644 spec/javascripts/right_sidebar_spec.js.coffee create mode 100644 spec/lib/banzai/filter/inline_diff_filter_spec.rb delete mode 100644 spec/lib/banzai/filter/reference_gatherer_filter_spec.rb create mode 100644 spec/lib/banzai/filter/wiki_link_filter_spec.rb create mode 100644 spec/lib/banzai/reference_parser/base_parser_spec.rb create mode 100644 spec/lib/banzai/reference_parser/commit_parser_spec.rb create mode 100644 spec/lib/banzai/reference_parser/commit_range_parser_spec.rb create mode 100644 spec/lib/banzai/reference_parser/external_issue_parser_spec.rb create mode 100644 spec/lib/banzai/reference_parser/issue_parser_spec.rb create mode 100644 spec/lib/banzai/reference_parser/label_parser_spec.rb create mode 100644 spec/lib/banzai/reference_parser/merge_request_parser_spec.rb create mode 100644 spec/lib/banzai/reference_parser/milestone_parser_spec.rb create mode 100644 spec/lib/banzai/reference_parser/snippet_parser_spec.rb create mode 100644 spec/lib/banzai/reference_parser/user_parser_spec.rb create mode 100644 spec/lib/container_registry/blob_spec.rb create mode 100644 spec/lib/container_registry/registry_spec.rb create mode 100644 spec/lib/container_registry/repository_spec.rb create mode 100644 spec/lib/container_registry/tag_spec.rb create mode 100644 spec/lib/gitlab/database/migration_helpers_spec.rb create mode 100644 spec/lib/gitlab/github_import/branch_formatter_spec.rb create mode 100644 spec/lib/gitlab/gitignore_spec.rb delete mode 100644 spec/lib/gitlab/import_url_spec.rb create mode 100644 spec/lib/gitlab/lazy_spec.rb create mode 100644 spec/lib/gitlab/middleware/rails_queue_duration_spec.rb create mode 100644 spec/lib/gitlab/url_sanitizer_spec.rb create mode 100644 spec/lib/json_web_token/rsa_token_spec.rb create mode 100644 spec/lib/json_web_token/token_spec.rb create mode 100644 spec/mailers/previews/devise_mailer_preview.rb create mode 100644 spec/models/ability_spec.rb delete mode 100644 spec/models/ci/runner_project_spec.rb create mode 100644 spec/models/concerns/participable_spec.rb create mode 100644 spec/models/legacy_diff_note_spec.rb rename spec/requests/api/{commit_status_spec.rb => commit_statuses_spec.rb} (99%) create mode 100644 spec/requests/api/gitignores_spec.rb create mode 100644 spec/requests/jwt_controller_spec.rb create mode 100644 spec/services/auth/container_registry_authentication_service_spec.rb create mode 100644 spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb create mode 100644 spec/support/reference_parser_helpers.rb create mode 100644 spec/tasks/gitlab/db_rake_spec.rb create mode 100755 vendor/assets/javascripts/jquery.scrollTo.js delete mode 100644 vendor/assets/stylesheets/animate.css create mode 100644 vendor/gitignore/Actionscript.gitignore create mode 100644 vendor/gitignore/Ada.gitignore create mode 100644 vendor/gitignore/Agda.gitignore create mode 100644 vendor/gitignore/Android.gitignore create mode 100644 vendor/gitignore/AppEngine.gitignore create mode 100644 vendor/gitignore/AppceleratorTitanium.gitignore create mode 100644 vendor/gitignore/ArchLinuxPackages.gitignore create mode 100644 vendor/gitignore/Autotools.gitignore create mode 100644 vendor/gitignore/C++.gitignore create mode 100644 vendor/gitignore/C.gitignore create mode 100644 vendor/gitignore/CFWheels.gitignore create mode 100644 vendor/gitignore/CMake.gitignore create mode 100644 vendor/gitignore/CUDA.gitignore create mode 100644 vendor/gitignore/CakePHP.gitignore create mode 100644 vendor/gitignore/ChefCookbook.gitignore create mode 120000 vendor/gitignore/Clojure.gitignore create mode 100644 vendor/gitignore/CodeIgniter.gitignore create mode 100644 vendor/gitignore/CommonLisp.gitignore create mode 100644 vendor/gitignore/Composer.gitignore create mode 100644 vendor/gitignore/Concrete5.gitignore create mode 100644 vendor/gitignore/Coq.gitignore create mode 100644 vendor/gitignore/CraftCMS.gitignore create mode 100644 vendor/gitignore/D.gitignore create mode 100644 vendor/gitignore/DM.gitignore create mode 100644 vendor/gitignore/Dart.gitignore create mode 100644 vendor/gitignore/Delphi.gitignore create mode 100644 vendor/gitignore/Drupal.gitignore create mode 100644 vendor/gitignore/EPiServer.gitignore create mode 100644 vendor/gitignore/Eagle.gitignore create mode 100644 vendor/gitignore/Elisp.gitignore create mode 100644 vendor/gitignore/Elixir.gitignore create mode 100644 vendor/gitignore/Elm.gitignore create mode 100644 vendor/gitignore/Erlang.gitignore create mode 100644 vendor/gitignore/ExpressionEngine.gitignore create mode 100644 vendor/gitignore/ExtJs.gitignore create mode 100644 vendor/gitignore/Fancy.gitignore create mode 100644 vendor/gitignore/Finale.gitignore create mode 100644 vendor/gitignore/ForceDotCom.gitignore create mode 120000 vendor/gitignore/Fortran.gitignore create mode 100644 vendor/gitignore/FuelPHP.gitignore create mode 100644 vendor/gitignore/GWT.gitignore create mode 100644 vendor/gitignore/Gcov.gitignore create mode 100644 vendor/gitignore/GitBook.gitignore create mode 100644 vendor/gitignore/Global/Anjuta.gitignore create mode 100644 vendor/gitignore/Global/Archives.gitignore create mode 100644 vendor/gitignore/Global/BricxCC.gitignore create mode 100644 vendor/gitignore/Global/CVS.gitignore create mode 100644 vendor/gitignore/Global/Calabash.gitignore create mode 100644 vendor/gitignore/Global/Cloud9.gitignore create mode 100644 vendor/gitignore/Global/CodeKit.gitignore create mode 100644 vendor/gitignore/Global/DartEditor.gitignore create mode 100644 vendor/gitignore/Global/Dreamweaver.gitignore create mode 100644 vendor/gitignore/Global/Dropbox.gitignore create mode 100644 vendor/gitignore/Global/Eclipse.gitignore create mode 100644 vendor/gitignore/Global/EiffelStudio.gitignore create mode 100644 vendor/gitignore/Global/Emacs.gitignore create mode 100644 vendor/gitignore/Global/Ensime.gitignore create mode 100644 vendor/gitignore/Global/Espresso.gitignore create mode 100644 vendor/gitignore/Global/FlexBuilder.gitignore create mode 100644 vendor/gitignore/Global/GPG.gitignore create mode 100644 vendor/gitignore/Global/IPythonNotebook.gitignore create mode 100644 vendor/gitignore/Global/JDeveloper.gitignore create mode 100644 vendor/gitignore/Global/JetBrains.gitignore create mode 100644 vendor/gitignore/Global/KDevelop4.gitignore create mode 100644 vendor/gitignore/Global/Kate.gitignore create mode 100644 vendor/gitignore/Global/Lazarus.gitignore create mode 100644 vendor/gitignore/Global/LibreOffice.gitignore create mode 100644 vendor/gitignore/Global/Linux.gitignore create mode 100644 vendor/gitignore/Global/LyX.gitignore create mode 100644 vendor/gitignore/Global/Matlab.gitignore create mode 100644 vendor/gitignore/Global/Mercurial.gitignore create mode 100644 vendor/gitignore/Global/MicrosoftOffice.gitignore create mode 100644 vendor/gitignore/Global/ModelSim.gitignore create mode 100644 vendor/gitignore/Global/Momentics.gitignore create mode 100644 vendor/gitignore/Global/MonoDevelop.gitignore create mode 100644 vendor/gitignore/Global/NetBeans.gitignore create mode 100644 vendor/gitignore/Global/Ninja.gitignore create mode 100644 vendor/gitignore/Global/NotepadPP.gitignore create mode 100644 vendor/gitignore/Global/OSX.gitignore create mode 100644 vendor/gitignore/Global/Otto.gitignore create mode 100644 vendor/gitignore/Global/Redcar.gitignore create mode 100644 vendor/gitignore/Global/Redis.gitignore create mode 100644 vendor/gitignore/Global/SBT.gitignore create mode 100644 vendor/gitignore/Global/SVN.gitignore create mode 100644 vendor/gitignore/Global/SlickEdit.gitignore create mode 100644 vendor/gitignore/Global/SublimeText.gitignore create mode 100644 vendor/gitignore/Global/SynopsysVCS.gitignore create mode 100644 vendor/gitignore/Global/Tags.gitignore create mode 100644 vendor/gitignore/Global/TextMate.gitignore create mode 100644 vendor/gitignore/Global/TortoiseGit.gitignore create mode 100644 vendor/gitignore/Global/Vagrant.gitignore create mode 100644 vendor/gitignore/Global/Vim.gitignore create mode 100644 vendor/gitignore/Global/VirtualEnv.gitignore create mode 100644 vendor/gitignore/Global/VisualStudioCode.gitignore create mode 100644 vendor/gitignore/Global/WebMethods.gitignore create mode 100644 vendor/gitignore/Global/Windows.gitignore create mode 100644 vendor/gitignore/Global/Xcode.gitignore create mode 100644 vendor/gitignore/Global/XilinxISE.gitignore create mode 100644 vendor/gitignore/Go.gitignore create mode 100644 vendor/gitignore/Gradle.gitignore create mode 100644 vendor/gitignore/Grails.gitignore create mode 100644 vendor/gitignore/Haskell.gitignore create mode 100644 vendor/gitignore/IGORPro.gitignore create mode 100644 vendor/gitignore/Idris.gitignore create mode 100644 vendor/gitignore/Java.gitignore create mode 100644 vendor/gitignore/Jboss.gitignore create mode 100644 vendor/gitignore/Jekyll.gitignore create mode 100644 vendor/gitignore/Joomla.gitignore create mode 100644 vendor/gitignore/KiCad.gitignore create mode 100644 vendor/gitignore/Kohana.gitignore create mode 100644 vendor/gitignore/LabVIEW.gitignore create mode 100644 vendor/gitignore/Laravel.gitignore create mode 100644 vendor/gitignore/Leiningen.gitignore create mode 100644 vendor/gitignore/LemonStand.gitignore create mode 100644 vendor/gitignore/Lilypond.gitignore create mode 100644 vendor/gitignore/Lithium.gitignore create mode 100644 vendor/gitignore/Lua.gitignore create mode 100644 vendor/gitignore/Magento.gitignore create mode 100644 vendor/gitignore/Maven.gitignore create mode 100644 vendor/gitignore/Mercury.gitignore create mode 100644 vendor/gitignore/MetaProgrammingSystem.gitignore create mode 100644 vendor/gitignore/Nanoc.gitignore create mode 100644 vendor/gitignore/Nim.gitignore create mode 100644 vendor/gitignore/Node.gitignore create mode 100644 vendor/gitignore/OCaml.gitignore create mode 100644 vendor/gitignore/Objective-C.gitignore create mode 100644 vendor/gitignore/Opa.gitignore create mode 100644 vendor/gitignore/OpenCart.gitignore create mode 100644 vendor/gitignore/OracleForms.gitignore create mode 100644 vendor/gitignore/Packer.gitignore create mode 100644 vendor/gitignore/Perl.gitignore create mode 100644 vendor/gitignore/Phalcon.gitignore create mode 100644 vendor/gitignore/PlayFramework.gitignore create mode 100644 vendor/gitignore/Plone.gitignore create mode 100644 vendor/gitignore/Prestashop.gitignore create mode 100644 vendor/gitignore/Processing.gitignore create mode 100644 vendor/gitignore/Python.gitignore create mode 100644 vendor/gitignore/Qooxdoo.gitignore create mode 100644 vendor/gitignore/Qt.gitignore create mode 100644 vendor/gitignore/R.gitignore create mode 100644 vendor/gitignore/README.md create mode 100644 vendor/gitignore/ROS.gitignore create mode 100644 vendor/gitignore/Rails.gitignore create mode 100644 vendor/gitignore/RhodesRhomobile.gitignore create mode 100644 vendor/gitignore/Ruby.gitignore create mode 100644 vendor/gitignore/Rust.gitignore create mode 100644 vendor/gitignore/SCons.gitignore create mode 100644 vendor/gitignore/Sass.gitignore create mode 100644 vendor/gitignore/Scala.gitignore create mode 100644 vendor/gitignore/Scheme.gitignore create mode 100644 vendor/gitignore/Scrivener.gitignore create mode 100644 vendor/gitignore/Sdcc.gitignore create mode 100644 vendor/gitignore/SeamGen.gitignore create mode 100644 vendor/gitignore/SketchUp.gitignore create mode 100644 vendor/gitignore/Smalltalk.gitignore create mode 100644 vendor/gitignore/Stella.gitignore create mode 100644 vendor/gitignore/SugarCRM.gitignore create mode 100644 vendor/gitignore/Swift.gitignore create mode 100644 vendor/gitignore/Symfony.gitignore create mode 100644 vendor/gitignore/SymphonyCMS.gitignore create mode 100644 vendor/gitignore/TeX.gitignore create mode 100644 vendor/gitignore/Terraform.gitignore create mode 100644 vendor/gitignore/Textpattern.gitignore create mode 100644 vendor/gitignore/TurboGears2.gitignore create mode 100644 vendor/gitignore/Typo3.gitignore create mode 100644 vendor/gitignore/Umbraco.gitignore create mode 100644 vendor/gitignore/Unity.gitignore create mode 100644 vendor/gitignore/UnrealEngine.gitignore create mode 100644 vendor/gitignore/VVVV.gitignore create mode 100644 vendor/gitignore/VisualStudio.gitignore create mode 100644 vendor/gitignore/Waf.gitignore create mode 100644 vendor/gitignore/WordPress.gitignore create mode 100644 vendor/gitignore/Xojo.gitignore create mode 100644 vendor/gitignore/Yeoman.gitignore create mode 100644 vendor/gitignore/Yii.gitignore create mode 100644 vendor/gitignore/ZendFramework.gitignore create mode 100644 vendor/gitignore/Zephir.gitignore diff --git a/.gitignore b/.gitignore index 8f861d76a3..ce6a363fe3 100644 --- a/.gitignore +++ b/.gitignore @@ -4,46 +4,46 @@ .bundle .chef .directory -.envrc -.gitlab_shell_secret +/.envrc +/.gitlab_shell_secret .idea -.rbenv-version +/.rbenv-version .rbx/ -.ruby-gemset -.ruby-version -.rvmrc +/.ruby-gemset +/.ruby-version +/.rvmrc .sass-cache/ -.secret -.vagrant -.byebug_history -Vagrantfile -backups/* -config/aws.yml -config/database.yml -config/gitlab.yml -config/gitlab_ci.yml -config/initializers/rack_attack.rb -config/initializers/smtp_settings.rb -config/initializers/relative_url.rb -config/resque.yml -config/unicorn.rb -config/secrets.yml -config/sidekiq.yml -coverage/* -db/*.sqlite3 -db/*.sqlite3-journal -db/data.yml -doc/code/* -dump.rdb -log/*.log* -nohup.out -public/assets/ -public/uploads.* -public/uploads/ -shared/artifacts/ -rails_best_practices_output.html +/.secret +/.vagrant +/.byebug_history +/Vagrantfile +/backups/* +/config/aws.yml +/config/database.yml +/config/gitlab.yml +/config/gitlab_ci.yml +/config/initializers/rack_attack.rb +/config/initializers/smtp_settings.rb +/config/initializers/relative_url.rb +/config/resque.yml +/config/unicorn.rb +/config/secrets.yml +/config/sidekiq.yml +/coverage/* +/db/*.sqlite3 +/db/*.sqlite3-journal +/db/data.yml +/doc/code/* +/dump.rdb +/log/*.log* +/nohup.out +/public/assets/ +/public/uploads.* +/public/uploads/ +/shared/artifacts/ +/rails_best_practices_output.html /tags -tmp/ -vendor/bundle/* -builds/* -shared/* +/tmp/* +/vendor/bundle/* +/builds/* +/shared/* diff --git a/.rubocop.yml b/.rubocop.yml index 9f179efa3c..84a8015b41 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,3 +1,5 @@ +require: rubocop-rspec + AllCops: TargetRubyVersion: 2.1 # Cop names are not displayed in offense messages by default. Change behavior @@ -21,6 +23,7 @@ AllCops: - 'lib/email_validator.rb' - 'lib/gitlab/upgrader.rb' - 'lib/gitlab/seeder.rb' + - 'generator_templates/**/*' ##################### Style ################################## @@ -56,7 +59,7 @@ Style/AndOr: # Use `Array#join` instead of `Array#*`. Style/ArrayJoin: - Enabled: false + Enabled: true # Use only ascii symbols in comments. Style/AsciiComments: @@ -68,7 +71,7 @@ Style/AsciiIdentifiers: # Checks for uses of Module#attr. Style/Attr: - Enabled: false + Enabled: true # Avoid the use of BEGIN blocks. Style/BeginBlock: @@ -80,7 +83,7 @@ Style/BarePercentLiterals: # Do not use block comments. Style/BlockComments: - Enabled: false + Enabled: true # Put end statement of multiline block on its own line. Style/BlockEndNewline: @@ -121,7 +124,7 @@ Style/ClassCheck: # Use self when defining module/class methods. Style/ClassMethods: - Enabled: false + Enabled: true # Avoid the use of class variables. Style/ClassVars: @@ -151,7 +154,7 @@ Style/ConstantName: # Use def with parentheses when there are arguments. Style/DefWithParentheses: - Enabled: false + Enabled: true # Checks for use of deprecated Hash methods. Style/DeprecatedHashMethods: @@ -215,15 +218,15 @@ Style/EmptyLiteral: # Avoid the use of END blocks. Style/EndBlock: - Enabled: false + Enabled: true # Use Unix-style line endings. Style/EndOfLine: - Enabled: false + Enabled: true # Favor the use of Fixnum#even? && Fixnum#odd? Style/EvenOdd: - Enabled: false + Enabled: true # Do not use unnecessary spacing. Style/ExtraSpacing: @@ -231,15 +234,20 @@ Style/ExtraSpacing: # Use snake_case for source file names. Style/FileName: - Enabled: false + Enabled: true + +# Checks for a line break before the first parameter in a multi-line method +# parameter definition. +Style/FirstMethodParameterLineBreak: + Enabled: true # Checks for flip flops. Style/FlipFlop: - Enabled: false + Enabled: true # Checks use of for or each in multiline loops. Style/For: - Enabled: false + Enabled: true # Enforce the use of Kernel#sprintf, Kernel#format or String#%. Style/FormatString: @@ -247,7 +255,7 @@ Style/FormatString: # Do not introduce global variables. Style/GlobalVars: - Enabled: false + Enabled: true # Check for conditionals that can be replaced with guard clauses. Style/GuardClause: @@ -268,7 +276,7 @@ Style/IfUnlessModifier: # Do not use if x; .... Use the ternary operator instead. Style/IfWithSemicolon: - Enabled: false + Enabled: true # Checks that conditional statements do not have an identical line at the # end of each branch, which can validly be moved out of the conditional. @@ -276,9 +284,9 @@ Style/IdenticalConditionalBranches: Enabled: false # Checks the indentation of the first line of the right-hand-side of a -# multi-line assignment. +# multi-line assignment. Style/IndentAssignment: - Enabled: false + Enabled: true # Keep indentation straight. Style/IndentationConsistency: @@ -298,7 +306,7 @@ Style/IndentHash: # Use Kernel#loop for infinite loops. Style/InfiniteLoop: - Enabled: false + Enabled: true # Use the new lambda literal syntax for single-line blocks. Style/Lambda: @@ -306,11 +314,11 @@ Style/Lambda: # Use lambda.call(...) instead of lambda.(...). Style/LambdaCall: - Enabled: false + Enabled: true # Comments should start with a space. Style/LeadingCommentSpace: - Enabled: false + Enabled: true # Use \ instead of + or << to concatenate two string literals at line end. Style/LineEndConcatenation: @@ -322,16 +330,22 @@ Style/MethodCallParentheses: # Checks if the method definitions have or don't have parentheses. Style/MethodDefParentheses: - Enabled: false + Enabled: true # Use the configured style when naming methods. Style/MethodName: - Enabled: false + Enabled: true # Checks for usage of `extend self` in modules. Style/ModuleFunction: Enabled: false +# Checks that the closing brace in an array literal is either on the same line +# as the last array element, or a new line. +Style/MultilineArrayBraceLayout: + Enabled: false + EnforcedStyle: symmetrical + # Avoid multi-line chains of blocks. Style/MultilineBlockChain: Enabled: false @@ -340,15 +354,32 @@ Style/MultilineBlockChain: Style/MultilineBlockLayout: Enabled: true +# Checks that the closing brace in a hash literal is either on the same line as +# the last hash element, or a new line. +Style/MultilineHashBraceLayout: + Enabled: false + EnforcedStyle: symmetrical + # Do not use then for multi-line if/unless. Style/MultilineIfThen: + Enabled: true + +# Checks that the closing brace in a method call is either on the same line as +# the last method argument, or a new line. +Style/MultilineMethodCallBraceLayout: Enabled: false + EnforcedStyle: symmetrical # Checks indentation of method calls with the dot operator that span more than # one line. Style/MultilineMethodCallIndentation: Enabled: false +# Checks that the closing brace in a method definition is symmetrical with +# respect to the opening brace and the method parameters. +Style/MultilineMethodDefinitionBraceLayout: + Enabled: false + # Checks indentation of binary operations that span more than one line. Style/MultilineOperationIndentation: Enabled: false @@ -363,7 +394,7 @@ Style/MutableConstant: # Favor unless over if for negative conditions (or control flow or). Style/NegatedIf: - Enabled: false + Enabled: true # Favor until over while for negative conditions. Style/NegatedWhile: @@ -371,7 +402,7 @@ Style/NegatedWhile: # Avoid using nested modifiers. Style/NestedModifier: - Enabled: false + Enabled: true # Parenthesize method calls which are nested inside the argument list of # another parenthesized method call. @@ -408,7 +439,7 @@ Style/OneLineConditional: # When defining binary operators, name the argument other. Style/OpMethod: - Enabled: false + Enabled: true # Check for simple usages of parallel assignment. It will only warn when # the number of variables matches on both sides of the assignment. @@ -455,10 +486,9 @@ Style/RedundantException: Style/RedundantFreeze: Enabled: false -# TODO: Enable RedundantParentheses Cop. # Checks for parentheses that seem not to serve any purpose. Style/RedundantParentheses: - Enabled: false + Enabled: true # Don't use return where it's not required. Style/RedundantReturn: @@ -484,11 +514,12 @@ Style/SelfAssignment: # Don't use semicolons to terminate expressions. Style/Semicolon: - Enabled: false + Enabled: true # Checks for proper usage of fail and raise. Style/SignalException: - Enabled: false + EnforcedStyle: only_raise + Enabled: true # Enforces the names of some block params. Style/SingleLineBlockParams: @@ -509,29 +540,28 @@ Style/SpaceAfterComma: # Do not put a space between a method name and the opening parenthesis in a # method definition. Style/SpaceAfterMethodName: - Enabled: false + Enabled: true # Tracks redundant space after the ! operator. Style/SpaceAfterNot: - Enabled: false + Enabled: true # Use spaces after semicolons. Style/SpaceAfterSemicolon: - Enabled: false + Enabled: true # Checks that the equals signs in parameter default assignments have or don't # have surrounding space depending on configuration. Style/SpaceAroundEqualsInParameterDefault: Enabled: false -# TODO: Enable SpaceAroundKeyword Cop. # Use a space around keywords if appropriate. Style/SpaceAroundKeyword: - Enabled: false + Enabled: true # Use a single space around operators. Style/SpaceAroundOperators: - Enabled: false + Enabled: true # Checks that the left block brace has or doesn't have space before it. Style/SpaceBeforeBlockBraces: @@ -539,11 +569,11 @@ Style/SpaceBeforeBlockBraces: # No spaces before commas. Style/SpaceBeforeComma: - Enabled: false + Enabled: true # Checks for missing space between code and a comment on the same line. Style/SpaceBeforeComment: - Enabled: false + Enabled: true # Checks that exactly one space is used between a method name and the first # argument for method calls without parentheses. @@ -552,7 +582,7 @@ Style/SpaceBeforeFirstArg: # No spaces before semicolons. Style/SpaceBeforeSemicolon: - Enabled: false + Enabled: true # Checks that block braces have or don't have surrounding space. # For blocks taking parameters, checks that the left brace has or doesn't @@ -574,11 +604,12 @@ Style/SpaceInsideParens: # No spaces inside range literals. Style/SpaceInsideRangeLiteral: - Enabled: false + Enabled: true # Checks for padding/surrounding spaces inside string interpolation. Style/SpaceInsideStringInterpolation: - Enabled: false + EnforcedStyle: no_space + Enabled: true # Avoid Perl-style global variables. Style/SpecialGlobalVars: @@ -586,7 +617,8 @@ Style/SpecialGlobalVars: # Check for the usage of parentheses around stabby lambda arguments. Style/StabbyLambdaParentheses: - Enabled: false + EnforcedStyle: require_parentheses + Enabled: true # Checks if uses of quotes match the configured preference. Style/StringLiterals: @@ -599,7 +631,9 @@ Style/StringLiteralsInInterpolation: # Checks if configured preferred methods are used over non-preferred. Style/StringMethods: - Enabled: false + PreferredMethods: + intern: to_sym + Enabled: true # Use %i or %I for arrays of symbols. Style/SymbolArray: @@ -657,23 +691,24 @@ Style/UnneededPercentQ: # Don't interpolate global, instance and class variables directly in strings. Style/VariableInterpolation: - Enabled: false + Enabled: true # Use the configured style when naming variables. Style/VariableName: - Enabled: false + EnforcedStyle: snake_case + Enabled: true # Use when x then ... for one-line cases. Style/WhenThen: - Enabled: false + Enabled: true # Checks for redundant do after while or until. Style/WhileUntilDo: - Enabled: false + Enabled: true # Favor modifier while/until usage when you have a single-line body. Style/WhileUntilModifier: - Enabled: false + Enabled: true # Use %w or %W for arrays of words. Style/WordArray: @@ -749,28 +784,28 @@ Lint/AssignmentInCondition: # Align block ends correctly. Lint/BlockAlignment: - Enabled: false + Enabled: true # Default values in optional keyword arguments and optional ordinal arguments # should not refer back to the name of the argument. Lint/CircularArgumentReference: - Enabled: false + Enabled: true # Checks for condition placed in a confusing position relative to the keyword. Lint/ConditionPosition: - Enabled: false + Enabled: true # Check for debugger calls. Lint/Debugger: - Enabled: false + Enabled: true # Align ends corresponding to defs correctly. Lint/DefEndAlignment: - Enabled: false + Enabled: true # Check for deprecated class method calls. Lint/DeprecatedClassMethods: - Enabled: false + Enabled: true # Check for duplicate method definitions. Lint/DuplicateMethods: @@ -782,15 +817,15 @@ Lint/DuplicatedKey: # Check for immutable argument given to each_with_object. Lint/EachWithObjectArgument: - Enabled: false + Enabled: true # Check for odd code arrangement in an else block. Lint/ElseLayout: - Enabled: false + Enabled: true # Checks for empty ensure block. Lint/EmptyEnsure: - Enabled: false + Enabled: true # Checks for empty string interpolation. Lint/EmptyInterpolation: @@ -798,37 +833,36 @@ Lint/EmptyInterpolation: # Align ends correctly. Lint/EndAlignment: - Enabled: false + Enabled: true # END blocks should not be placed inside method definitions. Lint/EndInMethod: - Enabled: false + Enabled: true # Do not use return in an ensure block. Lint/EnsureReturn: - Enabled: false + Enabled: true # The use of eval represents a serious security risk. Lint/Eval: - Enabled: false + Enabled: true # Catches floating-point literals too large or small for Ruby to represent. Lint/FloatOutOfRange: - Enabled: false + Enabled: true # The number of parameters to format/sprint must match the fields. Lint/FormatParameterMismatch: - Enabled: false + Enabled: true # Don't suppress exception. Lint/HandleExceptions: Enabled: false -# TODO: Enable ImplicitStringConcatenation Cop. # Checks for adjacent string literals on the same line, which could better be # represented as a single string literal. Lint/ImplicitStringConcatenation: - Enabled: false + Enabled: true # TODO: Enable IneffectiveAccessModifier Cop. # Checks for attempts to use `private` or `protected` to set the visibility @@ -839,15 +873,15 @@ Lint/IneffectiveAccessModifier: # Checks for invalid character literals with a non-escaped whitespace # character. Lint/InvalidCharacterLiteral: - Enabled: false + Enabled: true # Checks of literals used in conditions. Lint/LiteralInCondition: - Enabled: false + Enabled: true # Checks for literals used in interpolation. Lint/LiteralInInterpolation: - Enabled: false + Enabled: true # Use Kernel#loop with break rather than begin/end/until or begin/end/while # for post-loop tests. @@ -856,11 +890,11 @@ Lint/Loop: # Do not use nested method definitions. Lint/NestedMethodDefinition: - Enabled: false + Enabled: true # Do not omit the accumulator when calling `next` in a `reduce`/`inject` block. Lint/NextWithoutAccumulator: - Enabled: false + Enabled: true # Checks for method calls with a space before the opening parenthesis. Lint/ParenthesesAsGroupedExpression: @@ -869,11 +903,11 @@ Lint/ParenthesesAsGroupedExpression: # Checks for `rand(1)` calls. Such calls always return `0` and most likely # a mistake. Lint/RandOne: - Enabled: false + Enabled: true # Use parentheses in the method call to avoid confusion about precedence. Lint/RequireParentheses: - Enabled: false + Enabled: true # Avoid rescuing the Exception class. Lint/RescueException: @@ -908,7 +942,7 @@ Lint/UnusedMethodArgument: # Unreachable code. Lint/UnreachableCode: - Enabled: false + Enabled: true # Checks for useless access modifiers. Lint/UselessAccessModifier: @@ -920,33 +954,31 @@ Lint/UselessAssignment: # Checks for comparison of something with itself. Lint/UselessComparison: - Enabled: false + Enabled: true # Checks for useless `else` in `begin..end` without `rescue`. Lint/UselessElseWithoutRescue: - Enabled: false + Enabled: true # Checks for useless setter call to a local variable. Lint/UselessSetterCall: - Enabled: false + Enabled: true # Possible use of operator/literal/variable in void context. Lint/Void: - Enabled: false + Enabled: true ##################### Performance ############################ -# TODO: Enable Casecmp Cop. # Use `casecmp` rather than `downcase ==`. Performance/Casecmp: - Enabled: false + Enabled: true -# TODO: Enable DoubleStartEndWith Cop. # Use `str.{start,end}_with?(x, ..., y, ...)` instead of # `str.{start,end}_with?(x, ...) || str.{start,end}_with?(y, ...)`. Performance/DoubleStartEndWith: - Enabled: false + Enabled: true # TODO: Enable EndWith Cop. # Use `end_with?` instead of a regex match anchored to the end of a string. @@ -957,10 +989,9 @@ Performance/EndWith: Performance/LstripRstrip: Enabled: true -# TODO: Enable RangeInclude Cop. # Use `Range#cover?` instead of `Range#include?`. Performance/RangeInclude: - Enabled: false + Enabled: true # TODO: Enable RedundantBlockCall Cop. # Use `yield` instead of `block.call`. @@ -980,26 +1011,24 @@ Performance/RedundantMerge: MaxKeyValuePairs: 2 Enabled: false -# TODO: Enable RedundantSortBy Cop. # Use `sort` instead of `sort_by { |x| x }`. Performance/RedundantSortBy: - Enabled: false + Enabled: true -# TODO: Enable StartWith Cop. # Use `start_with?` instead of a regex match anchored to the beginning of a # string. Performance/StartWith: - Enabled: false + Enabled: true + # Use `tr` instead of `gsub` when you are replacing the same number of # characters. Use `delete` instead of `gsub` when you are deleting # characters. Performance/StringReplacement: - Enabled: false + Enabled: true -# TODO: Enable TimesMap Cop. # Checks for `.times.map` calls. Performance/TimesMap: - Enabled: false + Enabled: true ##################### Rails ################################## @@ -1024,11 +1053,11 @@ Rails/Delegate: # Prefer `find_by` over `where.first`. Rails/FindBy: - Enabled: false + Enabled: true # Prefer `all.find_each` over `all.find`. Rails/FindEach: - Enabled: false + Enabled: true # Prefer has_many :through to has_and_belongs_to_many. Rails/HasAndBelongsToMany: @@ -1040,7 +1069,7 @@ Rails/Output: # Checks for incorrect grammar when using methods like `3.day.ago`. Rails/PluralizationGrammar: - Enabled: false + Enabled: true # Checks for `read_attribute(:attr)` and `write_attribute(:attr, val)`. Rails/ReadWriteAttribute: @@ -1048,7 +1077,7 @@ Rails/ReadWriteAttribute: # Checks the arguments of ActiveRecord scopes. Rails/ScopeArgs: - Enabled: false + Enabled: true # Checks the correct usage of time zone aware methods. # http://danilenko.org/2012/7/6/rails_timezones @@ -1058,3 +1087,65 @@ Rails/TimeZone: # Use validates :attribute, hash of validations. Rails/Validation: Enabled: false + +##################### RSpec ################################## + +# Check that instances are not being stubbed globally. +RSpec/AnyInstance: + Enabled: false + +# Check that the first argument to the top level describe is the tested class or +# module. +RSpec/DescribeClass: + Enabled: false + +# Use `described_class` for tested class / module. +RSpec/DescribeMethod: + Enabled: false + +# Checks that the second argument to top level describe is the tested method +# name. +RSpec/DescribedClass: + Enabled: false + +# Checks for long example. +RSpec/ExampleLength: + Enabled: false + Max: 5 + +# Do not use should when describing your tests. +RSpec/ExampleWording: + Enabled: false + CustomTransform: + be: is + have: has + not: does not + IgnoredWords: [] + +# Checks the file and folder naming of the spec file. +RSpec/FilePath: + Enabled: false + CustomTransform: + RuboCop: rubocop + RSpec: rspec + +# Checks if there are focused specs. +RSpec/Focus: + Enabled: true + +# Checks for the usage of instance variables. +RSpec/InstanceVariable: + Enabled: false + +# Checks for multiple top-level describes. +RSpec/MultipleDescribes: + Enabled: false + +# Enforces the usage of the same method on all negative message expectations. +RSpec/NotToNot: + EnforcedStyle: not_to + Enabled: true + +# Prefer using verifying doubles over normal doubles. +RSpec/VerifiedDoubles: + Enabled: false diff --git a/app/views/projects/notes/_commit_discussion.html.haml b/.vagrant_enabled similarity index 100% rename from app/views/projects/notes/_commit_discussion.html.haml rename to .vagrant_enabled diff --git a/CHANGELOG b/CHANGELOG index 822fa4be56..ec026b8f39 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,47 +1,180 @@ Please view this file on the master branch, on stable branches it's out of date. -v 8.8.0 (unreleased) +v 8.9.0 (unreleased) + - Allow enabling wiki page events from Webhook management UI + - Make EmailsOnPushWorker use Sidekiq mailers queue + - Fix wiki page events' webhook to point to the wiki repository + - Fix issue todo not remove when leave project !4150 (Long Nguyen) + - Allow forking projects with restricted visibility level + - Improve note validation to prevent errors when creating invalid note via API + - Reduce number of fog gem dependencies + - Remove project notification settings associated with deleted projects + - Fix 404 page when viewing TODOs that contain milestones or labels in different projects + - Redesign navigation for project pages + - Fix groups API to list only user's accessible projects + - Redesign account and email confirmation emails + - Use gitlab-shell v3.0.0 + - Add DB index on users.state + - Add rake task 'gitlab:db:configure' for conditionally seeding or migrating the database + - Changed the Slack build message to use the singular duration if necessary (Aran Koning) + - Fix issues filter when ordering by milestone + - Todos will display target state if issuable target is 'Closed' or 'Merged' + - Fix bug when sorting issues by milestone due date and filtering by two or more labels + - Link to blank group icon doesn't throw a 404 anymore + - Remove 'main language' feature + - Pipelines can be canceled only when there are running builds + - Use downcased path to container repository as this is expected path by Docker + - Projects pending deletion will render a 404 page + - Measure queue duration between gitlab-workhorse and Rails + - Make authentication service for Container Registry to be compatible with < Docker 1.11 + - Add Application Setting to configure Container Registry token expire delay (default 5min) + - Cache assigned issue and merge request counts in sidebar nav + - Cache project build count in sidebar nav + - Reduce number of queries needed to render issue labels in the sidebar + - Improve error handling importing projects + - Put project Files and Commits tabs under Code tab + +v 8.8.3 + - Fix 404 page when viewing TODOs that contain milestones or labels in different projects. !4312 + - Fixed JS error when trying to remove discussion form. !4303 + - Fixed issue with button color when no CI enabled. !4287 + - Fixed potential issue with 2 CI status polling events happening. !3869 + - Improve design of Pipeline view. !4230 + - Fix gitlab importer failing to import new projects due to missing credentials. !4301 + - Fix import URL migration not rescuing with the correct Error. !4321 + - Fix health check access token changing due to old application settings being used. !4332 + - Make authentication service for Container Registry to be compatible with Docker versions before 1.11. !4363 + - Add Application Setting to configure Container Registry token expire delay (default 5 min). !4364 + - Pass the "Remember me" value to the 2FA token form. !4369 + - Fix incorrect links on pipeline page when merge request created from fork. !4376 + - Use downcased path to container repository as this is expected path by Docker. !4420 + - Fix wiki project clone address error (chujinjin). !4429 + - Fix serious performance bug with rendering Markdown with InlineDiffFilter. !4392 + - Fix missing number on generated ordered list element. !4437 + - Prevent disclosure of notes on confidential issues in search results. + +v 8.8.2 + - Added remove due date button. !4209 + - Fix Error 500 when accessing application settings due to nil disabled OAuth sign-in sources. !4242 + - Fix Error 500 in CI charts by gracefully handling commits with no durations. !4245 + - Fix table UI on CI builds page. !4249 + - Fix backups if registry is disabled. !4263 + - Fixed issue with merge button color. !4211 + - Fixed issue with enter key selecting wrong option in dropdown. !4210 + - When creating a .gitignore file a dropdown with templates will be provided. !4075 + - Fix concurrent request when updating build log in browser. !4183 + +v 8.8.1 + - Add documentation for the "Health Check" feature + - Allow anonymous users to access a public project's pipelines !4233 + - Fix MySQL compatibility in zero downtime migrations helpers + - Fix the CI login to Container Registry (the gitlab-ci-token user) + +v 8.8.0 + - Implement GFM references for milestones (Alejandro Rodríguez) + - Snippets tab under user profile. !4001 (Long Nguyen) + - Fix error when using link to uploads in global snippets + - Fix Error 500 when attempting to retrieve project license when HEAD points to non-existent ref - Assign labels and milestone to target project when moving issue. !3934 (Long Nguyen) + - Use a case-insensitive comparison in sanitizing URI schemes + - Toggle sign-up confirmation emails in application settings + - Make it possible to prevent tagged runner from picking untagged jobs + - Added `InlineDiffFilter` to the markdown parser. (Adam Butler) + - Added inline diff styling for `change_title` system notes. (Adam Butler) - Project#open_branches has been cleaned up and no longer loads entire records into memory. - Escape HTML in commit titles in system note messages + - Improve design of Pipeline View + - Fix scope used when accessing container registry + - Fix creation of Ci::Commit object which can lead to pending, failed in some scenarios - Improve multiple branch push performance by memoizing permission checking - Log to application.log when an admin starts and stops impersonating a user + - Changing the confidentiality of an issue now creates a new system note (Alex Moore-Niemi) - Updated gitlab_git to 10.1.0 - GitAccess#protected_tag? no longer loads all tags just to check if a single one exists - Reduce delay in destroying a project from 1-minute to immediately - Make build status canceled if any of the jobs was canceled and none failed - Upgrade Sidekiq to 4.1.2 + - Added /health_check endpoint for checking service status + - Make 'upcoming' filter for milestones work better across projects - Sanitize repo paths in new project error message - Bump mail_room to 0.7.0 to fix stuck IDLE connections - Remove future dates from contribution calendar graph. - Support e-mail notifications for comments on project snippets + - Fix API leak of notes of unauthorized issues, snippets and merge requests - Use ActionDispatch Remote IP for Akismet checking - Fix error when visiting commit builds page before build was updated - Add 'l' shortcut to open Label dropdown on issuables and 'i' to create new issue on a project - Update SVG sanitizer to conform to SVG 1.1 + - Speed up push emails with multiple recipients by only generating the email once - Updated search UI + - Added authentication service for Container Registry - Display informative message when new milestone is created + - Sanitize milestones and labels titles + - Support multi-line tag messages. !3833 (Calin Seciu) + - Force users to reset their password after an admin changes it - Allow "NEWS" and "CHANGES" as alternative names for CHANGELOG. !3768 (Connor Shea) - Added button to toggle whitespaces changes on diff view - Backport GitHub Enterprise import support from EE - Create tags using Rugged for performance reasons. !3745 + - Allow guests to set notification level in projects + - API: Expose Issue#user_notes_count. !3126 (Anton Popov) + - Don't show forks button when user can't view forks + - Fix atom feed links and rendering - Files over 5MB can only be viewed in their raw form, files over 1MB without highlighting !3718 - Add support for supressing text diffs using .gitattributes on the default branch (Matt Oakes) + - Add eager load paths to help prevent dependency load issues in Sidekiq workers. !3724 - Added multiple colors for labels in dropdowns when dups happen. + - Show commits in the same order as `git log` - Improve description for the Two-factor Authentication sign-in screen. (Connor Shea) - API support for the 'since' and 'until' operators on commit requests (Paco Guzman) - Fix Gravatar hint in user profile when Gravatar is disabled. !3988 (Artem Sidorenko) - Expire repository exists? and has_visible_content? caches after a push if necessary - - Fix unintentional filtering bug in issues sorted by milestone due (Takuya Noguchi) + - Fix unintentional filtering bug in Issue/MR sorted by milestone due (Takuya Noguchi) + - Fix adding a todo for private group members (Ahmad Sherif) + - Bump ace-rails-ap gem version from 2.0.1 to 4.0.2 which upgrades Ace Editor from 1.1.2 to 1.2.3 + - Total method execution timings are no longer tracked + - Allow Admins to remove the Login with buttons for OAuth services and still be able to import !4034. (Andrei Gliga) + - Add API endpoints for un/subscribing from/to a label. !4051 (Ahmad Sherif) + - Hide left sidebar on phone screens to give more space for content + - Redesign navigation for profile and group pages + - Add counter metrics for rails cache + - Import pull requests from GitHub where the source or target branches were removed + - All Grape API helpers are now instrumented + - Improve Issue formatting for the Slack Service (Jeroen van Baarsen) + - Fixed advice on invalid permissions on upload path !2948 (Ludovic Perrine) + - Allows MR authors to have the source branch removed when merging the MR. !2801 (Jeroen Jacobs) + - When creating a .gitignore file a dropdown with templates will be provided + +v 8.7.7 + - Fix import by `Any Git URL` broken if the URL contains a space + +v 8.7.6 + - Fix links on wiki pages for relative url setups. !4131 (Artem Sidorenko) + - Fix import from GitLab.com to a private instance failure. !4181 + - Fix external imports not finding the import data. !4106 + - Fix notification delay when changing status of an issue + +v 8.7.5 + - Fix relative links in wiki pages. !4050 + - Fix always showing build notification message when switching between merge requests !4086 + - Fix an issue when filtering merge requests with more than one label. !3886 + - Fix short note for the default scope on build page (Takuya Noguchi) v 8.7.4 - - Fix always showing build notification message when switching between merge requests + - Links for Redmine issue references are generated correctly again !4048 (Benedikt Huss) + - Fix setting trusted proxies !3970 + - Fix BitBucket importer bug when throwing exceptions !3941 + - Use sign out path only if not empty !3989 + - Running rake gitlab:db:drop_tables now drops tables with cascade !4020 + - Running rake gitlab:db:drop_tables uses "IF EXISTS" as a precaution !4100 + - Use a case-insensitive comparison in sanitizing URI schemes v 8.7.3 - Emails, Gitlab::Email::Message, Gitlab::Diff, and Premailer::Adapter::Nokogiri are now instrumented - Merge request widget displays TeamCity build state and code coverage correctly again. - Fix the line code when importing PR review comments from GitHub. !4010 - Wikis are now initialized on legacy projects when checking repositories + - Remove animate.css in favor of a smaller subset of animations. !3937 (Connor Shea) v 8.7.2 - The "New Branch" button is now loaded asynchronously @@ -850,7 +983,7 @@ v 8.1.3 - Use issue editor as cross reference comment author when issue is edited with a new mention - Add Facebook authentication -v 8.1.2 +v 8.1.1 - Fix cloning Wiki repositories via HTTP (Stan Hu) - Add migration to remove satellites directory - Fix specific runners visibility @@ -1475,20 +1608,17 @@ v 7.10.0 - Fix stuck Merge Request merging events from old installations (Ben Bodenmiller) - Fix merge request comments on files with multiple commits - Fix Resource Owner Password Authentication Flow - -v 7.9.4 - - Security: Fix project import URL regex to prevent arbitary local repos from being imported - - Fixed issue where only 25 commits would load in file listings - - Fix LDAP identities after config update - -v 7.9.3 - - Contains no changes - Add icons to Add dropdown items. - Allow admin to create public deploy keys that are accessible to any project. - Warn when gitlab-shell version doesn't match requirement. - Skip email confirmation when set by admin or via LDAP. - Only allow users to reference groups, projects, issues, MRs, commits they have access to. +v 7.9.4 + - Security: Fix project import URL regex to prevent arbitary local repos from being imported + - Fixed issue where only 25 commits would load in file listings + - Fix LDAP identities after config update + v 7.9.3 - Contains no changes diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9fe4cf7b0f..a15f8c4fec 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -311,13 +311,11 @@ request is as follows: 1. Create a feature branch 1. Write [tests](https://gitlab.com/gitlab-org/gitlab-development-kit#running-the-tests) and code 1. Add your changes to the [CHANGELOG](CHANGELOG) -1. If you are changing the README, some documentation or other things which - have no effect on the tests, add `[ci skip]` somewhere in the commit message - and make sure to read the [documentation styleguide][doc-styleguide] +1. If you are writing documentation, make sure to read the [documentation styleguide][doc-styleguide] 1. If you have multiple commits please combine them into one commit by [squashing them][git-squash] 1. Push the commit(s) to your fork -1. Submit a merge request (MR) to the master branch +1. Submit a merge request (MR) to the `master` branch 1. The MR title should describe the change you want to make 1. The MR description should give a motive for your change and the method you used to achieve it, see the [merge request description format] diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION index 37c2961c24..4a36342fca 100644 --- a/GITLAB_SHELL_VERSION +++ b/GITLAB_SHELL_VERSION @@ -1 +1 @@ -2.7.2 +3.0.0 diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION index 39e898a4f9..0a1ffad4b4 100644 --- a/GITLAB_WORKHORSE_VERSION +++ b/GITLAB_WORKHORSE_VERSION @@ -1 +1 @@ -0.7.1 +0.7.4 diff --git a/Gemfile b/Gemfile index 1137ef4d72..d9429de786 100644 --- a/Gemfile +++ b/Gemfile @@ -18,9 +18,8 @@ gem "mysql2", '~> 0.3.16', group: :mysql gem "pg", '~> 0.18.2', group: :postgres # Authentication libraries -gem 'devise', '~> 3.5.4' +gem 'devise', '~> 4.0' gem 'doorkeeper', '~> 3.1' -gem 'devise-async', '~> 0.9.0' gem 'omniauth', '~> 1.3.1' gem 'omniauth-auth0', '~> 1.4.1' gem 'omniauth-azure-oauth2', '~> 0.0.6' @@ -36,15 +35,16 @@ gem 'omniauth-shibboleth', '~> 1.2.0' gem 'omniauth-twitter', '~> 1.2.0' gem 'omniauth_crowd', '~> 2.2.0' gem 'rack-oauth2', '~> 1.2.1' +gem 'jwt' # Spam and anti-bot protection gem 'recaptcha', require: 'recaptcha/rails' gem 'akismet', '~> 2.0' # Two-factor authentication -gem 'devise-two-factor', '~> 2.0.0' +gem 'devise-two-factor', '~> 3.0.0' gem 'rqrcode-rails3', '~> 0.1.7' -gem 'attr_encrypted', '~> 1.3.4' +gem 'attr_encrypted', '~> 3.0.0' # Browser detection gem "browser", '~> 1.0.0' @@ -72,7 +72,7 @@ gem 'grape-entity', '~> 0.4.2' gem 'rack-cors', '~> 0.4.0', require: 'rack/cors' # Pagination -gem "kaminari", "~> 0.16.3" +gem "kaminari", "~> 0.17.0" # HAML gem "haml-rails", '~> 0.9.0' @@ -83,8 +83,14 @@ gem "carrierwave", '~> 0.10.0' # Drag and Drop UI gem 'dropzonejs-rails', '~> 0.7.1' +# for backups +gem 'fog-aws', '~> 0.9' +gem 'fog-core', '~> 1.40' +gem 'fog-local', '~> 0.3' +gem 'fog-google', '~> 0.3' +gem 'fog-openstack', '~> 0.1' + # for aws storage -gem "fog", "~> 1.36.0" gem "unf", '~> 0.1.4' # Authorization @@ -120,7 +126,7 @@ group :unicorn do end # State machine -gem "state_machines-activerecord", '~> 0.3.0' +gem "state_machines-activerecord", '~> 0.4.0' # Run events after state machine commits gem 'after_commit_queue' @@ -177,9 +183,6 @@ gem 'ruby-fogbugz', '~> 0.2.1' # d3 gem 'd3_rails', '~> 3.5.0' -#cal-heatmap -gem 'cal-heatmap-rails', '~> 3.6.0' - # underscore-rails gem "underscore-rails", "~> 1.8.0" @@ -197,7 +200,7 @@ gem 'licensee', '~> 8.0.0' gem "rack-attack", '~> 4.3.1' # Ace editor -gem 'ace-rails-ap', '~> 2.0.1' +gem 'ace-rails-ap', '~> 4.0.2' # Keyboard shortcuts gem 'mousetrap-rails', '~> 1.4.6' @@ -218,13 +221,13 @@ gem 'gitlab_emoji', '~> 0.3.0' gem 'gon', '~> 6.0.1' gem 'jquery-atwho-rails', '~> 1.3.2' gem 'jquery-rails', '~> 4.1.0' -gem 'jquery-scrollto-rails', '~> 1.4.3' gem 'jquery-ui-rails', '~> 5.0.0' gem 'raphael-rails', '~> 2.1.2' gem 'request_store', '~> 1.3.0' gem 'select2-rails', '~> 3.5.9' gem 'virtus', '~> 1.0.1' gem 'net-ssh', '~> 3.0.1' +gem 'base32', '~> 0.3.0' # Sentry integration gem 'sentry-raven', '~> 0.15' @@ -242,7 +245,6 @@ group :development do gem "foreman" gem 'brakeman', '~> 3.2.0', require: false - gem "annotate", "~> 2.7.0" gem 'letter_opener_web', '~> 1.3.0' gem 'quiet_assets', '~> 1.0.2' gem 'rerun', '~> 0.11.0' @@ -293,9 +295,10 @@ group :development, :test do gem 'spring-commands-spinach', '~> 1.1.0' gem 'spring-commands-teaspoon', '~> 0.0.2' - gem 'rubocop', '~> 0.38.0', require: false + 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 'coveralls', '~> 0.8.2', require: false gem 'simplecov', '~> 0.11.0', require: false gem 'flog', require: false gem 'flay', require: false @@ -325,8 +328,7 @@ gem "mail_room", "~> 0.7" gem 'email_reply_parser', '~> 0.5.8' ## CI -gem 'activerecord-deprecated_finders', '~> 1.0.3' -gem 'activerecord-session_store', '~> 0.1.0' +gem 'activerecord-session_store', '~> 1.0.0' gem "nested_form", '~> 0.3.2' # OAuth @@ -334,3 +336,6 @@ gem 'oauth2', '~> 1.0.0' # Soft deletion gem "paranoia", "~> 2.0" + +# Health check +gem 'health_check', '~> 1.5.1' diff --git a/Gemfile.lock b/Gemfile.lock index fe083c2b56..8ae25269e6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,9 +1,8 @@ GEM remote: https://rubygems.org/ specs: - CFPropertyList (2.3.2) RedCloth (4.2.9) - ace-rails-ap (2.0.1) + ace-rails-ap (4.0.2) actionmailer (4.2.6) actionpack (= 4.2.6) actionview (= 4.2.6) @@ -33,11 +32,12 @@ GEM activemodel (= 4.2.6) activesupport (= 4.2.6) arel (~> 6.0) - activerecord-deprecated_finders (1.0.4) - activerecord-session_store (0.1.2) - actionpack (>= 4.0.0, < 5) - activerecord (>= 4.0.0, < 5) - railties (>= 4.0.0, < 5) + activerecord-session_store (1.0.0) + actionpack (>= 4.0, < 5.1) + activerecord (>= 4.0, < 5.1) + multi_json (~> 1.11, >= 1.11.2) + rack (>= 1.5.2, < 3) + railties (>= 4.0, < 5.1) activesupport (4.2.6) i18n (~> 0.7) json (~> 1.7, >= 1.7.7) @@ -51,9 +51,6 @@ GEM activerecord (>= 3.0) akismet (2.0.0) allocations (1.0.4) - annotate (2.7.0) - activerecord (>= 3.2, < 6.0) - rake (~> 10.4) arel (6.0.3) asana (0.4.0) faraday (~> 0.9) @@ -62,8 +59,8 @@ GEM oauth2 (~> 1.0) asciidoctor (1.5.3) ast (2.2.0) - attr_encrypted (1.3.4) - encryptor (>= 1.3.0) + attr_encrypted (3.0.1) + encryptor (~> 3.0.0) attr_required (1.0.0) autoprefixer-rails (6.2.3) execjs @@ -74,7 +71,8 @@ GEM ice_nine (~> 0.11.0) thread_safe (~> 0.3, >= 0.3.1) babosa (1.0.2) - bcrypt (3.1.10) + base32 (0.3.2) + bcrypt (3.1.11) benchmark-ips (2.3.0) better_errors (1.0.1) coderay (>= 1.0.0) @@ -103,7 +101,6 @@ GEM bundler (~> 1.2) thor (~> 0.18) byebug (8.2.1) - cal-heatmap-rails (3.6.0) capybara (2.6.2) addressable mime-types (>= 1.16) @@ -157,21 +154,18 @@ GEM activerecord (>= 3.2.0, < 5.0) descendants_tracker (0.0.4) thread_safe (~> 0.3, >= 0.3.1) - devise (3.5.4) + devise (4.1.1) bcrypt (~> 3.0) orm_adapter (~> 0.1) - railties (>= 3.2.6, < 5) + railties (>= 4.1.0, < 5.1) responders - thread_safe (~> 0.1) warden (~> 1.2.3) - devise-async (0.9.0) - devise (~> 3.2) - devise-two-factor (2.0.1) + devise-two-factor (3.0.0) activesupport - attr_encrypted (~> 1.3.2) - devise (~> 3.5.0) + attr_encrypted (>= 1.3, < 4, != 2) + devise (~> 4.0) railties - rotp (~> 2) + rotp (~> 2.0) diff-lcs (1.2.5) diffy (3.0.7) docile (1.1.5) @@ -183,12 +177,12 @@ GEM email_spec (1.6.0) launchy (~> 2.1) mail (~> 2.2) - encryptor (1.3.0) + encryptor (3.0.0) equalizer (0.0.11) erubis (2.7.0) escape_utils (1.1.1) eventmachine (1.0.8) - excon (0.45.4) + excon (0.49.0) execjs (2.6.0) expression_parser (0.9.0) factory_girl (4.5.0) @@ -205,8 +199,6 @@ GEM multi_json ffaker (2.0.0) ffi (1.9.10) - fission (0.5.0) - CFPropertyList (~> 2.2) flay (2.6.1) ruby_parser (~> 3.0) sexp_processor (~> 4.0) @@ -216,109 +208,28 @@ GEM flowdock (0.7.1) httparty (~> 0.7) multi_json - fog (1.36.0) - fog-aliyun (>= 0.1.0) - fog-atmos - fog-aws (>= 0.6.0) - fog-brightbox (~> 0.4) - fog-core (~> 1.32) - fog-dynect (~> 0.0.2) - fog-ecloud (~> 0.1) - fog-google (<= 0.1.0) - fog-json - fog-local - fog-powerdns (>= 0.1.1) - fog-profitbricks - fog-radosgw (>= 0.0.2) - fog-riakcs - fog-sakuracloud (>= 0.0.4) - fog-serverlove - fog-softlayer - fog-storm_on_demand - fog-terremark - fog-vmfusion - fog-voxel - fog-xenserver - fog-xml (~> 0.1.1) - ipaddress (~> 0.5) - nokogiri (~> 1.5, >= 1.5.11) - fog-aliyun (0.1.0) - fog-core (~> 1.27) - fog-json (~> 1.0) - ipaddress (~> 0.8) - xml-simple (~> 1.1) - fog-atmos (0.1.0) - fog-core - fog-xml - fog-aws (0.8.1) + fog-aws (0.9.2) fog-core (~> 1.27) fog-json (~> 1.0) fog-xml (~> 0.1) ipaddress (~> 0.8) - fog-brightbox (0.10.1) - fog-core (~> 1.22) - fog-json - inflecto (~> 0.0.2) - fog-core (1.35.0) + fog-core (1.40.0) builder - excon (~> 0.45) + excon (~> 0.49) formatador (~> 0.2) - fog-dynect (0.0.2) - fog-core - fog-json - fog-xml - fog-ecloud (0.3.0) - fog-core - fog-xml - fog-google (0.1.0) + fog-google (0.3.2) fog-core fog-json fog-xml fog-json (1.0.2) fog-core (~> 1.0) multi_json (~> 1.10) - fog-local (0.2.1) + fog-local (0.3.0) fog-core (~> 1.27) - fog-powerdns (0.1.1) - fog-core (~> 1.27) - fog-json (~> 1.0) - fog-xml (~> 0.1) - fog-profitbricks (0.0.5) - fog-core - fog-xml - nokogiri - fog-radosgw (0.0.5) - fog-core (>= 1.21.0) - fog-json - fog-xml (>= 0.0.1) - fog-riakcs (0.1.0) - fog-core - fog-json - fog-xml - fog-sakuracloud (1.7.5) - fog-core - fog-json - fog-serverlove (0.1.2) - fog-core - fog-json - fog-softlayer (1.0.3) - fog-core - fog-json - fog-storm_on_demand (0.1.1) - fog-core - fog-json - fog-terremark (0.1.0) - fog-core - fog-xml - fog-vmfusion (0.1.0) - fission - fog-core - fog-voxel (0.1.0) - fog-core - fog-xml - fog-xenserver (0.2.2) - fog-core - fog-xml + fog-openstack (0.1.6) + fog-core (>= 1.39) + fog-json (>= 1.0) + ipaddress (>= 0.8) fog-xml (0.1.2) fog-core nokogiri (~> 1.5, >= 1.5.11) @@ -405,6 +316,8 @@ GEM html2haml (>= 1.0.1) railties (>= 4.0.1) hashie (3.4.3) + health_check (1.5.1) + rails (>= 2.3.0) highline (1.7.8) hipchat (1.5.2) httparty @@ -425,18 +338,15 @@ GEM httpclient (2.7.0.1) i18n (0.7.0) ice_nine (0.11.1) - inflecto (0.0.2) influxdb (0.2.3) cause json - ipaddress (0.8.2) + ipaddress (0.8.3) jquery-atwho-rails (1.3.2) jquery-rails (4.1.1) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) - jquery-scrollto-rails (1.4.3) - railties (> 3.1, < 5.0) jquery-turbolinks (2.1.0) railties (>= 3.1.0) turbolinks @@ -444,7 +354,7 @@ GEM railties (>= 3.2.16) json (1.8.3) jwt (1.5.2) - kaminari (0.16.3) + kaminari (0.17.0) actionpack (>= 3.0.0) activesupport (>= 3.0.0) kgio (2.10.0) @@ -552,7 +462,7 @@ GEM orm_adapter (0.5.0) paranoia (2.1.4) activerecord (~> 4.0) - parser (2.3.0.6) + parser (2.3.1.0) ast (~> 2.2) pg (0.18.4) poltergeist (1.9.0) @@ -658,7 +568,7 @@ GEM responders (2.1.1) railties (>= 4.2.0, < 5.1) rinku (1.7.3) - rotp (2.1.1) + rotp (2.1.2) rouge (1.10.1) rqrcode (0.7.0) chunky_png @@ -687,15 +597,17 @@ GEM rspec-retry (0.4.5) rspec-core rspec-support (3.4.1) - rubocop (0.38.0) - parser (>= 2.3.0.6, < 3.0) + rubocop (0.40.0) + parser (>= 2.3.1.0, < 3.0) powerpack (~> 0.1) rainbow (>= 1.99.1, < 3.0) ruby-progressbar (~> 1.7) unicode-display_width (~> 1.0, >= 1.0.1) + rubocop-rspec (1.5.0) + rubocop (>= 0.40.0) ruby-fogbugz (0.2.1) crack (~> 0.4) - ruby-progressbar (1.7.5) + ruby-progressbar (1.8.1) ruby-saml (1.1.2) nokogiri (>= 1.5.10) uuid (~> 2.3) @@ -789,11 +701,11 @@ GEM activesupport (>= 4.0) sprockets (>= 3.0.0) state_machines (0.4.0) - state_machines-activemodel (0.3.0) - activemodel (~> 4.1) + state_machines-activemodel (0.4.0) + activemodel (>= 4.1, < 5.1) state_machines (>= 0.4.0) - state_machines-activerecord (0.3.0) - activerecord (~> 4.1) + state_machines-activerecord (0.4.0) + activerecord (>= 4.1, < 5.1) state_machines-activemodel (>= 0.3.0) stringex (2.5.2) systemu (2.6.5) @@ -842,7 +754,7 @@ GEM unf (0.1.4) unf_ext unf_ext (0.0.7.2) - unicode-display_width (1.0.2) + unicode-display_width (1.0.5) unicorn (4.9.0) kgio (~> 2.6) rack @@ -859,7 +771,7 @@ GEM coercible (~> 1.0) descendants_tracker (~> 0.0, >= 0.0.3) equalizer (~> 0.0, >= 0.0.9) - warden (1.2.4) + warden (1.2.6) rack (>= 1.0) web-console (2.3.0) activemodel (>= 4.0) @@ -876,7 +788,6 @@ GEM builder expression_parser rinku - xml-simple (1.1.5) xpath (2.0.0) nokogiri (~> 1.3) @@ -885,20 +796,19 @@ PLATFORMS DEPENDENCIES RedCloth (~> 4.2.9) - ace-rails-ap (~> 2.0.1) - activerecord-deprecated_finders (~> 1.0.3) - activerecord-session_store (~> 0.1.0) + ace-rails-ap (~> 4.0.2) + activerecord-session_store (~> 1.0.0) acts-as-taggable-on (~> 3.4) addressable (~> 2.3.8) after_commit_queue akismet (~> 2.0) allocations (~> 1.0) - annotate (~> 2.7.0) asana (~> 0.4.0) asciidoctor (~> 1.5.2) - attr_encrypted (~> 1.3.4) + attr_encrypted (~> 3.0.0) awesome_print (~> 1.2.0) babosa (~> 1.0.2) + base32 (~> 0.3.0) benchmark-ips better_errors (~> 1.0.1) binding_of_caller (~> 0.7.2) @@ -908,7 +818,6 @@ DEPENDENCIES bullet bundler-audit byebug - cal-heatmap-rails (~> 3.6.0) capybara (~> 2.6.2) capybara-screenshot (~> 1.0.0) carrierwave (~> 0.10.0) @@ -921,9 +830,8 @@ DEPENDENCIES d3_rails (~> 3.5.0) database_cleaner (~> 1.4.0) default_value_for (~> 3.0.0) - devise (~> 3.5.4) - devise-async (~> 0.9.0) - devise-two-factor (~> 2.0.0) + devise (~> 4.0) + devise-two-factor (~> 3.0.0) diffy (~> 3.0.3) doorkeeper (~> 3.1) dropzonejs-rails (~> 0.7.1) @@ -933,7 +841,11 @@ DEPENDENCIES ffaker (~> 2.0.0) flay flog - fog (~> 1.36.0) + fog-aws (~> 0.9) + fog-core (~> 1.40) + fog-google (~> 0.3) + fog-local (~> 0.3) + fog-openstack (~> 0.1) font-awesome-rails (~> 4.2) foreman fuubar (~> 2.0.0) @@ -951,16 +863,17 @@ DEPENDENCIES grape (~> 0.13.0) grape-entity (~> 0.4.2) haml-rails (~> 0.9.0) + health_check (~> 1.5.1) hipchat (~> 1.5.0) html-pipeline (~> 1.11.0) httparty (~> 0.13.3) influxdb (~> 0.2) jquery-atwho-rails (~> 1.3.2) jquery-rails (~> 4.1.0) - jquery-scrollto-rails (~> 1.4.3) jquery-turbolinks (~> 2.1.0) jquery-ui-rails (~> 5.0.0) - kaminari (~> 0.16.3) + jwt + kaminari (~> 0.17.0) letter_opener_web (~> 1.3.0) licensee (~> 8.0.0) loofah (~> 2.0.3) @@ -1016,7 +929,8 @@ DEPENDENCIES rqrcode-rails3 (~> 0.1.7) rspec-rails (~> 3.4.0) rspec-retry - rubocop (~> 0.38.0) + rubocop (~> 0.40.0) + rubocop-rspec (~> 1.5.0) ruby-fogbugz (~> 0.2.1) sanitize (~> 2.0) sass-rails (~> 5.0.0) @@ -1041,7 +955,7 @@ DEPENDENCIES spring-commands-spinach (~> 1.1.0) spring-commands-teaspoon (~> 0.0.2) sprockets (~> 3.6.0) - state_machines-activerecord (~> 0.3.0) + state_machines-activerecord (~> 0.4.0) task_list (~> 1.0.2) teaspoon (~> 1.1.0) teaspoon-jasmine (~> 2.2.0) @@ -1061,4 +975,4 @@ DEPENDENCIES wikicloth (= 0.8.1) BUNDLED WITH - 1.12.1 + 1.12.4 diff --git a/README.md b/README.md index 5e41665a6b..fee93d5f9c 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,7 @@ # GitLab [![build status](https://gitlab.com/gitlab-org/gitlab-ce/badges/master/build.svg)](https://gitlab.com/gitlab-org/gitlab-ce/commits/master) -[![Build Status](https://semaphoreci.com/api/v1/projects/2f1a5809-418b-4cc2-a1f4-819607579fe7/400484/shields_badge.svg)](https://semaphoreci.com/gitlabhq/gitlabhq) [![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.svg)](https://codeclimate.com/github/gitlabhq/gitlabhq) -[![Coverage Status](https://coveralls.io/repos/gitlabhq/gitlabhq/badge.svg?branch=master)](https://coveralls.io/r/gitlabhq/gitlabhq?branch=master) ## Canonical source @@ -35,11 +33,11 @@ There are two editions of GitLab: On [about.gitlab.com](https://about.gitlab.com/) you can find more information about: -- [Subscriptions](https://about.gitlab.com/subscription/) +- [Subscriptions](https://about.gitlab.com/pricing/) - [Consultancy](https://about.gitlab.com/consultancy/) - [Community](https://about.gitlab.com/community/) - [Hosted GitLab.com](https://about.gitlab.com/gitlab-com/) use GitLab as a free service -- [GitLab Enterprise Edition](https://about.gitlab.com/gitlab-ee/) with additional features aimed at larger organizations. +- [GitLab Enterprise Edition](https://about.gitlab.com/features/#enterprise) with additional features aimed at larger organizations. - [GitLab CI](https://about.gitlab.com/gitlab-ci/) a continuous integration (CI) server that is easy to integrate with GitLab. ## Requirements diff --git a/VERSION b/VERSION index d5a967c393..6c07f65628 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.8.0-pre +8.9.0-pre diff --git a/app/assets/images/ci/arch.jpg b/app/assets/images/ci/arch.jpg deleted file mode 100644 index 0e05674e840c6946d5a40f340790289af2dc25f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25222 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 diff --git a/app/assets/images/ci/loader.gif b/app/assets/images/ci/loader.gif deleted file mode 100644 index 2fcb8f2da0d283628878cbc74b9dd848109a4535..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4405 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 AQ~&?~ diff --git a/app/assets/images/ci/service_sample.png b/app/assets/images/ci/service_sample.png deleted file mode 100644 index 65d29e3fd891b7b8deba8670cb7d74b03056e3d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 76024 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 z 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 Hu0mjflsE?Y literal 0 HcmV?d00001 diff --git a/app/assets/javascripts/api.js.coffee b/app/assets/javascripts/api.js.coffee index dd1bbb3755..3f61ea1eaf 100644 --- a/app/assets/javascripts/api.js.coffee +++ b/app/assets/javascripts/api.js.coffee @@ -1,14 +1,15 @@ @Api = - groups_path: "/api/:version/groups.json" - group_path: "/api/:version/groups/:id.json" - namespaces_path: "/api/:version/namespaces.json" - group_projects_path: "/api/:version/groups/:id/projects.json" - projects_path: "/api/:version/projects.json" - labels_path: "/api/:version/projects/:id/labels" - license_path: "/api/:version/licenses/:key" + groupsPath: "/api/:version/groups.json" + groupPath: "/api/:version/groups/:id.json" + namespacesPath: "/api/:version/namespaces.json" + groupProjectsPath: "/api/:version/groups/:id/projects.json" + projectsPath: "/api/:version/projects.json" + labelsPath: "/api/:version/projects/:id/labels" + licensePath: "/api/:version/licenses/:key" + gitignorePath: "/api/:version/gitignores/:key" group: (group_id, callback) -> - url = Api.buildUrl(Api.group_path) + url = Api.buildUrl(Api.groupPath) url = url.replace(':id', group_id) $.ajax( @@ -22,7 +23,7 @@ # Return groups list. Filtered by query # Only active groups retrieved groups: (query, skip_ldap, callback) -> - url = Api.buildUrl(Api.groups_path) + url = Api.buildUrl(Api.groupsPath) $.ajax( url: url @@ -36,7 +37,7 @@ # Return namespaces list. Filtered by query namespaces: (query, callback) -> - url = Api.buildUrl(Api.namespaces_path) + url = Api.buildUrl(Api.namespacesPath) $.ajax( url: url @@ -50,7 +51,7 @@ # Return projects list. Filtered by query projects: (query, order, callback) -> - url = Api.buildUrl(Api.projects_path) + url = Api.buildUrl(Api.projectsPath) $.ajax( url: url @@ -64,7 +65,7 @@ callback(projects) newLabel: (project_id, data, callback) -> - url = Api.buildUrl(Api.labels_path) + url = Api.buildUrl(Api.labelsPath) url = url.replace(':id', project_id) data.private_token = gon.api_token @@ -80,7 +81,7 @@ # Return group projects list. Filtered by query groupProjects: (group_id, query, callback) -> - url = Api.buildUrl(Api.group_projects_path) + url = Api.buildUrl(Api.groupProjectsPath) url = url.replace(':id', group_id) $.ajax( @@ -95,7 +96,7 @@ # Return text for a specific license licenseText: (key, data, callback) -> - url = Api.buildUrl(Api.license_path).replace(':key', key) + url = Api.buildUrl(Api.licensePath).replace(':key', key) $.ajax( url: url @@ -103,6 +104,12 @@ ).done (license) -> callback(license) + gitignoreText: (key, callback) -> + url = Api.buildUrl(Api.gitignorePath).replace(':key', key) + + $.get url, (gitignore) -> + callback(gitignore) + buildUrl: (url) -> url = gon.relative_url_root + url if gon.relative_url_root? return url.replace(':version', gon.api_version) diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee index 5bac8eef1c..18c1aa0d4e 100644 --- a/app/assets/javascripts/application.js.coffee +++ b/app/assets/javascripts/application.js.coffee @@ -18,8 +18,6 @@ #= require jquery.atwho #= require jquery.scrollTo #= require jquery.turbolinks -#= require d3 -#= require cal-heatmap #= require turbolinks #= require autosave #= require bootstrap/affix @@ -52,7 +50,13 @@ #= require shortcuts_network #= require jquery.nicescroll #= require date.format -#= require_tree . +#= require_directory ./behaviors +#= require_directory ./blob +#= require_directory ./ci +#= require_directory ./commit +#= require_directory ./extensions +#= require_directory ./lib +#= require_directory . #= require fuzzaldrin-plus #= require cropper @@ -204,6 +208,7 @@ $ -> $('.header-content .title').toggle() $('.header-content .navbar-collapse').toggle() $('.navbar-toggle').toggleClass('active') + $('.navbar-toggle i').toggleClass("fa-angle-right fa-angle-left") # Show/hide comments on diff $("body").on "click", ".js-toggle-diff-comments", (e) -> @@ -245,38 +250,6 @@ $ -> if $navIcon.hasClass('fa-angle-left') $navIconToggle.trigger('click') - $(document) - .off 'click', '.js-sidebar-toggle' - .on 'click', '.js-sidebar-toggle', (e, triggered) -> - e.preventDefault() - $this = $(this) - $thisIcon = $this.find 'i' - $allGutterToggleIcons = $('.js-sidebar-toggle i') - if $thisIcon.hasClass('fa-angle-double-right') - $allGutterToggleIcons - .removeClass('fa-angle-double-right') - .addClass('fa-angle-double-left') - $('aside.right-sidebar') - .removeClass('right-sidebar-expanded') - .addClass('right-sidebar-collapsed') - $('.page-with-sidebar') - .removeClass('right-sidebar-expanded') - .addClass('right-sidebar-collapsed') - else - $allGutterToggleIcons - .removeClass('fa-angle-double-left') - .addClass('fa-angle-double-right') - $('aside.right-sidebar') - .removeClass('right-sidebar-collapsed') - .addClass('right-sidebar-expanded') - $('.page-with-sidebar') - .removeClass('right-sidebar-collapsed') - .addClass('right-sidebar-expanded') - if not triggered - $.cookie("collapsed_gutter", - $('.right-sidebar') - .hasClass('right-sidebar-collapsed'), { path: '/' }) - fitSidebarForSize = -> oldBootstrapBreakpoint = bootstrapBreakpoint bootstrapBreakpoint = bp.getBreakpointSize() diff --git a/app/assets/javascripts/blob/blob_gitignore_selector.js.coffee b/app/assets/javascripts/blob/blob_gitignore_selector.js.coffee new file mode 100644 index 0000000000..cc8a497d08 --- /dev/null +++ b/app/assets/javascripts/blob/blob_gitignore_selector.js.coffee @@ -0,0 +1,58 @@ +class @BlobGitignoreSelector + constructor: (opts) -> + { + @dropdown + @editor + @$wrapper = @dropdown.closest('.gitignore-selector') + @$filenameInput = $('#file_name') + @data = @dropdown.data('filenames') + } = opts + + @dropdown.glDropdown( + data: @data, + filterable: true, + selectable: true, + search: + fields: ['name'] + clicked: @onClick + text: (gitignore) -> + gitignore.name + ) + + @toggleGitignoreSelector() + @bindEvents() + + bindEvents: -> + @$filenameInput + .on 'keyup blur', (e) => + @toggleGitignoreSelector() + + toggleGitignoreSelector: -> + filename = @$filenameInput.val() or $('.editor-file-name').text().trim() + @$wrapper.toggleClass 'hidden', filename isnt '.gitignore' + + onClick: (item, el, e) => + e.preventDefault() + @requestIgnoreFile(item.name) + + requestIgnoreFile: (name) -> + Api.gitignoreText name, @requestIgnoreFileSuccess.bind(@) + + requestIgnoreFileSuccess: (gitignore) -> + @editor.setValue(gitignore.content, 1) + @editor.focus() + +class @BlobGitignoreSelectors + constructor: (opts) -> + { + @$dropdowns = $('.js-gitignore-selector') + @editor + } = opts + + @$dropdowns.each (i, dropdown) => + $dropdown = $(dropdown) + + new BlobGitignoreSelector( + dropdown: $dropdown, + editor: @editor + ) diff --git a/app/assets/javascripts/blob/edit_blob.js.coffee b/app/assets/javascripts/blob/edit_blob.js.coffee index eea9aa972e..79141e768b 100644 --- a/app/assets/javascripts/blob/edit_blob.js.coffee +++ b/app/assets/javascripts/blob/edit_blob.js.coffee @@ -13,6 +13,7 @@ class @EditBlob @initModePanesAndLinks() new BlobLicenseSelector(@editor) + new BlobGitignoreSelectors(editor: @editor) initModePanesAndLinks: -> @$editModePanes = $(".js-edit-mode-pane") diff --git a/app/assets/javascripts/calendar.js.coffee b/app/assets/javascripts/calendar.js.coffee deleted file mode 100644 index d80e0e716c..0000000000 --- a/app/assets/javascripts/calendar.js.coffee +++ /dev/null @@ -1,34 +0,0 @@ -class @Calendar - constructor: (timestamps, starting_year, starting_month, calendar_activities_path) -> - cal = new CalHeatMap() - cal.init - itemName: ["contribution"] - data: timestamps - start: new Date(starting_year, starting_month) - domainLabelFormat: "%b" - id: "cal-heatmap" - domain: "month" - subDomain: "day" - range: 12 - tooltip: true - label: - position: "top" - legend: [ - 0 - 10 - 20 - 30 - ] - legendCellPadding: 3 - cellSize: $('.user-calendar').width() / 73 - onClick: (date, count) -> - formated_date = date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate() - $.ajax - url: calendar_activities_path - data: - date: formated_date - cache: false - dataType: "html" - success: (data) -> - $(".user-calendar-activities").html data - diff --git a/app/assets/javascripts/ci/application.js.coffee b/app/assets/javascripts/ci/application.js.coffee index 05aa0f366b..ca24c1d759 100644 --- a/app/assets/javascripts/ci/application.js.coffee +++ b/app/assets/javascripts/ci/application.js.coffee @@ -1,34 +1,6 @@ -# This is a manifest file that'll be compiled into application.js, which will include all the files -# listed below. -# -# Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, -# or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path. -# -# It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the -# the compiled file. -# -# WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD -# GO AFTER THE REQUIRES BELOW. -# #= require pager #= require jquery_nested_form #= require_tree . -# -$(document).on 'click', '.edit-runner-link', (event) -> - event.preventDefault() - - descr = $(this).closest('.runner-description').first() - descr.addClass('hide') - form = descr.next('.runner-description-form') - descrInput = form.find('input.description') - originalValue = descrInput.val() - form.removeClass('hide') - form.find('.cancel').on 'click', (event) -> - event.preventDefault() - - form.addClass('hide') - descrInput.val(originalValue) - descr.removeClass('hide') $(document).on 'click', '.assign-all-runner', -> $(this).replaceWith(' Assign in progress..') diff --git a/app/assets/javascripts/ci/build.coffee b/app/assets/javascripts/ci/build.coffee index 7afe8bf79e..98d05e4127 100644 --- a/app/assets/javascripts/ci/build.coffee +++ b/app/assets/javascripts/ci/build.coffee @@ -1,9 +1,12 @@ class CiBuild @interval: null + @state: null - constructor: (build_url, build_status) -> + constructor: (build_url, build_status, build_state) -> clearInterval(CiBuild.interval) + @state = build_state + @initScrollButtonAffix() if build_status == "running" || build_status == "pending" @@ -25,15 +28,22 @@ class CiBuild # CiBuild.interval = setInterval => if window.location.href.split("#").first() is build_url + last_state = @state $.ajax - url: build_url + url: build_url + "/trace.json?state=" + encodeURIComponent(@state) dataType: "json" - success: (build) => - if build.status == "running" - $('#build-trace code').html build.trace_html - $('#build-trace code').append '' + success: (log) => + return unless last_state is @state + + if log.state and log.status is "running" + @state = log.state + if log.append + $('.fa-refresh').before log.html + else + $('#build-trace code').html log.html + $('#build-trace code').append '' @checkAutoscroll() - else if build.status != build_status + else if log.status isnt build_status Turbolinks.visit build_url , 4000 diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee index f91aa3c5ad..a3185f8764 100644 --- a/app/assets/javascripts/dispatcher.js.coffee +++ b/app/assets/javascripts/dispatcher.js.coffee @@ -16,7 +16,6 @@ class Dispatcher shortcut_handler = null switch page when 'projects:issues:index' - Issues.init() Issuable.init() shortcut_handler = new ShortcutsNavigation() when 'projects:issues:show' @@ -119,7 +118,7 @@ class Dispatcher new UsersSelect() when 'projects' new NamespaceSelect() - when 'dashboard' + when 'dashboard', 'root' shortcut_handler = new ShortcutsDashboardNavigation() when 'profiles' new Profile() diff --git a/app/assets/javascripts/due_date_select.js.coffee b/app/assets/javascripts/due_date_select.js.coffee index a4304786cb..3cc7018517 100644 --- a/app/assets/javascripts/due_date_select.js.coffee +++ b/app/assets/javascripts/due_date_select.js.coffee @@ -11,6 +11,7 @@ class @DueDateSelect $block = $dropdown.closest('.block') $selectbox = $dropdown.closest('.selectbox') $value = $block.find('.value') + $valueContent = $block.find('.value-content') $sidebarValue = $('.js-due-date-sidebar-value', $block) fieldName = $dropdown.data('field-name') @@ -23,11 +24,15 @@ class @DueDateSelect $value.removeAttr('style') ) - addDueDate = -> + addDueDate = (isDropdown) -> # Create the post date value = $("input[name='#{fieldName}']").val() - date = new Date value.replace(new RegExp('-', 'g'), ',') - mediumDate = $.datepicker.formatDate 'M d, yy', date + + if value isnt '' + date = new Date value.replace(new RegExp('-', 'g'), ',') + mediumDate = $.datepicker.formatDate 'M d, yy', date + else + mediumDate = 'None' data = {} data[abilityName] = {} @@ -39,23 +44,35 @@ class @DueDateSelect data: data beforeSend: -> $loading.fadeIn() - $dropdown.trigger('loading.gl.dropdown') - $selectbox.hide() + if isDropdown + $dropdown.trigger('loading.gl.dropdown') + $selectbox.hide() $value.removeAttr('style') - $value.html(mediumDate) + $valueContent.html(mediumDate) $sidebarValue.html(mediumDate) + + if value isnt '' + $('.js-remove-due-date-holder').removeClass 'hidden' + else + $('.js-remove-due-date-holder').addClass 'hidden' ).done (data) -> - $dropdown.trigger('loaded.gl.dropdown') - $dropdown.dropdown('toggle') + if isDropdown + $dropdown.trigger('loaded.gl.dropdown') + $dropdown.dropdown('toggle') $loading.fadeOut() + $block.on 'click', '.js-remove-due-date', (e) -> + e.preventDefault() + $("input[name='#{fieldName}']").val '' + addDueDate(false) + $datePicker.datepicker( dateFormat: 'yy-mm-dd', defaultDate: $("input[name='#{fieldName}']").val() altField: "input[name='#{fieldName}']" onSelect: -> - addDueDate() + addDueDate(true) ) $(document) diff --git a/app/assets/javascripts/gfm_auto_complete.js.coffee b/app/assets/javascripts/gfm_auto_complete.js.coffee index 61e3f811e7..41dba34210 100644 --- a/app/assets/javascripts/gfm_auto_complete.js.coffee +++ b/app/assets/javascripts/gfm_auto_complete.js.coffee @@ -18,6 +18,10 @@ GitLab.GfmAutoComplete = Issues: template: '

  • ${id} ${title}
  • ' + # Milestones + Milestones: + template: '
  • ${title}
  • ' + # Add GFM auto-completion to all input fields, that accept GFM input. setup: (wrap) -> @input = $('.js-gfm-input') @@ -81,6 +85,19 @@ GitLab.GfmAutoComplete = title: sanitize(i.title) search: "#{i.iid} #{i.title}" + @input.atwho + at: '%' + alias: 'milestones' + searchKey: 'search' + displayTpl: @Milestones.template + insertTpl: '${atwho-at}"${title}"' + callbacks: + beforeSave: (milestones) -> + $.map milestones, (m) -> + id: m.iid + title: sanitize(m.title) + search: "#{m.title}" + @input.atwho at: '!' alias: 'mergerequests' @@ -105,6 +122,8 @@ GitLab.GfmAutoComplete = @input.atwho 'load', '@', data.members # load issues @input.atwho 'load', 'issues', data.issues + # load milestones + @input.atwho 'load', 'milestones', data.milestones # load merge requests @input.atwho 'load', 'mergerequests', data.mergerequests # load emojis diff --git a/app/assets/javascripts/gl_dropdown.js.coffee b/app/assets/javascripts/gl_dropdown.js.coffee index 1d1bfeb2e7..b3f1dc969b 100644 --- a/app/assets/javascripts/gl_dropdown.js.coffee +++ b/app/assets/javascripts/gl_dropdown.js.coffee @@ -60,9 +60,36 @@ class GitLabDropdownFilter results = data if search_text isnt '' - results = fuzzaldrinPlus.filter(data, search_text, - key: @options.keys - ) + # When data is an array of objects therefore [object Array] e.g. + # [ + # { prop: 'foo' }, + # { prop: 'baz' } + # ] + if _.isArray(data) + results = fuzzaldrinPlus.filter(data, search_text, + key: @options.keys + ) + else + # If data is grouped therefore an [object Object]. e.g. + # { + # groupName1: [ + # { prop: 'foo' }, + # { prop: 'baz' } + # ], + # groupName2: [ + # { prop: 'abc' }, + # { prop: 'def' } + # ] + # } + if gl.utils.isObject data + results = {} + for key, group of data + tmp = fuzzaldrinPlus.filter(group, search_text, + key: @options.keys + ) + + if tmp.length + results[key] = tmp.map (item) -> item @options.callback results else @@ -141,8 +168,9 @@ class GitLabDropdown searchFields = if @options.search then @options.search.fields else []; if @options.data - # If data is an array - if _.isArray @options.data + # If we provided data + # data could be an array of objects or a group of arrays + if _.isObject(@options.data) and not _.isFunction(@options.data) @fullData = @options.data @parseData @options.data else @@ -230,19 +258,33 @@ class GitLabDropdown parseData: (data) -> @renderedData = data - # Render each row - html = $.map data, (obj) => - return @renderItem(obj) - if @options.filterable and data.length is 0 # render no matching results html = [@noResults()] + else + # Handle array groups + if gl.utils.isObject data + html = [] + for name, groupData of data + # Add header for each group + html.push(@renderItem(header: name, name)) + + @renderData(groupData, name) + .map (item) -> + html.push item + else + # Render each row + html = @renderData(data) # Render the full menu full_html = @renderMenu(html.join("")) @appendMenu(full_html) + renderData: (data, group = false) -> + data.map (obj, index) => + return @renderItem(obj, group, index) + shouldPropagate: (e) => if @options.multiSelect $target = $(e.target) @@ -299,11 +341,10 @@ class GitLabDropdown selector = '.dropdown-content' if @dropdown.find(".dropdown-toggle-page").length selector = ".dropdown-page-one .dropdown-content" - $(selector, @dropdown).html html # Render the row - renderItem: (data) -> + renderItem: (data, group = false, index = false) -> html = "" # Divider @@ -346,8 +387,13 @@ class GitLabDropdown if @highlight text = @highlightTextMatches(text, @filterInput.val()) + if group + groupAttrs = "data-group='#{group}' data-index='#{index}'" + else + groupAttrs = '' + html = "
  • - + #{text}
  • " @@ -377,9 +423,15 @@ class GitLabDropdown rowClicked: (el) -> fieldName = @options.fieldName - selectedIndex = el.parent().index() if @renderedData - selectedObject = @renderedData[selectedIndex] + groupName = el.data('group') + if groupName + selectedIndex = el.data('index') + selectedObject = @renderedData[groupName][selectedIndex] + else + selectedIndex = el.closest('li').index() + selectedObject = @renderedData[selectedIndex] + value = if @options.id then @options.id(selectedObject, el) else selectedObject.id field = @dropdown.parent().find("input[name='#{fieldName}'][value='#{value}']") if el.hasClass(ACTIVE_CLASS) @@ -460,7 +512,7 @@ class GitLabDropdown return false if currentKeyCode is 13 - @selectRowAtIndex currentIndex + @selectRowAtIndex if currentIndex < 0 then 0 else currentIndex removeArrayKeyEvent: -> $('body').off 'keydown' diff --git a/app/assets/javascripts/graphs/application.js.coffee b/app/assets/javascripts/graphs/application.js.coffee new file mode 100644 index 0000000000..e0f681acf0 --- /dev/null +++ b/app/assets/javascripts/graphs/application.js.coffee @@ -0,0 +1,7 @@ +# This is a manifest file that'll be compiled into including all the files listed below. +# Add new JavaScript/Coffee code in separate files in this directory and they'll automatically +# be included in the compiled file accessible from http://example.com/assets/application.js +# It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +# the compiled file. +# +#= require_tree . diff --git a/app/assets/javascripts/stat_graph.js.coffee b/app/assets/javascripts/graphs/stat_graph.js.coffee similarity index 100% rename from app/assets/javascripts/stat_graph.js.coffee rename to app/assets/javascripts/graphs/stat_graph.js.coffee diff --git a/app/assets/javascripts/stat_graph_contributors.js.coffee b/app/assets/javascripts/graphs/stat_graph_contributors.js.coffee similarity index 98% rename from app/assets/javascripts/stat_graph_contributors.js.coffee rename to app/assets/javascripts/graphs/stat_graph_contributors.js.coffee index 3be14cb43d..1d9fae7cf7 100644 --- a/app/assets/javascripts/stat_graph_contributors.js.coffee +++ b/app/assets/javascripts/graphs/stat_graph_contributors.js.coffee @@ -1,5 +1,4 @@ #= require d3 -#= require stat_graph_contributors_util class @ContributorsStatGraph init: (log) -> diff --git a/app/assets/javascripts/stat_graph_contributors_graph.js.coffee b/app/assets/javascripts/graphs/stat_graph_contributors_graph.js.coffee similarity index 99% rename from app/assets/javascripts/stat_graph_contributors_graph.js.coffee rename to app/assets/javascripts/graphs/stat_graph_contributors_graph.js.coffee index b7a0e07376..584d281a51 100644 --- a/app/assets/javascripts/stat_graph_contributors_graph.js.coffee +++ b/app/assets/javascripts/graphs/stat_graph_contributors_graph.js.coffee @@ -1,6 +1,4 @@ #= require d3 -#= require jquery -#= require underscore class @ContributorsGraph MARGIN: diff --git a/app/assets/javascripts/stat_graph_contributors_util.js.coffee b/app/assets/javascripts/graphs/stat_graph_contributors_util.js.coffee similarity index 100% rename from app/assets/javascripts/stat_graph_contributors_util.js.coffee rename to app/assets/javascripts/graphs/stat_graph_contributors_util.js.coffee diff --git a/app/assets/javascripts/issuable.js.coffee b/app/assets/javascripts/issuable.js.coffee index afffed63ac..6504e48110 100644 --- a/app/assets/javascripts/issuable.js.coffee +++ b/app/assets/javascripts/issuable.js.coffee @@ -1,7 +1,11 @@ +issuable_created = false @Issuable = init: -> - Issuable.initTemplates() - Issuable.initSearch() + unless issuable_created + issuable_created = true + Issuable.initTemplates() + Issuable.initSearch() + Issuable.initChecks() initTemplates: -> Issuable.labelRow = _.template( @@ -19,7 +23,16 @@ .on 'keyup', -> clearTimeout(@timer) @timer = setTimeout( -> - Issuable.filterResults $('#issue_search_form') + $search = $('#issue_search') + $form = $('.js-filter-form') + $input = $("input[name='#{$search.attr('name')}']", $form) + + if $input.length is 0 + $form.append "" + else + $input.val $search.val() + + Issuable.filterResults $form , 500) toggleLabelFilters: -> @@ -59,15 +72,22 @@ dataType: "json" reload: -> - if Issues.created - Issues.initChecks() + if Issuable.created + Issuable.initChecks() $('#filter_issue_search').val($('#issue_search').val()) + initChecks: -> + $('.check_all_issues').on 'click', -> + $('.selected_issue').prop('checked', @checked) + Issuable.checkChanged() + + $('.selected_issue').on 'change', Issuable.checkChanged + updateStateFilters: -> - stateFilters = $('.issues-state-filters') + stateFilters = $('.issues-state-filters, .dropdown-menu-sort') newParams = {} - paramKeys = ['author_id', 'milestone_title', 'assignee_id', 'issue_search'] + paramKeys = ['author_id', 'milestone_title', 'assignee_id', 'issue_search', 'issue_search'] for paramKey in paramKeys newParams[paramKey] = gl.utils.getParameterValues(paramKey)[0] or '' @@ -82,3 +102,17 @@ else newUrl = gl.utils.mergeUrlParams(newParams, initialUrl) $(this).attr 'href', newUrl + + checkChanged: -> + checked_issues = $('.selected_issue:checked') + if checked_issues.length > 0 + ids = $.map checked_issues, (value) -> + $(value).data('id') + + $('#update_issues_ids').val ids + $('.issues-other-filters').hide() + $('.issues_bulk_update').show() + else + $('#update_issues_ids').val [] + $('.issues_bulk_update').hide() + $('.issues-other-filters').show() diff --git a/app/assets/javascripts/issuable_form.js.coffee b/app/assets/javascripts/issuable_form.js.coffee index 7a788f761b..898506fde3 100644 --- a/app/assets/javascripts/issuable_form.js.coffee +++ b/app/assets/javascripts/issuable_form.js.coffee @@ -19,6 +19,16 @@ class @IssuableForm @form.on "click", ".btn-cancel", @resetAutosave @initWip() + @initMoveDropdown() + + $issuableDueDate = $('#issuable-due-date') + + if $issuableDueDate.length + $('.datepicker').datepicker( + dateFormat: 'yy-mm-dd', + onSelect: (dateText, inst) -> + $issuableDueDate.val dateText + ).datepicker 'setDate', $.datepicker.parseDate('yy-mm-dd', $issuableDueDate.val()) initAutosave: -> new Autosave @titleField, [ @@ -80,3 +90,19 @@ class @IssuableForm addWip: -> @titleField.val "WIP: #{@titleField.val()}" + + initMoveDropdown: -> + $moveDropdown = $('.js-move-dropdown') + + if $moveDropdown.length + $('.js-move-dropdown').select2 + ajax: + url: $moveDropdown.data('projects-url') + results: (data) -> + return { + results: data + } + formatResult: (project) -> + project.name_with_namespace + formatSelection: (project) -> + project.name_with_namespace diff --git a/app/assets/javascripts/issues.js.coffee b/app/assets/javascripts/issues.js.coffee deleted file mode 100644 index 3330e6c68a..0000000000 --- a/app/assets/javascripts/issues.js.coffee +++ /dev/null @@ -1,38 +0,0 @@ -@Issues = - init: -> - Issues.created = true - Issues.initChecks() - - $("body").on "ajax:success", ".close_issue, .reopen_issue", -> - t = $(this) - totalIssues = undefined - reopen = t.hasClass("reopen_issue") - $(".issue_counter").each -> - issue = $(this) - totalIssues = parseInt($(this).html(), 10) - if reopen and issue.closest(".main_menu").length - $(this).html totalIssues + 1 - else - $(this).html totalIssues - 1 - - initChecks: -> - $(".check_all_issues").click -> - $(".selected_issue").prop("checked", @checked) - Issues.checkChanged() - - $(".selected_issue").bind "change", Issues.checkChanged - - checkChanged: -> - checked_issues = $(".selected_issue:checked") - if checked_issues.length > 0 - ids = [] - $.each checked_issues, (index, value) -> - ids.push $(value).attr("data-id") - - $("#update_issues_ids").val ids - $(".issues-other-filters").hide() - $(".issues_bulk_update").show() - else - $("#update_issues_ids").val [] - $(".issues_bulk_update").hide() - $(".issues-other-filters").show() diff --git a/app/assets/javascripts/layout_nav.js.coffee b/app/assets/javascripts/layout_nav.js.coffee new file mode 100644 index 0000000000..6adac6dac9 --- /dev/null +++ b/app/assets/javascripts/layout_nav.js.coffee @@ -0,0 +1,14 @@ +class @LayoutNav + $ -> + $('.fade-left').addClass('end-scroll') + $('.scrolling-tabs').on 'scroll', (event) -> + $this = $(this) + $el = $(event.target) + currentPosition = $this.scrollLeft() + size = bp.getBreakpointSize() + controlBtnWidth = $('.controls').width() + maxPosition = $this.get(0).scrollWidth - $this.parent().width() + maxPosition += controlBtnWidth if size isnt 'xs' and $('.nav-control').length + + $el.find('.fade-left').toggleClass('end-scroll', currentPosition is 0) + $el.find('.fade-right').toggleClass('end-scroll', currentPosition is maxPosition) diff --git a/app/assets/javascripts/lib/type_utility.js.coffee b/app/assets/javascripts/lib/type_utility.js.coffee new file mode 100644 index 0000000000..957f0d86b3 --- /dev/null +++ b/app/assets/javascripts/lib/type_utility.js.coffee @@ -0,0 +1,9 @@ +((w) -> + + w.gl ?= {} + w.gl.utils ?= {} + + w.gl.utils.isObject = (obj) -> + obj? and (obj.constructor is Object) + +) window diff --git a/app/assets/javascripts/lib/url_utility.js.coffee b/app/assets/javascripts/lib/url_utility.js.coffee index 6a00932c02..e8085e1c2e 100644 --- a/app/assets/javascripts/lib/url_utility.js.coffee +++ b/app/assets/javascripts/lib/url_utility.js.coffee @@ -26,10 +26,19 @@ newUrl = decodeURIComponent(url) for paramName, paramValue of params pattern = new RegExp "\\b(#{paramName}=).*?(&|$)" - if url.search(pattern) >= 0 + if not paramValue? + newUrl = newUrl.replace pattern, '' + else if url.search(pattern) isnt -1 newUrl = newUrl.replace pattern, "$1#{paramValue}$2" else newUrl = "#{newUrl}#{(if newUrl.indexOf('?') > 0 then '&' else '?')}#{paramName}=#{paramValue}" + + # Remove a trailing ampersand + lastChar = newUrl[newUrl.length - 1] + + if lastChar is '&' + newUrl = newUrl.slice 0, -1 + newUrl # removes parameter query string from url. returns the modified url diff --git a/app/assets/javascripts/merge_request_tabs.js.coffee b/app/assets/javascripts/merge_request_tabs.js.coffee index 372732d0aa..49a4727205 100644 --- a/app/assets/javascripts/merge_request_tabs.js.coffee +++ b/app/assets/javascripts/merge_request_tabs.js.coffee @@ -75,6 +75,9 @@ class @MergeRequestTabs @loadDiff($target.attr('href')) if bp? and bp.getBreakpointSize() isnt 'lg' @shrinkView() + + navBarHeight = $('.navbar-gitlab').outerHeight() + $.scrollTo(".merge-request-details .merge-request-tabs", offset: -navBarHeight) else if action == 'builds' @loadBuilds($target.attr('href')) @expandView() diff --git a/app/assets/javascripts/merge_request_widget.js.coffee b/app/assets/javascripts/merge_request_widget.js.coffee index f58647988a..779f536d9f 100644 --- a/app/assets/javascripts/merge_request_widget.js.coffee +++ b/app/assets/javascripts/merge_request_widget.js.coffee @@ -10,6 +10,7 @@ class @MergeRequestWidget $('#modal_merge_info').modal(show: false) @firstCICheck = true @readyForCICheck = false + @cancel = false clearInterval @fetchBuildStatusInterval @clearEventListeners() @@ -21,10 +22,16 @@ class @MergeRequestWidget clearEventListeners: -> $(document).off 'page:change.merge_request' + cancelPolling: -> + @cancel = true + addEventListeners: -> + allowedPages = ['show', 'commits', 'builds', 'changes'] $(document).on 'page:change.merge_request', => - if $('body').data('page') isnt 'projects:merge_requests:show' + page = $('body').data('page').split(':').last() + if allowedPages.indexOf(page) < 0 clearInterval @fetchBuildStatusInterval + @cancelPolling() @clearEventListeners() mergeInProgress: (deleteSourceBranch = false)-> @@ -67,6 +74,7 @@ class @MergeRequestWidget $('.ci-widget-fetching').show() $.getJSON @opts.ci_status_url, (data) => + return if @cancel @readyForCICheck = true if data.status is '' @@ -106,6 +114,7 @@ class @MergeRequestWidget @firstCICheck = false showCIStatus: (state) -> + return if not state? $('.ci_widget').hide() allowed_states = ["failed", "canceled", "running", "pending", "success", "skipped", "not_found"] if state in allowed_states @@ -113,7 +122,7 @@ class @MergeRequestWidget switch state when "failed", "canceled", "not_found" @setMergeButtonClass('btn-danger') - when "running", "pending" + when "running" @setMergeButtonClass('btn-warning') when "success" @setMergeButtonClass('btn-create') @@ -126,6 +135,6 @@ class @MergeRequestWidget $('.ci_widget:visible .ci-coverage').text(text) setMergeButtonClass: (css_class) -> - $('.accept_merge_request') + $('.js-merge-button,.accept-action .dropdown-toggle') .removeClass('btn-danger btn-warning btn-create') .addClass(css_class) diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee index efb3e8e219..f8151963fa 100644 --- a/app/assets/javascripts/notes.js.coffee +++ b/app/assets/javascripts/notes.js.coffee @@ -114,9 +114,9 @@ class @Notes @refresh() , @pollingInterval - refresh: -> + refresh: => return if @refreshing is true - refreshing = true + @refreshing = true if not document.hidden and document.URL.indexOf(@noteable_url) is 0 @getContent() @@ -134,8 +134,8 @@ class @Notes @renderDiscussionNote(note) else @renderNote(note) - always: => - @refreshing = false + .always () => + @refreshing = false ### Increase @pollingInterval up to 120 seconds on every function call, @@ -285,6 +285,7 @@ class @Notes form.addClass "js-main-target-form" form.find("#note_line_code").remove() + form.find("#note_type").remove() ### General note form setup. @@ -328,7 +329,7 @@ class @Notes @renderDiscussionNote(note) # cleanup after successfully creating a diff/discussion note - @removeDiscussionNoteForm($("#new-discussion-note-form-#{note.discussion_id}")) + @removeDiscussionNoteForm($(xhr.target)) ### Called in response to the edit note form being submitted @@ -472,6 +473,7 @@ class @Notes setupDiscussionNoteForm: (dataHolder, form) => # setup note target form.attr 'id', "new-discussion-note-form-#{dataHolder.data("discussionId")}" + form.find("#note_type").val dataHolder.data("noteType") form.find("#line_type").val dataHolder.data("lineType") form.find("#note_commit_id").val dataHolder.data("commitId") form.find("#note_line_code").val dataHolder.data("lineCode") diff --git a/app/assets/javascripts/right_sidebar.js.coffee b/app/assets/javascripts/right_sidebar.js.coffee index 2d084b76cf..c9cb0f4bb3 100644 --- a/app/assets/javascripts/right_sidebar.js.coffee +++ b/app/assets/javascripts/right_sidebar.js.coffee @@ -10,6 +10,40 @@ class @Sidebar $('.dropdown').on('loading.gl.dropdown', @sidebarDropdownLoading) $('.dropdown').on('loaded.gl.dropdown', @sidebarDropdownLoaded) + + $(document) + .off 'click', '.js-sidebar-toggle' + .on 'click', '.js-sidebar-toggle', (e, triggered) -> + e.preventDefault() + $this = $(this) + $thisIcon = $this.find 'i' + $allGutterToggleIcons = $('.js-sidebar-toggle i') + if $thisIcon.hasClass('fa-angle-double-right') + $allGutterToggleIcons + .removeClass('fa-angle-double-right') + .addClass('fa-angle-double-left') + $('aside.right-sidebar') + .removeClass('right-sidebar-expanded') + .addClass('right-sidebar-collapsed') + $('.page-with-sidebar') + .removeClass('right-sidebar-expanded') + .addClass('right-sidebar-collapsed') + else + $allGutterToggleIcons + .removeClass('fa-angle-double-left') + .addClass('fa-angle-double-right') + $('aside.right-sidebar') + .removeClass('right-sidebar-collapsed') + .addClass('right-sidebar-expanded') + $('.page-with-sidebar') + .removeClass('right-sidebar-collapsed') + .addClass('right-sidebar-expanded') + if not triggered + $.cookie("collapsed_gutter", + $('.right-sidebar') + .hasClass('right-sidebar-collapsed'), { path: '/' }) + + sidebarDropdownLoading: (e) -> $sidebarCollapsedIcon = $(@).closest('.block').find('.sidebar-collapsed-icon') img = $sidebarCollapsedIcon.find('img') @@ -76,7 +110,7 @@ class @Sidebar @triggerOpenSidebar() if not @isOpen() if action is 'hide' - @triggerOpenSidebar() is @isOpen() + @triggerOpenSidebar() if @isOpen() isOpen: -> @sidebar.is('.right-sidebar-expanded') diff --git a/app/assets/javascripts/search_autocomplete.js.coffee b/app/assets/javascripts/search_autocomplete.js.coffee index 6a7b4ad1db..2122e80f57 100644 --- a/app/assets/javascripts/search_autocomplete.js.coffee +++ b/app/assets/javascripts/search_autocomplete.js.coffee @@ -20,8 +20,7 @@ class @SearchAutocomplete @dropdown = @wrap.find('.dropdown') @dropdownContent = @dropdown.find('.dropdown-content') - @locationBadgeEl = @getElement('.search-location-badge') - @locationText = @getElement('.location-text') + @locationBadgeEl = @getElement('.location-badge') @scopeInputEl = @getElement('#scope') @searchInput = @getElement('.search-input') @projectInputEl = @getElement('#search_project_id') @@ -133,7 +132,7 @@ class @SearchAutocomplete scope: @scopeInputEl.val() # Location badge - _location: @locationText.text() + _location: @locationBadgeEl.text() } bindEvents: -> @@ -143,12 +142,14 @@ class @SearchAutocomplete @searchInput.on 'click', @onSearchInputClick @searchInput.on 'focus', @onSearchInputFocus @clearInput.on 'click', @onClearInputClick + @locationBadgeEl.on 'click', => + @searchInput.focus() onDocumentClick: (e) => # If clicking outside the search box # And search input is not focused # And we are not clicking inside a suggestion - if not $.contains(@dropdown[0], e.target) and @isFocused and not $(e.target).parents('ul').length + if not $.contains(@dropdown[0], e.target) and @isFocused and not $(e.target).closest('.search-form').length @onSearchInputBlur() enableAutocomplete: -> @@ -221,10 +222,8 @@ class @SearchAutocomplete category = if item.category? then "#{item.category}: " else '' value = if item.value? then item.value else '' - html = " - #{category}#{value} - " - @locationBadgeEl.html(html) + badgeText = "#{category}#{value}" + @locationBadgeEl.text(badgeText).show() @wrap.addClass('has-location-badge') restoreOriginalState: -> @@ -233,9 +232,8 @@ class @SearchAutocomplete for input in inputs @getElement("##{input}").val(@originalState[input]) - if @originalState._location is '' - @locationBadgeEl.empty() + @locationBadgeEl.hide() else @addLocationBadge( value: @originalState._location @@ -244,7 +242,7 @@ class @SearchAutocomplete @dropdown.removeClass 'open' badgePresent: -> - @locationBadgeEl.children().length + @locationBadgeEl.length resetSearchState: -> inputs = Object.keys @originalState @@ -257,7 +255,7 @@ class @SearchAutocomplete @getElement("##{input}").val('') removeLocationBadge: -> - @locationBadgeEl.empty() + @locationBadgeEl.hide() # Reset state @resetSearchState() diff --git a/app/assets/javascripts/shortcuts_dashboard_navigation.js.coffee b/app/assets/javascripts/shortcuts_dashboard_navigation.js.coffee index 4a05bdccdb..cca2b8a1fc 100644 --- a/app/assets/javascripts/shortcuts_dashboard_navigation.js.coffee +++ b/app/assets/javascripts/shortcuts_dashboard_navigation.js.coffee @@ -3,10 +3,10 @@ class @ShortcutsDashboardNavigation extends Shortcuts constructor: -> super() - Mousetrap.bind('g a', -> ShortcutsDashboardNavigation.findAndFollowLink('.shortcuts-activity')) - Mousetrap.bind('g i', -> ShortcutsDashboardNavigation.findAndFollowLink('.shortcuts-issues')) - Mousetrap.bind('g m', -> ShortcutsDashboardNavigation.findAndFollowLink('.shortcuts-merge_requests')) - Mousetrap.bind('g p', -> ShortcutsDashboardNavigation.findAndFollowLink('.shortcuts-projects')) + Mousetrap.bind('g a', -> ShortcutsDashboardNavigation.findAndFollowLink('.dashboard-shortcuts-activity')) + Mousetrap.bind('g i', -> ShortcutsDashboardNavigation.findAndFollowLink('.dashboard-shortcuts-issues')) + Mousetrap.bind('g m', -> ShortcutsDashboardNavigation.findAndFollowLink('.dashboard-shortcuts-merge_requests')) + Mousetrap.bind('g p', -> ShortcutsDashboardNavigation.findAndFollowLink('.dashboard-shortcuts-projects')) @findAndFollowLink: (selector) -> link = $(selector).attr('href') diff --git a/app/assets/javascripts/shortcuts_issuable.coffee b/app/assets/javascripts/shortcuts_issuable.coffee index ad9b3c1c6b..ccb42ab216 100644 --- a/app/assets/javascripts/shortcuts_issuable.coffee +++ b/app/assets/javascripts/shortcuts_issuable.coffee @@ -6,6 +6,10 @@ class @ShortcutsIssuable extends ShortcutsNavigation super() Mousetrap.bind('a', @openSidebarDropdown.bind(@, 'assignee')) Mousetrap.bind('m', @openSidebarDropdown.bind(@, 'milestone')) + Mousetrap.bind('r', => + @replyWithSelectedText() + return false + ) Mousetrap.bind('j', => @prevIssue() return false diff --git a/app/assets/javascripts/sidebar.js.coffee b/app/assets/javascripts/sidebar.js.coffee index 860d4f438d..ea4ac52da3 100644 --- a/app/assets/javascripts/sidebar.js.coffee +++ b/app/assets/javascripts/sidebar.js.coffee @@ -12,7 +12,7 @@ toggleSidebar = -> niceScrollBars.updateScrollBar(); ), 300 -$(document).on("click", '.toggle-nav-collapse', (e) -> +$(document).on("click", '.toggle-nav-collapse, .side-nav-toggle', (e) -> e.preventDefault() toggleSidebar() diff --git a/app/assets/javascripts/user_tabs.js.coffee b/app/assets/javascripts/user_tabs.js.coffee index c2aeffe238..70614396a4 100644 --- a/app/assets/javascripts/user_tabs.js.coffee +++ b/app/assets/javascripts/user_tabs.js.coffee @@ -26,6 +26,10 @@ # Personal projects # # +#
  • +# +# +#
  • # # #
    @@ -41,6 +45,9 @@ #
    # Projects content #
    +#
    +# Snippets content +#
    #
    # #
    @@ -100,7 +107,7 @@ class @UserTabs if action is 'activity' @loadActivities(source) - if action in ['groups', 'contributed', 'projects'] + if action in ['groups', 'contributed', 'projects', 'snippets'] @loadTab(source, action) loadTab: (source, action) -> diff --git a/app/assets/javascripts/users/application.js.coffee b/app/assets/javascripts/users/application.js.coffee new file mode 100644 index 0000000000..647ffbf5f4 --- /dev/null +++ b/app/assets/javascripts/users/application.js.coffee @@ -0,0 +1,8 @@ +# This is a manifest file that'll be compiled into including all the files listed below. +# Add new JavaScript/Coffee code in separate files in this directory and they'll automatically +# be included in the compiled file accessible from http://example.com/assets/application.js +# It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +# the compiled file. +# +#= require d3 +#= require_tree . diff --git a/app/assets/javascripts/users/calendar.js.coffee b/app/assets/javascripts/users/calendar.js.coffee new file mode 100644 index 0000000000..26a2606153 --- /dev/null +++ b/app/assets/javascripts/users/calendar.js.coffee @@ -0,0 +1,198 @@ +class @Calendar + constructor: (timestamps, @calendar_activities_path) -> + @currentSelectedDate = '' + @daySpace = 1 + @daySize = 15 + @daySizeWithSpace = @daySize + (@daySpace * 2) + @monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] + @months = [] + @highestValue = 0 + + # Get the highest value from the timestampes + _.each timestamps, (count) => + if count > @highestValue + @highestValue = count + + # Loop through the timestamps to create a group of objects + # The group of objects will be grouped based on the day of the week they are + @timestampsTmp = [] + i = 0 + group = 0 + _.each timestamps, (count, date) => + newDate = new Date parseInt(date) * 1000 + day = newDate.getDay() + + # Create a new group array if this is the first day of the week + # or if is first object + if (day is 0 and i isnt 0) or i is 0 + @timestampsTmp.push [] + group++ + + innerArray = @timestampsTmp[group-1] + + # Push to the inner array the values that will be used to render map + innerArray.push + count: count + date: newDate + day: day + + i++ + + # Init color functions + @color = @initColor() + @colorKey = @initColorKey() + + # Init the svg element + @renderSvg(group) + @renderDays() + @renderMonths() + @renderDayTitles() + @renderKey() + + @initTooltips() + + renderSvg: (group) -> + @svg = d3.select '.js-contrib-calendar' + .append 'svg' + .attr 'width', (group + 1) * @daySizeWithSpace + .attr 'height', 167 + .attr 'class', 'contrib-calendar' + + renderDays: -> + @svg.selectAll 'g' + .data @timestampsTmp + .enter() + .append 'g' + .attr 'transform', (group, i) => + _.each group, (stamp, a) => + if a is 0 and stamp.day is 0 + month = stamp.date.getMonth() + x = (@daySizeWithSpace * i + 1) + @daySizeWithSpace + lastMonth = _.last(@months) + if lastMonth? + lastMonthX = lastMonth.x + + if !lastMonth? + @months.push + month: month + x: x + else if month isnt lastMonth.month and x - @daySizeWithSpace isnt lastMonthX + @months.push + month: month + x: x + + "translate(#{(@daySizeWithSpace * i + 1) + @daySizeWithSpace}, 18)" + .selectAll 'rect' + .data (stamp) -> + stamp + .enter() + .append 'rect' + .attr 'x', '0' + .attr 'y', (stamp, i) => + (@daySizeWithSpace * stamp.day) + .attr 'width', @daySize + .attr 'height', @daySize + .attr 'title', (stamp) => + contribText = 'No contributions' + + if stamp.count > 0 + contribText = "#{stamp.count} contribution#{if stamp.count > 1 then 's' else ''}" + + date = dateFormat(stamp.date, 'mmm d, yyyy') + + "#{contribText}
    #{date}" + .attr 'class', 'user-contrib-cell js-tooltip' + .attr 'fill', (stamp) => + if stamp.count isnt 0 + @color(stamp.count) + else + '#ededed' + .attr 'data-container', 'body' + .on 'click', @clickDay + + renderDayTitles: -> + days = [{ + text: 'M' + y: 29 + (@daySizeWithSpace * 1) + }, { + text: 'W' + y: 29 + (@daySizeWithSpace * 3) + }, { + text: 'F' + y: 29 + (@daySizeWithSpace * 5) + }] + @svg.append 'g' + .selectAll 'text' + .data days + .enter() + .append 'text' + .attr 'text-anchor', 'middle' + .attr 'x', 8 + .attr 'y', (day) -> + day.y + .text (day) -> + day.text + .attr 'class', 'user-contrib-text' + + renderMonths: -> + @svg.append 'g' + .selectAll 'text' + .data @months + .enter() + .append 'text' + .attr 'x', (date) -> + date.x + .attr 'y', 10 + .attr 'class', 'user-contrib-text' + .text (date) => + @monthNames[date.month] + + renderKey: -> + keyColors = ['#ededed', @colorKey(0), @colorKey(1), @colorKey(2), @colorKey(3)] + @svg.append 'g' + .attr 'transform', "translate(18, #{@daySizeWithSpace * 8 + 16})" + .selectAll 'rect' + .data keyColors + .enter() + .append 'rect' + .attr 'width', @daySize + .attr 'height', @daySize + .attr 'x', (color, i) => + @daySizeWithSpace * i + .attr 'y', 0 + .attr 'fill', (color) -> + color + + initColor: -> + d3.scale + .linear() + .range(['#acd5f2', '#254e77']) + .domain([0, @highestValue]) + + initColorKey: -> + d3.scale + .linear() + .range(['#acd5f2', '#254e77']) + .domain([0, 3]) + + clickDay: (stamp) => + if @currentSelectedDate isnt stamp.date + @currentSelectedDate = stamp.date + formatted_date = @currentSelectedDate.getFullYear() + "-" + (@currentSelectedDate.getMonth()+1) + "-" + @currentSelectedDate.getDate() + + $.ajax + url: @calendar_activities_path + data: + date: formatted_date + cache: false + dataType: 'html' + beforeSend: -> + $('.user-calendar-activities').html '
    ' + success: (data) -> + $('.user-calendar-activities').html data + else + $('.user-calendar-activities').html '' + + initTooltips: -> + $('.js-contrib-calendar .js-tooltip').tooltip + html: true diff --git a/app/assets/javascripts/users_select.js.coffee b/app/assets/javascripts/users_select.js.coffee index b80b1b861c..519618aa61 100644 --- a/app/assets/javascripts/users_select.js.coffee +++ b/app/assets/javascripts/users_select.js.coffee @@ -93,7 +93,9 @@ class @UsersSelect $dropdown.glDropdown( data: (term, callback) => - @users term, (users) => + isAuthorFilter = $('.js-author-search') + + @users term, term is '' and isAuthorFilter, (users) => if term.length is 0 showDivider = 0 @@ -138,7 +140,7 @@ class @UsersSelect toggleLabel: (selected) -> if selected && 'id' of selected - selected.name + if selected.text then selected.text else selected.name else defaultLabel @@ -219,7 +221,7 @@ class @UsersSelect multiple: $(select).hasClass('multiselect') minimumInputLength: 0 query: (query) => - @users query.term, (users) => + @users query.term, @projectId?, (users) => data = { results: users } if query.term.length == 0 @@ -302,7 +304,7 @@ class @UsersSelect # Return users list. Filtered by query # Only active users retrieved - users: (query, callback) => + users: (query, fromProject, callback) => url = @buildUrl(@usersPath) $.ajax( @@ -311,7 +313,7 @@ class @UsersSelect search: query per_page: 20 active: true - project_id: @projectId + project_id: @projectId if fromProject group_id: @groupId current_user: @showCurrentUser author_id: @authorId diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 69b3b6586d..8b93665d08 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -8,9 +8,7 @@ *= require select2 *= require_self *= require dropzone/basic - *= require cal-heatmap *= require cropper.css - *= require animate */ /* diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss index 560de9fc0b..3cbddc59f1 100644 --- a/app/assets/stylesheets/framework.scss +++ b/app/assets/stylesheets/framework.scss @@ -5,6 +5,7 @@ @import 'framework/tw_bootstrap'; @import "framework/layout"; +@import "framework/animations.scss"; @import "framework/avatar.scss"; @import "framework/blocks.scss"; @import "framework/buttons.scss"; diff --git a/app/assets/stylesheets/framework/animations.scss b/app/assets/stylesheets/framework/animations.scss new file mode 100644 index 0000000000..1fec61bdba --- /dev/null +++ b/app/assets/stylesheets/framework/animations.scss @@ -0,0 +1,72 @@ +// This file is based off animate.css 3.5.1, available here: +// https://github.com/daneden/animate.css/blob/3.5.1/animate.css +// +// animate.css - http://daneden.me/animate +// Version - 3.5.1 +// Licensed under the MIT license - http://opensource.org/licenses/MIT +// +// Copyright (c) 2016 Daniel Eden + +.animated { + -webkit-animation-duration: 1s; + animation-duration: 1s; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; +} + +.animated.infinite { + -webkit-animation-iteration-count: infinite; + animation-iteration-count: infinite; +} + +.animated.hinge { + -webkit-animation-duration: 2s; + animation-duration: 2s; +} + +.animated.flipOutX, +.animated.flipOutY, +.animated.bounceIn, +.animated.bounceOut { + -webkit-animation-duration: .75s; + animation-duration: .75s; +} + +@-webkit-keyframes pulse { + from { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + + 50% { + -webkit-transform: scale3d(1.05, 1.05, 1.05); + transform: scale3d(1.05, 1.05, 1.05); + } + + to { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +@keyframes pulse { + from { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + + 50% { + -webkit-transform: scale3d(1.05, 1.05, 1.05); + transform: scale3d(1.05, 1.05, 1.05); + } + + to { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +.pulse { + -webkit-animation-name: pulse; + animation-name: pulse; +} diff --git a/app/assets/stylesheets/framework/avatar.scss b/app/assets/stylesheets/framework/avatar.scss index f5ce70b606..bb8d71fbae 100644 --- a/app/assets/stylesheets/framework/avatar.scss +++ b/app/assets/stylesheets/framework/avatar.scss @@ -45,6 +45,7 @@ &.s32 { font-size: 20px; line-height: 32px; } &.s40 { font-size: 16px; line-height: 40px; } &.s60 { font-size: 32px; line-height: 60px; } + &.s70 { font-size: 34px; line-height: 70px; } &.s90 { font-size: 36px; line-height: 90px; } &.s110 { font-size: 40px; line-height: 112px; font-weight: 300; } &.s140 { font-size: 72px; line-height: 140px; } diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss index 434a26d57c..6981f834d3 100644 --- a/app/assets/stylesheets/framework/blocks.scss +++ b/app/assets/stylesheets/framework/blocks.scss @@ -24,8 +24,8 @@ background-color: $background-color; padding: $gl-padding; margin-bottom: 0; - border-top: 1px solid $border-color; - border-bottom: 1px solid $border-color; + border-top: 1px solid $white-dark; + border-bottom: 1px solid $white-dark; color: $gl-gray; &.oneline-block { @@ -110,9 +110,9 @@ .cover-title { color: $gl-header-color; margin: 0; - font-size: 23px; + font-size: 24px; font-weight: normal; - margin: 16px 0 5px; + margin-bottom: 5px; color: #4c4e54; font-size: 23px; line-height: 1.1; @@ -137,7 +137,6 @@ } .cover-desc { - padding: 0 $gl-padding 3px; color: $gl-text-color; &.username:last-child { @@ -205,7 +204,7 @@ .content-block { padding: $gl-padding 0; - border-bottom: 1px solid $border-color; + border-bottom: 1px solid $white-dark; &.oneline-block { line-height: 36px; diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss index eaf85bb17c..467f3b35d7 100644 --- a/app/assets/stylesheets/framework/buttons.scss +++ b/app/assets/stylesheets/framework/buttons.scss @@ -16,6 +16,19 @@ @include btn-default; } +@mixin btn-outline($background, $text, $border, $hover-background, $hover-text, $hover-border) { + background-color: $background; + color: $text; + border-color: $border; + + &:hover, + &:focus { + background-color: $hover-background; + color: $hover-text; + border-color: $hover-border;; + } +} + @mixin btn-color($light, $border-light, $normal, $border-normal, $dark, $border-dark, $color) { background-color: $light; border-color: $border-light; @@ -106,11 +119,14 @@ @include btn-blue; } - &.btn-close, &.btn-warning { @include btn-orange; } + &.btn-close { + @include btn-outline($white-light, $orange-normal, $orange-normal, $orange-light, $white-light, $orange-light); + } + &.btn-danger, &.btn-remove, &.btn-red { diff --git a/app/assets/stylesheets/framework/calendar.scss b/app/assets/stylesheets/framework/calendar.scss index 11f39d583b..8642b7530e 100644 --- a/app/assets/stylesheets/framework/calendar.scss +++ b/app/assets/stylesheets/framework/calendar.scss @@ -1,70 +1,44 @@ .calender-block { + padding-left: 0; + padding-right: 0; + @media (min-width: $screen-sm-min) and (max-width: $screen-lg-min) { overflow-x: scroll; } } .user-calendar-activities { - .calendar_onclick_hr { - padding: 0; - margin: 10px 0; - } - .str-truncated { max-width: 70%; } - .text-expander { - background: #eee; - color: #555; - padding: 0 5px; + .user-calendar-activities-loading { + font-size: 24px; + } +} + +.user-calendar { + text-align: center; + + .calendar { + display: inline-block; + } +} + +.user-contrib-cell { + &:hover { cursor: pointer; - margin-left: 4px; - &:hover { - background-color: #ddd; - } + stroke: #000; } } -/** -* This overwrites the default values of the cal-heatmap gem -*/ -.calendar { - .qi { - fill: #fff; - } - - .q1 { - fill: #ededed !important; - } - - .q2 { - fill: #acd5f2 !important; - } - - .q3 { - fill: #7fa8d1 !important; - } - - .q4 { - fill: #49729b !important; - } - - .q5 { - fill: #254e77 !important; - } - - .future { - visibility: hidden; - } - - .domain-background { - fill: none; - shape-rendering: crispedges; - } - - .ch-tooltip { - padding: 3px; - font-weight: 550; - } +.user-contrib-text { + font-size: 12px; + fill: #959494; +} + +.calendar-hint { + margin-top: -23px; + float: right; + font-size: 12px; } diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index 3386523dbf..f8aecd0558 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -289,7 +289,7 @@ table { text-shadow: none; @media (min-width: $screen-sm-min) { - margin-top: 11px; + margin-top: 8px; } } diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index 4bf3a05040..93c63c6984 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -154,7 +154,7 @@ color: $dropdown-header-color; font-size: 13px; line-height: 22px; - padding: 0 10px 10px; + padding: 0 10px; } .separator + .dropdown-header { @@ -162,6 +162,10 @@ } } +.dropdown-menu-full-width { + width: 100%; +} + .dropdown-menu-paging { .dropdown-page-two, .dropdown-menu-back { diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss index 61d9954c6c..71a9f79be3 100644 --- a/app/assets/stylesheets/framework/files.scss +++ b/app/assets/stylesheets/framework/files.scss @@ -5,6 +5,10 @@ .file-holder { border: 1px solid $border-color; + &.file-holder-no-border { + border: 0; + } + &.readme-holder { margin: $gl-padding-top 0; } @@ -23,8 +27,17 @@ word-wrap: break-word; border-radius: 3px 3px 0 0; + &.file-title-clear { + padding-left: 0; + padding-right: 0; + background-color: transparent; + + .file-actions { + right: 0; + } + } + .file-actions { - float: right; position: absolute; top: 5px; right: 15px; @@ -36,22 +49,6 @@ } } - .filename { - &.old { - display: inline-block; - span.idiff { - background-color: #f8cbcb; - } - } - - &.new { - display: inline-block; - span.idiff { - background-color: #a6f3a6; - } - } - } - a:not(.btn) { color: $gl-dark-link-color; } diff --git a/app/assets/stylesheets/framework/forms.scss b/app/assets/stylesheets/framework/forms.scss index 558b133f59..46acc3b772 100644 --- a/app/assets/stylesheets/framework/forms.scss +++ b/app/assets/stylesheets/framework/forms.scss @@ -28,10 +28,6 @@ input[type='text'].danger { } label { - &.control-label { - @extend .col-sm-2; - } - &.inline-label { margin: 0; } @@ -41,6 +37,10 @@ label { } } +.control-label { + @extend .col-sm-2; +} + .inline-input-group { width: 250px; } diff --git a/app/assets/stylesheets/framework/gitlab-theme.scss b/app/assets/stylesheets/framework/gitlab-theme.scss index c83cf88159..16cf394c42 100644 --- a/app/assets/stylesheets/framework/gitlab-theme.scss +++ b/app/assets/stylesheets/framework/gitlab-theme.scss @@ -9,8 +9,7 @@ @mixin gitlab-theme($color-light, $color, $color-darker, $color-dark) { .page-with-sidebar { .header-logo { - background-color: $color; - border-color: $color; + background: $color-darker; a { color: $color-light; @@ -21,9 +20,13 @@ } &:hover { - background-color: $color-darker; + background-color: $color-dark; a { color: #fff; + + h3 { + color: #fff; + } } } } @@ -87,8 +90,8 @@ } $theme-blue: #2980b9; -$theme-charcoal: #333c47; -$theme-graphite: #888; +$theme-charcoal: #3d454d; +$theme-graphite: #666; $theme-gray: #373737; $theme-green: #019875; $theme-violet: #548; @@ -99,11 +102,11 @@ body { } &.ui_charcoal { - @include gitlab-theme(#c5d0de, $theme-charcoal, #2b333d, #24272d); + @include gitlab-theme(#d6d7d9, #485157, $theme-charcoal, #353b41); } &.ui_graphite { - @include gitlab-theme(#ccc, $theme-graphite, #777, #666); + @include gitlab-theme(#ccc, #777, $theme-graphite, #555); } &.ui_gray { diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index 97f9d58200..0da96c4017 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -6,12 +6,12 @@ header { transition-duration: .3s; &.navbar-empty { - height: 58px; + height: $header-height; background: #fff; - border-bottom: 1px solid #eee; + border-bottom: 1px solid $btn-gray-hover; .center-logo { - margin: 11px 0; + margin: 8px 0; text-align: center; #tanuki-logo, img { @@ -22,14 +22,18 @@ header { } &.navbar-gitlab { - padding: 0 20px; + padding: 0 16px; z-index: 100; margin-bottom: 0; - min-height: $header-height; + height: $header-height; background-color: $background-color; border: none; border-bottom: 1px solid $border-color; + @media (max-width: $screen-xs-min) { + padding: 0 16px; + } + &.with-horizontal-nav { border-bottom: none; } @@ -60,16 +64,44 @@ header { margin: 6px 0; border-radius: 0; position: absolute; - right: 2px; + right: -10px; + padding: 6px 10px; &:hover { - background-color: #eee; + background-color: $btn-gray-hover; } + &.active { color: $gl-icon-color; } } } + + &.header-collapsed { + padding: 0 16px; + } + + .side-nav-toggle { + display: none; + position: absolute; + left: -10px; + margin: 6px 0; + padding: 6px 10px; + border: none; + background-color: $background-color; + + &:hover { + background-color: $btn-gray-hover; + } + + &:focus { + outline: none; + } + + @media (max-width: $screen-xs-min) { + display: block; + } + } } .header-content { @@ -77,6 +109,10 @@ header { height: $header-height; padding-right: 40px; + @media (max-width: $screen-xs-min) { + padding-left: 40px; + } + @media (min-width: $screen-sm-min) { padding-right: 0; } @@ -145,6 +181,10 @@ header { @media (min-width: $screen-md-min) { @include collapsed-header; } + + @media (max-width: $screen-xs-min) { + margin-left: 0; + } } .header-expanded { @@ -153,6 +193,10 @@ header { @media (min-width: $screen-md-min) { margin-left: $sidebar_width; } + + @media (max-width: $screen-xs-min) { + margin-left: 0; + } } @media (max-width: $screen-xs-max) { diff --git a/app/assets/stylesheets/framework/mobile.scss b/app/assets/stylesheets/framework/mobile.scss index 33cbee8598..bd531f8376 100644 --- a/app/assets/stylesheets/framework/mobile.scss +++ b/app/assets/stylesheets/framework/mobile.scss @@ -48,10 +48,6 @@ display: block; } - .project-home-desc { - font-size: 21px; - } - .project-repo-buttons, .git-clone-holder { display: none; diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index 7c18e93a26..7eb7a8e454 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -1,3 +1,34 @@ +@mixin fade($gradient-direction, $rgba, $gradient-color) { + visibility: visible; + opacity: 1; + position: absolute; + bottom: 12px; + width: 43px; + height: 30px; + transition-duration: .3s; + -webkit-transform: translateZ(0); + background: -webkit-linear-gradient($gradient-direction, $rgba, $gradient-color 45%); + background: -o-linear-gradient($gradient-direction, $rgba, $gradient-color 45%); + background: -moz-linear-gradient($gradient-direction, $rgba, $gradient-color 45%); + background: linear-gradient($gradient-direction, $rgba, $gradient-color 45%); + + &.end-scroll { + visibility: hidden; + opacity: 0; + transition-duration: .3s; + } +} + +@mixin scrolling-links() { + white-space: nowrap; + overflow-x: auto; + overflow-y: hidden; + -webkit-overflow-scrolling: touch; + &::-webkit-scrollbar { + display: none; + } +} + .nav-links { padding: 0; margin: 0; @@ -119,7 +150,7 @@ } input { - height: 34px; + height: 35px; display: inline-block; position: relative; top: 2px; @@ -196,14 +227,22 @@ position: fixed; top: $header-height; width: 100%; - z-index: 1; + z-index: 11; background: $background-color; border-bottom: 1px solid $border-color; transition-duration: .3s; + .container-fluid { + position: relative; + } + .controls { float: right; - padding: 7px 5px 0 0; + padding: 7px 0 0; + + @media (max-width: $screen-xs-max) { + display: none; + } i { color: $layout-link-gray; @@ -221,14 +260,31 @@ .dropdown { margin-left: 7px; + + @media (max-width: $screen-xs-min) { + margin-left: 0; + } + + li.active { + font-weight: bold; + } } } .nav-links { + @include scrolling-links(); border-bottom: none; height: 51px; - white-space: nowrap; - overflow-x: auto; + + .fade-right { + @include fade(left, rgba(250, 250, 250, 0.4), $background-color); + right: 0; + } + + .fade-left { + @include fade(right, rgba(250, 250, 250, 0.4), $background-color); + left: 0; + } li { @@ -252,8 +308,62 @@ } } + .nav-control { + .fade-right { + + @media (min-width: $screen-xs-max) { + right: 67px; + } + @media (max-width: $screen-xs-min) { + right: 0; + } + } + } +} + +.nav-block { + position: relative; + + .nav-links { + @include scrolling-links(); + + .fade-right { + @include fade(left, rgba(255, 255, 255, 0.4), $white-light); + right: 0; + } + + .fade-left { + @include fade(right, rgba(255, 255, 255, 0.4), $white-light); + left: 0; + } + + &.event-filter { + .fade-right { + visibility: hidden; + + @media (max-width: $screen-xs-max) { + visibility: visible; + } + } + } + } } .page-with-layout-nav { - margin-top: 50px; + margin-top: $header-height + 2; + + .right-sidebar { + top: ($header-height * 2) + 2; + } +} + +.activities { + + .nav-block { + border-bottom: 1px solid $border-color; + + .nav-links { + border-bottom: none; + } + } } diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index e940fd7286..67f491b6d9 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -98,7 +98,7 @@ } .sidebar-user { - padding: 9px 22px; + padding: 7px 22px; position: fixed; bottom: 40px; width: $sidebar_width; @@ -210,15 +210,33 @@ } } +.sidebar-wrapper { + &.hidden-nav { + width: 0; + } +} + .page-sidebar-collapsed { padding-left: $sidebar_collapsed_width; + @media (max-width: $screen-xs-min) { + padding-left: 0; + } + .sidebar-wrapper { width: $sidebar_collapsed_width; + @media (max-width: $screen-xs-min) { + width: 0; + } + .header-logo { width: $sidebar_collapsed_width; + @media (max-width: $screen-xs-min) { + width: 0; + } + a { padding-left: ($sidebar_collapsed_width - 36) / 2; @@ -244,12 +262,22 @@ .collapse-nav a { width: $sidebar_collapsed_width; + + @media (max-width: $screen-xs-min) { + width: 0; + } } .sidebar-user { padding-left: ($sidebar_collapsed_width - 36) / 2; width: $sidebar_collapsed_width; + @media (max-width: $screen-xs-min) { + width: 0; + padding-left: 0; + padding-right: 0; + } + .username { display: none; } @@ -258,6 +286,10 @@ .layout-nav { padding-right: $sidebar_collapsed_width; + + @media (max-width: $screen-xs-min) { + padding-right: 0;; + } } } @@ -268,6 +300,10 @@ padding-left: $sidebar_width; } + @media (max-width: $screen-xs-min) { + padding-left: 0; + } + .sidebar-wrapper { width: $sidebar_width; @@ -276,7 +312,7 @@ } .nav-sidebar li a { - width: 230px; + width: $sidebar_width; &.back-link { i { @@ -287,7 +323,17 @@ } .layout-nav { - padding-right: $sidebar_width; + @media (max-width: $screen-xs-min) { + padding-right: 0; + } + + @media (min-width: $screen-xs-min) and (max-width: $screen-md-min) { + padding-right: 62px; + } + + @media (min-width: $screen-md-min) { + padding-right: $sidebar_width; + } } } diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss index 2779cd5678..3575984b22 100644 --- a/app/assets/stylesheets/framework/typography.scss +++ b/app/assets/stylesheets/framework/typography.scss @@ -269,3 +269,11 @@ h1, h2, h3, h4 { text-align: right; } } + +.idiff.deletion { + background: $line-removed-dark; +} + +.idiff.addition { + background: $line-added-dark; +} diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index ccb4e5381b..f253da814b 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -2,7 +2,7 @@ * Layout */ $sidebar_collapsed_width: 62px; -$sidebar_width: 230px; +$sidebar_width: 220px; $gutter_collapsed_width: 62px; $gutter_width: 290px; $gutter_inner_width: 258px; @@ -12,7 +12,7 @@ $gutter_inner_width: 258px; */ $border-color: #e5e5e5; $focus-border-color: #3aabf0; -$table-border-color: #ececec; +$table-border-color: #f0f0f0; $background-color: #fafafa; /* @@ -63,7 +63,8 @@ $gl-padding-top: 10px; /* * Misc */ -$row-hover: #f4f8fe; +$row-hover: #f7faff; +$row-hover-border: #b2d7ff; $progress-color: #c0392b; $avatar_radius: 50%; $header-height: 50px; @@ -104,7 +105,7 @@ $blue-medium-light: #3498cb; $blue-medium: #2f8ebf; $blue-medium-dark: #2d86b4; -$orange-light: rgba(252, 109, 38, 0.80); +$orange-light: #fc8a51; $orange-normal: #e75e40; $orange-dark: #ce5237; @@ -119,8 +120,8 @@ $border-white-light: #f1f2f4; $border-white-normal: #d6dae2; $border-white-dark: #c6cacf; -$border-gray-light: rgba(0, 0, 0, 0.06); -$border-gray-normal: rgba(0, 0, 0, 0.10);; +$border-gray-light: #dcdcdc; +$border-gray-normal: rgba(0, 0, 0, 0.10); $border-gray-dark: #c6cacf; $border-green-light: #2faa60; @@ -178,6 +179,7 @@ $table-border-gray: #f0f0f0; $line-target-blue: #eaf3fc; $line-select-yellow: #fcf8e7; $line-select-yellow-dark: #f0e2bd; + /* * Fonts */ @@ -215,6 +217,7 @@ $dropdown-toggle-hover-icon-color: $dropdown-toggle-hover-border-color; $btn-active-gray: #ececec; $btn-placeholder-gray: #c7c7c7; $btn-white-active: #848484; +$btn-gray-hover: #eee; /* * Award emoji diff --git a/app/assets/stylesheets/framework/zen.scss b/app/assets/stylesheets/framework/zen.scss index f870ea0d87..ff02ebdd34 100644 --- a/app/assets/stylesheets/framework/zen.scss +++ b/app/assets/stylesheets/framework/zen.scss @@ -32,7 +32,7 @@ } } -.zen-cotrol { +.zen-control { padding: 0; color: #555; background: none; diff --git a/app/assets/stylesheets/mailers/devise.scss b/app/assets/stylesheets/mailers/devise.scss new file mode 100644 index 0000000000..28611a5ec8 --- /dev/null +++ b/app/assets/stylesheets/mailers/devise.scss @@ -0,0 +1,134 @@ +// NOTE: This stylesheet is for the exclusive use of the `devise_mailer` layout +// used for Devise email templates, and _should not_ be included in any +// application stylesheets. +// +// Styles defined here are embedded directly into the resulting email HTML via +// the `premailer` gem. + +$body-background-color: #363636; +$message-background-color: #fafafa; + +$header-color: #6b4fbb; +$body-color: #444; +$cta-color: #e14329; +$footer-link-color: #7e7e7e; + +$font-family: Helvetica, Arial, sans-serif; + +body { + background-color: $body-background-color; + font-family: $font-family; + margin: 0; + padding: 0; +} + +table { + -premailer-cellpadding: 0; + -premailer-cellspacing: 0; + + border: 0; + border-collapse: separate; + + &#wrapper { + background-color: $body-background-color; + width: 100%; + } + + &#header { + margin: 0 auto; + text-align: left; + width: 600px; + } + + &#body { + background-color: $message-background-color; + border: 1px solid #000; + border-radius: 4px; + margin: 0 auto; + width: 600px; + } + + &#footer { + color: $footer-link-color; + font-size: 14px; + text-align: center; + width: 100%; + } + + td { + &#body-container { + padding: 20px 40px; + } + } +} + +.center { + text-align: center; +} + +#logo { + border: none; + outline: none; + min-height: 88px; + width: 134px; +} + +#content { + h2 { + color: $header-color; + font-size: 30px; + font-weight: 400; + line-height: 34px; + margin-top: 0; + } + + p { + color: $body-color; + font-size: 17px; + line-height: 24px; + margin-bottom: 0; + } +} + +#cta { + border: 1px solid $cta-color; + border-radius: 3px; + display: inline-block; + margin: 20px 0; + padding: 12px 24px; + + a { + background-color: $message-background-color; + color: $cta-color; + display: inline-block; + text-decoration: none; + } +} + +#tanuki { + padding: 40px 0 0; + + img { + border: none; + outline: none; + width: 37px; + min-height: 36px; + } +} + +#tagline { + font-size: 22px; + font-weight: 100; + padding: 4px 0 40px; +} + +#social { + padding: 0 10px 20px; + width: 600px; + word-spacing: 20px; + + a { + color: $footer-link-color; + text-decoration: none; + } +} diff --git a/app/assets/stylesheets/mailers/repository_push_email.scss b/app/assets/stylesheets/mailers/repository_push_email.scss new file mode 100644 index 0000000000..001994db97 --- /dev/null +++ b/app/assets/stylesheets/mailers/repository_push_email.scss @@ -0,0 +1,43 @@ +@import "framework/variables"; + +table.code { + width: 100%; + font-family: monospace; + border: none; + border-collapse: separate; + margin: 0; + padding: 0; + -premailer-cellpadding: 0; + -premailer-cellspacing: 0; + -premailer-width: 100%; + + td { + line-height: $code_line_height; + font-family: monospace; + font-size: $code_font_size; + } + + td.diff-line-num { + margin: 0; + padding: 0; + border: none; + background: $background-color; + color: rgba(0, 0, 0, 0.3); + padding: 0 5px; + border-right: 1px solid $border-color; + text-align: right; + min-width: 35px; + max-width: 50px; + width: 35px; + } + + td.line_content { + display: block; + margin: 0; + padding: 0 0.5em; + border: none; + white-space: pre; + } +} + +@import "highlight/white"; diff --git a/app/assets/stylesheets/pages/commit.scss b/app/assets/stylesheets/pages/commit.scss index c2cd227571..fc3f214aba 100644 --- a/app/assets/stylesheets/pages/commit.scss +++ b/app/assets/stylesheets/pages/commit.scss @@ -26,8 +26,28 @@ .commit-info-row { margin-bottom: 10px; + + &.commit-info-row-header { + line-height: 34px; + + @media (min-width: $screen-sm-min) { + margin-bottom: 0; + } + + .commit-options-dropdown-caret { + @media (max-width: $screen-sm) { + margin-left: 0; + } + } + } + .avatar { @extend .avatar-inline; + margin-left: 0; + + @media (min-width: $screen-sm-min) { + margin-left: 4px; + } } .commit-committer-link, .commit-author-link { @@ -35,10 +55,6 @@ font-weight: bold; } - .time_ago { - margin-left: 8px; - } - .fa-clipboard { color: $dropdown-title-btn-color; } diff --git a/app/assets/stylesheets/pages/detail_page.scss b/app/assets/stylesheets/pages/detail_page.scss index 5e61e61d85..1b389d8352 100644 --- a/app/assets/stylesheets/pages/detail_page.scss +++ b/app/assets/stylesheets/pages/detail_page.scss @@ -29,8 +29,6 @@ margin-top: 6px; p { - overflow-x: auto; - &:last-child { margin-bottom: 0; } diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss index 8981f070a2..22679c764d 100644 --- a/app/assets/stylesheets/pages/editor.scss +++ b/app/assets/stylesheets/pages/editor.scss @@ -23,7 +23,7 @@ .file-title { @extend .monospace; - line-height: 42px; + line-height: 35px; padding-top: 7px; padding-bottom: 7px; @@ -43,7 +43,7 @@ .editor-file-name { @extend .monospace; - + float: left; margin-right: 10px; } @@ -59,7 +59,22 @@ } .encoding-selector, - .license-selector { + .license-selector, + .gitignore-selector { display: inline-block; + vertical-align: top; + font-family: $regular_font; + } + + .gitignore-selector { + + .dropdown { + line-height: 21px; + } + + .dropdown-menu-toggle { + vertical-align: top; + width: 220px; + } } } diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 1cf3023ecc..787c387379 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -125,7 +125,7 @@ .right-sidebar { position: fixed; - top: 58px; + top: $header-height; bottom: 0; right: 0; z-index: 10; @@ -150,6 +150,10 @@ font-weight: 600; } + .light { + font-weight: normal; + } + .sidebar-collapsed-icon { display: none; } diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss index fc9db97132..4e35ca329e 100644 --- a/app/assets/stylesheets/pages/issues.scss +++ b/app/assets/stylesheets/pages/issues.scss @@ -40,11 +40,6 @@ } } -.issue-search-form { - margin: 0; - height: 24px; -} - form.edit-issue { margin: 0; } @@ -96,8 +91,3 @@ form.edit-issue { .issue-form .select2-container { width: 250px !important; } - -.issue-closed-by-widget { - color: $gl-text-color; - margin-left: 52px; -} diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index c4005ba1e6..8046e203a9 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -41,7 +41,7 @@ margin: 0; margin-left: 20px; padding: 5px; - padding-top: 12px; + padding-top: 8px; line-height: 20px; &.right { @@ -110,6 +110,29 @@ p:last-child { margin-bottom: 0; } + + @media (max-width: $screen-sm-max) { + h4 { + font-size: 15px; + } + + p { + font-size: 13px; + } + + .btn, + .btn-group, + .accept-action { + width: 100%; + margin-bottom: 4px; + } + + .accept-control { + width: 100%; + text-align: center; + margin: 0; + } + } } .mr-widget-footer { @@ -280,11 +303,5 @@ background-color: $white-light; color: $gl-placeholder-color; } - - th, - td { - padding: 16px; - } } } - diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss index 624c8249f7..a3e1ac13a4 100644 --- a/app/assets/stylesheets/pages/notes.scss +++ b/app/assets/stylesheets/pages/notes.scss @@ -226,8 +226,7 @@ ul.notes { } } -.note-action-button, -.discussion-action-button { +.note-action-button { display: inline-block; margin-left: 10px; line-height: 24px; diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss new file mode 100644 index 0000000000..6128868b67 --- /dev/null +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -0,0 +1,24 @@ +.pipelines { + .stage { + max-width: 100px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .duration, .finished_at { + margin: 4px 0; + } + + .commit-title { + margin: 0; + } + + .controls { + white-space: nowrap; + } + + .btn { + margin: 4px; + } +} diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss index abc5a0e987..167ab40d88 100644 --- a/app/assets/stylesheets/pages/profile.scss +++ b/app/assets/stylesheets/pages/profile.scss @@ -66,12 +66,6 @@ } } -.calendar-hint { - margin-top: -12px; - float: right; - font-size: 12px; -} - .profile-link-holder { display: inline; @@ -134,14 +128,6 @@ } } -.change-username-title { - color: $gl-warning; -} - -.remove-account-title { - color: $gl-danger; -} - .provider-btn-group { display: inline-block; margin-right: 10px; @@ -218,7 +204,7 @@ .btn { display: inline-block; - width: 48%; + width: 46%; } } } diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index c20f04653f..edef336481 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -7,10 +7,10 @@ } .no-ssh-key-message, .project-limit-message { background-color: #f28d35; - margin-bottom: 16px; + margin-bottom: 0; } .new_project, -.edit_project { +.edit-project { fieldset.features { .control-label { font-weight: normal; @@ -26,8 +26,13 @@ } .project-home-panel { - padding-bottom: 40px; - border-bottom: 1px solid $border-color; + background: $white-light; + text-align: left; + padding: 24px 0; + + .container-fluid { + position: relative; + } .cover-controls { .project-settings-dropdown { @@ -43,21 +48,55 @@ } } - .project-identicon-holder { - margin-bottom: 16px; + .cover-title { + margin-bottom: 0; + } - .avatar, .identicon { - margin: 0 auto; - float: none; - } + .project-image-container { + @include make-sm-column(1); + max-width: 86px; + min-width: 86px; + padding-right: 0; + margin: 11px 0; - .identicon { - @include border-radius(50%); + @media (max-width: $screen-md-max) { + padding-left: 0; + margin: 0 0 10px; + max-width: none; + min-width: none; + + .avatar.s70 { + margin: auto; + } } } + .project-info { + @include make-sm-column(10); + + h1 { + font-size: 24px; + font-weight: normal; + margin: 0; + } + + .project-home-desc { + p { + margin: 0; + } + } + } + + .identicon { + float: left; + @include border-radius(50%); + } + + .avatar { + float: none; + } + .notifications-btn { - margin-top: -28px; .fa-bell { margin-right: 6px; @@ -69,28 +108,45 @@ } .project-repo-buttons { - margin-top: 20px; - margin-bottom: 0; - - .count-buttons { - display: block; - margin-bottom: 20px; - } - - .clone-row { - .split-repo-buttons, - .project-clone-holder { - display: inline-block; - } - - .split-repo-buttons { - margin: 0 12px; - } - } + font-size: 0; .btn { @include btn-gray; + padding: 3px 10px; text-transform: none; + background-color: $background-color; + + .fa { + color: $layout-link-gray; + } + + .fa-caret-down { + margin-left: 3px; + } + } + + .btn-group:not(:first-child):not(:last-child) > .btn { + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; + } + + form { + margin-left: 10px; + } + + .count-buttons { + display: inline-block; + vertical-align: top; + margin-top: 16px; + } + + .project-clone-holder { + display: inline-block; + margin-top: 16px; + + input { + height: 29px; + } } .count-with-arrow { @@ -140,14 +196,18 @@ line-height: 13px; padding: $gl-vert-padding $gl-padding; letter-spacing: .4px; - padding: 10px 14px; + padding: 7px 14px; text-align: center; vertical-align: middle; touch-action: manipulation; cursor: pointer; background-image: none; white-space: nowrap; - margin: 0 11px 0 4px; + margin: 0 10px 0 4px; + + a { + color: inherit; + } &:hover { background: #fff; @@ -155,13 +215,37 @@ } } } + + .project-right-buttons { + position: absolute; + right: 16px; + bottom: 0; + + .btn { + padding: 3px 10px; + background-color: $background-color; + } + + @media (max-width: 1304px) { + top: 0; + } + } + + @media (max-width: $screen-md-max) { + text-align: center; + + .project-info, + .project-image-container { + width: 100%; + } + } } .split-one { display: inline-table; margin-right: 12px; - a { + > a { margin: -1px; } } @@ -285,11 +369,11 @@ a.deploy-project-label { } .project-stats { - text-align: center; margin-top: $gl-padding; margin-bottom: 0; - padding-top: 10px; - padding-bottom: 4px; + padding: 16px 0; + background-color: $white-light; + font-size: 0; ul.nav { display: inline-block; @@ -300,12 +384,11 @@ a.deploy-project-label { } .nav > li > a { - @include btn-default; - @include btn-gray; - background-color: transparent; - border: 1px solid #f7f8fa; - margin-left: 12px; + margin-right: 12px; + padding: 0 10px; + font-size: 15px; + color: $notes-light-color; } li { @@ -325,6 +408,10 @@ a.deploy-project-label { background-color: #f0f2f5; } } + + &.row-content-block.second-block { + margin-top: 0; + } } pre.light-well { @@ -442,9 +529,14 @@ pre.light-well { border-top: 0; .edit-project-readme { - z-index: 100; + z-index: 2; position: relative; } + + .wiki h1 { + border-bottom: none; + padding: 0; + } } .git-clone-holder { diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss index 2bff70c8c6..037ad52054 100644 --- a/app/assets/stylesheets/pages/search.scss +++ b/app/assets/stylesheets/pages/search.scss @@ -28,6 +28,7 @@ } .search-input { + padding-right: 20px; border: none; font-size: 14px; outline: none; @@ -47,6 +48,7 @@ display: inline-block; background-color: $location-badge-bg; vertical-align: top; + cursor: default; } .search-input-container { @@ -55,7 +57,7 @@ position: relative; } - .search-location-badge, .search-input-wrap { + .search-input-wrap { // Fallback if flexbox is not supported display: inline-block; } diff --git a/app/assets/stylesheets/pages/settings.scss b/app/assets/stylesheets/pages/settings.scss index 3fb7008571..2e8f356298 100644 --- a/app/assets/stylesheets/pages/settings.scss +++ b/app/assets/stylesheets/pages/settings.scss @@ -12,3 +12,11 @@ border: 1px solid $warning-message-border; border-radius: $border-radius-base; } + +.warning-title { + color: $gl-warning; +} + +.danger-title { + color: $gl-danger; +} diff --git a/app/assets/stylesheets/pages/snippets.scss b/app/assets/stylesheets/pages/snippets.scss index 639d639d5b..2aa939b7dc 100644 --- a/app/assets/stylesheets/pages/snippets.scss +++ b/app/assets/stylesheets/pages/snippets.scss @@ -16,19 +16,6 @@ } } -.snippet-box { - @include border-radius(2px); - - display: block; - float: left; - padding: 0 $gl-padding; - font-weight: normal; - margin-right: 10px; - font-size: $gl-font-size; - border: 1px solid; - line-height: 32px; -} - .markdown-snippet-copy { position: fixed; top: -10px; @@ -36,3 +23,34 @@ max-height: 0; max-width: 0; } + +.file-holder.snippet-file-content { + padding-bottom: $gl-padding; + border-bottom: 1px solid $border-color; + + .file-title { + padding-top: $gl-padding; + padding-bottom: $gl-padding; + } + + .file-actions { + top: 12px; + } + + .file-content { + border-left: 1px solid $border-color; + border-right: 1px solid $border-color; + border-bottom: 1px solid $border-color; + } +} + +.snippet-title { + font-size: 24px; + font-weight: normal; +} + +.snippet-actions { + @media (min-width: $screen-sm-min) { + float: right; + } +} diff --git a/app/assets/stylesheets/pages/todos.scss b/app/assets/stylesheets/pages/todos.scss index e51c3491da..afc00a6857 100644 --- a/app/assets/stylesheets/pages/todos.scss +++ b/app/assets/stylesheets/pages/todos.scss @@ -29,6 +29,17 @@ .todo-item { .todo-title { @include str-truncated(calc(100% - 174px)); + overflow: visible; + } + + .status-box { + margin: 0; + float: none; + display: inline-block; + font-weight: normal; + padding: 0 5px; + line-height: inherit; + font-size: 14px; } .todo-body { @@ -76,12 +87,11 @@ @media (max-width: $screen-xs-max) { .todo-item { - padding-left: $gl-padding; - .todo-title { white-space: normal; overflow: visible; max-width: 100%; + margin-bottom: 10px; } .avatar { diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss index a84fc2e031..f16fc7f388 100644 --- a/app/assets/stylesheets/pages/tree.scss +++ b/app/assets/stylesheets/pages/tree.scss @@ -15,16 +15,23 @@ margin-bottom: 0; tr { - > td, > th { + border-bottom: 1px solid $table-border-gray; + border-top: 1px solid $table-border-gray; + + td, th { line-height: 23px; } &:hover { - td { - background: $row-hover; - } cursor: pointer; + + td { + background-color: $row-hover; + border-top: 1px solid $row-hover-border; + border-bottom: 1px solid $row-hover-border; + } } + &.selected { td { background: $gray-dark; diff --git a/app/controllers/admin/abuse_reports_controller.rb b/app/controllers/admin/abuse_reports_controller.rb index e9b0972bdd..5055c318a5 100644 --- a/app/controllers/admin/abuse_reports_controller.rb +++ b/app/controllers/admin/abuse_reports_controller.rb @@ -9,6 +9,6 @@ class Admin::AbuseReportsController < Admin::ApplicationController abuse_report.remove_user(deleted_by: current_user) if params[:remove_user] abuse_report.destroy - render nothing: true + head :ok end end diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index ec22548dde..0a34a12e2a 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -19,6 +19,12 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController redirect_to admin_runners_path end + def reset_health_check_token + @application_setting.reset_health_check_access_token! + flash[:notice] = 'New health check access token has been generated!' + redirect_to :back + end + def clear_repository_check_states RepositoryCheck::ClearWorker.perform_async @@ -53,6 +59,12 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController end end + enabled_oauth_sign_in_sources = params[:application_setting].delete(:enabled_oauth_sign_in_sources) + + params[:application_setting][:disabled_oauth_sign_in_sources] = + AuthHelper.button_based_providers.map(&:to_s) - + Array(enabled_oauth_sign_in_sources) + params.require(:application_setting).permit( :default_projects_limit, :default_branch_protection, @@ -94,8 +106,11 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController :email_author_in_body, :repository_checks_enabled, :metrics_packet_size, + :send_user_confirmation_email, + :container_registry_token_expire_delay, restricted_visibility_levels: [], - import_sources: [] + import_sources: [], + disabled_oauth_sign_in_sources: [] ) end end diff --git a/app/controllers/admin/broadcast_messages_controller.rb b/app/controllers/admin/broadcast_messages_controller.rb index fc34292498..82055006ac 100644 --- a/app/controllers/admin/broadcast_messages_controller.rb +++ b/app/controllers/admin/broadcast_messages_controller.rb @@ -32,7 +32,7 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController respond_to do |format| format.html { redirect_back_or_default(default: { action: 'index' }) } - format.js { render nothing: true } + format.js { head :ok } end end diff --git a/app/controllers/admin/health_check_controller.rb b/app/controllers/admin/health_check_controller.rb new file mode 100644 index 0000000000..241c7be0ea --- /dev/null +++ b/app/controllers/admin/health_check_controller.rb @@ -0,0 +1,5 @@ +class Admin::HealthCheckController < Admin::ApplicationController + def show + @errors = HealthCheck::Utils.process_checks('standard') + end +end diff --git a/app/controllers/admin/keys_controller.rb b/app/controllers/admin/keys_controller.rb index cb33fdd976..054bb52b69 100644 --- a/app/controllers/admin/keys_controller.rb +++ b/app/controllers/admin/keys_controller.rb @@ -6,7 +6,7 @@ class Admin::KeysController < Admin::ApplicationController respond_to do |format| format.html - format.js { render nothing: true } + format.js { head :ok } end end diff --git a/app/controllers/admin/runners_controller.rb b/app/controllers/admin/runners_controller.rb index a701d49b84..7345c91f67 100644 --- a/app/controllers/admin/runners_controller.rb +++ b/app/controllers/admin/runners_controller.rb @@ -9,23 +9,18 @@ class Admin::RunnersController < Admin::ApplicationController end def show - @builds = @runner.builds.order('id DESC').first(30) - @projects = - if params[:search].present? - ::Project.search(params[:search]) - else - Project.all - end - @projects = @projects.where.not(id: @runner.projects.select(:id)) if @runner.projects.any? - @projects = @projects.page(params[:page]).per(30) + assign_builds_and_projects end def update - @runner.update_attributes(runner_params) - - respond_to do |format| - format.js - format.html { redirect_to admin_runner_path(@runner) } + if @runner.update_attributes(runner_params) + respond_to do |format| + format.js + format.html { redirect_to admin_runner_path(@runner) } + end + else + assign_builds_and_projects + render 'show' end end @@ -58,6 +53,18 @@ class Admin::RunnersController < Admin::ApplicationController end def runner_params - params.require(:runner).permit(:token, :description, :tag_list, :active) + params.require(:runner).permit(Ci::Runner::FORM_EDITABLE) + end + + def assign_builds_and_projects + @builds = runner.builds.order('id DESC').first(30) + @projects = + if params[:search].present? + ::Project.search(params[:search]) + else + Project.all + end + @projects = @projects.where.not(id: runner.projects.select(:id)) if runner.projects.any? + @projects = @projects.page(params[:page]).per(30) end end diff --git a/app/controllers/admin/spam_logs_controller.rb b/app/controllers/admin/spam_logs_controller.rb index 377e9741e5..3a2f018531 100644 --- a/app/controllers/admin/spam_logs_controller.rb +++ b/app/controllers/admin/spam_logs_controller.rb @@ -11,7 +11,7 @@ class Admin::SpamLogsController < Admin::ApplicationController redirect_to admin_spam_logs_path, notice: "User #{spam_log.user.username} was successfully removed." else spam_log.destroy - render nothing: true + head :ok end end end diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index f2f654c7bc..f35f4a8c81 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -119,6 +119,7 @@ class Admin::UsersController < Admin::ApplicationController user_params_with_pass.merge!( password: params[:user][:password], password_confirmation: params[:user][:password_confirmation], + password_expires_at: Time.now ) end @@ -153,7 +154,7 @@ class Admin::UsersController < Admin::ApplicationController respond_to do |format| format.html { redirect_back_or_admin_user(notice: "Successfully removed email.") } - format.js { render nothing: true } + format.js { head :ok } end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 17b3f49aed..c28d1ca9e3 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -176,7 +176,7 @@ class ApplicationController < ActionController::Base end def check_password_expiration - if current_user && current_user.password_expires_at && current_user.password_expires_at < Time.now && !current_user.ldap_user? + if current_user && current_user.password_expires_at && current_user.password_expires_at < Time.now && !current_user.ldap_user? redirect_to new_profile_password_path and return end end @@ -232,7 +232,7 @@ class ApplicationController < ActionController::Base end def configure_permitted_parameters - devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:username, :email, :password, :login, :remember_me, :otp_attempt) } + devise_parameter_sanitizer.permit(:sign_in, keys: [:username, :email, :password, :login, :remember_me, :otp_attempt]) end def hexdigest(string) @@ -263,7 +263,7 @@ class ApplicationController < ActionController::Base # internal repos where you are not a member. Enable this filter # or improve current implementation to filter only issues you # created or assigned or mentioned - #@filter_params[:authorized_only] = true + # @filter_params[:authorized_only] = true end @filter_params diff --git a/app/controllers/autocomplete_controller.rb b/app/controllers/autocomplete_controller.rb index eb0abc80ab..3865b2d61f 100644 --- a/app/controllers/autocomplete_controller.rb +++ b/app/controllers/autocomplete_controller.rb @@ -31,6 +31,24 @@ class AutocompleteController < ApplicationController render json: @user, only: [:name, :username, :id], methods: [:avatar_url] end + def projects + project = Project.find_by_id(params[:project_id]) + + projects = current_user.authorized_projects + projects = projects.select do |project| + current_user.can?(:admin_issue, project) + end + + no_project = { + id: 0, + name_with_namespace: 'No project', + } + projects.unshift(no_project) + projects.delete(project) + + render json: projects.to_json(only: [:id, :name_with_namespace], methods: :name_with_namespace) + end + private def find_users diff --git a/app/controllers/concerns/creates_commit.rb b/app/controllers/concerns/creates_commit.rb index 787416c17a..dacb5679dd 100644 --- a/app/controllers/concerns/creates_commit.rb +++ b/app/controllers/concerns/creates_commit.rb @@ -122,7 +122,7 @@ module CreatesCommit # Merge request from fork to this project @mr_source_project = @tree_edit_project @mr_target_project = @project - @mr_target_branch ||= @ref + @mr_target_branch ||= @ref end end end diff --git a/app/controllers/concerns/toggle_subscription_action.rb b/app/controllers/concerns/toggle_subscription_action.rb index 8a43c0b93c..9e3b9be2ff 100644 --- a/app/controllers/concerns/toggle_subscription_action.rb +++ b/app/controllers/concerns/toggle_subscription_action.rb @@ -6,7 +6,7 @@ module ToggleSubscriptionAction subscribable_resource.toggle_subscription(current_user) - render nothing: true + head :ok end private diff --git a/app/controllers/dashboard/labels_controller.rb b/app/controllers/dashboard/labels_controller.rb index 23a4ef21ea..2a88350a4c 100644 --- a/app/controllers/dashboard/labels_controller.rb +++ b/app/controllers/dashboard/labels_controller.rb @@ -1,6 +1,6 @@ class Dashboard::LabelsController < Dashboard::ApplicationController def index - labels = Label.where(project_id: projects).select(:title, :color).uniq(:title) + labels = Label.where(project_id: projects).select(:id, :title, :color).uniq(:title) respond_to do |format| format.json { render json: labels } diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb index 71acc244a9..c08eb81153 100644 --- a/app/controllers/dashboard/projects_controller.rb +++ b/app/controllers/dashboard/projects_controller.rb @@ -28,7 +28,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController end def starred - @projects = current_user.starred_projects.sorted_by_activity + @projects = current_user.viewable_starred_projects.sorted_by_activity @projects = filter_projects(@projects) @projects = @projects.includes(:namespace, :forked_from_project, :tags) @projects = @projects.sort(@sort = params[:sort]) diff --git a/app/controllers/dashboard/todos_controller.rb b/app/controllers/dashboard/todos_controller.rb index 5abf97342c..f9a1929c11 100644 --- a/app/controllers/dashboard/todos_controller.rb +++ b/app/controllers/dashboard/todos_controller.rb @@ -12,7 +12,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController respond_to do |format| format.html { redirect_to dashboard_todos_path, notice: todo_notice } - format.js { render nothing: true } + format.js { head :ok } format.json do render json: { count: @todos.size, done_count: current_user.todos.done.count } end @@ -24,7 +24,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController respond_to do |format| format.html { redirect_to dashboard_todos_path, notice: 'All todos were marked as done.' } - format.js { render nothing: true } + format.js { head :ok } format.json do find_todos render json: { count: @todos.size, done_count: current_user.todos.done.count } diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 1dce4a2172..4dda4e51f6 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -25,7 +25,7 @@ class DashboardController < Dashboard::ApplicationController def load_events projects = if params[:filter] == "starred" - current_user.starred_projects + current_user.viewable_starred_projects else current_user.authorized_projects end diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb index d5ef33888c..48dbf656e8 100644 --- a/app/controllers/groups/group_members_controller.rb +++ b/app/controllers/groups/group_members_controller.rb @@ -40,7 +40,7 @@ class Groups::GroupMembersController < Groups::ApplicationController respond_to do |format| format.html { redirect_to group_group_members_path(@group), notice: 'User was successfully removed from group.' } - format.js { render nothing: true } + format.js { head :ok } end end diff --git a/app/controllers/health_check_controller.rb b/app/controllers/health_check_controller.rb new file mode 100644 index 0000000000..037da7d2bc --- /dev/null +++ b/app/controllers/health_check_controller.rb @@ -0,0 +1,22 @@ +class HealthCheckController < HealthCheck::HealthCheckController + before_action :validate_health_check_access! + + private + + def validate_health_check_access! + render_404 unless token_valid? + end + + def token_valid? + token = params[:token].presence || request.headers['TOKEN'] + token.present? && + ActiveSupport::SecurityUtils.variable_size_secure_compare( + token, + current_application_settings.health_check_access_token + ) + end + + def render_404 + render file: Rails.root.join('public', '404'), layout: false, status: '404' + end +end diff --git a/app/controllers/jwt_controller.rb b/app/controllers/jwt_controller.rb new file mode 100644 index 0000000000..cee3b6c43e --- /dev/null +++ b/app/controllers/jwt_controller.rb @@ -0,0 +1,87 @@ +class JwtController < ApplicationController + skip_before_action :authenticate_user! + skip_before_action :verify_authenticity_token + before_action :authenticate_project_or_user + + SERVICES = { + Auth::ContainerRegistryAuthenticationService::AUDIENCE => Auth::ContainerRegistryAuthenticationService, + } + + def auth + service = SERVICES[params[:service]] + return head :not_found unless service + + result = service.new(@project, @user, auth_params).execute + + render json: result, status: result[:http_status] + end + + private + + def authenticate_project_or_user + authenticate_with_http_basic do |login, password| + # if it's possible we first try to authenticate project with login and password + @project = authenticate_project(login, password) + return if @project + + @user = authenticate_user(login, password) + return if @user + + render_403 + end + end + + def auth_params + params.permit(:service, :scope, :account, :client_id) + end + + def authenticate_project(login, password) + if login == 'gitlab-ci-token' + Project.find_by(builds_enabled: true, runners_token: password) + end + end + + def authenticate_user(login, password) + # TODO: this is a copy and paste from grack_auth, + # it should be refactored in the future + + user = Gitlab::Auth.new.find(login, password) + + # If the user authenticated successfully, we reset the auth failure count + # from Rack::Attack for that IP. A client may attempt to authenticate + # with a username and blank password first, and only after it receives + # a 401 error does it present a password. Resetting the count prevents + # false positives from occurring. + # + # Otherwise, we let Rack::Attack know there was a failed authentication + # attempt from this IP. This information is stored in the Rails cache + # (Redis) and will be used by the Rack::Attack middleware to decide + # whether to block requests from this IP. + config = Gitlab.config.rack_attack.git_basic_auth + + if config.enabled + if user + # A successful login will reset the auth failure count from this IP + Rack::Attack::Allow2Ban.reset(request.ip, config) + else + banned = Rack::Attack::Allow2Ban.filter(request.ip, config) do + # Unless the IP is whitelisted, return true so that Allow2Ban + # increments the counter (stored in Rails.cache) for the IP + if config.ip_whitelist.include?(request.ip) + false + else + true + end + end + + if banned + Rails.logger.info "IP #{request.ip} failed to login " \ + "as #{login} but has been temporarily banned from Git auth" + return + end + end + end + + user + end +end diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb index df98f56a1c..f35d631df0 100644 --- a/app/controllers/omniauth_callbacks_controller.rb +++ b/app/controllers/omniauth_callbacks_controller.rb @@ -97,7 +97,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController handle_signup_error end - def handle_service_ticket provider, ticket + def handle_service_ticket(provider, ticket) Gitlab::OAuth::Session.create provider, ticket session[:service_tickets] ||= {} session[:service_tickets][provider] = ticket diff --git a/app/controllers/profiles/emails_controller.rb b/app/controllers/profiles/emails_controller.rb index 0ede9b8e21..1c24c4db99 100644 --- a/app/controllers/profiles/emails_controller.rb +++ b/app/controllers/profiles/emails_controller.rb @@ -24,7 +24,7 @@ class Profiles::EmailsController < Profiles::ApplicationController respond_to do |format| format.html { redirect_to profile_emails_url } - format.js { render nothing: true } + format.js { head :ok } end end diff --git a/app/controllers/profiles/keys_controller.rb b/app/controllers/profiles/keys_controller.rb index a12549d6bc..830e0b9591 100644 --- a/app/controllers/profiles/keys_controller.rb +++ b/app/controllers/profiles/keys_controller.rb @@ -32,7 +32,7 @@ class Profiles::KeysController < Profiles::ApplicationController respond_to do |format| format.html { redirect_to profile_keys_url } - format.js { render nothing: true } + format.js { head :ok } end end diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb index be872a93fe..776ba92c9a 100644 --- a/app/controllers/projects/application_controller.rb +++ b/app/controllers/projects/application_controller.rb @@ -26,7 +26,7 @@ class Projects::ApplicationController < ApplicationController project_path = "#{namespace}/#{id}" @project = Project.find_with_namespace(project_path) - if @project && can?(current_user, :read_project, @project) + if can?(current_user, :read_project, @project) && !@project.pending_delete? if @project.path_with_namespace != project_path redirect_to request.original_url.gsub(project_path, @project.path_with_namespace) end diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb index d09e7375b6..dd9508da04 100644 --- a/app/controllers/projects/branches_controller.rb +++ b/app/controllers/projects/branches_controller.rb @@ -50,7 +50,7 @@ class Projects::BranchesController < Projects::ApplicationController redirect_to namespace_project_branches_path(@project.namespace, @project), status: 303 end - format.js { render status: status[:return_code] } + format.js { render nothing: true, status: status[:return_code] } end end diff --git a/app/controllers/projects/builds_controller.rb b/app/controllers/projects/builds_controller.rb index b8b9e78427..bb1f6c5e98 100644 --- a/app/controllers/projects/builds_controller.rb +++ b/app/controllers/projects/builds_controller.rb @@ -38,6 +38,14 @@ class Projects::BuildsController < Projects::ApplicationController end end + def trace + respond_to do |format| + format.json do + render json: @build.trace_with_state(params[:state]).merge!(id: @build.id, status: @build.status) + end + end + end + def retry unless @build.retryable? return render_404 diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index a202cb3869..10b5932aff 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -17,12 +17,12 @@ class Projects::CommitController < Projects::ApplicationController def show apply_diff_view_cookie! - @line_notes = commit.notes.inline + @grouped_diff_notes = commit.notes.grouped_diff_notes + @note = @project.build_commit_note(commit) - @notes = commit.notes.not_inline.fresh + @notes = commit.notes.non_diff_notes.fresh @noteable = @commit - @comments_allowed = @reply_allowed = true - @comments_target = { + @comments_target = { noteable_type: 'Commit', commit_id: @commit.id } @@ -67,10 +67,10 @@ class Projects::CommitController < Projects::ApplicationController create_commit(Commits::RevertService, success_notice: "The #{@commit.change_type_title} has been successfully reverted.", success_path: successful_change_path, failure_path: failed_change_path) end - + def cherry_pick assign_change_commit_vars(@commit.cherry_pick_branch_name) - + return render_404 if @target_branch.blank? create_commit(Commits::CherryPickService, success_notice: "The #{@commit.change_type_title} has been successfully cherry-picked.", diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb index 671d5c2302..af0b69a244 100644 --- a/app/controllers/projects/compare_controller.rb +++ b/app/controllers/projects/compare_controller.rb @@ -22,7 +22,8 @@ class Projects::CompareController < Projects::ApplicationController @base_commit = @project.merge_base_commit(@base_ref, @head_ref) @diffs = compare.diffs(diff_options) @diff_refs = [@base_commit, @commit] - @line_notes = [] + @diff_notes_disabled = true + @grouped_diff_notes = {} end end diff --git a/app/controllers/projects/container_registry_controller.rb b/app/controllers/projects/container_registry_controller.rb new file mode 100644 index 0000000000..d1f4649720 --- /dev/null +++ b/app/controllers/projects/container_registry_controller.rb @@ -0,0 +1,34 @@ +class Projects::ContainerRegistryController < Projects::ApplicationController + before_action :verify_registry_enabled + before_action :authorize_read_container_image! + before_action :authorize_update_container_image!, only: [:destroy] + layout 'project' + + def index + @tags = container_registry_repository.tags + end + + def destroy + url = namespace_project_container_registry_index_path(project.namespace, project) + + if tag.delete + redirect_to url + else + redirect_to url, alert: 'Failed to remove tag' + end + end + + private + + def verify_registry_enabled + render_404 unless Gitlab.config.registry.enabled + end + + def container_registry_repository + @container_registry_repository ||= project.container_registry_repository + end + + def tag + @tag ||= container_registry_repository.tag(params[:id]) + end +end diff --git a/app/controllers/projects/find_file_controller.rb b/app/controllers/projects/find_file_controller.rb index 54a0c447ae..cf53ad0a67 100644 --- a/app/controllers/projects/find_file_controller.rb +++ b/app/controllers/projects/find_file_controller.rb @@ -1,26 +1,26 @@ -# Controller for viewing a repository's file structure -class Projects::FindFileController < Projects::ApplicationController - include ExtractsPath - include ActionView::Helpers::SanitizeHelper - include TreeHelper - - before_action :require_non_empty_project - before_action :assign_ref_vars - before_action :authorize_download_code! - - def show - return render_404 unless @repository.commit(@ref) - - respond_to do |format| - format.html - end - end - - def list - file_paths = @repo.ls_files(@ref) - - respond_to do |format| - format.json { render json: file_paths } - end - end -end +# Controller for viewing a repository's file structure +class Projects::FindFileController < Projects::ApplicationController + include ExtractsPath + include ActionView::Helpers::SanitizeHelper + include TreeHelper + + before_action :require_non_empty_project + before_action :assign_ref_vars + before_action :authorize_download_code! + + def show + return render_404 unless @repository.commit(@ref) + + respond_to do |format| + format.html + end + end + + def list + file_paths = @repo.ls_files(@ref) + + respond_to do |format| + format.json { render json: file_paths } + end + end +end diff --git a/app/controllers/projects/hooks_controller.rb b/app/controllers/projects/hooks_controller.rb index dfa9bd259e..a60027ff47 100644 --- a/app/controllers/projects/hooks_controller.rb +++ b/app/controllers/projects/hooks_controller.rb @@ -27,8 +27,10 @@ class Projects::HooksController < Projects::ApplicationController if !@project.empty_repo? status, message = TestHookService.new.execute(hook, current_user) - if status - flash[:notice] = 'Hook successfully executed.' + if status && status >= 200 && status < 400 + flash[:notice] = "Hook executed successfully: HTTP #{status}" + elsif status + flash[:alert] = "Hook executed successfully but returned HTTP #{status} #{message}" else flash[:alert] = "Hook execution failed: #{message}" end @@ -61,7 +63,8 @@ class Projects::HooksController < Projects::ApplicationController :push_events, :tag_push_events, :token, - :url + :url, + :wiki_page_events ) end end diff --git a/app/controllers/projects/imports_controller.rb b/app/controllers/projects/imports_controller.rb index 7756f0f0ed..a1b84afcd9 100644 --- a/app/controllers/projects/imports_controller.rb +++ b/app/controllers/projects/imports_controller.rb @@ -20,6 +20,7 @@ class Projects::ImportsController < Projects::ApplicationController @project.import_retry else @project.import_start + @project.add_import_job end end diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 9c147b3689..d54284d7b2 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -73,12 +73,12 @@ class Projects::MergeRequestsController < Projects::ApplicationController # but we need it for the "View file @ ..." link by deleted files @base_commit ||= @merge_request.first_commit.parent || @merge_request.first_commit - @comments_allowed = @reply_allowed = true @comments_target = { noteable_type: 'MergeRequest', noteable_id: @merge_request.id } - @line_notes = @merge_request.notes.where("line_code is not null") + + @grouped_diff_notes = @merge_request.notes.grouped_diff_notes respond_to do |format| format.html @@ -117,6 +117,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController @commit = @merge_request.last_commit @base_commit = @merge_request.diff_base_commit @diffs = @merge_request.compare.diffs(diff_options) if @merge_request.compare + @diff_notes_disabled = true @ci_commit = @merge_request.ci_commit @statuses = @ci_commit.statuses if @ci_commit @@ -204,7 +205,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController end def branch_from - #This is always source + # This is always source @source_project = @merge_request.nil? ? @project : @merge_request.source_project @commit = @repository.commit(params[:ref]) if params[:ref].present? render layout: false @@ -228,6 +229,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController if ci_commit status = ci_commit.status coverage = ci_commit.try(:coverage) + + status ||= "preparing" else ci_service = @merge_request.source_project.ci_service status = ci_service.commit_status(merge_request.last_commit.sha, merge_request.source_branch) if ci_service @@ -237,8 +240,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController end end - status = "preparing" if status.nil? - response = { title: merge_request.title, sha: merge_request.last_commit_short_sha, @@ -300,7 +301,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController # Build a note object for comment form @note = @project.notes.new(noteable: @merge_request) @notes = @merge_request.mr_and_commit_notes.nonawards.inc_author.fresh - @discussions = Note.discussions_from_notes(@notes) + @discussions = @notes.discussions @noteable = @merge_request # Get commits from repository @@ -333,7 +334,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController params.require(:merge_request).permit( :title, :assignee_id, :source_project_id, :source_branch, :target_project_id, :target_branch, :milestone_id, - :state_event, :description, :task_num, label_ids: [] + :state_event, :description, :task_num, :force_remove_source_branch, + label_ids: [] ) end diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb index f7b6d137bd..da2892bfb3 100644 --- a/app/controllers/projects/milestones_controller.rb +++ b/app/controllers/projects/milestones_controller.rb @@ -75,7 +75,7 @@ class Projects::MilestonesController < Projects::ApplicationController respond_to do |format| format.html { redirect_to namespace_project_milestones_path } - format.js { render nothing: true } + format.js { head :ok } end end diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb index 707a0d0e5c..40b24d550e 100644 --- a/app/controllers/projects/notes_controller.rb +++ b/app/controllers/projects/notes_controller.rb @@ -43,7 +43,7 @@ class Projects::NotesController < Projects::ApplicationController end respond_to do |format| - format.js { render nothing: true } + format.js { head :ok } end end @@ -52,7 +52,7 @@ class Projects::NotesController < Projects::ApplicationController note.update_attribute(:attachment, nil) respond_to do |format| - format.js { render nothing: true } + format.js { head :ok } end end @@ -96,7 +96,7 @@ class Projects::NotesController < Projects::ApplicationController end def note_to_discussion_html(note) - return unless note.for_diff_line? + return unless note.diff_note? if params[:view] == 'parallel' template = "projects/notes/_diff_notes_with_reply_parallel" @@ -120,7 +120,7 @@ class Projects::NotesController < Projects::ApplicationController end def note_to_discussion_with_diff_html(note) - return unless note.for_diff_line? + return unless note.diff_note? render_to_string( "projects/notes/_discussion", @@ -158,7 +158,7 @@ class Projects::NotesController < Projects::ApplicationController def note_params params.require(:note).permit( :note, :noteable, :noteable_id, :noteable_type, :project_id, - :attachment, :line_code, :commit_id + :attachment, :line_code, :commit_id, :type ) end diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb new file mode 100644 index 0000000000..b36081205d --- /dev/null +++ b/app/controllers/projects/pipelines_controller.rb @@ -0,0 +1,59 @@ +class Projects::PipelinesController < Projects::ApplicationController + before_action :pipeline, except: [:index, :new, :create] + before_action :commit, only: [:show] + before_action :authorize_read_pipeline! + before_action :authorize_create_pipeline!, only: [:new, :create] + before_action :authorize_update_pipeline!, only: [:retry, :cancel] + + def index + @scope = params[:scope] + all_pipelines = project.ci_commits + @pipelines_count = all_pipelines.count + @running_or_pending_count = all_pipelines.running_or_pending.count + @pipelines = PipelinesFinder.new(project).execute(all_pipelines, @scope) + @pipelines = @pipelines.order(id: :desc).page(params[:page]).per(30) + end + + def new + @pipeline = project.ci_commits.new(ref: @project.default_branch) + end + + def create + @pipeline = Ci::CreatePipelineService.new(project, current_user, create_params).execute + unless @pipeline.persisted? + render 'new' + return + end + + redirect_to namespace_project_pipeline_path(project.namespace, project, @pipeline) + end + + def show + end + + def retry + pipeline.retry_failed + + redirect_back_or_default default: namespace_project_pipelines_path(project.namespace, project) + end + + def cancel + pipeline.cancel_running + + redirect_back_or_default default: namespace_project_pipelines_path(project.namespace, project) + end + + private + + def create_params + params.require(:pipeline).permit(:ref) + end + + def pipeline + @pipeline ||= project.ci_commits.find_by!(id: params[:id]) + end + + def commit + @commit ||= @pipeline.commit_data + end +end diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index 33b2625c0a..cdea5f0b77 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -55,7 +55,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController format.html do redirect_to namespace_project_project_members_path(@project.namespace, @project) end - format.js { render nothing: true } + format.js { head :ok } end end @@ -81,7 +81,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController respond_to do |format| format.html { redirect_to dashboard_projects_path, notice: "You left the project." } - format.js { render nothing: true } + format.js { head :ok } end else if current_user == @project.owner diff --git a/app/controllers/projects/protected_branches_controller.rb b/app/controllers/projects/protected_branches_controller.rb index e49259c34b..efa7bf14d0 100644 --- a/app/controllers/projects/protected_branches_controller.rb +++ b/app/controllers/projects/protected_branches_controller.rb @@ -39,7 +39,7 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController respond_to do |format| format.html { redirect_to namespace_project_protected_branches_path } - format.js { render nothing: true } + format.js { head :ok } end end diff --git a/app/controllers/projects/runners_controller.rb b/app/controllers/projects/runners_controller.rb index 0dd2d6a99b..0b4fa57250 100644 --- a/app/controllers/projects/runners_controller.rb +++ b/app/controllers/projects/runners_controller.rb @@ -20,7 +20,7 @@ class Projects::RunnersController < Projects::ApplicationController if @runner.update_attributes(runner_params) redirect_to runner_path(@runner), notice: 'Runner was successfully updated.' else - redirect_to runner_path(@runner), alert: 'Runner was not updated.' + render 'edit' end end @@ -64,6 +64,6 @@ class Projects::RunnersController < Projects::ApplicationController end def runner_params - params.require(:runner).permit(:description, :tag_list, :active) + params.require(:runner).permit(Ci::Runner::FORM_EDITABLE) end end diff --git a/app/controllers/projects/variables_controller.rb b/app/controllers/projects/variables_controller.rb index 0023465457..6f06872939 100644 --- a/app/controllers/projects/variables_controller.rb +++ b/app/controllers/projects/variables_controller.rb @@ -3,20 +3,44 @@ class Projects::VariablesController < Projects::ApplicationController layout 'project_settings' + def index + @variable = Ci::Variable.new + end + def show + @variable = @project.variables.find(params[:id]) end def update - if project.update_attributes(project_params) + @variable = @project.variables.find(params[:id]) + + if @variable.update_attributes(project_params) + redirect_to namespace_project_variables_path(project.namespace, project), notice: 'Variable was successfully updated.' + else + render action: "show" + end + end + + def create + @variable = Ci::Variable.new(project_params) + + if @variable.valid? && @project.variables << @variable redirect_to namespace_project_variables_path(project.namespace, project), notice: 'Variables were successfully updated.' else - render action: 'show' + render action: "index" end end + def destroy + @key = @project.variables.find(params[:id]) + @key.destroy + + redirect_to namespace_project_variables_path(project.namespace, project), notice: 'Variable was successfully removed.' + end + private def project_params - params.require(:project).permit({ variables_attributes: [:id, :key, :value, :_destroy] }) + params.require(:variable).permit([:id, :key, :value, :_destroy]) end end diff --git a/app/controllers/projects/wikis_controller.rb b/app/controllers/projects/wikis_controller.rb index 0d6c32fabd..4b404eb03f 100644 --- a/app/controllers/projects/wikis_controller.rb +++ b/app/controllers/projects/wikis_controller.rb @@ -91,8 +91,8 @@ class Projects::WikisController < Projects::ApplicationController def markdown_preview text = params[:text] - ext = Gitlab::ReferenceExtractor.new(@project, current_user, current_user) - ext.analyze(text) + ext = Gitlab::ReferenceExtractor.new(@project, current_user) + ext.analyze(text, author: current_user) render json: { body: view_context.markdown(text, pipeline: :wiki, project_wiki: @project_wiki), diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 3768efe142..f94e2a84fa 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -101,13 +101,7 @@ class ProjectsController < Projects::ApplicationController respond_to do |format| format.html do - if current_user - @membership = @project.team.find_member(current_user.id) - - if @membership - @notification_setting = current_user.notification_settings_for(@project) - end - end + @notification_setting = current_user.notification_settings_for(@project) if current_user if @project.repository_exists? if @project.empty_repo? @@ -147,6 +141,7 @@ class ProjectsController < Projects::ApplicationController @suggestions = { emojis: AwardEmoji.urls, issues: autocomplete.issues, + milestones: autocomplete.milestones, mergerequests: autocomplete.merge_requests, members: participants } @@ -202,8 +197,8 @@ class ProjectsController < Projects::ApplicationController def markdown_preview text = params[:text] - ext = Gitlab::ReferenceExtractor.new(@project, current_user, current_user) - ext.analyze(text) + ext = Gitlab::ReferenceExtractor.new(@project, current_user) + ext.analyze(text, author: current_user) render json: { body: view_context.markdown(text), @@ -235,7 +230,8 @@ class ProjectsController < Projects::ApplicationController def project_params params.require(:project).permit( :name, :path, :description, :issues_tracker, :tag_list, :runners_token, - :issues_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id, :default_branch, + :issues_enabled, :merge_requests_enabled, :snippets_enabled, :container_registry_enabled, + :issues_tracker_id, :default_branch, :wiki_enabled, :visibility_level, :import_url, :last_activity_at, :namespace_id, :avatar, :builds_enabled, :build_allow_git_fetch, :build_timeout_in_minutes, :build_coverage_regex, :public_builds, diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 352bff1938..75b78a49ea 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -37,8 +37,8 @@ class RegistrationsController < Devise::RegistrationsController super end - def after_sign_up_path_for(_resource) - users_almost_there_path + def after_sign_up_path_for(user) + user.confirmed? ? dashboard_projects_path : users_almost_there_path end def after_inactive_sign_up_path_for(_resource) diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index c29f4609e9..d68c2a708e 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -1,5 +1,6 @@ class SessionsController < Devise::SessionsController include AuthenticatesWithTwoFactor + include Devise::Controllers::Rememberable include Recaptcha::ClientHelper skip_before_action :check_2fa_requirement, only: [:destroy] @@ -96,6 +97,7 @@ class SessionsController < Devise::SessionsController # Remove any lingering user data from login session.delete(:otp_user_id) + remember_me(user) if user_params[:remember_me] == '1' sign_in(user) and return else flash.now[:alert] = 'Invalid two-factor code.' diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb index 2daceed039..2a17c1f34d 100644 --- a/app/controllers/snippets_controller.rb +++ b/app/controllers/snippets_controller.rb @@ -10,7 +10,7 @@ class SnippetsController < ApplicationController # Allow destroy snippet before_action :authorize_admin_snippet!, only: [:destroy] - skip_before_action :authenticate_user!, only: [:index, :user_index, :show, :raw] + skip_before_action :authenticate_user!, only: [:index, :show, :raw] layout 'snippets' respond_to :html diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 2ae180c8a1..a99632454d 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -58,11 +58,22 @@ class UsersController < ApplicationController end end + def snippets + load_snippets + + respond_to do |format| + format.html { render 'show' } + format.json do + render json: { + html: view_to_html_string("snippets/_snippets", collection: @snippets) + } + end + end + end + def calendar calendar = contributions_calendar @timestamps = calendar.timestamps - @starting_year = calendar.starting_year - @starting_month = calendar.starting_month render 'calendar', layout: false end @@ -116,6 +127,15 @@ class UsersController < ApplicationController @groups = JoinedGroupsFinder.new(user).execute(current_user) end + def load_snippets + @snippets = SnippetsFinder.new.execute( + current_user, + filter: :by_user, + user: user, + scope: params[:scope] + ).page(params[:page]) + end + def projects_for_current_user ProjectsFinder.new.execute(current_user) end diff --git a/app/finders/group_projects_finder.rb b/app/finders/group_projects_finder.rb index 3b9a421b11..aa8f4c1d0e 100644 --- a/app/finders/group_projects_finder.rb +++ b/app/finders/group_projects_finder.rb @@ -18,7 +18,7 @@ class GroupProjectsFinder < UnionFinder projects = [] if current_user - if @group.users.include?(current_user) + if @group.users.include?(current_user) || current_user.admin? projects << @group.projects unless only_shared projects << @group.shared_projects unless only_owned else diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb index f00f3f709e..7d8c56f4c2 100644 --- a/app/finders/issuable_finder.rb +++ b/app/finders/issuable_finder.rb @@ -250,12 +250,12 @@ class IssuableFinder def by_milestone(items) if milestones? if filter_by_no_milestone? - items = items.where(milestone_id: [-1, nil]) + items = items.left_joins_milestones.where(milestone_id: [-1, nil]) elsif filter_by_upcoming_milestone? - upcoming = Milestone.where(project_id: projects).upcoming - items = items.joins(:milestone).where(milestones: { title: upcoming.try(:title) }) + upcoming_ids = Milestone.upcoming_ids_by_projects(projects) + items = items.left_joins_milestones.where(milestone_id: upcoming_ids) else - items = items.joins(:milestone).where(milestones: { title: params[:milestone_title] }) + items = items.with_milestone(params[:milestone_title]) if projects items = items.where(milestones: { project_id: projects }) @@ -271,7 +271,7 @@ class IssuableFinder if filter_by_no_label? items = items.without_label else - items = items.with_label(label_names) + items = items.with_label(label_names, params[:sort]) if projects items = items.where(labels: { project_id: projects }) end diff --git a/app/finders/notes_finder.rb b/app/finders/notes_finder.rb index fa4c635f55..c41be33353 100644 --- a/app/finders/notes_finder.rb +++ b/app/finders/notes_finder.rb @@ -10,7 +10,7 @@ class NotesFinder notes = case target_type when "commit" - project.notes.for_commit_id(target_id).not_inline + project.notes.for_commit_id(target_id).non_diff_notes when "issue" project.issues.find(target_id).notes.nonawards.inc_author when "merge_request" diff --git a/app/finders/pipelines_finder.rb b/app/finders/pipelines_finder.rb new file mode 100644 index 0000000000..c19a795d46 --- /dev/null +++ b/app/finders/pipelines_finder.rb @@ -0,0 +1,38 @@ +class PipelinesFinder + attr_reader :project + + def initialize(project) + @project = project + end + + def execute(pipelines, scope) + case scope + when 'running' + pipelines.running_or_pending + when 'branches' + from_ids(pipelines, ids_for_ref(pipelines, branches)) + when 'tags' + from_ids(pipelines, ids_for_ref(pipelines, tags)) + else + pipelines + end + end + + private + + def ids_for_ref(pipelines, refs) + pipelines.where(ref: refs).group(:ref).select('max(id)') + end + + def from_ids(pipelines, ids) + pipelines.unscoped.where(id: ids) + end + + def branches + project.repository.branches.map(&:name) + end + + def tags + project.repository.tags.map(&:name) + end +end diff --git a/app/finders/todos_finder.rb b/app/finders/todos_finder.rb index 3ba27c4050..4bd46a7608 100644 --- a/app/finders/todos_finder.rb +++ b/app/finders/todos_finder.rb @@ -36,7 +36,7 @@ class TodosFinder private def action_id? - action_id.present? && [Todo::ASSIGNED, Todo::MENTIONED].include?(action_id.to_i) + action_id.present? && [Todo::ASSIGNED, Todo::MENTIONED, Todo::BUILD_FAILED].include?(action_id.to_i) end def action_id diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 3e0074da39..439b015b3b 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -110,8 +110,7 @@ module ApplicationHelper ] # If reference is commit id - we should add it to branch/tag selectbox - if(@ref && !options.flatten.include?(@ref) && - @ref =~ /\A[0-9a-zA-Z]{6,52}\z/) + if @ref && !options.flatten.include?(@ref) && @ref =~ /\A[0-9a-zA-Z]{6,52}\z/ options << ['Commit', [@ref]] end @@ -263,6 +262,8 @@ module ApplicationHelper assignee_id: params[:assignee_id], author_id: params[:author_id], sort: params[:sort], + issue_search: params[:issue_search], + label_name: params[:label_name] } options = exist_opts.merge(options) @@ -273,16 +274,11 @@ module ApplicationHelper end end - path = request.path - path << "?#{options.to_param}" - if add_label - if params[:label_name].present? and params[:label_name].respond_to?('any?') - params[:label_name].each do |label| - path << "&label_name[]=#{label}" - end - end - end - path + params = options.compact + + params.delete(:label_name) unless add_label + + "#{request.path}?#{params.to_param}" end def outdated_browser? diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index 914b0ef604..03080d2593 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -60,4 +60,18 @@ module ApplicationSettingsHelper end end end + + def oauth_providers_checkboxes + button_based_providers.map do |source| + disabled = current_application_settings.disabled_oauth_sign_in_sources.include?(source.to_s) + css_class = 'btn' + css_class << ' active' unless disabled + checkbox_name = 'application_setting[enabled_oauth_sign_in_sources][]' + + label_tag(checkbox_name, class: css_class) do + check_box_tag(checkbox_name, source, !disabled, + autocomplete: 'off') + Gitlab::OAuth::Provider.label_for(source) + end + end + end end diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb index b4f80fd9b3..b05fa0a14d 100644 --- a/app/helpers/auth_helper.rb +++ b/app/helpers/auth_helper.rb @@ -38,6 +38,16 @@ module AuthHelper auth_providers.reject { |provider| form_based_provider?(provider) } end + def enabled_button_based_providers + disabled_providers = current_application_settings.disabled_oauth_sign_in_sources || [] + + button_based_providers.map(&:to_s) - disabled_providers + end + + def button_based_providers_enabled? + enabled_button_based_providers.any? + end + def provider_image_tag(provider, size = 64) label = label_for_provider(provider) diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index 93241b3afb..cec2dc753f 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -184,4 +184,14 @@ module BlobHelper Other: licenses.reject(&:featured).map { |license| [license.name, license.key] } } end + + def gitignore_names + return @gitignore_names if defined?(@gitignore_names) + + @gitignore_names = { + Global: Gitlab::Gitignore.global.map { |gitignore| { name: gitignore.name } }, + # Note that the key here doesn't cover it really + Languages: Gitlab::Gitignore.languages_frameworks.map{ |gitignore| { name: gitignore.name } } + } + end end diff --git a/app/helpers/button_helper.rb b/app/helpers/button_helper.rb index a9047ede8c..f742922d92 100644 --- a/app/helpers/button_helper.rb +++ b/app/helpers/button_helper.rb @@ -30,7 +30,7 @@ module ButtonHelper content_tag :a, protocol, class: klass, - href: @project.http_url_to_repo, + href: project.http_url_to_repo, data: { html: true, placement: 'right', diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb index 417050b413..cfad17dcac 100644 --- a/app/helpers/ci_status_helper.rb +++ b/app/helpers/ci_status_helper.rb @@ -38,19 +38,30 @@ module CiStatusHelper icon(icon_name + ' fw') end - def render_ci_status(ci_commit, tooltip_placement: 'auto left') - # TODO: split this method into - # - render_commit_status - # - render_pipeline_status - link_to ci_icon_for_status(ci_commit.status), - ci_status_path(ci_commit), - class: "ci-status-link ci-status-icon-#{ci_commit.status.dasherize}", - title: "Build #{ci_label_for_status(ci_commit.status)}", - data: { toggle: 'tooltip', placement: tooltip_placement } + def render_commit_status(commit, tooltip_placement: 'auto left') + project = commit.project + path = builds_namespace_project_commit_path(project.namespace, project, commit) + render_status_with_link('commit', commit.status, path, tooltip_placement) + end + + def render_pipeline_status(pipeline, tooltip_placement: 'auto left') + project = pipeline.project + path = namespace_project_pipeline_path(project.namespace, project, pipeline) + render_status_with_link('pipeline', pipeline.status, path, tooltip_placement) end def no_runners_for_project?(project) project.runners.blank? && Ci::Runner.shared.blank? end + + private + + def render_status_with_link(type, status, path, tooltip_placement) + link_to ci_icon_for_status(status), + path, + class: "ci-status-link ci-status-icon-#{status.dasherize}", + title: "#{type.titleize}: #{ci_label_for_status(status)}", + data: { toggle: 'tooltip', placement: tooltip_placement } + end end diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index b59c3982ed..d328f56c80 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -123,13 +123,14 @@ module CommitsHelper ) end - def revert_commit_link(commit, continue_to_path, btn_class: nil) + def revert_commit_link(commit, continue_to_path, btn_class: nil, has_tooltip: true) return unless current_user - tooltip = "Revert this #{commit.change_type_title} in a new merge request" + tooltip = "Revert this #{commit.change_type_title} in a new merge request" if has_tooltip if can_collaborate_with_project? - link_to 'Revert', '#modal-revert-commit', 'data-toggle' => 'modal', 'data-container' => 'body', title: tooltip, class: "btn btn-default btn-grouped btn-#{btn_class} has-tooltip" + btn_class = "btn btn-grouped btn-close btn-#{btn_class}" unless btn_class.nil? + link_to 'Revert', '#modal-revert-commit', 'data-toggle' => 'modal', 'data-container' => 'body', title: (tooltip if has_tooltip), class: "#{btn_class} #{'has-tooltip' if has_tooltip}" elsif can?(current_user, :fork_project, @project) continue_params = { to: continue_to_path, @@ -140,17 +141,20 @@ module CommitsHelper namespace_key: current_user.namespace.id, continue: continue_params) - link_to 'Revert', fork_path, class: 'btn btn-grouped btn-close', method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: tooltip + btn_class = "btn btn-grouped btn-close" unless btn_class.nil? + + link_to 'Revert', fork_path, class: btn_class, method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: (tooltip if has_tooltip) end end - def cherry_pick_commit_link(commit, continue_to_path, btn_class: nil) + def cherry_pick_commit_link(commit, continue_to_path, btn_class: nil, has_tooltip: true) return unless current_user tooltip = "Cherry-pick this #{commit.change_type_title} in a new merge request" if can_collaborate_with_project? - link_to 'Cherry-pick', '#modal-cherry-pick-commit', 'data-toggle' => 'modal', 'data-container' => 'body', title: tooltip, class: "btn btn-default btn-grouped btn-#{btn_class} has-tooltip" + btn_class = "btn btn-default btn-grouped btn-#{btn_class}" unless btn_class.nil? + link_to 'Cherry-pick', '#modal-cherry-pick-commit', 'data-toggle' => 'modal', 'data-container' => 'body', title: (tooltip if has_tooltip), class: "#{btn_class} #{'has-tooltip' if has_tooltip}" elsif can?(current_user, :fork_project, @project) continue_params = { to: continue_to_path, @@ -161,7 +165,8 @@ module CommitsHelper namespace_key: current_user.namespace.id, continue: continue_params) - link_to 'Cherry-pick', fork_path, class: 'btn btn-grouped btn-close', method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: tooltip + btn_class = "btn btn-grouped btn-close" unless btn_class.nil? + link_to 'Cherry-pick', fork_path, class: "#{btn_class}", method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: (tooltip if has_tooltip) end end diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index 9f73edb455..cbe4717683 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -2,8 +2,8 @@ module DiffHelper def mark_inline_diffs(old_line, new_line) old_diffs, new_diffs = Gitlab::Diff::InlineDiff.new(old_line, new_line).inline_diffs - marked_old_line = Gitlab::Diff::InlineDiffMarker.new(old_line).mark(old_diffs) - marked_new_line = Gitlab::Diff::InlineDiffMarker.new(new_line).mark(new_diffs) + marked_old_line = Gitlab::Diff::InlineDiffMarker.new(old_line).mark(old_diffs, mode: :deletion) + marked_new_line = Gitlab::Diff::InlineDiffMarker.new(new_line).mark(new_diffs, mode: :addition) [marked_old_line, marked_new_line] end @@ -39,11 +39,11 @@ module DiffHelper end def unfold_bottom_class(bottom) - (bottom) ? 'js-unfold-bottom' : '' + bottom ? 'js-unfold-bottom' : '' end def unfold_class(unfold) - (unfold) ? 'unfold js-unfold' : '' + unfold ? 'unfold js-unfold' : '' end def diff_line_content(line, line_type = nil) @@ -55,22 +55,18 @@ module DiffHelper end end - def line_comments - @line_comments ||= @line_notes.select(&:active?).sort_by(&:created_at).group_by(&:line_code) - end + def organize_comments(left, right) + notes_left = notes_right = nil - def organize_comments(type_left, type_right, line_code_left, line_code_right) - comments_left = comments_right = nil - - unless type_left.nil? && type_right == 'new' - comments_left = line_comments[line_code_left] + unless left[:type].nil? && right[:type] == 'new' + notes_left = @grouped_diff_notes[left[:line_code]] end - unless type_left.nil? && type_right.nil? - comments_right = line_comments[line_code_right] + unless left[:type].nil? && right[:type].nil? + notes_right = @grouped_diff_notes[right[:line_code]] end - [comments_left, comments_right] + [notes_left, notes_right] end def inline_diff_btn @@ -96,8 +92,8 @@ module DiffHelper ].join(' ').html_safe end - def commit_for_diff(diff) - if diff.deleted_file + def commit_for_diff(diff_file) + if diff_file.deleted_file @base_commit || @commit.parent || @commit else @commit diff --git a/app/helpers/emails_helper.rb b/app/helpers/emails_helper.rb index 41b5bd7be9..8466d0aa0b 100644 --- a/app/helpers/emails_helper.rb +++ b/app/helpers/emails_helper.rb @@ -32,12 +32,6 @@ module EmailsHelper nil end - def color_email_diff(diffcontent) - formatter = Rouge::Formatters::HTML.new(css_class: 'highlight', inline_theme: 'github') - lexer = Rouge::Lexers::Diff - raw formatter.format(lexer.lex(diffcontent)) - end - def password_reset_token_valid_time valid_hours = Devise.reset_password_within / 60 / 60 if valid_hours >= 24 diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb index 592bad8ba2..bfedcb1c42 100644 --- a/app/helpers/events_helper.rb +++ b/app/helpers/events_helper.rb @@ -3,7 +3,7 @@ module EventsHelper author = event.author if author - link_to author.name, user_path(author.username), title: h(author.name) + link_to author.name, user_path(author.username), title: author.name else event.author_name end @@ -39,15 +39,6 @@ module EventsHelper end end - def icon_for_event - { - EventFilter.push => 'upload', - EventFilter.merged => 'check-square-o', - EventFilter.comments => 'comments', - EventFilter.team => 'user', - } - end - def event_preposition(event) if event.push? || event.commented? || event.target "at" @@ -66,11 +57,7 @@ module EventsHelper words << event.ref_name words << "at" elsif event.commented? - if event.note_commit? - words << event.note_short_commit_id - else - words << "##{truncate event.note_target_iid}" - end + words << event.note_target_reference words << "at" elsif event.milestone? words << "##{event.target_iid}" if event.target_iid @@ -93,21 +80,12 @@ module EventsHelper elsif event.merge_request? namespace_project_merge_request_url(event.project.namespace, event.project, event.merge_request) - elsif event.note? && event.note_commit? + elsif event.note? && event.commit_note? namespace_project_commit_url(event.project.namespace, event.project, event.note_target) elsif event.note? if event.note_target - if event.note_commit? - namespace_project_commit_path(event.project.namespace, event.project, - event.note_commit_id, - anchor: dom_id(event.target)) - elsif event.note_project_snippet? - namespace_project_snippet_path(event.project.namespace, - event.project, event.note_target) - else - event_note_target_path(event) - end + event_note_target_path(event) end elsif event.push? push_event_feed_url(event) @@ -143,42 +121,30 @@ module EventsHelper end def event_note_target_path(event) - if event.note? && event.note_commit? - namespace_project_commit_path(event.project.namespace, event.project, - event.note_target) + if event.note? && event.commit_note? + namespace_project_commit_path(event.project.namespace, + event.project, + event.note_target, + anchor: dom_id(event.target)) + elsif event.project_snippet_note? + namespace_project_snippet_path(event.project.namespace, + event.project, + event.note_target, + anchor: dom_id(event.target)) else polymorphic_path([event.project.namespace.becomes(Namespace), event.project, event.note_target], - anchor: dom_id(event.target)) + anchor: dom_id(event.target)) end end def event_note_title_html(event) if event.note_target - if event.note_commit? - link_to( - namespace_project_commit_path(event.project.namespace, event.project, - event.note_commit_id, - anchor: dom_id(event.target), title: h(event.target_title)), - class: "commit_short_id" - ) do - "#{event.note_target_type} #{event.note_short_commit_id}" - end - elsif event.note_project_snippet? - link_to(namespace_project_snippet_path(event.project.namespace, - event.project, - event.note_target), title: h(event.project.name)) do - "#{event.note_target_type} #{truncate event.note_target.to_reference}" - end - else - link_to event_note_target_path(event) do - "#{event.note_target_type} #{truncate event.note_target.to_reference}" - end + link_to(event_note_target_path(event), title: event.target_title, class: 'has-tooltip') do + "#{event.note_target_type} #{event.note_target_reference}" end else - content_tag :strong do - "(deleted)" - end + content_tag(:strong, '(deleted)') end end @@ -193,28 +159,6 @@ module EventsHelper "--broken encoding" end - def event_to_atom(xml, event) - if event.visible_to_user?(current_user) - xml.entry do - event_link = event_feed_url(event) - event_title = event_feed_title(event) - event_summary = event_feed_summary(event) - - xml.id "tag:#{request.host},#{event.created_at.strftime("%Y-%m-%d")}:#{event.id}" - xml.link href: event_link - xml.title truncate(event_title, length: 80) - xml.updated event.created_at.xmlschema - xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(event.author_email)) - xml.author do |author| - xml.name event.author_name - xml.email event.author_email - end - - xml.summary(type: "xhtml") { |x| x << event_summary unless event_summary.nil? } - end - end - end - def event_row_class(event) if event.body? "event-block" diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb index 3a45205563..0a1b48af21 100644 --- a/app/helpers/gitlab_markdown_helper.rb +++ b/app/helpers/gitlab_markdown_helper.rb @@ -13,7 +13,7 @@ module GitlabMarkdownHelper def link_to_gfm(body, url, html_options = {}) return "" if body.blank? - escaped_body = if body =~ /\A\ opts[:push_code_to_protected_branches], - author_id: opts[:author_id] || '' + author_id: opts[:author_id] || '' } } diff --git a/app/helpers/tab_helper.rb b/app/helpers/tab_helper.rb index 96a8367100..563ddd2a51 100644 --- a/app/helpers/tab_helper.rb +++ b/app/helpers/tab_helper.rb @@ -95,7 +95,9 @@ module TabHelper end def project_tab_class - return "active" if current_page?(controller: "/projects", action: :edit, id: @project) + if controller.controller_path.start_with?('projects') + return 'active' + end if ['services', 'hooks', 'deploy_keys', 'protected_branches'].include? controller.controller_name "active" @@ -112,7 +114,7 @@ module TabHelper end def profile_tab_class - if controller.controller_path =~ /\Aprofiles/ + if controller.controller_path.start_with?('profiles') return 'active' end diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb index 2f06668218..b4923fbb13 100644 --- a/app/helpers/todos_helper.rb +++ b/app/helpers/todos_helper.rb @@ -11,12 +11,15 @@ module TodosHelper case todo.action when Todo::ASSIGNED then 'assigned you' when Todo::MENTIONED then 'mentioned you on' + when Todo::BUILD_FAILED then 'The build failed for your' end end def todo_target_link(todo) target = todo.target_type.titleize.downcase - link_to "#{target} #{todo.target_reference}", todo_target_path(todo), { title: todo.target.title } + link_to "#{target} #{todo.target_reference}", todo_target_path(todo), + class: 'has-tooltip', + title: todo.target.title end def todo_target_path(todo) @@ -28,8 +31,21 @@ module TodosHelper namespace_project_commit_path(todo.project.namespace.becomes(Namespace), todo.project, todo.target, anchor: anchor) else - polymorphic_path([todo.project.namespace.becomes(Namespace), - todo.project, todo.target], anchor: anchor) + path = [todo.project.namespace.becomes(Namespace), todo.project, todo.target] + + path.unshift(:builds) if todo.build_failed? + + polymorphic_path(path, anchor: anchor) + end + end + + def todo_target_state_pill(todo) + return unless show_todo_state?(todo) + + content_tag(:span, nil, class: 'target-status') do + content_tag(:span, nil, class: "status-box status-box-#{todo.target.state.dasherize}") do + todo.target.state.capitalize + end end end @@ -91,4 +107,10 @@ module TodosHelper options_from_collection_for_select(types, 'name', 'title', params[:type]) end + + private + + def show_todo_state?(todo) + (todo.target.is_a?(MergeRequest) || todo.target.is_a?(Issue)) && ['closed', 'merged'].include?(todo.target.state) + end end diff --git a/app/mailers/devise_mailer.rb b/app/mailers/devise_mailer.rb index b616add283..415f6e1288 100644 --- a/app/mailers/devise_mailer.rb +++ b/app/mailers/devise_mailer.rb @@ -1,4 +1,6 @@ class DeviseMailer < Devise::Mailer default from: "#{Gitlab.config.gitlab.email_display_name} <#{Gitlab.config.gitlab.email_from}>" default reply_to: Gitlab.config.gitlab.email_reply_to + + layout 'devise_mailer' end diff --git a/app/mailers/emails/projects.rb b/app/mailers/emails/projects.rb index 377c2999d6..fdf1e9f5af 100644 --- a/app/mailers/emails/projects.rb +++ b/app/mailers/emails/projects.rb @@ -59,20 +59,20 @@ module Emails subject: subject("Project was moved")) end - def repository_push_email(project_id, recipient, opts = {}) + def repository_push_email(project_id, opts = {}) @message = - Gitlab::Email::Message::RepositoryPush.new(self, project_id, recipient, opts) + Gitlab::Email::Message::RepositoryPush.new(self, project_id, opts) # used in notify layout @target_url = @message.target_url - @project = Project.find project_id + @project = Project.find(project_id) + @diff_notes_disabled = true add_project_headers headers['X-GitLab-Author'] = @message.author_username mail(from: sender(@message.author_id, @message.send_from_committer_email?), reply_to: @message.reply_to, - to: @message.recipient, subject: @message.subject) end end diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb index 826e5f96fa..1c663bdd52 100644 --- a/app/mailers/notify.rb +++ b/app/mailers/notify.rb @@ -10,6 +10,8 @@ class Notify < BaseMailer include Emails::Builds add_template_helper MergeRequestsHelper + add_template_helper DiffHelper + add_template_helper BlobHelper add_template_helper EmailsHelper def test_email(recipient_email, subject, body) diff --git a/app/models/ability.rb b/app/models/ability.rb index 6103a2947e..44515550d9 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -23,20 +23,41 @@ class Ability end.concat(global_abilities(user)) end + # Given a list of users and a project this method returns the users that can + # read the given project. + def users_that_can_read_project(users, project) + if project.public? + users + else + users.select do |user| + if user.admin? + true + elsif project.internal? && !user.external? + true + elsif project.owner == user + true + elsif project.team.members.include?(user) + true + else + false + end + end + end + end + # List of possible abilities for anonymous user def anonymous_abilities(user, subject) - case true - when subject.is_a?(PersonalSnippet) + if subject.is_a?(PersonalSnippet) anonymous_personal_snippet_abilities(subject) - when subject.is_a?(ProjectSnippet) + elsif subject.is_a?(ProjectSnippet) anonymous_project_snippet_abilities(subject) - when subject.is_a?(CommitStatus) + elsif subject.is_a?(CommitStatus) anonymous_commit_status_abilities(subject) - when subject.is_a?(Project) || subject.respond_to?(:project) + elsif subject.is_a?(Project) || subject.respond_to?(:project) anonymous_project_abilities(subject) - when subject.is_a?(Group) || subject.respond_to?(:group) + elsif subject.is_a?(Group) || subject.respond_to?(:group) anonymous_group_abilities(subject) - when subject.is_a?(User) + elsif subject.is_a?(User) anonymous_user_abilities else [] @@ -60,7 +81,9 @@ class Ability :read_project_member, :read_merge_request, :read_note, + :read_pipeline, :read_commit_status, + :read_container_image, :download_code ] @@ -203,6 +226,8 @@ class Ability :admin_label, :read_commit_status, :read_build, + :read_container_image, + :read_pipeline, ] end @@ -214,9 +239,13 @@ class Ability :update_commit_status, :create_build, :update_build, + :create_pipeline, + :update_pipeline, :create_merge_request, :create_wiki, - :push_code + :push_code, + :create_container_image, + :update_container_image, ] end @@ -242,7 +271,9 @@ class Ability :admin_wiki, :admin_project, :admin_commit_status, - :admin_build + :admin_build, + :admin_container_image, + :admin_pipeline ] end @@ -285,6 +316,11 @@ class Ability unless project.builds_enabled rules += named_abilities('build') + rules += named_abilities('pipeline') + end + + unless project.container_registry_enabled + rules += named_abilities('container_image') end rules diff --git a/app/models/abuse_report.rb b/app/models/abuse_report.rb index b61f512312..b01a244032 100644 --- a/app/models/abuse_report.rb +++ b/app/models/abuse_report.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: abuse_reports -# -# id :integer not null, primary key -# reporter_id :integer -# user_id :integer -# message :text -# created_at :datetime -# updated_at :datetime -# - class AbuseReport < ActiveRecord::Base belongs_to :reporter, class_name: 'User' belongs_to :user diff --git a/app/models/appearance.rb b/app/models/appearance.rb index 4528760fef..4cf8dd9a8c 100644 --- a/app/models/appearance.rb +++ b/app/models/appearance.rb @@ -1,16 +1,3 @@ -# == Schema Information -# -# Table name: appearances -# -# id :integer not null, primary key -# title :string -# description :text -# header_logo :string -# logo :string -# created_at :datetime not null -# updated_at :datetime not null -# - class Appearance < ActiveRecord::Base validates :title, presence: true validates :description, presence: true diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 72ec91d290..42f908aa34 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -1,63 +1,13 @@ -# == Schema Information -# -# Table name: application_settings -# -# id :integer not null, primary key -# default_projects_limit :integer -# signup_enabled :boolean -# signin_enabled :boolean -# gravatar_enabled :boolean -# sign_in_text :text -# created_at :datetime -# updated_at :datetime -# home_page_url :string -# default_branch_protection :integer default(2) -# restricted_visibility_levels :text -# version_check_enabled :boolean default(TRUE) -# max_attachment_size :integer default(10), not null -# default_project_visibility :integer -# default_snippet_visibility :integer -# restricted_signup_domains :text -# user_oauth_applications :boolean default(TRUE) -# after_sign_out_path :string -# session_expire_delay :integer default(10080), not null -# import_sources :text -# help_page_text :text -# admin_notification_email :string -# shared_runners_enabled :boolean default(TRUE), not null -# max_artifacts_size :integer default(100), not null -# runners_registration_token :string -# require_two_factor_authentication :boolean default(FALSE) -# two_factor_grace_period :integer default(48) -# metrics_enabled :boolean default(FALSE) -# metrics_host :string default("localhost") -# metrics_pool_size :integer default(16) -# metrics_timeout :integer default(10) -# metrics_method_call_threshold :integer default(10) -# recaptcha_enabled :boolean default(FALSE) -# recaptcha_site_key :string -# recaptcha_private_key :string -# metrics_port :integer default(8089) -# metrics_sample_interval :integer default(15) -# sentry_enabled :boolean default(FALSE) -# sentry_dsn :string -# akismet_enabled :boolean default(FALSE) -# akismet_api_key :string -# email_author_in_body :boolean default(FALSE) -# default_group_visibility :integer -# repository_checks_enabled :boolean default(FALSE) -# metrics_packet_size :integer default(1) -# shared_runners_text :text -# - class ApplicationSetting < ActiveRecord::Base include TokenAuthenticatable add_authentication_token_field :runners_registration_token + add_authentication_token_field :health_check_access_token CACHE_KEY = 'application_setting.last' serialize :restricted_visibility_levels serialize :import_sources + serialize :disabled_oauth_sign_in_sources, Array serialize :restricted_signup_domains, Array attr_accessor :restricted_signup_domains_raw @@ -101,6 +51,10 @@ class ApplicationSetting < ActiveRecord::Base presence: true, numericality: { only_integer: true, greater_than: 0 } + validates :container_registry_token_expire_delay, + presence: true, + numericality: { only_integer: true, greater_than: 0 } + validates_each :restricted_visibility_levels do |record, attr, value| unless value.nil? value.each do |level| @@ -121,7 +75,18 @@ class ApplicationSetting < ActiveRecord::Base end end + validates_each :disabled_oauth_sign_in_sources do |record, attr, value| + unless value.nil? + value.each do |source| + unless Devise.omniauth_providers.include?(source.to_sym) + record.errors.add(attr, "'#{source}' is not an OAuth sign-in source") + end + end + end + end + before_save :ensure_runners_registration_token + before_save :ensure_health_check_access_token after_commit do Rails.cache.write(CACHE_KEY, self) @@ -137,6 +102,10 @@ class ApplicationSetting < ActiveRecord::Base Rails.cache.delete(CACHE_KEY) end + def self.cached + Rails.cache.fetch(CACHE_KEY) + end + def self.create_from_defaults create( default_projects_limit: Settings.gitlab['default_projects_limit'], @@ -159,6 +128,9 @@ class ApplicationSetting < ActiveRecord::Base recaptcha_enabled: false, akismet_enabled: false, repository_checks_enabled: true, + disabled_oauth_sign_in_sources: [], + send_user_confirmation_email: false, + container_registry_token_expire_delay: 5, ) end @@ -185,4 +157,8 @@ class ApplicationSetting < ActiveRecord::Base def runners_registration_token ensure_runners_registration_token! end + + def health_check_access_token + ensure_health_check_access_token! + end end diff --git a/app/models/audit_event.rb b/app/models/audit_event.rb index 44b090260e..967ffd46db 100644 --- a/app/models/audit_event.rb +++ b/app/models/audit_event.rb @@ -1,17 +1,3 @@ -# == Schema Information -# -# Table name: audit_events -# -# id :integer not null, primary key -# author_id :integer not null -# type :string not null -# entity_id :integer not null -# entity_type :string not null -# details :text -# created_at :datetime -# updated_at :datetime -# - class AuditEvent < ActiveRecord::Base serialize :details, Hash diff --git a/app/models/broadcast_message.rb b/app/models/broadcast_message.rb index 075ac733bf..61498140f2 100644 --- a/app/models/broadcast_message.rb +++ b/app/models/broadcast_message.rb @@ -1,17 +1,3 @@ -# == Schema Information -# -# Table name: broadcast_messages -# -# id :integer not null, primary key -# message :text not null -# starts_at :datetime -# ends_at :datetime -# created_at :datetime -# updated_at :datetime -# color :string -# font :string -# - class BroadcastMessage < ActiveRecord::Base include Sortable diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 4bc3a225e2..64723ab6b4 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -1,40 +1,3 @@ -# == Schema Information -# -# Table name: ci_builds -# -# id :integer not null, primary key -# project_id :integer -# status :string -# finished_at :datetime -# trace :text -# created_at :datetime -# updated_at :datetime -# started_at :datetime -# runner_id :integer -# coverage :float -# commit_id :integer -# commands :text -# job_id :integer -# name :string -# deploy :boolean default(FALSE) -# options :text -# allow_failure :boolean default(FALSE), not null -# stage :string -# trigger_request_id :integer -# stage_idx :integer -# tag :boolean -# ref :string -# user_id :integer -# type :string -# target_url :string -# description :string -# artifacts_file :text -# gl_project_id :integer -# artifacts_metadata :text -# erased_by_id :integer -# erased_at :datetime -# - module Ci class Build < CommitStatus belongs_to :runner, class_name: 'Ci::Runner' @@ -90,6 +53,7 @@ module Ci new_build.stage_idx = build.stage_idx new_build.trigger_request = build.trigger_request new_build.save + MergeRequests::AddTodoWhenBuildFailsService.new(build.project, nil).close(new_build) new_build end end @@ -132,8 +96,12 @@ module Ci end def trace_html - html = Ci::Ansi2html::convert(trace) if trace.present? - html || '' + trace_with_state[:html] || '' + end + + def trace_with_state(state = nil) + trace_with_state = Ci::Ansi2html::convert(trace, state) if trace.present? + trace_with_state || {} end def timeout @@ -238,7 +206,7 @@ module Ci end def recreate_trace_dir - unless Dir.exists?(dir_to_trace) + unless Dir.exist?(dir_to_trace) FileUtils.mkdir_p(dir_to_trace) end end @@ -318,14 +286,20 @@ module Ci project.runners_token end - def valid_token? token + def valid_token?(token) project.valid_runners_token? token end def can_be_served?(runner) + return false unless has_tags? || runner.run_untagged? + (tag_list - runner.tag_list).empty? end + def has_tags? + tag_list.any? + end + def any_runners_online? project.any_runners? { |runner| runner.active? && runner.online? && can_be_served?(runner) } end @@ -339,6 +313,7 @@ module Ci build_data = Gitlab::BuildDataBuilder.build(self) project.execute_hooks(build_data.dup, :build_hooks) project.execute_services(build_data.dup, :build_hooks) + project.running_or_pending_build_count(force: true) end def artifacts? diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb index 4ac4e0fb8b..f22b573a94 100644 --- a/app/models/ci/commit.rb +++ b/app/models/ci/commit.rb @@ -1,25 +1,3 @@ -# == Schema Information -# -# Table name: ci_commits -# -# id :integer not null, primary key -# project_id :integer -# ref :string -# sha :string -# before_sha :string -# push_data :text -# created_at :datetime -# updated_at :datetime -# tag :boolean default(FALSE) -# yaml_errors :text -# committed_at :datetime -# gl_project_id :integer -# status :string -# started_at :datetime -# finished_at :datetime -# duration :integer -# - module Ci class Commit < ActiveRecord::Base extend Ci::Model @@ -30,8 +8,6 @@ module Ci has_many :builds, class_name: 'Ci::Build' has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest' - delegate :stages, to: :statuses - validates_presence_of :sha validates_presence_of :status validate :valid_commit_sha @@ -44,7 +20,8 @@ module Ci end def self.stages - CommitStatus.where(commit: all).stages + # We use pluck here due to problems with MySQL which doesn't allow LIMIT/OFFSET in queries + CommitStatus.where(commit: pluck(:id)).stages end def project_id @@ -89,6 +66,29 @@ module Ci end end + def cancelable? + builds.running_or_pending.any? + end + + def cancel_running + builds.running_or_pending.each(&:cancel) + end + + def retry_failed + builds.latest.failed.select(&:retryable?).each(&:retry) + end + + def latest? + return false unless ref + commit = project.commit(ref) + return false unless commit + commit.sha == sha + end + + def triggered? + trigger_requests.any? + end + def create_builds(user, trigger_request = nil) return unless config_processor config_processor.stages.any? do |stage| diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb index add59a0889..adb6529220 100644 --- a/app/models/ci/runner.rb +++ b/app/models/ci/runner.rb @@ -1,28 +1,10 @@ -# == Schema Information -# -# Table name: ci_runners -# -# id :integer not null, primary key -# token :string -# created_at :datetime -# updated_at :datetime -# description :string -# contacted_at :datetime -# active :boolean default(TRUE), not null -# is_shared :boolean default(FALSE) -# name :string -# version :string -# revision :string -# platform :string -# architecture :string -# - module Ci class Runner < ActiveRecord::Base extend Ci::Model LAST_CONTACT_TIME = 5.minutes.ago - AVAILABLE_SCOPES = ['specific', 'shared', 'active', 'paused', 'online'] + AVAILABLE_SCOPES = %w[specific shared active paused online] + FORM_EDITABLE = %i[description tag_list active run_untagged] has_many :builds, class_name: 'Ci::Build' has_many :runner_projects, dependent: :destroy, class_name: 'Ci::RunnerProject' @@ -44,6 +26,8 @@ module Ci .where("ci_runner_projects.gl_project_id = :project_id OR ci_runners.is_shared = true", project_id: project_id) end + validate :tag_constraints + acts_as_taggable # Searches for runners matching the given query. @@ -76,7 +60,7 @@ module Ci end def display_name - return short_sha unless !description.blank? + return short_sha if description.blank? description end @@ -114,5 +98,18 @@ module Ci def short_sha token[0...8] if token end + + def has_tags? + tag_list.any? + end + + private + + def tag_constraints + unless has_tags? || run_untagged? + errors.add(:tags_list, + 'can not be empty when runner is not allowed to pick untagged jobs') + end + end end end diff --git a/app/models/ci/runner_project.rb b/app/models/ci/runner_project.rb index 7b16f207a2..4b44ffa886 100644 --- a/app/models/ci/runner_project.rb +++ b/app/models/ci/runner_project.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: ci_runner_projects -# -# id :integer not null, primary key -# runner_id :integer not null -# project_id :integer -# created_at :datetime -# updated_at :datetime -# gl_project_id :integer -# - module Ci class RunnerProject < ActiveRecord::Base extend Ci::Model diff --git a/app/models/ci/trigger.rb b/app/models/ci/trigger.rb index 4f3f4d79fa..a0b19b51a1 100644 --- a/app/models/ci/trigger.rb +++ b/app/models/ci/trigger.rb @@ -1,16 +1,3 @@ -# == Schema Information -# -# Table name: ci_triggers -# -# id :integer not null, primary key -# token :string -# project_id :integer -# deleted_at :datetime -# created_at :datetime -# updated_at :datetime -# gl_project_id :integer -# - module Ci class Trigger < ActiveRecord::Base extend Ci::Model diff --git a/app/models/ci/trigger_request.rb b/app/models/ci/trigger_request.rb index 9973d2e5ad..872d5fb31d 100644 --- a/app/models/ci/trigger_request.rb +++ b/app/models/ci/trigger_request.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: ci_trigger_requests -# -# id :integer not null, primary key -# trigger_id :integer not null -# variables :text -# created_at :datetime -# updated_at :datetime -# commit_id :integer -# - module Ci class TriggerRequest < ActiveRecord::Base extend Ci::Model diff --git a/app/models/ci/variable.rb b/app/models/ci/variable.rb index 4229fe085a..f8d5d4486f 100644 --- a/app/models/ci/variable.rb +++ b/app/models/ci/variable.rb @@ -1,17 +1,3 @@ -# == Schema Information -# -# Table name: ci_variables -# -# id :integer not null, primary key -# project_id :integer -# key :string -# value :text -# encrypted_value :text -# encrypted_value_salt :string -# encrypted_value_iv :string -# gl_project_id :integer -# - module Ci class Variable < ActiveRecord::Base extend Ci::Model @@ -25,6 +11,9 @@ module Ci format: { with: /\A[a-zA-Z0-9_]+\z/, message: "can contain only letters, digits and '_'." } - attr_encrypted :value, mode: :per_attribute_iv_and_salt, key: Gitlab::Application.secrets.db_key_base + attr_encrypted :value, + mode: :per_attribute_iv_and_salt, + key: Gitlab::Application.secrets.db_key_base, + algorithm: 'aes-256-cbc' end end diff --git a/app/models/commit.rb b/app/models/commit.rb index 562c3ed15b..f96c7cb34d 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -8,7 +8,10 @@ class Commit include StaticModel attr_mentionable :safe_message, pipeline: :single_line - participant :author, :committer, :notes + + participant :author + participant :committer + participant :notes_with_associations attr_accessor :project @@ -194,6 +197,10 @@ class Commit project.notes.for_commit_id(self.id) end + def notes_with_associations + notes.includes(:author, :project) + end + def method_missing(m, *args, &block) @raw.send(m, *args, &block) end @@ -219,7 +226,7 @@ class Commit def revert_branch_name "revert-#{short_id}" end - + def cherry_pick_branch_name project.repository.next_branch("cherry-pick-#{short_id}", mild: true) end @@ -251,11 +258,13 @@ class Commit end def has_been_reverted?(current_user = nil, noteable = self) - Gitlab::ReferenceExtractor.lazily do - noteable.notes.system.flat_map do |note| - note.all_references(current_user).commits - end - end.any? { |commit_ref| commit_ref.reverts_commit?(self) } + ext = all_references(current_user) + + noteable.notes_with_associations.system.each do |note| + note.all_references(current_user, extractor: ext) + end + + ext.commits.any? { |commit_ref| commit_ref.reverts_commit?(self) } end def change_type_title diff --git a/app/models/commit_range.rb b/app/models/commit_range.rb index 51673897d9..4066958f67 100644 --- a/app/models/commit_range.rb +++ b/app/models/commit_range.rb @@ -62,7 +62,7 @@ class CommitRange def initialize(range_string, project) @project = project - range_string.strip! + range_string = range_string.strip unless range_string =~ /\A#{PATTERN}\z/ raise ArgumentError, "invalid CommitRange string format: #{range_string}" diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index 1260c448de..f774b6e0ef 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -1,40 +1,3 @@ -# == Schema Information -# -# Table name: ci_builds -# -# id :integer not null, primary key -# project_id :integer -# status :string -# finished_at :datetime -# trace :text -# created_at :datetime -# updated_at :datetime -# started_at :datetime -# runner_id :integer -# coverage :float -# commit_id :integer -# commands :text -# job_id :integer -# name :string -# deploy :boolean default(FALSE) -# options :text -# allow_failure :boolean default(FALSE), not null -# stage :string -# trigger_request_id :integer -# stage_idx :integer -# tag :boolean -# ref :string -# user_id :integer -# type :string -# target_url :string -# description :string -# artifacts_file :text -# gl_project_id :integer -# artifacts_metadata :text -# erased_by_id :integer -# erased_at :datetime -# - class CommitStatus < ActiveRecord::Base include Statuseable @@ -51,7 +14,8 @@ class CommitStatus < ActiveRecord::Base alias_attribute :author, :user scope :latest, -> { where(id: unscope(:select).select('max(id)').group(:name, :commit_id)) } - scope :ordered, -> { order(:ref, :stage_idx, :name) } + scope :retried, -> { where.not(id: latest) } + scope :ordered, -> { order(:name) } scope :ignored, -> { where(allow_failure: true, status: [:failed, :canceled]) } state_machine :status, initial: :pending do @@ -82,6 +46,10 @@ class CommitStatus < ActiveRecord::Base after_transition [:pending, :running] => :success do |commit_status| MergeRequests::MergeWhenBuildSucceedsService.new(commit_status.commit.project, nil).trigger(commit_status) end + + after_transition any => :failed do |commit_status| + MergeRequests::AddTodoWhenBuildFailsService.new(commit_status.commit.project, nil).execute(commit_status) + end end delegate :sha, :short_sha, to: :commit @@ -91,13 +59,15 @@ class CommitStatus < ActiveRecord::Base end def self.stages - order_by = 'max(stage_idx)' - group('stage').order(order_by).pluck(:stage, order_by).map(&:first).compact + # We group by stage name, but order stages by theirs' index + unscoped.from(all, :sg).group('stage').order('max(stage_idx)', 'stage').pluck('sg.stage') end def self.stages_status - all.stages.inject({}) do |h, stage| - h[stage] = all.where(stage: stage).status + # We execute subquery for each stage to calculate a stage status + statuses = unscoped.from(all, :sg).group('stage').pluck('sg.stage', all.where('stage=sg.stage').status_sql) + statuses.inject({}) do |h, k| + h[k.first] = k.last h end end diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index 2e4efc4e8d..e86d5236ab 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -31,18 +31,21 @@ module Issuable scope :unassigned, -> { where("assignee_id IS NULL") } scope :of_projects, ->(ids) { where(project_id: ids) } scope :of_milestones, ->(ids) { where(milestone_id: ids) } + scope :with_milestone, ->(title) { left_joins_milestones.where(milestones: { title: title }) } scope :opened, -> { with_state(:opened, :reopened) } scope :only_opened, -> { with_state(:opened) } scope :only_reopened, -> { with_state(:reopened) } scope :closed, -> { with_state(:closed) } - scope :order_milestone_due_desc, -> { outer_join_milestone.reorder('milestones.due_date IS NULL ASC, milestones.due_date DESC, milestones.id DESC') } - scope :order_milestone_due_asc, -> { outer_join_milestone.reorder('milestones.due_date IS NULL ASC, milestones.due_date ASC, milestones.id ASC') } - scope :without_label, -> { joins("LEFT OUTER JOIN label_links ON label_links.target_type = '#{name}' AND label_links.target_id = #{table_name}.id").where(label_links: { id: nil }) } + scope :left_joins_milestones, -> { joins("LEFT OUTER JOIN milestones ON #{table_name}.milestone_id = milestones.id") } + scope :order_milestone_due_desc, -> { left_joins_milestones.reorder('milestones.due_date IS NULL, milestones.id IS NULL, milestones.due_date DESC') } + scope :order_milestone_due_asc, -> { left_joins_milestones.reorder('milestones.due_date IS NULL, milestones.id IS NULL, milestones.due_date ASC') } + + scope :without_label, -> { joins("LEFT OUTER JOIN label_links ON label_links.target_type = '#{name}' AND label_links.target_id = #{table_name}.id").where(label_links: { id: nil }) } scope :join_project, -> { joins(:project) } scope :references_project, -> { references(:project) } scope :non_archived, -> { join_project.where(projects: { archived: false }) } - scope :outer_join_milestone, -> { joins("LEFT OUTER JOIN milestones ON milestones.id = #{table_name}.milestone_id") } + delegate :name, :email, @@ -56,11 +59,23 @@ module Issuable prefix: true attr_mentionable :title, pipeline: :single_line - attr_mentionable :description, cache: true - participant :author, :assignee, :notes_with_associations + attr_mentionable :description + + participant :author + participant :assignee + participant :notes_with_associations + strip_attributes :title acts_as_paranoid + + after_save :update_assignee_cache_counts, if: :assignee_id_changed? + + def update_assignee_cache_counts + # make sure we flush the cache for both the old *and* new assignee + User.find(assignee_id_was).update_cache_counts if assignee_id_was + assignee.update_cache_counts if assignee + end end module ClassMethods @@ -123,13 +138,29 @@ module Issuable joins(join_clause).group(issuable_table[:id]).reorder("COUNT(notes.id) DESC") end - def with_label(title) - if title.is_a?(Array) && title.count > 1 - joins(:labels).where(labels: { title: title }).group('issues.id').having("count(distinct labels.title) = #{title.count}") + def with_label(title, sort = nil) + if title.is_a?(Array) && title.size > 1 + joins(:labels).where(labels: { title: title }).group(*grouping_columns(sort)).having("COUNT(DISTINCT labels.title) = #{title.size}") else joins(:labels).where(labels: { title: title }) end end + + # Includes table keys in group by clause when sorting + # preventing errors in postgres + # + # Returns an array of arel columns + def grouping_columns(sort) + grouping_columns = [arel_table[:id]] + + if ["milestone_due_desc", "milestone_due_asc"].include?(sort) + milestone_table = Milestone.arel_table + grouping_columns << milestone_table[:id] + grouping_columns << milestone_table[:due_date] + end + + grouping_columns + end end def today? @@ -160,6 +191,10 @@ module Issuable notes.awards.where(note: "thumbsup").count end + def user_notes_count + notes.user.count + end + def subscribed_without_subscriptions?(user) participants(user).include?(user) end @@ -178,6 +213,10 @@ module Issuable hook_data end + def labels_array + labels.to_a + end + def label_names labels.order('title ASC').pluck(:title) end diff --git a/app/models/concerns/mentionable.rb b/app/models/concerns/mentionable.rb index 98f71ae8cb..f00b5b8497 100644 --- a/app/models/concerns/mentionable.rb +++ b/app/models/concerns/mentionable.rb @@ -23,7 +23,7 @@ module Mentionable included do if self < Participable - participant ->(current_user) { mentioned_users(current_user) } + participant -> (user, ext) { all_references(user, extractor: ext) } end end @@ -43,23 +43,22 @@ module Mentionable self end - def all_references(current_user = self.author, text = nil) - ext = Gitlab::ReferenceExtractor.new(self.project, current_user, self.author) + def all_references(current_user = nil, text = nil, extractor: nil) + extractor ||= Gitlab::ReferenceExtractor. + new(project, current_user || author) if text - ext.analyze(text) + extractor.analyze(text, author: author) else self.class.mentionable_attrs.each do |attr, options| - text = send(attr) + text = __send__(attr) + options = options.merge(cache_key: [self, attr], author: author) - context = options.dup - context[:cache_key] = [self, attr] if context.delete(:cache) && self.persisted? - - ext.analyze(text, context) + extractor.analyze(text, options) end end - ext + extractor end def mentioned_users(current_user = nil) diff --git a/app/models/concerns/participable.rb b/app/models/concerns/participable.rb index fc6f83b918..9056722f45 100644 --- a/app/models/concerns/participable.rb +++ b/app/models/concerns/participable.rb @@ -3,8 +3,6 @@ # Contains functionality related to objects that can have participants, such as # an author, an assignee and people mentioned in its description or comments. # -# Used by Issue, Note, MergeRequest, Snippet and Commit. -# # Usage: # # class Issue < ActiveRecord::Base @@ -12,22 +10,36 @@ # # # ... # -# participant :author, :assignee, :notes, ->(current_user) { mentioned_users(current_user) } +# participant :author +# participant :assignee +# participant :notes +# +# participant -> (current_user, ext) do +# ext.analyze('...') +# end # end # # issue = Issue.last # users = issue.participants -# # `users` will contain the issue's author, its assignee, -# # all users returned by its #mentioned_users method, -# # as well as all participants to all of the issue's notes, -# # since Note implements Participable as well. -# module Participable extend ActiveSupport::Concern module ClassMethods - def participant(*attrs) - participant_attrs.concat(attrs) + # Adds a list of participant attributes. Attributes can either be symbols or + # Procs. + # + # When using a Proc instead of a Symbol the Proc will be given two + # arguments: + # + # 1. The current user (as an instance of User) + # 2. An instance of `Gitlab::ReferenceExtractor` + # + # It is expected that a Proc populates the given reference extractor + # instance with data. The return value of the Proc is ignored. + # + # attr - The name of the attribute or a Proc + def participant(attr) + participant_attrs << attr end def participant_attrs @@ -35,42 +47,42 @@ module Participable end end - # Be aware that this method makes a lot of sql queries. - # Save result into variable if you are going to reuse it inside same request - def participants(current_user = self.author) - participants = - Gitlab::ReferenceExtractor.lazily do - self.class.participant_attrs.flat_map do |attr| - value = - if attr.respond_to?(:call) - instance_exec(current_user, &attr) - else - send(attr) - end + # Returns the users participating in a discussion. + # + # This method processes attributes of objects in breadth-first order. + # + # Returns an Array of User instances. + def participants(current_user = nil) + current_user ||= author + ext = Gitlab::ReferenceExtractor.new(project, current_user) + participants = Set.new + process = [self] - participants_for(value, current_user) - end.compact.uniq - end + until process.empty? + source = process.pop - unless Gitlab::ReferenceExtractor.lazy? - participants.select! do |user| - user.can?(:read_project, project) + case source + when User + participants << source + when Participable + source.class.participant_attrs.each do |attr| + if attr.respond_to?(:call) + source.instance_exec(current_user, ext, &attr) + else + process << source.__send__(attr) + end + end + when Enumerable, ActiveRecord::Relation + # This uses reverse_each so we can use "pop" to get the next value to + # process (in order). Using unshift instead of pop would require + # moving all Array values one index to the left (which can be + # expensive). + source.reverse_each { |obj| process << obj } end end - participants - end + participants.merge(ext.users) - private - - def participants_for(value, current_user = nil) - case value - when User, Banzai::LazyReference - [value] - when Enumerable, ActiveRecord::Relation - value.flat_map { |v| participants_for(v, current_user) } - when Participable - value.participants(current_user) - end + Ability.users_that_can_read_project(participants.to_a, project) end end diff --git a/app/models/concerns/subscribable.rb b/app/models/concerns/subscribable.rb index d5a881b244..083257f100 100644 --- a/app/models/concerns/subscribable.rb +++ b/app/models/concerns/subscribable.rb @@ -36,6 +36,12 @@ module Subscribable update(subscribed: !subscribed?(user)) end + def subscribe(user) + subscriptions. + find_or_initialize_by(user_id: user.id). + update(subscribed: true) + end + def unsubscribe(user) subscriptions. find_or_initialize_by(user_id: user.id). diff --git a/app/models/deploy_key.rb b/app/models/deploy_key.rb index 43cf625f77..2c525d4cd7 100644 --- a/app/models/deploy_key.rb +++ b/app/models/deploy_key.rb @@ -1,18 +1,3 @@ -# == Schema Information -# -# Table name: keys -# -# id :integer not null, primary key -# user_id :integer -# created_at :datetime -# updated_at :datetime -# key :text -# title :string -# type :string -# fingerprint :string -# public :boolean default(FALSE), not null -# - class DeployKey < Key has_many :deploy_keys_projects, dependent: :destroy has_many :projects, through: :deploy_keys_projects diff --git a/app/models/deploy_keys_project.rb b/app/models/deploy_keys_project.rb index 18db521741..ae8486bd9a 100644 --- a/app/models/deploy_keys_project.rb +++ b/app/models/deploy_keys_project.rb @@ -1,14 +1,3 @@ -# == Schema Information -# -# Table name: deploy_keys_projects -# -# id :integer not null, primary key -# deploy_key_id :integer not null -# project_id :integer not null -# created_at :datetime -# updated_at :datetime -# - class DeployKeysProject < ActiveRecord::Base belongs_to :project belongs_to :deploy_key diff --git a/app/models/email.rb b/app/models/email.rb index eae2472f33..32a412ab87 100644 --- a/app/models/email.rb +++ b/app/models/email.rb @@ -1,14 +1,3 @@ -# == Schema Information -# -# Table name: emails -# -# id :integer not null, primary key -# user_id :integer not null -# email :string not null -# created_at :datetime -# updated_at :datetime -# - class Email < ActiveRecord::Base include Sortable diff --git a/app/models/event.rb b/app/models/event.rb index 25c7c3e6dc..716039fb54 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -1,19 +1,3 @@ -# == Schema Information -# -# Table name: events -# -# id :integer not null, primary key -# target_type :string -# target_id :integer -# title :string -# data :text -# project_id :integer -# created_at :datetime -# updated_at :datetime -# action :integer -# author_id :integer -# - class Event < ActiveRecord::Base include Sortable default_scope { where.not(author_id: nil) } @@ -96,7 +80,7 @@ class Event < ActiveRecord::Base end def target_title - target.title if target && target.respond_to?(:title) + target.try(:title) end def created? @@ -282,28 +266,20 @@ class Event < ActiveRecord::Base branch? && project.default_branch != branch_name end - def note_commit_id - target.commit_id - end - def target_iid target.respond_to?(:iid) ? target.iid : target_id end - def note_short_commit_id - Commit.truncate_sha(note_commit_id) - end - - def note_commit? - target.noteable_type == "Commit" + def commit_note? + target.for_commit? end def issue_note? - note? && target && target.noteable_type == "Issue" + note? && target && target.for_issue? end - def note_project_snippet? - target.noteable_type == "Snippet" + def project_snippet_note? + target.for_snippet? end def note_target @@ -311,19 +287,22 @@ class Event < ActiveRecord::Base end def note_target_id - if note_commit? + if commit_note? target.commit_id else target.noteable_id.to_s end end - def note_target_iid - if note_target.respond_to?(:iid) - note_target.iid + def note_target_reference + return unless note_target + + # Commit#to_reference returns the full SHA, but we want the short one here + if commit_note? + note_target.short_id else - note_target_id - end.to_s + note_target.to_reference + end end def note_target_type diff --git a/app/models/forked_project_link.rb b/app/models/forked_project_link.rb index 9b0c6263a9..9803bae0be 100644 --- a/app/models/forked_project_link.rb +++ b/app/models/forked_project_link.rb @@ -1,14 +1,3 @@ -# == Schema Information -# -# Table name: forked_project_links -# -# id :integer not null, primary key -# forked_to_project_id :integer not null -# forked_from_project_id :integer not null -# created_at :datetime -# updated_at :datetime -# - class ForkedProjectLink < ActiveRecord::Base belongs_to :forked_to_project, class_name: Project belongs_to :forked_from_project, class_name: Project diff --git a/app/models/generic_commit_status.rb b/app/models/generic_commit_status.rb index d4afd8cbe8..fa54e3540d 100644 --- a/app/models/generic_commit_status.rb +++ b/app/models/generic_commit_status.rb @@ -1,40 +1,3 @@ -# == Schema Information -# -# Table name: ci_builds -# -# id :integer not null, primary key -# project_id :integer -# status :string -# finished_at :datetime -# trace :text -# created_at :datetime -# updated_at :datetime -# started_at :datetime -# runner_id :integer -# coverage :float -# commit_id :integer -# commands :text -# job_id :integer -# name :string -# deploy :boolean default(FALSE) -# options :text -# allow_failure :boolean default(FALSE), not null -# stage :string -# trigger_request_id :integer -# stage_idx :integer -# tag :boolean -# ref :string -# user_id :integer -# type :string -# target_url :string -# description :string -# artifacts_file :text -# gl_project_id :integer -# artifacts_metadata :text -# erased_by_id :integer -# erased_at :datetime -# - class GenericCommitStatus < CommitStatus before_validation :set_default_values diff --git a/app/models/group.rb b/app/models/group.rb index cff7687795..aec92e335e 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -1,20 +1,3 @@ -# == Schema Information -# -# Table name: namespaces -# -# id :integer not null, primary key -# name :string not null -# path :string not null -# owner_id :integer -# created_at :datetime -# updated_at :datetime -# type :string -# description :string default(""), not null -# avatar :string -# share_with_group_lock :boolean default(FALSE) -# visibility_level :integer default(20), not null -# - require 'carrierwave/orm/activerecord' class Group < Namespace diff --git a/app/models/hooks/project_hook.rb b/app/models/hooks/project_hook.rb index 2b8f34a056..ba42a8eeb7 100644 --- a/app/models/hooks/project_hook.rb +++ b/app/models/hooks/project_hook.rb @@ -1,25 +1,3 @@ -# == Schema Information -# -# Table name: web_hooks -# -# id :integer not null, primary key -# url :string(2000) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# type :string default("ProjectHook") -# service_id :integer -# push_events :boolean default(TRUE), not null -# issues_events :boolean default(FALSE), not null -# merge_requests_events :boolean default(FALSE), not null -# tag_push_events :boolean default(FALSE) -# note_events :boolean default(FALSE), not null -# enable_ssl_verification :boolean default(TRUE) -# build_events :boolean default(FALSE), not null -# wiki_page_events :boolean default(FALSE), not null -# token :string -# - class ProjectHook < WebHook belongs_to :project diff --git a/app/models/hooks/service_hook.rb b/app/models/hooks/service_hook.rb index 0e176de5ef..eef24052a0 100644 --- a/app/models/hooks/service_hook.rb +++ b/app/models/hooks/service_hook.rb @@ -1,25 +1,3 @@ -# == Schema Information -# -# Table name: web_hooks -# -# id :integer not null, primary key -# url :string(2000) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# type :string default("ProjectHook") -# service_id :integer -# push_events :boolean default(TRUE), not null -# issues_events :boolean default(FALSE), not null -# merge_requests_events :boolean default(FALSE), not null -# tag_push_events :boolean default(FALSE) -# note_events :boolean default(FALSE), not null -# enable_ssl_verification :boolean default(TRUE) -# build_events :boolean default(FALSE), not null -# wiki_page_events :boolean default(FALSE), not null -# token :string -# - class ServiceHook < WebHook belongs_to :service diff --git a/app/models/hooks/system_hook.rb b/app/models/hooks/system_hook.rb index ad508cbbcb..777bad1e72 100644 --- a/app/models/hooks/system_hook.rb +++ b/app/models/hooks/system_hook.rb @@ -1,25 +1,3 @@ -# == Schema Information -# -# Table name: web_hooks -# -# id :integer not null, primary key -# url :string(2000) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# type :string default("ProjectHook") -# service_id :integer -# push_events :boolean default(TRUE), not null -# issues_events :boolean default(FALSE), not null -# merge_requests_events :boolean default(FALSE), not null -# tag_push_events :boolean default(FALSE) -# note_events :boolean default(FALSE), not null -# enable_ssl_verification :boolean default(TRUE) -# build_events :boolean default(FALSE), not null -# wiki_page_events :boolean default(FALSE), not null -# token :string -# - class SystemHook < WebHook def async_execute(data, hook_name) Sidekiq::Client.enqueue(SystemHookWorker, id, data, hook_name) diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb index 8e58c9583a..8b87b6c3d6 100644 --- a/app/models/hooks/web_hook.rb +++ b/app/models/hooks/web_hook.rb @@ -1,25 +1,3 @@ -# == Schema Information -# -# Table name: web_hooks -# -# id :integer not null, primary key -# url :string(2000) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# type :string default("ProjectHook") -# service_id :integer -# push_events :boolean default(TRUE), not null -# issues_events :boolean default(FALSE), not null -# merge_requests_events :boolean default(FALSE), not null -# tag_push_events :boolean default(FALSE) -# note_events :boolean default(FALSE), not null -# enable_ssl_verification :boolean default(TRUE) -# build_events :boolean default(FALSE), not null -# wiki_page_events :boolean default(FALSE), not null -# token :string -# - class WebHook < ActiveRecord::Base include Sortable include HTTParty @@ -60,7 +38,7 @@ class WebHook < ActiveRecord::Base basic_auth: auth) end - [(response.code >= 200 && response.code < 300), ActionView::Base.full_sanitizer.sanitize(response.to_s)] + [response.code, response.to_s] rescue SocketError, OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::ECONNREFUSED, Net::OpenTimeout => e logger.error("WebHook Error => #{e}") [false, e.to_s] diff --git a/app/models/identity.rb b/app/models/identity.rb index ef4d5f9909..3bacc450e6 100644 --- a/app/models/identity.rb +++ b/app/models/identity.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: identities -# -# id :integer not null, primary key -# extern_uid :string -# provider :string -# user_id :integer -# created_at :datetime -# updated_at :datetime -# - class Identity < ActiveRecord::Base include Sortable include CaseSensitivity diff --git a/app/models/issue.rb b/app/models/issue.rb index abaa509707..bd0fbc96d1 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: issues -# -# id :integer not null, primary key -# title :string -# assignee_id :integer -# author_id :integer -# project_id :integer -# created_at :datetime -# updated_at :datetime -# position :integer default(0) -# branch_name :string -# description :text -# milestone_id :integer -# state :string -# iid :integer -# updated_by_id :integer -# moved_to_id :integer -# confidential :boolean default(FALSE) -# deleted_at :datetime -# due_date :date -# - require 'carrierwave/orm/activerecord' class Issue < ActiveRecord::Base @@ -119,14 +95,13 @@ class Issue < ActiveRecord::Base end def referenced_merge_requests(current_user = nil) - @referenced_merge_requests ||= {} - @referenced_merge_requests[current_user] ||= begin - Gitlab::ReferenceExtractor.lazily do - [self, *notes].flat_map do |note| - note.all_references(current_user).merge_requests - end - end.sort_by(&:iid).uniq + ext = all_references(current_user) + + notes_with_associations.each do |object| + object.all_references(current_user, extractor: ext) end + + ext.merge_requests.sort_by(&:iid) end # All branches containing the current issue's ID, except for @@ -163,9 +138,13 @@ class Issue < ActiveRecord::Base def closed_by_merge_requests(current_user = nil) return [] unless open? - notes.system.flat_map do |note| - note.all_references(current_user).merge_requests - end.uniq.select { |mr| mr.open? && mr.closes_issue?(self) } + ext = all_references(current_user) + + notes.system.each do |note| + note.all_references(current_user, extractor: ext) + end + + ext.merge_requests.select { |mr| mr.open? && mr.closes_issue?(self) } end def moved? diff --git a/app/models/key.rb b/app/models/key.rb index b2b57849f8..0532e84f47 100644 --- a/app/models/key.rb +++ b/app/models/key.rb @@ -1,18 +1,3 @@ -# == Schema Information -# -# Table name: keys -# -# id :integer not null, primary key -# user_id :integer -# created_at :datetime -# updated_at :datetime -# key :text -# title :string -# type :string -# fingerprint :string -# public :boolean default(FALSE), not null -# - require 'digest/md5' class Key < ActiveRecord::Base @@ -41,7 +26,7 @@ class Key < ActiveRecord::Base end def publishable_key - #Removes anything beyond the keytype and key itself + # Removes anything beyond the keytype and key itself self.key.split[0..1].join(' ') end diff --git a/app/models/label.rb b/app/models/label.rb index 9a22398d95..e5ad11983b 100644 --- a/app/models/label.rb +++ b/app/models/label.rb @@ -1,17 +1,3 @@ -# == Schema Information -# -# Table name: labels -# -# id :integer not null, primary key -# title :string -# color :string -# project_id :integer -# created_at :datetime -# updated_at :datetime -# template :boolean default(FALSE) -# description :string -# - class Label < ActiveRecord::Base include Referable include Subscribable @@ -117,6 +103,10 @@ class Label < ActiveRecord::Base LabelsHelper::text_color_for_bg(self.color) end + def title=(value) + write_attribute(:title, Sanitize.clean(value.to_s)) if value.present? + end + private def label_format_reference(format = :id) diff --git a/app/models/label_link.rb b/app/models/label_link.rb index 7b8e872b6d..47bd6eaf35 100644 --- a/app/models/label_link.rb +++ b/app/models/label_link.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: label_links -# -# id :integer not null, primary key -# label_id :integer -# target_id :integer -# target_type :string -# created_at :datetime -# updated_at :datetime -# - class LabelLink < ActiveRecord::Base belongs_to :target, polymorphic: true belongs_to :label diff --git a/app/models/legacy_diff_note.rb b/app/models/legacy_diff_note.rb new file mode 100644 index 0000000000..bbefc911b2 --- /dev/null +++ b/app/models/legacy_diff_note.rb @@ -0,0 +1,157 @@ +class LegacyDiffNote < Note + serialize :st_diff + + validates :line_code, presence: true, line_code: true + + before_create :set_diff + + class << self + def build_discussion_id(noteable_type, noteable_id, line_code, active = true) + [super(noteable_type, noteable_id), line_code, active].join("-") + end + end + + def diff_note? + true + end + + def legacy_diff_note? + true + end + + def discussion_id + @discussion_id ||= self.class.build_discussion_id(noteable_type, noteable_id || commit_id, line_code, active?) + end + + def diff_file_hash + line_code.split('_')[0] if line_code + end + + def diff_old_line + line_code.split('_')[1].to_i if line_code + end + + def diff_new_line + line_code.split('_')[2].to_i if line_code + end + + def diff + @diff ||= Gitlab::Git::Diff.new(st_diff) if st_diff.respond_to?(:map) + end + + def diff_file_path + diff.new_path.presence || diff.old_path + end + + def diff_lines + @diff_lines ||= Gitlab::Diff::Parser.new.parse(diff.diff.each_line) + end + + def diff_line + @diff_line ||= diff_lines.find { |line| generate_line_code(line) == self.line_code } + end + + def diff_line_text + diff_line.try(:text) + end + + def diff_line_type + diff_line.try(:type) + end + + def highlighted_diff_lines + Gitlab::Diff::Highlight.new(diff_lines).highlight + end + + def truncated_diff_lines + max_number_of_lines = 16 + prev_match_line = nil + prev_lines = [] + + highlighted_diff_lines.each do |line| + if line.type == "match" + prev_lines.clear + prev_match_line = line + else + prev_lines << line + + break if generate_line_code(line) == self.line_code + + prev_lines.shift if prev_lines.length >= max_number_of_lines + end + end + + prev_lines + end + + # Check if this note is part of an "active" discussion + # + # This will always return true for anything except MergeRequest noteables, + # which have special logic. + # + # If the note's current diff cannot be matched in the MergeRequest's current + # diff, it's considered inactive. + def active? + return @active if defined?(@active) + return true if for_commit? + return true unless self.diff + return false unless noteable + + noteable_diff = find_noteable_diff + + if noteable_diff + parsed_lines = Gitlab::Diff::Parser.new.parse(noteable_diff.diff.each_line) + + @active = parsed_lines.any? { |line_obj| line_obj.text == diff_line_text } + else + @active = false + end + + @active + end + + private + + def find_diff + return nil unless noteable + return @diff if defined?(@diff) + + @diff = noteable.diffs(Commit.max_diff_options).find do |d| + d.new_path && Digest::SHA1.hexdigest(d.new_path) == diff_file_hash + end + end + + def set_diff + # First lets find notes with same diff + # before iterating over all mr diffs + diff = diff_for_line_code unless for_merge_request? + diff ||= find_diff + + self.st_diff = diff.to_hash if diff + end + + def diff_for_line_code + attributes = { + noteable_type: noteable_type, + line_code: line_code + } + + if for_commit? + attributes[:commit_id] = commit_id + else + attributes[:noteable_id] = noteable_id + end + + self.class.where(attributes).last.try(:diff) + end + + def generate_line_code(line) + Gitlab::Diff::LineCode.generate(diff_file_path, line.new_pos, line.old_pos) + end + + # Find the diff on noteable that matches our own + def find_noteable_diff + diffs = noteable.diffs(Commit.max_diff_options) + diffs.find { |d| d.new_path == self.diff.new_path } + end +end diff --git a/app/models/lfs_object.rb b/app/models/lfs_object.rb index 927e764af9..18657c3e1c 100644 --- a/app/models/lfs_object.rb +++ b/app/models/lfs_object.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: lfs_objects -# -# id :integer not null, primary key -# oid :string not null -# size :integer not null -# created_at :datetime -# updated_at :datetime -# file :string -# - class LfsObject < ActiveRecord::Base has_many :lfs_objects_projects, dependent: :destroy has_many :projects, through: :lfs_objects_projects diff --git a/app/models/lfs_objects_project.rb b/app/models/lfs_objects_project.rb index 890736bfc8..0fd5f089db 100644 --- a/app/models/lfs_objects_project.rb +++ b/app/models/lfs_objects_project.rb @@ -1,14 +1,3 @@ -# == Schema Information -# -# Table name: lfs_objects_projects -# -# id :integer not null, primary key -# lfs_object_id :integer not null -# project_id :integer not null -# created_at :datetime -# updated_at :datetime -# - class LfsObjectsProject < ActiveRecord::Base belongs_to :project belongs_to :lfs_object diff --git a/app/models/member.rb b/app/models/member.rb index cca82da89f..d3060f07fc 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -1,22 +1,3 @@ -# == Schema Information -# -# Table name: members -# -# id :integer not null, primary key -# access_level :integer not null -# source_id :integer not null -# source_type :string not null -# user_id :integer -# notification_level :integer not null -# type :string -# created_at :datetime -# updated_at :datetime -# created_by_id :integer -# invite_email :string -# invite_token :string -# invite_accepted_at :datetime -# - class Member < ActiveRecord::Base include Sortable include Gitlab::Access diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb index a48c1943e6..f63a0debf1 100644 --- a/app/models/members/group_member.rb +++ b/app/models/members/group_member.rb @@ -1,22 +1,3 @@ -# == Schema Information -# -# Table name: members -# -# id :integer not null, primary key -# access_level :integer not null -# source_id :integer not null -# source_type :string not null -# user_id :integer -# notification_level :integer not null -# type :string -# created_at :datetime -# updated_at :datetime -# created_by_id :integer -# invite_email :string -# invite_token :string -# invite_accepted_at :datetime -# - class GroupMember < Member SOURCE_TYPE = 'Namespace' diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb index 143350a0b5..46955b430f 100644 --- a/app/models/members/project_member.rb +++ b/app/models/members/project_member.rb @@ -1,22 +1,3 @@ -# == Schema Information -# -# Table name: members -# -# id :integer not null, primary key -# access_level :integer not null -# source_id :integer not null -# source_type :string not null -# user_id :integer -# notification_level :integer not null -# type :string -# created_at :datetime -# updated_at :datetime -# created_by_id :integer -# invite_email :string -# invite_token :string -# invite_accepted_at :datetime -# - class ProjectMember < Member SOURCE_TYPE = 'Project' @@ -24,7 +5,6 @@ class ProjectMember < Member belongs_to :project, class_name: 'Project', foreign_key: 'source_id' - # Make sure project member points only to project as it source default_value_for :source_type, SOURCE_TYPE validates_format_of :source_type, with: /\AProject\z/ @@ -34,6 +14,8 @@ class ProjectMember < Member scope :in_projects, ->(projects) { where(source_id: projects.pluck(:id)) } scope :with_user, ->(user) { where(user_id: user.id) } + before_destroy :delete_member_todos + class << self # Add users to project teams with passed access option @@ -121,6 +103,10 @@ class ProjectMember < Member private + def delete_member_todos + user.todos.where(project_id: source_id).destroy_all if user + end + def send_invite notification_service.invite_project_member(self, @raw_invite_token) diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 4175e1e5fb..722c258244 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -1,33 +1,3 @@ -# == Schema Information -# -# Table name: merge_requests -# -# id :integer not null, primary key -# target_branch :string not null -# source_branch :string not null -# source_project_id :integer not null -# author_id :integer -# assignee_id :integer -# title :string -# created_at :datetime -# updated_at :datetime -# milestone_id :integer -# state :string -# merge_status :string -# target_project_id :integer not null -# iid :integer -# description :text -# position :integer default(0) -# locked_at :datetime -# updated_by_id :integer -# merge_error :string -# merge_params :text -# merge_when_build_succeeds :boolean default(FALSE), not null -# merge_user_id :integer -# merge_commit_sha :string -# deleted_at :datetime -# - class MergeRequest < ActiveRecord::Base include InternalId include Issuable @@ -56,6 +26,10 @@ class MergeRequest < ActiveRecord::Base # when creating new merge request attr_accessor :can_be_created, :compare_commits, :compare + # Temporary fields to store target_sha, and base_sha to + # compare when importing pull requests from GitHub + attr_accessor :base_target_sha, :head_source_sha + state_machine :state, initial: :opened do event :close do transition [:reopened, :opened] => :closed @@ -312,6 +286,18 @@ class MergeRequest < ActiveRecord::Base last_commit == source_project.commit(source_branch) end + def should_remove_source_branch? + merge_params['should_remove_source_branch'].present? + end + + def force_remove_source_branch? + merge_params['force_remove_source_branch'].present? + end + + def remove_source_branch? + should_remove_source_branch? || force_remove_source_branch? + end + def mr_and_commit_notes # Fetch comments only from last 100 commits commits_for_notes_limit = 100 @@ -452,7 +438,10 @@ class MergeRequest < ActiveRecord::Base self.merge_when_build_succeeds = false self.merge_user = nil - self.merge_params = nil + if merge_params + merge_params.delete('should_remove_source_branch') + merge_params.delete('commit_message') + end self.save end @@ -520,10 +509,14 @@ class MergeRequest < ActiveRecord::Base end def target_sha - @target_sha ||= target_project.repository.commit(target_branch).try(:sha) + return @base_target_sha if defined?(@base_target_sha) + + target_project.repository.commit(target_branch).try(:sha) end def source_sha + return @head_source_sha if defined?(@head_source_sha) + last_commit.try(:sha) || source_tip.try(:sha) end @@ -544,7 +537,7 @@ class MergeRequest < ActiveRecord::Base end def ref_is_fetched? - File.exists?(File.join(project.repository.path_to_repo, ref_path)) + File.exist?(File.join(project.repository.path_to_repo, ref_path)) end def ensure_ref_fetched diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index 8951e92a0b..7d5103748f 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -1,18 +1,3 @@ -# == Schema Information -# -# Table name: merge_request_diffs -# -# id :integer not null, primary key -# state :string -# st_commits :text -# st_diffs :text -# merge_request_id :integer not null -# created_at :datetime -# updated_at :datetime -# base_commit_sha :string -# real_size :string -# - class MergeRequestDiff < ActiveRecord::Base include Sortable @@ -21,7 +6,7 @@ class MergeRequestDiff < ActiveRecord::Base belongs_to :merge_request - delegate :target_branch, :source_branch, to: :merge_request, prefix: nil + delegate :head_source_sha, :target_branch, :source_branch, to: :merge_request, prefix: nil state_machine :state, initial: :empty do state :collected @@ -53,8 +38,8 @@ class MergeRequestDiff < ActiveRecord::Base @diffs_no_whitespace ||= begin compare = Gitlab::Git::Compare.new( self.repository.raw_repository, - self.target_branch, - self.source_sha, + self.base, + self.head, ) compare.diffs(options) end @@ -113,9 +98,7 @@ class MergeRequestDiff < ActiveRecord::Base commits = compare.commits if commits.present? - commits = Commit.decorate(commits, merge_request.source_project). - sort_by(&:created_at). - reverse + commits = Commit.decorate(commits, merge_request.source_project).reverse end commits @@ -159,7 +142,7 @@ class MergeRequestDiff < ActiveRecord::Base self.st_diffs = new_diffs - self.base_commit_sha = self.repository.merge_base(self.source_sha, self.target_branch) + self.base_commit_sha = self.repository.merge_base(self.head, self.base) self.save end @@ -175,10 +158,24 @@ class MergeRequestDiff < ActiveRecord::Base end def source_sha + return head_source_sha if head_source_sha.present? + source_commit = merge_request.source_project.commit(source_branch) source_commit.try(:sha) end + def target_sha + merge_request.target_sha + end + + def base + self.target_sha || self.target_branch + end + + def head + self.source_sha + end + def compare @compare ||= begin @@ -187,8 +184,8 @@ class MergeRequestDiff < ActiveRecord::Base Gitlab::Git::Compare.new( self.repository.raw_repository, - self.target_branch, - self.source_sha + self.base, + self.head ) end end diff --git a/app/models/milestone.rb b/app/models/milestone.rb index 5ee8a965ad..e0c8454a99 100644 --- a/app/models/milestone.rb +++ b/app/models/milestone.rb @@ -1,18 +1,3 @@ -# == Schema Information -# -# Table name: milestones -# -# id :integer not null, primary key -# title :string not null -# project_id :integer not null -# description :text -# due_date :date -# created_at :datetime -# updated_at :datetime -# state :string -# iid :integer -# - class Milestone < ActiveRecord::Base # Represents a "No Milestone" state used for filtering Issues and Merge # Requests that have no milestone assigned. @@ -74,25 +59,67 @@ class Milestone < ActiveRecord::Base end end + def self.reference_prefix + '%' + end + def self.reference_pattern - nil + # NOTE: The iid pattern only matches when all characters on the expression + # are digits, so it will match %2 but not %2.1 because that's probably a + # milestone name and we want it to be matched as such. + @reference_pattern ||= %r{ + (#{Project.reference_pattern})? + #{Regexp.escape(reference_prefix)} + (?: + (? + \d+(?!\S\w)\b # Integer-based milestone iid, or + ) | + (? + [^"\s]+\b | # String-based single-word milestone title, or + "[^"]+" # String-based multi-word milestone surrounded in quotes + ) + ) + }x end def self.link_reference_pattern @link_reference_pattern ||= super("milestones", /(?\d+)/) end - def self.upcoming - self.where('due_date > ?', Time.now).reorder(due_date: :asc).first + def self.upcoming_ids_by_projects(projects) + rel = unscoped.of_projects(projects).active.where('due_date > ?', Time.now) + + if Gitlab::Database.postgresql? + rel.order(:project_id, :due_date).select('DISTINCT ON (project_id) id') + else + rel. + group(:project_id). + having('due_date = MIN(due_date)'). + pluck(:id, :project_id, :due_date). + map(&:first) + end end - def to_reference(from_project = nil) - escaped_title = self.title.gsub("]", "\\]") + ## + # Returns the String necessary to reference this Milestone in Markdown + # + # format - Symbol format to use (default: :iid, optional: :name) + # + # Examples: + # + # Milestone.first.to_reference # => "%1" + # Milestone.first.to_reference(format: :name) # => "%\"goal\"" + # Milestone.first.to_reference(project) # => "gitlab-org/gitlab-ce%1" + # + def to_reference(from_project = nil, format: :iid) + format_reference = milestone_format_reference(format) + reference = "#{self.class.reference_prefix}#{format_reference}" - h = Gitlab::Routing.url_helpers - url = h.namespace_project_milestone_url(self.project.namespace, self.project, self) - - "[#{escaped_title}](#{url})" + if cross_project_reference?(from_project) + project.to_reference + reference + else + reference + end end def reference_link_text(from_project = nil) @@ -129,6 +156,10 @@ class Milestone < ActiveRecord::Base nil end + def title=(value) + write_attribute(:title, Sanitize.clean(value.to_s)) if value.present? + end + # Sorts the issues for the given IDs. # # This method runs a single SQL query using a CASE statement to update the @@ -160,4 +191,16 @@ class Milestone < ActiveRecord::Base issues.where(id: ids). update_all(["position = CASE #{conditions} ELSE position END", *pairs]) end + + private + + def milestone_format_reference(format = :iid) + raise ArgumentError, 'Unknown format' unless [:iid, :name].include?(format) + + if format == :name && !name.include?('"') + %("#{name}") + else + iid + end + end end diff --git a/app/models/namespace.rb b/app/models/namespace.rb index 741e912171..da19462f26 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -1,20 +1,3 @@ -# == Schema Information -# -# Table name: namespaces -# -# id :integer not null, primary key -# name :string not null -# path :string not null -# owner_id :integer -# created_at :datetime -# updated_at :datetime -# type :string -# description :string default(""), not null -# avatar :string -# share_with_group_lock :boolean default(FALSE) -# visibility_level :integer default(20), not null -# - class Namespace < ActiveRecord::Base include Sortable include Gitlab::ShellAdapter @@ -127,6 +110,10 @@ class Namespace < ActiveRecord::Base # 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) @@ -148,6 +135,10 @@ class Namespace < ActiveRecord::Base end end + def any_project_has_container_registry_tags? + projects.any?(&:has_container_registry_tags?) + end + def send_update_instructions projects.each do |project| project.send_move_instructions("#{path_was}/#{project.path}") diff --git a/app/models/network/graph.rb b/app/models/network/graph.rb index f4e9012537..a2aee2f925 100644 --- a/app/models/network/graph.rb +++ b/app/models/network/graph.rb @@ -22,9 +22,16 @@ module Network def collect_notes h = Hash.new(0) - @project.notes.where('noteable_type = ?' ,"Commit").group('notes.commit_id').select('notes.commit_id, count(notes.id) as note_count').each do |item| - h[item.commit_id] = item.note_count.to_i - end + + @project + .notes + .where('noteable_type = ?', 'Commit') + .group('notes.commit_id') + .select('notes.commit_id, count(notes.id) as note_count') + .each do |item| + h[item.commit_id] = item.note_count.to_i + end + h end @@ -89,7 +96,7 @@ module Network end end - if self.class.max_count / 2 < offset then + if self.class.max_count / 2 < offset # get max index that commit is displayed in the center. offset - self.class.max_count / 2 else @@ -130,7 +137,7 @@ module Network commit.parents(@map).each do |parent| range = commit.time..parent.time - space = if commit.space >= parent.space then + space = if commit.space >= parent.space find_free_parent_space(range, parent.space, -1, commit.space) else find_free_parent_space(range, commit.space, -1, parent.space) @@ -144,7 +151,7 @@ module Network end def find_free_parent_space(range, space_base, space_step, space_default) - if is_overlap?(range, space_default) then + if is_overlap?(range, space_default) find_free_space(range, space_step, space_base, space_default) else space_default @@ -155,9 +162,9 @@ module Network range.each do |i| if i != range.first && i != range.last && - @commits[i].spaces.include?(overlap_space) then + @commits[i].spaces.include?(overlap_space) - return true; + return true end end @@ -198,7 +205,7 @@ module Network # Visit branching chains leaves.each do |l| parents = l.parents(@map).select{|p| p.space.zero?} - for p in parents + parents.each do |p| place_chain(p, l.time) end end @@ -216,7 +223,7 @@ module Network end def mark_reserved(time_range, space) - for day in time_range + time_range.each do |day| @reserved[day].push(space) end end @@ -225,15 +232,15 @@ module Network space_default ||= space_base reserved = [] - for day in time_range + time_range.each do |day| reserved.push(*@reserved[day]) end reserved.uniq! space = space_default - while reserved.include?(space) do + while reserved.include?(space) space += space_step - if space < space_base then + if space < space_base space_step *= -1 space = space_base + space_step end @@ -253,7 +260,7 @@ module Network leaves = [] leaves.push(commit) if commit.space.zero? - while true + loop do return leaves if commit.parents(@map).count.zero? commit = commit.parents(@map).first diff --git a/app/models/note.rb b/app/models/note.rb index deee2b9e88..c21981ead8 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -1,34 +1,12 @@ -# == Schema Information -# -# Table name: notes -# -# id :integer not null, primary key -# note :text -# noteable_type :string -# author_id :integer -# created_at :datetime -# updated_at :datetime -# project_id :integer -# attachment :string -# line_code :string -# commit_id :string -# noteable_id :integer -# system :boolean default(FALSE), not null -# st_diff :text -# updated_by_id :integer -# is_award :boolean default(FALSE), not null -# - -require 'carrierwave/orm/activerecord' - class Note < ActiveRecord::Base + extend ActiveModel::Naming include Gitlab::CurrentSettings include Participable include Mentionable default_value_for :system, false - attr_mentionable :note, cache: true, pipeline: :note + attr_mentionable :note, pipeline: :note participant :author belongs_to :project @@ -41,29 +19,33 @@ class Note < ActiveRecord::Base delegate :gfm_reference, :local_reference, to: :noteable delegate :name, to: :project, prefix: true delegate :name, :email, to: :author, prefix: true + delegate :title, to: :noteable, allow_nil: true before_validation :set_award! - before_validation :clear_blank_line_code! validates :note, :project, presence: true validates :note, uniqueness: { scope: [:author, :noteable_type, :noteable_id] }, if: ->(n) { n.is_award } validates :note, inclusion: { in: Emoji.emojis_names }, if: ->(n) { n.is_award } - validates :line_code, line_code: true, allow_blank: true # Attachments are deprecated and are handled by Markdown uploader validates :attachment, file_size: { maximum: :max_attachment_size } - validates :noteable_id, presence: true, if: ->(n) { n.noteable_type.present? && n.noteable_type != 'Commit' } - validates :commit_id, presence: true, if: ->(n) { n.noteable_type == 'Commit' } + validates :noteable_type, presence: true + validates :noteable_id, presence: true, unless: :for_commit? + validates :commit_id, presence: true, if: :for_commit? validates :author, presence: true + validate unless: :for_commit? do |note| + unless note.noteable.try(:project) == note.project + errors.add(:invalid_project, 'Note and noteable project mismatch') + end + end + mount_uploader :attachment, AttachmentUploader # Scopes scope :awards, ->{ where(is_award: true) } scope :nonawards, ->{ where(is_award: false) } scope :for_commit_id, ->(commit_id) { where(noteable_type: "Commit", commit_id: commit_id) } - scope :inline, ->{ where("line_code IS NOT NULL") } - scope :not_inline, ->{ where(line_code: nil) } scope :system, ->{ where(system: true) } scope :user, ->{ where(system: false) } scope :common, ->{ where(noteable_type: ["", nil]) } @@ -71,52 +53,61 @@ class Note < ActiveRecord::Base scope :inc_author_project, ->{ includes(:project, :author) } scope :inc_author, ->{ includes(:author) } + scope :legacy_diff_notes, ->{ where(type: 'LegacyDiffNote') } + scope :non_diff_notes, ->{ where(type: ['Note', nil]) } + scope :with_associations, -> do includes(:author, :noteable, :updated_by, project: [:project_members, { group: [:group_members] }]) end - serialize :st_diff - before_create :set_diff, if: ->(n) { n.line_code.present? } + before_validation :clear_blank_line_code! class << self - def discussions_from_notes(notes) - discussion_ids = [] - discussions = [] - - notes.each do |note| - next if discussion_ids.include?(note.discussion_id) - - # don't group notes for the main target - if !note.for_diff_line? && note.for_merge_request? - discussions << [note] - else - discussions << notes.select do |other_note| - note.discussion_id == other_note.discussion_id - end - discussion_ids << note.discussion_id - end - end - - discussions + def model_name + ActiveModel::Name.new(self, nil, 'note') end - def build_discussion_id(type, id, line_code) - [:discussion, type.try(:underscore), id, line_code].join("-").to_sym + def build_discussion_id(noteable_type, noteable_id) + [:discussion, noteable_type.try(:underscore), noteable_id].join("-") + end + + def discussions + all.group_by(&:discussion_id).values + end + + def grouped_diff_notes + legacy_diff_notes.select(&:active?).sort_by(&:created_at).group_by(&:line_code) end # Searches for notes matching the given query. # # This method uses ILIKE on PostgreSQL and LIKE on MySQL. # - # query - The search query as a String. + # query - The search query as a String. + # as_user - Limit results to those viewable by a specific user # # Returns an ActiveRecord::Relation. - def search(query) + def search(query, as_user: nil) table = arel_table pattern = "%#{query}%" - where(table[:note].matches(pattern)) + found_notes = joins('LEFT JOIN issues ON issues.id = noteable_id'). + where(table[:note].matches(pattern)) + + if as_user + found_notes.where(' + issues.confidential IS NULL + OR issues.confidential IS FALSE + OR (issues.confidential IS TRUE + AND (issues.author_id = :user_id + OR issues.assignee_id = :user_id + OR issues.project_id IN(:project_ids)))', + user_id: as_user.id, + project_ids: as_user.authorized_projects.select(:id)) + else + found_notes.where('issues.confidential IS NULL OR issues.confidential IS FALSE') + end end def grouped_awards @@ -137,167 +128,39 @@ class Note < ActiveRecord::Base system && SystemNoteService.cross_reference?(note) end - def max_attachment_size - current_application_settings.max_attachment_size.megabytes.to_i + def diff_note? + false end - def find_diff - return nil unless noteable - return @diff if defined?(@diff) + def legacy_diff_note? + false + end - # Don't use ||= because nil is a valid value for @diff - @diff = noteable.diffs(Commit.max_diff_options).find do |d| - Digest::SHA1.hexdigest(d.new_path) == diff_file_index if d.new_path - end + def active? + true + end + + def discussion_id + @discussion_id ||= + if for_merge_request? + [:discussion, :note, id].join("-") + else + self.class.build_discussion_id(noteable_type, noteable_id || commit_id) + end + end + + def max_attachment_size + current_application_settings.max_attachment_size.megabytes.to_i end def hook_attrs attributes end - def set_diff - # First lets find notes with same diff - # before iterating over all mr diffs - diff = diff_for_line_code unless for_merge_request? - diff ||= find_diff - - self.st_diff = diff.to_hash if diff - end - - def diff - @diff ||= Gitlab::Git::Diff.new(st_diff) if st_diff.respond_to?(:map) - end - - def diff_for_line_code - Note.where(noteable_id: noteable_id, noteable_type: noteable_type, line_code: line_code).last.try(:diff) - end - - # Check if this note is part of an "active" discussion - # - # This will always return true for anything except MergeRequest noteables, - # which have special logic. - # - # If the note's current diff cannot be matched in the MergeRequest's current - # diff, it's considered inactive. - def active? - return true unless self.diff - return false unless noteable - return @active if defined?(@active) - - noteable_diff = find_noteable_diff - - if noteable_diff - parsed_lines = Gitlab::Diff::Parser.new.parse(noteable_diff.diff.each_line) - - @active = parsed_lines.any? { |line_obj| line_obj.text == diff_line } - else - @active = false - end - - @active - end - - def diff_file_index - line_code.split('_')[0] if line_code - end - - def diff_file_name - diff.new_path if diff - end - - def file_path - if diff.new_path.present? - diff.new_path - elsif diff.old_path.present? - diff.old_path - end - end - - def diff_old_line - line_code.split('_')[1].to_i if line_code - end - - def diff_new_line - line_code.split('_')[2].to_i if line_code - end - - def generate_line_code(line) - Gitlab::Diff::LineCode.generate(file_path, line.new_pos, line.old_pos) - end - - def diff_line - return @diff_line if @diff_line - - if diff - diff_lines.each do |line| - if generate_line_code(line) == self.line_code - @diff_line = line.text - end - end - end - - @diff_line - end - - def diff_line_type - return @diff_line_type if @diff_line_type - - if diff - diff_lines.each do |line| - if generate_line_code(line) == self.line_code - @diff_line_type = line.type - end - end - end - - @diff_line_type - end - - def truncated_diff_lines - max_number_of_lines = 16 - prev_match_line = nil - prev_lines = [] - - highlighted_diff_lines.each do |line| - if line.type == "match" - prev_lines.clear - prev_match_line = line - else - prev_lines << line - - break if generate_line_code(line) == self.line_code - - prev_lines.shift if prev_lines.length >= max_number_of_lines - end - end - - prev_lines - end - - def diff_lines - @diff_lines ||= Gitlab::Diff::Parser.new.parse(diff.diff.each_line) - end - - def highlighted_diff_lines - Gitlab::Diff::Highlight.new(diff_lines).highlight - end - - def discussion_id - @discussion_id ||= Note.build_discussion_id(noteable_type, noteable_id || commit_id, line_code) - end - def for_commit? noteable_type == "Commit" end - def for_commit_diff_line? - for_commit? && for_diff_line? - end - - def for_diff_line? - line_code.present? - end - def for_issue? noteable_type == "Issue" end @@ -306,10 +169,6 @@ class Note < ActiveRecord::Base noteable_type == "MergeRequest" end - def for_merge_request_diff_line? - for_merge_request? && for_diff_line? - end - def for_snippet? noteable_type == "Snippet" end @@ -382,14 +241,8 @@ class Note < ActiveRecord::Base self.line_code = nil if self.line_code.blank? end - # Find the diff on noteable that matches our own - def find_noteable_diff - diffs = noteable.diffs(Commit.max_diff_options) - diffs.find { |d| d.new_path == self.diff.new_path } - end - def awards_supported? - (for_issue? || for_merge_request?) && !for_diff_line? + (for_issue? || for_merge_request?) && !diff_note? end def contains_emoji_only? diff --git a/app/models/notification_setting.rb b/app/models/notification_setting.rb index 846773752a..5001738f41 100644 --- a/app/models/notification_setting.rb +++ b/app/models/notification_setting.rb @@ -1,16 +1,3 @@ -# == Schema Information -# -# Table name: notification_settings -# -# id :integer not null, primary key -# user_id :integer not null -# source_id :integer not null -# source_type :string not null -# level :integer default(0), not null -# created_at :datetime not null -# updated_at :datetime not null -# - class NotificationSetting < ActiveRecord::Base enum level: { disabled: 0, participating: 1, watch: 2, global: 3, mention: 4 } diff --git a/app/models/oauth_access_token.rb b/app/models/oauth_access_token.rb index c78c7f4aa0..116fb71ac0 100644 --- a/app/models/oauth_access_token.rb +++ b/app/models/oauth_access_token.rb @@ -1,18 +1,3 @@ -# == Schema Information -# -# Table name: oauth_access_tokens -# -# id :integer not null, primary key -# resource_owner_id :integer -# application_id :integer -# token :string not null -# refresh_token :string -# expires_in :integer -# revoked_at :datetime -# created_at :datetime not null -# scopes :string -# - class OauthAccessToken < ActiveRecord::Base belongs_to :resource_owner, class_name: 'User' belongs_to :application, class_name: 'Doorkeeper::Application' diff --git a/app/models/personal_snippet.rb b/app/models/personal_snippet.rb index 1d5f4c5025..82c1c4de3a 100644 --- a/app/models/personal_snippet.rb +++ b/app/models/personal_snippet.rb @@ -1,18 +1,2 @@ -# == Schema Information -# -# Table name: snippets -# -# id :integer not null, primary key -# title :string -# content :text -# author_id :integer not null -# project_id :integer -# created_at :datetime -# updated_at :datetime -# file_name :string -# type :string -# visibility_level :integer default(0), not null -# - class PersonalSnippet < Snippet end diff --git a/app/models/project.rb b/app/models/project.rb index fdbabc7cf7..74db163bcb 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1,48 +1,3 @@ -# == Schema Information -# -# Table name: projects -# -# id :integer not null, primary key -# name :string -# path :string -# description :text -# created_at :datetime -# updated_at :datetime -# creator_id :integer -# issues_enabled :boolean default(TRUE), not null -# merge_requests_enabled :boolean default(TRUE), not null -# wiki_enabled :boolean default(TRUE), not null -# namespace_id :integer -# issues_tracker :string default("gitlab"), not null -# issues_tracker_id :string -# snippets_enabled :boolean default(TRUE), not null -# last_activity_at :datetime -# import_url :string -# visibility_level :integer default(0), not null -# archived :boolean default(FALSE), not null -# avatar :string -# import_status :string -# repository_size :float default(0.0) -# star_count :integer default(0), not null -# import_type :string -# import_source :string -# commit_count :integer default(0) -# import_error :text -# ci_id :integer -# builds_enabled :boolean default(TRUE), not null -# shared_runners_enabled :boolean default(TRUE), not null -# runners_token :string -# build_coverage_regex :string -# build_allow_git_fetch :boolean default(TRUE), not null -# build_timeout :integer default(3600), not null -# pending_delete :boolean default(FALSE) -# public_builds :boolean default(TRUE), not null -# main_language :string -# pushes_since_gc :integer default(0) -# last_repository_check_failed :boolean -# last_repository_check_at :datetime -# - require 'carrierwave/orm/activerecord' class Project < ActiveRecord::Base @@ -67,6 +22,7 @@ class Project < ActiveRecord::Base default_value_for :builds_enabled, gitlab_config_features.builds 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(:shared_runners_enabled) { current_application_settings.shared_runners_enabled } # set last_activity_at to the same as created_at @@ -94,6 +50,8 @@ class Project < ActiveRecord::Base attr_accessor :new_default_branch attr_accessor :old_path_with_namespace + alias_attribute :title, :name + # Relations belongs_to :creator, foreign_key: 'creator_id', class_name: 'User' belongs_to :group, -> { where(type: Group) }, foreign_key: 'namespace_id' @@ -213,17 +171,17 @@ class Project < ActiveRecord::Base scope :sorted_by_activity, -> { reorder(last_activity_at: :desc) } scope :sorted_by_stars, -> { reorder('projects.star_count DESC') } - scope :sorted_by_names, -> { joins(:namespace).reorder('namespaces.name ASC, projects.name ASC') } - scope :without_user, ->(user) { where('projects.id NOT IN (:ids)', ids: user.authorized_projects.map(&:id) ) } - scope :without_team, ->(team) { team.projects.present? ? where('projects.id NOT IN (:ids)', ids: team.projects.map(&:id)) : scoped } - scope :not_in_group, ->(group) { where('projects.id NOT IN (:ids)', ids: group.project_ids ) } scope :in_namespace, ->(namespace_ids) { where(namespace_id: namespace_ids) } - scope :in_group_namespace, -> { joins(:group) } scope :personal, ->(user) { where(namespace_id: user.namespace_id) } scope :joined, ->(user) { where('namespace_id != ?', user.namespace_id) } + scope :visible_to_user, ->(user) { where(id: user.authorized_projects.select(:id).reorder(nil)) } scope :non_archived, -> { where(archived: false) } scope :for_milestones, ->(ids) { joins(:milestones).where('milestones.id' => ids).distinct } + scope :with_push, -> { joins(:events).where('events.action = ?', Event::PUSHED) } + + scope :active, -> { joins(:issues, :notes, :merge_requests).order('issues.created_at, notes.created_at, merge_requests.created_at DESC') } + scope :abandoned, -> { where('projects.last_activity_at < ?', 6.months.ago) } state_machine :import_status, initial: :none do event :import_start do @@ -246,23 +204,10 @@ class Project < ActiveRecord::Base state :finished state :failed - after_transition any => :started, do: :schedule_add_import_job - after_transition any => :finished, do: :clear_import_data + after_transition any => :finished, do: :reset_cache_and_import_attrs end class << self - def abandoned - where('projects.last_activity_at < ?', 6.months.ago) - end - - def with_push - joins(:events).where('events.action = ?', Event::PUSHED) - end - - def active - joins(:issues, :notes, :merge_requests).order('issues.created_at, notes.created_at, merge_requests.created_at DESC') - end - # Searches for a list of projects based on the query given in `query`. # # On PostgreSQL this method uses "ILIKE" to perform a case-insensitive @@ -324,10 +269,6 @@ class Project < ActiveRecord::Base projects.iwhere('projects.path' => project_path).take end - def find_by_ci_id(id) - find_by(ci_id: id.to_i) - end - def visibility_levels Gitlab::VisibilityLevel.options end @@ -358,10 +299,6 @@ class Project < ActiveRecord::Base joins(join_body).reorder('join_note_counts.amount DESC') end - - def visible_to_user(user) - where(id: user.authorized_projects.select(:id).reorder(nil)) - end end def team @@ -372,6 +309,34 @@ class Project < ActiveRecord::Base @repository ||= Repository.new(path_with_namespace, self) end + def container_registry_path_with_namespace + path_with_namespace.downcase + end + + def container_registry_repository + return unless Gitlab.config.registry.enabled + + @container_registry_repository ||= begin + token = Auth::ContainerRegistryAuthenticationService.full_access_token(container_registry_path_with_namespace) + url = Gitlab.config.registry.api_url + host_port = Gitlab.config.registry.host_port + registry = ContainerRegistry::Registry.new(url, token: token, path: host_port) + registry.repository(container_registry_path_with_namespace) + end + end + + def container_registry_repository_url + if Gitlab.config.registry.enabled + "#{Gitlab.config.registry.host_port}/#{container_registry_path_with_namespace}" + end + end + + def has_container_registry_tags? + return unless container_registry_repository + + container_registry_repository.tags.any? + end + def commit(id = 'HEAD') repository.commit(id) end @@ -385,10 +350,6 @@ class Project < ActiveRecord::Base id && persisted? end - def schedule_add_import_job - run_after_commit(:add_import_job) - end - def add_import_job if forked? job_id = RepositoryForkWorker.perform_async(self.id, forked_from_project.path_with_namespace, self.namespace.path) @@ -403,7 +364,7 @@ class Project < ActiveRecord::Base end end - def clear_import_data + def reset_cache_and_import_attrs update(import_error: nil) ProjectCacheWorker.perform_async(self.id) @@ -412,14 +373,14 @@ class Project < ActiveRecord::Base end def import_url=(value) - import_url = Gitlab::ImportUrl.new(value) + import_url = Gitlab::UrlSanitizer.new(value) create_or_update_import_data(credentials: import_url.credentials) super(import_url.sanitized_url) end def import_url if import_data && super - import_url = Gitlab::ImportUrl.new(super, credentials: import_data.credentials) + import_url = Gitlab::UrlSanitizer.new(super, credentials: import_data.credentials) import_url.full_url else super @@ -469,17 +430,18 @@ class Project < ActiveRecord::Base end def safe_import_url - result = URI.parse(self.import_url) - result.password = '*****' unless result.password.nil? - result.user = '*****' unless result.user.nil? || result.user == "git" #tokens or other data may be saved as user - result.to_s - rescue - self.import_url + Gitlab::UrlSanitizer.new(import_url).masked_url end def check_limit unless creator.can_create_project? or namespace.kind == 'group' - self.errors.add(:limit_reached, "Your project limit is #{creator.projects_limit} projects! Please contact your administrator to increase it") + projects_limit = creator.projects_limit + + if projects_limit == 0 + self.errors.add(:limit_reached, "Personal project creation is not allowed. Please contact your administrator with questions") + else + self.errors.add(:limit_reached, "Your project limit is #{projects_limit} projects! Please contact your administrator to increase it") + end end rescue self.errors.add(:base, "Can't check your ability to create project") @@ -787,6 +749,11 @@ class Project < ActiveRecord::Base expire_caches_before_rename(old_path_with_namespace) + if has_container_registry_tags? + # we currently doesn't support renaming repository if it contains tags in container registry + 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 repository moved successfully we need to send update instructions to users. # However we cannot allow rollback since we moved repository @@ -983,13 +950,13 @@ class Project < ActiveRecord::Base shared_runners_enabled? && Ci::Runner.shared.active.any?(&block) end - def valid_runners_token? token + def valid_runners_token?(token) self.runners_token && ActiveSupport::SecurityUtils.variable_size_secure_compare(token, self.runners_token) end # TODO (ayufan): For now we use runners_token (backward compatibility) # In 8.4 every build will have its own individual token valid for time of build - def valid_build_token? token + def valid_build_token?(token) self.builds_enabled? && self.runners_token && ActiveSupport::SecurityUtils.variable_size_secure_compare(token, self.runners_token) end @@ -1045,6 +1012,24 @@ class Project < ActiveRecord::Base update_attribute(:pending_delete, true) end + def running_or_pending_build_count(force: false) + Rails.cache.fetch(['projects', id, 'running_or_pending_build_count'], force: force) do + builds.running_or_pending.count(:all) + end + end + + def mark_import_as_failed(error_message) + original_errors = errors.dup + sanitized_message = Gitlab::UrlSanitizer.sanitize(error_message) + + import_fail + update_column(:import_error, sanitized_message) + rescue ActiveRecord::ActiveRecordError => e + Rails.logger.error("Error setting import status to failed: #{e.message}. Original error: #{sanitized_message}") + ensure + @errors = original_errors + end + def add_export_job(current_user_id:) job_id = ProjectExportWorker.perform_async(current_user_id, self.id) diff --git a/app/models/project_group_link.rb b/app/models/project_group_link.rb index 66f5a609bf..e52a6bd7c8 100644 --- a/app/models/project_group_link.rb +++ b/app/models/project_group_link.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: project_group_links -# -# id :integer not null, primary key -# project_id :integer not null -# group_id :integer not null -# created_at :datetime -# updated_at :datetime -# group_access :integer default(30), not null -# - class ProjectGroupLink < ActiveRecord::Base GUEST = 10 REPORTER = 20 diff --git a/app/models/project_import_data.rb b/app/models/project_import_data.rb index 7830f764ed..ca8a9b4217 100644 --- a/app/models/project_import_data.rb +++ b/app/models/project_import_data.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: project_import_data -# -# id :integer not null, primary key -# project_id :integer -# data :text -# encrypted_credentials :text -# encrypted_credentials_iv :string -# encrypted_credentials_salt :string -# - require 'carrierwave/orm/activerecord' class ProjectImportData < ActiveRecord::Base @@ -18,7 +6,8 @@ class ProjectImportData < ActiveRecord::Base key: Gitlab::Application.secrets.db_key_base, marshal: true, encode: true, - mode: :per_attribute_iv_and_salt + mode: :per_attribute_iv_and_salt, + algorithm: 'aes-256-cbc' serialize :data, JSON diff --git a/app/models/project_services/asana_service.rb b/app/models/project_services/asana_service.rb index 368485a060..7c23b76676 100644 --- a/app/models/project_services/asana_service.rb +++ b/app/models/project_services/asana_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - require 'asana' class AsanaService < Service diff --git a/app/models/project_services/assembla_service.rb b/app/models/project_services/assembla_service.rb index ffb7455b01..d839221d31 100644 --- a/app/models/project_services/assembla_service.rb +++ b/app/models/project_services/assembla_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class AssemblaService < Service include HTTParty diff --git a/app/models/project_services/bamboo_service.rb b/app/models/project_services/bamboo_service.rb index c36ee95e37..1d1780dcfb 100644 --- a/app/models/project_services/bamboo_service.rb +++ b/app/models/project_services/bamboo_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class BambooService < CiService include HTTParty diff --git a/app/models/project_services/buildkite_service.rb b/app/models/project_services/buildkite_service.rb index f9f4897a06..86a06321e2 100644 --- a/app/models/project_services/buildkite_service.rb +++ b/app/models/project_services/buildkite_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - require "addressable/uri" class BuildkiteService < CiService diff --git a/app/models/project_services/builds_email_service.rb b/app/models/project_services/builds_email_service.rb index 20cdfcaffb..54da4d74fc 100644 --- a/app/models/project_services/builds_email_service.rb +++ b/app/models/project_services/builds_email_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class BuildsEmailService < Service prop_accessor :recipients boolean_accessor :add_pusher diff --git a/app/models/project_services/campfire_service.rb b/app/models/project_services/campfire_service.rb index 28c969fe57..511b2eac79 100644 --- a/app/models/project_services/campfire_service.rb +++ b/app/models/project_services/campfire_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class CampfireService < Service prop_accessor :token, :subdomain, :room validates :token, presence: true, if: :activated? diff --git a/app/models/project_services/ci_service.rb b/app/models/project_services/ci_service.rb index 9bc8f982da..596c00705a 100644 --- a/app/models/project_services/ci_service.rb +++ b/app/models/project_services/ci_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - # Base class for CI services # List methods you need to implement to get your CI service # working with GitLab Merge Requests diff --git a/app/models/project_services/custom_issue_tracker_service.rb b/app/models/project_services/custom_issue_tracker_service.rb index 4d1319eb6f..6b2b1daa72 100644 --- a/app/models/project_services/custom_issue_tracker_service.rb +++ b/app/models/project_services/custom_issue_tracker_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class CustomIssueTrackerService < IssueTrackerService prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url diff --git a/app/models/project_services/drone_ci_service.rb b/app/models/project_services/drone_ci_service.rb index d8e00e018c..966dbc41d7 100644 --- a/app/models/project_services/drone_ci_service.rb +++ b/app/models/project_services/drone_ci_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class DroneCiService < CiService prop_accessor :drone_url, :token, :enable_ssl_verification diff --git a/app/models/project_services/emails_on_push_service.rb b/app/models/project_services/emails_on_push_service.rb index 2dbd29062d..e0083c43ad 100644 --- a/app/models/project_services/emails_on_push_service.rb +++ b/app/models/project_services/emails_on_push_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class EmailsOnPushService < Service prop_accessor :send_from_committer_email prop_accessor :disable_diffs diff --git a/app/models/project_services/external_wiki_service.rb b/app/models/project_services/external_wiki_service.rb index 5469049bb5..d7b6e50519 100644 --- a/app/models/project_services/external_wiki_service.rb +++ b/app/models/project_services/external_wiki_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class ExternalWikiService < Service include HTTParty @@ -49,7 +25,7 @@ class ExternalWikiService < Service def execute(_data) @response = HTTParty.get(properties['external_wiki_url'], verify: true) rescue nil - if @response !=200 + if @response != 200 nil end end diff --git a/app/models/project_services/flowdock_service.rb b/app/models/project_services/flowdock_service.rb index 3dc1e0fbe8..dd00275187 100644 --- a/app/models/project_services/flowdock_service.rb +++ b/app/models/project_services/flowdock_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - require "flowdock-git-hook" class FlowdockService < Service diff --git a/app/models/project_services/gemnasium_service.rb b/app/models/project_services/gemnasium_service.rb index b4c311cf66..598aca5e06 100644 --- a/app/models/project_services/gemnasium_service.rb +++ b/app/models/project_services/gemnasium_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - require "gemnasium/gitlab_service" class GemnasiumService < Service diff --git a/app/models/project_services/gitlab_ci_service.rb b/app/models/project_services/gitlab_ci_service.rb index a92f722608..bbc312f521 100644 --- a/app/models/project_services/gitlab_ci_service.rb +++ b/app/models/project_services/gitlab_ci_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - # TODO(ayufan): The GitLabCiService is deprecated and the type should be removed when the database entries are removed class GitlabCiService < CiService # We override the active accessor to always make GitLabCiService disabled diff --git a/app/models/project_services/gitlab_issue_tracker_service.rb b/app/models/project_services/gitlab_issue_tracker_service.rb index 1adaeeb3b2..5d17c35833 100644 --- a/app/models/project_services/gitlab_issue_tracker_service.rb +++ b/app/models/project_services/gitlab_issue_tracker_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class GitlabIssueTrackerService < IssueTrackerService include Gitlab::Routing.url_helpers diff --git a/app/models/project_services/hipchat_service.rb b/app/models/project_services/hipchat_service.rb index f9ddf58872..0ff4f4c8dd 100644 --- a/app/models/project_services/hipchat_service.rb +++ b/app/models/project_services/hipchat_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class HipchatService < Service MAX_COMMITS = 3 diff --git a/app/models/project_services/irker_service.rb b/app/models/project_services/irker_service.rb index b9a592d709..2e5e854fc5 100644 --- a/app/models/project_services/irker_service.rb +++ b/app/models/project_services/irker_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - require 'uri' class IrkerService < Service @@ -94,7 +70,7 @@ class IrkerService < Service private def get_channels - return true unless :activated? + return true unless activated? return true if recipients.nil? || recipients.empty? map_recipients diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb index 98a3a7c6b8..6ae9b16d3c 100644 --- a/app/models/project_services/issue_tracker_service.rb +++ b/app/models/project_services/issue_tracker_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class IssueTrackerService < Service validates :project_url, :issues_url, :new_issue_url, presence: true, url: true, if: :activated? diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb index ba68658f0b..beda89d396 100644 --- a/app/models/project_services/jira_service.rb +++ b/app/models/project_services/jira_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class JiraService < IssueTrackerService include HTTParty include Gitlab::Routing.url_helpers diff --git a/app/models/project_services/pivotaltracker_service.rb b/app/models/project_services/pivotaltracker_service.rb index acaa0c3936..ad19b7795d 100644 --- a/app/models/project_services/pivotaltracker_service.rb +++ b/app/models/project_services/pivotaltracker_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class PivotaltrackerService < Service include HTTParty diff --git a/app/models/project_services/pushover_service.rb b/app/models/project_services/pushover_service.rb index a640c8cb44..3dd878e4c7 100644 --- a/app/models/project_services/pushover_service.rb +++ b/app/models/project_services/pushover_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class PushoverService < Service include HTTParty base_uri 'https://api.pushover.net/1' diff --git a/app/models/project_services/redmine_service.rb b/app/models/project_services/redmine_service.rb index e2137e92c6..11cce3e056 100644 --- a/app/models/project_services/redmine_service.rb +++ b/app/models/project_services/redmine_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class RedmineService < IssueTrackerService prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url diff --git a/app/models/project_services/slack_service.rb b/app/models/project_services/slack_service.rb index 83ffa53a40..cf9e4d5a8b 100644 --- a/app/models/project_services/slack_service.rb +++ b/app/models/project_services/slack_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class SlackService < Service prop_accessor :webhook, :username, :channel boolean_accessor :notify_only_broken_builds diff --git a/app/models/project_services/slack_service/build_message.rb b/app/models/project_services/slack_service/build_message.rb index c124cad4af..69c21b3fc3 100644 --- a/app/models/project_services/slack_service/build_message.rb +++ b/app/models/project_services/slack_service/build_message.rb @@ -35,8 +35,8 @@ class SlackService private def message - "#{project_link}: Commit #{commit_link} of #{branch_link} #{ref_type} by #{user_name} #{humanized_status} in #{duration} second(s)" - end + "#{project_link}: Commit #{commit_link} of #{branch_link} #{ref_type} by #{user_name} #{humanized_status} in #{duration} #{'second'.pluralize(duration)}" + end def format(string) Slack::Notifier::LinkFormatter.format(string) diff --git a/app/models/project_services/slack_service/issue_message.rb b/app/models/project_services/slack_service/issue_message.rb index 438ff33fdf..88e053ec19 100644 --- a/app/models/project_services/slack_service/issue_message.rb +++ b/app/models/project_services/slack_service/issue_message.rb @@ -34,7 +34,12 @@ class SlackService private def message - "#{user_name} #{state} #{issue_link} in #{project_link}: *#{title}*" + case state + when "opened" + "[#{project_link}] Issue #{state} by #{user_name}" + else + "[#{project_link}] Issue #{issue_link} #{state} by #{user_name}" + end end def opened_issue? @@ -42,7 +47,11 @@ class SlackService end def description_message - [{ text: format(description), color: attachment_color }] + [{ + title: issue_title, + title_link: issue_url, + text: format(description), + color: "#C95823" }] end def project_link @@ -50,7 +59,11 @@ class SlackService end def issue_link - "[issue ##{issue_iid}](#{issue_url})" + "[#{issue_title}](#{issue_url})" + end + + def issue_title + "##{issue_iid} #{title}" end end end diff --git a/app/models/project_services/teamcity_service.rb b/app/models/project_services/teamcity_service.rb index 4015da3150..b0dcb52eba 100644 --- a/app/models/project_services/teamcity_service.rb +++ b/app/models/project_services/teamcity_service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - class TeamcityService < CiService include HTTParty diff --git a/app/models/project_snippet.rb b/app/models/project_snippet.rb index b4b2807eba..25b5d77764 100644 --- a/app/models/project_snippet.rb +++ b/app/models/project_snippet.rb @@ -1,19 +1,3 @@ -# == Schema Information -# -# Table name: snippets -# -# id :integer not null, primary key -# title :string -# content :text -# author_id :integer not null -# project_id :integer -# created_at :datetime -# updated_at :datetime -# file_name :string -# type :string -# visibility_level :integer default(0), not null -# - class ProjectSnippet < Snippet belongs_to :project belongs_to :author, class_name: "User" @@ -23,5 +7,6 @@ class ProjectSnippet < Snippet # Scopes scope :fresh, -> { order("created_at DESC") } - participant :author, :notes + participant :author + participant :notes_with_associations end diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb index 7c1a61bb0b..25d82929c0 100644 --- a/app/models/project_wiki.rb +++ b/app/models/project_wiki.rb @@ -27,6 +27,10 @@ class ProjectWiki @project.path_with_namespace + ".wiki" end + def web_url + Gitlab::Routing.url_helpers.namespace_project_wiki_url(@project.namespace, @project, :home) + end + def url_to_repo gitlab_shell.url_to_repo(path_with_namespace) end @@ -40,7 +44,7 @@ class ProjectWiki end def wiki_base_path - ["/", @project.path_with_namespace, "/wikis"].join('') + [Gitlab.config.gitlab.relative_url_root, "/", @project.path_with_namespace, "/wikis"].join('') end # Returns the Gollum::Wiki object. @@ -113,7 +117,7 @@ class ProjectWiki end def page_title_and_dir(title) - title_array = title.split("/") + title_array = title.split("/") title = title_array.pop [title, title_array.join("/")] end @@ -142,6 +146,16 @@ class ProjectWiki wiki end + def hook_attrs + { + web_url: web_url, + git_ssh_url: ssh_url_to_repo, + git_http_url: http_url_to_repo, + path_with_namespace: path_with_namespace, + default_branch: default_branch + } + end + private def init_repo(path_with_namespace) diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb index 3d2052c892..33cf046fa7 100644 --- a/app/models/protected_branch.rb +++ b/app/models/protected_branch.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: protected_branches -# -# id :integer not null, primary key -# project_id :integer not null -# name :string not null -# created_at :datetime -# updated_at :datetime -# developers_can_push :boolean default(FALSE), not null -# - class ProtectedBranch < ActiveRecord::Base include Gitlab::ShellAdapter diff --git a/app/models/release.rb b/app/models/release.rb index dc700d1ea5..e196b84eb1 100644 --- a/app/models/release.rb +++ b/app/models/release.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: releases -# -# id :integer not null, primary key -# tag :string -# description :text -# project_id :integer -# created_at :datetime -# updated_at :datetime -# - class Release < ActiveRecord::Base belongs_to :project diff --git a/app/models/repository.rb b/app/models/repository.rb index 7aebfe279f..1ab163510b 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -81,7 +81,7 @@ class Repository def commit(id = 'HEAD') return nil unless exists? commit = Gitlab::Git::Commit.find(raw_repository, id) - commit = Commit.new(commit, @project) if commit + commit = ::Commit.new(commit, @project) if commit commit rescue Rugged::OdbError nil @@ -195,6 +195,10 @@ class Repository cache.fetch(:branch_names) { branches.map(&:name) } end + def branch_exists?(branch_name) + branch_names.include?(branch_name) + end + def tag_names cache.fetch(:tag_names) { raw_repository.tag_names } end @@ -241,7 +245,7 @@ class Repository def cache_keys %i(size branch_names tag_names commit_count readme version contribution_guide changelog - license_blob license_key) + license_blob license_key gitignore) end def build_cache @@ -252,6 +256,10 @@ class Repository end end + def expire_gitignore + cache.expire(:gitignore) + end + def expire_tags_cache cache.expire(:tag_names) @tags = nil @@ -453,7 +461,7 @@ class Repository def version cache.fetch(:version) do tree(:head).blobs.find do |file| - file.name.downcase == 'version' + file.name.casecmp('version').zero? end end end @@ -468,33 +476,37 @@ class Repository def changelog cache.fetch(:changelog) do - tree(:head).blobs.find do |file| - file.name =~ /\A(changelog|history|changes|news)/i - end + file_on_head(/\A(changelog|history|changes|news)/i) end end def license_blob - return nil if !exists? || empty? + return nil unless head_exists? cache.fetch(:license_blob) do - tree(:head).blobs.find do |file| - file.name =~ /\A(licen[sc]e|copying)(\..+|\z)/i - end + file_on_head(/\A(licen[sc]e|copying)(\..+|\z)/i) end end def license_key - return nil if !exists? || empty? + return nil unless head_exists? cache.fetch(:license_key) do Licensee.license(path).try(:key) end end - def gitlab_ci_yml + def gitignore return nil if !exists? || empty? + cache.fetch(:gitignore) do + file_on_head(/\A\.gitignore\z/) + end + end + + def gitlab_ci_yml + return nil unless head_exists? + @gitlab_ci_yml ||= tree(:head).blobs.find do |file| file.name == '.gitlab-ci.yml' end @@ -795,7 +807,7 @@ class Repository def check_revert_content(commit, base_branch) source_sha = find_branch(base_branch).target args = [commit.id, source_sha] - args << { mainline: 1 } if commit.merge_commit? + args << { mainline: 1 } if commit.merge_commit? revert_index = rugged.revert_commit(*args) return false if revert_index.conflicts? @@ -809,7 +821,7 @@ class Repository def check_cherry_pick_content(commit, base_branch) source_sha = find_branch(base_branch).target args = [commit.id, source_sha] - args << 1 if commit.merge_commit? + args << 1 if commit.merge_commit? cherry_pick_index = rugged.cherrypick_commit(*args) return false if cherry_pick_index.conflicts? @@ -850,7 +862,7 @@ class Repository 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 #{Regexp.escape(query)} #{ref || root_ref}) + 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}) Gitlab::Popen.popen(args, path_to_repo).first.scrub.split(/^--$/) end @@ -960,12 +972,6 @@ class Repository end end - def main_language - return if empty? || rugged.head_unborn? - - Linguist::Repository.new(rugged, rugged.head.target_id).language - end - def avatar return nil unless exists? @@ -981,4 +987,12 @@ class Repository def cache @cache ||= RepositoryCache.new(path_with_namespace) end + + def head_exists? + exists? && !empty? && !rugged.head_unborn? + end + + def file_on_head(regex) + tree(:head).blobs.find { |file| file.name =~ regex } + end end diff --git a/app/models/security_event.rb b/app/models/security_event.rb index 0bee03974f..d131c11cb6 100644 --- a/app/models/security_event.rb +++ b/app/models/security_event.rb @@ -1,16 +1,2 @@ -# == Schema Information -# -# Table name: audit_events -# -# id :integer not null, primary key -# author_id :integer not null -# type :string not null -# entity_id :integer not null -# entity_type :string not null -# details :text -# created_at :datetime -# updated_at :datetime -# - class SecurityEvent < AuditEvent end diff --git a/app/models/sent_notification.rb b/app/models/sent_notification.rb index 99279a2e08..375f195dba 100644 --- a/app/models/sent_notification.rb +++ b/app/models/sent_notification.rb @@ -1,17 +1,3 @@ -# == Schema Information -# -# Table name: sent_notifications -# -# id :integer not null, primary key -# project_id :integer -# noteable_id :integer -# noteable_type :string -# recipient_id :integer -# commit_id :string -# reply_key :string not null -# line_code :string -# - class SentNotification < ActiveRecord::Base belongs_to :project belongs_to :noteable, polymorphic: true diff --git a/app/models/service.rb b/app/models/service.rb index bf16a54530..de3fd24584 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -1,27 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string -# title :string -# project_id :integer -# created_at :datetime not null -# updated_at :datetime not null -# active :boolean not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# category :string default("common"), not null -# default :boolean default(FALSE) -# wiki_page_events :boolean default(TRUE) -# - # To add new service you should build a class inherited from Service # and implement a set of methods class Service < ActiveRecord::Base diff --git a/app/models/snippet.rb b/app/models/snippet.rb index 2f905a9094..407697b745 100644 --- a/app/models/snippet.rb +++ b/app/models/snippet.rb @@ -1,19 +1,3 @@ -# == Schema Information -# -# Table name: snippets -# -# id :integer not null, primary key -# title :string -# content :text -# author_id :integer not null -# project_id :integer -# created_at :datetime -# updated_at :datetime -# file_name :string -# type :string -# visibility_level :integer default(0), not null -# - class Snippet < ActiveRecord::Base include Gitlab::VisibilityLevel include Linguist::BlobHelper @@ -46,7 +30,8 @@ class Snippet < ActiveRecord::Base scope :public_and_internal, -> { where(visibility_level: [Snippet::PUBLIC, Snippet::INTERNAL]) } scope :fresh, -> { order("created_at DESC") } - participant :author, :notes + participant :author + participant :notes_with_associations def self.reference_prefix '$' @@ -116,6 +101,10 @@ class Snippet < ActiveRecord::Base content.lines.count > 1000 end + def notes_with_associations + notes.includes(:author, :project) + end + class << self # Searches for snippets with a matching title or file name. # diff --git a/app/models/spam_log.rb b/app/models/spam_log.rb index f49eb7d88e..12df68ef83 100644 --- a/app/models/spam_log.rb +++ b/app/models/spam_log.rb @@ -1,20 +1,3 @@ -# == Schema Information -# -# Table name: spam_logs -# -# id :integer not null, primary key -# user_id :integer -# source_ip :string -# user_agent :string -# via_api :boolean -# project_id :integer -# noteable_type :string -# title :string -# description :text -# created_at :datetime not null -# updated_at :datetime not null -# - class SpamLog < ActiveRecord::Base belongs_to :user diff --git a/app/models/subscription.rb b/app/models/subscription.rb index 242faa7d32..3b8aa1eb86 100644 --- a/app/models/subscription.rb +++ b/app/models/subscription.rb @@ -1,16 +1,3 @@ -# == Schema Information -# -# Table name: subscriptions -# -# id :integer not null, primary key -# user_id :integer -# subscribable_id :integer -# subscribable_type :string -# subscribed :boolean -# created_at :datetime -# updated_at :datetime -# - class Subscription < ActiveRecord::Base belongs_to :user belongs_to :subscribable, polymorphic: true diff --git a/app/models/todo.rb b/app/models/todo.rb index d85f7bfdf5..3a09137332 100644 --- a/app/models/todo.rb +++ b/app/models/todo.rb @@ -1,24 +1,7 @@ -# == Schema Information -# -# Table name: todos -# -# id :integer not null, primary key -# user_id :integer not null -# project_id :integer not null -# target_id :integer -# target_type :string not null -# author_id :integer -# action :integer not null -# state :string not null -# created_at :datetime -# updated_at :datetime -# note_id :integer -# commit_id :string -# - class Todo < ActiveRecord::Base - ASSIGNED = 1 - MENTIONED = 2 + ASSIGNED = 1 + MENTIONED = 2 + BUILD_FAILED = 3 belongs_to :author, class_name: "User" belongs_to :note @@ -46,6 +29,10 @@ class Todo < ActiveRecord::Base state :done end + def build_failed? + action == BUILD_FAILED + end + def body if note.present? note.note diff --git a/app/models/user.rb b/app/models/user.rb index 959b1f9375..172845c9d2 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,68 +1,3 @@ -# == Schema Information -# -# Table name: users -# -# id :integer not null, primary key -# email :string default(""), not null -# encrypted_password :string default(""), not null -# reset_password_token :string -# reset_password_sent_at :datetime -# remember_created_at :datetime -# sign_in_count :integer default(0) -# current_sign_in_at :datetime -# last_sign_in_at :datetime -# current_sign_in_ip :string -# last_sign_in_ip :string -# created_at :datetime -# updated_at :datetime -# name :string -# admin :boolean default(FALSE), not null -# projects_limit :integer default(10) -# skype :string default(""), not null -# linkedin :string default(""), not null -# twitter :string default(""), not null -# authentication_token :string -# theme_id :integer default(1), not null -# bio :string -# failed_attempts :integer default(0) -# locked_at :datetime -# username :string -# can_create_group :boolean default(TRUE), not null -# can_create_team :boolean default(TRUE), not null -# state :string -# color_scheme_id :integer default(1), not null -# notification_level :integer default(1), not null -# password_expires_at :datetime -# created_by_id :integer -# last_credential_check_at :datetime -# avatar :string -# confirmation_token :string -# confirmed_at :datetime -# confirmation_sent_at :datetime -# unconfirmed_email :string -# hide_no_ssh_key :boolean default(FALSE) -# website_url :string default(""), not null -# notification_email :string -# hide_no_password :boolean default(FALSE) -# password_automatically_set :boolean default(FALSE) -# location :string -# encrypted_otp_secret :string -# encrypted_otp_secret_iv :string -# encrypted_otp_secret_salt :string -# otp_required_for_login :boolean default(FALSE), not null -# otp_backup_codes :text -# public_email :string default(""), not null -# dashboard :integer default(0) -# project_view :integer default(0) -# consumed_timestep :integer -# layout :integer default(0) -# hide_project_limit :boolean default(FALSE) -# unlock_token :string -# otp_grace_period_started_at :datetime -# ldap_email :boolean default(FALSE), not null -# external :boolean default(FALSE) -# - require 'carrierwave/orm/activerecord' class User < ActiveRecord::Base @@ -85,14 +20,19 @@ class User < ActiveRecord::Base default_value_for :hide_no_password, false default_value_for :theme_id, gitlab_config.default_theme + attr_encrypted :otp_secret, + key: Gitlab::Application.config.secret_key_base, + mode: :per_attribute_iv_and_salt, + algorithm: 'aes-256-cbc' + devise :two_factor_authenticatable, - otp_secret_encryption_key: File.read(Rails.root.join('.secret')).chomp + otp_secret_encryption_key: Gitlab::Application.config.secret_key_base alias_attribute :two_factor_enabled, :otp_required_for_login devise :two_factor_backupable, otp_number_of_backup_codes: 10 serialize :otp_backup_codes, JSON - devise :lockable, :async, :recoverable, :rememberable, :trackable, + devise :lockable, :recoverable, :rememberable, :trackable, :validatable, :omniauthable, :confirmable, :registerable attr_accessor :force_random_password @@ -177,6 +117,7 @@ class User < ActiveRecord::Base before_save :ensure_external_user_rights after_save :ensure_namespace_correct after_initialize :set_projects_limit + before_create :check_confirmation_email after_create :post_create_hook after_destroy :post_destroy_hook @@ -372,6 +313,10 @@ class User < ActiveRecord::Base @reset_token end + def check_confirmation_email + skip_confirmation! unless current_application_settings.send_user_confirmation_email + end + def recently_sent_password_reset? reset_password_sent_at.present? && reset_password_sent_at >= 1.minute.ago end @@ -446,17 +391,17 @@ class User < ActiveRecord::Base Project.where("projects.id IN (#{projects_union.to_sql})") end + def viewable_starred_projects + starred_projects.where("projects.visibility_level IN (?) OR projects.id IN (#{projects_union.to_sql})", + [Project::PUBLIC, Project::INTERNAL]) + end + def owned_projects @owned_projects ||= Project.where('namespace_id IN (?) OR namespace_id = ?', owned_groups.select(:id), namespace.id).joins(:namespace) end - # Team membership in authorized projects - def tm_in_authorized_projects - ProjectMember.where(source_id: authorized_projects.map(&:id), user_id: self.id) - end - def is_admin? admin end @@ -546,10 +491,6 @@ class User < ActiveRecord::Base "#{name} (#{username})" end - def tm_of(project) - project.project_member_by_id(self.id) - end - def already_forked?(project) !!fork_of(project) end @@ -835,6 +776,23 @@ class User < ActiveRecord::Base notification_settings.find_or_initialize_by(source: source) end + def assigned_open_merge_request_count(force: false) + Rails.cache.fetch(['users', id, 'assigned_open_merge_request_count'], force: force) do + assigned_merge_requests.opened.count + end + end + + def assigned_open_issues_count(force: false) + Rails.cache.fetch(['users', id, 'assigned_open_issues_count'], force: force) do + assigned_issues.opened.count + end + end + + def update_cache_counts + assigned_open_merge_request_count(force: true) + assigned_open_issues_count(force: true) + end + private def projects_union diff --git a/app/models/users_star_project.rb b/app/models/users_star_project.rb index 413f3f485a..0dfe597317 100644 --- a/app/models/users_star_project.rb +++ b/app/models/users_star_project.rb @@ -1,14 +1,3 @@ -# == Schema Information -# -# Table name: users_star_projects -# -# id :integer not null, primary key -# project_id :integer not null -# user_id :integer not null -# created_at :datetime -# updated_at :datetime -# - class UsersStarProject < ActiveRecord::Base belongs_to :project, counter_cache: :star_count, touch: true belongs_to :user diff --git a/app/services/auth/container_registry_authentication_service.rb b/app/services/auth/container_registry_authentication_service.rb new file mode 100644 index 0000000000..e57b95f21e --- /dev/null +++ b/app/services/auth/container_registry_authentication_service.rb @@ -0,0 +1,87 @@ +module Auth + class ContainerRegistryAuthenticationService < BaseService + include Gitlab::CurrentSettings + + AUDIENCE = 'container_registry' + + def execute + return error('not found', 404) unless registry.enabled + + unless current_user || project + return error('forbidden', 403) unless scope + end + + { token: authorized_token(scope).encoded } + end + + def self.full_access_token(*names) + registry = Gitlab.config.registry + token = JSONWebToken::RSAToken.new(registry.key) + token.issuer = registry.issuer + token.audience = AUDIENCE + token.expire_time = token_expire_at + token[:access] = names.map do |name| + { type: 'repository', name: name, actions: %w(*) } + end + token.encoded + end + + private + + def authorized_token(*accesses) + token = JSONWebToken::RSAToken.new(registry.key) + token.issuer = registry.issuer + token.audience = params[:service] + token.subject = current_user.try(:username) + token.expire_time = ContainerRegistryAuthenticationService.token_expire_at + token[:access] = accesses.compact + token + end + + def scope + return unless params[:scope] + + @scope ||= process_scope(params[:scope]) + end + + def process_scope(scope) + type, name, actions = scope.split(':', 3) + actions = actions.split(',') + return unless type == 'repository' + + process_repository_access(type, name, actions) + end + + def process_repository_access(type, name, actions) + requested_project = Project.find_with_namespace(name) + return unless requested_project + + actions = actions.select do |action| + can_access?(requested_project, action) + end + + { type: type, name: name, actions: actions } if actions.present? + end + + def can_access?(requested_project, requested_action) + return false unless requested_project.container_registry_enabled? + + case requested_action + when 'pull' + requested_project == project || can?(current_user, :read_container_image, requested_project) + when 'push' + requested_project == project || can?(current_user, :create_container_image, requested_project) + else + false + end + end + + def registry + Gitlab.config.registry + end + + def self.token_expire_at + Time.now + current_application_settings.container_registry_token_expire_delay.minutes + end + end +end diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb new file mode 100644 index 0000000000..5bc0c31cb4 --- /dev/null +++ b/app/services/ci/create_pipeline_service.rb @@ -0,0 +1,50 @@ +module Ci + class CreatePipelineService < BaseService + def execute + pipeline = project.ci_commits.new(params) + + unless ref_names.include?(params[:ref]) + pipeline.errors.add(:base, 'Reference not found') + return pipeline + end + + unless commit + pipeline.errors.add(:base, 'Commit not found') + return pipeline + end + + unless can?(current_user, :create_pipeline, project) + pipeline.errors.add(:base, 'Insufficient permissions to create a new pipeline') + return pipeline + end + + begin + Ci::Commit.transaction do + pipeline.sha = commit.id + + unless pipeline.config_processor + pipeline.errors.add(:base, pipeline.yaml_errors || 'Missing .gitlab-ci.yml file') + raise ActiveRecord::Rollback + end + + pipeline.save! + pipeline.create_builds(current_user) + end + rescue + pipeline.errors.add(:base, 'The pipeline could not be created. Please try again.') + end + + pipeline + end + + private + + def ref_names + @ref_names ||= project.repository.ref_names + end + + def commit + @commit ||= project.commit(params[:ref]) + end + end +end diff --git a/app/services/create_commit_builds_service.rb b/app/services/create_commit_builds_service.rb index 0d2aa1ff03..5b6fefe669 100644 --- a/app/services/create_commit_builds_service.rb +++ b/app/services/create_commit_builds_service.rb @@ -18,19 +18,16 @@ class CreateCommitBuildsService return false end - commit = project.ci_commit(sha, ref) - unless commit - commit = project.ci_commits.new(sha: sha, ref: ref, before_sha: before_sha, tag: tag) + commit = Ci::Commit.new(project: project, sha: sha, ref: ref, before_sha: before_sha, tag: tag) - # Skip creating ci_commit when no gitlab-ci.yml is found - unless commit.ci_yaml_file - return false - end - - # Create a new ci_commit - commit.save! + # Skip creating ci_commit when no gitlab-ci.yml is found + unless commit.ci_yaml_file + return false end + # Create a new ci_commit + commit.save! + # Skip creating builds for commits that have [ci skip] unless commit.skip_ci? # Create builds for commit diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index 66136b6261..a886f35981 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -53,10 +53,6 @@ class GitPushService < BaseService # could cause the last commit of a merge request to change. update_merge_requests - # Checks if the main language has changed in the project and if so - # it updates it accordingly - update_main_language - perform_housekeeping end @@ -64,19 +60,6 @@ class GitPushService < BaseService @project.repository.copy_gitattributes(params[:ref]) end - def update_main_language - # Performance can be bad so for now only check main_language once - # See https://gitlab.com/gitlab-org/gitlab-ce/issues/14937 - return if @project.main_language.present? - - return unless is_default_branch? - return unless push_to_new_branch? || push_to_existing_branch? - - current_language = @project.repository.main_language - @project.update_attributes(main_language: current_language) - true - end - protected def update_merge_requests diff --git a/app/services/git_tag_push_service.rb b/app/services/git_tag_push_service.rb index 7410442609..299a0a967b 100644 --- a/app/services/git_tag_push_service.rb +++ b/app/services/git_tag_push_service.rb @@ -23,7 +23,7 @@ class GitTagPushService < BaseService commits = [] message = nil - if !Gitlab::Git.blank_ref?(params[:newrev]) + unless Gitlab::Git.blank_ref?(params[:newrev]) tag_name = Gitlab::Git.ref_name(params[:ref]) tag = project.repository.find_tag(tag_name) if tag && tag.target == params[:newrev] diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb index 3563cbaa99..c7d406cc33 100644 --- a/app/services/issues/update_service.rb +++ b/app/services/issues/update_service.rb @@ -24,6 +24,10 @@ module Issues todo_service.reassigned_issue(issue, current_user) end + if issue.previous_changes.include?('confidential') + create_confidentiality_note(issue) + end + added_labels = issue.labels - old_labels if added_labels.present? notification_service.relabeled_issue(issue, added_labels, current_user) @@ -37,5 +41,11 @@ module Issues def close_service Issues::CloseService end + + private + + def create_confidentiality_note(issue) + SystemNoteService.change_issue_confidentiality(issue, issue.project, current_user) + end end end diff --git a/app/services/merge_requests/add_todo_when_build_fails_service.rb b/app/services/merge_requests/add_todo_when_build_fails_service.rb new file mode 100644 index 0000000000..566049525c --- /dev/null +++ b/app/services/merge_requests/add_todo_when_build_fails_service.rb @@ -0,0 +1,17 @@ +module MergeRequests + class AddTodoWhenBuildFailsService < MergeRequests::BaseService + # Adds a todo to the parent merge_request when a CI build fails + def execute(commit_status) + each_merge_request(commit_status) do |merge_request| + todo_service.merge_request_build_failed(merge_request) + end + end + + # Closes any pending build failed todos for the parent MRs when a build is retried + def close(commit_status) + each_merge_request(commit_status) do |merge_request| + todo_service.merge_request_build_retried(merge_request) + end + end + end +end diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb index e6837a1869..9d7fca6882 100644 --- a/app/services/merge_requests/base_service.rb +++ b/app/services/merge_requests/base_service.rb @@ -38,5 +38,30 @@ module MergeRequests def filter_params super(:merge_request) end + + def merge_request_from(commit_status) + branches = commit_status.ref + + # This is for ref-less builds + branches ||= @project.repository.branch_names_contains(commit_status.sha) + + return [] if branches.blank? + + merge_requests = @project.origin_merge_requests.opened.where(source_branch: branches).to_a + merge_requests += @project.fork_merge_requests.opened.where(source_branch: branches).to_a + + merge_requests.uniq.select(&:source_project) + end + + def each_merge_request(commit_status) + merge_request_from(commit_status).each do |merge_request| + ci_commit = merge_request.ci_commit + + next unless ci_commit + next unless ci_commit.sha == commit_status.sha + + yield merge_request, ci_commit + end + end end end diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb index cd4230aa5e..1b48899bb0 100644 --- a/app/services/merge_requests/build_service.rb +++ b/app/services/merge_requests/build_service.rb @@ -66,7 +66,7 @@ module MergeRequests commits = merge_request.compare_commits if commits && commits.count == 1 commit = commits.first - merge_request.title = commit.title + merge_request.title = commit.title merge_request.description ||= commit.description.try(:strip) elsif iid && (issue = merge_request.target_project.get_issue(iid)) && !issue.try(:confidential?) case issue diff --git a/app/services/merge_requests/create_service.rb b/app/services/merge_requests/create_service.rb index 33609d01f2..96a25330af 100644 --- a/app/services/merge_requests/create_service.rb +++ b/app/services/merge_requests/create_service.rb @@ -8,11 +8,14 @@ module MergeRequests @project = Project.find(params[:target_project_id]) if params[:target_project_id] filter_params - label_params = params[:label_ids] - merge_request = MergeRequest.new(params.except(:label_ids)) + label_params = params.delete(:label_ids) + force_remove_source_branch = params.delete(:force_remove_source_branch) + + merge_request = MergeRequest.new(params) merge_request.source_project = source_project merge_request.target_project ||= source_project merge_request.author = current_user + merge_request.merge_params['force_remove_source_branch'] = force_remove_source_branch if merge_request.save merge_request.update_attributes(label_ids: label_params) diff --git a/app/services/merge_requests/merge_service.rb b/app/services/merge_requests/merge_service.rb index 9a58383b39..9aaf5a5e56 100644 --- a/app/services/merge_requests/merge_service.rb +++ b/app/services/merge_requests/merge_service.rb @@ -45,10 +45,14 @@ module MergeRequests def after_merge MergeRequests::PostMergeService.new(project, current_user).execute(merge_request) - if params[:should_remove_source_branch].present? - DeleteBranchService.new(@merge_request.source_project, current_user). + if params[:should_remove_source_branch].present? || @merge_request.force_remove_source_branch? + DeleteBranchService.new(@merge_request.source_project, branch_deletion_user). execute(merge_request.source_branch) end end + + def branch_deletion_user + @merge_request.force_remove_source_branch? ? @merge_request.author : current_user + end end 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 d6af12f973..8fd6a4ea1f 100644 --- a/app/services/merge_requests/merge_when_build_succeeds_service.rb +++ b/app/services/merge_requests/merge_when_build_succeeds_service.rb @@ -20,15 +20,9 @@ module MergeRequests # Triggers the automatic merge of merge_request once the build succeeds def trigger(commit_status) - merge_requests = merge_request_from(commit_status) - - merge_requests.each do |merge_request| + each_merge_request(commit_status) do |merge_request, ci_commit| next unless merge_request.merge_when_build_succeeds? next unless merge_request.mergeable? - - ci_commit = merge_request.ci_commit - next unless ci_commit - next unless ci_commit.sha == commit_status.sha next unless ci_commit.success? MergeWorker.perform_async(merge_request.id, merge_request.merge_user_id, merge_request.merge_params) @@ -47,20 +41,5 @@ module MergeRequests end end - private - - def merge_request_from(commit_status) - branches = commit_status.ref - - # This is for ref-less builds - branches ||= @project.repository.branch_names_contains(commit_status.sha) - - return [] if branches.blank? - - merge_requests = @project.origin_merge_requests.opened.where(source_branch: branches).to_a - merge_requests += @project.fork_merge_requests.opened.where(source_branch: branches).to_a - - merge_requests.uniq.select(&:source_project) - end end end diff --git a/app/services/merge_requests/refresh_service.rb b/app/services/merge_requests/refresh_service.rb index 8b3d56c2b4..fe0579744b 100644 --- a/app/services/merge_requests/refresh_service.rb +++ b/app/services/merge_requests/refresh_service.rb @@ -12,6 +12,7 @@ module MergeRequests close_merge_requests reload_merge_requests reset_merge_when_build_succeeds + mark_pending_todos_done # Leave a system note if a branch was deleted/added if branch_added? || branch_removed? @@ -80,6 +81,12 @@ module MergeRequests merge_requests_for_source_branch.each(&:reset_merge_when_build_succeeds) end + def mark_pending_todos_done + merge_requests_for_source_branch.each do |merge_request| + todo_service.merge_request_push(merge_request, @current_user) + end + end + def find_new_commits if branch_added? @commits = [] diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb index 477c64e737..026a37997d 100644 --- a/app/services/merge_requests/update_service.rb +++ b/app/services/merge_requests/update_service.rb @@ -11,6 +11,8 @@ module MergeRequests params.except!(:target_project_id) params.except!(:source_branch) + merge_request.merge_params['force_remove_source_branch'] = params.delete(:force_remove_source_branch) + update(merge_request) end diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb index 0158699481..2bb312bb25 100644 --- a/app/services/notes/create_service.rb +++ b/app/services/notes/create_service.rb @@ -5,8 +5,6 @@ module Notes note.author = current_user note.system = false - return unless valid_project?(note) - if note.save # Finish the harder work in the background NewNoteWorker.perform_in(2.seconds, note.id, params) @@ -15,14 +13,5 @@ module Notes note end - - private - - def valid_project?(note) - return false unless project - return true if note.for_commit? - - note.noteable.try(:project) == project - end end end diff --git a/app/services/projects/autocomplete_service.rb b/app/services/projects/autocomplete_service.rb index ba50305dbd..eb73948006 100644 --- a/app/services/projects/autocomplete_service.rb +++ b/app/services/projects/autocomplete_service.rb @@ -4,6 +4,10 @@ module Projects @project.issues.visible_to_user(current_user).opened.select([:iid, :title]) end + def milestones + @project.milestones.active.reorder(due_date: :asc, title: :asc).select([:iid, :title]) + end + def merge_requests @project.merge_requests.opened.select([:iid, :title]) end diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index 501e58c140..61cac5419a 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -6,6 +6,7 @@ module Projects def execute forked_from_project_id = params.delete(:forked_from_project_id) + import_data = params.delete(:import_data) @project = Project.new(params) @@ -49,22 +50,20 @@ module Projects @project.build_forked_project_link(forked_from_project_id: forked_from_project_id) end - Project.transaction do - @project.save + save_project_and_import_data(import_data) - if @project.persisted? && !@project.import? - raise 'Failed to create repository' unless @project.create_repository - end - end + @project.import_start if @project.import? after_create_actions if @project.persisted? + if @project.errors.empty? + @project.add_import_job if @project.import? + else + fail(error: @project.errors.full_messages.join(', ')) + end @project rescue => e - message = "Unable to save project: #{e.message}" - Rails.logger.error(message) - @project.errors.add(:base, message) if @project - @project + fail(error: e.message) end protected @@ -93,8 +92,30 @@ module Projects unless @project.group @project.team << [current_user, :master, current_user] end + end - @project.import_start if @project.import? + def save_project_and_import_data(import_data) + Project.transaction do + @project.create_or_update_import_data(data: import_data[:data], credentials: import_data[:credentials]) if import_data + + if @project.save && !@project.import? + raise 'Failed to create repository' unless @project.create_repository + end + end + end + + def fail(error:) + message = "Unable to save project. Error: #{error}" + message << "Project ID: #{@project.id}" if @project && @project.id + + Rails.logger.error(message) + + if @project && @project.import? + @project.errors.add(:base, message) + @project.mark_import_as_failed(message) + end + + @project end end end diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb index 19aab999e0..f09072975c 100644 --- a/app/services/projects/destroy_service.rb +++ b/app/services/projects/destroy_service.rb @@ -26,6 +26,10 @@ module Projects Project.transaction do project.destroy! + unless remove_registry_tags + raise_error('Failed to remove project container registry. Please try again or contact administrator') + end + unless remove_repository(repo_path) raise_error('Failed to remove project repository. Please try again or contact administrator') end @@ -35,7 +39,7 @@ module Projects end end - log_info("Project \"#{project.name}\" was removed") + log_info("Project \"#{project.path_with_namespace}\" was removed") system_hook_service.execute_hooks_for(project, :destroy) true end @@ -59,6 +63,12 @@ module Projects end end + def remove_registry_tags + return true unless Gitlab.config.registry.enabled + + project.container_registry_repository.delete_tags + end + def raise_error(message) raise DestroyError.new(message) end diff --git a/app/services/projects/fork_service.rb b/app/services/projects/fork_service.rb index 0577ae778d..de6dc38cc8 100644 --- a/app/services/projects/fork_service.rb +++ b/app/services/projects/fork_service.rb @@ -3,7 +3,7 @@ module Projects def execute new_params = { forked_from_project_id: @project.id, - visibility_level: @project.visibility_level, + visibility_level: allowed_visibility_level, description: @project.description, name: @project.name, path: @project.path, @@ -19,5 +19,17 @@ module Projects new_project = CreateService.new(current_user, new_params).execute new_project end + + private + + def allowed_visibility_level + project_level = @project.visibility_level + + if Gitlab::VisibilityLevel.non_restricted_level?(project_level) + project_level + else + Gitlab::VisibilityLevel.highest_allowed_level + end + end end end diff --git a/app/services/projects/housekeeping_service.rb b/app/services/projects/housekeeping_service.rb index 3b7c36f090..43db29315a 100644 --- a/app/services/projects/housekeeping_service.rb +++ b/app/services/projects/housekeeping_service.rb @@ -22,7 +22,7 @@ module Projects end def execute - raise LeaseTaken if !try_obtain_lease + raise LeaseTaken unless try_obtain_lease GitlabShellOneShotWorker.perform_async(:gc, @project.path_with_namespace) ensure diff --git a/app/services/projects/import_service.rb b/app/services/projects/import_service.rb index ef15ef6a47..c4838d31f2 100644 --- a/app/services/projects/import_service.rb +++ b/app/services/projects/import_service.rb @@ -39,7 +39,7 @@ module Projects begin gitlab_shell.import_repository(project.path_with_namespace, project.import_url) rescue Gitlab::Shell::Error => e - raise Error, e.message + raise Error, "Error importing repository #{project.import_url} into #{project.path_with_namespace} - #{e.message}" end end diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb index 111b3ec05e..03b57dea51 100644 --- a/app/services/projects/transfer_service.rb +++ b/app/services/projects/transfer_service.rb @@ -34,6 +34,11 @@ module Projects raise TransferError.new("Project with same path in target namespace already exists") end + if project.has_container_registry_tags? + # we currently doesn't support renaming repository if it contains tags in container registry + raise TransferError.new('Project cannot be transferred, because tags are present in its container registry') + end + project.expire_caches_before_rename(old_path) # Apply new namespace id and visibility level diff --git a/app/services/system_hooks_service.rb b/app/services/system_hooks_service.rb index e43b5b51e5..1fb72cf89e 100644 --- a/app/services/system_hooks_service.rb +++ b/app/services/system_hooks_service.rb @@ -85,7 +85,7 @@ class SystemHooksService path_with_namespace: model.path_with_namespace, project_id: model.id, owner_name: owner.name, - owner_email: owner.respond_to?(:email) ? owner.email : "", + owner_email: owner.respond_to?(:email) ? owner.email : "", project_visibility: Project.visibility_levels.key(model.visibility_level_field).downcase } end diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb index 4bdb1b0c07..4e8fa0818b 100644 --- a/app/services/system_note_service.rb +++ b/app/services/system_note_service.rb @@ -169,12 +169,33 @@ class SystemNoteService # # Returns the created Note object def self.change_title(noteable, project, author, old_title) - return unless noteable.respond_to?(:title) + new_title = noteable.title.dup - body = "Title changed from **#{old_title}** to **#{noteable.title}**" + old_diffs, new_diffs = Gitlab::Diff::InlineDiff.new(old_title, new_title).inline_diffs + + marked_old_title = Gitlab::Diff::InlineDiffMarker.new(old_title).mark(old_diffs, mode: :deletion, markdown: true) + marked_new_title = Gitlab::Diff::InlineDiffMarker.new(new_title).mark(new_diffs, mode: :addition, markdown: true) + + body = "Changed title: **#{marked_old_title}** → **#{marked_new_title}**" create_note(noteable: noteable, project: project, author: author, note: body) end + # Called when the confidentiality changes + # + # issue - Issue object + # project - Project owning the issue + # author - User performing the change + # + # Example Note text: + # + # "Made the issue confidential" + # + # Returns the created Note object + def self.change_issue_confidentiality(issue, project, author) + body = issue.confidential ? 'Made the issue confidential' : 'Made the issue visible' + create_note(noteable: issue, project: project, author: author, note: body) + end + # Called when a branch in Noteable is changed # # noteable - Noteable object diff --git a/app/services/todo_service.rb b/app/services/todo_service.rb index 42c5bca90f..4bf4e14472 100644 --- a/app/services/todo_service.rb +++ b/app/services/todo_service.rb @@ -80,6 +80,30 @@ class TodoService mark_pending_todos_as_done(merge_request, current_user) end + # When a build fails on the HEAD of a merge request we should: + # + # * create a todo for that user to fix it + # + def merge_request_build_failed(merge_request) + create_build_failed_todo(merge_request) + end + + # When a new commit is pushed to a merge request we should: + # + # * mark all pending todos related to the merge request for that user as done + # + def merge_request_push(merge_request, current_user) + mark_pending_todos_as_done(merge_request, current_user) + end + + # When a build is retried to a merge request we should: + # + # * mark all pending todos related to the merge request for the author as done + # + def merge_request_build_retried(merge_request) + mark_pending_todos_as_done(merge_request, merge_request.author) + end + # When create a note we should: # # * mark all pending todos related to the noteable for the note author as done @@ -145,6 +169,12 @@ class TodoService create_todos(mentioned_users, attributes) end + def create_build_failed_todo(merge_request) + author = merge_request.author + attributes = attributes_for_todo(merge_request.project, merge_request, author, Todo::BUILD_FAILED) + create_todos(author, attributes) + end + def attributes_for_target(target) attributes = { project_id: target.project.id, diff --git a/app/services/wiki_pages/base_service.rb b/app/services/wiki_pages/base_service.rb index 9162f12860..4c0a2c6b4d 100644 --- a/app/services/wiki_pages/base_service.rb +++ b/app/services/wiki_pages/base_service.rb @@ -6,9 +6,8 @@ module WikiPages object_kind: page.class.name.underscore, user: current_user.hook_attrs, project: @project.hook_attrs, - object_attributes: page.hook_attrs, - # DEPRECATED - repository: @project.hook_attrs.slice(:name, :url, :description, :homepage) + wiki: @project.wiki.hook_attrs, + object_attributes: page.hook_attrs } page_url = Gitlab::UrlBuilder.build(page) diff --git a/app/views/admin/abuse_reports/_abuse_report.html.haml b/app/views/admin/abuse_reports/_abuse_report.html.haml index 2ab01704b7..862b86d9d4 100644 --- a/app/views/admin/abuse_reports/_abuse_report.html.haml +++ b/app/views/admin/abuse_reports/_abuse_report.html.haml @@ -16,7 +16,7 @@ .light.small = time_ago_with_tooltip(abuse_report.created_at) %td - = markdown(abuse_report.message.squish!, pipeline: :single_line) + = markdown(abuse_report.message.squish!, pipeline: :single_line, author: reporter) %td - if user = link_to 'Remove user & report', admin_abuse_report_path(abuse_report, remove_user: true), diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index e0d8d16a95..f149f9eb43 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -103,12 +103,25 @@ = f.label :signup_enabled do = f.check_box :signup_enabled Sign-up enabled + .form-group + .col-sm-offset-2.col-sm-10 + .checkbox + = f.label :send_user_confirmation_email do + = f.check_box :send_user_confirmation_email + Send confirmation email on sign-up .form-group .col-sm-offset-2.col-sm-10 .checkbox = f.label :signin_enabled do = f.check_box :signin_enabled Sign-in enabled + - if omniauth_enabled? && button_based_providers.any? + .form-group + = f.label :enabled_oauth_sign_in_sources, 'Enabled OAuth Sign-In sources', class: 'control-label col-sm-2' + .col-sm-10 + .btn-group{ data: { toggle: 'buttons' } } + - oauth_providers_checkboxes.each do |source| + = source .form-group = f.label :two_factor_authentication, 'Two-factor authentication', class: 'control-label col-sm-2' .col-sm-10 @@ -165,6 +178,14 @@ .col-sm-10 = f.number_field :max_artifacts_size, class: 'form-control' + - if Gitlab.config.registry.enabled + %fieldset + %legend Container Registry + .form-group + = f.label :container_registry_token_expire_delay, 'Authorization token duration (minutes)', class: 'control-label col-sm-2' + .col-sm-10 + = f.number_field :container_registry_token_expire_delay, class: 'form-control' + %fieldset %legend Metrics %p diff --git a/app/views/admin/builds/index.html.haml b/app/views/admin/builds/index.html.haml index 804d7851bd..d74cf8598e 100644 --- a/app/views/admin/builds/index.html.haml +++ b/app/views/admin/builds/index.html.haml @@ -20,7 +20,7 @@ = link_to 'Cancel all', cancel_all_admin_builds_path, data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post .row-content-block.second-block - #{(@scope || 'running').capitalize} builds + #{(@scope || 'all').capitalize} builds %ul.content-list - if @builds.blank? @@ -47,4 +47,3 @@ = render "admin/builds/build", build: build = paginate @builds, theme: 'gitlab' - diff --git a/app/views/admin/health_check/show.html.haml b/app/views/admin/health_check/show.html.haml new file mode 100644 index 0000000000..c2313986a7 --- /dev/null +++ b/app/views/admin/health_check/show.html.haml @@ -0,0 +1,49 @@ +- page_title "Health Check" + +%h3.page-title + Health Check +.bs-callout.clearfix + .pull-left + %p + Access token is + %code#health-check-token= current_application_settings.health_check_access_token + = button_to reset_health_check_token_admin_application_settings_path, + method: :put, class: 'btn btn-default', + data: { confirm: 'Are you sure you want to reset the health check token?' } do + = icon('refresh') + Reset health check access token +%p.light + Health information can be retrieved as plain text, JSON, or XML using: + %ul + %li + %code= health_check_url(token: current_application_settings.health_check_access_token) + %li + %code= health_check_url(token: current_application_settings.health_check_access_token, format: :json) + %li + %code= health_check_url(token: current_application_settings.health_check_access_token, format: :xml) + +%p.light + You can also ask for the status of specific services: + %ul + %li + %code= health_check_url(token: current_application_settings.health_check_access_token, checks: :cache) + %li + %code= health_check_url(token: current_application_settings.health_check_access_token, checks: :database) + %li + %code= health_check_url(token: current_application_settings.health_check_access_token, checks: :migrations) + +%hr +.panel.panel-default + .panel-heading + Current Status: + - if @errors.blank? + = icon('circle', class: 'cgreen') + Healthy + - else + = icon('warning', class: 'cred') + Unhealthy + .panel-body + - if @errors.blank? + No Health Problems Detected + - else + = @errors diff --git a/app/views/admin/runners/_runner.html.haml b/app/views/admin/runners/_runner.html.haml index 6745e58dec..36b21eefde 100644 --- a/app/views/admin/runners/_runner.html.haml +++ b/app/views/admin/runners/_runner.html.haml @@ -11,18 +11,10 @@ = link_to admin_runner_path(runner) do = runner.short_sha %td - .runner-description - = runner.description - %span (#{link_to 'edit', '#', class: 'edit-runner-link'}) - .runner-description-form.hide - = form_for [:admin, runner], remote: true, html: { class: 'form-inline' } do |f| - .form-group - = f.text_field :description, class: 'form-control' - = f.submit 'Save', class: 'btn' - %span (#{link_to 'cancel', '#', class: 'cancel'}) + = runner.description %td - if runner.shared? - \- + n/a - else = runner.projects.count(:all) %td diff --git a/app/views/admin/runners/show.html.haml b/app/views/admin/runners/show.html.haml index 8700b4820c..c3784bf719 100644 --- a/app/views/admin/runners/show.html.haml +++ b/app/views/admin/runners/show.html.haml @@ -9,8 +9,6 @@ %span.runner-state.runner-state-specific Specific - - - if @runner.shared? .bs-callout.bs-callout-success %h4 This runner will process builds from ALL UNASSIGNED projects @@ -22,25 +20,9 @@ %h4 This runner will process builds only from ASSIGNED projects %p You can't make this a shared runner. %hr -= form_for @runner, url: admin_runner_path(@runner), html: { class: 'form-horizontal' } do |f| - .form-group - = label_tag :token, class: 'control-label' do - Token - .col-sm-10 - = f.text_field :token, class: 'form-control', readonly: true - .form-group - = label_tag :description, class: 'control-label' do - Description - .col-sm-10 - = f.text_field :description, class: 'form-control' - .form-group - = label_tag :tag_list, class: 'control-label' do - Tags - .col-sm-10 - = f.text_field :tag_list, value: @runner.tag_list.to_s, class: 'form-control' - .help-block You can setup builds to only use runners with specific tags - .form-actions - = f.submit 'Save', class: 'btn btn-save' + +.append-bottom-20 + = render '/projects/runners/form', runner: @runner, runner_form_url: admin_runner_path(@runner) .row .col-md-6 diff --git a/app/views/dashboard/issues.atom.builder b/app/views/dashboard/issues.atom.builder index 0d7b1b30dc..83c0c6da21 100644 --- a/app/views/dashboard/issues.atom.builder +++ b/app/views/dashboard/issues.atom.builder @@ -6,8 +6,5 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear xml.id issues_dashboard_url xml.updated @issues.first.created_at.xmlschema if @issues.any? - @issues.each do |issue| - issue_to_atom(xml, issue) - end + xml << render(partial: 'issues/issue', collection: @issues) if @issues.any? end - diff --git a/app/views/dashboard/projects/index.atom.builder b/app/views/dashboard/projects/index.atom.builder index d4daf07c6c..fb5be63b47 100644 --- a/app/views/dashboard/projects/index.atom.builder +++ b/app/views/dashboard/projects/index.atom.builder @@ -6,7 +6,5 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear xml.id dashboard_projects_url xml.updated @events[0].updated_at.xmlschema if @events[0] - @events.each do |event| - event_to_atom(xml, event) - end + xml << render(partial: 'events/event', collection: @events) if @events.any? end diff --git a/app/views/dashboard/todos/_todo.html.haml b/app/views/dashboard/todos/_todo.html.haml index aa0aff86d4..98f302d2f9 100644 --- a/app/views/dashboard/todos/_todo.html.haml +++ b/app/views/dashboard/todos/_todo.html.haml @@ -1,13 +1,15 @@ %li{class: "todo todo-#{todo.done? ? 'done' : 'pending'}", id: dom_id(todo), data:{url: todo_target_path(todo)} } .todo-item.todo-block = image_tag avatar_icon(todo.author_email, 40), class: 'avatar s40', alt:'' - .todo-title.title - %span.author-name - - if todo.author - = link_to_author(todo) - - else - (removed) + - unless todo.build_failed? + = todo_target_state_pill(todo) + + %span.author-name + - if todo.author + = link_to_author(todo) + - else + (removed) %span.todo-label = todo_action_name(todo) - if todo.target diff --git a/app/views/devise/mailer/confirmation_instructions.html.erb b/app/views/devise/mailer/confirmation_instructions.html.erb deleted file mode 100644 index c6fa8f0ee3..0000000000 --- a/app/views/devise/mailer/confirmation_instructions.html.erb +++ /dev/null @@ -1,9 +0,0 @@ -

    Welcome <%= @resource.name %>!

    - -<% if @resource.unconfirmed_email.present? %> -

    You can confirm your email (<%= @resource.unconfirmed_email %>) through the link below:

    -<% else %> -

    You can confirm your account through the link below:

    -<% end %> - -

    <%= link_to 'Confirm your account', confirmation_url(@resource, confirmation_token: @token) %>

    diff --git a/app/views/devise/mailer/confirmation_instructions.html.haml b/app/views/devise/mailer/confirmation_instructions.html.haml new file mode 100644 index 0000000000..086bb8e083 --- /dev/null +++ b/app/views/devise/mailer/confirmation_instructions.html.haml @@ -0,0 +1,16 @@ +.center + - if @resource.unconfirmed_email.present? + #content + %h2= @resource.unconfirmed_email + %p Click the link below to confirm your email address. + #cta + = link_to 'Confirm your email address', confirmation_url(@resource, confirmation_token: @token) + - else + #content + - if Gitlab.com? + %h2 Thanks for signing up to GitLab! + - else + %h2 Welcome, #{@resource.name}! + %p To get started, click the link below to confirm your account. + #cta + = link_to 'Confirm your account', confirmation_url(@resource, confirmation_token: @token) diff --git a/app/views/devise/mailer/confirmation_instructions.text.erb b/app/views/devise/mailer/confirmation_instructions.text.erb new file mode 100644 index 0000000000..9f76edb76a --- /dev/null +++ b/app/views/devise/mailer/confirmation_instructions.text.erb @@ -0,0 +1,9 @@ +Welcome, <%= @resource.name %>! + +<% if @resource.unconfirmed_email.present? %> +You can confirm your email (<%= @resource.unconfirmed_email %>) through the link below: +<% else %> +You can confirm your account through the link below: +<% end %> + +<%= confirmation_url(@resource, confirmation_token: @token) %> diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml index d65fa60025..28194506ac 100644 --- a/app/views/devise/sessions/new.html.haml +++ b/app/views/devise/sessions/new.html.haml @@ -4,7 +4,7 @@ = render 'devise/shared/signin_box' -# Omniauth fits between signin/ldap signin and signup and does not have a surrounding box - - if omniauth_enabled? && devise_mapping.omniauthable? + - if omniauth_enabled? && devise_mapping.omniauthable? && button_based_providers_enabled? .clearfix.prepend-top-20 = render 'devise/shared/omniauth_box' diff --git a/app/views/devise/sessions/two_factor.html.haml b/app/views/devise/sessions/two_factor.html.haml index c9d1e454a5..8c6a1552a5 100644 --- a/app/views/devise/sessions/two_factor.html.haml +++ b/app/views/devise/sessions/two_factor.html.haml @@ -4,6 +4,7 @@ %h3 Two-factor Authentication .login-body = form_for(resource, as: resource_name, url: session_path(resource_name), method: :post) do |f| + = f.hidden_field :remember_me, value: params[resource_name][:remember_me] = f.text_field :otp_attempt, class: 'form-control', placeholder: 'Two-factor Authentication code', required: true, autofocus: true %p.help-block.hint Enter the code from the two-factor app on your mobile device. If you've lost your device, you may enter one of your recovery codes. .prepend-top-20 diff --git a/app/views/devise/shared/_omniauth_box.html.haml b/app/views/devise/shared/_omniauth_box.html.haml index ecf680e7b2..de18bc2d84 100644 --- a/app/views/devise/shared/_omniauth_box.html.haml +++ b/app/views/devise/shared/_omniauth_box.html.haml @@ -1,7 +1,7 @@ %p %span.light Sign in with   - - providers = button_based_providers + - providers = enabled_button_based_providers - providers.each do |provider| %span.light - has_icon = provider_has_icon?(provider) diff --git a/app/views/doorkeeper/authorizations/new.html.haml b/app/views/doorkeeper/authorizations/new.html.haml index eae80e5210..ce05000720 100644 --- a/app/views/doorkeeper/authorizations/new.html.haml +++ b/app/views/doorkeeper/authorizations/new.html.haml @@ -1,4 +1,4 @@ -%h3.page-title Authorize required +%h3.page-title Authorization required %main{:role => "main"} %p.h4 Authorize diff --git a/app/views/events/_commit.html.haml b/app/views/events/_commit.html.haml index dce4081288..1bc9f60443 100644 --- a/app/views/events/_commit.html.haml +++ b/app/views/events/_commit.html.haml @@ -2,4 +2,4 @@ .commit-row-title = link_to truncate_sha(commit[:id]), namespace_project_commit_path(project.namespace, project, commit[:id]), class: "commit_short_id", alt: '', title: truncate_sha(commit[:id]) · - = markdown event_commit_title(commit[:message]), project: project, pipeline: :single_line + = markdown event_commit_title(commit[:message]), project: project, pipeline: :single_line, author: event.author diff --git a/app/views/events/_event.atom.builder b/app/views/events/_event.atom.builder new file mode 100644 index 0000000000..7890e717aa --- /dev/null +++ b/app/views/events/_event.atom.builder @@ -0,0 +1,20 @@ +return unless event.visible_to_user?(current_user) + +xml.entry do + xml.id "tag:#{request.host},#{event.created_at.strftime("%Y-%m-%d")}:#{event.id}" + xml.link href: event_feed_url(event) + xml.title truncate(event_feed_title(event), length: 80) + xml.updated event.created_at.xmlschema + xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(event.author_email)) + + xml.author do + xml.name event.author_name + xml.email event.author_email + end + + xml.summary(type: "xhtml") do |summary| + event_summary = event_feed_summary(event) + + summary << event_summary unless event_summary.nil? + end +end diff --git a/app/views/events/_event_issue.atom.haml b/app/views/events/_event_issue.atom.haml index fad6531002..083c393621 100644 --- a/app/views/events/_event_issue.atom.haml +++ b/app/views/events/_event_issue.atom.haml @@ -1,2 +1,2 @@ %div{xmlns: "http://www.w3.org/1999/xhtml"} - = markdown(issue.description, pipeline: :atom, project: issue.project) + = markdown(issue.description, pipeline: :atom, project: issue.project, author: issue.author) diff --git a/app/views/events/_event_merge_request.atom.haml b/app/views/events/_event_merge_request.atom.haml index 19bdc7b9ca..d7e0560062 100644 --- a/app/views/events/_event_merge_request.atom.haml +++ b/app/views/events/_event_merge_request.atom.haml @@ -1,2 +1,2 @@ %div{xmlns: "http://www.w3.org/1999/xhtml"} - = markdown(merge_request.description, pipeline: :atom, project: merge_request.project) + = markdown(merge_request.description, pipeline: :atom, project: merge_request.project, author: merge_request.author) diff --git a/app/views/events/_event_note.atom.haml b/app/views/events/_event_note.atom.haml index b730ebbd5f..1154f98282 100644 --- a/app/views/events/_event_note.atom.haml +++ b/app/views/events/_event_note.atom.haml @@ -1,2 +1,2 @@ %div{xmlns: "http://www.w3.org/1999/xhtml"} - = markdown(note.note, pipeline: :atom, project: note.project) + = markdown(note.note, pipeline: :atom, project: note.project, author: note.author) diff --git a/app/views/events/_event_push.atom.haml b/app/views/events/_event_push.atom.haml index b271b9daff..28bee1d0a3 100644 --- a/app/views/events/_event_push.atom.haml +++ b/app/views/events/_event_push.atom.haml @@ -6,7 +6,7 @@ %i at = commit[:timestamp].to_time.to_s(:short) - %blockquote= markdown(escape_once(commit[:message]), pipeline: :atom, project: event.project) + %blockquote= markdown(escape_once(commit[:message]), pipeline: :atom, project: event.project, author: event.author) - if event.commits_count > 15 %p %i diff --git a/app/views/events/event/_common.html.haml b/app/views/events/event/_common.html.haml index c994e3b997..c7f29f2fc0 100644 --- a/app/views/events/event/_common.html.haml +++ b/app/views/events/event/_common.html.haml @@ -4,7 +4,7 @@ = event_action_name(event) - if event.target - %strong= link_to event.target.reference_link_text, [event.project.namespace.becomes(Namespace), event.project, event.target] + %strong= link_to event.target.reference_link_text, [event.project.namespace.becomes(Namespace), event.project, event.target], class: 'has-tooltip', title: event.target_title = event_preposition(event) diff --git a/app/views/events/event/_push.html.haml b/app/views/events/event/_push.html.haml index 235bd46107..dc4ff17e31 100644 --- a/app/views/events/event/_push.html.haml +++ b/app/views/events/event/_push.html.haml @@ -15,7 +15,7 @@ %ul.well-list.event_commits - few_commits = event.commits[0...2] - few_commits.each do |commit| - = render "events/commit", commit: commit, project: project + = render "events/commit", commit: commit, project: project, event: event - create_mr = event.new_ref? && create_mr_button?(event.project.default_branch, event.ref_name, event.project) - if event.commits_count > 1 diff --git a/app/views/groups/_activities.html.haml b/app/views/groups/_activities.html.haml index dc76599b77..71cc4d87b1 100644 --- a/app/views/groups/_activities.html.haml +++ b/app/views/groups/_activities.html.haml @@ -4,7 +4,7 @@ .nav-block - if current_user .controls - = link_to dashboard_projects_path(:atom, { private_token: current_user.private_token }), class: 'btn rss-btn' do + = link_to group_path(@group, format: :atom, private_token: current_user.private_token), class: 'btn rss-btn' do %i.fa.fa-rss = render 'shared/event_filter' diff --git a/app/views/groups/issues.atom.builder b/app/views/groups/issues.atom.builder index 486d1d8587..c19671295a 100644 --- a/app/views/groups/issues.atom.builder +++ b/app/views/groups/issues.atom.builder @@ -1,13 +1,10 @@ xml.instruct! xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do - xml.title "#{@user.name} issues" - xml.link href: issues_dashboard_url(format: :atom, private_token: @user.private_token), rel: "self", type: "application/atom+xml" - xml.link href: issues_dashboard_url, rel: "alternate", type: "text/html" - xml.id issues_dashboard_url + xml.title "#{@group.name} issues" + xml.link href: issues_group_url(format: :atom, private_token: current_user.try(:private_token)), rel: "self", type: "application/atom+xml" + xml.link href: issues_group_url, rel: "alternate", type: "text/html" + xml.id issues_group_url xml.updated @issues.first.created_at.xmlschema if @issues.any? - @issues.each do |issue| - issue_to_atom(xml, issue) - end + xml << render(partial: 'issues/issue', collection: @issues) if @issues.any? end - diff --git a/app/views/groups/show.atom.builder b/app/views/groups/show.atom.builder index c66b82bb48..b68bf444d2 100644 --- a/app/views/groups/show.atom.builder +++ b/app/views/groups/show.atom.builder @@ -6,7 +6,5 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear xml.id group_url(@group) xml.updated @events[0].updated_at.xmlschema if @events[0] - @events.each do |event| - event_to_atom(xml, event) - end + xml << render(@events) if @events.any? end diff --git a/app/views/import/gitlab/status.html.haml b/app/views/import/gitlab/status.html.haml index e3a356b537..aedb8468ec 100644 --- a/app/views/import/gitlab/status.html.haml +++ b/app/views/import/gitlab/status.html.haml @@ -47,7 +47,7 @@ %td.import-target = repo["path_with_namespace"] %td.import-actions.job-status - = button_tag class: "btn js-add-to-import" do + = button_tag class: "btn btn-import js-add-to-import" do Import = icon("spinner spin", class: "loading-icon") diff --git a/app/views/issues/_issue.atom.builder b/app/views/issues/_issue.atom.builder new file mode 100644 index 0000000000..68a2d19e58 --- /dev/null +++ b/app/views/issues/_issue.atom.builder @@ -0,0 +1,14 @@ +xml.entry do + xml.id namespace_project_issue_url(issue.project.namespace, issue.project, issue) + xml.link href: namespace_project_issue_url(issue.project.namespace, issue.project, issue) + xml.title truncate(issue.title, length: 80) + xml.updated issue.created_at.xmlschema + xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(issue.author_email)) + + xml.author do |author| + xml.name issue.author_name + xml.email issue.author_email + end + + xml.summary issue.title +end diff --git a/app/views/kaminari/gitlab/_first_page.html.haml b/app/views/kaminari/gitlab/_first_page.html.haml index ada7306d98..e7a70e3bb2 100644 --- a/app/views/kaminari/gitlab/_first_page.html.haml +++ b/app/views/kaminari/gitlab/_first_page.html.haml @@ -2,7 +2,7 @@ -# available local variables -# url: url to the first page -# current_page: a page object for the currently displayed page --# num_pages: total number of pages +-# total_pages: total number of pages -# per_page: number of items to fetch per page -# remote: data-remote %li.first diff --git a/app/views/kaminari/gitlab/_gap.html.haml b/app/views/kaminari/gitlab/_gap.html.haml index 3ffd12f858..80ca30f36e 100644 --- a/app/views/kaminari/gitlab/_gap.html.haml +++ b/app/views/kaminari/gitlab/_gap.html.haml @@ -1,7 +1,7 @@ -# Non-link tag that stands for skipped pages... -# available local variables -# current_page: a page object for the currently displayed page --# num_pages: total number of pages +-# total_pages: total number of pages -# per_page: number of items to fetch per page -# remote: data-remote %li{class: "page"} diff --git a/app/views/kaminari/gitlab/_last_page.html.haml b/app/views/kaminari/gitlab/_last_page.html.haml index 3431d029bc..53f780d1d1 100644 --- a/app/views/kaminari/gitlab/_last_page.html.haml +++ b/app/views/kaminari/gitlab/_last_page.html.haml @@ -2,7 +2,7 @@ -# available local variables -# url: url to the last page -# current_page: a page object for the currently displayed page --# num_pages: total number of pages +-# total_pages: total number of pages -# per_page: number of items to fetch per page -# remote: data-remote %li.last diff --git a/app/views/kaminari/gitlab/_next_page.html.haml b/app/views/kaminari/gitlab/_next_page.html.haml index c805914fc3..125f09777b 100644 --- a/app/views/kaminari/gitlab/_next_page.html.haml +++ b/app/views/kaminari/gitlab/_next_page.html.haml @@ -2,7 +2,7 @@ -# available local variables -# url: url to the next page -# current_page: a page object for the currently displayed page --# num_pages: total number of pages +-# total_pages: total number of pages -# per_page: number of items to fetch per page -# remote: data-remote - if current_page.last? diff --git a/app/views/kaminari/gitlab/_page.html.haml b/app/views/kaminari/gitlab/_page.html.haml index a52d883b9a..522e4d1d05 100644 --- a/app/views/kaminari/gitlab/_page.html.haml +++ b/app/views/kaminari/gitlab/_page.html.haml @@ -3,7 +3,7 @@ -# page: a page object for "this" page -# url: url to this page -# current_page: a page object for the currently displayed page --# num_pages: total number of pages +-# total_pages: total number of pages -# per_page: number of items to fetch per page -# remote: data-remote %li{class: "page#{' active' if page.current?}"} diff --git a/app/views/kaminari/gitlab/_paginator.html.haml b/app/views/kaminari/gitlab/_paginator.html.haml index a12c53bcfe..f5e0d2ed3f 100644 --- a/app/views/kaminari/gitlab/_paginator.html.haml +++ b/app/views/kaminari/gitlab/_paginator.html.haml @@ -1,7 +1,7 @@ -# The container tag -# available local variables -# current_page: a page object for the currently displayed page --# num_pages: total number of pages +-# total_pages: total number of pages -# per_page: number of items to fetch per page -# remote: data-remote -# paginator: the paginator that renders the pagination tags inside @@ -9,7 +9,7 @@ %div.gl-pagination %ul.pagination.clearfix - unless current_page.first? - = first_page_tag unless num_pages < 5 # As kaminari will always show the first 5 pages + = first_page_tag unless total_pages < 5 # As kaminari will always show the first 5 pages = prev_page_tag - each_page do |page| - if page.left_outer? || page.right_outer? || page.inside_window? @@ -18,5 +18,5 @@ = gap_tag = next_page_tag - unless current_page.last? - = last_page_tag unless num_pages < 5 + = last_page_tag unless total_pages < 5 diff --git a/app/views/kaminari/gitlab/_prev_page.html.haml b/app/views/kaminari/gitlab/_prev_page.html.haml index afb20455e0..7edf10498a 100644 --- a/app/views/kaminari/gitlab/_prev_page.html.haml +++ b/app/views/kaminari/gitlab/_prev_page.html.haml @@ -2,7 +2,7 @@ -# available local variables -# url: url to the previous page -# current_page: a page object for the currently displayed page --# num_pages: total number of pages +-# total_pages: total number of pages -# per_page: number of items to fetch per page -# remote: data-remote - if current_page.first? diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml index 79cdbac1f3..b30fb0a5da 100644 --- a/app/views/layouts/_head.html.haml +++ b/app/views/layouts/_head.html.haml @@ -30,6 +30,9 @@ = javascript_include_tag "application" + - if page_specific_javascripts + = javascript_include_tag page_specific_javascripts, {"data-turbolinks-track" => true} + = csrf_meta_tags = include_gon diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml index 3c3bc41bf0..1e961853c7 100644 --- a/app/views/layouts/_page.html.haml +++ b/app/views/layouts/_page.html.haml @@ -1,5 +1,4 @@ .page-with-sidebar{ class: "#{page_sidebar_class} #{page_gutter_class}" } - = render "layouts/broadcast" .sidebar-wrapper.nicescroll{ class: nav_sidebar_class } .header-logo %a#logo @@ -26,7 +25,8 @@ .layout-nav .container-fluid = render "layouts/nav/#{nav}" - .content-wrapper{ class: ('page-with-layout-nav' if defined?(nav) && nav) } + .content-wrapper{ class: "#{layout_nav_class}" } + = render "layouts/broadcast" = render "layouts/flash" = yield :flash_message %div{ class: (container_class unless @no_container) } diff --git a/app/views/layouts/_search.html.haml b/app/views/layouts/_search.html.haml index 6b208c3d0b..b49207fc31 100644 --- a/app/views/layouts/_search.html.haml +++ b/app/views/layouts/_search.html.haml @@ -6,11 +6,8 @@ .search.search-form{class: "#{'has-location-badge' if label.present?}"} = form_tag search_path, method: :get, class: 'navbar-form' do |f| .search-input-container - .search-location-badge - - if label.present? - %span.location-badge - %i.location-text - = label + - if label.present? + .location-badge= label .search-input-wrap .dropdown{ data: {url: search_autocomplete_path } } = search_field_tag "search", nil, placeholder: 'Search', class: "search-input dropdown-menu-toggle", spellcheck: false, tabindex: "1", autocomplete: 'off', data: { toggle: 'dropdown' } diff --git a/app/views/layouts/devise_mailer.html.haml b/app/views/layouts/devise_mailer.html.haml new file mode 100644 index 0000000000..c258eafdd5 --- /dev/null +++ b/app/views/layouts/devise_mailer.html.haml @@ -0,0 +1,34 @@ +!!! 5 +%html + %head + %meta(content='text/html; charset=UTF-8' http-equiv='Content-Type') + = stylesheet_link_tag 'mailers/devise' + + %body + %table#wrapper + %tr + %td + %table#header + %td{valign: "top"} + = image_tag('mailers/gitlab_header_logo.png', id: 'logo', alt: 'GitLab Wordmark') + + %table#body + %tr + %td#body-container + = yield + + - if Gitlab.com? + %table#footer + %tr + %td#tanuki + = image_tag('mailers/gitlab_tanuki_2x.png', alt: 'GitLab Logo') + %tr + %td#tagline + Everyone can contribute + %tr + %td#social + = link_to 'Blog', 'https://about.gitlab.com/blog/' + = link_to 'Twitter', 'https://twitter.com/gitlab' + = link_to 'Facebook', 'https://www.facebook.com/gitlab/' + = link_to 'YouTube', 'https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg' + = link_to 'LinkedIn', 'https://www.linkedin.com/company/gitlab-com' diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml index 86930d4eaa..c33740e23f 100644 --- a/app/views/layouts/header/_default.html.haml +++ b/app/views/layouts/header/_default.html.haml @@ -1,9 +1,12 @@ %header.navbar.navbar-fixed-top.navbar-gitlab{ class: nav_header_class } %div{ class: fluid_layout ? "container-fluid" : "container-fluid" } .header-content - %button.navbar-toggle{type: 'button'} + %button.side-nav-toggle{type: 'button'} %span.sr-only Toggle navigation = icon('bars') + %button.navbar-toggle{type: 'button'} + %span.sr-only Toggle navigation + = icon('angle-left') .navbar-collapse.collapse %ul.nav.navbar-nav @@ -24,8 +27,9 @@ %li = link_to dashboard_todos_path, title: 'Todos', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do = icon('bell fw') - %span.badge.todos-pending-count - = todos_pending_count + - unless todos_pending_count == 0 + %span.badge.todos-pending-count + = todos_pending_count - if current_user.can_create_project? %li = link_to new_project_path, title: 'New project', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do diff --git a/app/views/layouts/nav/_admin.html.haml b/app/views/layouts/nav/_admin.html.haml index 280a1b9372..f292730fe4 100644 --- a/app/views/layouts/nav/_admin.html.haml +++ b/app/views/layouts/nav/_admin.html.haml @@ -41,6 +41,11 @@ = icon('file-text fw') %span Logs + = nav_link(controller: :health_check) do + = link_to admin_health_check_path, title: 'Health Check' do + = icon('medkit fw') + %span + Health Check = nav_link(controller: :broadcast_messages) do = link_to admin_broadcast_messages_path, title: 'Messages' do = icon('bullhorn fw') diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml index fad4224e94..306ebd5fcf 100644 --- a/app/views/layouts/nav/_dashboard.html.haml +++ b/app/views/layouts/nav/_dashboard.html.haml @@ -1,6 +1,6 @@ %ul.nav.nav-sidebar - = nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: {class: 'home'}) do - = link_to dashboard_projects_path, title: 'Projects' do + = nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: {class: "#{project_tab_class} home"}) do + = link_to dashboard_projects_path, title: 'Projects', class: 'dashboard-shortcuts-projects' do = icon('bookmark fw') %span Projects @@ -11,7 +11,7 @@ Todos %span.count.todos-pending-count= number_with_delimiter(todos_pending_count) = nav_link(path: 'dashboard#activity') do - = link_to activity_dashboard_path, class: 'shortcuts-activity', title: 'Activity' do + = link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity', title: 'Activity' do = icon('dashboard fw') %span Activity @@ -26,17 +26,17 @@ %span Milestones = nav_link(path: 'dashboard#issues') do - = link_to assigned_issues_dashboard_path, title: 'Issues', class: 'shortcuts-issues' do + = link_to assigned_issues_dashboard_path, title: 'Issues', class: 'dashboard-shortcuts-issues' do = icon('exclamation-circle fw') %span Issues - %span.count= number_with_delimiter(current_user.assigned_issues.opened.count) + %span.count= number_with_delimiter(current_user.assigned_open_issues_count) = nav_link(path: 'dashboard#merge_requests') do - = link_to assigned_mrs_dashboard_path, title: 'Merge Requests', class: 'shortcuts-merge_requests' do + = link_to assigned_mrs_dashboard_path, title: 'Merge Requests', class: 'dashboard-shortcuts-merge_requests' do = icon('tasks fw') %span Merge Requests - %span.count= number_with_delimiter(current_user.assigned_merge_requests.opened.count) + %span.count= number_with_delimiter(current_user.assigned_open_merge_request_count) = nav_link(controller: :snippets) do = link_to dashboard_snippets_path, title: 'Snippets' do = icon('clipboard fw') diff --git a/app/views/layouts/nav/_group.html.haml b/app/views/layouts/nav/_group.html.haml index 3438005863..de15add361 100644 --- a/app/views/layouts/nav/_group.html.haml +++ b/app/views/layouts/nav/_group.html.haml @@ -1,37 +1,40 @@ -= render 'layouts/nav/group_settings' +%div{ class: nav_control_class } + = render 'layouts/nav/group_settings' -%ul.nav-links - = nav_link(path: 'groups#show', html_options: {class: 'home'}) do - = link_to group_path(@group), title: 'Home' do - = icon('group fw') - %span - Group - = nav_link(path: 'groups#activity') do - = link_to activity_group_path(@group), title: 'Activity' do - = icon('dashboard fw') - %span - Activity - = nav_link(controller: [:group, :milestones]) do - = link_to group_milestones_path(@group), title: 'Milestones' do - = icon('clock-o fw') - %span - Milestones - = nav_link(path: 'groups#issues') do - = link_to issues_group_path(@group), title: 'Issues' do - = icon('exclamation-circle fw') - %span - Issues - - issues = IssuesFinder.new(current_user, group_id: @group.id, state: 'opened').execute - %span.badge.count= number_with_delimiter(issues.count) - = nav_link(path: 'groups#merge_requests') do - = link_to merge_requests_group_path(@group), title: 'Merge Requests' do - = icon('tasks fw') - %span - Merge Requests - - merge_requests = MergeRequestsFinder.new(current_user, group_id: @group.id, state: 'opened').execute - %span.badge.count= number_with_delimiter(merge_requests.count) - = nav_link(controller: [:group_members]) do - = link_to group_group_members_path(@group), title: 'Members' do - = icon('users fw') - %span - Members + %ul.nav-links.scrolling-tabs + .fade-left + = nav_link(path: 'groups#show', html_options: {class: 'home'}) do + = link_to group_path(@group), title: 'Home' do + = icon('group fw') + %span + Group + = nav_link(path: 'groups#activity') do + = link_to activity_group_path(@group), title: 'Activity' do + = icon('dashboard fw') + %span + Activity + = nav_link(controller: [:group, :milestones]) do + = link_to group_milestones_path(@group), title: 'Milestones' do + = icon('clock-o fw') + %span + Milestones + = nav_link(path: 'groups#issues') do + = link_to issues_group_path(@group), title: 'Issues' do + = icon('exclamation-circle fw') + %span + Issues + - issues = IssuesFinder.new(current_user, group_id: @group.id, state: 'opened').execute + %span.badge.count= number_with_delimiter(issues.count) + = nav_link(path: 'groups#merge_requests') do + = link_to merge_requests_group_path(@group), title: 'Merge Requests' do + = icon('tasks fw') + %span + Merge Requests + - merge_requests = MergeRequestsFinder.new(current_user, group_id: @group.id, state: 'opened').execute + %span.badge.count= number_with_delimiter(merge_requests.count) + = nav_link(controller: [:group_members]) do + = link_to group_group_members_path(@group), title: 'Members' do + = icon('users fw') + %span + Members + .fade-right diff --git a/app/views/layouts/nav/_group_settings.html.haml b/app/views/layouts/nav/_group_settings.html.haml index e391ec7f2b..0b2673f1a8 100644 --- a/app/views/layouts/nav/_group_settings.html.haml +++ b/app/views/layouts/nav/_group_settings.html.haml @@ -1,7 +1,7 @@ - if current_user - if access = @group.users.find_by(id: current_user.id) .controls - %span.dropdown.group-settings-dropdown + .dropdown.group-settings-dropdown %a.dropdown-new.btn.btn-default#group-settings-button{href: '#', 'data-toggle' => 'dropdown'} = icon('cog') = icon('caret-down') diff --git a/app/views/layouts/nav/_profile.html.haml b/app/views/layouts/nav/_profile.html.haml index d730840d63..2efc6c48a4 100644 --- a/app/views/layouts/nav/_profile.html.haml +++ b/app/views/layouts/nav/_profile.html.haml @@ -1,4 +1,5 @@ -%ul.nav-links +%ul.nav-links.scrolling-tabs + .fade-left = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do = link_to profile_path, title: 'Profile Settings' do = icon('user fw') @@ -47,3 +48,4 @@ = icon('history fw') %span Audit Log + .fade-right diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml index 479bde3371..9792c1c93b 100644 --- a/app/views/layouts/nav/_project.html.haml +++ b/app/views/layouts/nav/_project.html.haml @@ -1,131 +1,131 @@ -%ul.nav.nav-sidebar - - if @project.group - = nav_link do - = link_to group_path(@project.group), title: 'Go to group', class: 'back-link' do - = icon('caret-square-o-left fw') - %span - Go to group - - else - = nav_link do - = link_to root_path, title: 'Go to dashboard', class: 'back-link' do - = icon('caret-square-o-left fw') - %span - Go to dashboard +- if current_user + .controls + - access = user_max_access_in_project(current_user.id, @project) + - can_edit = can?(current_user, :admin_project, @project) + .dropdown.project-settings-dropdown + %a.dropdown-new.btn.btn-default#project-settings-button{href: '#', 'data-toggle' => 'dropdown'} + = icon('cog') + = icon('caret-down') + %ul.dropdown-menu.dropdown-menu-align-right + = render 'layouts/nav/project_settings' + %li.divider + - if can_edit + %li + = link_to edit_project_path(@project) do + Edit Project + - if access + %li + = link_to leave_namespace_project_project_members_path(@project.namespace, @project), + data: { confirm: leave_project_message(@project) }, method: :delete, title: 'Leave project' do + Leave Project - %li.separate-item - - = nav_link(path: 'projects#show', html_options: {class: 'home'}) do - = link_to project_path(@project), title: 'Project', class: 'shortcuts-project' do - = icon('bookmark fw') - %span - Project - = nav_link(path: 'projects#activity') do - = link_to activity_project_path(@project), title: 'Activity', class: 'shortcuts-project-activity' do - = icon('dashboard fw') - %span - Activity - - if project_nav_tab? :files - = nav_link(controller: %w(tree blob blame edit_tree new_tree find_file)) do - = link_to project_files_path(@project), title: 'Files', class: 'shortcuts-tree' do - = icon('files-o fw') +%div{ class: nav_control_class } + %ul.nav-links.scrolling-tabs + .fade-left + = nav_link(path: 'projects#show', html_options: {class: 'home'}) do + = link_to project_path(@project), title: 'Project', class: 'shortcuts-project' do + = icon('bookmark fw') %span - Files - - - if project_nav_tab? :commits - = nav_link(controller: %w(commit commits compare repositories tags branches releases network)) do - = link_to project_commits_path(@project), title: 'Commits', class: 'shortcuts-commits' do - = icon('history fw') + Project + = nav_link(path: 'projects#activity') do + = link_to activity_project_path(@project), title: 'Activity', class: 'shortcuts-project-activity' do + = icon('dashboard fw') %span + Activity + - if project_nav_tab? :files + = nav_link(controller: %w(tree blob blame edit_tree new_tree find_file commit commits compare repositories tags branches releases network)) do + = link_to project_files_path(@project), title: 'Files', class: 'shortcuts-tree' do + = icon('code fw') + %span + Code + + - if project_nav_tab? :pipelines + = nav_link(controller: :pipelines) do + = link_to project_pipelines_path(@project), title: 'Pipelines', class: 'shortcuts-pipelines' do + = icon('ship fw') + %span + Pipelines + + - if project_nav_tab? :container_registry + = nav_link(controller: %w(container_registry)) do + = link_to project_container_registry_path(@project), title: 'Container Registry', class: 'shortcuts-container-registry' do + = icon('hdd-o fw') + %span + Container Registry + + - if project_nav_tab? :graphs + = nav_link(controller: %w(graphs)) do + = link_to namespace_project_graph_path(@project.namespace, @project, current_ref), title: 'Graphs', class: 'shortcuts-graphs' do + = icon('area-chart fw') + %span + Graphs + + - if project_nav_tab? :milestones + = nav_link(controller: :milestones) do + = link_to namespace_project_milestones_path(@project.namespace, @project), title: 'Milestones' do + = icon('clock-o fw') + %span + Milestones + + - if project_nav_tab? :issues + = nav_link(controller: :issues) do + = link_to url_for_project_issues(@project, only_path: true), title: 'Issues', class: 'shortcuts-issues' do + = icon('exclamation-circle fw') + %span + Issues + - if @project.default_issues_tracker? + %span.badge.count.issue_counter= number_with_delimiter(@project.issues.visible_to_user(current_user).opened.count) + + - if project_nav_tab? :merge_requests + = nav_link(controller: :merge_requests) do + = link_to namespace_project_merge_requests_path(@project.namespace, @project), title: 'Merge Requests', class: 'shortcuts-merge_requests' do + = icon('tasks fw') + %span + Merge Requests + %span.badge.count.merge_counter= number_with_delimiter(@project.merge_requests.opened.count) + + - if project_nav_tab? :labels + = nav_link(controller: :labels) do + = link_to namespace_project_labels_path(@project.namespace, @project), title: 'Labels' do + = icon('tags fw') + %span + Labels + + - if project_nav_tab? :wiki + = nav_link(controller: :wikis) do + = link_to get_project_wiki_path(@project), title: 'Wiki', class: 'shortcuts-wiki' do + = icon('book fw') + %span + Wiki + + - if project_nav_tab? :snippets + = nav_link(controller: :snippets) do + = link_to namespace_project_snippets_path(@project.namespace, @project), title: 'Snippets', class: 'shortcuts-snippets' do + = icon('clipboard fw') + %span + Snippets + + -# Global shortcut to network page for compatibility + - if project_nav_tab? :network + %li.hidden + = link_to namespace_project_network_path(@project.namespace, @project, current_ref), title: 'Network', class: 'shortcuts-network' do + Network + + -# Shortcut to create a new issue + %li.hidden + = link_to new_namespace_project_issue_path(@project.namespace, @project), class: 'shortcuts-new-issue' do + Create a new issue + + -# Shortcut to builds page + - if project_nav_tab? :builds + %li.hidden + = link_to project_builds_path(@project), title: 'Builds', class: 'shortcuts-builds' do + Builds + + -# Shortcut to commits page + - if project_nav_tab? :commits + %li.hidden + = link_to project_commits_path(@project), title: 'Commits', class: 'shortcuts-commits' do Commits - - if project_nav_tab? :builds - = nav_link(controller: %w(builds)) do - = link_to project_builds_path(@project), title: 'Builds', class: 'shortcuts-builds' do - = icon('cubes fw') - %span - Builds - %span.count.builds_counter= number_with_delimiter(@project.builds.running_or_pending.count(:all)) - - - if project_nav_tab? :graphs - = nav_link(controller: %w(graphs)) do - = link_to namespace_project_graph_path(@project.namespace, @project, current_ref), title: 'Graphs', class: 'shortcuts-graphs' do - = icon('area-chart fw') - %span - Graphs - - - if project_nav_tab? :milestones - = nav_link(controller: :milestones) do - = link_to namespace_project_milestones_path(@project.namespace, @project), title: 'Milestones' do - = icon('clock-o fw') - %span - Milestones - - - if project_nav_tab? :issues - = nav_link(controller: :issues) do - = link_to url_for_project_issues(@project, only_path: true), title: 'Issues', class: 'shortcuts-issues' do - = icon('exclamation-circle fw') - %span - Issues - - if @project.default_issues_tracker? - %span.count.issue_counter= number_with_delimiter(@project.issues.visible_to_user(current_user).opened.count) - - - if project_nav_tab? :merge_requests - = nav_link(controller: :merge_requests) do - = link_to namespace_project_merge_requests_path(@project.namespace, @project), title: 'Merge Requests', class: 'shortcuts-merge_requests' do - = icon('tasks fw') - %span - Merge Requests - %span.count.merge_counter= number_with_delimiter(@project.merge_requests.opened.count) - - - if project_nav_tab? :team - = nav_link(controller: [:project_members, :teams]) do - = link_to namespace_project_project_members_path(@project.namespace, @project), title: 'Members', class: 'team-tab tab' do - = icon('users fw') - %span - Members - - - if project_nav_tab? :labels - = nav_link(controller: :labels) do - = link_to namespace_project_labels_path(@project.namespace, @project), title: 'Labels' do - = icon('tags fw') - %span - Labels - - - if project_nav_tab? :wiki - = nav_link(controller: :wikis) do - = link_to get_project_wiki_path(@project), title: 'Wiki', class: 'shortcuts-wiki' do - = icon('book fw') - %span - Wiki - - - if project_nav_tab? :forks - = nav_link(controller: :forks, action: :index) do - = link_to namespace_project_forks_path(@project.namespace, @project), title: 'Forks' do - = icon('code-fork fw') - %span - Forks - - - if project_nav_tab? :snippets - = nav_link(controller: :snippets) do - = link_to namespace_project_snippets_path(@project.namespace, @project), title: 'Snippets', class: 'shortcuts-snippets' do - = icon('clipboard fw') - %span - Snippets - - - if project_nav_tab? :settings - = nav_link(html_options: {class: "#{project_tab_class} separate-item"}) do - = link_to edit_project_path(@project), title: 'Settings' do - = icon('cogs fw') - %span - Settings - - -# Global shortcut to network page for compatibility - - if project_nav_tab? :network - %li.hidden - = link_to namespace_project_network_path(@project.namespace, @project, current_ref), title: 'Network', class: 'shortcuts-network' do - Network - - -# Shortcut to create a new issue - %li.hidden - = link_to new_namespace_project_issue_path(@project.namespace, @project), class: 'shortcuts-new-issue' do - Create a new issue + .fade-right diff --git a/app/views/layouts/nav/_project_settings.html.haml b/app/views/layouts/nav/_project_settings.html.haml index d429a92846..885e78d38c 100644 --- a/app/views/layouts/nav/_project_settings.html.haml +++ b/app/views/layouts/nav/_project_settings.html.haml @@ -1,63 +1,45 @@ -%ul.nav.nav-sidebar - = nav_link do - = link_to project_path(@project), title: 'Go to project', class: 'back-link' do - = icon('caret-square-o-left fw') +- if project_nav_tab? :team + = nav_link(controller: [:project_members, :teams]) do + = link_to namespace_project_project_members_path(@project.namespace, @project), title: 'Members', class: 'team-tab tab' do %span - Go to project + Members - %li.separate-item +- if @project.allowed_to_share_with_group? + = nav_link(controller: :group_links) do + = link_to namespace_project_group_links_path(@project.namespace, @project), title: "Groups" do + %span + Groups += nav_link(controller: :deploy_keys) do + = link_to namespace_project_deploy_keys_path(@project.namespace, @project), title: 'Deploy Keys' do + %span + Deploy Keys += nav_link(controller: :hooks) do + = link_to namespace_project_hooks_path(@project.namespace, @project), title: 'Webhooks' do + %span + Webhooks += nav_link(controller: :services) do + = link_to namespace_project_services_path(@project.namespace, @project), title: 'Services' do + %span + Services += nav_link(controller: :protected_branches) do + = link_to namespace_project_protected_branches_path(@project.namespace, @project), title: 'Protected Branches' do + %span + Protected Branches - %ul.sidebar-subnav - = nav_link(path: 'projects#edit') do - = link_to edit_project_path(@project), title: 'Project Settings' do - = icon('pencil-square-o fw') - %span - Project Settings - - if @project.allowed_to_share_with_group? - = nav_link(controller: :group_links) do - = link_to namespace_project_group_links_path(@project.namespace, @project), title: "Groups" do - = icon('share-square-o fw') - %span - Groups - = nav_link(controller: :deploy_keys) do - = link_to namespace_project_deploy_keys_path(@project.namespace, @project), title: 'Deploy Keys' do - = icon('key fw') - %span - Deploy Keys - = nav_link(controller: :hooks) do - = link_to namespace_project_hooks_path(@project.namespace, @project), title: 'Webhooks' do - = icon('link fw') - %span - Webhooks - = nav_link(controller: :services) do - = link_to namespace_project_services_path(@project.namespace, @project), title: 'Services' do - = icon('cogs fw') - %span - Services - = nav_link(controller: :protected_branches) do - = link_to namespace_project_protected_branches_path(@project.namespace, @project), title: 'Protected Branches' do - = icon('lock fw') - %span - Protected Branches - - - if @project.builds_enabled? - = nav_link(controller: :runners) do - = link_to namespace_project_runners_path(@project.namespace, @project), title: 'Runners' do - = icon('cog fw') - %span - Runners - = nav_link(controller: :variables) do - = link_to namespace_project_variables_path(@project.namespace, @project), title: 'Variables' do - = icon('code fw') - %span - Variables - = nav_link(controller: :triggers) do - = link_to namespace_project_triggers_path(@project.namespace, @project), title: 'Triggers' do - = icon('retweet fw') - %span - Triggers - = nav_link(controller: :badges) do - = link_to namespace_project_badges_path(@project.namespace, @project), title: 'Badges' do - = icon('star-half-empty fw') - %span - Badges +- if @project.builds_enabled? + = nav_link(controller: :runners) do + = link_to namespace_project_runners_path(@project.namespace, @project), title: 'Runners' do + %span + Runners + = nav_link(controller: :variables) do + = link_to namespace_project_variables_path(@project.namespace, @project), title: 'Variables' do + %span + Variables + = nav_link(controller: :triggers) do + = link_to namespace_project_triggers_path(@project.namespace, @project), title: 'Triggers' do + %span + Triggers + = nav_link(controller: :badges) do + = link_to namespace_project_badges_path(@project.namespace, @project), title: 'Badges' do + %span + Badges diff --git a/app/views/layouts/notify.html.haml b/app/views/layouts/notify.html.haml index 2997f59d94..dde2e2889d 100644 --- a/app/views/layouts/notify.html.haml +++ b/app/views/layouts/notify.html.haml @@ -4,6 +4,7 @@ %title GitLab = stylesheet_link_tag 'notify' + = yield :head %body %div.content = yield diff --git a/app/views/layouts/project.html.haml b/app/views/layouts/project.html.haml index 6dfe7fbdae..20d6cdf724 100644 --- a/app/views/layouts/project.html.haml +++ b/app/views/layouts/project.html.haml @@ -1,7 +1,7 @@ - page_title @project.name_with_namespace - page_description @project.description unless page_description - header_title project_title(@project) unless header_title -- sidebar "project" unless sidebar +- nav "project" - content_for :scripts_body_top do - project = @target_project || @project diff --git a/app/views/layouts/project_settings.html.haml b/app/views/layouts/project_settings.html.haml index 59ce38f67b..4bc94bd132 100644 --- a/app/views/layouts/project_settings.html.haml +++ b/app/views/layouts/project_settings.html.haml @@ -1,5 +1,4 @@ - page_title "Settings" -- header_title project_title(@project, "Settings", edit_project_path(@project)) -- sidebar "project_settings" +- nav "project" = render template: "layouts/project" diff --git a/app/views/notify/_note_message.html.haml b/app/views/notify/_note_message.html.haml index 12ded41fbf..e9c6617087 100644 --- a/app/views/notify/_note_message.html.haml +++ b/app/views/notify/_note_message.html.haml @@ -2,4 +2,4 @@ %div #{link_to @note.author_name, user_url(@note.author)} wrote: %div - = markdown(@note.note, pipeline: :email) + = markdown(@note.note, pipeline: :email, author: @note.author) diff --git a/app/views/notify/new_issue_email.html.haml b/app/views/notify/new_issue_email.html.haml index ad3ab2525b..f42b150c0d 100644 --- a/app/views/notify/new_issue_email.html.haml +++ b/app/views/notify/new_issue_email.html.haml @@ -2,7 +2,7 @@ %div #{link_to @issue.author_name, user_url(@issue.author)} wrote: -if @issue.description - = markdown(@issue.description, pipeline: :email) + = markdown(@issue.description, pipeline: :email, author: @issue.author) - if @issue.assignee_id.present? %p diff --git a/app/views/notify/new_merge_request_email.html.haml b/app/views/notify/new_merge_request_email.html.haml index 23423e7d98..158404de39 100644 --- a/app/views/notify/new_merge_request_email.html.haml +++ b/app/views/notify/new_merge_request_email.html.haml @@ -9,4 +9,4 @@ Assignee: #{@merge_request.author_name} → #{@merge_request.assignee_name} -if @merge_request.description - = markdown(@merge_request.description, pipeline: :email) + = markdown(@merge_request.description, pipeline: :email, author: @merge_request.author) diff --git a/app/views/notify/note_merge_request_email.html.haml b/app/views/notify/note_merge_request_email.html.haml index 65f0e4c406..a3643a00cf 100644 --- a/app/views/notify/note_merge_request_email.html.haml +++ b/app/views/notify/note_merge_request_email.html.haml @@ -1,7 +1,7 @@ -- if @note.diff_file_name +- if @note.legacy_diff_note? %p.details New comment on diff for - = link_to @note.diff_file_name, @target_url + = link_to @note.diff_file_path, @target_url \: = render 'note_message' diff --git a/app/views/notify/repository_push_email.html.haml b/app/views/notify/repository_push_email.html.haml index f2e405b14f..f1532371b2 100644 --- a/app/views/notify/repository_push_email.html.haml +++ b/app/views/notify/repository_push_email.html.haml @@ -1,3 +1,6 @@ += content_for :head do + = stylesheet_link_tag 'mailers/repository_push_email' + %h3 #{@message.author_name} #{@message.action_name} #{@message.ref_type} #{@message.ref_name} at #{link_to(@message.project_name_with_namespace, namespace_project_url(@message.project_namespace, @message.project))} @@ -43,26 +46,38 @@ = diff.new_path - unless @message.disable_diffs? - %h4 Changes: - - @message.diffs.each_with_index do |diff, i| - %li{id: "diff-#{i}"} - %a{href: @message.target_url + "#diff-#{i}"} - - if diff.deleted_file - %strong - = diff.old_path - deleted - - elsif diff.renamed_file - %strong - = diff.old_path - → - %strong - = diff.new_path - - else - %strong - = diff.new_path - %hr - = color_email_diff(diff.diff) - %br + - diff_files = @message.diffs - - if @message.compare_timeout - %h5 Huge diff. To prevent performance issues changes are hidden + - if @message.compare_timeout + %h5 The diff was not included because it is too large. + - else + %h4 Changes: + - diff_files.each_with_index do |diff_file, i| + %li{id: "diff-#{i}"} + %a{href: @message.target_url + "#diff-#{i}"}< + - if diff_file.deleted_file + %strong< + = diff_file.old_path + deleted + - elsif diff_file.renamed_file + %strong< + = diff_file.old_path + → + %strong< + = diff_file.new_path + - else + %strong< + = diff_file.new_path + - if diff_file.too_large? + The diff for this file was not included because it is too large. + - else + %hr + - diff_commit = diff_file.deleted_file ? @message.diff_refs.first : @message.diff_refs.last + - blob = @message.project.repository.blob_for_diff(diff_commit, diff_file) + - if blob && blob.respond_to?(:text?) && blob_text_viewable?(blob) + %table.code.white + - diff_file.highlighted_diff_lines.each do |line| + = render "projects/diffs/line", {line: line, diff_file: diff_file, line_code: nil, plain: true} + - else + No preview for this file type + %br diff --git a/app/views/notify/repository_push_email.text.haml b/app/views/notify/repository_push_email.text.haml index 53869e36b2..5ac23aa399 100644 --- a/app/views/notify/repository_push_email.text.haml +++ b/app/views/notify/repository_push_email.text.haml @@ -25,24 +25,28 @@ - else \- #{diff.new_path} - unless @message.disable_diffs? - \ - \ - Changes: - - @message.diffs.each do |diff| + - if @message.compare_timeout \ - \===================================== - - if diff.deleted_file - #{diff.old_path} deleted - - elsif diff.renamed_file - #{diff.old_path} → #{diff.new_path} - - else - = diff.new_path - \===================================== - != diff.diff - - if @message.compare_timeout - \ - \ - Huge diff. To prevent performance issues it was hidden + \ + The diff was not included because it is too large. + - else + \ + \ + Changes: + - @message.diffs.each do |diff_file| + \ + \===================================== + - if diff_file.deleted_file + #{diff_file.old_path} deleted + - elsif diff_file.renamed_file + #{diff_file.old_path} → #{diff_file.new_path} + - else + = diff_file.new_path + \===================================== + - if diff_file.too_large? + The diff for this file was not included because it is too large. + - else + != diff_file.diff.diff - if @message.target_url \ \ diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml index afd3d79321..01ac816194 100644 --- a/app/views/profiles/accounts/show.html.haml +++ b/app/views/profiles/accounts/show.html.haml @@ -70,7 +70,7 @@ - if current_user.can_change_username? .row.prepend-top-default .col-lg-3.profile-settings-sidebar - %h4.prepend-top-0.change-username-title + %h4.prepend-top-0.warning-title Change username %p Changing your username will change path to all personal projects! @@ -94,7 +94,7 @@ - if signup_enabled? .row.prepend-top-default .col-lg-3.profile-settings-sidebar - %h4.prepend-top-0.remove-account-title + %h4.prepend-top-0.danger-title Remove account .col-lg-9 - if @user.can_be_removed? diff --git a/app/views/profiles/preferences/show.html.haml b/app/views/profiles/preferences/show.html.haml index bfe53be685..1b1b16d656 100644 --- a/app/views/profiles/preferences/show.html.haml +++ b/app/views/profiles/preferences/show.html.haml @@ -5,7 +5,7 @@ %h4.prepend-top-0 Application theme %p - This setting allows you to customize the appearance of the site, ex. sidebar. + This setting allows you to customize the appearance of the site, e.g. the sidebar. .col-lg-9.application-theme - Gitlab::Themes.each do |theme| = label_tag do diff --git a/app/views/projects/_builds_settings.html.haml b/app/views/projects/_builds_settings.html.haml index 0de019983c..0568c2d305 100644 --- a/app/views/projects/_builds_settings.html.haml +++ b/app/views/projects/_builds_settings.html.haml @@ -1,74 +1,65 @@ %fieldset.builds-feature - %legend - Builds: - + %h5.prepend-top-0 + Builds - unless @repository.gitlab_ci_yml .form-group - .col-sm-offset-2.col-sm-10 - %p Builds need to be configured before you can begin using Continuous Integration. - = link_to 'Get started with Builds', help_page_path('ci/quick_start', 'README'), class: 'btn btn-info' - %hr + %p Builds need to be configured before you can begin using Continuous Integration. + = link_to 'Get started with Builds', help_page_path('ci/quick_start', 'README'), class: 'btn btn-info' + .form-group + %p Get recent application code using the following command: + .radio + = f.label :build_allow_git_fetch_false do + = f.radio_button :build_allow_git_fetch, 'false' + %strong git clone + %br + %span.descr Slower but makes sure you have a clean dir before every build + .radio + = f.label :build_allow_git_fetch_true do + = f.radio_button :build_allow_git_fetch, 'true' + %strong git fetch + %br + %span.descr Faster .form-group - .col-sm-offset-2.col-sm-10 - %p Get recent application code using the following command: - .radio - = f.label :build_allow_git_fetch_false do - = f.radio_button :build_allow_git_fetch, 'false' - %strong git clone - %br - %span.descr Slower but makes sure you have a clean dir before every build - .radio - = f.label :build_allow_git_fetch_true do - = f.radio_button :build_allow_git_fetch, 'true' - %strong git fetch - %br - %span.descr Faster + = f.label :build_timeout_in_minutes, 'Timeout', class: 'label-light' + = f.number_field :build_timeout_in_minutes, class: 'form-control', min: '0' + %p.help-block per build in minutes + .form-group + = f.label :build_coverage_regex, "Test coverage parsing", class: 'label-light' + .input-group + %span.input-group-addon / + = f.text_field :build_coverage_regex, class: 'form-control', placeholder: '\(\d+.\d+\%\) covered' + %span.input-group-addon / + %p.help-block + We will use this regular expression to find test coverage output in build trace. + Leave blank if you want to disable this feature + .bs-callout.bs-callout-info + %p Below are examples of regex for existing tools: + %ul + %li + Simplecov (Ruby) - + %code \(\d+.\d+\%\) covered + %li + pytest-cov (Python) - + %code \d+\%\s*$ + %li + phpunit --coverage-text --colors=never (PHP) - + %code ^\s*Lines:\s*\d+.\d+\% + %li + gcovr (C/C++) - + %code ^TOTAL.*\s+(\d+\%)$ + %li + tap --coverage-report=text-summary (Node.js) - + %code ^Statements\s*:\s*([^%]+) .form-group - = f.label :build_timeout_in_minutes, 'Timeout', class: 'control-label' - .col-sm-10 - = f.number_field :build_timeout_in_minutes, class: 'form-control', min: '0' - %p.help-block per build in minutes - .form-group - = f.label :build_coverage_regex, "Test coverage parsing", class: 'control-label' - .col-sm-10 - .input-group - %span.input-group-addon / - = f.text_field :build_coverage_regex, class: 'form-control', placeholder: '\(\d+.\d+\%\) covered' - %span.input-group-addon / - %p.help-block - We will use this regular expression to find test coverage output in build trace. - Leave blank if you want to disable this feature - .bs-callout.bs-callout-info - %p Below are examples of regex for existing tools: - %ul - %li - Simplecov (Ruby) - - %code \(\d+.\d+\%\) covered - %li - pytest-cov (Python) - - %code \d+\%\s*$ - %li - phpunit --coverage-text --colors=never (PHP) - - %code ^\s*Lines:\s*\d+.\d+\% - %li - gcovr (C/C++) - - %code ^TOTAL.*\s+(\d+\%)$ - %li - tap --coverage-report=text-summary (Node.js) - - %code ^Statements\s*:\s*([^%]+) + .checkbox + = f.label :public_builds do + = f.check_box :public_builds + %strong Public builds + .help-block Allow everyone to access builds for Public and Internal projects - .form-group - .col-sm-offset-2.col-sm-10 - .checkbox - = f.label :public_builds do - = f.check_box :public_builds - %strong Public builds - .help-block Allow everyone to access builds for Public and Internal projects - - .form-group - = f.label :runners_token, "Runners token", class: 'control-label' - .col-sm-10 - = f.text_field :runners_token, class: "form-control", placeholder: 'xEeFCaDAB89' - %p.help-block The secure token used to checkout project. + .form-group.append-bottom-0 + = f.label :runners_token, "Runners token", class: 'label-light' + = f.text_field :runners_token, class: "form-control", placeholder: 'xEeFCaDAB89' + %p.help-block The secure token used to checkout project. diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml index 9b5de17dd3..57c3d1b0a6 100644 --- a/app/views/projects/_home_panel.html.haml +++ b/app/views/projects/_home_panel.html.haml @@ -1,59 +1,37 @@ - empty_repo = @project.empty_repo? .project-home-panel.cover-block.clearfix{:class => ("empty-project" if empty_repo)} - .project-identicon-holder - = project_icon(@project, alt: '', class: 'project-avatar avatar s90') - .cover-title.project-home-desc - %h1 - = @project.name - %span.visibility-icon.has-tooltip{data: { container: 'body' }, title: visibility_icon_description(@project)} - = visibility_level_icon(@project.visibility_level, fw: false) + .container-fluid.container-limited + .row + .project-image-container + = project_icon(@project, alt: '', class: 'project-avatar avatar s70') + .project-info + .cover-title.project-home-desc + %h1 + = @project.name + %span.visibility-icon.has-tooltip{data: { container: 'body' }, title: visibility_icon_description(@project)} + = visibility_level_icon(@project.visibility_level, fw: false) - - if @project.description.present? - .cover-desc.project-home-desc - = markdown(@project.description, pipeline: :description) + - if @project.description.present? + .cover-desc.project-home-desc + = markdown(@project.description, pipeline: :description) - - if forked_from_project = @project.forked_from_project - .cover-desc - Forked from - = link_to project_path(forked_from_project) do - = forked_from_project.namespace.try(:name) + - if forked_from_project = @project.forked_from_project + .cover-desc + Forked from + = link_to project_path(forked_from_project) do + = forked_from_project.namespace.try(:name) - .cover-controls - - if current_user - = link_to namespace_project_path(@project.namespace, @project, format: :atom, private_token: current_user.private_token), class: 'btn btn-gray' do - = icon('rss') - - access = user_max_access_in_project(current_user.id, @project) - - can_edit = can?(current_user, :admin_project, @project) - - if access || can_edit - %span.dropdown.project-settings-dropdown - %a.dropdown-new.btn.btn-gray#project-settings-button{href: '#', 'data-toggle' => 'dropdown'} - = icon('cog') - = icon('angle-down') - %ul.dropdown-menu.dropdown-menu-right - - if can_edit - %li - = link_to edit_project_path(@project) do - Edit Project - - if access - %li - = link_to leave_namespace_project_project_members_path(@project.namespace, @project), - data: { confirm: leave_project_message(@project) }, method: :delete, title: 'Leave project' do - Leave Project + .project-repo-buttons + .count-buttons + = render 'projects/buttons/star' + = render 'projects/buttons/fork' - .project-repo-buttons - .split-one.count-buttons - = render 'projects/buttons/star' - = render 'projects/buttons/fork' - - .clone-row - .project-clone-holder - = render "shared/clone_panel" - - .split-repo-buttons - .btn-group.pull-left - = render "projects/buttons/download" - = render 'projects/buttons/dropdown' + .project-clone-holder + = render "shared/clone_panel" + .project-repo-buttons.btn-group.project-right-buttons + = render "projects/buttons/download" + = render 'projects/buttons/dropdown' = render 'projects/buttons/notifications' :javascript diff --git a/app/views/projects/_md_preview.html.haml b/app/views/projects/_md_preview.html.haml index 8de44a6c91..81afea2c60 100644 --- a/app/views/projects/_md_preview.html.haml +++ b/app/views/projects/_md_preview.html.haml @@ -8,7 +8,7 @@ %a.js-md-preview-button{ href: "#md-preview-holder", tabindex: -1 } Preview %li.pull-right - %button.zen-cotrol.zen-control-full.js-zen-enter{ type: 'button', tabindex: -1 } + %button.zen-control.zen-control-full.js-zen-enter{ type: 'button', tabindex: -1 } Go full screen .md-write-holder diff --git a/app/views/projects/_zen.html.haml b/app/views/projects/_zen.html.haml index e1e3501396..413477a2d3 100644 --- a/app/views/projects/_zen.html.haml +++ b/app/views/projects/_zen.html.haml @@ -4,5 +4,5 @@ = f.text_area attr, class: classes, placeholder: placeholder - else = text_area_tag attr, nil, class: classes, placeholder: placeholder - %a.zen-cotrol.zen-control-leave.js-zen-leave{ href: "#" } + %a.zen-control.zen-control-leave.js-zen-leave{ href: "#" } = icon('compress') diff --git a/app/views/projects/activity.html.haml b/app/views/projects/activity.html.haml index 69fa4ad37c..3c0f01cbf6 100644 --- a/app/views/projects/activity.html.haml +++ b/app/views/projects/activity.html.haml @@ -1,5 +1,4 @@ - page_title "Activity" -- header_title project_title(@project, "Activity", activity_project_path(@project)) = render 'projects/last_push' diff --git a/app/views/projects/artifacts/browse.html.haml b/app/views/projects/artifacts/browse.html.haml index 49f95ff37d..ede01dcc1a 100644 --- a/app/views/projects/artifacts/browse.html.haml +++ b/app/views/projects/artifacts/browse.html.haml @@ -1,5 +1,4 @@ - page_title 'Artifacts', "#{@build.name} (##{@build.id})", 'Builds' -= render 'projects/builds/header_title' .top-block.row-content-block.clearfix .pull-right diff --git a/app/views/projects/badges/index.html.haml b/app/views/projects/badges/index.html.haml index c22384ddf4..ee63bc55a3 100644 --- a/app/views/projects/badges/index.html.haml +++ b/app/views/projects/badges/index.html.haml @@ -1,6 +1,5 @@ - page_title 'Badges' - badges_path = namespace_project_badges_path(@project.namespace, @project) -- header_title project_title(@project, 'Badges', badges_path) .prepend-top-10 .panel.panel-default diff --git a/app/views/projects/blame/show.html.haml b/app/views/projects/blame/show.html.haml index 5f9a92ff93..377665b096 100644 --- a/app/views/projects/blame/show.html.haml +++ b/app/views/projects/blame/show.html.haml @@ -1,5 +1,4 @@ - page_title "Blame", @blob.path, @ref -- header_title project_title(@project, "Files", project_files_path(@project)) %h3.page-title Blame view diff --git a/app/views/projects/blob/_editor.html.haml b/app/views/projects/blob/_editor.html.haml index fefa652a3d..4071b59c00 100644 --- a/app/views/projects/blob/_editor.html.haml +++ b/app/views/projects/blob/_editor.html.haml @@ -16,6 +16,9 @@ .license-selector.js-license-selector.hide = select_tag :license_type, grouped_options_for_select(licenses_for_select, @project.repository.license_key), include_blank: true, class: 'select2 license-select', data: {placeholder: 'Choose a license template', project: @project.name, fullname: @project.namespace.human_name} + .gitignore-selector.hidden + = dropdown_tag("Choose a .gitignore template", options: { toggle_class: 'js-gitignore-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { filenames: gitignore_names } } ) + .encoding-selector = select_tag :encoding, options_for_select([ "base64", "text" ], "text"), class: 'select2' diff --git a/app/views/projects/blob/_header_title.html.haml b/app/views/projects/blob/_header_title.html.haml deleted file mode 100644 index 78c5ef20a5..0000000000 --- a/app/views/projects/blob/_header_title.html.haml +++ /dev/null @@ -1 +0,0 @@ -- header_title project_title(@project, "Files", project_files_path(@project)) diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml index effcce5a1c..e4f04ca776 100644 --- a/app/views/projects/blob/edit.html.haml +++ b/app/views/projects/blob/edit.html.haml @@ -1,5 +1,4 @@ - page_title "Edit", @blob.path, @ref -= render "header_title" .file-editor %ul.nav-links.no-bottom.js-edit-mode diff --git a/app/views/projects/blob/new.html.haml b/app/views/projects/blob/new.html.haml index 0459699432..c952bc7e5d 100644 --- a/app/views/projects/blob/new.html.haml +++ b/app/views/projects/blob/new.html.haml @@ -1,5 +1,4 @@ - page_title "New File", @path.presence, @ref -= render "header_title" %h3.page-title New File diff --git a/app/views/projects/blob/show.html.haml b/app/views/projects/blob/show.html.haml index 6988039b6c..ed670dae88 100644 --- a/app/views/projects/blob/show.html.haml +++ b/app/views/projects/blob/show.html.haml @@ -1,5 +1,4 @@ - page_title @blob.path, @ref -= render "header_title" = render 'projects/last_push' diff --git a/app/views/projects/branches/destroy.js.haml b/app/views/projects/branches/destroy.js.haml deleted file mode 100644 index a21ddaf493..0000000000 --- a/app/views/projects/branches/destroy.js.haml +++ /dev/null @@ -1 +0,0 @@ -$('.js-totalbranch-count').html("#{@repository.branch_count}") diff --git a/app/views/projects/branches/index.html.haml b/app/views/projects/branches/index.html.haml index ac7790421a..08148b1a18 100644 --- a/app/views/projects/branches/index.html.haml +++ b/app/views/projects/branches/index.html.haml @@ -1,5 +1,4 @@ - page_title "Branches" -= render "projects/commits/header_title" = render "projects/commits/head" .row-content-block .pull-right diff --git a/app/views/projects/branches/new.html.haml b/app/views/projects/branches/new.html.haml index c659af6338..5a6c8c243f 100644 --- a/app/views/projects/branches/new.html.haml +++ b/app/views/projects/branches/new.html.haml @@ -1,5 +1,4 @@ - page_title "New Branch" -= render "projects/commits/header_title" - if @error .alert.alert-danger diff --git a/app/views/projects/builds/_header_title.html.haml b/app/views/projects/builds/_header_title.html.haml deleted file mode 100644 index 082dab1f5b..0000000000 --- a/app/views/projects/builds/_header_title.html.haml +++ /dev/null @@ -1 +0,0 @@ -- header_title project_title(@project, "Builds", project_builds_path(@project)) diff --git a/app/views/projects/builds/index.html.haml b/app/views/projects/builds/index.html.haml index 2e8015d119..818d5d28f0 100644 --- a/app/views/projects/builds/index.html.haml +++ b/app/views/projects/builds/index.html.haml @@ -1,5 +1,5 @@ - page_title "Builds" -= render "header_title" += render "projects/pipelines/head" .top-area %ul.nav-links @@ -35,9 +35,6 @@ = icon('wrench') %span CI Lint -.row-content-block - #{(@scope || 'running').capitalize} builds from this project - %ul.content-list - if @builds.blank? %li diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml index c0f7a7686f..16017c994b 100644 --- a/app/views/projects/builds/show.html.haml +++ b/app/views/projects/builds/show.html.haml @@ -1,5 +1,5 @@ - page_title "#{@build.name} (##{@build.id})", "Builds" -= render "header_title" +- trace_with_state = @build.trace_with_state .build-page .row-content-block.top-block @@ -85,7 +85,9 @@ %pre.trace#build-trace %code.bash = preserve do - = raw @build.trace_html + = raw trace_with_state[:html] + - if @build.active? + %i{:class => "fa fa-refresh fa-spin"} %div#down-build-trace @@ -216,4 +218,4 @@ :javascript - new CiBuild("#{namespace_project_build_url(@project.namespace, @project, @build)}", "#{@build.status}") + new CiBuild("#{namespace_project_build_url(@project.namespace, @project, @build)}", "#{@build.status}", "#{trace_with_state[:state]}") diff --git a/app/views/projects/buttons/_dropdown.html.haml b/app/views/projects/buttons/_dropdown.html.haml index 1e4c46fca2..16b8e1cca9 100644 --- a/app/views/projects/buttons/_dropdown.html.haml +++ b/app/views/projects/buttons/_dropdown.html.haml @@ -2,7 +2,7 @@ .btn-group %a.btn.dropdown-toggle{href: '#', "data-toggle" => "dropdown"} = icon('plus') - %ul.dropdown-menu.dropdown-menu-right.project-home-dropdown + %ul.dropdown-menu.dropdown-menu-align-right.project-home-dropdown - can_create_issue = can?(current_user, :create_issue, @project) - merge_project = can?(current_user, :create_merge_request, @project) ? @project : (current_user && current_user.fork_of(@project)) - can_create_snippet = can?(current_user, :create_snippet, @project) diff --git a/app/views/projects/buttons/_fork.html.haml b/app/views/projects/buttons/_fork.html.haml index 5fb5fe5af2..34ad9fe2c4 100644 --- a/app/views/projects/buttons/_fork.html.haml +++ b/app/views/projects/buttons/_fork.html.haml @@ -12,7 +12,8 @@ = link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn has-tooltip' do = icon('code-fork fw') Fork - = link_to namespace_project_forks_path(@project.namespace, @project), class: 'count-with-arrow' do + %div.count-with-arrow %span.arrow %span.count - = @project.forks_count + = link_to namespace_project_forks_path(@project.namespace, @project) do + = @project.forks_count diff --git a/app/views/projects/buttons/_notifications.html.haml b/app/views/projects/buttons/_notifications.html.haml index c1e3e5b73a..1d05da5058 100644 --- a/app/views/projects/buttons/_notifications.html.haml +++ b/app/views/projects/buttons/_notifications.html.haml @@ -1,11 +1,11 @@ - if @notification_setting = form_for @notification_setting, url: namespace_project_notification_setting_path(@project.namespace.becomes(Namespace), @project), method: :patch, remote: true, html: { class: 'inline', id: 'notification-form' } do |f| = f.hidden_field :level - %span.dropdown + .dropdown %a.dropdown-new.btn.notifications-btn#notifications-button{href: '#', "data-toggle" => "dropdown"} = icon('bell') = notification_title(@notification_setting.level) - = icon('angle-down') - %ul.dropdown-menu.dropdown-menu-right.project-home-dropdown + = icon('caret-down') + %ul.dropdown-menu.dropdown-menu-align-right.project-home-dropdown - NotificationSetting.levels.each do |level| = notification_list_item(level.first, @notification_setting) diff --git a/app/views/projects/ci/builds/_build.html.haml b/app/views/projects/ci/builds/_build.html.haml index 8e95f04027..5bd6e3f0eb 100644 --- a/app/views/projects/ci/builds/_build.html.haml +++ b/app/views/projects/ci/builds/_build.html.haml @@ -13,7 +13,9 @@ %strong ##{build.id} - if build.stuck? - %i.fa.fa-warning.text-warning + = icon('warning', class: 'text-warning has-tooltip', title: 'Build is stuck. Check runners.') + - if defined?(retried) && retried + = icon('warning', class: 'text-warning has-tooltip', title: 'Build was retried.') - if defined?(commit_sha) && commit_sha %td @@ -70,11 +72,11 @@ .pull-right - if can?(current_user, :read_build, build) && build.artifacts? = link_to download_namespace_project_build_artifacts_path(build.project.namespace, build.project, build), title: 'Download artifacts', class: 'btn btn-build' do - %i.fa.fa-download + = icon('download') - if can?(current_user, :update_build, build) - if build.active? = link_to cancel_namespace_project_build_path(build.project.namespace, build.project, build, return_to: request.original_url), method: :post, title: 'Cancel', class: 'btn btn-build' do - %i.fa.fa-remove.cred + = icon('remove', class: 'cred') - elsif defined?(allow_retry) && allow_retry && build.retryable? = link_to retry_namespace_project_build_path(build.project.namespace, build.project, build, return_to: request.original_url), method: :post, title: 'Retry', class: 'btn btn-build' do - %i.fa.fa-refresh + = icon('refresh') diff --git a/app/views/projects/ci/commits/_commit.html.haml b/app/views/projects/ci/commits/_commit.html.haml new file mode 100644 index 0000000000..5e3a4123a8 --- /dev/null +++ b/app/views/projects/ci/commits/_commit.html.haml @@ -0,0 +1,71 @@ +- status = commit.status +%tr.commit + %td.commit-link + = link_to namespace_project_pipeline_path(@project.namespace, @project, commit.id), class: "ci-status ci-#{status}" do + = ci_icon_for_status(status) + %strong ##{commit.id} + + %td + %div.branch-commit + - if commit.ref + = link_to commit.ref, namespace_project_commits_path(@project.namespace, @project, commit.ref), class: "monospace" + · + = link_to commit.short_sha, namespace_project_commit_path(@project.namespace, @project, commit.sha), class: "commit-id monospace" +   + - if commit.tag? + %span.label.label-primary tag + - elsif commit.latest? + %span.label.label-success.has-tooltip{ title: 'Latest build for this branch' } latest + - if commit.triggered? + %span.label.label-primary triggered + - if commit.yaml_errors.present? + %span.label.label-danger.has-tooltip{ title: "#{commit.yaml_errors}" } yaml invalid + - if commit.builds.any?(&:stuck?) + %span.label.label-warning stuck + + %p.commit-title + - if commit_data = commit.commit_data + = link_to_gfm truncate(commit_data.title, length: 60), namespace_project_commit_path(@project.namespace, @project, commit_data.id), class: "commit-row-message" + - else + Cant find HEAD commit for this branch + + + - stages_status = commit.statuses.stages_status + - stages.each do |stage| + %td + - status = stages_status[stage] + - tooltip = "#{stage.titleize}: #{status || 'not found'}" + - if status + = link_to namespace_project_pipeline_path(@project.namespace, @project, commit.id, anchor: stage), class: "has-tooltip ci-status-icon-#{status}", title: tooltip do + = ci_icon_for_status(status) + - else + .light.has-tooltip{ title: tooltip } + \- + + %td + - if commit.started_at && commit.finished_at + %p.duration + #{duration_in_words(commit.finished_at, commit.started_at)} + + %td + .controls.hidden-xs.pull-right + - artifacts = commit.builds.latest.select { |b| b.artifacts? } + - if artifacts.present? + .dropdown.inline.build-artifacts + %button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'} + = icon('download') + %b.caret + %ul.dropdown-menu.dropdown-menu-align-right + - artifacts.each do |build| + %li + = link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, build), rel: 'nofollow' do + = icon("download") + %span #{build.name} + + - if can?(current_user, :update_pipeline, @project) + - if commit.retryable? + = link_to retry_namespace_project_pipeline_path(@project.namespace, @project, commit.id), class: 'btn has-tooltip', title: "Retry", method: :post do + = icon("repeat") + - if commit.cancelable? + = link_to cancel_namespace_project_pipeline_path(@project.namespace, @project, commit.id), class: 'btn btn-remove has-tooltip', title: "Cancel", method: :post do + = icon("remove") diff --git a/app/views/projects/commit/_builds.html.haml b/app/views/projects/commit/_builds.html.haml index 5c9a319ede..7f7a15aa21 100644 --- a/app/views/projects/commit/_builds.html.haml +++ b/app/views/projects/commit/_builds.html.haml @@ -1,2 +1,2 @@ - @ci_commits.each do |ci_commit| - = render "ci_commit", ci_commit: ci_commit + = render "ci_commit", ci_commit: ci_commit, pipeline_details: true diff --git a/app/views/projects/commit/_ci_commit.html.haml b/app/views/projects/commit/_ci_commit.html.haml index e849aefb18..32ff4d3097 100644 --- a/app/views/projects/commit/_ci_commit.html.haml +++ b/app/views/projects/commit/_ci_commit.html.haml @@ -1,24 +1,27 @@ .row-content-block.build-content.middle-block .pull-right - - if can?(current_user, :update_build, @project) + - if can?(current_user, :update_pipeline, ci_commit.project) - if ci_commit.builds.latest.failed.any?(&:retryable?) - = link_to "Retry failed", retry_builds_namespace_project_commit_path(@project.namespace, @project, ci_commit.sha), class: 'btn btn-grouped btn-primary', method: :post + = link_to "Retry failed", retry_namespace_project_pipeline_path(ci_commit.project.namespace, ci_commit.project, ci_commit.id), class: 'btn btn-grouped btn-primary', method: :post - if ci_commit.builds.running_or_pending.any? - = link_to "Cancel running", cancel_builds_namespace_project_commit_path(@project.namespace, @project, ci_commit.sha), data: { confirm: 'Are you sure?' }, class: 'btn btn-grouped btn-danger', method: :post + = link_to "Cancel running", cancel_namespace_project_pipeline_path(ci_commit.project.namespace, ci_commit.project, ci_commit.id), data: { confirm: 'Are you sure?' }, class: 'btn btn-grouped btn-danger', method: :post - .oneline - = pluralize ci_commit.statuses.count(:id), "build" - - if ci_commit.ref - for - %span.label.label-info - = ci_commit.ref - - if defined?(link_to_commit) && link_to_commit - for commit - = link_to ci_commit.short_sha, namespace_project_commit_path(@project.namespace, @project, ci_commit.sha), class: "monospace" - - if ci_commit.duration - in - = time_interval_in_words ci_commit.duration + .oneline.clearfix + - if defined?(pipeline_details) && pipeline_details + Pipeline + = link_to "##{ci_commit.id}", namespace_project_pipeline_path(ci_commit.project.namespace, ci_commit.project, ci_commit.id), class: "monospace" + with + = pluralize ci_commit.statuses.count(:id), "build" + - if ci_commit.ref + for + = link_to ci_commit.ref, namespace_project_commits_path(ci_commit.project.namespace, ci_commit.project, ci_commit.ref), class: "monospace" + - if defined?(link_to_commit) && link_to_commit + for commit + = link_to ci_commit.short_sha, namespace_project_commit_path(ci_commit.project.namespace, ci_commit.project, ci_commit.sha), class: "monospace" + - if ci_commit.duration + in + = time_interval_in_words ci_commit.duration - if ci_commit.yaml_errors.present? .bs-callout.bs-callout-danger @@ -28,7 +31,7 @@ %li= error You can also test your .gitlab-ci.yml in the #{link_to "Lint", ci_lint_path} -- if @project.builds_enabled? && !ci_commit.ci_yaml_file +- if ci_commit.project.builds_enabled? && !ci_commit.ci_yaml_file .bs-callout.bs-callout-warning \.gitlab-ci.yml not found in this commit @@ -38,34 +41,12 @@ %tr %th Status %th Build ID - %th Stage %th Name %th Tags %th Duration %th Finished at - - if @project.build_coverage_enabled? + - if ci_commit.project.build_coverage_enabled? %th Coverage %th - - builds = ci_commit.statuses.latest.ordered - = render builds, coverage: @project.build_coverage_enabled?, stage: true, ref: false, allow_retry: true - -- if ci_commit.retried.any? - .row-content-block.second-block - Retried builds - - .table-holder - %table.table.builds - %thead - %tr - %th Status - %th Build ID - %th Ref - %th Stage - %th Name - %th Tags - %th Duration - %th Finished at - - if @project.build_coverage_enabled? - %th Coverage - %th - = render ci_commit.retried, coverage: @project.build_coverage_enabled?, stage: true, ref: false + - ci_commit.statuses.stages.each do |stage| + = render 'projects/commit/ci_stage', stage: stage, statuses: ci_commit.statuses.where(stage: stage) diff --git a/app/views/projects/commit/_ci_stage.html.haml b/app/views/projects/commit/_ci_stage.html.haml new file mode 100644 index 0000000000..ae7bb01223 --- /dev/null +++ b/app/views/projects/commit/_ci_stage.html.haml @@ -0,0 +1,15 @@ +%tr + %th{colspan: 10} + %strong + %a{name: stage} + - status = statuses.latest.status + %span{class: "ci-status-link ci-status-icon-#{status}"} + = ci_icon_for_status(status) + - if stage +   + = stage.titleize.pluralize + = render statuses.latest.ordered, coverage: @project.build_coverage_enabled?, stage: false, ref: false, allow_retry: true + = render statuses.retried.ordered, coverage: @project.build_coverage_enabled?, stage: false, ref: false, retried: true + %tr + %td{colspan: 10} +   diff --git a/app/views/projects/commit/_commit_box.html.haml b/app/views/projects/commit/_commit_box.html.haml index 01163e526b..6674d58417 100644 --- a/app/views/projects/commit/_commit_box.html.haml +++ b/app/views/projects/commit/_commit_box.html.haml @@ -1,38 +1,36 @@ -.pull-right.commit-action-buttons - %div - - if @notes_count > 0 - %span.btn.disabled.btn-grouped - %i.fa.fa-comment - = @notes_count - .pull-left.btn-group - %a.btn.btn-grouped.dropdown-toggle{ data: {toggle: :dropdown} } - %i.fa.fa-download - Download as - %span.caret - %ul.dropdown-menu - - unless @commit.parents.length > 1 - %li= link_to "Email Patches", namespace_project_commit_path(@project.namespace, @project, @commit, format: :patch) - %li= link_to "Plain Diff", namespace_project_commit_path(@project.namespace, @project, @commit, format: :diff) - = link_to namespace_project_tree_path(@project.namespace, @project, @commit), class: "btn btn-grouped" do - = icon('files-o') - Browse Files - - unless @commit.has_been_reverted?(current_user) - = revert_commit_link(@commit, namespace_project_commit_path(@project.namespace, @project, @commit.id)) - = cherry_pick_commit_link(@commit, namespace_project_commit_path(@project.namespace, @project, @commit.id)) - %div - -%p -.commit-info-row - - if @commit.status - = link_to builds_namespace_project_commit_path(@project.namespace, @project, @commit.id), class: "ci-status ci-#{@commit.status}" do - = ci_icon_for_status(@commit.status) - build: - = ci_label_for_status(@commit.status) - %span.light Authored by +.commit-info-row.commit-info-row-header + %span.hidden-xs Authored by %strong = commit_author_link(@commit, avatar: true, size: 24) #{time_ago_with_tooltip(@commit.authored_date)} + .pull-right.commit-action-buttons + - if defined?(@notes_count) && @notes_count > 0 + %span.btn.disabled.btn-grouped.hidden-xs + = icon('comment') + = @notes_count + = link_to namespace_project_tree_path(@project.namespace, @project, @commit), class: "btn btn-grouped hidden-xs hidden-sm" do + Browse Files + .dropdown.inline + %a.btn.btn-default.dropdown-toggle{ data: { toggle: "dropdown" } } + %span.hidden-xs Options + %span.caret.commit-options-dropdown-caret + %ul.dropdown-menu.dropdown-menu-align-right + %li.visible-xs-block.visible-sm-block + = link_to namespace_project_tree_path(@project.namespace, @project, @commit) do + Browse Files + - unless @commit.has_been_reverted?(current_user) + %li.clearfix + = revert_commit_link(@commit, namespace_project_commit_path(@project.namespace, @project, @commit.id), has_tooltip: false) + %li.clearfix + = cherry_pick_commit_link(@commit, namespace_project_commit_path(@project.namespace, @project, @commit.id), has_tooltip: false) + %li.divider + %li.dropdown-header + Download + - unless @commit.parents.length > 1 + %li= link_to "Email Patches", namespace_project_commit_path(@project.namespace, @project, @commit, format: :patch) + %li= link_to "Plain Diff", namespace_project_commit_path(@project.namespace, @project, @commit, format: :diff) + - if @commit.different_committer? .commit-info-row %span.light Committed by @@ -41,8 +39,9 @@ #{time_ago_with_tooltip(@commit.committed_date)} .commit-info-row - %span.light Commit - = link_to @commit.id, namespace_project_commit_path(@project.namespace, @project, @commit), class: "monospace" + %span.hidden-xs.hidden-sm Commit + = link_to @commit.id, namespace_project_commit_path(@project.namespace, @project, @commit), class: "monospace hidden-xs hidden-sm" + = link_to @commit.short_id, namespace_project_commit_path(@project.namespace, @project, @commit), class: "monospace visible-xs-inline visible-sm-inline" = clipboard_button(clipboard_text: @commit.id) %span.cgray= pluralize(@commit.parents.count, "parent") - @commit.parents.each do |parent| @@ -51,12 +50,23 @@ %span.commit-info.branches %i.fa.fa-spinner.fa-spin +- if @commit.status + .commit-info-row + Builds for + = pluralize(@commit.ci_commits.count, 'pipeline') + = link_to builds_namespace_project_commit_path(@project.namespace, @project, @commit.id), class: "ci-status-link ci-status-icon-#{@commit.status}" do + = ci_icon_for_status(@commit.status) + = ci_label_for_status(@commit.status) + - if @commit.ci_commits.duration + in + = time_interval_in_words @commit.ci_commits.duration + .commit-box.content-block %h3.commit-title - = markdown escape_once(@commit.title), pipeline: :single_line + = markdown escape_once(@commit.title), pipeline: :single_line, author: @commit.author - if @commit.description.present? %pre.commit-description - = preserve(markdown(escape_once(@commit.description), pipeline: :single_line)) + = preserve(markdown(escape_once(@commit.description), pipeline: :single_line, author: @commit.author)) :javascript $(".commit-info.branches").load("#{branches_namespace_project_commit_path(@project.namespace, @project, @commit.id)}"); diff --git a/app/views/projects/commit/builds.html.haml b/app/views/projects/commit/builds.html.haml index 7118a4846c..2f051fb90e 100644 --- a/app/views/projects/commit/builds.html.haml +++ b/app/views/projects/commit/builds.html.haml @@ -1,7 +1,7 @@ - page_title "Builds", "#{@commit.title} (#{@commit.short_id})", "Commits" -= render "projects/commits/header_title" + .prepend-top-default = render "commit_box" -= render "ci_menu" += render "ci_menu" = render "builds" diff --git a/app/views/projects/commit/show.html.haml b/app/views/projects/commit/show.html.haml index e5e3d69603..401cb4f7e3 100644 --- a/app/views/projects/commit/show.html.haml +++ b/app/views/projects/commit/show.html.haml @@ -1,8 +1,6 @@ - page_title "#{@commit.title} (#{@commit.short_id})", "Commits" - page_description @commit.description -= render "projects/commits/header_title" - .prepend-top-default = render "commit_box" - if @commit.status diff --git a/app/views/projects/commits/_commit.atom.builder b/app/views/projects/commits/_commit.atom.builder new file mode 100644 index 0000000000..1657fb4616 --- /dev/null +++ b/app/views/projects/commits/_commit.atom.builder @@ -0,0 +1,14 @@ +xml.entry do + xml.id namespace_project_commit_url(@project.namespace, @project, id: commit.id) + xml.link href: namespace_project_commit_url(@project.namespace, @project, id: commit.id) + xml.title truncate(commit.title, length: 80) + xml.updated commit.committed_date.xmlschema + xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(commit.author_email)) + + xml.author do |author| + xml.name commit.author_name + xml.email commit.author_email + end + + xml.summary markdown(commit.description, pipeline: :single_line) +end diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml index c7d8c9a0d1..367027182b 100644 --- a/app/views/projects/commits/_commit.html.haml +++ b/app/views/projects/commits/_commit.html.haml @@ -17,14 +17,14 @@ .pull-right - if commit.status - = render_ci_status(commit) + = render_commit_status(commit) = clipboard_button(clipboard_text: commit.id) = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id" - if commit.description? .commit-row-description.js-toggle-content %pre - = preserve(markdown(escape_once(commit.description), pipeline: :single_line)) + = preserve(markdown(escape_once(commit.description), pipeline: :single_line, author: commit.author)) .commit-row-info by diff --git a/app/views/projects/commits/_commits.html.haml b/app/views/projects/commits/_commits.html.haml index 64e8da9201..7283a78a64 100644 --- a/app/views/projects/commits/_commits.html.haml +++ b/app/views/projects/commits/_commits.html.haml @@ -3,7 +3,7 @@ - commits, hidden = limited_commits(@commits) -- commits.group_by { |c| c.committed_date.to_date }.sort.reverse.each do |day, commits| +- commits.chunk { |c| c.committed_date.in_time_zone.to_date }.each do |day, commits| .row.commits-row .col-md-2.hidden-xs.hidden-sm %h5.commits-row-date diff --git a/app/views/projects/commits/_head.html.haml b/app/views/projects/commits/_head.html.haml index d1bd76ab52..1c136133ab 100644 --- a/app/views/projects/commits/_head.html.haml +++ b/app/views/projects/commits/_head.html.haml @@ -1,9 +1,11 @@ %ul.nav-links + = nav_link(controller: %w(tree blob blame edit_tree new_tree find_file)) do + = link_to project_files_path(@project) do + Files + = nav_link(controller: [:commit, :commits]) do = link_to namespace_project_commits_path(@project.namespace, @project, current_ref) do Commits - %span.badge - = number_with_delimiter(@repository.commit_count) = nav_link(controller: %w(network)) do = link_to namespace_project_network_path(@project.namespace, @project, current_ref) do @@ -16,9 +18,7 @@ = nav_link(html_options: {class: branches_tab_class}) do = link_to namespace_project_branches_path(@project.namespace, @project) do Branches - %span.badge.js-totalbranch-count= @repository.branch_count = nav_link(controller: [:tags, :releases]) do = link_to namespace_project_tags_path(@project.namespace, @project) do Tags - %span.badge.js-totaltags-count= @repository.tag_count diff --git a/app/views/projects/commits/_header_title.html.haml b/app/views/projects/commits/_header_title.html.haml deleted file mode 100644 index e4385893dd..0000000000 --- a/app/views/projects/commits/_header_title.html.haml +++ /dev/null @@ -1 +0,0 @@ -- header_title project_title(@project, "Commits", project_commits_path(@project)) diff --git a/app/views/projects/commits/show.atom.builder b/app/views/projects/commits/show.atom.builder index e310fafd82..30bb741207 100644 --- a/app/views/projects/commits/show.atom.builder +++ b/app/views/projects/commits/show.atom.builder @@ -6,18 +6,5 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear xml.id namespace_project_commits_url(@project.namespace, @project, @ref) xml.updated @commits.first.committed_date.xmlschema if @commits.any? - @commits.each do |commit| - xml.entry do - xml.id namespace_project_commit_url(@project.namespace, @project, id: commit.id) - xml.link href: namespace_project_commit_url(@project.namespace, @project, id: commit.id) - xml.title truncate(commit.title, length: 80) - xml.updated commit.committed_date.xmlschema - xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(commit.author_email)) - xml.author do |author| - xml.name commit.author_name - xml.email commit.author_email - end - xml.summary markdown(commit.description, pipeline: :single_line) - end - end + xml << render(@commits) if @commits.any? end diff --git a/app/views/projects/commits/show.html.haml b/app/views/projects/commits/show.html.haml index 088eaa2801..2c21923ed4 100644 --- a/app/views/projects/commits/show.html.haml +++ b/app/views/projects/commits/show.html.haml @@ -1,5 +1,4 @@ - page_title "Commits", @ref -= render "header_title" = content_for :meta_tags do - if current_user = auto_discovery_link_tag(:atom, namespace_project_commits_url(@project.namespace, @project, @ref, format: :atom, private_token: current_user.private_token), title: "#{@project.name}:#{@ref} commits") diff --git a/app/views/projects/compare/index.html.haml b/app/views/projects/compare/index.html.haml index 5e188dd0f3..0b8ed23b30 100644 --- a/app/views/projects/compare/index.html.haml +++ b/app/views/projects/compare/index.html.haml @@ -1,5 +1,4 @@ - page_title "Compare" -= render "projects/commits/header_title" = render "projects/commits/head" .row-content-block diff --git a/app/views/projects/compare/show.html.haml b/app/views/projects/compare/show.html.haml index 6252516823..cdc34f51d6 100644 --- a/app/views/projects/compare/show.html.haml +++ b/app/views/projects/compare/show.html.haml @@ -1,5 +1,4 @@ - page_title "#{params[:from]}...#{params[:to]}" -= render "projects/commits/header_title" = render "projects/commits/head" diff --git a/app/views/projects/container_registry/_tag.html.haml b/app/views/projects/container_registry/_tag.html.haml new file mode 100644 index 0000000000..4e9f936539 --- /dev/null +++ b/app/views/projects/container_registry/_tag.html.haml @@ -0,0 +1,21 @@ +%tr.tag + %td + = escape_once(tag.name) + = clipboard_button(clipboard_text: "docker pull #{tag.path}") + %td + - if layer = tag.layers.first + %span.has-tooltip{ title: "#{layer.revision}" } + = layer.short_revision + - else + \- + %td + = number_to_human_size(tag.total_size) + · + = pluralize(tag.layers.size, "layer") + %td + = time_ago_in_words(tag.created_at) + - if can?(current_user, :update_container_image, @project) + %td.content + .controls.hidden-xs.pull-right + = link_to namespace_project_container_registry_path(@project.namespace, @project, tag.name), class: 'btn btn-remove has-tooltip', title: "Remove", data: { confirm: "Are you sure?" }, method: :delete do + = icon("trash cred") diff --git a/app/views/projects/container_registry/index.html.haml b/app/views/projects/container_registry/index.html.haml new file mode 100644 index 0000000000..993da27310 --- /dev/null +++ b/app/views/projects/container_registry/index.html.haml @@ -0,0 +1,39 @@ +- page_title "Container Registry" + +%hr + +%ul.content-list + %li.light.prepend-top-default + %p + A 'container image' is a snapshot of a container. + You can host your container images with GitLab. + %br + To start using container images hosted on GitLab you first need to login: + %pre + %code + docker login #{Gitlab.config.registry.host_port} + %br + Then you are free to create and upload a container image with build and push commands: + %pre + docker build -t #{escape_once(@project.container_registry_repository_url)} . + %br + docker push #{escape_once(@project.container_registry_repository_url)} + + - if @tags.blank? + %li + .nothing-here-block No images in Container Registry for this project. + + - else + .table-holder + %table.table.tags + %thead + %tr + %th Name + %th Image ID + %th Size + %th Created + - if can?(current_user, :update_container_image, @project) + %th + + - @tags.each do |tag| + = render 'tag', tag: tag diff --git a/app/views/projects/deploy_keys/index.html.haml b/app/views/projects/deploy_keys/index.html.haml index e230834e8b..04fbb37d93 100644 --- a/app/views/projects/deploy_keys/index.html.haml +++ b/app/views/projects/deploy_keys/index.html.haml @@ -19,7 +19,7 @@ %ul.well-list = render @enabled_keys - else - .profile-settings-message.text-center + .settings-message.text-center No deploy keys found. Create one with the form above or add existing one below. %h5.prepend-top-default Deploy keys from projects you have access to (#{@available_project_keys.size}) @@ -27,7 +27,7 @@ %ul.well-list = render @available_project_keys - else - .profile-settings-message.text-center + .settings-message.text-center No deploy keys from your projects could be found. Create one with the form above or add existing one below. - if @available_public_keys.any? %h5.prepend-top-default diff --git a/app/views/projects/diffs/_file.html.haml b/app/views/projects/diffs/_file.html.haml index 0f04fc5d33..e5983c5803 100644 --- a/app/views/projects/diffs/_file.html.haml +++ b/app/views/projects/diffs/_file.html.haml @@ -11,11 +11,9 @@ = link_to "#diff-#{i}" do - if diff_file.renamed_file - old_path, new_path = mark_inline_diffs(diff_file.old_path, diff_file.new_path) - .filename.old - = old_path + = old_path → - .filename.new - = new_path + = new_path - else %span = diff_file.new_path @@ -41,7 +39,7 @@ .diff-content.diff-wrap-lines - # Skip all non non-supported blobs - - return unless blob.respond_to?('text?') + - return unless blob.respond_to?(:text?) - if diff_file.too_large? .nothing-here-block This diff could not be displayed because it is too large. - elsif blob_text_viewable?(blob) && !project.repository.diffable?(blob) diff --git a/app/views/projects/diffs/_line.html.haml b/app/views/projects/diffs/_line.html.haml index 107097ad96..f1577e8a47 100644 --- a/app/views/projects/diffs/_line.html.haml +++ b/app/views/projects/diffs/_line.html.haml @@ -15,7 +15,7 @@ = link_text - else = link_to "", "##{line_code}", id: line_code, data: { linenumber: link_text } - - if @comments_allowed && can?(current_user, :create_note, @project) + - if !@diff_notes_disabled && can?(current_user, :create_note, @project) = link_to_new_diff_note(line_code) %td.new_line.diff-line-num{ class: type, data: { linenumber: line.new_pos } } - link_text = type == "old" ? " ".html_safe : line.new_pos diff --git a/app/views/projects/diffs/_parallel_view.html.haml b/app/views/projects/diffs/_parallel_view.html.haml index 81948513e4..4ecc9528bd 100644 --- a/app/views/projects/diffs/_parallel_view.html.haml +++ b/app/views/projects/diffs/_parallel_view.html.haml @@ -16,7 +16,7 @@ - else %td.old_line.diff-line-num{id: left[:line_code], class: "#{left[:type]} #{'empty-cell' if !left[:number]}"} = link_to raw(left[:number]), "##{left[:line_code]}", id: left[:line_code] - - if @comments_allowed && can?(current_user, :create_note, @project) + - if !@diff_notes_disabled && can?(current_user, :create_note, @project) = link_to_new_diff_note(left[:line_code], 'old') %td.line_content{class: "parallel noteable_line #{left[:type]} #{left[:line_code]} #{'empty-cell' if left[:text].empty?}", data: { line_code: left[:line_code] }}= diff_line_content(left[:text]) @@ -29,14 +29,14 @@ %td.new_line.diff-line-num{id: new_line_code, class: "#{new_line_class} #{'empty-cell' if !right[:number]}", data: { linenumber: right[:number] }} = link_to raw(right[:number]), "##{new_line_code}", id: new_line_code - - if @comments_allowed && can?(current_user, :create_note, @project) - = link_to_new_diff_note(right[:line_code], 'new') + - if !@diff_notes_disabled && can?(current_user, :create_note, @project) + = link_to_new_diff_note(new_line_code, 'new') %td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code} #{'empty-cell' if right[:text].empty?}", data: { line_code: new_line_code }}= diff_line_content(right[:text]) - - if @reply_allowed - - comments_left, comments_right = organize_comments(left[:type], right[:type], left[:line_code], right[:line_code]) - - if comments_left.present? || comments_right.present? - = render "projects/notes/diff_notes_with_reply_parallel", notes_left: comments_left, notes_right: comments_right + - unless @diff_notes_disabled + - notes_left, notes_right = organize_comments(left, right) + - if notes_left.present? || notes_right.present? + = render "projects/notes/diff_notes_with_reply_parallel", notes_left: notes_left, notes_right: notes_right - if diff_file.diff.diff.blank? && diff_file.mode_changed? .file-mode-changed diff --git a/app/views/projects/diffs/_text_file.html.haml b/app/views/projects/diffs/_text_file.html.haml index e7169d7b59..068593a7dd 100644 --- a/app/views/projects/diffs/_text_file.html.haml +++ b/app/views/projects/diffs/_text_file.html.haml @@ -6,16 +6,15 @@ %table.text-file.code.js-syntax-highlight{ class: too_big ? 'hide' : '' } - last_line = 0 - - raw_diff_lines = diff_file.diff_lines.to_a - diff_file.highlighted_diff_lines.each_with_index do |line, index| - line_code = generate_line_code(diff_file.file_path, line) - last_line = line.new_pos = render "projects/diffs/line", {line: line, diff_file: diff_file, line_code: line_code} - - if @reply_allowed - - comments = @line_notes.select { |n| n.line_code == line_code && n.active? }.sort_by(&:created_at) - - unless comments.empty? - = render "projects/notes/diff_notes_with_reply", notes: comments, line: raw_diff_lines[index].text + - unless @diff_notes_disabled + - diff_notes = @grouped_diff_notes[line_code] + - if diff_notes + = render "projects/notes/diff_notes_with_reply", notes: diff_notes - if last_line > 0 = render "projects/diffs/match_line", { line: "", diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 76a4f41193..18b125ff9d 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -1,251 +1,221 @@ -.project-edit-container.prepend-top-default - .project-edit-errors - .project-edit-content - .panel.panel-default - .panel-heading +.project-edit-container + .row.prepend-top-default + .col-lg-3.profile-settings-sidebar + %h4.prepend-top-0 Project settings - .panel-body - = form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "edit_project form-horizontal fieldset-form" }, authenticity_token: true do |f| - - %fieldset - .form-group.project_name_holder - = f.label :name, class: 'control-label' do - Project name - .col-sm-10 - = f.text_field :name, class: "form-control", id: "project_name_edit" - - - .form-group - = f.label :description, class: 'control-label' do - Project description - %span.light (optional) - .col-sm-10 - = f.text_area :description, class: "form-control", rows: 3, maxlength: 250 - - - unless @project.empty_repo? - .form-group - = f.label :default_branch, "Default Branch", class: 'control-label' - .col-sm-10= f.select(:default_branch, @project.repository.branch_names, {}, {class: 'select2 select-wide'}) - - - = render 'shared/visibility_level', f: f, visibility_level: @project.visibility_level, can_change_visibility_level: can_change_visibility_level?(@project, current_user), form_model: @project - + .col-lg-9 + = form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "edit-project" }, authenticity_token: true do |f| + %fieldset.append-bottom-0 .form-group - = f.label :tag_list, "Tags", class: 'control-label' - .col-sm-10 - = f.text_field :tag_list, value: @project.tag_list.to_s, maxlength: 2000, class: "form-control" - %p.help-block Separate tags with commas. + = f.label :name, class: 'label-light' do + Project name + = f.text_field :name, class: "form-control", id: "project_name_edit" + .form-group + = f.label :description, class: 'label-light' do + Project description + %span.light (optional) + = f.text_area :description, class: "form-control", rows: 3, maxlength: 250 - %fieldset.features - %legend - Features: + - unless @project.empty_repo? .form-group - .col-sm-offset-2.col-sm-10 - .checkbox - = f.label :issues_enabled do - = f.check_box :issues_enabled - %strong Issues - %br - %span.descr Lightweight issue tracking system for this project - - .form-group - .col-sm-offset-2.col-sm-10 - .checkbox - = f.label :merge_requests_enabled do - = f.check_box :merge_requests_enabled - %strong Merge Requests - %br - %span.descr Submit changes to be merged upstream - - .form-group - .col-sm-offset-2.col-sm-10 - .checkbox - = f.label :builds_enabled do - = f.check_box :builds_enabled - %strong Builds - %br - %span.descr Test and deploy your changes before merge - - .form-group - .col-sm-offset-2.col-sm-10 - .checkbox - = f.label :wiki_enabled do - = f.check_box :wiki_enabled - %strong Wiki - %br - %span.descr Pages for project documentation - - .form-group - .col-sm-offset-2.col-sm-10 - .checkbox - = f.label :snippets_enabled do - = f.check_box :snippets_enabled - %strong Snippets - %br - %span.descr Share code pastes with others out of git repository - - = render 'builds_settings', f: f - - %fieldset.features - %legend - Project avatar: - .form-group - .col-sm-offset-2.col-sm-10 - - if @project.avatar? - = project_icon("#{@project.namespace.to_param}/#{@project.to_param}", alt: '', class: 'avatar project-avatar s160') - %p.light - - if @project.avatar_in_git - Project avatar in repository: #{ @project.avatar_in_git } - %p.light - - if @project.avatar? - You can change your project avatar here - - else - You can upload a project avatar here - %a.choose-btn.btn.btn-sm.js-choose-project-avatar-button - %i.icon-paper-clip - %span Choose File ... -   - %span.file_name.js-avatar-filename File name... - = f.file_field :avatar, class: "js-project-avatar-input hidden" - .light The maximum file size allowed is 200KB. - - if @project.avatar? - %hr - = link_to 'Remove avatar', namespace_project_avatar_path(@project.namespace, @project), data: { confirm: "Project avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar" - - - .form-actions - = f.submit 'Save changes', class: "btn btn-save" - - - - .danger-settings - .panel.panel-default - .panel-heading Housekeeping - .errors-holder - .panel-body - %p - Runs a number of housekeeping tasks within the current repository, - such as compressing file revisions and removing unreachable objects. - %br - - .form-actions - = link_to 'Housekeeping', housekeeping_namespace_project_path(@project.namespace, @project), - method: :post, class: "btn btn-default" - - - if can? current_user, :archive_project, @project - - if @project.archived? - .panel.panel-success - .panel-heading - Unarchive project - .panel-body - %p - Unarchiving the project will mark its repository as active. + = f.label :default_branch, "Default Branch", class: 'label-light' + = f.select(:default_branch, @project.repository.branch_names, {}, {class: 'select2 select-wide'}) + .form-group.project-visibility-level-holder + = f.label :visibility_level, class: 'label-light' do + Visibility Level + = link_to "(?)", help_page_path("public_access", "public_access") + - if can_change_visibility_level?(@project, current_user) + = render('shared/visibility_radios', model_method: :visibility_level, form: f, selected_level: @project.visibility_level, form_model: @project) + - else + .info + = visibility_level_icon(@project.visibility_level) + %strong + = visibility_level_label(@project.visibility_level) + .light= visibility_level_description(@project.visibility_level, @project) + .form-group + = f.label :tag_list, "Tags", class: 'label-light' + = f.text_field :tag_list, value: @project.tag_list.to_s, maxlength: 2000, class: "form-control" + %p.help-block Separate tags with commas. + %hr + %fieldset.features.append-bottom-0 + %h5.prepend-top-0 + Features + .form-group + .checkbox + = f.label :issues_enabled do + = f.check_box :issues_enabled + %strong Issues %br - The project can be committed to. + %span.descr Lightweight issue tracking system for this project + .form-group + .checkbox + = f.label :merge_requests_enabled do + = f.check_box :merge_requests_enabled + %strong Merge Requests %br - %strong Once active this project shows up in the search and on the dashboard. - - .form-actions - = link_to 'Unarchive project', unarchive_namespace_project_path(@project.namespace, @project), - data: { confirm: "Are you sure that you want to unarchive this project?\nWhen this project is unarchived it is active and can be committed to again." }, - method: :post, class: "btn btn-success" - - else - .panel.panel-warning - .panel-heading - Archive project - .panel-body - %p - Archiving the project will mark its repository as read-only. + %span.descr Submit changes to be merged upstream + .form-group + .checkbox + = f.label :builds_enabled do + = f.check_box :builds_enabled + %strong Builds %br - It is hidden from the dashboard and doesn't show up in searches. + %span.descr Test and deploy your changes before merge + .form-group + .checkbox + = f.label :wiki_enabled do + = f.check_box :wiki_enabled + %strong Wiki %br - %strong Archived projects cannot be committed to! - - .form-actions - = link_to 'Archive project', archive_namespace_project_path(@project.namespace, @project), - data: { confirm: "Are you sure that you want to archive this project?\nAn archived project cannot be committed to." }, - method: :post, class: "btn btn-warning" - - else - .nothing-here-block Only the project owner can archive a project - - .panel.panel-default.panel.panel-warning - .panel-heading Rename repository - .errors-holder - .panel-body - = form_for([@project.namespace.becomes(Namespace), @project], html: { class: 'form-horizontal' }) do |f| - .form-group.project_name_holder - = f.label :name, class: 'control-label' do - Project name - .col-sm-9 - .form-group - = f.text_field :name, class: "form-control" + %span.descr Pages for project documentation + .form-group + .checkbox + = f.label :snippets_enabled do + = f.check_box :snippets_enabled + %strong Snippets + %br + %span.descr Share code pastes with others out of git repository + - if Gitlab.config.registry.enabled .form-group - = f.label :path, class: 'control-label' do - %span Path - .col-sm-9 - .form-group - .input-group - .input-group-addon - #{URI.join(root_url, @project.namespace.path)}/ - = f.text_field :path, class: 'form-control' - %ul - %li Be careful. Renaming a project's repository can have unintended side effects. - %li You will need to update your local repositories to point to the new location. - .form-actions - = f.submit 'Rename project', class: "btn btn-warning" - - - if can?(current_user, :change_namespace, @project) - .panel.panel-default.panel.panel-danger - .panel-heading Transfer project - .errors-holder - .panel-body - = form_for([@project.namespace.becomes(Namespace), @project], url: transfer_namespace_project_path(@project.namespace, @project), method: :put, remote: true, html: { class: 'transfer-project form-horizontal' }) do |f| - .form-group - = label_tag :new_namespace_id, nil, class: 'control-label' do - %span Namespace - .col-sm-9 - .form-group - = select_tag :new_namespace_id, namespaces_options(@project.namespace_id), { prompt: 'Choose a project namespace', class: 'select2' } - %ul - %li Be careful. Changing the project's namespace can have unintended side effects. - %li You can only transfer the project to namespaces you manage. - %li You will need to update your local repositories to point to the new location. - %li Project visibility level will be changed to match namespace rules when transfering to a group. - .form-actions - = f.submit 'Transfer project', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => transfer_project_message(@project) } - - else - .nothing-here-block Only the project owner can transfer a project - - - if @project.forked? - - if can?(current_user, :remove_fork_project, @project) - = form_for([@project.namespace.becomes(Namespace), @project], url: remove_fork_namespace_project_path(@project.namespace, @project), method: :delete, remote: true, html: { class: 'transfer-project form-horizontal' }) do |f| - .panel.panel-default.panel.panel-danger - .panel-heading Remove fork relationship - .panel-body - %p - This will remove the fork relationship to source project - #{link_to @project.forked_from_project.name_with_namespace, project_path(@project.forked_from_project)}. + .checkbox + = f.label :container_registry_enabled do + = f.check_box :container_registry_enabled + %strong Container Registry %br - %strong Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source. - .form-actions - = button_to 'Remove fork relationship', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_fork_project_message(@project) } + %span.descr Enable Container Registry for this repository + %hr + = render 'builds_settings', f: f + %hr + %fieldset.features.append-bottom-default + %h5.prepend-top-0 + Project avatar + .form-group + - if @project.avatar? + = project_icon("#{@project.namespace.to_param}/#{@project.to_param}", alt: '', class: 'avatar project-avatar s160') + %p.light + - if @project.avatar_in_git + Project avatar in repository: #{ @project.avatar_in_git } + %a.choose-btn.btn.js-choose-project-avatar-button + Browse file... + %span.file_name.prepend-left-default.js-avatar-filename No file chosen + = f.file_field :avatar, class: "js-project-avatar-input hidden" + .help-block The maximum file size allowed is 200KB. + - if @project.avatar? + %hr + = link_to 'Remove avatar', namespace_project_avatar_path(@project.namespace, @project), data: { confirm: "Project avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar" + = f.submit 'Save changes', class: "btn btn-save" + .row.prepend-top-default + %hr + .row.prepend-top-default + .col-lg-3 + %h4.prepend-top-0 + Housekeeping + %p.append-bottom-0 + %p + Runs a number of housekeeping tasks within the current repository, + such as compressing file revisions and removing unreachable objects. + .col-lg-9 + = link_to 'Housekeeping', housekeeping_namespace_project_path(@project.namespace, @project), + method: :post, class: "btn btn-save" + %hr + - if can? current_user, :archive_project, @project + .row.prepend-top-default + .col-lg-3 + %h4.warning-title.prepend-top-0 + - if @project.archived? + Unarchive project + - else + Archive project + %p.append-bottom-0 + - if @project.archived? + Unarchiving the project will mark its repository as active. The project can be committed to. + - else + Archiving the project will mark its repository as read-only. It is hidden from the dashboard and doesn't show up in searches. + .col-lg-9 + - if @project.archived? + %p + %strong Once active this project shows up in the search and on the dashboard. + = link_to 'Unarchive project', unarchive_namespace_project_path(@project.namespace, @project), + data: { confirm: "Are you sure that you want to unarchive this project?\nWhen this project is unarchived it is active and can be committed to again." }, + method: :post, class: "btn btn-success" - else - .nothing-here-block Only the project owner can remove the fork relationship. - - - if can?(current_user, :remove_project, @project) - .panel.panel-default.panel.panel-danger - .panel-heading Remove project - .panel-body - = form_tag(namespace_project_path(@project.namespace, @project), method: :delete, class: 'form-horizontal') do - %p - Removing the project will delete its repository and all related resources including issues, merge requests etc. - %br - %strong Removed projects cannot be restored! - .form-actions - = button_to 'Remove project', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_project_message(@project) } - - else - .nothing-here-block Only the project owner can remove a project. - + %p + %strong Archived projects cannot be committed to! + = link_to 'Archive project', archive_namespace_project_path(@project.namespace, @project), + data: { confirm: "Are you sure that you want to archive this project?\nAn archived project cannot be committed to." }, + method: :post, class: "btn btn-warning" + %hr + .row.prepend-top-default + .col-lg-3 + %h4.prepend-top-0.warning-title + Rename repository + .col-lg-9 + = form_for([@project.namespace.becomes(Namespace), @project]) do |f| + .form-group.project_name_holder + = f.label :name, class: 'label-light' do + Project name + .form-group + = f.text_field :name, class: "form-control" + .form-group + = f.label :path, class: 'label-light' do + %span Path + .form-group + .input-group + .input-group-addon + #{URI.join(root_url, @project.namespace.path)}/ + = f.text_field :path, class: 'form-control' + %ul + %li Be careful. Renaming a project's repository can have unintended side effects. + %li You will need to update your local repositories to point to the new location. + = f.submit 'Rename project', class: "btn btn-warning" + - if can?(current_user, :change_namespace, @project) + %hr + .row.prepend-top-default + .col-lg-3 + %h4.prepend-top-0.danger-title + Transfer project + .col-lg-9 + = form_for([@project.namespace.becomes(Namespace), @project], url: transfer_namespace_project_path(@project.namespace, @project), method: :put, remote: true) do |f| + .form-group + = label_tag :new_namespace_id, nil, class: 'label-light' do + %span Namespace + .form-group + = select_tag :new_namespace_id, namespaces_options(@project.namespace_id), { prompt: 'Choose a project namespace', class: 'select2' } + %ul + %li Be careful. Changing the project's namespace can have unintended side effects. + %li You can only transfer the project to namespaces you manage. + %li You will need to update your local repositories to point to the new location. + %li Project visibility level will be changed to match namespace rules when transfering to a group. + = f.submit 'Transfer project', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => transfer_project_message(@project) } + - if @project.forked? && can?(current_user, :remove_fork_project, @project) + %hr + .row.prepend-top-default.append-bottom-default + .col-lg-3 + %h4.prepend-top-0.danger-title + Remove fork relationship + %p.append-bottom-0 + %p + This will remove the fork relationship to source project + = succeed "." do + = link_to @project.forked_from_project.name_with_namespace, project_path(@project.forked_from_project) + .col-lg-9 + = form_for([@project.namespace.becomes(Namespace), @project], url: remove_fork_namespace_project_path(@project.namespace, @project), method: :delete, remote: true, html: { class: 'transfer-project' }) do |f| + %p + %strong Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source. + = button_to 'Remove fork relationship', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_fork_project_message(@project) } + - if can?(current_user, :remove_project, @project) + %hr + .row.prepend-top-default.append-bottom-default + .col-lg-3 + %h4.prepend-top-0.danger-title + Remove project + %p.append-bottom-0 + Removing the project will delete its repository and all related resources including issues, merge requests etc. + .col-lg-9 + = form_tag(namespace_project_path(@project.namespace, @project), method: :delete) do + %p + %strong Removed projects cannot be restored! + = button_to 'Remove project', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_project_message(@project) } .save-project-loader.hide .center @@ -254,5 +224,4 @@ Saving project. %p Please wait a moment, this page will automatically refresh when ready. - = render 'shared/confirm_modal', phrase: @project.path diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml index 1a2e59752f..636beb73ec 100644 --- a/app/views/projects/empty.html.haml +++ b/app/views/projects/empty.html.haml @@ -15,10 +15,14 @@ If you already have files you can push them using command line instructions below. %p Otherwise you can start with adding a - = link_to "README", new_readme_path, class: 'underlined-link' + = succeed ',' do + = link_to "README", new_readme_path, class: 'underlined-link' + a + = succeed ',' do + = link_to "LICENSE", add_special_file_path(@project, file_name: 'LICENSE'), class: 'underlined-link' or a - = link_to "LICENSE", add_special_file_path(@project, file_name: 'LICENSE'), class: 'underlined-link' - file to this project. + = link_to '.gitignore', add_special_file_path(@project, file_name: '.gitignore'), class: 'underlined-link' + to this project. - if can?(current_user, :push_code, @project) %div{ class: container_class } diff --git a/app/views/projects/find_file/show.html.haml b/app/views/projects/find_file/show.html.haml index 1fe1d98bf1..9322c82904 100644 --- a/app/views/projects/find_file/show.html.haml +++ b/app/views/projects/find_file/show.html.haml @@ -1,5 +1,4 @@ - page_title "Find File", @ref -- header_title project_title(@project, "Files", project_files_path(@project)) .file-finder-holder.tree-holder.clearfix .nav-block diff --git a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml index f21c864e35..5bc5c71283 100644 --- a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml +++ b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml @@ -12,6 +12,9 @@ - else %strong ##{generic_commit_status.id} + - if defined?(retried) && retried + = icon('warning', class: 'text-warning has-tooltip', title: 'Status was retried.') + - if defined?(commit_sha) && commit_sha %td = link_to generic_commit_status.short_sha, namespace_project_commit_path(generic_commit_status.project.namespace, generic_commit_status.project, generic_commit_status.sha), class: "monospace" @@ -37,11 +40,13 @@ %td = generic_commit_status.name - .pull-right - - if generic_commit_status.tags.any? - - generic_commit_status.tags.each do |tag| - %span.label.label-primary - = tag + %td + - if generic_commit_status.tags.any? + - generic_commit_status.tags.each do |tag| + %span.label.label-primary + = tag + - if defined?(retried) && retried + %span.label.label-warning retried %td.duration - if generic_commit_status.duration diff --git a/app/views/projects/graphs/_head.html.haml b/app/views/projects/graphs/_head.html.haml index 79a56647c5..8becaea246 100644 --- a/app/views/projects/graphs/_head.html.haml +++ b/app/views/projects/graphs/_head.html.haml @@ -1,3 +1,4 @@ +- page_specific_javascripts asset_path("graphs/application.js") %ul.nav-links = nav_link(action: :show) do = link_to 'Contributors', namespace_project_graph_path diff --git a/app/views/projects/graphs/_header_title.html.haml b/app/views/projects/graphs/_header_title.html.haml deleted file mode 100644 index 1e2f61cd22..0000000000 --- a/app/views/projects/graphs/_header_title.html.haml +++ /dev/null @@ -1 +0,0 @@ -- header_title project_title(@project, "Graphs", namespace_project_graph_path(@project.namespace, @project, current_ref)) diff --git a/app/views/projects/graphs/ci.html.haml b/app/views/projects/graphs/ci.html.haml index 9f05be9982..19ccc125ea 100644 --- a/app/views/projects/graphs/ci.html.haml +++ b/app/views/projects/graphs/ci.html.haml @@ -1,5 +1,4 @@ - page_title "Continuous Integration", "Graphs" -= render "header_title" = render 'head' .row-content-block.append-bottom-default .oneline diff --git a/app/views/projects/graphs/commits.html.haml b/app/views/projects/graphs/commits.html.haml index da9f648cc9..d9b2fb6c06 100644 --- a/app/views/projects/graphs/commits.html.haml +++ b/app/views/projects/graphs/commits.html.haml @@ -1,5 +1,4 @@ - page_title "Commits", "Graphs" -= render "header_title" = render 'head' .row-content-block.append-bottom-default diff --git a/app/views/projects/graphs/languages.html.haml b/app/views/projects/graphs/languages.html.haml index ebecab1dbf..249c16f470 100644 --- a/app/views/projects/graphs/languages.html.haml +++ b/app/views/projects/graphs/languages.html.haml @@ -1,5 +1,4 @@ - page_title "Languages", "Graphs" -= render "header_title" = render 'head' .row-content-block.append-bottom-default diff --git a/app/views/projects/graphs/show.html.haml b/app/views/projects/graphs/show.html.haml index ad4a932d39..33970e7b90 100644 --- a/app/views/projects/graphs/show.html.haml +++ b/app/views/projects/graphs/show.html.haml @@ -1,5 +1,4 @@ - page_title "Contributors", "Graphs" -= render "header_title" = render 'head' .row-content-block.append-bottom-default @@ -19,7 +18,7 @@ .header.clearfix %h3#date_header.page-title %p.light - Commits to #{@ref}, excluding merge commits. Limited by 6,000 commits + Commits to #{@ref}, excluding merge commits. Limited to 6,000 commits. %input#brush_change{:type => "hidden"} .graphs #contributors-master diff --git a/app/views/projects/hooks/_project_hook.html.haml b/app/views/projects/hooks/_project_hook.html.haml index 62eba5888a..8151187d49 100644 --- a/app/views/projects/hooks/_project_hook.html.haml +++ b/app/views/projects/hooks/_project_hook.html.haml @@ -3,7 +3,7 @@ .col-md-8.col-lg-7 %strong.light-header= hook.url %div - - %w(push_events tag_push_events issues_events note_events merge_requests_events build_events).each do |trigger| + - %w(push_events tag_push_events issues_events note_events merge_requests_events build_events wiki_page_events).each do |trigger| - if hook.send(trigger) %span.label.label-gray.deploy-project-label= trigger.titleize .col-md-4.col-lg-5.text-right-lg.prepend-top-5 diff --git a/app/views/projects/hooks/index.html.haml b/app/views/projects/hooks/index.html.haml index 36c1d69f06..917a0b805b 100644 --- a/app/views/projects/hooks/index.html.haml +++ b/app/views/projects/hooks/index.html.haml @@ -64,6 +64,13 @@ Build events %p.light This url will be triggered when the build status changes + %div + = f.check_box :wiki_page_events, class: 'pull-left' + .prepend-left-20 + = f.label :wiki_page_events, class: 'label-light append-bottom-0' do + Wiki Page events + %p.light + This url will be triggered when a wiki page is created/updated .form-group = f.label :enable_ssl_verification, "SSL verification", class: "label-light" %div @@ -80,5 +87,5 @@ - @hooks.each do |hook| = render "project_hook", hook: hook - else - %p.profile-settings-message.text-center.append-bottom-0 + %p.settings-message.text-center.append-bottom-0 No webhooks found, add one in the form above. diff --git a/app/views/projects/issues/_header_title.html.haml b/app/views/projects/issues/_header_title.html.haml deleted file mode 100644 index 99f03549c4..0000000000 --- a/app/views/projects/issues/_header_title.html.haml +++ /dev/null @@ -1 +0,0 @@ -- header_title project_title(@project, "Issues", namespace_project_issues_path(@project.namespace, @project)) diff --git a/app/views/projects/issues/_issue.html.haml b/app/views/projects/issues/_issue.html.haml index 9ad86ed71c..78f6415060 100644 --- a/app/views/projects/issues/_issue.html.haml +++ b/app/views/projects/issues/_issue.html.haml @@ -6,7 +6,7 @@ .issue-title.title %span.issue-title-text = confidential_icon(issue) - = link_to_gfm issue.title, issue_path(issue) + = link_to issue.title, issue_path(issue) %ul.controls - if issue.closed? %li @@ -28,16 +28,10 @@ = downvotes - note_count = issue.notes.user.nonawards.count - - if note_count > 0 - %li - = link_to issue_path(issue) + "#notes" do - = icon('comments') - = note_count - - else - %li - = link_to issue_path(issue) + "#notes", class: "issue-no-comments" do - = icon('comments') - = note_count + %li + = link_to issue_path(issue, anchor: 'notes'), class: ('issue-no-comments' if note_count.zero?) do + = icon('comments') + = note_count .issue-info #{issue.to_reference} · diff --git a/app/views/projects/issues/_merge_requests.html.haml b/app/views/projects/issues/_merge_requests.html.haml index d6b38b327f..2f9dc867d0 100644 --- a/app/views/projects/issues/_merge_requests.html.haml +++ b/app/views/projects/issues/_merge_requests.html.haml @@ -7,7 +7,7 @@ %li %span.merge-request-ci-status - if merge_request.ci_commit - = render_ci_status(merge_request.ci_commit) + = render_pipeline_status(merge_request.ci_commit) - elsif has_any_ci = icon('blank fw') %span.merge-request-id @@ -24,5 +24,8 @@ MERGED - elsif merge_request.closed? CLOSED - - if @closed_by_merge_requests.present? + %li = render partial: 'projects/issues/closed_by_box', locals: {merge_request_count: @merge_requests.count} + - if @closed_by_merge_requests.present? + %li + = render partial: 'projects/issues/closed_by_box', locals: {merge_request_count: @merge_requests.count} diff --git a/app/views/projects/issues/_related_branches.html.haml b/app/views/projects/issues/_related_branches.html.haml index bdfa0c7009..5f9d291998 100644 --- a/app/views/projects/issues/_related_branches.html.haml +++ b/app/views/projects/issues/_related_branches.html.haml @@ -8,7 +8,7 @@ - ci_commit = @project.ci_commit(sha, branch) if sha - if ci_commit %span.related-branch-ci-status - = render_ci_status(ci_commit) + = render_pipeline_status(ci_commit) %span.related-branch-info %strong = link_to namespace_project_compare_path(@project.namespace, @project, from: @project.default_branch, to: branch), class: "label-branch" do diff --git a/app/views/projects/issues/edit.html.haml b/app/views/projects/issues/edit.html.haml index 20216297d2..7cf1923456 100644 --- a/app/views/projects/issues/edit.html.haml +++ b/app/views/projects/issues/edit.html.haml @@ -1,5 +1,4 @@ - page_title "Edit", "#{@issue.title} (##{@issue.iid})", "Issues" -= render "header_title" %h3.page-title Edit Issue ##{@issue.iid} diff --git a/app/views/projects/issues/index.atom.builder b/app/views/projects/issues/index.atom.builder index ee8a941465..7ad7c9c87e 100644 --- a/app/views/projects/issues/index.atom.builder +++ b/app/views/projects/issues/index.atom.builder @@ -6,7 +6,5 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear xml.id namespace_project_issues_url(@project.namespace, @project) xml.updated @issues.first.created_at.xmlschema if @issues.any? - @issues.each do |issue| - issue_to_atom(xml, issue) - end + xml << render(partial: 'issues/issue', collection: @issues) if @issues.any? end diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml index efa7642b2d..19a6f4a91f 100644 --- a/app/views/projects/issues/index.html.haml +++ b/app/views/projects/issues/index.html.haml @@ -1,5 +1,4 @@ - page_title "Issues" -= render "header_title" = content_for :meta_tags do - if current_user diff --git a/app/views/projects/issues/new.html.haml b/app/views/projects/issues/new.html.haml index b317a0c1cf..e8aae0f47e 100644 --- a/app/views/projects/issues/new.html.haml +++ b/app/views/projects/issues/new.html.haml @@ -1,5 +1,4 @@ - page_title "New Issue" -= render "header_title" %h3.page-title New Issue diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index bde80bbb54..f3b0469b7d 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -1,7 +1,6 @@ - page_title "#{@issue.title} (##{@issue.iid})", "Issues" - page_description @issue.description - page_card_attributes @issue.card_attributes -- header_title project_title(@project, "Issues", namespace_project_issues_path(@project.namespace, @project)) .clearfix.detail-page-header .issuable-header @@ -53,12 +52,12 @@ .issue-details.issuable-details .detail-page-description.content-block %h2.title - = markdown escape_once(@issue.title), pipeline: :single_line + = markdown escape_once(@issue.title), pipeline: :single_line, author: @issue.author - if @issue.description.present? .description{ class: can?(current_user, :update_issue, @issue) ? 'js-task-list-container' : '' } .wiki = preserve do - = markdown(@issue.description, cache_key: [@issue, "description"]) + = markdown(@issue.description, cache_key: [@issue, "description"], author: @issue.author) %textarea.hidden.js-task-list-field = @issue.description = edited_time_ago_with_tooltip(@issue, placement: 'bottom', html_class: 'issue_edited_ago') diff --git a/app/views/projects/labels/_header_title.html.haml b/app/views/projects/labels/_header_title.html.haml deleted file mode 100644 index abe28da483..0000000000 --- a/app/views/projects/labels/_header_title.html.haml +++ /dev/null @@ -1 +0,0 @@ -- header_title project_title(@project, "Labels", namespace_project_labels_path(@project.namespace, @project)) diff --git a/app/views/projects/labels/edit.html.haml b/app/views/projects/labels/edit.html.haml index 675a805e12..6901ba13ab 100644 --- a/app/views/projects/labels/edit.html.haml +++ b/app/views/projects/labels/edit.html.haml @@ -1,5 +1,4 @@ - page_title "Edit", @label.name, "Labels" -= render "header_title" %h3.page-title Edit Label diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml index cc41130a9d..2557d1a4d5 100644 --- a/app/views/projects/labels/index.html.haml +++ b/app/views/projects/labels/index.html.haml @@ -1,5 +1,4 @@ - page_title "Labels" -= render "header_title" .top-area .nav-text @@ -18,6 +17,6 @@ - else .nothing-here-block - if can? current_user, :admin_label, @project - Create first label or #{link_to 'generate', generate_namespace_project_labels_path(@project.namespace, @project), method: :post} default set of labels + Create a label or #{link_to 'generate a default set of labels', generate_namespace_project_labels_path(@project.namespace, @project), method: :post}. - else No labels created diff --git a/app/views/projects/labels/new.html.haml b/app/views/projects/labels/new.html.haml index e20fd7d689..49ddf90161 100644 --- a/app/views/projects/labels/new.html.haml +++ b/app/views/projects/labels/new.html.haml @@ -1,5 +1,4 @@ - page_title "New Label" -= render "header_title" %h3.page-title New Label diff --git a/app/views/projects/merge_requests/_header_title.html.haml b/app/views/projects/merge_requests/_header_title.html.haml deleted file mode 100644 index 669a9b06bd..0000000000 --- a/app/views/projects/merge_requests/_header_title.html.haml +++ /dev/null @@ -1 +0,0 @@ -- header_title project_title(@project, "Merge Requests", namespace_project_merge_requests_path(@project.namespace, @project)) diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml index e740fe8c84..c02f94490a 100644 --- a/app/views/projects/merge_requests/_merge_request.html.haml +++ b/app/views/projects/merge_requests/_merge_request.html.haml @@ -1,7 +1,7 @@ %li{ class: mr_css_classes(merge_request) } .merge-request-title.title %span.merge-request-title-text - = link_to_gfm merge_request.title, merge_request_path(merge_request) + = link_to merge_request.title, merge_request_path(merge_request) %ul.controls - if merge_request.merged? %li @@ -13,7 +13,7 @@ - if merge_request.ci_commit %li - = render_ci_status(merge_request.ci_commit) + = render_pipeline_status(merge_request.ci_commit) - if merge_request.open? && merge_request.broken? %li @@ -36,16 +36,10 @@ = downvotes - note_count = merge_request.mr_and_commit_notes.user.nonawards.count - - if note_count > 0 - %li - = link_to merge_request_path(merge_request) + "#notes" do - = icon('comments') - = note_count - - else - %li - = link_to merge_request_path(merge_request) + "#notes", class: "merge-request-no-comments" do - = icon('comments') - = note_count + %li + = link_to merge_request_path(merge_request, anchor: 'notes'), class: ('merge-request-no-comments' if note_count.zero?) do + = icon('comments') + = note_count .merge-request-info #{merge_request.to_reference} · diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index 290753d57c..7af227129e 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -1,7 +1,6 @@ - page_title "#{@merge_request.title} (#{@merge_request.to_reference})", "Merge Requests" - page_description @merge_request.description - page_card_attributes @merge_request.card_attributes -- header_title project_title(@project, "Merge Requests", namespace_project_merge_requests_path(@project.namespace, @project)) - if diff_view == 'parallel' - fluid_layout true diff --git a/app/views/projects/merge_requests/dropdowns/_branch.html.haml b/app/views/projects/merge_requests/dropdowns/_branch.html.haml index ba8d9a5835..a60c445aa5 100644 --- a/app/views/projects/merge_requests/dropdowns/_branch.html.haml +++ b/app/views/projects/merge_requests/dropdowns/_branch.html.haml @@ -1,5 +1,5 @@ %ul - branches.each do |branch| %li - %a{ href: '#', class: "#{('is-active' if selected == branch)}", data: { id: branch } } + %a{ href: '#', class: "#{('is-active' if selected == branch)}", title: branch, data: { id: branch } } = branch diff --git a/app/views/projects/merge_requests/edit.html.haml b/app/views/projects/merge_requests/edit.html.haml index b31ea5e532..03159f123f 100644 --- a/app/views/projects/merge_requests/edit.html.haml +++ b/app/views/projects/merge_requests/edit.html.haml @@ -1,5 +1,4 @@ - page_title "Edit", "#{@merge_request.title} (#{@merge_request.to_reference}", "Merge Requests" -= render "header_title" %h3.page-title Edit Merge Request #{@merge_request.to_reference} diff --git a/app/views/projects/merge_requests/index.html.haml b/app/views/projects/merge_requests/index.html.haml index e56a44e0a7..b517e874b0 100644 --- a/app/views/projects/merge_requests/index.html.haml +++ b/app/views/projects/merge_requests/index.html.haml @@ -1,5 +1,4 @@ - page_title "Merge Requests" -= render "header_title" = render 'projects/last_push' diff --git a/app/views/projects/merge_requests/invalid.html.haml b/app/views/projects/merge_requests/invalid.html.haml index f5bf16ef3a..a00d3128ff 100644 --- a/app/views/projects/merge_requests/invalid.html.haml +++ b/app/views/projects/merge_requests/invalid.html.haml @@ -1,5 +1,4 @@ - page_title "#{@merge_request.title} (#{@merge_request.to_reference}", "Merge Requests" -= render "header_title" .merge-request = render "projects/merge_requests/show/mr_title" diff --git a/app/views/projects/merge_requests/new.html.haml b/app/views/projects/merge_requests/new.html.haml index d259968030..2e798ce780 100644 --- a/app/views/projects/merge_requests/new.html.haml +++ b/app/views/projects/merge_requests/new.html.haml @@ -1,5 +1,4 @@ - page_title "New Merge Request" -= render "header_title" - if @merge_request.can_be_created && !params[:change_branches] = render 'new_submit' diff --git a/app/views/projects/merge_requests/show/_mr_box.html.haml b/app/views/projects/merge_requests/show/_mr_box.html.haml index a23bd8d18d..ebf18f6ac8 100644 --- a/app/views/projects/merge_requests/show/_mr_box.html.haml +++ b/app/views/projects/merge_requests/show/_mr_box.html.haml @@ -1,13 +1,13 @@ .detail-page-description.content-block %h2.title - = markdown escape_once(@merge_request.title), pipeline: :single_line + = markdown escape_once(@merge_request.title), pipeline: :single_line, author: @merge_request.author %div - if @merge_request.description.present? .description{class: can?(current_user, :update_merge_request, @merge_request) ? 'js-task-list-container' : ''} .wiki = preserve do - = markdown(@merge_request.description, cache_key: [@merge_request, "description"]) + = markdown(@merge_request.description, cache_key: [@merge_request, "description"], author: @merge_request.author) %textarea.hidden.js-task-list-field = @merge_request.description diff --git a/app/views/projects/merge_requests/widget/_open.html.haml b/app/views/projects/merge_requests/widget/_open.html.haml index 55dbae598d..13359abede 100644 --- a/app/views/projects/merge_requests/widget/_open.html.haml +++ b/app/views/projects/merge_requests/widget/_open.html.haml @@ -26,4 +26,4 @@ %i.fa.fa-check Accepting this merge request will close #{"issue".pluralize(@closes_issues.size)} = succeed '.' do - != markdown issues_sentence(@closes_issues), pipeline: :gfm + != markdown issues_sentence(@closes_issues), pipeline: :gfm, author: @merge_request.author diff --git a/app/views/projects/merge_requests/widget/_show.html.haml b/app/views/projects/merge_requests/widget/_show.html.haml index 3c68d61c4b..b79508bdc3 100644 --- a/app/views/projects/merge_requests/widget/_show.html.haml +++ b/app/views/projects/merge_requests/widget/_show.html.haml @@ -13,7 +13,7 @@ check_enable: #{@merge_request.unchecked? ? "true" : "false"}, ci_status_url: "#{ci_status_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}", gitlab_icon: "#{asset_path 'gitlab_logo.png'}", - ci_status: "", + ci_status: "#{@merge_request.ci_commit ? @merge_request.ci_commit.status : ''}", ci_message: { normal: "Build {{status}} for \"{{title}}\"", preparing: "{{status}} build for \"{{title}}\"" @@ -26,4 +26,10 @@ builds_path: "#{builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}" }; + if (typeof merge_request_widget !== 'undefined') { + clearInterval(merge_request_widget.fetchBuildStatusInterval); + merge_request_widget.cancelPolling(); + merge_request_widget.clearEventListeners(); + } + merge_request_widget = new MergeRequestWidget(opts); diff --git a/app/views/projects/merge_requests/widget/open/_accept.html.haml b/app/views/projects/merge_requests/widget/open/_accept.html.haml index 807833741a..cfdf4edac3 100644 --- a/app/views/projects/merge_requests/widget/open/_accept.html.haml +++ b/app/views/projects/merge_requests/widget/open/_accept.html.haml @@ -25,7 +25,10 @@ - else = f.button class: "btn btn-create btn-grouped js-merge-button accept_merge_request #{status_class}" do Accept Merge Request - - if @merge_request.can_remove_source_branch?(current_user) + - if @merge_request.force_remove_source_branch? + .accept-control + The source branch will be removed. + - elsif @merge_request.can_remove_source_branch?(current_user) .accept-control.checkbox = label_tag :should_remove_source_branch, class: "remove_source_checkbox" do = check_box_tag :should_remove_source_branch diff --git a/app/views/projects/merge_requests/widget/open/_merge_when_build_succeeds.html.haml b/app/views/projects/merge_requests/widget/open/_merge_when_build_succeeds.html.haml index 2168294c68..b83ddcab3a 100644 --- a/app/views/projects/merge_requests/widget/open/_merge_when_build_succeeds.html.haml +++ b/app/views/projects/merge_requests/widget/open/_merge_when_build_succeeds.html.haml @@ -2,17 +2,16 @@ Set by #{link_to_member(@project, @merge_request.merge_user, avatar: true)} to be merged automatically when the build succeeds. %div - - should_remove_source_branch = @merge_request.merge_params["should_remove_source_branch"].present? %p = succeed '.' do The changes will be merged into %span.label-branch= @merge_request.target_branch - - if should_remove_source_branch + - if @merge_request.remove_source_branch? The source branch will be removed. - else The source branch will not be removed. - - remove_source_branch_button = @merge_request.can_remove_source_branch?(current_user) && !should_remove_source_branch && @merge_request.merge_user == current_user + - remove_source_branch_button = !@merge_request.remove_source_branch? && @merge_request.can_remove_source_branch?(current_user) && @merge_request.merge_user == current_user - user_can_cancel_automatic_merge = @merge_request.can_cancel_merge_when_build_succeeds?(current_user) - if remove_source_branch_button || user_can_cancel_automatic_merge .clearfix.prepend-top-10 diff --git a/app/views/projects/merge_requests/widget/open/_not_allowed.html.haml b/app/views/projects/merge_requests/widget/open/_not_allowed.html.haml index a8145558ca..57ce195902 100644 --- a/app/views/projects/merge_requests/widget/open/_not_allowed.html.haml +++ b/app/views/projects/merge_requests/widget/open/_not_allowed.html.haml @@ -1,4 +1,6 @@ -%h4 +%h4 Ready to be merged automatically %p Ask someone with write access to this repository to merge this request. + - if @merge_request.force_remove_source_branch? + The source branch will be removed. diff --git a/app/views/projects/milestones/_header_title.html.haml b/app/views/projects/milestones/_header_title.html.haml deleted file mode 100644 index 5f4b6982a6..0000000000 --- a/app/views/projects/milestones/_header_title.html.haml +++ /dev/null @@ -1 +0,0 @@ -- header_title project_title(@project, "Milestones", namespace_project_milestones_path(@project.namespace, @project)) diff --git a/app/views/projects/milestones/edit.html.haml b/app/views/projects/milestones/edit.html.haml index 43f8863163..be682226ab 100644 --- a/app/views/projects/milestones/edit.html.haml +++ b/app/views/projects/milestones/edit.html.haml @@ -1,5 +1,4 @@ - page_title "Edit", @milestone.title, "Milestones" -= render "header_title" %h3.page-title Edit Milestone ##{@milestone.iid} diff --git a/app/views/projects/milestones/index.html.haml b/app/views/projects/milestones/index.html.haml index abe567af1d..e6133b22f9 100644 --- a/app/views/projects/milestones/index.html.haml +++ b/app/views/projects/milestones/index.html.haml @@ -1,6 +1,4 @@ - page_title "Milestones" -= render "header_title" - .top-area = render 'shared/milestones_filter' diff --git a/app/views/projects/milestones/new.html.haml b/app/views/projects/milestones/new.html.haml index 0d016f7831..7f372b4169 100644 --- a/app/views/projects/milestones/new.html.haml +++ b/app/views/projects/milestones/new.html.haml @@ -1,5 +1,4 @@ - page_title "New Milestone" -= render "header_title" %h3.page-title New Milestone diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml index 6ec8466015..19944e3e02 100644 --- a/app/views/projects/milestones/show.html.haml +++ b/app/views/projects/milestones/show.html.haml @@ -1,8 +1,6 @@ - page_title @milestone.title, "Milestones" - page_description @milestone.description -= render "header_title" - .detail-page-header .status-box{ class: status_box_class(@milestone) } - if @milestone.closed? diff --git a/app/views/projects/network/show.html.haml b/app/views/projects/network/show.html.haml index 8065663ca2..326180ebe4 100644 --- a/app/views/projects/network/show.html.haml +++ b/app/views/projects/network/show.html.haml @@ -1,5 +1,4 @@ - page_title "Network", @ref -= render "projects/commits/header_title" = render "projects/commits/head" = render "head" .project-network diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index a4c6094c69..f9ac16b32f 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -1,5 +1,5 @@ - page_title 'New Project' -- header_title "Projects", root_path +- header_title "Projects", dashboard_projects_path %h3.page-title New Project diff --git a/app/views/projects/notes/_diff_notes_with_reply.html.haml b/app/views/projects/notes/_diff_notes_with_reply.html.haml index 39be072855..8144c1ba49 100644 --- a/app/views/projects/notes/_diff_notes_with_reply.html.haml +++ b/app/views/projects/notes/_diff_notes_with_reply.html.haml @@ -1,10 +1,8 @@ -- note = notes.first # example note --# Check if line want not changed since comment was left -- if !defined?(line) || line == note.diff_line - %tr.notes_holder - %td.notes_line{ colspan: 2 } - %td.notes_content - %ul.notes{ data: { discussion_id: note.discussion_id } } - = render notes - .discussion-reply-holder - = link_to_reply_diff(note) +- note = notes.first +%tr.notes_holder + %td.notes_line{ colspan: 2 } + %td.notes_content + %ul.notes{ data: { discussion_id: note.discussion_id } } + = render partial: "projects/notes/note", collection: notes, as: :note + .discussion-reply-holder + = link_to_reply_discussion(note) diff --git a/app/views/projects/notes/_diff_notes_with_reply_parallel.html.haml b/app/views/projects/notes/_diff_notes_with_reply_parallel.html.haml index f8aa5e2fa7..45986b0d1e 100644 --- a/app/views/projects/notes/_diff_notes_with_reply_parallel.html.haml +++ b/app/views/projects/notes/_diff_notes_with_reply_parallel.html.haml @@ -1,27 +1,27 @@ -- note1 = notes_left.present? ? notes_left.first : nil -- note2 = notes_right.present? ? notes_right.first : nil +- note_left = notes_left.present? ? notes_left.first : nil +- note_right = notes_right.present? ? notes_right.first : nil %tr.notes_holder - - if note1 + - if note_left %td.notes_line.old %td.notes_content.parallel.old - %ul.notes{ data: { discussion_id: note1.discussion_id } } - = render notes_left + %ul.notes{ data: { discussion_id: note_left.discussion_id } } + = render partial: "projects/notes/note", collection: notes_left, as: :note .discussion-reply-holder - = link_to_reply_diff(note1, 'old') + = link_to_reply_discussion(note_left, 'old') - else %td.notes_line.old= "" %td.notes_content.parallel.old= "" - - if note2 + - if note_right %td.notes_line.new %td.notes_content.parallel.new - %ul.notes{ data: { discussion_id: note2.discussion_id } } - = render notes_right + %ul.notes{ data: { discussion_id: note_right.discussion_id } } + = render partial: "projects/notes/note", collection: notes_right, as: :note .discussion-reply-holder - = link_to_reply_diff(note2, 'new') + = link_to_reply_discussion(note_right, 'new') - else %td.notes_line.new= "" %td.notes_content.parallel.new= "" diff --git a/app/views/projects/notes/_discussion.html.haml b/app/views/projects/notes/_discussion.html.haml index 572b00a38c..7869d6413d 100644 --- a/app/views/projects/notes/_discussion.html.haml +++ b/app/views/projects/notes/_discussion.html.haml @@ -1,13 +1,46 @@ - note = discussion_notes.first +- expanded = !note.diff_note? || note.active? %li.note.note-discussion.timeline-entry .timeline-entry-inner .timeline-icon = link_to user_path(note.author) do - = image_tag avatar_icon(note.author_email), class: "avatar s40" + = image_tag avatar_icon(note.author), class: "avatar s40" .timeline-content - - if note.for_merge_request? - - (active_notes, outdated_notes) = discussion_notes.partition(&:active?) - = render "projects/notes/discussions/active", discussion_notes: active_notes if active_notes.length > 0 - = render "projects/notes/discussions/outdated", discussion_notes: outdated_notes if outdated_notes.length > 0 - - else - = render "projects/notes/discussions/commit", discussion_notes: discussion_notes + .discussion.js-toggle-container{ class: note.discussion_id } + .discussion-header + = link_to_member(@project, note.author, avatar: false) + + .inline.discussion-headline-light + = note.author.to_reference + started a discussion on + + - if note.for_commit? + - commit = note.noteable + - if commit + commit + = link_to commit.short_id, namespace_project_commit_path(note.project.namespace, note.project, note.noteable, anchor: note.line_code), class: 'monospace' + - else + a deleted commit + - else + - if note.active? + = link_to diffs_namespace_project_merge_request_path(note.project.namespace, note.project, note.noteable, anchor: note.line_code) do + the diff + - else + an outdated diff + + = time_ago_with_tooltip(note.created_at, placement: "bottom", html_class: "note-created-ago") + + .discussion-actions + = link_to "#", class: "note-action-button discussion-toggle-button js-toggle-button" do + - if expanded + = icon("chevron-up") + - else + = icon("chevron-down") + + Toggle discussion + + .discussion-body.js-toggle-content{ class: ("hide" unless expanded) } + - if note.diff_note? + = render "projects/notes/discussions/diff_with_notes", discussion_notes: discussion_notes + - else + = render "projects/notes/discussions/notes", discussion_notes: discussion_notes diff --git a/app/views/projects/notes/_form.html.haml b/app/views/projects/notes/_form.html.haml index d0ac380f21..67ed38a7b2 100644 --- a/app/views/projects/notes/_form.html.haml +++ b/app/views/projects/notes/_form.html.haml @@ -6,6 +6,7 @@ = f.hidden_field :line_code = f.hidden_field :noteable_id = f.hidden_field :noteable_type + = f.hidden_field :type = render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true } do = render 'projects/zen', f: f, attr: :note, classes: 'note-textarea js-note-text', placeholder: "Write a comment or drag your files here..." diff --git a/app/views/projects/notes/_note.html.haml b/app/views/projects/notes/_note.html.haml index aeb7c1d5ee..f1045bbd8c 100644 --- a/app/views/projects/notes/_note.html.haml +++ b/app/views/projects/notes/_note.html.haml @@ -1,5 +1,8 @@ +- return unless note.author +- return if note.cross_reference_not_visible_for?(current_user) + - note_editable = note_editable?(note) -%li.timeline-entry{ id: dom_id(note), class: [dom_class(note), "note-row-#{note.id}", ('system-note' if note.system)], data: {author_id: note.author.id, editable: note_editable} } +%li.timeline-entry{ id: dom_id(note), class: ["note", "note-row-#{note.id}", ('system-note' if note.system)], data: {author_id: note.author.id, editable: note_editable} } .timeline-entry-inner .timeline-icon %a{href: user_path(note.author)} @@ -8,8 +11,8 @@ .note-header = link_to_member(note.project, note.author, avatar: false) .inline.note-headline-light - = "#{note.author.to_reference}" - - if !note.system + = note.author.to_reference + - unless note.system commented %a{ href: "##{dom_id(note)}" } = time_ago_with_tooltip(note.created_at, placement: 'bottom', html_class: 'note-created-ago') @@ -26,7 +29,7 @@ .note-body{class: note_editable ? 'js-task-list-container' : ''} .note-text = preserve do - = markdown(note.note, pipeline: :note, cache_key: [note, "note"]) + = markdown(note.note, pipeline: :note, cache_key: [note, "note"], author: note.author) - if note_editable = render 'projects/notes/edit_form', note: note = edited_time_ago_with_tooltip(note, placement: 'bottom', html_class: 'note_edited_ago', include_author: true) diff --git a/app/views/projects/notes/_notes.html.haml b/app/views/projects/notes/_notes.html.haml index 62db86fb18..ebf7e8a9cb 100644 --- a/app/views/projects/notes/_notes.html.haml +++ b/app/views/projects/notes/_notes.html.haml @@ -2,14 +2,9 @@ - @discussions.each do |discussion_notes| - note = discussion_notes.first - if note_for_main_target?(note) - - next if note.cross_reference_not_visible_for?(current_user) - - = render discussion_notes + = render partial: "projects/notes/note", object: note, as: :note - else = render 'projects/notes/discussion', discussion_notes: discussion_notes - else - @notes.each do |note| - - next unless note.author - - next if note.cross_reference_not_visible_for?(current_user) - - = render note + = render partial: "projects/notes/note", object: note, as: :note diff --git a/app/views/projects/notes/discussions/_active.html.haml b/app/views/projects/notes/discussions/_active.html.haml deleted file mode 100644 index 0ea8862a68..0000000000 --- a/app/views/projects/notes/discussions/_active.html.haml +++ /dev/null @@ -1,16 +0,0 @@ -- note = discussion_notes.first -.discussion.js-toggle-container{ class: note.discussion_id } - .discussion-header - = link_to_member(@project, note.author, avatar: false) - .inline.discussion-headline-light - = "#{note.author.to_reference} started a discussion" - = link_to diffs_namespace_project_merge_request_path(note.project.namespace, note.project, note.noteable, anchor: note.line_code) do - on the diff - = time_ago_with_tooltip(note.created_at, placement: "bottom", html_class: "discussion_updated_ago") - .discussion-actions - = link_to "#", class: "discussion-action-button discussion-toggle-button js-toggle-button" do - %i.fa.fa-chevron-up - Show/hide discussion - - .discussion-body.js-toggle-content - = render "projects/notes/discussions/diff", discussion_notes: discussion_notes, note: note diff --git a/app/views/projects/notes/discussions/_commit.html.haml b/app/views/projects/notes/discussions/_commit.html.haml deleted file mode 100644 index 2a2ead58ee..0000000000 --- a/app/views/projects/notes/discussions/_commit.html.haml +++ /dev/null @@ -1,25 +0,0 @@ -- note = discussion_notes.first -- commit = note.noteable -- commit_description = commit ? 'commit' : 'a deleted commit' -.discussion.js-toggle-container{ class: note.discussion_id } - .discussion-header - = link_to_member(@project, note.author, avatar: false) - .inline.discussion-headline-light - = "#{note.author.to_reference} started a discussion on #{commit_description}" - - if commit - = link_to(commit.short_id, namespace_project_commit_path(note.project.namespace, note.project, note.noteable), class: 'monospace') - = time_ago_with_tooltip(note.created_at, placement: "bottom", html_class: "discussion_updated_ago") - .discussion-actions - = link_to "#", class: "note-action-button discussion-toggle-button js-toggle-button" do - %i.fa.fa-chevron-up - Show/hide discussion - .discussion-body.js-toggle-content - - if note.for_diff_line? - = render "projects/notes/discussions/diff", discussion_notes: discussion_notes, note: note - - else - .panel.panel-default - .notes{ data: { discussion_id: discussion_notes.first.discussion_id } } - %ul.notes.timeline - = render discussion_notes - .discussion-reply-holder - = link_to_reply_diff(discussion_notes.first) diff --git a/app/views/projects/notes/discussions/_diff.html.haml b/app/views/projects/notes/discussions/_diff.html.haml deleted file mode 100644 index d46aab000c..0000000000 --- a/app/views/projects/notes/discussions/_diff.html.haml +++ /dev/null @@ -1,28 +0,0 @@ -- diff = note.diff -- if diff - .diff-file - .diff-header - %span - - if diff.deleted_file - = diff.old_path - - else - = diff.new_path - - if diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode - %span.file-mode= "#{diff.a_mode} → #{diff.b_mode}" - .diff-content.code.js-syntax-highlight - %table - - note.truncated_diff_lines.each do |line| - - type = line.type - - line_code = generate_line_code(note.file_path, line) - %tr.line_holder{ id: line_code, class: "#{type}" } - - if type == "match" - %td.old_line.diff-line-num= "..." - %td.new_line.diff-line-num= "..." - %td.line_content.match= line.text - - else - %td.old_line.diff-line-num{ data: { linenumber: type == "new" ? " ".html_safe : line.old_pos } } - %td.new_line.diff-line-num{ data: { linenumber: type == "old" ? " ".html_safe : line.new_pos } } - %td.line_content{ class: ['noteable_line', type, line_code], line_code: line_code }= diff_line_content(line.text, type) - - - if line_code == note.line_code - = render "projects/notes/diff_notes_with_reply", notes: discussion_notes diff --git a/app/views/projects/notes/discussions/_diff_with_notes.html.haml b/app/views/projects/notes/discussions/_diff_with_notes.html.haml new file mode 100644 index 0000000000..6401245bf7 --- /dev/null +++ b/app/views/projects/notes/discussions/_diff_with_notes.html.haml @@ -0,0 +1,30 @@ +- note = discussion_notes.first +- diff = note.diff +- return unless diff + +.diff-file + .diff-header + %span + - if diff.deleted_file + = diff.old_path + - else + = diff.new_path + - if diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode + %span.file-mode= "#{diff.a_mode} → #{diff.b_mode}" + .diff-content.code.js-syntax-highlight + %table + - note.truncated_diff_lines.each do |line| + - type = line.type + - line_code = generate_line_code(note.diff_file_path, line) + %tr.line_holder{ id: line_code, class: "#{type}" } + - if type == "match" + %td.old_line.diff-line-num= "..." + %td.new_line.diff-line-num= "..." + %td.line_content.match= line.text + - else + %td.old_line.diff-line-num{ data: { linenumber: type == "new" ? " ".html_safe : line.old_pos } } + %td.new_line.diff-line-num{ data: { linenumber: type == "old" ? " ".html_safe : line.new_pos } } + %td.line_content{ class: ['noteable_line', type, line_code], line_code: line_code }= diff_line_content(line.text, type) + + - if line_code == note.line_code + = render "projects/notes/diff_notes_with_reply", notes: discussion_notes diff --git a/app/views/projects/notes/discussions/_notes.html.haml b/app/views/projects/notes/discussions/_notes.html.haml new file mode 100644 index 0000000000..e598e3c7c6 --- /dev/null +++ b/app/views/projects/notes/discussions/_notes.html.haml @@ -0,0 +1,7 @@ +- note = discussion_notes.first +.panel.panel-default + .notes{ data: { discussion_id: note.discussion_id } } + %ul.notes.timeline + = render partial: "projects/notes/note", collection: discussion_notes, as: :note + .discussion-reply-holder + = link_to_reply_discussion(note) diff --git a/app/views/projects/notes/discussions/_outdated.html.haml b/app/views/projects/notes/discussions/_outdated.html.haml deleted file mode 100644 index 45141bcd1d..0000000000 --- a/app/views/projects/notes/discussions/_outdated.html.haml +++ /dev/null @@ -1,14 +0,0 @@ -- note = discussion_notes.first -.discussion.js-toggle-container{ class: note.discussion_id } - .discussion-header - = link_to_member(@project, note.author, avatar: false) - .inline.discussion-headline-light - = "#{note.author.to_reference} started a discussion" - on the outdated diff - = time_ago_with_tooltip(note.created_at, placement: "bottom", html_class: "discussion_updated_ago") - .discussion-actions - = link_to "#", class: "note-action-button discussion-toggle-button js-toggle-button" do - %i.fa.fa-chevron-down - Show/hide discussion - .discussion-body.js-toggle-content.hide - = render "projects/notes/discussions/diff", discussion_notes: discussion_notes, note: note diff --git a/app/views/projects/pipelines/_head.html.haml b/app/views/projects/pipelines/_head.html.haml new file mode 100644 index 0000000000..6e757df541 --- /dev/null +++ b/app/views/projects/pipelines/_head.html.haml @@ -0,0 +1,14 @@ +%ul.nav-links + - if project_nav_tab? :pipelines + = nav_link(controller: :pipelines) do + = link_to project_pipelines_path(@project), title: 'Pipelines', class: 'shortcuts-pipelines' do + %span + Pipelines + %span.badge.count.ci_counter= number_with_delimiter(@project.ci_commits.running_or_pending.count) + + - if project_nav_tab? :builds + = nav_link(controller: %w(builds)) do + = link_to project_builds_path(@project), title: 'Builds', class: 'shortcuts-builds' do + %span + Builds + %span.badge.count.builds_counter= number_with_delimiter(@project.running_or_pending_build_count) diff --git a/app/views/projects/pipelines/_info.html.haml b/app/views/projects/pipelines/_info.html.haml new file mode 100644 index 0000000000..8289aefcde --- /dev/null +++ b/app/views/projects/pipelines/_info.html.haml @@ -0,0 +1,37 @@ +%p +.commit-info-row + Pipeline + = link_to "##{@pipeline.id}", namespace_project_pipeline_path(@project.namespace, @project, @pipeline.id), class: "monospace" + with + = pluralize @pipeline.statuses.count(:id), "build" + - if @pipeline.ref + for + = link_to @pipeline.ref, namespace_project_commits_path(@project.namespace, @project, @pipeline.ref), class: "monospace" + - if @pipeline.duration + in + = time_interval_in_words @pipeline.duration + + .pull-right + = link_to namespace_project_pipeline_path(@project.namespace, @project, @pipeline), class: "ci-status ci-#{@pipeline.status}" do + = ci_icon_for_status(@pipeline.status) + = ci_label_for_status(@pipeline.status) + +- if @commit + .commit-info-row + %span.light Authored by + %strong + = commit_author_link(@commit, avatar: true, size: 24) + #{time_ago_with_tooltip(@commit.authored_date)} + +.commit-info-row + %span.light Commit + = link_to @pipeline.sha, namespace_project_commit_path(@project.namespace, @project, @pipeline.sha), class: "monospace" + = clipboard_button(clipboard_text: @pipeline.sha) + +- if @commit + .commit-box.content-block + %h3.commit-title + = markdown escape_once(@commit.title), pipeline: :single_line + - if @commit.description.present? + %pre.commit-description + = preserve(markdown(escape_once(@commit.description), pipeline: :single_line)) diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml new file mode 100644 index 0000000000..453767920b --- /dev/null +++ b/app/views/projects/pipelines/index.html.haml @@ -0,0 +1,58 @@ +- page_title "Pipelines" += render "projects/pipelines/head" + +.top-area + %ul.nav-links + %li{class: ('active' if @scope.nil?)} + = link_to project_pipelines_path(@project) do + All + %span.badge.js-totalbuilds-count + = number_with_delimiter(@pipelines_count) + + %li{class: ('active' if @scope == 'running')} + = link_to project_pipelines_path(@project, scope: :running) do + Running + %span.badge.js-running-count + = number_with_delimiter(@running_or_pending_count) + + %li{class: ('active' if @scope == 'branches')} + = link_to project_pipelines_path(@project, scope: :branches) do + Branches + + %li{class: ('active' if @scope == 'tags')} + = link_to project_pipelines_path(@project, scope: :tags) do + Tags + + .nav-controls + - if can? current_user, :create_pipeline, @project + = link_to new_namespace_project_pipeline_path(@project.namespace, @project), class: 'btn btn-create' do + = icon('plus') + New pipeline + + - unless @repository.gitlab_ci_yml + = link_to 'Get started with Pipelines', help_page_path('ci/quick_start', 'README'), class: 'btn btn-info' + + = link_to ci_lint_path, class: 'btn btn-default' do + = icon('wrench') + %span CI Lint + +%ul.content-list.pipelines + - stages = @pipelines.stages + - if @pipelines.blank? + %li + .nothing-here-block No pipelines to show + - else + .table-holder + %table.table.builds + %tbody + %th ID + %th Commit + - stages.each do |stage| + %th.stage + %span.has-tooltip{ title: "#{stage.titleize}" } + = stage.titleize.pluralize + %th Duration + %th + = render @pipelines, commit_sha: true, stage: true, allow_retry: true, stages: stages + + = paginate @pipelines, theme: 'gitlab' diff --git a/app/views/projects/pipelines/new.html.haml b/app/views/projects/pipelines/new.html.haml new file mode 100644 index 0000000000..5f4ec2e40c --- /dev/null +++ b/app/views/projects/pipelines/new.html.haml @@ -0,0 +1,21 @@ +- page_title "New Pipeline" + +%h3.page-title + New Pipeline +%hr + += form_for @pipeline, as: :pipeline, url: namespace_project_pipelines_path(@project.namespace, @project), html: { id: "new-pipeline-form", class: "form-horizontal js-new-pipeline-form js-requires-input" } do |f| + = form_errors(@pipeline) + .form-group + = f.label :ref, 'Create for', class: 'control-label' + .col-sm-10 + = f.text_field :ref, required: true, tabindex: 2, class: 'form-control' + .help-block Existing branch name, tag + .form-actions + = f.submit 'Create pipeline', class: 'btn btn-create', tabindex: 3 + = link_to 'Cancel', namespace_project_pipelines_path(@project.namespace, @project), class: 'btn btn-cancel' + +:javascript + var availableRefs = #{@project.repository.ref_names.to_json}; + + new NewBranchForm($('.js-new-pipeline-form'), availableRefs) diff --git a/app/views/projects/pipelines/show.html.haml b/app/views/projects/pipelines/show.html.haml new file mode 100644 index 0000000000..2aad560241 --- /dev/null +++ b/app/views/projects/pipelines/show.html.haml @@ -0,0 +1,8 @@ +- page_title "Pipeline" + +.prepend-top-default + - if @commit + = render "projects/pipelines/info" + %div.block-connector + += render "projects/commit/ci_commit", ci_commit: @pipeline diff --git a/app/views/projects/project_members/_header_title.html.haml b/app/views/projects/project_members/_header_title.html.haml deleted file mode 100644 index a31f0a37fa..0000000000 --- a/app/views/projects/project_members/_header_title.html.haml +++ /dev/null @@ -1 +0,0 @@ -- header_title project_title(@project, "Members", namespace_project_project_members_path(@project.namespace, @project)) diff --git a/app/views/projects/project_members/import.html.haml b/app/views/projects/project_members/import.html.haml index 189906498c..eef97107d7 100644 --- a/app/views/projects/project_members/import.html.haml +++ b/app/views/projects/project_members/import.html.haml @@ -1,5 +1,4 @@ - page_title "Import members" -= render "header_title" %h3.page-title Import members from another project diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml index ebcfc907eb..15dc064e7e 100644 --- a/app/views/projects/project_members/index.html.haml +++ b/app/views/projects/project_members/index.html.haml @@ -1,5 +1,4 @@ - page_title "Members" -= render "header_title" .project-members-page.prepend-top-default - if can?(current_user, :admin_project_member, @project) diff --git a/app/views/projects/protected_branches/_branches_list.html.haml b/app/views/projects/protected_branches/_branches_list.html.haml index b9e9dd8aae..565905cbe7 100644 --- a/app/views/projects/protected_branches/_branches_list.html.haml +++ b/app/views/projects/protected_branches/_branches_list.html.haml @@ -1,7 +1,7 @@ %h5.prepend-top-0 Already Protected (#{@branches.size}) - if @branches.empty? - %p.profile-settings-message.text-center + %p.settings-message.text-center No branches are protected, protect a branch with the form above. - else - can_admin_project = can?(current_user, :admin_project, @project) diff --git a/app/views/projects/releases/edit.html.haml b/app/views/projects/releases/edit.html.haml index 0d59cec322..835398b6f9 100644 --- a/app/views/projects/releases/edit.html.haml +++ b/app/views/projects/releases/edit.html.haml @@ -1,5 +1,4 @@ - page_title "Edit", @tag.name, "Tags" -= render "projects/commits/header_title" = render "projects/commits/head" .row-content-block diff --git a/app/views/projects/repositories/_feed.html.haml b/app/views/projects/repositories/_feed.html.haml index 6ca919f7f8..43a6fdfd10 100644 --- a/app/views/projects/repositories/_feed.html.haml +++ b/app/views/projects/repositories/_feed.html.haml @@ -12,7 +12,7 @@ = link_to namespace_project_commits_path(@project.namespace, @project, commit.id) do %code= commit.short_id = image_tag avatar_icon(commit.author_email), class: "", width: 16, alt: '' - = markdown escape_once(truncate(commit.title, length: 40)), pipeline: :single_line + = markdown escape_once(truncate(commit.title, length: 40)), pipeline: :single_line, author: commit.author %td %span.pull-right.cgray = time_ago_with_tooltip(commit.committed_date) diff --git a/app/views/projects/runners/_form.html.haml b/app/views/projects/runners/_form.html.haml new file mode 100644 index 0000000000..d62f5c8f13 --- /dev/null +++ b/app/views/projects/runners/_form.html.haml @@ -0,0 +1,32 @@ += form_for runner, url: runner_form_url, html: { class: 'form-horizontal' } do |f| + = form_errors(runner) + .form-group + = label :active, "Active", class: 'control-label' + .col-sm-10 + .checkbox + = f.check_box :active + %span.light Paused runners don't accept new builds + .form-group + = label :run_untagged, 'Run untagged jobs', class: 'control-label' + .col-sm-10 + .checkbox + = f.check_box :run_untagged + %span.light Indicates whether this runner can pick jobs without tags + .form-group + = label_tag :token, class: 'control-label' do + Token + .col-sm-10 + = f.text_field :token, class: 'form-control', readonly: true + .form-group + = label_tag :description, class: 'control-label' do + Description + .col-sm-10 + = f.text_field :description, class: 'form-control' + .form-group + = label_tag :tag_list, class: 'control-label' do + Tags + .col-sm-10 + = f.text_field :tag_list, value: runner.tag_list.to_s, class: 'form-control' + .help-block You can setup jobs to only use runners with specific tags + .form-actions + = f.submit 'Save changes', class: 'btn btn-save' diff --git a/app/views/projects/runners/_runner.html.haml b/app/views/projects/runners/_runner.html.haml index 47ec420189..96e2aac451 100644 --- a/app/views/projects/runners/_runner.html.haml +++ b/app/views/projects/runners/_runner.html.haml @@ -5,7 +5,7 @@ - if @runners.include?(runner) = link_to runner.short_sha, runner_path(runner) %small - =link_to edit_namespace_project_runner_path(@project.namespace, @project, runner) do + = link_to edit_namespace_project_runner_path(@project.namespace, @project, runner) do %i.fa.fa-edit.btn - else = runner.short_sha diff --git a/app/views/projects/runners/_specific_runners.html.haml b/app/views/projects/runners/_specific_runners.html.haml index 30cd1263a1..8ae9f0d95f 100644 --- a/app/views/projects/runners/_specific_runners.html.haml +++ b/app/views/projects/runners/_specific_runners.html.haml @@ -8,7 +8,7 @@ Install GitLab Runner software. Checkout the #{link_to 'GitLab Runner section', 'https://about.gitlab.com/gitlab-ci/#gitlab-runner', target: '_blank'} to install it %li - Specify following URL during runner setup: + Specify the following URL during runner setup: %code #{ci_root_url(only_path: false)} %li Use the following registration token during setup: diff --git a/app/views/projects/runners/edit.html.haml b/app/views/projects/runners/edit.html.haml index eba03028af..9570688865 100644 --- a/app/views/projects/runners/edit.html.haml +++ b/app/views/projects/runners/edit.html.haml @@ -1,29 +1,6 @@ - page_title "Edit", "#{@runner.description} ##{@runner.id}", "Runners" %h4 Runner ##{@runner.id} + %hr -= form_for @runner, url: runner_path(@runner), html: { class: 'form-horizontal' } do |f| - .form-group - = label :active, "Active", class: 'control-label' - .col-sm-10 - .checkbox - = f.check_box :active - %span.light Paused runners don't accept new builds - .form-group - = label_tag :token, class: 'control-label' do - Token - .col-sm-10 - = f.text_field :token, class: 'form-control', readonly: true - .form-group - = label_tag :description, class: 'control-label' do - Description - .col-sm-10 - = f.text_field :description, class: 'form-control' - .form-group - = label_tag :tag_list, class: 'control-label' do - Tags - .col-sm-10 - = f.text_field :tag_list, value: @runner.tag_list.to_s, class: 'form-control' - .help-block You can setup jobs to only use runners with specific tags - .form-actions - = f.submit 'Save changes', class: 'btn btn-save' + = render 'form', runner: @runner, runner_form_url: runner_path(@runner) diff --git a/app/views/projects/runners/show.html.haml b/app/views/projects/runners/show.html.haml index 5bf4c09ca2..f24e1b9144 100644 --- a/app/views/projects/runners/show.html.haml +++ b/app/views/projects/runners/show.html.haml @@ -17,50 +17,39 @@ %th Property Name %th Value %tr - %td - Tags + %td Active + %td= @runner.active? ? 'Yes' : 'No' + %tr + %td Can run untagged jobs + %td= @runner.run_untagged? ? 'Yes' : 'No' + %tr + %td Tags %td - @runner.tag_list.each do |tag| %span.label.label-primary = tag %tr - %td - Name - %td - = @runner.name + %td Name + %td= @runner.name %tr - %td - Version - %td - = @runner.version + %td Version + %td= @runner.version %tr - %td - Revision - %td - = @runner.revision + %td Revision + %td= @runner.revision %tr - %td - Platform - %td - = @runner.platform + %td Platform + %td= @runner.platform %tr - %td - Architecture - %td - = @runner.architecture + %td Architecture + %td= @runner.architecture %tr - %td - Description - %td - = @runner.description + %td Description + %td= @runner.description %tr - %td - Last contact + %td Last contact %td - if @runner.contacted_at #{time_ago_in_words(@runner.contacted_at)} ago - else Never - - - diff --git a/app/views/projects/services/_form.html.haml b/app/views/projects/services/_form.html.haml index 1b70880043..1f13ea28b4 100644 --- a/app/views/projects/services/_form.html.haml +++ b/app/views/projects/services/_form.html.haml @@ -1,18 +1,16 @@ -%h3.page-title - = @service.title - = boolean_to_icon @service.activated? +.row.prepend-top-default.append-bottom-default + .col-lg-3 + %h4.prepend-top-0 + = @service.title + = boolean_to_icon @service.activated? -%p= @service.description - -%hr - -= form_for(@service, as: :service, url: namespace_project_service_path(@project.namespace, @project, @service.to_param), method: :put, html: { class: 'form-horizontal' }) do |form| - = render 'shared/service_settings', form: form - - .form-actions - = form.submit 'Save changes', class: 'btn btn-save' -   - - if @service.valid? && @service.activated? - - disabled = @service.can_test? ? '':'disabled' - = link_to 'Test settings', test_namespace_project_service_path(@project.namespace, @project, @service.to_param), class: "btn #{disabled}" - = link_to "Cancel", namespace_project_services_path(@project.namespace, @project), class: "btn btn-cancel" + %p= @service.description + .col-lg-9 + = form_for(@service, as: :service, url: namespace_project_service_path(@project.namespace, @project, @service.to_param), method: :put, html: { class: 'form-horizontal' }) do |form| + = render 'shared/service_settings', form: form + = form.submit 'Save changes', class: 'btn btn-save' +   + - if @service.valid? && @service.activated? + - disabled = @service.can_test? ? '':'disabled' + = link_to 'Test settings', test_namespace_project_service_path(@project.namespace, @project, @service.to_param), class: "btn #{disabled}" + = link_to "Cancel", namespace_project_services_path(@project.namespace, @project), class: "btn btn-cancel" diff --git a/app/views/projects/services/index.html.haml b/app/views/projects/services/index.html.haml index c1356f6db0..4a33a5bc6f 100644 --- a/app/views/projects/services/index.html.haml +++ b/app/views/projects/services/index.html.haml @@ -1,24 +1,32 @@ - page_title "Services" -%h3.page-title Project services -%p.light Project services allow you to integrate GitLab with other applications -.table-holder - %table.table - %thead - %tr - %th - %th Service - %th Description - %th Last edit - - @services.sort_by(&:title).each do |service| - %tr - %td - = boolean_to_icon service.activated? - %td - = link_to edit_namespace_project_service_path(@project.namespace, @project, service.to_param) do - %strong= service.title - %td - = service.description - %td.light - = time_ago_in_words service.updated_at - ago +.row.prepend-top-default.append-bottom-default + .col-lg-3 + %h4.prepend-top-0 + Project services + %p Project services allow you to integrate GitLab with other applications + .col-lg-9 + %table.table + %colgroup + %col + %col + %col.hidden-xs + %col{ width: "120" } + %thead + %tr + %th + %th Service + %th.hidden-xs Description + %th Last edit + - @services.sort_by(&:title).each do |service| + %tr + %td + = boolean_to_icon service.activated? + %td + = link_to edit_namespace_project_service_path(@project.namespace, @project, service.to_param) do + %strong= service.title + %td.hidden-xs + = service.description + %td.light + = time_ago_in_words service.updated_at + ago diff --git a/app/views/projects/show.atom.builder b/app/views/projects/show.atom.builder index 9b3d3f069d..11310d5e1e 100644 --- a/app/views/projects/show.atom.builder +++ b/app/views/projects/show.atom.builder @@ -6,7 +6,5 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear xml.id namespace_project_url(@project.namespace, @project) xml.updated @events[0].updated_at.xmlschema if @events[0] - @events.each do |event| - event_to_atom(xml, event) - end + xml << render(@events) if @events.any? end diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index 74feb9e328..a19c7c406a 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -13,50 +13,50 @@ = render "home_panel" .project-stats.row-content-block.second-block - %ul.nav - %li - = link_to namespace_project_commits_path(@project.namespace, @project, current_ref) do - = pluralize(number_with_delimiter(@project.commit_count), 'commit') - %li - = link_to namespace_project_branches_path(@project.namespace, @project) do - = pluralize(number_with_delimiter(@repository.branch_names.count), 'branch') - %li - = link_to namespace_project_tags_path(@project.namespace, @project) do - = pluralize(number_with_delimiter(@repository.tag_names.count), 'tag') - - %li - = link_to project_files_path(@project) do - = repository_size - - - if default_project_view != 'readme' && @repository.readme + .container-fluid.container-limited + %ul.nav %li - = link_to 'Readme', readme_path(@project) - - - if @repository.changelog + = link_to project_files_path(@project) do + Files (#{repository_size}) %li - = link_to 'Changelog', changelog_path(@project) - - - if @repository.license_blob + = link_to namespace_project_commits_path(@project.namespace, @project, current_ref) do + #{'Commit'.pluralize(@project.commit_count)} (#{number_with_delimiter(@project.commit_count)}) %li - = link_to license_short_name(@project), license_path(@project) - - - if @repository.contribution_guide + = link_to namespace_project_branches_path(@project.namespace, @project) do + #{'Branch'.pluralize(@repository.branch_names.count)} (#{number_with_delimiter(@repository.branch_names.count)}) %li - = link_to 'Contribution guide', contribution_guide_path(@project) + = link_to namespace_project_tags_path(@project.namespace, @project) do + #{'Tag'.pluralize(@repository.tag_names.count)} (#{number_with_delimiter(@repository.tag_names.count)}) - - if current_user && can_push_branch?(@project, @project.default_branch) - - unless @repository.changelog - %li.missing - = link_to add_special_file_path(@project, file_name: 'CHANGELOG') do - Add Changelog - - unless @repository.license_blob - %li.missing - = link_to add_special_file_path(@project, file_name: 'LICENSE') do - Add License - - unless @repository.contribution_guide - %li.missing - = link_to add_special_file_path(@project, file_name: 'CONTRIBUTING.md', commit_message: 'Add contribution guide') do - Add Contribution guide + - if default_project_view != 'readme' && @repository.readme + %li + = link_to 'Readme', readme_path(@project) + + - if @repository.changelog + %li + = link_to 'Changelog', changelog_path(@project) + + - if @repository.license_blob + %li + = link_to license_short_name(@project), license_path(@project) + + - if @repository.contribution_guide + %li + = link_to 'Contribution guide', contribution_guide_path(@project) + + - if current_user && can_push_branch?(@project, @project.default_branch) + - unless @repository.changelog + %li.missing + = link_to add_special_file_path(@project, file_name: 'CHANGELOG') do + Add Changelog + - unless @repository.license_blob + %li.missing + = link_to add_special_file_path(@project, file_name: 'LICENSE') do + Add License + - unless @repository.contribution_guide + %li.missing + = link_to add_special_file_path(@project, file_name: 'CONTRIBUTING.md', commit_message: 'Add contribution guide') do + Add Contribution guide - if @repository.commit .content-block.second-block.white diff --git a/app/views/projects/snippets/_actions.html.haml b/app/views/projects/snippets/_actions.html.haml index 4a51546942..bf57beb9d0 100644 --- a/app/views/projects/snippets/_actions.html.haml +++ b/app/views/projects/snippets/_actions.html.haml @@ -1,11 +1,27 @@ -= link_to new_namespace_project_snippet_path(@project.namespace, @project), class: 'btn btn-grouped new-snippet-link', title: "New Snippet" do - = icon('plus') - New Snippet -- if can?(current_user, :admin_project_snippet, @snippet) - = link_to namespace_project_snippet_path(@project.namespace, @project, @snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-grouped btn-remove", title: 'Delete Snippet' do - = icon('trash-o') - Delete -- if can?(current_user, :update_project_snippet, @snippet) - = link_to edit_namespace_project_snippet_path(@project.namespace, @project, @snippet), class: "btn btn-grouped snippable-edit" do - = icon('pencil-square-o') - Edit +.hidden-xs + = link_to new_namespace_project_snippet_path(@project.namespace, @project), class: 'btn btn-grouped btn-create new-snippet-link', title: "New Snippet" do + = icon('plus') + New Snippet + - if can?(current_user, :update_project_snippet, @snippet) + = link_to edit_namespace_project_snippet_path(@project.namespace, @project, @snippet), class: "btn btn-grouped snippable-edit" do + Edit + - if can?(current_user, :update_project_snippet, @snippet) + = link_to namespace_project_snippet_path(@project.namespace, @project, @snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-grouped btn-warning", title: 'Delete Snippet' do + Delete +.visible-xs-block.dropdown + %button.btn.btn-default.btn-block.append-bottom-0.prepend-top-5{ data: { toggle: "dropdown" } } + Options + %span.caret + .dropdown-menu.dropdown-menu-full-width + %ul + %li + = link_to new_namespace_project_snippet_path(@project.namespace, @project), title: "New Snippet" do + New Snippet + - if can?(current_user, :update_project_snippet, @snippet) + %li + = link_to edit_namespace_project_snippet_path(@project.namespace, @project, @snippet) do + Edit + - if can?(current_user, :update_project_snippet, @snippet) + %li + = link_to namespace_project_snippet_path(@project.namespace, @project, @snippet), method: :delete, data: { confirm: "Are you sure?" }, title: 'Delete Snippet' do + Delete diff --git a/app/views/projects/snippets/_header_title.html.haml b/app/views/projects/snippets/_header_title.html.haml deleted file mode 100644 index 04f0bbe985..0000000000 --- a/app/views/projects/snippets/_header_title.html.haml +++ /dev/null @@ -1 +0,0 @@ -- header_title project_title(@project, "Snippets", namespace_project_snippets_path(@project.namespace, @project)) diff --git a/app/views/projects/snippets/edit.html.haml b/app/views/projects/snippets/edit.html.haml index dc3ea1fcf1..216f70f560 100644 --- a/app/views/projects/snippets/edit.html.haml +++ b/app/views/projects/snippets/edit.html.haml @@ -1,5 +1,4 @@ - page_title "Edit", @snippet.title, "Snippets" -= render "header_title" %h3.page-title Edit Snippet diff --git a/app/views/projects/snippets/index.html.haml b/app/views/projects/snippets/index.html.haml index 103ff44746..96fee3b17b 100644 --- a/app/views/projects/snippets/index.html.haml +++ b/app/views/projects/snippets/index.html.haml @@ -1,5 +1,4 @@ - page_title "Snippets" -= render "header_title" .row-content-block.top-block .pull-right diff --git a/app/views/projects/snippets/new.html.haml b/app/views/projects/snippets/new.html.haml index e57237991b..772a594269 100644 --- a/app/views/projects/snippets/new.html.haml +++ b/app/views/projects/snippets/new.html.haml @@ -1,5 +1,4 @@ - page_title "New Snippets" -= render "header_title" %h3.page-title New Snippet diff --git a/app/views/projects/snippets/show.html.haml b/app/views/projects/snippets/show.html.haml index 7c599563ce..bae4d8f349 100644 --- a/app/views/projects/snippets/show.html.haml +++ b/app/views/projects/snippets/show.html.haml @@ -1,18 +1,15 @@ - page_title @snippet.title, "Snippets" -= render "header_title" .snippet-holder = render 'shared/snippets/header' - %article.file-holder - .file-title + %article.file-holder.file-holder-no-border.snippet-file-content + .file-title.file-title-clear = blob_icon 0, @snippet.file_name - %strong - = @snippet.file_name + = @snippet.file_name .file-actions.hidden-xs = clipboard_button(clipboard_target: ".blob-content[data-blob-id='#{@snippet.id}']") = link_to 'Raw', raw_namespace_project_snippet_path(@project.namespace, @project, @snippet), class: "btn btn-sm", target: "_blank" - = render 'shared/snippets/blob' %div#notes= render "projects/notes/notes_with_form" diff --git a/app/views/projects/tags/destroy.js.haml b/app/views/projects/tags/destroy.js.haml index ffeacb5a00..e4a78fadbe 100644 --- a/app/views/projects/tags/destroy.js.haml +++ b/app/views/projects/tags/destroy.js.haml @@ -1,3 +1,2 @@ -$('.js-totaltags-count').html("#{@repository.tags.size}"); - if @repository.tags.empty? $('.tags').load(document.URL + ' .nothing-here-block').hide().fadeIn(1000) diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml index dc6ece30dd..8f381663e6 100644 --- a/app/views/projects/tags/index.html.haml +++ b/app/views/projects/tags/index.html.haml @@ -1,5 +1,4 @@ - page_title "Tags" -= render "projects/commits/header_title" = render "projects/commits/head" .row-content-block diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml index b40a6e5cb2..3a097750d6 100644 --- a/app/views/projects/tags/new.html.haml +++ b/app/views/projects/tags/new.html.haml @@ -1,5 +1,4 @@ - page_title "New Tag" -= render "projects/commits/header_title" - if @error .alert.alert-danger @@ -23,7 +22,7 @@ .form-group = label_tag :message, nil, class: 'control-label' .col-sm-10 - = text_field_tag :message, nil, required: false, tabindex: 3, class: 'form-control' + = text_area_tag :message, nil, required: false, tabindex: 3, class: 'form-control', rows: 5 .help-block Optionally, enter a message to create an annotated tag. %hr .form-group diff --git a/app/views/projects/tags/show.html.haml b/app/views/projects/tags/show.html.haml index 9c916fd02d..b7d7d5c538 100644 --- a/app/views/projects/tags/show.html.haml +++ b/app/views/projects/tags/show.html.haml @@ -1,5 +1,4 @@ - page_title @tag.name, "Tags" -= render "projects/commits/header_title" = render "projects/commits/head" .row-content-block @@ -19,15 +18,13 @@ %i.fa.fa-trash-o .title %span.item-title= @tag.name - - if @tag.message.present? - %span.light -   - = strip_gpg_signature(@tag.message) - if @commit = render 'projects/branches/commit', commit: @commit, project: @project - else Cant find HEAD commit for this tag - + - if @tag.message.present? + %pre.body + = strip_gpg_signature(@tag.message) .append-bottom-default.prepend-top-default - if @release.description.present? diff --git a/app/views/projects/tree/show.html.haml b/app/views/projects/tree/show.html.haml index 91fb2a4459..59f60c4687 100644 --- a/app/views/projects/tree/show.html.haml +++ b/app/views/projects/tree/show.html.haml @@ -1,9 +1,9 @@ - page_title @path.presence || "Files", @ref -- header_title project_title(@project, "Files", project_files_path(@project)) = content_for :meta_tags do - if current_user = auto_discovery_link_tag(:atom, namespace_project_commits_url(@project.namespace, @project, @ref, format: :atom, private_token: current_user.private_token), title: "#{@project.name}:#{@ref} commits") = render 'projects/last_push' += render "projects/commits/head" .tree-controls = render 'projects/find_file_link' diff --git a/app/views/projects/triggers/index.html.haml b/app/views/projects/triggers/index.html.haml index f91885b216..7f3de47d7d 100644 --- a/app/views/projects/triggers/index.html.haml +++ b/app/views/projects/triggers/index.html.haml @@ -5,7 +5,7 @@ %h4.prepend-top-0 = page_title %p - Triggers can be used to force a rebuild of a specific branch or tag with an API call. + Triggers can force a specific branch or tag to rebuild with an API call. .col-lg-9 %h5.prepend-top-0 Your triggers @@ -18,8 +18,8 @@ %th = render partial: 'trigger', collection: @triggers, as: :trigger - else - %p.profile-settings-message.text-center.append-bottom-default - There are no triggers to use, add one by the button below. + %p.settings-message.text-center.append-bottom-default + No triggers have been created yet. Add one using the button below. = form_for @trigger, url: url_for(controller: 'projects/triggers', action: 'create') do |f| = f.submit "Add Trigger", class: 'btn btn-success' @@ -28,8 +28,7 @@ Use CURL %p.light - Copy the token above and set your branch or tag name. This is the reference that will be rebuild. - + Copy the token above, set your branch or tag name, and that reference will be rebuilt. %pre :plain @@ -41,10 +40,10 @@ Use .gitlab-ci.yml %p.light - Copy the snippet to - %i .gitlab-ci.yml - of dependent project. - At the end of your build it will trigger this project to rebuilt. + In the + %code .gitlab-ci.yml + of the dependent project, include the following snippet. + The project will rebuild at the end of the build. %pre :plain @@ -57,9 +56,8 @@ %p.light Add - %strong variables[VARIABLE]=VALUE - to API request. - The value of variable could then be used to distinguish triggered build from normal one. + %code variables[VARIABLE]=VALUE + to an API request. Variable values can be used to distinguish between triggered builds and normal builds. %pre.append-bottom-0 :plain diff --git a/app/views/projects/variables/_content.html.haml b/app/views/projects/variables/_content.html.haml new file mode 100644 index 0000000000..0249e0c1bf --- /dev/null +++ b/app/views/projects/variables/_content.html.haml @@ -0,0 +1,8 @@ +%h4.prepend-top-0 + Secret Variables +%p + These variables will be set to environment by the runner. +%p + So you can use them for passwords, secret keys or whatever you want. +%p + The value of the variable can be visible in build log if explicitly asked to do so. diff --git a/app/views/projects/variables/_form.html.haml b/app/views/projects/variables/_form.html.haml new file mode 100644 index 0000000000..a5bae83e0c --- /dev/null +++ b/app/views/projects/variables/_form.html.haml @@ -0,0 +1,10 @@ += form_for [@project.namespace.becomes(Namespace), @project, @variable] do |f| + = form_errors(@variable) + + .form-group + = f.label :key, "Key", class: "label-light" + = f.text_field :key, class: "form-control", placeholder: "PROJECT_VARIABLE", required: true + .form-group + = f.label :value, "Value", class: "label-light" + = f.text_area :value, class: "form-control", placeholder: "PROJECT_VARIABLE", required: true + = f.submit btn_text, class: "btn btn-save" diff --git a/app/views/projects/variables/_table.html.haml b/app/views/projects/variables/_table.html.haml new file mode 100644 index 0000000000..6c43f822db --- /dev/null +++ b/app/views/projects/variables/_table.html.haml @@ -0,0 +1,25 @@ +.table-responsive.variables-table + %table.table + %colgroup + %col + %col + %col{ width: 100 } + %thead + %th Key + %th Value + %th + %tbody + - @project.variables.each do |variable| + - if variable.id? + %tr + %td= variable.key + %td= variable.value + %td + = link_to namespace_project_variable_path(@project.namespace, @project, variable), class: "btn btn-transparent btn-variable-edit" do + %span.sr-only + Update + = icon("pencil") + = link_to namespace_project_variable_path(@project.namespace, @project, variable), class: "btn btn-transparent btn-variable-delete", method: :delete, data: { confirm: "Are you sure?" } do + %span.sr-only + Remove + = icon("trash") diff --git a/app/views/projects/variables/index.html.haml b/app/views/projects/variables/index.html.haml new file mode 100644 index 0000000000..09bb54600a --- /dev/null +++ b/app/views/projects/variables/index.html.haml @@ -0,0 +1,17 @@ +- page_title "Variables" + +.row.prepend-top-default.append-bottom-default + .col-lg-3 + = render "content" + .col-lg-9 + %h5.prepend-top-0 + Add a variable + = render "form", btn_text: "Add new variable" + %hr + %h5.prepend-top-0 + Your variables (#{@project.variables.size}) + - if @project.variables.empty? + %p.settings-message.text-center.append-bottom-0 + No variables found, add one with the form above. + - else + = render "table" diff --git a/app/views/projects/variables/show.html.haml b/app/views/projects/variables/show.html.haml index ca284b84d3..297a53ca98 100644 --- a/app/views/projects/variables/show.html.haml +++ b/app/views/projects/variables/show.html.haml @@ -1,36 +1,9 @@ - page_title "Variables" -%h3.page-title - Secret Variables -%p.light - These variables will be set to environment by the runner. - %br - So you can use them for passwords, secret keys or whatever you want. - %br - The value of the variable can be visible in build log if explicitly asked to do so. - -%hr - - -= nested_form_for @project, url: url_for(controller: 'projects/variables', action: 'update'), html: { class: 'form-horizontal' } do |f| - = form_errors(@project) - - = f.fields_for :variables do |variable_form| - .form-group - = variable_form.label :key, 'Key', class: 'control-label' - .col-sm-10 - = variable_form.text_field :key, class: 'form-control', placeholder: "PROJECT_VARIABLE" - - .form-group - = variable_form.label :value, 'Value', class: 'control-label' - .col-sm-10 - = variable_form.text_area :value, class: 'form-control', rows: 2, placeholder: "" - - = variable_form.link_to_remove "Remove this variable", class: 'btn btn-danger pull-right prepend-top-10' - %hr - %p - .clearfix - = f.link_to_add "Add a variable", :variables, class: 'btn btn-success pull-right' - - .form-actions - = f.submit 'Save changes', class: 'btn btn-save', return_to: request.original_url +.row.prepend-top-default.append-bottom-default + .col-lg-3 + = render "content" + .col-lg-9 + %h5.prepend-top-0 + Update variable + = render "form", btn_text: "Save variable" diff --git a/app/views/projects/wikis/_header_title.html.haml b/app/views/projects/wikis/_header_title.html.haml deleted file mode 100644 index 408adc36ca..0000000000 --- a/app/views/projects/wikis/_header_title.html.haml +++ /dev/null @@ -1 +0,0 @@ -- header_title project_title(@project, 'Wiki', get_project_wiki_path(@project)) diff --git a/app/views/projects/wikis/edit.html.haml b/app/views/projects/wikis/edit.html.haml index 4dd818c7f6..aaa15dd3bb 100644 --- a/app/views/projects/wikis/edit.html.haml +++ b/app/views/projects/wikis/edit.html.haml @@ -1,5 +1,4 @@ - page_title "Edit", @page.title.capitalize, "Wiki" -= render "header_title" = render 'nav' .top-area diff --git a/app/views/projects/wikis/empty.html.haml b/app/views/projects/wikis/empty.html.haml index c7e490c3cd..7dfa405d06 100644 --- a/app/views/projects/wikis/empty.html.haml +++ b/app/views/projects/wikis/empty.html.haml @@ -1,5 +1,4 @@ - page_title "Wiki" -= render "header_title" %h3.page-title Empty page %hr diff --git a/app/views/projects/wikis/git_access.html.haml b/app/views/projects/wikis/git_access.html.haml index ba3f2cadc4..ccceab6155 100644 --- a/app/views/projects/wikis/git_access.html.haml +++ b/app/views/projects/wikis/git_access.html.haml @@ -1,5 +1,4 @@ - page_title "Git Access", "Wiki" -= render "header_title" = render 'nav' .row-content-block diff --git a/app/views/projects/wikis/history.html.haml b/app/views/projects/wikis/history.html.haml index dcaddae2b0..45460ed9f4 100644 --- a/app/views/projects/wikis/history.html.haml +++ b/app/views/projects/wikis/history.html.haml @@ -1,5 +1,4 @@ - page_title "History", @page.title.capitalize, "Wiki" -= render "header_title" = render 'nav' .top-area diff --git a/app/views/projects/wikis/pages.html.haml b/app/views/projects/wikis/pages.html.haml index 92b494a513..2f6162fa3c 100644 --- a/app/views/projects/wikis/pages.html.haml +++ b/app/views/projects/wikis/pages.html.haml @@ -1,5 +1,4 @@ - page_title "Pages", "Wiki" -= render "header_title" = render 'nav' diff --git a/app/views/projects/wikis/show.html.haml b/app/views/projects/wikis/show.html.haml index 067fb7f8f5..1cb48a1e85 100644 --- a/app/views/projects/wikis/show.html.haml +++ b/app/views/projects/wikis/show.html.haml @@ -1,5 +1,4 @@ - page_title @page.title.capitalize, "Wiki" -= render "header_title" = render 'nav' .top-area diff --git a/app/views/search/results/_issue.html.haml b/app/views/search/results/_issue.html.haml index 640890fbe9..8f68d6d1b8 100644 --- a/app/views/search/results/_issue.html.haml +++ b/app/views/search/results/_issue.html.haml @@ -7,7 +7,7 @@ - if issue.description.present? .description.term = preserve do - = search_md_sanitize(markdown(truncate(issue.description, length: 200, separator: " "), { project: issue.project })) + = search_md_sanitize(markdown(truncate(issue.description, length: 200, separator: " "), { project: issue.project, author: issue.author })) %span.light #{issue.project.name_with_namespace} - if issue.closed? diff --git a/app/views/search/results/_merge_request.html.haml b/app/views/search/results/_merge_request.html.haml index 333f653321..6331c2bd6b 100644 --- a/app/views/search/results/_merge_request.html.haml +++ b/app/views/search/results/_merge_request.html.haml @@ -6,7 +6,7 @@ - if merge_request.description.present? .description.term = preserve do - = search_md_sanitize(markdown(merge_request.description, { project: merge_request.project })) + = search_md_sanitize(markdown(merge_request.description, { project: merge_request.project, author: merge_request.author })) %span.light #{merge_request.project.name_with_namespace} .pull-right diff --git a/app/views/search/results/_note.html.haml b/app/views/search/results/_note.html.haml index d9400b1d9f..8163aff43b 100644 --- a/app/views/search/results/_note.html.haml +++ b/app/views/search/results/_note.html.haml @@ -19,4 +19,4 @@ .note-search-result .term = preserve do - = search_md_sanitize(markdown(note.note, {no_header_anchors: true})) + = search_md_sanitize(markdown(note.note, {no_header_anchors: true, author: note.author})) diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml index 974751d997..84b3f44c0a 100644 --- a/app/views/shared/_clone_panel.html.haml +++ b/app/views/shared/_clone_panel.html.haml @@ -5,7 +5,7 @@ %a#clone-dropdown.clone-dropdown-btn.btn{href: '#', 'data-toggle' => 'dropdown'} %span = default_clone_protocol.upcase - = icon('angle-down') + = icon('caret-down') %ul.dropdown-menu.dropdown-menu-right.clone-options-dropdown %li = ssh_clone_button(project) diff --git a/app/views/shared/_event_filter.html.haml b/app/views/shared/_event_filter.html.haml index c38d9313db..3005500221 100644 --- a/app/views/shared/_event_filter.html.haml +++ b/app/views/shared/_event_filter.html.haml @@ -1,5 +1,7 @@ -%ul.nav-links.event-filter +%ul.nav-links.event-filter.scrolling-tabs + .fade-left = event_filter_link EventFilter.push, 'Push events' = event_filter_link EventFilter.merged, 'Merge events' = event_filter_link EventFilter.comments, 'Comments' = event_filter_link EventFilter.team, 'Team' + .fade-right diff --git a/app/views/shared/_sort_dropdown.html.haml b/app/views/shared/_sort_dropdown.html.haml index d327bd0a96..1e0f075b30 100644 --- a/app/views/shared/_sort_dropdown.html.haml +++ b/app/views/shared/_sort_dropdown.html.haml @@ -6,7 +6,7 @@ - else = sort_title_recently_created %b.caret - %ul.dropdown-menu.dropdown-menu-align-right + %ul.dropdown-menu.dropdown-menu-align-right.dropdown-menu-sort %li = link_to page_filter_path(sort: sort_value_recently_created) do = sort_title_recently_created diff --git a/app/views/shared/groups/_list.html.haml b/app/views/shared/groups/_list.html.haml index 1aa7ed1f2e..427595c47a 100644 --- a/app/views/shared/groups/_list.html.haml +++ b/app/views/shared/groups/_list.html.haml @@ -3,4 +3,4 @@ - groups.each_with_index do |group, i| = render "shared/groups/group", group: group - else - %h3 No groups found + .nothing-here-block No groups found diff --git a/app/views/shared/issuable/_filter.html.haml b/app/views/shared/issuable/_filter.html.haml index 9474462cbd..cedff4af2e 100644 --- a/app/views/shared/issuable/_filter.html.haml +++ b/app/views/shared/issuable/_filter.html.haml @@ -1,6 +1,8 @@ .issues-filters .issues-details-filters.row-content-block.second-block - = form_tag page_filter_path(without: [:assignee_id, :author_id, :milestone_title, :label_name]), method: :get, class: 'filter-form' do + = form_tag page_filter_path(without: [:assignee_id, :author_id, :milestone_title, :label_name, :issue_search]), method: :get, class: 'filter-form js-filter-form' do + - if params[:issue_search].present? + = hidden_field_tag :issue_search, params[:issue_search] - if controller.controller_name == 'issues' && can?(current_user, :admin_issue, @project) .check-all-holder = check_box_tag "check_all_issues", nil, false, @@ -10,7 +12,7 @@ - if params[:author_id].present? = hidden_field_tag(:author_id, params[:author_id]) = dropdown_tag(user_dropdown_label(params[:author_id], "Author"), options: { toggle_class: "js-user-search js-filter-submit js-author-search", title: "Filter by author", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-author js-filter-submit", - placeholder: "Search authors", data: { any_user: "Any Author", first_user: (current_user.username if current_user), current_user: true, project_id: (@project.id if @project), selected: params[:author_id], field_name: "author_id", default_label: "Author" } }) + placeholder: "Search authors", data: { any_user: "Any Author", first_user: (current_user.username if current_user), current_user: true, project_id: (@project.id if @project), selected: params[:author], field_name: "author_id", default_label: "Author" } }) .filter-item.inline - if params[:assignee_id].present? diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml index 5c52cc6d1d..b430251dbf 100644 --- a/app/views/shared/issuable/_form.html.haml +++ b/app/views/shared/issuable/_form.html.haml @@ -44,45 +44,53 @@ This issue is confidential and should only be visible to team members - if can?(current_user, :"admin_#{issuable.to_ability_name}", issuable.project) + - has_due_date = issuable.has_attribute?(:due_date) %hr - .form-group - .issue-assignee - = f.label :assignee_id, "Assignee", class: 'control-label' - .col-sm-10 - .issuable-form-select-holder - = users_select_tag("#{issuable.class.model_name.param_key}[assignee_id]", - placeholder: 'Select assignee', class: 'custom-form-control', null_user: true, - selected: issuable.assignee_id, project: @target_project || @project, - first_user: true, current_user: true, include_blank: true) -   - = link_to 'Assign to me', '#', class: 'btn assign-to-me-link' - .form-group - .issue-milestone - = f.label :milestone_id, "Milestone", class: 'control-label' - .col-sm-10 - - if milestone_options(issuable).present? + .row + %div{ class: (has_due_date ? "col-lg-6" : "col-sm-12") } + .form-group.issue-assignee + = f.label :assignee_id, "Assignee", class: "control-label #{"col-lg-4" if has_due_date}" + .col-sm-10{ class: ("col-lg-8" if has_due_date) } .issuable-form-select-holder - = f.select(:milestone_id, milestone_options(issuable), - { include_blank: true }, { class: 'select2', data: { placeholder: 'Select milestone' } }) - - else - .prepend-top-10 - %span.light No open milestones available. -   - - if can? current_user, :admin_milestone, issuable.project - = link_to 'Create new milestone', new_namespace_project_milestone_path(issuable.project.namespace, issuable.project), target: :blank - .form-group - - has_labels = issuable.project.labels.any? - = f.label :label_ids, "Labels", class: 'control-label' - .col-sm-10{ class: ('issuable-form-padding-top' if !has_labels) } - - if has_labels - .issuable-form-select-holder - = f.collection_select :label_ids, issuable.project.labels.all, :id, :name, - { selected: issuable.label_ids }, multiple: true, class: 'select2', data: { placeholder: "Select labels" } - - else - %span.light No labels yet. -   - - if can? current_user, :admin_label, issuable.project - = link_to 'Create new label', new_namespace_project_label_path(issuable.project.namespace, issuable.project), target: :blank + = users_select_tag("#{issuable.class.model_name.param_key}[assignee_id]", + placeholder: 'Select assignee', class: 'custom-form-control', null_user: true, + selected: issuable.assignee_id, project: @target_project || @project, + first_user: true, current_user: true, include_blank: true) + %div + = link_to 'Assign to me', '#', class: 'assign-to-me-link prepend-top-5 inline' + .form-group.issue-milestone + = f.label :milestone_id, "Milestone", class: "control-label #{"col-lg-4" if has_due_date}" + .col-sm-10{ class: ("col-lg-8" if has_due_date) } + - if milestone_options(issuable).present? + .issuable-form-select-holder + = f.select(:milestone_id, milestone_options(issuable), + { include_blank: true }, { class: 'select2', data: { placeholder: 'Select milestone' } }) + - else + .prepend-top-10 + %span.light No open milestones available. + - if can? current_user, :admin_milestone, issuable.project + %div + = link_to 'Create new milestone', new_namespace_project_milestone_path(issuable.project.namespace, issuable.project), target: :blank, class: "prepend-top-5 inline" + .form-group + - has_labels = issuable.project.labels.any? + = f.label :label_ids, "Labels", class: "control-label #{"col-lg-4" if has_due_date}" + .col-sm-10{ class: "#{"col-lg-8" if has_due_date} #{'issuable-form-padding-top' if !has_labels}" } + - if has_labels + .issuable-form-select-holder + = f.collection_select :label_ids, issuable.project.labels.all, :id, :name, + { selected: issuable.label_ids }, multiple: true, class: 'select2', data: { placeholder: "Select labels" } + - else + %span.light No labels yet. + - if can? current_user, :admin_label, issuable.project + %div + = link_to 'Create new label', new_namespace_project_label_path(issuable.project.namespace, issuable.project), target: :blank, class: "prepend-top-5 inline" + - if has_due_date + .col-lg-6 + .form-group + = f.label :due_date, "Due date", class: "control-label" + = f.hidden_field :due_date, id: "issuable-due-date" + .col-sm-10 + .datepicker - if issuable.can_move?(current_user) %hr @@ -90,9 +98,7 @@ = label_tag :move_to_project_id, 'Move', class: 'control-label' .col-sm-10 .issuable-form-select-holder - - projects = project_options(issuable, current_user, ability: :admin_issue) - = select_tag(:move_to_project_id, projects, include_blank: true, - class: 'select2', data: { placeholder: 'Select project' }) + = hidden_field_tag :move_to_project_id, nil, class: 'js-move-dropdown', data: { placeholder: 'Select project', projects_url: autocomplete_projects_path(project_id: @project.id) }   %span{ data: { toggle: 'tooltip', placement: 'auto top' }, style: 'cursor: default', title: 'Moving an issue will copy the discussion to a different project and close it here. All participants will be notified of the new location.' } @@ -114,6 +120,13 @@ - if @merge_request.new_record?   = link_to 'Change branches', mr_change_branches_path(@merge_request) + - if @merge_request.can_remove_source_branch?(current_user) + .form-group + .col-sm-10.col-sm-offset-2 + .checkbox + = label_tag 'merge_request[force_remove_source_branch]' do + = check_box_tag 'merge_request[force_remove_source_branch]', '1', @merge_request.force_remove_source_branch? + Remove source branch when merge request is accepted. - is_footer = !(issuable.is_a?(MergeRequest) && issuable.new_record?) .row-content-block{class: (is_footer ? "footer-block" : "middle-block")} diff --git a/app/views/shared/issuable/_search_form.html.haml b/app/views/shared/issuable/_search_form.html.haml index afad48499b..186963b32b 100644 --- a/app/views/shared/issuable/_search_form.html.haml +++ b/app/views/shared/issuable/_search_form.html.haml @@ -1,8 +1,2 @@ = form_tag(path, method: :get, id: "issue_search_form", class: 'issue-search-form') do = search_field_tag :issue_search, params[:issue_search], { placeholder: 'Filter by name ...', class: 'form-control issue_search search-text-input input-short', spellcheck: false } - = hidden_field_tag :state, params['state'] - = hidden_field_tag :scope, params['scope'] - = hidden_field_tag :assignee_id, params['assignee_id'] - = hidden_field_tag :author_id, params['author_id'] - = hidden_field_tag :milestone_id, params['milestone_id'] - = hidden_field_tag :label_id, params['label_id'] diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index ed1b8a8da2..d6552ae7f1 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -87,10 +87,16 @@ - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project) = link_to 'Edit', '#', class: 'edit-link pull-right' .value.bold.hide-collapsed - - if issuable.due_date - = issuable.due_date.to_s(:medium) - - else - .light None + %span.value-content + - if issuable.due_date + = issuable.due_date.to_s(:medium) + - else + None + - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project) + %span.light.js-remove-due-date-holder{ class: ("hidden" if issuable.due_date.nil?) } + \- + %a.js-remove-due-date{ href: "#", role: "button" } + remove due date - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project) .selectbox.hide-collapsed = f.hidden_field :due_date, value: issuable.due_date @@ -108,20 +114,20 @@ .sidebar-collapsed-icon = icon('tags') %span - = issuable.labels.count + = issuable.labels_array.size .title.hide-collapsed Labels = icon('spinner spin', class: 'block-loading') - if can_edit_issuable = link_to 'Edit', '#', class: 'edit-link pull-right' - .value.bold.issuable-show-labels.hide-collapsed{ class: ("has-labels" if issuable.labels.any?) } - - if issuable.labels.any? - - issuable.labels.each do |label| + .value.bold.issuable-show-labels.hide-collapsed{ class: ("has-labels" if issuable.labels_array.any?) } + - if issuable.labels_array.any? + - issuable.labels_array.each do |label| = link_to_label(label, type: issuable.to_ability_name) - else .light None .selectbox.hide-collapsed - - issuable.labels.each do |label| + - issuable.labels_array.each do |label| = hidden_field_tag "#{issuable.to_ability_name}[label_names][]", label.id, id: nil .dropdown %button.dropdown-menu-toggle.js-label-select.js-multiselect{type: "button", data: {toggle: "dropdown", field_name: "#{issuable.to_ability_name}[label_names][]", ability_name: issuable.to_ability_name, show_no: "true", show_any: "true", project_id: (@project.id if @project), issue_update: issuable_json_path(issuable), labels: (namespace_project_labels_path(@project.namespace, @project, :json) if @project)}} diff --git a/app/views/shared/milestones/_participants_tab.html.haml b/app/views/shared/milestones/_participants_tab.html.haml index 67ae85ac27..549d2e2f61 100644 --- a/app/views/shared/milestones/_participants_tab.html.haml +++ b/app/views/shared/milestones/_participants_tab.html.haml @@ -3,6 +3,6 @@ %li = link_to user, title: user.name, class: "darken" do = image_tag avatar_icon(user, 32), class: "avatar s32" - %strong= truncate(user.name, lenght: 40) + %strong= truncate(user.name, length: 40) %br %small.cgray= user.username diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml index ab8b022411..b8b66d08db 100644 --- a/app/views/shared/projects/_project.html.haml +++ b/app/views/shared/projects/_project.html.haml @@ -12,12 +12,9 @@ %li.project-row{ class: css_class } = cache(cache_key) do .controls - - if project.main_language - %span - = project.main_language - if project.commit.try(:status) %span - = render_ci_status(project.commit) + = render_commit_status(project.commit) - if forks %span = icon('code-fork') diff --git a/app/views/shared/snippets/_header.html.haml b/app/views/shared/snippets/_header.html.haml index e65b181487..af75349626 100644 --- a/app/views/shared/snippets/_header.html.haml +++ b/app/views/shared/snippets/_header.html.haml @@ -1,25 +1,24 @@ -.detail-page-header - .snippet-box.has-tooltip{class: visibility_level_color(@snippet.visibility_level), title: snippet_visibility_level_description(@snippet.visibility_level, @snippet), data: { container: 'body' }} +.detail-page-header.clearfix + .snippet-box.has-tooltip.inline.append-right-5{ title: snippet_visibility_level_description(@snippet.visibility_level, @snippet), data: { container: "body" } } + %span.sr-only + = visibility_level_label(@snippet.visibility_level) = visibility_level_icon(@snippet.visibility_level, fw: false) - = visibility_level_label(@snippet.visibility_level) - %span.identifier - Snippet ##{@snippet.id} + %strong.item-title + Snippet #{@snippet.to_reference} %span.creator - · created by #{link_to_member(@project, @snippet.author, size: 24)} - · + created by #{link_to_member(@project, @snippet.author, size: 24, author_class: "author item-title")} = time_ago_with_tooltip(@snippet.created_at, placement: 'bottom', html_class: 'snippet_updated_ago') - if @snippet.updated_at != @snippet.created_at %span - · = icon('edit', title: 'edited') = time_ago_with_tooltip(@snippet.updated_at, placement: 'bottom', html_class: 'snippet_edited_ago') - .pull-right + .snippet-actions - if @snippet.project_id? = render "projects/snippets/actions" - else = render "snippets/actions" -.detail-page-description.row-content-block.second-block - %h2.title - = markdown escape_once(@snippet.title), pipeline: :single_line +.content-block.second-block + %h2.snippet-title.prepend-top-0.append-bottom-0 + = markdown escape_once(@snippet.title), pipeline: :single_line, author: @snippet.author diff --git a/app/views/snippets/_actions.html.haml b/app/views/snippets/_actions.html.haml index 1979ae6d5b..a7769654b6 100644 --- a/app/views/snippets/_actions.html.haml +++ b/app/views/snippets/_actions.html.haml @@ -1,11 +1,27 @@ -= link_to new_snippet_path, class: 'btn btn-grouped new-snippet-link', title: "New Snippet" do - = icon('plus') - New Snippet -- if can?(current_user, :update_personal_snippet, @snippet) - = link_to edit_snippet_path(@snippet), class: "btn btn-grouped snippable-edit" do - = icon('pencil-square-o') - Edit -- if can?(current_user, :admin_personal_snippet, @snippet) - = link_to snippet_path(@snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-grouped btn-remove", title: 'Delete Snippet' do - = icon('trash-o') - Delete +.hidden-xs + = link_to new_snippet_path, class: "btn btn-grouped btn-create new-snippet-link", title: "New Snippet" do + = icon('plus') + New Snippet + - if can?(current_user, :update_personal_snippet, @snippet) + = link_to edit_snippet_path(@snippet), class: "btn btn-grouped snippable-edit" do + Edit + - if can?(current_user, :admin_personal_snippet, @snippet) + = link_to snippet_path(@snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-grouped btn-warning", title: 'Delete Snippet' do + Delete +.visible-xs-block.dropdown + %button.btn.btn-default.btn-block.append-bottom-0.prepend-top-5{ data: { toggle: "dropdown" } } + Options + %span.caret + .dropdown-menu.dropdown-menu-full-width + %ul + %li + = link_to new_snippet_path, title: "New Snippet" do + New Snippet + - if can?(current_user, :update_personal_snippet, @snippet) + %li + = link_to edit_snippet_path(@snippet) do + Edit + - if can?(current_user, :admin_personal_snippet, @snippet) + %li + = link_to snippet_path(@snippet), method: :delete, data: { confirm: "Are you sure?" }, title: 'Delete Snippet' do + Delete diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml index a2b3656877..ed3992650d 100644 --- a/app/views/snippets/show.html.haml +++ b/app/views/snippets/show.html.haml @@ -3,11 +3,10 @@ .snippet-holder = render 'shared/snippets/header' - %article.file-holder - .file-title + %article.file-holder.file-holder-no-border.snippet-file-content + .file-title.file-title-clear = blob_icon 0, @snippet.file_name - %strong - = @snippet.file_name + = @snippet.file_name .file-actions.hidden-xs = clipboard_button(clipboard_target: ".blob-content[data-blob-id='#{@snippet.id}']") = link_to 'Raw', raw_snippet_path(@snippet), class: "btn btn-sm", target: "_blank" diff --git a/app/views/users/calendar.html.haml b/app/views/users/calendar.html.haml index 1de71f37d1..77f2ddefb1 100644 --- a/app/views/users/calendar.html.haml +++ b/app/views/users/calendar.html.haml @@ -1,10 +1,9 @@ -#cal-heatmap.calendar - :javascript - new Calendar( - #{@timestamps.to_json}, - #{@starting_year}, - #{@starting_month}, - '#{user_calendar_activities_path}' - ); - -.calendar-hint Summary of issues, merge requests, and push events +.clearfix.calendar + .js-contrib-calendar + .calendar-hint + Summary of issues, merge requests, and push events +:javascript + new Calendar( + #{@timestamps.to_json}, + '#{user_calendar_activities_path}' + ); diff --git a/app/views/users/calendar_activities.html.haml b/app/views/users/calendar_activities.html.haml index 027a93a75f..630d97e339 100644 --- a/app/views/users/calendar_activities.html.haml +++ b/app/views/users/calendar_activities.html.haml @@ -1,23 +1,27 @@ %h4.prepend-top-20 - %span.light Contributions for + Contributions for %strong #{@calendar_date.to_s(:short)} -%ul.bordered-list - - @events.sort_by(&:created_at).each do |event| - %li - %span.light - %i.fa.fa-clock-o - = event.created_at.to_s(:time) - - if event.push? - #{event.action_name} #{event.ref_type} #{event.ref_name} - - else - = event_action_name(event) - - if event.target - %strong= link_to "##{event.target_iid}", [event.project.namespace.becomes(Namespace), event.project, event.target] - - at - %strong - - if event.project - = link_to_project event.project +- if @events.any? + %ul.bordered-list + - @events.sort_by(&:created_at).each do |event| + %li + %span.light + %i.fa.fa-clock-o + = event.created_at.to_s(:time) + - if event.push? + #{event.action_name} #{event.ref_type} #{event.ref_name} - else - = event.project_name + = event_action_name(event) + - if event.target + %strong= link_to "##{event.target_iid}", [event.project.namespace.becomes(Namespace), event.project, event.target] + + at + %strong + - if event.project + = link_to_project event.project + - else + = event.project_name +- else + %p + No contributions found for #{@calendar_date.to_s(:short)} diff --git a/app/views/users/show.atom.builder b/app/views/users/show.atom.builder index e9e466c635..6c85e5f9fb 100644 --- a/app/views/users/show.atom.builder +++ b/app/views/users/show.atom.builder @@ -6,7 +6,5 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear xml.id user_url(@user) xml.updated @events[0].updated_at.xmlschema if @events[0] - @events.each do |event| - event_to_atom(xml, event) - end + xml << render(@events) if @events.any? end diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index 3c0b89c674..8268380daf 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -1,5 +1,6 @@ - page_title @user.name - page_description @user.bio +- page_specific_javascripts asset_path("users/application.js") - header_title @user.name, user_path(@user) - @no_container = true @@ -81,15 +82,17 @@ %li.projects-tab = link_to user_projects_path, data: {target: 'div#projects', action: 'projects', toggle: 'tab'} do Personal projects + %li.snippets-tab + = link_to user_snippets_path, data: {target: 'div#snippets', action: 'snippets', toggle: 'tab'} do + Snippets %div{ class: container_class } .tab-content #activity.tab-pane .row-content-block.calender-block.white.second-block.hidden-xs - %div{ class: container_class } - .user-calendar{data: {href: user_calendar_path}} - %h4.center.light - %i.fa.fa-spinner.fa-spin + .user-calendar{data: {href: user_calendar_path}} + %h4.center.light + %i.fa.fa-spinner.fa-spin .user-calendar-activities .content_list{ data: {href: user_path} } @@ -104,6 +107,9 @@ #projects.tab-pane - # This tab is always loaded via AJAX + #snippets.tab-pane + - # This tab is always loaded via AJAX + .loading-status = spinner diff --git a/app/workers/emails_on_push_worker.rb b/app/workers/emails_on_push_worker.rb index c4d8595d45..971f969e25 100644 --- a/app/workers/emails_on_push_worker.rb +++ b/app/workers/emails_on_push_worker.rb @@ -1,6 +1,9 @@ class EmailsOnPushWorker include Sidekiq::Worker + sidekiq_options queue: :mailers + attr_reader :email, :skip_premailer + def perform(project_id, recipients, push_data, options = {}) options.symbolize_keys! options.reverse_merge!( @@ -25,15 +28,18 @@ class EmailsOnPushWorker :push end + diff_refs = nil compare = nil reverse_compare = false if action == :push compare = Gitlab::Git::Compare.new(project.repository.raw_repository, before_sha, after_sha) + diff_refs = [project.merge_base_commit(before_sha, after_sha), project.commit(after_sha)] return false if compare.same if compare.commits.empty? compare = Gitlab::Git::Compare.new(project.repository.raw_repository, after_sha, before_sha) + diff_refs = [project.merge_base_commit(after_sha, before_sha), project.commit(before_sha)] reverse_compare = true @@ -41,26 +47,42 @@ class EmailsOnPushWorker end end - recipients.split(" ").each do |recipient| + recipients.split.each do |recipient| begin - Notify.repository_push_email( - project_id, + send_email( recipient, - author_id: author_id, - ref: ref, - action: action, - compare: compare, - reverse_compare: reverse_compare, - send_from_committer_email: send_from_committer_email, - disable_diffs: disable_diffs - ).deliver_now + project_id, + author_id: author_id, + ref: ref, + action: action, + compare: compare, + reverse_compare: reverse_compare, + diff_refs: diff_refs, + send_from_committer_email: send_from_committer_email, + disable_diffs: disable_diffs + ) + # These are input errors and won't be corrected even if Sidekiq retries rescue Net::SMTPFatalError, Net::SMTPSyntaxError => e logger.info("Failed to send e-mail for project '#{project.name_with_namespace}' to #{recipient}: #{e}") end end ensure + @email = nil compare = nil GC.start end + + private + + def send_email(recipient, project_id, options) + # Generating the body of this email can be expensive, so only do it once + @skip_premailer ||= email.present? + @email ||= Notify.repository_push_email(project_id, options) + + email.to = recipient + email.add_message_id + email.header[:skip_premailer] = true if skip_premailer + email.deliver_now + end end diff --git a/app/workers/repository_fork_worker.rb b/app/workers/repository_fork_worker.rb index f9e3233798..d947f10551 100644 --- a/app/workers/repository_fork_worker.rb +++ b/app/workers/repository_fork_worker.rb @@ -15,8 +15,7 @@ class RepositoryForkWorker result = gitlab_shell.fork_repository(source_path, target_path) unless result logger.error("Unable to fork project #{project_id} for repository #{source_path} -> #{target_path}") - project.update(import_error: "The project could not be forked.") - project.import_fail + project.mark_import_as_failed('The project could not be forked.') return end @@ -24,8 +23,7 @@ class RepositoryForkWorker unless project.valid_repo? logger.error("Project #{project_id} had an invalid repository after fork") - project.update(import_error: "The forked repository is invalid.") - project.import_fail + project.mark_import_as_failed('The forked repository is invalid.') return end diff --git a/app/workers/repository_import_worker.rb b/app/workers/repository_import_worker.rb index 2937493c61..7d819fe78f 100644 --- a/app/workers/repository_import_worker.rb +++ b/app/workers/repository_import_worker.rb @@ -13,8 +13,7 @@ class RepositoryImportWorker result = Projects::ImportService.new(project, current_user).execute if result[:status] == :error - project.update(import_error: result[:message]) - project.import_fail + project.mark_import_as_failed(result[:message]) return end diff --git a/config/application.rb b/config/application.rb index b602e2b616..49d4d3ba55 100644 --- a/config/application.rb +++ b/config/application.rb @@ -1,23 +1,32 @@ require File.expand_path('../boot', __FILE__) require 'rails/all' -require 'devise' -I18n.config.enforce_available_locales = false + Bundler.require(:default, Rails.env) -require_relative '../lib/gitlab/redis' module Gitlab class Application < Rails::Application + require_dependency Rails.root.join('lib/gitlab/redis') + # Settings in config/environments/* take precedence over those specified here. # Application configuration should go into files in config/initializers # -- all .rb files in that directory are automatically loaded. - # Custom directories with classes and modules you want to be autoloadable. - config.autoload_paths.push(*%W(#{config.root}/lib - #{config.root}/app/models/hooks - #{config.root}/app/models/concerns - #{config.root}/app/models/project_services - #{config.root}/app/models/members)) + # Sidekiq uses eager loading, but directories not in the standard Rails + # directories must be added to the eager load paths: + # https://github.com/mperham/sidekiq/wiki/FAQ#why-doesnt-sidekiq-autoload-my-rails-application-code + # Also, there is no need to add `lib` to autoload_paths since autoloading is + # configured to check for eager loaded paths: + # https://github.com/rails/rails/blob/v4.2.6/railties/lib/rails/engine.rb#L687 + # This is a nice reference article on autoloading/eager loading: + # http://blog.arkency.com/2014/11/dont-forget-about-eager-load-when-extending-autoload + config.eager_load_paths.push(*%W(#{config.root}/lib + #{config.root}/app/models/ci + #{config.root}/app/models/hooks + #{config.root}/app/models/members + #{config.root}/app/models/project_services)) + + config.generators.templates.push("#{config.root}/generator_templates") # Only load the plugins named here, in the order given (default is alphabetical). # :all can be used as a placeholder for all plugins not explicitly named. @@ -32,7 +41,7 @@ module Gitlab config.encoding = "utf-8" # Configure sensitive parameters which will be filtered from the log file. - # + # # Parameters filtered: # - Password (:password, :password_confirmation) # - Private tokens (:private_token) @@ -71,6 +80,9 @@ module Gitlab config.assets.precompile << "*.png" config.assets.precompile << "print.css" config.assets.precompile << "notify.css" + config.assets.precompile << "mailers/*.css" + config.assets.precompile << "graphs/application.js" + config.assets.precompile << "users/application.js" # Version of your assets, change this if you want to expire all your assets config.assets.version = '1.0' diff --git a/config/boot.rb b/config/boot.rb index 4489e58688..f2830ae316 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -3,4 +3,4 @@ require 'rubygems' # Set up gems listed in the Gemfile. ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) -require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) +require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) diff --git a/config/environments/development.rb b/config/environments/development.rb index 4f39016bfa..8cca0039b4 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -39,6 +39,7 @@ Rails.application.configure do config.action_mailer.delivery_method = :letter_opener_web # Don't make a mess when bootstrapping a development environment config.action_mailer.perform_deliveries = (ENV['BOOTSTRAP'] != '1') + config.action_mailer.preview_path = 'spec/mailers/previews' config.eager_load = false end diff --git a/config/environments/test.rb b/config/environments/test.rb index a703c0934f..fb25d3a8b1 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -20,7 +20,7 @@ Rails.application.configure do config.action_dispatch.show_exceptions = false # Disable request forgery protection in test environment - config.action_controller.allow_forgery_protection = false + config.action_controller.allow_forgery_protection = false # Tell Action Mailer not to deliver emails to the real world. # The :test delivery method accumulates sent emails in the diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index e682bcb976..0510e7df59 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -98,6 +98,7 @@ production: &base wiki: true snippets: false builds: true + container_registry: true ## Webhook settings # Number of seconds to wait for HTTP response after sending webhook HTTP POST request (default: 10) @@ -175,6 +176,15 @@ production: &base repository_archive_cache_worker: cron: "0 * * * *" + registry: + # enabled: true + # host: registry.example.com + # port: 5005 + # api_url: http://localhost:5000/ # internal address to the registry, will be used by GitLab to directly communicate with API + # key_path: config/registry.key + # path: shared/registry + # issuer: gitlab-issuer + # # 2. GitLab CI settings # ========================== diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index 8db2c05fe4..436751b9d1 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -1,4 +1,4 @@ -require 'gitlab' # Load lib/gitlab.rb as soon as possible +require_dependency Rails.root.join('lib/gitlab') # Load Gitlab as soon as possible class Settings < Settingslogic source ENV.fetch('GITLAB_CONFIG') { "#{Rails.root}/config/gitlab.yml" } @@ -52,7 +52,7 @@ class Settings < Settingslogic # check that values in `current` (string or integer) is a contant in `modul`. def verify_constant_array(modul, current, default) values = default || [] - if !current.nil? + unless current.nil? values = [] current.each do |constant| values.push(verify_constant(modul, constant, nil)) @@ -126,7 +126,7 @@ end Settings['omniauth'] ||= Settingslogic.new({}) -Settings.omniauth['enabled'] = false if Settings.omniauth['enabled'].nil? +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? Settings.omniauth['allow_single_sign_on'] = false if Settings.omniauth['allow_single_sign_on'].nil? Settings.omniauth['external_providers'] = [] if Settings.omniauth['external_providers'].nil? @@ -134,7 +134,7 @@ Settings.omniauth['block_auto_created_users'] = true if Settings.omniauth['block Settings.omniauth['auto_link_ldap_user'] = false if Settings.omniauth['auto_link_ldap_user'].nil? Settings.omniauth['auto_link_saml_user'] = false if Settings.omniauth['auto_link_saml_user'].nil? -Settings.omniauth['providers'] ||= [] +Settings.omniauth['providers'] ||= [] Settings.omniauth['cas3'] ||= Settingslogic.new({}) Settings.omniauth.cas3['session_duration'] ||= 8.hours Settings.omniauth['session_tickets'] ||= Settingslogic.new({}) @@ -168,7 +168,7 @@ end Settings['shared'] ||= Settingslogic.new({}) Settings.shared['path'] = File.expand_path(Settings.shared['path'] || "shared", Rails.root) -Settings['issues_tracker'] ||= {} +Settings['issues_tracker'] ||= {} # # GitLab @@ -183,7 +183,7 @@ Settings.gitlab['ssh_host'] ||= Settings.gitlab.host Settings.gitlab['https'] = false if Settings.gitlab['https'].nil? Settings.gitlab['port'] ||= Settings.gitlab.https ? 443 : 80 Settings.gitlab['relative_url_root'] ||= ENV['RAILS_RELATIVE_URL_ROOT'] || '' -Settings.gitlab['protocol'] ||= Settings.gitlab.https ? "https" : "http" +Settings.gitlab['protocol'] ||= Settings.gitlab.https ? "https" : "http" Settings.gitlab['email_enabled'] ||= true if Settings.gitlab['email_enabled'].nil? Settings.gitlab['email_from'] ||= ENV['GITLAB_EMAIL_FROM'] || "gitlab@#{Settings.gitlab.host}" Settings.gitlab['email_display_name'] ||= ENV['GITLAB_EMAIL_DISPLAY_NAME'] || 'GitLab' @@ -196,7 +196,7 @@ Settings.gitlab['user_home'] ||= begin rescue ArgumentError # no user configured '/home/' + Settings.gitlab['user'] end -Settings.gitlab['time_zone'] ||= nil +Settings.gitlab['time_zone'] ||= nil Settings.gitlab['signup_enabled'] ||= true if Settings.gitlab['signup_enabled'].nil? Settings.gitlab['signin_enabled'] ||= true if Settings.gitlab['signin_enabled'].nil? Settings.gitlab['restricted_visibility_levels'] = Settings.send(:verify_constant_array, Gitlab::VisibilityLevel, Settings.gitlab['restricted_visibility_levels'], []) @@ -206,12 +206,13 @@ Settings.gitlab['default_projects_features'] ||= {} Settings.gitlab['webhook_timeout'] ||= 10 Settings.gitlab['max_attachment_size'] ||= 10 Settings.gitlab['session_expire_delay'] ||= 10080 -Settings.gitlab.default_projects_features['issues'] = true if Settings.gitlab.default_projects_features['issues'].nil? -Settings.gitlab.default_projects_features['merge_requests'] = true if Settings.gitlab.default_projects_features['merge_requests'].nil? -Settings.gitlab.default_projects_features['wiki'] = true if Settings.gitlab.default_projects_features['wiki'].nil? -Settings.gitlab.default_projects_features['snippets'] = false if Settings.gitlab.default_projects_features['snippets'].nil? -Settings.gitlab.default_projects_features['builds'] = true if Settings.gitlab.default_projects_features['builds'].nil? -Settings.gitlab.default_projects_features['visibility_level'] = Settings.send(:verify_constant, Gitlab::VisibilityLevel, Settings.gitlab.default_projects_features['visibility_level'], Gitlab::VisibilityLevel::PRIVATE) +Settings.gitlab.default_projects_features['issues'] = true if Settings.gitlab.default_projects_features['issues'].nil? +Settings.gitlab.default_projects_features['merge_requests'] = true if Settings.gitlab.default_projects_features['merge_requests'].nil? +Settings.gitlab.default_projects_features['wiki'] = true if Settings.gitlab.default_projects_features['wiki'].nil? +Settings.gitlab.default_projects_features['snippets'] = false if Settings.gitlab.default_projects_features['snippets'].nil? +Settings.gitlab.default_projects_features['builds'] = true if Settings.gitlab.default_projects_features['builds'].nil? +Settings.gitlab.default_projects_features['container_registry'] = true if Settings.gitlab.default_projects_features['container_registry'].nil? +Settings.gitlab.default_projects_features['visibility_level'] = Settings.send(:verify_constant, Gitlab::VisibilityLevel, Settings.gitlab.default_projects_features['visibility_level'], Gitlab::VisibilityLevel::PRIVATE) Settings.gitlab['repository_downloads_path'] = File.join(Settings.shared['path'], 'cache/archive') if Settings.gitlab['repository_downloads_path'].nil? Settings.gitlab['restricted_signup_domains'] ||= [] Settings.gitlab['import_sources'] ||= ['github','bitbucket','gitlab','gitorious','google_code','fogbugz','git'] @@ -225,8 +226,8 @@ Settings['gitlab_ci'] ||= Settingslogic.new({}) Settings.gitlab_ci['shared_runners_enabled'] = true if Settings.gitlab_ci['shared_runners_enabled'].nil? Settings.gitlab_ci['all_broken_builds'] = true if Settings.gitlab_ci['all_broken_builds'].nil? Settings.gitlab_ci['add_pusher'] = false if Settings.gitlab_ci['add_pusher'].nil? -Settings.gitlab_ci['url'] ||= Settings.send(:build_gitlab_ci_url) Settings.gitlab_ci['builds_path'] = File.expand_path(Settings.gitlab_ci['builds_path'] || "builds/", Rails.root) +Settings.gitlab_ci['url'] ||= Settings.send(:build_gitlab_ci_url) # # Reply by email @@ -240,7 +241,20 @@ Settings.incoming_email['enabled'] = false if Settings.incoming_email['enabled'] Settings['artifacts'] ||= Settingslogic.new({}) Settings.artifacts['enabled'] = true if Settings.artifacts['enabled'].nil? Settings.artifacts['path'] = File.expand_path(Settings.artifacts['path'] || File.join(Settings.shared['path'], "artifacts"), Rails.root) -Settings.artifacts['max_size'] ||= 100 # in megabytes +Settings.artifacts['max_size'] ||= 100 # in megabytes + +# +# Registry +# +Settings['registry'] ||= Settingslogic.new({}) +Settings.registry['enabled'] ||= false +Settings.registry['host'] ||= "example.com" +Settings.registry['port'] ||= nil +Settings.registry['api_url'] ||= "http://localhost:5000/" +Settings.registry['key'] ||= nil +Settings.registry['issuer'] ||= nil +Settings.registry['host_port'] ||= [Settings.registry['host'], Settings.registry['port']].compact.join(':') +Settings.registry['path'] = File.expand_path(Settings.registry['path'] || File.join(Settings.shared['path'], 'registry'), Rails.root) # # Git LFS @@ -298,7 +312,7 @@ Settings['backup'] ||= Settingslogic.new({}) Settings.backup['keep_time'] ||= 0 Settings.backup['pg_schema'] = nil Settings.backup['path'] = File.expand_path(Settings.backup['path'] || "tmp/backups/", Rails.root) -Settings.backup['archive_permissions'] ||= 0600 +Settings.backup['archive_permissions'] ||= 0600 Settings.backup['upload'] ||= Settingslogic.new({ 'remote_directory' => nil, 'connection' => nil }) # Convert upload connection settings to use symbol keys, to make Fog happy if Settings.backup['upload']['connection'] diff --git a/config/initializers/5_backend.rb b/config/initializers/5_backend.rb index 80d641d73a..e026151a03 100644 --- a/config/initializers/5_backend.rb +++ b/config/initializers/5_backend.rb @@ -1,11 +1,11 @@ # GIT over HTTP -require Rails.root.join("lib", "gitlab", "backend", "grack_auth") +require_dependency Rails.root.join('lib/gitlab/backend/grack_auth') # GIT over SSH -require Rails.root.join("lib", "gitlab", "backend", "shell") +require_dependency Rails.root.join('lib/gitlab/backend/shell') # GitLab shell adapter -require Rails.root.join("lib", "gitlab", "backend", "shell_adapter") +require_dependency Rails.root.join('lib/gitlab/backend/shell_adapter') required_version = Gitlab::VersionInfo.parse(Gitlab::Shell.version_required) current_version = Gitlab::VersionInfo.parse(Gitlab::Shell.new.version) diff --git a/config/initializers/carrierwave.rb b/config/initializers/carrierwave.rb index df28d30d75..1933afcbfb 100644 --- a/config/initializers/carrierwave.rb +++ b/config/initializers/carrierwave.rb @@ -2,7 +2,7 @@ CarrierWave::SanitizedFile.sanitize_regexp = /[^[:word:]\.\-\+]/ aws_file = Rails.root.join('config', 'aws.yml') -if File.exists?(aws_file) +if File.exist?(aws_file) AWS_CONFIG = YAML.load(File.read(aws_file))[Rails.env] CarrierWave.configure do |config| @@ -20,7 +20,7 @@ if File.exists?(aws_file) config.fog_public = false # optional, defaults to {} - config.fog_attributes = { 'Cache-Control'=>'max-age=315576000' } + config.fog_attributes = { 'Cache-Control' => 'max-age=315576000' } # optional time (in seconds) that authenticated urls will be valid. # when fog_public is false and provider is AWS or Google, defaults to 600 diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 31dceaebca..021bdb1125 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -243,7 +243,7 @@ Devise.setup do |config| when Hash # Add procs for handling SLO if provider['name'] == 'cas3' - provider['args'][:on_single_sign_out] = lambda do |request| + provider['args'][:on_single_sign_out] = lambda do |request| ticket = request.params[:session_index] raise "Service Ticket not found." unless Gitlab::OAuth::Session.valid?(:cas3, ticket) Gitlab::OAuth::Session.destroy(:cas3, ticket) diff --git a/config/initializers/devise_async.rb b/config/initializers/devise_async.rb deleted file mode 100644 index 05a1852cdb..0000000000 --- a/config/initializers/devise_async.rb +++ /dev/null @@ -1 +0,0 @@ -Devise::Async.backend = :sidekiq diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb index 66ac88e9f4..7bd1310504 100644 --- a/config/initializers/doorkeeper.rb +++ b/config/initializers/doorkeeper.rb @@ -52,7 +52,7 @@ Doorkeeper.configure do # For more information go to # https://github.com/doorkeeper-gem/doorkeeper/wiki/Using-Scopes default_scopes :api - #optional_scopes :write, :update + # optional_scopes :write, :update # Change the way client credentials are retrieved from the request object. # By default it retrieves first from the `HTTP_AUTHORIZATION` header, then @@ -71,7 +71,7 @@ Doorkeeper.configure do # The value can be any string. Use nil to disable this feature. When disabled, clients must provide a valid URL # (Similar behaviour: https://developers.google.com/accounts/docs/OAuth2InstalledApp#choosingredirecturi) # - native_redirect_uri nil#'urn:ietf:wg:oauth:2.0:oob' + native_redirect_uri nil # 'urn:ietf:wg:oauth:2.0:oob' # Specify what grant flows are enabled in array of Strings. The valid # strings and the flows they enable are: diff --git a/config/initializers/health_check.rb b/config/initializers/health_check.rb new file mode 100644 index 0000000000..79e2d23ab2 --- /dev/null +++ b/config/initializers/health_check.rb @@ -0,0 +1,3 @@ +HealthCheck.setup do |config| + config.standard_checks = ['database', 'migrations', 'cache'] +end diff --git a/config/initializers/metrics.rb b/config/initializers/metrics.rb index b2d08d87ba..0c78871471 100644 --- a/config/initializers/metrics.rb +++ b/config/initializers/metrics.rb @@ -12,6 +12,7 @@ if Gitlab::Metrics.enabled? Gitlab::Application.configure do |config| config.middleware.use(Gitlab::Metrics::RackMiddleware) + config.middleware.use(Gitlab::Middleware::RailsQueueDuration) end Sidekiq.configure_server do |config| @@ -118,6 +119,8 @@ if Gitlab::Metrics.enabled? # Instrument the classes used for checking if somebody has push access. config.instrument_instance_methods(Gitlab::GitAccess) config.instrument_instance_methods(Gitlab::GitAccessWiki) + + config.instrument_instance_methods(API::Helpers) end GC::Profiler.enable diff --git a/config/initializers/monkey_patch.rb b/config/initializers/monkey_patch.rb deleted file mode 100644 index 62b05a5528..0000000000 --- a/config/initializers/monkey_patch.rb +++ /dev/null @@ -1,48 +0,0 @@ -## This patch is from rails 4.2-stable. Remove it when 4.2.6 is released -## https://github.com/rails/rails/issues/21108 - -module ActiveRecord - module ConnectionAdapters - class AbstractMysqlAdapter < AbstractAdapter - # SHOW VARIABLES LIKE 'name' - def show_variable(name) - variables = select_all("select @@#{name} as 'Value'", 'SCHEMA') - variables.first['Value'] unless variables.empty? - rescue ActiveRecord::StatementInvalid - nil - end - - - # MySQL is too stupid to create a temporary table for use subquery, so we have - # to give it some prompting in the form of a subsubquery. Ugh! - def subquery_for(key, select) - subsubselect = select.clone - subsubselect.projections = [key] - - subselect = Arel::SelectManager.new(select.engine) - subselect.project Arel.sql(key.name) - # Materialized subquery by adding distinct - # to work with MySQL 5.7.6 which sets optimizer_switch='derived_merge=on' - subselect.from subsubselect.distinct.as('__active_record_temp') - end - end - end -end - -module ActiveRecord - module ConnectionAdapters - class MysqlAdapter < AbstractMysqlAdapter - ADAPTER_NAME = 'MySQL'.freeze - - # Get the client encoding for this database - def client_encoding - return @client_encoding if @client_encoding - - result = exec_query( - "select @@character_set_client", - 'SCHEMA') - @client_encoding = ENCODINGS[result.rows.last.last] - end - end - end -end diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb index 4c164119ff..26c30e523a 100644 --- a/config/initializers/omniauth.rb +++ b/config/initializers/omniauth.rb @@ -13,7 +13,7 @@ end OmniAuth.config.full_host = Settings.gitlab['base_url'] OmniAuth.config.allowed_request_methods = [:post] -#In case of auto sign-in, the GET method is used (users don't get to click on a button) +# In case of auto sign-in, the GET method is used (users don't get to click on a button) OmniAuth.config.allowed_request_methods << :get if Gitlab.config.omniauth.auto_sign_in_with_provider.present? OmniAuth.config.before_request_phase do |env| OmniAuth::RequestForgeryProtection.call(env) diff --git a/config/initializers/premailer.rb b/config/initializers/premailer.rb index b9176688bc..cb00d3cfe9 100644 --- a/config/initializers/premailer.rb +++ b/config/initializers/premailer.rb @@ -3,6 +3,6 @@ Premailer::Rails.config.merge!( generate_text_part: false, preserve_styles: true, remove_comments: true, - remove_ids: true, + remove_ids: false, remove_scripts: false ) diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb index 599dabb9e5..0d9d87bac0 100644 --- a/config/initializers/session_store.rb +++ b/config/initializers/session_store.rb @@ -23,6 +23,6 @@ else secure: Gitlab.config.gitlab.https, httponly: true, expires_in: Settings.gitlab['session_expire_delay'] * 60, - path: (Rails.application.config.relative_url_root.nil?) ? '/' : Gitlab::Application.config.relative_url_root + path: Rails.application.config.relative_url_root.nil? ? '/' : Gitlab::Application.config.relative_url_root ) end diff --git a/config/routes.rb b/config/routes.rb index dafecc9464..428302d0fd 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -56,6 +56,7 @@ Rails.application.routes.draw do # Autocomplete get '/autocomplete/users' => 'autocomplete#users' get '/autocomplete/users/:id' => 'autocomplete#user' + get '/autocomplete/projects' => 'autocomplete#projects' # Emojis resources :emojis, only: :index @@ -64,6 +65,9 @@ Rails.application.routes.draw do get 'search' => 'search#show' get 'search/autocomplete' => 'search#autocomplete', as: :search_autocomplete + # JSON Web Token + get 'jwt/auth' => 'jwt#auth' + # API API::API.logger Rails.logger mount API::API => '/api' @@ -73,6 +77,9 @@ Rails.application.routes.draw do mount Sidekiq::Web, at: '/admin/sidekiq', as: :sidekiq end + # Health check + get 'health_check(/:checks)' => 'health_check#index', as: :health_check + # Enable Grack support mount Grack::AuthSpawner, at: '/', constraints: lambda { |request| /[-\/\w\.]+\.git\//.match(request.path_info) }, via: [:get, :post, :put] @@ -80,7 +87,7 @@ Rails.application.routes.draw do get 'help' => 'help#index' get 'help/:category/:file' => 'help#show', as: :help_page, constraints: { category: /.*/, file: /[^\/\.]+/ } get 'help/shortcuts' - get 'help/ui' => 'help#ui' + get 'help/ui' => 'help#ui' # # Global snippets @@ -91,7 +98,8 @@ Rails.application.routes.draw do end end - get '/s/:username' => 'snippets#index', as: :user_snippets, constraints: { username: /.*/ } + get '/s/:username', to: redirect('/u/%{username}/snippets'), + constraints: { username: /[a-zA-Z.0-9_\-]+(? 'users#calendar', as: :user_calendar, - constraints: { username: /.*/ } - - get 'u/:username/calendar_activities' => 'users#calendar_activities', as: :user_calendar_activities, - constraints: { username: /.*/ } - - get 'u/:username/groups' => 'users#groups', as: :user_groups, - constraints: { username: /.*/ } - - get 'u/:username/projects' => 'users#projects', as: :user_projects, - constraints: { username: /.*/ } - - get 'u/:username/contributed' => 'users#contributed', as: :user_contributed_projects, - constraints: { username: /.*/ } - - get '/u/:username' => 'users#show', as: :user, - constraints: { username: /[a-zA-Z.0-9_\-]+(? 'omniauth_callbacks#omniauth_error', as: :omniauth_error @@ -659,9 +668,16 @@ Rails.application.routes.draw do end resources :protected_branches, only: [:index, :create, :update, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } - resource :variables, only: [:show, :update] + resources :variables, only: [:index, :show, :update, :create, :destroy] resources :triggers, only: [:index, :create, :destroy] + resources :pipelines, only: [:index, :new, :create, :show] do + member do + post :cancel + post :retry + end + end + resources :builds, only: [:index, :show], constraints: { id: /\d+/ } do collection do post :cancel_all @@ -672,6 +688,7 @@ Rails.application.routes.draw do post :cancel post :retry post :erase + get :trace get :raw end @@ -688,6 +705,8 @@ Rails.application.routes.draw do end end + resources :container_registry, only: [:index, :destroy], constraints: { id: Gitlab::Regex.container_registry_reference_regex } + resources :milestones, constraints: { id: /\d+/ } do member do put :sort_issues @@ -774,7 +793,7 @@ Rails.application.routes.draw do end # Get all keys of user - get ':username.keys' => 'profiles/keys#get_keys' , constraints: { username: /.*/ } + get ':username.keys' => 'profiles/keys#get_keys', constraints: { username: /.*/ } get ':id' => 'namespaces#show', constraints: { id: /(?:[^.]|\.(?!atom$))+/, format: /atom/ } end diff --git a/db/migrate/20160302152808_remove_wrong_import_url_from_projects.rb b/db/migrate/20160302152808_remove_wrong_import_url_from_projects.rb index 8a351cf27a..6aed0fe03d 100644 --- a/db/migrate/20160302152808_remove_wrong_import_url_from_projects.rb +++ b/db/migrate/20160302152808_remove_wrong_import_url_from_projects.rb @@ -24,11 +24,11 @@ class RemoveWrongImportUrlFromProjects < ActiveRecord::Migration def process_projects_with_wrong_url projects_with_wrong_import_url.each do |project| begin - import_url = Gitlab::ImportUrl.new(project["import_url"]) + import_url = Gitlab::UrlSanitizer.new(project["import_url"]) update_import_url(import_url, project) update_import_data(import_url, project) - rescue URI::InvalidURIError + rescue Addressable::URI::InvalidURIError nullify_import_url(project) end end diff --git a/db/migrate/20160308212903_add_default_group_visibility_to_application_settings.rb b/db/migrate/20160308212903_add_default_group_visibility_to_application_settings.rb index 75de5f70fa..72b862d67d 100644 --- a/db/migrate/20160308212903_add_default_group_visibility_to_application_settings.rb +++ b/db/migrate/20160308212903_add_default_group_visibility_to_application_settings.rb @@ -7,7 +7,9 @@ class AddDefaultGroupVisibilityToApplicationSettings < ActiveRecord::Migration add_column :application_settings, :default_group_visibility, :integer # Unfortunately, this can't be a `default`, since we don't want the configuration specific # `allowed_visibility_level` to end up in schema.rb - execute("UPDATE application_settings SET default_group_visibility = #{allowed_visibility_level}") + + visibility_level = allowed_visibility_level || Gitlab::VisibilityLevel::PRIVATE + execute("UPDATE application_settings SET default_group_visibility = #{visibility_level}") end def down diff --git a/db/migrate/20160407120251_add_images_enabled_for_project.rb b/db/migrate/20160407120251_add_images_enabled_for_project.rb new file mode 100644 index 0000000000..47f0ca8e8d --- /dev/null +++ b/db/migrate/20160407120251_add_images_enabled_for_project.rb @@ -0,0 +1,5 @@ +class AddImagesEnabledForProject < ActiveRecord::Migration + def change + add_column :projects, :container_registry_enabled, :boolean + end +end diff --git a/db/migrate/20160504091942_add_disabled_oauth_sign_in_sources_to_application_settings.rb b/db/migrate/20160504091942_add_disabled_oauth_sign_in_sources_to_application_settings.rb new file mode 100644 index 0000000000..facd33875b --- /dev/null +++ b/db/migrate/20160504091942_add_disabled_oauth_sign_in_sources_to_application_settings.rb @@ -0,0 +1,5 @@ +class AddDisabledOauthSignInSourcesToApplicationSettings < ActiveRecord::Migration + def change + add_column :application_settings, :disabled_oauth_sign_in_sources, :text + end +end diff --git a/db/migrate/20160504112519_add_run_untagged_to_ci_runner.rb b/db/migrate/20160504112519_add_run_untagged_to_ci_runner.rb new file mode 100644 index 0000000000..84e5e4eabe --- /dev/null +++ b/db/migrate/20160504112519_add_run_untagged_to_ci_runner.rb @@ -0,0 +1,13 @@ +class AddRunUntaggedToCiRunner < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + disable_ddl_transaction! + + def up + add_column_with_default(:ci_runners, :run_untagged, :boolean, + default: true, allow_null: false) + end + + def down + remove_column(:ci_runners, :run_untagged) + end +end diff --git a/db/migrate/20160508215820_add_type_to_notes.rb b/db/migrate/20160508215820_add_type_to_notes.rb new file mode 100644 index 0000000000..58944d4e65 --- /dev/null +++ b/db/migrate/20160508215820_add_type_to_notes.rb @@ -0,0 +1,5 @@ +class AddTypeToNotes < ActiveRecord::Migration + def change + add_column :notes, :type, :string + end +end diff --git a/db/migrate/20160508221410_set_type_on_legacy_diff_notes.rb b/db/migrate/20160508221410_set_type_on_legacy_diff_notes.rb new file mode 100644 index 0000000000..c3f23d89d5 --- /dev/null +++ b/db/migrate/20160508221410_set_type_on_legacy_diff_notes.rb @@ -0,0 +1,5 @@ +class SetTypeOnLegacyDiffNotes < ActiveRecord::Migration + def change + execute "UPDATE notes SET type = 'LegacyDiffNote' WHERE line_code IS NOT NULL" + end +end diff --git a/db/migrate/20160509201028_add_health_check_access_token_to_application_settings.rb b/db/migrate/20160509201028_add_health_check_access_token_to_application_settings.rb new file mode 100644 index 0000000000..9d729fec18 --- /dev/null +++ b/db/migrate/20160509201028_add_health_check_access_token_to_application_settings.rb @@ -0,0 +1,5 @@ +class AddHealthCheckAccessTokenToApplicationSettings < ActiveRecord::Migration + def change + add_column :application_settings, :health_check_access_token, :string + end +end diff --git a/db/migrate/20160516174813_add_send_user_confirmation_email_to_application_settings.rb b/db/migrate/20160516174813_add_send_user_confirmation_email_to_application_settings.rb new file mode 100644 index 0000000000..c34e7ba540 --- /dev/null +++ b/db/migrate/20160516174813_add_send_user_confirmation_email_to_application_settings.rb @@ -0,0 +1,12 @@ +class AddSendUserConfirmationEmailToApplicationSettings < ActiveRecord::Migration + def up + add_column :application_settings, :send_user_confirmation_email, :boolean, default: false + + #Sets confirmation email to true by default on existing installations. + execute "UPDATE application_settings SET send_user_confirmation_email=true" + end + + def down + remove_column :application_settings, :send_user_confirmation_email + end +end diff --git a/db/migrate/20160525205328_remove_main_language_from_projects.rb b/db/migrate/20160525205328_remove_main_language_from_projects.rb new file mode 100644 index 0000000000..0f9d60c385 --- /dev/null +++ b/db/migrate/20160525205328_remove_main_language_from_projects.rb @@ -0,0 +1,21 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class RemoveMainLanguageFromProjects < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + # When using the methods "add_concurrent_index" or "add_column_with_default" + # you must disable the use of transactions as these methods can not run in an + # existing transaction. When using "add_concurrent_index" make sure that this + # method is the _only_ method called in the migration, any other changes + # should go in a separate migration. This ensures that upon failure _only_ the + # index creation fails and can be retried or reverted easily. + # + # To disable transactions uncomment the following line and remove these + # comments: + # disable_ddl_transaction! + + def change + remove_column :projects, :main_language + end +end diff --git a/db/migrate/20160527020117_remove_notification_settings_for_deleted_projects.rb b/db/migrate/20160527020117_remove_notification_settings_for_deleted_projects.rb new file mode 100644 index 0000000000..7910120b4e --- /dev/null +++ b/db/migrate/20160527020117_remove_notification_settings_for_deleted_projects.rb @@ -0,0 +1,13 @@ +class RemoveNotificationSettingsForDeletedProjects < ActiveRecord::Migration + def up + execute <<-SQL + DELETE FROM notification_settings + WHERE notification_settings.source_type = 'Project' + AND NOT EXISTS ( + SELECT * + FROM projects + WHERE projects.id = notification_settings.source_id + ) + SQL + end +end diff --git a/db/migrate/20160528043124_add_users_state_index.rb b/db/migrate/20160528043124_add_users_state_index.rb new file mode 100644 index 0000000000..e77a546073 --- /dev/null +++ b/db/migrate/20160528043124_add_users_state_index.rb @@ -0,0 +1,9 @@ +class AddUsersStateIndex < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + disable_ddl_transaction! + + def change + add_concurrent_index :users, :state + end +end diff --git a/db/migrate/20160530150109_add_container_registry_token_expire_delay_to_application_settings.rb b/db/migrate/20160530150109_add_container_registry_token_expire_delay_to_application_settings.rb new file mode 100644 index 0000000000..e21376bd57 --- /dev/null +++ b/db/migrate/20160530150109_add_container_registry_token_expire_delay_to_application_settings.rb @@ -0,0 +1,9 @@ +# This is ONLINE migration + +class AddContainerRegistryTokenExpireDelayToApplicationSettings < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + def change + add_column :application_settings, :container_registry_token_expire_delay, :integer, default: 5 + end +end diff --git a/db/schema.rb b/db/schema.rb index 71d953afe3..b2af810f60 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160508194200) do +ActiveRecord::Schema.define(version: 20160530150109) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -43,43 +43,47 @@ ActiveRecord::Schema.define(version: 20160508194200) do t.datetime "created_at" t.datetime "updated_at" t.string "home_page_url" - t.integer "default_branch_protection", default: 2 + t.integer "default_branch_protection", default: 2 t.text "restricted_visibility_levels" - t.boolean "version_check_enabled", default: true - t.integer "max_attachment_size", default: 10, null: false + t.boolean "version_check_enabled", default: true + t.integer "max_attachment_size", default: 10, null: false t.integer "default_project_visibility" t.integer "default_snippet_visibility" t.text "restricted_signup_domains" - t.boolean "user_oauth_applications", default: true + t.boolean "user_oauth_applications", default: true t.string "after_sign_out_path" - t.integer "session_expire_delay", default: 10080, null: false + t.integer "session_expire_delay", default: 10080, null: false t.text "import_sources" t.text "help_page_text" t.string "admin_notification_email" - t.boolean "shared_runners_enabled", default: true, null: false - t.integer "max_artifacts_size", default: 100, null: false + t.boolean "shared_runners_enabled", default: true, null: false + t.integer "max_artifacts_size", default: 100, null: false t.string "runners_registration_token" - t.boolean "require_two_factor_authentication", default: false - t.integer "two_factor_grace_period", default: 48 - t.boolean "metrics_enabled", default: false - t.string "metrics_host", default: "localhost" - t.integer "metrics_pool_size", default: 16 - t.integer "metrics_timeout", default: 10 - t.integer "metrics_method_call_threshold", default: 10 - t.boolean "recaptcha_enabled", default: false + t.boolean "require_two_factor_authentication", default: false + t.integer "two_factor_grace_period", default: 48 + t.boolean "metrics_enabled", default: false + t.string "metrics_host", default: "localhost" + t.integer "metrics_pool_size", default: 16 + t.integer "metrics_timeout", default: 10 + t.integer "metrics_method_call_threshold", default: 10 + t.boolean "recaptcha_enabled", default: false t.string "recaptcha_site_key" t.string "recaptcha_private_key" - t.integer "metrics_port", default: 8089 - t.boolean "akismet_enabled", default: false + t.integer "metrics_port", default: 8089 + t.boolean "akismet_enabled", default: false t.string "akismet_api_key" - t.integer "metrics_sample_interval", default: 15 - t.boolean "sentry_enabled", default: false + t.integer "metrics_sample_interval", default: 15 + t.boolean "sentry_enabled", default: false t.string "sentry_dsn" - t.boolean "email_author_in_body", default: false + t.boolean "email_author_in_body", default: false t.integer "default_group_visibility" - t.boolean "repository_checks_enabled", default: false + t.boolean "repository_checks_enabled", default: false t.text "shared_runners_text" - t.integer "metrics_packet_size", default: 1 + t.integer "metrics_packet_size", default: 1 + t.text "disabled_oauth_sign_in_sources" + t.string "health_check_access_token" + t.boolean "send_user_confirmation_email", default: false + t.integer "container_registry_token_expire_delay", default: 5 end create_table "audit_events", force: :cascade do |t| @@ -267,6 +271,7 @@ ActiveRecord::Schema.define(version: 20160508194200) do t.string "revision" t.string "platform" t.string "architecture" + t.boolean "run_untagged", default: true, null: false end add_index "ci_runners", ["description"], name: "index_ci_runners_on_description_trigram", using: :gin, opclasses: {"description"=>"gin_trgm_ops"} @@ -634,6 +639,7 @@ ActiveRecord::Schema.define(version: 20160508194200) do t.text "st_diff" t.integer "updated_by_id" t.boolean "is_award", default: false, null: false + t.string "type" end add_index "notes", ["author_id"], name: "index_notes_on_author_id", using: :btree @@ -755,10 +761,10 @@ ActiveRecord::Schema.define(version: 20160508194200) do t.integer "build_timeout", default: 3600, null: false t.boolean "pending_delete", default: false t.boolean "public_builds", default: true, null: false - t.string "main_language" t.integer "pushes_since_gc", default: 0 t.boolean "last_repository_check_failed" t.datetime "last_repository_check_at" + t.boolean "container_registry_enabled" end add_index "projects", ["builds_enabled", "shared_runners_enabled"], name: "index_projects_on_builds_enabled_and_shared_runners_enabled", using: :btree @@ -995,6 +1001,7 @@ ActiveRecord::Schema.define(version: 20160508194200) do add_index "users", ["name"], name: "index_users_on_name", using: :btree add_index "users", ["name"], name: "index_users_on_name_trigram", using: :gin, opclasses: {"name"=>"gin_trgm_ops"} add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree + add_index "users", ["state"], name: "index_users_on_state", using: :btree add_index "users", ["username"], name: "index_users_on_username", using: :btree add_index "users", ["username"], name: "index_users_on_username_trigram", using: :gin, opclasses: {"username"=>"gin_trgm_ops"} diff --git a/doc/README.md b/doc/README.md index e358da1c42..d1345ab249 100644 --- a/doc/README.md +++ b/doc/README.md @@ -13,6 +13,7 @@ - [Profile Settings](profile/README.md) - [Project Services](project_services/project_services.md) Integrate a project with external services, such as CI and chat. - [Public access](public_access/public_access.md) Learn how you can allow public and internal access to projects. +- [Container Registry](container_registry/README.md) Learn how to use GitLab Container Registry. - [SSH](ssh/README.md) Setup your ssh keys and deploy keys for secure access to your projects. - [Webhooks](web_hooks/web_hooks.md) Let GitLab notify you when new code has been pushed to your project. - [Workflow](workflow/README.md) Using GitLab functionality and importing projects from GitHub and SVN. @@ -41,8 +42,10 @@ - [Git LFS configuration](workflow/lfs/lfs_administration.md) - [Housekeeping](administration/housekeeping.md) Keep your Git repository tidy and fast. - [GitLab Performance Monitoring](monitoring/performance/introduction.md) Configure GitLab and InfluxDB for measuring performance metrics +- [Monitoring uptime](monitoring/health_check.md) Check the server status using the health check endpoint - [Sidekiq Troubleshooting](administration/troubleshooting/sidekiq.md) Debug when Sidekiq appears hung and is not processing jobs - [High Availability](administration/high_availability/README.md) Configure multiple servers for scaling or high availability +- [Container Registry](administration/container_registry.md) Configure Docker Registry with GitLab ## Contributor documentation diff --git a/doc/administration/container_registry.md b/doc/administration/container_registry.md new file mode 100644 index 0000000000..caf9a5bef2 --- /dev/null +++ b/doc/administration/container_registry.md @@ -0,0 +1,375 @@ +# GitLab Container Registry Administration + +> **Note:** +This feature was [introduced][ce-4040] in GitLab 8.8. + +With the Docker Container Registry integrated into GitLab, every project can +have its own space to store its Docker images. + +You can read more about Docker Registry at https://docs.docker.com/registry/introduction/. + +--- + + + +**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + +- [Enable the Container Registry](#enable-the-container-registry) +- [Container Registry domain configuration](#container-registry-domain-configuration) + - [Configure Container Registry under an existing GitLab domain](#configure-container-registry-under-an-existing-gitlab-domain) + - [Configure Container Registry under its own domain](#configure-container-registry-under-its-own-domain) +- [Disable Container Registry site-wide](#disable-container-registry-site-wide) +- [Disable Container Registry per project](#disable-container-registry-per-project) +- [Disable Container Registry for new projects site-wide](#disable-container-registry-for-new-projects-site-wide) +- [Container Registry storage path](#container-registry-storage-path) +- [Storage limitations](#storage-limitations) +- [Changelog](#changelog) + + + +## Enable the Container Registry + +**Omnibus GitLab installations** + +All you have to do is configure the domain name under which the Container +Registry will listen to. Read [#container-registry-domain-configuration](#container-registry-domain-configuration) +and pick one of the two options that fits your case. + +>**Note:** +The container Registry works under HTTPS by default. Using HTTP is possible +but not recommended and out of the scope of this document. +Read the [insecure Registry documentation][docker-insecure] if you want to +implement this. + +--- + +**Installations from source** + +If you have installed GitLab from source: + +1. You will have to [install Docker Registry][registry-deploy] by yourself. +1. After the installation is complete, you will have to configure the Registry's + settings in `gitlab.yml` in order to enable it. +1. Use the sample NGINX configuration file that is found under + [`lib/support/nginx/registry-ssl`][registry-ssl] and edit it to match the + `host`, `port` and TLS certs paths. + +The contents of `gitlab.yml` are: + +``` +registry: + enabled: true + host: registry.gitlab.example.com + port: 5005 + api_url: http://localhost:5000/ + key_path: config/registry.key + path: shared/registry + issuer: gitlab-issuer +``` + +where: + +| Parameter | Description | +| --------- | ----------- | +| `enabled` | `true` or `false`. Enables the Registry in GitLab. By default this is `false`. | +| `host` | The host URL under which the Registry will run and the users will be able to use. | +| `port` | The port under which the external Registry domain will listen on. | +| `api_url` | The internal API URL under which the Registry is exposed to. It defaults to `http://localhost:5000`. | +| `key_path`| The private key location that is a pair of Registry's `rootcertbundle`. Read the [token auth configuration documentation][token-config]. | +| `path` | This should be the same directory like specified in Registry's `rootdirectory`. Read the [storage configuration documentation][storage-config]. This path needs to be readable by the GitLab user, the web-server user and the Registry user. Read more in [#container-registry-storage-path](#container-registry-storage-path). | +| `issuer` | This should be the same value as configured in Registry's `issuer`. Read the [token auth configuration documentation][token-config]. | + +>**Note:** +GitLab does not ship with a Registry init file. Hence, [restarting GitLab][restart gitlab] +will not restart the Registry should you modify its settings. Read the upstream +documentation on how to achieve that. + +## Container Registry domain configuration + +There are two ways you can configure the Registry's external domain. + +- Either [use the existing GitLab domain][existing-domain] where in that case + the Registry will have to listen on a port and reuse GitLab's TLS certificate, +- or [use a completely separate domain][new-domain] with a new TLS certificate + for that domain. + +Since the container Registry requires a TLS certificate, in the end it all boils +down to how easy or pricey is to get a new one. + +Please take this into consideration before configuring the Container Registry +for the first time. + +### Configure Container Registry under an existing GitLab domain + +If the Registry is configured to use the existing GitLab domain, you can +expose the Registry on a port so that you can reuse the existing GitLab TLS +certificate. + +Assuming that the GitLab domain is `https://gitlab.example.com` and the port the +Registry is exposed to the outside world is `4567`, here is what you need to set +in `gitlab.rb` or `gitlab.yml` if you are using Omnibus GitLab or installed +GitLab from source respectively. + +--- + +**Omnibus GitLab installations** + +1. Your `/etc/gitlab/gitlab.rb` should contain the Registry URL as well as the + path to the existing TLS certificate and key used by GitLab: + + ```ruby + registry_external_url 'https://gitlab.example.com:4567' + ``` + + Note how the `registry_external_url` is listening on HTTPS under the + existing GitLab URL, but on a different port. + + If your TLS certificate is not in `/etc/gitlab/ssl/gitlab.example.com.crt` + and key not in `/etc/gitlab/ssl/gitlab.example.com.key` uncomment the lines + below: + + ```ruby + registry_nginx['ssl_certificate'] = "/path/to/certificate.pem" + registry_nginx['ssl_certificate_key'] = "/path/to/certificate.key" + ``` + +1. Save the file and [reconfigure GitLab][] for the changes to take effect. + +--- + +**Installations from source** + +1. Open `/home/git/gitlab/config/gitlab.yml`, find the `registry` entry and + configure it with the following settings: + + ``` + registry: + enabled: true + host: gitlab.example.com + port: 4567 + ``` + +1. Save the file and [restart GitLab][] for the changes to take effect. +1. Make the relevant changes in NGINX as well (domain, port, TLS certificates path). + +--- + +Users should now be able to login to the Container Registry with their GitLab +credentials using: + +```bash +docker login gitlab.example.com:4567 +``` + +### Configure Container Registry under its own domain + +If the Registry is configured to use its own domain, you will need a TLS +certificate for that specific domain (e.g., `registry.example.com`) or maybe +a wildcard certificate if hosted under a subdomain of your existing GitLab +domain (e.g., `registry.gitlab.example.com`). + +Let's assume that you want the container Registry to be accessible at +`https://registry.gitlab.example.com`. + +--- + +**Omnibus GitLab installations** + +1. Place your TLS certificate and key in + `/etc/gitlab/ssl/registry.gitlab.example.com.crt` and + `/etc/gitlab/ssl/registry.gitlab.example.com.key` and make sure they have + correct permissions: + + ```bash + chmod 600 /etc/gitlab/ssl/registry.gitlab.example.com.* + ``` + +1. Once the TLS certificate is in place, edit `/etc/gitlab/gitlab.rb` with: + + ```ruby + registry_external_url 'https://registry.gitlab.example.com' + ``` + + Note how the `registry_external_url` is listening on HTTPS. + +1. Save the file and [reconfigure GitLab][] for the changes to take effect. + +> **Note:** +If you have a [wildcard certificate][], you need to specify the path to the +certificate in addition to the URL, in this case `/etc/gitlab/gitlab.rb` will +look like: +> +```ruby +registry_nginx['ssl_certificate'] = "/etc/gitlab/ssl/certificate.pem" +registry_nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/certificate.key" +``` + +--- + +**Installations from source** + +1. Open `/home/git/gitlab/config/gitlab.yml`, find the `registry` entry and + configure it with the following settings: + + ``` + registry: + enabled: true + host: registry.gitlab.example.com + ``` + +1. Save the file and [restart GitLab][] for the changes to take effect. +1. Make the relevant changes in NGINX as well (domain, port, TLS certificates path). + +--- + +Users should now be able to login to the Container Registry using their GitLab +credentials: + +```bash +docker login registry.gitlab.example.com +``` + +## Disable Container Registry site-wide + +>**Note:** +Disabling the Registry in the Rails GitLab application as set by the following +steps, will not remove any existing Docker images. This is handled by the +Registry application itself. + +**Omnibus GitLab** + +1. Open `/etc/gitlab/gitlab.rb` and set `registry['enable']` to `false`: + + ```ruby + registry['enable'] = false + ``` + +1. Save the file and [reconfigure GitLab][] for the changes to take effect. + +--- + +**Installations from source** + +1. Open `/home/git/gitlab/config/gitlab.yml`, find the `registry` entry and + set `enabled` to `false`: + + ``` + registry: + enabled: false + ``` + +1. Save the file and [restart GitLab][] for the changes to take effect. + +## Disable Container Registry per project + +If Registry is enabled in your GitLab instance, but you don't need it for your +project, you can disable it from your project's settings. Read the user guide +on how to achieve that. + +## Disable Container Registry for new projects site-wide + +If the Container Registry is enabled, then it will be available on all new +projects. To disable this function and let the owners of a project to enable +the Container Registry by themselves, follow the steps below. + +--- + +**Omnibus GitLab installations** + +1. Edit `/etc/gitlab/gitlab.rb` and add the following line: + + ```ruby + gitlab_rails['gitlab_default_projects_features_container_registry'] = false + ``` + +1. Save the file and [reconfigure GitLab][] for the changes to take effect. + +--- + +**Installations from source** + +1. Open `/home/git/gitlab/config/gitlab.yml`, find the `default_projects_features` + entry and configure it so that `container_registry` is set to `false`: + + ``` + ## Default project features settings + default_projects_features: + issues: true + merge_requests: true + wiki: true + snippets: false + builds: true + container_registry: false + ``` + +1. Save the file and [restart GitLab][] for the changes to take effect. + +## Container Registry storage path + +To change the storage path where Docker images will be stored, follow the +steps below. + +This path is accessible to: + +- the user running the Container Registry daemon, +- the user running GitLab + +> **Warning** You should confirm that all GitLab, Registry and web server users +have access to this directory. + +--- + +**Omnibus GitLab installations** + +The default location where images are stored in Omnibus, is +`/var/opt/gitlab/gitlab-rails/shared/registry`. To change it: + +1. Edit `/etc/gitlab/gitlab.rb`: + + ```ruby + gitlab_rails['registry_path'] = "/path/to/registry/storage" + ``` + +1. Save the file and [reconfigure GitLab][] for the changes to take effect. + +--- + +**Installations from source** + +The default location where images are stored in source installations, is +`/home/git/gitlab/shared/registry`. To change it: + +1. Open `/home/git/gitlab/config/gitlab.yml`, find the `registry` entry and + change the `path` setting: + + ``` + registry: + path: shared/registry + ``` + +1. Save the file and [restart GitLab][] for the changes to take effect. + +## Storage limitations + +Currently, there is no storage limitation, which means a user can upload an +infinite amount of Docker images with arbitrary sizes. This setting will be +configurable in future releases. + +## Changelog + +**GitLab 8.8 ([source docs][8-8-docs])** + +- GitLab Container Registry feature was introduced. + +[reconfigure gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure +[restart gitlab]: restart_gitlab.md#installations-from-source +[wildcard certificate]: https://en.wikipedia.org/wiki/Wildcard_certificate +[ce-4040]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4040 +[docker-insecure]: https://docs.docker.com/registry/insecure/ +[registry-deploy]: https://docs.docker.com/registry/deploying/ +[storage-config]: https://docs.docker.com/registry/configuration/#storage +[token-config]: https://docs.docker.com/registry/configuration/#token +[8-8-docs]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-8-stable/doc/administration/container_registry.md +[registry-ssl]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/support/nginx/registry-ssl +[existing-domain]: #configure-container-registry-under-an-existing-gitlab-domain +[new-domain]: #configure-container-registry-under-its-own-domain diff --git a/doc/administration/environment_variables.md b/doc/administration/environment_variables.md index 43ab153d76..7f53915a4d 100644 --- a/doc/administration/environment_variables.md +++ b/doc/administration/environment_variables.md @@ -58,4 +58,4 @@ to the naming scheme `GITLAB_#{name in 1_settings.rb in upper case}`. It's possible to preconfigure the GitLab docker image by adding the environment variable `GITLAB_OMNIBUS_CONFIG` to the `docker run` command. -For more information see the ['preconfigure-docker-container' section in the Omnibus documentation](http://doc.gitlab.com/omnibus/docker/#preconfigure-docker-container). +For more information see the ['preconfigure-docker-container' section in the Omnibus documentation](http://docs.gitlab.com/omnibus/docker/#preconfigure-docker-container). diff --git a/doc/administration/high_availability/README.md b/doc/administration/high_availability/README.md index 43d85ffb77..d74a786ac2 100644 --- a/doc/administration/high_availability/README.md +++ b/doc/administration/high_availability/README.md @@ -19,6 +19,8 @@ Components/Servers Required: - 2 servers/virtual machines (one active/one passive) +![Active/Passive HA Diagram](../img/high_availability/active-passive-diagram.png) + ### Active/Active This architecture scales easily because all application servers handle @@ -26,6 +28,8 @@ user requests simultaneously. The database, Redis, and GitLab application are all deployed on separate servers. The configuration is **only** highly-available if the database, Redis and storage are also configured as such. +![Active/Active HA Diagram](../img/high_availability/active-active-diagram.png) + **Steps to configure active/active:** 1. [Configure the database](database.md) diff --git a/doc/administration/high_availability/load_balancer.md b/doc/administration/high_availability/load_balancer.md index b1fe34ed9a..136f570ac2 100644 --- a/doc/administration/high_availability/load_balancer.md +++ b/doc/administration/high_availability/load_balancer.md @@ -60,4 +60,4 @@ Read more on high-availability configuration: configure custom domains with custom SSL, which would not be possible if SSL was terminated at the load balancer. -[gitlab-pages]: http://doc.gitlab.com/ee/pages/administration.html +[gitlab-pages]: http://docs.gitlab.com/ee/pages/administration.html diff --git a/doc/administration/high_availability/nfs.md b/doc/administration/high_availability/nfs.md index e4e124e200..537f4f3501 100644 --- a/doc/administration/high_availability/nfs.md +++ b/doc/administration/high_availability/nfs.md @@ -2,8 +2,8 @@ ## Required NFS Server features -**File locking**: GitLab **requires** file locking which is only supported -natively in NFS version 4. NFSv3 also supports locking as long as +**File locking**: GitLab **requires** advisory file locking, which is only +supported natively in NFS version 4. NFSv3 also supports locking as long as Linux Kernel 2.6.5+ is used. We recommend using version 4 and do not specifically test NFSv3. @@ -113,4 +113,4 @@ Read more on high-availability configuration: 1. [Configure the GitLab application servers](gitlab.md) 1. [Configure the load balancers](load_balancer.md) -[udp-log-shipping]: http://doc.gitlab.com/omnibus/settings/logs.html#udp-log-shipping-gitlab-enterprise-edition-only "UDP log shipping" +[udp-log-shipping]: http://docs.gitlab.com/omnibus/settings/logs.html#udp-log-shipping-gitlab-enterprise-edition-only "UDP log shipping" diff --git a/doc/administration/high_availability/redis.md b/doc/administration/high_availability/redis.md index d89a1e582c..f6153216f3 100644 --- a/doc/administration/high_availability/redis.md +++ b/doc/administration/high_availability/redis.md @@ -26,7 +26,7 @@ that runs Redis. ```ruby external_url 'https://gitlab.example.com' - # Disable all components except PostgreSQL + # Disable all components except Redis redis['enable'] = true bootstrap['enable'] = false nginx['enable'] = false diff --git a/doc/administration/img/high_availability/active-active-diagram.png b/doc/administration/img/high_availability/active-active-diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..81259e0ae9348a16e66407946719ddf3d75d974b GIT binary patch literal 29607 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

    =&`f@jjZ+V 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 DRoJv# literal 0 HcmV?d00001 diff --git a/doc/administration/repository_checks.md b/doc/administration/repository_checks.md index 3411e4af6a..4172b604ce 100644 --- a/doc/administration/repository_checks.md +++ b/doc/administration/repository_checks.md @@ -5,7 +5,7 @@ This feature was [introduced][ce-3232] in GitLab 8.7. It is OFF by default because it still causes too many false alarms. Git has a built-in mechanism, [git fsck][git-fsck], to verify the -integrity of all data commited to a repository. GitLab administrators +integrity of all data committed to a repository. GitLab administrators can trigger such a check for a project via the project page under the admin panel. The checks run asynchronously so it may take a few minutes before the check result is visible on the project admin page. If the @@ -41,4 +41,4 @@ alarms you can choose to clear ALL repository check states from the --- [ce-3232]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3232 "Auto git fsck" -[git-fsck]: https://www.kernel.org/pub/software/scm/git/docs/git-fsck.html "git fsck documentation" \ No newline at end of file +[git-fsck]: https://www.kernel.org/pub/software/scm/git/docs/git-fsck.html "git fsck documentation" diff --git a/doc/administration/troubleshooting/sidekiq.md b/doc/administration/troubleshooting/sidekiq.md index 134a758376..a776cd3f05 100644 --- a/doc/administration/troubleshooting/sidekiq.md +++ b/doc/administration/troubleshooting/sidekiq.md @@ -150,6 +150,14 @@ To output a backtrace from all threads at once: apply all thread bt ``` +Once you're done debugging with `gdb`, be sure to detach from the process and +exit: + +``` +detach +exit +``` + ## Check for blocking queries Sometimes the speed at which Sidekiq processes jobs can be so fast that it can diff --git a/doc/api/README.md b/doc/api/README.md index ff039f1886..27c5962dec 100644 --- a/doc/api/README.md +++ b/doc/api/README.md @@ -33,7 +33,7 @@ following locations: - [Build triggers](build_triggers.md) - [Build Variables](build_variables.md) - [Runners](runners.md) -- [Licenses](licenses.md) +- [Open source license templates](licenses.md) ## Authentication diff --git a/doc/api/build_triggers.md b/doc/api/build_triggers.md index 4a12e962b6..0881a7d7a9 100644 --- a/doc/api/build_triggers.md +++ b/doc/api/build_triggers.md @@ -101,8 +101,18 @@ DELETE /projects/:id/triggers/:token | Attribute | Type | required | Description | |-----------|---------|----------|--------------------------| | `id` | integer | yes | The ID of a project | -| `token` | string | yes | The `token` of a project | +| `token` | string | yes | The `token` of a trigger | ``` curl -X DELETE -H "PRIVATE_TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/triggers/7b9148c158980bbd9bcea92c17522d" ``` + +```json +{ + "created_at": "2015-12-23T16:25:56.760Z", + "deleted_at": "2015-12-24T12:32:20.100Z", + "last_used": null, + "token": "7b9148c158980bbd9bcea92c17522d", + "updated_at": "2015-12-24T12:32:20.100Z" +} +``` diff --git a/doc/api/groups.md b/doc/api/groups.md index 2821bc21b8..1ccb9715e9 100644 --- a/doc/api/groups.md +++ b/doc/api/groups.md @@ -265,7 +265,6 @@ GET /groups/:id/members { "id": 1, "username": "raymond_smith", - "email": "ray@smith.org", "name": "Raymond Smith", "state": "active", "created_at": "2012-10-22T14:13:35Z", @@ -274,7 +273,6 @@ GET /groups/:id/members { "id": 2, "username": "john_doe", - "email": "joh@doe.org", "name": "John Doe", "state": "active", "created_at": "2012-10-22T14:13:35Z", diff --git a/doc/api/issues.md b/doc/api/issues.md index 3e78149f44..fc7a7ae0c0 100644 --- a/doc/api/issues.md +++ b/doc/api/issues.md @@ -77,7 +77,8 @@ Example response: "created_at" : "2016-01-04T15:31:51.081Z", "iid" : 6, "labels" : [], - "subscribed" : false + "subscribed" : false, + "user_notes_count": 1 } ] ``` @@ -154,7 +155,8 @@ Example response: "title" : "Ut commodi ullam eos dolores perferendis nihil sunt.", "updated_at" : "2016-01-04T15:31:46.176Z", "created_at" : "2016-01-04T15:31:46.176Z", - "subscribed" : false + "subscribed" : false, + "user_notes_count": 1 } ] ``` @@ -216,7 +218,8 @@ Example response: "title" : "Ut commodi ullam eos dolores perferendis nihil sunt.", "updated_at" : "2016-01-04T15:31:46.176Z", "created_at" : "2016-01-04T15:31:46.176Z", - "subscribed": false + "subscribed": false, + "user_notes_count": 1 } ``` @@ -271,7 +274,8 @@ Example response: "description" : null, "updated_at" : "2016-01-07T12:44:33.959Z", "milestone" : null, - "subscribed" : true + "subscribed" : true, + "user_notes_count": 0 } ``` @@ -329,7 +333,8 @@ Example response: "id" : 85, "assignee" : null, "milestone" : null, - "subscribed" : true + "subscribed" : true, + "user_notes_count": 0 } ``` diff --git a/doc/api/labels.md b/doc/api/labels.md index 3730c07c5a..a181c0f57a 100644 --- a/doc/api/labels.md +++ b/doc/api/labels.md @@ -39,7 +39,7 @@ Example response: { "name" : "critical", "color" : "#d9534f", - "description": "Criticalissue. Need fix ASAP", + "description": "Critical issue. Need fix ASAP", "open_issues_count": 1, "closed_issues_count": 3, "open_merge_requests_count": 1 @@ -165,3 +165,73 @@ Example response: "description": "Documentation" } ``` + +## Subscribe to a label + +Subscribes the authenticated user to a label to receive notifications. If the +operation is successful, status code `201` together with the updated label is +returned. If the user is already subscribed to the label, the status code `304` +is returned. If the project or label is not found, status code `404` is +returned. + +``` +POST /projects/:id/labels/:label_id/subscription +``` + +| Attribute | Type | Required | Description | +| ---------- | ----------------- | -------- | ------------------------------------ | +| `id` | integer | yes | The ID of a project | +| `label_id` | integer or string | yes | The ID or title of a project's label | + +```bash +curl -X POST -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/labels/1/subscription +``` + +Example response: + +```json +{ + "name": "Docs", + "color": "#cc0033", + "description": "", + "open_issues_count": 0, + "closed_issues_count": 0, + "open_merge_requests_count": 0, + "subscribed": true +} +``` + +## Unsubscribe from a label + +Unsubscribes the authenticated user from a label to not receive notifications +from it. If the operation is successful, status code `200` together with the +updated label is returned. If the user is not subscribed to the label, the +status code `304` is returned. If the project or label is not found, status code +`404` is returned. + +``` +DELETE /projects/:id/labels/:label_id/subscription +``` + +| Attribute | Type | Required | Description | +| ---------- | ----------------- | -------- | ------------------------------------ | +| `id` | integer | yes | The ID of a project | +| `label_id` | integer or string | yes | The ID or title of a project's label | + +```bash +curl -X DELETE -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/labels/1/subscription +``` + +Example response: + +```json +{ + "name": "Docs", + "color": "#cc0033", + "description": "", + "open_issues_count": 0, + "closed_issues_count": 0, + "open_merge_requests_count": 0, + "subscribed": false +} +``` diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md index 2057f9d77a..8217e30fe2 100644 --- a/doc/api/merge_requests.md +++ b/doc/api/merge_requests.md @@ -67,7 +67,8 @@ Parameters: }, "merge_when_build_succeeds": true, "merge_status": "can_be_merged", - "subscribed" : false + "subscribed" : false, + "user_notes_count": 1 } ] ``` @@ -130,7 +131,8 @@ Parameters: }, "merge_when_build_succeeds": true, "merge_status": "can_be_merged", - "subscribed" : true + "subscribed" : true, + "user_notes_count": 1 } ``` @@ -230,6 +232,7 @@ Parameters: "merge_when_build_succeeds": true, "merge_status": "can_be_merged", "subscribed" : true, + "user_notes_count": 1, "changes": [ { "old_path": "VERSION", @@ -308,7 +311,8 @@ Parameters: }, "merge_when_build_succeeds": true, "merge_status": "can_be_merged", - "subscribed" : true + "subscribed" : true, + "user_notes_count": 0 } ``` @@ -378,7 +382,8 @@ Parameters: }, "merge_when_build_succeeds": true, "merge_status": "can_be_merged", - "subscribed" : true + "subscribed" : true, + "user_notes_count": 1 } ``` @@ -472,7 +477,8 @@ Parameters: }, "merge_when_build_succeeds": true, "merge_status": "can_be_merged", - "subscribed" : true + "subscribed" : true, + "user_notes_count": 1 } ``` @@ -537,7 +543,8 @@ Parameters: }, "merge_when_build_succeeds": true, "merge_status": "can_be_merged", - "subscribed" : true + "subscribed" : true, + "user_notes_count": 1 } ``` @@ -602,7 +609,8 @@ Example response: "title" : "Consequatur vero maxime deserunt laboriosam est voluptas dolorem.", "created_at" : "2016-01-04T15:31:51.081Z", "iid" : 6, - "labels" : [] + "labels" : [], + "user_notes_count": 1 }, ] ``` diff --git a/doc/api/notes.md b/doc/api/notes.md index a6b5b1787f..7aa1c2155b 100644 --- a/doc/api/notes.md +++ b/doc/api/notes.md @@ -15,7 +15,7 @@ GET /projects/:id/issues/:issue_id/notes Parameters: - `id` (required) - The ID of a project -- `issue_id` (required) - The IID of an issue (not ID) +- `issue_id` (required) - The ID of an issue ```json [ @@ -73,7 +73,7 @@ GET /projects/:id/issues/:issue_id/notes/:note_id Parameters: - `id` (required) - The ID of a project -- `issue_id` (required) - The IID of a project issue (not ID) +- `issue_id` (required) - The ID of a project issue - `note_id` (required) - The ID of an issue note ### Create new issue note @@ -87,7 +87,7 @@ POST /projects/:id/issues/:issue_id/notes Parameters: - `id` (required) - The ID of a project -- `issue_id` (required) - The IID of an issue (not ID) +- `issue_id` (required) - The ID of an issue - `body` (required) - The content of a note - `created_at` (optional) - Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z @@ -102,7 +102,7 @@ PUT /projects/:id/issues/:issue_id/notes/:note_id Parameters: - `id` (required) - The ID of a project -- `issue_id` (required) - The IID of an issue (not ID) +- `issue_id` (required) - The ID of an issue - `note_id` (required) - The ID of a note - `body` (required) - The content of a note @@ -120,7 +120,7 @@ Parameters: | Attribute | Type | Required | Description | | --------- | ---- | -------- | ----------- | | `id` | integer | yes | The ID of a project | -| `issue_id` | integer | yes | The IID of an issue | +| `issue_id` | integer | yes | The ID of an issue | | `note_id` | integer | yes | The ID of a note | ```bash diff --git a/doc/api/projects.md b/doc/api/projects.md index de1faadebf..f5f195b97d 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -424,6 +424,7 @@ Parameters: - `builds_enabled` (optional) - `wiki_enabled` (optional) - `snippets_enabled` (optional) +- `container_registry_enabled` (optional) - `public` (optional) - if `true` same as setting visibility_level = 20 - `visibility_level` (optional) - `import_url` (optional) @@ -447,6 +448,7 @@ Parameters: - `builds_enabled` (optional) - `wiki_enabled` (optional) - `snippets_enabled` (optional) +- `container_registry_enabled` (optional) - `public` (optional) - if `true` same as setting visibility_level = 20 - `visibility_level` (optional) - `import_url` (optional) @@ -472,6 +474,7 @@ Parameters: - `builds_enabled` (optional) - `wiki_enabled` (optional) - `snippets_enabled` (optional) +- `container_registry_enabled` (optional) - `public` (optional) - if `true` same as setting visibility_level = 20 - `visibility_level` (optional) - `public_builds` (optional) diff --git a/doc/api/runners.md b/doc/api/runners.md index cc6c6b7cb2..ddfa298f79 100644 --- a/doc/api/runners.md +++ b/doc/api/runners.md @@ -275,7 +275,7 @@ POST /projects/:id/runners | `runner_id` | integer | yes | The ID of a runner | ``` -curl -X POST -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/project/9/runners" -F "runner_id=9" +curl -X POST -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/9/runners" -F "runner_id=9" ``` Example response: @@ -306,7 +306,7 @@ DELETE /projects/:id/runners/:runner_id | `runner_id` | integer | yes | The ID of a runner | ``` -curl -X DELETE -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/project/9/runners/9" +curl -X DELETE -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/9/runners/9" ``` Example response: diff --git a/doc/api/services.md b/doc/api/services.md index 7d45b2cf46..ccfc0fccb7 100644 --- a/doc/api/services.md +++ b/doc/api/services.md @@ -16,8 +16,8 @@ PUT /projects/:id/services/asana Parameters: -- `api_key` (**required**) - User API token. User must have access to task,all comments will be attributed to this user. -- `restrict_to_branch` (optional) - Comma-separated list of branches which will beautomatically inspected. Leave blank to include all branches. +- `api_key` (**required**) - User API token. User must have access to task, all comments will be attributed to this user. +- `restrict_to_branch` (optional) - Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches. ### Delete Asana service @@ -491,7 +491,7 @@ Jira issue tracker Set JIRA service for a project. -> Setting `project_url`, `issues_url` and `new_issue_url` will allow a user to easily navigate to the Jira issue tracker. See the [integration doc](http://doc.gitlab.com/ce/integration/external-issue-tracker.html) for details. Support for referencing commits and automatic closing of Jira issues directly from GitLab is [available in GitLab EE.](http://doc.gitlab.com/ee/integration/jira.html) +> Setting `project_url`, `issues_url` and `new_issue_url` will allow a user to easily navigate to the Jira issue tracker. See the [integration doc](http://docs.gitlab.com/ce/integration/external-issue-tracker.html) for details. Support for referencing commits and automatic closing of Jira issues directly from GitLab is [available in GitLab EE.](http://docs.gitlab.com/ee/integration/jira.html) ``` PUT /projects/:id/services/jira @@ -503,6 +503,8 @@ Parameters: - `project_url` (**required**) - Project url - `issues_url` (**required**) - Issue url - `description` (optional) - Jira issue tracker +- `username` (optional) - Jira username +- `password` (optional) - Jira password ### Delete JIRA service diff --git a/doc/api/settings.md b/doc/api/settings.md index 1e745115dc..43a0fe35e4 100644 --- a/doc/api/settings.md +++ b/doc/api/settings.md @@ -37,7 +37,8 @@ Example response: "created_at" : "2016-01-04T15:44:55.176Z", "default_project_visibility" : 0, "gravatar_enabled" : true, - "sign_in_text" : null + "sign_in_text" : null, + "container_registry_token_expire_delay": 5 } ``` @@ -64,6 +65,7 @@ PUT /application/settings | `restricted_signup_domains` | array of strings | no | Force people to use only corporate emails for sign-up. Default is null, meaning there is no restriction. | | `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 | ```bash curl -X PUT -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/application/settings?signup_enabled=false&default_project_visibility=1 @@ -90,6 +92,7 @@ Example response: "default_snippet_visibility": 0, "restricted_signup_domains": [], "user_oauth_applications": true, - "after_sign_out_path": "" + "after_sign_out_path": "", + "container_registry_token_expire_delay": 5 } ``` diff --git a/doc/ci/deployment/README.md b/doc/ci/examples/deployment/README.md similarity index 100% rename from doc/ci/deployment/README.md rename to doc/ci/examples/deployment/README.md diff --git a/doc/ci/quick_start/README.md b/doc/ci/quick_start/README.md index 6a42a935ab..386b8e29fc 100644 --- a/doc/ci/quick_start/README.md +++ b/doc/ci/quick_start/README.md @@ -212,8 +212,8 @@ If you want to receive e-mail notifications about the result status of the builds, you should explicitly enable the **Builds Emails** service under your project's settings. -For more information read the [Builds emails service documentation] -(../../project_services/builds_emails.md). +For more information read the +[Builds emails service documentation](../../project_services/builds_emails.md). ## Builds badge diff --git a/doc/ci/runners/README.md b/doc/ci/runners/README.md index a06650b338..b42d7a62eb 100644 --- a/doc/ci/runners/README.md +++ b/doc/ci/runners/README.md @@ -125,7 +125,13 @@ shared runners will only run the jobs they are equipped to run. For instance, at GitLab we have runners tagged with "rails" if they contain the appropriate dependencies to run Rails test suites. -### Be Careful with Sensitive Information +### Prevent runner with tags from picking jobs without tags + +You can configure a runner to prevent it from picking jobs with tags when +the runnner does not have tags assigned. This setting is available on each +runner in *Project Settings* > *Runners*. + +### Be careful with sensitive information If you can run a build on a runner, you can get access to any code it runs and get the token of the runner. With shared runners, this means that anyone diff --git a/doc/ci/triggers/README.md b/doc/ci/triggers/README.md index 79ed512aab..5c316510d0 100644 --- a/doc/ci/triggers/README.md +++ b/doc/ci/triggers/README.md @@ -33,7 +33,7 @@ POST /projects/:id/trigger/builds The required parameters are the trigger's `token` and the Git `ref` on which the trigger will be performed. Valid refs are the branch, the tag or the commit -SHA. The `:id` of a project can be found by [querying the API](../api/projects.md) +SHA. The `:id` of a project can be found by [querying the API](../../api/projects.md) or by visiting the **Triggers** page which provides self-explanatory examples. When a rebuild is triggered, the information is exposed in GitLab's UI under diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md index 7e9bced761..a3481f58c6 100644 --- a/doc/ci/yaml/README.md +++ b/doc/ci/yaml/README.md @@ -128,7 +128,7 @@ builds, including deploy builds. This can be an array or a multi-line string. ### after_script >**Note:** -Introduced in GitLab 8.7 and GitLab Runner v1.2. +Introduced in GitLab 8.7 and requires Gitlab Runner v1.2 (not yet released) `after_script` is used to define the command that will be run after for all builds. This has to be an array or a multi-line string. @@ -348,7 +348,7 @@ job_name: | allow_failure | no | Allow build to fail. Failed build doesn't contribute to commit status | | when | no | Define when to run build. Can be `on_success`, `on_failure` or `always` | | dependencies | no | Define other builds that a build depends on so that you can pass artifacts between them| -| artifacts | no | Define list build artifacts | +| artifacts | no | Define list of build artifacts | | cache | no | Define list of files that should be cached between subsequent runs | | before_script | no | Override a set of commands that are executed before build | | after_script | no | Override a set of commands that are executed after build | diff --git a/doc/container_registry/README.md b/doc/container_registry/README.md new file mode 100644 index 0000000000..4df24ef13c --- /dev/null +++ b/doc/container_registry/README.md @@ -0,0 +1,113 @@ +# GitLab Container Registry + +> **Note:** +This feature was [introduced][ce-4040] in GitLab 8.8. + +> **Note:** +This document is about the user guide. To learn how to enable GitLab Container +Registry across your GitLab instance, visit the +[administrator documentation](../administration/container_registry.md). + +With the Docker Container Registry integrated into GitLab, every project can +have its own space to store its Docker images. + +You can read more about Docker Registry at https://docs.docker.com/registry/introduction/. + +--- + +## Enable the Container Registry for your project + +1. First, ask your system administrator to enable GitLab Container Registry + following the [administration documentation](../administration/container_registry.md). + If you are using GitLab.com, this is enabled by default so you can start using + the Registry immediately. + +1. Go to your project's settings and enable the **Container Registry** feature + on your project. For new projects this might be enabled by default. For + existing projects you will have to explicitly enable it. + + ![Enable Container Registry](img/project_feature.png) + +## Build and push images + +After you save your project's settings, you should see a new link in the +sidebar called **Container Registry**. Following this link will get you to +your project's Registry panel where you can see how to login to the Container +Registry using your GitLab credentials. + +For example if the Registry's URL is `registry.example.com`, the you should be +able to login with: + +``` +docker login registry.example.com +``` + +Building and publishing images should be a straightforward process. Just make +sure that you are using the Registry URL with the namespace and project name +that is hosted on GitLab: + +``` +docker build -t registry.example.com/group/project . +docker push registry.example.com/group/project +``` + +## Use images from GitLab Container Registry + +To download and run a container from images hosted in GitLab Container Registry, +use `docker run`: + +``` +docker run [options] registry.example.com/group/project [arguments] +``` + +For more information on running Docker containers, visit the +[Docker documentation][docker-docs]. + +## Control Container Registry from within GitLab + +GitLab offers a simple Container Registry management panel. Go to your project +and click **Container Registry** in the left sidebar. + +This view will show you all tags in your project and will easily allow you to +delete them. + +![Container Registry panel](img/container_registry.png) + +## Build and push images using GitLab CI + +> **Note:** +This feature requires GitLab 8.8 and GitLab Runner 1.2. + +Make sure that your GitLab Runner is configured to allow building docker images. +You have to check the [Using Docker Build documentation](../../ci/docker/using_docker_build.md). + +You can use [docker:dind](https://hub.docker.com/_/docker/) to build your images, +and this is how `.gitlab-ci.yml` should look like: + +``` + build_image: + image: docker:git + services: + - docker:dind + stage: build + script: + - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.example.com + - docker build -t registry.example.com/group/project:latest . + - docker push registry.example.com/group/project:latest +``` + +You have to use the credentials of the special `gitlab-ci-token` user with its +password stored in `$CI_BUILD_TOKEN` in order to push to the Registry connected +to your project. This allows you to automated building and deployment of your +Docker images. + +## Limitations + +In order to use a container image from your private project as an `image:` in +your `.gitlab-ci.yml`, you have to follow the +[Using a private Docker Registry][private-docker] +documentation. This workflow will be simplified in the future. + +[ce-4040]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4040 +[docker-docs]: https://docs.docker.com/engine/userguide/intro/ +[private-docker]: https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/blob/master/docs/configuration/advanced-configuration.md#using-a-private-docker-registry diff --git a/doc/container_registry/img/container_registry.png b/doc/container_registry/img/container_registry.png new file mode 100644 index 0000000000000000000000000000000000000000..e9505a73b408e29a78898014ccfc5b5f8eb80bf9 GIT binary patch literal 354050 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�yf+{HcXUO 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

    =Si7>XP2FLWJZj$ZQ*!HL+Z#wC}JsiJi%d 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 Lm*7vI{^frFZcP$s literal 0 HcmV?d00001 diff --git a/doc/container_registry/img/project_feature.png b/doc/container_registry/img/project_feature.png new file mode 100644 index 0000000000000000000000000000000000000000..57a73d253c0b8ca6c92c80fca13068e5e764a69d GIT binary patch literal 392842 zcmeFZXFOc(+CGd(kZ2(yI?)Ldy?4=j8C~?=4bdZd7YxyR9Y*gh2%<+By#-?!Eqc_v zlY2kU-uHj+_uaqb%lql?)3VmO+F6eCJdf*I6RD;mi}R55Aqol#j=Y?-1_}yR4+;tf zFXjW}9ahZOJSZsG#I{mWYVuN2)M{?dR<;h7C@6A~AOME0=HSz80}V_pHhfg(JU$5@ z(2CGx_iH({5CSPlwHn&!hmiY3kDm}3J+7&|pU_~&5&hLoE3o1%FT@lX*Z;Ba?lgku&3mZeYYc6lzVq7p4p-3X?xZBt02o3h3U=rHp?& zqFKSNAr^}63(`e9YHn}e!DrQ^;Z^;~uCldiRvh1NQNt-)BTSr@aPRGN33mILpL%gW z*}PlUKL}u(7Fc0PnH352w(fsPqh#+(5ONF2p(MhoA^i;ZCQs{lvN}o-PKUjCQ7dy- zZS@WnIv$_!Ay4l#BUhT^O6r6 z!rnD!x~d`JG*T_1GdzkD2bv{WWMqjUJL=F!A^zBoJGbGWqZ^Yc#!Jl<5t-`V>xz$h zBZ2Y;?UlpM8^JFR+Rs*CqJ7EZLF_4^TXPi9RuqFJ090cRwG zy_YQg$yp8(tCR?Hs8`$ia4%ajGu(c|xEX^IHAl31ego3H7(u1!ZJ}dE{p#H_N$ltP zF~@JDW?HJTP!CtPdrZee=jB_z%ewt|8vi}{tNdG~W{Cv+gLl&3rJq{P*^yT1{&Er{}_2&nCp%qy!VoQX_;Y+R$AUGASvL7Qk4shJv-!B}JM9H@JgJJO} z@_K0UPb-%;#vPBdLygofaQrI6rS~&{f%t3)u+#K=4^A8 zd!W%-HBfYg(_+;z#PukH{UN3rKn+!hZ|xqM#IuM8N7VO~Lbb=y zyc5o_Ut+vKFUlpaK)09RnL}@UPw|Ft4llj?u?s=w{Zw&`X4Hf3h6xHIGkI-a8BXbZusVVi zzNXrUJ$NY-6GZZ6<|FG?yo`C7?gNI;Tc(z}^g7}D-TL3!I>Y3vjrV9(KJV}oHihkS zp{stHe=91AXA%b35cJVjk7o}}4@t9E zE7m>f=N}}vX#`)N9s<*W)R8(32IZ(Z@~t6_FM(6oD10 zl8KU)ll?&@EX2$J7Am#Q{3URHu37ndRgXqmiAI5&E-Xc%i^T}4!lTcl3QR+&Kp&Nl zL*?v>?Skyc8weUI?MkLwx1TLX9H?4P5l=KtjDKx|Mk1^bd5C!g4ABN%gkEz`bCdHB z@L1VR+mJ&OUcL-trcM4ZtlK>|-aPn&`?Xih;j@E}Mds%*ErMGeTe`|r$`GrxE#pzL z^ql&S`a${v`r!KX21=Wag_H%t25XyHyPSyw3b5#m`3ql%`MF#3Lqx7%ieQak9k3B$ zII}Ygox+(R+J?-E6fJ@WzMf1B&lnVVDOJhlKn{z>r%Vb04S(L(4Biw+Q8gc>OUHQ#x+HhS}{y!Au;(B2r2 z{b{#rkzwC9dY+w?ZuHTp#t6Jj=Bw!2=pTCv#7LJ)==BSK8a^AR6K6P}Kd`9cQ6g8; zr{bt$l4+C~I_8_{YZzlRX~^5WuR*+vl6?u1?OGek64uTvc5pOxIGB;*7exAo1>VV^JL zQRRu`6E}|r-IF+qY)Zas=xfNAMV2jUUNhcT(HAQ7t)1GO9ONtcsGKGM>(SaTYtf8X z(ai2o_oR+ZNJ(zw+UH_T*B(Hq;wi5ttPGr6SDANh{&1Ob@oCOpdU#NWJsuMk15e9N z19SP-w%4)L`FP*8+pX;GCG08BAG+teBizH>lH4w~KAcP*t0y1 zWt~+pm2Rib|8O|pYZQ3k{&dWnd)Dh9#rsS9skh@v>{jZ?p)r2@n*qt8p3KlL;>D+c zCtU`~^`#BcO%@XJv#Q-R#*FPGbM`zOTU#m5(;Zd*a)tBb# z?2jRF%cyMz=emdUwW&2tepGXeD;Mjt^(M{-c&n?PpUysI2Qy&sk>^vf*h{8c@tpBk z^C;?T=nLY7Q#je5*@&EGj5?pmV#iIBL-||RpTTqoYw|W^2Ch{xRZg=_<1oa zJ3wD>Nl;&i(Sx!L;eWQ-@Xp@4D%`lsgBI}`J{pqIAE zCC8;}FK8%uC|nS4_pbVfdDUk{ zR6AIRowu)cWG)oDhr3rM#k7AeeIL4kc6a&RwJxPD&ED$&@Yx=%ZPIt%T@~oG-;Li1 zGel2Faa9rEuMQ42g&QG5}CTAPDPXx6VvZ&a++_d-J z@tvW3)mWQHUD;q#IKEC*!oSQ?5Bn6@b1amuv^H3@g7GfoK8o}wE(JCR27FCZ4v~O? zYn173(|Vj}rrvI2%IJsAuR`#oq@01M)D39gW%#+dn_X?Thk51BaZwnLVHcuh_}@qZ zPu?;kwgc`5BnP6FsW_Uei}(1WprGd1YUz6DDk}+^J3F$QS~#0ovcGk7L6#6GD8g?A zk(Z8^9;Vc99UYw91>cH1|LYAw!RGGm zkiAD#SfKhl=&=5Dqw9=6U-)W7;QHFE}fh&+G(YoLGr{bQb%Z*BiIl9T)Y zEDO0nj$cnWUa`OA_-Eh9rozAO3aZ(@wRF&xwso|0az~CK%E>LjFZ@@7|9JGTA^+A? z?_W({@pJS3z3JZ`{ZCV2j$cdo+mikvufOgh1t$7XnB$+q7kzj;-SZv=MI1$5T0-kB z>RuMsJ42bYA6+e+EsQk8Enk!+--+|5XcE%7MP&}r*m&MIlrWkA5*rb6fh(A( z-I%FU-x(56qe>sRFo;W{p%TcU$$t@$x7spU-GyW$_zr(r zzP&p0H33B8Q=_0_ild<6ze7R)znA}44*$Ozf%q(q+7z%=Qk5E?6?KKIW?h=(x5s}) zU=yuQTu%L!9&>GPiax9cA=E8gaYa*j@3&3a!ySzu4m`p7I=?)CT2?2UyIVhQh!8ZF zSN(lY5EsB&lLn|P7}c|7rnYW>>R)2pk{=OQ$M^%UQo~2hggxwm-iElkAOg%Or_Hw{ z@QIFpe-bF@<)J8XZct7Qtog`$T9R*Awb(X{^6mxe{kANS5D2UqpDcu{R~~{TpSLP(^;7B*E|Yfr?2dk0M*O?O{rk zrTrq2pQP{otJ=hakv5?Vkz;fT{NL}#LjrAip1DHkqN75S1YWr5>V?t2oEJYh{zU%| z;?8oaxR=YbU0naYdXkuXnr_=|q>GT5oXyviqkp0xSAuOjTnnR0G1oZYM5~Jv3#pM! zpPjY-{&_eq_WeKU$tX&^K`2?f?Uslq&BZ6mnZF!l*|0#d`XvwR_hloV%ZgvBGf->S z(3Zc2t)fNK8`P-;) z0M1@{cfX`;F6()j+Ji4rza8X)-0-)f;`E?jOYEv^$WN+rd0kjoFjE-~cScy2MHSoi z_v+6He!n|ZOlev*wm3tOlXcM|u_JG?{6p))?OaxnHvNKjB(DsWEgj7tBqNCoYLP0& zAe*E(siFnYDLJ#87_Q=ki#BPALUjp&LjL zc`TRafoUnXXqKg_bwh@)2UF-Dq)6NB=z_zKE9w?-$YvGl7)Qox;TvmD;@UOlk{9FL znutZwCKSsjwzfN@{=^+sb4e*Gh8*2n79WwFDb&!8bgB#v1eMaBE4F%x5sYf= z))2Zyc@3}R#|L}o1#=%uvBwmjXAM%9H6~4hlU~U$yQ-es)$$y47U2E9AEG}lWe6{$ zb5vIF((noHpUjy}bG&wBzIOHUe1fRxWP~~q_#}NL0VaA`Evh?85p9JB*6F){Df+Y}H z3%MdRdR%v-1?{q+PFmMysk?D1@>vsb{>2zYfT7P#5+`%VohQq;W}&kNg16@Peiu@N z@V8ZPmE_NO*gITzCcMc?Af<=FV>Vpnjy1zTKG|%y3%;@Q^{+(XxI$PP)0V)eq)77# zU5F9>%>j^BT55p?S`#KJ!ExP=k_x9d;RotvwXC}}r4FY^54T3ss<&K|0DN7y%brlQ zFu0NPZcVEGk%Vf|6Fr-wqyme!zkZ15O_6+EzqC(eX7HkRxf``?$v>u`Lj&mH>Hl-{ z1(dR@Q$gf_{kB5uZtnhX2JO<`dg3jh0h6>V1$ObiDVp3yZR!QT%yxrtaFDFs^O`ziSab%=!)HHB*(+3Ds? zN0|oZr!9~@X)Q=+--Jqy;E>U{N~_so!&&co;b~ZdtmyA6;+?oHdZJqei?(yk*|5=g zk%_}1B#vpvt%0yFWzM3td_%qEO50ATZ-%4T_!ZD2pU7ZbOnzf>W0q{z6^ZBov5DVK zbi`+A)pp{PUFQK6*=7hLO<8N5nzOx%7Y&`zBo20f(B)o4Wjm|j&t$M_QN50n9I6x_^@9697}pq#3HdFkOq*s3|ppD|H95&>2?gP6CVNNZkk# zr;cimrK_F=8mixiFmYXrpV zJJ0Cpcd33#E*#Cqx@FeiG4VcOn<63)PTZ5KX?;{ltSuU4_=F_ur8?{(s3EBa|F%&D z!tdnYvXGDc2g}UO5?{jA=-Xy3RMDDea#OcR*3uGCY*4$@*qy&>SvPYWDynm^gdP|s z7vAB%;P4?KO(!HDFp$eRGJpfUck(5Rn<^k&n2TjrKu`y3|uT1*}t& zPq)wh+KUF5|D~UXFdR2aPW^Na3lLFJscA#z)L}N&x1i_XJN*YP31d)mk}Wn{WGys) zGS6?Z{xxrdLMA?oIP^=3#=y)dF|oO-XjWtjpg>A3k(anY$S#Y??b6~Hv}-ZQsA<=d zm2i2gD?mof;=J49N-k*VU-&2KqZ?sFFHN}`g*xnH5Tp;W7|QF76Yp%S$Rs1y9H`7; z&H5$lr`kHPaWe9AhB0H3h|MJB{3Ym4@hu@eAPp4zyr33oYfyVw!ROEgd>Ka0KLB%9 z0=b@vGPNvqSiu)qqU-QdJ;iLUutBlwBrLQZHniX&dR<{i<4Pd-$hM1m-p-9wVRA+i zC<}^zo~p+2&4??$B!Ls-jDMI0076=*Fpw{u1Ks6|}04LL^knVQUQE-#@nL-JV>aZ3=DP-_m z62eLJ1&}>SUCX;>R#d8JX(1R=v{5(?6>lS8+?dwh&hF|XC)#g|^Orfa z5(PCjHpXT&IRsqX5*>E6tU>QrE&1$L;;p*$;yl6*0d6()wKrw}KGp$rJIe_4Wrw+w zHTa5Xns8Y+;@ul|Q)7KHL&i!SWfLE{S43&GC`roC>BfvP0gneaSvZQ7cDEI?)~>j@ zxv{TLVgs}N*Ca3k@|{;Zr$#b#Pm7$HlUSx)Cb0iCXK{A46(C8fRSUkl&VBR|Jje1+ z3Q8gW4VDWrr%Qcf@Axj7&KgX6!-%PVUT@&}pC^wScQ`IKUc^qnKB*mZF;#WzId1r1 zHhc_)y5Y2(me2{_u@$Sxvds&~Z;v?Tg%sGm^?BSB+qWI9!I+~2Ij*j)_M>n!C{}Ut zw;oOBfenb=90|0kF5YsnEgBRS716`c0X>_!EPtCiCwe;-D_sF;CB9rHii%4lZSjB0 z(Bu-{t-v8*a8m1)p!ZH+s?*)UMb~wPfcsXvUHZ}+V+3{yO=>SdS5G%U)L(t5V5l^c z%x!*iNJe>}lEbd;!)67SHr+QB{HVoFvs0O}Bt?b;PJl@kNz#fHee;KttUN_;CYi7COrLBk9SCO`xNJzUiY~m-vktID(zIGENIbY8YO{@9;t^ zX9x~XQe^<#R@c7Fy7LopdRawrcLNv8@&9y(aWgzqY2f-k+PpaT-akVjof3*{a|mjI zs16$cr@kn{|3-1C(V(At#~w8E`~CQCRHB-*;&9_^%w6pGs!C@-x~nUW?cwmO8{4Bt zmqTtK@E8&`r>u0d3@BkE!JTMrNg6b8JYkQ zeG#RVl>6Kt1}9rXo?}iEtCx^#uTy@NJeBz{%1Ed~DccGC<{16U$;bAV!57>*M9c&A zg*g8Vn)rCAK=$=3Hp$Q+b0=OZo|+J9N%f6PdW7xk<|ohp;ex&4UVe8=i!Qv2Jq z>_8Wejav5ON6BmqCc8G6_Ke!;EVK2iq6P=?Cp#y@aG^K@lg{(!AV4~8reu`R=Sr^B zPP3u+h|S?CH)omVNJ7SgnFR#o%QHUF)4wqpbP`C-(Us=cX`%7krYIy_{g=3-7K?t` z5_`4wY|%Gkmh?npl^n=fCn^l-)k98fbb6wmtb(0Sb;{JI!cbSlz}O};M6{vXQnOUK zW(drs4Z!v6k={2Kz5ELuskELZQze%)UhnSKKrmaBS;ft8-tdFzjP-{OE&6Cb z_Og_1mc(Gs@%sfDlE=XoJmWde@xVP&QZh1Goj#>rxqqtd7kiXzhP8$csF4ab{cmz% zK(nRFd@z-HR#Gb}IP;!bjFRnSI21;dlmm`SvBk6#(~=o4GKJ;=KI~t z1PfQZU=kY>hH6_=>YnYqu&ICaFSAX^5FZ@^O@9B40MrZo}IZi{d_^M z>TTl>$gzBqk^@#jCf3En1D3D%=78>&tR&bH9E}n92K2B^m0vX!+=>3tJaJO-!^}a zqXf`wbT^8%hv=A&F~{MTLUV7JyhDdd{gl@X7-yK@bN)-0L6Vr1o++dK$G^-j*Do;p zr|#kfoXCfK2IKf|#yupLJCGIlVP*DC^ct-4`P{ydThU}gyvcTy)K>KTM??dDus9a_ z&8nb+nvC|p7WXf^`CrCUoR~J(Yod}XqoaV*v%<&=wqMiV7&q!3-+Sx^gR@3!Ksb#! zJ$PjKg^rGKbVOTz`J}|NBxQ86wnIi=U%xPMt3Y(A5*fL#u6%ap z>q@wJc@;V_IzbC1W>*A`PfirIS(0v2QrRccmK2*Panvzic0Cf3eQiogH)X^>TV>2f z7;w_{AgDv>QNHQ1%Fn#%ED=`CxtR?a+YX0-Eq+kx2hr49g&Fc2SCfDrre5F3rK#OJ zonGc##!iTy1fNO|?y_Wdu&JLYX^X{U!_gp>H-h<;UPNQ+*SkaA^F;jky2Ml zHDvpJR~gp$a}?l2UofP1SD%?lK>TK&amBZUzMPYjFdnu#5lh@zf!Prh5(-P=YhTw57(n*;@l7H|NA) zgEO1&7p$O+?vQLIb9=`A$Fra~$bOq>vz{RSMuM(j(1i0m4 z@>u>ch7B=Gw2L8c#ho^#68ZM~3GB+?F%ePIQUOBfes}XfEh|wKSwprwXE9@TLvi1}WiMC(H;rs8; zQ^NNbElRRH6SF%iChHHzE(0c<4AV4L5LOE*S>qW^UlxZ~aBoI9W(px+1bQpgm{Q#1 z?7@=S`j-bDE7ktEvERs}!qEO5Y)YxoumS=rbB)a&qEq94K)JXeSHsGt`j#mSr|AtF zd0F{_vnqDWvV+FK0mmhNxju#1hg_>9q5Y-aXj8Xy(&)v2I_&1`ecZ-0QK8t&DlS0C zBkt0OkyB& zjmcby6-PPZE# za(VDGq_sVwD}QskDy5C&kfa&WIY_L|I!%+&v!n~Bxm zO07GKq)EU;^>4oWFz@Mjs!}lep08mG`yjiC(3VrD$j;fwKP!fuM`NbKXhYyg+dk+0 z6#;RDoh1R_r~8h4qA$dgIXYfk0Pf}PUN@4#r^?=Os^N{yhNV+`W@c|MRyiswEAz4@ zYp)O5IB2VY+TjR|EcsA=xR-zcV_$(sUPp0}<4#Y%%QrScFO56i zR5BLVOdiwDr-WoZV+VtP@*}t+L@#pC4H+Sg~ zLBBTH2!?$uFa zqJwx-EV80ctTbry8FPUyF*b3;#vUQ}N=V>tqj}BEjJ6!Di&)9#0lTRQsU`t>TO(<- ztU47o&ca#x?Qd(^f2>E>!n1unnWnJWG)edz=BgzQI5}nDan497M-`(xKy+-RK@?v#9qTyv@1n%dYxH zJ~A^3YyUPW$BqNvoXaQq_xy037JuMk_D6*TAv(1hJKFM5i+G;H20v0#VrTsP*ZLFT zVxFP7)%7~eg-Wns4}B4*meIOnABW(@;?ZbU6%8*#-Y`U&r)=}rIDz|u;w_S$ZcPxA znZSx#r|gXL)XR7yJw6JC63zet5WP6{V>E+ChYu3L7}^7#rQVpQhpQ%{y0<}$+WY>s z{>X-S-^|85)=crqlj|(6l_T;sBsM;C3SstM3&OB~XL*e|OgMxB z7p;(`;&3WQ>Mo>B#dF@0IE}|XC5DuTMXA2RN$(*h(T?x3o_C|^+K&3}uVcTUTqQ6XwnLqXar3zBRMJoyjWDAe2M@7Z_te9&c zO3Z|2T84B)*kyMBH=Ss)wlr~QzH0~o;A*OIG}Y{2g>vSmC8a*~GZ zwmTXK!QJ)XE3i}(V=efY=(R)IOH)a8V07hlL0-7SYRc6J$7@-Q%(GPA-Px*(vHQC- zl}VPvDc*3r(Q%%G&{GLOoEC<-i0oedl*&pJ^822*x$|jFIjJTQ5WiYzz>3;|kCRcY zMPxg2KDAb(q!Sqmq#n?|pnDiY-@o-*u78fq=5niv16}fOu~vDGU0%rw{Cjlw!1<+& zebOh}_t9I4gA{z(bH^R;T%c4Ii|3ARGkVs20b=!Y6KrQUy0)3oumq0|4T0;uDGV`0 zvN;vXG>j`KFENFbvow&dG4|fT=C?u}%ty$*>Vgmk7BOwGJ8*-!uRQ#Ne?pjhU|n63Dc( zeGA;7>SVIMHV^6-z@;=5T;HOc!M!{pkaG*@I-4>0kh$g%Pw9WEK5rf`(oWRD?RWCpPS0nM_ZT|NXdzc;92Dvupc4AZ9Q%N>DpG%TCL?6~d04;tY$y zN&4*Nz?%)Kj_XPJCHUy0envIKWlbXgb*qkgc#)fmSO3|-L_P2UD?=sA2^2sAXrjaj zrA|ZE@?*4xTN&dEwZn=^Lo636odKH(V z5rInZn2X7e9^!UT!$JdN>SPAlQ2AWK6Kf+>jjSnS|1<4zfl)zIJw{%j-xTOeu~OP| z|Etpvk9%d`vYz0Qax-n9lr{Q)@5Y#HFVah?(mfEc*Yk&%XEqkFW|fJGc-h>Psrr}e z(gmHB@3-eE-JLge4I<6#>1Dg45XAg!glqgu-MA<#29;kmx#yf|WM;IZualu;rqQDO ze<&1&uZHpXRus&d%lKH~_AWg{c^gUaCer6#u&~0?b~`RsSUI|GYP~qL4)MCq7wp|; zjl2eH1}HOLgkUZxiiqhDz%iHixj!I15F4;c-uBS&BUgsbApM4B8Z6i9%plEgfCZjf z0}Ng_L^2NVJwWMz#`E$Cu*^3)qWtai;Y~r$;dK?TD8O1n=@{W?)T*VQ?fY7vm_1?U zVl`7q`Zok>p8%R&{wbt`PJ;X;+U(8QkpSPX0(qPtS zbo%@mHPByHVIOy@(DTck2HzVEf>Aj1a^XtmcspG6%S{8v&|*f)a60m=#sgmLgozH> zFQ=$eo904$97)%}IDc=Ugm<5iX(OZ8l56;dntGPB&&2_SJu6ScU^~!5J7v}+aM^ba zV$jv+=!G9rcttS%)O#O&ZDs7eR@A#rI50F98R*$L6E9ET(N3DB5>uh*j;v*D3}Ej7 zFyTa!swnftl6!p96)0y%mdc-wqvJI3LL)q%P*wO9Wt{IJ+wn~uLdGUNW|yl!Am{iZ z|7O6IzgrIsB{@j9hcIVw8PeYjjh`>a0)@0XoYcZ!0QKu60Ay3Ckk*pf$39Z}6yMSx zaLZR2cUXLShnfccR-e7{Lyd7^)PUD_R#_hsmrKU$@Li{?0oRiSjGK2w$@F<=W&y+j zDL&~BrwZ5>u;~1GcYWCksxuttYfUUMz8>Xer8ubW#T9^UFjX*&xtoNg5 zNGAH};Cf%QWq%Bb+b2|v&*$dq_H3&rY*@&>#oQ(IY##)38lQ8vSC!Ub2jW(}qpDm? ziBiy`)N72jN!iIalgfy6u*iJ90?&8v9#w2*K?do8s=cu&33yoarsmkmNZHzOg^8;)|6A?(kUBUP_Z*( z={(rD==@<{Rg@<9`s@|e^M1WDYrGGlLdAPuD;WV@92q|wwRBdmtjkuN18w>5=*pID zmGt%;ZfznR4E(Yj430{%DRnvgefXkID^t^3MUAf=*+!o)8mGpBjT50&CbT%cVhlKh z<1cajHipes^Kle6%PnVzgTa)bt00jg>zox0v0US;8Jy#VRkI&#ON~lfRleHnfhYO` z9$yAFO*{pS7|z(@{Vjv=zeb2Ax8Gguc7!+RSFmR6HOv~LCW2BMJoojTd7j!gLDn^J zt(%8vA3IEdADMs*oZFzjm{czwJ3DD=CS|(ZU~yWeG9R(LCPSCR^jjy)NeF#J{MwUK zoiVCw{FKMy_Lpk_Bo=06Zbz)M1T~;4+(`&ze*kVJmUB=Axp((J`h)_rCIX` znJSCZq4{uJH!eDz90X>&UXdJMg98qsLdeq(G8a*zJ26(4d zHtqwQ%_dakuUW`mE_aRt`VGTBTUp*}E#ENNRvr$?2;lyrxB`s+L2*G0wTs&FX)|%P zbTL^U4Iw!}x4ofO+gWx#F%!X3!xOuQ-Yy5c#&)fiWA`R+N_H*Y=45M#IWeAmofZDk z;Oq--U)jT(nUnG%VQiTQ#uz-8sTzuU)X5rKl0^fo6SXZOh-~TtrgC?Aw#2-A#C7`7 zf_&KH{>vPHo~@w#Q=6A~B);;i-Hx@u<*C{mDpkde&AOt1kynv(mY|i!o2p|leX8Q( z+5-|!+rsJQn@P_ZD3r|k?DfuaQ~U>eP*;_&F=furdOydTdAFX3w@r1mp0Fq&WT%`~ z{(-+P__}_PZ4b$;cW{`<*W0fmkCn|p4NfH*0)n){v4QIu!rrwPiotX(wk8gN3XY6} zuIwd*nQmX9o=!;iLm=?@vd9dpf{O9t(}OQDS>lN&2C>@V$-%gSa>xRTaQ>Wc)rYIL zf@qqzzLJ03M5ifMF>O`ey^;57!@#MfXbp5Wtz$%Blofrx>}Aq5v^_u@7Cj;?ZAY19 z9q{B0B(nYR$pqLdnVa~Yfq`50;%J)Kgg`FuPHeD!RmaRmLB%@ukRc%K8oBdDHD2x~ z5TmKnw~+J1+PBhtU&ETuGM^7^PqB)%V#5Gg_s(Jfo!oTul}J0b5&#@5oSR16Rf zCA0JkDR&PwqzK@6Q0ME7g=h4YXNlE=js}4DkKEpCVl?;0a_t^WdE$8x)Ni~pT}O9b z{FrL&Cx6g!XnZKxivU;)K>f!A;B=jwhDGj;N)dk}W&g6}TsN%dRW?AC@&0nb1XVb4 z_mlOcw_2mpYmrHt_>2Z6XoyiQ?%KD7slu>jvMsgJlRWU|h|_iQbIgw)M;jfXTuz-Z ztCoYS-OXX-uGdBIW{h|mVNoWPP=@<2Qyw6I9_>2^A~jd!qCy70+~BwMm&^AibyyJP zpYRJ@0G+W21is&Fm>cET;xCQcLK2WFu;RNd7I#=VgOPHa%fl|iyswRhm;95L9?dYA zS)#4=Vr7$Dj_+Y|Uhsp6Q$(7N;_l*tUo|?0xs!6G-r0!5*}QvnMc0wwybZY)sfsYO zZu{pY$7o2B=%Ep#P~09PPpf2>b%r{rRd%B_<&*PgbAbNS1r{o{>jnqz#S&g6!2)T; z_h6ID8Q}3Xo^x_Q!2`JhnDx!@sYNEyWcU?+UH|u8=N~*|0Y7i=ERVl6^0;k%wAdT2 z&5ObC2|6wjyJa56IzW~$Cygkq1tj!5MRC4}AH}|-ZDTI2oSBfd>E&SKC7U0Ushyhw z{9#Ac#A3uIey$(oR&I){hPQ?}x`cOWfGY}^;?xh&T0x&q#>F^%?lDKcL>8VZCapq| z0ig1e%gb@%J#=_u*`jMa30J=X>GCKC-SWBfPX?aApKW@MGZhhwZ!-6}R>RTiH%klaU4Y;=YCRy9Ev7|78DhjtRG%I$sBEILR z5S+6sxh6rV{Uc!ZlzTMrnPxbj2xDo5ao{#feQSG{vHNzcedWdXUOeBNQ0K1OMlZ+p zMuUodsIKaDrMoi4%u+7j;IIPp7G*`*bma1#YYiwhALO}L<2^ASRtd*9R z@1Z%WkZHH3sv?9!djO9>k4%v1H;lnBP$;ZT@P_lCCc|^L*%rWn1YY46<3HqDWSo)) z3!B7#yo009I)8ancbl3fdX+Nfwl;~)_w1Sz#^6ZF=?#pfUAEeo(+;$0XYF+~I0uYl zL2OH1C#Q&3g|A~oX2MWTG)jt|43O5n&jQTyPdXx6g1Pse91htxRW&cVzbAWXkn^jXcD-<(29{>%@037cj63@tS0bUoMU+pq@6(fpf5>7!R4+@?YbNQw)h- zw2XV>p(P@;HEt)uzh1r6?|O+qup;oS0bz=E8Cv^_hPRQ5st{K)Ax{U$y6#YaEE#ch zwxPoMW;U2&Xq{Fq?y~aG9Vp&%)K9j-wKP%Knk1OYKl&D)Z03zTjp^8xP@ipo*a<(t z)$T8BG7B7bfE_#lKA9xSov!)vKm@Srwd$WOl`_i8Pbq4s-*sZ5aeaH3HV)iCFF>B* zn6=FqK^PaKo*c2)1|&@-4{FP{jv83@HjRyYJMmculo+=Ux*=27=;3eJB^6Owsq$_* z5A0F}dv?mr?>)f&o=G)LA_;gm)p9%08gH>t9GlIRA=tQMSCU@U?UYsyN9PD!^i&Ps zTGY1FE-_ZLBSVP8jQ~Ck8$UG(;MErjN>-xZKi$jjjRdPSNsA&%3!>7=5d2<4%q4F( z&gabIEvL&hqZ^A1hUkbq#-51e5N>5^+XJc+M;Aw&$uQy)P(|FA66D4r=D24abQ!#seYz@a$Z2x~4_ru$ z)dG2k5k&Tu8QfpqeG4wC&#CGwW91drE-AH|dg#5G$7liUjdS}>gE5pqIRS^yDBD{s z_wQ@0*2zCOXB}l0Q8Ciy!+ea5OI2c}SBIc|RX}|kj-A|(+1gqz$6s(G66bZN4gWap zV8p>X>-fsV=juyB(0&)4!O?NS@#pu@+Ku{P*gIya<6dbrH2m)eG&jpPE}AAjKUq!G z7!#31x4|g}aDdX+LG&mSR^%5rTJ}*AnU6omdg9x~5;tbEczbX86F^=ANhP-dxRrX`#m};B#i&$1I`l`bDB4HF##+W5P48 zljn+HgM)ERVB=EG%tmg4;tJcNaRSuVDV_Y5(Pc3{z% zrM#SqSFLtehtC^s2a2Q>Zm#?L`CzHh0kpTT$uPu$@41w%1iCF9j(7@r%PKBQ@SZh5 zjx~+i&X#2uPDysb2_vTV2Aqre4+Ofid=O=kg5At{g;xcwXF;c*BMCb&NM=Z!Ch}!g zs;-lCNmQ;0W?QJ`*@yaZS`(wlJY-Vr9=f_!6$b$7Dq-oXZTpQGP0#{C!afoPrH|C* zZRB~$mqzSkDZ$7(5ifo@7hE=yEwVV=iu~kO1a2YnmCbToSLVM%>JAaz66Rp3@|zoFH|%URmi+ZL~&Z%qCdq_(#|cvQkJ zb7%JlMm+m(55PKYgsX}C1KdnEp!XV!Tx0|BbDch`p;_OlQW5v$JIF}GG_yO}dEBSzIG5_7SWxh|=zm{X&;UyeV z11~ofE{8l$3WlCbWwu6f=S`J68Xc7jx45)S<1Opq&N*tyd$#*rRKfaNc7-W89I04V z#RL%z-(I)C2UbBC^>!OdmzNx3wEj_zbjC(icN+qFoh`-;`(E#2*jGyPeUqg7s$CcA ze^6c?(7U%YSo@uo9M3Z^dxZ|ae0@1UJ9f!Pu=>#<*=-Eg=Vkb!>vZhC@-g&hr*82n z??qozCrel7-s__={1f9Onp8gnhNo*UGIB%+@V9-?PXj*T@GT|Gw@3mCX6?Uzpp_j0 z0gTgHy4KDO0g|&+aTFe3C7e9fcQiV?on^ic=leT8qCyavuri>adYU+ew#-%Rn&u<$yX^KrbOU?5|tx+Golkr?=O zI-;RsIOJd*lX&*sPRPSYPH7p9$4CnC03o#=~T@!`~&gTn%PCON&Ju7tqI- zJOn}JcchxaA;z6|6WAxK+s{Nx^>oOxfWH1>w8jeS$Ra!%`{2U@F0_jvlehALk0*cS zGlL3ceXFc*9*R)5V7_QXyA9$Z^Wh+Uf#{bPpV9nZmM!KjfYv<7n3r*Z&3f95I|Uf5Zyvz@2f2Y@xB1ZB4g z#$6qyO5w85vex0p3Tdmbbq9eLy3L;$xN24^>fkcUyDV9x(*k`?dZm{T+RT*QhuOcV zbcSd=Yd@8R*RjdzhXJ#~z&X3jZzC|zEY~n_12M%)c-ur3)!r7=&X^5>-emMC>h<0K z{uaQ3-LBF9U7A^^5 z=+oO*TSl}O&))YR0oDjk?xwnTSm|~Jbd>gn2YCHI0me0$ngUWLoKyl?TTJw$4^o1MjPnz0RP*M9h@77Byt6 zYUyMZCOxE`jJjroitC*CJ>fh(Htaa`2z7o*0d>TQ@>FS)uiTsU~Qmq!f zgn1o`HvxY7W)X^j(JL9Z%QL>HJX)^Tdo%?l9`$X~nnGo*p=^mFDp?jPGQ4DCHc76O z{+>rHC+0^qwX>+2g6-Dp>4C0h%om1E;90K5>_^Gwf`x#76$*bkgVQG;^lo1L6zD0Z z2^06C`G08o>aeE%ux}Lv0Ra&KB~=te7~M4#5hbNTN~F7+F(s8onvv4ogOQR02BW)U zjIIqv^X~UN&%1xmwd>^fKKK2plLb6&-bl4=X8F2F$t8VKq}n%KW$NkyzB)T{>7tVN z0=^pLcv@8%e^5aMk-^&#@Dx0%^&polXp@5e-Mh>YqWcTMtZz13tXq=4mVfC#ubNLo zbiexTp|HaEEqYOH3NmntY*e1pEt#%mux%~dQQfHu@k4PG*@;2q8Q*7Jm+SwMc{t<2 z|D@!t!nFba{|bU|)5^BS^J{)v@B0Dl`tTkHNGiHzK2#j~{ju|ozM}$y`Zgwn#8lmJ zWuWsFMtZWon%v2Sq=Pi+r~kaXZA2;Ku=6HL`Aq{ zDTS@sc`RShs+7p*+(>0Zl{AwyS#$Q|(6jPEt|RfR&l}Ccsut1GT6oNCuvIBg?D4Ea z8b&#Nd4BK91mC;*nJRGwSj!0k*8 zxrVvIH}Mo_-*}CC*zY+D^`XQGfw2zdrK*e{l<3NHUO=1&}}nmX~r%3@>?Pq9bZcW#-MSVaq#}8r*42>i7H_= z&~l1LKFV1lxn*(9HXN3}pTlp@yo3<(<;r$@5q=gn!TqauM?mu}YCw z`8LmC{#u5Gu#xqy6nqC}hHq`K{`1SgicNF}c54jPPRxSU{)I_`_Y9mXjSD}vWfu-~ zb1^X0+ay54=#qVHqHX55y~63+i?+Gokkkh>UaV~2Aw!LUK)G9 zqJWt#Qrt;(tIV~SFs_HmFLxJn<2Pev5J(~Q{k?^xtuP?gwnC+haKdYt;y7HRz@lz- zVX8)~M^8nz$`mi5I&o}S6>I;k6tlJFLuap1ET4c8u}iz6rIjG^mzwZO3m=(_HiQ_R zSAHf^YWn0MP?A3L2z^x}zR)nuw>1DO754SOF|)&mX5}|3_$`0&)tI?dXvbx48@9Rz zA$|xFHWJ)z0Xks@MSO8IZZx8x{l7S(dDkB||N8g&b0}CtnLLs=w~y%!VCr5+OtnvZ z#)D-}sNSG`Z}6A`!oGfK!~T}>!}i~B?*4u#x{i#enU`~kc~h#HT1E7o#}ddBl3-=< z-{VL-$^pu_PHMaA#z!T+I4Lb%%$Y?0^SPCHGtEcxHk^}(NP9co#MlRwayog)Rcp=A zWHBenV5|2<{0)!NwT zITGWVbpNMjNx&iSF8yAj+~>K*ch$l}J#THtZl)7wuKwx}R1(QW>SuyJ5(zy!us#Vv zDp|+%=0>uK*wff%)J-Z%Jo}imZD8p(70G02`-G;x{37(>Z2J|Vl8*ie8&!hug_OpKoqO$modu#=F#G3E|<)=fk2@6x;S0AO`;p@A^7`d6Kp2 zt*^c1&XlC-=f;4~TR;1)TSxN5wQ$I5g&I};Ub?@MT>}N3iC{d>#+0_~CNWOMx_dBM zX6E9YcHL*5=N>XP@e3QCS3difvvUgyI?eVhzfkL6#ai*uCB3;Wc1sb3>G&8og@K$0 z4*ugk(*tC6f_-+Y;4kY9i&+ggFcK8VSP2`#sWQc~rz?{q2_N@7zI#ll0hX%8t~Cd8 z_iWM~q}*k~0Lc@|`rsQ4K3{c(!G#{@-K~PW9=jy{IES1;yFggGD0u2-%zsqUHNQ4W z2}G1Hjl<}#ls%x)5^ZZtd)#Oq(vqPO>TaG?C!ReNWzv(PYJ4Gw$qr>!*gEYiWc}Of zrj@pYrwI4epzy+NpRd;xND2z1@}PZPQe~ zyFrwIS>hTtEi-j5lnoXK7dw3rG||TU%}joy+EG*CIKBQ!xi9VcLsx||J|`L&!&8d&yeOp z(V{mx-P|>Z6LqD_jm#5m=Wqn&=ZPbMw|?PmyUrYGpq}jo2T)N`NDIb(>_)fb0)y2J zoQM@yxOT_<&0T0r_1O6zk(a+Eaob+iY}~pIK&ZJ!R+HgBO^JM8J-@Iv8@}mIiW>}n zJaxwM0~WTbRL|`~tZlb-+b_3fNKg4Mwsg)U;GttI9_fxJHgFOlr?gz5}qd zJ_q?g7)*+nst~q48+uJ;)+uZ8&KcI_=^s_x%lR62=2YtI!oo5QF9Wcg+jFGGB3)cy*Qav=dp7UuX-o1S;alfzPocT5NIX!G zHh!wU;rZHW5>w`0K3Pj%(Rx~}v}D`pSxC{JGPGX%121Xgy7(Q4f-!YnOC>ORjd8yOzM6 zzQ|_+`3u(E09Ul3rw=E?cI2cg3&t9g6Zo!r$^Wtse;z3tk3zd=#PJQQDdd%)z9 z-Hu!;T~sQ1G*X!hKS}mUVR*>&*@Ja)O4M7<`P#ke)w-nhI+~qwUyGZiGu4xJ*)YS!uh5qZ^O$OE8H(Q_ruX#XXHV2}X!|>;y>80~S{{(SE1yXuke_4Lf41@yYR6|<(-Waw@srg|W=L4CW!K#MnrXqs(5yfT7k5Ok%@3$8 zHDntC=)PpAFJ5GOCgc#YYt~bfZys3s)mpo7kgt^`g=R?I--+6+y57+Gl+jwR?Y)uV zak<^%6Nz4rHT_v|ugvdl+5&rS<3=TI2c@!aI#biHSUu?h1itk(R`oej zS_Qb}uak&TImf<6a)3qalwxMKL|@lRqr0is@We4~>z`_$afda6Jx$1>QSFDtxyo*R zCRlk@^usypw1*_s)=efgJ(YYEKv|;GxYV*8)L@>X*~Eo?$ezrM_2`FZo1$}N#z*;F zda&82(|8R8QQz6;oEDnPYOd2AP2UJ4<)jTzjvn%{x2sC_-i9vRxqq~T_@pRSuWegd z59*ixOrz!#)I{21RCJ5(P&CxrQZ8MT6O0xcX`JpREjox zKf!l9H};Mfw@+&%d+~ zVvT;bz+Lb!;}G$Nt?LI1L|SXP?>Ux?s@K0kKomtgQjBe*t+l{-Ud<0&J z)J(?RkR^M1j6$GB6?snl)8?~zvm?}z(WuqZC_DQ9#B$FhJW7+IF3^J_OYwLjsCjc@ z{Vz05wfqUvdcmha0+m0)Y#VE|KHIc>ql>VA@D`C^xid4}KWoYmijoKLXd?UBsn9!$ zBlc`t4|HnP?rUp`1_!-4E{}jrdR)Pwds%)EOVj$+!5Zgse!QpigzuL;)-}9ylR`fj-`wtDIDvXUsLzl6r!T{_-d-Z5S9wf9ULs1 zq)be*TWW&ne7cr_OWOupbMC-ACx6by@_(pliLc`{Y+IZzXjDX54))Q&NB&m;(mq36 z-*`Wj8?jd=7*}#c*uT1|`od!Cc+~@<*~Fj5%_-r1YIRbQX}K4$`H;sK9@f9ETqET@dsweVEvN?wxDV|V1}ME}jjRNJiGDkGuWjs`hi zDS*`5eo#MUMAch~Qvqjp-)Htbwm$+3k3=95?3&*X1W84!G z3JkD1zxs2^p-5MHO@D}pJ<`Q()L6Kf8X`Vv`-Q#GfHT1QJU@~HeK$d4!DkRvXF9tZ z5p&QSQ_-voap!I{!D|rrO}>3)A++*ZkCnfN=;UWtN{-QjFL~&;yvLMWUl~||WAWCY zFxKJf3y$-4v@{zKvQq)hpTC{Ad^Oc*sE9V=U}y9%=Q`9$NO9>lo$5v7l*Nvw#_eKk zDW7qmy#sDJ!l5^xJdPK}3XAk!09k~!{qr01jb0uA!Q~GR`x*voTX79(;Pn^BZA|pH zwO1z-#{Isxd}_#M4YQ5cs(sh!-4(5cvwkgpmkLL(Eo15P?6f9J7H?E>ocV>fE7Jto z`na{J2D~SVGJ*-@I-MN=C_y8J+D>>}Rx-t(nkuNqUDDlZTSR#r#O00eEcIv&^&bpL z=^$aF#-7DjOP#p>6ykjFgAt?Gmc_Yl}7wo=vb!eW_saLZAo%_06#giWwg!{h*gMs=54nsbZ z!MAL_56cIiG>EIFv}8*9ourRu&sGMmFSU86Mz}){u+d|dY`Ff-+TS5UWb09iJ z^k9~`>(k|-;+`yGeZ=A68PC6^9T+X zYb>oAwO9u#ojY+z(%HWWG@#{m$gvnqWM#OQ#$+qp*8;rGkj#1jk>&ulZHjJnJ zerVFleLhU{U{ip&1uWn&FZxW%$IU9qVkjdWv-sYs`yQ#n`OQ}ufnWGIDVq2HHOa6> z5wqSHgYMY=UCM1%68J04|G}-`QB3+y72!o1POMaK<2z;wjHCohi9e6)Y7zF?v>In_ z%zQ)aRz+T)<2hUC@r`I$gnq#n?|KKhTmnhgw;kNJLHD?Y2`9+=F*`%A*Ah{RO(-Zi zzH&k;ss=e<2}eUq8%o~ZxIuibPdRo!8ouHj=oFnWv;odS%i~fT8S6>;Mda_5j`GX$ zzZoB&2rFp%fV8bI6KK;G21-qi85*>2juIEz)`PzAx4mK8dP>uD5i|jYGkKb6^Qg_? zN2a{(x(l-3dug1Oa~|fRO{B37kUXO!lgk|Wz39{KQ+AtlUa^TdLFy7?T!?4jV7>Q^ zDa6={F^L)6{icVx4YU@5!ooeS|ei|UkO7cqn>rI*$Y%x0^&Dl04hMSe`hU17G^<3C0x zR8?(H)=HhizZ!A0&n5;*HTE0b-ZYLR>D})r{ZZwxC$87zP=#fItVtB@->HktfO%IeA-vnt-J$!!S%|0ad_fnK1;v*uGJD@;aZ)wlCBW5MAmz~AT*V((y!tdk9p~IH) zfqu^+EwUTG^4*j3CCh|*mVtyC3TD=W`P)Q4-;kMmEoIRI;1Gp>f#S9ID~Gnd5X z_)5+Dn&YX{)Lgc`1#&9+qXw3TNQtq-gil5!g*Tc4Nh>1_;M`s2vRJJ3g|I%${2Q$x)3?W| zS^6HRN_Z=_u{j0?lwc1p(%!cA*PNMzDl?yNIlD{;yK49}w`p`g!lgYwxInJBOnKU= z;TH}!Mza;1P{=IKZ8YNHy+6y+&ywN6yCYlbInq0s3q~tjQ zpC=inBTwZ99p_nrXE);KH>xTLFY=|pPCAG=Z@AGjU(Nj!Uw^i?Rvc4-0#sRX!{Eh| zp8ub#b%eld`pPx{fqK+*ubPW9Bt`6x6`eke@axfp) z2rUE8%R-$0eqw34^*qna6zr7)iuE~5*FXy+qBP()L$C|d5+ogiL`B0F;dJ+G=PyDy zg|TdTaRJk{NSwyBw{j5_(}u>&{QL*64ZN4MbY?Lt9vL#B2C1Yyy{*5>C5*EE=`#HTBZQ z3n!H&Y8q@NPtU?Oj{gvI$0}AY8bcF%cGedW-0@m9Jn=lc3(}Kck5|d*`e>r-qahnJ zhsd;&*S@FIVk2ye0T3S>zJjPHkV5o>lJuwd3^RX7`wnMKalb=rB+0b8=s=U*@SSD2 zbu>PpO9uV;)Ao%~xsjYybT=Rgk^jaVueCx9ioI>B^beh&L{N@tDEV`wjqPob+xu$h zn_jO{3#pVGz67WHnQI%NI!4PW+S1wvn4211P&3tj&M~ci?)}=frg_4H|pTeN=`_%=zse3-r&`^?Wy zZkIhoFFqKqHQYBAvz`UuYR33m7QYxm$(cBn(Z%Q~YMgVqt896-`tGp(_l0jd6Rw!6 zEpN<5A0DX^0edW(Ufxs&d^SXDU!Kn#zrcq&{CQbvxZnEEIp7l8eLUdU%GE@^&jDaa z>?KEMzOoeO41{Tq`yc*D%Ww{Wa7;=11gA9|Sk=53&tRp-WP^cgq?U}<1-;a|*n71^W|oN_$egzNpOTxN0E z?o%X^nE>n95xIT2M(8;p2TnjB#Xb<>N(J=G%M+W(hp1a~#1G<^=1)_vRw6#P7Y``d zQ!ZREi8&d>=^XqlX?>k}(Lq&7Q%V_yDic;@$so{!83Z|0>D$$rx(e!OMP8i8*4WW44y){JF?lQ01+F`kAND~>WJPEFxIJVINCZY&M*07F!e3yIcV$Eg3!q>v~8khk6 z^&U%{AjOA9A7eQ0UQk6Znlgn;N`JDK8r*774!%nF$Tqp`*Fj2Yu~FK^43-$jmVhtj z#%(MH!AbIqqAF2L6%@aiI?wcKl!3UT3s^fAqcAokqG`8a;JrSmiWo69K$l0INURI0 zBnS*i$eup6hR!b7>^6^0i}9GF*K`cnSuVlozQX1Mf=q4nak<5u?Xl$!;gs3M)u3i( zUC$-Y;tOEwOBAgrnrEn&>UKqx=0Y=sMHnHgQzy|bq;i()hYFWRO#5%l*KRSL&k409 z_|i5|WUi#vnib^SX!wK1J@lLq-7Yhd?)Pl}2!OG&GdUHm4%Mo}e#NV)2=%VyAS9|z zwbzmVpn^?o!?^8b=Cr#!#>g@8HMmWg8+PPeK{sRoN*|cUNIruw?@Z#Dk$67oFdnlW z6zF!jyjOkI-GoZAn3n{8WC<+o#7e$7VT{d-BY5CObWnslD!?>da%VYULn+{FLR8sEj~tC~V|>~^;mBn@*oways5 zzFUuPV%?GoOY`O9YU_d)z6kZpYWrbQ2i5Y$wLFVVWMt!TGW-JDd2h!rEH*Y}RVEAp zD|lwEZ+3DAFK|x~Sv+(o(o&>TsCHdwbgwq+`!gVG)nX#yu{-_8P1_aKc7@_uZ7qiJ zOjF>aU1{%1)o-7so0#B<+3)pN593}Kn=SwQS>5@MN%G0|_$gkn?z8ny;^DEjKStnd z>v!0u?GChzd1=URLm(qAiL(Ida(j|~`v>ogT|#Jk8*a&^*EZ@8v)nHCdXo%Q50VDRk^D5%E{1 zRBBK!2V12i*)Y{+`tg-H?t6Ro&mqw;hj5>Rgza4Oj)Jxq#1APvrENi%FT~bVIn-(n ziX^dMV{F>8p!}ZnwPiiR-7+7+Dt|KCG~$plvs4=MmA%KdU({-yl67D*qJGh-WZr29 z1u%8r#CPjSKl7~o; z)D~>Wkl1$?**ZB^k9;&H+(-<(sRhdXJhf49?uOW6>)&nNSjpBDNHa(5KCX+^s zb#EOB;H0@BevLxl%?KWZUJr@N33P%y{#sQ+|8!80e^xZ;nY{WMVL|rPvLPySC}Sn> zWC*%9101fsuY7q^vxQzv@jn&1zM85)R(Ds!ylvT-04BSRvL> z8=p;Wx=8n8se-2xiwEPGAJ7Nzssea-$nqHF^;8HC+I_}o9@8^B0{_1w_+yCbZZzR2Y z8C*3zje3+XYi^eU+?(_qgRL*{>$BTrBvi~cTuM2UvJ_{%s~`POhlFylLtIz&pJ5cl zCL1k)Z!z@`D`vAd*t((iv!QO4`4Cz5EwQvMa{5csM?=Nm+>tfj6qrj95)|xRPajl9FmI@s|HhQqY|s66xU`M7 z-yN!lclY?WbZ=)H;ZkzcdS;O&3eh>(ypmqRh;BummRH*i|9N5i@Z`Dq`mb1iyJ_AT z5N-j57q-WZsR9l0maC#4scf7i-0c8wdp-8T_ohQg-WER8jxfEj-u(%T4MHJ>&dAmwAdcIgt?Ienp7`fWSyTHBAKkgJoxiiGUq>e93_<~bxmxSE`p0SILS zH3=*$*S9d=8l2)r9e$^9TM+xE`mnp_{y-%80RSOd1KP1H=y!6x@f?z~F9V?j(8d|| zzp091$*Y%Pu%fG!wpeNpp(xH)4>*%^@pPSWrcpDS;i4kNb;o^cP@`0_^SH{Ct@j!U zjJL%XU5`wC4FW-R#Uktdutq)kWZa^9L~b#Aui5i;G!PFOPiK_y`Bx5yNi(LLrqRmt zmg8<>7Y#Y6vmA^5kicn0_ zDBtQy2LeRWt;>Y^{ZKyhCJAribXfJxPl&hb(&#Dw$QF2{DUzF7^nRuuKieEg>|BzP22WfJ?1;k%|CG3*M~D3J-=i&>zUJ;wB0T5aeqrg z%Pj~Db4Fk`8Qj-D^TP^?mM8hPq@pGH*WynnB~A^#C*+wLGfk`?@ zQj>NbC7J2bpA&?(54vLTSA|yH2y5VhrIBRIcQ`Xxe5JT&;Bb-4$e-;Q+8QBwI6Tno zyOaJz=Rm5mqx^4u1!LXNGR29Hs_2KPI_jaJUj7p_-X8V=n@snxaf|V=6$fdpcNev! zxoNdp9OVM^{G8oh2Wg4QCbvh3#SAm@+O)(R7_ihEw4OGqduw`_fGA2>5?S&K1TY%R z?AzHUErP3I3Gb7+6?<9qz46HkY{q&qeo2Gj$FjXPJIxX#rF&|afc1sO^HB%bgt@6c zt^Dqk$=oNd@|5ZlyA0O~?DiDA)+AMgvZ1-YAj40vP)>NyTohbdmufz?J!5|3xY+zz z)3YesV_9(Ktew*W!QC=u`hJ$yK7XOqZOx{M2!Q>rT+h2>z`E5dxf!sLUASGIpH+e=6qskZ#mbKm zhg|$P#hWeT)}keh*p&H2jvK!XCoCtn!p41hOBcqB0SA)SmPgDn9_=?D_eP!J%ye2$ z#Qrmw+@~5InqhEgXm<^g*y@U_-ga=D*-wD!E8l=mkpz`x+csD7i@sgI(@iYJ0)x2z z$PhiUK)fOO(*J-XFQ_t`qXdvM5Uur5-y&OvjOEpr<(wc|E0Wji#*d$ySj291J&R(J zSUiH>;3T&`>EQ3J)MwRdvrI^@XS(ZtOB)XRN{T6chxH!~<eoA*2vRagKb)*EJ}Bbx^-O`9zZJ?Fqua)I2cbDKLK|+dwQhrV@%eZk z#Ax^MzjCV%@o&Sh@R#u`!WlMhqHY0*Ap~))oZSw?b{)=e*7pk&q@|8Ttas>yfS5wY zh#RD6XFpLakRD4rn@BCE5kJ>3K$v`o`j_BOq>2l-D6>jxSjECk#e}tNK}Yak%ilw0 zU$e{F7b;h6k_ApaXBw5geA&=wSnyoG@uwQEX?dk*y@l!=vpZH$*>3?Z*b#iVX6ihr zbg=Mj!pk(+iF9mKQq-HV_4Y8+b9H$om35K7-Yi!@UPq|Z2gl?EKG8Y6M(zziXPhd2 zMP#wYBH-TOP+#-yo`IX>KLFd4az`{_e{}|eg?g( z^Es5EZug}=dKEvGc1@0Ivx>U$C`P(H1rdfc{>>@>?Rz827+Gl@xYIzR`beL?5$+^P zpH+^0ohV_?zpjW5lh+fqPxu8eHIZQQR8{RFb#H17rYULtQN3`PonJ-nbm^uzmrNHK z+|Kd+E2(Un)t1_-|3-aDtysysNqR*6+mYj583wn8dbfde55k8s?DyN^39m!RA8q2S zq(1uxCjG0tOBDB>Jlz$+u`in);`}y1?W-p61je4$|K`55`Db+mCBx3;`A_k5@4O$a zNtvrCg#-D{S5_}P^B;y%2ahd}MxGfI1)(Z#j3k3tE!BRXQH@jaf{v+pJ(6uX4fv<3 zF|226ahYExfT~i=``~rq0;5lVUHrI$8M* zysIDf@PwsmQ2hb7(2-%P_ZP6Nc-}za_)rjP-Fn0^n)as>fa|P z@)Ppm>FKAZI7%x54G-u|G~?h#I|#p(_b%H%LZ7>LvBUpzy={Im0{@xJL>VL>DHhv5 z$r3IxpC~L<1!>QHlIF&Exd(LyQmd$+O!)9ZPuz+CUsToz|HNIQ__yRGRgOc>`> zqPZ@Go)*iunX7liZNaNptJpH%y)W!qO?$6PRKokS;boTG+5^*`c1cG>tL`4NHSfBa zmoXT%LY=nfqSd7RnsJtbrQ%R{4T`d`_Jv?GIJ_kd{Ls#o>-(zTy77->D`!Fbw`t-7 z;7Pf~_p1uJf9vbqd{I^1sfPOV>3T8A#lVBENrLAR?NoHf6GW(grH55E;E7BfG2T6_KZ3 zr=z7mzs$49^_eqN&S-PLY*ukv7_EvG>xT=pbCiA7RXe{Zomq(X=$7z1yKtmzH`ein zW0c-=3`_dikrePVBFqswFIeFq-e7{sL=ZWzvu23=w<%AE0qPIQm$V=_(!G->+nv(R z<+3E-!tA0f@ZmZw#S^(H->0cbNy-v#p1&|+BZw|b?ungP{~?K+Yl{BL#iDA6CU zt21I-JgCl-*VU5#bjDJ^tpBo!jyo=qDkD3)F#nop7Y@9Z}LFxfA=o5|eXy<0J8Lf+Mn zuP<2odn5kj6oSn6Uy;0$C;nH=*oV_(9`p{8NGxqDnZIm_m|xUj1Vn{r&?movQ$Ep! z{>fp^|AsPW8kC6vTS=;G?2J3SmN!(oEBy%;^nJ^bOT2?hsY&#{t!g5r=HyP&oD;c) z`)-auCya}AXSTb4SfyilC5G3P&CPD+Vc-3ya_=5ifS%LB@Y&3kauC?5d~Z(F*~n5m z(IDF_g~;pm`1h+>V#C_?MCz9#6&g;GM`=%Poj=8%v!{`UnRLuciE!0V2wMw}cr;kM zS#YFjiV{ngT@txmqQXs_bo8g@Yn|(W<-JbQrhTp*6lzngPieem?OQCU?ct^!y-u4C z>#=ot%$5ypZ5U5c*Ts|;HvY6&YQ~nMF!)-JtHnM1CF*+ob5ht-^nT#yiShA&_?a#D z`W`K7^vdZUi=rY}Uul!-NkV-59l6>IhXv0{$0g}KsR!a!D~SaS3*OFEX9=zG`^{@A zMMRbEbJ}lsctYc!V9uze6+ndnD%LbKH2=jJA1SFQOhOO3_r^<#i)(*59npKeAu7 z_W^m`y08!422%pBhR3NW9Osu42VC9)B8PCB$MpZTBQjT1Pla}#@L9VVT@amWxwprE zZ!UTyDkdP`S%kThm|ZXvtlD`&ton0ZHa#S)Pb^p(B!K3=^C-&cj%Ry+wf;B%zn=Qz zB}1uOtR*_ngx9P_nl&X8|6Lqge(Qg8YgL8pnlJni z7*;6TP>8=6;BdZ=T5_&+yNrFJ2;4NWB6>%E0so1d=uC@k!cY%Tlx3M{hMYLO#vNGd zAyKzAC|5Cxj*^{U~ zPObV^*Xz^ed4ObKvGBoy^EJeS1hG!?*46q8BsIU)TQRm~AJs z@%n!L^mwwQ_k6oH0Dj4_bmNIjBnsVIS<*!^Q!d> z6La`c#TjZ6{r45B9iGp~Tw9UFHB0L#Qr=8lmM#R29i>TTBY!@JZ0X06Xd4gZ&(an~ znf{4T<3=P8^1TH8w!9`hUGnCPH~ZBjvq~m>WUZTq+(*~%J}ihTFY9S}HQxTJ^>B^{ z8lXTWyr=M+6--K#3A)?KKieMrw$|!-5mobj5=R_(}D9tiT$DmQ+XI}#^RR`PYr}d!JH%CKYD+>A9OFF$D2>QEz zOM%Fgv&F2ECdD~=At@bG#=&g(sDrXTtqVg-2|CFW6jwi-{3zxhhf zX9*eizZkrfoW9K53mF6Rk2?~b7=ugg!oyy!o<47}H&nm>jOXFcpR4ZuHVRT#W(~H@ zPJz@Edbbx?hUEC;SpAc!!$6Ldr;B~X99}1xJIe(x)l*ZUt=H9g5A2JLD&6JBm{r}H zkHU>ZZ>4#M;Gel(n1E&C9Q_WNxY7hWRm)4R6uo*E6dJCB+!(r!t_&E5yl>z&WqvK8 zirU3(1li?cFy}so!;>6zdnuzaabnOu`5~GCo4)*|#cvG9&G~Xw?{nBrE5uHl^Wf%T ztK-F8rG8C&$55Q~?`CR7qzTI)wff4g@d72B^0b9!aZ|)PFZ-B`s(nu>IsdTzlPhG( zA5BH;Z;-KW^%nO51bO}!b9xa_iOuDP;`9>e)f4vR7A;2?(ODC?#cJHW?>b`* zO19EVq?nJYhY(+#Zd`}fRKon5JL;o%7INoroc+Zq;4gIB9HNbz=9k^_Wo}>O&8`*3 zq2GCqdFUP=u2mAT9%?y+EbJA$v#$1{d%MnG9eA6KES}I`sr}Qr{-Vz1JPZ|rIi;q^ zd9mxN7r`{nM|G?{WIk<3Y<(S;)s|=5f@PdOd%e3SO&aq0to5VlW1E$5p$)ji!}!vE zLLaH0M{DqK96yWfdAZ9QPR_BHm!Z{G<8ll|)e6AKCHW6oRjv}bo`@m*}9LgmJ}y{ag+h2jxm(RLrevzpl>A7K@o43 zB4gg-Un9I-^9Rzmd1As)NBlJha82@(|I@K5Pe{*{(a+tx*WDm>=Zh@UMEEm`&}=l2 zoI{z)obUJWS>(&n`?K#M9(h4&R56nK3RZ8x_gu*2#>J2B$A>?P+Q~>7!8$nzYEh-< ztbEIV^TZ+0dck+00@XsgnnXbBc?-J4_g+{Uu5^_$K!x4z zQ_(gFU5ck9asY*aHXj9jo@_64N&DbtR%Jhn|02U(;MJP4dBg*qH-B@MX^-U@oe8sY z(Dh6HC3xe~O0dC*32n~)_uAI+c+EW!jS&!^;^jMNO$Cq8{fir=VtDS=*?XrV-9@tj zg-9Y0?={I}Dk^IsAI?v6Qfk^oc)a9q?XK#?31wD*aq_7q^2S z@bZ?(;*9yNfq)dU4T4hLx3l{JOSjkX!{KJN41X?B9CxT(k`yToG2>w%`z`6z(Ba46 zoqgs9nDP`#Ps5rgiAKV*;d>$Ct}K^)@o%E227Oz9Qcmp$UB%Wci$08et-i4W{9zo< znBFA~J9+A5v7y~y)AML|RDI90;@^2vn~WC1TOJ}Z>nQ)gQ-=5n`4N7k`{~(+i?9|H zjXz)Cw_QF!mj%>>_@>)4MzMMAtdLddD`G4tJ(CXoRhj%SD{tS}4h31m)9<`aDK||N z^B~IVd3@w$(khxk9KXi#cdF%L4k6{SkzqGT!Vrz?OIqN1e@B|jEvfyph%`AQvxQV) z9{J`e%|SvpT_=Va(Rv@CFfO9?)$}MRR+?&wS9~g#T{Qq_B*$K*;I*Ra*a4WzBp{H2 z+OAx)X9VxHvJp&m>5qP44S_`z{N7tRtXtZNM{h0?IJR0mCRfoY4V^N+e8OhLhp(7eZ~QMFT_d=0-|x*!tr= zV%PT4d*Is8#^flmi>H8NKi&&2#DC=p|8|mj?Q|f8D^@=G0;hb6{io`;NXb|}qX9`Z zt(c`%Vmfi=(qsPunXgE!Do?U{*wWhINOqB<{jgM5sy!g(PjSiQiJe~TJE=c8X?AK- zU&<{5-NvQurkHJl9?%P_dv}nqztc!Rdv(#?6qC-AHaIG0Ci+!etg9$6j(`!V`+;AU zy&+!%{r+#IIqr%&Ts1Ubn2IU?n5GxMyu?T6MVOo^+=>n%nN4@)KD@#sg|=@mII;ju zXitj~>n~&ekBlS_8+&-P4qZhJT?OdF8J8akd<>BFC&LU8*P7?%aE~N5F4GkqRaaLp z2Vi)9;3Eo|wzqd`ofq{^DF)Id=z5~6JXl3Gg;vj>|5>o@I5%BqtPVF0Se?{8LkZTw zK0=Qw(&0TS`b3Jg{q4nR?YtQlO}kzX)nAa7TD?KqzkHNu8bXz{2)+dY;aN`FKareX z1lwr3Tggqp^?P~|M(veNBC(l0iOso!=QPS)BPLe!CTmKsc6T~$h6a`+uK;-N;DzFk>SRisuEsYZpe*EIcE zqpI2Pz(^!Y>Qr}7FK#j-cJAf|*VYLGicOu!Qr8f?I*Dx^&t+n*eJvl@iQ5;=&uA`X za1s0OEJ7qrw9W8O%jJ>&)29Kj47WVh(47NGibU(VcxlQSV$F7AAdJqR7YY>I)4fm0 zBTkn=r#83#;S`?f{hARxqptfxJTnQmezjvaw{xV2mQ8MM3L?P&jR2Ml-R#A_BuN@ z&3@kYh-l-l?2|>d$E5M|jmT2}9|wdj}2a9w0x8?Ep>ZU^HU#ac9t-+P> z_!3UmzGmJEs}H)!*DfY1;PS0d)GookLv1@QX(inR z7@9*AUS@Mi`6K>=LB(yV^TKr)ahSAQLs6(s##d50W2cu72R{deEHEsWB`yBg>&RgD z-dM3Mv0qbfxIQ9nz`{E|^TA1)T5ssCwr;h3$1Mia3G`NV|0FU3Dn#{aZE=cHtGq7A ztuNRcSNc#UmMiA{5@}-EG=2&fru0hm9B%pCbL97Mf{Ga4L$_*4q$c!z?N9E=g3x#@ zJfTT0X9hk{$9t@ zwO2A-07AR$!_YQrYh|TO2dd5ZkgG5HI%I*w?)Z#5ZcQ?it7chv?w9j5uDxolh6 zkvsHSc3}9)nPSFkb91nOkCQ}kZN(Gj&$`sNK`3#a6aAm!{HD7mP{xunv7ov+VeO9# z)UWu}hGL)XN97NXVjQ^*SDm~RJBQo8bb^zBgRWk)v1%jS%6Xk`jqK)?2e6o7`Qx-J zy8sglx8xaSx*tw=tn$}(i;q8$g&97v#J$72x+n>WUuSPvL-ag?&I*kS`&)a3&#wk^fP^){QUf7wSv)O=;gu;lKUtgZF1g`909{T z1k8S9OjyXK3!4+Ujwa*p05axzApCiIA)Kc>+dF}WPhXTXZKesh8@|2K`G{jfEJs8u zYeLsBUu$Wr`;(IIiW7dgAM)$*-d6Xs$(F!(l4#Wp#l<6YP)J|U4kK`Xg1+(oEKXaZzqa7C?Oxs06v&-^Q zdOII(k&N~xl-GK4hL8h7dOOJ+3^7pb83e-e)de(K4tUSkm8_ap*V9+Ovg8Eq&bDGj zrsRf?oK3xc(ODuh@_hWDNyz>CS)q`k$VYn_j3xbF7*kJ$M<{L~Bunlf3L$Fn$?WNz zG1+=3z_aP1%NdFPk!Cq2&~Z;cwUg@D8+cNdWL(`_T$udn=2L}frN*YF868Gvc2{Onq4c{fqJPUzk7TY{0Vvzh1~LLXV4 z9jn-`2CW_-7m_*cLmhRhS(>=_-m#A+F9^91Vb}TZcM6Sx@+{R35y(`ODLZwEVwAhT zRaq({l|3vbZmb_UB|EP#k&T23UH?R=w-nhQnl#$$X|r91bOfI7p=lPs%?6iqK)U)J zE%pM|vW~u#LIl5`T_Bx?$_(fVY;H`xTwDX4Bu{W)r!_vSDEm$Ououj&m}@-AeA7!` zdH6MPM{HY$<&i?Dg~q?&32pBu7zgw!RPm&fVB^WR-p&@>EbI+C#1>PM{l-HIp$1cv zOTE@JOec2H190k~Mk@~Pr?AhMvAXCo^5b_+-1O~GtipD`$|mCX<@)s5NE4Sb#Eg{M z=sxZZ6?o^3-+EDdYn`K2cDvo^$1*V19uZyr?*|QkBl=t)O`ii0APVUiV(X?u3Uk3a zs*Md{R`*`;yw=P~yEy;uABddjGa zTmFr9bR6}i=UTmHuNgEQ$RDIm3R)B3x#Qm3-c{x`Z$Nvx{n2J)Daj%U650v9u;N1G z^}ZC}UVRmHFp+y|vV{Ef6FiOGyC;F<#ROXByS z!p@O$-m&+uzC`iXf2h^>)gu~zeHv(P*C~?pMtdsaD*<^q8O8js*L$jI%e*8wcFS03 zDESf_gTwA;1^${IMOQz#VgL217t#y@8$qhdVD?1Dy66^H=NF4L;+K$X9vchp594<`5#dPydP z^Tz#Ltd}kdb2gO#)F~DD#?Up07IxDV7QaGDN?KPgpYi!K0>!~up&O84ci$vgeX)*h z?pv*@5{FgA4x3#B${`&c;yFsL zQ9hf){9Q6cpw{r%aAOoV6;1aF31f1k-i@w5VGLXjaT$YlZ8j&l)7E3;I-|#_?S?0* z?MhIKvwNC1_s6!FWYDeJ3-Qa)YvZ%Csg2=Ysy5-9ggYKb0$v_)bn;mwcCT zg+}zI(gZfNZdx2uCMRyX9q&9{Z%+%qy%2eF-{wVi+#GH_lWMXn7%0|{r`Td-ooP#&!?ev#&WBGUBy-(546I*a( z3S6i{I97cLV^XK;Hg2S0`r~87hSSmH)0|yWOOJzT0b*sqJP|KK;2+{wZ95V~bQ)c0n{6!{!}58g?d^!ZcJ zODGF)_|Bp!S$n^!Pct!1E@0P%4q3eF=rBohpFnK5PLVgdGU7m*?|;R_)hRsuzEAFQ zAUA(19?Ku;C;f|iR@!B`dRXF1{z1P77w!)+79Q`I^ln9G+YjSgcS%V}oF-@*?lpIV za~)RCu9G z$Ahn4d1rg1gA7WgdzqM$V+^@6?;}?`k{KwZ2`;w2y^`se_E>&Jp8vh8dQ#O>Xvw3q z5nSeCJagL?V)$zg!oo1`;_Fm8Pf*!RMU(}`b{3}f#QI2U*|}XWipUUqI}I3*-u`b*PUDG zul&UA5J~Ok!Z}OR5=q6)K*N39x8yX~Mfm#Z;0Fm-0Cs&guLjK~GftX6-jd&?w#vqA zB36-}6RzIx#QY^;?YM7Jey-{~aLMDG(#+k!3Os)#CnN&+B{HYZ!z4=a5BX4rkuB8 z;l1t(Z@DOO8L-08XhkXig_T_JNVIJj#??!%iy0mxbp=xIs)Hg7vfq z5>EP3%N-e&Q>5{^&IboQm9{L9ztjB*?(cFxF5iW3Mb^5$^VU=l$S?m|i-{3l;}9ZW zr{40uw_SW_H&U*z@hb|7i~CaYXuLA1ye{yL20eA@ZN|~T7)!33ibMs$1ht7ijX{*##^24`HkwK{Z@7z~*R4CDdgbYWu^@p%TCU)o7t{N6A$K#ody5%Joj3;ih6 zkj^e&@vf@LOAS8j5dE{Eua$jsSb2e-_Z{mP22NHJO}a_^PXNGL1S$k7plPSVNcIk& zb}3iNvPJyBW)^1Nu*B|bVgP0#9no3N&y{CNCLPduO>vQpL;)I)KL)z-r!vP(-=V*>B$m)$cgI!8qFTG_!}G8tBS{5Ug|A;5G7rRH&tO0q0;WszI6G{+m{=z^u9 zlrv%@vk@RUdT$r@$(cC*q-Kyk((`qL3TTr&zn!Fa9oT}!4xhnoN`jmC!W>Vn@qX7B z8$DThTa%*m(cVQj)sy0h?BGDi_p;ZvpQzuCdq$)`QgaNiHZoT`@n(YIW?IyTs}ILY z4F@4l-b7C=EYNKwzLc|jW&fDy%`i0^?(^DYk1ZPE5se5rkHtTjsi(~LIH>NclGSr* zOvm0J&V>9@_3yu42lMda>160ovp766+pDVKMxNg%WMO6;3*flA+$`$ks`sb)0$+Xw zOMl>fN>~|8{A&M5FaV1MIb~zAA}qsSV8}s0Mzh(I%2^hfKptPzb?P^w-%m1+A3UX9 zkDXJr>sPD#$d4Z(r5H#2SfW>S?bK3scn-X76gD9}_D(o;d=i!xqJ8q$;1CqpI0oB> zfx4wQrYi-0vvN2UqnYdo=`Nw({?U77YrC&hJ>DDkAM!{ogkr||Y|aMXhxm8FC!PKD_d zJ>l8XU|)Y|6yd>cSiJtxO`XRZ6KN5%BDh`#jvpF8iM6ofG7%(bynf+JtJZXM6ohM# zf!~E|Q*MyaA(+|??eE~ixYZ*n>ymjP`}`!jR@lI{N#28hJ@yElv=dt*KMPE~a^2(8+mR9}eQ8JbDXPQj^-&BmTAQoLTWqkT4fujH|`cZZiUokf8-UbASBd)Cn?LbJ;i7JWvBcv8KPPU*j8eDup% zfR77dWSD=MJSL*bwR1fR373h)8P*32N0aVo$3?n$Ce>DBK<4*>b1?d@FI$`aTAQuZ z+56IHK}AEUjW=WifJW_kG`#KA=N7@U8xVjdY@W&!ZZMWU${g|_qjqmkn}Ds1IX1#o=_FEHTCKXXFjF0uSCmTs5cuvIhbpsF={c-go=KuHyjEVn0*0| zTlqTzwV6%;ezCRrG_35;=!)S+NJj{Uj-=sILW=+G%G46_^z`(?B})ApDKFkUf+eXJ z`cu1=gUl}~cz}rUCo+ERc`iTDAOmXts7<1yCkyBVcj)901x?UTeIY)@P zI!DLWQ-=_q!+_2Dwz14L6%(TX2Ri;TT{&xNHfc!$O1e*bKHx#)R|va{9V{V5Ibwzq@9PwOF?5^HTEU4-i&D7BQ5WrzAuA-@AZ z#Aub!&m_Lo7h(WrS67Vs=a8}~8xEQGKJrTq4L;vu9whJ^mU%hC62U|gx2y9K**VaK zjaN><>(jMKo&Df$*a2~Y4`II;90c}n^@w$R0KB@FCaL<5KPrtBKKnv!Lbf?tF*`Wk z%X@jXi%zN`=NPGZ?s9)fHpM@0B)@Pz^=!`8o!@9&yA$EkqG>(PGobY?cZ|lkphWak zHr|O!=QKYjoU5}Yuv@LxzmK2FvvBQtF1kN3H0Ey>yJ{On#*Z`66^knHx0>U|M+8&` z5PlA)RHYUv>3(pD0eQ*r}(YJ8>-SH&6 zqTo$E>i1g^8=#tpfwO7$)m{nPJbf<%QV(6=EUK<9qo3+Dqu)$8{e>;nTMALBxs#wp za?7#!oU3d~{(j4A(EM|gHrXY~wwc6;y7pn>V$^^c()~6X)MW&jMhT(K>Im|Uzk+GW zl#q$uR5~`0%)xQl3fCj19WG-d+&&a&ZW<;=H;T4|4=pI@J~tU>+MZHVp5Dp{_~kX6 z-u;O?CeXCIrqhuQM3B$p?}};`X?Pn;EF$i5-0tp*=zZSLz`IM8AR*KEO|3}W!h+uS z*X^!IFZw+Zs}=%MSLF!T`gfKqO)*8q=T%iGIKZ5gX_`)KN^Y%4 zV$HG2AAt2JIl@0gx?deF7fA&ze)p<%kKyO%w~cY%LJqq+^Q97+GiSiJ?cnN=8&8}3 z@g>mlc008*;g$UBo^#*v_M^7nkCj((i%7`;HUgl@dUpQv{QmHkJRI*DFtZ=Xh_l&dx#B5PY&{Dup870r zq!2HFqg1IDr%OKZsaG7YY-+0{Mf6FV0Y7Doh%+K#L49Y%WvS70Av69*Z6GD>S`Se+ z%_PFd-#1$3uYf+M62VXK>2KP&aGc|YES-C842f%w;R{S1V(gX=9Str z_};bKT>pIIT11J>5T$hVe3o7$6$0{`LnjCaA>IUkXHqM)!maI>+N^Dyzgg-9oD5%r z@EKm@6Yb5|4~CxWD2pHRhOLH0m*fV2*8RLk^)k50s-O_G?{`T)>Xp;J>Tl-;y;UJ` zQJ4dmz0AHTswMpDyXs3ZVE;x8E*U2_Q=5sntQq1wY+Tqzmr2C*5m)7Wwy)PYop|{z zs!^|STa9eyn?lWd2JMk_u_^SmNb9dcgZVIYa#?Sp?#Itxp>y4w$LVt@9YadU4H?+I zeph(mQ@1Voc4z<}pT`?T!u+`BxJ)yyRSy6olGaRb_36%ZA092+ffiBS`a=w%r5ARC z+t<&|F3#%!nl{8^#Y-mgiyOdp`-7{O9EoJFBBy{#_}&U47|zjpgE*!N|1*|DpgoVx zRf$~4s_IGwvZyM-RH~jm@#k`s6S!>l1&VA;Y{zjZpF0&6xj-Hcb4sgkh*=178 zlRb*5Z;GRlfP3g@0Rre@#j3~4ZaC8M6xUzB=|0^HYYPdo57=c?{^k=C^Oh~aof&C_n%2~6&E2hp)BTEC2 zuZ13!tDn=0>26EkjEdGd28it7X85pW@~`xq>Wj?ye4*jnVr2{wx5QMSGMpkHSmUA< zGn$&$Y)?m{4DsNzvE=b>yQ4i*LB-#FP_NIy^=jE!=-RDu4rv?!G>sA2?&g7XpsK7B zxERF`pYdZ@2*k`j}XUCh$mLv3(Y*w>Mhm@6F5GY$@MDXEX!{U%?F2HBgR-d!FP?U4gZ^9z{fb1%t) zWo9>)`=;tN;bUB80=ew#;$M!VC$dgBHh4}iqhj8gFAlz(I^cJv)CO~xR1U(;p4*!> zSb^Kut)G=C zQ71;Nw1f^v)ce)MUfMh_(Xxk8w9_-0QlsmKjD+>Q#>)jTqxhDl{xYX zNLzL8({I{GEsCv`0}qqj1?J*03ru4}@?)|wJI@av$qCLSwc|0gUOHACvS>kfbmzX` zzx*1`@m8?wzHiIFfD@x;O z%&e8{0VS3E$~_47VCV@ylR^I3I~p0T(w|TojzJaeVQV3qBJj5NQQ*RsKUBeOXc{fL zA4Cw&_(UcM3ET|Mzx(L(l_&8_64n7xTDoyjz$6qGFg>Gh1jSsTUYA}kQ zh@TG&air~(TExITN>-frg9b!<13vd)K+FsRCEpRM2m^UZBAs% z^jY(xH}Dw+AFv8M)=e4@&ahRP_TmgPRl{H!k#k|0oIwWu{vuDw1)fRAkYhBkiM_Q+ zqWQsu#%us$8C+xj15@~sB(~lFI(6}d%T?z`P$pL`H1VKyaJd9j2zPLQ&0oq|p(-Tz z3B4NI+o7j_ripwPorY<-CgCvS3z^98fc!yaJ0Y(7`yXxIc-|_!WXCwYMx4RXZJ3qW zA*UEQR=s#|9s@<%Zzbjv%^)RPZ`71&lU;qQd9UdrtX;#l`<0srhm}ce`}EWFL(%W5tvQ)?09!JJ5w-r7}yT2kbzn9KJZ@#R<$v$8h-?6 zca-*VaNdmYVl_T%MP;hQC9_1{-AZ7;NDorflv!Fc$57vIuC1J`c0aUl!8d&IWg$%0 zuE$$EPD72e#(n;M?^p1Sb9xVtO}=}Q+Ti&lGZL1^o9l#^*T;sK-{2nb_4a5G3@gi;GT##Q6w~heC>>E|p_;th>!D9j0X(xjY zzC)h3#L?)GP2zaxpw8+};Wpag`Ecd$P<|liTq%_|LI%pmR@y;Ms|8Utdkbey#~u@* ztsR8&ssOuBPej2##PD}SAE1l5mKY)Tw@^#V(R{!=dxrU>waqeG=O3!{zKwj^GK^m0 zNQ;32s+_E9zU{wHOXl6kT**LSr_0F~9FOfz3G3^XmlO~rvfVaH>sQJ7Jh@a%ao}y9 z&j-!gPg6^`8*nSfu2%rk+h5)w)UOL_`8+%SeEyP_hn7@A+AK<9I4rk1Pjztx6D@p~ zx8Jt`!y*&9i!HAICM`&2~7`)p4M*ygSUS3A%GuDg6Q@CYmT)H`mkn;`?Y6vSCgCtR+o5=#R1f4-M+#ej+H+)^mR6 zX%F0j6Re$}Tr~ETyX#S<*DAbkvqQ72Hy2$c_YefZRYYfi$h_Z;br4Kf35%zM4!QxQ zl&f$3WwB=EeQ|bryJyevM$kDa>1xepIIjE6Yl>#2{hTWXzPV`=4bCZZCzT$(?Z zQCdaFYS$_Msx$qQxWXwA-TnNdv!0(R0D4#T_J>OwIHpYo)-ZoWo+wo*6s*b6l&nRe{iRY!JAM-#;HmvNbyWq#Ie zzzFWXkr5nQ`Fg7%O-dw*VS6B;$Hc^Z$-*)?`8?K^TPM;|)tG1_UM@`@_Lb85IEB7l z+?XKz>NYDS1r^w*#=oe1p(O*uP~L(-Af37@kju`GGVNLfh$ML4&tE3PJ2^i)C zcXW6Blj#0ZyDtD9Rk|J@o#rFY_{farpK+;N~&I zE;b*eRe=7&8phU*=9^KByYVTQ!%=O+$2Rk$0_X5h=s?rkwanQ3CLF{Wl` zCA_>qTU$F~#;Vk2mJuAQlkcdRnB3iUrDIQEGkjKdHX%srXt}Kwl%Y5jB~rnYrq2g$ zG2Pj`53mZ@Qqn_evW?ulKlxPsG`k%`KfR?`;^lrlfH2fZprfk`J(53z76Xi*7f?pl zk>)|@tbnh+beMx{ZdAb^1+(N{7^AcVWr&ZAhck?PR;csAu$13>~?#5JJuEuFnNSN9=Gzj zsrl4RQLjJCSl^bHEbo_`!rQ0bYEACzkiXpCPFouNf#E!R zfqZxFS7c>CmF}_y)XBiUaFmVy!d>(*C8RBZT!0{;bGO`}*-l1T8j|0nT`|j0|7}}k z-y1wvm}(X6?PmeW+qdTHy!q6@Q=|gXnx0HlTO8WgxHBVR*6klQt5QDZXDRjbc593# zU++PeX(-61ZAYO8tOX1PBeX0wH+iq%;pDj8pxB6u2N7YQb#{g(SSjA1c0^Rl8|&Lh zqz7s;aB*>!K|R?%YSPeiIc0Y0etLDJwQg@+!%E2aM5L`#+Nxj7a5GA29uBYp*~Y&r z28;VeyC~~drq_=2%P3y-f83|uy79*$aKU+EfX)ouLl4*b_&>ajKgTQ`qOhB&^k>8u zfCYyWAo?A(swwLOheeAr`Z_wlq1F-&rL&{}IdTi?R@j1tM(X_*w-*h3+Z*z=G!@OJ z(_g_%lTG*ALBCOkK|=5N0ly8Fx^nFc!F%F6j?vIc<%g&NzU`Wv+&4&jDisWcSN(4J zK>Le`cb^-p+86(UZ&@z%WBJIZSih_S`lu?8hKmPhVrZb$VaFXr_QjYx9oO{1 zxz*Vw{Ws_Ie}Cnc4+tywoA&`NYhqW&uZVAV;m}gLA+z^XREJI!QRi9@-Fju-`A6GXpR64Vr?^X|p>dfpO=aC=m|dNVf9QeO)3c1r-j zXhDn;=Tk%xdK5C{GA2Xe3sJq{j_n9}iD+(!$=_CO*ca(28nFk{rbJlWgh}l3(dLu4 ztD^tbp7YmIi9LPhc=H`4DiGt0Fik8IZ*5m4lY%pw{XYn*O6GMEmT0tA2exkmQjkj*H{b5Wl^k@8_#(_83hO9h!fvL#- zUxi}w5usHrvd6*A#JoiamtG9Ht8tXS4jpy(KT7BZ&qx_fly2#n8Z!JT?_FWo-L^wu z6i|uHZyML)LZPRmpIoHvKmnt=(!8Vm^gW&(Ht6R}(yMwfRahhgv55g^{)^yE;t&K8 zyVu^VGf90!$hlW-9}50&)%gFuNMHlqhilwhN)tWGrdB@dX;GO90<0Fk#@KHH`&{x`$=>+L292+g3bE#q}LFZAMHg4sA8fp^btb81Q+lC_esdNYDfhA(5Vgf=|1vURmDK-XE(B}n+FZVlo;EQ2HJ4?L zOuMN6Yi+z^KE&t5WGmy2By3HS96(DUHH!J%^9BCAMgA?BW|wyz){#lejyuS5#@36K z^7jw+;LtouU`1>a_i>8UmceOF0+#M( z(y(gKb~JK+{FN$3rj0)30AvIP`Jx8sVjpXs!qmv1YU~Ha&NVU2%HElOOWFS={x0Gt zF-gx&(L#z$1)qrYLSzO||3#txdfz`;Sne*Mxgci>%YwT@75(J==PH8JObo(hWXW=T zb9%6%BC=vbWrm$a6QFgu_y>)jW7Of`kqya#Gg*aVW%L3Qe?mJj<5%SVkOvz5uVz#& zE_U~bCG#;dI+)vPEO#zVmLub1EN$i;Q*ml}aw?GR{9l#$Z+Ci-nVFfR1UK`0_x0_y zm13STR3?~xb%^ryjVPwrz8ENBONd`QVmuh0#A#NoAJ-*cFZ+-mT*zQMRWw@x>vwBZ z*d&JTK@)Ly<~T%M7d>s?cXj*?d-`{Wi0iG`tw6_!qi{gx&13CjFGAMZ%@Qn!MHgs2 z_)iMoMH^_~3{Za0wmbN~7p2_8)e7J?@U=GRT zL@o?uzNe`GyNvIOmk))>!gqlev7p>kG#&yOo2O)aL+*=y z%P(bu4-PC5DuGJ)Kb(Mn^IO(liQ%np%o$3I_M$C*b?_BBC~#NrRhY?V#r(=qud00v zv;{NLrpon}Wtl}?6zA9(Rn+5XkCa7is$llw%vU8bXeI3Hi*sAKnLFp`(SsTl*#W$@ zx8IyJZi1T21TCmhsm6xtPciPFmiXBwvM+h4iEo9FFuf75)lX_LRzLj@=iT27sf*-^ z@GALySlFGD_Ebf^WWr?PxGgOi@Ko4BC4&s41sq#Qo4FDgfxP6{iy>vGjJ9~O;52OE z$4pR@2Sf%XIJ5tk0sJpZjUMx1Ka%$Tpx943#hgODr+BmkGH<{LcHbX_4GpZ1Ob)@6 z4eRQqFG+;L-!_O{TwE>$r6tfaFUAelP}t#4$#5qP-r1y^z0PPcb1-*{HlB^Z+BPOT zG)E1`+HSG)g0Y3&sMu$$3-C({F~S}zmA?}sQ(R;N=@L~W$^>PFo z|HZ(j1yFs?rmdD@cFGg7zmc^5()ID25qq&Ttli2nULe(n_q74}e-x(QXM|<7qv2-A zn4jms=EaA>RuFjg!c(K*_Sn;AB`6!GpY#%F1XrE61`oD`r{?bU3Gz3sr_bK81 z`PBP1O4{EP>PoRB{VMkK!G0x~dZ~jY6tyDie3{;LJs4gwXKUy$tem9dE*HvSD5R5R zh7L~?ibMv!2`4S#kmW@Ug8%x||9*H3YVYoU-eQ3NxzIp#zuAhz9=Oy>zufCbvze^5 zgknPu`cX-F3hy?}ZKtw>=&6kIYgU$IQ=Dl@4*9)varOp5{ezEMJ6*^op$MS@%k>Ua z@72}cxVZ4Ry1C7R>$|!n`-X=8;7N&vJUIo(F9@sM(!xn3L;$*oh0U=%3B2{h`1mKm zsMr&fL%r838@B|bzP_5BynoU(Vi)MA2bvdJy_2#xrQIv!9irJWD5J^$$)p2ssDE6m zo8D=~BLyAi1nVZ7=noGQnbfs>v+3{w+a7+^*}2ihXOxn)mG;IXN)x zYuscHDaO+>(=`xhpJ zOuJ3)5Sr}=K zXe;CG-Qi%cZ4dHm%LakPniWsprT@eAsLDaGk61X!?-;)pNLq~LS|GaA5Fde@>lH^k zALeuKct_Z&iOzg0V^D_FWa{(<`21U8{>HFaH*>gh}r0Aj2_buzX6}J zCd42kpe=dQa0c^Bl%ef--2$h>6HCJH z2tUs(H5v^C*5~?`s9R-+2L>i!)Lm>8<4;hsR2}c9@9w;F!Zii1;@bHHJH~YwuMM45 z*q+}r+iepJtqEMMy$KFhE&pqHa((M_}H( z?P6i5O>Y8a7JriNJ4}P(J275?X8qu)_p?8K1R@3V(^%(5AG2#F3D*gGRw<4$SU)Y7 z)dM0cNC^*>OB^6+T*DkcFUR3b1es8t-OiT(e;5Ae%yXcD@`u*lFH1crZMQoapP@Ox zuzNn8X7Ybza zG(JgarnI@N(r?BliJ>WAb3uuWgeCwN_;?oD1Tg}rWSN(zyqef7&9zEQCqc@kk! zg29JOtgImb*A8j+i&D+XE2oEQm&2DuHrn4AcIOgJby21gT@L%J%g@IXOUuhY0*y?I z8)Z?mTMliH8ZMy+vz0k3j!x6=Yd@Zh`c{(z)1qxSOky0fwPj$r6=AnG=N2NZLf+@3 z^NFVS@78oUk>RsZH-pkj|5+kW=-1>woMhddhqse1FZBTByh&Zg$rOn3{3k_iCHBc1 zATi9atFdjC)xg^OiIyC(o@X9{yGy^AG-#7E4wgl8VIHiRqQ6#4cNX=EiZizq_kp92 z&&{C|L$UMiv8hD#SQbG_Kqhl7b%<~pi{hkEF~cIGlLD}hibh}w6X0}KGU8}M6BF-- zlg7Ea+#7LwQx4pRf)7$d%FHH$qik(#gs#T;qzj|E zG-_U34k#8rcYg7cOXdZh2wL~;<}X$?U4{{=>K6NVHIELR)=vk9HEmkzYfI4#+q&l5 z%fk*;?6VN$QKiK0JjKgy3zbxmwbTB7CW=X-yGGp8$84F&hKFCS*w>MP!I>L8MpijY zK7v^{`czb!tERm|zFr|3o3;?EC9TMR9HwwTWVjFez>yyH{MRL=#ZPP(lktf zIYR?bZfg(0AVA1xGLak=!!TDNa#KmgUw98uGyJ{}j zm%*qusEKlC6DtkSR`f!8!`MfIUhn=(equ`2gI6DLoVEyeA=~(WcOwH=ByyW;QA)0o zJ9maNpuH6U=VN2}uD?QV!t%xVpyL&2_lMVu6*MTt)nnRQ3I@u3B}=sTn#X~P8$7&} zl@x-5>qZg;o}zE=D!y#0pe(&UVHMcTtX*G*Hv0-9O?O$UKCBnUABpV;-r=e{1fw0d zl4bi}n!>AYdnW{7wWSh6Z64Vi(!IPB3P==_+57w(cvd3rXElRLxwoi`t1Ittn_&)k z*Zq7E2i<&gwUq-G3zX+jzK&VU@5kldn;eeU%eX&wN(zm*s)YW@GrnVfa#y2%HL9u| z2ZYkvDMdgG4yB$ozZCqE)%k^WLc#8MAHU-d3pKivd3yWuzMR_z{meML=2_{PaGcX76Ja19x=Zq8n?bUY7K?U zw5XM(^w^fLd|;DLAc$?r@A(9MPb_Fk^z<#Zy$Bj#c_?-=q@Afd;v(F-_eYh2v%x{A zzU^-;bHxd^tqc4#;e0}PcbWUa?&;AAk+mC$^ET~UoIHIlWvk8^?`v87Gc8G(jTE92 zFjo)*=*Q*BD%Dt{=gCS-Tzq^Ugd-|`Y|IObRzHu@p#HQmB{{i(jq3gnHHmT;&*5sd zX_)(Ptc=JxEai289Sbw_7aNtv>`5{hHtB0dM!{;DA>W}`$-0}T%)*5q$salpF5H zEPD1(x<2tU0DWFA8@GU3{2&yT!UtE94Y_#Va_`*pxV+3(bzY8J=d_q15?1r57-yJ3 zwjs2k3;BIjxfXM967<+KNQ_=D>da5h+jH$=;9^c<=QP-MyAZIRWGzA6{kX|f6n?R^ zFpna~WF40Y_gN$wjh;PjB~9_yM`6(S=3o_ZsW~oQf9?L7B4paoA45C&m1FL`j=2X2JvC0db$`2q!qiE*p6 z-`!U$L7eA@LYHKk=A_Mq1$AZ&JM^8^<{%bxz-4<*!NNV%o0&lI-No7EVI){045$6-Xpt9<(siy~R->Uj6P&HX zp95JlsFCq9!gh)H;hq@>M`taF*^qU-sa7$sqWo?y%wizuKA*38aX8Ie2Vgy2>%)

    uDZNwpRya-A~c4yLD{silC6^wQr6P0rpR&>s4pcTk+p)nI316q!92SM`5!xT2pA z^}D!JJH0IuT%Tv)2tMSb+2T7kz{09%)SMd%vo!Fb3^ls}ze>Lp#GhFEdTZGsO6iaC zt|sQ=Iug&L$f_sNm@U>afP$=b9Q}DB&!X@#Awk@!%)NP$d2JPo<3#x?43TPJsfkZaV+mpy8H{Nn2@J@sh&UMC!2%)+Q+#daGNztecJqYW08 zSCHG^%|ol?-?1_>1$HgGEw-_l)zReeq152Gf0pfgi%0x<_fD#I9y)VK8a=umZphL_ z%tRu$z#CLSGI8GUw{EZhN{t4FKg%5zOIie>|NX?hjNzX?L!wOC3(nTlP=ITw3o=T= zs>u5ca{cSZixOK_S9%!Ug8R4T4*&$C#y|}=P(aHQ8Hye__Y`q<4~W=0BL6Vp zw5WkM4GDM!002>IYHPO}Z<8|sKO2HdN~(93INq|fI3*t3PeqGa9?te|`vnr&m3O{E=nM4|t8m_XJg3&C zSz!I*>2_!3sX$WaeP5npMUkXCUCUhGW+Lk9;dVb%50rXO?*KXgaXI)y@GOVdh?T?Y zil2&(4(TU32@29+XNmS_f~Pup9_7*&P&8X8ys$k@nj)Ehf0I~1qgZt(YDY|ukv{|6U7=b%1<>$rD6@W(;QbT1>8Ak&cQhCkKUKwWnOgu zwGD-n2Nr(1JiRw3gI9p zJ2yLpPF~)n)B8V_Hm__Hd(4j!rdoL(+xpqPQXlnN$U4)@3XUPR=@bOKpex6t0rXPxhEF>=$d&B$}z#lQDf) zrDtI8QXp#cpR%8)mmICy+LAh7aK)u&(han*kWgrDFz&Y4Zr_!1Z3G%>j)}JX%)Hyu z3qbyk!O1tAWjV8zve?M)V8)oJViOo(+5Y^rTIgq2h>`3DEEF zcO;&B$=z{#tyGq-<(Cz5C#00OwjX`TTU;WZO27c9?mv=AG#^d`IaQU8+_%gUodxao z=W=7;q-{!!sz#gjap4TBXe(3Ro9jB0+>6V3^Ia^6S5wr3Tl#@yaG@&qL9JSE9}#Sm z+=|jU{f-kiNp_XivObk%fi?qxt;Bu)jOnc#!uy)prEE|U<$5Q?bWV7xU) zTM@ufTWZD4&jWxSK26qk$`auyH4d14?bn}M(>$T6m&H5QA)hO zQrRe7G2%|+?4iIWF*CYThyo)rNXrRtEr19WC{&>O{$rdHNSmG)nkJKZ8 zm5CTjHHZ2(j$)wP8YN|-c2-@JEpq`?qEJ_uOYp^n5pDw?%5dO=9f&gX+1r62e{Cfz zSD%jU9doZ8tTAj}wEcpnlgx{r>*Oj8TEQgU$r^TOn{(SL>FXl1GfcewH28<~tVHas zI)&PAWdI3A0qr*%c_o*xOGNnzcu@v6W@PtwxNr_RGa`zzHjsU(L4KNw8jY?hdj~ z&_uBPULzB5m~kAn^r;zV`jVolF&m*=y0K~Zj&zHVP^{3gBtcEa2W{#T`Yiim`Nq#< z>OPO~9N$+3VsD*kkoRSDM=EfvASYcaYa+U(uzILi7_pGB{sW_`WP`1M7A|&}&X4#s z8k(9HV(v|6<(tPNM8y>)fiU)U^ps>2kT%Ff1P4yYx7ek^WbM89aln*L+}-}kmPHe} z!WQqMwsdcb<*}FQY3J*w*}mIc#Gf}m6&GZQru8Zgz*y9($@Gc9#c zIF1*t98BMv`6BH(NdP&@;%WiD1xyO%1s#%5W;E3uv^N;zD7j?-asN>g5x(fLh+G1ctHJ4%jg=-f`!C##m zKGsOX*Kc~;N`Js3WqQZ&kj6(;x_ZS()xvJvKFZS1u!^|Q=Ccjh_g@vj!jU;w>T%z{ z=k1G1jp{7>Lh?GKDY-y9iRr85cphPIZkef;lehJosHmu=gEn;kx;n0@DhoUoi5bjv ztyyK$p=92~jM*Hy3?4a0Q&Usj?TNzWw&t3LnNdv4%n#R&kB{}*p6;Jva;3kYYj;m~ zat;AgWw85hhK`MlK5(FCV3NRpClm?Gl%z})wQttOfH zXj0F>=fhuSwhY&Vid@ezBHIT>@uz;gm;BZ+`_kkn)H)SN)CpJ^o0xc7qg0Y88ctYf zfm=|eQMlsR=B#xG&o6dYwB`xf37p(@7Qd()1B?<>%bn%gt$efU*pp_gX?Cd*yzW}< zKyk8&i-N%xdd_uy5Yw`Ibhy}|<6S%yx)sAvO+Z)TCKhA;6)%mnTgD^i!F;B!aZQu! ziObw?b`_ub52>|PuttnSq0yK3L$8sMYY(>h`B7gv41AAZA6^;rmHbVixEhFCN>jPp zLR^7y6ZsQ?@QNy(DinXF9~TdU%Qe4LTCb$1n0A<;?D=SHyh;En+BWqCW;D5@-k2Zy zeliq~I90wH>s+I2||sX_b73IA(eI*i?PU_rq3e ztsKYaM%&vT2j{#p$*dL^T~O<76e1UC_q%Gb#hYe5C9iGu@YHXD9kC2cOZ9}_7QLkc zGfq5ruce8!7meTP3vi98So$T=-^bV&rK(cTp8O=z9b6K+vG0FV#|2+%zNdoHp?TfZ*zgg3a~(bcTKQ9T}0DCvOGSY8HD2Fu3!q#UBN+#>fCp=CbKUiFA$xfic^c^lc3 z!r?95kzru}e1;i#sVyyc>s#G=1>z*1D-%9fTUQG*BIz*4?pV!O3+HPg7kGE<7!$Cs z@7Zcw5=y7AX#wweKh2H)pf(SF?^S&sJ7DQrwiSAUAxTX9>|p$X#7lHX5*Ov^OyU^9yJ5{3?GMoyLKqm|uvvEAQ&c^_z2@($){_ z3!zjv1*G4Q`yFVzf)K*Jivt3km_U-5F5^>8*s}7(gF9pWsJUV|arq;;Ms|fe3pg~@ zwxKQ@m)5%@n_J4s+UuTFu`Aa4i8BMP{ihMJm4py67=L_2Az$F~#Mk$=u6RZ^mVK>0 zZ5EXHEJ(R*9?vADyd~FYH1J-#(TarPq&*sjcouCdZL$Tu(m^;PS^NPtji2=gfZbt#qh> zD0sJuOr(=+ay+-yJ3h=#a*S;nS$(Y7DbIvCTDmERLDWVbVt@RpNCGKR;9576Vj4^D!xUFZIp&GyEjy<1qCO~7T zMY(VM{H5+gydTrJYWRNr+bs5 zxHF}okAJ_mN0d?FP6bLSqIig}+Kj(&H|?QqcO(`jyca>O$Xc~jwa;)ifv4|wGO5xO z+=smYx8OF~JN#S(3xM?27FceZU7UFV>GsB6VI)>3ZpEMbzrh+)oY#3C9aB(KFonxF z24#DkG0|QFJqIAuETpjHWT9Bw0H|S)ouuEB&7S_Dulc3J9w~yICD-M6fR8}E@s*1E zJ-L<4UAN8aNcnwEB8QqwnAKwJ0)L=d8}GR|kG^7|$Fn%?J;%jEN494cHOE~l>8BHj zHl5NNgVsfLkEV$0-al$veJGT%Q#|dem_2y-Zt`-_#>kViH#lirXbjHh=NhW%wKjPG zttaZRS(zJ*SU){q^*G0aXUa+x}nOBwB zFgg`ETF`f>u54G9tfJ4Dkbe~%ZSrgu98^9wM3>$c-GAmX`OQ>z?6>;vgw3_9@(p^n z;`rPyw2l@^_0yW#eU4J-wuP4tohsWd(*%6C{ltTUPy)jae<{-P&#x z8+0~Ox7T}WRnH-kd|HH^Cnx3FW^Gz+tk>Q=A(bOXF*cS>XU{Zt-6nW~`y}XC4ZpY^VeTBF$JYJV9$kpLBgO-o-te zu?giGFnq6j5wJu_!@yj{!)v|hjfpvEuIdol_z29=h)Tfq@;6tluw2wj^XFPt6L>Oe z+aoS4Tsv0*e1%X=Y_+39hzhr(ql1a5)T8OLpWp(`A9U;tI3`<7*&}48;ljCPuRD!&{Vf1c4xr#l0Vkr}`s5PhdmOI7B2R8OHOv zC0O0h97+yWz##}n))&?Pn0EU}#Gk#{r@4UJK=t~54BJhIf16{K5|L3w;nm)K%cq7s zeE($Sh;csFd(Y>6bZx~t7l>gy>W0GhkNlQfviG|JG|z8YI~}kcKRuI|mjqC>TFrlj@CTyy8_q2)$TTW{DqLT=03 zz5RoW~gM~}uT9f?&Mu?y_TQ@X75~p4e!o=6Zx; znl43&esoO=7nw0>ig$I1#|ip(>mxC-$sDe+pMl`bYiZB82L%2XCH2t z^`vzLJBU{_YmN2qt@5rQZ62qXMthlCCRHZWX~j$G^NBOzoB5%!#Z?ssqX{+J>wR*0 z+WcBYPYaxP=!dr94mW0}an?)7`X0Wef8i@~FNRZi?e~NSm`+PRkZoD@-K~q?G#n4w zk>Lo6yW5|1@s-EdYWGI&tj^Ni-6vj42A^_7a(N9z5KV^?)W(v*^{zyy0}CV@s9Z5& zp)U&tiuhC^zy%TbGt-&d1+LMb>|(Hk`EWecvug`jjf@OF9cA{se((OZR4dOs=?%3+ z1^#qdajJlr-BDasSX$RvT+od;z+6_}?6}46vc^@iTnbka+S%E@_quZrW%$fz=jTP~ z3T&MFjpqofST;?D-<`KYLE-n3$NbL(Fv>{k4j(C*@^Ya^2NaR#G-XtN-pM<#^i9-I zEf|#G?tK=rp**guHC66F5tN;07W&@)?bD6?q!|&BEW1gcx@dJF#EoA7pxVgrot`oY&hXlm@ zgTxIb24n`rrDT|^Sb*6R^g3pfm>Fkt96qDLmFkQZk3EDDDurj;@n?MEAWj)RaPO|`?#do+F|*FoFir~%JUeS z*ZDeneIhC}9{we+(6?Z2ujrBFMEa41)#TuIoXE)g+c@jpJ;Ii|Ct>xAu3(Q@;bOXX zq{fRB3zsCGCo^8D8PiWrW4flEq^~WanV*E*dAt&_EHX(Nl!MB)JZk0$%D1}9ND~Vu zUznaz=ML3g0cm=dHP9BHl4g57ljUJTDJpuo8W-Q(<|cDU!?L&F7vna!usg}%h3&Aw zBgHBB&3128Idd^SVP!nl`wnEcd?D{Lyf<&eCE9n}FCB5dHT>>9HS0Tq>Ds;H<-5sy z@Z;?b_P2d4Cqr7__#uu7uHQ3}LjJ`a+GB z#VaG8s`PivInlMSH=W}-G+=V0vAI-Rodi7YsVh0X9rxRV$|mfEy~Y-nS79fb4RZ=1 z{ORO*i`S30ADpPYXWXT}qv+UApuJhCl>^DE!n!@NKUbHP8tOPqX@20F>^@+IlqL8F;$Dl!#%m;?zpzN za6iPYT-FV*h|>?IR1)8br-+lL-_eR8fWdby8(UVSF^Q=-OsTY*0Is~B*I|?d)gU%&zd3w z{F_9t4IFxygn#N~x_gvI+3`Mdx*w{RgWH72^wGBCF5EnHEN;ZVmk*n|zr3E|*uN<4 z#D+b5RQ}~3n;NjMc|Rs0CQh*++nSY_6gPluLYdxgI>@#biud{uA)OL8X`YXiMG%_F zIIc{O2fCMBSzEXkc*dbCig9?5oTfv&mTb9Q>bXYr3#+-SCZ6EwteP8=9;TvZ&1y1S zRe|;U*UKXNfX(};#aU9(QGl-OV=xaf4yiJ z%zjrB5`|qTwgI~0h(InXCiKUH$*BTGWO}ItBy89fH91aGGDQ^$V8MGq$ldG+&$Cj+ zEy7{SpM#<&Y#xt?s?X0S4i}zz?3ebCju(MtX=!g$n-#lRwYT>^&hYn6 z`68lM#e`PK1D9vs`u0T0GBWL5%`ZczbHP+*W-C>mfPk1DkVF@Rp!0&RM1qiK zarnkRoC*TY9g3WcTI3}Du~<*Jd}fc3oe!q7X z`B=6SY||k+Jt@@jp4-TWT{3xsp_(PQZ+2m^nzk87WoO>oO2-zBS`=NVG$>I;HLr^1 zlxz!&`bXY%C|`nfHz==Z}-_iFqmR8KEGjYf8i7fl-)Y{q2Zhn*oXy8y8cKh=6RW&Q~9Yf&3P6d z9G#+P9&tI?$s5m~H_QXJs4c%mQl?)>w|}UhsK}lVst1jy?3{EDv^50!L{#)U7R2z>c+VA;rd}$*H6{4fII90p| z?ysZVGhQjvSJ{_RJn!9Le9MZxn+48|-Gvg*M^*r(}+yov~Mf}{YJ%ORD9YX%oPbseY zndI4sg6Zubl>lyk zbq`m9C1=lmtm}=%OAnnrg5$#cOq~qgzGF6x<|fzFzNCyczL;O;f&+?qCIn*Fc5*hl zP8b>*Y7xKGJ z>v#2G4qEm*k44CS4&rSU^Dw2MhbL`Qu<%|_TxppdE+u1kOHr}1qWJoSx3s@EoHui7 z$uW6t_xY70dypBvLNoF3_JZ`)6A{qwd@~jOg}BU6OHHm_NOQ4P_SU+jl~y=XRZT8V2W7g^hE&6>;nh_-a%> zR(H7xPvRp}a)HK;C5BlnyU_bk&Y=chhrGMRiI|$htC-}87vSR<6ze^lAw`XoX)i?P z+z%}W)6Sbk+|~k|cP~TZ1CGoW&OOV)wFN6*y$%MADpEL6amnlZvgq4adv?2320umC z)yHHk!z@H=YjD5|od(E*+Rs38t^IeRJw^97Igij3-kEA4eS`U_b%Po^oAoMbV z=Ve1$VraU)BP@^Fg61@)U{Y76N$_?D1&dhjTm(+?CiPZxF@62=qO*0!ZCQ3dQz+B= zENI@6F6nwIW~FBg)I26~RJUnQ(2*f~KR1CXWiP|E()?VkW^WHvEN$Xh#PTGwMW6if zSVw(&^`tG!Ne>LEac^q4@-3=1hTG zO4CJL`Wj6vn5VdPB9*7|kw153E=RKTKXF_DA;|k~l&1DZjbQ3=WKnsQR1zy^MClo_ z13tRP;V@=zr?wf2S9R*7G|FpLkf2p&@|#JXu;_s<$79Fp?YLNoFpERF>^4iBg?&$~ zb`rZ48~&2f0QgBD0)<9!Wp(vRMmS%q{{Yb^7>k21RonTG_X42~&v_lab-%t+4<97m zAyk|-FRnF*>is+_)x)fye%_{gtDdOgzCA`89dJx{weo}g4X?83g#PhOTTBM-0w{YT z!;U-QGhA@fj8ii>%;ueSvx#9|fHmBxK&)x$W2hV-;AGVzMR`sUd@}puWgseHg6p_W zoNprbr<+udoi~8?4D4QN6f?*g8*fJ*ndX^&R9>HPC3|z4-p2pJM1DlJ+gqO={f~FxF%Y#He*38OG#5nt^W#FQ4 z?At9j`|{@v{C*-cO~`mEb+3>fc^%%En`^wm1fD31K{;S^``&6U{o3bs>o7$>IW_si z7sSBfbAc%?;@P6x&wq;IeDzhtd9hwa{~OG-$o7&Zr+Ha%wQs|H$oMu=;@En$hN)&n z{aRyqe(bB-E7N@5+s2<`LpjjXx+LhCuI;*OK1e~sEq}u^Bo`EnR~s}uUNB={^oHrk zZ^^HVsB18sZ83CGWm&{(wSlYQU`zxXA>=nz%NO3GTO=vm>iiQIW6Z^Cnix z^^}S)-S%(-5u*roW(=P1TxV;Eycs)w{(an|fUDqC9Z&<$sQOiE* zge`8Mt8RW)7WPQ~#NBXb0=5N^h7E_5dU3_N^j;A zf&~iN2-yZDpD-6WS;jA6i6XN73<%{rB6ECC&Maf_YC~?yY*J*0$6d8c*;>lp!RbSl+d%K&(M+pG zl^7i*B~tBaE+)Z{fxeMZR+^N(x=VWuAS!G)Munz_xeE$y)A221kjXvmxMU)f0EBQJ z`ye!mE8$LBW8MkZ8-u#r>&NAjvlQ_mQLg_GvOkg|ARMZ7Vm=p_`v_uu{$X{_afKbP(i<~X*S%&HF^5`!RF$2{FbLtkTZ>H znwkC%lm50C>pQ7iv+F4Miz}_mqL)XNc%xWx{?;RWOSrIhnyhwWJy&AMmcGM+Ob;qy zCP`bMd-vG40igA&Z3?Hu8v`j#irh@iLj89d=ZEAh_KugFc#>Y_1W{tth_WO3_rgCl zs|dMGnET@U(xoDcm^U0xv+4p8T9vl<)eRmxOvC10s-)M?vl8TUr% z(RhT|rgKC6WKsC-E_cQ-Dr>slob~g$f&C z+?`~U8Q*LXP$mhXi)h^3l`Xm8HoYj>{`(o5qv=T%+Q@IqENX^pQ|iX!ucXO4oO65n z3K8$oR0uj@tY)FRjYdO>p#{>X6D=3VKJyFmq zi_Mlz3M+l3KaQ8@+Q%}zZEE+Hl$TVO(8QJ$MrKT(olRvWsgT6@9Vn7!SQJ-E-Kn@3 zztwdyo@5yLLz*wG_#tnnSVG$5*MgMy`klI0CtIRqtby_qDR=T?+c`5Uo3W9}fi0xj zIXUFtZcW2(x7<5;a4JjMwua48YWKMWunk&Re*&Ljr%3@P6>jb8Hlo9+6rwf@em8uX z-pejmJ`tm#SRg6;F2IFyP*O&_2y%SisV}QyjCJREUfj@C*92%?7Vr<# z)${HsZut(vwTi2`-7YCy`x+c>UtOJ*w{nUskT&xj+9T25aHBBuu<@OgVKJ!`@EsvsP0W>fnbkuUX8ctS}UY;%jt5 z&YldnN6Jn6+Q)S=M~&p%qR$m(7@k7Jn6$7+^z$;_vF+vyCT%&qwJTgWe($KU4$her zF_k0?yB`zwJ=Hx7yLF!2btO7?87ze!FWN)gPT#etpTRyY5$0)6d2GQ@P_>Kv z*bnL{7SL=PcUv`N@8_>!To#~jL@OWl#WixwoR^DV{q!HYL3UGo`Jo&FA#iYBjq_rI z_Zkz0w?1Du?V|0nWzx#{j50|&`QVR_Kf2reMHa<6S6F*)aGn9o+48bJ*n!SZ#^raCS!zmReGx ztE2XJxooHtnT^qakjz`@h)v6H-@bV|0M)@fNAm468k{OCa)^wjb8~Viy>mm}yPcUU zDk{d4Mb(S*r46B9eqF~hG3&Xw-B9Y?oQp&wONvWB`bYo^f*7QOen)715J6NX|GCCN0 zw)#5ao4n0(9Q~QDy6?8CLAr@wnNG+bkwE!?MTN zd?v_7e%@KP$<(ZbahF`cW=g9?IWKa@=C)dkP>WY|Ot)1fNPA;^6%pjsMUjgd)}Dp0 z`(DhmGqfDB&I~Wx9y?UB>a``^w?A39Av{TbqM~I}r6bJ1T`n&_CiIhHh&54}_ma|) zut?0U-j=>pqJErr1fKYYG^kdXiT$1+Cr@tX8}kRXZF3D z!Ak06t<968Hg?@D6sru00jViVty_|!rc2BW1*5y3cpgQOuP9NPVrb5t2|juq33{0x z18RmV)@S19mc(97yIefionk@7CWgV zAD!QsJb{m!RVYCGd6SfvW)|v6bx8u4ZJe@Zq4L+>kkGoV@$SssBP%zRyo}Ry zGV`WOqb5A*ZC%VNvBB{ zlWDB+J^3HP%5VC`LxzXk_xSZ(R)`93fMNYE@9W-wd9ZN}W_P##4@*J_k_-55cL_gn{Qyt!AARlYKsMO0tvr;n}*yJ_lH zYR@bx$3K5afTd2yh2?nOQuUmwfa}5td4u3^)0IRnr#(%e&{=2A7JZoYQ5+C7ae2If z$U)o3>Ir1;ey0Nq{Q$CRpA+(MM2pK;A>$>SS6R$_R9d^nTn8HQbh^bkUfJa)9UaXZ znERL}2KLWrQZ#g!41)pMer|kla?*7EKFGb_n5krz)V+87DuD&p^)`n?-N*0bI*}e9 z)qW71UcT>y_5Aq5H<0!1UWlFG@47Z20`p)Ke)hdFoie3Z5wF=j&ZO2|^M@(v z)*B7TXYEbi=aSrjk%FSrcM z7*62o2u@_(FKUI`C9wpM!jvX;zI0UIs&OJ0wka*tU?jlnDKc-f{?Dh^kTF)@8~1X$;s{O z*d)ENdaYgW!oIlWB=``Y;ZjTX{TIwyA?p!NsLdn_(Nf!5`0|TW91~Z)t$Tq>t|yt> z`xn?p&&B$^$(w`VbJTCZlBC%5!g78=>3fVnvep+Pb>_b)#ko&fle?cx^0#C>^pLV{ z3&nB67gW;E0dAy0dHH~wB;UHX!hF=d|6^W<-XR2MkNr+CG`f3IWbpe|&HaR#_36-T z{!OWyWsAPHzU0ApadJ=>k=LLGRuP6JMC00+tVO*FwtB+BT8R{VZ_N;O{VZ+O()GfX`h!?Zl;$vnte$$*zr@9S z_x2ZvuV3(sj+I-GzKH~EgMr_*8Y@9G<JM~x;eRdD*zxYg?GbZ;~Aa1bAuy)Z_$DZwzV0fL=GRv%|Oyn6ZawMWN8 zA^QZ#^9pHD*tCPlB)JNRug8J!sUNG>CW}mkMx)nDaVsWK9hqfa zGSK9UTE(eNvVGoV;+!Z);nA*0V}ly6lJ8{=3<(5JMdGX@3Tbz*BvYEccT=3Gk)#Z} zf2oA=itEMf%Flda9ouQSs@CaR7Ycc5yarte>v$LjkjQR*4) zaj&X{6}z8x1Rq|M>7?;=onwS@MA6kdDtN@6kV^zt`QGlZBek&VZr8TxaZCrCHk^jwc;YS7h+?TzI2@P z2XT8|5r9+oum&M+Ay<2>3e&e{v+k!N@jzu8s4E$f(@mW90)tn8T(Y>75d{Z(MoI=5 zLKjWBW%e3Xw#O5|n}CVM!=`$T3UR02bGeYvw6;CiZ^gw1k>Y^AZ8PvMSmBSL4&A_f(**S+g=*SRtb;x`uW&0c z3!83%a1*`g0MDZ#o}&j%R~_Y{Zb!CWt3dRIKVph%P&sxT!RN}*iP;oH3|C0Ki{WY_ zk;d+Br8z{-pbPi1&AP8#b~%qB1v^t8yQ%8pDbHOys^_F*dC8?Z%_-op=d~&PX!d^S zw#cS$pQytkn1LzDEPAMRC;MU-eFzmkg){8)>Yo-##sj4I=8&!Fnei<)GfN5@2glPo zs~oln}=GKXc^RtO?NVCa-EJTv;_)}5$-#@MCZel`ALG$z<0QwK0rn!)2dcP+8hXE zNoKs&Q0|LOe$gn64@3Z1IwCNe0e1fmpmg|vlINOShA6H^(Unr?7O~tmMZAmc?l7i| zh$wib-RC2?zPzk#cw&7+%fvh%27{S0zRc!ml*!`|47P(ngzQU7Gjf61ja|JW8Y<^K z3_*&c&U*g0O zQz%$2J&~P*?0!}n$qO}}mxqp@#}t&Hi9_JmAv||6Sxv=LCg_udvu`NqwBRj%>J^R- zq|KQxIk)bxE2?+e#&w$HEgBGSE~>+q+e>{BqU&Jl!}D*M#YK!9*_cMn`93~A2{Qf$ ztE)8iCJ8D$IyeLts5#uQpy(6L=k$l1M5dlZ zcPrHwmu(EBUaL5V2Oc`-B3n>|mLtju7psCb-E}dAg|s3S)X;%W2lYMDp324wdkiN1 z8q1F3Hw3&osR~-gnzj%hS4h^Hur(ymkL>!-h{@-|2>T7kVefaHugwBR4f|qo>xQ`Z zc}Qj3`BOMom?tS4XU23guA&%9kCr5CC9YKA1zu^eg0hw{!w_8yd4?XanVMGd%!v(I zt(r0ruyRtXaWf-0&S?T=icIQandGLv=9gc~ks3ulZJ&!weocz6T8=tzTM%Y4@xc&J z!A3rc?tE3YDl&;t?@Pw!2W2hCu203n(1^k=gBh+sX)=cwX=3=C%dA9zA!sC<_HcJSD2|*Y8`cpTD#W1SJL!V(}7QekGs9 za&I@G)E=~Uo!jI&*#TE~YNQ-T%tao)(E%)VnT{Xl{k%6ckRc1^Qzb$Fu*2vIV2aBP z@^$$3eFO?-DU32l%D%hFz7I&VodEo~3YiRwn!eF^Vxl!HE!SU0?O`fUzyBT=h zTx*R{R;Y^VSzQ~*PqizeZR#_)9{08OC$Bv)TuKEUa_Ub+Fnb&dHgUA%BjL3>bl2MP zJXdqyA2dci_HsR!$7gSvb%Ud+6t&HHxpp{PV5>xvw%J+D(_rLbba3s5R^ppJi>NZp z*&Zi8#Tj}zWM+Tj9uuBdHz<5@h9&!aOypO1CF296&3#|4@QrA|Zrr6%9ZFwp6=oV` zD~+bkc12nUN5*sg6e7Ms5aE7*33@Y9ar<=uWwN-%c2RL~lx`<&6E$n5Xh2q(q@aVF z05A$qmFW2b3P<*uv=V~}rw!BNYF*!vR3|)@6U4(S`GA1w1!@Km3*_jlH3JzZ`(dI#;Q4Tt z0m{ZuP-$p%`||`UQ(?}xHsCLv)Qz}oCU9D%?jpYY2LvtyNJ0l2M-1)K+)u@3#&J|Jj?cU=vkCSAZCQ(`* zv~Rt&5gYV-0dCSuo1EEcHP`z&3Z(OO7xJ$zE$~5HMlT$#+_93*B^gm9)Gh|u`Sm$y zk2LE84|M*bpZQz>A#KbKgtEIjSEF&y9Ri05+CjCLmX7@+eBA3?bF7LD;4l7S6!*YI$m@r+>t%8`%(@i4T}W&_lS_RV$Fn3YB-c>?UZ&A1`i~$X4N^};y=J{E>*#*Va*rwphJmjMK3QFa*N;`WJ z{4Sn@W3zT?YsSaRYwgRItd!)IAP0_^;GTGc{n-WlrB7M`rDsmAO@?4y z{cmP=T%yvp%Q@tjGppfL-yd8)W{P+dNItF+X3gYSMlr2kU5&qFuwx**igkclJPQq<^ZO?^a&!!)7)Z_si}qfF&-`({8h&>9;Y|fZ?BSHoPjY zv6Cir8~5#Pn;$Vle)F8=1oQrai}n^$zmk{qt*?OgrSR-sTyuI_5jJb(srXQjpqUWO zkyM`?U(NTyu-g?DJM4c7ZUP9rQUW*5B%u$oJ-+N*b^F(ASk(Wlg7vZu&e^@hhcsbMifU~&kYR? zO=FnvGBM?8gfMiwcn1JZLMRQ&Ho>!yEldeC!u7CJm`6Pe#K&*!tc&eD6Pm)8H*NAaU zX*E`^+zd_mA*oR!xI?-Ac(O1^_v7*&7(cj3*Hu*(0r?#Y2&pRo#CdQ*UWZTT^U zJ{(CUD=U*GD0JDKEX;&A=Hx7FRbRG&;jlF2gKi;5d*~b1XJw&wC1l$l(kamtDL4jx zl$2mVvt|8PkJv3>EL<%n9Mlv0DIix0I4<`LWfZyrl zZ-0s3KJItw_+idhh4wm6#-QzVl1aHSkO$4!j-(3|Zz=i}C6p~PYEPIAEM4PRIw6}? z&#etgPy29EsXQRE;W2P0Jd+Q^nkTOW9uI&y?W}>iK=@qtNI<)q@4HVSc80W=$L|Yzn&Yz}u>ZuC@QcF8&6FUtiP7QoXW=U7}4R zen~E#7DkN?d`TwH`^%P|cNKF# zI$pJ#_$v|p`#6v|)gz>pb7relWInfGPk&$~tu2q)Bn+5|rj<{uNCu7>E!)@8l?kG7 zxlg5xYS*TKFs01x)<+MlP@|z(S$O{CCeQTlF4Z*)I^=w;#={W*x3%loODw)nXP^(cM|x?2Kjf|r|0F9I%T>) z2>yMl|2#8ng|vCy&9$F|g<{lL6z(LS+6;I+y5@^C<04?n6(>JU#(C`dtc~`}vjAZaa{7it9{7(q*bf;{v>T}{ z*M1}>3A_P+d@Uv_J?MDkZKuOL`a!$HGvHS%dG6lS!Esm{4?4O`qJCv7{V9b1b0BaJ zEc*Gd%RVmD2K0u>9l9ATrr#7lrnnL}0}TXD(qRJ|*VT3m@hP zl#Z=WAU$D}YXyL$X0=ThCxDeCsv#2`(mWn<`Ml)=&2!mwU+kZqmIlDYz0GQ!$pU~2 zoWPxwyPj@m-1sys8c6GE;yZR0^~J&lU~tWq;yhCf(C7RWVhEp0*uaU5_{4kCHq`j? zp};?Q-hYIQfGWZjU&COVqd4C~sMbMhr%8gah!@sv;3$E;{B4?Es>oO9hBSk?2fhVi zDB%{C34eaWDTn&?bok%7%_owd-PZ4y^o{>z_xy)>`7dXDR>^cv2TBS3%hgv&cS*T2 zw)Bmq8cwFRK(IPzX;^O9M_WgW39e(Cnlj69a`y9xvboZt$y%_k7Ft~Ju^uIEy`z~{ z;%G$n9Xape6jrkW=U**x0z{-3`vKM-=2tA$3|QZ-nArj&mdsQC&;@?c{@*!6sw`&B zg&B@c_Vf9yyTmb_?5n75^Q+=MMKq=C8M5kaeM|PZm>MTqyGFnv4+L)DOIhyW<(XSV z=}UYvE_sQ+8mRowLZ}k`0{J!D*^{-DRDKQ_{4J*YKNXpuG6KO+#WkYv8f3Gw$geVZzZ-*%P z!YmxO+vk^Pl#SGIQ`~$$_7UIz@5}S|m;N0X#63uW3_|?w-II=v4pI8`9-GV_7=`N3 zT%ew1Ib8hdXj$VHBL&;Z`h}5Wqk1eId%_Db0fw{BVgZ$26)R;#f2WNCahKfrvsY$ElzO+NbnZT5d%(4RuY>O_RQ>@O|6 z>aj3nwH&Xm4G0L9zNAzM)5fbhbi(*A%%=taF9iF~<@%GNb;&XEi$Mjq167;0B=)9r z9$eX^;BshO0ScwsuB~W{{C~LS&x`-#;5*Ob$Z;GBwOz?%=4{$DQt&Y}BIn6FSF9g1 zmphaa|NALop!x`3-47RcFW~}r6Z%N_p1z>lSuXK^4@6=vgcGG8Zw=SSWiNMe5nw_r zV}fYo6U@rCFaIl^{uO6`jW<&s3tq0r&(vLSoLsLLyv8iD0<#~Zl@#!`XU#tSk{|5@jc%O}o)K>Cpcct@>=(qPx zWKIZ))m$VK()V8+WwQP6Up4&krt!;-a!Iiojz_0C+kxLCWry3r+@|k-0pss%@P9b} zy5{kV-6$xQr^utDoe@k+fn-O}|Hm?VKfXeL$klq9V%L-KKN8}9+zx&}`O};1J0G#} zTz%BU5~{;|{e-ps{~9L5KF$~=miaIO^dDnOArAvB`=5g~UH)06+Jut*tGf(y%ZHgjV|Ji=8||u>UHR9Mz3v(_=^f8Tr3GE(CniW)UQM%w^y? zkH;^zGVL^PROSD=@%$Sw$p{|qJ_d?%8VP4a1hC-Z;z}4(ppyK)>^^s*sf~>UFCvug z$Vl=VDB_}{PpVCRxknD)31nAa9EH@g)m3y6mAzyBCYdj1n z{8TXScH27D@JBBgBvNQdD;}Ie4e#i22iv59K zfx^0P85i9hXpi?5{6ml?vq37}rMFidv7wf;6I$P%$1n&oTS`))Jop~+YGJ>q<#Ek$ z*h|eArssv!#(%upf5vN?htqyCkvB*wk*(JO%6vS(!djDwiT7KMv^7;!jLjpcN7NF2 zhxt>Mhn}3A{DS)0W!}}dqjkW%MYm9$F&4ygyH`4u4cY(=KHG|`-I%~1f=7irY zx129w&Qkw0X#-;+A}910F8;}u{v4z>W9YKf+}VV`00XyG>JNymutv{%?W*^Ns&}!runOHjg)v;y9|t@E`dku%Q`5 zjrft+ccikGYIU%cj)2>dLF=vm6+ixb_kS6D=lG45@HI@se7sr95_2Ny#5Ud?p5=T> za?w!a^{B7iWLy823;rYI|LtTcmUy_<6V~qn?#P+>l%{rHI2!0SEn8@)Tn-5sL9lkV zdNMl+vG-i&bE`Y9C1L*!95={7&G9sVd>|0W9V!or4+o~Wl$4OD=u>$GT%orh@m#-u zy&OnaKA4e4f3yK)iuQk;30|i(=BQ^8sa&I20^TcX$|%l&o{8dL!Xf_7>;n9}Ia(^K zsz#CN-#G8A#Cvn7^>Rg>cK#cHJt6=`ceSjxy}?F=M^=_7%`I~~AY?X*iILP^rAsvi z{&K4KZ~DZaj0_kcJq&!@C5*r;;=Ns%EpCVZuQTy+#!4mCYzRCHX^Kw9&Ds!?P#A%( z``Oq_iDs8sv-N-tEdMJ-U{F1@^nXM3zPC%zdz%j1bw}zi!p3ko(uu|b*wa1?AxluK z<^fs3rVIjfQBXU+P&PZ?Le#FU`(zcr9lMlDF_N=q_7{Kr8(#j`ugkLDVb+JnlA-T0 zkZ{yw6tnZYP3>BRLxWqs2Gj@9eNw1dHLzT=FZn&s{J-An@3I5&cL4GT2_;!^NZp^n z;n-ps6j2HZ3K|BM?k${LjW7QzfBFlQefT~s0zo3GP42aa6o$WJh0i?c_jxxVJA)So z6pSJk4C;&4eb59+HVqLyGm(AE9$K~lI#6W4%z6#78mOI0=r2J1H%j;y;`zS%Sh-OB zn^wIeuCk-O{bE7+prmcE3E^+d>O=>i#O>yds{g~-J4Q#=cYofUbZi?PTOB*;*tTuk z>ewAyosOMUY&+?oV%s*RuIv8aYdz1*TC=9!=bY5mPo8{5Ll@ii(PX^YcNi zoa!K2G6<>EK_xk+oc8N)JD6Sv6ouA5zc6TIB2f*EG+@1O2o$c(h)yr~Kld3B0zE{Q z9uwdbYC=5NZL*3MxmA!etxnG0_Bcml5pt=6r}UGpH8)1I^W^`h{3obOC?9`aZ(Z>d zAGCNB8Ykkn)u^VfZv6goUs_!)E)#v}q3je~QCj+sx*@ag)0F^o(vs}i+1bEGr%#>B zp*&2|!GU>AUy(%o&a4D6yJrkOClVQm5~8i0+3fcX8;OwTC$_#P7-QNvatIe95ol^J zo!6tzw1UI!V}w6t)P z0){6bvN_5Y1XWTRj5o3G6&T?*)P(ewsMNQ*f1-kB*Zf6-5cz7Mb&A%>?zQZG#DhPR zT|BKxG-4uU#wh@Ur%!CG>T)D)_icQ7SoB^CfNo`3r5m})sI%!YQBwSmjV3UIPinsI z2-a>hC-b(zd#OzIa1SHOELj#{dKk}*eHym&{RSomnF#vuggG7F%#7@8WXhhBTqKzuh@`|NqSWKR<>UI*7K}m8FQ6gNKCfN;f(QZVjD^YmL0jxV}Q)J#&PK za}J+e<_mhvx2W z*1YE!REnuJj+wEls@{-^bTR}a2u9GNt+=YN7V#pCm-mNAIMU$T^X+|s!PL3OyW>?L z#DD5fXk_o`p1P~hsn~%qllBxc-G9$YBFVH`!T5{UTiV3H!X^*2%9wMCg(fRU*P91l zuuW!-Sy5@YZkEL@1Dnki!N6zIt9?4`1CJ(0;2Ru+V=)%oeEn z6rcz{IQMj3hMV`gN;4%|^@($|x%b3cPz3oYAw z>;-dllwVjft)~!w_ytVt1tmzd3+n|1DpUG@_c5K)`R#-f*7!4c%R`Dn8qjfzgu*uV z0#N&`J)#b|{TljS6u;54ZKHWW@9GGA&gw?SPP!EcEM|Kl21 zotv#{0+eJ)TpSVzn!x)6!m;&FwEzH%i>Mb18U}-LguIS_rKpU?l4*?Y6$2rl@Ia*o zVk2wr&s)Nh!oFnj7KZZNA%cC?)Hq|;yQ_!N;}b7TT;5D_mlW>HyEbXDqT=wEy_mid zfp!#l%J{+BdT`V7_fs=upXJAmg|)!)&eiJ={2Ie&@%;f*@*Jn@=X7q;;knGn*1YyF zdES?l9p(Ha!FTWmIkBu=&O}28uBEqmad)Zfnh$sQrLdbUb!c|y2^KhU_qNV3;?MnT2Bz%rbu}<$Osa*B3(NW>qgxPeySFUWwH*i^64f!77zkq;^ zXtN3=Z|&2o`JC?IC+L76CzegBqX9s(e(%Krf@wbCd8{8L_l{k+9MMw}l5gHxWxKa1u{r#H7vA0-mg#o|0(MP# zTkjqleeIVHJr5%Hput4%+aFT1C^1=l_*B`B^yYGSe|GR5=9wRx&anm{YYWjHe(^M9hcZJ+#BV&HGsQjG2 zrUNH0lV|Ngg4ro-oQ8TRz3eu&dzyGT)PlH$xW+mFi7A~lhG9h*5;Us}m0{AhJA&9?wcNjcH+L4S9=jfd|0qQcm(110GZNdli_D|Q;yM<#} zw4{zzag~1P`+Tq@%L))`82FG3K|b|289gGMiZx)y0yY}#N~_8x!hNk(J~2{|;dbX2 z!`P<HIj04zjgsL(dE;(7#dLMf+QE+DoyGF9KjQF!zF82dL_(d zzN1?Xos?V*iqHX|@X9vYPqb<44)R}o&b{s_Y`%9rv3-V1Z}$kyYB%g;vsD-&hP5Z}Q81;m0b&)f$X^FA9v60Of zWe1`p$$jQGYc^$HHbhT&YYU8bo=_twHjT%h+xJ4#@Snm^nGF3hotn;P#=?v|<-LP= zGagN2{=u8hjYHGmN#EuC&VX~j*Xe27#Lc72FR(Hf*g6PF$uP;K>%cQV_{*#1M90F5 zw5;{&aK7e4xxZ!)aedbK(*_?;^3$n>6q>%94$O0vW50#5Zzqt3 zmvP^EN_ugg!8$JaBUza}d~wqK{k%{zg&`{d?bTC=?Fl*aRo zY^{kG?my8Di2g}?MiDL#M|WrHB`v7 zoud-_ftit7#?d>C6gu8eGN1s9xHx}#((JHF)XW{p$kR87XpyJfXf}@3uOIp4v31%H z$;->jsV;BI(WzIG;yvQa`oZh$=vlN1ZdEV|vJ$?|(60m9N2=vEsw+BodhL+MlseN1 z&0iB*2Op76Iy6{vP8Ym)Y@jqi%eq0!Mp@zf>=k0wU84}7ZYQCmSq+fSjByf~K(go7 zd`fY-zBvi6ot}T66cmW4cgT)^E`pz3){b8I^u}{oc|tvi!!eB#C;{lR9~&nAQ!;wz z2;EYyIZfuk#1tikj8f(P-2Edzl>f`tl}**?^tHxhFjG2d6#Dv#kjZ%J{je8AM0=^E z(9FI@?&!Gw_8op+eg4pwsL1Z2@U*gqwe!?;wroxR;^{o|p}-Z-VB-_)GW|fPDe$8jR2L)qrnTRF;}asKWblrPYj3-_I_@pmDB> zX(K#fsss5@?t8b-poe&3b+_a`nHR%=hxxqt|KtLl68R15ew)gG%P8{m<$!^67;Gu3 zXj|*B&(wrv+^^?{;jTC^cd?T(XZkNln?ZyX`hBT9O;Gg`yLSrHSA4#<+(u43m9I~7 zm72|hrGSGI>5k4qG~N=XzR|gG@jYE!RT_NIG5yLDYKFgOaK99z8KI;75oFggg7MqJ zyr_{LUhe+h(o$uc;$0aV4{ttBZjE#yUYZoSyrKfVtZVwn-oYVWhK-AV+qR zA<5oiBLJ2_z;`Kq4ODdP9zc{>&Em=@8Onplzznm`j6)d5R#F}u7Qw45pljfx<5%>^ zNDuvDF_HWJsG$7jfHYXn3i#N)E}{sMcU;Ia7|bJj$97-hu2IVlr0aeblcmLC0>|F) zKC=>};%eqs^SnrWz1GFql@3eGB-rkQX~_8ZxhD%T4(UGP-Z^_CCaVR zeb&lawvOca9=9B>cGO!vQ@8%+`E5+YPTBc0n&zoqEQK^Y_AV2_kn4L6|HloMZuam1L+}=4x6{v57cW*n}T_fL>{A zChyVlTe)WT9@_;aO!B4Z**GZ2FVU(*C+ombpDI|W=>JKgXAWWaQsR3f8aXhHh6xx; z2*V%GM3RPy3pxt>E_tmrG0%3T4Fap~=(ZEI3s^U2;x$9Ap zTWRLqCo@}yePnnpp$;gf8h_iewyuLUObmYeWxQvRUevRUNIK;_C|M>LTm*`+j7^X( zG8$M#eal8NLVBP9feCFr#wN42DF1~tl@3C1GaZ>(ZqR^US4=2CLO8#yZ1gCl1`w|x zTF9zPTB>YeK+ZhV75OmeGGAk-k5ZENFj!`5B0c?6JwE(4H(NF1bu-D*XCBg^^UE%M zo=Efiq43**0dH`1@4;B}b(Vo`pICH_(DI*>t0kUxeuWVCM~4Uo=KO9(qJQc)Ap%$e z&1Z|sTHA2%#T{O!jR|342`M^)@LPXZY;pc3jBs;5O!)A@E22RK8)0sV4aMk3{e@S1 zjjbh`-f5$~w&f6r7iutllb54N7jt))eU77w+`Cf6S;_aDtqJesxg{-)-7Xrss~I}n zmYu$ggQ0!#dRiTA#Yxh$TwJ?P^S`JZI9}T1yUD zBycj2TQquQb<$yI(Wk=Xar`jKd4=%Xa-ux2lbIGM}oHb#*YruN0rl>q;x1$q8Eo zg;`o6%&Q7>No)IQh`3P|(;LKWZLGzA{qm^&d}6%HT&kwVM@Cs$ zTwFa5h4ZGiPFJR|^nfO(!pKM8IBm<xYtfnJ#go!T9k)2MVx{ZL%;ddr_2mrqnX{9q zn0HgG-ex$_F4(|!&hBOsZTlciNgL(yVt6urtLd-Pg?|?se)3*y^WN9~4Q(O+Z;+Z9 zhE4C%bayLjSB`M3ki|YhA`&{EyJ|7xE|I~;zX{-}>vc04i(;B%wH z;LTh(w7$=&ubX_*&q_>*7dG3c9&7S-tfRP?%gfA-J(D#HJmU4lahpVQr=NU^(-vqX zA9(|R^=Mi&`3$nY_p3(7ZKc3rsh_BEu<=7Iw~5C&msHu*h=w+CEL&TJ&(*D(JW@e0!a6kFX9ll`I!I zjpfvm1?OuPto80Q%(8RGS7&QGHwS*=X>Rf#7JTQ? zs=!=+pBNV+8;su9%WlEF8IZ2SKVzl`Q#ts`)l3{??`4O10YuQqnZ!1+_LQz+(Q)`b z_r%}@T{ZW4TF#VGQd#nI!jks2ir^veiv#eO><57cQ zhC^bLWWQ$FJ!WVN|4a33t47a{O7`SmT1O7i*Mpp9h)n^T%=1?~+hKbZ9WsHq@YE`}`4WsnSpj%K9cTTk z`-2j6<{FzCJ&sV%%J2ibamUGXChw-au00}ME{3HYtD*YSn%?N#xir>G<+qEI(4g#0 z!QT3C|9I?>To4wA_mouE^Wq0W6ws!&0gf)$6GEX3s6%dbbS&ez8alV8*Owih+ctEU zW+Opfr4$(NBv z`tV_8{@-7C2zHwkStEu|wOsFqnk1)#xc_aQ_w-OEBu4$o)YH75qSPc7-l(rbX~1F_ z7y(ZzNjv?v;pvvc>#VQ>umxq1(#Znt7levQd0BX07sc1#U>SA7ecac6;) z6^1M3rrEF`ShKD(HZ%YU&r&wQ*JjQ3NX(BsoJKfwY9ny{pd5cfYH?J;qPqThZoLuj zv8f-9x4PMRoBRPO9kAuM9+w$kyOSd=a#+iqH?+2mg`dp3^1*OvydKw6b-+>XK;Hj{ zFuc`d;nB>-nm-14Lo3A3J3y!VK~{A_JMdUU=jtS2v1i&82v+I6JUp^NDQKod+=w$3 zA$$Rwo*Mc21=KeAKuJ-x9h1wJ@rRPW??P5z!X9$1BwWu&!F0#XNxN>0WYQO|WRljcScd|Y$E z;dQ5%=h}u4xo86F_kX;g%(W@ z@N@bNF2c&gn`6ZfrFD70Gx7{&$gjtPj8v!)*46mk=JEy6dB>|H)ZO|f2`RwPf1zfx zjKG4wtf6Vy@yCrv@LW}DhZz;pc+MKc@2R4^t-;rt;S|9x!to#6y`xKR_>PQSm*0c^wr%rL;3QKVPjP_+Yf_46SoxB91>_%mL>sDHC`+ls-}#t$D)~ca2*>U zQ~$nD$o-187@Z+P!S&1AvwKRCMb+jkudp~yRa&%&zox;CP3<&!_XI|7yJ&+%mL!4123Cw$~D zcyry=gzm1dihALnDz`Q3kIe32t(4pudgm|LYrtMZ(0}&Zo{p&9k0rJG;r)ts0aQYZ zAl7wKg?TeX@c;7tegZF%T^$+$JZbd0^-lvw&%*(y#L32QYz8+@P)6;s&(t@FT zmg2&}N1m^tQ?SZ;#y$?YyyJcQRlW03gGVs>yPWiA#gk#p;IdScYgvRBPuVto8GQSu z&+;a$ywjD@(Lj(~MXh_y=iG+gq|f!u_$8E6a1x1b>D!eafvejyca$a+Cz48viwU1f z`6b5AOdF=A3hvPswr>aHndfcZhrFYe*2v9?YI|9w53Ym83!vy!IWBBmU)Smq;t;pg z>(jf^6X@)rlY>AQUT!zciv`l*V6nl0!jH4lEA@R1sQVs)o{cc8-icUK!+V4~DY*LZ zFeXIB6))Kz=TYY!U&PD*A?+m!?w1hARsLKZb^-gFR-&cUe^3QUQ(do+npV#*!OS63 zS5L2MgGYtX&Z^A@$jJA8H|KefVeyu|HQ*n)K{4g($4${^#emA=ljNkp)qDILX<}|? zS0!-9+4}5a+CfP%<(S1`7nR0yLK5^jy^+%+p|AB$*wj*&fr3>-FhFX-iT0r%;drJ0}SBdA>}9vDL4=$K%a5a^|dK*WFee)YvjZ zumq3tvB2_`#_6E~erHM*cVk2M%mCH@xB4b$4Y$VX0zoJ7vk%$vo`Y`4*?2O?X)?QO zepfl%0^)f@V+12|VX_Q`b1Q80Mb}qizH4aD_C|D6;6huHvbD`S% zHyIZFUE>ofvRg06bka*DY5i4n9d(Z`i&Xn0duCEk%fk{~y~?GL=T9XU2`hBQ4#|B| zID9@y*>W8FCpc)on69slYLQk95M`E;ozci&RdSJmoLq^!k* z0?CFc2>MPN+WYAdDMGn!Jv`HtQamY*X?t$A}F^6|PL72;4 zJ|{}mR*i5x)bpjl!0@@8nAD^2!Kb_?3+Q=g=R~wtDQ7R;(*fy{Kq^2i;oB3@{Ke-jbQt0ypzzj0xE(53A6sdjx44O0xdKTRm0urkP0A!IHCt>s<>HDwAY(#p=#F zxN!I`Q7aLG1M_HNZhxfNqK1T=lwh3MU%Dm>QWz17rze$Wu3Ix3HHr1idguv<)Ej`H zAyL`9L<;aN?U@-|8phQ{lgBs_y{eVb0a7kTiz!v|2%C`eNp`NTM>-4*H~uwWafrOZ zVS`Zedoz(?INc#Uh0DPp>HS{IW$PSUHO8^b>IYX6_cOXCeL9BCX5uE3gZ$HsE%CEY z-#pqaW;Cq^XUEnN?7zz~^+i5aL2lPchu?Z_f9wU*%`WRl)^u?hkE2H(YaD$0i7)IRGhM;cjHlcjAR-Gt8|v* zF*>mdcfBfaU^2$muHK+}yh=Mh%2bM^`wP4oQ z?w&(H>OP(fQi1b}<-lp<3gxL4;e?6UshEoB7hU)h-Y}gS6Ska{NWBu#Z2*b2Eyuz1 zh*0B^bW_^%Z1?X*-JI};p>e)1Je^zrT#Ayr^ecvSmNB^T`}%q*Y|f z{qAQnM|no8#6!hw+&k&9>mxH%0T(fh=rJ(>*bFGn99Du;%-@92wr;F485%J0Bvzwj zb7IkdIoEZK2;h75e>ADwtbTKm>FM|C9+*#eZ(Pk(U4tSbMFryrtb6Ux=<& zNZWk3)6K}KgmtdqZG-#-xF?Z)E8XMwRqMpK<%iPaF3)PSgI-;IOtZ!co7p=KpELz`sk~PTaVTDpE=!J*yERF{Zq~QgJBGz znr+q;_3Q?ve5uv#wKund%k9=6y=}dyCItqO4hA>zAyN7cXR2JSPB039*Pram9mv_@ zif$2yJQJw7RuMZL4UO<4%TIS#kDF2;%}SP#n^~1*Jv~(2>^j$S7S+y_S%#-~(n}y? z?@-6WQg%Yf>O}__JQXEx*RHk31cmnD0%Zs zqygF9?UpN1(f87(deq`2ZjilFtIRG0f9N})RNlhkgkCB`N0i+HtmE2seJ!9iKJOGY zN>$cjliB~6#MmJJ(X(Nt+%2#8v!or)uCs}+aOu(*NQf8irJ)BFeU5v;Tm-4*(go)G z;DG@gJ+~U_{aTX9W)g$kx;;R88Q<*^|Eo0R_=jta9%7 zLqV=TC9Fcvufb){&!qRAtO`3zzW5Mc0W>DoA#=H*WY{vC3$z4x)KJJ0TihQkG#)gR zG&9E46ztG4nKpH9-M0Ln^z!O}UgKD6R->1lK}pNVz9X*tkV&YRDg6j33(oEQ`w|;O zX<8i=!Ieo5OBWvd7J=ax6w-l(-0EM9#+Qu6@}x72evH+VxHc6z_Cqv(7>e^k~9!6C%_f&oejD4VO6dDBZ@84j4pNDV!{Djeit&a`?uUQ7{2*}71 z_V$c>KDEf5voD$s$+%}zl>wKqBZged3)g08dW$}EMxz)wLf~(?%z^GhisfT(bq{%i zag*{G;YDJiVfTj255|wB{ERyGS!?1Y!oWTnIS2V6GxAmcBaf=$vNs#MEeVHe-PCne zI-Uv}al4{jDPHdOx@z25V=cAV8)fj3y}v@pgHOA>2HQuu44$S70fr$eDA~F?*TVrl zpBH7yRa_X$8Vss(?f7K)1Y9>+f+Rx#6&x+}R+*eUZuE zw}nmSBGU^0NwW)1bhqoYD(dmAkjxH&xZvH$7^6x)bgcS^=$#I595ryiuEU-oX3$Qs z6<#K-rq98^6QWgK*s*@(D5lucw)G`d3|(O5Kqk2slCx&4U&Z6FJb24AvOqGo4#5kV z@fZ3-f#t2BqFvsNhiD^2tzSI<+?o~5gHwRGyzf=O%3_;n{@=FYR4dRQd0nHsT)(k; zSbcOa?tLn`;-9XrD5q5q)DY{~BL^q77P2~DFLiQPLz==>q!HCY_l`mo)Ga?<7mc%7 zMZ+O;*-KldT2j&9Ui7_KT)IH?jt&;oX}*joG;;o-?GlQ7FlYvR>n?e@@x0P+9hw_v z&-+~SacF?6Rx2n6m}d7o_SjKeCqWY zBhQ4}xO;A?w@?=Mz9(SSoFat7y1E`FHrXFbS!5I-aN&<1y$~Yu+C#O`pQgD_10)B; z4F_DIs8{L7s?ibmF@3bml}y*USXs#g{A_pDb!cK&!`N!-U~dT+++AvM6D)W0FXT>B zd+8O&C^wha>Vl$6m3LjUY+{hXIJ|B;aZ#T&_bs?MSlQg2-n=X4akpqJ`EP1APsnso z0LsjSf`sW&5@RyTzj2w#Fv++>4AI>3bw@+D#7IXW5v&`~SI68tGE*95)51*YYpcTj zJww)R+IfTYuz?d>oRBJK{A&h#UU+XI@mT4EPPrVib+#X!-yL(t_G(&T$x>3m&h|>b zp7>C%>=URbY7C%+ksn2IdGT>lk)raH@4Yi>DEM%G@tU)3FPp|GH#83-6d=Q6AKV{}F@hmx)Q zQ;ZLRyziy5zZGscM2n<7AI0`ZkT63 zDTx$j>K?6|U+*OQISzCR7gyvlYJUB{hPPu~{AwJ%BCzDc?7Xj;-RA)eivvW=5_}K=Aj8t#_K# zKj;Dd(ZpEo49{18njMX&6cYa2Nuy-OP{5lwKCyb$MSq2)p2-6zob1Y*ERP?%;LBX| zct*{M31$7O3l90>^6IPC%x%Jw8i~csk2rc;6KrNu&;$V_a3@Ren7GZCSStS3i^I#T%L6XCp+YY#40{dt2z$(S{sx8kaQpdsZHR+@ zIqFIT$@6E$aP)9B0IW;GJ|%$BeI?}%ne_C(EC9(t_hd~C?GSWKx58B&&PX5qI{P$c z>M24%RhqD4P4`Ee+erwrKy6pRA@An3C0WQ;a-;MHg-ojF#BRscmX8CEz@@Q~)CWFw zn;l2}!sA0W>#=-Ro#$W;YWM!*$ZF#{yO;_jz+RV1zbCo)aVO6{J>GM@zYUGJd^#jm zckQ&GcxG^2s~g5X45T&FMW+3Sny2L80y_9E=02!xMbKyqxVE95M*@P6Vgq|B?v^yY|E;Opze3pS1DcH zd8)&kIW)HSMzJhS=0(NuWsEA=wX@8;?fjHg7*?VXewR7UYHw6hjAUwu?-Yh`IqoH& zki;QnuYA&!pB(JGXzBHuS;wdTk;cI0Z1-l%u7$=0X!1AWuPu^m-w1la?ORM2p7;{t z@t*N2WX*VuB}9#@RZY`GFSvdGZB9D1URPu~;|D?tiJ)v>N{BbxPW=`_fki+UF4}2v znD?dURn(!vUKZ4Y!o$*vay=sp}|IYg zu{Is#A4c2E^38q(cO#qMNi9H~NrM2a@lLx#h)XYZ#uzY-U%qaGGmPDIz)i^7Vj2Xl zLsX0s|J)tGUJ}_^tvi6P2O3ww{t(kuZfTjCJ-84S+>COPq8Lv$^RP+S9Ny<>eXgTp z_&s`9^7eGISrv81r=tB}J5eiPdz_LMd&1lN2L>sTRpt57E9TEXvp+wXPNU!zjVr>hLA|Ra)i$h7EHGH{M^n4@cWNV8oFpgeYO`?-pv|!6*wM ztAbqEGL#~$Z(jg6qNZf*ME-PHh<$p?`RxCUs?Ja?fiBLZUb~@HcX&3SZ#z|5>*Sgg zFo<(aCPpJkk2Bg3)H~cJAfKZ!NwtiuuFbcR3s;D+uQEq|6KcuLga7*Ib@A$wX!7YC z^KZgWZHPG&eSAzA%VLFh5Si!7i=0!ZXJ8|yc8q#T$M&5lsYGEgJ>4E+;CNv;&3oJi zz!<_~@-sZOTQtqL{HUs+k&W0o}+>K@50CN} zRwXA}LH7$90Q3NR>RC_kHEiL1vm={+%Tej}voXd9ks?1rrVb>7+7ey0Ffsq>>(`jf z!u7W+H6TrJq7B}6dBvW9AS321(Z?z5CZG?G4xVEHHv*YxJoZMo{5+8DXe|kq-!i>Z zZ~sQ0N5v9y4YHS}3`FzT@a)Iia(}-EiU8={F4nlS1p|nhnwl2#Iim-S?Z6m$ytnvk z%WNe)Hpa)s+L9(q`0CGk(O{_Bry1z!?^e7wv`~9C*3Le}yKMbt<_y{JSj@(fg=hDx zOU@DYzT-krwbNXjs=tD_BGN~Lf52U31$P_EZkhx=o9q{X#7&Ct8+SAFnu)$!VrPgx zmfB6)gP%7_`Q`pHbN7)%H#m~Zy_HGwhyMxh!h`5({P?1(2i*OHr{bAa zA6LNJfuYGoKhOafeZS&peHcxpHE=n2L`pLkxCy&SmeQfc@2s4akRJOFQM z-I^A=74iFC@SZ4o-+-?LT&AE~jC;uSASH*ydhc$so_y8<~l z591t7xU4G(LVcbFmVhkZ#Mf-&1>NA64qHnONdssn8~<$(3Iz$E)anW#0%PQcM|X!E zJASXNutezENr+H9*sVroW>+v%2=gVbf#9Y?6J1>>KgXj3>xa=;jwtI&?j6X;F^)4$q0{e4hN}EbC8X7J%lARJRA%J;Rs*HhB$*D+YdR6%C3U zA|Z>+ONx5E)Kl}x&H|#p=ctW*o=R}pY(^-?$P&gk?#;H)Zv>yz0Jd(?n82LvsTbVp zv8Pc%9i3HhBXjgVrp5keDs>k<25X)oLl&QwCGRrACiZ(vYmZJKwlQ<>)^n;(^C_Py zt2cbGiZ0K1DaZb0jiHnG9f?_<5G=c`J5D0el`Q})2FVD?zu zW9JDYvG}n|)29MCO(hUq5Bz{7qfo50>H(|3dU{baPiX%22w5RJh=$u@FjQwaWi_?D zpPE`3ni-K5yQmRI_+a=)c0$qv zf~b}Jo_Y5!Q6#gNY#_;^3&AMUbduk8e7r1$#DJDL;xEL3=N0Ba;PWGYP>aUoBT+uMe6Y#xGDu1nSPK+&IC-=P<2aSnx7Zj$>QIH?F%H-Zy`+#<$Ci74JvE8uAz@k2}KKd zS=x1-hg3`dsON$pgh?05R?Y>Zva-YH7;dmXL zZWVyw%w@e9e`{PXks^*|bFcPBsZ!Cm?(vcQIUxjuVECV;<1p%A>v>MSZ7h|KJ=p1d z<%ld$28@UicDM||BY2{wnmGZpMn*flj_DC1mdG=5o?5B&bC<$U)3KWp;fWGeeb={`d z=hnEm>pN(bZ6!4ja~+qu8tg!)Wdf(z!vq$B8aF;)7(R-=zj(oSXN>aekg1>SwyD@7 z+Y|p$uv3ed6{dvN!=Y~)=rDW!W7tGSEXBQk;-8UxrRH~I3)^*VK-cHlTr&) zp|Kf@pvIT!67ox$=)V2sjr7pMzz|<@8--nIr{c}PX6#!t|lO=B6sZE8f@;E@2E~QC$y<5F5Jo$3%Oh? z=$+5wQOB8o(QfaGKV{dX7`nFS>3t;8ug#oF8_Hx8AH%vmw<9RFaD7n*tEsC=7~} zAo`B=3>5#mcG{e}bhN;kP(EWZn==hJkIy~qeZ)1Y5{W4J(bv!URiruVaFVZGN0%Nf zDd}RYmmxj2-C!l>R5usH4K@z0eB)~U_8ZzDL!^%oc%UOsC_Fe(C+RqGqs>bR>U-%z z_D%GoF6)Ls<>ZB=@vJC%6kxfLA~2GRt|_21h`GMZXb%jYc#FnhbUsnfx>Q%}6A(kT zp+ltQRPoIp?@9;rX$cDp*Ej^}LVw-%&f%t3H{{520_u5awG%$58!gx8mIMhq=DN1n zQo~&7uPH8#f3?IvjK3%2k@Js~!|v8aj&c|o3xy$Ua<&ZGVQHPO9v8iAMBRlGw7mIV?g7BhT8XZuE)0 zdUXw8a%$-_H_D7Y%zfnmCxkns_q%Xy{X_e2pHE82RfJnf_mWWw&#huPh(D#-u#1*@ zP-Rkk<^An&zpU0@dr`R!vO-Mpr+KYxZ~babe>Tl=1p8_=vxn@^1%pBb56i;d(ZkQ% z`%_pevUkSQJw}P<(m8Co8AQ*AGQ~7}{I0i8n}Nhmip(9i>Q}2&m%dJ+Z*kC%#qBz1 zQ89z#*JnFAVij6G*W1tmVqGo`TA0t8?e%yHU2ibSP;2y7E(xqPX#HxO%JVjs=n5hw z6LMHM75C*tfdL1ujF0!j> za1p4!u7dW5UE8J94v(!+vWqGe@8rK^n;?#9?!=fqO)sE&dREa!wC_=u^ExLUy@6qz zOHH>wo5!FddbJ3w)+CpDW51VVs-UZ~LOomd2u`o_Vk0`6*%N_UX<%>=8A9))A=JmR zJ;~!apha|J6bj=)TKu=Q`~z#%=xFPeTvc8t=S%;k=|fy?qHh0=UC)(p4#C zya42qBy5uyGIN=U8qBJtlqEWRZuiCm5}sG^l0@d~Z(8-&IMVx}J#o%wwDkQuG*a?q z1HW5RXBczGE?x$4!}jiGxd4YT?0O=j_89TcP=8GtyCt%wa|V_Z#uLyiDoQ<(^kBJ? z-j~KV3m65h^nhoN*;COJOE05Dr(YK=nDz{X<=Z-es6IwH>`U)zb$-r2iz_<2uUecW zIf+HLJz2UO0X&Fmf^76J7O z@Ob#WL&mODz#v`|s{j6o+5{!rqYJbfU07Z|=F>;?C*d^VbZlhg$Vh5J00+X9Syx(G zI-Vm`*pYw7DGsH~e&;8;1$X3wA zrM;5bRaRv~ULK>>ZPrFWt&oL`!uH59rRi^)$yo`*AqnU`j z?T0md)tKsx~RXC3B4(g=xFLwyIM%3z~@)w;>&RuDC@~xapB$nedsxq(vQq#MPsL)@Msf z##t$WT3R3O6(`hovZ-sA(prVHE9PF0eXqB#!Q$*(9${7514=dE{DMRs)qNu1A(rem z92ZzMyr%l@W_Md_7h z;PPuhDQ1s5oi3s(ekJ^Zm6#BzYC>i6xuE zJZ2-;jwbqzl^3(PUAi&}vGD%pkxA7^+nq;TTs-2b**iJFk3ftf1%{BHuyw92crQju z3&-yYVM>#;0#gF;PS~_d1=4(z{OQ5Abyp|CrLIpk#uu`!F)fnaK}m=jX?e|Fr6t}U zncp7VH#ag$5Se`bAG##I^c8m`_JO3LAeIg zglw=`CF6d)D*Ujoybq+-2VA0&ZfbdqeHuPdKAv`cKWSK%mFkNIv`bPOe6AK3@%BJ9 z%lLrw$#m{OS8zxvYK7pewYa@|2Rq>>$TBw|exR~CL;PTx-v;GqmRt^@mT9aw@~7K} z7$I97AqzktnV{gNPv4i~gi~o*S&Vf^3CL1WELKHGQc}{Hl@(g=z@u1R+FAf(I!Lv| zsQ=Bf$|B#mP9NhaC@`;phhOu5vG|69_vg3P{lj{JcY3;>s;;iCEN@KnB6REyK`D=7vqJfS*^d(EJx?@uV~cGi-~MmiSnG=lfh_Esv0qE#fy{Trv8OVS!;%>?8BFro?}y;iJzrh zWm0&a^DRBb>TH+B9tarrzdDhBXVZ)?!Z`QF(%#l5`IghJzXD!To#RD~hI2^Y+V|1$ zbgFBB+jaHDWopWFA&Y=jvoO&b!fze@JC%%$Ju8YU3!`TqK~ zs`oe!ljWL&=Cw&wX>JozOjz9BKoqBOv7m@0&H8#bjAdp57n^*&g9y%a>|qyw%v3jo zguUDJKyc;OwW*2$Jzqy;_O@k}@JwzGT+e%nOfO`S>Ghl7BeVIT#`celh+z~{>(PG3 zr4xkAx^~6pTalkVIaoYtMT3HfIavtZhn-+XYEt+^WtNZdRLUis7xO)l6MBa`7YC>h zD9h@m3c(>PRJK%=TaqyI!o(?yDUnF~9Xp>zdAr;Z9L*vXbQux+b+3a_8AFo+*n7#N zha07xjDFAM0^b*un#bkafZBCAN`s;lUizLPk&WzY)LGTQ(zwbHCSWi#zAHP+OSXDz zVscfk0h`B0o68O(8c7gRS;-8pf1%MP1a0SCMOMGOXiv*M3w?i`h-H!7dy6CtL=Jsu z@dJA@36fUDiLK@p&sXo>4~EEmY3No? zp@K8_x`RyfTqC=`+>EdAdT=YjK6*MEuTrfjVfR~g^NPfMxsB8(?Z}@8-PPaDZio{s zXhXP}uG@p`vFKH1d{FA{r)DIPZ#q- zT~@~{4a$@Lw9!@)Y?gs_pCAoN*?k;FhcHojW$1MG0b(F7Vq>bdzdvVIVvK$%qt&Ts zL}H+Md6M6`OD-!TMenG1j!YXGOYik{vWzHZfcnR@w1P8qPRQ)4tyOA`Fta4qhQf66 zh?HQQ0M{Aqkdu(xi-<4by(PtEZyS3iy4dM+)s4Fizjd%18FuJTew{)L%#{fbv_U>y zhg8GaC$GdU$oxFTv#$=C4d+-N`kEf8qtdJ4-b3n2^om~&#=ZKL8q`0_El_n^p?YL0?e>aq=BU4IFVmQQA`fMhhT-j?Qs;f z|L|HgvRd~;xCBp(VJ~Hv#FKYC9ZuO)UwdN*!-4AyTppNfloG*r%L;I8 z0WZTp@5ec=GP=O@MiQDY)i*YBdED;i^TABsWpxm9=)@!#Q9i$ZdT&X&Yoh^0f86K! zNgQVxNLIL1|DIAq-5g`Z2;bvQ)EsRoTf5|xuCxg;*6^B#l5XZErQ_4_1{ze3)DvRt z_1PWVN6+M>jL8trk}cuV(4sz0zO^TCy9Ig+mPYPMTgE8jZps);NtOnREfWqg->L7vyZ zt+HD(7?s1-0II^HZ@hz8_D!|E$0fUrX^oh~0$@V~;EuMH%7*Z7wHP7mN0a4&yENYK z1Itm}oiXOA4LVCwgjcAy*px`hwBka1r9^5mq+A@A$R%BzaP=Ket7EKs!Zh9~zNfAC zvJEs#$~FToa}Xgc-=Wc+Svx%UIVf0+Fjj6WdVa1rlWX3Lq@nGGxz=z+!Y=eg8N0iO zuef4L*N-#jH?lCdt}n)_Pv2)a;ECp!sRBjm?h$D_sqRdBJxth`oXM^5JP_O&LRi*kOSfbDLY=|F}7Eo5e_a z#T7->MXOeS$kj5wxQ)ov`)WTl;49iv=JX7EhL-;ue}~YOM7>X0_>9@$PT2YC{(ZWd z)2}}mR%g}L5|x5dvw~3Ml*857UCN6ouP*G>l*BQZjcA1fckFVMC+k>*HIuRSKb8h0 zlP(6Kxjkp8F6*T&!yay;)^ey(XYf*}4s#0%z73NW6?Qi1Wn?!D>Va?T`D#}v6H^d% z+gMadCi>x91A=KpO#vpqMu`%ZR=RK~F(bRVEc5My6$%i@8P;7~g@|pwKRSzxWG|k4 z!As7C2P?LiV>Q=>UiszwEp0XHRAyN#;#x1t*X>W)Sq8djz~o^e&0AWJyVJq~E^k!W zF*x(=*;bq|)hIgCLr@*JG3vxvg8Kw03x<0I_PrTf8D@E07;9%adL^Fz5$QbhBGI$_ zm^VD0^j6pmS3(@*n_l?QixjJ92roH-jAN|2F&;Pdn_Zn!BsfSM6zW4W*0_fxq7isy z4KwQoV?yMK_9%<+V{diT)$zbRg?xKOXYv=Z=rx1E6|7!uWLxYEr*g}ws~1UL-ZW{} zm2`ni6y13&Y3i-OOQ!P?_C*22l$0=k)UX0qg4by3VGTBKcN0p1uTST&%~~e8My#fJo7n3G^TFk!k4u(*0B$QN4I}zTX;fbJuk?^$z^&A{Vj^k3>RYONgFa_F2S?BEg$7)Z6xtwHP#0rF{MBA=B;3D^HYcR!b45W)}gz zNN<$m*U##7ItLtYl5U$`kWRcFPsB+~$xCe7y>ON-O`4FOF*(u~WnEyJw}Z$Zq>-cd z5*`GM6X|SDT~>ZGV9qexN4VM7>3KA>oU}E#@wz`e3HqXE9%A6h7s-lg**SnYvKB40 znItNJPlFu7tU{`DX8j6tuyxlMMQy{@BU5p(@|nVU)|5v{@n>4l-a>{ccDeowW!^_I zf>JD%C6M1vp3&99bv!FR>yr*`gR?>4oeQ=5VI~(^@J2@pGgP8kd+3mh)rRz#Rv~ls zYWJ|z^~v6aHWWLurFxJQOu%ft6PedZUn!;aB+*@E_h~AAg+h~s>@m{Q(SW^L=j zmI3I0$s^?BnQ!DHgCB0?5g-j*tE9L65)2BRc<%dR)J*jy z4CShyfC^(uQ`{Pt$D!3!kP>3!>&oI0=M_(EI=V>ngdgRz!0D`EG-dUjhVDUTC@KEp z5)!s2JNvj$nMf@SL(E?WmsU*^n|M0dbesa*hFE8U4-c9MJ`CE3h=|O#dAA+z7niq= zFA0i^-azsN)JJZ3x1@fU?FW8bIDF$xz2RPzj?~9rEyu^El4Ph+SV<`y0b7u)T zlw(l7`zUMNWT>4Er$!+q5Pg->SKM{{t=1%FI!aK?c3vx{PI zEH-UVNfNck9dusv%@LFv67s38pAX#R;}sxu%( zU+?HlQpWw;rtbIG{oM2Gn5cR>nJpzO>8-#k>Vs$kaCjW-M}f=J^tF!ZbOWK*TOoD7 zQv8{)_>uw%O$^qohCEU9`|q>Rq>JZn>*DK1v|aV77pP(!Tu-1rTYi#c_`3Q97s=4GV3eEM*jif;n4EC2B;HabL zoGRbmie{w)P?SQv(ha(=a2&Z~F~OO08+}G=t$l}qH5CKI{LTd?9z?P1T5#)(CzpL+ z&S%XEkc{Pq5G-6RTU`3_+#gpA)y^5MB<;CsyIqgPhPOMCAWOWnp5^&dC9sk~pq3(1 z(s9u~ig7@S=qy}w8kHp+o#J=?6#Dp3qXT*BdYEr7=bdQV^2>#D2g&GM-kwW!I>3X7 zHg6H>hq)2za~HSP=nRmha{kgbIGvxAR6SGC`gm*J-P_w(?Zp-Y4)?QV1ox5pN-T&Q z67>rEgSp8m@Zo(tLAn<1EUTh=XY}1| z?SfSoIN#i6Z;}ceHKD!et>PJ^Nce0l%TcRkEl$Hq(9yA`hLy8rGer!TNxynyo0(bG z1v*j!DmZ4kTtA??=!!yF4UKz2oYm{kY3<^SozGJpsi1|ESUN+keb7#aRm0Yqm`Ct9 z3w~aH5Gkw?6t#a`NCFgB40{^7b53d7);R|4N^rph?!nrqq1P&}gH*gCkO{Av98TR6 zlujY|_$r>ww_ooC{;3WO)&Xk5`2uanWuDu?JpTdWf~By;vXm{`_b@NCR2`a6m!ynM2f|~(pjP_`Kl&g;K05|Nv^ldOlxu@UY(J9 zk8Xm#wCF-aTZlCoL%AD}eovio=19Cm+pa0jN%!fJ_tKvwKXMaBbz3&9q2EVQm(WqDB-^^qdCHcfhUj~~(=#;O1GI0!>TP6nINI5}EbAG&*~F1#lfySj@8TTbmIrEiGL(V^xSXzEd+W1RZ!yFCDi- zArtd7!!0E=&~U(SBLnydW^}wgQKosmD8dc`Rjn+btX5M5_L7>yv8>QYBJI>x_og z2KrNQh1FU63txK+P*B?w1J9|Bckdy3?6FfFNt6q!JApjtnX_W_9k{Mr@XsdTW*SW}3?NH|@RK`$V=u zFm-9%5q5Vm!{TDNk9Q$`C#P_5HXTxPgi^6zpW3ibCexjEFxtUxy>%Ivm2hUwHA`E-98^X_;EMS zLg6hEk%t|jGOhFkRr_E`oc;l=V%DA=Bk$ZQnV)x9HU)jp`*n_bSM8#^@I2`6%QXlL z{4~C+9{Ny-Y3=`{IG$A662nWSL(%P4OF3qS7gv!*4 z?LWyXd_i@!1~{gV4SF3P5g7DN@iz}{5~zBNpAb@+j1V5e__>5Y%)M6$e$pCQEz3RQ z0gUL=&?TOgY%k}>ja<46Ga7#n9r?gU>f*baR&-k10l-xz*UHd zHR#UXFv1TzAvWT;I9rEN_{-8w0tH_kkGXq4_XX_;q`C|guX}Ks zC3WdC)n5dQ~K6+g=4)Aj})tZb-X{W zTnsgp+ry#kg(@efXM&Z#@yS5`6G8b3Z5>e34URZ=;C&ce;T{93b* z_&rX-MkZ7&1=6~zDR0(iS`+LQa86V{3Eh|$pfl~GMfyePY1xRjJ8x1KtvJSA14Un< zQv~7cO;fslmy-rf2>ICO?<1{2&~H}ttFD=Ih~|@RTkkneR~Gy`5vCx+cIK~PG-i5> z<{rau9V1Okx(_?c^}?AQJ+1n3Ntx!UvSb%wU*_2d@hf*E*Fr^1#d2ubO5cx|VK2D_ zg7>JTiM?D325qj&xT_?95U8-4w zv((l#C!ODEqW^S#%>fNQ%^RnRzk6r*Z4%eq0s}iH@P0J3-1(^2^n{R;hn%pAoGkOH zyt;OM=hB0q*j96btv8}?krQ{xyu$Sv$iP|<9jc(H1mQ#+2LJvOo%9=N6hCkDGH>KbQV(+Yjv_;j*8O z1_oW#86xtl2bgu1d(1%lO5@xk3NkbsORg&0CvOg$C8Y-ir$>GqcetX;cPCvBHnd4R z4|aJXuGItc9oz;}whQxHB4`F5TvhU8H{2!;x2SeKT~&PNQYQ9>oYV3p2k(mf=uxDJ zKAbK(_T`8!vXnw(%70xLrH%9kM;FL|O{Tcs_XS+LE8DN>4RKx?A!B}Ye+%1@$dgks zl`m9si|kHXagw2S?s%B@IYsIx=QJL072bbBF%ca~T=xn9=()Ww^U2CBo;H~4K7^Y> z%ox&Ff~^n`+r?UJGm5r+fo^j&ucPnPTqirgW#Q&QR!iAo^E?Zt&o~|i+~`NJIk~}9 zNZ2QR`&DIjL*ftB21(g2Q2$K-(pWAv)dZU%c(nNoqw5LBH5_aw%oE>tEU*%KeDQKx zfP>0b`HjuV<$`r~%@k_$5HZJ76zVp?QQH$=Xjm93K7Lq*LErjpg@G)QuDFa$AM1?f zMoPd0I0+a4`O?1%u1$g!*D}kC^N)acC@6;K8)`K)J>DjP`?>NhM@W-`TshwYeO`PO zsEC03Ha$I&rl}g`zeYr|_p0w z#sk+J7b6uqr)$pboDNNK$*9v(LJ*@806wCwZZ~)@HYoq(bIcHEd*L7ajN@ee=eq+8 zoC3&rEhpU8tCpj+$2!xkh5U`zyjapnBY&*v{Hj7VXFj3zM`#vkq7`d@(P&G1%WYvF_rBAP) z0EEkRjkOU5(( zO3I%}{gDFp^MLRLK4T``=erY7>f|r{SXZT-z!`VbMw{@+#!yr|^gmuZ&wmDx+mrDu zTgVp3h9`F4sxrCXzNCCp=l+}=pA>1+%=AQ^xAx#w~EZsE!vN zSeTHdHHClvt{p^RbW>|3Hn;V%FeB3NaK|SIT1Ik~3Av^`kZPMP1rIO6xO@Yk?RJJI zhQm&8?1BXsKL2!;5}b|*p8ezJZ8xf4W(}6^UkG@hA%fDN50t1ovnHh`i@Oa)x@ld#T(pYeC&ce`KZf@ zu@mx)e}s3;K>Lrp_zzXQ=*KAI8}=Q4YaSTd>$~lqZ-EtEo?(nqj*B7fw-&ur7XX@2 z!t5=ak!E)(deQ-RpJ5li@KwGT*Rxb@d4?FRw+5x#hjK$qU5q3Wb3;YrnQE6sf*jtm?pjDZsl2@Zg+vQn0p|J*kO zF41^ipYnnV#RQ^ij$nsG?MD<95Q0HgS=p#`1MFRc_0Uoi`~i-TU`A09LRVl2P9!R6 z$&p?1W_6pNecJo@^9|9x{rysrzMh^^3{tV4V!>wNX9yo)aRW$JV&l)Mwee(3V+~uI z!=~nEigUpFJ59N_>8xyc!*tO#F(uBgB)zF)g4vNsXQJ?Iwr`FkCDoS{N-IMvMfCBm zc#V=Ws=aNfTqs6xdp5qbAvZX%pprW3!TMc)op!Nc|6_AZ}46)Bz`aXBj=IXqTR;S*I;%R ziNPLlzLw65lTKy^!Xe@RfX`{$*ve%gH$IWjbP=Q-JzZPMaph3uCZP z`nT}~REXcOK@BSN1Q^mqQ1ZLuZ4b|6G?q!6hf#kH3L@p2_WhKNW}~K0tKl<&`CSs> zB>|YJaKo*-Qa@JTODwRju3aX`1R@y<=Ju@sku|}uTICl>hRy~jKKa^~R}2?m0gay; z9idxU3Q@15tp$SZ?~^Pr%jBwYD4O2YAXWxQX2Uy}7ukPPi0gN5_?C+)RaF|m>G+mu znJVG2Z+IAz73fwI#7;u+82@+#ieaF7!W+YHoy=Z zw;J zMW3dX2ocj#gS5(UaN(2RHlBa+*xrt!OT5@Vi(De&12fMJ+;$e#8{*Fzo2EvH7rW&+ z5$moB2xb?`Aw`pp9CY1#V`>IZY{N<$7N9Hph~`990i-dLr8b?Hyr zfZRaA{Z7Q}zas5chnSZ3n|jFB*4AVBOY>j0V4P0KfhYY3Qg|`B47%*3l2B4-_vMYGL z?q?gv58ZC&hx{IBQxWnB0so}|el@HFMqu8)eXCocT2eYzU0bUTwa&%egWmkx$U909 zH~gxw?IOa$U&!jUV~y5+SzoQ_y2P3*YW7l4lB>v@FMaTJoBXGKsx|Q6n6`h!lx-9t ztbDd;^D9KZQ7wQBGmHHJ86q+DFX#A|g8BpIhy9V7U&QgZG5_iVzr6tdQXKdhApxTw zCgiVB{HsUcBPN*cr(1i_zfcJObHq_0Fq1A&KFQ$-etQ_ESrY5l!`$CN4jm*Q4!>}T5XsB>#jHQuNEd`W9r(Xq689Lo zVK!dAOq{<8N(;lsn3%~snv*Yq;ONEu@yD{Dyihv0ld8Mvb$_$1sp6T9VF{)pPOr$? zbm3)Q8U1wf1!$g|Nz0Y{a8z#GIJSHaLj#rAYI^!8?MXc{%%Cu!GOLkLNq!rTd?-sptpEGtjuTaS- zOVs@Aa$&~fz5QCrlQ5fpKez>=&Gp2oUM+ysp!^`JY<+>Ituvh;&Z@yM@5)WlD-e#z z6GrMXDR-@Z<$)j(_U>gy3mV{lmlZ=%M3+PTlPgH8-tBX~XUV`IxCqx@*=IjE2V2rE z&>*8MCp;`ep9_pxe<=)NUKGdEe3|FA8eRDt$z6jqTw4u_EAnD%- z`141BXD}Y79Hc(Q26Dd>U?>S<)BcD0wTB>9x_ZHC?yG@l{_Yj*#ZYjQcC-yNeH6TT zU|gVj3O!ZlW$DrChG#AL3R`nfz{m=cSd+u21V%b3j7&4fQd4}QI|<&yn+|Y&Z1(Ya zJB_ZJjqCdd_7iaI8W%vXS5h2~Pnnf7$gcVNxT=1;|BjKL6|F`o-&S{lf)d{q@lf+~ z78R?ZAU&GS3WXgK|KzDsG zGoqI~-mG!M_MNv8(NqPT*;%IH^W0z^)$}9(^LaT9ClqTdm*;?VSu|%$!};~XB<1h( zg9s^+@nsI_)(jn>#9?4;3t5ldKWpO*u*y%F_EY!`JKf;t-K&>6Wr96X)2r_-@6n|# z+|kW@1~+6Mk(N1KQg^bZ#!ifH>#Ri9lUZPDNaVL93r8^N-5{^U9dX>FHR8CtJ^BuyIu~sSggS*2RJXaHD%ng9c zfEo_hdDe`h?)alsk&`{V59nUf+&Xi76(Aa`e#N|!BRbYw(47*1@0I%W1niJ0v)x~x z5q=Yv7RvTAId{}}k>55_U-5oH5*qd@f@NExz<0%x+kUi_K{P|K zl2|bqD$OF})PWTuS1viuygy~IZSHAkXQXYul9RMa16gs|K2Li*f@2y&%amA?FEKN9 zFE*D|Ycgw?8S^=ea#_5&KdQJLh9OekSJyGupHM7$9DzeUieX{aBS>*;tH}!<8Xm1C z*p7+#AE&@ST1r1FX|SaN-mj<`Ui@c0w2+~M#mGe}&$>0oeR0uj+Y@R2atopPX^WSb z-gXbIM70X3oac#{*+3H?H!|H7+3V~aL36E;QUT9Os{*zy-cUF&vqh=}(=Agua`VLg zu;WFsRY3kakkXvJBvP}s;;SUjV=}Ai=Pgr0a&WXH_5ITW zpq&EStbOGvT|90y(Wz>gY=|X*UV_7g-}S_ic6+EsJn`6skp_)%CuUt)`>l$y-skKQ z4Y8UHqjeye8Daw^>PnOHf?dkLI{%E`L3TlYLC_gIj*+%bJma~juCq04;6K`{23M7u zU*aKaVK`#GmSsp?_SkkEa44V@TD}=pO>pnxIvM`Oo55HB&G&E&@>)u(tSl=7M1TH# zTSN5FaC#X?okDwqXP93+Y7z--sKAO?GkP5^Eo!!B(v73(x3V}@xAy@RiI9{0G|X-^ zxb~PMCnrkG?Xz}FY?J)rkhP%Ni7f_zKcY5)!=GIlVhj3pel7{wvil99k|D>VBNH|C zJPPUObZh9|ygUON#(ST-Eq5=vI3EBvm9^Iir!v-<#xf=0#=oGe3SW~&8JQtrxyVIul*3EI##&_xL!Jes0wldnQ zZLL)0$bG4%}wZVI%$mFT5ET8kmbigUx^5eE!H0pbZb~pG@TMVJ0pB%Ln#kQ&jAK zl;f{#`detg-vnkN&fkyzCy4)l#YA{gi2n$8dpiat4Gn$*ra|dH!t5qOOhr|wGGLgA zfr9{Pfoes0U}#19pRxXHN&Fes;L?0xJM_`}@(`xEXm9xLT1H&_ZM#3T!e`dY_0aaUQE-g1fb+IyM{Xicvr^b7(TMc^55 z7Hie}zWeea`vRWW=NaVR{229w{02YcIX&tBx3B$SkWm;&=uSrnY7vq@{Nrzbbx3~( zv{^EilKPwZ{PzG_!~(>c*ctM#|Bj45eoWx%Im-W$^$X7b$F1K9-2VyT@7B@(t*!rP zz5i1gzuPLnD#KPwmi#CEt|I~TWy0Q>6dWIpur4rLQTgm6P5MWL`yU*C|HMlI*4a=Hk(RhM5G&5NWR z<;2!5J7QPfy$O&p2OW;S)^a5GbOD~i_9U+(7aJMG;x!dzCD5}AZATu11O4vCbPB1A z^2MOmzQM7g}onM*fWfdzi{K~PU>eRrEa`-ipe>cu`6E)fn;%{O34Y^=P2*@@42c+@G z1ne(ylg-O@IeAU&V&}Wl5$bnNxn{NOMJua%c&wLiwRnsYxCjqMefLcGk4a4n||!$A*9Bop~0~72645tl<)6_7JZ-YI$dfID(jLne1-ZuCG*z+ z5u+4??TDVe)a)gS!1i60y}M!JdLhT#rRKisdCvX$Ls%tC?ec9eof5Sx&GKrH_oV0h z6<(%W@3-L2Kg(sR6Jc(`#~KWcxNl(o6#|W_J_7ahuz4=f^Jw*3MQ2kp(xU|{ydQj5 zNrqn6TDNQsYg*@9ndj?%gTaeU&#r!b7TknXq&E{pF21h?GNVx#t$CCPkzY5(<8{dJ zBqKXhG}Op%G2W{KO=4dv9Svvjcs_Kp#3VC`Pru09Y&X7LU5aqK>q4U4Op3{BE>At6 zzh2Gft|{(0K;oJLSB|Fg&Y)V!g+gqqKDl5m3SEukyH~uTwPZfap0YTrUOV_KpPFnR z%I)1H7OP&7H?ZLHB-VsTXgSp}qF8m8(e@>yx$GhoaCIXaG+3PPvZyrp2*QEUrK;+T71$Ov?7i;5Y(sMkE(hqo* zgz}($nv1XF>~G8bQ*acs`T*CpYW_8)ppV*V-0x`)=JuJ-9{?)_??v;1h8#?u`qUpM zAzSqGk&|gxKU{WeIIiSOEN+|Wc&J-@gY2|eoDxV~M$}pm>v3>xg8tb z4QEQ-j?*7Y_5rt_q_0GR)#fzV%%`>5l(Xv!BJsEu+&=WBI}A44d2bx>8ocSk*$iZ# zSGb_yJr6q_U485PD6DnjZ9RsWUDbK1L+5zgH6gQavn%Q8{9(bF-tO)ou+mQ;>P2(o zEi&)?kLyq82XLn_-gzWyvENqYpK7%XZWy=0qkgBO<C;~I8{*sZTt_tfs_A*}oKuG#I<`~# zS|1`kxX!9;03JhJwQR)^pK5E%IM0NWhZFmj>mZ9~Q3NvJpew5a=LK!#{iq{Z;OVW` z-z;7Ei3{2&!`)F`bsp`V;O1(LF7QZs?|?hH*&NO*$V^;R9nP@k-)%*QW#Q7tr&2nP zM>O)iMM;UJbpICXR!}l4eY9Y!wh~tYl1;Mmurbp`N#XQd%{JqPKdgUAXvzB>p^kR9 zkSH4-{4MBk*qUVxdPgILNls5tx6(Pp95nXwajo_X7#DSybN^B_%M+fx&-UuE;#dOl zLI&LUfqJVa%VyN?3ZS^V-d}7;kUro>9n35+w3M{9HVHj2i|sC`#O|Fdj*yf{G{l=v zuXyG(v{@TmHh5yHU#GmG_DpEiW**>%ntSDWeQQ3yrgg%?H=K){#G|Cmx&d&^Gl;8s z$m6GZx=!MI)ZkC`++}y{3CMRH#3>l`dZU#5wEH}OUUbjeOT%64+c!J!TZMq-<=X~n z?khAYdftVm^TOw^SvqV~TB?_s-lt~g z5MJHhX1vZ+9x}dTs2c3mp0&*A%(oKfnoWlND@<~PRtJA(g!c}^Gd!-53FqY{Pr{+> zi5uU1E7Mz#%EI{nCFbZNV3mr#DLo#QfOQdm6iJ~&b~jE>+UMbG@4zaKB|b7JY7D9$th;o4z7W43~sZydO)R&VPaRM z==Dq+#&%jn+XQde!(jQLx>=mi!?oMconQq8PT3LT!@~tkqqV8K&|0L)-TsK_;rK;s zQjPf(TB&Eg^qG;TMjA)+>xet$3T4{M{0ek;XQ!4{MP#mlW33|uA)PrquYgule8RE7 zmEoz*x@I|lBewRb_vxdD2FgIPSMV%;@&ZOgORLBtVb~JHRauu`>fKA~-?kh9)#nZDxdT{@0PeS1sgNFC#9y_Fb z2$2BZS}q99r+PhJ-1bl1aE#Vi?pT-1<@VkYAM=>xJu}r0NyAm zj-4&6ySw?1C1c1Q3+Rk9?C*2YS*lGP{TKxON1)9inV#ZSS1v$Ov~-sYCvH0i5Ba3< z!|_{Tb#Z%F+n9Szq`VOJIy9}SbL1$)OI|uz1|GGOad6NbbNx~oD@8>w96be#?i9_| z8V06sj}4Dja$NPm$+Oe4NgQ+5A1=B8(8gD9mD--7owV$-E2R`atSAIhj%ZeP&ZoGR zk~usrph9ntv`j#EfX)F)ErKVJ_%ky}2$6{Y5*k~W+mw2(Y-9NDNP*J~!B-Jdk`iO> zIly;PQi!*B1wcRfn4O`qr*ncQ3mdUL#a3!Y;sN?uTIbu#GNDU7^+-%J$7YRCX{j@~ zHP6P@PQqr)vdO862Uld)eU>M=ughr+>O-6|xX=3^ zHzkG8L_J9a3m@+03zIL|=I>r{rxSk6cFGM*)S`ba6GMT=Uor*}aY`FC&mb6Qv}0kf zvlET%Irs?{Yq2H}C~B;2pO2-DuIl~u({l_SgJ8uPZpNc!ttO$*c98#$7Xkt#DBzrU z0p#ZdPB;1V`^hMHF}3DHQk-cP6qs?Mv=g{t)(u12kChp!(UhV@Gwdl1QMOC+K zI+SovTWJxN8FdH4)**GPtrX_LiI!z%IyMxN`y?bUXE=fgsA|GSEj%RueYk z<@$PY!sDDxnSW{e7gLWKEe@z)26&N<5<&u$lN%Ng8#2I;3U{gh3W#E;{$$*4{u zq57=2)7B>ypTg}T(IU-f)LI5{YcMs<*82|==RNYdtH>ULj0d$ns&lmgwVONUK4%ki z&$n+F?+BS3u-f*gu+LA2vB<8%Z1_vLkXd&ytpO>nTJ+Wqnh8#}2>%YrYw8yq2DGgM zNaut=E9}{eM`gn6rccYb%dmUvN0{bQ-X&3sk?>5icYEN%xpdpw8E>dW@)P?voof7P z$mN8_4{VrN*&paMvz*fIlKJiyP*c;ss}Zr%xhM3mpwxyxcCj>vRjS9gjT*11P$4E? zsZz*{0Je79V!v3Yphd;L+Hsq~gT-r5uiXXJIlTr2xuMJW2- zHG7|SutnRV{yU0-m4JK|^EUGl0^eR7l#SBVJOl6o`-8{biT+SuG7nQbpK91!@8G^iRchyl4(BzXn_ zCDY>>Q4d`4I>CnVb|0 z7uQbOY89eRAkV7vD3cE);zU^UwQyuqT9Af$)KIAQ3T&J*1IxeZVFu zYqmp9-R^_Ka1Q>(B>QFYR(4c%_My-Eg!EYOC)WXKR`aymS})+BcbRsj`ijeH(>q5U znQ<}&!07Rn_RMWk%RA}8vHGxKD{O|pkr!F3yGQ8Di)=N z?=$M=w_o;JUN}COScAG+%UqGSOhFpSHTh)P`KheR+uz;F8j_te-n~~AX?jyo-nCU_ z-AGS!S2&!mn(JK0Ubwlcx0z<&YNr6A*M(NgSnXvl=@s1Fh9}R7k!jB} z>8U{WmGQWww%wR}5-kTWAguZoyL;%e##zELThrYh-q7a;Qr@cL#MLJ6B-a+Nr_(zw z!%0=chH2A|vm-Z}Rj7XrKlo(+L^SS)gI%CrBO3*1mE%uS)MX%?XQxuikD_POS>tjR zKWaU<(n;2A=DgH;v)j~2nL|}b-FmE8 z>ID6w%OVbwgvmR;O{e;d)_&4W#f1wPhtaI3${B zM1?S3T%;bV1?bKiXXVz6c@E*fKN$V`U$+Rboqw66At=;30I5`*K22vIZ`Ormj#Vzc z@XAxYNn2(lH5aDX{4E-*m4`NqB<_*78G|C;$1U;q+1l<_twbJ1p6xdVgm21jYSLUi z#b!U4a=I>`N!<>S@=vjlo0O4Rz(tyjOtW9?eCw;8W}i@-MI%kOn5)o!y3^L0g}yVF znscTb&HGqfI{y?R9+RXTla7IPd95pSc$r!7f^Do-w*tedKd8l^;t&In813ZSEE$Dm`ELx@0ZEn8z z4N)vSC;M2?ESGPtDq4wj#9i{}w_ek>hHkmste_)2H}dEwJ;j+F_%0ow+}z(*e(7mB zKaF8{2;VQ6xFLqfZkPm4I5fLh;8z?vv>E)U4g%!zpqtb@$u{E_++D0SDa~Wj6Vtp^ zYMq!Pn{ZfJagB?xEc6s)A<`jDbV@Ovw|ytyj8u0ZH?-xfWB})VV@LF4?2ZVva4R-3 z9m{S3pP%EBcLZ$>-it2t#(#=kE4ZoT^VI3+TN|&Aopz>6 zl2IttDrfLK=G?BZZX-<}=CK69=~P9Q4w>oXl$M$g^Ni)$Z&h5S7Q@a{%n3dNreSdG zJU`@$B=@MW&Yv!ub0r}2@5ggYRKA;mqhG?ytG`SSz52iea%rl%!^&gQ(%&gC20No% zhHj_l4oe?4vds_0n((Dz|AD+;j&d1;&?UIN;L|>M9Yv}TN7k=zkiF*rcaFMIIS3MV zE^0A8Xq4-L7dgqBQZH^n3RBxcjvL(*7RW05dhY3j|85%3fMwXkC}sN*g%>YP5dKl(+s&kt}KJ=*hvDVZYmm zPVJsMVqkE(9}4~d@%HBNP`7RW_?1*7QbP7h2q9UsQ<7!ugRv&r_dUjvgve5MW8ZgT z?95QIGh>~}I!bnC?1Qm@DQP5_h1L=%>y zd}eC2Z$jDqe;Dikb@T+$nEg5~pR$fTCVgS}99=g<_s8O#R8dKkbFu(NF!LW=rN24c zr8(M$i=;U;VE?Z#{HtC1FK>L|18uVZw>|%Nk8&EnBB?rCqwoLU*6`nFph50m0piQ- zA%A-$`tSa+6EA110aQCXE0|fv&O8sm2MNw1U=OvA8p< zu5OdrrbR=kU#nDdv{NKH>R-&3!5h`Xd9%VlBJUsQG{}N{V=~Nw+?C}w{l9?~^t1f$3Uj2{Gt{}t>BI^i=a8vyDU2%ERvU$z& zl-VBxQa{$C0trN+MSEnKV4h%^V4E-vGO~AvLekC3D-b*ow|}72TcM-|j3S{iv@qC5PTrQo+dcqf z-u8&iJ|x$5QRdduW0Y%&TK2uZU=+J)rY!E$LIMtjui zaZ}=Jh1iD(UDtpnfBw4wKL~PKUh2P zs(P6+{vN~1(!y8MO67T3VfuZgB*CL)Pf;j6TaykIJ{6w9_+_!;ng{K3<3Uo*m{(8V z_u_rGz^7_FDGbzP^!$LHw#?G92M=x_#y*+G5U&Q}41Hiz3IvWxlp9ye<&OjwaCgk? z9cp`KO~cFl{vM%1y-IRFigDHZ!`|=F%;{URsk?mpBPA0O-aosq9rtyRt6&$&UlHoZ zGE1sB5dAL_XQ|$BtuC zUICGB)l2E<92~|?c!XDTz3ys!Ba!r|R;R!jmVF4Hy%P_FKQCr%LHpKCUt{dH{d-bv z(z>S8pi`(NNu{sVyJM$2hn&p8sB87Mmr1EKL(FyP0%x{Y1+2 zyoS0i2JY`Utelar-P{tSrT1w&Sj92(Lt#t&eL#a(0iwA^{nAMFC`vY3GM1}%K|EGu zIZ76i)$+Rhnfn5!f*IH7s$*q~L^0Krp)!|hqbAjE8E2oqwWtJ7tQUPS`TKSE)yyi- z+{HhK7BT*ZMt(hIiIE$qX35m}w$h!>-q>9Q#}=4AkYn>}GE;&}l{lxT{B&9&c=8?Y z8kybmd9D(}AHL%Lo@o$MZy$&)H!dEpFW0q_59c%kl~7!U#=kI2kcjR22%Bpz&s>^@ zeIDoC-GU-{4hC-%zF_J4CR$&WfCk23y9Uj$-R-}(tK>8&UY+y>Xw<(sy!LyP%NN#` zc*x!~*JxrzC!UfrlXt1rvl`ntMf23_XHo6ll|n1!(GzL--IA*hZ!fwf&>lpS$gY<1 z)GU2())n=v;IV_Oy=UpMu$DovXo#CXziqEyp-a5p@fZlgU47$Tu-4-xIr&-U?`c5# zS5#i3M@QhdCe-XCsI3Cj!@}_J@RD!7Pc(G>R-6vnzRDaoaiT%@x|l z#>N7m>mu?TLV*?Bb3*K@^}4p3Ym+sv{By+sN?T9(;e?8>cFoNi?;w9xZNKRzb%$S$ zrZs{p?zbjEROHFZ7!pxp;cGL6H?fC!v;bOkH3UFdUuDDDj(tJHHFIc5>Dek}{3lKd ztz5>veone|Ev?ZQZr?2 zX=N39s-mj%)Gkf73iPw~*x&QzUv$oYs4M6uoy*BrsnBNmku#epp)>n4AQrT)>)(I9 z2tIJx1xf@5uu7K@Os7h77rwmveC&aHpShgZK)iT*s_M<`FUzJGtcv8-8!vm|-&(9* zS$kwa>1UvPMiJDn~ z0nZcN6t36%=SZ(RHQ%lH2gxo;;&>`{{B8LX-|vPD_0p4|kINZy;?^JaKBS5WrO{qN zi`@o6O}`b|2hH49dTV1^B!Rwb;ckuZ zU5xE2N=M(%CscEN+BRK%*38mT{r5JtoEpV`0D^5KJ!|ufEt1arz{!9O7~rexKM~ehQQ{Vw5!N8BURPnAgzvS#4kfnDQs_9s90EA6Ba2#4=@a3$3mSplOS{weY zqP2ylDZZGt8ud|1&+NwywgS}z-&apT$=l!6IhM8p8w~rb1glfk_vF@b&EEB-rs|Cyj~g{LlY__>z7EQdw#2zKady}7^AHhOqeW8oRURhV@S{haAGicQ~R}W8fpBUOp+6Pzt z+Ro69w|3YsWcs1N;Kp03pPTBWNguqUBWjGVsa!R(+~|4R(gTs$;}CK;cKKlXo`<*h zaj$9J#s$Eu9m9N&yvl5vZx_VEEdE~3zEH_x3LsGHunN=thZBB1wUNEdm{O9Js;}&P znVy%}9=mEYt6i-3AWek*7ai$Qr`6slNkH?o^YrnI5Jz0!a84rk9$&BBLy_Z(()i(z zQgFr}ZXRQv7vQ;{GL=(O%#j3*PTMc*rvchkk>-UH6&7%R$n)02&&nJHIYBc}Y;ls4YQH5W&q^8kr=HAqn;@RRi; zU3<<3{;O}c%O>pX)X{k<+n%PojOF{&D&^%RSBaGgHqpyrI-J~H(vOKWzW;t8)uRxL z((!#YE^(@iGadSABr-Sg0_GQ(k~nrKFgZ}Gk)P}(FuWwDzf^w;H3rTAHP`!4>e`S_ zvps1O&v{bI2K}efaIZ`81LuAdyT9pSK_2RLoWR72X^mw~0{>L)tUF@PVx3S?zc`YD znz-uCyqqTBFPw=Qz4TuWttoW8`7vZ+hdfCmV9Kxh_P;*oqCoy{&_(87Ko?6==k)F4 z7`<>>?_+N)O5D;PzD3#7t?9;eDqY6zQ%2VeS_d43K`*0RW*8?{3Yo;B0!&Mc4qO!WT|^s`TBmiSt^CSlx|F!182V}8A;wai(^5?U0gHJj;Z;$9Fbnl2Or!=R9e^(TLcOH%idxRP`C_A1-z z(-XCO$t`{k)eyyW8nyHfu@%hQV;SYS>rNUhd1s{MpEx_Kp4>nvvg+R}{M)Xb5l?^q zlN$O9-nCYq`~Ax~i#l5He;m!9hfY26YeGBg zxo3s)pBw%4i=`p#L-x&J2n zx^KaJXD5!-d7IJn9(Pi`v@pKM($b%qmcXXvPSKf%?+O6jcKR_)^=KQUyzRz@R6bV? zFK>A38xp|Sysr)7`q-si|1DVSXzf9dyft_+8<+B^0_WPI@z|N4Gn+F_{$>{!2+Pbd4S0S%V?{Fg(pe) zBdSItul{!kZ<7D21;EVpXi|L9WGpchPwrSgpp+%<%^CJtFEDpFK6et9-p z$5$_O07F;q=DR9|2&0jPKS- z*Q~)hbHz(qljk#c`qt~;UECm|M{=dJyR_r%#2Q<58lzNjaGm@R)O{D9-c`j)e2kt< zURYnbSAp$ zxc|df|9X<B7V?FUhW#)-rw4E25a9;_PZa{!u&7)?nbmG88WS*Xk2i!^B+k<-| zi>{cd-j5#JkhaB-AC(4_C?SXtoK?Pucg;X1g8q8VMzrk=>PuBO3SWW!UamxDn^2ph z$m?Y)G6ia+Zm+a$dFl5NgyZk?Yj~d=UEB7KJ-;v^H^2L)HO`~YfGlD5%I_=t2TA%J zYIa#ITs-`*4t%GehIr4*N3sJ0Ys+jnA5KI-NYy>O!hIHm0Z5iHvPpyHP`|F;2A$_kQ1$qqusE) zb5svE_qE3l3{zKjhER952HN-GAKX~CyZ3hQ$$4`6Fb?;1N;V$xQ+Ge#3 zE9ZE0kpiQt0~{nJo?1 zwDaDSJMJbKPrtuSJv2&KPeI>3*RG__&d4I}QG|Z)2Zt!;kA*uQ1ef_m``LzKfV|LY zejzt)Z7Ha^h_1dJbXP6;Ff8(Beoo63C26a*F-LTlZM zKEh?YVVesyPNv=S*|JE+hb^lP>}gE-FFP}b&Qk&Hx*w<8I6PL0Ze>0-)wLKKYJIXD z9cf%`;lR^CITX3M7sa6@FtHmDn=89Vm>A1j;R8-sWq?*6J!69u4uw1l@)tq&CgNw% zTv*q8lnjrab{rt8R-CoINpEX=vk2lWy2|n|^}C}TI;(aMDG69d5#-_}HhTj0DYE(N z)OO29RP)`f*{fnR69Jt^<(?qStLQc0ye~$(b@<%2bisJqUch@YjC%7so7OI$hx?O^ z*{7T!U5n8Q*`w%I)>Cj{am7=h$mBH67>}=M`M3c4zzTouV$s>M$SdZ6a@u|oj+1?o zi{RCMI@msBv$FqfbZE)H@@kJL&Qqw*=x6hypVCv&P2p;POwxG?x(@K>ewTt=6!V|0 zonNNWAUjF6EFbQpl_vLD_L}AxEThLZ19`CX{!hcKwhD>77xs$o-BCZ8}UYBSxQO|V_17K&Lt9PnJ*Lv z%hb~>F)A?0^;42Fwx9MrcG&X+)_&_@mbB&JYgR-j{hU0fJ;r+ibWa3#=7?PUQd{py zc;B=&KWT;M6CKkJFsM4O1|-mGvd}iLt}6qi|ox z&0Is{?`t*nol`xB;~JH~wz;3MQC*XYu7&&L{(-M5FZta~SXq2uaBqX}#)mJ=PbBs7 zw*q0xsx1R7;8mmtLHxA27gSRE9XRb5=93Ld&7~ZQ-h|x4fDwY26MP)QK{P?cXHNj= z>r#saziL!4byZeuB4Dga2IWw?_fcydv>EX6K!}!sNBRk-UpazW#<=&Dc-jv1@N(=m&qF0T+bycP}st z<>ODZF%k_bLJQ?riZ)lu%$7@}G>j&glL{*Hb)3=hN}Q&luTHSmPT#L6LzHOs;FZLKC{esTN0zXDY$GAWkK@Ezgrs~<6jDb!!M@HsyPKe*{I6f;H|1%Fv)GS-wdBYNB8 zd;NOl!DI%ZyedPkB|36*qa!SBeTkqPO{m=p2XVd=RHIG<8mZ>91~`QGCQY$%k|9RY z5_>IuU0gkoJ=w>%P2RcW3~l>8C3^#X2*SmVi(x8vqp~q#Ynv#P5MA~{bOv?_FWy|v zxg)agNOycw+N*TkcMoFi(3!SDTvova*n=+878L1Kx31*z zq)uvb4-cSm1Ho>G6Kt1Bb+7j{rns+<;S@rB*3d3lD zI_#-6B}AU^9yf-~fa|PP-)_Fy>Rfb4uL8W;tC}&0FR2F5k*-w5u=nA|Aft+z# zaj?dC0ka! zl3oS(%ivL=E4|w%`20;oq*vKROQCaI35Khb!~HCQ=@qatxr!!AgJD*W0Y@`zTTEFn2j_s|-w0?kOb z=O1&~b`W(2Yp7-#W_em2Rt~3Ns&OH*-WwUJv>H>TmoXmZ%5%Hj>2W#T^v2PiQ#roQ zj}+qyS0Jj$;Xlx#(x>}UlM1Ve_Nv?BU1gD!h7Y?=nF~@Fy0HhFck$OF%cG2TRxh!k z44qSKIqFv`hSh4BSqHrc6OZ)b1bBehAD$Uih6FB0hqOG`+d5gq$XM$kRwb6dxm#!w z2=0947T|%Cu6MA8W$yWI_HTQyM#YJ^xx6eW>TA5Omy}9dq za?Kst0>bN+X%A2;p2Lj|HfLs$*Q=wK+M^5~1cu|&Q>`*!O!28N-{_lcGOnDmr2)Add-tOfe1A0Z zL2$HL?V0RJ)vU7!_{^z=Y$sXnXQthrL0r-A zKnEgxAmh5tSf>cw?3L=A^X`Supmk+U^W}AjsdwRmzQK?bc)-o=u`r_fzF`AhVU)ng zlr4wXYZaAc;Q>+kYtSU0H%cpLN3FPnj%M(q_685y6tif0s>4L`x7(zj^Qd^WU9|!< zhqxu29Uv%>mNch>xy7z2pnF5WsKIgWFlz_s>kTg5TJvhsg$-p~Rku*OT02r1xF@^L zu@xK9yYsXEy5zTex24T=SYH{36(ToC$$&DIyOi`cY3yW3{(H~4=+w?LPJIr(4&W9c zW}QvBs{9HdoqzAC_!vsAyOUPS-?6J95@6DddMxM`$Y9jgFRw)0eALJU2l@v_-!F{y274BOJ5T~zfe^m}S%IlNiQ-}#nF zY>9hyX{6`c(x`2u*3KU!UXC0QbAnVLPbPAlO{C?QqcaUS7BvRTl&I`iOx{ZeNz_)Z zb$0%sc>JiZ?M*YZwchY zd1UmdaaJLl<4Hvx^x_)X82uyOyGJx&rk7nTAVI~nqu^#Wr zmIUFJQhivExk|H|wGZaPI^*2>P1W>+fL^}zicEFxx~^`Z5N;#@(>yQ<+gvzNZ$CCn>;Idupd?&2;iGI+%K?ohH(wWdFP$dBz&r9lXS3AJBv zG7=z@pTi9mfsX1|>WZ63WH2V?8)0{&PZKX6dkxSw`M+`2eT!l~VW0q5rz<0Qh2=fj zYb3ovKSe{4C0_n9?=_$9k7z{>Z7{TF4)BeoNfzGgf}8kQk*{157Cs1&Ui0@};|o-t ztQ6QGtq`oM7@9E1Ly;TtSa+&e; zAv-b0OV+&!zKx%Qg@Jd6tiLA~?G)~a)oO%id{kiT(=xeuhUi=3fzdZ;NR#Ge zBR^U5xh_%Y*2WrJlYEN^b~b<8@?C?gcDwfoeWDr$n7r7`NQCaYu+y;H}D=vP|}7J45YeHU&k?)$m7S4pz&NPVUQ}a0&L7 zWW9RF^j#0jZSxOXiGwjaaDBwlWKoSPNM(@EJS`1uv^2Yev1URh3n(vHPdZ)!I4jsm z?o0CEA8P|zu zzQUiyXD~on^p}${U+X0xv>WezFg{9I6XsoTTs2!>x=+?H%-SR%rPDWX+q4-z%qBdv5wvzN8-dWO6T6NaYXF?w zY^!24w?eq4$i=)C&~ciQ1FNvmOkJbvMl<599g;7KNHn#-Jr{i|-ZvE- zqqBo?OY72M!~w+jRDs4%i~hmd5x0azC9v7+)f@KmVg82a4F^I?@TT*=*M+-TlLtOm zN$8=}zx6wK$TkQcxnC>TS?H7i>cfla_3saT;R+}~uQ`pb25b0b`vx8J@(?njS+H~k z)dAt0)y3NQM~ULhvb)y+)z+>Qaa<)jDTffyjL4Me;8oUF<5q9e!B z$a!`K$yCni2M($f0t)+iQ-d&0ioJqlPtxhvLxz|bFmYI@P9o!(n zsfrk%W0A0qG9wI>R$)??$nIUa|KOBKe-h`ve*COCy}n(20&d-pKn10%pR%HZ1Q{Kn z19oHI>l?mHpxMajWuiRmveYmxmBEb3Uu(gs((g<9BVB3U-+3|s;jpRnB86l3UwJ>5 zzZNYagOyx{-OMIlP;l0_Ek^N{P^|9kB;a@!@t;L;Ay(u*vVR|nhQJF=1z^C!FR^W( zAoYD_&{ejF9-m-r)pPGG$s4^|xU`?H+@Xo78fLj!17aI(jJHHNIZPd9crR26N6D~j zoWBgnF^nq;fPqxD3~5tt)`hMN?A=#aTud{+#8Hd2uSS*zq&UIN#|4cVmxDF#LeuOg zjUtolro%V%=iGMY#&!D9*DFolqxj8!p7h?oH}sQN)l=R)(b0i6R_Bl%;DgJo$r~0@ z)Ky(Km+@8*+pb&1o;v}7n6EvFy3sqQbU_)6^RBdDe!7PLP)((@qj zX|z98oH#@$XwLhYA=A}#v3C$U6;aoV%O|#e#2MBg>bqZ7bY8i79CEN(cdO}$n}-K6)|-G5z!}wi55Ac2 z($aQSGF57Pq|>f}{KGq5sXit?{YpwUk>c)tJ)Pr3XPJh(>9W05JN97#3eo?HUqd2)fZ==seCaMtn=UY05v6YxZiO-9JpKBj$LgS^P`KqqafYceHWSdj zcJO9NrPr#o?5;pV2^E_pXZHK1$OaoH$I<+Q>yW{UPoE_-RslwOOJ=O5*sI+hnd;h3 zpYNsn>p@Hn^;kUy;*jI5kF^B!m+j*gp>;1B-#pGrMEV#m%DRJ}QyV@f)->o9*P%~U z?(3bdgm^-vokJFm_IWImt($7IwKZm%yS=($HAMrnOxEWoW%U3LW_|K|MS@%s2WBE< zZ3&c$*!kP5Jm`tObvpm;qbyO6&o^;{uhuj`9ZKNF?&6(fE4yvYH=$$glH|+YU&QU*8 z@+Bi8Scs1)06WgvJwS6^t1ch`QP*nh)g@vj;Swgt!dAWfg#r@u}*s*)SM zWoacUWQI7rJdlx4mWgadRsA$i+fpr98j4*7>cdRud6P=NTzjH#PV!)`bjvqO-?z_ z6oJd#L*mw_hb+#dW`-3$R(8NuN(HcA51q7~)yvfxJ`)|*v|?}P)J0Y$zJxx{E`UIB z)-50qxYr#!tm3f>JXp6gZ0@pCfODpDuq;;A%JI}%sm8fQT(A8e$P3%GTG`q@zfiiJ zf%_>q6M`%BI_D+-qiu8Y=>;VjG*@(=`t`2mWQ-&JrgQ~sb4_XIsan*{M|uAFwR4=z z-`unOEscuP=j&GqZcvi0ggLN3!APF!Y}n+5%Im-jU8CzcRcAQWL|`y49Sbr)5~&?c zy(Nw@*RCi~Yc3*bo!Rlil4{uKxTXDs0Qyh2>)tMnQ6({J^ zfDkQ(k3l+d)4JuMo$U{AyJPv5r`+e0ud0&=U!3d{Rcsz6JIg;8e@;uJac&MS zgn6$elJMlr7Lx5S24Ro6O)Hm0DbGZziFF*(XbPD%FpOw{v4=Q;PE}`-zMSYtG*>e| zB^>lan0PZvFXEXXcp6Gnx)v8x8knPaRkRbvP>GI)1oZit{L4ZjzHbEvxk1+Hj$h{O zO4aU8(ZTjQWr$~Q3WPLY7LDujc(1Va)FvOeueRE)x*$1USJL7=!w6!jtT~dD)tU9Ba2P~edcFp`ed+O|RKjPb)U>c@ zf0}n5C5_OT?)->T{!!?%Jd_yBt`4~hj^jpy9 zIn@Z5(4Jyh8+;ITvz{g;-NmAq7o&k_Y7Ug$I4CndtY%axxIoHHAYR`#PjT|$TfY=# z^v<*WhaUS-AUKu%sfTC7XtcG|-c85mwYwdPWQ-0aWrGru(1V#rE&iD8AKJ_qF@Ul_ zne*WKT-xo0nJ)v8Nk~Z&Y$zq019}3b-qq!A4WkE78rZ15w?9h^uSgI7_>0Ewr?~r- zw<=Deif|s2X1kE|BiB7XEhGQvivlg(0&k(@n_1>-{$R}Mvw>>_+Cr_xm@U(CqB@>2 zTePOLe`^t1kiD2@SqOqVlzU@#9A6GbdRdWwwdXR*cF8FBo3ZePW{-K_+!)t{ngF7` zE*f8Prf^rMb(3bpv2#8qC4OEN<@n)!|pLu{rd_pGmJ&&&LAYo6V~maPX!KpYR9fUY87 zpNj|TQKI5@H1tprjVZZfmeT1Uf8d4DLI;Wl-ogBIw!M&>5Eq+M*5bEK#iJWws^0Zx zR^ox)F$-YmD=uo6RnKlH#|;-y(HTST8_T}c0{9_W(ek-gebhj-} zs+rGm{cEhP(J>jkZlO4=#;YfQ=+E)_n z5*ChLW%N3wm#wuo@1PS@YwJXh?z?)K_k=*aOoFTgO5HL`MEd*_VUl_}r$|}}_h%)B zvY6bfGdyT*8ny8kbW6s~P-CY8u{-AN>xP7`IvHWdno8oVR(J3sF5##MpBSE1 zESsIjj{wJ4)`d^a9w|qQYX#P+Pf5-QGB$EsEsQ2?dyZtfd+zQg*}9zG?GW?NIt6KC zuc`}apsxl#;CH*`Xnb(GHceryzkA%ZSsy`?BmewvQOXC#hq>A+Oomzj-gH%76VQO& zgeotM}}m=G1$iyb;pg314oTMxhM#358A|9TFnL@N=5c>U#v46xB}aJ zf%67)4EQ>a?ZYZJ@jpHW(znEM{YA7=l9rqRK$ML6XHZ9fknHk5CsFXr7HW>qT)a$E zQiR!mOCdZAGtY6ZrQyx{N))!NC3zRH>)hV+_5smmWGR8)mu^t9N$LeZoHEM3Ai7{S z;W;mcojqZ{jvN%waTCVC+R&Z(?jjwu@7X(W=th5j{Dmft9ZfSDLFnkE>=_1@V{p_` z*2n-|$-zw4eVY48DXfPAKiGA431OXfTY2L%2|ZhM$+z+@oB#~ss0tA!=3>Agcv}Q-eu{s{E~%QDv@k&;c{B-N@ks3q2u!kSuD2VjlbV-W zn!GWn?^}M->{Qp#U+(f5)9OlbyEkx7i9ZWZI7+N+!r5tZS*Zm>e;n&^^ucH2 zXDRL3?e?O>cKOGC5QdFb_OL$ZS$POA!?$Hm8|`YDM+Sst2#=;FtCed zVTgPDvV3(kS*_}hZlowLZ=)ORG}4aU+aOh}^vl zPo5r3#MrYiKYMY<<02rVz=5}uXXD#$LY;xU)C{}4^-ev#noehUoxfK4{F+fw6VD#8 zu)w6k^E-DMV+v$Z#v-x7EK z7HIldfXjBlyUzdvHIy`K#7aA^d*%iQpxRU2b<1$6oSeOu(_%xXu0=#`x5S6r&7Bra4=9yjl9wT(DAE_;h(k{Yxc8+PR9T9JLRmlE3}FFn z{O*1Cs60eeLh>ui@?_=vw1b3JJhmj^gh7APVD$$JC2I>UX;PjRO+VhFs1mtZ=d32Umjht!ctgVOrlEHN%R zYLh~GQjCP|iZM+;3=F_pEcE|dpvuKv-xnAAx^gMZH8dn71ThmES2`uU`XD-@;$M(e zs+cyf0T%DnL<#z&_vr3oZ{E^$UBiGjG|ZwBZc?v?9N2X%O%zZdFh)08>oo4fx(dQ*zS0Qqlz8m73m}y}qdEv0yMir9Gw>dxE?@ zEi+T2d5jO zJ1o1>U$tQ;1g4s{#x~Pfr$D==;Q{m{c6|Yi3%kC^#)HTk!NZu)x@z+}HGY z%gjMl>xj_`PY9^L80i_!U~g&WBNBi+4rFaVGHt}bda?l1TV=pF-mX@{{ z1hpdG4DOy$K4gR*lO|bZmhiaul7<5%(9{3%!-oemX{c0<;sb-$*eV`okIZt9qSc5k zo<4jHaBSRTd2Pg${{b>!T^aq;p;8AVv612F$b!1bE5XxjT}k8g2+ZOv5os3V(-(Ud zJ)fma5g&MvElH-{ds9UDyf#hRHsz7z^4FgTl^L@<6S*q zD;twaU+*=#+m#+G2u}DZWOwYOuRndLnR-5Up_M&7sm|mb{Pbfn9St4P#!fRTS zb_Ht^rTNBZ(OA|e+xIe8rB&Vc8sk$-mEFuF=~Jy|1)S5d>(yk3*Hv^Ev0cSWCERZQ z6pmW1jbARmEj?+r8)!1_GxZ|I$@S@}mTc2Y#O?N&zXT+$%o2(t$eFVz6DO}7VZ|_( z>7~0SdU!Pvuo5prSnWVD`PM!PZcxbLIftv)^aD@swcoaL zJVhO3a!TT!6c$@N|784*M`U0E{^P;`W~qWjR&IQHwF(NMiuENE)($%6d^hH9AP8nY zdwRX4=}yd9uyaxZ{655>0?yfQi|IqLm#kOf6zq2iuiLAPco(K~)1;7zZk(CX_HTC_^CvTx&aRs3I9y zVUAxGNWOq<*`yU%uQ;x{vgy;-AF#H924V%5KZ4w7=^Tc!TW+-XQwtR{P9@D9$p=pO z&gmJS&4bgFK6f(K|*=rf`UX((8-5jmk_ymlJMhBn_i9K8lQ^i;u+R-x!q)2cE(NL4pJ03EY3MRdLXU3^_a?~(MO?qckVnQg|4Z7~rE^&F= zpZC765?y9~F?x5~^e^1|M-YUlct9ephTrS7K#iJslI=A#Fkc#9>Ry*rJDgp?+q)fq zbBv!1?7{#7j**A=rY#U+In`}3)H2E$BnKaw`&8Y zIUO;;JNWt!KO{W|m8XZ}QPRMw-J1z|P43OTqY9U(m^Ib>a$c-dRpuT(5;{1%c28go z`;dl&{#yRG zX^@uIM~H}hK|_Q1;`lJMq7+PudgQUB+098z4^KNFCnui+ynr3VLy+gT|3Au5h?%($ z_p`I$Ppy-D4Q5}=PWk+1fz61qB^|6WKAQF)6VphC&puD>5^7iS z^739)i;D>oyM}x_@2EENsKVrpmCRPw1Ozxs#VVCY%eH9SmsmcQ`DPs5=;;xk0XB!% zV@J8Y#fi}3NIE{lB{&%CF~fcnp{jfQBuvf3XGVE=uX5*T(r2tvBkJ(lY~yGQZ~0jz z_1{pbutCu9@Nm|;W;;V!ZOF=I7h7d=aQ5F^67e9k|8>e6O zk%AT{Sc#J%;3apK`avsJdcl&|1}_9B5ww<{FKc_C#D=a*l_1l50M8zN|C{ZAe0p6wW(&Al>XgK9 zVrQ7{OZn@*g^Ncnki$Xso*ciHz}8|ulaX>7dB5kjobZ(=={l^x14 z*kVo@HpC1dVUfHmS=hYRK3|(rS9?8;mJ~f!M&hl4^jJ(RmGnNIy%I_|A+XHsq03Ab z0b*~z!jCP@udpk)rmGJn=wyuAU%f(+>o-k5ezbS_;6{G+GkD$go@uuzZ9 zWIHIQ`*tfs^}@()rvF3PmB&N5w*OO+N|b~m%c-OY6+?C^lzo?B5Lw5*?^~9#R+8+p zGsZqM2163czRZm5TecYt#@NUFruY55?>Ti&zt8#oH;>2XdG6<4uKW64*Z2NjKk<+L z?lQFQ+;stZzKP2o&U4mLvhf8sK192y6Om%kMgTCjOQPo)-5IQXLncpcPljgSC#hAe zprx`vOR1PR@f96l6+Vg*Xkl?U0BTB;5kQiDR+4wXM(X@w{X^)OR6bl?MZeq>mDJx_ zy`GOQraYDr3rK3~mFp5{SqV}%9IG+DuPM=UHlUm~I2a*&<0E*#(9I~g)Cj+nBvC?% zLNinc7dpXPcf3l?3JlFmODU{xigovTJyvPia0jvRtCgRYzBw68S&!G&ALW7eoGJSF zDoUgYDvaAmQ|WTIgBZ*s8_;JnV~k^&|FRwajXh`3&W5}4Gq`HRexYi{Tynmb%UVI# zJRY>52NGR7>WN!CWm-ko0-^+qcLINRqRIj>cr_YRw&A9}R~}^R4?Xc)TCY@brE|>i z94==O4^Ev_F^{s;X@yK+L?DdHn$ug_X*R>UHeLxtubN$yGGIBgbpr3nAv@GG;iH|X zNrsvF?I5BlGe&Xm8oT@{Yga#}nXQ+!GAtu6adGgj>9w;U0M*kNmddNf3w5R zpynw9%0NMyS@7ML%+98p_3I1Uf7%t^vx=yDj!!Lq&t`K&u%G=ExQqJ$Tl$*_=P{h7B7;|Ml$k-%Pg?JX##z0a>o{_?2sCHO{63YFW7FZY(U>Bz(P#FPZH| zQgkb+)a!7~q&g1S-6|>4jqZvf*#JC~Z)%pbW}OQLxHO3?@m*cnq5J`abJ2 zSxFC`HXnDD^XNh$FbSsZ3uY2mm+Wk4->^ySw5y|zqC+r+!;@iDT_*QgS>1#`V9vAp-c6W>_!>W-M|}a9J?ib+2sV-VH|T1Yd8` z(A50A)u^25)GO;;5sC6kP?BNw!_=D^PD143SK0J>{cOS*+u6yJ65Abd{T z1ztxIHkXOVaU*HY7~FQ|AYs+_cIj_lvV%VVYT5kcRX7~&cC>qaLiAK9j;2|?cDC#| ziqn2)3i>UMcSF(T(S88i`odW5(h&uhJHIPY0!OI?+2Y}ttkV~17A`95)pN0ndxu`z z0th72UTQ33ERvqe^c=?TUEJFbpQ2J_`-`^fmK)hb*Y%v^#a%ZrXBMIRO5s#?E338& z1-#jg_uso?pE$B7=eQyClr=wQ)mLG*N4>;4Mh29rK;<1U6c_b4lnTP*5U|lx#Hq+y!jE^!MyaOip6{(HW+m)IZy`?zZ#`g+7Nsb z9UOBxX`=XnGjKFN)zYMAykqm`4VyCWQlk>2I~$J3sV%v%0rnt8$c#06xz;TwoB{7j zSiZqirE2Bs;<2%lwFoCbE2os~psq+3R)i2-rV$tnl^feN&X?Mc@3+zoD(4f?O_y1@C z*qD}7OCcLSUQ*0jBIR4Zs52-a8bE8D2RHbSlaZ`JkMm-QV**IUnxUj^nerp}u%&F$+H019KN74%K?^4ns%719 zOy;fDebea;=u|_A!zNIl%peB)q-LUZeSfFDRMV8Ja*b;fz)H~%pU+mam`HfzyUS1q z4`%b8K0%_8w3Y(*PeqeOJ!=Taw=B@Uz}ah3h>;caHhXt1fjz(0kRo8*^l;E@BKvC* z;i+SV|H_VPpup#qU0|>DX2^Vl84s9acrw0GA(;dquReYsm098=H8ExM^5;bM-@830 z!oRB#*3csvv_3G?43YBmRz^tABF+3>^hoD=_dSHJXmQM{xWorah0R-7ZL-TMdYdes zbW7ZFI6xy;o__uqUk8f*>z{B5WKF*Kf4m~5cgZ*1Lq zYa#jG14Hs^Pf!O+Zqp!TB6{`HC#j%02DJNmK|rr{s#rb2(eyA!iD6HLI1%`8yfnLb zYr%FInSc-4W-Xpwy|7CEPN$f4!ZTt!Q|%#!JUfX2H|@bRfaDy3Th88@*0OI4Yo|e; z@L?gWWJlxvLy^P191+e{Io3({v>x16X^%JEpb=@r6JO{mvS-&7&j744&s?SW(-P%8 zOUu^$BsZH|hHPgzGN+J7Wh~(#AhW%2E)<&Ow0BR^kg7A~5t5h%aDS*1MciM!X=6Th z1bQ&)(0%gjTL6M_o~`5kGCrR@5F-k8pEN=8Yx0ViVrv^$(j^>qG<1b!@PSQ|WZb=c zA9go~zQE*Ep1a$m`MF;EPvK%fN$@-3ure>7z+_iHajY|V1gugQMi4t}VWF|n7o2!m zc#)a7`K_4zW{-S_@OZ4-?cRTI*-z%|r%U^*AFxFLi`;=})-{^uj5nz{g2wbL+`$fs zREbn+DH~8BhtnnKi&r056uj+)AfFiD684c8g!)Ew-G$mA&Th^bKc4ge5yKWr3$`Li{ly< z-5qKXT|fb>86+uJNgSKg9Ts-9{Y4f;|$;<`PSoORwwGrjEtCqx?ew4f8 z105S?^LYs%BwvOG3FDijnC$QFA{M?Lz=Q0l?HCITYId7E==KS84moKl)h1pm1EEks z2N8`aLBPBc_Dj0gam;v><+;@_X?hlf&@GN0kM$BO;Kj4QUC?`e`o~!6-?`Y||Hh+6 z-RVDu=X`y|e0TmGd=KBHthS~X&GqiEs0_J!917aD>I-4VtGHyo_(b}Qg&D^7StZB! zB^jO`R3!Ts>!!-p0Vrk(inKuuIyJX-Xu3!Ka(sznBikR zp<||{r&s0YdEzEh0Ot_#sk7F*t%ni3my@nCyQawHd zbRR&oKb&(82i4@D0P$)$4ny9JE4C~5cf67bDWhiM5H$f~CBQR=?UilMfr8OnWbgIC zR6o)#?px=zpQJ?pgSCE+{h(7q1UugMjO6`JgVUR`kr{aE7`5lqGYG6*RJR!wkIO1D zO6b-a`7)j{)G4?3nAy2Wb$^Rsm{7AS=`xkwXu@3){x~BZw+5KME`V**oE*$5=*D(@ z5Y%*R`C1L*@yJdD;%mhkxk;c&mJxf}tK$mVWw&6qFrwfIR;@no;YQ0+u#~<4M4g)~ z<6TU!rY&anOSfMARvg&w)mZ26wM0~zH&oE|OhoOwQ^{@(^Y2373PY4EC6J_6MnI)g zH2$`lCgo6sAU*nSRn$GKXzqTWrVd4Vo@_Oia*r|z}JynWOK!2 zdIou_9dQ-}P~t7f@yvNweqwM?xmu&DO~YPoj}yUf`|?cPVorZzw@tcOP?Z|dTF%K} zm!758ju7$}CeqIx`foS%Z02tQA0rkX6d&g?r){C?wVhaasIs-(UkH(PFMuXZU7K)4 zP^-e_F7$4GDs30t$(e#);P`N!pYtP}(uKu{s}De#$FtJfmT=SeJ+Qm?0d5v^3NAg7 z0!EeKEU1my!*s#H#Ib7Kt-d@r%^)iq|JkG@V*P^Cu&Mavd$)tE;y)?AV3h-aT8>-e z&y<&KLf=?N4lL!o>To;rMRwUm+2~NWmX|{dxji|QJfXiLX}f&SL;fkwd_Q~v&GmV#9+eUyVHJmyEyOWj-y~|ae#c)-owZZsLW9t8n2>Pi^4I+z?W~0+NAQ_fD~CaVNv8V0|QXE(Z_P9 zG)A1&%mNnk)E`ZL;`O-O0?&G=*?R4)P!FgV7N5~nXxYmKJW!IMbHfZCe4JkN?05n9 z{#e39tvwbH>~TIAr50Sf#5HFy^3KSPKnQjVDoy%kJuY(Z(dxAUVHA*04shEXfK=g_ z{YMcU>i2%%02Qu2y(Dx5?5~So{Mw8fvY_Rp7PBy>fYvLC)iblw&`GWAh?og<_-LW+ zq%38wThhw|MzVbLh!)BjH_SV-mf`H)kykC;Ps?)aV5_6L!5C!UYY@n#qy=1GpxuCT zVeX5Mf2|I~KC33F9#qStG+E=Vx7e~QxXFwHBpZmN7pTrJIM5?Vi^U~a&1m^mI9 z|H{Anu0P$A0^_2S$F2sEa_Knfx0D{_s&f^ulWi}pvp|Sie1j?@bE^_`j%Y^yD_8xhAErp9Pn}WrsnvtIH6;1Y}H@M(lQ=#h_dBwdld1}=# z8w9;GMyg<({$8s^+ty&>VC3%6>5fyI1ctJlicoMG8w$}TZ2i*o*g?Dct2s_ zk=+Z0D<0N6r;7cE^y4ORZuOZ3Pq#Z9ts=6PlJv8{>j!Lrg<>00*Fh@~`FePwFQ9s{^GiE{(6UrGAOm-^M^6?vMY<;_gYKD(G948BGeLs$qTtvwsu z9Kloi-a?HbGMV$;X;P!L9*buI)NV*aIJ|je4+HGYYLS%?kt0SKH;p22S z=cOnZxXde+PDwMHZI^L(*6XIlQHSh@URmy3J83}@!KEgGpX@#d_To1+C$OsYlS5*y zCB{nJAnA%G$&?kN7=L9P8?zaa(P^IB4D%8>RC_GU=VtHrMvd+lNt-@- zD=$|^4M|eZ8PSaa%7M*_u&hV z4D=VaHMSu^WC6yu0{hy-! zf4J8?^3+iGZ)b(hWPRA@zB$-gj(Xo2MOGnK_qYYwkNUqDK1a%wJJ7bWnu9swD$vgP zZ(;a$xcy^&1{pcm^g7w(+?cvgcVm=l@Fl++dN7n3Y{9H!Qx@s>P6;ukSCass+bcAJ z@9uo9A22MOI0onsIGRw~<=$SP1UsTf2L$2jK@? z-|ts6zjhkfJ4{EcKtxJVY*}u=IirPerOnmrwPKMmZSGPDXyZYKy za$g*QbJ*5jjwtq~1%uSb6A5D?Z+xq)sox^-`Sj}iNTcv9AD(b;>B#wPI};!{1{5U4ifq|$mF zi_eZ`Fg8z$(BGkHSo}1>yZVd0ryDg*kj~gMG)}bZ$mXPEe7Id$Nf*g$pFQ{s=0x;h2aUdN|A&xF!yXb>@{wfz7ui z`0C;Bqr|koND83ercWplMc0SemayrHz^2?VS#_iKOhG>Zo7Y0@lu|^2aHaaTnbhN8 zAJ2$rXi@puC`-*(vOd#C#=kLyxwDK&2Ul4i45E7N<*9n@S-75)HbHVr{)CpX@{JI~ z>!sV4`&Ii4AM#I;cZkQbrm(IGE2sHV&ol4j%WCn*m)zi6uJ0T4pju+F4(z8tnBZ_;rn!r zjKv zCZjPUqvfQ7GFBs5tCC98a)&1xF+q`{rZ7C_kxg2&Z+Noyu-xA#DvAWi!Yc`QdVzrPTBlPkvRpiRv%t2KuK~K%~9n<`4=Yxj4##PG0r%-EYvq6&VR-fQdB+zrS6^q z6vu}G{P-{BBojF6qS?G|n&r4#H4E4$xM#2KwtFCNEE4M%)W`*SrGhD^^Mm({=PWg4 z7MMW1w0`?`2eq-S4t(bid7TdBhCF3HVQaxN9z`lc83z+m3pslJ9>e?u8C~@LOK;FW zRZ|twtz=-7dQ@E@JIUspRsCiXA15xr=}d|z#Uv`Xuhf14ITibhxYtjS`b%6?;7**`a~Y>IL?JB7{t?bWM%K^E*T2p<>;x!MgWN0v9x*b##)s zR8FNr@2ANb6-l-CV(YT~pZ?T&zq%xSuggK^7(8|~PKU>P;&k^|KxCblq`_^dF_?nw zCGA)W+q>tcGdwFR{veWAJ}AO@$Fs%i7`j@SkGIAXdYrFXaW!Ewu&})GaWTToS6#q+ zsD=*r55=ls-^-D0Mb?DKC!W7f4Wcb{M;$xj*gcru?!)H8{40O%2QZmEeM;21_P*u+ zRe0*B3Htp~PmucA7^OFV>w*7hX#e;Z+Yi)?9$+e}rSBg#?LUtxp@whE?60W&Y6$*z zPKcUQCp-IE%M;tbz5T0a=~HE;4Pi{Y|E~tJS5Pr0!_M?A(I2|@Kkfg;vqDR#j3mg& z^K<{N2L6YbaDn}w;o*Oeojiux^ZJet{-I0w@0N!izeyeBV?lRM|175Vf7uwT(GwmML;?a?Ek3H zljlO2U-ZvR(LYubRU@l}W@j|2B)m4^hd#R$@tsCwaCWTlnvY;z{`n_|EB#cG@ahvx zB@XEL*wM%l=;;2d1@N!Q==q&G;aU91_=l+}&&*T-zYjAAt3LX*goEO>_!4%bgwjuC zguz59$L(QuFqsnX@dIz8x%_;$9Z#0`@7{GJLj?eyM-!fZzM#0_{5j}mGdu{P9&VXu zAx|$qeeS1D`|st{!;@>^!z;X+O+Pl^80+Kp6@>+_BEU&%Bc`Rf1%4~@CC>MN1sokK z?Z3Z%h0n}%t*$Jqjwk!QPh1*67iD>@YCJjqBX8Z4frjj~VMOmh(dH?B+9apFi|-xp zcS%W_-Wb=w?6NUxHEn)7OZ&N`_`|9?1h%!0+Blpkm~)i`{v3K(>M`a_wr6-uXuyX9s~_e z^%rB1wnp*R!ozdmD}Eu?a~`bIsj}yEe(1A5W=04o#7uJ(!2U$C#4}Clu6^VWZUX~o zsy%Svb`s$hPMo&atBCFlmtGW{aoqRtwlxW1y$3VmbQ%`lCm)>-y15MjF0g?ofd%8# zxYu3tA}wSL9OD}-y2$#q_8~$BtD&j>*#Kb5xpVK--I{UMV+%LW4Mk(7?g3v>tH}Rt z>uPCCD34^>f4=vXrlg*?L?45^Jl1@yj+}no=4^V>c1MW}_6wot(P$8Zo@XWag~55r zFqI^>fV{D6lRG6>&T?`J;&rEA$r;i&-Gr`*iGO6do6Tu_^vX2w9JK};_uSvx(huW$yc#J3eAi^?XlaZA**t-7P7DYG%%9eo zE%i>45tE*^Y;#iLOS6=lgUaA0{YOYxIw*@x*7TuFE(3HV*E6sh+g= zsM_1o&=0pPl=a=u^5b)UmL4;scn!QpYSJb=*xs|78zoW26u@(Ac)i-{Ps2`6M``j& z2Pv;DsLn;uq(Oz?tS*L6rh?$+*g<*RX%LX-Os|?A_(18}VxFnZbpc4iYs;`mAT&1b z2m)N!j@B;w76h?PSAfK^ z_vQu^ZpfLGv6ux|XO@GF9xMmo!@%pr{*_b@9?vxpz|J+OJ@Y{IPT9VD$0LTNi#jXEPA%S`sJ)*!$$d^=!{{YZb3 zoAX(q%dl3iz)+POMfNF`BefJ4<1zXz88(`Ek*VV7#DpR{H&p;vem2!)t&*uC zb^1N1#!QIHgYcO!{{7{2#J!{!^gfZ+fvD8RGmOLlCweLsMy?`GbpbbhCTOj-kyCCD!WRSc+=l0i=G5Q7U@&>75@8ocuVwk3nE{*f=BS zS79(cn#xaY+Q-^Zh*ak-+v(*K@2oTh5(WV7NSrS6>?E&8okB z3AkHM@p;m~>tKZvAAhmZnW?3bNs+V&wQ3j|WnIc=8AT;O;nUH1ldbM|$6OI$L*6-` z&+B`C>z=5Q!@ca%TrEwtR1S;$%Cq`v*w@3t#mBFB0$49_Si2#T?j+ESMH^zlk zZauwy=NGKoP$dEL(T4o~p3t9(_~_~omK`sW-GHYJykE-ft=)+KKBm-{-sYBx+NYp# zuXwO3I*^WWDL!Hp!_VL55Ho_SplQ|@C82y(^`{nd(Z|ei&u%@7NOw$PTO>#{kG`^I zT>=7>IiKNLqG57_abk+r0G@c5i$VZrF5>3dTkKUqBBh zOvwJEhae}%Vxw+L<9?weNwx6D$op3H2wUWm|KUKK0@Opri_RT0;5z7E?r*qW?R_pw zLT@NDIj1}8P?bm(ICsWq))^4555WZ|`c${6Dj@r%>naI145yR1mm<=U9g{3j?K9&= ziI)w)i+y)jCY|7_-3;(!Cx1GV2ZH!0kW%(*e zV6lxCb3HBL-nmnIt~vTYIw^nnTqmf|$2*++xA7kjNW>|8I2A4haaT3s$YNaN%6ImX z+}x%}q=&l9_Qazrp&Ul>!jl`Z!6=bDz^ZyxVUr?=f7bRmxZi}zKvP+TA61mA#?*#UWs+vkM!OA z;McmObt6VORWxc$V^4$J9z|ZF-G6p$S|<`;r*N#ncm^n#9K=0#IPbYTg6?g&Quzhv zy-Snfs`0*KCXtMz9lA{S->&}=DB2zzg_|{rAAY&@Qz5C)J*xjLkD_E)bfY%z!tDFi za`)l=b%bcosXhhJ*A`gBLh47<-l($NjRMEzC!^;uvZJV0D0((0D@DFm+Ih={LjFn< zv0J8oJ*h{kJXyB4ll1nanu8H%!??|%zcYT0U|G|v>l6IS?h*VqfIgG$n}Sg%BDFN7 z7z6|Gihq(-%&&+$86CZ_tAO2h020QBT1NztJP(TU4=4UmxY_fwavi`h=gw&0T6U~5~#GIVba2T(>`Dml5eU{s$=Y30Tr(bR)huhvX9S(er$+`YXu&Fd; zN@M}$lb`p%-nqzlKFHTsS#cM}w5k}s7mL*8UYM9ign}1GZlt>4c^1lwdiJjk@S|O3 zbal=ft;;7}FswGCy~m$2^cH@*A1@@`{?c8w zf8Ft3r`|h`s*Dc<`o3rjuGKP&`ZIl-NEGSID5cMxiWzN{jUi)YynDo%#yW4U5=vEY zXbVGKJSOD!AZGtSb2DML*KTR#B^12W#fPR8e^G(S1=Rq{!LTspe;O{_8@VqT(9%Ln^wg!R6LW+EmyGG)U=S zgs4*`|E1KXbk+RitZZL|dBvz9h8&<4A=EaW#$)J*dASUNmKpBo}2xOUhh!+d|ZIrY3@HSQEKfl>!ToM zlTeqf5o)zp*qwA3ze&vJ3+kpj&xHI-9!{P|=z#@#$ExAl(B%qhwO2Tv^n9_DzUmnw zx~s0j`SERe&cT7ONQBp6E^xzY3i~=Ai1MhE9X93ClRb#lLG2Fh!jr~l0QMs{yZyc~ z$!zvr@pHgl>JD6$7?--nbD{^wlas6Q=;X2;l#5I}w^DO7(?QwpNh7Q97ehxS99T%_ zSUKlX{bn9qaDZBfAr0m(st{C0OD6-B>Q%LtEyL7@B2=yqX~V?5R~sfFX%3p{E(NbinU?Z7V-5EgRyz=@kO(7 zv6FFr`ItK*VWV@1yHDRxCfka(Y+K}xn9=YRKJYz*wfU;89XWrFyk9w-1w0=J@@XG+ zpECY1U*$RJHznR9H=3l1Sm))ks-nJEqlE&IZ@*WgW#p9n)(~$yT-AY@Qahc##rcxj z#rqF?Wi^44y;$|s9tpvQ6AhoyX12B+M+Mi6*Bz4Q)j7(Cbnc+#$TTaIX=7+dx3{CK zU08o+-4NWW7&^qCIA>fl;*6;V0V_R<<0W#VMpA<URCC>mdit}qw_j~Y;!N-VSE zBX@MD)y4FPg+gn1Yr_fYIBrtvovM9&_&f5R7m0t)*~8myK$l&Q&fikWLsm0a#8g+K zaWd7aBV)JWxSV&)>+a|F3m0+^pHyf)pEleJRdtBi&bs4M#mg3?5V_(9%vN5w;)Pk_=mY#6en9pMCSnw*kAr0^YP7 z#JKlbs2fiKcLi;5J~B2Fy~JKgP^FyXfWH7aD-NKbiD%Jx%ke``{}J<%zw$lG%Oocq z8UM#0slU+4AE|NIYshut_Y<#UE26qPqcqh zlci76%*lJRNnVFAGvi<4uQ#WAlYKt`_jFwepI{XrJ>oOHlngVV4b-I2$ z0dY5)hI&l44D1i)oi#QnG2K^Q?9~WbW{Go;ISQ z%CfO{QA+yjr%e=GlDcJg7m}|F+P>L}wdJMNY%!GwWGH`IFV>Hp98w<$ajhHUP`mj4 z&`?iy8wL(Sf4QiCdTcb{b(?x!9^+9S6vJOn{Qs{hWl#SwO^uHq7q>ee{=;61uhia_`m=6+U)0<)W_e)@dWG@&2h+Pg<%^}&nxRb z4~fea`ub?}qtVUzs-wYUKym(}HG%(zpsORrLF@D9?l_n%dRdJC!m(_K}*sRv(I zI!;?zj$GL9GXs#Z(-Z5G%)iIl-$@AHRDDB4UtyOKRefJDwJad1c)wkJaPt-1T;09p zRO9|2T3hAhZBK~lIzkQ?c2b1&`AvU^3VqP29(cE$PE{m$Bz+0TInnbW)BacNyHF)Q z^U3jof@fzCaUC5Ib!_i!n#%ZBkY*XxsM3EW=`#xh?%Lp;1Mel#Cvm@9Ksr4csSp!g z!V;4MAEdMy|pgG#p+U zVy{57JB@#c)fe!uvQ@e$LSmR%>MyDHzF z%NndOGh4+RVR&-y?^ElCM;Yb_U!tR!fN%_HIcUG~bWv z61z6PIEpAIF7GNoda+BJF7Y4A#0@~!v3X1VTl<-JdkrMfo{GLnbN(YGIET7T{3yRO z=a%0VShMb$jekbRK@jioJ^-J@{%HQbqaVh4`QqqP8{&4}NTV$^#-!v`G|s9V zzZAlAH-+I*ea2&qibYi5J&)%(hx1K@FG%ftG+W%%)$IQ=UWa=nCs&qHe}K4P|54Y*{?BdddrWIF2-u}+XMRg! z+Z=fvumZKED!6n=2WLl~UM%maJb*Mr-KYvIP-2wR5Hv=3Sg%YrnL(ve^|$W+eQJgJ zCGnC+g8YNfG8>T+(*{r=Kl$4#?rY^U3!w5o!yQTt09fyYGBYiTq280IW}ZpFI3fjvGS#$@BG=qAn|2$^L`M+n+18*sJR?Ju=^b1n9jbUPt51f)74cvC^{r{;MF_Uz!q{tDn8wFX=izev2j^oIG{u;UOD@e0-BAYh(Md zmIKU5vtWll6n5@f9Ui%hyPH+X)BOpn{G+fc)i!e=RJul{1QfM8Qy|mpo*X#>%L*?0r${3$2{_JuY@y;P zY%4}{vx5T#*zIA8p4@!98njd$DbA+!lc)5nSMr2>V4{|QSv}D_=x7_-!{?#X{w=Rh z9Q+PU+l<=8;Q^(fCX7)1H#OLrSEX+GxO3Q4(3J!BXD!@0>L6h)cH{@j#35f z?0aWVXDhHKnqPhS{P(8{6!*-zbfUEHYiXmeuX}wjW=gnQ&v!NSUOw5>kc z{YG}+_d^Y`<#<=A5|QJX6Xuf$!dU(ptaBeD(P*!gOP^D^=ouYk#Y&&huwuX-rt{13ML8K+)`zrYo?7YIn*G;uJ5(J8yFYITv);{HI z*U0vAT*dA;2za)8Uc@b>PZ)cBJpuC5kAtJ?^{UyRr;40cVjBZX${xk7f8!q6Ju`k= zywEgdhZt09B+lTJtriw^P+bq`lXUKG_p@$Ru3J{Nd~<0w{1}iWDl6+f*h#c{R>tz^ zF@&+is-VHpxNlUW_y<&aspo+M=%sIplMqEuwYnOX9&%Tl{l`4~FMBE*L`_@_l?fBp z#cMx>hx=t5Zgi6U4!48RZxiH-y-O=&EhSI%crI%!*_K#0)T);V4bX z?e@BA=Ze`N$H#bvFx87PUue2%kAE3Xl6fJ73qAz+U0%OBPJE!1oraIo)-~jK+>ICl zNDlOz(JxqiNpML%Qb)Fl+q_beT(;Y5R295wiOyyC8n2IsdIlp=85p_gkO{6AUmKekT=0tm5b1?A3LE_!sv^?up%iuw7srCHp?o?YNEqms zM3l?*37XCZy(wnV{N`tj%Pj7sLN`VHL?3;OTenUHC@FOv1PWYgwf2&*Yk8e~GK{`6 z^WHx*VDkIl)uRGU+Py@g%bN}*&2LgZlMTODaerNm9Vil*FfCRrZ(!}~scdAfy=BX> zxusQUn!Z(Q0Bm-)Hl8N;d5W7{Q z)()F6Z0eTV3NB#_mNFCY-ZvJ~pKjByJLsYFj1ZoJs#1ue{QN^)F->_jy23X_6C2^=`Smga>r~7%#{&x|Nps2jGmBVw~X2))lEi~n$K#o;pM7C;pEAXaV>x-f{k5QfS)2o{>%JJfm!G zlyoRNMAM9XD?{?O93~>`T(**;iBCV_!(wTmHG5N~b@uV;r7_37Fn;vfi3nznMm)2 z3tr>7pj&nR+kT)$b`Hq9q6@99t+auy*9-hh>#&gN&g*6nwn=ZgC|_bdgPNE1GZB%t zxtm}fa|g3B12)W8==MX6%0b7BqLU{a++n6Lh0zYs{^8Ts-Fwp- zdC0lRc&iC5-sxwf(O~2)mr{sh?D$aecd^P5okBmfsneDe7wabrW$61( zg*5KYr&%N1zO=F}r9#?#-aaJT60z1pa_lTQmYOBOBPI5jOC|m9*(YONG9+)5#E9e? zleNU1nf1-iFUga!Xc@7QFVJE%TaPIUop}tKkc(QNR#s)zg&M9^Sm`Yez9vhG3$?jN zes;nZrZAP+L%D)?Pm_l{Z941I9r#EZobQdhhR$?&57FcqT>u@e%P% zq4q4!!=>Ha&bqEh5}p}!-rMc9hLq*Y5-n*F^w=0un`i{a!>H``5hBE6XEqSM`g&IrHzEhf9oUo0?|36OHr@_L$-3g*b2T+?#hv$K z=kM&qzUlQ|?4ewM9zSB=Zp}y4P1Q@m7R5E~TUW7J$*g}Y==d|CRq7I{WLr3U zx~61FlhZrtN0tNroZQFkTTBgtHk_rX>EaAV1kpQmDR2S3#L!sYXm0tyW3V>2DCdaWDsVc;u`)FCHnT()0+)OxwA=UJJVn?W{zz?rQE3QReStzs<~WJ zLt&XaG>7nmEXk*DCE}v(UDkWOp1?d~MEH!8C+>Utk}=xH+AogEhZvg|M{cLCGtbxF zwV_J?a7d>s*Wu9NPFp8c=urwThq1?uiK6@O_esQdN_KEytuFTTr7c#Bp}0m$UJD`{ z5_s)TgyZ%Q`Qed>y247HyO0F^(HfssJ+j4<%u?ixJi8x3W3K zx`nCb$~DN`BS;5H;A{Luf7#txnVh3ZX{6^1C`tXnWCz)t!uh{plFKWz+A7(qDO+1C zE9;nR4pW7+w#$SX*N$emd^{-#JTiF|b1ghmcLB>eAt&wx&w`S^ww$~NDcuk~?Kr~C9%PWs&(x>?xq z$Jq1*(eiHq{7uV58jJMevV7tq85eV(*Qu-=dgQv90*e5R#WN}ffjJ!~FGhRW*HHAn z@r+Z@YAma=w$|68`?D2DHmxy>7TqPNp#a4?O55b2qvXyBo|WA@ffJ5| z_>8S-;g0RmC5`bh`qZz(b!(%6=^0A8o+Z!|AfCC6(-{`rB?DN7`ejt#i&Ln*u5!|L zM!e1aX7~5_#F+o$4j1WDdJdF6BSwJz8*5n^b))-qH)O?tmFp+jMMZVJyM46>+Y|1z zsA2+}QnJHmU9+Lf?hhQQPKI#gi89kD-&GR0T}({^2(sD6Os0W%hZ9`XC*aB#(g*)0 zSi*HAh`%MyMUPf?zx44jy1d04?JKb24@Uem=AJN9;D%rIK31eLYCwn17Zqp7N-y#!<@h`IzC_)!{~z|=JD$yc{~y0Qv_{cZ(VAT-iq@>H)mCfo z)Cg^jAohwCs;VuDw)WmL_7*}_(He;ru@ck>LMS4L@ymUmd!2K7zMu2=?{WUSa`DKO z>vg@Z_xrV;&nGpK?URC;>U{_^=Ug}_XctAG1{R4uH31o|egGg8e*ri?HPND6KZCjm zC6Dxw)}}-alA7MreQ8o8NXp~;@nF)j^OWx$T~u z^q;F_u(xQ1f5ax_bM6{c?Hgmj8~GdHj~2c3p?U?~;p!3w$zxYF*Udc_PZbLb&Fz|b zT(emjAqW{Z6sgF20}4m>^CYD!>rbUVd%1Z}$NeVS2$nrafo!~8eBuj#IzIY*eAIco z;_x}=l)wYk!H<0bPGzN4nkh>Ak1~w7bW3;BlD-_n+bw4HKMV9e(jqO6K9RpzR)&1H z-)}Krja$z&fiKC82%I(yHC|>qtf}L{%68jw8wDwEh^)5^kL;=e{ zDl5EcbaGy5gfZUwq*H;KoZaULBBPT#Bk2`sfHSYVY-d>o}d z(|9vqX7BArE89?iQP2x&A~{X4U{8}@U{gH6y0Zpugn6^A0q{Hm1W%Tmqw+|p6J`mt zwR2rvJ=F<>CT8HQNxCZkJ~2CtxoGOmnuF7f#RKxAk+%#;A)g`Df1#=nm_nUg~zabr_q>^nCHg(@2AX5Oj<7$M=OoyLT$Z2!4m^H ze3ACrm(xvpz2XGQfqxjb1_t5vJW0*B8&D z?&Tc|%^CEX3ewRtEip`N(v@I?$G;+7=ruOnW85Rf-VSFjd{Ttr-ARf!70xJrldmAJ zvt;~2o5ZixMA8F2RMbg3-!y18WwRF{~<+v=r-2E05#LdMFmj5tI>_8pkHC zE8Kk&YQ%=OM-J0?Prrpmh3b!BqwV+m_wG8yb?o|)bb<`E1H*umk1s|KS0?|6AfRD5 z9VK&q#m=Q&-y9P1v#e<%f!WN>RPU(LZ{?5>r(4bl(+qXb@Hb}wye`B$e9q`i-H7GS zO<`CZ6Czn`OC)E+tSNJ?Cn-6H6C33a7Al5bKTH*+t5icYo-#m@qh|OU}RU($tlOefDM`n@?j(p4zz;O_1Nc7P`DJWT9NtTYbhZ7Ic ziX0rCLyc3cCPNu$GPCHAqDR7B%2q%Wfz({4U3qne`d%hKtIZ5Lj52imHZUtuO;GO1 zSJ|sLys~-Vr5b4LG7yB78v>MPLG)|g7bc4xQEL}Q#8{p}rmQ%2cg6dp*ZOs%2MT`- zNeO~=5oNC^E37S&S`rDTaA*BJ@B~m9plo26CDq?6nreRNM()- zSVP8R*F>NIIF<=@l(Bp}<|hNiHKv#6qTS7~LX4Ns=6{0kGb?IjS_I6{sPleY*rl&_ z2ND{>J7+)5#2rq$%vY}TL4k$4kX5#7Kd?|uXb8eg6>G)lR|HkamB zW}s;al(YbZKjdU;XRuCo?`1@yH>~ptiFa!tBWYK!fM%w(ipdv>@ZzJRNO`V_;HOe(?IBG^F+6os2lM!{Q8-IhT0h z7t0`O_q!d7sJw*pSwpPST+1LT|U; zLbIR5RFNOTaB-sb?WCiETS+(mio^e`KED#_Z_dztjlD^8j@I(&fN;4(Pgll`&Chzv zLj?)&2eQ?2uO_;wIlh(cM+s_R1_zdlKvm~iEnl0F5^n%1_Gz${&kFe?TkkJHXAiDC zzYB#8;3uRP%OlwAYlDh(EyJLehKY?s%~>{H=(3VJj z$b((p&?ujLm|Utnx9Sd}44x*vQA^h!F6UpKGq$T!S{96^d_F^BaxTu-Tx+&yWfnt0AMsk77o~{GqI%!s_d~LV285iT6fec?Zc~AX z3x75kRhn4e^2BC6#z*gr zcLmm#qCKitRg(5YZBG?$F8F|~8PMl~&YBP2&}y+MIkip~Q%yk9g zXkw3B1GYU=>|L>J6|W95sU9%`8z4RM*AAPi-teP#boi2N_;Y#{pE;#e@w%ZS#TUrS z8#5snutoZ2#)#Y`26x4Ibz--y_p78(+8W%dp4aXh$8n#OahSA@M7X{vR)U)8AU$lsy|?eW;`-qDpzMJqsA1JM zYhUf!1i~~KP?%+ljKqAThsZ$l)V%#n?7R1E zuwAN^f+AA_5XfbV0`5GZVvlP50?rV;2dFe=K7F!{bPL*~%AUV{do2uABaIj9Mv@d0 zq8>ddn&!Rqs(4t|(Ds_I-U3i@_w|6B;%$BZms995>c?(hfDC>tf=ANGU@s^iyM_d8 zbF6Xm#3>oGh%Jesl0VyGhmitg*i`k$07}|W&@dzX(7&iySk(AS67EHFJZ{ZtyG-HZ zQBZNYD$}2S{%2Bowob)BnS;6M3jNi7j$>fkI|P`jOA}_fvC;S!03h!SPhrafucQMR zU2H~13W*(Pa>@`tO0Yl391ix1@O-mN?=OK*CVw>@+AflVRP1JL0cw{Wk<~5}YNoA- z>@ZvJCF+9&thHV9@)rB{Wjbk$wYzra;CS4wgEm6AS)~TM)>6hEk8tkvkJs;IJ}l)m z57L7JVSP_H$LTjMFzpLH%ao@>vWGEwt)G*KPU#0G@N|pOn{C!;I zkwevKmqNDLZusNQ*reE~NVx1U0|S51CbgRK28*bh#DMJfX*UzBr`W(R(fNuKYRtIp zLa`S`_j`*3Vb;FmoKa-d89x^sWQl(U5N~i;5Dl2pscRAJwR+pmEAPFcBiFurSYxb_qc$@oDvLyI* zH-GOs&Fy%*v|S~^KBhU?2)tR!`&te^g(^^R(<;#`fhc+yn)GZUJa+;dpP@BOi*k>% z#hhdi`T9d`^nv|;@03uFL_~s-jA@8C{~{d=$pfX}a%(a>4;&}^O`a2Yzy6Lvrx|2e z3r8(r8Q=G8rmIWN4ZQ?_Re@hR*>N+}hC;DDxS^v_s8o+>R7RGdiMB4lw9`k?$@WC6 z)!x0eO+Xw>c>!3~Bwq63(}JUjkGJW}#X!^^f!Ni16LLtAJ#`@I`{ zXA-kw^NghzDv!t>y&1U#<)}v>?#A(-MIK3(L6?G7=HKQF3M|$eh_AlDe%-mtan#RJ zOj2IkEw^)8dW6}$FuYl)m%O`mU1vST>$=T*5=fY+WzZybK;5ac!O~x@OQ>ch4Iq!~ zI+?`VUJglq-v^M6Y(?F07~_QK9k#sQu-3s>XF#3xi~KlrpWpV??{Utj(nk&`)L$UK zX=y&?$*4s(&*WE=clfTUwLuo?AUD^34|M5)%zxNFGKkUrSreb*?2hq?UFyXACq0%s zg`XoiYpz1#jLXbm^9w`tXTUdT%cQUh6)p+J3%)3;wDP6Pckqr6I05!!?nCutfPE-+ zJrX?kP-xJslVfdTQb9z*GLojP(X3{#Wqb?TL5Vj?H$Hz7zi=h;j~CtZV({0wn~Dct zpxx@L=Oh;p-9QCPGS0g?DN9f%&+G1+2_KnnCo395rdJknhPK+>ing8GIM;gih19-^ zIE>y`oTH~QOowB3*%Omq1(-$m3MR)coxJ8-bxjAeTZBw~9B12^wO%iW_M7c!HcB?A z^@})M4DaWZc2obFnYK80cX>YgB>li`@MLr&Rkizp{zKbj*N0QKEfCs$trprmOGTv{ zv`EW4_t@VZqz9>?Yadi|(uq z7|ULE`Hp4M=#}=qmB7Q&H^jhEx|f^yd@2vEvi6GS z=-3h8l^^bUlb2(}IQ+~W%?5czP^Th>U3L*gBU`9p;PYs$DjbdX+0-G~j&1p&dAywK z$(WIY1*VtPI@rY~_%6!AD-B$C$UzaU&|w$_y{(y1t=O`dC4Dw^Wj%knJG^(Y|IjJ1jLSs%a&J&g zr4D#9>tP;?m33e6!dUS^*eNBLuu-#B1g_@*R>iJV&}HE>B-#K$Bz-{Q7__f1#g4uQ z0W=|$mAi4h&^e;c*NJY{lLiDG0L%^)h8_9(;Xo6v?ZxjpaA4CXginPJGUd8Yo#tz# zQed^=W9#$oWD0xFmTEtNdI7OuwTbE4d$b}zHv4LsTjtob*?gUGXo>&MFchn3Kh*g4qJTq9ozPsL%}8Nd z<{Cf6%saX;kDR}x0p25{l|YWRZOgBxXc*shDZa`{WTMtt!QcH(^R|Fcy=Q%gAorRX zCUyc{W|}s9C`Utj&5?Jc{%ynMvI*8zmXhxVe&70Q1N+C3q~+y00KBYK7&t2wQR^@! zY+B(N3H#ub3_&sYt#mwgFlmT~71{D%V>#_}+)5#WFCO4$+v|Q0Xda1f7%a2?o@76G zeoa53Y~@p~@`%taas|<7ZDRJOTViZsy2t^Y>WNvVg3UZL+)!2PO+DvemZ!$$>2ykt z4PfHZ`ZC(_@-NS>vDz84!yHuRIQ6mIh$@@VrnzaeFv=n2T+$iEV{eNC`{a^1 zU2Y0gl!qza!&Tx=1ssdOq5XSEajb;lN1s4eAVwv&y)n8KGY{?%)H%PYM(tx=*C>lC z*X_-&)u*sdUUY!r05b|=d=Xv~eG#gx3}4M!cO^oTO+}WraEy~fA_y5RN09IyppnAj zpRZcG06cqZ?^-KMKr6Q-u!6XMZF7aMNauOs=>jJr*|=4h(?^FFb`&JH0bvIHeeUnK z&Oor$gBO>mk-qR<<+F>Ik2{f2;@qzyp8YkZRHJhFDm+2FtW`ryN!e_65L;bRIt&A+ z*$A2SdlF!VarQx+$VBuWQ*Aa4*^&qYbI=~yKcGY!iwwc4`Im7?n!M=%$8GRw#iLl>-2kil|)A^Ayn*_7ec&)!kS zBe4Zi(0j)H8z1>h8?A%$ang4gJQz|OL|0~sEz)OC%sRn_!ffyAfU27a*0oyQq?HB= zoAYdxRfE)cgL%YLj>6$-{S=W_8P2yQ;NxwWR$9FTYS>InKC$zckF0>sN(6)9bpWA=}K}^4~}~8*H@? z`Tndn96QOu`gSD`R?z#AM^eINm*0?Lw@G|2aZ_qsTbS8YqSa<@cQ`cC)!CLw9go>I~CQ_XRJvOZKWZhidbtYvTHasJ>mWzd|B^^S{?x*S> z=MM|-&+Pq?9OIi4USDE_)R*A2Xn{fmF(>D}l;#B^bt0T9zPU0tP{#8rGkCc7)H516 zoUA3w^k?`u{k$ik;3O*_yvvZjb7G-pU*ZQFXKqa2`R~?lQ2l#z(&^|ye~HVqFsTEE z220L0LZ!FldY}fQAAq+JBsQ8SMKx?7;8b)d^lxVRy+Jzd${@L&)7uVp9#{J%m`Ol4 zYu5vRqhqhDD8#b3f1mR@=ie3=YKO}dl!l!;`Pui{%;aqjFXX*YhsAoyt5;3M*>$Gh zZnHUiA`O9@XI;)e+1MG6Siu?C2J5bks?*m_oZQRh3d;~TbQ$DTJZ2XUh;>dpa+BtcmD zPwj`>2^s_{rSHv(a>LLGNYdpy1hrYmzx{KKdFJyW7@We+P}^?NBI;>I=}x=F4f$k7 zPKU10qbc{^m^xb2;zWn+vfBi!g=+TWq`c9&41-Jt>k-g!^@EB|MzdNEzL32| z29nA%Vqu$Aetdwcs*R`_W%rGj^36|&KCjE4f@Bbz zT;R4!+p%n-J~yZVl0*B+{?ue^nRtq_hT<_*?}rR5ALy2nH&O(VwRYYWHiZP9QOy2> zpoE|wm}%!S%RM+tp|!2T%9#1St+ISD6fE2|?N&<){Ippm)7AUL$EQWWc?@As)Fy9E z_8vaq-`dGGLd7)yu7-D?Bh-L2GeJIL^*}@ zHWu_tMHuZq88{AUL<@H*L1Q}uLAr&@YEq~qd8cwE!6N0?r{vjXAI*x#thCdNMc*i> z7{rkUgy=m;bDz!8%HPEX!ciN8er?uXHYr<^LmFlSc0)!G7in<0U)^=aOCL)XcPuz! zvPuNVcjNa$VFkOr@j}(@7u0Re{;zSmZ`i zvAy3f`S%Sl*ku^^q+zYT2m8nx*d(xSfhrc_YJ-g(TS@w4y0KEzdHZH+yWUp?F-){q zdO|8ynF4Wk?F?Z!FI3*}oY1uJyTID5U&{#WV>OLnH2*>hI1Gcpsg2aAYq;((>el&obz zMsnd>ICc+0ngLfFrg>1|OIHMeB-?Mg)iu)#^FhW@gnhl7!0dOgtX3!1KiQDo@kqULN?`UCU=OLS z6=MH2&MJ2DtA4@~=IGJm#^}A5X2r3Jv(nH+DT^sy-`Cob47P#m3+F{lmdxU}x7w0p zKlE>PFy_31+GxHQx#rOX{*J~keR(Uly8kqZ?WUXUG(%1i8|xCsY6ht2zDGeHnh_JI zRzSMt>*a;}RQHzFD{`^;V)dl;OZi)(a#}IYkI?TrXwo;Gdy)$1IA7a;j~2xwg}D_U zIz&siX5>83z$BWC=t~{!+H+X%6T&^DtY*|vy4$fe zCwSDNtKYo3O?Y|{gWV#%DQk(JLk@BCCGCBiZ$~4*X?5i$`72y&cN7HHl(hi`P4QoA z{D<#n^P#jExKkFtJyTBgp1+Xs^V-IUv3B-6E@Z0y><6=njgfy4zMpy3S8Fx<_c;qxs^?=f>S* zwL=nW_5h+fo{N}Mb}49oY{FP{;APyQA_k-%Z>!BQ(@kwP*XXtC65LahS~XRS5cyXn z_cw&!wLPCYCtTU3Bwp80M>*GawTp1F(C~ zYR)#G<(9AK5?vhIQW|V_k;;L+ zMs5>FrTU?Cuc}oUPH?!ho>8x()-Q$k*cBHYurg&T(V~Luq{90eY`sQrvuH>SOW2y8 z@>qBFaT*49Hivu)_s}(9j`kSq#T~~4rZiegAb6&l{lhJDz?NlZN6X^}^+|_1WMw%; z2d^J*35qC<2C_i}kv!5O+}@18$MCm7mp^+DT-?XvA1cZbQ(6CcU?(%~_z!z4$+cYp zNopaUZ&zTkn7X?Rc4-f@FcjSAi@NcHJzTdFcvSkM{p0?nGSv0Rl#RrE%?87Q9gn6R z798r4#6-eTja5PKaI9PVafY33eQH!*Bui~nJUwPJ>2yD73~|rt+_ED`U`uX5TPF4` zVI1vsrS)tdO5+~){tQ`S-P?t z66s}I9zo=wY9`$;a0!mYOu@$UJ3I=6%ZGW5&KI3yS+Lv2$`rOr@jZJhA|wc$E$AKT zYq>OX_58!cOL@HrCFfWWTl-m~;cL(mTLnVeUD4qm(^Mz%&lTtI8|eMUzm5vxq>-G1 zwxlP^6j33wCyEof$t0JhYAaLwIxAP@<*)ZxUmrip$YEP+Mv# zNXKkdww$gOl!x7&V*BvEs31R@dCYmR!p+YScOmj%yQpPwn`Q&RyrbEj`t&g4w$No% zE6Xwvy8#l@x61FMDuLS_+4oB3W-L}afMuHfk!F=PWPdO&Zf4S>lyVfKdha(q=zpFH zwi6C!8PCjeov#yw z>H?+s`P9L?#fR|jL-VvoXm8`^YZeZ+31jE+TXfY@eAS0jB0@dkeNb>o@5NpxSUOcx*kvof$l!rJRTWgiOEVUI zD9551GivrjgxhBngOzjn;GLq>nP_8Iioae7xi{fkzcFUtlH<`BWm;UO-|?U+GLKHb zRH8z!1!Al_X|r7COeu#>=whQo z>zoWC6~5`xvfF78IQR9#G19h~a;k(`K)}A@f)#AHSkiKY`JjZ}lA=`VS$ObzgQJIB zj~*_N&BLb>-Knkw4TAGgzala(B-(^BVoR#bDy_64%FV=kU@C`14hNF4$Ny@v|GsWT z9SdIEIhmJO9`86nC#ViKL4O*0@TC}_jwr$(@8N>^f2dSJr zw~oa-xwV=WFjC-VcrE9q%~Q;caVYIg?htv`3)|PS(ZaHMecF>F1+p*;IA=anw&{1m9?UN`Ch4XGFD^ z&jibX;R;jncJVEaj>3~wJxT%F@0GlhPac1x`oe$HwQ%rfS}UJ^Tvxd~`NOkzQTT7E z?LR^SE?_X6gR(ChjT{<(4i0^l*>`hu*J3-ww4$>*uvj)R*W>^5q*t#+dTCNG7Uhe*^zWs<%P(GBQ@NaKb@yir)V<6E z{sXe-(uX8dlkXyMh*^t!FJPT5PEwOaU@AN7+d$i!QMKt?w5~3%??t{{bOZq=1phWg z{8yZ`sz)vLZu=Nr`gfIDE~VhnyVR!D17MR?%!cx0G53SKam!W4%CL7!S-5Wn!d|Y$ z`sWi*5!ZnyO_>BgAxxtA#OECpDTevWy&uX36kl6FWr{C`S8Eg^ZLhQ?AJR<`-*S_ zknHwXIqq){_|MqkpU%0F)H9&$ew0UrX~J=C;(zR& z|C|s1bMo^Kpnm4;uQk^nWxKcKzmLXf59Vg<>k1xFq(-}tY1br);XPgsYZkv^b{#9Y zPDiDxto530eKIPNv)1;Vp2bMb*ZZmw=ThnZ?+g8YacZc;Ro`~|O8-%fHP*W)+M1@l zv3?_5tkweql3U8X$d@s$HuBDGM0#ZcZ?_5$D4nVp0PZ(vbdfcT)X7NF9yU*-=9@6! z+lY=)!`f5CY?twCvee)=PoZpsgGw$lXssU$tQz&$m|fVUNe3oFtkTb_Cl)yDd?M;c z?v}g18F8VaX`;;kEhPCj-h$t5DL9A96)~wdkDrTI`TR}M3*)40WN3)_<$e8>NnS^g zFVM@&D}6usgudi%0n2bLtUk3iVEG3Rt<3l06t4$CI**J$jbi1c<~vL`M+keW&ROy) zo*Fdg)fVIF5`0d~FhPr}GEe}!F+(l?X*NEybAcna-AMb2l6u;p|2A&n;tqD0bs85rG9<^}?Dcm6Hn z{^tPd4@dqq!}j!HL%WD3C6eCU%_P3$McuU1=14S>0sgBINX$tu&YMza{1-UNj2W z%}awQ2q+!7h8kZ8EJD`Wo@y?P@f^>TWaR1Zk@rZt^dw=&5Ub=5KXe(<6q$f3L~mVO zZVIZa&lCj);uYm&aIy_E^PsKe?aX^C|Fzj9sIL^aL_+qgSFTz84V%;;3q&x6TP}Ce zd4RN0dIo$-_Q)7~ymLE<6c!CT)vZl zI9+A55PKc{`Z&naKcVd6G&x==h|HXvfrpDa`G_X}m!ipM?Kr7~5#ya7j7=}Q4$xdX zaeM-2w&{YX+hU9Z1QZe7DzBJvNx3(qwNf@wsz?qH`yJ%@bLX_*XJARi_Yk+pSDYwI zVqUZFeO$aJ$KXGj^OBDOLxH_%i}8t6Xx1r04bk{k0v+2;kwJJ+xn3KwKjK9vS>DJk z{Zz401D10=&K>zEP3DHlZM}2Fu<>%BnY6<${2tlfG*w&5iCNl-e9H+&%v6u4bMPXb zVhyz$AWpQ28IGzPl{#SI0yhLl2$1znpinXWz>|w6Kk$*5FAS7%KCpLL|A`3cQA!pI zFwPHmD@~%J{`u7aiwx)CZZd<{<-&Vr?+VPG7e9phXKHJ`{XjZiJ`SK_U=Pe-^{-oa zU&23${&#-YFG^Kz0VgDob}kMt2_CFQISY+uhl(AJ;ij6(Cu5=_BGCyHGR({{_F)iN z9&R_h>z$O=bT3qU?9GJH^NzJDsQ@B&d8$Lcq*|00wnGj9g=+LO6B{3}lgKo^W5-p! z^hV;w4c3_zH#D_%U5$U|RB)(Yuu`m^z6RXRxvd`M7Ee=~d?_&Sby;KOlOW#(H<2ml zdC4FG6c-1dg`Xj9MYcIV`zP*(s_I!3rP3BFIa+U70wVgE6IOGGRK4;pU~9kYR0U+N zcc{dsX_Dr%hJfvIf=rr-{~U#3YjM(s3X`$ZA+JS@L-`d@oBKVA8#v=#v{C{u(UH}mnZf>cMyW*XUe!X9#U_T{;~RjTr; zRcqiQlc}aB0;#Sq@#`4Npi-GBzX@PXS^-25k9ZDxhkYJ5y^=Is1gCtkd`0`xgPx>` zxL-~D<}Myk1Xpdj{~JRCV1(giweWq?pw!W>25=IKq?7+3?)Q@z;7=?GygW@9wj6LTUuj0jR_JNL9>*pd^(l=f#oVKa*DG^W6~bJu>E6s)%wGK`D)6&qh_<* z3;MkNCnCe#K1UV9V5;8huyP^Rfp6(KJ))aL3fR!RY67=L8%8=Z7xV8xiH6Bt8@NQ8 zKZ$#C`VTGuvgUA-H2#Vcl(9 zF=`%c`ww_mCf9_{mAff-d#=9uutFt_=sM#{&m)9cZWSF&HSyT`@>!;)c9J(tz~mss z+bFzz$`uP( zrM=%iJYRY{Z~Qb89PgzU- zRhf09Fyyi&zwh&`<1_M8uldAeIGRC_e^q(-Nd){`EZmQz=I3A#`<4%f_7c1Q3NhWc z^RoP^_8BD!&%>$sqak34RqnMDZ%k&VRw0d|tGx3Q^0~~1cQm3!x(zZO8);K<8TKVXMHWg9Yp{=^@ zi;|S-UwIMxBw4l!HXMf_w*; zR0p@Fq7@3S*k@7UW3CD|E20Aypbg0;d`=hjk&9OsJIVSH59le0%6jYL%7$~WiKV&w zyLj_WUUH!E(wYYzZ1Xm3J6`+H9l zhm5Smz!fO_q7Y9?Da-MfGao7G#gCPDv$VxE%5dIS24 zx!O0787*PLP>_pckhf8N;U}>rVWU0J4TD_nJ0O`^jp36g%^RbPo%*HaFZabw-LIPX zWDSyTQ0?e88Bxg`Z!s?wt&%U~`6k#BFTAxt$ruMML5YtV+eiFBcY3l%E+pltahf5A zo%uYo7dE5&E~Y(d_i$-`j8MI>IwCgq12&$8=6Ag{Isv~bWhvKl;Jv)SoC==t5o$5a z!zSFIiiTcMbfwgC;KW9dd_Tdh{fl?~_R-Tic+bGW%bKw>@IH+}EB|_rmnUI{OtVIpZ+QcNx!95fZ^JN{LS|V}A?e5#8DULFeEFFz)!eqlm zoexwN4bV`Jt9NvycXG*}tQ*GDi7ti%NRGnLo{cTv5qr6g;&YIEamr&cmwNBqP1NIU z{@#p?5)-R}l(fQKLmlOfRQgjEu!11z&jhZxVzV;!f%bCNQ<9j2IXk@Eea4X!I!MMl zJPrayQ%n346WS4-2DQe~tpTqO3Giwto|ua(y5-$Hj z`~P&k7b>UEQUhTo*ALP2S45%L)EKC=vl}XlXVVpJ{1w|ATLV`fqd>T(HJUSByk|fn zG4S%{d(q0I5+O~M)LN73UhG~@isV-6)(g3=Rpd9tx!wcgQunD>R$d|(bt5HAOc)$A z1_a(TN;*i$0W65UwCtmT5<_NfftJSXj0m4X8Ez><&_qvJyn~VRP_S?C>K?h9l%Tc% z`!tT-3y*j5$d4nW`63?5-uA`O_g#!RI-_42W7yMa5T8&gsDmhTve7;&d6@HkZ~5hI zCP_?GbX6hGuC)72KCGbJuCFejw9HcE zU8)eG`e|8wlS2H#AtP|7Un+caI0{o+Z)-R2vYA>pX(d-<5OKI3@0kr=kT1wh8%Mas zrPZAm;YJ0Q`X(Rfro&0{8UWx1HzV&L#>7v$xZF8a{IPt20zSoGbUJqBXD{DR&aIk$ z;vO6*JKa4Ugj3#RL z4uEg61Wv?pttq}i``o{8{RBS>FwauWr;5oNmS{_;-k?wI@5N{X__ke-uL=n_SMQAp zjP1os$Ac2{OtiGwB~F+s+heAcwrBca$3gTp%#v}pEPAAQ&fKhZi96hPe(kJ0B~Jhj zzgQ!jKC!t~P>Op_X>pBQ>c6sTUZ1ra3@YV9{W~29((6(tOq^xwNd%~iA@}KjQhfUt z7rbL}@(BmYr%``vh;99JJB?UOvR|i)JS}l)>Y$t_Xv1W6>L{*&`u3H|28K*$>wB%m z_FS-HSiww`?|?4K7Xtm$Y;0o0T0Zy2j|`S-*Rp02^3Bt;3|3T)#^G0*pEjL%@W9FwS|QW!lI3gi5m(yk8I zTIAOR4p`Ror9Y{N5Z#OBT(z-hc7#M0_1MF=Hw;v3`VEcEA`9-7D{X=gpam?zi_Y(# z8z}y_8MvzgwXOqE0E+B6Fi2iF17aN|nN-$MLI3JXN9NH=hq;IA_=K7rvGOsmX!Ly` zu>YoAeoj#m#$kKKOtL@hrNQo-p4#5pSbR8O)B4Tbq)#OiYmJjkkDXWqrrAt9A`7|Wkc5B;?E zg`lgDbntJ==C)Hfe0m4`^%6e1LM_m=wS`(lq4QhV4IMYA1Na-4))imIFX2uwBC6H^;daml3in-R*xEX2V71oXWevr+Tcz>$U{&HU8wgKYIlKelCjcn83^V z#6_kwl}z8`j5O_ec}!IyGY(*_r(?I_Uh$i>57Pz#Cv@x^avl(<$Ulb7dsOYorYRx& z?hC+SjLg9k!MH?y=_*wVB zVaD_uwVfJDmn?OqU50-tcK958EP%%4HYgn&4+FA_H;7ICFf=k_==D4Ci+slx`hgX- z(Hqtq_zyh(6{h!pwm)m`WzO|bxqnJ635YaH!mRj`M)j+Gx@UFdNI}TQ-O})5w&OGB zpsjftrvo(}3*5f#`+q2++S0Czo$dRSy;vzY&HTE@pNx3Hv==gS)m$Q;=E9v*-YqvE z@r;Z_WR|MbxTSFk4V1w##>15cCK3!~?%8keuz5pu{t^+{Hper)7isSx7IZ zO9qY4n#URA=Ze0XkcRB@e+5}9=u}%&FQ_t%*DctgwIO+;a*B3E{Z(G&i|Hm2TLbv4 zE-%EE9#7KQj%Ow5yrt`d+678j@3(7nj)!#LsOD^Aa(>NG&CidX*Y_Su4 zTMC4LyuEFv#7|%RdGsih{ZV2v`2Et zn!C&+CJb5B=69Ca@phyLC&)6o{Gi;pm7m1p6Mt$u%y_=Vw8JaG+llgoW+LUVtKoML zY*}m@NRaP}ahevU-Qf!3$E0AF9TP!Yyklvq z42iV#)XKZS4I3YP4y_n42_Kmf&-f!!RsqwLBuyXUr}$k;SbAbQt-Qc_~f$v@?ibB`t7Vc~m#|Bl{4m&3vVM!1a(gm^8PB3c5fhdVSs zfSjbHmc1Y5cb-|D$1)R84)aGOFQ^^=neCeAwI3Ap6Kr!&_WE%d8(jF$HJ;40U;7_O zQ9CsrZPhl{u8nuDZwP*@PT0)sQV~0B@8~n9P)-?1g@~m3M+jvMejeS!5a;%EO0={W ze6vE-P{hR|pwo_VtMst=fMyS%(K+h6DWa@zRE%CrkZuap=(O4`b`tKcI)^NMA7Ea3ESGQH32CNy;|fF?!o>6pgtYgezbUh++BC6(fG z*{QUiBTKM45%h+L2}g!)px$RkFH6Uf!Bj4t@gp_nw4q*=205qQF8%oxQvFkC*+3B< zY2a5QA1(QxYp2{g)3=VmDqSaRzNi7H?g^PziED{*YmpADG4WkHDVpTx>Hl@iO!R&6 zW56Ce|H07;mQlsf2&cSWE=PY&h&KF%*p0%sh1LxDr_fb=amn^#bt2n0(IIhh#O|0f zlV{Akh0JlW+n-0^M{!uRqnnwZ$z(QkaPXtLW_!YAUEi>ie4o#8tppK!C*>iw#4{(( zxa=XCB+2Ri$VPkskwJVj#p6Ylj*^P+gfQV0pIGgo=Lvo3;NurEf1$adax9vDMc(b) z!I!7arQCGddoqoCYV5J3DSke+S;RtQN>wkfrg;%A>; zp0siOC{{13&I_O4pXJ^^SS7pu_}4U zZk_R}`}n&Rg6rt_`%j*6zX@_pq_%6Nz6p5B@c<aXH3_--`((^T;mUi z3D$VG1VnJI7@KCAreJ zU@J7YX9==!Tc4lvaLFIXsqjg9_I2YiZJrdh>Rt zhbkNQV>&4%r|IA5c(%O|3Nj1iAjhQFyHS(Ma7HT>4q6HNYOc~F^p`UDhZge1AjfVl zoXbZU8(;Y$8LaHzoUnbt zo4V&t)m#2wO;PqJmv&wi#Jxw37Y?TB$xdDMvXn7dr(`ZX@QF+F+qSS3fmq*Y7oq*@ zCXX?9j7RkQ&!SfNZCR8t!(%(nKI5Q+_-Xyu)h37gu9Jc%OEfJZ{Jx173BFv%X{f&z zura1z6lv4sH}Y??Vp>9*ZEa==d1)=W)1a`n8K*E>JH0rW5i4s-QH{`YaWNtv-iCE7 z$0zErPvJr}Z5xcfG&w^%@gb@&uU4%@Yb}oMe=g(gRiQ_#;FPqy`Xuzjq}qv;^ZI|W zwSNaxYsUw$?bcUv12CWp{rfr{JGuuVFzhCkwmQoo^%keE#oo6--EYqfvEU{|T|maF zu)mpqQ@oaaSl66CJUAr=s?TBxzpVn8`MrtZt@nY>Tg}MB?Ts}XNpTG(XCsCg(;7aE z!kMtzX8gmVZd2ZrwC=#sASai@e z``9RA>pWy*Df8Y9bn|Z<&K4oK-!jN1u580OUVrc=23z~N+_H=n&Km+PU#IyJ*Z!vd zB~Z+#6aPbc(G zv-Kz0-td83lcI4~Z(B0_dEFqN95a2HxQ`jzCIql9r8N|cVY}`4^A;iaqHcj9?BW<2r2L>F9 z>%MRHB6|&ubQop`q&qbYn$^#?5KrL2-O0LPik{5^e_Gq0WtvK0Y=fAutFA z841@IeunXsRn0zeSIPMX%RswbnPEjLyp4x>9KKoJN zuu+#LI=)jD#>Bsj82%w&;N>}xy$vD}Zog@U?V3t5u{qI)6{||u%)eZCf zCeVv&UpG)Civk4#EnZsM+4`cYUuNB!P!klKUEJ%Ts=Pcc_YV(S)%{Pqcxkv>$f4aio7W20-(C>_9>uEOZY{R`V=6Bh12h>oy@H z!i6%d6B<$fG_RaD)7ehis0`1KLWFBx{?d#H=UjrZ2CD-D9m9WBD%IX-#{C@y_XKhR zAd2F<4)Wh)u)`cs*uaw<(&+Ku05}x~x&vAdww)ihov+u-qr;4jhp}bRrn4hh}I&MRHM|Sub14}O8(E8hpH6zZ~&$q`Gcu4R(7uR(*(j*)1_toTb zl{uF93pA7VhI4Gs92y%un#xt*u;`X@koc@Ve|e>OnX84&rr<{`6Puu zj~%qBErfr0OYUTv#stvp^4`z+ncv-%<^42Le|nZsEIsb4SEi(n zsGD@6+0OEMqa`f#s1p;NkDCrg4_gjx;leb^!`a4OQu+Vw6>h%xML*xh>L@F zZ3Y})%gN9&gmuW|Mkvq>x1bTz#5=(m+~6)(tpew);Pco8zfz_SJ`S+eYR1JAXbJeto6H$h(liO^}~ra5TAnU4m5QcgETw}f4p!~!I=Hc zy8Rio+;Z6`JYI)>YQK9GzcF#W_&5Xlvev>6T0yhHj)ci@>Lst{+pFZ##cEJvkmd1|zF78# zGw;h*g(B$@Viy%|SkE!j_0y%Ha*_~jKW{5Y3Cxb3Zdw8%10lr8?00?av#$rR-RW~u zTx}c>c5zrxH8_M+)`T;<%f6USU$Twxb^oi~N#MIQl&np+{(KAr$+B@`NZ?ZOJ7dS{w~QGB+!^*|pDf>#*NR{DIg0r=0>~stF)_ zmQ!sb{&GS1Af3;fUK0?S{}Fvye`F$Xxdk>tijXzSb0C{lRS39}!c#A(sYYQb&Sk=b z5c;iCq>RB;(~J{A1}G+--9d`z78volSfrJjX<6lcn6$y(=29vzdxd$sETn*@ffX;g z*P|M(zBknsdU7w0FAx5!70Gq)fO=Lf?Btin{{CkUjqEH`!udkJW`!3rxXt-6Kikb+ zo&YDe20-?km=_7kG>%kp9xcMcAGA$2E~pb3I{|myxFle7DAqLfnGI)q+MYu9ugz|2 z-XHA5j=Fx@@5<603&o3_~EnWo#xC7J*yECkx=&Oi<5% zun>ozL3s#~LO<46lucvD5g}F%C;SR3Hlq(!@c;bl%D(OyMvVC0E(hqNrUpRW&uOeb zAp8ew^*6V$)d+mUwL$}t-{Ez*06Km!U2L7LshEu=uc#8aGq6|OW((r={A}=0YzK`1 zXUp!MR+ED@u$hqEUOK@9(0cbpg2rb=Cj?m-=FF34%5Fgqf*_G7J3cv{BKW?CNsF(m zn>-}{DICpE5N=eWOL)MAnT>SCeOo{mTv$d}$~BuK&1ropv^Ds;&?+N_)>G>I0~7EJ zgoHz0fxI`M=Jpz*ccn}ZO@CgWG_Ph+Ue+C#YoIir5#TE@bzv(c9N67fC9GHPCNGptiCQsD`KCk~MSsKz{s z$qx&m_08~Bi+p&EUxS}GE9?pr8jn1;P5|wg*w|CH8=fTUlU0T=ToP@) zZO0l7lX>;JYvflgr92v;f-}spb_kIffu<(+zH89)7J|~BJK4Q^J#izhI{EvM*a<;9 z7c^B9SKBEztM)y%LdhuCeY#`m3-_$3+mUQdH8EBhCeoVJLrpM|(uW2X&t6g(Lz&^~Pt zSgRayRCn=6k6WXPh;|CAD@Q%v``y4|lfLpywf0ftDr;YlzEZAz>S7C|m}Mk`jxQ7@ zp4v~SKVv^gP&!!}3AH!G)OOv^Wlx^4JF_W@ldQ$X_!2<5L6B>`->>VQ5WRdrK8nG za+%?G^~?5!g1{QR+ul21$&*WMnDf4j8JrnPCj2_}Hn}f?+I~sI-~e+fnbP=5jB+^z z;6$X~!Y*(1!KJXWS2nl~4^bxnJN9V|Nb-Nep#?2HCi4hy7~52>}e!<6g0?PFC#h-p1heK$ylV45R*pFgNJiV+kiV8hZ+ z#5zhU)pRf6Obt1hsl#3U@=0VU*sO4MarxPE?{;xwc|Q1o*1zDRQ-ukNG+$qoBVw9$-A^qH&Fp&%y`wg9kI$P#SptXkEy%Wpq!@vg5~S(N+BRusptjVqkmt9hu# zIoz+6IizQSeR%@EfJ15*=U{hERg0q4b(!4njt2?rtjh!)1roZ?}bDXTBrk$nz4-}o5rjJ-tWMZ-h2LpUtR3>LQ`AAeS5^F ztaC*oi&a))MGFfPg(31^*wl4}Y?mfWG;Akz7}wjAkW0Yoz$IgmVef<8lmmSD*ps{7 z!M{6$DI`#*5Ep>oybREDf-RsEIXqIJiUsTxC*|3cJ7Iy78kJFx3O=1XXY(r;a+evo zeRkCo4vr^aa~KcK)hbtOn7vGC^&ZXH^tt_rq*s6hZZZ;=+=A6swr5wBU|>*ywH(7; zj{C=Bs2nNPq_y+fbrfTxLNdU6#N9sKTY%$^1W{L6amRR#*N^}L_Y59u9Zw0^jxZBF zV&7~b!+fLx%$k2nKcX9JC2vV>UB693Z1|kD7*!D|MaI?ufp_WU?qOXs;y&D z-|OD_d6ji;#4X1!&ts4xATQt3n+{v9pxvgBdXN?4E^mRvFuPy|)gum7@l$jKj5b^9 zz+meg-gR+%84^FIB8;nH-0|%1?nerCafZN9#yX^4sR0-aMDUksgKOO z#Vb$g4lC~SH4eIJB%p=Nz%A+x7AW_i!FF4gH3RSYVZn-OJv3`CRJjhax?+8Q?soLD z^6HJe*zBR|c2Wh`c4imu8*ug;Fx?G6vlEP^?_O+X*PsZcvI9nV89=(ylYNJ$1+y7hwj$ORV-roV zL?oG*q1wVt!lnc2LxdTWR8mjSiJ=Pe*ZjzdA-Co_S!-xKV)jxXch5M&AM(l4SWt~4 z2)HEW%|d)`K)D?6nK23B9gbZ=-jWidh%EBsrPY(MogiE}X1O#n*t2-isobC!g`yGr zOfv-dH#TE4Y>v|E!dKk!m``Sj3C%tl%i_aS4O0B_IFJQA*c0dw>MYq|{%~eVogWT! znqe-)S{KI;+b!too$PO6Tu1~2@EQ{>f~u1H<2Fexh3;aSNfjV|p@Hsu!?~{6^mwPV zlQG=YNL*|sein9(b(vWNf!-NfPr8X`=VhQ+JBF8Gh-uu|a9sc8^2lk4 zI4YD3{XLLGEe;d5F9>8*sUxH=%Wn@EmHh_L(tuM}B-~vj3l@Fm1$LzVSXevLkd{>q z@o~mBp~8(PRif=0|F%y!y(wQv$w%aGZ`PD7#w47$%oTLHT0Vs& zQe05y{RurH3CbSCO74pbd6Vp8`g61mNih78-YvVGEtstRzA=sMzBq2hbKkkXY2pRF zO@}q#N2_B_HzC_pVk~wQm|DGYlIfsE+1|GO%rtd@x%a$1doSXEdQ)q@vilkKeQ?UM zf4g0E;GA`N9$#|CJ3^1XrGjVJGrsX{Mb1SAZrJHRJp2cU*0c|zfhX1`yA0No4R(x| z7XS|{|E(|ZS#Pg)?^W@(4uIR_8u&JuKON&-C9=1oc*zu#j`QL#0i~SMK;!bN1A-)` zQHS*LDwZM0CYR44zaIQcm>H^|4&9nn?ji+J28 zjY7?M-o{7{QvN6jO+LN=7R~?+@~I=0u2jx=sRm^gsEO205lYFLxB3f)r7~hdV?Wrv zd=TpYVxYY6l`68nkzaXb&s={(WuD2iN3E3}<+@0epnDMtgb;~H&J2yELT8I1bd>Qx zo{5nP>8R=(Av-;mAK;8=>rVWLA+*&_aVdbrvIBb*sBp5m!1CIL+MI)Z$(bwR@8*g}@K zegzO#-<;rBuFeG|zr7tA9V4m)!z#axtzIe*6Hv3OP7h}*kZ`1NeF@id^B4n2yqQ<) zVi_^Z{+>dNF=Fs(WR7zOi2~FZOdz+$)e1|=1)-Cwp~Yh=@!r~S*<^{>@C4cckrlsWK!9_tm{tDmDT6Zk{zWJRGPUX*j&dNy z=}I9mV4!g)+r4&u<=&IHbB!9RHLN5mc^IgWY5nIb{h~EY{4Jvc=Pv|-;U*&4H3$+O!AB~~f03I}x85gL`Bp)mpp zV=e$|c}_n~(L*xi@KIbWG*$$rPS>&7z4F#3e-LJZa&f3|YkA<~XsE2c^fn`MLN?_` zfluwR$$5`0rFso&RFd{MKVUC}zvbgt5+qx0E2jtG?BRsc)g&mTKnm7T?sK~5B9|LB zNy0wNMqisMs?#Z`k`T^uiN%g*7DKp{fo6QFc`mlf4v{v#4W46hEB+Ffnev1W-2_gk zUgt)rZx`O+6U@Ejw4~tEt+ZAyq=vTr3dX!(Fq2w?`S`pSL4kFNbhnsp)qB&lXMOYFlY_fy1SQ3=@Hp^y zM*6j!%hoAysw_%ku;EQeOQ;4O&ye=bl2t< zDQP|e6zHT&x6>9>#-;w**pa0$-G-AU(<(*x?d}qLdi~N)&7<^g`>+Ld14au6rq7jd z1rn9NGe>`%{G}lo(VnMNIX!B671nC@)S*pS|jS6qktM=?ZXXZnbQwSR$!|yHQ zbji!Dl&`GW(Z$A=lXpgazSjBXlMXp9@ludGjj1hS`b7jUn$C_ihAjF@6B?U#Jql?xn$q; zWTKh;>rSNuY-WvdLwQ3*=iPl@4&kX3VqW~~F~{l2lKA*wsy%BJGbvii_W=5zi!4%N z6Wq4d_V>f$6S|z28$mTAE74y~Fq)YooGOs^NGTG>KQoF%I01Vy$+t#e7AjdoaSV=z z5Ay10*g8a4rx8kMX)sExPwMFJ?$n8J)I7o-20$&c?M_*X6*h;DiQ+~cg3R!goN{Ar zCeJBXOVh2zyRhrgGt4^;sya0myD&sJKl5;>c9LD z`IGPbo0jmIz?gQ#PcK_-UD6o(eem&lQHTU5rG-0~*nX6*0_>L9E6$8ued2oV9aDQd z47k8$8cuLNNl&wVdvWu8m>#mP!Mn$z<3QdH7(b_A$sq3oX(LzKg}=pktVDfGeF9+~ zg3o=3Y#+K~_MAZl4+V~!7SbNFEHbPaKiWu=S%gA-PcDo{46&XC02RwoF9xla2QLH? z?ozFyJoH}yb+!cr*5n*No+M1->ScHCDK*Pscbp;}oO&V50I``kfOJ(M1jNI>R*JVL z?qdokEfQm{fCgIeETD%PIFjWD~0s`ia?fhL)PX3#n&ew-uyK?9E+ z0h4*f;r*+1@zWs3jFv58Fq>69&r8!(|{aCpr z%UkhN+E1J6G2{U0X(8i-I+KE@@dz77e`utieconuhuXlbStzDtz4SER$!71O_JK~m zj^^>T5HHpG<&-3y2zXdTJDTLqkJ*Lij;KYfa^`x#@IrZp&v|&6qiM03hRl(=>W_O6 zito9WVCrRE-5ytY{kmQVSaz)%ZURK4ry#p(ZMhvPnt_T2bbTMPDqVS2*7I&>io<8P zS2Dd#U1n3wHCHJm$J z*jxV4u02>eJ9xAv zCvsh)GiocUc(FWNZ>D|3o1F{*V4to;u%fSf;G>H_dOIPUWiSeJVi#`lDo{Cbr-v^G zWPGy_u6>HAm)StEs$r3xn+EW6kPAAH;)aC$!EpX_CE$K6;Myg9W9_{tmotO&Vv+ET zW|sdb4<0o63U5wqD#b(Lk=2*}41`TIL)-c&Q&E1-pWx7!Ox8ajj7q_o)<= zC3S9gqoG2;f;{8+gvH9rfpapif&Q#&UP)cl&tAP0%?g|CTXuY@Kx{K#W@+M$v2>JqNHOHR`)J*oRuzu3?o?w056)bM|Ocl%O6Bhz6WOn%_p6T;COR_sXvbshVo$+MmO?M&L7B@WCx)=V%ZR4yD0ue zm;wi0zhQI;Ic|VLgW(s~SFyQ3^#J&gkF-^fu1L2QL2Ec*gUA2==6-`V%g{fb9*oQB z&`|60TtA7B)oZmg_+ypb6})#qqsFW3Hl9v`d2Dp6`tmR)fXyV!#*q$k#7tV54e)J_ zjUDDsguJafOfi_*%||gwNmMW%apF-n-4_wDcY`LHR$u5Z1=ii#PH1FH86oMXj|(Mq zl-F^MqfluK=Z+lOnGJ19kaTC!*zm^5VdfCNfFs z?!tPEEV!+G2l0ve^D9bK1Mc2fCurNL%Hlze_Y!lS1M9rk#nm*9Q&}F?9B}$NW)_^d zY!P6q?{lF^JU5FxG(_uol#I;Z;2^XL%1*EUi5rlTZBRsjQtH)m4?Qy5Z-+QL+v)EiNX_ z6&lHP#BRkWGicwAffKe>CrnoJwj$K~og}n&u!rC4ZN)yyB^#&gw<4uKkkkzZTDehq z$#+}s4_XP~ZCMSUh=__>{G$aJj$RyX;wx_|8%}o0(o=48D0U*15^#+Bud~(cpD18j z(Fg1`FH@q1<}XaPyiH^r}fna%twv!n#D@%<+zjmvagmh~-oaT_nMcqaN|Y)E-6x)9Kdq z^ti#khq@y$Z?i5u7**aFc4sFRtapE*3igr_q?38qhRQo~In1fO>++ZF!KIb-(_OPfWc{Mo>lnnPvT9(b zpds+pRuaHql**WAoCbNM0e@Rh8(9DzPwr|Bk(XcH#iAhb)-4}D_gsbFq++h$E~!QN zh-FdSh`vMGNqT#X#XYJ8R4*1ZakSG%IzrQuXz0Fx<=Q! zu-W`;jPpyI^m2v9^doRb<@+=tt{lBerDn{vK{k{iR-&*f-Y60hdSGTvNF^u@=(lFq z+b$nLBtt_mam_V~D%4IE51FDWw ze6_-q+g<+jxp}Ai%DHT;U9PruoIuR<&>QKrY91?Ql}fF!d9$OXn^E*~bt?ZY96SP! zz{vWI`$wN)C-+UxqehY1wn@>b+`=y|=kjJxl8<<&q29x%bro&4tGwI0@I!uUP33;s zJ=>UoE$YRRS96C~_h0vkcQsr;R@6@`$(MpplT1tj-yPd)?YLDUEIju{=f!-SQ5wHh z)BrCJb~p2Q<8p}dP>6Ao{|j@j^GDUHYV6)BNwv-U0U322WZ$}@puaTTT0(IcH0owy zvPe)G>w$=nY_vl3eMM>d_a#G>aJwrH5@h(k;EM&@K?5V=&F7VFDNf4GDdzK01=H!Ip2x6jUdg2|N~=dXTJv+0 zwTyZl|L@@BiAD6=Hk=d}`6pm0fIA-&+%>!{i?_XiUMX|3c z_*uFI+|BTqEBtdQ_4{E1r<{}B=i@m)&OwIuR!8y;vf}D7vyJi+`KYdZ3KQJA3iM4S zb9~7<0Vlw+d5AA6ko0SRQmEue7F`t8MYE`o1=qLSaGPtjQZJ(!9^^2Z;|N(_`KXge zuNdk0mDcTZ*O2~+-uC`CLx>HvG_wqQl?ke@#sjWVrxYE@i>7o?w)DhS0j}h@qTRV6 z8oqjSb8e#$BVngj;TH|?v&^zjx2x%dmGo&ixk_*wu7g~sB_*HUTg2v|9dDv!d_B=W zHJK1DB12(#zDm`f(GocbYAR=uKILHhXY0XyPuX=+?ObP8QVeYvW2hiz8&T)JrFg35 zL(A4kc!j+RKc!_sidRdI!D!s=vx|Yknt`~d!II&}dl~1oXAto6LPEy#D=sDz3JmF0 z^#~PEH0d*0H$$O%(Q@`n@l`T3D;BW}qKIvd0xEIp>G!n`QJdNyZ?)sE)ts#hg-T8K zA=q~Wh7o!4()uh6_j42jC_af($8od;CgN#6y5yo~{)sZ?F7rtAtj%Ufexvb%+bD?s z&~{Ox!ombhQ;SDR!?~w?- zd&dX`E#6~0b9KMwBJX&^=3QJhllE&ML$t8gG zdYaup`xFL!&1kcb>=Ut{O@DC$2KzCM40H${kpA6)Ef@}!Q%aIM8eg&Fqm?+W_dFMu zqbOJK@U&^tjTz&P-6}4#>wCx1Gd+_2sNGMrl+jHm(A7*I5d0PC z6La>!y#jg96guSl{Edh*(dA50sZP*E9SVAmm6XWbjIGlzA1!$*>=U4z%gjz(!`6AMQombW`dBMl9~X-&1eD{Dz{-L=bM z!RC#eb=9roz%=R8iSda+nyBl&iJTuH|8~Oi0+qi;CuU%U6D~BDsCIjNeX!*J1e`gG z1STXlcZ4Dudq2qX3uD$lm|ChYm3^Pq@0a({=U*jg@3!Mwe)oOIw&xj(dTXHshml2> zkGyY@)T4(wJt^6dQr|e?G`$BQ1Iybn;yWe*5tFh8SMBV!%+<+Pli!dmFQo?c@_%-H z0&^5ee*oZq+fy5&w8#o|HmjP-GUUH--c=Jhp%@h(nu&+8wE+knPGt3LzmM^sy*0w_ z?FBWjq7!g(57}=4^E_MhRAP^4Um=fe3t#B$8+SPn{Oc0TPu%KHEAWI{el)+o(or>^ zxWgjleZQ~Z^zSl02&<-co8H;bl}=`*suIzX%RQjDtkQZ%r(#MN*%lMn@m(4F==DEIMI-c%~aC;3D+gPN_6F%?s% zQRj^VWp*#|=nw_{LANbhtff0H!g>Kgabm01ZUXy8M2~t@3U7uiUm+iJE{A5>uFUWn z_s%d5XpqZvHG`mOv#lmYMOiCQueq_v&*U#Rg4^y*v7d9CJVTh|@3|@RMqi}3l*qkF ze`W^vY=|VB`9LkZ8S^SGS3{)WuQ$>Txb3qaOa;Kp9!5HQJP+^Cs1O+{L!xhZ;|@MV zFxkbW(KuwlZvZ&($qI!Kl%NKkb{nR*Yq|anyZ`ee^&dTpB!p+@wtlnB4X$@V$<;5@ zA(sBzo=|Z88?rFAFKNgxmge=+obVX9!iIT|iXmYrgT!2xu)q%p2pf^W<8TG8FqXz) zT1q%)MF|e|?|!b?XI*-Rh@y*&wvzD49=p7xk;Ny zwl_u0S~G5E90%Ban5+i18=v&n&~;OppkK^)@`M5gUu9mOJ z0^$b@>Hmhi+L^uJ4P6x<+OCghu zc~agVBv85ACy<$-=RW1bQj;kso|Qid{Tv#F5LQbjhKf)kBBcbwD(ZG~vf_$a_%wj8 zdWB|4hScMtzMx&&5Lj@Oa(1zfqZ=rFgW;3@1FZd%1H+|bpTxJX>LTsW)P9wT&v6YhloyTASvVzvfzVgxtJlC0n>%GIoArxwU(Vzo-SpFRpYb48W)ND8 zZ!a703KZ7K_hbnyVwQ*HzIc;{;)e|I!XK6Gb4EiJDVGT9$4#9bq>B`s;c4a-uZo|V zx=7yHWA~z<6R?r?y+l@^DdL-;jke+F-s-D0fBU#Ely-i8r-dDz$oN}M`VXA>oqd^V z<75uDYVm~V&KwMGrT5C5rC|?H`{|8I@+1D&Tb4aj$nINS@-b0~ea* zhK9c3Oqr>1s~bD&e80C=V<2Wzla}PoABsg~^C3=AM2)3C)aV(;_Lm2{$%ovpYDHVH zm?m!`O$jX}rKnf=h=slUVXi`G;ESGjY``RP*g#C7!F*wp9FZz{CyMv0&srtDa0%B; zdWmy_=OdxcW<_hyDGu05odnc1HR<=Q zzyTi40ZZx@a8K3P)yFC>qDmKoUNP@jIrbk693XVwvv@VYRv<~YjFl0!9+S@jM`$Iz zUd$|K4~RzStpV(uYdIYxH59zKV5pzo*Y$;3 z_$CxRPo%=t*H76KbAG)=&f5~p(V5A0VL{7HZgL8j?s|(>9C;McPqfuQ ztmsaqWLgYw&YyQZO-vkR^1I@VSN@S+DKf4bbSrrvP`6*rR=#$Fr81@%xpFIASxvSo73*s0N`ebx zu!r(ZGk|AF>m3j%w~BkG38F|(tH2WvI3K_^CR@z+QfX?`RM+)*&ViBYE}R!nJz!Up zVt=+Yrr3Y8%r7`v@J>Z>#6%`5IvOA|w!WPrjF)vK(phQ73Y*p-)%bQFBQ!H=qI_TJ zF?4&^po7h`(HM1d?BUWacc42_3ss8h*E*)VQXz5Id$S7%c+(1{tH4&;O{m<=pSxB2 z_W7v1Vp4RTU%8CJhdx!q{Yjx8a%|C$LKEh`IF!i3iT7v2$<_%eKCN72ZwW_X?Qzh< z0CsGr5V+xpdZO1%_yaBjD?}OthDG$#(Zcnzg6?ys14|TxRkMR7?h^$Bm>?wC$%M*F zd&Rl(h}+77^?VCPFwME!Imp7M?iGJVN4Va>>F2T<%^!uW6^p@jV03>`>Fak!G&KeW zXV(O;`dELrTvXDesgZo&w6C0@sg;<)ERd!1}peL*GN)&a2WV@SB0}CYjx+N8A=j-)^sLGW+i9lD0q;R}S3f{lph!UPRprV_uarq#$`G#VKRJs|R;v-hQvm9MqLk z%!f26F-w2bVn?^jZU&v2C1p~5@W8!w#t!@kixTiNu;w$ zEz%Q@@d{h6>yyTCr9HCxL#^v1-|hUt&GmBIbr?T4UvP5?f_rw z=ls1kS)HNyRi#&5!Y5v>${eiK%oSe*tEVkW&=nQE6*@`0h+7Z`C(O)hOxX={Jn0F! zt4d7ziI?%StoH-+HD-0Zs!8AbQ_)!zKU?g@HOt5DOYltZ8;CYvRvRsPGctIb+M9WM zu1+8=(g=!w`V?X%KxzZL6+9&x6WFRVBD%l*H%22{534U^z_O6@G-rnC2*95>ILSfbH|Z1pJns6jrJ799SpvNCXaLyq8_Vh~*q;zM z0XnzKkfdrT7)9oxf;!)0n?vg#9MV0W>&)EXRhLr;T2y+x&Ao&z5@0G=T(m;)5+S<{ z+diO_C~|WPBOvA*FMp-Qym<<&I?RaS*86eAj7h1x>Pv=Xs;a8(SIT%>7zYl8fNq7T zc+}9$q_Sgb#tj*c84L475D01Bq}i%7I&cfx0YB(Y3>hxp1Ll<>bkB}c4{yVDSDm7x zw30LQJxU#mc#a*_K5pvnX=NV4&U-XE3Gm|EV_>c=NC~IqSd`did9H1@h+wvJyT5PO z2H2<|U-CElvEQZtY8ZdH>%|L(g{7=ZhT>C@#qPJ>q8X=37SoRraYG$Lq_ji$b^Ten zC@9hOZ7xD|H#VC9yt&!iDr()6r*(T-PCJ<5vVbEa<*D|(oA7Ksuhd<06+w9#T_p+RsPt)X>~Iz{pW;m^p3Dd!S)zZ*qR;+E!L$bY#DqMx*QVrGPuEnQ+F)`gJDn zK{yCS)YlF#Kay}Y#aQ-}Mle^yr3k@9gy zJvFVz{mLNX@X;NxqiLq|kLJb%qru3}Eb1o(tUUe5h=|ov?KmjBZ~)OKLq!VP=_`r~ z3oA}ZheVpi`I$1d{G*g(&pWf&s8ccXz)!z-T z)feQnI7e2I^~g-vCkfbo_*eZ;@o{z=^r0srGS)`v!eP5767rcyc0#L){MY&hBP!s) zXAtNZXt~9OqZ1ww!o!rW(C-(}Y{6gaYa^`KVhV}HX2HXKhMpmVL$g%yW+@Sokf<@f zS0*=RJ`VysB@xq2HJ7MU)+WZXxo;ba@DUG4nJ7vVyE7*@3O$-|#}8jTnn3V7^x^%% z3~B(=;3+hppE1X~`2s~?h39kU$(U}>Q72dg7!hS!@B1|E)}0b+WcA22?(-YD?SK`) zR%WW22H@<|jVipnTFOV3x|&%I6UQgzjtEU{mxn`11Z)HxZV<@S7{z@?c*xzaCZ#cPgVMK=+r({X*l?DECvh?lXMu?k_Gaa)ju@6{9wHc;&=} z#*+K_jQD69A1&R;o2Ei9)mR(Oy|Pk&Z8wM%&Ity4t*#tQUQ9BKyv|#EeDlw7(%;aD zJN7zuzTGr1K0cJcxNBK_Ouc6HdMH8qxk%M%Pg9txU6^X#@Dk6fU*{gk*`n>lo6_4m zzU}6&l~xOB7;(3gb^Z#Il^D(^`g>R58hY`duFkN$JtnYKwcv0LxCuI*b5EI5Xz`-M z0}p@Ey3|cV0qjeZyy@4WSXThz(W{ll`|Ds7oWtQpI<`$W1{8d5doJ>1$3wUvomK{> z^4aWb7H7iAabT_u#Z)@oC{u??*A{)DjhSe4;%0)yAgk!E{Dur*nB47#jaNt-(a%;? zgjg*agHZ{P0{tOAxku0|fm|>rE09!oIM#*T3l5K4!zJ3Zf8X~5TpC@N9~Z} zx(JKVL=N2S35E>@WRP8NUI{m?D_BPB`g_mrYJx{X?2=O(db;y%_tJ2P+rcu)v!!}m zwD=AWsb0o;i$YwFX<})y9j)d_+Qki+pDxy-KR%puR#vA6@L=Mx{FURH^FI?R*`$B48KfE1jcBS; zKk~`a+0<$F{qX|%!JvAV)+|#6lvhg7U|kkZo5GKjW41%^j}x!f4GNl3P3Uk1^9K*X z=oH!mN3L@LoH$(HaK%r%7nPeyEF*^rLCc8xzY$;r3ua=@%RN@ONywGpnZ*^}ncW(^ zvRIWxgoE-JU}?%yAMdw$ieQuMd{g(IFwl3hqh74R^~ay0ykERda5V z=69b$^4jKvc-A)-Eo=CS&KWtAo!Y#wzaDd5x9$Hx?=U&{0WcRcwJdWKz>=gGR>&=A zG#e^F=_%hf=KcDz0V7Xj?ug+kd$pa4u~=XmN>0SGY1X6`x38Ub1InfUb8tTaa3nS@ zWWB~t0+6}cI!kBy^_|H|kwBxd@k+!kFzCMdqZvxLDFq05YSYEI&HR$iOf^(+a)fc;{&_t76M8#5l}F}%>xJ1x8{H9`KZ&@K5dl3qq611AL@0p}v&ty}(7^xxAi`!>jGr4qtNh6t{Q zhLP@9~r>1!S*qv#m!hWLjRA;JUF81Wngz$WH3_{e$rQt7mN8`%=ry*g=cZWq&I{sQX@iw>^wY9_cj2vW z733JP#bEZj{uYmQe1SB2lW*&h--4#W~GN9r}3iQ-i#Z+i|aNUgPAG!yHG` zvkW@|yb!`RE)GzWqt;@wu0Kwd|RuL8U2KgX)T)_EzE$VAdi-rt%?0DKRh7riwi7JGpSF%GSyCmZ_Z*nX!mWZ7N@z*C z53eji@AQhYbkC)J7_`3U!&VBmk06;o+cbW_r+=4#9Pk;K&b@BA|Dwx?x78yorDJt$ zt{Y)}Ts_%I{v)UM*LKA}96tDDrr1@N$8};~$_>UzOzK=NC0Al!&B-2S2q|thO^PQG z%*;|Nyd1tw+{zblpV(4K4Pc)X4_?8s_40794D2F}jDq))!I2AaL!}`TK=30*D6iZp z`8Bt$_bR&3@XR85QMiWHPU^Oo>p;@fyp1Zudk`S4?R8ebL^WFN)7+Ii-I|Z5KNQk) zuLP%Tv@8NX9P3C7)4DtXd5 z)-muL9B`qufOrgY$^P6}NMI~%RvUSlbB_u$S7!Af?Ma%`2AJ)&W+a{5%gbA!Gpysc zDmL;#pAmK9a4Z(*a{q)>U2tH&s2hpGGNwzPDbq9N3frW?t6}m(s}hUdzW1zlw)OXt z2-aeV{;ucxk2CCk*OXmlh;Ov1NsJ_J)RDjX)(>Ci(nfVqstT7R2$7OGB|0(@>7UXB zwp#HdB|EON0DIk|Vvp_>K7iP(3ae7sJ&sF!nez3M&{jP($?8TbTonZGK{!X=Mt$ z^1&8A_xtweL5wXqO3Jwmru$9~3MMd?;|_)|*W7s(dwfIx_!JRtB z=L!dkeUiynWu=>|+mdVzrH%qpJ!*_1b_qQuE^wa7`PH$#ry5^U3R@;Vm0xD^+*Ud> z9C=+!fmB`Fo=~1D`_e<=&q$o``2SVIe?0I#SiY3@q_J{pM$%+u1Ywh&H|u0)Iy;x7 z?_p+V3Ys!ZN|{U5=Q@4LldjhgkkrIS&a!$Zu&aCSzE`$)vjd&oa_tq|(KrdKSbzKc zQgiyxe(2;n?}Mz4mOdc`w)b{`FP(2jUXfw^gV=bUx<6Kj*t=+1p61Yhpu=Y!0|SQK zS8vKnEld9dYi2Z#?qgbr=J?tFzDrGE>3WADvy{Q>m*P|WEQPrFPjxScNrv{w)}`tM z24nmq2y;E4c8?)Ps@*AfBR57yZ|xeGn-r9^(Y*_+Rz`z7c6jkaZjApm42VMSFT;TT z+Nkq8vHG4!@V`@gjyK210s{l{^n2tHaq)ORwim*0K4z8k;g^$w3-^IR*r9i9Jo(B5 zDG7-Ihv$=Qx=_k zLFYKyeL}1`xK?YKcFp*23ibMuMdP^6>K+C;aovizhU$O2=Gp-(?U>jX+&^M@9oEb3 zZ?sR`B3Ue|V_3Vbv?kK~Gy*0Ibvi2VrKEYFDTi1^7#Z(Nhjku=8yl;~;-(X$Cn_6- zLr`Dedo3oUdmIV^O;@>pls5ll_kT#m{}Q9l0Y7WUYcge1tu~vEpZ;LC1SK#-QDO7D z;1HMI+!z#<)qs-2RuerWN%$!L)@!y7M1w z{}h^YQQeDd7l&N9|ox=wQAbU3~x zr@x(n8&NSJ5uNn87=g$xDkydzp7=esQBWSK|M^BfqTVeZKOz%Cc!gs9+owAkJnMa9 z)gXQ3=9n7h968b!MCh@aXd?!ZPW*QcM^GMKKgMseA3lC9f8HiCdw!aPc<)d%B-y{gT~I=zhnmO+>GkCl46t|@d^wj= z*FObCsnSvL4i8b*aP9K>58%`9_Lo2$b(C@!PvIY&^nNml=QkZK1aQJSikixwJ>Vf3 zL`1U5?UH7xsj40leKGXtN)jk~{I%Z&m@I;8Wz~5ekzZW$Spc zcR=Vt+ETW1<3`qjxxSLg2zYGvaM*vqRL|C2UT|Yc6txSA9X;kwsrWZ=d@hn?`$Oj& z{wOJfxjFQ+5Dtx|-lKPtpwQ9M56urU-a+PkIp-4ye@~GD^EM-jv8&cqRg)N|EJE@@ z5TFMzb@_Zi96_{DPoY8XQB*=v+{68BtePDMHpRao)M+1s+h$6-zi8BH#4a~kOmlVy zC$%w#R8~EES>rZ6uerk^vvf7M@(}J|o*8R=C?b)ZxWHJo^m`%slk=uP5R{I)lDbS4 z1YmzQASvj(OgzX-ooj`z_SveroP1OY#;7UxvyB&5z_DFXVi0g^%O=AfhEPW%LO9}4 z2-2m3oY>cTz2ZnGH-z066S62)oKW<`FVd`%uQ#Nq(n^<2OPnf}|AnpRUqY)zIjIJF zor#AGDM5xnh$dtg?oi!$=&`iT9t8ZlywRf=Epy5KB=oR0eVB!89Pw^dLP40-IOF;* zeI;I{)Aa3`B1<9&{X(&lUq4vC4D`u{wT!~rMVm5y^hCFA8XXlvao1Ua6!rLm-Wg? z%%44)soI;%IC@JthT<^KKfuN1<1<{C6Oai=`^!0Zi$I*hjb9J! z11fB4#hNg2@OTziFA1R&KeHSkRDjw+3p@}ro!j7c(D2Px3i|jrxBMv(7+X3ZS+%sok+PbpKf2~C` zS8T6%_&qcDu8HI1Y}>5|0Mp+6N|{R@GJb|?8JAywQ#qI!9cy_3O1Es}>8H8r+%)-v zRe!m{W3rXVT^A|6Re#-<=h9Y`C0!J2A)j%$M@H5cfa6QHEtmp!;Ofgtthe>RvGqzV z!HO8IBfLH2T}-M+Fe;G@5fUu z`A6uk2LWYXgRIiJ@ypm`ioL0VHCl|`9%~h>3b)pB=be;-iyo-4Gj$Tnq(Sz>fHGeK zsf-wa7_^1MlUcs6rZ}`m0^b4Sf%!l$NKKtCxuBeEsVBHLH_zb8z}5W1LFam!^Zo3$ zrxII9OtRBF^#lu>k-Be0*g*yroP46FcMZ9l44644zkv^)d51Y_BA6@Y`jyrJWQ8-S zAM@A-n-yUftGKFK4g@b7PehY%Lzh+649&E@CEGtnDM69E^B18Rcf3BgRGZ`J_Z+V7 z2p1|yPtH{XA2rGqR27@pkTX+#x8-^7I7+3@*QIm;dyV>Q7g$ovZYrGb4$ad8 zQt64>lRGS|;s!GQ;{{MpTZlMSl%6*FC3xM#|M9PyQ}H)o^7>Ujjwf~q?+Gx4;LA!;Y#s0?05 zZ~A00quLqq269ji_wOy^A7dp=tspoSxp1tTJ?_ZiGBZXkjc4wg84C;dzN$UHO$tZGp3W7oc% z;ZX=VQ}sEtRwH935U5)dRXA31F;sm?!R4K2={TqqI+Qn@y_qWZl$abZyQdCg`s+hqa!O&LIgnIDMr-iY`H;?tvc^NABzdfsO3Qf+Bj8bPQfgU9i_8%78h3TY*jYG9nMND z#GkK3_}i4XBA7lc5s|v@GUsaF86+!cE|;q!PS;X@^7P!$&KHciOtUvp*eB4a8}Qk8 z>%#4wAM0+feqvjlhNAJbO1^h%>)X7^qg)mAIRBUoti%mbRq7B0Z>>~?U1Ns$IW?== z(Bgn7IrHU|sMo15uac48)KA}a5buABu&H>zpFgXfXT)?nYJ0u3j;p$TpK7pqdt+8( z>Vodt#8gSt37mVR^1`;d<|Z*b^L6{?8rf$EpK-Qg_z|IM_wt~F(k+wFw6l$rHg*#z z;zrk2Ik8FrJc~8M(=l>0 z7a?4HX?Bavlvic&f<-1g$hb}#TxksA1KSf1PPV(znLnrqApXKmsTWpxck?+ku!oJv z2GxGl@vjDJwpx)>nA$jcU;BS@E;f85e+#qV4KHt?%yDvf2^K8U42jRFl<)6%>=&5`%j zKt8?O_bai@fazyaFj1?wDOSDS{O*tayqw0SAYui#r`ex8`azajg7W5({@Zzesa1nm%;Dn6UJELS zpV>7~zFF^_2Q2Wt<+Bjpd_Q{hE+re%74T@t^aA`IKWIL%bz4ib{t^Z)iI(!*g~RB0 zk4Mon&RT~#lEs@YI)#G@Zw4pxZ<{%HxxE4CI+~iUQh#7WaUSfsIP2&v~J7vBZ#Y9N>6E&<+ zN3MQBsPl^H`o*VgAWyb*U)r7XHmakw;U%SKWpL(E z6NqLbwwv>-y?I&WY!D}tw^@9o^YF7zwPpemRB^?}1#dJ9@ zIx48M{MlIi#v>9U5`V7w_k={6S+7I^#t&iMGSNai8z zq1G{i337}JY>}^4jzUbn;L8_rSf{e-svV!Z$PYw*9YLIGe@gQ{uaykEsGIe*ftm%b z0Gki(gIK*!<25He%iUa(Ra1A}hu8t&BGN~x^_)o)U$IFCZCYQ5+RwsKz2`}+O){|b zXFFqOkM;+paen98PpMMe4Vd6NfQ9aNDK7(HY=usP+Vg`}+5HZTEj#;glm=Cb7evY_ zpEZ62D5ZiC#mu6Q2ktAlXvQVz1{}eA4&OaUO2m~U*az=E44F?6GQHt(R+YYy6r>rJ zxWlh6mwJPdXbm=`xN)a+II85yA!qr!-z55b3vm|O?y2fiY92Yg#53*M5{KmJqjvTj z8?N@$YTNMM0oR>b=+(%0CKtU5DVs`^rA1>=!zuBA=`O|4k)E*KAQ<%64ZQ5^Np|nA z+VLw(+BUe_P~Wv+=)hh-nWLKISh0-O2KNo-@3cJYJDu@Z+K<+3F}rhn5?(uBA=`H~ z68%#-w9eyBz%S+du*Wu)#~aqLj-F?p*u!yu)N?7sTsH6xjig_WGe@mv==ph7qo^;+ zxA`!h##hFcw#tRP_3*@waWT1EL$U1UX_VkibrO{t=W>J^z;HrDYDVjx18wBCku#2#+b>{Pk-h$ z{piG}YUS8ny-+PWJEMecUR0hNKMTcfOh)QCjPR5;6(Ws!M$t{-A_sF_MN#$pCl~rv zuo4~#Ejh+`E4Gc(Ovm#hH}F_*gkOyJiNVb23?ydv;Qi3bT(gnD9IDCYZ7okpy*dRT zBGGDhlHJ$Gvc7obMJY2lmS4QxTe3=9P0t8SVfDl8y}uS@U}c?at5_%%v-8mgzS6rm zaLJV3=ga^oYn-EM6I^4lBNk1;31=bu#!1cZrP(@>QMJm#%I&Lw;uE;W730@;hcW&- z%V*7h7dTW!;LjY#r6+s?H|eGC$vA{&@fibctY1Q$r%s2g>j@W%{Zpm9^jb%6A~jTo z;EpFIFOXy3TZZQXPF%^E?yF^=pAvpqypjUha+1-frrd!iiJOhFU43ZtdH>jAKK8tU z=cgUaoLoWvtRQ&c$YI5({#YO3wk$T2wnhH7aXw6%ngo@#=l^}=;D(IU7M;-!x?_Ip zWFr+)eYS7avZC#`9xPz9zLK$`-Dv6^bdDG(oh%uzLA+t|7IS2in;_Ky4D14vL~)8X zhQk5G0`>vz=!V<1`FgacdmEzBt-PGeB^If8qglx9A741ppn4RjXR&#fIb8g$`RfsK z?~(a1TmOy1?#R(3BIlj}XWx+dVvF>6nyo0@5m~eJeKjtiBKDQk*4-bKEcr&d^;9^l zYKVnIzsM0?%E#?fkbJR)W zxtYp~Bgn%_!)MWIY+k|h1Tfvg`H&l&T+@dI@e#f5gKQIZc`EHMc5C{0RgqWpsZs!m zCkeOe$gv%1mL5Gn!KU3gcFN2GdfD)HN4J=6wq|Nd5d-i;Yo3MhP**6OSE5g3=L~Ze zKPK)ztoZa}L*EC9Zj7A2t6HD0i z^E+KP)92+72eV3Ud60%qBH0(%D*b>_{+l~QgOgloYmc^$x1}=G@(?~@X2#B62K|$r zeRR=JUkZd9Wg{UbK_INUf?trMT-gatGgHi+>F2dUcG#2g?cqkNs~e^4FOLDB6Y)KG zVY0Z(u0d+51;-k_OCl?HUe4puuFDy1E;9YaZ*b1?x3Y+`qG5Xb&QyxdG`1m96#P~n zi|1~ChLK*p?8zJeA$NVflq&CU?pKb5kuGdj^O%U3zZpZOtrGoq3jcN*{EHLv!o-V9 zOUZ^`(wjxCFx6$_ti(nKrl^w%7Q{_10y0+f9K7ek#a|1txvH8995a7$4L~KGoh>mOAQZErQC}vtobZT6^J# zD4fiWPY>voZm=JvSrXZWWRGjrk@Bxo8t3Gf$D4z7EX($7a~^Pp`zkO|6&1_4OcyK-rSa$G;r0a@0h5zlY%~n zp5{S5cWnvqliTtRP$@|!+r=1Fp?gGk)Apd)(ituin37(%n?L)1t3vT*HOiE8VJ9i?as|S?4#WN-5i&k1|QOyJ%)jZj2U2w|I;_ zAZL^Os#0Se>vsXB1@#QCAyMPF%#xv@^C1m@C@L-8e)(+8_fRppifvBF)NQXtjn16D z;cgzlun{4V<)trM>bILxXmd4;AWnV9t!KQS*o7%XDK`z(JjB1SH29KP#$ zSQoGCArRiM7b05Z@=~;E$;nSw*S#Zgr*ik9r%^Vn+h3v=IT|p_Zfgpr7G1L#6$e%2 z4JJVh=jscF5Z`{&`xH$A{Mi8?%2o!>ISlfZmu*&TR&6>Z^J&^)Oy^hy8%1MtFD*De z8r)cG*8TDmxd;DdPl3)+M<%4|Jikjq0^y%;Tb^b*KAN5|b+M`YPo~oSUeLsZ0aB2f zPt>cj*T8C0GVdpIrM(1{sD-Z;ah=E3s`=uGeVwSf{E{=B7 z(}!BL@;B4Ks1vo+i^_(2^CtAHzjo<%p|(T(Wo(9bl}Ra^gCPtB^;f>qm6~g&=UOSf znUFTz8^X}5Qj2r&HgIm$n_ljnaV&+9(WTPmaeHMhHC7*cIX{_U!omt2mKgOF@#NJv z65d@|-8d}26BB1!Yp%+4#y3+BE?tFAFL8J9|0-rK=T}pFRud)tPs`Q_gTRiD<~6IZ)8s}=S1z)Co?ut80y z#dwh>eaPAzy+#_UuH~gmp_BhTxm#N8!TIhRi-x@}I0vSWA%92{|2`QKly^1718!JU zSU8lQ9*D@f4YwK5W2lMbY3tr&LCq>XhLt4VH`^c_d5EwdxF){X#0K4>v+I!3RdX?v(-LMPpTBm^mK{QC7132n2U#p zN17zGVai@j)~~FvmyU!^XJb-Ttqi;q0naFQFDyuFBJGHs-be91w5N>!_)+|kPvL4( zA+-pXjCmgczkZH6-le8hXJaY3XZPzL{>h^ML@+>Awy5;>8bcO~l&38Yiy@DzihERz z&rk|Eu;^!am~ZUW@gHyBB{6X3@2J42rPeHeF1Hq|@2|Y#6Bg){YjzOKb zQKMFL=h-=4P# zQAJ?ckDA(>2$$=Fw|_Mj`4RH=_C;qt=Lz@Xsm*wBg8lnQ*>VeM9&^yZZ$dEk^xI<-% zed*W7urp;k*<1Oqs+^Q24-hY0T z-DacW2yx4HI~9oVm^QYFzZAcjbVMCMSMXgHcJ@#t~p>m}p}-az{BbA-z2rTNd}Qy4T3V zz{AkP$fI_WHa_b-5TU`~@7WfwYJs-u<;`LARAcxqeyfx-8s{hayszNXk#=Ey1G~70 zy7So`HQhxXKVJ2L2wkQ;B9(t&W!nZH6%*4|;=#_e8*FTSC|iaSG?zp?DB11lOG1To z^_^bxoa!_6JK2nnk|~^WPArLFbA<23V^pfEXWMG7ucb46-%XcmcnY*OT|>#<8;$9~ z{S4w7mAi1QcS@B7;uAef%QH<@$zlB+2w6x89AB>#@qXIiW4V>LUF;?uC623CT1g+3 zw9>?CCY`fOEjVrpK6@SLJx9Va+xloK3{`aDlKOdASk&F6NRDJs=}X^I%8PEDgzL87*%X|=JMH4^Z29WUJ4{u!>mOlx~ecxr` zo_3yKrB9hYVknHWiD*dmN^KDr8mr9N97W^LCCa(sWRRGBcTl$ER8!S+%`H z%U{cgP}KR=rwWR^_0hJ))*`@iFsWzYs`XTpPo<4m-RdzPH@E7+!9m3){-gzs+#Bx(+g@zhdV9WnV&M)mOB2wj15Zappu`T3Yl!2oK(Pv`=1>bN{0iES&4XEFM>zyue3|vg6_~L$|V`F=uX0Y!n z-rl*uhMt3)u z5TBG8pahIPBb_;WtT0as(~ia7$2rLW%Cz5MKoOUh@wYQkN8o&AJgSV_$vh|U5c;yH z0pSuZNUXacH*ua<Mr`%GF9QV~yhX z?==(>b$AO%oe)-8qv(ICgR+!#uc};ZWFAR#v`!qaI42l*$TW@GUXW}wFD{~F1vDip zI>I~wfi@$3@8I4QIt|>G>ywNhUm(mJ$#?A?XUY`Nn^Ba`%1Y97rKYBK7T+))=y)vPy-I)nMH<&9 zU2KEC?$6Ax^~h((O~Xel-lGJxMyct>HihQ%@r<{#l{-!GaB$Q^Z%#2vuJMnI`tJ%2 zw)m|)XdiTur!hi|^{3{?oB52X zxTSmDnEXvUe>J23sAECz>7FUoy>ETv-bU+PJ4$Bckwwj*5;qhhGb#xQEYYvFzs!v;XJ+FF)^o;}+Gfd&AT*%|BA$uQ%3T{j%(~WYzdT zEa9&Y{(jLxBP#eb(#VF>i2i@Ezzo8x_%5eQ&fKOC|6@{IBGTmirN=10QN#Qnb6kI2 zIi7-ePxMMtp*!in-^m~DK1jtkt4gKriUlbC7Ymfkz$b?P|H!Pz9&NHif0aPn3VEoi z=MGQ<-!o=maWg(4W5QOJ-&Tl?;U5`cJTS(D)G9HqFjW-f(<6 zskMpdpUBXqV7gIoj|(2up;H>fp!&h-p3M~r{YFK~*$4VkmN^NTBggxWmL8JsjUm&` zo2jon%GX`)BFQHp4m0J~?Hc0((ETs`B`-=1HN0^b+p;vD^i?0+=>{EvFs(h-a$ zBimAsfRj%wEp7~ZYyhc6e->AM?R8cT$E^71Q<*eyz?u|7s?Q<<58*wQB;1>><5CZO1oM%3Ok? zg#(22Or@&7e& zBz6%j*mKwNfDimv1Xv0sT3a+2I5{}(`7=#9+Q-(EqWV^5kkl(y#?ONpdcWD#MmXh@ zhmW1zsjTvEWSO8Y-OWEAq1FFrtGi_z6( z+pZMQ=!n_9>fQIMHIBnY`uYXmB2h(#5Q(VetqnsTM_EFhq%aC5RmGS4Od+#?kWi49I2((oP`W*txsr44`esBg^X^0US z@qV8*6Xx3`A^tnnM0{#fIek&Zf{e@iqc26`t{#N2Osk*&qVY904lSc`-fho!1pR{Q zX}9MR9b9>uANJW4QQr8N2AIAzQEs`(9AA7i$d;L-#Hk7asvLB4&sOWFvqd)~z9bw* zbID4cj_;I&g_Aj&ntHqm3$L-WQH-_Ivgu?;jm<0I)tj7u&%R{C?ySVZajsbl2v?Ny z0<>0LBkz4ePD11!Pcl&o0n8lO1INz+l*wEA$t_0Z8s)C8nU#;nl02PeGfk~%g!GS( zg)R4Q<#NC&b&Y|!chb}zC${(<#X571cBNY7MGmU6is(u(s9=?d_QuAFiV*sb98#q3 zRs-``6!TbsX_C@rYcIG3W8eT|wW+7tI>juVjk*g*8oMBWVF1wC+0+rJTfE3v2j**B zlTB%`-w|4JM70RPytk(LGy{YyVm3b5xH%7K6i=Jn^Bd|xSiS=SL0uQu&6kbt?2xsP ze`Z)R7K2Q9X@EZ1yjV$ye=3~CX?#DB05N3SimBgHH-`iSkW0lui%ZZnDV);@h1`=_ zSp!nQ6`y)`Zp&}?bBW0t!c3Eowab0j%DU8}=j7A@NoTB7B>~km?B_01)<;;6{wAk|RUz)8m6Q|4!6S2Q$-vevR*{n=ZMCi_2=*Qt z(;*%wZoH>Jt6OWv=(#|WE4J^8jN<)WuK$PGzO9gvsRh52iK)8&Crc5eM3g0ZI_+-P zD0kXnoMH5aSYREcb_6t{HtM|5X?yWOqQUdA{klrDPBpuEYeM5!(g#@}cC%#5 zk^=@mZc;}twydqzX8Mj#`7Y9t0c{2HnVx1JqDor)=+_?yK@?`>0MTw2s#R1ryg$-hq)25lJ9bKa>bp* zyL54TLK{oSZ!_cEJ=o<^&uHtJ(~myYjp8WKoT`_f$PuPI5h;EqI+BG-ZyR4emC)KM zDgbY`PliA0-nQU!?z)pCofVW}BF^x)iGm%Yd9|Ge4-tw#%SR2>1KOLiK>gygxq6i& zx_6YpM`jgDJhan=Yc&azRlzlzd;;t6j9YcDU%$>UL9*y=yzz4`5+@nt2G;rG0jfx^ z%0gyyuIv>H{PI=dMW^{wP4e*+nr+yA?t=ws zeeL>S)6FsFtzBM7y!?w)9v%+g4&15ffBxM`%13j75XI6z@<$&dM;o{urvtVfI6A4h~*#;%|5JP>m$wjPkmv-9FV zxg72Q2C(Tz9bJx2V6^vY=8@`G6s$j=RHr6dYa|~EolFYEU89+6XsaZ8Zlzs#Bmct* z%-@>e1MLbrSg3zEG_c4{QXmFd82}NQ?!ux8#P17q6RlgJF5Z&9Hr}<vw`FC*QtEcA02G3;h62Z6b^^6d)dCydswchy7Hd2wA za~;d@&K(>t=zDguv=b3@(iA!Wud}CLnATg;s0Wh`xZ({95A-Zub#n|x{e1off5885Mi*n=1 zvxlH=t!IvD*{=lw$MeS~YqDPx(IVYMMEDdn`8uy@qY4oJFRlI_393*2#(}4@MG^2u zAa17s#Bi{x@~NB z1oO>(EsbfTA+ph@i;aUwbxpCv!ew!9FVu7q_5Lu!Xwfm6ue9zpLy!7;S%}td-dC^} zSMPsG5sp3AJeqpis0f<`oF*n6S_h8f+nYw29SLsaCw{y?r&npj!(G-KGr3Yj(PYx50JxYo~rd7 zzM|-ew^nwoAxT5M9rPNBYgdDh#%RSIVjy#*Nv^HKDda0^Y>6$R+u#F#0=}Z#l2mS1)na?IwI0Iew3S z8A&$XRl9_l>uA>QN&;f-Z_{({r7y`Yg*N#qh5spjdPr0QI=DFdxp4P&%(Pt+P1WN} zw7-X9DE?JIsN<9zyhWxFsa+UQqnnJM@ilDk?(qMbDCLilFwK?>Ty_(=6@U2{fi8l;-O3b&teb1svV2#3qF;gb+NWS@fOK zmaJLB&qA$|+N3F?Iv={uC+NjOV+w@`8!|l>x@a`DvK{KLRDGsRnkK%W6I^!p3Nnp zS@DA%(I)2T9M&{(D)4>FXZ3L`qGy%Q%g$^1U+_=`Vz>&Y#p4T*UBi`NH?pRRMX71o$IxSPIP1(PjC;j2mS64UMbzaB7xI~7$UJoss!Y8+7z zOeLnw^KQ}`MM!=8`dTZ%x>M;5QFd;DIlkm(Ys#k{s>!-dDJiK7y_1*ropyZgEdqAo zw#(IGlTd+ui*zTZXOVniT3F8ay}}12UAFzI<$0I0WxR9y*=9vlsv%kIB5SJ#l(%eV zfK4uFMN6;sk>45^dO0P0H{T7Q{xKQDNcq5yZItdV{Y33*#Fa)TbbT6rdid00J@H-? zwACR)`>0zhfws;fz9WVG@3Nm6grrrSoXaflLrVS>_CL;(k6e{LA?$3-(+}T7n3k6h zE!YqUr4}QOgRxtgE3={FDVoV`^~ITzUf#jj8eX~e6am06m8m^^1P?iQr%KOlwKbz& zE-B+K^%l_BtiT**wj85|Q`MAz77Nl5Uki)ac`VUd-<@P7#Wvm+oa<}t+5)B(uB`Pv zyA8YJ)yu5W4oIAgD9fxv77wkEaF%VL&F1Z?w1UUUgEpome)G^@HI#p4Rnl`QJD}4XO)czwns}rv4G^F=}^(*8?&v z#Bx8#bwNJ?3OI8De}AsCx0@OJCWpvKY%fi@Q2#Ty$-fDTMN_>r^a=(Ai+jBcKx>~kafRpMI*)YNh4)o}c+F@hTtqMWXmT2fLOV zo1gm8YCqi6YbJNnZFRGplWwbJgM)-W=PGp*T&}aF_-bI~7wQ+wcdJ}DCApM^!4d$? z0X~w;WKHhRq{!l1vJTs>4Gx{t2%Hl}=?IPT~(lMi9F3u@PfoHTaQdRc4_}TbmgyRn@yv8VIox0qNrhNg-!Z6C9X%EqPwwKymctvpng6sQiL6 zF9zecRlH=D;FC!_-txVsmS$oj1YnyI%gR z;E|e$dU3YR6FwOk)3{4^A*bY%VhJpljLeqKR^@l&g`x{i$p@K0Dnrx{A9xy*uX>}j-m@yNo_yVwHUerwuF!40$YV{rbYkd3;e%iO8GQsena z{q=>tRkzqCH^+qD6Gg8o&lG-iIDn*!K*-)X<-lr}x(UIvXU^pJx}UxI-aYTxS|=P7 zT{A^fI+qOk9B%Yf?@=0iY)YX$VQ3;xw{bd0Uwc`4#@>Hch2sUURSew*D?pnWv@@_l zpinC@^S2W7`1{e-%~yb?{PYOPYgTC@l$< z-O%r4`JB$-gUSL!p&Cm-gvLPdkt+CV$vAW;fZ5IwMyv6I6FQ zeLz0_i?WCALqddosyvBl79FY~p`PSLwgkjNWU(m7EZd$Cw!B%=MQ;=h-lSZq#jf>V#SI_wEm-*Mb zyvmVVN_pn~Ld@4tH0MLD)re0JJSpqgDGzr$WL?1Q4bn0&Ckbqcd*|oOA*o38;8ZdjYHr7ul#oyl2{gHOfW-i{`H)Z0&tSf`(dZJkXf!9)5$^ z`Uk-~BxcP^QmP`(>^w5c{8nRZRkM-Rs1FU7$1?j-z|A)SK3V}9N>H$SlrZAAl3b?{ z37#4D zB90DOw0n2aPO)hV+oj>#^rSR8H%U(V^S#K?b4h73a~cEVUV`gkv?;Fl!}?=+-Nn*g zl{5~wntEVh!6k*YMv-0=WA$Zg6aG`ECy&z1QIyJTMKRoG3+|6M`0U=-#ns*K^3zLk z6f!Ot-a@ELW_KxDUUsYBXNq$v?xw8*KYq&&wD_zph+S9Ouzt~2xq&O699bK9=WpuR zQMb+)$Ge_r!!#>|GuvJgxvFBdyWD4QbS^7$cv;lCTa+uJx@T%T8~6G}w)rTzXWr=* ziX%(M$X_oMH{yI{6!kf6STphsnmU(Xfspx*-3|aGzt^ zp6{o1#w+)K&(ay~L#OioZFj#N=;(7VSCRg=>-PJSG`=c{lvS{f%WPk;9-cK|bP|cj|Led?Oks&`q z*IK9RE*Bg!XuSd27X_3(tWpGdhv*h^R%^eGyDF6Wu;i?+Th4s6s#Q~TSEq=hw|DV7 z#UAlOy1qOs(w9hgG1tt1IDM}u93W1da9abT;m#xBTEDYBX6ah6ZX<^r)>~h!JgaL+ zMO%+;&UU-ljD+ASOx&XqrVCq#;rqtEh~F!f%a&(j1tAv_%zYY$r) zB_wPt_kdSk$RLH#J(KT2{9kXG)wwJ*+HJY==)Kt4E$Ct2L#;)`gT()ZQ>5QFB=A$* z)b{jrb*C%+?d|V&Jx}WAc60sqaiBOuu3jtBT>7D+a1{=l>+V;q%Yd*fU!3H_3E);v z)eL~SUMHseW?Nh_z%N$7@1q;Xfv9PdS>_RSukgXK)^c6}QEnwH6BnP1c1A3_jgk}i0BzI*YeKSpD1q(Lcd?|iU-)01VJ-?^>0sd|W zEYjnekV);V)VL^KM$1xd!T}&FrI(M;?U)c|lYJbWvNEFALDoh0mmn66hngUB(tBI% zx6Z%P$(J$9VecTnA8ZIdJPM7m1A7iZS6b#K-K(EW)k<7%7<(~DL%eISBRB~YfwZ*n z^YS9&4#{KrcqiaN+=*Q`*~c>RFUNrtcWN+cV-G=15snn=sZ?$251to!e7W+)L0R&C zZFIy7!!qpa4f8qDlLCtuxbVE*VV#7gf@DGyLT&Pgp3Ded`OU))FT-@9fPRV8QDkvXgjy>S9 zgIV9QKR9qW?J9F4E6m)xWN_8Sv7E|?6>_v}b(d%vecN6Pa@VVa+!=9wRKX+MtiH9<(El;C4o^JJX6NYQlRN$P64KpW>M7^ti!)OeNZ zqn$FUP^cJc(YF?@J(QhgBVNwQ@Y`IubH8(Gt=< z33~?@2a~C5*J(+7L|waDCikBaEmMPNjYVGnXTU*$;aK?a4*fgq!(9CxCk&njFl<#k zC?sjzgM2~w$eb&~vI9#!{)0LE^H$;6w_bvuB;L&Z&`U7!$sv)F1Q6UT?HC5J(H+4t z_B4NbXD0CNpS=JKs z1;f*7p%Z#Kd2EM4^tx?JJsnbPw1IUO1JC*gW1bx4ar-4r&xQUQSBmzd z*$*q7I&*?EED1TBqV68!9rP(vjS1Of^yogbm8jdas7BH)#exu)rvtW%`uZTA2mozL zq)Vrlryb<}xkOR7&LozE78QY<{jJ{Le)Np~C5Ms%$G&=OmDa3yuzar^sbYuYd0v-prJNCnPL4=#&8?IY+oi+*6L!hJa81TxKhDV;=P&)JASbS$OUhk7 zUpaSvj#bt1+PTa4iNjONPD)h9P4mVFJ@4;H9)J69Nz`FWX;chh@lVnE9&G<4O!kML zU8+f?;^B65eprzIPGFm2q)M$*(*2jUU<1nSsthL z)1R%StQEcq=2TQXe28A0;m~#Ub4Qf8(s}8bwENNr(~U}*QO0Re^`*A_z|D{tU|)W4 zbbs_<=;J%;Izf)wK~H~IJjZgO+5Rxi;b#{W%XR~LmPO(^lz%@ems9wt$ET-czh^J; zlG^^PPtW?-(-8`_M+GaU4nsm#a-Ga)nDAMV;p_sqy2AA+OYPLo&U`58&VRDo{_=Z% zxRR7OcK?}-1aV0UV&G~ny);o>=dAv8qxM68KLgaUL)Y=EUnG(Dr|#4U<0$ic6gFH-}SkhvazXSby*oekMEL{-$t^6{AqXc!G`&3t(ugem51)A=H=Ns$S~TRd2r5 z=DD2uilMIXStxX%A5>}PMJn+gm&@YS1ZGF_z(R*%>q zT9bBO{f1fV;&b`)n{?RJMz{hf}*a}185BzekCgvAb7v5-@8>E5TbX6UD=9ceR<7Q;dVxFO5VIM`uN zU^b$2aUJ?>1n4M3>L)R9VD%UZb5+O#daY_BRnF7nbC4M1svoq?_CX<947qEjPF}5# z0|{nVEAKxHNv`70`k&r0_WWv1^{l|m(`v6UuVcHzZHd2^)I`O^fOll#;=S?Pj-+ZY z_i}egucBx8EV6$c6LDkc_8l|t2Q`8V?ysQjDwW980qb(R^%x(h)Lu8{G)QZt_$k~l zm_NOwe!y(TKDYam&;QxEK7;lPw@m2=kxfg$hWv~j&( zx6b-*#U*pTDP4}Ub60J}s(E$Q(?W2b9%h4$$~$Ghkj-FijocEj&T-j;A`S*+8Xbd~ z{0RJ;U3TTX6K}7GT@lduG#m;^&oaB{ic_DuKcVcnZnEn+tG02}LvvvHl0;|nnPK4C zD`r(2JK+C8+@GuJ-}k-zw^uGsr?%qXHUu*(SETRECFtVo>e(hY3`e75PcSnwE)v%> zgTR~XqcMwduBuxbj@PlR%d;jbkKU>+5B3=PuP>21%hxH=Ja)@s9U*k5bPa~D!lL8y zG*lc7#sW&U22n;9>Cc9?itCPcQk(sc&V>QXn`O>p?9Z{|lc*>enMB}^k8 zt8@ec_Q;%bD4l*Unx*22HT%m?T6NRO)#b5I>Sg62=H{bbO^?NvL%QCdo79;TUUn=G zKt^5OuI5V)t9T4O(~IS;Wg5kqQMvR?b3|<$oJ~@$TQGJ$i8>KSoj99q@Aq!J-U`2J zb2{Q)1&#cXxjHk?xLvL`{t+{kHxTD;GG#M}X~g4}!qa}XB|gB zdA+4GIDo0SACZynQt!ZOE?*Sm+|qznaTH-MahEQqXhwY1=d?sh&ZC%Z!}6iBElg+M zVaL5~&|Hb`vV`=>A7bo3-)4!#{E=@y@e*=9z0E$-Na5Hf<%!POq*L2ZRE&MQD4l=J#JK zKY%`%fmW%p%8YwZ7_=6-~@!V#i)h-?_b-*U1;+xmdd` z*H7ivE_x3$Rgv2CA;KcvE1iB?J1QGJ#%5MI6M07?c-Qzs+)(>O4qLcMTM4m&e{=lP z5vJKQqc-Ce@}02wxGY({dUz4u62XpKQ!jOON6&(j=#I!8X@hUy-grHc@sG5X4Dg{T}`5iOE`>+a>|)GW-c*noGA-ZZRqCde83ddbjJCyRD$B7K$ZR zE+WKiTcUQmqHltXZ7L^3$)7I}HmsP8Z1KARi^O4553?k({pU+!vK_MZOw}ldS${8? z0AD(m^0%0bING%~i`BECVtV6GTTN^h9uWYQhJfw`w0g{qNz2#of0on!52b0i#7xD1 zuOmesIv$p(dVM!fZViwfEpq(6^ z7%OeDZMN{hEwZz2Bu}NMeLmzYsHlPeMk$GDLrQ%Ae(7H63;&x>AwGshE6maQT(JVy!Q+mNT`aFP&-D{O;o#8qMJ))!0J2QXW z=*W9grE)e3-+6Nno03-{JKpJu=pSS@tPqq5&`LI}Bc*Z6lituIJ{C7?npfHEzrW`Z zfJ?c0^{QM~bM$=kP6?_QsUqDV@?k#AAf!tCK>(#Wp%Ws@feZc&s-+&2L7ScT+H0K? za?_Hsm{70v-qzp2^jIvb9quyyTBCUsfLtT5q>O(+*1pfZiFcRwY&sEPveDTMk#(#m zigzg1ZY|otz9#9n64Bxq;1nWlMts+2^W>wH3$e4n6Un6Avtk5{_ZJ`GNkeXpfG7?zha_wVb3MYUxy-Fp z!urPw*whgo0W;EGOl_PT9-#+ z@1~ZMp0|>aCEE&^hF1doqI+CKPDvxs`#Br2 zx80NW`hS{s`kSZpuhkC}xiS?u;zsk_>cr7=Cpde>uPRA!9hC-0#VpJO3)y9*#0@zh z!X10lwagb(*x8iwO-n`YpgFHOx?l!pbvnwbh24YV;smhCqRjm|wdj+moxrvYJJyMk z7c#?0heCloUfFJ*jQr(HzVPap-yGSTTCH1|R~J{l>~5F#Ks**@!XmnEa*gyPoric^ z88%crO_)k3-5rv1l-FLpFIgZAexrP&%1Q-dyJW_ULOg$6XG#__&$`5Y72~{U-T+F? zw(=t$S{z-vMp~S}mNB}j5N_FM)<2sV&jcJW)bfRMtjTYs(VKYTwlasanMxxrO^8g8 z&0;y*qnz>L1XHwR5*Hmuc@ZY#Qqk86HFQD}=YwV*KwhXjeyP@L5?=-Af&8BIcI}@{ zghAg)rR|r9Z?-;nNXJY1DNv^C=O+C^yg5>Bh$&sFpH_|<7afROlcE{ip`jzVkTEw2G6QA`eb z60$I_c}2F^%d)oJ;X!N7Hl?6)*q_=_ooBI!b`t-^BHUVq0f`OBLEy&<;=9~v{ApOv zqqO>yW(o)1OpG(l`E#;da5^%IB3@kZ7wil{jatoB($I}fxnACrjnDGx5})7UikUZ> zp^<*B9dgS|R$D3hXtGs!E(l%y0M<7BIjM zKZ)&$^EJ>(n`wQ~{o3Kc#%DtWxb#pycOd0&(WLuI3YVrU z^PTs@p>Zjn?Y>rUj=oj#w;)3oq}1fM9z5meA8d~!+9}~|h6%?VGCH&{{l9@|o{*sk zO93HDWIhN8BJUy*(fA5FANKL2YOka%AU0W^$Jn86wN^SQ$G zR>S#)>q;(l)|;B&7H!=TZw#YUu}j(H@(04JY(ta%*R|wmV^$akzpjF7WrZjoj5k=- zcEZfrQMk7?TF|i3R6<`h$I^UDG8($FJ(qPq4E9B(N{+Y9f;Th9Ni`H(nDE61AtlZA zkK%^f9D# zW?unz%B&3>0ng1ciD8R#<30@;k5~9S+L^HwX}VL!^H?|b8bEJWof8cww6_Ps@7*Uerj0ca=03uMW`UTd7 z2N4sagoB5Pbw_a{(^IVfNN2yEd~<@p-*o#hA+;gjdYI4E!e~iyT*UExQ&M~QcBW3G z*tH1&#~3og5X$wSQmGf1waksXr#4;0eW2-qZk5|nDahn$b z^$OxM6SMLlFfcF@r9D?Y24DmJ`FpxnNyo~z2QJ}3OIua#!X5gN><=IuGFvng!X^@2 z-ewQNSV;W2`O>T9kG%<;?&Er5H#)`f$%viQ$1IunvaN37c=orV2}xLtu=~eQod8%)_5B%M##H|IPeHP6LV}S z{ZNqDjYj_-!!%B#OZ;2DN9Sv6>?1ahLjq<`I^GQJn+i04AGyYZkmEyq^j0yF_eod= zps-(5>wCE>!6;$hj1a~&CuYn1M@DAZnvW0$ZmJ)$$^K!m*8u*_iJr8oycob`IHX%4 z^5vjLN+DU_bR!&YmGZ=#l*EZbxiwDn%!e)$P(8Ty%{GJ01)1G#1ldgWv5u<5QdT>Z zAB;X@@JwmxT_Eq`c%Gf`M`*TYFZorL8;tk3Qm$T1&m!aOcmN3xCfNtYOnZ>>zru+F z*Y8jUbE+fwC5v;A^7kycqiR;%W+m&7>R z;@%r)o0|gUc{J$7ll}wa|174daQ*1m@cA%XYL!7eFtv2^*|lqa1U~TCjY&Vfk&5S_ z4+bA(R`Ogk#HSc)7Pp1+MmO!M_$J;uT)>()4^-n>%hMG?=Wc$9r_+?qW8#=y%y%WT zl1A-&=hs+1OIEqK6c`rXd>@YNi#%mT>Tc0j>5m-bwaZ-<7Met?WCeBWW`N%lB#WlA zVg^aCR75|OH%_Kj|-HwuoH(IgsNkX(= zJV`p!3SKjde7RGvKD{|q5s1w4lHoipDzbnz%alk*s3^|mg^zwD6cvmC>G8?2_$tIs z;%jjsp>unUMM4vO?*RUq+CM8{`p=XI$c)Nfz(`6R!Et|Z*g0v^;gVBqU}OYFSJ91> z6z*UKJ?3MtH zBDLn7m%NU@)RHc9joB5H)DubFSL=(riCK6EU!ys9t&$7l!$^ zJEXT|iS?76b0&iPy!{hnbU;~(QM@>)C?c-ocmXwr!J|jn!#l8TxKF~nPLe(~SuXGd zK!nN{ed$On85IwZg9Gbsk4d2M^W(n5?cd|@NtX0Hd~X5ictz1O3$ z1lNv49@5x5hgpsdFAO5Lt8^x#)uIS$e(F~_&hMqzrR|uY?bGv1qbiQ1{iF?n4Ot|3 z(x>h!F&Tn@1+)itCX$vmoVYl4;e^7m@@^joL>KcTi(0+H%NtL9KzCCE4?DgeDomkA zciXq~Jw-QrJdhD5@X0HLzcV7NRNEQXC-+OV+CW7Y8Yb8}W#$vMKHHwZ0Ka;KUW1aA zfBKcE4ijd+exNJJuMhvP6gLvBc)0_oq32$(o35OQ*+J=iTs$5T2 zAsSydFfmTWlz;ZYbb37}_r!dX1MX~>K=Y0rJ65(fGd}Jl9s0$ zgQ}*Uo?>KTvi2=MT`=?9sm`&Eyk%N%{{Hpy9| zgy(^C>R^M0m`SNgVa!a`RubXz`l<GSF8{Cm zevi^2`cFNr)tzGhJ#r!HMg89WXB*zifXIH?Z3JK4x9uL^ffHp3I~J4BWJj|-!^cej zFtPKe`U)8Sey`$!@6ris=O(6BFN?PR&|?sq+P={!tA3&);zW+03P1!0?~1i*4Uw&L$Lfn&p>&1pWT} z4V+DD|JyXnQd{b_12RezD66p%<>4M=DLqJ^i1O z`Be1*{V96?MbG~F%KxuEe{8^=b3fXEbN8pduFZ^;fFkO47x~%b{ET_Dl27YnoqZC- z9S76y9*3-q7yx{?^s7Br_Hh~iZV34^WtU{4>YAofMA>(n-5_<-Wvb!O?B~z9`T1(p zj;|r1p?ccdZ>ao+r%-cJ`J_J>yoZ*Uw4JPj@!hzg?dDcY9WS6;xFwLI8x?Z$lz|0P z=F3=PrRQadA73&4Qi=oJm8hEGKC9{W{V)jyhLgr3jj**==3*O<68b4cMa97?2za!M zB^&uflApF`ggSQ4QPrcUsHp6oBpmbdBJzE6?%w{R1+&_SCuQsa=nYv}v$V9dlV{G9aW!D0juL7N;kBgv zf&zUXpGpKdoK40-9dYL3tp*cB$3&OgZOt zyf0^?NsMlGw-Se~L+46}Z83kw^`G0?KlUnDow__#&m_Os=foF>gKhFKnn}{bHcln< zp9(lD3=zO#PL_8kKw=->%@@R=3i7czST8*%1Eo=v_XK}uH-J8M^cI~aN8#Gc0OM#2 zc4szr}Zpe3b zBT?vZYildDOKdTk1|$#xoct`I#R0m^AJ_vl#EwXNF6Y+N$YShsN-b+3aqLh}J2u#R zJJ_7!22_gyB$r*<@=UP2m)g~1TRvxR z$V#MEocz_Y1(sZWNP!%b+!nU_fjBN|`fZNa%a- zudfbIu>y{5EJ1Rfs9F8;jj|c0RB##~RjnU%?D|74gh@$-m=b*=L+fJKw-@0pOO!a6 zmtjuG7`+u4%grV=4Qv_EVMnNzI2qj2JH5JiUGZ+aoP!1Osk>*+?tCE2E0?Qx2%pEi z2+M%aO}{X!f$k=$b_Yw%l{Z^Z-vcf}+V7}DJ3a13DO!XaqD~9OkK58n4)qxEeNY97 z&wi~@##0@YAbq){bZR!M>{;a|Z@s>K!Cp$Efszj}Qt!$!nRMDvJ$tousT)|_a@4Mo zCo-h7%YfPyFt>%@V|2SMSL=0kEjC}7Bm3sfRoyJkHsc($VO9+tSbwU!1O9%xE;7I6 zrJJMWUZ9*YIqsxdr$()ID~Tob(e*-uN#jZV+U)t}3$NQbW=9fAG>5_R*t)0m!`DuP z^|i*F?fdZPE)(IrqRySha%F@t4Q-oVA4+2JEFJQfb#a5rC7i>SWIBY_nTo(mE%j0?l7Di`mB2Y zGhTUps3n;7zc5rZHBx!~=_rHOs5Hp$Wcs(mVdri|!m&dZ0e<1QIVPVNm6kZp3ib(W zoR0QOEtBxM?#-Aha|MRkuj5WVnS0~zEVlb5{b_9g;pVkY^YOBBxD9fpn12)uM8FAx!&XA|Jm4j~-@Ss3<>(oKyR1HhiEZ@v<4hk!- zmx#ag-v)Vopdvmx?u!x7d~JJiV8O}nY@Q8K3Q_Ez~pqhVVIc)b$gk1)i5pbprof{4!$~h{8K`aU-p&@-Eb}G1*KLDH7<$_Ia4mv(M92B>7xC|BK^Wr~i^8n8Nxi3k zIQs)d1kS}v0wX4iOiC;;2 zR&|ZNXzQKb_m*HqwE_hE^Cb%WjS5Hq`jH8M^N6Rm+N(9eO-XxWj#l7?X1EF%EMZbI zCwDXFV=t|Uhd03-IzHnjKjE!Vu5}SnXM-&7jELsPgQP1>IqFmvUQOs#?WjwQ)eETj z>M=xJyp%IInq&7-?3nZ=HXi>QpWM|Ye;NC5GibA8B*CX z8u4p^A8~(^u|45^m)h){I#x%RIJ_{%>vVuu5diq~m+Kufzi5%Me80yH?Pr_L4zo$4 zc5KOoI3!-{cnbe??+5ArYhx5g8EK6N{^qA(JgFi{>>ttneoIWznXd+T_yzhX z*rd*{rN8WcDJg%9$|2mZA)0+}XI#Q*@8x28i{fv4y|svyQd;N;oO?N%MY6mgQ4QYK ztOuKUYxJqiC~rA3<$nVW&mIM?2Ig5t!-GXQ`kUyK>cXUcNsCrU)uDR1Vj*G5KkO@7 zsX^kn;^Ij)=(SFLDMm*2=Ak%UF^>a zr5I5gJ!XtCbVxWj)!fgTq$CRP-WK2;324X`1+U7^?pQ*^9$x-Y@&9HArnDN!42}UH z-XCfuC54VX4GJ>Q(Mjvojv&cs=}eD0*P}>wq;XNxC|r;4J)y$YY~B(MeKoUZM&;*U z*|9{{7;m`mXZ`MD0BAn`=;Zni{_C8VeEy}oAL?5lBw?wdXM0&GF8g>Q+L5TbyAUZd z*bKkfd*_XGOT70PZ`0>rEnaH5^Ygk+zh)daF-whzp{Sk`afjKn4oDbsTMYngtj1^IhC5<;iS|^N?k+rQ3d5EaAcymA>jpha)?(yzET{#q;zsYso}?}I_ltKKae z%tk_i#FuwHsLhcExu;e33QwKADxn9h514iy1LMTIr(7;J1uKE!vxKzmMKYk&JSMG%ftM8KG_NwT*znvdb}VNtfcK*PPWf ztAXR!`B2VF+_THY)Nb;gYaF7|eOCG6^5BeB>QR~P7gyla?wNbb?p<<1Z2EdFg=$;3 z;wI-XiTO&j9W1W1SCo>6-~q5XKt`h2Yc2L@?w=>CcFrZ~OuGGvu ziD)Sy3w^pJ!Vfe-Kf8sQf1$w+H^v;EBr9*8kC#-Aq^XDREWz3Z^)wB$S}}nSA+ud4nY4@TX6o)b8J>ZfAR`J3*68*1NY%f3YKy2m2-l#h8z! z`VxO2_&xpd!54(3HQHvDL5+2`h^2!x_62K=+e{{R_rBbJ2(P@KOLn90&+%zr@Qn&v zy?#IMETwSu{u$9?jKcAr zTcGnhA^Yxx&5dXnJ^*~(ZMjd)xc=SW4=lNIj)5WLR-}hD`m+sJiQ{M)TAVtFOR>o2 zU1&(iJ8XI`g6e|HhGPd12 zQ>@!0o1mnGa`oi+3TT1lH^L-so~mC=EI6_R1F44MVpY#BZ4KVr{_S8(GcV$PShBb! z880|sNpa3|V}qwc=@>2`9$l}?DU!(H!&zDD^Xl6T_-9N7yNk*5BIaXMKyGVCwt0tY1eq0(Vb{I%r&`0C43IBa1sS1k*Vm zGko2K-`xqo5^(Pz{79745}q&~AB?dC1kBc1_smcWd6wjvH#KXWx=+m|(fzTkf$nNk z8Bqc9aJ&_lpK(IehsHltqSx)HT4<=p*DtpXjs^41KY2A+Rx91o!q>zfNA0Ysl@|@z z{XH5w8^krg7Oa)81u5EEmCAMQE^u=kDL2Ab7)RRAIfFyw_DTFvmrH_PoK=71sBfT~ z_2CQ~<7I|C=>RZttmOcEX8?(?GfKY_sXrtoo~^uZkZtj)v6*|gcPuiW-XItyLFxwN zx&KC4)BWBL|M%gMW0YFC?@Y&9gl;$0v3_@`$yxy_fP+R1W!=|@I6Y6)TVv&eYFY5i*A+t-HVHq zd2+#7kAkli@Ymli@M_x$1TCVX;GIhqt3lcG8LK+EKkEqdufVKA7ZbIue6%mIXZWLY z)ot?(WWA>E)(XDnSOD&AMmr-TV`lD0PcdYrJCD~jv&l?#590Ww(UKv8G!3uEBLTkP zL1(99w*iswhvXz58Z%|7paLlVOi{-QnrQ!SG;DE)&sW*>b1L~m6dN0HlwPXZTy#SfPu78X}$@FL9TizAf>(l&jH%dAP(^0&p;|MJha7B4#`F zo4HHlF)<{$UwzkhJ=52~<8v-jwYJ{?wD?&yey@`lRqm@5CXUW~_-9eg-TWK;{m~JI zwi6*}2rlcp*_on3fkSn9YD8cA+f z90}7eED+w2Ct`@^k^e1D`S*k7(9s^#Z`r+3)5(3o{clA{b3*%}$%$*ZP0h`kybVHS zbBmT7Pf~O_Kvk~V+Nr}!TT8R@{+TiUP=u9Dg*Hm0QHtSH(`b9XdS>kkwcG^KWI6S% zmgNcRo!?T+<}&x5ncr;ZsFhYr=mJ2&?uej)$LN(~an7$Yd?l6;Q3*@Sd!O-pQIr(O{$F+bw;PECI9{ZtQ|EgS=sa~NPSMbir*J0=^jqQ@q zL7?42)fmfYsnEW#N>_1`$ULgAfp{91#oP*ajC}=P%&Z$JxeG3lfal_JC4cav{-yzc z8ijuu71A7Zl!!1KEn~*LSvNAw z&{gNVA*fgR3SV~5{yxaO--P>iH)E+5R!?i-R0mZt>M3>S}6 z7iTf~MRsmE)>R2<^S~5onhnUkI=%v^s#=iOZhk==gqO_OMGEwxAjcF2nzEF8y3z^4TQCQ*D_&Hh<1)XD1sCT@9Y( z^BO%9l`NT-eq9A+Gfo58S!Sie?Skj}nALF)!b$&IavMAre1l=6FW+9?F#+TH`hFK8J%8d6aqYPsmJEa!B^q`<#*c`r-b^0@HmO0*psU%&|{Ebnd zjulR7ZwS%M%ETYCxz@Q&S_{vp`aF^V8L)N@p8|q=U-FY;1WYU%!{en@W2$Ui;kajW8Ce z)!W;rA=bxs_tH-zhIDU$FX42ooNzA>xa+J;-xu}Qi53{Su>Kp?{IEDb-irEC%}+d8 zKzjQ~fdFk!6%?#GNUfPYboIc|<`o=?G+Y9{TToPFy<~C7*X|5YL8}&^TwJYYS#8{H z-~=h$wLQSQ3p(p-2<|5fBTU!dU3enH(6qIb=h!ahyX9DnD6sEe+ohYgq5rgXoE3E~ zASgMhc8JMpqKN>xHt!lnB+jRSg}C_CeR|lT;r%4qo(I+Tume0ul&D8|?-dNJ{HnAf zzw;qGdpPowAV-`N{ig}fGUQq^rQe;7@y@H9&b?|p!IhY;gG-7lSkW(p0sZroCi{nR*jPq-&Pihnn=?Byr z4uI-;CreumIQ-L0_i{RML6y{rdSlArszosgnq8jOP|n6ml@8bvZ1!xu)*4MFq`imx zt>)@IX)iGm_$W7eP4#I>if6Sl4_&lj!54=t246SwHo+kDmvbz?^K_^kK<476wx`ye6&nJj<(0g9EG;`a=-&?zcwZ0xZ;W#q`ezNl+c%=^!=LRbr7rf zDne#d>^U2Up;G$SjLupN!`?1lU|VIe-3FO<`(F;0;d$wvD5bL%rpDhLh>#Uk;G_;` zWa=V^TP_rdJ5cG2q|O0Y>6RsBFr)y@=N8s;<{v@;1$8DWGRm5$bic8xCEpcPqc)!I4|SKb8~bMVTKuya13J(j1IwlafF zLx@-v067jkt1LDGb~L=DG`>KlPFGIo1oQEYjnDVHM%YhONVB}~801RI8Vjl;Y0ksh zdbkW~F$jwa1z5Fw`kmWbMZof~0fX`}M+@st47$&^>mUtsoXm3wy4~_$qPyRTnSwi` z?bGg;Q6ri~dNC|RnD5B<-1SIoau zvFjQ!FQ0d2dApwqeP-6U(9eb&F@!;HEk{r4urlcak>_xZ{+$$E= z(NFEU2;5#+(7Y#;2QhITwYW|0Ck^Z&^^Wg-QTw`jzqQaTb-(0BQ}16}1JX?O*b@fa z0_QolO$l1D<0H$rrQCx=-dP5&bS3u{WchYi-q1)S^JldlOWYcE_C1M#1*X^fNc-t7 z_KN7-4ui_7p_X5z*e)EhGQjD{?~R`(h1r@o`FWuV_OS2!E;wTb2TFvW0P2!QW7`9A zM)wkvkM9i1yC=UbwzNDnw#2Ul_`3)64cFEjTkJ_&Lt@S!&e6EST~)hUySG>3BJ=JMy?w}Qh8*R2lkdcd#8T~AZt}$@mm;9Tsn!gRnKNm5U9O1 zBVGMy>B`P^*}I=^o&L9#Y2c-ez2sKrJW!TYt?yDWxXGBF8*c9LcE>tF4)FNM{$bTD z#}?rYkcpBy*{hj1O{~5x3MaHawEFU7c)SA-^@N-RNQa)ECC^+!`vLIh?-bhzCT6!N z?>~VTcgtGgtg@}_<5K+Us(YrbytkeUcH$@^sxDWMuE)O|?s*46GZsTN3kn}N^ z!pN5=|JuZVT^(h#ZHYK_WUH0-sHW<}7F09Sd3Jv_n78=qgn-47za-R#$L;vFx&10F0wBF8d4huZou3MOtRL_D-nS0e?aGIIs^{*?} zY|AHjuU|_6;D!0kII@=T6|2U`G-!UrnYuY{{14@w`xbAykLWB zBj66`*~8-)YCh}6{+q5}_zy^>lahTIa8Y3D>B+ro7B8az-vlhWe4kG-6mt+5jHchfJuC^ zo&_NPmY%nH1V*Rqq25_^ZA@YncYi=u<#u4`AoMf zpf(dtQ}}rPocbcBLy5S+6bc4e@91?ea}rm+lJ$GV7apD@*GPGEl%Ly#ZKGh?4Rd~* z?z%~KGv7m}*zt>?Cyk6zi(0|b zm9~}HLC(p1GySHW$5sTN3M&vnKG3bsi`6-R0Rge-(UM4}0UO-B`<{Lw%Ux8;bj@;O zJ@0ix;6teQ1a4LkQ!8yLy{4F zwpl=hk)(VeZkbn9O47ungc7$l_t9Qw^JOzOGTMMb$%8(~TfUQgfm#^GiTk7ZGr%)< z-?o?l(>ugHUNZ2;q0;w0a}RI>?fc2)(=nO49Th}gFA z2|xfeU2h^U1U0Lx5)Is160I?+)T#)=Xs>a09kS=5*6K3V6ODMvTB^gQv{t2{UEnlg z7qm)-GG>hn)cmv6zpk+d*s5t~W$>bqfJJ^qz7y5QHAgP}Gc%TJdW99)I>TU`c5|vk z%8+LwlP(9$#N?endYpuE;tj^>`Ow-9@% zyq0sf#>J2anOSUkvTx`DKesu1UzdryyI1y2O4$Hblx-&UKDr}!HHDLhU!43+a^vVj z@!jO#%vL0y2xheUt!1=A{L6#pTGDO>eIJ*aGck0`+aC}pS)IE&K#Jce`yN|z`ov=)>7MnZu zqCFmqcF|pEU_GTn)?@j>;0qzCGCPW&aKbj(X<3N6_1uP`#oeJz@du`r6)J^th`I&Z zD<;!7jP1Fz5f%z6iOybAj;F9y)~4?}e$PbMRUEsREi@3|xWEiJ z?zM~(ZT&(z8i6uBFGqV0sl6KXwcR7=`(hybX~?8`6PX=g(+alaATdW6u3;nfdJaul zaO5DWsq&F8RKJF&%y)Hg#Yxv3Gz_VS3KT-y&q1HnQ;IuA);qHyTuKfon-m5od|&w* zn~iLKKc(yDSbEcx!eXMu@6U(!IX^>rGZxOJt>@Vb1MU})x277GF$}<#C;iZ#ZC^}Vg;L`f${A}9-_0UOfJJv`ys=M9ACZaQSP%BD`Uim*!VlZ z8sy0x>CgBo_WdL7mnO3!gE{G2%=z9}vlilMe_v&`-~ykNsXlvV*%y`>5yv5i$zB@uU3+VlefFs-!BKor;=xI9E%V8|Ew+9shZ7O>>FfyW z-Py|kl(KJ7$r^=tgbh!B*O@pxCWKsRk-|whd;`M(#}ugSC>ZO)_8A-G4q7j`Ux*$$AMZd+O(~^ZaCC1{@scoFaysKE zXxJvs0T*y)TV>RIwQc_)t&(MHhahwXreh!7rNp3NFdqC;{ zE?TLq^U*ndz@B4d;5SM?S>ePTm^z`#w_bOdyqakkl;kIfS(7e6{N3g=vw!tT8T_fi{e;NuQmH2 zFHe2zhW=2(X$#tE^8EE<%5#)q%_>x^Ofk?`ZB@$J&kg_p&za$O#hr!V~F zT&sC^_;-0xmxw3pRN;*@m9d=FHWe0VA&X*T;R^YM|k%iF#aDT6##(zNxn! zurTl-TFRrTH_KkAo zNGd3cprWyy?eqsE92BccL6X}^i;mvbtnq+F5Q>cFwU8N0sFe`%NO90Dg;1`of{;D)G}(R*Kl9Rn2BWc*HD#k z=|G4qHH8d%R@wzjG;0!1tk;0lw>A7_JRW50NJ{;eC({`>HU&Q-TyxA>7FWh51JY&eK6hIRD=-;t zk7NoAc!Y4(gqGH(($x&UK$o-ZwoF$YrnB)qR;4dKRY=Rkekfa(B~In6IW^c2*wm1ryn+k7yswr5PY#I{hc%TB)scZ`t8SPQ6K6U1GffIL zt#QD>#|_CF6z0%f@=O!cQCXQZmTbMKaOvjd=;yci+n>eVQ&8ws{!muR4AG$lbd^@> zmxVbLGGvGAa;Wk84#!+KD;+JpGw02-{SmNYQY~7m32vu~j8%MM@qp$%_5I5QB9RJj z$+PH21fL|g-NWdLhTo0jT+DP zYinPFDZ>Q`LACoa{msg_Vm2evu6at1E!lj5n*Pb*+XRk!?XI1dFi~gUOojR^u^vH> zwbz5dpI1Wli%tZhS*9}IN@*XMG+$wo&!=*(;Y26pma7UMR7dZoHw`dcJzOrs_vJ9u zGuSHB6%BICQBj6p>@k&h=$pY0INxXvllrS_=F4BEt~Nl4HN*@*Rz26HKL!PMNy@%M z1y4!-FMvDdCR2p47qK*KJD6ibcYPKt!n>D^m-Yu6K_RGoB-Npp5Ns88I5g4| z2AG75aXp$Lm^1R~c(s3C0Uqbh6%hGChDByrbXM1s9Rl5D=c4@@A{NVaC2oCA5f4a> z;npW74?%xK)kKo^gDP${nu% z`Itd&zd8Yt0Ty!ZAMaam2$`P%zN9tq5>176P*I2+Wjr2A3Tq3qKbi#iXmXW6T9|k= zSGu`MJ7Nk%V6Vmq7c|v85a*L&L1Tf&OsFs;M_e|e@Tx4X(Qr;YVCvo2bke(K&Q7kc zyO&+>8wxYZmIu4#I#t-o*1o_CGd8@t?OfyNm+$E*;}+^pIXL45h+DQD=a^)@;LUX@ zpYo*{W%6S~58lRr#Pm!@+`P?Ek4>d|*G}%4rfn#6t3kXk@N_@2x5)OCd7Q2FH2C?+ zJj0mZqtLI6WdBs*qd^LfU69&yQMeK^Sr#l@LGYFOvNMkKJe)4YYDbNF;l8*=Ov>d{ z{;}Ecilzy`1KmXtzt3b-xZwK-DkDxri`UNa@q$Is*VdYB-g5bKL+Z@j|6t^Ahm`e` zSqB~tFJHWpvO{9-7ctk7e@#`zF}boM&%~le&Xx6B^GAEzqpcq=d~j&xmXhAd?V(?@ zG`2`B($E;KnwazpeRuZFE{#irKspJBff@$``x{-@RK=YPhI1q<)KBSutqq!7`X=i1 z_;<(if4#66cjZf1GkqU>s#_JAvI ztU%Z~xgqL;>E$eqn^B&{j2Ece1DvG1x4*E+ayv<~JArkuwy_6 zt-jbE0L}QV2&&aj$TlK{f(~2DHB{8HuV8m6RL6{3O-ACguB9_>%ty7h^ED$dy@a|V zR+8Shz}-t_g?LKkM-bj^am+V||18`wC^a~|4C5pdmKWqH+Bo%7VV9$$5AAsL(p+zk{f5P-y$ki=s=-H8CaPls9;6-) zb3jP1?o3=Agzp5qHXnvP+%@{+S1Yb?mFCj>*n3=>zqB!Cg`QLKOt`}Icnqe#=GyAk02VB<|{RMxXyo6@f&?TMQddHd+qlcO_rK&5RZRW#?*Yw+tZ9n_!-C6w)V*D-faNik|AUHx?RGzklB^yW;QAM zvz3JS4`J5$Qv_*UwPicxea&nwf~kl?h1Y3fUaKL@ z5jsR|J)VxwlnSk$#HJcc`IPeugV|@$F~R_#-vORK>J1eXiB(3@45jp1v`jf2H=i6J z`&Y{x<3gYHc0Lb8D|&TtO$4}>dK7#0TVlM&HN~A=$}msyL^W&oSMy>N)7amlcb=55 zEz8%nE^L^V4scOo3keZ0Ea_JafL!zqGG0zLmE2fEK2dyU7u4xkd$*}2O#a5Wk;t8q zFu$%{%f9S9L{StWcH&e{zhXq@U2VVb*$Hf$FxTXSay#K=-A`0Bf4l8r-q=!P6G%EZ zm2~h8qzjRV+~l!-kX5Jgc+I*TMT5=#TUF5j@M?>BkFbg&(Fun^XSnVN z&w{VJ5Q{l~=83-SafCBVNA40UZC|uRzUzru3t{e7iebS0>SwF1t+e{8MG) zn$4FWw}6t*$_qNG?)_(ycFxlwcHz)B)>+A9A9^l(H?JRUPuitIYfdp&UtF21|4GN{ z4SDTnLavUWTV}2~3_&#dj(*BxI<8@#i6-BEZFAEUVN_awu5*CsH2GMlXNikVlq2*C zpO4we$&|rR@7`(o z}h(Mf^VmKa^?a&EoCmrlr3) z>tJf#_E1VYDaOwxb0C=Y&o|}DFEIm-iv@n@Mw3Wr6$R4S&|T?6bI)m@CP?Dz*-p%S z)0e=Rwr>b-Biu<`gYRvW)lKCw1m5JPMhc z+j^_Wb{tAD!aiH}K9judlp10&JXGE z)m_KRv-U5=34+vCw0@{;<@!Ltn)uY_x9tEi*AP=-EU0*ulW@1*-}X)7MD+%Z9d6KF zCF05&*@V{q_oLcAZ$^mEg&f(V_&YrOa|{)p>!-fiAwen2LJ&wKQ`y}q>XMm+*)kyp z*|S_b8J%*=9gqPaP3ghOBXI;w$_6Ip>IJ!6=hfL%QKf1lIzAA6PBI_q<6N_M-uUhe z!6zHPxGWm_Y*#Gdo|Lq7)z@#>Al(IFskQVL^}Jd%9%UN0b}0FCvjzY5{e074eb=Xj zoOAKYA)CYBFmfvpL(}FL0>*)p4lW~;#%X0G9rPtxd4fu$r@<}wMmdi_GOG(Vbn|-s z)MQ-mY3xYTFe-O@%0|f5{2ibbQ{nk&qybAHDF0)rIHEKj#yK~dot}<;#pGq6TLR$XpFQnmhZt3caVJby) zBFdg{e@;2cnh(J6$XUlSGQ1dUmE3GvSLdYbI{>ABxi6{y0hcojiWfDrwkrFa!qtY* z|5~dN%lKe@#@6rsJo}Ws_qt*JAnjt~USIs0?T z70H+JTeId4!~XAKDOGw>V#YEy5|EtiUUtP|6*~6lTmuS|dYp#2c_(_NC8$QU zuroL;(ph};^e6J^pulu_Vc}#Zvix%)?%*O$HZ`zbZK4($bvgq}@hVzgoUOmpWIYvf zSm#9M$BKjaS;X2zzorkuZ#UBdZqr!C%+$X#qszIOR`|$n4s8pDV2{;O+yDlFu5N%} z*r+A9p?LhEb^McH8;f6tArx{~r~o8l;R;0WUxHQG)4PiK&+XF{B#afbEXupbs|?}Z z7Z^;gbvqL~IGj9F!>AS2!6YbFdekFJ?_vi2J2D7Bh~c21xm`N{wZj)Zto*1|Ony2* z=gMtAcSEwr);vcmCBdiS3C*_ws_K5FN9Kh_x5{1L66X!8nX_Mfc-nJ=CALkjBS(B| zA23y#x`LuPtxaqFdF@s#0#v~tXj!LuRa8bu>l6vroymcvfT$nbkkN&z5 zalsZy{67BHS5v(u!aNoemgGevWuLYu>!WLC)^yIf9a8VfN*Wb;wSN_dV=!zzjZ00f ze|Lx3sMPxe(3lUhznvzhHe)Bezyoez<0vVrC`S32$F+EtfRo?n2|QB;`g-o=XO~-G0PrS(Nad=>-WP?r;M;<+DKYnO!~}6;;|Vw_r{_M*GFGg)yB19nlX6E3U;#hpQuX$Ty4&mK!ob zm_Z);@AK9S+0m&aQ_CeXR5eLd?a{BU{p;^9oyQ-xKl}wygJQl-%=Lx@%|&-A0s42G z-bB%zJcT`_x&EPyUN!sjwkKO@-Dc4ZMMd5BhW=((jzq#<$xYWO+s+`2dTRpSC{&hc zt$fMeaE3XpLTifWiDxS%!FxUdVw1Gx#GNwZ;B(xi8I3=pZxrXHQK;4Y3mR#PMc82$!+Or#s{v5GoU(3ZMVewLR8s4ki;5 zf`Xb2;+qHPhaG9k?3&8NTqfq6#r*4rn}}uV?|^Y!_rGY1;Pd$~>-I3?4_2leYkY#> zOK07T?!s@@m0vYF=_={}-Y@mRk&`kB-mKmZ3iSE|w2*y8&?CM{;hoI2vaa&74cR@; z&4sb1)}v?Ep&t#rz4{lViCDyq^B;x4p`=)|jchL(7!!tDTVSLkihWe+I^Xy*caEXQ z$bHcD2w|I;A8!$|=?yBRSwVt~2Flps|)yJo6Ueu<+sS=FZsg z0==c=&hU!+s?;cVX&<-zdP5P87Gux~Z)x?}(y`t$eYe;W8tZ#SrdjmOpRz$Z{B`vkA7b=J;(6#MC zl)9v0Vnpd+?r9hYD@b8i`$`GaVhMF?(6D^5BG~Qa^zfdIY|Y@Pb)nhWzVAYVv|(N7 z2lm5?Dkg7J%U7?kg#>MIb!$;q_NsI)=nU<;}}lQH(lHPluMogikbbi%5GW45)1;TJ3= z`^<~ptUCG4Qh&XQY1=fY_4shG$MMny5l1pE@?W@R_}JQM3vk|(U<6HLx7@i#&>#Js zftq@RIGN-!e6c1k$I|{HY6AONw3TiUt0T@xYuuyEycojAeDHk6mz=%Hi=Rf?qTaHR zV|Rq-^5cA6eF!JQKmEV{koh(U8~PdmeO|lPBzvA z0?wMD2D(W-qDu5V-iy+*G1-rP9prnfa+gRJozYL${?(`qeNwR5*0O#Qec9S%???vn zqEDwCKeb-fe*UL}Z0+nr$m%yM^i`N%RQ0E`;`>t!J)F&16^ z;Lz}@j&lDMHZ{1+ph&wOg>F;XK{WHXTDO4!?GI#6Fl90?oDMr%@|j7^05HGEyb<%& zR84s0s0_ebW83d-4QOo*os+<0=ga09ppMF=&T&JbLPd^F74{PXup$%UHDGGvD9i6g zhE*nBa#=-CrmJZy>-PX5uxDVNj%RTJ7f=k0*|iYFni^lwu9dAuRuM~7CV+o%^6MPx zh$CfoP3QDG)LAcvWc-L?(kA-h(6b(Ur)EJH656VTu%LX!PaPs^Yi7_q+YpF)cX+0H zJO-~g_2~3Yno-9sUUbIyuktqES7(+TZKAS7c9ph5v^5o$=(`-(?pWk?&P{D}X0M0_ zJOz5X<`ixj##)$v2Kw0?HwWQ|sxul%vrCO_@87Z_n=}grS{%A3%i}g;4}SdAu(zfR zIT?Ui21t*Cbi(?cAP5Nvhv~Z*OR17;@RP!r7I1pu=9NPyRg_|+YQa?wn{MYp&4naj z8s^%kYR{Dm2?iBLz)u=;NneUzwQkrn4f_h+%BeM9M^2Q_!JS}GQNm$qpUj+dBz|f{ zsR=)eFe>Sb6x?o|Yeq~?z{p~sY}IpgW|gd`exRaiJUXM815Vx))*Xhbc+y&)^80v) zMzI8z2D&()1V{>|dcI&am)?Z1P#+a^KQ%$!k!g%5OUf|?~96&tpXXh4r z8D8T_r;Uh0;8`KY$MJKoGr)(&NSbwXdz}Kc;k^3g;rSJ*)my!b5Fx=#=w6vwjmF{G zBc-vOW?d$Hv@xO^K+It%tPRWgI5mX@E{azT4Zuy{v=!mX1lf@ckCSuH0zL~>DBMwQ zOxS{$yxK7l;aAYOMfl-3^ za71JSXgSGzL)-TBdzpe z>cC{g#k3&f6!1eq#ejPy;IO*q@mx2CVkBd+nNDXLPW275GIKq$*Mge-xT=Z~dR7IB zPQ9HzHPLmCU@gxA8s43pZhM1nmA8Z_i@BW-5?h!*9{Xape3mV=fai^U8ax$L)@AQN+?oMqWiIzQ zq67RUIY)ywcZ2cBG=cZi&9^Dss{H#_mE8O2$CK~dKJ-folck9K)f?%Fe!JNt^em0eE>KD&HWETE2tJjQhItG-L zwJznF<~q0uMLrV7d+!CWQd48UXH2-sOe_zoS=>vkM|nn_e-RyWdiIBS-R`SF{vUL@ zd{#EagCjTr8R$kf=+-+U56|_lzq?_DX!olon9DrrWE;LL-5Znq(r_JZAj6tai%sHKfvL8`o(sLf(w#=~!>maJe(bBhZ&Yn^bvBp>zTCK zV3H?(cX_6dZs}%@lo2dV2D;oeCR@1Lz^&3p4FhIoG>vi1)|TQKy|_Mm7CVe+QyCw{ zj{T&GO>yfgr(wUw;gG{n?LemjbX+je&bjRrYQ{Mbq^ncHDc?NC!U_~$xhdP^P|F2O zfj#9Y1quaKGS(Y^qP66DB5t}OXT#xA>lt;SqR(OB>4c%Y+tzSfWEOfG4ofW-)SqBgC^39vBEfGg<=FEA}xN$4P~Y+5-Yp>>KaglX0*@n_Ii z;T7M>_@4_&NDE(Z64KMBZb#|!+aO6J)eDUzWUUXb^w-BmqxHi zTpP2RREv_jo`!zJ(Ob+Ae7nq|WJ(8uLO5n0O#%`3tT$? zP+wnvWlNrqZ#ypG-O&Frw_oWU%AjN6@1lOL&ly8h5`MfoyXB{#R#lU3n#K;%#LvR8 z-%NG;^VU{mMPI%Ic63d2y}nCHD6h$7f=C&2EW;_wkYP|4}_NXQs>} z7ZLPrb8G6{SeP}8%>_mTN&dn!wKFzw55>bA|C2^SGtXWJcNCWsJWY*+XqL@{wH;fqLDs^%nigWks2t7W73W*uIr*lyW#(7- zIpzkW&6eESSsOA5{Vr!I@wDFq?qSf}8O&W%hJCB3<`^c_@chl@jv#Khd3}g;>z06; zF5GwRnZ0Wv46Aq4DlG=@tg~k<+l&JTa1dM;Ao)xO;&VcoZWRvM(Lp+(9COggnM*&{ zkr^lkJ)ocAWjy_WfuESoW%WR`CTo{Lbip*JE(P=9^#WsFgK(-tXs9=tZ#;l$;nS?T zvYd71!T$LLcej2}SyXn|Q^~c&{%$E8dOh#{kTQaJD84Xdr#}56F#!RehSN^w7$=2l zdj}(v`i}ZUT`lw6WUV#_D3PnV^5F@zXp>j8dJ+@X3{oI>Zr&JTqIYnyL}0Qo^7 zv;8z{GYHv@gy30BbqZax9mqUNwA)?9d}_<*4?cV7ie`>Fyz_t#_*Y;~%B)s6)#ctt zeIoM3C+-g(@Cx%DSNmjs%Cg%LPMyz4iPY2hW^CYX1Uh(#IqG(qS9<*8weu3{B7a5B zsL)`dTm8)fRy8ezK@YpS$|*ww{Jx^2oy!O-U7ezc&rod@C?lt`k*QyBexQ(!4OBW8 zPG@t%KXY-o@)+QD@5%flW1L(8`X{y6orwT6+KA$7^6$9x6YAy_-Su|jE*dVLb>4rX zADY69y`7-~pf8WaRc>%Ky0s5AJqxvG%Z5%)HD7)odxnr%n3j?wzb5lPjKM}H zB+mI^lM2lY&OY;A8sZ6aZvXM4O!qHKPw^z-w=bLU#(Dg6dg7N)St?WzshyV0b7|FV zUmBcGqEJ=&Ds=lrs&{Y1E6mSYJKEMXJ=Y80hf#I%=R3w%{TfF-6KIQZAIa4HrDpn% z#%YNr8neWJ9%JH>kY(kYg#A$}s$?^k8bVjGfx!||e&UPvL`tVrZEInj@U5Ib!WjX4 zC*Xt!*N3_1$R*2$6^1l?Z%>=t4Cj{8a{l0QW%#8sTYZ^A5j zfw!&8CI*ed49y6O;$OZbfh#4?Q&9Hn18c^eG?i1b(&m*Yt}fRTk-yHl0Q4{JIn|$1 z?{{r6XnvZlyeM>QYm(f{>#N`RTAOhu=njdd_< zesqhnXl=)Td@3>}yX76MzlK!!%!a!L(T7*- zl_A*=as=reW)4FYZdf#TYh^-A^(iyrGT-AeB7cbxzTQ}8RGx8Hz7NQUc;;37sU&mi zK@}=EM*-(TB~Vm9?n~lNSX0w>TUFlvd7KPdR)b~It&l&*n=*(#$bIp@o*kXiX6|;n z6Nl2))QpFbtE;PprRb#oU%2M*3ML097w-!y2U_dJ5@(aGnD&ix6xfE33Z!gES+H9a zVGBBz#Av+kX0h<#ng(2B=6+R5h9^7Ud3z>TN4*tYdMflfB=oWefw#cs!LWgKasFl= zJ-61wdykYapPDk?HwFH;+~?xJpOF zUKGV3rOE{(rDq%Mp!ANCL2Pb7@?*T-r@w+x{HZqDnF>$gIFX~3F~Z#jYYG#M{#{8~ zmE$$EzTbDw5{^ALOX4*BXU$#nG=jp)zbFO&OURS%Ukkl|t;GCgg7nV~BFU?87b$tN zep}*S_R=pp``^F5d^COf*CLM@IySh4xfuP z7QjC??~O}6tbb?E{p0OX*pe?%*pfLo-u-7l@HY}9|8dj5Bc!|5pX~8k@^Tmc3WWXt z^IwWGdHv&A|Bhh)SDF4xSO2dv{YT35kG(8$SAo*|z0Sr|oNCkKO>u5s$6`aM%0tBX zHJi}_B~fC3k)QXeTsDsz&(@?5g&z^i}RW7Vm&2TiS5bqdLc@klHtQW)M@ecGKx}m*XmTw zHQvr}Z^t*2U&c2z!(m#a+QHcgq}7Mp7TBS%E$!G(5kwIQ?5?q`<;cER%rtzP>-lyNiXTVdQ5Z36H0mnwsc@ zwqdXj!ZN>QC8Wu*HMFubh*`)32M^V^9&rB<#0EZVX(f4^{_w0EV3qLwB7SMesZJYC zYcmsEJm*wXvl#cN8kGER@p*sI_#^Mj-em82e!n2O%W=1}x0^xN%g7b^e0=BuNJ!O& zrs3QlbyeMoPWD?F%)&qF)@E7{{c82)#L^Cpo1yn>i_CypJwo2KbgI9g%Kuxr@7~D! zjkiPjl5*u3_e(%PAUdsx2hhf8W_1Ajrs#TqKHS~B*42xyBIt03Xto53!Ooj2cfp7E zRtTbl0cJ6^-q~`ZJA(j6p0^t-@>Pre-mCi0m4osI6+rU3q}i+cTl67dU06l6?aGEsE*( zmi1{^C5?`4xtV}EF&skVZM+ke!>YwI3tB8R`$Yy4WP(;?jG^! zqB@Zmwe+cTq^uFZa)9wPew$lY#eH)@J0s0vT}GNX5;g0#?Jsqgf*OV}RBKj(401Rt zIhLYC&-wK#UF03Hg!&#vDTV|A;{vZ{#}E)l?Tz=yYPJOjDR(|3jBigB!BfCI7sA6P zkGQmM=c%8VgLfO|P&#>K=T)}v@2VdPa?wK@E#84vl7QDI9Oh0~4u%q*!#%V9=N0mchOp-m!_X<;&cve32Q~5mll}hI^+@n&r0gKG zLoHiPf}+iH)jX;tqIKb`>=z5Jofb9QsH7^Sk5qZx!B3I{fYVIjR=x6-Zdbrl>m`!L^kkY1Y6Fgsak^D zpy^Ul7lL>p+{->V5DfppnIB&fjBd;>#$0ioI*VD@JP|0bG>-lQ^c6bLqB3QB6mfYQ zz)?=jXD1;>-~I*$du9w8X%r)SHJ>TG=H{$u>$YytwSm$4T1U)+=1Ty)H=kiTQl$7BC;#!0o|Bv?9Pb7VZ&j5%|vGNZXa}G?wq2# z&^f=%sU{;?XW6Akflqs6R1fWoyBA$Mom#QqSPr^!?@CzPpYI9PO+Ivxm$n`acDyvUzNz>31f?*jn!aUN(h`=K zKc;=gLTx|6F7@Uc|BDyyt^tjJ9xd{Pd3$t6pF18Swwd4beEk+WeN4noL%s#p8#Xt{ zt8&yaEhjYRIoX7TZoV^fjB`$b*+d;W4Q|36=hs@KW~EJYNF7W*fXJXb4M#2^j(Rbv zDN`T38y#N6NRvOJ!oU`pEP+6Xs{BafTf?7E4HLR2i4iOIBabLi9L8l-q8=tY24V_24PVoi?aVy=`%u^)nmS?v;0Sm#{_B3-T52# zBS&$W-iUN@{FtU)=J?q$5&6W8b9><+h;+~;1PgI-v(+Y+7oj}gjSj93a>6G=wN--u zuG!A=_)~?B?jIe{<=$6xPo4aj<-$FiaNT!fx^m^!ImFq^`oY=i!*tg>%g7*uPOhtI zVl#EWu@xqrx11`lYpJX43xeWT1vc?F4<9<7V2F+xZnl!8T5$is(m=V>kKLS29RvI= zPVWt@)*vijBy{tc7-b44b{55_)~XZ>BZOXyN79#tV$#g^GY3&}zAd#+!Q$f%8xe>G zx#9oPP+FYZe zzjUakkQ{^`drcWl7?3S1+n*Xh?Dq3)rxNjsf}|b0qU@=1^I!; z@@W?-O*a)B6XaCmAg%Gvk+Dp=lrz+tH7lp2xw)>1YiReY1PlzJU+x z=3Lion7cLTIW{F>`PsA5vkKoPy+NxGTav`jQyr#RNEdp~oXK>%rx*jw8-@Cr zbB`YJg7Qp<4%z`J0Jp9gdF2&;#HekWz0)qIs#@dGEqhrEN6Uq)J{JN$G_Q1G@EuYx zPKU<{2?=@et>SLTVrkg?Tyx{Q$=QcHt>fD7l8OGYq>xU=L+$)}}lg!<3QSZ8Tzp=dRDU`gF7-(N-uPjOSmH4$k<=-8SB>wDM0Ug`#ma-~_ zD7_0ME>JLn$$@FhD?!dXTN#0yGdU%t8_8m_vv7n`^ z5wO10)14X^*QFsz!Ww?IF$`GYGu|DLILkX!K2lVB zo(eRv{AIeQhOgX5>a_p*dV_$pz{9$@2DJlJvlJ@4N&r))PVeOw78y4+k;7;!_XcS~B?GNp>=#}3>Uh>^E$ z1@i`c*nIO$t5#V0GsVwRG-Nl+hZ0py8kO45Rl1IaVn6Zs_NM5+T)%yd@V%C8F2Byt zKenDe1BfGW64#ixj%nIK628wk42>OCS|H5=Tmz{aS_Frnx$(s-gsj`~?Wi~A8|;^b zXfHqau6}ON2Oq9voC*jzzA_j_U@)8#KVkT&&HB}uJIqkt!V~WLMA3`&?}}!hNC{Oz zvWR7U$y>a)homT;P^R5|$tV(oYH5nJ_Go~erXE5J$2vIBYB#ccE;jLqZSMY5Uq${V za;#_RxbLK5-{89?vT?sjjMv?Ktker$v=rTXsV=c>a?@~*01Dxn&*uo8VGwb^k1+IX z+*ZoTJ8u~tK6y=K%CRT!$Ikb&u39q0_<$HSsJ1@we0ZT!iqthp;Fj*I`I+R2zayn) zUB3|+&m#H#MCNz-XMRIDg)O)o+CcuK_=Lah4l5bI^~8Q}1k5Vk{UiLvyCoq3P2-#+ ze>Q1fi#fjwk&(xZQfU#3S^09+s^%DYu5&V^t@h1ooa#uIX*Oq%R*BO#*TSG_>Dh53 ze<#cWc^PoFz+KZ^J_OYWgK@f~u@^gDO|!q|;il`fQxv7ta=)=OY<(pxYj}09LZN+f zZ9dR`KI-Pg)yD_DJA=fDunZ3T*ti?2*t{y)QaSM27}LJ~!JD^1FGK#TuJ&(Z_J3Z` zO8m_{Kbze?&{5^?XMmo{RX>P(Eyc6f)JCFC_p@jtyc$^zl?&a1#^W$W4g*~+7O%Mp z7`M!X3mXC0)_^Fht2g5qEbf;?YuSHyxyqdob*KL&!_Pv0s3>;k&e9bZ75uACZdBlg zc(7Fl3YNgdjNcDCQ-EUefV55b?>^Onn}7EV_}zq()w}&})S`!GmNt?lY30iMx&5=+ zPap|ax)2=dPG9ekrM6-ZvqR2dM_i>9=tzvvnAkRvlYNOa(U5wd}KEb}Y zncIO6Fx?po6GtS&+2&&1L6yYJ|A)Bu4rF_8|A$Wpt?E#!YPZ!^QKR;zRaJW?YO75U zTkWE)wpMLoZxTe2n2|b)+B1n2vuea9Gzd@5ec#{noc7%3`F($XJ%9Qn@_y%?>wT@) zb-k{`8}O(n76W7N$sxmn$WdHE34*C|KyK`mGpzz~0ItpSi)tl=}gQH2pYHGQFAw z;p!P(aijrp`REP353b2^mCf(8+g-Nq%H1HgkIN0c8JL{_s2h z%M|}-W=4wr5b4rhoIN{*Z)yXZ3}0<4v&i5~3b{2gS$gG|KI zCihglG_3>9 z&uL6c*TZi;`CpbE)FXIo!btUjLz?O6|7#RUAZMhu=muXUqUl4k5 z(lq;28jFIgvSvgKUoP(9+Gvx}VS2t}?vAas_}d>XEGZJtP{)3za)OdYC=+pz;Zoa4 zVEB4=d3wj46}N;Dm}3eMOvA2Y54iD?bl*(=ev4z$sKr60e=*c2;<|T+Hgr z&AV(O(cHVkTMaBOlU3?ih&#oe4iHa+QCp1_8wJrEPEJl4hQmXveBMaiQ1yQ}g#QWB zGtQm1@19OzmvmFaH+bt?S>^2v=OOy?H%3eikKKx&%ltM=@(4A*8(KaTW4o%?J zUTK?dnxx_%{^^d?aO)h#Cin++sFvdc^kfKyA*p8HxX2;vWhX9#-_3`Fsw2p+Z{fYW z7w}2`xrhO=|A3nR{ebCADDj#VK^64V%an|0rQ?Yz*}0Vlu&PjKE?2OA@AUfbbxW=r z1@GU&r0)ZQz4TZ?TFV4ORcmVci%gkTtLnAl7+A$8<(Rs&g?IKNgU;35&_9)Bs3GO} z>lCy9Kw5qJe}sy|=ek{fwu6~hD}iCvVKd@sGl(Bqaq!bjqs5G}_T*imPhg;l!Y~d0 z5+Cp_?Q7}i#R&^DXd53NO0L~rV{mR`D)(Bj(u|l?I=w8sdf8Fv`hP!m$#kk8V*6u9 zUN?RoeeL%4Y}uMldD4tD{aN3YLyT8<9S_xMAY^W~!l-ND2ExAl7bU3!A`s}?i zg-^3DEawN7BkjK_W1P>vF+td`@shVg)C@3mMKAR#?0Sx%+n##AUz4mJiw;0SSLW^f zPLxoKZ7iAT>oT!zo8wXEBbCqD8?y2@nqyIsYU7*+f$_ouoaL-w{(*vwn!WDq3VO32 zO{~&827=@j zytRJ-+_C#?t5F0(6N>S1j+I6ojXq8?5Ua&ID;0j=%r2IowIhW7PNU|~xa)}a&uMzr zt?r^5xJBiUyl?i)EiBB>s2D0|%hmYKlmtpEDglIE0#1CRyEcAiUs~!_cbJZ<9rRozk_p#yYPAf)CKfE8G+ozg()-Q1Wbprhm_tLS- zy_ZSy(eHn}6nWS)$R;GwbUmrf-}dk&KF<3)?$Rn`(fiW%{k<MVejPRCS0E5N+}nW+3D8@ za=clD%tQaMxl2PIA-r2AUb%#j0hYf{2 z5AXOGAAqRp`Hj`L90$c6J0Wp$bE`ZqyVrtToU+jBUmyMu)~DqdVt6A}5rw^uS@kzj zurMv-wYX~UL^wQGP}cLx)Kh{Ou-j*{U~GsmR532|o}WvU-4%{*w9C6^^G4WLVocXn||JuW35EY~0ulVO%6(5?Z z4lg!)mB*~feB%Q_zZ73IGzV6>h-ca_d3QIm^8X#NGUE8>@w|m=&m6Qt~xEZ|7W& zCbZ)5EjfN;eS-qM2}O@sixPqYDL*;MfVu_%11Luli@o0*%pRRK+Op8(JbDz#A$aNj zqP$DR$cKey@x5L0`wO1*Bja@{aP$xLa#Qvj4GU016B8JeqJr$NIdq0SF07xU$467g z8mbK)@yUg{wczsWvp=)CHwcJUh;tgIIZMM-5>TND!jyg1%9rx}!o$yJ;rSi6#HvotR`MJke3fimb6jX&5x-P&^ zgKu7Fs(Qvu64@m_6f@o}I0^EXxg;`ee7Q_l_fxsn(X~sQSmeOdWIEdOhi-q)}TVZN81qHBe!PZ-Xy-=VGm!v7zbcC zNbG7r<1Xj4@eT3weYi+fK*~zXMswLcbkEF|F&|`X9x3gufNVB)>N2f(L{aOH?-?~X zX8{ew4{WJpa(B1tDGz~fuC~7Yfgxq-K(PSLG)AaEXgnMT|G0176e*PckA39GJ-`|kscLQDRj&wxbz%qIT1Sp9SLN;>1J z&&n5fBa@sgS-&AxHv5HXw`En$9xr7Em(k&Z>86Q1c^Vpz-PN(Xp>E}3jWt|L4{bmP z#N|izF7~T~BD99DpR4j|l)n|0Gj5XaY5Q8u2Slx1&;iL^cfY&Xo))7KWNZBNi?@ME zo&@sT+uxPV<%Z&?4!3|MgPvEetE?I~9JS^ArUce^xkFu?F6WRh_xKCPI&6}8L@koP zxZ+5P5pedL`S^z)@d()NoUw0?HGzX{_*u=fFHDuWODlRGL!-tno*wbkqsFNhY#vpR z!y^K$1}|~GFzT$;1-%9c3v1*!Dwv%VemcbnA%1T#3-&t{r>+QNf)nmhgOvz|?-~BV z#&zn7|l-VQSLgWpuH{ z1B={Ovrd|AuA04FG)^)rQRmk?Rwq|veUgsVLUXm$SYVXAcFNPsAH~TBQv8Al7tiq~ z;}E=YiHz)}num1-QKr!xz60)bG|IyQw)a~Yo?m0!(znOhgn3hNwzI} z;lq=Utoa*vBlB_^2S*(}y>Pu;g=aRF>hCH;t27fZcfl~X-wp1Hu3ox4+LKyj&zZ){ z_Zm#-j$PiOPY>@*7Y>Q5X!v|}*3?yZP2QxVFTEF|)ZYh)83Q8h4yDP^l2K<8E1X$< zeb_dpT(`egQQ>6g&Vm+Oxj7Laoh;W=#(%#sicjb5R#hbMWEKp~hAd2RAXHhgqi~3t zYW5(&@#sU>bn-vA-0y&|riGvKJ@xxZK4$dqTT=aQmN2D{Z7-%WLLnNP0qD`um5Z;_ zJ_TBj#YGz)J0n=hZ;eC$oeLX10%s3A#civ=_J~&xCuCh2#P^tk9ot zYO|}TRTOFUipgYgT)F(ZJGCO<9@E+B1S7`vDXBO9#YADvEK3t*J~_?({>k$CZeRe! zH<-iK!L35z`iCC4B`bH_R4nZM({fUfts9d|6T}u_hks zHmh0qQZr!b90ZcUHsF(3%&2_O9+l_AoAz5PXgI?bA}?eTK%LmfZ(4RpJL#JsrApiE zspBj7U@J*DG=?)(v7=jlis4$Nky}S^A4Pq+^&uFpflto{<~lQX)!)`n)1~%0kVfip zI)N}8wrTZo$q8^$cRQ@80^r#9x%YC9#7R5Kers%aH~d@?HCTd;!VbWYP}9@w?Ou(L zTfukLhT$Rd0|&1@4@42*dytnhH~-0pc)~M~HXW`q#@P0gTTH3W1)Kr}jHpaYmd!N^ z0O1^X(VZ3Anzj5^Y4?=^SN8Ssxh*opjvR>RR$H2YcO##;3~xM7OqUX08@5CLCIKVf z(d4N-XMLA|4M{5*S~za8<=1Q;D4cm{yToVVbB;2fZ=TxG3u?elcVrF64Y63QMkvG~ z_6X+ia>BX1>Bf2zD!gX0 zn~^2g^FEcCZo>O9j6oy>DcJep!B-R4cp!W?8EI3trn}P%bt3{;$q}G$u1#2m+m5iu z^glaieD?UJ7|wSNoBJhT$)*l1M{tX7;0}rT%i%q0;GummN++95VWEl0z+KL- zs~~KWx3@gRuZ!vfR_e^S*F7A+aoc_~-a^Fgu%)lCzX*0@LW=DAmo$V5LUvTCYW>bok>PcHbCllpn~sIk zY9BBm;Hqx0f5zREj;`Ep0T-MTgr#@N zl$xUt3vXu&h4~ncp9!7o@!TrR3&}i9}6++Eg(24DhY6S^-4aL$B z@4kNu#rMvhe+|-pNBBvUJ{RkJM)aj`w3jQ^nY+7x*cet(Fv1rYPRXsJe(Z(HQ zk4#($BaG?e8*9ngkWiNZ)(^L@N^A<-o=bucL2E%_9<6q%&kA1&-C@wERX=wo`J0mq z`A*&YFIj7EPg5B>adGGLSKejC5lR`8T2d0K#Dcy*maBjHbd%S&rLa+)I}x`0kcUgD zw6rugBtAYd{zkV>?PhJN@#e=5A3p3RywMM%1u!mSe~$zsS;9ADh=LU5x})QTQo^6 zy4|V88Uj*uGcTVCB*4d)na-sY9LXY;qrW5w|8z8erUeF?KQEK`JrCz|ehJ7w8{Kis zHQMZ1^?|NaG6MZCsOpSD-MF>0M)u8J22?#~t0Mg!XJMSM^!!>8x(XCUi)+Hxv^ZnD zG`~h00t!Pu>J`#Z^P=Y-YO2v5^;2rfm=ubM9IQ5PB`ywB7>;M_uT=qPawoi;xeuYi7 zV5dCuMQxDOEtTQ+c97p2FwijZtaEI-Kk6y6n$~3^)9shWnm<+CCQS_)y?ode_xR68 z|H^g!xJGkPq=g4K03la~P5w~?Wm(5zM>|LbXB$e%R>;9e1VCex>?^zpc99v?hCapR z;^j!05J|7Kk^TsWBB1h>sba>33CxI7GRnzC7hi$!Uk?oc7y!$=k|F_3Q>aG;)*mar zo_EdrrlOEyuUpx^26r+l4SALVu+}j?nfZ|U)&0(uOV8!HMS+JE@(#OTuW2Oj$wg1` z1GWC~m*r4XV%6!nhOjPQzqjt}jNgn4i-QfI2d|R8LY#PsPL74Aah8Pbhte|dhWRZ7 zFRnvGe&IlB)MLhbfBQR-R77BX-Z79jNpXVl*^_TFh^!%sZxLIcXxl@lz zEz;=We)87Tt5$JZkE{P=RTOV-hQ!6@T=+F>*XJ8bqtpP~&QDl*alFqH;E>LE5eG{F zsY>u|u8oxH_w78ZeIn=cxN1D6?P`i&q}{g)1NQ-~++JROW9Q(<`+CUL6JD3WD}aw_ zIqA*vW_(N)yMm*Y##3rir(h;%`7B$MRWJe*o!?9!r_MGZsjns_G4?9s24 zNS38(E99!fg&rB53iY#9KQSXRz=uAW!2pbG)r*d+qQULU6k^HYF6FzyLE;8w1Cz{X zfa|fn=$+ZRJ=Y+^B+NQ-O(4KL!3DNS0<8YdpmJa@CbD14d*Qi}8?nm5sf%{M+rP^_ zO#)>6^u5~A?Tf56R$HcIaW2E`PUgJ%h`kj&CaD5*pg}jY6I)j+=`vPa9<2UD%)!Md zO@K|pG^iJB6T>D|aOTi>p%Q4YI$_9kxA=Zb?Tr^_eW&t&${ohrO+Y|-4 z@ST!3cKtcqzf|{`KgAc<4$&XqJ*oB;+|*6-J?=nvS-y+AcjrdJD{6*^?e7Lz==h#% zVjNB})+{-#USA7iUj3*Z zb?2kiyU>B-Y!RGDtxY_$M`*v_!=8Fs+`g23e9zH$zn*-Gr#Z-R(LVaXj;d9P?XvyN z3`REGRALEs#shey7?zh#-20C2Q>?4&;S=>9$*!@C zwy25c$sar0@};AiB`?=U=L0hA{TU>5l;#UrOm030w0RiC zx~XF~X&{tAroy++znd`Hs!Nv4pOGyzYVPiBtzJ6`oPBqzg8iyFn2KjGEAASjc{=>V z-BVA2d{qL&l@5`<#J4BEc*=ho}Pt+VAOa%6Ir@=yxmKqWbLeHf9`CbAA32(6T1YglSmeNkLhQw0dBG{c^^OW5Yx z0F|tagTMhDN=eL3{by70r0fRyA>{ga$r_Sb*?Rcx4Diilg0yjh3RU(A#FiE?w$wHI z_5MgmUsH4MjazN$?oJ2wn{Tt_YXFxz{yf2d$CLi)pXfr+x9?r8;3cvw$omX)k1N^6?*kP z{vp&Ag>uz=xkqkU$#qN!%G~G?Lcq#w7g0IN_vIAvS1a4|C=8$P^ z;=+1t&kt8?b+ycj`WL2**=4%(_XxAa8-`i6nVBx(a50yPdb>TMx}IAr|E(~Dk7L`4 z6S(0^#wXq&tK@r8UBq=-Q`J89!p?p9vUrU>ebs~cvqFAH-uV6_m|uNfQ23V34E z7H`nO3(YJcwHJcq9}hHB#Z5dTX^)_>tNtP>{jWkFwfLy2QjXZklk3I1GI!!pidWDM zq4c%;vNEC*qwl6y9X!0%_YRzgW z{4`a!o;-J0>TLm=J9pUtn&w~4XKRh^q~!i_n66Ek{x~Vx?`(y<5Bty((X81R_A5yw zXmmg3HK<>IIy}pL>ax=YQ??^MoiJkARVAprFFy-0$23>>dVAtiLB6%#n$K|+4>^Q{ zdT*G3IcpG4d{79$b6~ zL=x`Yy(^W?Zv<-0SGUXxIUd%qrnefa?QgmTN={5nZ0s5C_åz*7yW%*ssUEYL{ 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 RGvKph+pa& +Visibility: public +Number of lines: 21 + +def #{name}(#{args_signature}) + trans = Gitlab::Metrics::Instrumentation.transaction + + if trans + start = Time.now + retval = super + duration = (Time.now - start) * 1000.0 + + if duration >= Gitlab::Metrics.method_call_threshold + trans.increment(:method_duration, duration) + + trans.add_metric(Gitlab::Metrics::Instrumentation::SERIES, + { duration: duration }, + method: #{label.inspect}) + end + + retval + else + super + end +end +``` + +## Instrumenting Ruby Blocks + +Measuring blocks of Ruby code is done by calling `Gitlab::Metrics.measure` and +passing it a block. For example: ```ruby Gitlab::Metrics.measure(:foo) do @@ -14,6 +127,10 @@ Gitlab::Metrics.measure(:foo) do end ``` +The block is executed and the execution time is stored as a set of fields in the +currently running transaction. If no transaction is present the block is yielded +without measuring anything. + 3 values are measured for a block: 1. The real time elapsed, stored in NAME_real_time. diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md index 28dedf3978..02e024ca15 100644 --- a/doc/development/migration_style_guide.md +++ b/doc/development/migration_style_guide.md @@ -8,7 +8,10 @@ In addition, having to take a server offline for a an upgrade small or big is a big burden for most organizations. For this reason it is important that your migrations are written carefully, can be applied online and adhere to the style guide below. -It's advised to have offline migrations only in major GitLab releases. +Migrations should not require GitLab installations to be taken offline unless +_absolutely_ necessary. If a migration requires downtime this should be +clearly mentioned during the review process as well as being documented in the +monthly release post. When writing your migrations, also consider that databases might have stale data or inconsistencies and guard for that. Try to make as little assumptions as possible @@ -58,6 +61,45 @@ remove_index :namespaces, column: :name if index_exists?(:namespaces, :name) If you need to add an unique index please keep in mind there is possibility of existing duplicates. If it is possible write a separate migration for handling this situation. It can be just removing or removing with overwriting all references to these duplicates depend on situation. +When adding an index make sure to use the method `add_concurrent_index` instead +of the regular `add_index` method. The `add_concurrent_index` method +automatically creates concurrent indexes when using PostgreSQL, removing the +need for downtime. To use this method you must disable transactions by calling +the method `disable_ddl_transaction!` in the body of your migration class like +so: + +``` +class MyMigration < ActiveRecord::Migration + disable_ddl_transaction! + + def change + + end +end +``` + +## Adding Columns With Default Values + +When adding columns with default values you should use the method +`add_column_with_default`. This method ensures the table is updated without +requiring downtime. This method is not reversible so you must manually define +the `up` and `down` methods in your migration class. + +For example, to add the column `foo` to the `projects` table with a default +value of `10` you'd write the following: + +``` +class MyMigration < ActiveRecord::Migration + def up + add_column_with_default(:projects, :foo, :integer, 10) + end + + def down + remove_column(:projects, :foo) + end +end +``` + ## Testing Make sure that your migration works with MySQL and PostgreSQL with data. An empty database does not guarantee that your migration is correct. @@ -74,7 +116,7 @@ Example with Arel: users = Arel::Table.new(:users) users.group(users[:user_id]).having(users[:id].count.gt(5)) -#updtae other tables with this results +#update other tables with these results ``` Example with plain SQL and `quote_string` helper: @@ -89,4 +131,4 @@ select_all("SELECT name, COUNT(id) as cnt FROM tags GROUP BY name HAVING COUNT(i execute("UPDATE taggings SET tag_id = #{origin_tag_id} WHERE tag_id IN(#{duplicate_ids.join(",")})") execute("DELETE FROM tags WHERE id IN(#{duplicate_ids.join(",")})") end -``` \ No newline at end of file +``` diff --git a/doc/development/testing.md b/doc/development/testing.md index 33eed29ba5..513457d203 100644 --- a/doc/development/testing.md +++ b/doc/development/testing.md @@ -65,7 +65,7 @@ the command line via `bundle exec teaspoon`, or via a web browser at - Use `context` to test branching logic. - Don't `describe` symbols (see [Gotchas](gotchas.md#dont-describe-symbols)). - Don't supply the `:each` argument to hooks since it's the default. -- Prefer `not_to` to `to_not`. +- Prefer `not_to` to `to_not` (_this is enforced by Rubocop_). - Try to match the ordering of tests to the ordering within the class. - Try to follow the [Four-Phase Test][four-phase-test] pattern, using newlines to separate phases. diff --git a/doc/development/ui_guide.md b/doc/development/ui_guide.md index a3e260a5f8..23760a14b3 100644 --- a/doc/development/ui_guide.md +++ b/doc/development/ui_guide.md @@ -6,3 +6,51 @@ We created a page inside GitLab where you can check commonly used html and css e When you run GitLab instance locally - just visit http://localhost:3000/help/ui page to see UI examples you can use during GitLab development. + +## Design repository + +All design files are stored in the [gitlab-design](https://gitlab.com/gitlab-org/gitlab-design) +repository and maintained by GitLab UX designers. + +## Navigation + +GitLab's layout contains 2 sections: the left sidebar and the content. The left sidebar contains a static navigation menu. +This menu will be visible regardless of what page you visit. The left sidebar also contains the GitLab logo +and the current user's profile picture. The content section contains a header and the content itself. +The header describes the current GitLab page and what navigation is +available to user in this area. Depending on the area (project, group, profile setting) the header name and navigation may change. For example when user visits one of the +project pages the header will contain a project name and navigation for that project. When the user visits a group page it will contain a group name and navigation related to this group. + +### Adding new tab to header navigation + +We try to keep the amount of tabs in the header navigation between 5 and 10 so that it fits on a typical laptop screen. We also try not to confuse the user with too many options. Ideally each +tab should represent separate functionality. Everything related to the issue +tracker should be under the 'Issues' tab while everything related to the wiki should +be under 'Wiki' tab and so on and so forth. + +## Mobile screen size + +We want GitLab to work well on small mobile screens as well. Size limitations make it is impossible to fit everything on a mobile screen. In this case it is OK to hide +part of the UI for smaller resolutions in favor of a better user experience. +However core functionality like browsing files, creating issues, writing comments, should +be available on all resolutions. + +## Icons + +* `trash` icon for button or link that does destructive action like removing +information from database or file system +* `x` icon for closing/hiding UI element. For example close modal window +* `pencil` icon for edit button or link +* `eye` icon for subscribe action +* `rss` for rss/atom feed +* `plus` for link or dropdown that lead to page where you create new object (For example new issue page) + + +## Buttons + +* Button should contain icon or text. Exceptions should be approved by UX designer. +* Use gray button on white background or white button on gray background. +* Use red button for destructive actions (not revertable). For example removing issue. +* Use green or blue button for primary action. Primary button should be only one. +Do not use both green and blue button in one form. + diff --git a/doc/gitlab-basics/create-issue.md b/doc/gitlab-basics/create-issue.md index 87f078def0..5221d85b66 100644 --- a/doc/gitlab-basics/create-issue.md +++ b/doc/gitlab-basics/create-issue.md @@ -24,4 +24,4 @@ You may assign the Issue to a user, add a milestone and add labels (they are all ![Submit new issue](basicsimages/submit_new_issue.png) -Your Issue will now be added to the Issue Tracker and will be ready to be reviewed. You can comment on it and mention the people involved. You can also link Issues to the Merge Requests where the Issues are solved. To do this, you can use an [Issue closing pattern](http://doc.gitlab.com/ce/customization/issue_closing.html). +Your Issue will now be added to the Issue Tracker and will be ready to be reviewed. You can comment on it and mention the people involved. You can also link Issues to the Merge Requests where the Issues are solved. To do this, you can use an [Issue closing pattern](http://docs.gitlab.com/ce/customization/issue_closing.html). diff --git a/doc/gitlab-basics/create-project.md b/doc/gitlab-basics/create-project.md index b545d62549..f737dffc02 100644 --- a/doc/gitlab-basics/create-project.md +++ b/doc/gitlab-basics/create-project.md @@ -14,7 +14,7 @@ Fill out the required information: 1. Select a [visibility level](https://gitlab.com/help/public_access/public_access) -1. You can also [import your existing projects](http://doc.gitlab.com/ce/workflow/importing/README.html) +1. You can also [import your existing projects](http://docs.gitlab.com/ce/workflow/importing/README.html) 1. Click on "create project" diff --git a/doc/hooks/custom_hooks.md b/doc/hooks/custom_hooks.md index dcdf49d337..820934f97f 100644 --- a/doc/hooks/custom_hooks.md +++ b/doc/hooks/custom_hooks.md @@ -2,7 +2,7 @@ **Note: Custom git hooks must be configured on the filesystem of the GitLab server. Only GitLab server administrators will be able to complete these tasks. -Please explore [webhooks](../web_hooks/web_hooks.md) as an option if you do not have filesystem access. For a user configurable Git Hooks interface, please see [GitLab Enterprise Edition Git Hooks](http://doc.gitlab.com/ee/git_hooks/git_hooks.html).** +Please explore [webhooks](../web_hooks/web_hooks.md) as an option if you do not have filesystem access. For a user configurable Git Hooks interface, please see [GitLab Enterprise Edition Git Hooks](http://docs.gitlab.com/ee/git_hooks/git_hooks.html).** Git natively supports hooks that are executed on different actions. Examples of server-side git hooks include pre-receive, post-receive, and update. diff --git a/doc/install/installation.md b/doc/install/installation.md index e3af302226..1318b3d1fa 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -6,7 +6,7 @@ Since an installation from source is a lot of work and error prone we strongly r One reason the Omnibus package is more reliable is its use of Runit to restart any of the GitLab processes in case one crashes. On heavily used GitLab instances the memory usage of the Sidekiq background worker will grow over time. -Omnibus packages solve this by [letting the Sidekiq terminate gracefully](http://doc.gitlab.com/ce/operations/sidekiq_memory_killer.html) if it uses too much memory. +Omnibus packages solve this by [letting the Sidekiq terminate gracefully](http://docs.gitlab.com/ce/operations/sidekiq_memory_killer.html) if it uses too much memory. After this termination Runit will detect Sidekiq is not running and will start it. Since installations from source don't have Runit, Sidekiq can't be terminated and its memory usage will grow over time. @@ -269,9 +269,9 @@ sudo usermod -aG redis git ### Clone the Source # Clone GitLab repository - sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 8-7-stable gitlab + sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 8-8-stable gitlab -**Note:** You can change `8-7-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server! +**Note:** You can change `8-8-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server! ### Configure It @@ -394,7 +394,7 @@ GitLab Shell is an SSH access and repository management software developed speci cd /home/git sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-workhorse.git cd gitlab-workhorse - sudo -u git -H git checkout v0.7.1 + sudo -u git -H git checkout v0.7.4 sudo -u git -H make ### Initialize Database and Activate Advanced Features diff --git a/doc/install/relative_url.md b/doc/install/relative_url.md index 0245febfcd..44d2a14f36 100644 --- a/doc/install/relative_url.md +++ b/doc/install/relative_url.md @@ -132,5 +132,5 @@ To disable the relative URL: 1. Follow the same as above starting from 2. and set up the GitLab URL to one that doesn't contain a relative path. -[omnibus-rel]: http://doc.gitlab.com/omnibus/settings/configuration.html#configuring-a-relative-url-for-gitlab "How to setup relative URL in Omnibus GitLab" +[omnibus-rel]: http://docs.gitlab.com/omnibus/settings/configuration.html#configuring-a-relative-url-for-gitlab "How to setup relative URL in Omnibus GitLab" [restart gitlab]: ../administration/restart_gitlab.md#installations-from-source "How to restart GitLab" diff --git a/doc/install/requirements.md b/doc/install/requirements.md index df8e8bdc47..09c6211b3a 100644 --- a/doc/install/requirements.md +++ b/doc/install/requirements.md @@ -81,7 +81,7 @@ errors during usage. - More users? Run it on [multiple application servers](https://about.gitlab.com/high-availability/) We recommend having at least 1GB of swap on your server, even if you currently have -enough available RAM. Having swap will help reduce the chance of errors occuring +enough available RAM. Having swap will help reduce the chance of errors occurring if your available memory changes. Notice: The 25 workers of Sidekiq will show up as separate processes in your process overview (such as top or htop) but they share the same RAM allocation since Sidekiq is a multithreaded application. Please see the section below about Unicorn workers for information about many you need of those. @@ -150,3 +150,4 @@ On a very active server (10,000 active users) the Sidekiq process can use 1GB+ o - Safari 7+ (known problem: required fields in html5 do not work) - Opera (Latest released version) - Internet Explorer (IE) 11+ but please make sure that you have the `Compatibility View` mode disabled. +- Edge (Latest stable version) diff --git a/doc/integration/README.md b/doc/integration/README.md index 6fe04aa2a0..fd330dd7a7 100644 --- a/doc/integration/README.md +++ b/doc/integration/README.md @@ -19,7 +19,7 @@ See the documentation below for details on how to configure these services. GitLab Enterprise Edition contains [advanced Jenkins support][jenkins]. -[jenkins]: http://doc.gitlab.com/ee/integration/jenkins.html +[jenkins]: http://docs.gitlab.com/ee/integration/jenkins.html ## Project services diff --git a/doc/integration/cas.md b/doc/integration/cas.md index e6b2071f19..e34e306f9a 100644 --- a/doc/integration/cas.md +++ b/doc/integration/cas.md @@ -27,17 +27,18 @@ To enable the CAS OmniAuth provider you must register your application with your ```ruby gitlab_rails['omniauth_providers'] = [ { - name: "cas3", - label: "cas", - args: { - url: 'CAS_SERVER', - login_url: '/CAS_PATH/login', - service_validate_url: '/CAS_PATH/p3/serviceValidate', - logout_url: '/CAS_PATH/logout'} } - } + "name"=> "cas3", + "label"=> "cas", + "args"=> { + "url"=> 'CAS_SERVER', + "login_url"=> '/CAS_PATH/login', + "service_validate_url"=> '/CAS_PATH/p3/serviceValidate', + "logout_url"=> '/CAS_PATH/logout' + } } ] ``` + For installations from source: @@ -57,6 +58,8 @@ To enable the CAS OmniAuth provider you must register your application with your 1. Save the configuration file. +1. Run `gitlab-ctl reconfigure` for the omnibus package. + 1. Restart GitLab for the changes to take effect. On the sign in page there should now be a CAS tab in the sign in form. diff --git a/doc/integration/google.md b/doc/integration/google.md index f9a20dd840..82978b68a3 100644 --- a/doc/integration/google.md +++ b/doc/integration/google.md @@ -11,9 +11,9 @@ To enable the Google OAuth2 OmniAuth provider you must register your application - Project ID: Must be unique to all Google Developer registered applications. Google provides a randomly generated Project ID by default. You can use the randomly generated ID or choose a new one. 1. Refresh the page. You should now see your new project in the list. Click on the project. -1. Select "APIs & auth" in the left menu. +1. Select the "Google APIs" tab in the Overview. -1. Select "APIs" in the submenu. +1. Select and enable the following Google APIs - listed under "Popular APIs" - Enable `Contacts API` - Enable `Google+ API` diff --git a/doc/integration/img/enabled-oauth-sign-in-sources.png b/doc/integration/img/enabled-oauth-sign-in-sources.png new file mode 100644 index 0000000000000000000000000000000000000000..95f8bbdcd2489c4eb14c100c92dffadf3a1a65fc GIT binary patch literal 49081 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 T3O4XXNYA9j6~w-Z7zO**Note:** +This setting was introduced with version 8.8 of GitLab. + +Administrators are able to enable or disable Sign In via some OmniAuth providers. + +>**Note:** +By default Sign In is enabled via all the OAuth Providers that have been configured in `config/gitlab.yml`. + +In order to enable/disable an OmniAuth provider, go to Admin Area -> Settings -> Sign-in Restrictions section -> Enabled OAuth Sign-In sources and select the providers you want to enable or disable. + +![Enabled OAuth Sign-In sources](img/enabled-oauth-sign-in-sources.png) diff --git a/doc/intro/README.md b/doc/intro/README.md index ab298d3808..382d10aaf4 100644 --- a/doc/intro/README.md +++ b/doc/intro/README.md @@ -39,4 +39,4 @@ Install and update your GitLab installation. - [Install GitLab](https://about.gitlab.com/installation/) - [Update GitLab](https://about.gitlab.com/update/) -- [Explore Omnibus GitLab configuration options](http://doc.gitlab.com/omnibus/settings/configuration.html) +- [Explore Omnibus GitLab configuration options](http://docs.gitlab.com/omnibus/settings/configuration.html) diff --git a/doc/logs/logs.md b/doc/logs/logs.md index 27937e5176..f84060b8d0 100644 --- a/doc/logs/logs.md +++ b/doc/logs/logs.md @@ -1,6 +1,6 @@ ## Log system -GitLab has advanced log system so everything is logging and you can analize your instance using various system log files. -In addition to system log files, GitLab Enterprise Edition comes with Audit Events. Find more about them [in Audit Events documentation](http://doc.gitlab.com/ee/administration/audit_events.html) +GitLab has an advanced log system where everything is logged so that you can analyze your instance using various system log files. +In addition to system log files, GitLab Enterprise Edition comes with Audit Events. Find more about them [in Audit Events documentation](http://docs.gitlab.com/ee/administration/audit_events.html) System log files are typically plain text in a standard log file format. This guide talks about how to read and use these system log files. @@ -67,13 +67,13 @@ gitlab-shell is using by Gitlab for executing git commands and provide ssh acces ``` I, [2015-02-13T06:17:00.671315 #9291] INFO -- : Adding project root/example.git at . -I, [2015-02-13T06:17:00.679433 #9291] INFO -- : Moving existing hooks directory and simlinking global hooks directory for /var/opt/gitlab/git-data/repositories/root/example.git. +I, [2015-02-13T06:17:00.679433 #9291] INFO -- : Moving existing hooks directory and symlinking global hooks directory for /var/opt/gitlab/git-data/repositories/root/example.git. ``` #### unicorn_stderr.log This file lives in `/var/log/gitlab/unicorn/unicorn_stderr.log` for omnibus package or in `/home/git/gitlab/log/unicorn_stderr.log` for installations from the source. -Unicorn is a high-performance forking Web server which is used for serving GitLab application. You can look at this log, for example, if your application does not respond. This log cantains all information about state of unicorn processes at any given time. +Unicorn is a high-performance forking Web server which is used for serving the GitLab application. You can look at this log if, for example, your application does not respond. This log contains all information about the state of unicorn processes at any given time. ``` I, [2015-02-13T06:14:46.680381 #9047] INFO -- : Refreshing Gem list diff --git a/doc/markdown/markdown.md b/doc/markdown/markdown.md index 4f199b6af6..236eb7b12c 100644 --- a/doc/markdown/markdown.md +++ b/doc/markdown/markdown.md @@ -8,6 +8,7 @@ * [Multiple underscores in words](#multiple-underscores-in-words) * [URL auto-linking](#url-auto-linking) * [Code and Syntax Highlighting](#code-and-syntax-highlighting) +* [Inline Diff](#inline-diff) * [Emoji](#emoji) * [Special GitLab references](#special-gitlab-references) * [Task lists](#task-lists) @@ -153,6 +154,19 @@ s = "There is no highlighting for this." But let's throw in a tag. ``` +## Inline Diff + +With inline diffs tags you can display {+ additions +} or [- deletions -]. + +The wrapping tags can be either curly braces or square brackets [+ additions +] or {- deletions -}. + +However the wrapping tags cannot be mixed as such: + +- {+ additions +] +- [+ additions +} +- {- deletions -] +- [- deletions -} + ## Emoji Sometimes you want to :monkey: around a bit and add some :star2: to your :speech_balloon:. Well we have a gift for you: @@ -185,20 +199,23 @@ GFM will turn that reference into a link so you can navigate between them easily GFM will recognize the following: -| input | references | -|:-----------------------|:---------------------------| -| `@user_name` | specific user | -| `@group_name` | specific group | -| `@all` | entire team | -| `#123` | issue | -| `!123` | merge request | -| `$123` | snippet | -| `~123` | label by ID | -| `~bug` | one-word label by name | -| `~"feature request"` | multi-word label by name | -| `9ba12248` | specific commit | -| `9ba12248...b19a04f5` | commit range comparison | -| `[README](doc/README)` | repository file references | +| input | references | +|:-----------------------|:--------------------------- | +| `@user_name` | specific user | +| `@group_name` | specific group | +| `@all` | entire team | +| `#123` | issue | +| `!123` | merge request | +| `$123` | snippet | +| `~123` | label by ID | +| `~bug` | one-word label by name | +| `~"feature request"` | multi-word label by name | +| `%123` | milestone by ID | +| `%v1.23` | one-word milestone by name | +| `%"release candidate"` | multi-word milestone by name | +| `9ba12248` | specific commit | +| `9ba12248...b19a04f5` | commit range comparison | +| `[README](doc/README)` | repository file references | GFM also recognizes certain cross-project references: @@ -206,6 +223,7 @@ GFM also recognizes certain cross-project references: |:----------------------------------------|:------------------------| | `namespace/project#123` | issue | | `namespace/project!123` | merge request | +| `namespace/project%123` | milestone | | `namespace/project$123` | snippet | | `namespace/project@9ba12248` | specific commit | | `namespace/project@9ba12248...b19a04f5` | commit range comparison | @@ -402,7 +420,7 @@ There are two ways to create links, inline-style and reference-style. [I'm a reference-style link][Arbitrary case-insensitive reference text] -[I'm a relative reference to a repository file](LICENSE) +[I'm a relative reference to a repository file](LICENSE)[^1] [You can use numbers for reference-style link definitions][1] @@ -594,3 +612,4 @@ By including colons in the header row, you can align the text within that column [rouge]: http://rouge.jneen.net/ "Rouge website" [redcarpet]: https://github.com/vmg/redcarpet "Redcarpet website" +[^1]: This link will be broken if you see this document from the Help page or docs.gitlab.com diff --git a/doc/migrate_ci_to_ce/README.md b/doc/migrate_ci_to_ce/README.md index 5ec0a2069b..8f9ef05494 100644 --- a/doc/migrate_ci_to_ce/README.md +++ b/doc/migrate_ci_to_ce/README.md @@ -355,7 +355,7 @@ sudo chown git:git /var/opt/gitlab/gitlab-ci/builds ``` #### Problems when importing CI database to GitLab -If you were migrating CI database from MySQL to PostgreSQL manually you can see errros during import about missing sequences: +If you were migrating CI database from MySQL to PostgreSQL manually you can see errors during import about missing sequences: ``` ALTER SEQUENCE ERROR: relation "ci_builds_id_seq" does not exist diff --git a/doc/monitoring/health_check.md b/doc/monitoring/health_check.md new file mode 100644 index 0000000000..0d17799372 --- /dev/null +++ b/doc/monitoring/health_check.md @@ -0,0 +1,66 @@ +# Health Check + +>**Note:** This feature was [introduced][ce-3888] in GitLab 8.8. + +GitLab provides a health check endpoint for uptime monitoring on the `health_check` web +endpoint. The health check reports on the overall system status based on the status of +the database connection, the state of the database migrations, and the ability to write +and access the cache. This endpoint can be provided to uptime monitoring services like +[Pingdom][pingdom], [Nagios][nagios-health], and [NewRelic][newrelic-health]. + +## Access Token + +An access token needs to be provided while accessing the health check endpoint. The current +accepted token can be found on the `admin/health_check` page of your GitLab instance. + +![access token](img/health_check_token.png) + +The access token can be passed as a URL parameter: + +``` +https://gitlab.example.com/health_check.json?token=ACCESS_TOKEN +``` + +or as an HTTP header: + +```bash +curl -H "TOKEN: ACCESS_TOKEN" https://gitlab.example.com/health_check.json +``` + +## Using the Endpoint + +Once you have the access token, health information can be retrieved as plain text, JSON, +or XML using the `health_check` endpoint: + +- `https://gitlab.example.com/health_check?token=ACCESS_TOKEN` +- `https://gitlab.example.com/health_check.json?token=ACCESS_TOKEN` +- `https://gitlab.example.com/health_check.xml?token=ACCESS_TOKEN` + +You can also ask for the status of specific services: + +- `https://gitlab.example.com/health_check/cache.json?token=ACCESS_TOKEN` +- `https://gitlab.example.com/health_check/database.json?token=ACCESS_TOKEN` +- `https://gitlab.example.com/health_check/migrations.json?token=ACCESS_TOKEN` + +For example, the JSON output of the following health check: + +```bash +curl -H "TOKEN: ACCESS_TOKEN" https://gitlab.example.com/health_check.json +``` + +would be like: + +``` +{"healthy":true,"message":"success"} +``` + +## Status + +On failure, the endpoint will return a `500` HTTP status code. On success, the endpoint +will return a valid successful HTTP status code, and a `success` message. Ideally your +uptime monitoring should look for the success message. + +[ce-3888]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3888 +[pingdom]: https://www.pingdom.com +[nagios-health]: https://nagios-plugins.org/doc/man/check_http.html +[newrelic-health]: https://docs.newrelic.com/docs/alerts/alert-policies/downtime-alerts/availability-monitoring diff --git a/doc/monitoring/img/health_check_token.png b/doc/monitoring/img/health_check_token.png new file mode 100644 index 0000000000000000000000000000000000000000..2daf8606b009aedda120af03baa13c36a195f07d GIT binary patch literal 10884 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 literal 0 HcmV?d00001 diff --git a/doc/operations/moving_repositories.md b/doc/operations/moving_repositories.md index 39086b7a25..54adb99386 100644 --- a/doc/operations/moving_repositories.md +++ b/doc/operations/moving_repositories.md @@ -134,7 +134,7 @@ sudo -u git sh -c ' cat /var/opt/gitlab/transfer-logs/* | sort | uniq -u |\ /usr/bin/env JOBS=10 \ /opt/gitlab/embedded/service/gitlab-rails/bin/parallel-rsync-repos \ - /var/opt/gitlab/transfer-logs/succes-$(date +%s).log \ + /var/opt/gitlab/transfer-logs/success-$(date +%s).log \ /var/opt/gitlab/git-data/repositories \ /mnt/gitlab/repositories ' @@ -145,7 +145,7 @@ sudo -u git -H sh -c ' cat /home/git/transfer-logs/* | sort | uniq -u |\ /usr/bin/env JOBS=10 \ bin/parallel-rsync-repos \ - /home/git/transfer-logs/succes-$(date +%s).log \ + /home/git/transfer-logs/success-$(date +%s).log \ /home/git/repositories \ /mnt/gitlab/repositories ` @@ -164,7 +164,7 @@ sudo gitlab-rake gitlab:list_repos SINCE='2015-10-1 12:00 UTC' |\ sudo -u git \ /usr/bin/env JOBS=10 \ /opt/gitlab/embedded/service/gitlab-rails/bin/parallel-rsync-repos \ - succes-$(date +%s).log \ + success-$(date +%s).log \ /var/opt/gitlab/git-data/repositories \ /mnt/gitlab/repositories @@ -174,7 +174,7 @@ sudo -u git -H bundle exec rake gitlab:list_repos SINCE='2015-10-1 12:00 UTC' |\ sudo -u git -H \ /usr/bin/env JOBS=10 \ bin/parallel-rsync-repos \ - succes-$(date +%s).log \ + success-$(date +%s).log \ /home/git/repositories \ /mnt/gitlab/repositories ``` diff --git a/doc/permissions/permissions.md b/doc/permissions/permissions.md index 6219693b8a..b76ce31cba 100644 --- a/doc/permissions/permissions.md +++ b/doc/permissions/permissions.md @@ -27,6 +27,7 @@ documentation](../workflow/add-user/add-user.md). | Manage issue tracker | | ✓ | ✓ | ✓ | ✓ | | Manage labels | | ✓ | ✓ | ✓ | ✓ | | See a commit status | | ✓ | ✓ | ✓ | ✓ | +| See a container registry | | ✓ | ✓ | ✓ | ✓ | | Manage merge requests | | | ✓ | ✓ | ✓ | | Create new merge request | | | ✓ | ✓ | ✓ | | Create new branches | | | ✓ | ✓ | ✓ | @@ -37,6 +38,8 @@ documentation](../workflow/add-user/add-user.md). | Write a wiki | | | ✓ | ✓ | ✓ | | Cancel and retry builds | | | ✓ | ✓ | ✓ | | Create or update commit status | | | ✓ | ✓ | ✓ | +| Update a container registry | | | ✓ | ✓ | ✓ | +| Remove a container registry image | | | ✓ | ✓ | ✓ | | Create new milestones | | | | ✓ | ✓ | | Add new team members | | | | ✓ | ✓ | | Push to protected branches | | | | ✓ | ✓ | diff --git a/doc/raketasks/README.md b/doc/raketasks/README.md index 6be954ad68..a49c43b8ef 100644 --- a/doc/raketasks/README.md +++ b/doc/raketasks/README.md @@ -8,4 +8,4 @@ - [User management](user_management.md) - [Webhooks](web_hooks.md) - [Import](import.md) of git repositories in bulk -- [Rebuild authorized_keys file](http://doc.gitlab.com/ce/raketasks/maintenance.html#rebuild-authorized_keys-file) task for administrators +- [Rebuild authorized_keys file](http://docs.gitlab.com/ce/raketasks/maintenance.html#rebuild-authorized_keys-file) task for administrators diff --git a/doc/security/README.md b/doc/security/README.md index 4cd0fdd409..38706e48ec 100644 --- a/doc/security/README.md +++ b/doc/security/README.md @@ -8,3 +8,4 @@ - [User File Uploads](user_file_uploads.md) - [How we manage the CRIME vulnerability](crime_vulnerability.md) - [Enforce Two-factor authentication](two_factor_authentication.md) +- [Send email confirmation on sign-up](user_email_confirmation.md) diff --git a/doc/security/user_email_confirmation.md b/doc/security/user_email_confirmation.md new file mode 100644 index 0000000000..4293944ae8 --- /dev/null +++ b/doc/security/user_email_confirmation.md @@ -0,0 +1,7 @@ +# User email confirmation at sign-up + +Gitlab admin can enable email confirmation on sign-up, if you want to confirm all +user emails before they are able to sign-in. + +In the Admin area under **Settings** (`/admin/application_settings`), go to section +**Sign-in Restrictions** and look for **Send confirmation email on sign-up** option. diff --git a/doc/update/8.6-to-8.7.md b/doc/update/8.6-to-8.7.md index 4a2c6ea91d..bb463d43a7 100644 --- a/doc/update/8.6-to-8.7.md +++ b/doc/update/8.6-to-8.7.md @@ -86,6 +86,14 @@ sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS ### 7. Update configuration files +#### New configuration options for `gitlab.yml` + +There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them manually to your current `gitlab.yml`: + +```sh +git diff origin/8-6-stable:config/gitlab.yml.example origin/8-7-stable:config/gitlab.yml.example +``` + #### Git configuration Disable `git gc --auto` because GitLab runs `git gc` for us already. diff --git a/doc/update/8.7-to-8.8.md b/doc/update/8.7-to-8.8.md new file mode 100644 index 0000000000..32906650f6 --- /dev/null +++ b/doc/update/8.7-to-8.8.md @@ -0,0 +1,162 @@ +# From 8.7 to 8.8 + +Make sure you view this update guide from the tag (version) of GitLab you would +like to install. In most cases this should be the highest numbered production +tag (without rc in it). You can select the tag in the version dropdown at the +top left corner of GitLab (below the menu bar). + +If the highest number stable branch is unclear please check the +[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation +guide links by version. + +### 1. Stop server + + sudo service gitlab stop + +### 2. Backup + +```bash +cd /home/git/gitlab +sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production +``` + +### 3. Get latest code + +```bash +sudo -u git -H git fetch --all +sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically +``` + +For GitLab Community Edition: + +```bash +sudo -u git -H git checkout 8-8-stable +``` + +OR + +For GitLab Enterprise Edition: + +```bash +sudo -u git -H git checkout 8-8-stable-ee +``` + +### 4. Update gitlab-shell + +```bash +cd /home/git/gitlab-shell +sudo -u git -H git fetch --all --tags +sudo -u git -H git checkout v2.7.2 +``` + +### 5. Update gitlab-workhorse + +Install and compile gitlab-workhorse. This requires +[Go 1.5](https://golang.org/dl) which should already be on your system from +GitLab 8.1. + +```bash +cd /home/git/gitlab-workhorse +sudo -u git -H git fetch --all +sudo -u git -H git checkout v0.7.1 +sudo -u git -H make +``` + +### 6. Install libs, migrations, etc. + +```bash +cd /home/git/gitlab + +# MySQL installations (note: the line below states '--without postgres') +sudo -u git -H bundle install --without postgres development test --deployment + +# PostgreSQL installations (note: the line below states '--without mysql') +sudo -u git -H bundle install --without mysql development test --deployment + +# Optional: clean up old gems +sudo -u git -H bundle clean + +# Run database migrations +sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production + +# Clean up assets and cache +sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production + +``` + +### 7. Update configuration files + +#### New configuration options for `gitlab.yml` + +There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them manually to your current `gitlab.yml`: + +```sh +git diff origin/8-7-stable:config/gitlab.yml.example origin/8-8-stable:config/gitlab.yml.example +``` + +#### Git configuration + +Disable `git gc --auto` because GitLab runs `git gc` for us already. + +```sh +sudo -u git -H git config --global gc.auto 0 +``` + +#### Nginx configuration + +Ensure you're still up-to-date with the latest NGINX configuration changes: + +```sh +# For HTTPS configurations +git diff origin/8-7-stable:lib/support/nginx/gitlab-ssl origin/8-8-stable:lib/support/nginx/gitlab-ssl + +# For HTTP configurations +git diff origin/8-7-stable:lib/support/nginx/gitlab origin/8-8-stable:lib/support/nginx/gitlab +``` + +If you are using Apache instead of NGINX please see the updated [Apache templates]. +Also note that because Apache does not support upstreams behind Unix sockets you +will need to let gitlab-workhorse listen on a TCP port. You can do this +via [/etc/default/gitlab]. + +[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache +[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-8-stable/lib/support/init.d/gitlab.default.example#L37 + +#### Init script + +Ensure you're still up-to-date with the latest init script changes: + + sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab + +### 8. Start application + + sudo service gitlab start + sudo service nginx restart + +### 9. Check application status + +Check if GitLab and its environment are configured correctly: + + sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production + +To make sure you didn't miss anything run a more thorough check: + + sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production + +If all items are green, then congratulations, the upgrade is complete! + +## Things went south? Revert to previous version (8.7) + +### 1. Revert the code to the previous version + +Follow the [upgrade guide from 8.6 to 8.7](8.6-to-8.7.md), except for the +database migration (the backup is already migrated to the previous version). + +### 2. Restore from the backup + +```bash +cd /home/git/gitlab +sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production +``` + +If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above. diff --git a/doc/update/README.md b/doc/update/README.md index a770633c9b..975d72164b 100644 --- a/doc/update/README.md +++ b/doc/update/README.md @@ -29,7 +29,7 @@ Based on your installation, choose a section below that fits your needs. ## Omnibus Packages -- The [Omnibus update guide](http://doc.gitlab.com/omnibus/update/README.html) +- The [Omnibus update guide](http://docs.gitlab.com/omnibus/update/README.html) contains the steps needed to update an Omnibus GitLab package. ## Installation from source @@ -86,10 +86,10 @@ possible. information about configuring GitLab to work with a MySQL database. - [Restoring from backup after a failed upgrade](restore_after_failure.md) -[omnidocker]: http://doc.gitlab.com/omnibus/docker/README.html +[omnidocker]: http://docs.gitlab.com/omnibus/docker/README.html [source-ee]: https://gitlab.com/gitlab-org/gitlab-ee/tree/master/doc/update [source-ce]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update [ee-ce]: ../downgrade_ee_to_ce/README.md [ce]: https://about.gitlab.com/features/#community [ee]: https://about.gitlab.com/features/#enterprise -[omni-ce-ee]: http://doc.gitlab.com/omnibus/update/README.html#from-community-edition-to-enterprise-edition +[omni-ce-ee]: http://docs.gitlab.com/omnibus/update/README.html#from-community-edition-to-enterprise-edition diff --git a/doc/update/patch_versions.md b/doc/update/patch_versions.md index b4283a526f..60729316cd 100644 --- a/doc/update/patch_versions.md +++ b/doc/update/patch_versions.md @@ -57,10 +57,10 @@ sudo -u git -H make cd /home/git/gitlab # PostgreSQL -sudo -u git -H bundle install --without development test mysql --with postgres --deployment +sudo -u git -H bundle install --without development test mysql --deployment # MySQL -sudo -u git -H bundle install --without development test postgres --with mysql --deployment +sudo -u git -H bundle install --without development test postgres --deployment # Optional: clean up old gems sudo -u git -H bundle clean diff --git a/doc/web_hooks/web_hooks.md b/doc/web_hooks/web_hooks.md index c1c51302e7..8559b67af0 100644 --- a/doc/web_hooks/web_hooks.md +++ b/doc/web_hooks/web_hooks.md @@ -13,6 +13,19 @@ You can configure webhooks to listen for specific events like pushes, issues or Webhooks can be used to update an external issue tracker, trigger CI builds, update a backup mirror, or even deploy to your production server. +## Webhook endpoint tips + +If you are writing your own endpoint (web server) that will receive +GitLab webhooks keep in mind the following things: + +- Your endpoint should send its HTTP response as fast as possible. If + you wait too long, GitLab may decide the hook failed and retry it. +- Your endpoint should ALWAYS return a valid HTTP response. If you do + not do this then GitLab will think the hook failed and retry it. + Most HTTP libraries take care of this for you automatically but if + you are writing a low-level hook this is important to remember. +- GitLab ignores the HTTP status code returned by your endpoint. + ## SSL Verification By default, the SSL certificate of the webhook endpoint is verified based on @@ -682,6 +695,61 @@ X-Gitlab-Event: Merge Request Hook } ``` +## Wiki Page events + +Triggered when a wiki page is created or edited. + +**Request Header**: + +``` +X-Gitlab-Event: Wiki Page Hook +``` + +**Request Body**: + +```json +{ + "object_kind": "wiki_page", + "user": { + "name": "Administrator", + "username": "root", + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon" + }, + "project": { + "name": "awesome-project", + "description": "This is awesome", + "web_url": "http://example.com/root/awesome-project", + "avatar_url": null, + "git_ssh_url": "git@example.com:root/awesome-project.git", + "git_http_url": "http://example.com/root/awesome-project.git", + "namespace": "root", + "visibility_level": 0, + "path_with_namespace": "root/awesome-project", + "default_branch": "master", + "homepage": "http://example.com/root/awesome-project", + "url": "git@example.com:root/awesome-project.git", + "ssh_url": "git@example.com:root/awesome-project.git", + "http_url": "http://example.com/root/awesome-project.git" + }, + "wiki": { + "web_url": "http://example.com/root/awesome-project/wikis/home", + "git_ssh_url": "git@example.com:root/awesome-project.wiki.git", + "git_http_url": "http://example.com/root/awesome-project.wiki.git", + "path_with_namespace": "root/awesome-project.wiki", + "default_branch": "master" + }, + "object_attributes": { + "title": "Awesome", + "content": "awesome content goes here", + "format": "markdown", + "message": "adding an awesome page to the wiki", + "slug": "awesome", + "url": "http://example.com/root/awesome-project/wikis/awesome", + "action": "create" + } +} +``` + #### Example webhook receiver If you want to see GitLab's webhooks in action for testing purposes you can use diff --git a/doc/workflow/gitlab_flow.md b/doc/workflow/gitlab_flow.md index 1b354bcc0f..2b2f140f8b 100644 --- a/doc/workflow/gitlab_flow.md +++ b/doc/workflow/gitlab_flow.md @@ -131,7 +131,7 @@ When you feel comfortable with it to be merged you assign it to the person that There is room for more feedback and after the assigned person feels comfortable with the result the branch is merged. If the assigned person does not feel comfortable they can close the merge request without merging. -In GitLab it is common to protect the long-lived branches (e.g. the master branch) so that normal developers [can't modify these protected branches](http://doc.gitlab.com/ce/permissions/permissions.html). +In GitLab it is common to protect the long-lived branches (e.g. the master branch) so that normal developers [can't modify these protected branches](http://docs.gitlab.com/ce/permissions/permissions.html). So if you want to merge it into a protected branch you assign it to someone with master authorizations. ## Issues with GitLab flow @@ -187,7 +187,7 @@ If you have an issue that spans across multiple repositories, the best thing is ![Vim screen showing the rebase view](rebase.png) With git you can use an interactive rebase (`rebase -i`) to squash multiple commits into one and reorder them. -In GitLab EE and .com you can also [rebase before merge](http://doc.gitlab.com/ee/workflow/rebase_before_merge.html) from the web interface. +In GitLab EE and .com you can also [rebase before merge](http://docs.gitlab.com/ee/workflow/rebase_before_merge.html) from the web interface. This functionality is useful if you made a couple of commits for small changes during development and want to replace them with a single commit or if you want to make the order more logical. However you should never rebase commits you have pushed to a remote server. Somebody can have referred to the commits or cherry-picked them. diff --git a/doc/workflow/groups.md b/doc/workflow/groups.md index 52bf611dc5..34ada1774d 100644 --- a/doc/workflow/groups.md +++ b/doc/workflow/groups.md @@ -54,7 +54,7 @@ If necessary, you can increase the access level of an individual user for a spec ## Managing group memberships via LDAP In GitLab Enterprise Edition it is possible to manage GitLab group memberships using LDAP groups. -See [the GitLab Enterprise Edition documentation](http://doc.gitlab.com/ee/integration/ldap.html) for more information. +See [the GitLab Enterprise Edition documentation](http://docs.gitlab.com/ee/integration/ldap.html) for more information. ## Allowing only admins to create groups diff --git a/doc/workflow/importing/import_projects_from_github.md b/doc/workflow/importing/import_projects_from_github.md index e670e415c7..a7dfac2c12 100644 --- a/doc/workflow/importing/import_projects_from_github.md +++ b/doc/workflow/importing/import_projects_from_github.md @@ -44,5 +44,5 @@ case the namespace is taken, the project will be imported on the user's namespace. [gh-import]: ../../integration/github.md "GitHub integration" -[ee-gh]: http://doc.gitlab.com/ee/integration/github.html "GitHub integration for GitLab EE" +[ee-gh]: http://docs.gitlab.com/ee/integration/github.html "GitHub integration for GitLab EE" [new-project]: ../../gitlab-basics/create-project.md "How to create a new project in GitLab" diff --git a/doc/workflow/importing/import_projects_from_gitlab_com.md b/doc/workflow/importing/import_projects_from_gitlab_com.md index 1117db98e7..dcc00074b7 100644 --- a/doc/workflow/importing/import_projects_from_gitlab_com.md +++ b/doc/workflow/importing/import_projects_from_gitlab_com.md @@ -2,7 +2,7 @@ You can import your existing GitLab.com projects to your GitLab instance. But keep in mind that it is possible only if GitLab support is enabled on your GitLab instance. -You can read more about GitLab support [here](http://doc.gitlab.com/ce/integration/gitlab.html) +You can read more about GitLab support [here](http://docs.gitlab.com/ce/integration/gitlab.html) To get to the importer page you need to go to "New project" page. ![New project page](gitlab_importer/new_project_page.png) diff --git a/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md b/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md index 31620044b1..9fe065fa68 100644 --- a/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md +++ b/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md @@ -4,7 +4,7 @@ Managing large files such as audio, video and graphics files has always been one of the shortcomings of Git. The general recommendation is to not have Git repositories larger than 1GB to preserve performance. -GitLab already supports [managing large files with git annex](http://doc.gitlab.com/ee/workflow/git_annex.html) +GitLab already supports [managing large files with git annex](http://docs.gitlab.com/ee/workflow/git_annex.html) (EE only), however in certain environments it is not always convenient to use different commands to differentiate between the large files and regular ones. @@ -127,7 +127,7 @@ To prevent this from happening, set the lfs url in project Git config: ```bash -git config --add lfs.url "http://gitlab.example.com/group/project.git/info/lfs/objects/batch" +git config --add lfs.url "http://gitlab.example.com/group/project.git/info/lfs" ``` ### Credentials are always required when pushing an object @@ -152,4 +152,4 @@ If you are using OS X you can use `osxkeychain` to store and encrypt your creden For Windows, you can use `wincred` or Microsoft's [Git Credential Manager for Windows](https://github.com/Microsoft/Git-Credential-Manager-for-Windows/releases). More details about various methods of storing the user credentials can be found -on [Git Credential Storage documentation](https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage). \ No newline at end of file +on [Git Credential Storage documentation](https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage). diff --git a/doc/workflow/notifications.md b/doc/workflow/notifications.md index 80817c98d2..cbca94c0b5 100644 --- a/doc/workflow/notifications.md +++ b/doc/workflow/notifications.md @@ -69,7 +69,7 @@ In all of the below cases, the notification will be sent to: ...with notification level "Participating" or higher -- Watchers: project members with notification level "Watch" +- Watchers: users with notification level "Watch" - Subscribers: anyone who manually subscribed to the issue/merge request | Event | Sent to | diff --git a/features/project/active_tab.feature b/features/project/active_tab.feature index 2fd097d100..26e6750302 100644 --- a/features/project/active_tab.feature +++ b/features/project/active_tab.feature @@ -10,14 +10,9 @@ Feature: Project Active Tab Then the active main tab should be Home And no other main tabs should be active - Scenario: On Project Files + Scenario: On Project Code Given I visit my project's files page - Then the active main tab should be Files - And no other main tabs should be active - - Scenario: On Project Commits - Given I visit my project's commits page - Then the active main tab should be Commits + Then the active main tab should be Code And no other main tabs should be active Scenario: On Project Issues @@ -30,11 +25,6 @@ Feature: Project Active Tab Then the active main tab should be Merge Requests And no other main tabs should be active - Scenario: On Project Members - Given I visit my project's members page - Then the active main tab should be Members - And no other main tabs should be active - Scenario: On Project Wiki Given I visit my project's wiki page Then the active main tab should be Wiki @@ -49,13 +39,6 @@ Feature: Project Active Tab # Sub Tabs: Settings - Scenario: On Project Settings/Edit - Given I visit my project's settings page - And I click the "Edit" tab - Then the active sub nav should be Edit - And no other sub navs should be active - And the active main tab should be Settings - Scenario: On Project Settings/Hooks Given I visit my project's settings page And I click the "Hooks" tab @@ -70,40 +53,52 @@ Feature: Project Active Tab And no other sub navs should be active And the active main tab should be Settings - # Sub Tabs: Commits + Scenario: On Project Members + Given I visit my project's members page + Then the active sub nav should be Members + And no other sub navs should be active + And the active main tab should be Settings - Scenario: On Project Commits/Commits + # Sub Tabs: Code + + Scenario: On Project Code/Files + Given I visit my project's files page + Then the active sub tab should be Files + And no other sub tabs should be active + And the active main tab should be Code + + Scenario: On Project Code/Commits Given I visit my project's commits page Then the active sub tab should be Commits And no other sub tabs should be active - And the active main tab should be Commits + And the active main tab should be Code - Scenario: On Project Commits/Network + Scenario: On Project Code/Network Given I visit my project's network page Then the active sub tab should be Network And no other sub tabs should be active - And the active main tab should be Commits + And the active main tab should be Code - Scenario: On Project Commits/Compare + Scenario: On Project Code/Compare Given I visit my project's commits page And I click the "Compare" tab Then the active sub tab should be Compare And no other sub tabs should be active - And the active main tab should be Commits + And the active main tab should be Code - Scenario: On Project Commits/Branches + Scenario: On Project Code/Branches Given I visit my project's commits page And I click the "Branches" tab Then the active sub tab should be Branches And no other sub tabs should be active - And the active main tab should be Commits + And the active main tab should be Code - Scenario: On Project Commits/Tags + Scenario: On Project Code/Tags Given I visit my project's commits page And I click the "Tags" tab Then the active sub tab should be Tags And no other sub tabs should be active - And the active main tab should be Commits + And the active main tab should be Code Scenario: On Project Issues/Browse Given I visit my project's issues page diff --git a/features/project/builds/summary.feature b/features/project/builds/summary.feature index 3c029a973d..550ebccf0d 100644 --- a/features/project/builds/summary.feature +++ b/features/project/builds/summary.feature @@ -24,3 +24,4 @@ Feature: Project Builds Summary Then recent build has been erased And recent build summary does not have artifacts widget And recent build summary contains information saying that build has been erased + And the build count cache is updated diff --git a/features/project/commits/tags.feature b/features/project/commits/tags.feature deleted file mode 100644 index a4be39b2d4..0000000000 --- a/features/project/commits/tags.feature +++ /dev/null @@ -1,46 +0,0 @@ -@project_commits -Feature: Project Commits Tags - Background: - Given I sign in as a user - And I own project "Shop" - Given I visit project tags page - - Scenario: I can see all git tags - Then I should see "Shop" all tags list - - Scenario: I create a tag - And I click new tag link - And I submit new tag form - Then I should see new tag created - - Scenario: I create a tag with release notes - Given I click new tag link - And I submit new tag form with release notes - Then I should see new tag created - And I should see tag release notes - - Scenario: I create a tag with invalid name - And I click new tag link - And I submit new tag form with invalid name - Then I should see new an error that tag is invalid - - Scenario: I create a tag with invalid reference - And I click new tag link - And I submit new tag form with invalid reference - Then I should see new an error that tag ref is invalid - - Scenario: I create a tag that already exists - And I click new tag link - And I submit new tag form with tag that already exists - Then I should see new an error that tag already exists - - Scenario: I delete a tag - Given I visit tag 'v1.1.0' page - Given I delete tag 'v1.1.0' - Then I should not see tag 'v1.1.0' - - Scenario: I add release notes to the tag - Given I visit tag 'v1.1.0' page - When I click edit tag link - And I fill release notes and submit form - Then I should see tag release notes diff --git a/features/project/create.feature b/features/project/create.feature index 27136798e3..67336d73bf 100644 --- a/features/project/create.feature +++ b/features/project/create.feature @@ -7,20 +7,8 @@ Feature: Project Create @javascript Scenario: User create a project Given I sign in as a user - When I visit new project page And I have an ssh key + When I visit new project page And fill project form with valid data Then I should see project page - And I should see empty project instuctions - - @javascript - Scenario: Empty project instructions - Given I sign in as a user - And I have an ssh key - When I visit new project page - And fill project form with valid data - Then I see empty project instuctions - And I click on HTTP - Then Remote url should update to http link - And If I click on SSH - Then Remote url should update to ssh link + And I should see empty project instructions diff --git a/features/project/project.feature b/features/project/project.feature index f1f3ed2606..aa22401c88 100644 --- a/features/project/project.feature +++ b/features/project/project.feature @@ -18,15 +18,6 @@ Feature: Project Then I should see the default project avatar And I should not see the "Remove avatar" button - Scenario: I should have back to group button - And project "Shop" belongs to group - And I visit project "Shop" page - Then I should see back to group button - - Scenario: I should have back to group button - And I visit project "Shop" page - Then I should see back to dashboard button - Scenario: I should have readme on page And I visit project "Shop" page Then I should see project "Shop" README diff --git a/features/project/shortcuts.feature b/features/project/shortcuts.feature index 10e7c23461..c73d0b3233 100644 --- a/features/project/shortcuts.feature +++ b/features/project/shortcuts.feature @@ -8,19 +8,21 @@ Feature: Project Shortcuts @javascript Scenario: Navigate to files tab Given I press "g" and "f" - Then the active main tab should be Files + Then the active main tab should be Code + Then the active sub tab should be Files @javascript Scenario: Navigate to commits tab Given I visit my project's files page Given I press "g" and "c" - Then the active main tab should be Commits + Then the active main tab should be Code + Then the active sub tab should be Commits @javascript Scenario: Navigate to network tab Given I press "g" and "n" Then the active sub tab should be Network - And the active main tab should be Commits + And the active main tab should be Code @javascript Scenario: Navigate to graphs tab diff --git a/features/steps/admin/active_tab.rb b/features/steps/admin/active_tab.rb index 90d13abdb1..f2db180138 100644 --- a/features/steps/admin/active_tab.rb +++ b/features/steps/admin/active_tab.rb @@ -1,7 +1,7 @@ class Spinach::Features::AdminActiveTab < Spinach::FeatureSteps include SharedAuthentication include SharedPaths - include SharedActiveTab + include SharedSidebarActiveTab step 'the active main tab should be Home' do ensure_active_main_tab('Overview') @@ -34,4 +34,12 @@ class Spinach::Features::AdminActiveTab < Spinach::FeatureSteps step 'the active main tab should be Messages' do ensure_active_main_tab('Messages') end + + step 'no other main tabs should be active' do + expect(page).to have_selector('.nav-sidebar > li.active', count: 1) + end + + def ensure_active_main_tab(content) + expect(find('.nav-sidebar > li.active')).to have_content(content) + end end diff --git a/features/steps/admin/users.rb b/features/steps/admin/users.rb index 4bc290b6bd..8fb8a86d58 100644 --- a/features/steps/admin/users.rb +++ b/features/steps/admin/users.rb @@ -158,7 +158,7 @@ class Spinach::Features::AdminUsers < Spinach::FeatureSteps step 'I should not see twitter details' do expect(page).to have_content 'Pete' - expect(page).to_not have_content 'twitter' + expect(page).not_to have_content 'twitter' end step 'click on ssh keys tab' do diff --git a/features/steps/dashboard/active_tab.rb b/features/steps/dashboard/active_tab.rb index 0e2c04fb29..04fe96cef2 100644 --- a/features/steps/dashboard/active_tab.rb +++ b/features/steps/dashboard/active_tab.rb @@ -1,9 +1,5 @@ class Spinach::Features::DashboardActiveTab < Spinach::FeatureSteps include SharedAuthentication include SharedPaths - include SharedActiveTab - - step 'the active main tab should be Help' do - ensure_active_main_tab('Help') - end + include SharedSidebarActiveTab end diff --git a/features/steps/dashboard/dashboard.rb b/features/steps/dashboard/dashboard.rb index b5980b3510..80ed4c6d64 100644 --- a/features/steps/dashboard/dashboard.rb +++ b/features/steps/dashboard/dashboard.rb @@ -13,7 +13,7 @@ class Spinach::Features::Dashboard < Spinach::FeatureSteps end step 'I should see "Shop" project CI status' do - expect(page).to have_link "Build skipped" + expect(page).to have_link "Commit: skipped" end step 'I should see last push widget' do diff --git a/features/steps/dashboard/issues.rb b/features/steps/dashboard/issues.rb index e21af72a77..8706f0e8e7 100644 --- a/features/steps/dashboard/issues.rb +++ b/features/steps/dashboard/issues.rb @@ -74,7 +74,7 @@ class Spinach::Features::DashboardIssues < Spinach::FeatureSteps def project @project ||= begin - project =create :project + project = create :project project.team << [current_user, :master] project end diff --git a/features/steps/dashboard/merge_requests.rb b/features/steps/dashboard/merge_requests.rb index a2adc87f8e..06db36c701 100644 --- a/features/steps/dashboard/merge_requests.rb +++ b/features/steps/dashboard/merge_requests.rb @@ -100,7 +100,7 @@ class Spinach::Features::DashboardMergeRequests < Spinach::FeatureSteps def project @project ||= begin - project =create :project + project = create :project project.team << [current_user, :master] project end diff --git a/features/steps/dashboard/shortcuts.rb b/features/steps/dashboard/shortcuts.rb index a9083850b5..118d27888d 100644 --- a/features/steps/dashboard/shortcuts.rb +++ b/features/steps/dashboard/shortcuts.rb @@ -2,5 +2,6 @@ class Spinach::Features::DashboardShortcuts < Spinach::FeatureSteps include SharedAuthentication include SharedPaths include SharedProject - include SharedActiveTab + include SharedSidebarActiveTab + include SharedShortcuts end diff --git a/features/steps/dashboard/todos.rb b/features/steps/dashboard/todos.rb index 2b23df6764..bd8a270202 100644 --- a/features/steps/dashboard/todos.rb +++ b/features/steps/dashboard/todos.rb @@ -20,7 +20,7 @@ class Spinach::Features::DashboardTodos < Spinach::FeatureSteps step 'I have todos' do create(:todo, user: current_user, project: project, author: mary_jane, target: issue, action: Todo::MENTIONED) create(:todo, user: current_user, project: project, author: john_doe, target: issue, action: Todo::ASSIGNED) - note = create(:note, author: john_doe, noteable: issue, note: "#{current_user.to_reference} Wdyt?") + note = create(:note, author: john_doe, noteable: issue, note: "#{current_user.to_reference} Wdyt?", project: project) create(:todo, user: current_user, project: project, author: john_doe, target: issue, action: Todo::MENTIONED, note: note) create(:todo, user: current_user, project: project, author: john_doe, target: merge_request, action: Todo::ASSIGNED) end @@ -106,7 +106,7 @@ class Spinach::Features::DashboardTodos < Spinach::FeatureSteps if pending expect(page).to have_link 'Done' else - expect(page).to_not have_link 'Done' + expect(page).not_to have_link 'Done' end end end diff --git a/features/steps/profile/active_tab.rb b/features/steps/profile/active_tab.rb index 3b59089a09..4724a32627 100644 --- a/features/steps/profile/active_tab.rb +++ b/features/steps/profile/active_tab.rb @@ -22,8 +22,4 @@ class Spinach::Features::ProfileActiveTab < Spinach::FeatureSteps step 'the active main tab should be Audit Log' do ensure_active_main_tab('Audit Log') end - - def ensure_active_main_tab(content) - expect(find('.layout-nav li.active')).to have_content(content) - end end diff --git a/features/steps/profile/profile.rb b/features/steps/profile/profile.rb index 909de31a47..b1a87b96ef 100644 --- a/features/steps/profile/profile.rb +++ b/features/steps/profile/profile.rb @@ -166,7 +166,7 @@ class Spinach::Features::Profile < Spinach::FeatureSteps end step 'I have group with projects' do - @group = create(:group) + @group = create(:group) @group.add_owner(current_user) @project = create(:project, namespace: @group) @event = create(:closed_issue_event, project: @project) diff --git a/features/steps/project/active_tab.rb b/features/steps/project/active_tab.rb index 19d81453d8..745fd3471c 100644 --- a/features/steps/project/active_tab.rb +++ b/features/steps/project/active_tab.rb @@ -16,12 +16,14 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps end step 'I click the "Snippets" tab' do - click_link('Snippets') + page.within('.layout-nav') do + click_link('Snippets') + end end - step 'I click the "Edit" tab' do - page.within '.sidebar-subnav' do - click_link('Project Settings') + step 'I click the "Edit Project"' do + page.within '.layout-nav .controls' do + click_link('Edit Project') end end @@ -33,14 +35,10 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps click_link('Deploy Keys') end - step 'the active sub nav should be Team' do + step 'the active sub nav should be Members' do ensure_active_sub_nav('Members') end - step 'the active sub nav should be Edit' do - ensure_active_sub_nav('Project') - end - step 'the active sub nav should be Hooks' do ensure_active_sub_nav('Webhooks') end @@ -56,17 +54,15 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps end step 'I click the "Branches" tab' do - click_link('Branches') + page.within '.content' do + click_link('Branches') + end end step 'I click the "Tags" tab' do click_link('Tags') end - step 'the active sub tab should be Commits' do - ensure_active_sub_tab('Commits') - end - step 'the active sub tab should be Compare' do ensure_active_sub_tab('Compare') end @@ -82,11 +78,15 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps # Sub Tabs: Issues step 'I click the "Milestones" tab' do - click_link('Milestones') + page.within('.layout-nav') do + click_link('Milestones') + end end step 'I click the "Labels" tab' do - click_link('Labels') + page.within('.layout-nav') do + click_link('Labels') + end end step 'the active sub tab should be Issues' do diff --git a/features/steps/project/builds/summary.rb b/features/steps/project/builds/summary.rb index e9e2359146..374eb0b0e0 100644 --- a/features/steps/project/builds/summary.rb +++ b/features/steps/project/builds/summary.rb @@ -36,4 +36,8 @@ class Spinach::Features::ProjectBuildsSummary < Spinach::FeatureSteps expect(page).to have_content 'Build has been erased' end end + + step 'the build count cache is updated' do + expect(@build.project.running_or_pending_build_count).to eq @build.project.builds.running_or_pending.count(:all) + end end diff --git a/features/steps/project/commits/commits.rb b/features/steps/project/commits/commits.rb index 93c37bf507..e1b29f1e57 100644 --- a/features/steps/project/commits/commits.rb +++ b/features/steps/project/commits/commits.rb @@ -105,7 +105,7 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps end step 'I should not see button to create a new merge request' do - expect(page).to_not have_link 'Create Merge Request' + expect(page).not_to have_link 'Create Merge Request' end step 'I should see button to the merge request' do @@ -173,7 +173,7 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps end step 'I see commit ci info' do - expect(page).to have_content "build: pending" + expect(page).to have_content "Builds for 1 pipeline pending" end step 'I click status link' do @@ -181,7 +181,7 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps end step 'I see builds list' do - expect(page).to have_content "build: pending" + expect(page).to have_content "Builds for 1 pipeline pending" expect(page).to have_content "1 build" end diff --git a/features/steps/project/commits/tags.rb b/features/steps/project/commits/tags.rb deleted file mode 100644 index 912ba580ef..0000000000 --- a/features/steps/project/commits/tags.rb +++ /dev/null @@ -1,90 +0,0 @@ -class Spinach::Features::ProjectCommitsTags < Spinach::FeatureSteps - include SharedAuthentication - include SharedProject - include SharedPaths - - step 'I should see "Shop" all tags list' do - expect(page).to have_content "Tags" - expect(page).to have_content "v1.0.0" - end - - step 'I click new tag link' do - click_link 'New tag' - end - - step 'I submit new tag form' do - fill_in 'tag_name', with: 'v7.0' - fill_in 'ref', with: 'master' - click_button 'Create tag' - end - - step 'I submit new tag form with release notes' do - fill_in 'tag_name', with: 'v7.0' - fill_in 'ref', with: 'master' - fill_in 'release_description', with: 'Awesome release notes' - click_button 'Create tag' - end - - step 'I fill release notes and submit form' do - fill_in 'release_description', with: 'Awesome release notes' - click_button 'Save changes' - end - - step 'I submit new tag form with invalid name' do - fill_in 'tag_name', with: 'v 1.0' - fill_in 'ref', with: 'master' - click_button 'Create tag' - end - - step 'I submit new tag form with invalid reference' do - fill_in 'tag_name', with: 'foo' - fill_in 'ref', with: 'foo' - click_button 'Create tag' - end - - step 'I submit new tag form with tag that already exists' do - fill_in 'tag_name', with: 'v1.0.0' - fill_in 'ref', with: 'master' - click_button 'Create tag' - end - - step 'I should see new tag created' do - expect(page).to have_content 'v7.0' - end - - step 'I should see new an error that tag is invalid' do - expect(page).to have_content 'Tag name invalid' - end - - step 'I should see new an error that tag ref is invalid' do - expect(page).to have_content 'Target foo is invalid' - end - - step 'I should see new an error that tag already exists' do - expect(page).to have_content 'Tag v1.0.0 already exists' - end - - step "I visit tag 'v1.1.0' page" do - click_link 'v1.1.0' - end - - step "I delete tag 'v1.1.0'" do - page.within('.content') do - first('.btn-remove').click - end - end - - step "I should not see tag 'v1.1.0'" do - page.within '.tags' do - expect(page).not_to have_link 'v1.1.0' - end - end - - step 'I click edit tag link' do - click_link 'Edit release notes' - end - - step 'I should see tag release notes' do - expect(page).to have_content 'Awesome release notes' - end -end diff --git a/features/steps/project/create.rb b/features/steps/project/create.rb index 422b151eaa..5f5f806df3 100644 --- a/features/steps/project/create.rb +++ b/features/steps/project/create.rb @@ -13,33 +13,9 @@ class Spinach::Features::ProjectCreate < Spinach::FeatureSteps expect(current_path).to eq namespace_project_path(Project.last.namespace, Project.last) end - step 'I should see empty project instuctions' do + step 'I should see empty project instructions' do expect(page).to have_content "git init" expect(page).to have_content "git remote" expect(page).to have_content Project.last.url_to_repo end - - step 'I see empty project instuctions' do - expect(page).to have_content "git init" - expect(page).to have_content "git remote" - expect(page).to have_content Project.last.url_to_repo - end - - step 'I click on HTTP' do - find('#clone-dropdown').click - find('.http-selector').click - end - - step 'Remote url should update to http link' do - expect(page).to have_content "git remote add origin #{Project.last.http_url_to_repo}" - end - - step 'If I click on SSH' do - find('#clone-dropdown').click - find('.ssh-selector').click - end - - step 'Remote url should update to ssh link' do - expect(page).to have_content "git remote add origin #{Project.last.url_to_repo}" - end end diff --git a/features/steps/project/fork.rb b/features/steps/project/fork.rb index 527f7853da..8abeb5ee24 100644 --- a/features/steps/project/fork.rb +++ b/features/steps/project/fork.rb @@ -36,7 +36,7 @@ class Spinach::Features::ProjectFork < Spinach::FeatureSteps end step 'I goto the Merge Requests page' do - page.within '.page-sidebar-expanded' do + page.within '.layout-nav' do click_link "Merge Requests" end end diff --git a/features/steps/project/hooks.rb b/features/steps/project/hooks.rb index b1ffe7f7b4..13c0713669 100644 --- a/features/steps/project/hooks.rb +++ b/features/steps/project/hooks.rb @@ -59,7 +59,7 @@ class Spinach::Features::ProjectHooks < Spinach::FeatureSteps step 'hook should be triggered' do expect(current_path).to eq namespace_project_hooks_path(current_project.namespace, current_project) expect(page).to have_selector '.flash-notice', - text: 'Hook successfully executed.' + text: 'Hook executed successfully: HTTP 200' end step 'I should see hook error message' do diff --git a/features/steps/project/issues/award_emoji.rb b/features/steps/project/issues/award_emoji.rb index c5d45709b4..1b14659b4d 100644 --- a/features/steps/project/issues/award_emoji.rb +++ b/features/steps/project/issues/award_emoji.rb @@ -39,8 +39,8 @@ class Spinach::Features::AwardEmoji < Spinach::FeatureSteps step 'I can see the activity and food categories' do page.within '.emoji-menu' do - expect(page).to_not have_selector 'Activity' - expect(page).to_not have_selector 'Food' + expect(page).not_to have_selector 'Activity' + expect(page).not_to have_selector 'Food' end end diff --git a/features/steps/project/issues/issues.rb b/features/steps/project/issues/issues.rb index fc12843ea5..5cd431e05d 100644 --- a/features/steps/project/issues/issues.rb +++ b/features/steps/project/issues/issues.rb @@ -216,7 +216,7 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps page.within 'li.issue:nth-child(3)' do expect(page).to have_content 'Bugfix' - expect(page).to_not have_content '0 0' + expect(page).not_to have_content '0 0' end end end @@ -235,7 +235,7 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps page.within 'li.issue:nth-child(3)' do expect(page).to have_content 'Bugfix' - expect(page).to_not have_content '0 0' + expect(page).not_to have_content '0 0' end end end @@ -348,7 +348,7 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps step 'another user adds a comment with text "Yay!" to issue "Release 0.4"' do issue = Issue.find_by!(title: 'Release 0.4') - create(:note_on_issue, noteable: issue, note: 'Yay!') + create(:note_on_issue, noteable: issue, project: project, note: 'Yay!') end step 'I should see a new comment with text "Yay!"' do diff --git a/features/steps/project/issues/labels.rb b/features/steps/project/issues/labels.rb index 0ca2d6257c..8d87f6a7a5 100644 --- a/features/steps/project/issues/labels.rb +++ b/features/steps/project/issues/labels.rb @@ -24,8 +24,8 @@ class Spinach::Features::ProjectIssuesLabels < Spinach::FeatureSteps step 'I should see labels help message' do page.within '.labels' do - expect(page).to have_content 'Create first label or generate default set of '\ - 'labels' + expect(page).to have_content 'Create a label or generate a default set '\ + 'of labels' end end diff --git a/features/steps/project/merge_requests.rb b/features/steps/project/merge_requests.rb index 3b1a00f628..b30346790e 100644 --- a/features/steps/project/merge_requests.rb +++ b/features/steps/project/merge_requests.rb @@ -203,7 +203,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps page.within 'li.merge-request:nth-child(3)' do expect(page).to have_content 'Bug NS-05' - expect(page).to_not have_content '0 0' + expect(page).not_to have_content '0 0' end end end @@ -222,7 +222,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps page.within 'li.merge-request:nth-child(3)' do expect(page).to have_content 'Bug NS-05' - expect(page).to_not have_content '0 0' + expect(page).not_to have_content '0 0' end end end @@ -273,7 +273,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps step 'user "John Doe" leaves a comment like "Line is wrong" on diff' do mr = MergeRequest.find_by(title: "Bug NS-05") create(:note_on_merge_request_diff, project: project, - noteable_id: mr.id, + noteable: mr, author: user_exists("John Doe"), line_code: sample_commit.line_code, note: 'Line is wrong') @@ -525,7 +525,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps step 'I should see merge request "Bug NS-05" with CI status' do page.within ".mr-list" do - expect(page).to have_link "Build pending" + expect(page).to have_link "Pipeline: pending" end end @@ -567,7 +567,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps click_diff_line(sample_compare.changes[1][:line_code]) end - def have_visible_content (text) + def have_visible_content(text) have_css("*", text: text, visible: true) end diff --git a/features/steps/project/project.rb b/features/steps/project/project.rb index ef185861e0..a1785311c2 100644 --- a/features/steps/project/project.rb +++ b/features/steps/project/project.rb @@ -114,7 +114,9 @@ class Spinach::Features::Project < Spinach::FeatureSteps end step 'I should not see "Snippets" button' do - expect(page).not_to have_link 'Snippets' + page.within '.content' do + expect(page).not_to have_link 'Snippets' + end end step 'project "Shop" belongs to group' do @@ -123,14 +125,6 @@ class Spinach::Features::Project < Spinach::FeatureSteps @project.save! end - step 'I should see back to dashboard button' do - expect(page).to have_content 'Go to dashboard' - end - - step 'I should see back to group button' do - expect(page).to have_content 'Go to group' - end - step 'I click notifications drop down button' do click_link 'notifications-button' end diff --git a/features/steps/project/project_find_file.rb b/features/steps/project/project_find_file.rb index 8c1d09d6cc..47de4b91df 100644 --- a/features/steps/project/project_find_file.rb +++ b/features/steps/project/project_find_file.rb @@ -13,12 +13,12 @@ class Spinach::Features::ProjectFindFile < Spinach::FeatureSteps end step 'I should see "find file" page' do - ensure_active_main_tab('Files') + ensure_active_main_tab('Code') expect(page).to have_selector('.file-finder-holder', count: 1) end step 'I fill in Find by path with "git"' do - ensure_active_main_tab('Files') + ensure_active_main_tab('Code') expect(page).to have_selector('.file-finder-holder', count: 1) end diff --git a/features/steps/project/project_milestone.rb b/features/steps/project/project_milestone.rb index 2508c09e36..1864b3a2b5 100644 --- a/features/steps/project/project_milestone.rb +++ b/features/steps/project/project_milestone.rb @@ -52,7 +52,7 @@ class Spinach::Features::ProjectMilestone < Spinach::FeatureSteps end step 'I click link "Labels"' do - page.within('.nav-links') do + page.within('.layout-nav .nav-links') do page.find(:xpath, "//a[@href='#tab-labels']").click end end diff --git a/features/steps/project/project_shortcuts.rb b/features/steps/project/project_shortcuts.rb index 49e9c5520b..8143b01ca4 100644 --- a/features/steps/project/project_shortcuts.rb +++ b/features/steps/project/project_shortcuts.rb @@ -3,6 +3,7 @@ class Spinach::Features::ProjectShortcuts < Spinach::FeatureSteps include SharedPaths include SharedProject include SharedProjectTab + include SharedShortcuts step 'I press "g" and "f"' do find('body').native.send_key('g') diff --git a/features/steps/project/snippets.rb b/features/steps/project/snippets.rb index 786a0cad97..beb8ecfc79 100644 --- a/features/steps/project/snippets.rb +++ b/features/steps/project/snippets.rb @@ -43,12 +43,12 @@ class Spinach::Features::ProjectSnippets < Spinach::FeatureSteps step 'I click link "Edit"' do page.within ".detail-page-header" do - click_link "Edit" + first(:link, "Edit").click end end step 'I click link "Delete"' do - click_link "Delete" + first(:link, "Delete").click end step 'I submit new snippet "Snippet three"' do diff --git a/features/steps/project/source/browse_files.rb b/features/steps/project/source/browse_files.rb index c26d7a1521..2c0498de3b 100644 --- a/features/steps/project/source/browse_files.rb +++ b/features/steps/project/source/browse_files.rb @@ -337,13 +337,15 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps end step 'I should see buttons for allowed commands' do - expect(page).to have_content 'Raw' - expect(page).to have_content 'History' - expect(page).to have_content 'Permalink' - expect(page).not_to have_content 'Edit' - expect(page).not_to have_content 'Blame' - expect(page).to have_content 'Delete' - expect(page).to have_content 'Replace' + page.within '.content' do + expect(page).to have_content 'Raw' + expect(page).to have_content 'History' + expect(page).to have_content 'Permalink' + expect(page).not_to have_content 'Edit' + expect(page).not_to have_content 'Blame' + expect(page).to have_content 'Delete' + expect(page).to have_content 'Replace' + end end step 'I should see a notice about a new fork having been created' do diff --git a/features/steps/project/team_management.rb b/features/steps/project/team_management.rb index 3fbcf770b6..c6ced74737 100644 --- a/features/steps/project/team_management.rb +++ b/features/steps/project/team_management.rb @@ -126,7 +126,7 @@ class Spinach::Features::ProjectTeamManagement < Spinach::FeatureSteps step 'I share project with group "OpenSource"' do project = Project.find_by(name: 'Shop') - os_group = create(:group, name: 'OpenSource') + os_group = create(:group, name: 'OpenSource') create(:project, group: os_group) @os_user1 = create(:user) @os_user2 = create(:user) diff --git a/features/steps/shared/active_tab.rb b/features/steps/shared/active_tab.rb index 0bee91d758..ace717b990 100644 --- a/features/steps/shared/active_tab.rb +++ b/features/steps/shared/active_tab.rb @@ -2,7 +2,7 @@ module SharedActiveTab include Spinach::DSL def ensure_active_main_tab(content) - expect(find('.nav-sidebar > li.active')).to have_content(content) + expect(find('.layout-nav li.active')).to have_content(content) end def ensure_active_sub_tab(content) @@ -10,11 +10,11 @@ module SharedActiveTab end def ensure_active_sub_nav(content) - expect(find('.sidebar-subnav > li.active')).to have_content(content) + expect(find('.layout-nav .controls li.active')).to have_content(content) end step 'no other main tabs should be active' do - expect(page).to have_selector('.nav-sidebar > li.active', count: 1) + expect(page).to have_selector('.layout-nav .nav-links > li.active', count: 1) end step 'no other sub tabs should be active' do @@ -22,26 +22,6 @@ module SharedActiveTab end step 'no other sub navs should be active' do - expect(page).to have_selector('.sidebar-subnav > li.active', count: 1) - end - - step 'the active main tab should be Home' do - ensure_active_main_tab('Projects') - end - - step 'the active main tab should be Projects' do - ensure_active_main_tab('Projects') - end - - step 'the active main tab should be Issues' do - ensure_active_main_tab('Issues') - end - - step 'the active main tab should be Merge Requests' do - ensure_active_main_tab('Merge Requests') - end - - step 'the active main tab should be Help' do - ensure_active_main_tab('Help') + expect(page).to have_selector('.layout-nav .controls li.active', count: 1) end end diff --git a/features/steps/shared/diff_note.rb b/features/steps/shared/diff_note.rb index e846c52d47..e8b1e4b487 100644 --- a/features/steps/shared/diff_note.rb +++ b/features/steps/shared/diff_note.rb @@ -23,7 +23,7 @@ module SharedDiffNote page.within(diff_file_selector) do click_diff_line(sample_commit.line_code) - page.within("form[id$='#{sample_commit.line_code}']") do + page.within("form[id$='#{sample_commit.line_code}-true']") do fill_in "note[note]", with: "Typo, please fix" find(".js-comment-button").trigger("click") sleep 0.05 @@ -33,7 +33,7 @@ module SharedDiffNote step 'I leave a diff comment in a parallel view on the left side like "Old comment"' do click_parallel_diff_line(sample_commit.line_code, 'old') - page.within("#{diff_file_selector} form[id$='#{sample_commit.line_code}']") do + page.within("#{diff_file_selector} form[id$='#{sample_commit.line_code}-true']") do fill_in "note[note]", with: "Old comment" find(".js-comment-button").trigger("click") end @@ -41,7 +41,7 @@ module SharedDiffNote step 'I leave a diff comment in a parallel view on the right side like "New comment"' do click_parallel_diff_line(sample_commit.line_code, 'new') - page.within("#{diff_file_selector} form[id$='#{sample_commit.line_code}']") do + page.within("#{diff_file_selector} form[id$='#{sample_commit.line_code}-true']") do fill_in "note[note]", with: "New comment" find(".js-comment-button").trigger("click") end @@ -51,7 +51,7 @@ module SharedDiffNote page.within(diff_file_selector) do click_diff_line(sample_commit.line_code) - page.within("form[id$='#{sample_commit.line_code}']") do + page.within("form[id$='#{sample_commit.line_code}-true']") do fill_in "note[note]", with: "Should fix it :smile:" find('.js-md-preview-button').click end @@ -62,7 +62,7 @@ module SharedDiffNote page.within(diff_file_selector) do click_diff_line(sample_commit.del_line_code) - page.within("form[id$='#{sample_commit.del_line_code}']") do + page.within("form[id$='#{sample_commit.del_line_code}-true']") do fill_in "note[note]", with: "DRY this up" find('.js-md-preview-button').click end @@ -91,7 +91,7 @@ module SharedDiffNote page.within(diff_file_selector) do click_diff_line(sample_commit.line_code) - page.within("form[id$='#{sample_commit.line_code}']") do + page.within("form[id$='#{sample_commit.line_code}-true']") do fill_in 'note[note]', with: ':smile:' click_button('Comment') end diff --git a/features/steps/shared/issuable.rb b/features/steps/shared/issuable.rb index a58b3cb7e1..733e80b727 100644 --- a/features/steps/shared/issuable.rb +++ b/features/steps/shared/issuable.rb @@ -111,7 +111,7 @@ module SharedIssuable step 'I sort the list by "Oldest updated"' do find('button.dropdown-toggle.btn').click - page.within('ul.dropdown-menu.dropdown-menu-align-right li') do + page.within('.content ul.dropdown-menu.dropdown-menu-align-right li') do click_link "Oldest updated" end end @@ -119,7 +119,7 @@ module SharedIssuable step 'I sort the list by "Least popular"' do find('button.dropdown-toggle.btn').click - page.within('ul.dropdown-menu.dropdown-menu-align-right li') do + page.within('.content ul.dropdown-menu.dropdown-menu-align-right li') do click_link 'Least popular' end end @@ -127,13 +127,13 @@ module SharedIssuable step 'I sort the list by "Most popular"' do find('button.dropdown-toggle.btn').click - page.within('ul.dropdown-menu.dropdown-menu-align-right li') do + page.within('.content ul.dropdown-menu.dropdown-menu-align-right li') do click_link 'Most popular' end end step 'The list should be sorted by "Oldest updated"' do - page.within('div.dropdown.inline.prepend-left-10') do + page.within('.content div.dropdown.inline.prepend-left-10') do expect(page.find('button.dropdown-toggle.btn')).to have_content('Oldest updated') end end diff --git a/features/steps/shared/note.rb b/features/steps/shared/note.rb index a3c3887ab4..3d7c6ef9d2 100644 --- a/features/steps/shared/note.rb +++ b/features/steps/shared/note.rb @@ -107,7 +107,7 @@ module SharedNote end step 'I should see no notes at all' do - expect(page).to_not have_css('.note') + expect(page).not_to have_css('.note') end # Markdown diff --git a/features/steps/shared/project.rb b/features/steps/shared/project.rb index ea5f958030..ce9ea7ee18 100644 --- a/features/steps/shared/project.rb +++ b/features/steps/shared/project.rb @@ -95,7 +95,7 @@ module SharedProject step 'I should see project settings' do expect(current_path).to eq edit_namespace_project_path(@project.namespace, @project) expect(page).to have_content("Project name") - expect(page).to have_content("Features:") + expect(page).to have_content("Features") end def current_project diff --git a/features/steps/shared/project_tab.rb b/features/steps/shared/project_tab.rb index 4fc2ece79f..bfee879330 100644 --- a/features/steps/shared/project_tab.rb +++ b/features/steps/shared/project_tab.rb @@ -8,12 +8,8 @@ module SharedProjectTab ensure_active_main_tab('Project') end - step 'the active main tab should be Files' do - ensure_active_main_tab('Files') - end - - step 'the active main tab should be Commits' do - ensure_active_main_tab('Commits') + step 'the active main tab should be Code' do + ensure_active_main_tab('Code') end step 'the active main tab should be Graphs' do @@ -41,9 +37,7 @@ module SharedProjectTab end step 'the active main tab should be Settings' do - page.within '.nav-sidebar' do - expect(page).to have_content('Go to project') - end + expect(page).to have_selector('.layout-nav .nav-links > li.active', count: 0) end step 'the active main tab should be Activity' do @@ -53,4 +47,12 @@ module SharedProjectTab step 'the active sub tab should be Network' do ensure_active_sub_tab('Network') end + + step 'the active sub tab should be Files' do + ensure_active_sub_tab('Files') + end + + step 'the active sub tab should be Commits' do + ensure_active_sub_tab('Commits') + end end diff --git a/features/steps/shared/shortcuts.rb b/features/steps/shared/shortcuts.rb index bbb7afec0a..a75a8474d2 100644 --- a/features/steps/shared/shortcuts.rb +++ b/features/steps/shared/shortcuts.rb @@ -1,4 +1,4 @@ -module SharedActiveTab +module SharedShortcuts include Spinach::DSL step 'I press "g" and "p"' do diff --git a/features/steps/shared/sidebar_active_tab.rb b/features/steps/shared/sidebar_active_tab.rb new file mode 100644 index 0000000000..5c47238777 --- /dev/null +++ b/features/steps/shared/sidebar_active_tab.rb @@ -0,0 +1,35 @@ +module SharedSidebarActiveTab + include Spinach::DSL + + step 'the active main tab should be Help' do + ensure_active_main_tab('Help') + end + + step 'no other main tabs should be active' do + expect(page).to have_selector('.nav-sidebar > li.active', count: 1) + end + + def ensure_active_main_tab(content) + expect(find('.nav-sidebar li.active')).to have_content(content) + end + + step 'the active main tab should be Home' do + ensure_active_main_tab('Projects') + end + + step 'the active main tab should be Projects' do + ensure_active_main_tab('Projects') + end + + step 'the active main tab should be Issues' do + ensure_active_main_tab('Issues') + end + + step 'the active main tab should be Merge Requests' do + ensure_active_main_tab('Merge Requests') + end + + step 'the active main tab should be Help' do + ensure_active_main_tab('Help') + end +end diff --git a/features/steps/snippets/snippets.rb b/features/steps/snippets/snippets.rb index 023032e679..19366b1107 100644 --- a/features/steps/snippets/snippets.rb +++ b/features/steps/snippets/snippets.rb @@ -14,12 +14,12 @@ class Spinach::Features::Snippets < Spinach::FeatureSteps step 'I click link "Edit"' do page.within ".detail-page-header" do - click_link "Edit" + first(:link, "Edit").click end end step 'I click link "Delete"' do - click_link "Delete" + first(:link, "Delete").click end step 'I submit new snippet "Personal snippet three"' do diff --git a/features/steps/user.rb b/features/steps/user.rb index b1d088f07f..59385a6ab5 100644 --- a/features/steps/user.rb +++ b/features/steps/user.rb @@ -34,7 +34,7 @@ class Spinach::Features::User < Spinach::FeatureSteps end step 'I should see contributions calendar' do - expect(page).to have_css('.cal-heatmap-container') + expect(page).to have_css('.js-contrib-calendar') end def contributed_project diff --git a/generator_templates/active_record/migration/create_table_migration.rb b/generator_templates/active_record/migration/create_table_migration.rb new file mode 100644 index 0000000000..27acc75dcc --- /dev/null +++ b/generator_templates/active_record/migration/create_table_migration.rb @@ -0,0 +1,35 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class <%= migration_class_name %> < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + # When using the methods "add_concurrent_index" or "add_column_with_default" + # you must disable the use of transactions as these methods can not run in an + # existing transaction. When using "add_concurrent_index" make sure that this + # method is the _only_ method called in the migration, any other changes + # should go in a separate migration. This ensures that upon failure _only_ the + # index creation fails and can be retried or reverted easily. + # + # To disable transactions uncomment the following line and remove these + # comments: + # disable_ddl_transaction! + + def change + create_table :<%= table_name %> do |t| +<% attributes.each do |attribute| -%> +<% if attribute.password_digest? -%> + t.string :password_digest<%= attribute.inject_options %> +<% else -%> + t.<%= attribute.type %> :<%= attribute.name %><%= attribute.inject_options %> +<% end -%> +<% end -%> +<% if options[:timestamps] %> + t.timestamps null: false +<% end -%> + end +<% attributes_with_index.each do |attribute| -%> + add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %> +<% end -%> + end +end diff --git a/generator_templates/active_record/migration/migration.rb b/generator_templates/active_record/migration/migration.rb new file mode 100644 index 0000000000..06bdea1136 --- /dev/null +++ b/generator_templates/active_record/migration/migration.rb @@ -0,0 +1,55 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class <%= migration_class_name %> < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + # When using the methods "add_concurrent_index" or "add_column_with_default" + # you must disable the use of transactions as these methods can not run in an + # existing transaction. When using "add_concurrent_index" make sure that this + # method is the _only_ method called in the migration, any other changes + # should go in a separate migration. This ensures that upon failure _only_ the + # index creation fails and can be retried or reverted easily. + # + # To disable transactions uncomment the following line and remove these + # comments: + # disable_ddl_transaction! + +<%- if migration_action == 'add' -%> + def change +<% attributes.each do |attribute| -%> + <%- if attribute.reference? -%> + add_reference :<%= table_name %>, :<%= attribute.name %><%= attribute.inject_options %> + <%- else -%> + add_column :<%= table_name %>, :<%= attribute.name %>, :<%= attribute.type %><%= attribute.inject_options %> + <%- if attribute.has_index? -%> + add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %> + <%- end -%> + <%- end -%> +<%- end -%> + end +<%- elsif migration_action == 'join' -%> + def change + create_join_table :<%= join_tables.first %>, :<%= join_tables.second %> do |t| + <%- attributes.each do |attribute| -%> + <%= '# ' unless attribute.has_index? -%>t.index <%= attribute.index_name %><%= attribute.inject_index_options %> + <%- end -%> + end + end +<%- else -%> + def change +<% attributes.each do |attribute| -%> +<%- if migration_action -%> + <%- if attribute.reference? -%> + remove_reference :<%= table_name %>, :<%= attribute.name %><%= attribute.inject_options %> + <%- else -%> + <%- if attribute.has_index? -%> + remove_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %> + <%- end -%> + remove_column :<%= table_name %>, :<%= attribute.name %>, :<%= attribute.type %><%= attribute.inject_options %> + <%- end -%> +<%- end -%> +<%- end -%> + end +<%- end -%> +end diff --git a/lib/api/api.rb b/lib/api/api.rb index cc1004f800..6cd909f611 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -1,5 +1,3 @@ -Dir["#{Rails.root}/lib/api/*.rb"].each {|file| require file} - module API class API < Grape::API include APIGuard @@ -25,38 +23,41 @@ module API format :json content_type :txt, "text/plain" - helpers Helpers + # Ensure the namespace is right, otherwise we might load Grape::API::Helpers + helpers ::API::Helpers - mount Groups - mount GroupMembers - mount Users - mount Projects - mount Repositories - mount Issues - mount Milestones - mount Session - mount MergeRequests - mount Notes - mount Internal - mount SystemHooks - mount ProjectSnippets - mount ProjectMembers - mount DeployKeys - mount ProjectHooks - mount Services - mount Files - mount Commits - mount CommitStatus - mount Namespaces - mount Branches - mount Labels - mount Settings - mount Keys - mount Tags - mount Triggers - mount Builds - mount Variables - mount Runners - mount Licenses + mount ::API::Groups + mount ::API::GroupMembers + mount ::API::Users + mount ::API::Projects + mount ::API::Repositories + mount ::API::Issues + mount ::API::Milestones + mount ::API::Session + mount ::API::MergeRequests + mount ::API::Notes + mount ::API::Internal + mount ::API::SystemHooks + mount ::API::ProjectSnippets + mount ::API::ProjectMembers + mount ::API::DeployKeys + mount ::API::ProjectHooks + mount ::API::Services + mount ::API::Files + mount ::API::Commits + mount ::API::CommitStatuses + mount ::API::Namespaces + mount ::API::Branches + mount ::API::Labels + mount ::API::Settings + mount ::API::Keys + mount ::API::Tags + mount ::API::Triggers + mount ::API::Builds + mount ::API::Variables + mount ::API::Runners + mount ::API::Licenses + mount ::API::Subscriptions + mount ::API::Gitignores end end diff --git a/lib/api/api_guard.rb b/lib/api/api_guard.rb index b9994fcefd..7e67edb203 100644 --- a/lib/api/api_guard.rb +++ b/lib/api/api_guard.rb @@ -2,171 +2,175 @@ require 'rack/oauth2' -module APIGuard - extend ActiveSupport::Concern +module API + module APIGuard + extend ActiveSupport::Concern - included do |base| - # OAuth2 Resource Server Authentication - use Rack::OAuth2::Server::Resource::Bearer, 'The API' do |request| - # The authenticator only fetches the raw token string + included do |base| + # OAuth2 Resource Server Authentication + use Rack::OAuth2::Server::Resource::Bearer, 'The API' do |request| + # The authenticator only fetches the raw token string - # Must yield access token to store it in the env - request.access_token - end - - helpers HelperMethods - - install_error_responders(base) - end - - # Helper Methods for Grape Endpoint - module HelperMethods - # Invokes the doorkeeper guard. - # - # If token is presented and valid, then it sets @current_user. - # - # If the token does not have sufficient scopes to cover the requred scopes, - # then it raises InsufficientScopeError. - # - # If the token is expired, then it raises ExpiredError. - # - # If the token is revoked, then it raises RevokedError. - # - # If the token is not found (nil), then it raises TokenNotFoundError. - # - # Arguments: - # - # scopes: (optional) scopes required for this guard. - # Defaults to empty array. - # - def doorkeeper_guard!(scopes: []) - if (access_token = find_access_token).nil? - raise TokenNotFoundError - - else - case validate_access_token(access_token, scopes) - when Oauth2::AccessTokenValidationService::INSUFFICIENT_SCOPE - raise InsufficientScopeError.new(scopes) - when Oauth2::AccessTokenValidationService::EXPIRED - raise ExpiredError - when Oauth2::AccessTokenValidationService::REVOKED - raise RevokedError - when Oauth2::AccessTokenValidationService::VALID - @current_user = User.find(access_token.resource_owner_id) - end + # Must yield access token to store it in the env + request.access_token end + + helpers HelperMethods + + install_error_responders(base) end - def doorkeeper_guard(scopes: []) - if access_token = find_access_token - case validate_access_token(access_token, scopes) - when Oauth2::AccessTokenValidationService::INSUFFICIENT_SCOPE - raise InsufficientScopeError.new(scopes) + # Helper Methods for Grape Endpoint + module HelperMethods + # Invokes the doorkeeper guard. + # + # If token is presented and valid, then it sets @current_user. + # + # If the token does not have sufficient scopes to cover the requred scopes, + # then it raises InsufficientScopeError. + # + # If the token is expired, then it raises ExpiredError. + # + # If the token is revoked, then it raises RevokedError. + # + # If the token is not found (nil), then it raises TokenNotFoundError. + # + # Arguments: + # + # scopes: (optional) scopes required for this guard. + # Defaults to empty array. + # + def doorkeeper_guard!(scopes: []) + if (access_token = find_access_token).nil? + raise TokenNotFoundError - when Oauth2::AccessTokenValidationService::EXPIRED - raise ExpiredError - - when Oauth2::AccessTokenValidationService::REVOKED - raise RevokedError - - when Oauth2::AccessTokenValidationService::VALID - @current_user = User.find(access_token.resource_owner_id) - end - end - end - - def current_user - @current_user - end - - private - def find_access_token - @access_token ||= Doorkeeper.authenticate(doorkeeper_request, Doorkeeper.configuration.access_token_methods) - end - - def doorkeeper_request - @doorkeeper_request ||= ActionDispatch::Request.new(env) - end - - def validate_access_token(access_token, scopes) - Oauth2::AccessTokenValidationService.validate(access_token, scopes: scopes) - end - end - - module ClassMethods - # Installs the doorkeeper guard on the whole Grape API endpoint. - # - # Arguments: - # - # scopes: (optional) scopes required for this guard. - # Defaults to empty array. - # - def guard_all!(scopes: []) - before do - guard! scopes: scopes - end - end - - private - def install_error_responders(base) - error_classes = [ MissingTokenError, TokenNotFoundError, - ExpiredError, RevokedError, InsufficientScopeError] - - base.send :rescue_from, *error_classes, oauth2_bearer_token_error_handler - end - - def oauth2_bearer_token_error_handler - Proc.new do |e| - response = - case e - when MissingTokenError - Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new - - when TokenNotFoundError - Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new( - :invalid_token, - "Bad Access Token.") - - when ExpiredError - Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new( - :invalid_token, - "Token is expired. You can either do re-authorization or token refresh.") - - when RevokedError - Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new( - :invalid_token, - "Token was revoked. You have to re-authorize from the user.") - - when InsufficientScopeError - # FIXME: ForbiddenError (inherited from Bearer::Forbidden of Rack::Oauth2) - # does not include WWW-Authenticate header, which breaks the standard. - Rack::OAuth2::Server::Resource::Bearer::Forbidden.new( - :insufficient_scope, - Rack::OAuth2::Server::Resource::ErrorMethods::DEFAULT_DESCRIPTION[:insufficient_scope], - { scope: e.scopes }) + else + case validate_access_token(access_token, scopes) + when Oauth2::AccessTokenValidationService::INSUFFICIENT_SCOPE + raise InsufficientScopeError.new(scopes) + when Oauth2::AccessTokenValidationService::EXPIRED + raise ExpiredError + when Oauth2::AccessTokenValidationService::REVOKED + raise RevokedError + when Oauth2::AccessTokenValidationService::VALID + @current_user = User.find(access_token.resource_owner_id) end + end + end - response.finish + def doorkeeper_guard(scopes: []) + if access_token = find_access_token + case validate_access_token(access_token, scopes) + when Oauth2::AccessTokenValidationService::INSUFFICIENT_SCOPE + raise InsufficientScopeError.new(scopes) + + when Oauth2::AccessTokenValidationService::EXPIRED + raise ExpiredError + + when Oauth2::AccessTokenValidationService::REVOKED + raise RevokedError + + when Oauth2::AccessTokenValidationService::VALID + @current_user = User.find(access_token.resource_owner_id) + end + end + end + + def current_user + @current_user + end + + private + + def find_access_token + @access_token ||= Doorkeeper.authenticate(doorkeeper_request, Doorkeeper.configuration.access_token_methods) + end + + def doorkeeper_request + @doorkeeper_request ||= ActionDispatch::Request.new(env) + end + + def validate_access_token(access_token, scopes) + Oauth2::AccessTokenValidationService.validate(access_token, scopes: scopes) end end - end - # - # Exceptions - # + module ClassMethods + # Installs the doorkeeper guard on the whole Grape API endpoint. + # + # Arguments: + # + # scopes: (optional) scopes required for this guard. + # Defaults to empty array. + # + def guard_all!(scopes: []) + before do + guard! scopes: scopes + end + end - class MissingTokenError < StandardError; end + private - class TokenNotFoundError < StandardError; end + def install_error_responders(base) + error_classes = [ MissingTokenError, TokenNotFoundError, + ExpiredError, RevokedError, InsufficientScopeError] - class ExpiredError < StandardError; end + base.send :rescue_from, *error_classes, oauth2_bearer_token_error_handler + end - class RevokedError < StandardError; end + def oauth2_bearer_token_error_handler + Proc.new do |e| + response = + case e + when MissingTokenError + Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new - class InsufficientScopeError < StandardError - attr_reader :scopes - def initialize(scopes) - @scopes = scopes + when TokenNotFoundError + Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new( + :invalid_token, + "Bad Access Token.") + + when ExpiredError + Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new( + :invalid_token, + "Token is expired. You can either do re-authorization or token refresh.") + + when RevokedError + Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new( + :invalid_token, + "Token was revoked. You have to re-authorize from the user.") + + when InsufficientScopeError + # FIXME: ForbiddenError (inherited from Bearer::Forbidden of Rack::Oauth2) + # does not include WWW-Authenticate header, which breaks the standard. + Rack::OAuth2::Server::Resource::Bearer::Forbidden.new( + :insufficient_scope, + Rack::OAuth2::Server::Resource::ErrorMethods::DEFAULT_DESCRIPTION[:insufficient_scope], + { scope: e.scopes }) + end + + response.finish + end + end + end + + # + # Exceptions + # + + class MissingTokenError < StandardError; end + + class TokenNotFoundError < StandardError; end + + class ExpiredError < StandardError; end + + class RevokedError < StandardError; end + + class InsufficientScopeError < StandardError + attr_reader :scopes + def initialize(scopes) + @scopes = scopes + end end end end diff --git a/lib/api/commit_statuses.rb b/lib/api/commit_statuses.rb index 7388ed2f4e..9bcd33ff19 100644 --- a/lib/api/commit_statuses.rb +++ b/lib/api/commit_statuses.rb @@ -2,7 +2,7 @@ require 'mime/types' module API # Project commit statuses API - class CommitStatus < Grape::API + class CommitStatuses < Grape::API resource :projects do before { authenticate! } diff --git a/lib/api/commits.rb b/lib/api/commits.rb index 93a3a5ce08..4a11c8e362 100644 --- a/lib/api/commits.rb +++ b/lib/api/commits.rb @@ -107,6 +107,8 @@ module API break if opts[:line_code] end + + opts[:type] = LegacyDiffNote.name if opts[:line_code] end note = ::Notes::CreateService.new(user_project, current_user, opts).execute diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 716ca6f7ed..790a1869f7 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -66,7 +66,8 @@ module API expose :owner, using: Entities::UserBasic, unless: ->(project, options) { project.group } expose :name, :name_with_namespace expose :path, :path_with_namespace - expose :issues_enabled, :merge_requests_enabled, :wiki_enabled, :builds_enabled, :snippets_enabled, :created_at, :last_activity_at + expose :issues_enabled, :merge_requests_enabled, :wiki_enabled, :builds_enabled, :snippets_enabled, :container_registry_enabled + expose :created_at, :last_activity_at expose :shared_runners_enabled expose :creator_id expose :namespace @@ -170,10 +171,10 @@ module API expose :label_names, as: :labels expose :milestone, using: Entities::Milestone expose :assignee, :author, using: Entities::UserBasic - expose :subscribed do |issue, options| issue.subscribed?(options[:current_user]) end + expose :user_notes_count end class MergeRequest < ProjectEntity @@ -187,10 +188,10 @@ module API expose :milestone, using: Entities::Milestone expose :merge_when_build_succeeds expose :merge_status - expose :subscribed do |merge_request, options| merge_request.subscribed?(options[:current_user]) end + expose :user_notes_count end class MergeRequestChanges < MergeRequest @@ -227,9 +228,9 @@ module API class CommitNote < Grape::Entity expose :note - expose(:path) { |note| note.diff_file_name } - expose(:line) { |note| note.diff_new_line } - expose(:line_type) { |note| note.diff_line_type } + expose(:path) { |note| note.diff_file_path if note.legacy_diff_note? } + expose(:line) { |note| note.diff_new_line if note.legacy_diff_note? } + expose(:line_type) { |note| note.diff_line_type if note.legacy_diff_note? } expose :author, using: Entities::UserBasic expose :created_at end @@ -307,6 +308,10 @@ module API class Label < Grape::Entity expose :name, :color, :description expose :open_issues_count, :closed_issues_count, :open_merge_requests_count + + expose :subscribed do |label, options| + label.subscribed?(options[:current_user]) + end end class Compare < Grape::Entity @@ -357,6 +362,7 @@ module API expose :restricted_signup_domains expose :user_oauth_applications expose :after_sign_out_path + expose :container_registry_token_expire_delay end class Release < Grape::Entity @@ -403,6 +409,7 @@ module API class RunnerDetails < Runner expose :tag_list + expose :run_untagged expose :version, :revision, :platform, :architecture expose :contacted_at expose :token, if: lambda { |runner, options| options[:current_user].is_admin? || !runner.is_shared? } @@ -451,5 +458,13 @@ module API expose(:limitations) { |license| license.meta['limitations'] } expose :content end + + class GitignoresList < Grape::Entity + expose :name + end + + class Gitignore < Grape::Entity + expose :name, :content + end end end diff --git a/lib/api/gitignores.rb b/lib/api/gitignores.rb new file mode 100644 index 0000000000..270c9501dd --- /dev/null +++ b/lib/api/gitignores.rb @@ -0,0 +1,29 @@ +module API + class Gitignores < Grape::API + + # Get the list of the available gitignore templates + # + # Example Request: + # GET /gitignores + get 'gitignores' do + present Gitlab::Gitignore.all, with: Entities::GitignoresList + end + + # Get the text for a specific gitignore + # + # Parameters: + # name (required) - The name of a license + # + # Example Request: + # GET /gitignores/Elixir + # + get 'gitignores/:name' do + required_attributes! [:name] + + gitignore = Gitlab::Gitignore.find(params[:name]) + not_found!('.gitignore') unless gitignore + + present gitignore, with: Entities::Gitignore + end + end +end diff --git a/lib/api/groups.rb b/lib/api/groups.rb index 91e420832f..9d8b8d737a 100644 --- a/lib/api/groups.rb +++ b/lib/api/groups.rb @@ -95,8 +95,7 @@ module API # GET /groups/:id/projects get ":id/projects" do group = find_group(params[:id]) - projects = group.projects - projects = filter_projects(projects) + projects = GroupProjectsFinder.new(group).execute(current_user) projects = paginate projects present projects, with: Entities::Project end diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 40c967453f..2aaa0557ea 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -2,7 +2,7 @@ module API module Helpers PRIVATE_TOKEN_HEADER = "HTTP_PRIVATE_TOKEN" PRIVATE_TOKEN_PARAM = :private_token - SUDO_HEADER ="HTTP_SUDO" + SUDO_HEADER = "HTTP_SUDO" SUDO_PARAM = :sudo def parse_boolean(value) @@ -29,7 +29,7 @@ module API @current_user end - def sudo_identifier() + def sudo_identifier identifier ||= params[SUDO_PARAM] || env[SUDO_HEADER] # Regex for integers @@ -95,6 +95,17 @@ module API end end + def find_project_label(id) + label = user_project.labels.find_by_id(id) || user_project.labels.find_by_title(id) + label || not_found!('Label') + end + + def find_project_issue(id) + issue = user_project.issues.find(id) + not_found! unless can?(current_user, :read_issue, issue) + issue + end + def paginate(relation) relation.page(params[:page]).per(params[:per_page].to_i).tap do |data| add_pagination_headers(data) diff --git a/lib/api/issues.rb b/lib/api/issues.rb index 4092874948..f59a4d6c01 100644 --- a/lib/api/issues.rb +++ b/lib/api/issues.rb @@ -103,8 +103,7 @@ module API # Example Request: # GET /projects/:id/issues/:issue_id get ":id/issues/:issue_id" do - @issue = user_project.issues.find(params[:issue_id]) - not_found! unless can?(current_user, :read_issue, @issue) + @issue = find_project_issue(params[:issue_id]) present @issue, with: Entities::Issue, current_user: current_user end @@ -234,42 +233,6 @@ module API authorize!(:destroy_issue, issue) issue.destroy end - - # Subscribes to a project issue - # - # Parameters: - # id (required) - The ID of a project - # issue_id (required) - The ID of a project issue - # Example Request: - # POST /projects/:id/issues/:issue_id/subscription - post ':id/issues/:issue_id/subscription' do - issue = user_project.issues.find(params[:issue_id]) - - if issue.subscribed?(current_user) - not_modified! - else - issue.toggle_subscription(current_user) - present issue, with: Entities::Issue, current_user: current_user - end - end - - # Unsubscribes from a project issue - # - # Parameters: - # id (required) - The ID of a project - # issue_id (required) - The ID of a project issue - # Example Request: - # DELETE /projects/:id/issues/:issue_id/subscription - delete ':id/issues/:issue_id/subscription' do - issue = user_project.issues.find(params[:issue_id]) - - if issue.subscribed?(current_user) - issue.unsubscribe(current_user) - present issue, with: Entities::Issue, current_user: current_user - else - not_modified! - end - end end end end diff --git a/lib/api/labels.rb b/lib/api/labels.rb index 4af6bef0fa..c806829d69 100644 --- a/lib/api/labels.rb +++ b/lib/api/labels.rb @@ -11,7 +11,7 @@ module API # Example Request: # GET /projects/:id/labels get ':id/labels' do - present user_project.labels, with: Entities::Label + present user_project.labels, with: Entities::Label, current_user: current_user end # Creates a new label @@ -36,7 +36,7 @@ module API label = user_project.labels.create(attrs) if label.valid? - present label, with: Entities::Label + present label, with: Entities::Label, current_user: current_user else render_validation_error!(label) end @@ -90,7 +90,7 @@ module API attrs[:name] = attrs.delete(:new_name) if attrs.key?(:new_name) if label.update(attrs) - present label, with: Entities::Label + present label, with: Entities::Label, current_user: current_user else render_validation_error!(label) end diff --git a/lib/api/licenses.rb b/lib/api/licenses.rb index 187d2c0470..be0e113fbc 100644 --- a/lib/api/licenses.rb +++ b/lib/api/licenses.rb @@ -2,15 +2,15 @@ module API # Licenses API class Licenses < Grape::API PROJECT_TEMPLATE_REGEX = - /[\<\{\[] - (project|description| - one\sline\s.+\swhat\sit\sdoes\.) # matching the start and end is enough here - [\>\}\]]/xi.freeze + /[\<\{\[] + (project|description| + one\sline\s.+\swhat\sit\sdoes\.) # matching the start and end is enough here + [\>\}\]]/xi.freeze YEAR_TEMPLATE_REGEX = /[<{\[](year|yyyy)[>}\]]/i.freeze FULLNAME_TEMPLATE_REGEX = - /[\<\{\[] - (fullname|name\sof\s(author|copyright\sowner)) - [\>\}\]]/xi.freeze + /[\<\{\[] + (fullname|name\sof\s(author|copyright\sowner)) + [\>\}\]]/xi.freeze # Get the list of the available license templates # diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb index 7e78609ecb..4e7de8867b 100644 --- a/lib/api/merge_requests.rb +++ b/lib/api/merge_requests.rb @@ -327,42 +327,6 @@ module API issues = ::Kaminari.paginate_array(merge_request.closes_issues(current_user)) present paginate(issues), with: Entities::Issue, current_user: current_user end - - # Subscribes to a merge request - # - # Parameters: - # id (required) - The ID of a project - # merge_request_id (required) - The ID of a merge request - # Example Request: - # POST /projects/:id/issues/:merge_request_id/subscription - post "#{path}/subscription" do - merge_request = user_project.merge_requests.find(params[:merge_request_id]) - - if merge_request.subscribed?(current_user) - not_modified! - else - merge_request.toggle_subscription(current_user) - present merge_request, with: Entities::MergeRequest, current_user: current_user - end - end - - # Unsubscribes from a merge request - # - # Parameters: - # id (required) - The ID of a project - # merge_request_id (required) - The ID of a merge request - # Example Request: - # DELETE /projects/:id/merge_requests/:merge_request_id/subscription - delete "#{path}/subscription" do - merge_request = user_project.merge_requests.find(params[:merge_request_id]) - - if merge_request.subscribed?(current_user) - merge_request.unsubscribe(current_user) - present merge_request, with: Entities::MergeRequest, current_user: current_user - else - not_modified! - end - end end end end diff --git a/lib/api/notes.rb b/lib/api/notes.rb index 71a53e6f0d..d4fcfd3d4d 100644 --- a/lib/api/notes.rb +++ b/lib/api/notes.rb @@ -19,20 +19,24 @@ module API # GET /projects/:id/issues/:noteable_id/notes # GET /projects/:id/snippets/:noteable_id/notes get ":id/#{noteables_str}/:#{noteable_id_str}/notes" do - @noteable = user_project.send(:"#{noteables_str}").find(params[:"#{noteable_id_str}"]) + @noteable = user_project.send(noteables_str.to_sym).find(params[noteable_id_str.to_sym]) - # We exclude notes that are cross-references and that cannot be viewed - # by the current user. By doing this exclusion at this level and not - # at the DB query level (which we cannot in that case), the current - # page can have less elements than :per_page even if - # there's more than one page. - notes = - # paginate() only works with a relation. This could lead to a - # mismatch between the pagination headers info and the actual notes - # array returned, but this is really a edge-case. - paginate(@noteable.notes). - reject { |n| n.cross_reference_not_visible_for?(current_user) } - present notes, with: Entities::Note + if can?(current_user, noteable_read_ability_name(@noteable), @noteable) + # We exclude notes that are cross-references and that cannot be viewed + # by the current user. By doing this exclusion at this level and not + # at the DB query level (which we cannot in that case), the current + # page can have less elements than :per_page even if + # there's more than one page. + notes = + # paginate() only works with a relation. This could lead to a + # mismatch between the pagination headers info and the actual notes + # array returned, but this is really a edge-case. + paginate(@noteable.notes). + reject { |n| n.cross_reference_not_visible_for?(current_user) } + present notes, with: Entities::Note + else + not_found!("Notes") + end end # Get a single +noteable+ note @@ -45,13 +49,14 @@ module API # GET /projects/:id/issues/:noteable_id/notes/:note_id # GET /projects/:id/snippets/:noteable_id/notes/:note_id get ":id/#{noteables_str}/:#{noteable_id_str}/notes/:note_id" do - @noteable = user_project.send(:"#{noteables_str}").find(params[:"#{noteable_id_str}"]) + @noteable = user_project.send(noteables_str.to_sym).find(params[noteable_id_str.to_sym]) @note = @noteable.notes.find(params[:note_id]) + can_read_note = can?(current_user, noteable_read_ability_name(@noteable), @noteable) && !@note.cross_reference_not_visible_for?(current_user) - if @note.cross_reference_not_visible_for?(current_user) - not_found!("Note") - else + if can_read_note present @note, with: Entities::Note + else + not_found!("Note") end end @@ -136,5 +141,11 @@ module API end end end + + helpers do + def noteable_read_ability_name(noteable) + "read_#{noteable.class.to_s.underscore.downcase}".to_sym + end + end end end diff --git a/lib/api/projects.rb b/lib/api/projects.rb index cc2c7a0c50..5a22d14988 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -44,7 +44,7 @@ module API # Example Request: # GET /projects/starred get '/starred' do - @projects = current_user.starred_projects + @projects = current_user.viewable_starred_projects @projects = filter_projects(@projects) @projects = paginate @projects present @projects, with: Entities::Project @@ -94,6 +94,7 @@ module API # builds_enabled (optional) # wiki_enabled (optional) # snippets_enabled (optional) + # container_registry_enabled (optional) # shared_runners_enabled (optional) # namespace_id (optional) - defaults to user namespace # public (optional) - if true same as setting visibility_level = 20 @@ -112,6 +113,7 @@ module API :builds_enabled, :wiki_enabled, :snippets_enabled, + :container_registry_enabled, :shared_runners_enabled, :namespace_id, :public, @@ -143,6 +145,7 @@ module API # builds_enabled (optional) # wiki_enabled (optional) # snippets_enabled (optional) + # container_registry_enabled (optional) # shared_runners_enabled (optional) # public (optional) - if true same as setting visibility_level = 20 # visibility_level (optional) @@ -206,6 +209,7 @@ module API # builds_enabled (optional) # wiki_enabled (optional) # snippets_enabled (optional) + # container_registry_enabled (optional) # shared_runners_enabled (optional) # public (optional) - if true same as setting visibility_level = 20 # visibility_level (optional) - visibility level of a project @@ -222,6 +226,7 @@ module API :builds_enabled, :wiki_enabled, :snippets_enabled, + :container_registry_enabled, :shared_runners_enabled, :public, :visibility_level, diff --git a/lib/api/runners.rb b/lib/api/runners.rb index 8ec91485b2..4faba9dc87 100644 --- a/lib/api/runners.rb +++ b/lib/api/runners.rb @@ -49,7 +49,7 @@ module API runner = get_runner(params[:id]) authenticate_update_runner!(runner) - attrs = attributes_for_keys [:description, :active, :tag_list] + attrs = attributes_for_keys [:description, :active, :tag_list, :run_untagged] if runner.update(attrs) present runner, with: Entities::RunnerDetails, current_user: current_user else diff --git a/lib/api/subscriptions.rb b/lib/api/subscriptions.rb new file mode 100644 index 0000000000..c49e2a21b8 --- /dev/null +++ b/lib/api/subscriptions.rb @@ -0,0 +1,60 @@ +module API + class Subscriptions < Grape::API + before { authenticate! } + + subscribable_types = { + 'merge_request' => proc { |id| user_project.merge_requests.find(id) }, + 'merge_requests' => proc { |id| user_project.merge_requests.find(id) }, + 'issues' => proc { |id| find_project_issue(id) }, + 'labels' => proc { |id| find_project_label(id) }, + } + + resource :projects do + subscribable_types.each do |type, finder| + type_singularized = type.singularize + type_id_str = :"#{type_singularized}_id" + entity_class = Entities.const_get(type_singularized.camelcase) + + # Subscribe to a resource + # + # Parameters: + # id (required) - The ID of a project + # subscribable_id (required) - The ID of a resource + # Example Request: + # POST /projects/:id/labels/:subscribable_id/subscription + # POST /projects/:id/issues/:subscribable_id/subscription + # POST /projects/:id/merge_requests/:subscribable_id/subscription + post ":id/#{type}/:#{type_id_str}/subscription" do + resource = instance_exec(params[type_id_str], &finder) + + if resource.subscribed?(current_user) + not_modified! + else + resource.subscribe(current_user) + present resource, with: entity_class, current_user: current_user + end + end + + # Unsubscribe from a resource + # + # Parameters: + # id (required) - The ID of a project + # subscribable_id (required) - The ID of a resource + # Example Request: + # DELETE /projects/:id/labels/:subscribable_id/subscription + # DELETE /projects/:id/issues/:subscribable_id/subscription + # DELETE /projects/:id/merge_requests/:subscribable_id/subscription + delete ":id/#{type}/:#{type_id_str}/subscription" do + resource = instance_exec(params[type_id_str], &finder) + + if !resource.subscribed?(current_user) + not_modified! + else + resource.unsubscribe(current_user) + present resource, with: entity_class, current_user: current_user + end + end + end + end + end +end diff --git a/lib/api/users.rb b/lib/api/users.rb index ea6fa2dc8a..8a376d3c2a 100644 --- a/lib/api/users.rb +++ b/lib/api/users.rb @@ -76,7 +76,7 @@ module API required_attributes! [:email, :password, :name, :username] attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :bio, :location, :can_create_group, :admin, :confirm, :external] admin = attrs.delete(:admin) - confirm = !(attrs.delete(:confirm) =~ (/(false|f|no|0)$/i)) + confirm = !(attrs.delete(:confirm) =~ /(false|f|no|0)$/i) user = User.build_user(attrs) user.admin = admin unless admin.nil? user.skip_confirmation! unless confirm diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb index 4962f5e53c..660ca8c292 100644 --- a/lib/backup/manager.rb +++ b/lib/backup/manager.rb @@ -1,5 +1,8 @@ module Backup class Manager + ARCHIVES_TO_BACKUP = %w[uploads builds artifacts lfs registry] + FOLDERS_TO_BACKUP = %w[repositories db] + def pack # Make sure there is a connection ActiveRecord::Base.connection.reconnect! @@ -45,7 +48,7 @@ module Backup end connection = ::Fog::Storage.new(connection_settings) - directory = connection.directories.get(remote_directory) + directory = connection.directories.create(key: remote_directory) if directory.files.create(key: tar_file, body: File.open(tar_file), public: false, multipart_chunk_size: Gitlab.config.backup.upload.multipart_chunk_size, @@ -147,7 +150,7 @@ module Backup end def skipped?(item) - settings[:skipped] && settings[:skipped].include?(item) + settings[:skipped] && settings[:skipped].include?(item) || disabled_features.include?(item) end private @@ -157,11 +160,17 @@ module Backup end def archives_to_backup - %w{uploads builds artifacts lfs}.map{ |name| (name + ".tar.gz") unless skipped?(name) }.compact + ARCHIVES_TO_BACKUP.map{ |name| (name + ".tar.gz") unless skipped?(name) }.compact end def folders_to_backup - %w{repositories db}.reject{ |name| skipped?(name) } + FOLDERS_TO_BACKUP.reject{ |name| skipped?(name) } + end + + def disabled_features + features = [] + features << 'registry' unless Gitlab.config.registry.enabled + features end def settings diff --git a/lib/backup/registry.rb b/lib/backup/registry.rb new file mode 100644 index 0000000000..67fe023108 --- /dev/null +++ b/lib/backup/registry.rb @@ -0,0 +1,13 @@ +require 'backup/files' + +module Backup + class Registry < Files + def initialize + super('registry', Settings.registry.path) + end + + def create_files_dir + Dir.mkdir(app_files_dir, 0700) + end + end +end diff --git a/lib/banzai/filter/abstract_reference_filter.rb b/lib/banzai/filter/abstract_reference_filter.rb index b8962379cb..db95d7c908 100644 --- a/lib/banzai/filter/abstract_reference_filter.rb +++ b/lib/banzai/filter/abstract_reference_filter.rb @@ -18,10 +18,6 @@ module Banzai @object_sym ||= object_name.to_sym end - def self.data_reference - @data_reference ||= "data-#{object_name.dasherize}" - end - def self.object_class_title @object_title ||= object_class.name.titleize end @@ -45,10 +41,6 @@ module Banzai end end - def self.referenced_by(node) - { object_sym => LazyReference.new(object_class, node.attr(data_reference)) } - end - def object_class self.class.object_class end @@ -236,7 +228,9 @@ module Banzai if cache.key?(key) cache[key] else - cache[key] = yield + value = yield + cache[key] = value if key.present? + value end end end diff --git a/lib/banzai/filter/commit_range_reference_filter.rb b/lib/banzai/filter/commit_range_reference_filter.rb index b469ea0f62..bbb88c979c 100644 --- a/lib/banzai/filter/commit_range_reference_filter.rb +++ b/lib/banzai/filter/commit_range_reference_filter.rb @@ -4,6 +4,8 @@ module Banzai # # This filter supports cross-project references. class CommitRangeReferenceFilter < AbstractReferenceFilter + self.reference_type = :commit_range + def self.object_class CommitRange end @@ -14,34 +16,18 @@ module Banzai end end - def self.referenced_by(node) - project = Project.find(node.attr("data-project")) rescue nil - return unless project - - id = node.attr("data-commit-range") - range = find_object(project, id) - - return unless range - - { commit_range: range } - end - def initialize(*args) super @commit_map = {} end - def self.find_object(project, id) + def find_object(project, id) range = CommitRange.new(id, project) range.valid_commits? ? range : nil end - def find_object(*args) - self.class.find_object(*args) - end - def url_for_object(range, project) h = Gitlab::Routing.url_helpers h.namespace_project_compare_url(project.namespace, project, diff --git a/lib/banzai/filter/commit_reference_filter.rb b/lib/banzai/filter/commit_reference_filter.rb index bd88207326..2ce1816672 100644 --- a/lib/banzai/filter/commit_reference_filter.rb +++ b/lib/banzai/filter/commit_reference_filter.rb @@ -4,6 +4,8 @@ module Banzai # # This filter supports cross-project references. class CommitReferenceFilter < AbstractReferenceFilter + self.reference_type = :commit + def self.object_class Commit end @@ -14,28 +16,12 @@ module Banzai end end - def self.referenced_by(node) - project = Project.find(node.attr("data-project")) rescue nil - return unless project - - id = node.attr("data-commit") - commit = find_object(project, id) - - return unless commit - - { commit: commit } - end - - def self.find_object(project, id) + def find_object(project, id) if project && project.valid_repo? project.commit(id) end end - def find_object(*args) - self.class.find_object(*args) - end - def url_for_object(commit, project) h = Gitlab::Routing.url_helpers h.namespace_project_commit_url(project.namespace, project, commit, diff --git a/lib/banzai/filter/external_issue_reference_filter.rb b/lib/banzai/filter/external_issue_reference_filter.rb index 37344b9057..eaa702952c 100644 --- a/lib/banzai/filter/external_issue_reference_filter.rb +++ b/lib/banzai/filter/external_issue_reference_filter.rb @@ -4,6 +4,8 @@ module Banzai # References are ignored if the project doesn't use an external issue # tracker. class ExternalIssueReferenceFilter < ReferenceFilter + self.reference_type = :external_issue + # Public: Find `JIRA-123` issue references in text # # ExternalIssueReferenceFilter.references_in(text) do |match, issue| @@ -21,18 +23,6 @@ module Banzai end end - def self.referenced_by(node) - project = Project.find(node.attr("data-project")) rescue nil - return unless project - - id = node.attr("data-external-issue") - external_issue = ExternalIssue.new(id, project) - - return unless external_issue - - { external_issue: external_issue } - end - def call # Early return if the project isn't using an external tracker return doc if project.nil? || default_issues_tracker? diff --git a/lib/banzai/filter/inline_diff_filter.rb b/lib/banzai/filter/inline_diff_filter.rb new file mode 100644 index 0000000000..beb21b19ab --- /dev/null +++ b/lib/banzai/filter/inline_diff_filter.rb @@ -0,0 +1,26 @@ +module Banzai + module Filter + class InlineDiffFilter < HTML::Pipeline::Filter + IGNORED_ANCESTOR_TAGS = %w(pre code tt).to_set + + def call + search_text_nodes(doc).each do |node| + next if has_ancestor?(node, IGNORED_ANCESTOR_TAGS) + + content = node.to_html + html_content = inline_diff_filter(content) + + next if content == html_content + + node.replace(html_content) + end + doc + end + + def inline_diff_filter(text) + html_content = text.gsub(/(?:\[\-(.*?)\-\]|\{\-(.*?)\-\})/, '\1\2') + html_content.gsub(/(?:\[\+(.*?)\+\]|\{\+(.*?)\+\})/, '\1\2') + end + end + end +end diff --git a/lib/banzai/filter/issue_reference_filter.rb b/lib/banzai/filter/issue_reference_filter.rb index 2732e0b514..2496e70400 100644 --- a/lib/banzai/filter/issue_reference_filter.rb +++ b/lib/banzai/filter/issue_reference_filter.rb @@ -5,15 +5,12 @@ module Banzai # # This filter supports cross-project references. class IssueReferenceFilter < AbstractReferenceFilter + self.reference_type = :issue + def self.object_class Issue end - def self.user_can_see_reference?(user, node, context) - issue = Issue.find(node.attr('data-issue')) rescue nil - Ability.abilities.allowed?(user, :read_issue, issue) - end - def find_object(project, id) project.get_issue(id) end diff --git a/lib/banzai/filter/label_reference_filter.rb b/lib/banzai/filter/label_reference_filter.rb index 8488a493b5..e4d3f87d0a 100644 --- a/lib/banzai/filter/label_reference_filter.rb +++ b/lib/banzai/filter/label_reference_filter.rb @@ -2,6 +2,8 @@ module Banzai module Filter # HTML filter that replaces label references with links. class LabelReferenceFilter < AbstractReferenceFilter + self.reference_type = :label + def self.object_class Label end diff --git a/lib/banzai/filter/merge_request_reference_filter.rb b/lib/banzai/filter/merge_request_reference_filter.rb index cad38a5185..ac5216d9cf 100644 --- a/lib/banzai/filter/merge_request_reference_filter.rb +++ b/lib/banzai/filter/merge_request_reference_filter.rb @@ -5,6 +5,8 @@ module Banzai # # This filter supports cross-project references. class MergeRequestReferenceFilter < AbstractReferenceFilter + self.reference_type = :merge_request + def self.object_class MergeRequest end diff --git a/lib/banzai/filter/milestone_reference_filter.rb b/lib/banzai/filter/milestone_reference_filter.rb index 4cb8217802..ca686c87d9 100644 --- a/lib/banzai/filter/milestone_reference_filter.rb +++ b/lib/banzai/filter/milestone_reference_filter.rb @@ -2,6 +2,8 @@ module Banzai module Filter # HTML filter that replaces milestone references with links. class MilestoneReferenceFilter < AbstractReferenceFilter + self.reference_type = :milestone + def self.object_class Milestone end @@ -10,11 +12,53 @@ module Banzai project.milestones.find_by(iid: id) end - def url_for_object(issue, project) + def references_in(text, pattern = Milestone.reference_pattern) + # We'll handle here the references that follow the `reference_pattern`. + # Other patterns (for example, the link pattern) are handled by the + # default implementation. + return super(text, pattern) if pattern != Milestone.reference_pattern + + text.gsub(pattern) do |match| + milestone = find_milestone($~[:project], $~[:milestone_iid], $~[:milestone_name]) + + if milestone + yield match, milestone.iid, $~[:project], $~ + else + match + end + end + end + + def find_milestone(project_ref, milestone_id, milestone_name) + project = project_from_ref(project_ref) + return unless project + + milestone_params = milestone_params(milestone_id, milestone_name) + project.milestones.find_by(milestone_params) + end + + def milestone_params(iid, name) + if name + { name: name.tr('"', '') } + else + { iid: iid.to_i } + end + end + + def url_for_object(milestone, project) h = Gitlab::Routing.url_helpers h.namespace_project_milestone_url(project.namespace, project, milestone, only_path: context[:only_path]) end + + def object_link_text(object, matches) + if context[:project] == object.project + super + else + "#{escape_once(super)} in #{escape_once(object.project.path_with_namespace)}". + html_safe + end + end end end end diff --git a/lib/banzai/filter/redactor_filter.rb b/lib/banzai/filter/redactor_filter.rb index e589b5df6e..c753a84a20 100644 --- a/lib/banzai/filter/redactor_filter.rb +++ b/lib/banzai/filter/redactor_filter.rb @@ -7,8 +7,11 @@ module Banzai # class RedactorFilter < HTML::Pipeline::Filter def call - Querying.css(doc, 'a.gfm').each do |node| - unless user_can_see_reference?(node) + nodes = Querying.css(doc, 'a.gfm[data-reference-type]') + visible = nodes_visible_to_user(nodes) + + nodes.each do |node| + unless visible.include?(node) # The reference should be replaced by the original text, # which is not always the same as the rendered text. text = node.attr('data-original') || node.text @@ -21,20 +24,30 @@ module Banzai private - def user_can_see_reference?(node) - if node.has_attribute?('data-reference-filter') - reference_type = node.attr('data-reference-filter') - reference_filter = Banzai::Filter.const_get(reference_type) + def nodes_visible_to_user(nodes) + per_type = Hash.new { |h, k| h[k] = [] } + visible = Set.new - reference_filter.user_can_see_reference?(current_user, node, context) - else - true + nodes.each do |node| + per_type[node.attr('data-reference-type')] << node end + + per_type.each do |type, nodes| + parser = Banzai::ReferenceParser[type].new(project, current_user) + + visible.merge(parser.nodes_visible_to_user(current_user, nodes)) + end + + visible end def current_user context[:current_user] end + + def project + context[:project] + end end end end diff --git a/lib/banzai/filter/reference_filter.rb b/lib/banzai/filter/reference_filter.rb index 31386cf851..41ae0e1f9c 100644 --- a/lib/banzai/filter/reference_filter.rb +++ b/lib/banzai/filter/reference_filter.rb @@ -8,24 +8,8 @@ module Banzai # :project (required) - Current project, ignored if reference is cross-project. # :only_path - Generate path-only links. class ReferenceFilter < HTML::Pipeline::Filter - def self.user_can_see_reference?(user, node, context) - if node.has_attribute?('data-project') - project_id = node.attr('data-project').to_i - return true if project_id == context[:project].try(:id) - - project = Project.find(project_id) rescue nil - Ability.abilities.allowed?(user, :read_project, project) - else - true - end - end - - def self.user_can_reference?(user, node, context) - true - end - - def self.referenced_by(node) - raise NotImplementedError, "#{self} does not implement #{__method__}" + class << self + attr_accessor :reference_type end # Returns a data attribute String to attach to a reference link @@ -43,7 +27,9 @@ module Banzai # # Returns a String def data_attribute(attributes = {}) - attributes[:reference_filter] = self.class.name.demodulize + attributes = attributes.reject { |_, v| v.nil? } + + 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/reference_gatherer_filter.rb b/lib/banzai/filter/reference_gatherer_filter.rb deleted file mode 100644 index 96fdb06304..0000000000 --- a/lib/banzai/filter/reference_gatherer_filter.rb +++ /dev/null @@ -1,65 +0,0 @@ -module Banzai - module Filter - # HTML filter that gathers all referenced records that the current user has - # permission to view. - # - # Expected to be run in its own post-processing pipeline. - # - class ReferenceGathererFilter < HTML::Pipeline::Filter - def initialize(*) - super - - result[:references] ||= Hash.new { |hash, type| hash[type] = [] } - end - - def call - Querying.css(doc, 'a.gfm').each do |node| - gather_references(node) - end - - load_lazy_references unless ReferenceExtractor.lazy? - - doc - end - - private - - def gather_references(node) - return unless node.has_attribute?('data-reference-filter') - - reference_type = node.attr('data-reference-filter') - reference_filter = Banzai::Filter.const_get(reference_type) - - return if context[:reference_filter] && reference_filter != context[:reference_filter] - - return if author && !reference_filter.user_can_reference?(author, node, context) - - return unless reference_filter.user_can_see_reference?(current_user, node, context) - - references = reference_filter.referenced_by(node) - return unless references - - references.each do |type, values| - Array.wrap(values).each do |value| - result[:references][type] << value - end - end - end - - def load_lazy_references - refs = result[:references] - refs.each do |type, values| - refs[type] = ReferenceExtractor.lazily(values) - end - end - - def current_user - context[:current_user] - end - - def author - context[:author] - end - end - end -end diff --git a/lib/banzai/filter/sanitization_filter.rb b/lib/banzai/filter/sanitization_filter.rb index 42dbab9d27..ca80aac5a0 100644 --- a/lib/banzai/filter/sanitization_filter.rb +++ b/lib/banzai/filter/sanitization_filter.rb @@ -63,7 +63,7 @@ module Banzai begin uri = Addressable::URI.parse(node['href']) - uri.scheme.strip! if uri.scheme + uri.scheme = uri.scheme.strip.downcase if uri.scheme node.remove_attribute('href') if UNSAFE_PROTOCOLS.include?(uri.scheme) rescue Addressable::URI::InvalidURIError diff --git a/lib/banzai/filter/snippet_reference_filter.rb b/lib/banzai/filter/snippet_reference_filter.rb index d507eb5ebe..212a0bbf2a 100644 --- a/lib/banzai/filter/snippet_reference_filter.rb +++ b/lib/banzai/filter/snippet_reference_filter.rb @@ -5,6 +5,8 @@ module Banzai # # This filter supports cross-project references. class SnippetReferenceFilter < AbstractReferenceFilter + self.reference_type = :snippet + def self.object_class Snippet end diff --git a/lib/banzai/filter/upload_link_filter.rb b/lib/banzai/filter/upload_link_filter.rb index 7edfe5ade2..c0f503c9af 100644 --- a/lib/banzai/filter/upload_link_filter.rb +++ b/lib/banzai/filter/upload_link_filter.rb @@ -8,6 +8,8 @@ module Banzai # class UploadLinkFilter < HTML::Pipeline::Filter def call + return doc unless project + doc.search('a').each do |el| process_link_attr el.attribute('href') end @@ -31,7 +33,11 @@ module Banzai end def build_url(uri) - File.join(Gitlab.config.gitlab.url, context[:project].path_with_namespace, uri) + File.join(Gitlab.config.gitlab.url, project.path_with_namespace, uri) + end + + def project + context[:project] end # Ensure that a :project key exists in context diff --git a/lib/banzai/filter/user_reference_filter.rb b/lib/banzai/filter/user_reference_filter.rb index eea3af842b..331d800725 100644 --- a/lib/banzai/filter/user_reference_filter.rb +++ b/lib/banzai/filter/user_reference_filter.rb @@ -4,6 +4,8 @@ module Banzai # # A special `@all` reference is also supported. class UserReferenceFilter < ReferenceFilter + self.reference_type = :user + # Public: Find `@user` user references in text # # UserReferenceFilter.references_in(text) do |match, username| @@ -21,43 +23,6 @@ module Banzai end end - def self.referenced_by(node) - if node.has_attribute?('data-group') - group = Group.find(node.attr('data-group')) rescue nil - return unless group - - { user: group.users } - elsif node.has_attribute?('data-user') - { user: LazyReference.new(User, node.attr('data-user')) } - elsif node.has_attribute?('data-project') - project = Project.find(node.attr('data-project')) rescue nil - return unless project - - { user: project.team.members.flatten } - end - end - - def self.user_can_see_reference?(user, node, context) - if node.has_attribute?('data-group') - group = Group.find(node.attr('data-group')) rescue nil - Ability.abilities.allowed?(user, :read_group, group) - else - super - end - end - - def self.user_can_reference?(user, node, context) - # Only team members can reference `@all` - if node.has_attribute?('data-project') - project = Project.find(node.attr('data-project')) rescue nil - return false unless project - - user && project.team.member?(user) - else - super - end - end - def call return doc if project.nil? @@ -114,9 +79,12 @@ module Banzai def link_to_all(link_text: nil) project = context[:project] + author = context[:author] + url = urls.namespace_project_url(project.namespace, project, only_path: context[:only_path]) - data = data_attribute(project: project.id) + + data = data_attribute(project: project.id, author: author.try(:id)) text = link_text || User.reference_prefix + 'all' link_tag(url, data, text) diff --git a/lib/banzai/filter/wiki_link_filter.rb b/lib/banzai/filter/wiki_link_filter.rb index 06d10c9850..7dc771afd7 100644 --- a/lib/banzai/filter/wiki_link_filter.rb +++ b/lib/banzai/filter/wiki_link_filter.rb @@ -25,7 +25,7 @@ module Banzai end def process_link_attr(html_attr) - return if html_attr.blank? || file_reference?(html_attr) + return if html_attr.blank? || file_reference?(html_attr) || hierarchical_link?(html_attr) uri = URI(html_attr.value) if uri.relative? && uri.path.present? @@ -40,12 +40,17 @@ module Banzai uri end + def project_wiki + context[:project_wiki] + end + def file_reference?(html_attr) !File.extname(html_attr.value).blank? end - def project_wiki - context[:project_wiki] + # Of the form `./link`, `../link`, or similar + def hierarchical_link?(html_attr) + html_attr.value[0] == '.' end def project_wiki_base_path diff --git a/lib/banzai/lazy_reference.rb b/lib/banzai/lazy_reference.rb deleted file mode 100644 index 1095b4debc..0000000000 --- a/lib/banzai/lazy_reference.rb +++ /dev/null @@ -1,25 +0,0 @@ -module Banzai - class LazyReference - def self.load(refs) - lazy_references, values = refs.partition { |ref| ref.is_a?(self) } - - lazy_values = lazy_references.group_by(&:klass).flat_map do |klass, refs| - ids = refs.flat_map(&:ids) - klass.where(id: ids) - end - - values + lazy_values - end - - attr_reader :klass, :ids - - def initialize(klass, ids) - @klass = klass - @ids = Array.wrap(ids).map(&:to_i) - end - - def load - self.klass.where(id: self.ids) - end - end -end diff --git a/lib/banzai/pipeline/gfm_pipeline.rb b/lib/banzai/pipeline/gfm_pipeline.rb index ed3cfd6b02..b27ecf3c92 100644 --- a/lib/banzai/pipeline/gfm_pipeline.rb +++ b/lib/banzai/pipeline/gfm_pipeline.rb @@ -23,7 +23,8 @@ module Banzai Filter::LabelReferenceFilter, Filter::MilestoneReferenceFilter, - Filter::TaskListFilter + Filter::TaskListFilter, + Filter::InlineDiffFilter ] end diff --git a/lib/banzai/pipeline/reference_extraction_pipeline.rb b/lib/banzai/pipeline/reference_extraction_pipeline.rb deleted file mode 100644 index 919998380e..0000000000 --- a/lib/banzai/pipeline/reference_extraction_pipeline.rb +++ /dev/null @@ -1,11 +0,0 @@ -module Banzai - module Pipeline - class ReferenceExtractionPipeline < BasePipeline - def self.filters - FilterArray[ - Filter::ReferenceGathererFilter - ] - end - end - end -end diff --git a/lib/banzai/reference_extractor.rb b/lib/banzai/reference_extractor.rb index f4079538ec..bf366962ae 100644 --- a/lib/banzai/reference_extractor.rb +++ b/lib/banzai/reference_extractor.rb @@ -1,28 +1,6 @@ module Banzai # Extract possible GFM references from an arbitrary String for further processing. class ReferenceExtractor - class << self - LAZY_KEY = :banzai_reference_extractor_lazy - - def lazy? - Thread.current[LAZY_KEY] - end - - def lazily(values = nil, &block) - return (values || block.call).uniq if lazy? - - begin - Thread.current[LAZY_KEY] = true - - values ||= block.call - - Banzai::LazyReference.load(values.uniq).uniq - ensure - Thread.current[LAZY_KEY] = false - end - end - end - def initialize @texts = [] end @@ -31,23 +9,21 @@ module Banzai @texts << Renderer.render(text, context) end - def references(type, context = {}) - filter = Banzai::Filter["#{type}_reference"] + def references(type, project, current_user = nil) + processor = Banzai::ReferenceParser[type]. + new(project, current_user) - context.merge!( - pipeline: :reference_extraction, + processor.process(html_documents) + end - # ReferenceGathererFilter - reference_filter: filter - ) + private - self.class.lazily do - @texts.flat_map do |html| - text_context = context.dup - result = Renderer.render_result(html, text_context) - result[:references][type] - end.uniq - end + def html_documents + # This ensures that we don't memoize anything until we have a number of + # text blobs to parse. + return [] if @texts.empty? + + @html_documents ||= @texts.map { |html| Nokogiri::HTML.fragment(html) } end end end diff --git a/lib/banzai/reference_parser.rb b/lib/banzai/reference_parser.rb new file mode 100644 index 0000000000..557bec4316 --- /dev/null +++ b/lib/banzai/reference_parser.rb @@ -0,0 +1,14 @@ +module Banzai + module ReferenceParser + # Returns the reference parser class for the given type + # + # Example: + # + # Banzai::ReferenceParser['issue'] + # + # This would return the `Banzai::ReferenceParser::IssueParser` class. + def self.[](name) + const_get("#{name.to_s.camelize}Parser") + end + end +end diff --git a/lib/banzai/reference_parser/base_parser.rb b/lib/banzai/reference_parser/base_parser.rb new file mode 100644 index 0000000000..3d7b9c4a02 --- /dev/null +++ b/lib/banzai/reference_parser/base_parser.rb @@ -0,0 +1,204 @@ +module Banzai + module ReferenceParser + # Base class for reference parsing classes. + # + # Each parser should also specify its reference type by calling + # `self.reference_type = ...` in the body of the class. The value of this + # method should be a symbol such as `:issue` or `:merge_request`. For + # example: + # + # class IssueParser < BaseParser + # self.reference_type = :issue + # end + # + # The reference type is used to determine what nodes to pass to the + # `referenced_by` method. + # + # Parser classes should either implement the instance method + # `references_relation` or overwrite `referenced_by`. The + # `references_relation` method is supposed to return an + # ActiveRecord::Relation used as a base relation for retrieving the objects + # referenced in a set of HTML nodes. + # + # Each class can implement two additional methods: + # + # * `nodes_user_can_reference`: returns an Array of nodes the given user can + # refer to. + # * `nodes_visible_to_user`: returns an Array of nodes that are visible to + # the given user. + # + # You only need to overwrite these methods if you want to tweak who can see + # which references. For example, the IssueParser class defines its own + # `nodes_visible_to_user` method so it can ensure users can only see issues + # they have access to. + class BaseParser + class << self + attr_accessor :reference_type + end + + # Returns the attribute name containing the value for every object to be + # parsed by the current parser. + # + # For example, for a parser class that returns "Animal" objects this + # attribute would be "data-animal". + def self.data_attribute + @data_attribute ||= "data-#{reference_type.to_s.dasherize}" + end + + def initialize(project = nil, current_user = nil) + @project = project + @current_user = current_user + end + + # Returns all the nodes containing references that the user can refer to. + def nodes_user_can_reference(user, nodes) + nodes + end + + # Returns all the nodes that are visible to the given user. + def nodes_visible_to_user(user, nodes) + projects = lazy { projects_for_nodes(nodes) } + project_attr = 'data-project' + + nodes.select do |node| + if node.has_attribute?(project_attr) + node_id = node.attr(project_attr).to_i + + if project && project.id == node_id + true + else + can?(user, :read_project, projects[node_id]) + end + else + true + end + end + end + + # Returns an Array of objects referenced by any of the given HTML nodes. + def referenced_by(nodes) + ids = unique_attribute_values(nodes, self.class.data_attribute) + + references_relation.where(id: ids) + end + + # Returns the ActiveRecord::Relation to use for querying references in the + # DB. + def references_relation + raise NotImplementedError, + "#{self.class} does not implement #{__method__}" + end + + # Returns a Hash containing attribute values per project ID. + # + # The returned Hash uses the following format: + # + # { project id => [value1, value2, ...] } + # + # nodes - An Array of HTML nodes to process. + # attribute - The name of the attribute (as a String) for which to gather + # values. + # + # Returns a Hash. + def gather_attributes_per_project(nodes, attribute) + per_project = Hash.new { |hash, key| hash[key] = Set.new } + + nodes.each do |node| + project_id = node.attr('data-project').to_i + id = node.attr(attribute) + + per_project[project_id] << id if id + end + + per_project + end + + # Returns a Hash containing objects for an attribute grouped per their + # IDs. + # + # The returned Hash uses the following format: + # + # { id value => row } + # + # nodes - An Array of HTML nodes to process. + # + # collection - The model or ActiveRecord relation to use for retrieving + # rows from the database. + # + # attribute - The name of the attribute containing the primary key values + # for every row. + # + # Returns a Hash. + def grouped_objects_for_nodes(nodes, collection, attribute) + return {} if nodes.empty? + + ids = unique_attribute_values(nodes, attribute) + + collection.where(id: ids).each_with_object({}) do |row, hash| + hash[row.id] = row + end + end + + # Returns an Array containing all unique values of an attribute of the + # given nodes. + def unique_attribute_values(nodes, attribute) + values = Set.new + + nodes.each do |node| + if node.has_attribute?(attribute) + values << node.attr(attribute) + end + end + + values.to_a + end + + # Processes the list of HTML documents and returns an Array containing all + # the references. + def process(documents) + type = self.class.reference_type + + nodes = documents.flat_map do |document| + Querying.css(document, "a[data-reference-type='#{type}'].gfm").to_a + end + + gather_references(nodes) + end + + # Gathers the references for the given HTML nodes. + def gather_references(nodes) + nodes = nodes_user_can_reference(current_user, nodes) + nodes = nodes_visible_to_user(current_user, nodes) + + referenced_by(nodes) + end + + # Returns a Hash containing the projects for a given list of HTML nodes. + # + # The returned Hash uses the following format: + # + # { project ID => project } + # + def projects_for_nodes(nodes) + @projects_for_nodes ||= + grouped_objects_for_nodes(nodes, Project, 'data-project') + end + + def can?(user, permission, subject) + Ability.abilities.allowed?(user, permission, subject) + end + + def find_projects_for_hash_keys(hash) + Project.where(id: hash.keys) + end + + private + + attr_reader :current_user, :project + + def lazy(&block) + Gitlab::Lazy.new(&block) + end + end + end +end diff --git a/lib/banzai/reference_parser/commit_parser.rb b/lib/banzai/reference_parser/commit_parser.rb new file mode 100644 index 0000000000..0fee9d267d --- /dev/null +++ b/lib/banzai/reference_parser/commit_parser.rb @@ -0,0 +1,34 @@ +module Banzai + module ReferenceParser + class CommitParser < BaseParser + self.reference_type = :commit + + def referenced_by(nodes) + commit_ids = commit_ids_per_project(nodes) + projects = find_projects_for_hash_keys(commit_ids) + + projects.flat_map do |project| + find_commits(project, commit_ids[project.id]) + end + end + + def commit_ids_per_project(nodes) + gather_attributes_per_project(nodes, self.class.data_attribute) + end + + def find_commits(project, ids) + commits = [] + + return commits unless project.valid_repo? + + ids.each do |id| + commit = project.commit(id) + + commits << commit if commit + end + + commits + end + end + end +end diff --git a/lib/banzai/reference_parser/commit_range_parser.rb b/lib/banzai/reference_parser/commit_range_parser.rb new file mode 100644 index 0000000000..69d01f8db1 --- /dev/null +++ b/lib/banzai/reference_parser/commit_range_parser.rb @@ -0,0 +1,38 @@ +module Banzai + module ReferenceParser + class CommitRangeParser < BaseParser + self.reference_type = :commit_range + + def referenced_by(nodes) + range_ids = commit_range_ids_per_project(nodes) + projects = find_projects_for_hash_keys(range_ids) + + projects.flat_map do |project| + find_ranges(project, range_ids[project.id]) + end + end + + def commit_range_ids_per_project(nodes) + gather_attributes_per_project(nodes, self.class.data_attribute) + end + + def find_ranges(project, range_ids) + ranges = [] + + range_ids.each do |id| + range = find_object(project, id) + + ranges << range if range + end + + ranges + end + + def find_object(project, id) + range = CommitRange.new(id, project) + + range.valid_commits? ? range : nil + end + end + end +end diff --git a/lib/banzai/reference_parser/external_issue_parser.rb b/lib/banzai/reference_parser/external_issue_parser.rb new file mode 100644 index 0000000000..a1264db211 --- /dev/null +++ b/lib/banzai/reference_parser/external_issue_parser.rb @@ -0,0 +1,25 @@ +module Banzai + module ReferenceParser + class ExternalIssueParser < BaseParser + self.reference_type = :external_issue + + def referenced_by(nodes) + issue_ids = issue_ids_per_project(nodes) + projects = find_projects_for_hash_keys(issue_ids) + issues = [] + + projects.each do |project| + issue_ids[project.id].each do |id| + issues << ExternalIssue.new(id, project) + end + end + + issues + end + + def issue_ids_per_project(nodes) + gather_attributes_per_project(nodes, self.class.data_attribute) + end + end + end +end diff --git a/lib/banzai/reference_parser/issue_parser.rb b/lib/banzai/reference_parser/issue_parser.rb new file mode 100644 index 0000000000..24076e3d9e --- /dev/null +++ b/lib/banzai/reference_parser/issue_parser.rb @@ -0,0 +1,40 @@ +module Banzai + module ReferenceParser + class IssueParser < BaseParser + self.reference_type = :issue + + def nodes_visible_to_user(user, nodes) + # It is not possible to check access rights for external issue trackers + return nodes if project && project.external_issue_tracker + + issues = issues_for_nodes(nodes) + + nodes.select do |node| + issue = issue_for_node(issues, node) + + issue ? can?(user, :read_issue, issue) : false + end + end + + def referenced_by(nodes) + issues = issues_for_nodes(nodes) + + nodes.map { |node| issue_for_node(issues, node) }.uniq + end + + def issues_for_nodes(nodes) + @issues_for_nodes ||= grouped_objects_for_nodes( + nodes, + Issue.all.includes(:author, :assignee, :project), + self.class.data_attribute + ) + end + + private + + def issue_for_node(issues, node) + issues[node.attr(self.class.data_attribute).to_i] + end + end + end +end diff --git a/lib/banzai/reference_parser/label_parser.rb b/lib/banzai/reference_parser/label_parser.rb new file mode 100644 index 0000000000..e5d1eb11d7 --- /dev/null +++ b/lib/banzai/reference_parser/label_parser.rb @@ -0,0 +1,11 @@ +module Banzai + module ReferenceParser + class LabelParser < BaseParser + self.reference_type = :label + + def references_relation + Label + end + end + end +end diff --git a/lib/banzai/reference_parser/merge_request_parser.rb b/lib/banzai/reference_parser/merge_request_parser.rb new file mode 100644 index 0000000000..c9a9ca79c0 --- /dev/null +++ b/lib/banzai/reference_parser/merge_request_parser.rb @@ -0,0 +1,11 @@ +module Banzai + module ReferenceParser + class MergeRequestParser < BaseParser + self.reference_type = :merge_request + + def references_relation + MergeRequest.includes(:author, :assignee, :target_project) + end + end + end +end diff --git a/lib/banzai/reference_parser/milestone_parser.rb b/lib/banzai/reference_parser/milestone_parser.rb new file mode 100644 index 0000000000..a000ac61e5 --- /dev/null +++ b/lib/banzai/reference_parser/milestone_parser.rb @@ -0,0 +1,11 @@ +module Banzai + module ReferenceParser + class MilestoneParser < BaseParser + self.reference_type = :milestone + + def references_relation + Milestone + end + end + end +end diff --git a/lib/banzai/reference_parser/snippet_parser.rb b/lib/banzai/reference_parser/snippet_parser.rb new file mode 100644 index 0000000000..fa71b3c952 --- /dev/null +++ b/lib/banzai/reference_parser/snippet_parser.rb @@ -0,0 +1,11 @@ +module Banzai + module ReferenceParser + class SnippetParser < BaseParser + self.reference_type = :snippet + + def references_relation + Snippet + end + end + end +end diff --git a/lib/banzai/reference_parser/user_parser.rb b/lib/banzai/reference_parser/user_parser.rb new file mode 100644 index 0000000000..a12b0d1956 --- /dev/null +++ b/lib/banzai/reference_parser/user_parser.rb @@ -0,0 +1,92 @@ +module Banzai + module ReferenceParser + class UserParser < BaseParser + self.reference_type = :user + + def referenced_by(nodes) + group_ids = [] + user_ids = [] + project_ids = [] + + nodes.each do |node| + if node.has_attribute?('data-group') + group_ids << node.attr('data-group').to_i + elsif node.has_attribute?(self.class.data_attribute) + user_ids << node.attr(self.class.data_attribute).to_i + elsif node.has_attribute?('data-project') + project_ids << node.attr('data-project').to_i + end + end + + find_users_for_groups(group_ids) | find_users(user_ids) | + find_users_for_projects(project_ids) + end + + def nodes_visible_to_user(user, nodes) + group_attr = 'data-group' + groups = lazy { grouped_objects_for_nodes(nodes, Group, group_attr) } + visible = [] + remaining = [] + + nodes.each do |node| + if node.has_attribute?(group_attr) + node_group = groups[node.attr(group_attr).to_i] + + if node_group && + can?(user, :read_group, node_group) + visible << node + end + # Remaining nodes will be processed by the parent class' + # implementation of this method. + else + remaining << node + end + end + + visible + super(current_user, remaining) + end + + def nodes_user_can_reference(current_user, nodes) + project_attr = 'data-project' + author_attr = 'data-author' + + projects = lazy { projects_for_nodes(nodes) } + users = lazy { grouped_objects_for_nodes(nodes, User, author_attr) } + + nodes.select do |node| + project_id = node.attr(project_attr) + user_id = node.attr(author_attr) + + if project && project_id && project.id == project_id.to_i + true + elsif project_id && user_id + project = projects[project_id.to_i] + user = users[user_id.to_i] + + project && user ? project.team.member?(user) : false + else + true + end + end + end + + def find_users(ids) + return [] if ids.empty? + + User.where(id: ids).to_a + end + + def find_users_for_groups(ids) + return [] if ids.empty? + + User.joins(:group_members).where(members: { source_id: ids }).to_a + end + + def find_users_for_projects(ids) + return [] if ids.empty? + + Project.where(id: ids).flat_map { |p| p.team.members.to_a } + end + end + end +end diff --git a/lib/ci/ansi2html.rb b/lib/ci/ansi2html.rb index ac6d667cf8..229050151d 100644 --- a/lib/ci/ansi2html.rb +++ b/lib/ci/ansi2html.rb @@ -23,8 +23,8 @@ module Ci cross: 0x10, } - def self.convert(ansi) - Converter.new().convert(ansi) + def self.convert(ansi, state = nil) + Converter.new.convert(ansi, state) end class Converter @@ -84,22 +84,38 @@ module Ci def on_107(s) set_bg_color(7, 'l') end def on_109(s) set_bg_color(9, 'l') end - def convert(ansi) - @out = "" - @n_open_tags = 0 - reset() + attr_accessor :offset, :n_open_tags, :fg_color, :bg_color, :style_mask - s = StringScanner.new(ansi.gsub("<", "<")) - while(!s.eos?) + STATE_PARAMS = [:offset, :n_open_tags, :fg_color, :bg_color, :style_mask] + + def convert(raw, new_state) + reset_state + restore_state(raw, new_state) if new_state.present? + + start = @offset + ansi = raw[@offset..-1] + + open_new_tag + + s = StringScanner.new(ansi) + until s.eos? if s.scan(/\e([@-_])(.*?)([@-~])/) handle_sequence(s) + elsif s.scan(/\e(([@-_])(.*?)?)?$/) + break + elsif s.scan(/' else @out << s.scan(/./m) end + @offset += s.matched_size end close_open_tags() - @out + + { state: state, html: @out, text: ansi[0, @offset - start], append: start > 0 } end def handle_sequence(s) @@ -121,6 +137,20 @@ module Ci evaluate_command_stack(commands) + open_new_tag + end + + def evaluate_command_stack(stack) + return unless command = stack.shift() + + if self.respond_to?("on_#{command}", true) + self.send("on_#{command}", stack) + end + + evaluate_command_stack(stack) + end + + def open_new_tag css_classes = [] unless @fg_color.nil? @@ -138,20 +168,8 @@ module Ci css_classes << "term-#{css_class}" if @style_mask & flag != 0 end - open_new_tag(css_classes) if css_classes.length > 0 - end + return if css_classes.empty? - def evaluate_command_stack(stack) - return unless command = stack.shift() - - if self.respond_to?("on_#{command}", true) - self.send("on_#{command}", stack) - end - - evaluate_command_stack(stack) - end - - def open_new_tag(css_classes) @out << %{} @n_open_tags += 1 end @@ -163,6 +181,31 @@ module Ci end end + def reset_state + @offset = 0 + @n_open_tags = 0 + @out = '' + reset + end + + def state + state = STATE_PARAMS.inject({}) do |h, param| + h[param] = send(param) + h + end + Base64.urlsafe_encode64(state.to_json) + end + + def restore_state(raw, new_state) + state = Base64.urlsafe_decode64(new_state) + state = JSON.parse(state, symbolize_names: true) + return if state[:offset].to_i > raw.length + + STATE_PARAMS.each do |param| + send("#{param}=".to_sym, state[param]) + end + end + def reset @fg_color = nil @bg_color = nil diff --git a/lib/ci/api/api.rb b/lib/ci/api/api.rb index 353c4ddebf..17bb99a2ae 100644 --- a/lib/ci/api/api.rb +++ b/lib/ci/api/api.rb @@ -1,9 +1,7 @@ -Dir["#{Rails.root}/lib/ci/api/*.rb"].each {|file| require file} - module Ci module API class API < Grape::API - include APIGuard + include ::API::APIGuard version 'v1', using: :path rescue_from ActiveRecord::RecordNotFound do @@ -31,9 +29,9 @@ module Ci helpers ::API::Helpers helpers Gitlab::CurrentSettings - mount Builds - mount Runners - mount Triggers + mount ::Ci::API::Builds + mount ::Ci::API::Runners + mount ::Ci::API::Triggers end end end diff --git a/lib/ci/api/runners.rb b/lib/ci/api/runners.rb index 192b1d18a5..0c41f22c7c 100644 --- a/lib/ci/api/runners.rb +++ b/lib/ci/api/runners.rb @@ -28,20 +28,20 @@ module Ci post "register" do required_attributes! [:token] + attributes = { description: params[:description], + tag_list: params[:tag_list] } + + unless params[:run_untagged].nil? + attributes[:run_untagged] = params[:run_untagged] + end + runner = if runner_registration_token_valid? # Create shared runner. Requires admin access - Ci::Runner.create( - description: params[:description], - tag_list: params[:tag_list], - is_shared: true - ) + Ci::Runner.create(attributes.merge(is_shared: true)) elsif project = Project.find_by(runners_token: params[:token]) # Create a specific runner for project. - project.runners.create( - description: params[:description], - tag_list: params[:tag_list] - ) + project.runners.create(attributes) end return forbidden! unless runner diff --git a/lib/ci/charts.rb b/lib/ci/charts.rb index d53bdcbd0f..e163663693 100644 --- a/lib/ci/charts.rb +++ b/lib/ci/charts.rb @@ -64,7 +64,8 @@ module Ci commits.each do |commit| @labels << commit.short_sha - @build_times << (commit.duration / 60) + duration = commit.duration || 0 + @build_times << (duration / 60) end end end diff --git a/lib/ci/gitlab_ci_yaml_processor.rb b/lib/ci/gitlab_ci_yaml_processor.rb index 504d3df9d3..026a5ac97c 100644 --- a/lib/ci/gitlab_ci_yaml_processor.rb +++ b/lib/ci/gitlab_ci_yaml_processor.rb @@ -1,6 +1,6 @@ module Ci class GitlabCiYamlProcessor - class ValidationError < StandardError;end + class ValidationError < StandardError; end DEFAULT_STAGES = %w(build test deploy) DEFAULT_STAGE = 'test' @@ -265,7 +265,7 @@ module Ci end def validate_job_dependencies!(name, job) - if !validate_array_of_strings(job[:dependencies]) + unless validate_array_of_strings(job[:dependencies]) raise ValidationError, "#{name} job: dependencies parameter should be an array of strings" end diff --git a/lib/container_registry/blob.rb b/lib/container_registry/blob.rb new file mode 100644 index 0000000000..4e20dc4f87 --- /dev/null +++ b/lib/container_registry/blob.rb @@ -0,0 +1,48 @@ +module ContainerRegistry + class Blob + attr_reader :repository, :config + + delegate :registry, :client, to: :repository + + def initialize(repository, config) + @repository = repository + @config = config || {} + end + + def valid? + digest.present? + end + + def path + "#{repository.path}@#{digest}" + end + + def digest + config['digest'] + end + + def type + config['mediaType'] + end + + def size + config['size'] + end + + def revision + digest.split(':')[1] + end + + def short_revision + revision[0..8] + end + + def delete + client.delete_blob(repository.name, digest) + end + + def data + @data ||= client.blob(repository.name, digest, type) + end + end +end diff --git a/lib/container_registry/client.rb b/lib/container_registry/client.rb new file mode 100644 index 0000000000..4d726692f4 --- /dev/null +++ b/lib/container_registry/client.rb @@ -0,0 +1,61 @@ +require 'faraday' +require 'faraday_middleware' + +module ContainerRegistry + class Client + attr_accessor :uri + + MANIFEST_VERSION = 'application/vnd.docker.distribution.manifest.v2+json' + + def initialize(base_uri, options = {}) + @base_uri = base_uri + @faraday = Faraday.new(@base_uri) do |conn| + initialize_connection(conn, options) + end + end + + def repository_tags(name) + @faraday.get("/v2/#{name}/tags/list").body + end + + def repository_manifest(name, reference) + @faraday.get("/v2/#{name}/manifests/#{reference}").body + end + + def repository_tag_digest(name, reference) + response = @faraday.head("/v2/#{name}/manifests/#{reference}") + response.headers['docker-content-digest'] if response.success? + end + + def delete_repository_tag(name, reference) + @faraday.delete("/v2/#{name}/manifests/#{reference}").success? + end + + def blob(name, digest, type = nil) + headers = {} + headers['Accept'] = type if type + @faraday.get("/v2/#{name}/blobs/#{digest}", nil, headers).body + end + + def delete_blob(name, digest) + @faraday.delete("/v2/#{name}/blobs/#{digest}").success? + end + + private + + def initialize_connection(conn, options) + conn.request :json + conn.headers['Accept'] = MANIFEST_VERSION + + conn.response :json, content_type: /\bjson$/ + + if options[:user] && options[:password] + conn.request(:basic_auth, options[:user].to_s, options[:password].to_s) + elsif options[:token] + conn.request(:authorization, :bearer, options[:token].to_s) + end + + conn.adapter :net_http + end + end +end diff --git a/lib/container_registry/config.rb b/lib/container_registry/config.rb new file mode 100644 index 0000000000..589f9f4380 --- /dev/null +++ b/lib/container_registry/config.rb @@ -0,0 +1,16 @@ +module ContainerRegistry + class Config + attr_reader :tag, :blob, :data + + def initialize(tag, blob) + @tag, @blob = tag, blob + @data = JSON.parse(blob.data) + end + + def [](key) + return unless data + + data[key] + end + end +end diff --git a/lib/container_registry/registry.rb b/lib/container_registry/registry.rb new file mode 100644 index 0000000000..0e634f6b6e --- /dev/null +++ b/lib/container_registry/registry.rb @@ -0,0 +1,21 @@ +module ContainerRegistry + class Registry + attr_reader :uri, :client, :path + + def initialize(uri, options = {}) + @uri = uri + @path = options[:path] || default_path + @client = ContainerRegistry::Client.new(uri, options) + end + + def repository(name) + ContainerRegistry::Repository.new(self, name) + end + + private + + def default_path + @uri.sub(/^https?:\/\//, '') + end + end +end diff --git a/lib/container_registry/repository.rb b/lib/container_registry/repository.rb new file mode 100644 index 0000000000..0e4a7cb3cc --- /dev/null +++ b/lib/container_registry/repository.rb @@ -0,0 +1,48 @@ +module ContainerRegistry + class Repository + attr_reader :registry, :name + + delegate :client, to: :registry + + def initialize(registry, name) + @registry, @name = registry, name + end + + def path + [registry.path, name].compact.join('/') + end + + def tag(tag) + ContainerRegistry::Tag.new(self, tag) + end + + def manifest + return @manifest if defined?(@manifest) + + @manifest = client.repository_tags(name) + end + + def valid? + manifest.present? + end + + def tags + return @tags if defined?(@tags) + return [] unless manifest && manifest['tags'] + + @tags = manifest['tags'].map do |tag| + ContainerRegistry::Tag.new(self, tag) + end + end + + def blob(config) + ContainerRegistry::Blob.new(self, config) + end + + def delete_tags + return unless tags + + tags.all?(&:delete) + end + end +end diff --git a/lib/container_registry/tag.rb b/lib/container_registry/tag.rb new file mode 100644 index 0000000000..43f8d6dc8c --- /dev/null +++ b/lib/container_registry/tag.rb @@ -0,0 +1,77 @@ +module ContainerRegistry + class Tag + attr_reader :repository, :name + + delegate :registry, :client, to: :repository + + def initialize(repository, name) + @repository, @name = repository, name + end + + def valid? + manifest.present? + end + + def manifest + return @manifest if defined?(@manifest) + + @manifest = client.repository_manifest(repository.name, name) + end + + def path + "#{repository.path}:#{name}" + end + + def [](key) + return unless manifest + + manifest[key] + end + + def digest + return @digest if defined?(@digest) + + @digest = client.repository_tag_digest(repository.name, name) + end + + def config_blob + return @config_blob if defined?(@config_blob) + return unless manifest && manifest['config'] + + @config_blob = repository.blob(manifest['config']) + end + + def config + return unless config_blob + + @config ||= ContainerRegistry::Config.new(self, config_blob) + end + + def created_at + return unless config + + @created_at ||= DateTime.rfc3339(config['created']) + end + + def layers + return @layers if defined?(@layers) + return unless manifest + + @layers = manifest['layers'].map do |layer| + repository.blob(layer) + end + end + + def total_size + return unless layers + + layers.map(&:size).sum + end + + def delete + return unless digest + + client.delete_repository_tag(repository.name, digest) + end + end +end diff --git a/lib/event_filter.rb b/lib/event_filter.rb index f15b2cfd23..668d2fa41b 100644 --- a/lib/event_filter.rb +++ b/lib/event_filter.rb @@ -27,7 +27,7 @@ class EventFilter @params = if params params.dup else - []#EventFilter.default_filter + [] # EventFilter.default_filter end end diff --git a/lib/gitlab.rb b/lib/gitlab.rb index 7479e729db..37f4c34054 100644 --- a/lib/gitlab.rb +++ b/lib/gitlab.rb @@ -1,4 +1,4 @@ -require 'gitlab/git' +require_dependency 'gitlab/git' module Gitlab def self.com? diff --git a/lib/gitlab/backend/shell.rb b/lib/gitlab/backend/shell.rb index 132f9cd196..3e3986d638 100644 --- a/lib/gitlab/backend/shell.rb +++ b/lib/gitlab/backend/shell.rb @@ -180,7 +180,7 @@ module Gitlab # exists?('gitlab/cookies.git') # def exists?(dir_name) - File.exists?(full_path(dir_name)) + File.exist?(full_path(dir_name)) end protected diff --git a/lib/gitlab/bitbucket_import/client.rb b/lib/gitlab/bitbucket_import/client.rb index 9b83292ef3..8d1ad62fae 100644 --- a/lib/gitlab/bitbucket_import/client.rb +++ b/lib/gitlab/bitbucket_import/client.rb @@ -121,7 +121,7 @@ module Gitlab def get(url) response = api.get(url) - raise Unauthorized if (400..499).include?(response.code.to_i) + raise Unauthorized if (400..499).cover?(response.code.to_i) response end diff --git a/lib/gitlab/bitbucket_import/project_creator.rb b/lib/gitlab/bitbucket_import/project_creator.rb index 941f818b84..b90ef0b0fb 100644 --- a/lib/gitlab/bitbucket_import/project_creator.rb +++ b/lib/gitlab/bitbucket_import/project_creator.rb @@ -11,7 +11,7 @@ module Gitlab end def execute - project = ::Projects::CreateService.new( + ::Projects::CreateService.new( current_user, name: repo["name"], path: repo["slug"], @@ -21,11 +21,8 @@ module Gitlab import_type: "bitbucket", import_source: "#{repo["owner"]}/#{repo["slug"]}", import_url: "ssh://git@bitbucket.org/#{repo["owner"]}/#{repo["slug"]}.git", + import_data: { credentials: { bb_session: session_data } } ).execute - - project.create_or_update_import_data(credentials: { bb_session: session_data }) - - project end end end diff --git a/lib/gitlab/ci/build/artifacts/metadata.rb b/lib/gitlab/ci/build/artifacts/metadata.rb index f2020c82d4..cd2e83b4c2 100644 --- a/lib/gitlab/ci/build/artifacts/metadata.rb +++ b/lib/gitlab/ci/build/artifacts/metadata.rb @@ -56,7 +56,7 @@ module Gitlab child_pattern = '[^/]*/?$' unless @opts[:recursive] match_pattern = /^#{Regexp.escape(@path)}#{child_pattern}/ - until gz.eof? do + until gz.eof? begin path = read_string(gz).force_encoding('UTF-8') meta = read_string(gz).force_encoding('UTF-8') diff --git a/lib/gitlab/contributions_calendar.rb b/lib/gitlab/contributions_calendar.rb index 85583dce9e..9dc2602867 100644 --- a/lib/gitlab/contributions_calendar.rb +++ b/lib/gitlab/contributions_calendar.rb @@ -19,7 +19,7 @@ module Gitlab select('date(created_at) as date, count(id) as total_amount'). map(&:attributes) - dates = (1.year.ago.to_date..(Date.today + 1.day)).to_a + dates = (1.year.ago.to_date..Date.today).to_a dates.each do |date| date_id = date.to_time.to_i.to_s diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb index f44d1b3a44..92c7e8b9d8 100644 --- a/lib/gitlab/current_settings.rb +++ b/lib/gitlab/current_settings.rb @@ -1,20 +1,24 @@ module Gitlab module CurrentSettings def current_application_settings - key = :current_application_settings - - RequestStore.store[key] ||= begin - settings = nil - - if connect_to_db? - settings = ::ApplicationSetting.current - settings ||= ::ApplicationSetting.create_from_defaults unless ActiveRecord::Migrator.needs_migration? - end - - settings || fake_application_settings + if RequestStore.active? + RequestStore.fetch(:current_application_settings) { ensure_application_settings! } + else + ensure_application_settings! end end + def ensure_application_settings! + settings = ::ApplicationSetting.cached + + if !settings && connect_to_db? + settings = ::ApplicationSetting.current + settings ||= ::ApplicationSetting.create_from_defaults unless ActiveRecord::Migrator.needs_migration? + end + + settings || fake_application_settings + end + def fake_application_settings OpenStruct.new( default_projects_limit: Settings.gitlab['default_projects_limit'], @@ -36,6 +40,7 @@ module Gitlab two_factor_grace_period: 48, akismet_enabled: false, repository_checks_enabled: true, + container_registry_token_expire_delay: 5, ) end diff --git a/lib/gitlab/database.rb b/lib/gitlab/database.rb index 6f9da69983..42bec913a4 100644 --- a/lib/gitlab/database.rb +++ b/lib/gitlab/database.rb @@ -5,11 +5,11 @@ module Gitlab end def self.mysql? - adapter_name.downcase == 'mysql2' + adapter_name.casecmp('mysql2').zero? end def self.postgresql? - adapter_name.downcase == 'postgresql' + adapter_name.casecmp('postgresql').zero? end def self.version diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb new file mode 100644 index 0000000000..fd14234c55 --- /dev/null +++ b/lib/gitlab/database/migration_helpers.rb @@ -0,0 +1,142 @@ +module Gitlab + module Database + module MigrationHelpers + # Creates a new index, concurrently when supported + # + # On PostgreSQL this method creates an index concurrently, on MySQL this + # creates a regular index. + # + # Example: + # + # add_concurrent_index :users, :some_column + # + # See Rails' `add_index` for more info on the available arguments. + def add_concurrent_index(*args) + if transaction_open? + raise 'add_concurrent_index can not be run inside a transaction, ' \ + 'you can disable transactions by calling disable_ddl_transaction! ' \ + 'in the body of your migration class' + end + + if Database.postgresql? + args << { algorithm: :concurrently } + end + + add_index(*args) + end + + # Updates the value of a column in batches. + # + # This method updates the table in batches of 5% of the total row count. + # Any data inserted while running this method (or after it has finished + # running) is _not_ updated automatically. + # + # This method _only_ updates rows where the column's value is set to NULL. + # + # table - The name of the table. + # column - The name of the column to update. + # value - The value for the column. + def update_column_in_batches(table, column, value) + quoted_table = quote_table_name(table) + quoted_column = quote_column_name(column) + + ## + # Workaround for #17711 + # + # It looks like for MySQL `ActiveRecord::Base.conntection.quote(true)` + # returns correct value (1), but `ActiveRecord::Migration.new.quote` + # returns incorrect value ('true'), which causes migrations to fail. + # + quoted_value = connection.quote(value) + processed = 0 + + total = exec_query("SELECT COUNT(*) AS count FROM #{quoted_table}"). + to_hash. + first['count']. + to_i + + # Update in batches of 5% + batch_size = ((total / 100.0) * 5.0).ceil + + while processed < total + start_row = exec_query(%Q{ + SELECT id + FROM #{quoted_table} + ORDER BY id ASC + LIMIT 1 OFFSET #{processed} + }).to_hash.first + + stop_row = exec_query(%Q{ + SELECT id + FROM #{quoted_table} + ORDER BY id ASC + LIMIT 1 OFFSET #{processed + batch_size} + }).to_hash.first + + query = %Q{ + UPDATE #{quoted_table} + SET #{quoted_column} = #{quoted_value} + WHERE id >= #{start_row['id']} + } + + if stop_row + query += " AND id < #{stop_row['id']}" + end + + execute(query) + + processed += batch_size + end + end + + # Adds a column with a default value without locking an entire table. + # + # This method runs the following steps: + # + # 1. Add the column with a default value of NULL. + # 2. Update all existing rows in batches. + # 3. Change the default value of the column to the specified value. + # 4. Update any remaining rows. + # + # These steps ensure a column can be added to a large and commonly used + # table without locking the entire table for the duration of the table + # modification. + # + # table - The name of the table to update. + # column - The name of the column to add. + # type - The column type (e.g. `:integer`). + # default - The default value for the column. + # allow_null - When set to `true` the column will allow NULL values, the + # default is to not allow NULL values. + def add_column_with_default(table, column, type, default:, allow_null: false) + if transaction_open? + raise 'add_column_with_default can not be run inside a transaction, ' \ + 'you can disable transactions by calling disable_ddl_transaction! ' \ + 'in the body of your migration class' + end + + transaction do + add_column(table, column, type, default: nil) + + # Changing the default before the update ensures any newly inserted + # rows already use the proper default value. + change_column_default(table, column, default) + end + + begin + transaction do + update_column_in_batches(table, column, default) + end + # We want to rescue _all_ exceptions here, even those that don't inherit + # from StandardError. + rescue Exception => error # rubocop: disable all + remove_column(table, column) + + raise error + end + + change_column_null(table, column, false) unless allow_null + end + end + end +end diff --git a/lib/gitlab/diff/inline_diff_marker.rb b/lib/gitlab/diff/inline_diff_marker.rb index dccb717e95..87a9b1e23a 100644 --- a/lib/gitlab/diff/inline_diff_marker.rb +++ b/lib/gitlab/diff/inline_diff_marker.rb @@ -1,6 +1,11 @@ module Gitlab module Diff class InlineDiffMarker + MARKDOWN_SYMBOLS = { + addition: "+", + deletion: "-" + } + attr_accessor :raw_line, :rich_line def initialize(raw_line, rich_line = raw_line) @@ -8,7 +13,7 @@ module Gitlab @rich_line = ERB::Util.html_escape(rich_line) end - def mark(line_inline_diffs) + def mark(line_inline_diffs, mode: nil, markdown: false) return rich_line unless line_inline_diffs marker_ranges = [] @@ -20,13 +25,22 @@ module Gitlab end offset = 0 - # Mark each range - marker_ranges.each_with_index do |range, i| - class_names = ["idiff"] - class_names << "left" if i == 0 - class_names << "right" if i == marker_ranges.length - 1 - offset = insert_around_range(rich_line, range, "", "", offset) + # Mark each range + marker_ranges.each_with_index do |range, index| + before_content = + if markdown + "{#{MARKDOWN_SYMBOLS[mode]}" + else + "" + end + after_content = + if markdown + "#{MARKDOWN_SYMBOLS[mode]}}" + else + "" + end + offset = insert_around_range(rich_line, range, before_content, after_content, offset) end rich_line.html_safe @@ -34,6 +48,14 @@ module Gitlab private + def html_class_names(marker_ranges, mode, index) + class_names = ["idiff"] + class_names << "left" if index == 0 + class_names << "right" if index == marker_ranges.length - 1 + class_names << mode if mode + class_names.join(" ") + end + # Mapping of character positions in the raw line, to the rich (highlighted) line def position_mapping @position_mapping ||= begin diff --git a/lib/gitlab/diff/parser.rb b/lib/gitlab/diff/parser.rb index d0815fc7ee..522dd2b942 100644 --- a/lib/gitlab/diff/parser.rb +++ b/lib/gitlab/diff/parser.rb @@ -17,16 +17,16 @@ module Gitlab Enumerator.new do |yielder| @lines.each do |line| next if filename?(line) - - full_line = line.gsub(/\n/, '') - + + full_line = line.delete("\n") + if line.match(/^@@ -/) type = "match" - + line_old = line.match(/\-[0-9]*/)[0].to_i.abs rescue 0 line_new = line.match(/\+[0-9]*/)[0].to_i.abs rescue 0 - - next if line_old <= 1 && line_new <= 1 #top of file + + next if line_old <= 1 && line_new <= 1 # top of file yielder << Gitlab::Diff::Line.new(full_line, type, line_obj_index, line_old, line_new) line_obj_index += 1 next @@ -39,8 +39,8 @@ module Gitlab yielder << Gitlab::Diff::Line.new(full_line, type, line_obj_index, line_old, line_new) line_obj_index += 1 end - - + + case line[0] when "+" line_new += 1 diff --git a/lib/gitlab/email/message/repository_push.rb b/lib/gitlab/email/message/repository_push.rb index 8f9be6cd9a..e2fee6b9f3 100644 --- a/lib/gitlab/email/message/repository_push.rb +++ b/lib/gitlab/email/message/repository_push.rb @@ -2,22 +2,21 @@ module Gitlab module Email module Message class RepositoryPush - attr_accessor :recipient attr_reader :author_id, :ref, :action include Gitlab::Routing.url_helpers + include DiffHelper delegate :namespace, :name_with_namespace, to: :project, prefix: :project delegate :name, to: :author, prefix: :author delegate :username, to: :author, prefix: :author - def initialize(notify, project_id, recipient, opts = {}) + def initialize(notify, project_id, opts = {}) raise ArgumentError, 'Missing options: author_id, ref, action' unless opts[:author_id] && opts[:ref] && opts[:action] @notify = notify @project_id = project_id - @recipient = recipient @opts = opts.dup @author_id = @opts.delete(:author_id) @@ -38,7 +37,7 @@ module Gitlab end def diffs - @diffs ||= (compare.diffs if compare) + @diffs ||= (safe_diff_files(compare.diffs, diff_refs) if compare) end def diffs_count @@ -49,6 +48,10 @@ module Gitlab @opts[:compare] end + def diff_refs + @opts[:diff_refs] + end + def compare_timeout diffs.overflow? if diffs end diff --git a/lib/gitlab/email/reply_parser.rb b/lib/gitlab/email/reply_parser.rb index 6ed36b51f1..3411eb1d9c 100644 --- a/lib/gitlab/email/reply_parser.rb +++ b/lib/gitlab/email/reply_parser.rb @@ -65,7 +65,7 @@ module Gitlab (l =~ /On \w+ \d+,? \d+,?.*wrote:/) # Headers on subsequent lines - break if (0..2).all? { |off| lines[idx+off] =~ REPLYING_HEADER_REGEX } + break if (0..2).all? { |off| lines[idx + off] =~ REPLYING_HEADER_REGEX } # Headers on the same line break if REPLYING_HEADER_LABELS.count { |label| l.include?(label) } >= 3 diff --git a/lib/gitlab/fogbugz_import/project_creator.rb b/lib/gitlab/fogbugz_import/project_creator.rb index 3840765db8..1918d5b208 100644 --- a/lib/gitlab/fogbugz_import/project_creator.rb +++ b/lib/gitlab/fogbugz_import/project_creator.rb @@ -12,7 +12,7 @@ module Gitlab end def execute - project = ::Projects::CreateService.new( + ::Projects::CreateService.new( current_user, name: repo.safe_name, path: repo.path, @@ -21,12 +21,9 @@ module Gitlab visibility_level: Gitlab::VisibilityLevel::INTERNAL, import_type: 'fogbugz', import_source: repo.name, - import_url: Project::UNKNOWN_IMPORT_URL + import_url: Project::UNKNOWN_IMPORT_URL, + import_data: { data: { 'repo' => repo.raw_data, 'user_map' => user_map }, credentials: { fb_session: fb_session } } ).execute - - project.create_or_update_import_data(data: { 'repo' => repo.raw_data, 'user_map' => user_map }, credentials: { fb_session: fb_session }) - - project end end end diff --git a/lib/gitlab/github_import/branch_formatter.rb b/lib/gitlab/github_import/branch_formatter.rb new file mode 100644 index 0000000000..a15fc84b41 --- /dev/null +++ b/lib/gitlab/github_import/branch_formatter.rb @@ -0,0 +1,29 @@ +module Gitlab + module GithubImport + class BranchFormatter < BaseFormatter + delegate :repo, :sha, :ref, to: :raw_data + + def exists? + project.repository.branch_exists?(ref) + end + + def name + @name ||= exists? ? ref : "#{ref}-#{short_id}" + end + + def valid? + repo.present? + end + + def valid? + repo.present? + end + + private + + def short_id + sha.to_s[0..7] + end + end + end +end diff --git a/lib/gitlab/github_import/importer.rb b/lib/gitlab/github_import/importer.rb index 0f9e3ee14e..408d9b7963 100644 --- a/lib/gitlab/github_import/importer.rb +++ b/lib/gitlab/github_import/importer.rb @@ -3,12 +3,15 @@ module Gitlab class Importer include Gitlab::ShellAdapter - attr_reader :project, :client + attr_reader :client, :project, :repo, :repo_url def initialize(project) - @project = project - if import_data_credentials - @client = Client.new(import_data_credentials[:user]) + @project = project + @repo = project.import_source + @repo_url = project.import_url + + if credentials + @client = Client.new(credentials[:user]) @formatter = Gitlab::ImportFormatter.new else raise Projects::ImportService::Error, "Unable to find project import data credentials for project ID: #{@project.id}" @@ -22,12 +25,12 @@ module Gitlab private - def import_data_credentials - @import_data_credentials ||= project.import_data.credentials if project.import_data + def credentials + @credentials ||= project.import_data.credentials if project.import_data end def import_labels - client.labels(project.import_source).each do |raw_data| + client.labels(repo).each do |raw_data| Label.create!(LabelFormatter.new(project, raw_data).attributes) end @@ -37,7 +40,7 @@ module Gitlab end def import_milestones - client.list_milestones(project.import_source, state: :all).each do |raw_data| + client.list_milestones(repo, state: :all).each do |raw_data| Milestone.create!(MilestoneFormatter.new(project, raw_data).attributes) end @@ -47,9 +50,7 @@ module Gitlab end def import_issues - client.list_issues(project.import_source, state: :all, - sort: :created, - direction: :asc).each do |raw_data| + client.list_issues(repo, state: :all, sort: :created, direction: :asc).each do |raw_data| gh_issue = IssueFormatter.new(project, raw_data) if gh_issue.valid? @@ -68,29 +69,50 @@ module Gitlab end def import_pull_requests - client.pull_requests(project.import_source, state: :all, - sort: :created, - direction: :asc).each do |raw_data| - pull_request = PullRequestFormatter.new(project, raw_data) + pull_requests = client.pull_requests(repo, state: :all, sort: :created, direction: :asc) + .map { |raw| PullRequestFormatter.new(project, raw) } + .select(&:valid?) - if pull_request.valid? - merge_request = MergeRequest.new(pull_request.attributes) + source_branches_removed = pull_requests.reject(&:source_branch_exists?).map { |pr| [pr.source_branch_name, pr.source_branch_sha] } + target_branches_removed = pull_requests.reject(&:target_branch_exists?).map { |pr| [pr.target_branch_name, pr.target_branch_sha] } + branches_removed = source_branches_removed | target_branches_removed - if merge_request.save - apply_labels(pull_request.number, merge_request) - import_comments(pull_request.number, merge_request) - import_comments_on_diff(pull_request.number, merge_request) - end + create_refs(branches_removed) + + pull_requests.each do |pull_request| + merge_request = MergeRequest.new(pull_request.attributes) + + if merge_request.save + apply_labels(pull_request.number, merge_request) + import_comments(pull_request.number, merge_request) + import_comments_on_diff(pull_request.number, merge_request) end end + delete_refs(branches_removed) + true rescue ActiveRecord::RecordInvalid => e raise Projects::ImportService::Error, e.message end + def create_refs(branches) + branches.each do |name, sha| + client.create_ref(repo, "refs/heads/#{name}", sha) + end + + project.repository.fetch_ref(repo_url, '+refs/heads/*', 'refs/heads/*') + end + + def delete_refs(branches) + branches.each do |name, _| + client.delete_ref(repo, "heads/#{name}") + project.repository.rm_branch(project.creator, name) + end + end + def apply_labels(number, issuable) - issue = client.issue(project.import_source, number) + issue = client.issue(repo, number) if issue.labels.count > 0 label_ids = issue.labels.map do |raw| @@ -102,12 +124,12 @@ module Gitlab end def import_comments(issue_number, noteable) - comments = client.issue_comments(project.import_source, issue_number) + comments = client.issue_comments(repo, issue_number) create_comments(comments, noteable) end def import_comments_on_diff(pull_request_number, merge_request) - comments = client.pull_request_comments(project.import_source, pull_request_number) + comments = client.pull_request_comments(repo, pull_request_number) create_comments(comments, merge_request) end diff --git a/lib/gitlab/github_import/pull_request_formatter.rb b/lib/gitlab/github_import/pull_request_formatter.rb index d21b942ad4..a2947b56ad 100644 --- a/lib/gitlab/github_import/pull_request_formatter.rb +++ b/lib/gitlab/github_import/pull_request_formatter.rb @@ -1,15 +1,20 @@ module Gitlab module GithubImport class PullRequestFormatter < BaseFormatter + delegate :exists?, :name, :project, :repo, :sha, to: :source_branch, prefix: true + delegate :exists?, :name, :project, :repo, :sha, to: :target_branch, prefix: true + def attributes { iid: number, title: raw_data.title, description: description, - source_project: source_project, - source_branch: source_branch.name, - target_project: target_project, - target_branch: target_branch.name, + source_project: source_branch_project, + source_branch: source_branch_name, + head_source_sha: source_branch_sha, + target_project: target_branch_project, + target_branch: target_branch_name, + base_target_sha: target_branch_sha, state: state, milestone: milestone, author_id: author_id, @@ -24,7 +29,15 @@ module Gitlab end def valid? - !cross_project? && source_branch.present? && target_branch.present? + source_branch.valid? && target_branch.valid? && !cross_project? + end + + def source_branch + @source_branch ||= BranchFormatter.new(project, raw_data.head) + end + + def target_branch + @target_branch ||= BranchFormatter.new(project, raw_data.base) end private @@ -52,7 +65,7 @@ module Gitlab end def cross_project? - source_repo.present? && target_repo.present? && source_repo.id != target_repo.id + source_branch_repo.id != target_branch_repo.id end def description @@ -65,35 +78,10 @@ module Gitlab end end - def source_project - project - end - - def source_repo - raw_data.head.repo - end - - def source_branch - source_project.repository.find_branch(raw_data.head.ref) - end - - def target_project - project - end - - def target_repo - raw_data.base.repo - end - - def target_branch - target_project.repository.find_branch(raw_data.base.ref) - end - def state - @state ||= case true - when raw_data.state == 'closed' && raw_data.merged_at.present? + @state ||= if raw_data.state == 'closed' && raw_data.merged_at.present? 'merged' - when raw_data.state == 'closed' + elsif raw_data.state == 'closed' 'closed' else 'opened' diff --git a/lib/gitlab/gitignore.rb b/lib/gitlab/gitignore.rb new file mode 100644 index 0000000000..f46b43b61a --- /dev/null +++ b/lib/gitlab/gitignore.rb @@ -0,0 +1,56 @@ +module Gitlab + class Gitignore + FILTER_REGEX = /\.gitignore\z/.freeze + + def initialize(path) + @path = path + end + + def name + File.basename(@path, '.gitignore') + end + + def content + File.read(@path) + end + + class << self + def all + languages_frameworks + global + end + + def find(key) + file_name = "#{key}.gitignore" + + directory = select_directory(file_name) + directory ? new(File.join(directory, file_name)) : nil + end + + def global + files_for_folder(global_dir).map { |file| new(File.join(global_dir, file)) } + end + + def languages_frameworks + files_for_folder(gitignore_dir).map { |file| new(File.join(gitignore_dir, file)) } + end + + private + + def select_directory(file_name) + [gitignore_dir, global_dir].find { |dir| File.exist?(File.join(dir, file_name)) } + end + + def global_dir + File.join(gitignore_dir, 'Global') + end + + def gitignore_dir + Rails.root.join('vendor/gitignore') + end + + def files_for_folder(dir) + Dir.glob("#{dir.to_s}/*.gitignore").map { |file| file.gsub(FILTER_REGEX, '') } + end + end + end +end diff --git a/lib/gitlab/gitlab_import/importer.rb b/lib/gitlab/gitlab_import/importer.rb index 96717b42ba..3f76ec9797 100644 --- a/lib/gitlab/gitlab_import/importer.rb +++ b/lib/gitlab/gitlab_import/importer.rb @@ -5,9 +5,9 @@ module Gitlab def initialize(project) @project = project - credentials = import_data - if credentials && credentials[:password] - @client = Client.new(credentials[:password]) + import_data = project.import_data + if import_data && import_data.credentials && import_data.credentials[:password] + @client = Client.new(import_data.credentials[:password]) @formatter = Gitlab::ImportFormatter.new else raise Projects::ImportService::Error, "Unable to find project import data credentials for project ID: #{@project.id}" @@ -17,7 +17,7 @@ module Gitlab def execute project_identifier = CGI.escape(project.import_source) - #Issues && Comments + # Issues && Comments issues = client.issues(project_identifier) issues.each do |issue| diff --git a/lib/gitlab/google_code_import/project_creator.rb b/lib/gitlab/google_code_import/project_creator.rb index 0abb7a64c1..326cfcaa8a 100644 --- a/lib/gitlab/google_code_import/project_creator.rb +++ b/lib/gitlab/google_code_import/project_creator.rb @@ -11,7 +11,7 @@ module Gitlab end def execute - project = ::Projects::CreateService.new( + ::Projects::CreateService.new( current_user, name: repo.name, path: repo.name, @@ -21,12 +21,9 @@ module Gitlab visibility_level: Gitlab::VisibilityLevel::PUBLIC, import_type: "google_code", import_source: repo.name, - import_url: repo.import_url + import_url: repo.import_url, + import_data: { data: { 'repo' => repo.raw_data, 'user_map' => user_map } } ).execute - - project.create_or_update_import_data(data: { 'repo' => repo.raw_data, 'user_map' => user_map }) - - project end end end diff --git a/lib/gitlab/lazy.rb b/lib/gitlab/lazy.rb new file mode 100644 index 0000000000..2a659ae4c7 --- /dev/null +++ b/lib/gitlab/lazy.rb @@ -0,0 +1,34 @@ +module Gitlab + # A class that can be wrapped around an expensive method call so it's only + # executed when actually needed. + # + # Usage: + # + # object = Gitlab::Lazy.new { some_expensive_work_here } + # + # object['foo'] + # object.bar + class Lazy < BasicObject + def initialize(&block) + @block = block + end + + def method_missing(name, *args, &block) + __evaluate__ + + @result.__send__(name, *args, &block) + end + + def respond_to_missing?(name, include_private = false) + __evaluate__ + + @result.respond_to?(name, include_private) || super + end + + private + + def __evaluate__ + @result = @block.call unless defined?(@result) + end + end +end diff --git a/lib/gitlab/markup_helper.rb b/lib/gitlab/markup_helper.rb index a5f767b134..dda371e655 100644 --- a/lib/gitlab/markup_helper.rb +++ b/lib/gitlab/markup_helper.rb @@ -40,7 +40,7 @@ module Gitlab # Returns boolean def plain?(filename) filename.downcase.end_with?('.txt') || - filename.downcase == 'readme' + filename.casecmp('readme').zero? end def previewable?(filename) diff --git a/lib/gitlab/metrics/instrumentation.rb b/lib/gitlab/metrics/instrumentation.rb index 708ef79f30..0f115893a1 100644 --- a/lib/gitlab/metrics/instrumentation.rb +++ b/lib/gitlab/metrics/instrumentation.rb @@ -154,8 +154,6 @@ module Gitlab duration = (Time.now - start) * 1000.0 if duration >= Gitlab::Metrics.method_call_threshold - trans.increment(:method_duration, duration) - trans.add_metric(Gitlab::Metrics::Instrumentation::SERIES, { duration: duration }, method: #{label.inspect}) diff --git a/lib/gitlab/metrics/subscribers/rails_cache.rb b/lib/gitlab/metrics/subscribers/rails_cache.rb index 49e5f86e6e..8e345e8ae4 100644 --- a/lib/gitlab/metrics/subscribers/rails_cache.rb +++ b/lib/gitlab/metrics/subscribers/rails_cache.rb @@ -6,26 +6,28 @@ module Gitlab attach_to :active_support def cache_read(event) - increment(:cache_read_duration, event.duration) + increment(:cache_read, event.duration) end def cache_write(event) - increment(:cache_write_duration, event.duration) + increment(:cache_write, event.duration) end def cache_delete(event) - increment(:cache_delete_duration, event.duration) + increment(:cache_delete, event.duration) end def cache_exist?(event) - increment(:cache_exists_duration, event.duration) + increment(:cache_exists, event.duration) end def increment(key, duration) return unless current_transaction current_transaction.increment(:cache_duration, duration) - current_transaction.increment(key, duration) + current_transaction.increment(:cache_count, 1) + current_transaction.increment("#{key}_duration".to_sym, duration) + current_transaction.increment("#{key}_count".to_sym, 1) end private diff --git a/lib/gitlab/middleware/go.rb b/lib/gitlab/middleware/go.rb index 50b0dd3238..5764ab1565 100644 --- a/lib/gitlab/middleware/go.rb +++ b/lib/gitlab/middleware/go.rb @@ -39,7 +39,7 @@ module Gitlab request_url = URI.join(base_url, project_path) domain_path = strip_url(request_url.to_s) - "\n"; + "\n" end def strip_url(url) diff --git a/lib/gitlab/middleware/rails_queue_duration.rb b/lib/gitlab/middleware/rails_queue_duration.rb new file mode 100644 index 0000000000..56608b1b27 --- /dev/null +++ b/lib/gitlab/middleware/rails_queue_duration.rb @@ -0,0 +1,24 @@ +# This Rack middleware is intended to measure the latency between +# gitlab-workhorse forwarding a request to the Rails application and the +# time this middleware is reached. + +module Gitlab + module Middleware + class RailsQueueDuration + def initialize(app) + @app = app + end + + def call(env) + trans = Gitlab::Metrics.current_transaction + proxy_start = env['HTTP_GITLAB_WORHORSE_PROXY_START'].presence + if trans && proxy_start + # Time in milliseconds since gitlab-workhorse started the request + trans.set(:rails_queue_duration, Time.now.to_f * 1_000 - proxy_start.to_f / 1_000_000) + end + + @app.call(env) + end + end + end +end diff --git a/lib/gitlab/project_search_results.rb b/lib/gitlab/project_search_results.rb index 71c5b6801f..183bd10d6a 100644 --- a/lib/gitlab/project_search_results.rb +++ b/lib/gitlab/project_search_results.rb @@ -74,7 +74,7 @@ module Gitlab end def notes - project.notes.user.search(query).order('updated_at DESC') + project.notes.user.search(query, as_user: @current_user).order('updated_at DESC') end def commits diff --git a/lib/gitlab/redis.rb b/lib/gitlab/redis.rb index 5c352c96de..40766f35f7 100644 --- a/lib/gitlab/redis.rb +++ b/lib/gitlab/redis.rb @@ -25,7 +25,7 @@ module Gitlab end @pool.with { |redis| yield redis } end - + def self.redis_store_options url = new.url redis_config_hash = ::Redis::Store::Factory.extract_host_options_from_uri(url) @@ -40,10 +40,10 @@ module Gitlab def initialize(rails_env=nil) rails_env ||= Rails.env config_file = File.expand_path('../../../config/resque.yml', __FILE__) - + @url = "redis://localhost:6379" - if File.exists?(config_file) - @url =YAML.load_file(config_file)[rails_env] + if File.exist?(config_file) + @url = YAML.load_file(config_file)[rails_env] end end end diff --git a/lib/gitlab/reference_extractor.rb b/lib/gitlab/reference_extractor.rb index 13c4d64c99..11c0b01f0d 100644 --- a/lib/gitlab/reference_extractor.rb +++ b/lib/gitlab/reference_extractor.rb @@ -4,10 +4,9 @@ module Gitlab REFERABLES = %i(user issue label milestone merge_request snippet commit commit_range) attr_accessor :project, :current_user, :author - def initialize(project, current_user = nil, author = nil) + def initialize(project, current_user = nil) @project = project @current_user = current_user - @author = author @references = {} @@ -18,17 +17,21 @@ module Gitlab super(text, context.merge(project: project)) end + def references(type) + super(type, project, current_user) + end + REFERABLES.each do |type| define_method("#{type}s") do - @references[type] ||= references(type, reference_context) + @references[type] ||= references(type) end end def issues if project && project.jira_tracker? - @references[:external_issue] ||= references(:external_issue, reference_context) + @references[:external_issue] ||= references(:external_issue) else - @references[:issue] ||= references(:issue, reference_context) + @references[:issue] ||= references(:issue) end end @@ -46,11 +49,5 @@ module Gitlab @pattern = Regexp.union(patterns.compact) end - - private - - def reference_context - { project: project, current_user: current_user, author: author } - end end end diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb index ace906a6f5..1cbd6d945a 100644 --- a/lib/gitlab/regex.rb +++ b/lib/gitlab/regex.rb @@ -96,5 +96,9 @@ module Gitlab (? %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage target text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space], - 'altGlyph' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight format glyph-orientation-horizontal glyph-orientation-vertical glyphRef id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rotate shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering unicode-bidi visibility word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y], - 'altGlyphDef' => %w[id xml:base xml:lang xml:space], - 'altGlyphItem' => %w[id xml:base xml:lang xml:space], - 'animate' => %w[accumulate additive alignment-baseline attributeName attributeType baseline-shift begin by calcMode clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dur enable-background end externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight from glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning keySplines keyTimes letter-spacing lighting-color marker-end marker-mid marker-start mask max min onbegin onend onload onrepeat opacity overflow pointer-events repeatCount repeatDur requiredExtensions requiredFeatures restart shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width systemLanguage text-anchor text-decoration text-rendering to unicode-bidi values visibility word-spacing writing-mode xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space], - 'animateColor' => %w[accumulate additive alignment-baseline attributeName attributeType baseline-shift begin by calcMode clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dur enable-background end externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight from glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning keySplines keyTimes letter-spacing lighting-color marker-end marker-mid marker-start mask max min onbegin onend onload onrepeat opacity overflow pointer-events repeatCount repeatDur requiredExtensions requiredFeatures restart shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width systemLanguage text-anchor text-decoration text-rendering to unicode-bidi values visibility word-spacing writing-mode xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space], - 'animateMotion' => %w[accumulate additive begin by calcMode dur end externalResourcesRequired fill from id keyPoints keySplines keyTimes max min onbegin onend onload onrepeat origin path repeatCount repeatDur requiredExtensions requiredFeatures restart rotate systemLanguage to values xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space], - 'animateTransform' => %w[accumulate additive attributeName attributeType begin by calcMode dur end externalResourcesRequired fill from id keySplines keyTimes max min onbegin onend onload onrepeat repeatCount repeatDur requiredExtensions requiredFeatures restart systemLanguage to type values xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space], - 'circle' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor cx cy direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events r requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space], - 'clipPath' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule clipPathUnits color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space], - 'color-profile' => %w[id local name rendering-intent xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space], - 'cursor' => %w[externalResourcesRequired id requiredExtensions requiredFeatures systemLanguage x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y], - 'defs' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space], - 'desc' => %w[class id style xml:base xml:lang xml:space], - 'ellipse' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor cx cy direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rx ry shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space], - 'feBlend' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in in2 kerning letter-spacing lighting-color marker-end marker-mid marker-start mask mode opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], - 'feColorMatrix' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering type unicode-bidi values visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], - 'feComponentTransfer' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], - 'feComposite' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in in2 k1 k2 k3 k4 kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity operator overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], - 'feConvolveMatrix' => %w[alignment-baseline baseline-shift bias class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display divisor dominant-baseline edgeMode enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kernelMatrix kernelUnitLength kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity order overflow pointer-events preserveAlpha result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style targetX targetY text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], - 'feDiffuseLighting' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor diffuseConstant direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kernelUnitLength kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style surfaceScale text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], - 'feDisplacementMap' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in in2 kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result scale shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xChannelSelector xml:base xml:lang xml:space y yChannelSelector], - 'feDistantLight' => %w[azimuth elevation id xml:base xml:lang xml:space], - 'feFlood' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], - 'feFuncA' => %w[amplitude exponent id intercept offset slope tableValues type xml:base xml:lang xml:space], - 'feFuncB' => %w[amplitude exponent id intercept offset slope tableValues type xml:base xml:lang xml:space], - 'feFuncG' => %w[amplitude exponent id intercept offset slope tableValues type xml:base xml:lang xml:space], - 'feFuncR' => %w[amplitude exponent id intercept offset slope tableValues type xml:base xml:lang xml:space], - 'feGaussianBlur' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stdDeviation stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], - 'feImage' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events preserveAspectRatio result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y], - 'feMerge' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], - 'feMergeNode' => %w[id xml:base xml:lang xml:space], - 'feMorphology' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity operator overflow pointer-events radius result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], - 'feOffset' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], - 'fePointLight' => %w[id x xml:base xml:lang xml:space y z], - 'feSpecularLighting' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kernelUnitLength kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering specularConstant specularExponent stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style surfaceScale text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], - 'feSpotLight' => %w[id limitingConeAngle pointsAtX pointsAtY pointsAtZ specularExponent x xml:base xml:lang xml:space y z], - 'feTile' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], - 'feTurbulence' => %w[alignment-baseline baseFrequency baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask numOctaves opacity overflow pointer-events result seed shape-rendering stitchTiles stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering type unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], - 'filter' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter filterRes filterUnits flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events primitiveUnits shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y], - 'font' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x horiz-origin-y id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi vert-adv-y vert-origin-x vert-origin-y visibility word-spacing writing-mode xml:base xml:lang xml:space], - 'font-face' => %w[accent-height alphabetic ascent bbox cap-height descent font-family font-size font-stretch font-style font-variant font-weight hanging id ideographic mathematical overline-position overline-thickness panose-1 slope stemh stemv strikethrough-position strikethrough-thickness underline-position underline-thickness unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical widths x-height xml:base xml:lang xml:space], - 'font-face-format' => %w[id string xml:base xml:lang xml:space], - 'font-face-name' => %w[id name xml:base xml:lang xml:space], - 'font-face-src' => %w[id xml:base xml:lang xml:space], - 'font-face-uri' => %w[id xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space], - 'foreignObject' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], - 'g' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space], - 'glyph' => %w[alignment-baseline arabic-form baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor d direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x id image-rendering kerning lang letter-spacing lighting-color marker-end marker-mid marker-start mask opacity orientation overflow pointer-events shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode unicode-bidi vert-adv-y vert-origin-x vert-origin-y visibility word-spacing writing-mode xml:base xml:lang xml:space], - 'glyphRef' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight format glyph-orientation-horizontal glyph-orientation-vertical glyphRef id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y], - 'hkern' => %w[g1 g2 id k u1 u2 xml:base xml:lang xml:space], - 'image' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events preserveAspectRatio requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility width word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y], - 'line' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode x1 x2 xml:base xml:lang xml:space y1 y2], - 'linearGradient' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical gradientTransform gradientUnits id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events shape-rendering spreadMethod stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility word-spacing writing-mode x1 x2 xlink:arcrole xlink:href xlink:role xlink:title xlink:type xml:base xml:lang xml:space y1 y2], - 'marker' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start markerHeight markerUnits markerWidth mask opacity orient overflow pointer-events preserveAspectRatio refX refY shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi viewBox visibility word-spacing writing-mode xml:base xml:lang xml:space], - 'mask' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask maskContentUnits maskUnits opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], - 'metadata' => %w[id xml:base xml:lang xml:space], - 'missing-glyph' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor d direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi vert-adv-y vert-origin-x vert-origin-y visibility word-spacing writing-mode xml:base xml:lang xml:space], - 'mpath' => %w[externalResourcesRequired id xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space], - 'path' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor d direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pathLength pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space], - 'pattern' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow patternContentUnits patternTransform patternUnits pointer-events preserveAspectRatio requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering unicode-bidi viewBox visibility width word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y], - 'polygon' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events points requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space], - 'polyline' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events points requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space], - 'radialGradient' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor cx cy direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight fx fy glyph-orientation-horizontal glyph-orientation-vertical gradientTransform gradientUnits id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events r shape-rendering spreadMethod stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility word-spacing writing-mode xlink:arcrole xlink:href xlink:role xlink:title xlink:type xml:base xml:lang xml:space], - 'rect' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rx ry shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], - 'script' => %w[externalResourcesRequired id type xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space], - 'set' => %w[attributeName attributeType begin dur end externalResourcesRequired fill id max min onbegin onend onload onrepeat repeatCount repeatDur requiredExtensions requiredFeatures restart systemLanguage to xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space], - 'stop' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask offset opacity overflow pointer-events shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space], - 'style' => %w[id media title type xml:base xml:lang xml:space], - 'svg' => %w[alignment-baseline baseProfile baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering contentScriptType contentStyleType cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onabort onactivate onclick onerror onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup onresize onscroll onunload onzoom opacity overflow pointer-events preserveAspectRatio requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering unicode-bidi version viewBox visibility width word-spacing writing-mode x xml:base xml:lang xml:space xmlns y zoomAndPan], - 'switch' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space], - 'symbol' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events preserveAspectRatio shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi viewBox visibility word-spacing writing-mode xml:base xml:lang xml:space], - 'text' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning lengthAdjust letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rotate shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering textLength transform unicode-bidi visibility word-spacing writing-mode x xml:base xml:lang xml:space y], - 'textPath' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning lengthAdjust letter-spacing lighting-color marker-end marker-mid marker-start mask method onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering spacing startOffset stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering textLength unicode-bidi visibility word-spacing writing-mode xlink:arcrole xlink:href xlink:role xlink:title xlink:type xml:base xml:lang xml:space], - 'title' => %w[class id style xml:base xml:lang xml:space], - 'tref' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning lengthAdjust letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rotate shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering textLength unicode-bidi visibility word-spacing writing-mode x xlink:arcrole xlink:href xlink:role xlink:title xlink:type xml:base xml:lang xml:space y], - 'tspan' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning lengthAdjust letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rotate shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering textLength unicode-bidi visibility word-spacing writing-mode x xml:base xml:lang xml:space y], - 'use' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility width word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y], - 'view' => %w[externalResourcesRequired id preserveAspectRatio viewBox viewTarget xml:base xml:lang xml:space zoomAndPan], - 'vkern' => %w[g1 g2 id k u1 u2 xml:base xml:lang xml:space] - }.freeze + ALLOWED_ATTRIBUTES = { + 'a' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage target text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space], + 'altGlyph' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight format glyph-orientation-horizontal glyph-orientation-vertical glyphRef id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rotate shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering unicode-bidi visibility word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y], + 'altGlyphDef' => %w[id xml:base xml:lang xml:space], + 'altGlyphItem' => %w[id xml:base xml:lang xml:space], + 'animate' => %w[accumulate additive alignment-baseline attributeName attributeType baseline-shift begin by calcMode clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dur enable-background end externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight from glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning keySplines keyTimes letter-spacing lighting-color marker-end marker-mid marker-start mask max min onbegin onend onload onrepeat opacity overflow pointer-events repeatCount repeatDur requiredExtensions requiredFeatures restart shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width systemLanguage text-anchor text-decoration text-rendering to unicode-bidi values visibility word-spacing writing-mode xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space], + 'animateColor' => %w[accumulate additive alignment-baseline attributeName attributeType baseline-shift begin by calcMode clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dur enable-background end externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight from glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning keySplines keyTimes letter-spacing lighting-color marker-end marker-mid marker-start mask max min onbegin onend onload onrepeat opacity overflow pointer-events repeatCount repeatDur requiredExtensions requiredFeatures restart shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width systemLanguage text-anchor text-decoration text-rendering to unicode-bidi values visibility word-spacing writing-mode xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space], + 'animateMotion' => %w[accumulate additive begin by calcMode dur end externalResourcesRequired fill from id keyPoints keySplines keyTimes max min onbegin onend onload onrepeat origin path repeatCount repeatDur requiredExtensions requiredFeatures restart rotate systemLanguage to values xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space], + 'animateTransform' => %w[accumulate additive attributeName attributeType begin by calcMode dur end externalResourcesRequired fill from id keySplines keyTimes max min onbegin onend onload onrepeat repeatCount repeatDur requiredExtensions requiredFeatures restart systemLanguage to type values xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space], + 'circle' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor cx cy direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events r requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space], + 'clipPath' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule clipPathUnits color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space], + 'color-profile' => %w[id local name rendering-intent xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space], + 'cursor' => %w[externalResourcesRequired id requiredExtensions requiredFeatures systemLanguage x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y], + 'defs' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space], + 'desc' => %w[class id style xml:base xml:lang xml:space], + 'ellipse' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor cx cy direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rx ry shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space], + 'feBlend' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in in2 kerning letter-spacing lighting-color marker-end marker-mid marker-start mask mode opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], + 'feColorMatrix' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering type unicode-bidi values visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], + 'feComponentTransfer' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], + 'feComposite' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in in2 k1 k2 k3 k4 kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity operator overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], + 'feConvolveMatrix' => %w[alignment-baseline baseline-shift bias class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display divisor dominant-baseline edgeMode enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kernelMatrix kernelUnitLength kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity order overflow pointer-events preserveAlpha result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style targetX targetY text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], + 'feDiffuseLighting' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor diffuseConstant direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kernelUnitLength kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style surfaceScale text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], + 'feDisplacementMap' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in in2 kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result scale shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xChannelSelector xml:base xml:lang xml:space y yChannelSelector], + 'feDistantLight' => %w[azimuth elevation id xml:base xml:lang xml:space], + 'feFlood' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], + 'feFuncA' => %w[amplitude exponent id intercept offset slope tableValues type xml:base xml:lang xml:space], + 'feFuncB' => %w[amplitude exponent id intercept offset slope tableValues type xml:base xml:lang xml:space], + 'feFuncG' => %w[amplitude exponent id intercept offset slope tableValues type xml:base xml:lang xml:space], + 'feFuncR' => %w[amplitude exponent id intercept offset slope tableValues type xml:base xml:lang xml:space], + 'feGaussianBlur' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stdDeviation stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], + 'feImage' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events preserveAspectRatio result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y], + 'feMerge' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], + 'feMergeNode' => %w[id xml:base xml:lang xml:space], + 'feMorphology' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity operator overflow pointer-events radius result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], + 'feOffset' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], + 'fePointLight' => %w[id x xml:base xml:lang xml:space y z], + 'feSpecularLighting' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kernelUnitLength kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering specularConstant specularExponent stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style surfaceScale text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], + 'feSpotLight' => %w[id limitingConeAngle pointsAtX pointsAtY pointsAtZ specularExponent x xml:base xml:lang xml:space y z], + 'feTile' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], + 'feTurbulence' => %w[alignment-baseline baseFrequency baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask numOctaves opacity overflow pointer-events result seed shape-rendering stitchTiles stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering type unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], + 'filter' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter filterRes filterUnits flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events primitiveUnits shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y], + 'font' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x horiz-origin-y id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi vert-adv-y vert-origin-x vert-origin-y visibility word-spacing writing-mode xml:base xml:lang xml:space], + 'font-face' => %w[accent-height alphabetic ascent bbox cap-height descent font-family font-size font-stretch font-style font-variant font-weight hanging id ideographic mathematical overline-position overline-thickness panose-1 slope stemh stemv strikethrough-position strikethrough-thickness underline-position underline-thickness unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical widths x-height xml:base xml:lang xml:space], + 'font-face-format' => %w[id string xml:base xml:lang xml:space], + 'font-face-name' => %w[id name xml:base xml:lang xml:space], + 'font-face-src' => %w[id xml:base xml:lang xml:space], + 'font-face-uri' => %w[id xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space], + 'foreignObject' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], + 'g' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space], + 'glyph' => %w[alignment-baseline arabic-form baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor d direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x id image-rendering kerning lang letter-spacing lighting-color marker-end marker-mid marker-start mask opacity orientation overflow pointer-events shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode unicode-bidi vert-adv-y vert-origin-x vert-origin-y visibility word-spacing writing-mode xml:base xml:lang xml:space], + 'glyphRef' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight format glyph-orientation-horizontal glyph-orientation-vertical glyphRef id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y], + 'hkern' => %w[g1 g2 id k u1 u2 xml:base xml:lang xml:space], + 'image' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events preserveAspectRatio requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility width word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y], + 'line' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode x1 x2 xml:base xml:lang xml:space y1 y2], + 'linearGradient' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical gradientTransform gradientUnits id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events shape-rendering spreadMethod stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility word-spacing writing-mode x1 x2 xlink:arcrole xlink:href xlink:role xlink:title xlink:type xml:base xml:lang xml:space y1 y2], + 'marker' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start markerHeight markerUnits markerWidth mask opacity orient overflow pointer-events preserveAspectRatio refX refY shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi viewBox visibility word-spacing writing-mode xml:base xml:lang xml:space], + 'mask' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask maskContentUnits maskUnits opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], + 'metadata' => %w[id xml:base xml:lang xml:space], + 'missing-glyph' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor d direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi vert-adv-y vert-origin-x vert-origin-y visibility word-spacing writing-mode xml:base xml:lang xml:space], + 'mpath' => %w[externalResourcesRequired id xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space], + 'path' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor d direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pathLength pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space], + 'pattern' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow patternContentUnits patternTransform patternUnits pointer-events preserveAspectRatio requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering unicode-bidi viewBox visibility width word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y], + 'polygon' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events points requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space], + 'polyline' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events points requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space], + 'radialGradient' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor cx cy direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight fx fy glyph-orientation-horizontal glyph-orientation-vertical gradientTransform gradientUnits id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events r shape-rendering spreadMethod stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility word-spacing writing-mode xlink:arcrole xlink:href xlink:role xlink:title xlink:type xml:base xml:lang xml:space], + 'rect' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rx ry shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y], + 'script' => %w[externalResourcesRequired id type xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space], + 'set' => %w[attributeName attributeType begin dur end externalResourcesRequired fill id max min onbegin onend onload onrepeat repeatCount repeatDur requiredExtensions requiredFeatures restart systemLanguage to xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space], + 'stop' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask offset opacity overflow pointer-events shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space], + 'style' => %w[id media title type xml:base xml:lang xml:space], + 'svg' => %w[alignment-baseline baseProfile baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering contentScriptType contentStyleType cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onabort onactivate onclick onerror onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup onresize onscroll onunload onzoom opacity overflow pointer-events preserveAspectRatio requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering unicode-bidi version viewBox visibility width word-spacing writing-mode x xml:base xml:lang xml:space xmlns y zoomAndPan], + 'switch' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space], + 'symbol' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events preserveAspectRatio shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi viewBox visibility word-spacing writing-mode xml:base xml:lang xml:space], + 'text' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning lengthAdjust letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rotate shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering textLength transform unicode-bidi visibility word-spacing writing-mode x xml:base xml:lang xml:space y], + 'textPath' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning lengthAdjust letter-spacing lighting-color marker-end marker-mid marker-start mask method onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering spacing startOffset stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering textLength unicode-bidi visibility word-spacing writing-mode xlink:arcrole xlink:href xlink:role xlink:title xlink:type xml:base xml:lang xml:space], + 'title' => %w[class id style xml:base xml:lang xml:space], + 'tref' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning lengthAdjust letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rotate shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering textLength unicode-bidi visibility word-spacing writing-mode x xlink:arcrole xlink:href xlink:role xlink:title xlink:type xml:base xml:lang xml:space y], + 'tspan' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning lengthAdjust letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rotate shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering textLength unicode-bidi visibility word-spacing writing-mode x xml:base xml:lang xml:space y], + 'use' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility width word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y], + 'view' => %w[externalResourcesRequired id preserveAspectRatio viewBox viewTarget xml:base xml:lang xml:space zoomAndPan], + 'vkern' => %w[g1 g2 id k u1 u2 xml:base xml:lang xml:space] + }.freeze + end end end end diff --git a/lib/gitlab/url_builder.rb b/lib/gitlab/url_builder.rb index 2bbbd3074e..fe65c24610 100644 --- a/lib/gitlab/url_builder.rb +++ b/lib/gitlab/url_builder.rb @@ -62,7 +62,7 @@ module Gitlab end def wiki_page_url - "#{Gitlab.config.gitlab.url}#{object.wiki.wiki_base_path}/#{object.slug}" + namespace_project_wiki_url(object.wiki.project.namespace, object.wiki.project, object.slug) end end end diff --git a/lib/gitlab/import_url.rb b/lib/gitlab/url_sanitizer.rb similarity index 66% rename from lib/gitlab/import_url.rb rename to lib/gitlab/url_sanitizer.rb index d23b013c1f..7d02fe3c97 100644 --- a/lib/gitlab/import_url.rb +++ b/lib/gitlab/url_sanitizer.rb @@ -1,7 +1,13 @@ module Gitlab - class ImportUrl + class UrlSanitizer + def self.sanitize(content) + regexp = URI::Parser.new.make_regexp(['http', 'https', 'ssh', 'git']) + + content.gsub(regexp) { |url| new(url).masked_url } + end + def initialize(url, credentials: nil) - @url = URI.parse(URI.encode(url)) + @url = Addressable::URI.parse(url) @credentials = credentials end @@ -9,6 +15,13 @@ module Gitlab @sanitized_url ||= safe_url.to_s end + def masked_url + url = @url.dup + url.password = "*****" unless url.password.nil? + url.user = "*****" unless url.user.nil? + url.to_s + end + def credentials @credentials ||= { user: @url.user, password: @url.password } end diff --git a/lib/gitlab/visibility_level.rb b/lib/gitlab/visibility_level.rb index a1ee1cba21..9462f3368e 100644 --- a/lib/gitlab/visibility_level.rb +++ b/lib/gitlab/visibility_level.rb @@ -32,6 +32,13 @@ module Gitlab } end + def highest_allowed_level + restricted_levels = current_application_settings.restricted_visibility_levels + + allowed_levels = self.values - restricted_levels + allowed_levels.max || PRIVATE + end + def allowed_for?(user, level) user.is_admin? || allowed_level?(level.to_i) end diff --git a/lib/json_web_token/rsa_token.rb b/lib/json_web_token/rsa_token.rb new file mode 100644 index 0000000000..d6d6af7089 --- /dev/null +++ b/lib/json_web_token/rsa_token.rb @@ -0,0 +1,42 @@ +module JSONWebToken + class RSAToken < Token + attr_reader :key_file + + def initialize(key_file) + super() + @key_file = key_file + end + + def encoded + headers = { + kid: kid + } + JWT.encode(payload, key, 'RS256', headers) + end + + private + + def key_data + @key_data ||= File.read(key_file) + end + + def key + @key ||= OpenSSL::PKey::RSA.new(key_data) + end + + def public_key + key.public_key + end + + def kid + # calculate sha256 from DER encoded ASN1 + kid = Digest::SHA256.digest(public_key.to_der) + + # we encode only 30 bytes with base32 + kid = Base32.encode(kid[0..29]) + + # insert colon every 4 characters + kid.scan(/.{4}/).join(':') + end + end +end diff --git a/lib/json_web_token/token.rb b/lib/json_web_token/token.rb new file mode 100644 index 0000000000..5b67715b0b --- /dev/null +++ b/lib/json_web_token/token.rb @@ -0,0 +1,46 @@ +module JSONWebToken + class Token + attr_accessor :issuer, :subject, :audience, :id + attr_accessor :issued_at, :not_before, :expire_time + + def initialize + @id = SecureRandom.uuid + @issued_at = Time.now + # we give a few seconds for time shift + @not_before = issued_at - 5.seconds + # default 60 seconds should be more than enough for this authentication token + @expire_time = issued_at + 1.minute + @custom_payload = {} + end + + def [](key) + @custom_payload[key] + end + + def []=(key, value) + @custom_payload[key] = value + end + + def encoded + raise NotImplementedError + end + + def payload + @custom_payload.merge(default_payload) + end + + private + + def default_payload + { + jti: id, + aud: audience, + sub: subject, + iss: issuer, + iat: issued_at.to_i, + nbf: not_before.to_i, + exp: expire_time.to_i + }.compact + end + end +end diff --git a/lib/support/nginx/registry-ssl b/lib/support/nginx/registry-ssl new file mode 100644 index 0000000000..92511e2686 --- /dev/null +++ b/lib/support/nginx/registry-ssl @@ -0,0 +1,53 @@ +## Lines starting with two hashes (##) are comments with information. +## Lines starting with one hash (#) are configuration parameters that can be uncommented. +## +################################### +## configuration ## +################################### + +## Redirects all HTTP traffic to the HTTPS host +server { + listen *:80; + server_name registry.gitlab.example.com; + server_tokens off; ## Don't show the nginx version number, a security best practice + return 301 https://$http_host:$request_uri; + access_log /var/log/nginx/gitlab_registry_access.log gitlab_access; + error_log /var/log/nginx/gitlab_registry_error.log; +} + +server { + # If a different port is specified in https://gitlab.com/gitlab-org/gitlab-ce/blob/8-8-stable/config/gitlab.yml.example#L182, + # it should be declared here as well + listen *:443 ssl http2; + server_name registry.gitlab.example.com; + server_tokens off; ## Don't show the nginx version number, a security best practice + + client_max_body_size 0; + chunked_transfer_encoding on; + + ## Strong SSL Security + ## https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html & https://cipherli.st/ + ssl on; + ssl_certificate /etc/gitlab/ssl/registry.gitlab.example.com.crt + ssl_certificate_key /etc/gitlab/ssl/registry.gitlab.example.com.key + + ssl_ciphers 'ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4'; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_prefer_server_ciphers on; + ssl_session_cache builtin:1000 shared:SSL:10m; + ssl_session_timeout 5m; + + access_log /var/log/gitlab/nginx/gitlab_registry_access.log gitlab_access; + error_log /var/log/gitlab/nginx/gitlab_registry_error.log; + + location / { + proxy_set_header Host $http_host; # required for docker client's sake + proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_read_timeout 900; + + proxy_pass http://localhost:5000; + } + +} diff --git a/lib/tasks/auto_annotate_models.rake b/lib/tasks/auto_annotate_models.rake deleted file mode 100644 index 16bad4bd2b..0000000000 --- a/lib/tasks/auto_annotate_models.rake +++ /dev/null @@ -1,44 +0,0 @@ -if Rails.env.development? - task :set_annotation_options do - # You can override any of these by setting an environment variable of the - # same name. - Annotate.set_defaults( - 'routes' => 'false', - 'position_in_routes' => 'before', - 'position_in_class' => 'before', - 'position_in_test' => 'before', - 'position_in_fixture' => 'before', - 'position_in_factory' => 'before', - 'position_in_serializer' => 'before', - 'show_foreign_keys' => 'true', - 'show_indexes' => 'false', - 'simple_indexes' => 'false', - 'model_dir' => 'app/models', - 'root_dir' => '', - 'include_version' => 'false', - 'require' => '', - 'exclude_tests' => 'true', - 'exclude_fixtures' => 'true', - 'exclude_factories' => 'true', - 'exclude_serializers' => 'true', - 'exclude_scaffolds' => 'true', - 'exclude_controllers' => 'true', - 'exclude_helpers' => 'true', - 'ignore_model_sub_dir' => 'false', - 'ignore_columns' => nil, - 'ignore_unknown_models' => 'false', - 'hide_limit_column_types' => 'integer,boolean', - 'skip_on_db_migrate' => 'false', - 'format_bare' => 'true', - 'format_rdoc' => 'false', - 'format_markdown' => 'false', - 'sort' => 'false', - 'force' => 'false', - 'trace' => 'false', - 'wrapper_open' => nil, - 'wrapper_close' => nil, - ) - end - - Annotate.load_tasks -end diff --git a/lib/tasks/gitlab/backup.rake b/lib/tasks/gitlab/backup.rake index 402bb338f2..596eaca6d0 100644 --- a/lib/tasks/gitlab/backup.rake +++ b/lib/tasks/gitlab/backup.rake @@ -14,6 +14,7 @@ namespace :gitlab do Rake::Task["gitlab:backup:builds:create"].invoke Rake::Task["gitlab:backup:artifacts:create"].invoke Rake::Task["gitlab:backup:lfs:create"].invoke + Rake::Task["gitlab:backup:registry:create"].invoke backup = Backup::Manager.new backup.pack @@ -54,6 +55,7 @@ namespace :gitlab do Rake::Task['gitlab:backup:builds:restore'].invoke unless backup.skipped?('builds') Rake::Task['gitlab:backup:artifacts:restore'].invoke unless backup.skipped?('artifacts') Rake::Task['gitlab:backup:lfs:restore'].invoke unless backup.skipped?('lfs') + Rake::Task['gitlab:backup:registry:restore'].invoke unless backup.skipped?('registry') Rake::Task['gitlab:shell:setup'].invoke backup.cleanup @@ -173,6 +175,33 @@ namespace :gitlab do end end + namespace :registry do + task create: :environment do + $progress.puts "Dumping container registry images ... ".blue + + if Gitlab.config.registry.enabled + if ENV["SKIP"] && ENV["SKIP"].include?("registry") + $progress.puts "[SKIPPED]".cyan + else + Backup::Registry.new.dump + $progress.puts "done".green + end + else + $progress.puts "[DISABLED]".cyan + end + end + + task restore: :environment do + $progress.puts "Restoring container registry images ... ".blue + if Gitlab.config.registry.enabled + Backup::Registry.new.restore + $progress.puts "done".green + else + $progress.puts "[DISABLED]".cyan + end + end + end + def configure_cron_mode if ENV['CRON'] # We need an object we can say 'puts' and 'print' to; let's use a diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index effb8eb600..fad89c7376 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -303,7 +303,7 @@ namespace :gitlab do else puts "no".red try_fixing_it( - "sudo find #{upload_path} -type d -not -path #{upload_path} -exec chmod 0700 {} \\;" + "sudo chmod 700 #{upload_path}" ) for_more_information( see_installation_guide_section "GitLab" diff --git a/lib/tasks/gitlab/db.rake b/lib/tasks/gitlab/db.rake index 1c706dc11b..86f5d65f12 100644 --- a/lib/tasks/gitlab/db.rake +++ b/lib/tasks/gitlab/db.rake @@ -29,10 +29,22 @@ namespace :gitlab do tables.delete 'schema_migrations' # Truncate schema_migrations to ensure migrations re-run connection.execute('TRUNCATE schema_migrations') + # Drop tables with cascade to avoid dependent table errors # PG: http://www.postgresql.org/docs/current/static/ddl-depend.html # MySQL: http://dev.mysql.com/doc/refman/5.7/en/drop-table.html - tables.each { |t| connection.execute("DROP TABLE #{t} CASCADE") } + # Add `IF EXISTS` because cascade could have already deleted a table. + tables.each { |t| connection.execute("DROP TABLE IF EXISTS #{t} CASCADE") } + end + + desc 'Configures the database by running migrate, or by loading the schema and seeding if needed' + task configure: :environment do + if ActiveRecord::Base.connection.tables.any? + Rake::Task['db:migrate'].invoke + else + Rake::Task['db:schema:load'].invoke + Rake::Task['db:seed_fu'].invoke + end end end end diff --git a/lib/tasks/gitlab/update_gitignore.rake b/lib/tasks/gitlab/update_gitignore.rake new file mode 100644 index 0000000000..84aa312002 --- /dev/null +++ b/lib/tasks/gitlab/update_gitignore.rake @@ -0,0 +1,46 @@ +namespace :gitlab do + desc "GitLab | Update gitignore" + task :update_gitignore do + unless clone_gitignores + puts "Cloning the gitignores failed".red + return + end + + remove_unneeded_files(gitignore_directory) + remove_unneeded_files(global_directory) + + puts "Done".green + end + + def clone_gitignores + FileUtils.rm_rf(gitignore_directory) if Dir.exist?(gitignore_directory) + FileUtils.cd vendor_directory + + system('git clone --depth=1 --branch=master https://github.com/github/gitignore.git') + end + + # Retain only certain files: + # - The LICENSE, because we have to + # - The sub dir global + # - The gitignores themself + # - Dir.entires returns also the entries '.' and '..' + def remove_unneeded_files(path) + Dir.foreach(path) do |file| + FileUtils.rm_rf(File.join(path, file)) unless file =~ /(\.{1,2}|LICENSE|Global|\.gitignore)\z/ + end + end + + private + + def vendor_directory + Rails.root.join('vendor') + end + + def gitignore_directory + File.join(vendor_directory, 'gitignore') + end + + def global_directory + File.join(gitignore_directory, 'Global') + end +end diff --git a/lib/tasks/rubocop.rake b/lib/tasks/rubocop.rake index ddfaf5d51f..78ffccc9d0 100644 --- a/lib/tasks/rubocop.rake +++ b/lib/tasks/rubocop.rake @@ -1,4 +1,5 @@ unless Rails.env.production? require 'rubocop/rake_task' + RuboCop::RakeTask.new end diff --git a/public/robots.txt b/public/robots.txt index 4f616c7f4c..334f4c0353 100644 --- a/public/robots.txt +++ b/public/robots.txt @@ -65,3 +65,4 @@ Disallow: /*/*/deploy_keys Disallow: /*/*/hooks Disallow: /*/*/services Disallow: /*/*/protected_branches +Disallow: /*/*/uploads/ diff --git a/shared/registry/.gitkeep b/shared/registry/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spec/config/mail_room_spec.rb b/spec/config/mail_room_spec.rb index 462afb24f0..6fad7e2b9e 100644 --- a/spec/config/mail_room_spec.rb +++ b/spec/config/mail_room_spec.rb @@ -43,7 +43,7 @@ describe "mail_room.yml" do redis_config_file = Rails.root.join('config', 'resque.yml') redis_url = - if File.exists?(redis_config_file) + if File.exist?(redis_config_file) YAML.load_file(redis_config_file)[Rails.env] else "redis://localhost:6379" diff --git a/spec/controllers/admin/projects_controller_spec.rb b/spec/controllers/admin/projects_controller_spec.rb index 2ba0d48919..4cb8b8da15 100644 --- a/spec/controllers/admin/projects_controller_spec.rb +++ b/spec/controllers/admin/projects_controller_spec.rb @@ -17,7 +17,7 @@ describe Admin::ProjectsController do it 'does not retrieve the project' do get :index, visibility_levels: [Gitlab::VisibilityLevel::INTERNAL] - expect(response.body).to_not match(project.name) + expect(response.body).not_to match(project.name) end end end diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb index ce2a62ae1f..6caf37ddc2 100644 --- a/spec/controllers/admin/users_controller_spec.rb +++ b/spec/controllers/admin/users_controller_spec.rb @@ -114,6 +114,82 @@ describe Admin::UsersController do end end + describe 'POST update' do + context 'when the password has changed' do + def update_password(user, password, password_confirmation = nil) + params = { + id: user.to_param, + user: { + password: password, + password_confirmation: password_confirmation || password + } + } + + post :update, params + end + + context 'when the new password is valid' do + it 'redirects to the user' do + update_password(user, 'AValidPassword1') + + expect(response).to redirect_to(admin_user_path(user)) + end + + it 'updates the password' do + update_password(user, 'AValidPassword1') + + expect { user.reload }.to change { user.encrypted_password } + end + + it 'sets the new password to expire immediately' do + update_password(user, 'AValidPassword1') + + expect { user.reload }.to change { user.password_expires_at }.to(a_value <= Time.now) + end + end + + context 'when the new password is invalid' do + it 'shows the edit page again' do + update_password(user, 'invalid') + + expect(response).to render_template(:edit) + end + + it 'returns the error message' do + update_password(user, 'invalid') + + expect(assigns[:user].errors).to contain_exactly(a_string_matching(/too short/)) + end + + it 'does not update the password' do + update_password(user, 'invalid') + + expect { user.reload }.not_to change { user.encrypted_password } + end + end + + context 'when the new password does not match the password confirmation' do + it 'shows the edit page again' do + update_password(user, 'AValidPassword1', 'AValidPassword2') + + expect(response).to render_template(:edit) + end + + it 'returns the error message' do + update_password(user, 'AValidPassword1', 'AValidPassword2') + + expect(assigns[:user].errors).to contain_exactly(a_string_matching(/doesn't match/)) + end + + it 'does not update the password' do + update_password(user, 'AValidPassword1', 'AValidPassword2') + + expect { user.reload }.not_to change { user.encrypted_password } + end + end + end + end + describe "POST impersonate" do context "when the user is blocked" do before do diff --git a/spec/controllers/health_check_controller_spec.rb b/spec/controllers/health_check_controller_spec.rb new file mode 100644 index 0000000000..0d8a68bb51 --- /dev/null +++ b/spec/controllers/health_check_controller_spec.rb @@ -0,0 +1,105 @@ +require 'spec_helper' + +describe HealthCheckController do + let(:token) { current_application_settings.health_check_access_token } + let(:json_response) { JSON.parse(response.body) } + let(:xml_response) { Hash.from_xml(response.body)['hash'] } + + describe 'GET #index' do + context 'when services are up but NO access token' do + it 'returns a not found page' do + get :index + expect(response).to be_not_found + end + end + + context 'when services are up and an access token is provided' do + it 'supports passing the token in the header' do + request.headers['TOKEN'] = token + get :index + expect(response).to be_success + expect(response.content_type).to eq 'text/plain' + end + + it 'supports successful plaintest response' do + get :index, token: token + expect(response).to be_success + expect(response.content_type).to eq 'text/plain' + end + + it 'supports successful json response' do + get :index, token: token, format: :json + expect(response).to be_success + expect(response.content_type).to eq 'application/json' + expect(json_response['healthy']).to be true + end + + it 'supports successful xml response' do + get :index, token: token, format: :xml + expect(response).to be_success + expect(response.content_type).to eq 'application/xml' + expect(xml_response['healthy']).to be true + end + + it 'supports successful responses for specific checks' do + get :index, token: token, checks: 'email', format: :json + expect(response).to be_success + expect(response.content_type).to eq 'application/json' + expect(json_response['healthy']).to be true + end + end + + context 'when a service is down but NO access token' do + it 'returns a not found page' do + get :index + expect(response).to be_not_found + end + end + + context 'when a service is down and an access token is provided' do + before do + allow(HealthCheck::Utils).to receive(:process_checks).with('standard').and_return('The server is on fire') + allow(HealthCheck::Utils).to receive(:process_checks).with('email').and_return('Email is on fire') + end + + it 'supports passing the token in the header' do + request.headers['TOKEN'] = token + get :index + expect(response.status).to eq(500) + expect(response.content_type).to eq 'text/plain' + expect(response.body).to include('The server is on fire') + end + + it 'supports failure plaintest response' do + get :index, token: token + expect(response.status).to eq(500) + expect(response.content_type).to eq 'text/plain' + expect(response.body).to include('The server is on fire') + end + + it 'supports failure json response' do + get :index, token: token, format: :json + expect(response.status).to eq(500) + expect(response.content_type).to eq 'application/json' + expect(json_response['healthy']).to be false + expect(json_response['message']).to include('The server is on fire') + end + + it 'supports failure xml response' do + get :index, token: token, format: :xml + expect(response.status).to eq(500) + expect(response.content_type).to eq 'application/xml' + expect(xml_response['healthy']).to be false + expect(xml_response['message']).to include('The server is on fire') + end + + it 'supports failure responses for specific checks' do + get :index, token: token, checks: 'email', format: :json + expect(response.status).to eq(500) + expect(response.content_type).to eq 'application/json' + expect(json_response['healthy']).to be false + expect(json_response['message']).to include('Email is on fire') + end + end + end +end diff --git a/spec/controllers/projects/branches_controller_spec.rb b/spec/controllers/projects/branches_controller_spec.rb index 8ad7347211..c4b4a888b4 100644 --- a/spec/controllers/projects/branches_controller_spec.rb +++ b/spec/controllers/projects/branches_controller_spec.rb @@ -122,27 +122,23 @@ describe Projects::BranchesController do let(:branch) { "feature" } it { expect(response.status).to eq(200) } - it { expect(subject).to render_template('destroy') } end context "valid branch name with unencoded slashes" do let(:branch) { "improve/awesome" } it { expect(response.status).to eq(200) } - it { expect(subject).to render_template('destroy') } end context "valid branch name with encoded slashes" do let(:branch) { "improve%2Fawesome" } it { expect(response.status).to eq(200) } - it { expect(subject).to render_template('destroy') } end context "invalid branch name, valid ref" do let(:branch) { "no-branch" } it { expect(response.status).to eq(404) } - it { expect(subject).to render_template('destroy') } end end end diff --git a/spec/controllers/projects/compare_controller_spec.rb b/spec/controllers/projects/compare_controller_spec.rb index 788a609ee4..4018dac95a 100644 --- a/spec/controllers/projects/compare_controller_spec.rb +++ b/spec/controllers/projects/compare_controller_spec.rb @@ -19,7 +19,7 @@ describe Projects::CompareController do to: ref_to) expect(response).to be_success - expect(assigns(:diffs).first).to_not be_nil + expect(assigns(:diffs).first).not_to be_nil expect(assigns(:commits).length).to be >= 1 end @@ -32,7 +32,7 @@ describe Projects::CompareController do w: 1) expect(response).to be_success - expect(assigns(:diffs).first).to_not be_nil + expect(assigns(:diffs).first).not_to be_nil expect(assigns(:commits).length).to be >= 1 # without whitespace option, there are more than 2 diff_splits diff_splits = assigns(:diffs).first.diff.split("\n") diff --git a/spec/controllers/projects/group_links_controller_spec.rb b/spec/controllers/projects/group_links_controller_spec.rb index 40bd83af86..fbe8758dda 100644 --- a/spec/controllers/projects/group_links_controller_spec.rb +++ b/spec/controllers/projects/group_links_controller_spec.rb @@ -28,7 +28,7 @@ describe Projects::GroupLinksController do expect(group.shared_projects).to include project end - it 'redirects to project group links page'do + it 'redirects to project group links page' do expect(response).to redirect_to( namespace_project_group_links_path(project.namespace, project) ) @@ -43,7 +43,7 @@ describe Projects::GroupLinksController do end it 'does not share project with that group' do - expect(group.shared_projects).to_not include project + expect(group.shared_projects).not_to include project end end end diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb index 2b2ad3b941..c469480b08 100644 --- a/spec/controllers/projects/issues_controller_spec.rb +++ b/spec/controllers/projects/issues_controller_spec.rb @@ -56,7 +56,7 @@ describe Projects::IssuesController do move_issue expect(response).to have_http_status :found - expect(another_project.issues).to_not be_empty + expect(another_project.issues).not_to be_empty end end diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index c0a1f45195..4f621a43d7 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -63,7 +63,7 @@ describe Projects::MergeRequestsController do id: merge_request.iid, format: format) - expect(response.body).to eq((merge_request.send(:"to_#{format}")).to_s) + expect(response.body).to eq(merge_request.send(:"to_#{format}").to_s) end it "should not escape Html" do diff --git a/spec/controllers/projects/notification_settings_controller_spec.rb b/spec/controllers/projects/notification_settings_controller_spec.rb index 4908b54564..c5d17d97ec 100644 --- a/spec/controllers/projects/notification_settings_controller_spec.rb +++ b/spec/controllers/projects/notification_settings_controller_spec.rb @@ -34,5 +34,19 @@ describe Projects::NotificationSettingsController do expect(response.status).to eq 200 end end + + context 'not authorized' do + let(:private_project) { create(:project, :private) } + before { sign_in(user) } + + it 'returns 404' do + put :update, + namespace_id: private_project.namespace.to_param, + project_id: private_project.to_param, + notification_setting: { level: :participating } + + expect(response.status).to eq(404) + 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 ed64e7cf9a..750fbecdd0 100644 --- a/spec/controllers/projects/project_members_controller_spec.rb +++ b/spec/controllers/projects/project_members_controller_spec.rb @@ -38,7 +38,7 @@ describe Projects::ProjectMembersController do include_context 'import applied' it 'does not import team members' do - expect(project.team_members).to_not include member + expect(project.team_members).not_to include member end it 'responds with not found' do diff --git a/spec/controllers/projects/raw_controller_spec.rb b/spec/controllers/projects/raw_controller_spec.rb index 1caa476d37..fb29274c68 100644 --- a/spec/controllers/projects/raw_controller_spec.rb +++ b/spec/controllers/projects/raw_controller_spec.rb @@ -42,7 +42,7 @@ describe Projects::RawController do before do public_project.lfs_objects << lfs_object allow_any_instance_of(LfsObjectUploader).to receive(:exists?).and_return(true) - allow(controller).to receive(:send_file) { controller.render nothing: true } + allow(controller).to receive(:send_file) { controller.head :ok } end it 'serves the file' do diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index 069cd917e5..fba545560c 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -8,6 +8,40 @@ describe ProjectsController do let(:txt) { fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain') } describe "GET show" do + context "user not project member" do + before { sign_in(user) } + + context "user does not have access to project" do + let(:private_project) { create(:project, :private) } + + it "does not initialize notification setting" do + get :show, namespace_id: private_project.namespace.path, id: private_project.path + expect(assigns(:notification_setting)).to be_nil + end + end + + context "user has access to project" do + context "and does not have notification setting" do + it "initializes notification as disabled" do + get :show, namespace_id: public_project.namespace.path, id: public_project.path + expect(assigns(:notification_setting).level).to eq("global") + end + end + + context "and has notification setting" do + before do + setting = user.notification_settings_for(public_project) + setting.level = :watch + setting.save + end + + it "shows current notification setting" do + get :show, namespace_id: public_project.namespace.path, id: public_project.path + expect(assigns(:notification_setting).level).to eq("watch") + end + end + end + end context "rendering default project view" do render_views @@ -81,6 +115,17 @@ describe ProjectsController do expect(public_project_with_dot_atom).not_to be_valid end end + + context 'when the project is pending deletions' do + it 'renders a 404 error' do + project = create(:project, pending_delete: true) + sign_in(user) + + get :show, namespace_id: project.namespace.path, id: project.path + + expect(response.status).to eq 404 + end + end end describe "#update" do diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb new file mode 100644 index 0000000000..209fa37d97 --- /dev/null +++ b/spec/controllers/registrations_controller_spec.rb @@ -0,0 +1,33 @@ +require 'spec_helper' + +describe RegistrationsController do + describe '#create' do + around(:each) do |example| + perform_enqueued_jobs do + example.run + end + end + + let(:user_params) { { user: { name: "new_user", username: "new_username", email: "new@user.com", password: "Any_password" } } } + + context 'when sending email confirmation' do + before { allow_any_instance_of(ApplicationSetting).to receive(:send_user_confirmation_email).and_return(false) } + + it 'logs user in directly' do + post(:create, user_params) + expect(ActionMailer::Base.deliveries.last).to be_nil + expect(subject.current_user).not_to be_nil + end + end + + context 'when not sending email confirmation' do + before { allow_any_instance_of(ApplicationSetting).to receive(:send_user_confirmation_email).and_return(true) } + + it 'does not authenticate user and sends confirmation email' do + post(:create, user_params) + expect(ActionMailer::Base.deliveries.last.to.first).to eq(user_params[:user][:email]) + expect(subject.current_user).to be_nil + end + end + end +end diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb index 83cc8ec6d2..5dc8724fb5 100644 --- a/spec/controllers/sessions_controller_spec.rb +++ b/spec/controllers/sessions_controller_spec.rb @@ -12,7 +12,7 @@ describe SessionsController do post(:create, user: { login: 'invalid', password: 'invalid' }) expect(response) - .to set_flash.now[:alert].to /Invalid login or password/ + .to set_flash.now[:alert].to /Invalid Login or password/ end end @@ -35,6 +35,27 @@ describe SessionsController do post(:create, { user: user_params }, { otp_user_id: user.id }) end + context 'remember_me field' do + it 'sets a remember_user_token cookie when enabled' do + allow(controller).to receive(:find_user).and_return(user) + expect(controller). + to receive(:remember_me).with(user).and_call_original + + authenticate_2fa(remember_me: '1', otp_attempt: user.current_otp) + + expect(response.cookies['remember_user_token']).to be_present + end + + it 'does nothing when disabled' do + allow(controller).to receive(:find_user).and_return(user) + expect(controller).not_to receive(:remember_me) + + authenticate_2fa(remember_me: '0', otp_attempt: user.current_otp) + + expect(response.cookies['remember_user_token']).to be_nil + end + end + ## # See #14900 issue # @@ -47,7 +68,7 @@ describe SessionsController do authenticate_2fa(login: another_user.username, otp_attempt: another_user.current_otp) - expect(subject.current_user).to_not eq another_user + expect(subject.current_user).not_to eq another_user end end @@ -56,7 +77,7 @@ describe SessionsController do authenticate_2fa(login: another_user.username, otp_attempt: 'invalid') - expect(subject.current_user).to_not eq another_user + expect(subject.current_user).not_to eq another_user end end @@ -73,7 +94,7 @@ describe SessionsController do before { authenticate_2fa(otp_attempt: 'invalid') } it 'does not authenticate' do - expect(subject.current_user).to_not eq user + expect(subject.current_user).not_to eq user end it 'warns about invalid OTP code' do diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index 8045c8b940..c61ec17466 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -112,4 +112,26 @@ describe UsersController do expect(response).to render_template('calendar_activities') end end + + describe 'GET #snippets' do + before do + sign_in(user) + end + + context 'format html' do + it 'renders snippets page' do + get :snippets, username: user.username + expect(response.status).to eq(200) + expect(response).to render_template('show') + end + end + + context 'format json' do + it 'response with snippets json data' do + get :snippets, username: user.username, format: :json + expect(response.status).to eq(200) + expect(JSON.parse(response.body)).to have_key('html') + end + end + end end diff --git a/spec/factories/abuse_reports.rb b/spec/factories/abuse_reports.rb index d0e8c77851..8f6422a782 100644 --- a/spec/factories/abuse_reports.rb +++ b/spec/factories/abuse_reports.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: abuse_reports -# -# id :integer not null, primary key -# reporter_id :integer -# user_id :integer -# message :text -# created_at :datetime -# updated_at :datetime -# - FactoryGirl.define do factory :abuse_report do reporter factory: :user diff --git a/spec/factories/broadcast_messages.rb b/spec/factories/broadcast_messages.rb index c80e736655..efe9803b1a 100644 --- a/spec/factories/broadcast_messages.rb +++ b/spec/factories/broadcast_messages.rb @@ -1,17 +1,3 @@ -# == Schema Information -# -# Table name: broadcast_messages -# -# id :integer not null, primary key -# message :text not null -# starts_at :datetime -# ends_at :datetime -# created_at :datetime -# updated_at :datetime -# color :string(255) -# font :string(255) -# - FactoryGirl.define do factory :broadcast_message do message "MyText" diff --git a/spec/factories/forked_project_links.rb b/spec/factories/forked_project_links.rb index 19a54946fe..b16c1272e6 100644 --- a/spec/factories/forked_project_links.rb +++ b/spec/factories/forked_project_links.rb @@ -1,14 +1,3 @@ -# == Schema Information -# -# Table name: forked_project_links -# -# id :integer not null, primary key -# forked_to_project_id :integer not null -# forked_from_project_id :integer not null -# created_at :datetime -# updated_at :datetime -# - FactoryGirl.define do factory :forked_project_link do association :forked_to_project, factory: :project diff --git a/spec/factories/label_links.rb b/spec/factories/label_links.rb index 2939d4307c..3580174e87 100644 --- a/spec/factories/label_links.rb +++ b/spec/factories/label_links.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: label_links -# -# id :integer not null, primary key -# label_id :integer -# target_id :integer -# target_type :string(255) -# created_at :datetime -# updated_at :datetime -# - FactoryGirl.define do factory :label_link do label diff --git a/spec/factories/labels.rb b/spec/factories/labels.rb index ea2be8928d..eb48909985 100644 --- a/spec/factories/labels.rb +++ b/spec/factories/labels.rb @@ -1,16 +1,3 @@ -# == Schema Information -# -# Table name: labels -# -# id :integer not null, primary key -# title :string(255) -# color :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# template :boolean default(FALSE) -# - FactoryGirl.define do factory :label do sequence(:title) { |n| "label#{n}" } diff --git a/spec/factories/lfs_objects.rb b/spec/factories/lfs_objects.rb index 327858ce43..a81645acd2 100644 --- a/spec/factories/lfs_objects.rb +++ b/spec/factories/lfs_objects.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: lfs_objects -# -# id :integer not null, primary key -# oid :string(255) not null -# size :integer not null -# created_at :datetime -# updated_at :datetime -# file :string(255) -# - include ActionDispatch::TestProcess FactoryGirl.define do diff --git a/spec/factories/lfs_objects_projects.rb b/spec/factories/lfs_objects_projects.rb index 50b45843c9..1ed0355c8e 100644 --- a/spec/factories/lfs_objects_projects.rb +++ b/spec/factories/lfs_objects_projects.rb @@ -1,14 +1,3 @@ -# == Schema Information -# -# Table name: lfs_objects_projects -# -# id :integer not null, primary key -# lfs_object_id :integer not null -# project_id :integer not null -# created_at :datetime -# updated_at :datetime -# - FactoryGirl.define do factory :lfs_objects_project do lfs_object diff --git a/spec/factories/merge_requests.rb b/spec/factories/merge_requests.rb index e281e2f227..c6a08d78b7 100644 --- a/spec/factories/merge_requests.rb +++ b/spec/factories/merge_requests.rb @@ -1,32 +1,3 @@ -# == Schema Information -# -# Table name: merge_requests -# -# id :integer not null, primary key -# target_branch :string(255) not null -# source_branch :string(255) not null -# source_project_id :integer not null -# author_id :integer -# assignee_id :integer -# title :string(255) -# created_at :datetime -# updated_at :datetime -# milestone_id :integer -# state :string(255) -# merge_status :string(255) -# target_project_id :integer not null -# iid :integer -# description :text -# position :integer default(0) -# locked_at :datetime -# updated_by_id :integer -# merge_error :string(255) -# merge_params :text -# merge_when_build_succeeds :boolean default(FALSE), not null -# merge_user_id :integer -# merge_commit_sha :string -# - FactoryGirl.define do factory :merge_request do title diff --git a/spec/factories/notes.rb b/spec/factories/notes.rb index e5dcb15901..c32e205ee6 100644 --- a/spec/factories/notes.rb +++ b/spec/factories/notes.rb @@ -1,24 +1,3 @@ -# == Schema Information -# -# Table name: notes -# -# id :integer not null, primary key -# note :text -# noteable_type :string(255) -# author_id :integer -# created_at :datetime -# updated_at :datetime -# project_id :integer -# attachment :string(255) -# line_code :string(255) -# commit_id :string(255) -# noteable_id :integer -# system :boolean default(FALSE), not null -# st_diff :text -# updated_by_id :integer -# is_award :boolean default(FALSE), not null -# - require_relative '../support/repo_helpers' include ActionDispatch::TestProcess @@ -28,41 +7,39 @@ FactoryGirl.define do project note "Note" author + on_issue factory :note_on_commit, traits: [:on_commit] - factory :note_on_commit_diff, traits: [:on_commit, :on_diff] + factory :note_on_commit_diff, traits: [:on_commit, :on_diff], class: LegacyDiffNote factory :note_on_issue, traits: [:on_issue], aliases: [:votable_note] factory :note_on_merge_request, traits: [:on_merge_request] - factory :note_on_merge_request_diff, traits: [:on_merge_request, :on_diff] + factory :note_on_merge_request_diff, traits: [:on_merge_request, :on_diff], class: LegacyDiffNote factory :note_on_project_snippet, traits: [:on_project_snippet] factory :system_note, traits: [:system] factory :downvote_note, traits: [:award, :downvote] factory :upvote_note, traits: [:award, :upvote] trait :on_commit do - project + noteable nil + noteable_id nil + noteable_type 'Commit' commit_id RepoHelpers.sample_commit.id - noteable_type "Commit" end trait :on_diff do line_code "0_184_184" end - trait :on_merge_request do - project - noteable_id 1 - noteable_type "MergeRequest" + trait :on_issue do + noteable { create(:issue, project: project) } end - trait :on_issue do - noteable_id 1 - noteable_type "Issue" + trait :on_merge_request do + noteable { create(:merge_request, source_project: project) } end trait :on_project_snippet do - noteable_id 1 - noteable_type "Snippet" + noteable { create(:snippet, project: project) } end trait :system do diff --git a/spec/factories/oauth_access_tokens.rb b/spec/factories/oauth_access_tokens.rb index 7700b15d53..ccf02d0719 100644 --- a/spec/factories/oauth_access_tokens.rb +++ b/spec/factories/oauth_access_tokens.rb @@ -1,18 +1,3 @@ -# == Schema Information -# -# Table name: oauth_access_tokens -# -# id :integer not null, primary key -# resource_owner_id :integer -# application_id :integer -# token :string not null -# refresh_token :string -# expires_in :integer -# revoked_at :datetime -# created_at :datetime not null -# scopes :string -# - FactoryGirl.define do factory :oauth_access_token do resource_owner diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index ecd0e44dd6..da8d97c9f8 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -1,42 +1,3 @@ -# == Schema Information -# -# Table name: projects -# -# id :integer not null, primary key -# name :string(255) -# path :string(255) -# description :text -# created_at :datetime -# updated_at :datetime -# creator_id :integer -# issues_enabled :boolean default(TRUE), not null -# merge_requests_enabled :boolean default(TRUE), not null -# wiki_enabled :boolean default(TRUE), not null -# namespace_id :integer -# issues_tracker :string(255) default("gitlab"), not null -# issues_tracker_id :string(255) -# snippets_enabled :boolean default(TRUE), not null -# last_activity_at :datetime -# import_url :string(255) -# visibility_level :integer default(0), not null -# archived :boolean default(FALSE), not null -# avatar :string(255) -# import_status :string(255) -# repository_size :float default(0.0) -# star_count :integer default(0), not null -# import_type :string(255) -# import_source :string(255) -# commit_count :integer default(0) -# import_error :text -# ci_id :integer -# builds_enabled :boolean default(TRUE), not null -# shared_runners_enabled :boolean default(TRUE), not null -# runners_token :string -# build_coverage_regex :string -# build_allow_git_fetch :boolean default(TRUE), not null -# build_timeout :integer default(3600), not null -# - FactoryGirl.define do # Project without repository # @@ -60,6 +21,12 @@ FactoryGirl.define do trait :private do visibility_level Gitlab::VisibilityLevel::PRIVATE end + + trait :empty_repo do + after(:create) do |project| + project.create_repository + end + end end # Project with empty repository @@ -67,9 +34,7 @@ FactoryGirl.define do # This is a case when you just created a project # but not pushed any code there yet factory :project_empty_repo, parent: :empty_project do - after :create do |project| - project.create_repository - end + empty_repo end # Project with test repository diff --git a/spec/factories/releases.rb b/spec/factories/releases.rb index 7f331c3725..74497dc82c 100644 --- a/spec/factories/releases.rb +++ b/spec/factories/releases.rb @@ -1,15 +1,3 @@ -# == Schema Information -# -# Table name: releases -# -# id :integer not null, primary key -# tag :string(255) -# description :text -# project_id :integer -# created_at :datetime -# updated_at :datetime -# - FactoryGirl.define do factory :release do tag "v1.1.0" diff --git a/spec/factories/todos.rb b/spec/factories/todos.rb index 7ae06c2784..f426e27afe 100644 --- a/spec/factories/todos.rb +++ b/spec/factories/todos.rb @@ -1,21 +1,3 @@ -# == Schema Information -# -# Table name: todos -# -# id :integer not null, primary key -# user_id :integer not null -# project_id :integer not null -# target_id :integer -# target_type :string not null -# author_id :integer -# action :integer not null -# state :string not null -# created_at :datetime -# updated_at :datetime -# note_id :integer -# commit_id :string -# - FactoryGirl.define do factory :todo do project @@ -36,5 +18,9 @@ FactoryGirl.define do commit_id RepoHelpers.sample_commit.id target_type "Commit" end + + trait :build_failed do + action { Todo::BUILD_FAILED } + end end end diff --git a/spec/factories_spec.rb b/spec/factories_spec.rb index 62de081661..675d9bd18b 100644 --- a/spec/factories_spec.rb +++ b/spec/factories_spec.rb @@ -5,8 +5,8 @@ describe 'factories' do describe "#{factory.name} factory" do let(:entity) { build(factory.name) } - it 'does not raise error when created 'do - expect { entity }.to_not raise_error + it 'does not raise error when created' do + expect { entity }.not_to raise_error end it 'should be valid', if: factory.build_class < ActiveRecord::Base do diff --git a/spec/features/admin/admin_builds_spec.rb b/spec/features/admin/admin_builds_spec.rb index 2e9851fb44..7bbe20fec4 100644 --- a/spec/features/admin/admin_builds_spec.rb +++ b/spec/features/admin/admin_builds_spec.rb @@ -19,6 +19,7 @@ describe 'Admin Builds' do visit admin_builds_path expect(page).to have_selector('.nav-links li.active', text: 'All') + expect(page).to have_selector('.row-content-block', text: 'All builds') expect(page.all('.build-link').size).to eq(4) expect(page).to have_link 'Cancel all' end diff --git a/spec/features/admin/admin_health_check_spec.rb b/spec/features/admin/admin_health_check_spec.rb new file mode 100644 index 0000000000..dec2dedf2b --- /dev/null +++ b/spec/features/admin/admin_health_check_spec.rb @@ -0,0 +1,55 @@ +require 'spec_helper' + +feature "Admin Health Check", feature: true do + include WaitForAjax + + before do + login_as :admin + end + + describe '#show' do + before do + visit admin_health_check_path + end + + it { page.has_text? 'Health Check' } + it { page.has_text? 'Health information can be retrieved' } + + it 'has a health check access token' do + token = current_application_settings.health_check_access_token + expect(page).to have_content("Access token is #{token}") + expect(page).to have_selector('#health-check-token', text: token) + end + + describe 'reload access token', js: true do + it 'changes the access token' do + orig_token = current_application_settings.health_check_access_token + click_button 'Reset health check access token' + wait_for_ajax + expect(find('#health-check-token').text).not_to eq orig_token + end + end + end + + context 'when services are up' do + before do + visit admin_health_check_path + end + + it 'shows healthy status' do + expect(page).to have_content('Current Status: Healthy') + end + end + + context 'when a service is down' do + before do + allow(HealthCheck::Utils).to receive(:process_checks).and_return('The server is on fire') + visit admin_health_check_path + end + + it 'shows unhealthy status' do + expect(page).to have_content('Current Status: Unhealthy') + expect(page).to have_content('The server is on fire') + end + end +end diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb index 26d03944b8..8ebd4a6808 100644 --- a/spec/features/admin/admin_runners_spec.rb +++ b/spec/features/admin/admin_runners_spec.rb @@ -79,7 +79,7 @@ describe "Admin Runners" do end it 'changes registration token' do - expect(page_token).to_not eq token + expect(page_token).not_to eq token end end end diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb index 4570e40912..96621843b3 100644 --- a/spec/features/admin/admin_users_spec.rb +++ b/spec/features/admin/admin_users_spec.rb @@ -152,7 +152,7 @@ describe "Admin::Users", feature: true do it 'sees impersonation log out icon' do icon = first('.fa.fa-user-secret') - expect(icon).to_not eql nil + expect(icon).not_to eql nil end it 'can log out of impersonated user back to original user' do @@ -210,6 +210,8 @@ describe "Admin::Users", feature: true do before do fill_in "user_name", with: "Big Bang" fill_in "user_email", with: "bigbang@mail.com" + fill_in "user_password", with: "AValidPassword1" + fill_in "user_password_confirmation", with: "AValidPassword1" check "user_admin" click_button "Save changes" end @@ -223,6 +225,7 @@ describe "Admin::Users", feature: true do @simple_user.reload expect(@simple_user.name).to eq('Big Bang') expect(@simple_user.is_admin?).to be_truthy + expect(@simple_user.password_expires_at).to be <= Time.now end end end diff --git a/spec/features/builds_spec.rb b/spec/features/builds_spec.rb index 090a941958..7a05d30e8b 100644 --- a/spec/features/builds_spec.rb +++ b/spec/features/builds_spec.rb @@ -46,7 +46,7 @@ describe "Builds" do it { expect(page).to have_content @build.short_sha } it { expect(page).to have_content @build.ref } it { expect(page).to have_content @build.name } - it { expect(page).to_not have_link 'Cancel running' } + it { expect(page).not_to have_link 'Cancel running' } end end @@ -62,7 +62,7 @@ describe "Builds" do it { expect(page).to have_content @build.short_sha } it { expect(page).to have_content @build.ref } it { expect(page).to have_content @build.name } - it { expect(page).to_not have_link 'Cancel running' } + it { expect(page).not_to have_link 'Cancel running' } end describe "GET /:project/builds/:id" do diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb index dacaa96d76..20f0b27bcc 100644 --- a/spec/features/commits_spec.rb +++ b/spec/features/commits_spec.rb @@ -137,8 +137,8 @@ describe 'Commits' do expect(page).to have_content commit.git_commit_message expect(page).to have_content commit.git_author_name expect(page).to have_link('Download artifacts') - expect(page).to_not have_link('Cancel running') - expect(page).to_not have_link('Retry failed') + expect(page).not_to have_link('Cancel running') + expect(page).not_to have_link('Retry failed') end end @@ -155,9 +155,9 @@ describe 'Commits' do expect(page).to have_content commit.sha[0..7] expect(page).to have_content commit.git_commit_message expect(page).to have_content commit.git_author_name - expect(page).to_not have_link('Download artifacts') - expect(page).to_not have_link('Cancel running') - expect(page).to_not have_link('Retry failed') + expect(page).not_to have_link('Download artifacts') + expect(page).not_to have_link('Cancel running') + expect(page).not_to have_link('Retry failed') end end end diff --git a/spec/features/container_registry_spec.rb b/spec/features/container_registry_spec.rb new file mode 100644 index 0000000000..53b4f02711 --- /dev/null +++ b/spec/features/container_registry_spec.rb @@ -0,0 +1,44 @@ +require 'spec_helper' + +describe "Container Registry" do + let(:project) { create(:empty_project) } + let(:repository) { project.container_registry_repository } + let(:tag_name) { 'latest' } + let(:tags) { [tag_name] } + + before do + login_as(:user) + project.team << [@user, :developer] + stub_container_registry_tags(*tags) + stub_container_registry_config(enabled: true) + allow(Auth::ContainerRegistryAuthenticationService).to receive(:full_access_token).and_return('token') + end + + describe 'GET /:project/container_registry' do + before do + visit namespace_project_container_registry_index_path(project.namespace, project) + end + + context 'when no tags' do + let(:tags) { [] } + + it { expect(page).to have_content('No images in Container Registry for this project') } + end + + context 'when there are tags' do + it { expect(page).to have_content(tag_name)} + end + end + + describe 'DELETE /:project/container_registry/tag' do + before do + visit namespace_project_container_registry_index_path(project.namespace, project) + end + + it do + expect_any_instance_of(::ContainerRegistry::Tag).to receive(:delete).and_return(true) + + click_on 'Remove' + end + end +end diff --git a/spec/features/issues/filter_issues_spec.rb b/spec/features/issues/filter_issues_spec.rb index 192e361937..7efbaaa048 100644 --- a/spec/features/issues/filter_issues_spec.rb +++ b/spec/features/issues/filter_issues_spec.rb @@ -154,4 +154,180 @@ describe 'Filter issues', feature: true do end end end + + describe 'filter issues by text' do + before do + create(:issue, title: "Bug", project: project) + + bug_label = create(:label, project: project, title: 'bug') + milestone = create(:milestone, title: "8", project: project) + + issue = create(:issue, + title: "Bug 2", + project: project, + milestone: milestone, + author: user, + assignee: user) + issue.labels << bug_label + + visit namespace_project_issues_path(project.namespace, project) + end + + context 'only text', js: true do + it 'should filter issues by searched text' do + fill_in 'issue_search', with: 'Bug' + + page.within '.issues-list' do + expect(page).to have_selector('.issue', count: 2) + end + end + + it 'should not show any issues' do + fill_in 'issue_search', with: 'testing' + + page.within '.issues-list' do + expect(page).not_to have_selector('.issue') + end + end + end + + context 'text and dropdown options', js: true do + it 'should filter by text and label' do + fill_in 'issue_search', with: 'Bug' + + page.within '.issues-list' do + expect(page).to have_selector('.issue', count: 2) + end + + click_button 'Label' + page.within '.labels-filter' do + click_link 'bug' + end + + page.within '.issues-list' do + expect(page).to have_selector('.issue', count: 1) + end + end + + it 'should filter by text and milestone' do + fill_in 'issue_search', with: 'Bug' + + page.within '.issues-list' do + expect(page).to have_selector('.issue', count: 2) + end + + click_button 'Milestone' + page.within '.milestone-filter' do + click_link '8' + end + + page.within '.issues-list' do + expect(page).to have_selector('.issue', count: 1) + end + end + + it 'should filter by text and assignee' do + fill_in 'issue_search', with: 'Bug' + + page.within '.issues-list' do + expect(page).to have_selector('.issue', count: 2) + end + + click_button 'Assignee' + page.within '.dropdown-menu-assignee' do + click_link user.name + end + + page.within '.issues-list' do + expect(page).to have_selector('.issue', count: 1) + end + end + + it 'should filter by text and author' do + fill_in 'issue_search', with: 'Bug' + + page.within '.issues-list' do + expect(page).to have_selector('.issue', count: 2) + end + + click_button 'Author' + page.within '.dropdown-menu-author' do + click_link user.name + end + + page.within '.issues-list' do + expect(page).to have_selector('.issue', count: 1) + end + end + end + end + + describe 'filter issues and sort', js: true do + before do + bug_label = create(:label, project: project, title: 'bug') + bug_one = create(:issue, title: "Frontend", project: project) + bug_two = create(:issue, title: "Bug 2", project: project) + + bug_one.labels << bug_label + bug_two.labels << bug_label + + visit namespace_project_issues_path(project.namespace, project) + end + + it 'should be able to filter and sort issues' do + click_button 'Label' + page.within '.labels-filter' do + click_link 'bug' + end + + page.within '.issues-list' do + expect(page).to have_selector('.issue', count: 2) + end + + click_button 'Last created' + page.within '.dropdown-menu-sort' do + click_link 'Oldest created' + end + + page.within '.issues-list' do + expect(first('.issue')).to have_content('Frontend') + end + end + end + + describe 'filter by any author', js: true do + before do + user2 = create(:user, name: "tester") + create(:issue, project: project, author: user) + create(:issue, project: project, author: user2) + + visit namespace_project_issues_path(project.namespace, project) + end + + it 'should show filter by any author link' do + click_button "Author" + fill_in "Search authors", with: "tester" + + page.within ".dropdown-menu-author" do + expect(page).to have_content "tester" + end + end + + it 'should show filter issues by any author' do + page.within '.issues-list' do + expect(page).to have_selector ".issue", count: 2 + end + + click_button "Author" + fill_in "Search authors", with: "tester" + + page.within ".dropdown-menu-author" do + click_link "tester" + end + + page.within '.issues-list' do + expect(page).to have_selector ".issue", count: 1 + end + end + end end diff --git a/spec/features/issues/move_spec.rb b/spec/features/issues/move_spec.rb index 84c8e20eba..c7019c5aea 100644 --- a/spec/features/issues/move_spec.rb +++ b/spec/features/issues/move_spec.rb @@ -19,7 +19,7 @@ feature 'issue move to another project' do end scenario 'moving issue to another project not allowed' do - expect(page).to have_no_select('move_to_project_id') + expect(page).to have_no_selector('#move_to_project_id') end end @@ -37,7 +37,7 @@ feature 'issue move to another project' do end scenario 'moving issue to another project' do - select(new_project.name_with_namespace, from: 'move_to_project_id') + first('#move_to_project_id', visible: false).set(new_project.id) click_button('Save changes') expect(current_url).to include project_path(new_project) @@ -47,14 +47,18 @@ feature 'issue move to another project' do expect(page).to have_content(issue.title) end - context 'projects user does not have permission to move issue to exist' do + context 'user does not have permission to move the issue to a project', js: true do let!(:private_project) { create(:project, :private) } let(:another_project) { create(:project) } background { another_project.team << [user, :guest] } scenario 'browsing projects in projects select' do - options = [ '', 'No project', new_project.name_with_namespace ] - expect(page).to have_select('move_to_project_id', options: options) + click_link 'Select project' + + page.within '.select2-results' do + expect(page).to have_content 'No project' + expect(page).to have_content new_project.name_with_namespace + end end end @@ -65,7 +69,7 @@ feature 'issue move to another project' do end scenario 'user wants to move issue that has already been moved' do - expect(page).to have_no_select('move_to_project_id') + expect(page).to have_no_selector('#move_to_project_id') end end end diff --git a/spec/features/issues/note_polling_spec.rb b/spec/features/issues/note_polling_spec.rb index e4efdbe242..f5cfe2d666 100644 --- a/spec/features/issues/note_polling_spec.rb +++ b/spec/features/issues/note_polling_spec.rb @@ -9,8 +9,11 @@ feature 'Issue notes polling' do end scenario 'Another user adds a comment to an issue', js: true do - note = create(:note_on_issue, noteable: issue, note: 'Looks good!') + note = create(:note, noteable: issue, project: project, + note: 'Looks good!') + page.execute_script('notes.refresh();') + expect(page).to have_selector("#note_#{note.id}", text: 'Looks good!') end end diff --git a/spec/features/issues/update_issues_spec.rb b/spec/features/issues/update_issues_spec.rb index b03dd0f666..466a6f7dfa 100644 --- a/spec/features/issues/update_issues_spec.rb +++ b/spec/features/issues/update_issues_spec.rb @@ -95,7 +95,7 @@ feature 'Multiple issue updating from issues#index', feature: true do find('.dropdown-menu-milestone a', text: "No Milestone").click click_update_issues_button - expect(first('.issue')).to_not have_content milestone.title + expect(first('.issue')).not_to have_content milestone.title end end diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb index d5755c293c..9271964166 100644 --- a/spec/features/issues_spec.rb +++ b/spec/features/issues_spec.rb @@ -64,10 +64,68 @@ describe 'Issues', feature: true do end end + describe 'due date', js: true do + context 'on new form' do + before do + visit new_namespace_project_issue_path(project.namespace, project) + end + + it 'should save with due date' do + date = Date.today.at_beginning_of_month + + fill_in 'issue_title', with: 'bug 345' + fill_in 'issue_description', with: 'bug description' + + page.within '.datepicker' do + click_link date.day + end + + expect(find('#issuable-due-date', visible: false).value).to eq date.to_s + + click_button 'Submit issue' + + page.within '.issuable-sidebar' do + expect(page).to have_content date.to_s(:medium) + end + end + end + + context 'on edit form' do + 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) + end + + it 'should save with due date' do + date = Date.today.at_beginning_of_month + + expect(find('#issuable-due-date', visible: false).value).to eq date.to_s + + date = date.tomorrow + + fill_in 'issue_title', with: 'bug 345' + fill_in 'issue_description', with: 'bug description' + + page.within '.datepicker' do + click_link date.day + end + + expect(find('#issuable-due-date', visible: false).value).to eq date.to_s + + click_button 'Save changes' + + page.within '.issuable-sidebar' do + expect(page).to have_content date.to_s(:medium) + end + end + end + end + describe 'Issue info' do it 'excludes award_emoji from comment count' do issue = create(:issue, author: @user, assignee: @user, project: project, title: 'foobar') - create(:upvote_note, noteable: issue) + create(:upvote_note, noteable: issue, project: project) visit namespace_project_issues_path(project.namespace, project, assignee_id: @user.id) @@ -331,7 +389,7 @@ describe 'Issues', feature: true do page.within '.assignee' do click_link 'Edit' end - + page.within '.dropdown-menu-user' do click_link @user.name end @@ -431,6 +489,43 @@ describe 'Issues', feature: true do end end + describe 'due date' do + context 'update due on issue#show', js: true do + let(:issue) { create(:issue, project: project, author: @user, assignee: @user) } + + before do + visit namespace_project_issue_path(project.namespace, project, issue) + end + + it 'should add due date to issue' do + page.within '.due_date' do + click_link 'Edit' + + page.within '.ui-datepicker-calendar' do + first('.ui-state-default').click + end + + expect(page).to have_no_content 'None' + end + end + + it 'should remove due date from issue' do + page.within '.due_date' do + click_link 'Edit' + + page.within '.ui-datepicker-calendar' do + first('.ui-state-default').click + end + + expect(page).to have_no_content 'None' + + click_link 'remove due date' + expect(page).to have_content 'None' + end + end + end + end + def first_issue page.all('ul.issues-list > li').first.text end diff --git a/spec/features/login_spec.rb b/spec/features/login_spec.rb index 8c38dd5b12..c1b178c3b6 100644 --- a/spec/features/login_spec.rb +++ b/spec/features/login_spec.rb @@ -32,7 +32,7 @@ feature 'Login', feature: true do let(:user) { create(:user, :two_factor) } before do - login_with(user) + login_with(user, remember: true) expect(page).to have_content('Two-factor Authentication') end @@ -52,6 +52,12 @@ feature 'Login', feature: true do expect(current_path).to eq root_path end + it 'persists remember_me value via hidden field' do + field = first('input#user_remember_me', visible: false) + + expect(field.value).to eq '1' + end + it 'blocks login with invalid code' do enter_code('foo') expect(page).to have_content('Invalid two-factor code') @@ -121,7 +127,7 @@ feature 'Login', feature: true do user = create(:user, password: 'not-the-default') login_with(user) - expect(page).to have_content('Invalid login or password.') + expect(page).to have_content('Invalid Login or password.') end end diff --git a/spec/features/markdown_spec.rb b/spec/features/markdown_spec.rb index 0148c87084..1d892fe1a5 100644 --- a/spec/features/markdown_spec.rb +++ b/spec/features/markdown_spec.rb @@ -278,6 +278,10 @@ describe 'GitLab Markdown', feature: true do it 'includes GollumTagsFilter' do expect(doc).to parse_gollum_tags end + + it 'includes InlineDiffFilter' do + expect(doc).to parse_inline_diffs + end end # Fake a `current_user` helper diff --git a/spec/features/merge_requests/created_from_fork_spec.rb b/spec/features/merge_requests/created_from_fork_spec.rb new file mode 100644 index 0000000000..edc0bdec3d --- /dev/null +++ b/spec/features/merge_requests/created_from_fork_spec.rb @@ -0,0 +1,58 @@ +require 'spec_helper' + +feature 'Merge request created from fork' do + given(:user) { create(:user) } + given(:project) { create(:project, :public) } + given(:fork_project) { create(:project, :public) } + + given!(:merge_request) do + create(:forked_project_link, forked_to_project: fork_project, + forked_from_project: project) + + create(:merge_request_with_diffs, source_project: fork_project, + target_project: project, + description: 'Test merge request') + end + + background do + fork_project.team << [user, :master] + login_as user + end + + scenario 'user can access merge request' do + visit_merge_request(merge_request) + + expect(page).to have_content 'Test merge request' + end + + context 'pipeline present in source project' do + include WaitForAjax + + given(:pipeline) do + create(:ci_commit_with_two_jobs, project: fork_project, + sha: merge_request.last_commit.id, + ref: merge_request.source_branch) + end + + background { pipeline.create_builds(user) } + + scenario 'user visits a pipelines page', js: true do + visit_merge_request(merge_request) + page.within('.merge-request-tabs') { click_link 'Builds' } + wait_for_ajax + + page.within('table.builds') do + expect(page).to have_content 'rspec' + expect(page).to have_content 'spinach' + end + + expect(find_link('Cancel running')[:href]) + .to include fork_project.path_with_namespace + end + end + + def visit_merge_request(mr) + visit namespace_project_merge_request_path(project.namespace, + project, mr) + end +end diff --git a/spec/features/merge_requests/user_lists_merge_requests_spec.rb b/spec/features/merge_requests/user_lists_merge_requests_spec.rb new file mode 100644 index 0000000000..1c130057c5 --- /dev/null +++ b/spec/features/merge_requests/user_lists_merge_requests_spec.rb @@ -0,0 +1,161 @@ +require 'spec_helper' + +describe 'Projects > Merge requests > User lists merge requests', feature: true do + include SortingHelper + + let(:project) { create(:project, :public) } + let(:user) { create(:user) } + + before do + @fix = create(:merge_request, + title: 'fix', + source_project: project, + source_branch: 'fix', + assignee: user, + milestone: create(:milestone, due_date: '2013-12-11'), + created_at: 1.minute.ago, + updated_at: 1.minute.ago) + create(:merge_request, + title: 'markdown', + source_project: project, + source_branch: 'markdown', + assignee: user, + milestone: create(:milestone, due_date: '2013-12-12'), + created_at: 2.minutes.ago, + updated_at: 2.minutes.ago) + create(:merge_request, + title: 'lfs', + source_project: project, + source_branch: 'lfs', + created_at: 3.minutes.ago, + updated_at: 10.seconds.ago) + end + + it 'filters on no assignee' do + visit_merge_requests(project, assignee_id: IssuableFinder::NONE) + + expect(current_path).to eq(namespace_project_merge_requests_path(project.namespace, project)) + expect(page).to have_content 'lfs' + expect(page).not_to have_content 'fix' + expect(page).not_to have_content 'markdown' + expect(count_merge_requests).to eq(1) + end + + it 'filters on a specific assignee' do + visit_merge_requests(project, assignee_id: user.id) + + expect(page).not_to have_content 'lfs' + expect(page).to have_content 'fix' + expect(page).to have_content 'markdown' + expect(count_merge_requests).to eq(2) + end + + it 'sorts by newest' do + visit_merge_requests(project, sort: sort_value_recently_created) + + expect(first_merge_request).to include('lfs') + expect(last_merge_request).to include('fix') + expect(count_merge_requests).to eq(3) + end + + it 'sorts by oldest' do + visit_merge_requests(project, sort: sort_value_oldest_created) + + expect(first_merge_request).to include('fix') + expect(last_merge_request).to include('lfs') + expect(count_merge_requests).to eq(3) + end + + it 'sorts by last updated' do + visit_merge_requests(project, sort: sort_value_recently_updated) + + expect(first_merge_request).to include('lfs') + expect(count_merge_requests).to eq(3) + end + + it 'sorts by oldest updated' do + visit_merge_requests(project, sort: sort_value_oldest_updated) + + expect(first_merge_request).to include('markdown') + expect(count_merge_requests).to eq(3) + end + + it 'sorts by milestone due soon' do + visit_merge_requests(project, sort: sort_value_milestone_soon) + + expect(first_merge_request).to include('fix') + expect(count_merge_requests).to eq(3) + end + + it 'sorts by milestone due later' do + visit_merge_requests(project, sort: sort_value_milestone_later) + + expect(first_merge_request).to include('markdown') + expect(count_merge_requests).to eq(3) + end + + it 'filters on one label and sorts by due soon' do + label = create(:label, project: project) + create(:label_link, label: label, target: @fix) + + visit_merge_requests(project, label_name: [label.name], + sort: sort_value_due_date_soon) + + expect(first_merge_request).to include('fix') + expect(count_merge_requests).to eq(1) + end + + context 'while filtering on two labels' do + let(:label) { create(:label, project: project) } + let(:label2) { create(:label, project: project) } + + before do + create(:label_link, label: label, target: @fix) + create(:label_link, label: label2, target: @fix) + end + + it 'sorts by due soon' do + visit_merge_requests(project, label_name: [label.name, label2.name], + sort: sort_value_due_date_soon) + + expect(first_merge_request).to include('fix') + expect(count_merge_requests).to eq(1) + end + + context 'filter on assignee and' do + it 'sorts by due soon' do + visit_merge_requests(project, label_name: [label.name, label2.name], + assignee_id: user.id, + sort: sort_value_due_date_soon) + + expect(first_merge_request).to include('fix') + expect(count_merge_requests).to eq(1) + end + + it 'sorts by recently due milestone' do + visit namespace_project_merge_requests_path(project.namespace, project, + label_name: [label.name, label2.name], + assignee_id: user.id, + sort: sort_value_milestone_soon) + + expect(first_merge_request).to include('fix') + end + end + end + + def visit_merge_requests(project, opts = {}) + visit namespace_project_merge_requests_path(project.namespace, project, opts) + end + + def first_merge_request + page.all('ul.mr-list > li').first.text + end + + def last_merge_request + page.all('ul.mr-list > li').last.text + end + + def count_merge_requests + page.all('ul.mr-list > li').count + end +end diff --git a/spec/features/notes_on_merge_requests_spec.rb b/spec/features/notes_on_merge_requests_spec.rb index 389812ff7e..2835cf4449 100644 --- a/spec/features/notes_on_merge_requests_spec.rb +++ b/spec/features/notes_on_merge_requests_spec.rb @@ -19,10 +19,14 @@ describe 'Comments', feature: true do end describe 'On a merge request', js: true, feature: true do - let!(:merge_request) { create(:merge_request) } - let!(:project) { merge_request.source_project } + let!(:project) { create(:project) } + let!(:merge_request) do + create(:merge_request, source_project: project, target_project: project) + end + let!(:note) do - create(:note_on_merge_request, :with_attachment, project: project) + create(:note_on_merge_request, :with_attachment, noteable: merge_request, + project: project) end before do @@ -192,7 +196,7 @@ describe 'Comments', feature: true do end it 'should be removed when canceled' do - page.within(".diff-file form[id$='#{line_code}']") do + page.within(".diff-file form[id$='#{line_code}-true']") do find('.js-close-discussion-note-form').trigger('click') end diff --git a/spec/features/participants_autocomplete_spec.rb b/spec/features/participants_autocomplete_spec.rb index 1adab7e9c6..c7c00a3266 100644 --- a/spec/features/participants_autocomplete_spec.rb +++ b/spec/features/participants_autocomplete_spec.rb @@ -32,7 +32,8 @@ feature 'Member autocomplete', feature: true do context 'adding a new note on a Issue', js: true do before do issue = create(:issue, author: author, project: project) - create(:note, note: 'Ultralight Beam', noteable: issue, author: participant) + create(:note, note: 'Ultralight Beam', noteable: issue, + project: project, author: participant) visit_issue(project, issue) end @@ -47,7 +48,8 @@ feature 'Member autocomplete', feature: true do context 'adding a new note on a Merge Request ', js: true do before do merge = create(:merge_request, source_project: project, target_project: project, author: author) - create(:note, note: 'Ultralight Beam', noteable: merge, author: participant) + create(:note, note: 'Ultralight Beam', noteable: merge, + project: project, author: participant) visit_merge_request(project, merge) end diff --git a/spec/features/pipelines_spec.rb b/spec/features/pipelines_spec.rb new file mode 100644 index 0000000000..acd6fb3538 --- /dev/null +++ b/spec/features/pipelines_spec.rb @@ -0,0 +1,189 @@ +require 'spec_helper' + +describe "Pipelines" do + include GitlabRoutingHelper + + let(:project) { create(:empty_project) } + let(:user) { create(:user) } + + before do + login_as(user) + project.team << [user, :developer] + end + + describe 'GET /:project/pipelines' do + let!(:pipeline) { create(:ci_commit, project: project, ref: 'master', status: 'running') } + + [:all, :running, :branches].each do |scope| + context "displaying #{scope}" do + let(:project) { create(:project) } + + before { visit namespace_project_pipelines_path(project.namespace, project, scope: scope) } + + it { expect(page).to have_content(pipeline.short_sha) } + end + end + + context 'anonymous access' do + before { visit namespace_project_pipelines_path(project.namespace, project) } + + it { expect(page).to have_http_status(:success) } + end + + context 'cancelable pipeline' do + let!(:running) { create(:ci_build, :running, commit: pipeline, stage: 'test', commands: 'test') } + + before { visit namespace_project_pipelines_path(project.namespace, project) } + + it { expect(page).to have_link('Cancel') } + it { expect(page).to have_selector('.ci-running') } + + context 'when canceling' do + before { click_link('Cancel') } + + it { expect(page).not_to have_link('Cancel') } + it { expect(page).to have_selector('.ci-canceled') } + end + end + + context 'retryable pipelines' do + let!(:failed) { create(:ci_build, :failed, commit: pipeline, stage: 'test', commands: 'test') } + + before { visit namespace_project_pipelines_path(project.namespace, project) } + + it { expect(page).to have_link('Retry') } + it { expect(page).to have_selector('.ci-failed') } + + context 'when retrying' do + before { click_link('Retry') } + + it { expect(page).not_to have_link('Retry') } + it { expect(page).to have_selector('.ci-pending') } + end + end + + context 'for generic statuses' do + context 'when running' do + let!(:running) { create(:generic_commit_status, status: 'running', commit: pipeline, stage: 'test') } + + before { visit namespace_project_pipelines_path(project.namespace, project) } + + it 'not be cancelable' do + expect(page).not_to have_link('Cancel') + end + + it 'pipeline is running' do + expect(page).to have_selector('.ci-running') + end + end + + context 'when failed' do + let!(:running) { create(:generic_commit_status, status: 'failed', commit: pipeline, stage: 'test') } + + before { visit namespace_project_pipelines_path(project.namespace, project) } + + it 'not be retryable' do + expect(page).not_to have_link('Retry') + end + + it 'pipeline is failed' do + expect(page).to have_selector('.ci-failed') + end + end + end + + context 'downloadable pipelines' do + context 'with artifacts' do + let!(:with_artifacts) { create(:ci_build, :artifacts, :success, commit: pipeline, name: 'rspec tests', stage: 'test') } + + before { visit namespace_project_pipelines_path(project.namespace, project) } + + it { expect(page).to have_selector('.build-artifacts') } + it { expect(page).to have_link(with_artifacts.name) } + end + + context 'without artifacts' do + let!(:without_artifacts) { create(:ci_build, :success, commit: pipeline, name: 'rspec', stage: 'test') } + + it { expect(page).not_to have_selector('.build-artifacts') } + end + end + end + + describe 'GET /:project/pipelines/:id' do + let(:pipeline) { create(:ci_commit, project: project, ref: 'master') } + + before do + @success = create(:ci_build, :success, commit: pipeline, stage: 'build', name: 'build') + @failed = create(:ci_build, :failed, commit: pipeline, stage: 'test', name: 'test', commands: 'test') + @running = create(:ci_build, :running, commit: pipeline, stage: 'deploy', name: 'deploy') + @external = create(:generic_commit_status, status: 'success', commit: pipeline, name: 'jenkins', stage: 'external') + end + + before { visit namespace_project_pipeline_path(project.namespace, project, pipeline) } + + it 'showing a list of builds' do + expect(page).to have_content('Tests') + expect(page).to have_content(@success.id) + expect(page).to have_content('Deploy') + expect(page).to have_content(@failed.id) + expect(page).to have_content(@running.id) + expect(page).to have_content(@external.id) + expect(page).to have_content('Retry failed') + expect(page).to have_content('Cancel running') + end + + context 'retrying builds' do + it { expect(page).not_to have_content('retried') } + + context 'when retrying' do + before { click_on 'Retry failed' } + + it { expect(page).not_to have_content('Retry failed') } + it { expect(page).to have_content('retried') } + end + end + + context 'canceling builds' do + it { expect(page).not_to have_selector('.ci-canceled') } + + context 'when canceling' do + before { click_on 'Cancel running' } + + it { expect(page).not_to have_content('Cancel running') } + it { expect(page).to have_selector('.ci-canceled') } + end + end + end + + describe 'POST /:project/pipelines' do + let(:project) { create(:project) } + + before { visit new_namespace_project_pipeline_path(project.namespace, project) } + + context 'for valid commit' do + before { fill_in('Create for', with: 'master') } + + context 'with gitlab-ci.yml' do + before { stub_ci_commit_to_return_yaml_file } + + it { expect{ click_on 'Create pipeline' }.to change{ Ci::Commit.count }.by(1) } + end + + context 'without gitlab-ci.yml' do + before { click_on 'Create pipeline' } + + it { expect(page).to have_content('Missing .gitlab-ci.yml file') } + end + end + + context 'for invalid commit' do + before do + fill_in('Create for', with: 'invalid reference') + click_on 'Create pipeline' + end + + it { expect(page).to have_content('Reference not found') } + end + end +end diff --git a/spec/features/projects/badges/list_spec.rb b/spec/features/projects/badges/list_spec.rb index 13c9b95b31..51be81d634 100644 --- a/spec/features/projects/badges/list_spec.rb +++ b/spec/features/projects/badges/list_spec.rb @@ -8,12 +8,10 @@ feature 'list of badges' do project = create(:project) project.team << [user, :master] login_as(user) - visit edit_namespace_project_path(project.namespace, project) + visit namespace_project_badges_path(project.namespace, project) end scenario 'user displays list of badges' do - click_link 'Badges' - expect(page).to have_content 'build status' expect(page).to have_content 'Markdown' expect(page).to have_content 'HTML' @@ -26,7 +24,6 @@ feature 'list of badges' do end scenario 'user changes current ref on badges list page', js: true do - click_link 'Badges' select2('improve/awesome', from: '#ref') expect(page).to have_content 'badges/improve/awesome/build.svg' diff --git a/spec/features/projects/developer_views_empty_project_instructions_spec.rb b/spec/features/projects/developer_views_empty_project_instructions_spec.rb new file mode 100644 index 0000000000..0c51fe72ca --- /dev/null +++ b/spec/features/projects/developer_views_empty_project_instructions_spec.rb @@ -0,0 +1,63 @@ +require 'rails_helper' + +feature 'Developer views empty project instructions', feature: true do + let(:project) { create(:empty_project, :empty_repo) } + let(:developer) { create(:user) } + + background do + project.team << [developer, :developer] + + login_as(developer) + end + + context 'without an SSH key' do + scenario 'defaults to HTTP' do + visit_project + + expect_instructions_for('http') + end + + scenario 'switches to SSH', js: true do + visit_project + + select_protocol('SSH') + + expect_instructions_for('ssh') + end + end + + context 'with an SSH key' do + background do + create(:personal_key, user: developer) + end + + scenario 'defaults to SSH' do + visit_project + + expect_instructions_for('ssh') + end + + scenario 'switches to HTTP', js: true do + visit_project + + select_protocol('HTTP') + + expect_instructions_for('http') + end + end + + def visit_project + visit namespace_project_path(project.namespace, project) + end + + def select_protocol(protocol) + find('#clone-dropdown').click + find(".#{protocol.downcase}-selector").click + end + + def expect_instructions_for(protocol) + msg = :"#{protocol.downcase}_url_to_repo" + + expect(page).to have_content("git clone #{project.send(msg)}") + end +end diff --git a/spec/features/projects/files/gitignore_dropdown_spec.rb b/spec/features/projects/files/gitignore_dropdown_spec.rb new file mode 100644 index 0000000000..073a83b689 --- /dev/null +++ b/spec/features/projects/files/gitignore_dropdown_spec.rb @@ -0,0 +1,30 @@ +require 'spec_helper' + +feature 'User wants to add a .gitignore file', feature: true do + include WaitForAjax + + before do + user = create(:user) + project = create(:project) + project.team << [user, :master] + login_as user + visit namespace_project_new_blob_path(project.namespace, project, 'master', file_name: '.gitignore') + end + + scenario 'user can see .gitignore dropdown' do + expect(page).to have_css('.gitignore-selector') + end + + scenario 'user can pick a .gitignore file from the dropdown', js: true do + find('.js-gitignore-selector').click + wait_for_ajax + within '.gitignore-selector' do + find('.dropdown-input-field').set('rails') + find('.dropdown-content li', text: 'Rails').click + end + wait_for_ajax + + expect(page).to have_content('/.bundle') + expect(page).to have_content('# Gemfile.lock, .ruby-version, .ruby-gemset') + end +end diff --git a/spec/features/projects/files/project_owner_creates_license_file_spec.rb b/spec/features/projects/files/project_owner_creates_license_file_spec.rb index 3d6ffbc4c6..ecc818eb1e 100644 --- a/spec/features/projects/files/project_owner_creates_license_file_spec.rb +++ b/spec/features/projects/files/project_owner_creates_license_file_spec.rb @@ -25,7 +25,7 @@ feature 'project owner creates a license file', feature: true, js: true do file_content = find('.file-content') expect(file_content).to have_content('The MIT License (MIT)') - expect(file_content).to have_content("Copyright (c) 2016 #{project.namespace.human_name}") + expect(file_content).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}") fill_in :commit_message, with: 'Add a LICENSE file', visible: true click_button 'Commit Changes' @@ -33,7 +33,7 @@ feature 'project owner creates a license file', feature: true, js: true do expect(current_path).to eq( namespace_project_blob_path(project.namespace, project, 'master/LICENSE')) expect(page).to have_content('The MIT License (MIT)') - expect(page).to have_content("Copyright (c) 2016 #{project.namespace.human_name}") + expect(page).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}") end scenario 'project master creates a license file from the "Add license" link' do @@ -48,7 +48,7 @@ feature 'project owner creates a license file', feature: true, js: true do file_content = find('.file-content') expect(file_content).to have_content('The MIT License (MIT)') - expect(file_content).to have_content("Copyright (c) 2016 #{project.namespace.human_name}") + expect(file_content).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}") fill_in :commit_message, with: 'Add a LICENSE file', visible: true click_button 'Commit Changes' @@ -56,6 +56,6 @@ feature 'project owner creates a license file', feature: true, js: true do expect(current_path).to eq( namespace_project_blob_path(project.namespace, project, 'master/LICENSE')) expect(page).to have_content('The MIT License (MIT)') - expect(page).to have_content("Copyright (c) 2016 #{project.namespace.human_name}") + expect(page).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}") end end diff --git a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb index 3268e24020..34eda29c28 100644 --- a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb +++ b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb @@ -24,7 +24,7 @@ feature 'project owner sees a link to create a license file in empty project', f file_content = find('.file-content') expect(file_content).to have_content('The MIT License (MIT)') - expect(file_content).to have_content("Copyright (c) 2016 #{project.namespace.human_name}") + expect(file_content).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}") fill_in :commit_message, with: 'Add a LICENSE file', visible: true # Remove pre-receive hook so we can push without auth @@ -34,6 +34,6 @@ feature 'project owner sees a link to create a license file in empty project', f expect(current_path).to eq( namespace_project_blob_path(project.namespace, project, 'master/LICENSE')) expect(page).to have_content('The MIT License (MIT)') - expect(page).to have_content("Copyright (c) 2016 #{project.namespace.human_name}") + expect(page).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}") end end diff --git a/spec/features/project/shortcuts_spec.rb b/spec/features/projects/shortcuts_spec.rb similarity index 79% rename from spec/features/project/shortcuts_spec.rb rename to spec/features/projects/shortcuts_spec.rb index 2595c4181e..54aa9c66a0 100644 --- a/spec/features/project/shortcuts_spec.rb +++ b/spec/features/projects/shortcuts_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' feature 'Project shortcuts', feature: true do - let(:project) { create(:project) } + let(:project) { create(:project, name: 'Victorialand') } let(:user) { create(:user) } describe 'On a project', js: true do @@ -14,7 +14,7 @@ feature 'Project shortcuts', feature: true do describe 'pressing "i"' do it 'redirects to new issue page' do find('body').native.send_key('i') - expect(page).to have_content('New Issue') + expect(page).to have_content('Victorialand') end end end diff --git a/spec/features/runners_spec.rb b/spec/features/runners_spec.rb index 8edeb8d18a..a5ed3595b0 100644 --- a/spec/features/runners_spec.rb +++ b/spec/features/runners_spec.rb @@ -29,8 +29,8 @@ describe "Runners" do end before do - expect(page).to_not have_content(@specific_runner3.display_name) - expect(page).to_not have_content(@specific_runner3.display_name) + expect(page).not_to have_content(@specific_runner3.display_name) + expect(page).not_to have_content(@specific_runner3.display_name) end it "places runners in right places" do @@ -110,4 +110,37 @@ describe "Runners" do expect(page).to have_content(@specific_runner.platform) end end + + feature 'configuring runners ability to picking untagged jobs' do + given(:project) { create(:empty_project) } + given(:runner) { create(:ci_runner) } + + background do + project.team << [user, :master] + project.runners << runner + end + + scenario 'user checks default configuration' do + visit namespace_project_runner_path(project.namespace, project, runner) + + expect(page).to have_content 'Can run untagged jobs Yes' + end + + context 'when runner has tags' do + before { runner.update_attribute(:tag_list, ['tag']) } + + scenario 'user wants to prevent runner from running untagged job' do + visit runners_path(project) + page.within('.activated-specific-runners') do + first('small > a').click + end + + uncheck 'runner_run_untagged' + click_button 'Save changes' + + expect(page).to have_content 'Can run untagged jobs No' + expect(runner.reload.run_untagged?).to eq false + end + end + end end diff --git a/spec/features/signup_spec.rb b/spec/features/signup_spec.rb index 58aabd913e..4229e82b44 100644 --- a/spec/features/signup_spec.rb +++ b/spec/features/signup_spec.rb @@ -2,20 +2,45 @@ require 'spec_helper' feature 'Signup', feature: true do describe 'signup with no errors' do - it 'creates the user account and sends a confirmation email' do - user = build(:user) - visit root_path + context "when sending confirmation email" do + before { allow_any_instance_of(ApplicationSetting).to receive(:send_user_confirmation_email).and_return(true) } - fill_in 'new_user_name', with: user.name - fill_in 'new_user_username', with: user.username - fill_in 'new_user_email', with: user.email - fill_in 'new_user_password', with: user.password - click_button "Sign up" + it 'creates the user account and sends a confirmation email' do + user = build(:user) - expect(current_path).to eq users_almost_there_path - expect(page).to have_content("Please check your email to confirm your account") + visit root_path + + fill_in 'new_user_name', with: user.name + fill_in 'new_user_username', with: user.username + fill_in 'new_user_email', with: user.email + fill_in 'new_user_password', with: user.password + click_button "Sign up" + + expect(current_path).to eq users_almost_there_path + expect(page).to have_content("Please check your email to confirm your account") + end end + + context "when not sending confirmation email" do + before { allow_any_instance_of(ApplicationSetting).to receive(:send_user_confirmation_email).and_return(false) } + + it 'creates the user account and goes to dashboard' do + user = build(:user) + + visit root_path + + fill_in 'new_user_name', with: user.name + fill_in 'new_user_username', with: user.username + fill_in 'new_user_email', with: user.email + fill_in 'new_user_password', with: user.password + click_button "Sign up" + + expect(current_path).to eq dashboard_projects_path + 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_creates_tag_spec.rb b/spec/features/tags/master_creates_tag_spec.rb new file mode 100644 index 0000000000..08a97085a9 --- /dev/null +++ b/spec/features/tags/master_creates_tag_spec.rb @@ -0,0 +1,62 @@ +require 'spec_helper' + +feature 'Master creates tag', feature: true do + let(:user) { create(:user) } + let(:project) { create(:project, namespace: user.namespace) } + + before do + project.team << [user, :master] + login_with(user) + visit namespace_project_tags_path(project.namespace, project) + end + + scenario 'with an invalid name displays an error' do + create_tag_in_form(tag: 'v 1.0', ref: 'master') + + expect(page).to have_content 'Tag name invalid' + end + + scenario 'with an invalid reference displays an error' do + create_tag_in_form(tag: 'v2.0', ref: 'foo') + + expect(page).to have_content 'Target foo is invalid' + end + + scenario 'that already exists displays an error' do + create_tag_in_form(tag: 'v1.1.0', ref: 'master') + + expect(page).to have_content 'Tag v1.1.0 already exists' + end + + scenario 'with multiline message displays the message in a

     block' do
    +    create_tag_in_form(tag: 'v3.0', ref: 'master', message: "Awesome tag message\n\n- hello\n- world")
    +
    +    expect(current_path).to eq(
    +      namespace_project_tag_path(project.namespace, project, 'v3.0'))
    +    expect(page).to have_content 'v3.0'
    +    page.within 'pre.body' do
    +      expect(page).to have_content "Awesome tag message\n\n- hello\n- world"
    +    end
    +  end
    +
    +  scenario 'with multiline release notes parses the release note as Markdown' do
    +    create_tag_in_form(tag: 'v4.0', ref: 'master', desc: "Awesome release notes\n\n- hello\n- world")
    +
    +    expect(current_path).to eq(
    +      namespace_project_tag_path(project.namespace, project, 'v4.0'))
    +    expect(page).to have_content 'v4.0'
    +    page.within '.description' do
    +      expect(page).to have_content 'Awesome release notes'
    +      expect(page).to have_selector('ul li', count: 2)
    +    end
    +  end
    +
    +  def create_tag_in_form(tag:, ref:, message: nil, desc: nil)
    +    click_link 'New tag'
    +    fill_in 'tag_name', with: tag
    +    fill_in 'ref', with: ref
    +    fill_in 'message', with: message unless message.nil?
    +    fill_in 'release_description', with: desc unless desc.nil?
    +    click_button 'Create tag'
    +  end
    +end
    diff --git a/spec/features/tags/master_deletes_tag_spec.rb b/spec/features/tags/master_deletes_tag_spec.rb
    new file mode 100644
    index 0000000000..f0990118e3
    --- /dev/null
    +++ b/spec/features/tags/master_deletes_tag_spec.rb
    @@ -0,0 +1,41 @@
    +require 'spec_helper'
    +
    +feature 'Master deletes tag', feature: true do
    +  let(:user) { create(:user) }
    +  let(:project) { create(:project, namespace: user.namespace) }
    +
    +  before do
    +    project.team << [user, :master]
    +    login_with(user)
    +    visit namespace_project_tags_path(project.namespace, project)
    +  end
    +
    +  context 'from the tags list page' do
    +    scenario 'deletes the tag' do
    +      expect(page).to have_content 'v1.1.0'
    +
    +      page.within('.content') do
    +        first('.btn-remove').click
    +      end
    +
    +      expect(current_path).to eq(
    +        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
    +    scenario 'deletes the tag' do
    +      click_on 'v1.0.0'
    +      expect(current_path).to eq(
    +        namespace_project_tag_path(project.namespace, project, 'v1.0.0'))
    +
    +      click_on 'Delete tag'
    +
    +      expect(current_path).to eq(
    +        namespace_project_tags_path(project.namespace, project))
    +      expect(page).not_to have_content 'v1.0.0'
    +    end
    +  end
    +end
    diff --git a/spec/features/tags/master_updates_tag_spec.rb b/spec/features/tags/master_updates_tag_spec.rb
    new file mode 100644
    index 0000000000..6b5b3122f7
    --- /dev/null
    +++ b/spec/features/tags/master_updates_tag_spec.rb
    @@ -0,0 +1,42 @@
    +require 'spec_helper'
    +
    +feature 'Master updates tag', feature: true do
    +  let(:user) { create(:user) }
    +  let(:project) { create(:project, namespace: user.namespace) }
    +
    +  before do
    +    project.team << [user, :master]
    +    login_with(user)
    +    visit namespace_project_tags_path(project.namespace, project)
    +  end
    +
    +  context 'from the tags list page' do
    +    scenario 'updates the release notes' do
    +      page.within(first('.content-list .controls')) do
    +        click_link 'Edit release notes'
    +      end
    +
    +      fill_in 'release_description', with: 'Awesome release notes'
    +      click_button 'Save changes'
    +
    +      expect(current_path).to eq(
    +        namespace_project_tag_path(project.namespace, project, 'v1.1.0'))
    +      expect(page).to have_content 'v1.1.0'
    +      expect(page).to have_content 'Awesome release notes'
    +    end
    +  end
    +
    +  context 'from a specific tag page' do
    +    scenario 'updates the release notes' do
    +      click_on 'v1.1.0'
    +      click_link 'Edit release notes'
    +      fill_in 'release_description', with: 'Awesome release notes'
    +      click_button 'Save changes'
    +
    +      expect(current_path).to eq(
    +        namespace_project_tag_path(project.namespace, project, 'v1.1.0'))
    +      expect(page).to have_content 'v1.1.0'
    +      expect(page).to have_content 'Awesome release notes'
    +    end
    +  end
    +end
    diff --git a/spec/features/tags/master_views_tags_spec.rb b/spec/features/tags/master_views_tags_spec.rb
    new file mode 100644
    index 0000000000..29d2c24472
    --- /dev/null
    +++ b/spec/features/tags/master_views_tags_spec.rb
    @@ -0,0 +1,73 @@
    +require 'spec_helper'
    +
    +feature 'Master views tags', feature: true do
    +  let(:user) { create(:user) }
    +
    +  before do
    +    project.team << [user, :master]
    +    login_with(user)
    +  end
    +
    +  context 'when project has no tags' do
    +    let(:project) { create(:project_empty_repo) }
    +    before do
    +      visit namespace_project_path(project.namespace, project)
    +      click_on 'README'
    +      fill_in :commit_message, with: 'Add a README file', visible: true
    +      # Remove pre-receive hook so we can push without auth
    +      FileUtils.rm_f(File.join(project.repository.path, 'hooks', 'pre-receive'))
    +      click_button 'Commit Changes'
    +      visit namespace_project_tags_path(project.namespace, project)
    +    end
    +
    +    scenario 'displays a specific message' do
    +      expect(page).to have_content 'Repository has no tags yet.'
    +    end
    +  end
    +
    +  context 'when project has tags' do
    +    let(:project) { create(:project, namespace: user.namespace) }
    +    before do
    +      visit namespace_project_tags_path(project.namespace, project)
    +    end
    +
    +    scenario 'views the tags list page' do
    +      expect(page).to have_content 'v1.0.0'
    +    end
    +
    +    scenario 'views a specific tag page' do
    +      click_on 'v1.0.0'
    +
    +      expect(current_path).to eq(
    +        namespace_project_tag_path(project.namespace, project, 'v1.0.0'))
    +      expect(page).to have_content 'v1.0.0'
    +      expect(page).to have_content 'This tag has no release notes.'
    +    end
    +
    +    describe 'links on the tag page' do
    +      scenario 'has a button to browse files' do
    +        click_on 'v1.0.0'
    +
    +        expect(current_path).to eq(
    +          namespace_project_tag_path(project.namespace, project, 'v1.0.0'))
    +
    +        click_on 'Browse files'
    +
    +        expect(current_path).to eq(
    +          namespace_project_tree_path(project.namespace, project, 'v1.0.0'))
    +      end
    +
    +      scenario 'has a button to browse commits' do
    +        click_on 'v1.0.0'
    +
    +        expect(current_path).to eq(
    +          namespace_project_tag_path(project.namespace, project, 'v1.0.0'))
    +
    +        click_on 'Browse commits'
    +
    +        expect(current_path).to eq(
    +          namespace_project_commits_path(project.namespace, project, 'v1.0.0'))
    +      end
    +    end
    +  end
    +end
    diff --git a/spec/features/task_lists_spec.rb b/spec/features/task_lists_spec.rb
    index b7368cca29..6ed279ef9b 100644
    --- a/spec/features/task_lists_spec.rb
    +++ b/spec/features/task_lists_spec.rb
    @@ -75,7 +75,10 @@ feature 'Task Lists', feature: true do
     
       describe 'for Notes' do
         let!(:issue) { create(:issue, author: user, project: project) }
    -    let!(:note)  { create(:note, note: markdown, noteable: issue, author: user) }
    +    let!(:note) do
    +      create(:note, note: markdown, noteable: issue,
    +                    project: project, author: user)
    +    end
     
         it 'renders for note body' do
           visit_issue(project, issue)
    diff --git a/spec/features/todos/target_state_spec.rb b/spec/features/todos/target_state_spec.rb
    new file mode 100644
    index 0000000000..72491ac7e6
    --- /dev/null
    +++ b/spec/features/todos/target_state_spec.rb
    @@ -0,0 +1,65 @@
    +require 'rails_helper'
    +
    +feature 'Todo target states', feature: true do
    +  let(:user)    { create(:user) }
    +  let(:author)  { create(:user) }
    +  let(:project) { create(:project) }
    +
    +  before do
    +    login_as user
    +  end
    +
    +  scenario 'on a closed issue todo has closed label' do
    +    issue_closed = create(:issue, state: 'closed')
    +    create_todo issue_closed
    +    visit dashboard_todos_path
    +
    +    page.within '.todos-list' do
    +      expect(page).to have_content('Closed')
    +    end
    +  end
    +
    +  scenario 'on an open issue todo does not have an open label' do
    +    issue_open = create(:issue)
    +    create_todo issue_open
    +    visit dashboard_todos_path
    +
    +    page.within '.todos-list' do
    +      expect(page).not_to have_content('Open')
    +    end
    +  end
    +
    +  scenario 'on a merged merge request todo has merged label' do
    +    mr_merged = create(:merge_request, :simple, author: user, state: 'merged')
    +    create_todo mr_merged
    +    visit dashboard_todos_path
    +
    +    page.within '.todos-list' do
    +      expect(page).to have_content('Merged')
    +    end
    +  end
    +
    +  scenario 'on a closed merge request todo has closed label' do
    +    mr_closed = create(:merge_request, :simple, author: user, state: 'closed')
    +    create_todo mr_closed
    +    visit dashboard_todos_path
    +
    +    page.within '.todos-list' do
    +      expect(page).to have_content('Closed')
    +    end
    +  end
    +
    +  scenario 'on an open merge request todo does not have an open label' do
    +    mr_open = create(:merge_request, :simple, author: user)
    +    create_todo mr_open
    +    visit dashboard_todos_path
    +
    +    page.within '.todos-list' do
    +      expect(page).not_to have_content('Open')
    +    end
    +  end
    +
    +  def create_todo(target)
    +    create(:todo, :mentioned, user: user, project: project, target: target, author: author)
    +  end
    +end
    diff --git a/spec/features/todos/todos_spec.rb b/spec/features/todos/todos_spec.rb
    index 3354f52929..4e627753cc 100644
    --- a/spec/features/todos/todos_spec.rb
    +++ b/spec/features/todos/todos_spec.rb
    @@ -43,6 +43,27 @@ describe 'Dashboard Todos', feature: true do
           end
         end
     
    +    context 'User has Todos with labels spanning multiple projects' do
    +      before do
    +        label1 = create(:label, project: project)
    +        note1 = create(:note_on_issue, note: "Hello #{label1.to_reference(format: :name)}", noteable_id: issue.id, noteable_type: 'Issue', project: issue.project)
    +        create(:todo, :mentioned, project: project, target: issue, user: user, note_id: note1.id)
    +
    +        project2 = create(:project)
    +        label2 = create(:label, project: project2)
    +        issue2 = create(:issue, project: project2)
    +        note2 = create(:note_on_issue, note: "Test #{label2.to_reference(format: :name)}", noteable_id: issue2.id, noteable_type: 'Issue', project: project2)
    +        create(:todo, :mentioned, project: project2, target: issue2, user: user, note_id: note2.id)
    +
    +        login_as(user)
    +        visit dashboard_todos_path
    +      end
    +
    +      it 'shows page with two Todos' do
    +        expect(page).to have_selector('.todos-list .todo', count: 2)
    +      end
    +    end
    +
         context 'User has multiple pages of Todos' do
           before do
             allow(Todo).to receive(:default_per_page).and_return(1)
    diff --git a/spec/features/variables_spec.rb b/spec/features/variables_spec.rb
    index afea1840cd..a2b8f7b693 100644
    --- a/spec/features/variables_spec.rb
    +++ b/spec/features/variables_spec.rb
    @@ -1,24 +1,53 @@
     require 'spec_helper'
     
    -describe "Variables" do
    -  let(:user) { create(:user) }
    -  before { login_as(user) }
    +describe 'Project variables', js: true do
    +  let(:user)     { create(:user) }
    +  let(:project)  { create(:project) }
    +  let(:variable) { create(:ci_variable, key: 'test') }
     
    -  describe "specific runners" do
    -    before do
    -      @project = FactoryGirl.create :empty_project
    -      @project.team << [user, :master]
    +  before do
    +    login_as(user)
    +    project.team << [user, :master]
    +    project.variables << variable
    +
    +    visit namespace_project_variables_path(project.namespace, project)
    +  end
    +
    +  it 'should show list of variables' do
    +    page.within('.variables-table') do
    +      expect(page).to have_content(variable.key)
    +    end
    +  end
    +
    +  it 'should add new variable' do
    +    fill_in('variable_key', with: 'key')
    +    fill_in('variable_value', with: 'key value')
    +    click_button('Add new variable')
    +
    +    page.within('.variables-table') do
    +      expect(page).to have_content('key')
    +    end
    +  end
    +
    +  it 'should delete variable' do
    +    page.within('.variables-table') do
    +      find('.btn-variable-delete').click
         end
     
    -    it "creates variable", js: true do
    -      visit namespace_project_variables_path(@project.namespace, @project)
    -      click_on "Add a variable"
    -      fill_in "Key", with: "SECRET_KEY"
    -      fill_in "Value", with: "SECRET_VALUE"
    -      click_on "Save changes"
    +    expect(page).not_to have_selector('variables-table')
    +  end
     
    -      expect(page).to have_content("Variables were successfully updated.")
    -      expect(@project.variables.count).to eq(1)
    +  it 'should edit variable' do
    +    page.within('.variables-table') do
    +      find('.btn-variable-edit').click
    +    end
    +
    +    fill_in('variable_key', with: 'key')
    +    fill_in('variable_value', with: 'key value')
    +    click_button('Save variable')
    +
    +    page.within('.variables-table') do
    +      expect(page).to have_content('key')
         end
       end
     end
    diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb
    index bc607a2975..ec8809e692 100644
    --- a/spec/finders/issues_finder_spec.rb
    +++ b/spec/finders/issues_finder_spec.rb
    @@ -1,10 +1,10 @@
     require 'spec_helper'
     
     describe IssuesFinder do
    -  let(:user) { create :user }
    -  let(:user2) { create :user }
    -  let(:project1) { create(:project) }
    -  let(:project2) { create(:project) }
    +  let(:user) { create(:user) }
    +  let(:user2) { create(:user) }
    +  let(:project1) { create(:empty_project) }
    +  let(:project2) { create(:empty_project) }
       let(:milestone) { create(:milestone, project: project1) }
       let(:label) { create(:label, project: project2) }
       let(:issue1) { create(:issue, author: user, assignee: user, project: project1, milestone: milestone) }
    @@ -16,101 +16,147 @@ describe IssuesFinder do
         project1.team << [user, :master]
         project2.team << [user, :developer]
         project2.team << [user2, :developer]
    +
    +    issue1
    +    issue2
    +    issue3
       end
     
    -  describe :execute do
    -    before :each do
    -      issue1
    -      issue2
    -      issue3
    -    end
    +  describe '#execute' do
    +    let(:search_user) { user }
    +    let(:params) { {} }
    +    let(:issues) { IssuesFinder.new(search_user, params.merge(scope: scope, state: 'opened')).execute }
     
         context 'scope: all' do
    -      it 'should filter by all' do
    -        params = { scope: "all", state: 'opened' }
    -        issues = IssuesFinder.new(user, params).execute
    -        expect(issues.size).to eq(3)
    +      let(:scope) { 'all' }
    +
    +      it 'returns all issues' do
    +        expect(issues).to contain_exactly(issue1, issue2, issue3)
           end
     
    -      it 'should filter by assignee id' do
    -        params = { scope: "all", assignee_id: user.id, state: 'opened' }
    -        issues = IssuesFinder.new(user, params).execute
    -        expect(issues.size).to eq(2)
    +      context 'filtering by assignee ID' do
    +        let(:params) { { assignee_id: user.id } }
    +
    +        it 'returns issues assigned to that user' do
    +          expect(issues).to contain_exactly(issue1, issue2)
    +        end
           end
     
    -      it 'should filter by author id' do
    -        params = { scope: "all", author_id: user2.id, state: 'opened' }
    -        issues = IssuesFinder.new(user, params).execute
    -        expect(issues).to eq([issue3])
    +      context 'filtering by author ID' do
    +        let(:params) { { author_id: user2.id } }
    +
    +        it 'returns issues created by that user' do
    +          expect(issues).to contain_exactly(issue3)
    +        end
           end
     
    -      it 'should filter by milestone id' do
    -        params = { scope: "all", milestone_title: milestone.title, state: 'opened' }
    -        issues = IssuesFinder.new(user, params).execute
    -        expect(issues).to eq([issue1])
    +      context 'filtering by milestone' do
    +        let(:params) { { milestone_title: milestone.title } }
    +
    +        it 'returns issues assigned to that milestone' do
    +          expect(issues).to contain_exactly(issue1)
    +        end
           end
     
    -      it 'should filter by no milestone id' do
    -        params = { scope: "all", milestone_title: Milestone::None.title, state: 'opened' }
    -        issues = IssuesFinder.new(user, params).execute
    -        expect(issues).to match_array([issue2, issue3])
    +      context 'filtering by no milestone' do
    +        let(:params) { { milestone_title: Milestone::None.title } }
    +
    +        it 'returns issues with no milestone' do
    +          expect(issues).to contain_exactly(issue2, issue3)
    +        end
           end
     
    -      it 'should filter by label name' do
    -        params = { scope: "all", label_name: label.title, state: 'opened' }
    -        issues = IssuesFinder.new(user, params).execute
    -        expect(issues).to eq([issue2])
    +      context 'filtering by upcoming milestone' do
    +        let(:params) { { milestone_title: Milestone::Upcoming.name } }
    +
    +        let(:project_no_upcoming_milestones) { create(:empty_project, :public) }
    +        let(:project_next_1_1) { create(:empty_project, :public) }
    +        let(:project_next_8_8) { create(:empty_project, :public) }
    +
    +        let(:yesterday) { Date.today - 1.day }
    +        let(:tomorrow) { Date.today + 1.day }
    +        let(:two_days_from_now) { Date.today + 2.days }
    +        let(:ten_days_from_now) { Date.today + 10.days }
    +
    +        let(:milestones) do
    +          [
    +            create(:milestone, :closed, project: project_no_upcoming_milestones),
    +            create(:milestone, project: project_next_1_1, title: '1.1', due_date: two_days_from_now),
    +            create(:milestone, project: project_next_1_1, title: '8.8', due_date: ten_days_from_now),
    +            create(:milestone, project: project_next_8_8, title: '1.1', due_date: yesterday),
    +            create(:milestone, project: project_next_8_8, title: '8.8', due_date: tomorrow)
    +          ]
    +        end
    +
    +        before do
    +          milestones.each do |milestone|
    +            create(:issue, project: milestone.project, milestone: milestone, author: user, assignee: user)
    +          end
    +        end
    +
    +        it 'returns issues in the upcoming milestone for each project' do
    +          expect(issues.map { |issue| issue.milestone.title }).to contain_exactly('1.1', '8.8')
    +          expect(issues.map { |issue| issue.milestone.due_date }).to contain_exactly(tomorrow, two_days_from_now)
    +        end
           end
     
    -      it 'returns unique issues when filtering by multiple labels' do
    -        label2 = create(:label, project: project2)
    +      context 'filtering by label' do
    +        let(:params) { { label_name: label.title } }
     
    -        create(:label_link, label: label2, target: issue2)
    -
    -        params = {
    -          scope:      'all',
    -          label_name: [label.title, label2.title].join(','),
    -          state:      'opened'
    -        }
    -
    -        issues = IssuesFinder.new(user, params).execute
    -
    -        expect(issues).to eq([issue2])
    +        it 'returns issues with that label' do
    +          expect(issues).to contain_exactly(issue2)
    +        end
           end
     
    -      it 'should filter by no label name' do
    -        params = { scope: "all", label_name: Label::None.title, state: 'opened' }
    -        issues = IssuesFinder.new(user, params).execute
    -        expect(issues).to match_array([issue1, issue3])
    +      context 'filtering by multiple labels' do
    +        let(:params) { { label_name: [label.title, label2.title].join(',') } }
    +        let(:label2) { create(:label, project: project2) }
    +
    +        before { create(:label_link, label: label2, target: issue2) }
    +
    +        it 'returns the unique issues with any of those labels' do
    +          expect(issues).to contain_exactly(issue2)
    +        end
           end
     
    -      it 'should be empty for unauthorized user' do
    -        params = { scope: "all", state: 'opened' }
    -        issues = IssuesFinder.new(nil, params).execute
    -        expect(issues.size).to be_zero
    +      context 'filtering by no label' do
    +        let(:params) { { label_name: Label::None.title } }
    +
    +        it 'returns issues with no labels' do
    +          expect(issues).to contain_exactly(issue1, issue3)
    +        end
           end
     
    -      it 'should not include unauthorized issues' do
    -        params = { scope: "all", state: 'opened' }
    -        issues = IssuesFinder.new(user2, params).execute
    -        expect(issues.size).to eq(2)
    -        expect(issues).not_to include(issue1)
    -        expect(issues).to include(issue2)
    -        expect(issues).to include(issue3)
    +      context 'when the user is unauthorized' do
    +        let(:search_user) { nil }
    +
    +        it 'returns no results' do
    +          expect(issues).to be_empty
    +        end
    +      end
    +
    +      context 'when the user can see some, but not all, issues' do
    +        let(:search_user) { user2 }
    +
    +        it 'returns only issues they can see' do
    +          expect(issues).to contain_exactly(issue2, issue3)
    +        end
           end
         end
     
         context 'personal scope' do
    -      it 'should filter by assignee' do
    -        params = { scope: "assigned-to-me", state: 'opened' }
    -        issues = IssuesFinder.new(user, params).execute
    -        expect(issues.size).to eq(2)
    +      let(:scope) { 'assigned-to-me' }
    +
    +      it 'returns issue assigned to the user' do
    +        expect(issues).to contain_exactly(issue1, issue2)
           end
     
    -      it 'should filter by project' do
    -        params = { scope: "assigned-to-me", state: 'opened', project_id: project1.id }
    -        issues = IssuesFinder.new(user, params).execute
    -        expect(issues.size).to eq(1)
    +      context 'filtering by project' do
    +        let(:params) { { project_id: project1.id } }
    +
    +        it 'returns issues assigned to the user in that project' do
    +          expect(issues).to contain_exactly(issue1)
    +        end
           end
         end
       end
    diff --git a/spec/fixtures/container_registry/config_blob.json b/spec/fixtures/container_registry/config_blob.json
    new file mode 100644
    index 0000000000..1028c994a2
    --- /dev/null
    +++ b/spec/fixtures/container_registry/config_blob.json
    @@ -0,0 +1 @@
    +{"architecture":"amd64","config":{"Hostname":"b14cd8298755","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":null,"Cmd":null,"Image":"","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":null},"container":"b14cd82987550b01af9a666a2f4c996280a6152e66873134fae5a0f223dc5976","container_config":{"Hostname":"b14cd8298755","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":null,"Cmd":["/bin/sh","-c","#(nop) ADD file:033ab063740d9ff4dcfb1c69eccf25f91d88729f57cd5a73050e014e3e094aa0 in /"],"Image":"","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":null},"created":"2016-04-01T20:53:00.160300546Z","docker_version":"1.9.1","history":[{"created":"2016-04-01T20:53:00.160300546Z","created_by":"/bin/sh -c #(nop) ADD file:033ab063740d9ff4dcfb1c69eccf25f91d88729f57cd5a73050e014e3e094aa0 in /"}],"os":"linux","rootfs":{"type":"layers","diff_ids":["sha256:c56b7dabbc7aa730eeab07668bdcbd7e3d40855047ca9a0cc1bfed23a2486111"]}}
    diff --git a/spec/fixtures/container_registry/tag_manifest.json b/spec/fixtures/container_registry/tag_manifest.json
    new file mode 100644
    index 0000000000..1b6008e287
    --- /dev/null
    +++ b/spec/fixtures/container_registry/tag_manifest.json
    @@ -0,0 +1 @@
    +{"schemaVersion":2,"mediaType":"application/vnd.docker.distribution.manifest.v2+json","config":{"mediaType":"application/octet-stream","size":1145,"digest":"sha256:d7a513a663c1a6dcdba9ed832ca53c02ac2af0c333322cd6ca92936d1d9917ac"},"layers":[{"mediaType":"application/vnd.docker.image.rootfs.diff.tar.gzip","size":2319870,"digest":"sha256:420890c9e918b6668faaedd9000e220190f2493b0693ee563ebd7b4cc754a57d"}]}
    diff --git a/spec/fixtures/markdown.md.erb b/spec/fixtures/markdown.md.erb
    index 1772cc3f6a..34ce7c4f03 100644
    --- a/spec/fixtures/markdown.md.erb
    +++ b/spec/fixtures/markdown.md.erb
    @@ -216,10 +216,14 @@ References should be parseable even inside _<%= merge_request.to_reference %>_ e
     
     #### MilestoneReferenceFilter
     
    -- Milestone: <%= milestone.to_reference %>
    +- Milestone by ID: <%= simple_milestone.to_reference %>
    +- Milestone by name: <%= Milestone.reference_prefix %><%= simple_milestone.name %>
    +- Milestone by name in quotes: <%= milestone.to_reference(format: :name) %>
     - Milestone in another project: <%= xmilestone.to_reference(project) %>
    -- Ignored in code: `<%= milestone.to_reference %>`
    -- Link to milestone by URL: [Milestone](<%= urls.namespace_project_milestone_url(milestone.project.namespace, milestone.project, milestone) %>)
    +- Ignored in code: `<%= simple_milestone.to_reference %>`
    +- Ignored in links: [Link to <%= simple_milestone.to_reference %>](#milestone-link)
    +- Milestone by URL: <%= urls.namespace_project_milestone_url(milestone.project.namespace, milestone.project, milestone) %>
    +- Link to milestone by URL: [Milestone](<%= milestone.to_reference %>)
     
     ### Task Lists
     
    @@ -239,3 +243,16 @@ References should be parseable even inside _<%= merge_request.to_reference %>_ e
     - [[link-text|http://example.com/pdfs/gollum.pdf]]
     - [[images/example.jpg]]
     - [[http://example.com/images/example.jpg]]
    +
    +### Inline Diffs
    +
    +With inline diffs tags you can display {+ additions +} or [- deletions -].
    +
    +The wrapping tags can be either curly braces or square brackets [+ additions +] or {- deletions -}.
    +
    +However the wrapping tags can not be mixed as such -
    +
    +- {+ additions +]
    +- [+ additions +}
    +- {- delletions -]
    +- [- delletions -}
    diff --git a/spec/helpers/auth_helper_spec.rb b/spec/helpers/auth_helper_spec.rb
    index e47a54fdac..49ea4fa6d3 100644
    --- a/spec/helpers/auth_helper_spec.rb
    +++ b/spec/helpers/auth_helper_spec.rb
    @@ -2,7 +2,7 @@ require "spec_helper"
     
     describe AuthHelper do
       describe "button_based_providers" do
    -    it 'returns all enabled providers' do
    +    it 'returns all enabled providers from devise' do
           allow(helper).to receive(:auth_providers) { [:twitter, :github] }
           expect(helper.button_based_providers).to include(*[:twitter, :github])
         end
    @@ -17,4 +17,49 @@ describe AuthHelper do
           expect(helper.button_based_providers).to eq([])
         end
       end
    +
    +  describe 'enabled_button_based_providers' do
    +    before do
    +      allow(helper).to receive(:auth_providers) { [:twitter, :github] }
    +    end
    +
    +    context 'all providers are enabled to sign in' do
    +      it 'returns all the enabled providers from settings' do
    +        expect(helper.enabled_button_based_providers).to include('twitter', 'github')
    +      end
    +    end
    +
    +    context 'GitHub OAuth sign in is disabled from application setting' do
    +      it "doesn't return github as provider" do
    +        stub_application_setting(
    +          disabled_oauth_sign_in_sources: ['github']
    +        )
    +
    +        expect(helper.enabled_button_based_providers).to include('twitter')
    +        expect(helper.enabled_button_based_providers).not_to include('github')
    +      end
    +    end
    +  end
    +
    +  describe 'button_based_providers_enabled?' do
    +    before do
    +      allow(helper).to receive(:auth_providers) { [:twitter, :github] }
    +    end
    +
    +    context 'button based providers enabled' do
    +      it 'returns true' do
    +        expect(helper.button_based_providers_enabled?).to be true
    +      end
    +    end
    +
    +    context 'all the button based providers are disabled via application_setting' do
    +      it 'returns false' do
    +        stub_application_setting(
    +          disabled_oauth_sign_in_sources: ['github', 'twitter']
    +        )
    +
    +        expect(helper.button_based_providers_enabled?).to be false
    +      end
    +    end
    +  end
     end
    diff --git a/spec/helpers/diff_helper_spec.rb b/spec/helpers/diff_helper_spec.rb
    index b7810185d1..52764f41e0 100644
    --- a/spec/helpers/diff_helper_spec.rb
    +++ b/spec/helpers/diff_helper_spec.rb
    @@ -93,9 +93,9 @@ describe DiffHelper do
         it "returns strings with marked inline diffs" do
           marked_old_line, marked_new_line = mark_inline_diffs(old_line, new_line)
     
    -      expect(marked_old_line).to eq("abc 'def'")
    +      expect(marked_old_line).to eq("abc 'def'")
           expect(marked_old_line).to be_html_safe
    -      expect(marked_new_line).to eq("abc "def"")
    +      expect(marked_new_line).to eq("abc "def"")
           expect(marked_new_line).to be_html_safe
         end
       end
    diff --git a/spec/helpers/events_helper_spec.rb b/spec/helpers/events_helper_spec.rb
    index e68a5ec29a..c0d2be98e8 100644
    --- a/spec/helpers/events_helper_spec.rb
    +++ b/spec/helpers/events_helper_spec.rb
    @@ -1,64 +1,65 @@
     require 'spec_helper'
     
     describe EventsHelper do
    -  include ApplicationHelper
    -  include GitlabMarkdownHelper
    +  describe '#event_note' do
    +    before do
    +      allow(helper).to receive(:current_user).and_return(double)
    +    end
     
    -  let(:current_user) { create(:user, email: "current@email.com") }
    +    it 'should display one line of plain text without alteration' do
    +      input = 'A short, plain note'
    +      expect(helper.event_note(input)).to match(input)
    +      expect(helper.event_note(input)).not_to match(/\.\.\.\z/)
    +    end
     
    -  it 'should display one line of plain text without alteration' do
    -    input = 'A short, plain note'
    -    expect(event_note(input)).to match(input)
    -    expect(event_note(input)).not_to match(/\.\.\.\z/)
    -  end
    +    it 'should display inline code' do
    +      input = 'A note with `inline code`'
    +      expected = 'A note with inline code'
     
    -  it 'should display inline code' do
    -    input = 'A note with `inline code`'
    -    expected = 'A note with inline code'
    +      expect(helper.event_note(input)).to match(expected)
    +    end
     
    -    expect(event_note(input)).to match(expected)
    -  end
    +    it 'should truncate a note with multiple paragraphs' do
    +      input = "Paragraph 1\n\nParagraph 2"
    +      expected = 'Paragraph 1...'
     
    -  it 'should truncate a note with multiple paragraphs' do
    -    input = "Paragraph 1\n\nParagraph 2"
    -    expected = 'Paragraph 1...'
    +      expect(helper.event_note(input)).to match(expected)
    +    end
     
    -    expect(event_note(input)).to match(expected)
    -  end
    +    it 'should display the first line of a code block' do
    +      input = "```\nCode block\nwith two lines\n```"
    +      expected = %r{Code block\.\.\.
    } - it 'should display the first line of a code block' do - input = "```\nCode block\nwith two lines\n```" - expected = %r{Code block\.\.\.} + expect(helper.event_note(input)).to match(expected) + end - expect(event_note(input)).to match(expected) - end + it 'should truncate a single long line of text' do + text = 'The quick brown fox jumped over the lazy dog twice' # 50 chars + input = text * 4 + expected = (text * 2).sub(/.{3}/, '...') - it 'should truncate a single long line of text' do - text = 'The quick brown fox jumped over the lazy dog twice' # 50 chars - input = "#{text}#{text}#{text}#{text}" # 200 chars - expected = "#{text}#{text}".sub(/.{3}/, '...') + expect(helper.event_note(input)).to match(expected) + end - expect(event_note(input)).to match(expected) - end + it 'should preserve a link href when link text is truncated' do + text = 'The quick brown fox jumped over the lazy dog' # 44 chars + input = "#{text}#{text}#{text} " # 133 chars + link_url = 'http://example.com/foo/bar/baz' # 30 chars + input << link_url + expected_link_text = 'http://example...
    ' - it 'should preserve a link href when link text is truncated' do - text = 'The quick brown fox jumped over the lazy dog' # 44 chars - input = "#{text}#{text}#{text} " # 133 chars - link_url = 'http://example.com/foo/bar/baz' # 30 chars - input << link_url - expected_link_text = 'http://example...' + expect(helper.event_note(input)).to match(link_url) + expect(helper.event_note(input)).to match(expected_link_text) + end - expect(event_note(input)).to match(link_url) - expect(event_note(input)).to match(expected_link_text) - end - - it 'should preserve code color scheme' do - input = "```ruby\ndef test\n 'hello world'\nend\n```" - expected = '
    ' \
    -      "def test\n" \
    -      "  \'hello world\'\n" \
    -      "end" \
    -      '
    ' - expect(event_note(input)).to eq(expected) + it 'should preserve code color scheme' do + input = "```ruby\ndef test\n 'hello world'\nend\n```" + expected = '
    ' \
    +        "def test\n" \
    +        "  \'hello world\'\n" \
    +        "end" \
    +        '
    ' + expect(helper.event_note(input)).to eq(expected) + end end end diff --git a/spec/helpers/merge_requests_helper_spec.rb b/spec/helpers/merge_requests_helper_spec.rb index 600e1c4e9e..8e7ed42e88 100644 --- a/spec/helpers/merge_requests_helper_spec.rb +++ b/spec/helpers/merge_requests_helper_spec.rb @@ -17,7 +17,7 @@ describe MergeRequestsHelper do it 'does not include api credentials in a link' do allow(ci_service). to receive(:build_page).and_return("http://secretuser:secretpass@jenkins.example.com:8888/job/test1/scm/bySHA1/12d65c") - expect(helper.ci_build_details_path(merge_request)).to_not match("secret") + expect(helper.ci_build_details_path(merge_request)).not_to match("secret") end end diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb index 29bcb8c589..ac5af8740d 100644 --- a/spec/helpers/projects_helper_spec.rb +++ b/spec/helpers/projects_helper_spec.rb @@ -88,18 +88,18 @@ describe ProjectsHelper do end describe 'default_clone_protocol' do - describe 'using HTTP' do + context 'when user is not logged in and gitlab protocol is HTTP' do it 'returns HTTP' do - expect(helper).to receive(:current_user).and_return(nil) + allow(helper).to receive(:current_user).and_return(nil) expect(helper.send(:default_clone_protocol)).to eq('http') end end - describe 'using HTTPS' do + context 'when user is not logged in and gitlab protocol is HTTPS' do it 'returns HTTPS' do - allow(Gitlab.config.gitlab).to receive(:protocol).and_return('https') - expect(helper).to receive(:current_user).and_return(nil) + stub_config_setting(protocol: 'https') + allow(helper).to receive(:current_user).and_return(nil) expect(helper.send(:default_clone_protocol)).to eq('https') end diff --git a/spec/javascripts/fixtures/right_sidebar.html.haml b/spec/javascripts/fixtures/right_sidebar.html.haml new file mode 100644 index 0000000000..95efaff4b6 --- /dev/null +++ b/spec/javascripts/fixtures/right_sidebar.html.haml @@ -0,0 +1,13 @@ +%div + %div.page-gutter.page-with-sidebar + + %aside.right-sidebar + %div.block.issuable-sidebar-header + %a.gutter-toggle.pull-right.js-sidebar-toggle + %i.fa.fa-angle-double-left + + %form.issuable-context-form + %div.block.labels + %div.sidebar-collapsed-icon + %i.fa.fa-tags + %span 1 diff --git a/spec/javascripts/stat_graph_contributors_graph_spec.js b/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js similarity index 98% rename from spec/javascripts/stat_graph_contributors_graph_spec.js rename to spec/javascripts/graphs/stat_graph_contributors_graph_spec.js index 78d39f1b42..82ee1954a5 100644 --- a/spec/javascripts/stat_graph_contributors_graph_spec.js +++ b/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js @@ -1,4 +1,4 @@ -//= require stat_graph_contributors_graph +//= require graphs/stat_graph_contributors_graph describe("ContributorsGraph", function () { describe("#set_x_domain", function () { diff --git a/spec/javascripts/stat_graph_contributors_util_spec.js b/spec/javascripts/graphs/stat_graph_contributors_util_spec.js similarity index 99% rename from spec/javascripts/stat_graph_contributors_util_spec.js rename to spec/javascripts/graphs/stat_graph_contributors_util_spec.js index dbafe782b7..5b99244747 100644 --- a/spec/javascripts/stat_graph_contributors_util_spec.js +++ b/spec/javascripts/graphs/stat_graph_contributors_util_spec.js @@ -1,4 +1,4 @@ -//= require stat_graph_contributors_util +//= require graphs/stat_graph_contributors_util describe("ContributorsStatGraphUtil", function () { diff --git a/spec/javascripts/stat_graph_spec.js b/spec/javascripts/graphs/stat_graph_spec.js similarity index 92% rename from spec/javascripts/stat_graph_spec.js rename to spec/javascripts/graphs/stat_graph_spec.js index 4c652910cd..4b05d401a4 100644 --- a/spec/javascripts/stat_graph_spec.js +++ b/spec/javascripts/graphs/stat_graph_spec.js @@ -1,4 +1,4 @@ -//= require stat_graph +//= require graphs/stat_graph describe("StatGraph", function () { diff --git a/spec/javascripts/project_title_spec.js.coffee b/spec/javascripts/project_title_spec.js.coffee index 3d8de2ff98..1cf34d4d2d 100644 --- a/spec/javascripts/project_title_spec.js.coffee +++ b/spec/javascripts/project_title_spec.js.coffee @@ -1,5 +1,6 @@ #= require bootstrap #= require select2 +#= require lib/type_utility #= require gl_dropdown #= require api #= require project_select diff --git a/spec/javascripts/right_sidebar_spec.js.coffee b/spec/javascripts/right_sidebar_spec.js.coffee new file mode 100644 index 0000000000..2075cacdb6 --- /dev/null +++ b/spec/javascripts/right_sidebar_spec.js.coffee @@ -0,0 +1,69 @@ +#= require right_sidebar +#= require jquery +#= require jquery.cookie + +@sidebar = null +$aside = null +$toggle = null +$icon = null +$page = null +$labelsIcon = null + + +assertSidebarState = (state) -> + + shouldBeExpanded = state is 'expanded' + shouldBeCollapsed = state is 'collapsed' + + expect($aside.hasClass('right-sidebar-expanded')).toBe shouldBeExpanded + expect($page.hasClass('right-sidebar-expanded')).toBe shouldBeExpanded + expect($icon.hasClass('fa-angle-double-right')).toBe shouldBeExpanded + + expect($aside.hasClass('right-sidebar-collapsed')).toBe shouldBeCollapsed + expect($page.hasClass('right-sidebar-collapsed')).toBe shouldBeCollapsed + expect($icon.hasClass('fa-angle-double-left')).toBe shouldBeCollapsed + + +describe 'RightSidebar', -> + + fixture.preload 'right_sidebar.html' + + beforeEach -> + fixture.load 'right_sidebar.html' + + @sidebar = new Sidebar + $aside = $ '.right-sidebar' + $page = $ '.page-with-sidebar' + $icon = $aside.find 'i' + $toggle = $aside.find '.js-sidebar-toggle' + $labelsIcon = $aside.find '.sidebar-collapsed-icon' + + + it 'should expand the sidebar when arrow is clicked', -> + + $toggle.click() + assertSidebarState 'expanded' + + + it 'should collapse the sidebar when arrow is clicked', -> + + $toggle.click() + assertSidebarState 'expanded' + + $toggle.click() + assertSidebarState 'collapsed' + + + it 'should float over the page and when sidebar icons clicked', -> + + $labelsIcon.click() + assertSidebarState 'expanded' + + + it 'should collapse when the icon arrow clicked while it is floating on page', -> + + $labelsIcon.click() + assertSidebarState 'expanded' + + $toggle.click() + assertSidebarState 'collapsed' diff --git a/spec/lib/award_emoji_spec.rb b/spec/lib/award_emoji_spec.rb index 88c2291295..c309857429 100644 --- a/spec/lib/award_emoji_spec.rb +++ b/spec/lib/award_emoji_spec.rb @@ -5,7 +5,7 @@ describe AwardEmoji do subject { AwardEmoji.urls } it { is_expected.to be_an_instance_of(Array) } - it { is_expected.to_not be_empty } + it { is_expected.not_to be_empty } context 'every Hash in the Array' do it 'has the correct keys and values' do diff --git a/spec/lib/banzai/filter/commit_range_reference_filter_spec.rb b/spec/lib/banzai/filter/commit_range_reference_filter_spec.rb index c2a8ad36c3..593bd6d5ca 100644 --- a/spec/lib/banzai/filter/commit_range_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/commit_range_reference_filter_spec.rb @@ -98,11 +98,6 @@ describe Banzai::Filter::CommitRangeReferenceFilter, lib: true do expect(link).not_to match %r(https?://) expect(link).to eq urls.namespace_project_compare_url(project.namespace, project, from: commit1.id, to: commit2.id, only_path: true) end - - it 'adds to the results hash' do - result = reference_pipeline_result("See #{reference}") - expect(result[:references][:commit_range]).not_to be_empty - end end context 'cross-project reference' do @@ -135,11 +130,6 @@ describe Banzai::Filter::CommitRangeReferenceFilter, lib: true do exp = act = "Fixed #{project2.to_reference}@#{commit1.id}...#{commit2.id.reverse}" expect(reference_filter(act).to_html).to eq exp end - - it 'adds to the results hash' do - result = reference_pipeline_result("See #{reference}") - expect(result[:references][:commit_range]).not_to be_empty - end end context 'cross-project URL reference' do @@ -173,10 +163,5 @@ describe Banzai::Filter::CommitRangeReferenceFilter, lib: true do exp = act = "Fixed #{project2.to_reference}@#{commit1.id}...#{commit2.id.reverse}" expect(reference_filter(act).to_html).to eq exp end - - it 'adds to the results hash' do - result = reference_pipeline_result("See #{reference}") - expect(result[:references][:commit_range]).not_to be_empty - end end end diff --git a/spec/lib/banzai/filter/commit_reference_filter_spec.rb b/spec/lib/banzai/filter/commit_reference_filter_spec.rb index 63a32d9d45..d46d3f1489 100644 --- a/spec/lib/banzai/filter/commit_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/commit_reference_filter_spec.rb @@ -93,11 +93,6 @@ describe Banzai::Filter::CommitReferenceFilter, lib: true do expect(link).not_to match %r(https?://) expect(link).to eq urls.namespace_project_commit_url(project.namespace, project, reference, only_path: true) end - - it 'adds to the results hash' do - result = reference_pipeline_result("See #{reference}") - expect(result[:references][:commit]).not_to be_empty - end end context 'cross-project reference' do @@ -124,11 +119,6 @@ describe Banzai::Filter::CommitReferenceFilter, lib: true do exp = act = "Committed #{invalidate_reference(reference)}" expect(reference_filter(act).to_html).to eq exp end - - it 'adds to the results hash' do - result = reference_pipeline_result("See #{reference}") - expect(result[:references][:commit]).not_to be_empty - end end context 'cross-project URL reference' do @@ -154,10 +144,5 @@ describe Banzai::Filter::CommitReferenceFilter, lib: true do act = "Committed #{invalidate_reference(reference)}" expect(reference_filter(act).to_html).to match(/#{Regexp.escape(invalidate_reference(reference))}<\/a>/) end - - it 'adds to the results hash' do - result = reference_pipeline_result("See #{reference}") - expect(result[:references][:commit]).not_to be_empty - end end end diff --git a/spec/lib/banzai/filter/inline_diff_filter_spec.rb b/spec/lib/banzai/filter/inline_diff_filter_spec.rb new file mode 100644 index 0000000000..9e52637129 --- /dev/null +++ b/spec/lib/banzai/filter/inline_diff_filter_spec.rb @@ -0,0 +1,68 @@ +require 'spec_helper' + +describe Banzai::Filter::InlineDiffFilter, lib: true do + include FilterSpecHelper + + it 'adds inline diff span tags for deletions when using square brackets' do + doc = "START [-something deleted-] END" + expect(filter(doc).to_html).to eq('START something deleted END') + end + + it 'adds inline diff span tags for deletions when using curley braces' do + doc = "START {-something deleted-} END" + expect(filter(doc).to_html).to eq('START something deleted END') + end + + it 'does not add inline diff span tags when a closing tag is not provided' do + doc = "START [- END" + expect(filter(doc).to_html).to eq(doc) + end + + it 'adds inline span tags for additions when using square brackets' do + doc = "START [+something added+] END" + expect(filter(doc).to_html).to eq('START something added END') + end + + it 'adds inline span tags for additions when using curley braces' do + doc = "START {+something added+} END" + expect(filter(doc).to_html).to eq('START something added END') + end + + it 'does not add inline diff span tags when a closing addition tag is not provided' do + doc = "START {+ END" + expect(filter(doc).to_html).to eq(doc) + end + + it 'does not add inline diff span tags when the tags do not match' do + examples = [ + "{+ additions +]", + "[+ additions +}", + "{- delletions -]", + "[- delletions -}" + ] + + examples.each do |doc| + expect(filter(doc).to_html).to eq(doc) + end + end + + it 'prevents user-land html being injected' do + doc = "START {+<script>alert('I steal cookies')</script>+} END" + expect(filter(doc).to_html).to eq("START <script>alert('I steal cookies')</script> END") + end + + it 'preserves content inside pre tags' do + doc = "
    START {+something added+} END
    " + expect(filter(doc).to_html).to eq(doc) + end + + it 'preserves content inside code tags' do + doc = "START {+something added+} END" + expect(filter(doc).to_html).to eq(doc) + end + + it 'preserves content inside tt tags' do + doc = "START {+something added+} END" + expect(filter(doc).to_html).to eq(doc) + 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 266ebef33d..8e6a264970 100644 --- a/spec/lib/banzai/filter/issue_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/issue_reference_filter_spec.rb @@ -91,11 +91,6 @@ describe Banzai::Filter::IssueReferenceFilter, lib: true do expect(link).to eq helper.url_for_issue(issue.iid, project, only_path: true) end - it 'adds to the results hash' do - result = reference_pipeline_result("Fixed #{reference}") - expect(result[:references][:issue]).to eq [issue] - end - it 'does not process links containing issue numbers followed by text' do href = "#{reference}st" doc = reference_filter("") @@ -136,11 +131,6 @@ describe Banzai::Filter::IssueReferenceFilter, lib: true do expect(reference_filter(act).to_html).to eq exp end - - it 'adds to the results hash' do - result = reference_pipeline_result("Fixed #{reference}") - expect(result[:references][:issue]).to eq [issue] - end end context 'cross-project URL reference' do @@ -160,11 +150,6 @@ describe Banzai::Filter::IssueReferenceFilter, lib: true do doc = reference_filter("Fixed (#{reference}.)") expect(doc.to_html).to match(/\(#{Regexp.escape(issue.to_reference(project))} \(comment 123\)<\/a>\.\)/) end - - it 'adds to the results hash' do - result = reference_pipeline_result("Fixed #{reference}") - expect(result[:references][:issue]).to eq [issue] - end end context 'cross-project reference in link href' do @@ -184,11 +169,6 @@ describe Banzai::Filter::IssueReferenceFilter, lib: true do doc = reference_filter("Fixed (#{reference}.)") expect(doc.to_html).to match(/\(Reference<\/a>\.\)/) end - - it 'adds to the results hash' do - result = reference_pipeline_result("Fixed #{reference}") - expect(result[:references][:issue]).to eq [issue] - end end context 'cross-project URL in link href' do @@ -208,10 +188,5 @@ describe Banzai::Filter::IssueReferenceFilter, lib: true do doc = reference_filter("Fixed (#{reference}.)") expect(doc.to_html).to match(/\(Reference<\/a>\.\)/) end - - it 'adds to the results hash' do - result = reference_pipeline_result("Fixed #{reference}") - expect(result[:references][:issue]).to eq [issue] - end end end diff --git a/spec/lib/banzai/filter/label_reference_filter_spec.rb b/spec/lib/banzai/filter/label_reference_filter_spec.rb index b0a38e7c25..f1064a701d 100644 --- a/spec/lib/banzai/filter/label_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/label_reference_filter_spec.rb @@ -48,11 +48,6 @@ describe Banzai::Filter::LabelReferenceFilter, lib: true do expect(link).to eq urls.namespace_project_issues_path(project.namespace, project, label_name: label.name) end - it 'adds to the results hash' do - result = reference_pipeline_result("Label #{reference}") - expect(result[:references][:label]).to eq [label] - end - describe 'label span element' do it 'includes default classes' do doc = reference_filter("Label #{reference}") @@ -170,11 +165,6 @@ describe Banzai::Filter::LabelReferenceFilter, lib: true do expect(link).to have_attribute('data-label') expect(link.attr('data-label')).to eq label.id.to_s end - - it 'adds to the results hash' do - result = reference_pipeline_result("Label #{reference}") - expect(result[:references][:label]).to eq [label] - end end describe 'cross project label references' do diff --git a/spec/lib/banzai/filter/merge_request_reference_filter_spec.rb b/spec/lib/banzai/filter/merge_request_reference_filter_spec.rb index 352710df30..3185e41fe5 100644 --- a/spec/lib/banzai/filter/merge_request_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/merge_request_reference_filter_spec.rb @@ -78,11 +78,6 @@ describe Banzai::Filter::MergeRequestReferenceFilter, lib: true do expect(link).not_to match %r(https?://) expect(link).to eq urls.namespace_project_merge_request_url(project.namespace, project, merge, only_path: true) end - - it 'adds to the results hash' do - result = reference_pipeline_result("Merge #{reference}") - expect(result[:references][:merge_request]).to eq [merge] - end end context 'cross-project reference' do @@ -109,11 +104,6 @@ describe Banzai::Filter::MergeRequestReferenceFilter, lib: true do expect(reference_filter(act).to_html).to eq exp end - - it 'adds to the results hash' do - result = reference_pipeline_result("Merge #{reference}") - expect(result[:references][:merge_request]).to eq [merge] - end end context 'cross-project URL reference' do @@ -133,10 +123,5 @@ describe Banzai::Filter::MergeRequestReferenceFilter, lib: true do doc = reference_filter("Merge (#{reference}.)") expect(doc.to_html).to match(/\(#{Regexp.escape(merge.to_reference(project))} \(diffs, comment 123\)<\/a>\.\)/) end - - it 'adds to the results hash' do - result = reference_pipeline_result("Merge #{reference}") - expect(result[:references][:merge_request]).to eq [merge] - end end end diff --git a/spec/lib/banzai/filter/milestone_reference_filter_spec.rb b/spec/lib/banzai/filter/milestone_reference_filter_spec.rb index ebf3d7489b..9424f2363e 100644 --- a/spec/lib/banzai/filter/milestone_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/milestone_reference_filter_spec.rb @@ -3,8 +3,9 @@ require 'spec_helper' describe Banzai::Filter::MilestoneReferenceFilter, lib: true do include FilterSpecHelper - let(:project) { create(:project, :public) } - let(:milestone) { create(:milestone, project: project) } + let(:project) { create(:project, :public) } + let(:milestone) { create(:milestone, project: project) } + let(:reference) { milestone.to_reference } it 'requires project context' do expect { described_class.call('') }.to raise_error(ArgumentError, /:project/) @@ -17,10 +18,106 @@ describe Banzai::Filter::MilestoneReferenceFilter, lib: true do end end - context 'internal reference' do - # Convert the Markdown link to only the URL, since these tests aren't run through the regular Markdown pipeline. - # Milestone reference behavior in the full Markdown pipeline is tested elsewhere. - let(:reference) { milestone.to_reference.gsub(/\[([^\]]+)\]\(([^)]+)\)/, '\2') } + it 'includes default classes' do + doc = reference_filter("Milestone #{reference}") + expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-milestone' + end + + it 'includes a data-project attribute' do + doc = reference_filter("Milestone #{reference}") + link = doc.css('a').first + + expect(link).to have_attribute('data-project') + expect(link.attr('data-project')).to eq project.id.to_s + end + + it 'includes a data-milestone attribute' do + doc = reference_filter("See #{reference}") + link = doc.css('a').first + + expect(link).to have_attribute('data-milestone') + expect(link.attr('data-milestone')).to eq milestone.id.to_s + end + + it 'supports an :only_path context' do + doc = reference_filter("Milestone #{reference}", only_path: true) + link = doc.css('a').first.attr('href') + + expect(link).not_to match %r(https?://) + expect(link).to eq urls. + namespace_project_milestone_path(project.namespace, project, milestone) + end + + context 'Integer-based references' do + it 'links to a valid reference' do + doc = reference_filter("See #{reference}") + + expect(doc.css('a').first.attr('href')).to eq urls. + namespace_project_milestone_url(project.namespace, project, milestone) + end + + it 'links with adjacent text' do + doc = reference_filter("Milestone (#{reference}.)") + expect(doc.to_html).to match(%r(\(#{milestone.name}\.\))) + end + + it 'ignores invalid milestone IIDs' do + exp = act = "Milestone #{invalidate_reference(reference)}" + + expect(reference_filter(act).to_html).to eq exp + end + end + + context 'String-based single-word references' do + let(:milestone) { create(:milestone, name: 'gfm', project: project) } + let(:reference) { "#{Milestone.reference_prefix}#{milestone.name}" } + + it 'links to a valid reference' do + doc = reference_filter("See #{reference}") + + expect(doc.css('a').first.attr('href')).to eq urls. + namespace_project_milestone_url(project.namespace, project, milestone) + expect(doc.text).to eq 'See gfm' + end + + it 'links with adjacent text' do + doc = reference_filter("Milestone (#{reference}.)") + expect(doc.to_html).to match(%r(\(#{milestone.name}\.\))) + end + + it 'ignores invalid milestone names' do + exp = act = "Milestone #{Milestone.reference_prefix}#{milestone.name.reverse}" + + expect(reference_filter(act).to_html).to eq exp + end + end + + context 'String-based multi-word references in quotes' do + let(:milestone) { create(:milestone, name: 'gfm references', project: project) } + let(:reference) { milestone.to_reference(format: :name) } + + it 'links to a valid reference' do + doc = reference_filter("See #{reference}") + + expect(doc.css('a').first.attr('href')).to eq urls. + namespace_project_milestone_url(project.namespace, project, milestone) + expect(doc.text).to eq 'See gfm references' + end + + it 'links with adjacent text' do + doc = reference_filter("Milestone (#{reference}.)") + expect(doc.to_html).to match(%r(\(#{milestone.name}\.\))) + end + + it 'ignores invalid milestone names' do + exp = act = %(Milestone #{Milestone.reference_prefix}"#{milestone.name.reverse}") + + expect(reference_filter(act).to_html).to eq exp + end + end + + describe 'referencing a milestone in a link href' do + let(:reference) { %Q{Milestone} } it 'links to a valid reference' do doc = reference_filter("See #{reference}") @@ -30,29 +127,12 @@ describe Banzai::Filter::MilestoneReferenceFilter, lib: true do end it 'links with adjacent text' do - doc = reference_filter("milestone (#{reference}.)") - expect(doc.to_html).to match(/\(#{Regexp.escape(milestone.title)}<\/a>\.\)/) - end - - it 'includes a title attribute' do - doc = reference_filter("milestone #{reference}") - expect(doc.css('a').first.attr('title')).to eq "Milestone: #{milestone.title}" - end - - it 'escapes the title attribute' do - milestone.update_attribute(:title, %{">whateverMilestone\.\))) end it 'includes a data-project attribute' do - doc = reference_filter("milestone #{reference}") + doc = reference_filter("Milestone #{reference}") link = doc.css('a').first expect(link).to have_attribute('data-project') @@ -66,10 +146,31 @@ describe Banzai::Filter::MilestoneReferenceFilter, lib: true do expect(link).to have_attribute('data-milestone') expect(link.attr('data-milestone')).to eq milestone.id.to_s end + end - it 'adds to the results hash' do - result = reference_pipeline_result("milestone #{reference}") - expect(result[:references][:milestone]).to eq [milestone] + describe 'cross project milestone references' do + let(:another_project) { create(:empty_project, :public) } + let(:project_path) { another_project.path_with_namespace } + let(:milestone) { create(:milestone, project: another_project) } + let(:reference) { milestone.to_reference(project) } + + let!(:result) { reference_filter("See #{reference}") } + + it 'points to referenced project milestone page' do + expect(result.css('a').first.attr('href')).to eq urls. + namespace_project_milestone_url(another_project.namespace, + another_project, + milestone) + end + + it 'contains cross project content' do + expect(result.css('a').first.text).to eq "#{milestone.name} in #{project_path}" + end + + it 'escapes the name attribute' do + allow_any_instance_of(Milestone).to receive(:title).and_return(%{">whateverText) + exp = 'Text' + expect(filter(act).to_html).to eq exp + end + it 'allows whitelisted HTML tags from the user' do exp = act = "
    \n
    Term
    \n
    Definition
    \n
    " expect(filter(act).to_html).to eq exp diff --git a/spec/lib/banzai/filter/snippet_reference_filter_spec.rb b/spec/lib/banzai/filter/snippet_reference_filter_spec.rb index 26466fbb18..5068ddd7fa 100644 --- a/spec/lib/banzai/filter/snippet_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/snippet_reference_filter_spec.rb @@ -77,11 +77,6 @@ describe Banzai::Filter::SnippetReferenceFilter, lib: true do expect(link).not_to match %r(https?://) expect(link).to eq urls.namespace_project_snippet_url(project.namespace, project, snippet, only_path: true) end - - it 'adds to the results hash' do - result = reference_pipeline_result("Snippet #{reference}") - expect(result[:references][:snippet]).to eq [snippet] - end end context 'cross-project reference' do @@ -107,11 +102,6 @@ describe Banzai::Filter::SnippetReferenceFilter, lib: true do expect(reference_filter(act).to_html).to eq exp end - - it 'adds to the results hash' do - result = reference_pipeline_result("Snippet #{reference}") - expect(result[:references][:snippet]).to eq [snippet] - end end context 'cross-project URL reference' do @@ -137,10 +127,5 @@ describe Banzai::Filter::SnippetReferenceFilter, lib: true do expect(reference_filter(act).to_html).to match(/#{Regexp.escape(invalidate_reference(reference))}<\/a>/) end - - it 'adds to the results hash' do - result = reference_pipeline_result("Snippet #{reference}") - expect(result[:references][:snippet]).to eq [snippet] - end end end diff --git a/spec/lib/banzai/filter/upload_link_filter_spec.rb b/spec/lib/banzai/filter/upload_link_filter_spec.rb index 3b073a90a9..b83be54746 100644 --- a/spec/lib/banzai/filter/upload_link_filter_spec.rb +++ b/spec/lib/banzai/filter/upload_link_filter_spec.rb @@ -8,6 +8,10 @@ describe Banzai::Filter::UploadLinkFilter, lib: true do project: project }) + raw_filter(doc, contexts) + end + + def raw_filter(doc, contexts = {}) described_class.call(doc, contexts) end @@ -70,4 +74,18 @@ describe Banzai::Filter::UploadLinkFilter, lib: true do expect(doc.at_css('img')['src']).to match "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/uploads/%ED%95%9C%EA%B8%80.png" end end + + context 'when project context does not exist' do + let(:upload_link) { link('/uploads/e90decf88d8f96fe9e1389afc2e4a91f/test.jpg') } + + it 'does not raise error' do + expect { raw_filter(upload_link, project: nil) }.not_to raise_error + end + + it 'does not rewrite link' do + doc = raw_filter(upload_link, project: nil) + + expect(doc.to_html).to eq upload_link + end + end end diff --git a/spec/lib/banzai/filter/user_reference_filter_spec.rb b/spec/lib/banzai/filter/user_reference_filter_spec.rb index 8bdebae184..d7dfd6699e 100644 --- a/spec/lib/banzai/filter/user_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/user_reference_filter_spec.rb @@ -31,28 +31,22 @@ describe Banzai::Filter::UserReferenceFilter, lib: true do end it 'supports a special @all mention' do - doc = reference_filter("Hey #{reference}") + doc = reference_filter("Hey #{reference}", author: user) expect(doc.css('a').length).to eq 1 expect(doc.css('a').first.attr('href')) .to eq urls.namespace_project_url(project.namespace, project) end - context "when the author is a member of the project" do + it 'includes a data-author attribute when there is an author' do + doc = reference_filter(reference, author: user) - it 'adds to the results hash' do - result = reference_pipeline_result("Hey #{reference}", author: project.creator) - expect(result[:references][:user]).to eq [project.creator] - end + expect(doc.css('a').first.attr('data-author')).to eq(user.id.to_s) end - context "when the author is not a member of the project" do + it 'does not include a data-author attribute when there is no author' do + doc = reference_filter(reference) - let(:other_user) { create(:user) } - - it "doesn't add to the results hash" do - result = reference_pipeline_result("Hey #{reference}", author: other_user) - expect(result[:references][:user]).to eq [] - end + expect(doc.css('a').first.has_attribute?('data-author')).to eq(false) end end @@ -83,11 +77,6 @@ describe Banzai::Filter::UserReferenceFilter, lib: true do expect(link).to have_attribute('data-user') expect(link.attr('data-user')).to eq user.namespace.owner_id.to_s end - - it 'adds to the results hash' do - result = reference_pipeline_result("Hey #{reference}") - expect(result[:references][:user]).to eq [user] - end end context 'mentioning a group' do @@ -106,11 +95,6 @@ describe Banzai::Filter::UserReferenceFilter, lib: true do expect(link).to have_attribute('data-group') expect(link.attr('data-group')).to eq group.id.to_s end - - it 'adds to the results hash' do - result = reference_pipeline_result("Hey #{reference}") - expect(result[:references][:user]).to eq group.users - end end it 'links with adjacent text' do @@ -151,10 +135,5 @@ describe Banzai::Filter::UserReferenceFilter, lib: true do expect(link).to have_attribute('data-user') expect(link.attr('data-user')).to eq user.namespace.owner_id.to_s end - - it 'adds to the results hash' do - result = reference_pipeline_result("Hey #{reference}") - expect(result[:references][:user]).to eq [user] - end end end diff --git a/spec/lib/banzai/filter/wiki_link_filter_spec.rb b/spec/lib/banzai/filter/wiki_link_filter_spec.rb new file mode 100644 index 0000000000..185abbb210 --- /dev/null +++ b/spec/lib/banzai/filter/wiki_link_filter_spec.rb @@ -0,0 +1,85 @@ +require 'spec_helper' + +describe Banzai::Filter::WikiLinkFilter, lib: true do + include FilterSpecHelper + + let(:namespace) { build_stubbed(:namespace, name: "wiki_link_ns") } + let(:project) { build_stubbed(:empty_project, :public, name: "wiki_link_project", namespace: namespace) } + let(:user) { double } + let(:project_wiki) { ProjectWiki.new(project, user) } + + describe "links within the wiki (relative)" do + describe "hierarchical links to the current directory" do + it "doesn't rewrite non-file links" do + link = "Link to Page" + filtered_link = filter(link, project_wiki: project_wiki).children[0] + + expect(filtered_link.attribute('href').value).to eq('./page') + end + + it "doesn't rewrite file links" do + link = "Link to Page" + filtered_link = filter(link, project_wiki: project_wiki).children[0] + + expect(filtered_link.attribute('href').value).to eq('./page.md') + end + end + + describe "hierarchical links to the parent directory" do + it "doesn't rewrite non-file links" do + link = "Link to Page" + filtered_link = filter(link, project_wiki: project_wiki).children[0] + + expect(filtered_link.attribute('href').value).to eq('../page') + end + + it "doesn't rewrite file links" do + link = "Link to Page" + filtered_link = filter(link, project_wiki: project_wiki).children[0] + + expect(filtered_link.attribute('href').value).to eq('../page.md') + end + end + + describe "hierarchical links to a sub-directory" do + it "doesn't rewrite non-file links" do + link = "Link to Page" + filtered_link = filter(link, project_wiki: project_wiki).children[0] + + expect(filtered_link.attribute('href').value).to eq('./subdirectory/page') + end + + it "doesn't rewrite file links" do + link = "Link to Page" + filtered_link = filter(link, project_wiki: project_wiki).children[0] + + expect(filtered_link.attribute('href').value).to eq('./subdirectory/page.md') + end + end + + describe "non-hierarchical links" do + it 'rewrites non-file links to be at the scope of the wiki root' do + link = "Link to Page" + filtered_link = filter(link, project_wiki: project_wiki).children[0] + + expect(filtered_link.attribute('href').value).to match('/wiki_link_ns/wiki_link_project/wikis/page') + end + + it "doesn't rewrite file links" do + link = "Link to Page" + filtered_link = filter(link, project_wiki: project_wiki).children[0] + + expect(filtered_link.attribute('href').value).to eq('page.md') + end + end + end + + describe "links outside the wiki (absolute)" do + it "doesn't rewrite links" do + link = "Link to Page" + filtered_link = filter(link, project_wiki: project_wiki).children[0] + + expect(filtered_link.attribute('href').value).to eq('http://example.com/page') + end + end +end diff --git a/spec/lib/banzai/reference_parser/base_parser_spec.rb b/spec/lib/banzai/reference_parser/base_parser_spec.rb new file mode 100644 index 0000000000..543b4786d8 --- /dev/null +++ b/spec/lib/banzai/reference_parser/base_parser_spec.rb @@ -0,0 +1,237 @@ +require 'spec_helper' + +describe Banzai::ReferenceParser::BaseParser, lib: true do + include ReferenceParserHelpers + + let(:user) { create(:user) } + let(:project) { create(:empty_project, :public) } + + subject do + klass = Class.new(described_class) do + self.reference_type = :foo + end + + klass.new(project, user) + end + + describe '.reference_type=' do + it 'sets the reference type' do + dummy = Class.new(described_class) + dummy.reference_type = :foo + + expect(dummy.reference_type).to eq(:foo) + end + end + + describe '#nodes_visible_to_user' do + let(:link) { empty_html_link } + + context 'when the link has a data-project attribute' do + it 'returns the nodes if the attribute value equals the current project ID' do + link['data-project'] = project.id.to_s + + expect(Ability.abilities).not_to receive(:allowed?) + expect(subject.nodes_visible_to_user(user, [link])).to eq([link]) + end + + it 'returns the nodes if the user can read the project' do + other_project = create(:empty_project, :public) + + link['data-project'] = other_project.id.to_s + + expect(Ability.abilities).to receive(:allowed?). + with(user, :read_project, other_project). + and_return(true) + + expect(subject.nodes_visible_to_user(user, [link])).to eq([link]) + end + + it 'returns an empty Array when the attribute value is empty' do + link['data-project'] = '' + + expect(subject.nodes_visible_to_user(user, [link])).to eq([]) + end + + it 'returns an empty Array when the user can not read the project' do + other_project = create(:empty_project, :public) + + link['data-project'] = other_project.id.to_s + + expect(Ability.abilities).to receive(:allowed?). + with(user, :read_project, other_project). + and_return(false) + + expect(subject.nodes_visible_to_user(user, [link])).to eq([]) + end + end + + context 'when the link does not have a data-project attribute' do + it 'returns the nodes' do + expect(subject.nodes_visible_to_user(user, [link])).to eq([link]) + end + end + end + + describe '#nodes_user_can_reference' do + it 'returns the nodes' do + link = double(:link) + + expect(subject.nodes_user_can_reference(user, [link])).to eq([link]) + end + end + + describe '#referenced_by' do + context 'when references_relation is implemented' do + it 'returns a collection of objects' do + links = Nokogiri::HTML.fragment(""). + children + + expect(subject).to receive(:references_relation).and_return(User) + expect(subject.referenced_by(links)).to eq([user]) + end + end + + context 'when references_relation is not implemented' do + it 'raises NotImplementedError' do + links = Nokogiri::HTML.fragment('').children + + expect { subject.referenced_by(links) }. + to raise_error(NotImplementedError) + end + end + end + + describe '#references_relation' do + it 'raises NotImplementedError' do + expect { subject.references_relation }.to raise_error(NotImplementedError) + end + end + + describe '#gather_attributes_per_project' do + it 'returns a Hash containing attribute values per project' do + link = Nokogiri::HTML.fragment(''). + children[0] + + hash = subject.gather_attributes_per_project([link], 'data-foo') + + expect(hash).to be_an_instance_of(Hash) + + expect(hash[1].to_a).to eq(['2']) + end + end + + describe '#grouped_objects_for_nodes' do + it 'returns a Hash grouping objects per ID' do + nodes = [double(:node)] + + expect(subject).to receive(:unique_attribute_values). + with(nodes, 'data-user'). + and_return([user.id]) + + hash = subject.grouped_objects_for_nodes(nodes, User, 'data-user') + + expect(hash).to eq({ user.id => user }) + end + + it 'returns an empty Hash when the list of nodes is empty' do + expect(subject.grouped_objects_for_nodes([], User, 'data-user')).to eq({}) + end + end + + describe '#unique_attribute_values' do + it 'returns an Array of unique values' do + link = double(:link) + + expect(link).to receive(:has_attribute?). + with('data-foo'). + twice. + and_return(true) + + expect(link).to receive(:attr). + with('data-foo'). + twice. + and_return('1') + + nodes = [link, link] + + expect(subject.unique_attribute_values(nodes, 'data-foo')).to eq(['1']) + end + end + + describe '#process' do + it 'gathers the references for every node matching the reference type' do + dummy = Class.new(described_class) do + self.reference_type = :test + end + + instance = dummy.new(project, user) + document = Nokogiri::HTML.fragment('') + + expect(instance).to receive(:gather_references). + with([document.children[1]]). + and_return([user]) + + expect(instance.process([document])).to eq([user]) + end + end + + describe '#gather_references' do + let(:link) { double(:link) } + + it 'does not process links a user can not reference' do + expect(subject).to receive(:nodes_user_can_reference). + with(user, [link]). + and_return([]) + + expect(subject).to receive(:referenced_by).with([]) + + subject.gather_references([link]) + end + + it 'does not process links a user can not see' do + expect(subject).to receive(:nodes_user_can_reference). + with(user, [link]). + and_return([link]) + + expect(subject).to receive(:nodes_visible_to_user). + with(user, [link]). + and_return([]) + + expect(subject).to receive(:referenced_by).with([]) + + subject.gather_references([link]) + end + + it 'returns the references if a user can reference and see a link' do + expect(subject).to receive(:nodes_user_can_reference). + with(user, [link]). + and_return([link]) + + expect(subject).to receive(:nodes_visible_to_user). + with(user, [link]). + and_return([link]) + + expect(subject).to receive(:referenced_by).with([link]) + + subject.gather_references([link]) + end + end + + describe '#can?' do + it 'delegates the permissions check to the Ability class' do + user = double(:user) + + expect(Ability.abilities).to receive(:allowed?). + with(user, :read_project, project) + + subject.can?(user, :read_project, project) + end + end + + describe '#find_projects_for_hash_keys' do + it 'returns a list of Projects' do + expect(subject.find_projects_for_hash_keys(project.id => project)). + to eq([project]) + end + end +end diff --git a/spec/lib/banzai/reference_parser/commit_parser_spec.rb b/spec/lib/banzai/reference_parser/commit_parser_spec.rb new file mode 100644 index 0000000000..0b76d29fce --- /dev/null +++ b/spec/lib/banzai/reference_parser/commit_parser_spec.rb @@ -0,0 +1,113 @@ +require 'spec_helper' + +describe Banzai::ReferenceParser::CommitParser, lib: true do + include ReferenceParserHelpers + + let(:project) { create(:empty_project, :public) } + let(:user) { create(:user) } + subject { described_class.new(project, user) } + let(:link) { empty_html_link } + + describe '#referenced_by' do + context 'when the link has a data-project attribute' do + before do + link['data-project'] = project.id.to_s + end + + context 'when the link has a data-commit attribute' do + before do + link['data-commit'] = '123' + end + + it 'returns an Array of commits' do + commit = double(:commit) + + allow_any_instance_of(Project).to receive(:valid_repo?). + and_return(true) + + expect(subject).to receive(:find_commits). + with(project, ['123']). + and_return([commit]) + + expect(subject.referenced_by([link])).to eq([commit]) + end + + it 'returns an empty Array when the commit could not be found' do + allow_any_instance_of(Project).to receive(:valid_repo?). + and_return(true) + + expect(subject).to receive(:find_commits). + with(project, ['123']). + and_return([]) + + expect(subject.referenced_by([link])).to eq([]) + end + + it 'skips projects without valid repositories' do + allow_any_instance_of(Project).to receive(:valid_repo?). + and_return(false) + + expect(subject.referenced_by([link])).to eq([]) + end + end + + context 'when the link does not have a data-commit attribute' do + it 'returns an empty Array' do + allow_any_instance_of(Project).to receive(:valid_repo?). + and_return(true) + + expect(subject.referenced_by([link])).to eq([]) + end + end + end + + context 'when the link does not have a data-project attribute' do + it 'returns an empty Array' do + allow_any_instance_of(Project).to receive(:valid_repo?). + and_return(true) + + expect(subject.referenced_by([link])).to eq([]) + end + end + end + + describe '#commit_ids_per_project' do + before do + link['data-project'] = project.id.to_s + end + + it 'returns a Hash containing commit IDs per project' do + link['data-commit'] = '123' + + hash = subject.commit_ids_per_project([link]) + + expect(hash).to be_an_instance_of(Hash) + + expect(hash[project.id].to_a).to eq(['123']) + end + + it 'does not add a project when the data-commit attribute is empty' do + hash = subject.commit_ids_per_project([link]) + + expect(hash).to be_empty + end + end + + describe '#find_commits' do + it 'returns an Array of commit objects' do + commit = double(:commit) + + expect(project).to receive(:commit).with('123').and_return(commit) + expect(project).to receive(:valid_repo?).and_return(true) + + expect(subject.find_commits(project, %w{123})).to eq([commit]) + end + + it 'skips commit IDs for which no commit could be found' do + expect(project).to receive(:commit).with('123').and_return(nil) + expect(project).to receive(:valid_repo?).and_return(true) + + expect(subject.find_commits(project, %w{123})).to eq([]) + end + end +end diff --git a/spec/lib/banzai/reference_parser/commit_range_parser_spec.rb b/spec/lib/banzai/reference_parser/commit_range_parser_spec.rb new file mode 100644 index 0000000000..ba982f3854 --- /dev/null +++ b/spec/lib/banzai/reference_parser/commit_range_parser_spec.rb @@ -0,0 +1,120 @@ +require 'spec_helper' + +describe Banzai::ReferenceParser::CommitRangeParser, lib: true do + include ReferenceParserHelpers + + let(:project) { create(:empty_project, :public) } + let(:user) { create(:user) } + subject { described_class.new(project, user) } + let(:link) { empty_html_link } + + describe '#referenced_by' do + context 'when the link has a data-project attribute' do + before do + link['data-project'] = project.id.to_s + end + + context 'when the link as a data-commit-range attribute' do + before do + link['data-commit-range'] = '123..456' + end + + it 'returns an Array of commit ranges' do + range = double(:range) + + expect(subject).to receive(:find_object). + with(project, '123..456'). + and_return(range) + + expect(subject.referenced_by([link])).to eq([range]) + end + + it 'returns an empty Array when the commit range could not be found' do + expect(subject).to receive(:find_object). + with(project, '123..456'). + and_return(nil) + + expect(subject.referenced_by([link])).to eq([]) + end + end + + context 'when the link does not have a data-commit-range attribute' do + it 'returns an empty Array' do + expect(subject.referenced_by([link])).to eq([]) + end + end + end + + context 'when the link does not have a data-project attribute' do + it 'returns an empty Array' do + expect(subject.referenced_by([link])).to eq([]) + end + end + end + + describe '#commit_range_ids_per_project' do + before do + link['data-project'] = project.id.to_s + end + + it 'returns a Hash containing range IDs per project' do + link['data-commit-range'] = '123..456' + + hash = subject.commit_range_ids_per_project([link]) + + expect(hash).to be_an_instance_of(Hash) + + expect(hash[project.id].to_a).to eq(['123..456']) + end + + it 'does not add a project when the data-commit-range attribute is empty' do + hash = subject.commit_range_ids_per_project([link]) + + expect(hash).to be_empty + end + end + + describe '#find_ranges' do + it 'returns an Array of range objects' do + range = double(:commit) + + expect(subject).to receive(:find_object). + with(project, '123..456'). + and_return(range) + + expect(subject.find_ranges(project, ['123..456'])).to eq([range]) + end + + it 'skips ranges that could not be found' do + expect(subject).to receive(:find_object). + with(project, '123..456'). + and_return(nil) + + expect(subject.find_ranges(project, ['123..456'])).to eq([]) + end + end + + describe '#find_object' do + let(:range) { double(:range) } + + before do + expect(CommitRange).to receive(:new).and_return(range) + end + + context 'when the range has valid commits' do + it 'returns the commit range' do + expect(range).to receive(:valid_commits?).and_return(true) + + expect(subject.find_object(project, '123..456')).to eq(range) + end + end + + context 'when the range does not have any valid commits' do + it 'returns nil' do + expect(range).to receive(:valid_commits?).and_return(false) + + expect(subject.find_object(project, '123..456')).to be_nil + end + end + end +end diff --git a/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb b/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb new file mode 100644 index 0000000000..a6ef8394fe --- /dev/null +++ b/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb @@ -0,0 +1,62 @@ +require 'spec_helper' + +describe Banzai::ReferenceParser::ExternalIssueParser, lib: true do + include ReferenceParserHelpers + + let(:project) { create(:empty_project, :public) } + let(:user) { create(:user) } + subject { described_class.new(project, user) } + let(:link) { empty_html_link } + + describe '#referenced_by' do + context 'when the link has a data-project attribute' do + before do + link['data-project'] = project.id.to_s + end + + context 'when the link has a data-external-issue attribute' do + it 'returns an Array of ExternalIssue instances' do + link['data-external-issue'] = '123' + + refs = subject.referenced_by([link]) + + expect(refs).to eq([ExternalIssue.new('123', project)]) + end + end + + context 'when the link does not have a data-external-issue attribute' do + it 'returns an empty Array' do + expect(subject.referenced_by([link])).to eq([]) + end + end + end + + context 'when the link does not have a data-project attribute' do + it 'returns an empty Array' do + expect(subject.referenced_by([link])).to eq([]) + end + end + end + + describe '#issue_ids_per_project' do + before do + link['data-project'] = project.id.to_s + end + + it 'returns a Hash containing range IDs per project' do + link['data-external-issue'] = '123' + + hash = subject.issue_ids_per_project([link]) + + expect(hash).to be_an_instance_of(Hash) + + expect(hash[project.id].to_a).to eq(['123']) + end + + it 'does not add a project when the data-external-issue attribute is empty' do + hash = subject.issue_ids_per_project([link]) + + expect(hash).to be_empty + end + end +end diff --git a/spec/lib/banzai/reference_parser/issue_parser_spec.rb b/spec/lib/banzai/reference_parser/issue_parser_spec.rb new file mode 100644 index 0000000000..514c752546 --- /dev/null +++ b/spec/lib/banzai/reference_parser/issue_parser_spec.rb @@ -0,0 +1,79 @@ +require 'spec_helper' + +describe Banzai::ReferenceParser::IssueParser, lib: true do + include ReferenceParserHelpers + + let(:project) { create(:empty_project, :public) } + let(:user) { create(:user) } + let(:issue) { create(:issue, project: project) } + subject { described_class.new(project, user) } + let(:link) { empty_html_link } + + describe '#nodes_visible_to_user' do + context 'when the link has a data-issue attribute' do + before do + link['data-issue'] = issue.id.to_s + end + + it 'returns the nodes when the user can read the issue' do + expect(Ability.abilities).to receive(:allowed?). + with(user, :read_issue, issue). + and_return(true) + + expect(subject.nodes_visible_to_user(user, [link])).to eq([link]) + end + + it 'returns an empty Array when the user can not read the issue' do + expect(Ability.abilities).to receive(:allowed?). + with(user, :read_issue, issue). + and_return(false) + + expect(subject.nodes_visible_to_user(user, [link])).to eq([]) + end + end + + context 'when the link does not have a data-issue attribute' do + it 'returns an empty Array' do + expect(subject.nodes_visible_to_user(user, [link])).to eq([]) + end + end + + context 'when the project uses an external issue tracker' do + it 'returns all nodes' do + link = double(:link) + + expect(project).to receive(:external_issue_tracker).and_return(true) + + expect(subject.nodes_visible_to_user(user, [link])).to eq([link]) + end + end + end + + describe '#referenced_by' do + context 'when the link has a data-issue attribute' do + context 'using an existing issue ID' do + before do + link['data-issue'] = issue.id.to_s + end + + it 'returns an Array of issues' do + expect(subject.referenced_by([link])).to eq([issue]) + end + + it 'returns an empty Array when the list of nodes is empty' do + expect(subject.referenced_by([link])).to eq([issue]) + expect(subject.referenced_by([])).to eq([]) + end + end + end + end + + describe '#issues_for_nodes' do + it 'returns a Hash containing the issues for a list of nodes' do + link['data-issue'] = issue.id.to_s + nodes = [link] + + expect(subject.issues_for_nodes(nodes)).to eq({ issue.id => issue }) + end + end +end diff --git a/spec/lib/banzai/reference_parser/label_parser_spec.rb b/spec/lib/banzai/reference_parser/label_parser_spec.rb new file mode 100644 index 0000000000..77fda47f0e --- /dev/null +++ b/spec/lib/banzai/reference_parser/label_parser_spec.rb @@ -0,0 +1,31 @@ +require 'spec_helper' + +describe Banzai::ReferenceParser::LabelParser, lib: true do + include ReferenceParserHelpers + + let(:project) { create(:empty_project, :public) } + let(:user) { create(:user) } + let(:label) { create(:label, project: project) } + subject { described_class.new(project, user) } + let(:link) { empty_html_link } + + describe '#referenced_by' do + describe 'when the link has a data-label attribute' do + context 'using an existing label ID' do + it 'returns an Array of labels' do + link['data-label'] = label.id.to_s + + expect(subject.referenced_by([link])).to eq([label]) + end + end + + context 'using a non-existing label ID' do + it 'returns an empty Array' do + link['data-label'] = '' + + expect(subject.referenced_by([link])).to eq([]) + end + end + end + end +end diff --git a/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb b/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb new file mode 100644 index 0000000000..cf89ad598e --- /dev/null +++ b/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb @@ -0,0 +1,30 @@ +require 'spec_helper' + +describe Banzai::ReferenceParser::MergeRequestParser, lib: true do + include ReferenceParserHelpers + + let(:user) { create(:user) } + let(:merge_request) { create(:merge_request) } + subject { described_class.new(merge_request.target_project, user) } + let(:link) { empty_html_link } + + describe '#referenced_by' do + describe 'when the link has a data-merge-request attribute' do + context 'using an existing merge request ID' do + it 'returns an Array of merge requests' do + link['data-merge-request'] = merge_request.id.to_s + + expect(subject.referenced_by([link])).to eq([merge_request]) + end + end + + context 'using a non-existing merge request ID' do + it 'returns an empty Array' do + link['data-merge-request'] = '' + + expect(subject.referenced_by([link])).to eq([]) + end + end + end + end +end diff --git a/spec/lib/banzai/reference_parser/milestone_parser_spec.rb b/spec/lib/banzai/reference_parser/milestone_parser_spec.rb new file mode 100644 index 0000000000..6aa45a22cc --- /dev/null +++ b/spec/lib/banzai/reference_parser/milestone_parser_spec.rb @@ -0,0 +1,31 @@ +require 'spec_helper' + +describe Banzai::ReferenceParser::MilestoneParser, lib: true do + include ReferenceParserHelpers + + let(:project) { create(:empty_project, :public) } + let(:user) { create(:user) } + let(:milestone) { create(:milestone, project: project) } + subject { described_class.new(project, user) } + let(:link) { empty_html_link } + + describe '#referenced_by' do + describe 'when the link has a data-milestone attribute' do + context 'using an existing milestone ID' do + it 'returns an Array of milestones' do + link['data-milestone'] = milestone.id.to_s + + expect(subject.referenced_by([link])).to eq([milestone]) + end + end + + context 'using a non-existing milestone ID' do + it 'returns an empty Array' do + link['data-milestone'] = '' + + expect(subject.referenced_by([link])).to eq([]) + end + end + end + end +end diff --git a/spec/lib/banzai/reference_parser/snippet_parser_spec.rb b/spec/lib/banzai/reference_parser/snippet_parser_spec.rb new file mode 100644 index 0000000000..59127b7c5d --- /dev/null +++ b/spec/lib/banzai/reference_parser/snippet_parser_spec.rb @@ -0,0 +1,31 @@ +require 'spec_helper' + +describe Banzai::ReferenceParser::SnippetParser, lib: true do + include ReferenceParserHelpers + + let(:project) { create(:empty_project, :public) } + let(:user) { create(:user) } + let(:snippet) { create(:snippet, project: project) } + subject { described_class.new(project, user) } + let(:link) { empty_html_link } + + describe '#referenced_by' do + describe 'when the link has a data-snippet attribute' do + context 'using an existing snippet ID' do + it 'returns an Array of snippets' do + link['data-snippet'] = snippet.id.to_s + + expect(subject.referenced_by([link])).to eq([snippet]) + end + end + + context 'using a non-existing snippet ID' do + it 'returns an empty Array' do + link['data-snippet'] = '' + + expect(subject.referenced_by([link])).to eq([]) + end + end + end + end +end diff --git a/spec/lib/banzai/reference_parser/user_parser_spec.rb b/spec/lib/banzai/reference_parser/user_parser_spec.rb new file mode 100644 index 0000000000..9a82891297 --- /dev/null +++ b/spec/lib/banzai/reference_parser/user_parser_spec.rb @@ -0,0 +1,189 @@ +require 'spec_helper' + +describe Banzai::ReferenceParser::UserParser, lib: true do + include ReferenceParserHelpers + + let(:group) { create(:group) } + let(:user) { create(:user) } + let(:project) { create(:empty_project, :public, group: group, creator: user) } + subject { described_class.new(project, user) } + let(:link) { empty_html_link } + + describe '#referenced_by' do + context 'when the link has a data-group attribute' do + context 'using an existing group ID' do + before do + link['data-group'] = project.group.id.to_s + end + + it 'returns the users of the group' do + create(:group_member, group: group, user: user) + + expect(subject.referenced_by([link])).to eq([user]) + end + + it 'returns an empty Array when the group has no users' do + expect(subject.referenced_by([link])).to eq([]) + end + end + + context 'using a non-existing group ID' do + it 'returns an empty Array' do + link['data-group'] = '' + + expect(subject.referenced_by([link])).to eq([]) + end + end + end + + context 'when the link has a data-user attribute' do + it 'returns an Array of users' do + link['data-user'] = user.id.to_s + + expect(subject.referenced_by([link])).to eq([user]) + end + end + + context 'when the link has a data-project attribute' do + context 'using an existing project ID' do + let(:contributor) { create(:user) } + + before do + project.team << [user, :developer] + project.team << [contributor, :developer] + end + + it 'returns the members of a project' do + link['data-project'] = project.id.to_s + + # This uses an explicit sort to make sure this spec doesn't randomly + # fail when objects are returned in a different order. + refs = subject.referenced_by([link]).sort_by(&:id) + + expect(refs).to eq([user, contributor]) + end + end + + context 'using a non-existing project ID' do + it 'returns an empty Array' do + link['data-project'] = '' + + expect(subject.referenced_by([link])).to eq([]) + end + end + end + end + + describe '#nodes_visible_to_use?' do + context 'when the link has a data-group attribute' do + context 'using an existing group ID' do + before do + link['data-group'] = group.id.to_s + end + + it 'returns the nodes if the user can read the group' do + expect(Ability.abilities).to receive(:allowed?). + with(user, :read_group, group). + and_return(true) + + expect(subject.nodes_visible_to_user(user, [link])).to eq([link]) + end + + it 'returns an empty Array if the user can not read the group' do + expect(Ability.abilities).to receive(:allowed?). + with(user, :read_group, group). + and_return(false) + + expect(subject.nodes_visible_to_user(user, [link])).to eq([]) + end + end + + context 'when the link does not have a data-group attribute' do + context 'with a data-project attribute' do + it 'returns the nodes if the attribute value equals the current project ID' do + link['data-project'] = project.id.to_s + + expect(Ability.abilities).not_to receive(:allowed?) + + expect(subject.nodes_visible_to_user(user, [link])).to eq([link]) + end + + it 'returns the nodes if the user can read the project' do + other_project = create(:empty_project, :public) + + link['data-project'] = other_project.id.to_s + + expect(Ability.abilities).to receive(:allowed?). + with(user, :read_project, other_project). + and_return(true) + + expect(subject.nodes_visible_to_user(user, [link])).to eq([link]) + end + + it 'returns an empty Array if the user can not read the project' do + other_project = create(:empty_project, :public) + + link['data-project'] = other_project.id.to_s + + expect(Ability.abilities).to receive(:allowed?). + with(user, :read_project, other_project). + and_return(false) + + expect(subject.nodes_visible_to_user(user, [link])).to eq([]) + end + end + + context 'without a data-project attribute' do + it 'returns the nodes' do + expect(subject.nodes_visible_to_user(user, [link])).to eq([link]) + end + end + end + end + end + + describe '#nodes_user_can_reference' do + context 'when the link has a data-author attribute' do + it 'returns the nodes when the user is a member of the project' do + other_project = create(:project) + other_project.team << [user, :developer] + + link['data-project'] = other_project.id.to_s + link['data-author'] = user.id.to_s + + expect(subject.nodes_user_can_reference(user, [link])).to eq([link]) + end + + it 'returns an empty Array when the project could not be found' do + link['data-project'] = '' + link['data-author'] = user.id.to_s + + expect(subject.nodes_user_can_reference(user, [link])).to eq([]) + end + + it 'returns an empty Array when the user could not be found' do + other_project = create(:project) + + link['data-project'] = other_project.id.to_s + link['data-author'] = '' + + expect(subject.nodes_user_can_reference(user, [link])).to eq([]) + end + + it 'returns an empty Array when the user is not a team member' do + other_project = create(:project) + + link['data-project'] = other_project.id.to_s + link['data-author'] = user.id.to_s + + expect(subject.nodes_user_can_reference(user, [link])).to eq([]) + end + end + + context 'when the link does not have a data-author attribute' do + it 'returns the nodes' do + expect(subject.nodes_user_can_reference(user, [link])).to eq([link]) + end + end + end +end diff --git a/spec/lib/ci/ansi2html_spec.rb b/spec/lib/ci/ansi2html_spec.rb index 3a2b568f4c..898f1e84ab 100644 --- a/spec/lib/ci/ansi2html_spec.rb +++ b/spec/lib/ci/ansi2html_spec.rb @@ -4,131 +4,185 @@ describe Ci::Ansi2html, lib: true do subject { Ci::Ansi2html } it "prints non-ansi as-is" do - expect(subject.convert("Hello")).to eq('Hello') + expect(subject.convert("Hello")[:html]).to eq('Hello') end it "strips non-color-changing controll sequences" do - expect(subject.convert("Hello \e[2Kworld")).to eq('Hello world') + expect(subject.convert("Hello \e[2Kworld")[:html]).to eq('Hello world') end it "prints simply red" do - expect(subject.convert("\e[31mHello\e[0m")).to eq('Hello') + expect(subject.convert("\e[31mHello\e[0m")[:html]).to eq('Hello') end it "prints simply red without trailing reset" do - expect(subject.convert("\e[31mHello")).to eq('Hello') + expect(subject.convert("\e[31mHello")[:html]).to eq('Hello') end it "prints simply yellow" do - expect(subject.convert("\e[33mHello\e[0m")).to eq('Hello') + expect(subject.convert("\e[33mHello\e[0m")[:html]).to eq('Hello') end it "prints default on blue" do - expect(subject.convert("\e[39;44mHello")).to eq('Hello') + expect(subject.convert("\e[39;44mHello")[:html]).to eq('Hello') end it "prints red on blue" do - expect(subject.convert("\e[31;44mHello")).to eq('Hello') + expect(subject.convert("\e[31;44mHello")[:html]).to eq('Hello') end it "resets colors after red on blue" do - expect(subject.convert("\e[31;44mHello\e[0m world")).to eq('Hello world') + expect(subject.convert("\e[31;44mHello\e[0m world")[:html]).to eq('Hello world') end it "performs color change from red/blue to yellow/blue" do - expect(subject.convert("\e[31;44mHello \e[33mworld")).to eq('Hello world') + expect(subject.convert("\e[31;44mHello \e[33mworld")[:html]).to eq('Hello world') end it "performs color change from red/blue to yellow/green" do - expect(subject.convert("\e[31;44mHello \e[33;42mworld")).to eq('Hello world') + expect(subject.convert("\e[31;44mHello \e[33;42mworld")[:html]).to eq('Hello world') end it "performs color change from red/blue to reset to yellow/green" do - expect(subject.convert("\e[31;44mHello\e[0m \e[33;42mworld")).to eq('Hello world') + expect(subject.convert("\e[31;44mHello\e[0m \e[33;42mworld")[:html]).to eq('Hello world') end it "ignores unsupported codes" do - expect(subject.convert("\e[51mHello\e[0m")).to eq('Hello') + expect(subject.convert("\e[51mHello\e[0m")[:html]).to eq('Hello') end it "prints light red" do - expect(subject.convert("\e[91mHello\e[0m")).to eq('Hello') + expect(subject.convert("\e[91mHello\e[0m")[:html]).to eq('Hello') end it "prints default on light red" do - expect(subject.convert("\e[101mHello\e[0m")).to eq('Hello') + expect(subject.convert("\e[101mHello\e[0m")[:html]).to eq('Hello') end it "performs color change from red/blue to default/blue" do - expect(subject.convert("\e[31;44mHello \e[39mworld")).to eq('Hello world') + expect(subject.convert("\e[31;44mHello \e[39mworld")[:html]).to eq('Hello world') end it "performs color change from light red/blue to default/blue" do - expect(subject.convert("\e[91;44mHello \e[39mworld")).to eq('Hello world') + expect(subject.convert("\e[91;44mHello \e[39mworld")[:html]).to eq('Hello world') end it "prints bold text" do - expect(subject.convert("\e[1mHello")).to eq('Hello') + expect(subject.convert("\e[1mHello")[:html]).to eq('Hello') end it "resets bold text" do - expect(subject.convert("\e[1mHello\e[21m world")).to eq('Hello world') - expect(subject.convert("\e[1mHello\e[22m world")).to eq('Hello world') + expect(subject.convert("\e[1mHello\e[21m world")[:html]).to eq('Hello world') + expect(subject.convert("\e[1mHello\e[22m world")[:html]).to eq('Hello world') end it "prints italic text" do - expect(subject.convert("\e[3mHello")).to eq('Hello') + expect(subject.convert("\e[3mHello")[:html]).to eq('Hello') end it "resets italic text" do - expect(subject.convert("\e[3mHello\e[23m world")).to eq('Hello world') + expect(subject.convert("\e[3mHello\e[23m world")[:html]).to eq('Hello world') end it "prints underlined text" do - expect(subject.convert("\e[4mHello")).to eq('Hello') + expect(subject.convert("\e[4mHello")[:html]).to eq('Hello') end it "resets underlined text" do - expect(subject.convert("\e[4mHello\e[24m world")).to eq('Hello world') + expect(subject.convert("\e[4mHello\e[24m world")[:html]).to eq('Hello world') end it "prints concealed text" do - expect(subject.convert("\e[8mHello")).to eq('Hello') + expect(subject.convert("\e[8mHello")[:html]).to eq('Hello') end it "resets concealed text" do - expect(subject.convert("\e[8mHello\e[28m world")).to eq('Hello world') + expect(subject.convert("\e[8mHello\e[28m world")[:html]).to eq('Hello world') end it "prints crossed-out text" do - expect(subject.convert("\e[9mHello")).to eq('Hello') + expect(subject.convert("\e[9mHello")[:html]).to eq('Hello') end it "resets crossed-out text" do - expect(subject.convert("\e[9mHello\e[29m world")).to eq('Hello world') + expect(subject.convert("\e[9mHello\e[29m world")[:html]).to eq('Hello world') end it "can print 256 xterm fg colors" do - expect(subject.convert("\e[38;5;16mHello")).to eq('Hello') + expect(subject.convert("\e[38;5;16mHello")[:html]).to eq('Hello') end it "can print 256 xterm fg colors on normal magenta background" do - expect(subject.convert("\e[38;5;16;45mHello")).to eq('Hello') + expect(subject.convert("\e[38;5;16;45mHello")[:html]).to eq('Hello') end it "can print 256 xterm bg colors" do - expect(subject.convert("\e[48;5;240mHello")).to eq('Hello') + expect(subject.convert("\e[48;5;240mHello")[:html]).to eq('Hello') end it "can print 256 xterm bg colors on normal magenta foreground" do - expect(subject.convert("\e[48;5;16;35mHello")).to eq('Hello') + expect(subject.convert("\e[48;5;16;35mHello")[:html]).to eq('Hello') end it "prints bold colored text vividly" do - expect(subject.convert("\e[1;31mHello\e[0m")).to eq('Hello') + expect(subject.convert("\e[1;31mHello\e[0m")[:html]).to eq('Hello') end it "prints bold light colored text correctly" do - expect(subject.convert("\e[1;91mHello\e[0m")).to eq('Hello') + expect(subject.convert("\e[1;91mHello\e[0m")[:html]).to eq('Hello') + end + + it "prints <" do + expect(subject.convert("<")[:html]).to eq('<') + end + + describe "incremental update" do + shared_examples 'stateable converter' do + let(:pass1) { subject.convert(pre_text) } + let(:pass2) { subject.convert(pre_text + text, pass1[:state]) } + + it "to returns html to append" do + expect(pass2[:append]).to be_truthy + expect(pass2[:html]).to eq(html) + expect(pass1[:text] + pass2[:text]).to eq(pre_text + text) + expect(pass1[:html] + pass2[:html]).to eq(pre_html + html) + end + end + + context "with split word" do + let(:pre_text) { "\e[1mHello" } + let(:pre_html) { "Hello" } + let(:text) { "\e[1mWorld" } + let(:html) { "World" } + + it_behaves_like 'stateable converter' + end + + context "with split sequence" do + let(:pre_text) { "\e[1m" } + let(:pre_html) { "" } + let(:text) { "Hello" } + let(:html) { "Hello" } + + it_behaves_like 'stateable converter' + end + + context "with partial sequence" do + let(:pre_text) { "Hello\e" } + let(:pre_html) { "Hello" } + let(:text) { "[1m World" } + let(:html) { " World" } + + it_behaves_like 'stateable converter' + end + + context 'with new line' do + let(:pre_text) { "Hello\r" } + let(:pre_html) { "Hello\r" } + let(:text) { "\nWorld" } + let(:html) { "
    World" } + + it_behaves_like 'stateable converter' + end end end diff --git a/spec/lib/ci/charts_spec.rb b/spec/lib/ci/charts_spec.rb index 50a77308cd..9d1215a576 100644 --- a/spec/lib/ci/charts_spec.rb +++ b/spec/lib/ci/charts_spec.rb @@ -12,5 +12,12 @@ describe Ci::Charts, lib: true do chart = Ci::Charts::BuildTime.new(@commit.project) expect(chart.build_times).to eq([2]) end + + it 'should handle nil build times' do + create(:ci_commit, duration: nil, project: @commit.project) + + chart = Ci::Charts::BuildTime.new(@commit.project) + expect(chart.build_times).to eq([2, 0]) + end end end diff --git a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb index c7ab318537..7375539cf1 100644 --- a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb +++ b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb @@ -443,12 +443,12 @@ module Ci context 'when job variables are defined' do context 'when syntax is correct' do it 'returns job variables' do - variables = { + variables = { KEY1: 'value1', SOME_KEY_2: 'value2' } - config = YAML.dump( + config = YAML.dump( { before_script: ['pwd'], rspec: { variables: variables, @@ -619,19 +619,19 @@ module Ci context 'no dependencies' do let(:dependencies) { } - it { expect { subject }.to_not raise_error } + it { expect { subject }.not_to raise_error } end context 'dependencies to builds' do let(:dependencies) { ['build1', 'build2'] } - it { expect { subject }.to_not raise_error } + it { expect { subject }.not_to raise_error } end context 'dependencies to builds defined as symbols' do let(:dependencies) { [:build1, :build2] } - it { expect { subject }.to_not raise_error } + it { expect { subject }.not_to raise_error } end context 'undefined dependency' do diff --git a/spec/lib/container_registry/blob_spec.rb b/spec/lib/container_registry/blob_spec.rb new file mode 100644 index 0000000000..4d8cb787dd --- /dev/null +++ b/spec/lib/container_registry/blob_spec.rb @@ -0,0 +1,61 @@ +require 'spec_helper' + +describe ContainerRegistry::Blob do + let(:digest) { 'sha256:0123456789012345' } + let(:config) do + { + 'digest' => digest, + 'mediaType' => 'binary', + 'size' => 1000 + } + end + + let(:registry) { ContainerRegistry::Registry.new('http://example.com') } + let(:repository) { registry.repository('group/test') } + let(:blob) { repository.blob(config) } + + it { expect(blob).to respond_to(:repository) } + it { expect(blob).to delegate_method(:registry).to(:repository) } + it { expect(blob).to delegate_method(:client).to(:repository) } + + context '#path' do + subject { blob.path } + + it { is_expected.to eq('example.com/group/test@sha256:0123456789012345') } + end + + context '#digest' do + subject { blob.digest } + + it { is_expected.to eq(digest) } + end + + context '#type' do + subject { blob.type } + + it { is_expected.to eq('binary') } + end + + context '#revision' do + subject { blob.revision } + + it { is_expected.to eq('0123456789012345') } + end + + context '#short_revision' do + subject { blob.short_revision } + + it { is_expected.to eq('012345678') } + end + + context '#delete' do + before do + stub_request(:delete, 'http://example.com/v2/group/test/blobs/sha256:0123456789012345'). + to_return(status: 200) + end + + subject { blob.delete } + + it { is_expected.to be_truthy } + end +end diff --git a/spec/lib/container_registry/registry_spec.rb b/spec/lib/container_registry/registry_spec.rb new file mode 100644 index 0000000000..4f3f8b24fc --- /dev/null +++ b/spec/lib/container_registry/registry_spec.rb @@ -0,0 +1,28 @@ +require 'spec_helper' + +describe ContainerRegistry::Registry do + let(:path) { nil } + let(:registry) { described_class.new('http://example.com', path: path) } + + subject { registry } + + it { is_expected.to respond_to(:client) } + it { is_expected.to respond_to(:uri) } + it { is_expected.to respond_to(:path) } + + it { expect(subject.repository('test')).not_to be_nil } + + context '#path' do + subject { registry.path } + + context 'path from URL' do + it { is_expected.to eq('example.com') } + end + + context 'custom path' do + let(:path) { 'registry.example.com' } + + it { is_expected.to eq(path) } + end + end +end diff --git a/spec/lib/container_registry/repository_spec.rb b/spec/lib/container_registry/repository_spec.rb new file mode 100644 index 0000000000..279709521c --- /dev/null +++ b/spec/lib/container_registry/repository_spec.rb @@ -0,0 +1,65 @@ +require 'spec_helper' + +describe ContainerRegistry::Repository do + let(:registry) { ContainerRegistry::Registry.new('http://example.com') } + let(:repository) { registry.repository('group/test') } + + it { expect(repository).to respond_to(:registry) } + it { expect(repository).to delegate_method(:client).to(:registry) } + it { expect(repository.tag('test')).not_to be_nil } + + context '#path' do + subject { repository.path } + + it { is_expected.to eq('example.com/group/test') } + end + + context 'manifest processing' do + before do + stub_request(:get, 'http://example.com/v2/group/test/tags/list'). + with(headers: { 'Accept' => 'application/vnd.docker.distribution.manifest.v2+json' }). + to_return( + status: 200, + body: JSON.dump(tags: ['test']), + headers: { 'Content-Type' => 'application/vnd.docker.distribution.manifest.v2+json' }) + end + + context '#manifest' do + subject { repository.manifest } + + it { is_expected.not_to be_nil } + end + + context '#valid?' do + subject { repository.valid? } + + it { is_expected.to be_truthy } + end + + context '#tags' do + subject { repository.tags } + + it { is_expected.not_to be_empty } + end + end + + context '#delete_tags' do + let(:tag) { ContainerRegistry::Tag.new(repository, 'tag') } + + before { expect(repository).to receive(:tags).twice.and_return([tag]) } + + subject { repository.delete_tags } + + context 'succeeds' do + before { expect(tag).to receive(:delete).and_return(true) } + + it { is_expected.to be_truthy } + end + + context 'any fails' do + before { expect(tag).to receive(:delete).and_return(false) } + + it { is_expected.to be_falsey } + end + end +end diff --git a/spec/lib/container_registry/tag_spec.rb b/spec/lib/container_registry/tag_spec.rb new file mode 100644 index 0000000000..858cb0bb13 --- /dev/null +++ b/spec/lib/container_registry/tag_spec.rb @@ -0,0 +1,89 @@ +require 'spec_helper' + +describe ContainerRegistry::Tag do + let(:registry) { ContainerRegistry::Registry.new('http://example.com') } + let(:repository) { registry.repository('group/test') } + let(:tag) { repository.tag('tag') } + let(:headers) { { 'Accept' => 'application/vnd.docker.distribution.manifest.v2+json' } } + + it { expect(tag).to respond_to(:repository) } + it { expect(tag).to delegate_method(:registry).to(:repository) } + it { expect(tag).to delegate_method(:client).to(:repository) } + + context '#path' do + subject { tag.path } + + it { is_expected.to eq('example.com/group/test:tag') } + end + + context 'manifest processing' do + before do + stub_request(:get, 'http://example.com/v2/group/test/manifests/tag'). + with(headers: headers). + to_return( + status: 200, + body: File.read(Rails.root + 'spec/fixtures/container_registry/tag_manifest.json'), + headers: { 'Content-Type' => 'application/vnd.docker.distribution.manifest.v2+json' }) + end + + context '#layers' do + subject { tag.layers } + + it { expect(subject.length).to eq(1) } + end + + context '#total_size' do + subject { tag.total_size } + + it { is_expected.to eq(2319870) } + end + + context 'config processing' do + before do + stub_request(:get, 'http://example.com/v2/group/test/blobs/sha256:d7a513a663c1a6dcdba9ed832ca53c02ac2af0c333322cd6ca92936d1d9917ac'). + with(headers: { 'Accept' => 'application/octet-stream' }). + to_return( + status: 200, + body: File.read(Rails.root + 'spec/fixtures/container_registry/config_blob.json')) + end + + context '#config' do + subject { tag.config } + + it { is_expected.not_to be_nil } + end + + context '#created_at' do + subject { tag.created_at } + + it { is_expected.not_to be_nil } + end + end + end + + context 'manifest digest' do + before do + stub_request(:head, 'http://example.com/v2/group/test/manifests/tag'). + with(headers: headers). + to_return(status: 200, headers: { 'Docker-Content-Digest' => 'sha256:digest' }) + end + + context '#digest' do + subject { tag.digest } + + it { is_expected.to eq('sha256:digest') } + end + + context '#delete' do + before do + stub_request(:delete, 'http://example.com/v2/group/test/manifests/sha256:digest'). + with(headers: headers). + to_return(status: 200) + end + + subject { tag.delete } + + it { is_expected.to be_truthy } + end + end +end diff --git a/spec/lib/gitlab/akismet_helper_spec.rb b/spec/lib/gitlab/akismet_helper_spec.rb index 53f5d6c5c8..88a7152886 100644 --- a/spec/lib/gitlab/akismet_helper_spec.rb +++ b/spec/lib/gitlab/akismet_helper_spec.rb @@ -6,8 +6,8 @@ describe Gitlab::AkismetHelper, type: :helper do before do allow(Gitlab.config.gitlab).to receive(:url).and_return(Settings.send(:build_gitlab_url)) - current_application_settings.akismet_enabled = true - current_application_settings.akismet_api_key = '12345' + allow_any_instance_of(ApplicationSetting).to receive(:akismet_enabled).and_return(true) + allow_any_instance_of(ApplicationSetting).to receive(:akismet_api_key).and_return('12345') end describe '#check_for_spam?' do diff --git a/spec/lib/gitlab/bitbucket_import/client_spec.rb b/spec/lib/gitlab/bitbucket_import/client_spec.rb index af839f4242..7718689e6d 100644 --- a/spec/lib/gitlab/bitbucket_import/client_spec.rb +++ b/spec/lib/gitlab/bitbucket_import/client_spec.rb @@ -59,7 +59,7 @@ describe Gitlab::BitbucketImport::Client, lib: true do bitbucket_access_token_secret: "test" } }) project.import_url = "ssh://git@bitbucket.org/test/test.git" - expect { described_class.from_project(project) }.to_not raise_error + expect { described_class.from_project(project) }.not_to raise_error end end end 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 acca0b08ba..711a3e1c7d 100644 --- a/spec/lib/gitlab/ci/build/artifacts/metadata/entry_spec.rb +++ b/spec/lib/gitlab/ci/build/artifacts/metadata/entry_spec.rb @@ -10,8 +10,8 @@ describe Gitlab::Ci::Build::Artifacts::Metadata::Entry do 'path/dir_1/subdir/subfile' => { size: 10 }, 'path/second_dir' => {}, 'path/second_dir/dir_3/file_2' => { size: 10 }, - 'path/second_dir/dir_3/file_3'=> { size: 10 }, - 'another_directory/'=> {}, + 'path/second_dir/dir_3/file_3' => { size: 10 }, + 'another_directory/' => {}, 'another_file' => {}, '/file/with/absolute_path' => {} } end @@ -122,7 +122,7 @@ describe Gitlab::Ci::Build::Artifacts::Metadata::Entry do describe 'empty path', path: '' do subject { |example| path(example) } - it { is_expected.to_not have_parent } + it { is_expected.not_to have_parent } describe '#children' do subject { |example| path(example).children } diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb new file mode 100644 index 0000000000..35ade7a2be --- /dev/null +++ b/spec/lib/gitlab/database/migration_helpers_spec.rb @@ -0,0 +1,128 @@ +require 'spec_helper' + +describe Gitlab::Database::MigrationHelpers, lib: true do + let(:model) do + ActiveRecord::Migration.new.extend( + Gitlab::Database::MigrationHelpers + ) + end + + before { allow(model).to receive(:puts) } + + describe '#add_concurrent_index' do + context 'outside a transaction' do + before do + expect(model).to receive(:transaction_open?).and_return(false) + end + + context 'using PostgreSQL' do + it 'creates the index concurrently' do + expect(Gitlab::Database).to receive(:postgresql?).and_return(true) + + expect(model).to receive(:add_index). + with(:users, :foo, algorithm: :concurrently) + + model.add_concurrent_index(:users, :foo) + end + end + + context 'using MySQL' do + it 'creates a regular index' do + expect(Gitlab::Database).to receive(:postgresql?).and_return(false) + + expect(model).to receive(:add_index). + with(:users, :foo) + + model.add_concurrent_index(:users, :foo) + end + end + end + + context 'inside a transaction' do + it 'raises RuntimeError' do + expect(model).to receive(:transaction_open?).and_return(true) + + expect { model.add_concurrent_index(:users, :foo) }. + to raise_error(RuntimeError) + end + end + end + + describe '#update_column_in_batches' do + before do + create_list(:empty_project, 5) + end + + it 'updates all the rows in a table' do + model.update_column_in_batches(:projects, :import_error, 'foo') + + expect(Project.where(import_error: 'foo').count).to eq(5) + end + + it 'updates boolean values correctly' do + model.update_column_in_batches(:projects, :archived, true) + + expect(Project.where(archived: true).count).to eq(5) + end + end + + describe '#add_column_with_default' do + context 'outside of a transaction' do + before do + expect(model).to receive(:transaction_open?).and_return(false) + + expect(model).to receive(:transaction).twice.and_yield + + expect(model).to receive(:add_column). + with(:projects, :foo, :integer, default: nil) + + expect(model).to receive(:change_column_default). + with(:projects, :foo, 10) + end + + it 'adds the column while allowing NULL values' do + expect(model).to receive(:update_column_in_batches). + with(:projects, :foo, 10) + + expect(model).not_to receive(:change_column_null) + + model.add_column_with_default(:projects, :foo, :integer, + default: 10, + allow_null: true) + end + + it 'adds the column while not allowing NULL values' do + expect(model).to receive(:update_column_in_batches). + with(:projects, :foo, 10) + + expect(model).to receive(:change_column_null). + with(:projects, :foo, false) + + model.add_column_with_default(:projects, :foo, :integer, default: 10) + end + + it 'removes the added column whenever updating the rows fails' do + expect(model).to receive(:update_column_in_batches). + with(:projects, :foo, 10). + and_raise(RuntimeError) + + expect(model).to receive(:remove_column). + with(:projects, :foo) + + expect do + model.add_column_with_default(:projects, :foo, :integer, default: 10) + end.to raise_error(RuntimeError) + end + end + + context 'inside a transaction' do + it 'raises RuntimeError' do + expect(model).to receive(:transaction_open?).and_return(true) + + expect do + model.add_column_with_default(:projects, :foo, :integer, default: 10) + end.to raise_error(RuntimeError) + end + end + end +end diff --git a/spec/lib/gitlab/email/message/repository_push_spec.rb b/spec/lib/gitlab/email/message/repository_push_spec.rb index b2d7a79981..c19f33e222 100644 --- a/spec/lib/gitlab/email/message/repository_push_spec.rb +++ b/spec/lib/gitlab/email/message/repository_push_spec.rb @@ -8,7 +8,7 @@ describe Gitlab::Email::Message::RepositoryPush do let!(:author) { create(:author, name: 'Author') } let(:message) do - described_class.new(Notify, project.id, 'recipient@example.com', opts) + described_class.new(Notify, project.id, opts) end context 'new commits have been pushed to repository' do @@ -57,7 +57,7 @@ describe Gitlab::Email::Message::RepositoryPush do describe '#diffs' do subject { message.diffs } - it { is_expected.to all(be_an_instance_of Gitlab::Git::Diff) } + it { is_expected.to all(be_an_instance_of Gitlab::Diff::File) } end describe '#diffs_count' do diff --git a/spec/lib/gitlab/gfm/reference_rewriter_spec.rb b/spec/lib/gitlab/gfm/reference_rewriter_spec.rb index 0a7ca3ec84..0af249d869 100644 --- a/spec/lib/gitlab/gfm/reference_rewriter_spec.rb +++ b/spec/lib/gitlab/gfm/reference_rewriter_spec.rb @@ -33,8 +33,8 @@ describe Gitlab::Gfm::ReferenceRewriter do end it { is_expected.to include issue_first.to_reference(new_project) } - it { is_expected.to_not include issue_second.to_reference(new_project) } - it { is_expected.to_not include merge_request.to_reference(new_project) } + it { is_expected.not_to include issue_second.to_reference(new_project) } + it { is_expected.not_to include merge_request.to_reference(new_project) } end context 'description ambigous elements' do diff --git a/spec/lib/gitlab/gfm/uploads_rewriter_spec.rb b/spec/lib/gitlab/gfm/uploads_rewriter_spec.rb index eda956e6f0..6eca33f9fe 100644 --- a/spec/lib/gitlab/gfm/uploads_rewriter_spec.rb +++ b/spec/lib/gitlab/gfm/uploads_rewriter_spec.rb @@ -32,13 +32,13 @@ describe Gitlab::Gfm::UploadsRewriter do let(:new_paths) { new_files.map(&:path) } it 'rewrites content' do - expect(new_text).to_not eq text + expect(new_text).not_to eq text expect(new_text.length).to eq text.length end it 'copies files' do expect(new_files).to all(exist) - expect(old_paths).to_not match_array new_paths + expect(old_paths).not_to match_array new_paths expect(old_paths).to all(include(old_project.path_with_namespace)) expect(new_paths).to all(include(new_project.path_with_namespace)) end @@ -48,8 +48,8 @@ describe Gitlab::Gfm::UploadsRewriter do end it 'generates a new secret for each file' do - expect(new_paths).to_not include image_uploader.secret - expect(new_paths).to_not include zip_uploader.secret + expect(new_paths).not_to include image_uploader.secret + expect(new_paths).not_to include zip_uploader.secret end end diff --git a/spec/lib/gitlab/github_import/branch_formatter_spec.rb b/spec/lib/gitlab/github_import/branch_formatter_spec.rb new file mode 100644 index 0000000000..3cb634ba01 --- /dev/null +++ b/spec/lib/gitlab/github_import/branch_formatter_spec.rb @@ -0,0 +1,71 @@ +require 'spec_helper' + +describe Gitlab::GithubImport::BranchFormatter, lib: true do + let(:project) { create(:project) } + let(:repo) { double } + let(:raw) do + { + ref: 'feature', + repo: repo, + sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b' + } + end + + describe '#exists?' do + it 'returns true when branch exists' do + branch = described_class.new(project, double(raw)) + + expect(branch.exists?).to eq true + end + + it 'returns false when branch does not exist' do + branch = described_class.new(project, double(raw.merge(ref: 'removed-branch'))) + + expect(branch.exists?).to eq false + end + end + + describe '#name' do + it 'returns raw ref when branch exists' do + branch = described_class.new(project, double(raw)) + + expect(branch.name).to eq 'feature' + end + + it 'returns formatted ref when branch does not exist' do + branch = described_class.new(project, double(raw.merge(ref: 'removed-branch'))) + + expect(branch.name).to eq 'removed-branch-2e5d3239' + end + end + + describe '#repo' do + it 'returns raw repo' do + branch = described_class.new(project, double(raw)) + + expect(branch.repo).to eq repo + end + end + + describe '#sha' do + it 'returns raw sha' do + branch = described_class.new(project, double(raw)) + + expect(branch.sha).to eq '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b' + end + end + + describe '#valid?' do + it 'returns true when repository exists' do + branch = described_class.new(project, double(raw)) + + expect(branch.valid?).to eq true + end + + it 'returns false when repository does not exist' do + branch = described_class.new(project, double(raw.merge(repo: nil))) + + expect(branch.valid?).to eq false + end + end +end diff --git a/spec/lib/gitlab/github_import/pull_request_formatter_spec.rb b/spec/lib/gitlab/github_import/pull_request_formatter_spec.rb index e59c0ca110..120f59e6e7 100644 --- a/spec/lib/gitlab/github_import/pull_request_formatter_spec.rb +++ b/spec/lib/gitlab/github_import/pull_request_formatter_spec.rb @@ -4,9 +4,9 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do let(:project) { create(:project) } let(:repository) { double(id: 1, fork: false) } let(:source_repo) { repository } - let(:source_branch) { double(ref: 'feature', repo: source_repo) } + let(:source_branch) { double(ref: 'feature', repo: source_repo, sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b') } let(:target_repo) { repository } - let(:target_branch) { double(ref: 'master', repo: target_repo) } + let(:target_branch) { double(ref: 'master', repo: target_repo, sha: '8ffb3c15a5475e59ae909384297fede4badcb4c7') } let(:octocat) { double(id: 123456, login: 'octocat') } let(:created_at) { DateTime.strptime('2011-01-26T19:01:12Z') } let(:updated_at) { DateTime.strptime('2011-01-27T19:01:12Z') } @@ -41,8 +41,10 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do description: "*Created by: octocat*\n\nPlease pull these awesome changes", source_project: project, source_branch: 'feature', + head_source_sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b', target_project: project, target_branch: 'master', + base_target_sha: '8ffb3c15a5475e59ae909384297fede4badcb4c7', state: 'opened', milestone: nil, author_id: project.creator_id, @@ -66,8 +68,10 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do description: "*Created by: octocat*\n\nPlease pull these awesome changes", source_project: project, source_branch: 'feature', + head_source_sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b', target_project: project, target_branch: 'master', + base_target_sha: '8ffb3c15a5475e59ae909384297fede4badcb4c7', state: 'closed', milestone: nil, author_id: project.creator_id, @@ -91,8 +95,10 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do description: "*Created by: octocat*\n\nPlease pull these awesome changes", source_project: project, source_branch: 'feature', + head_source_sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b', target_project: project, target_branch: 'master', + base_target_sha: '8ffb3c15a5475e59ae909384297fede4badcb4c7', state: 'merged', milestone: nil, author_id: project.creator_id, @@ -137,11 +143,11 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do let(:milestone) { double(number: 45) } let(:raw_data) { double(base_data.merge(milestone: milestone)) } - it 'returns nil when milestone does not exists' do + it 'returns nil when milestone does not exist' do expect(pull_request.attributes.fetch(:milestone)).to be_nil end - it 'returns milestone when is exists' do + it 'returns milestone when it exists' do milestone = create(:milestone, project: project, iid: 45) expect(pull_request.attributes.fetch(:milestone)).to eq milestone @@ -158,36 +164,16 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do end describe '#valid?' do - let(:invalid_branch) { double(ref: 'invalid-branch').as_null_object } + context 'when source, and target repos are not a fork' do + let(:raw_data) { double(base_data) } - context 'when source, and target repositories are the same' do - context 'and source and target branches exists' do - let(:raw_data) { double(base_data.merge(head: source_branch, base: target_branch)) } - - it 'returns true' do - expect(pull_request.valid?).to eq true - end - end - - context 'and source branch doesn not exists' do - let(:raw_data) { double(base_data.merge(head: invalid_branch, base: target_branch)) } - - it 'returns false' do - expect(pull_request.valid?).to eq false - end - end - - context 'and target branch doesn not exists' do - let(:raw_data) { double(base_data.merge(head: source_branch, base: invalid_branch)) } - - it 'returns false' do - expect(pull_request.valid?).to eq false - end + it 'returns true' do + expect(pull_request.valid?).to eq true end end context 'when source repo is a fork' do - let(:source_repo) { double(id: 2, fork: true) } + let(:source_repo) { double(id: 2) } let(:raw_data) { double(base_data) } it 'returns false' do @@ -196,7 +182,7 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do end context 'when target repo is a fork' do - let(:target_repo) { double(id: 2, fork: true) } + let(:target_repo) { double(id: 2) } let(:raw_data) { double(base_data) } it 'returns false' do diff --git a/spec/lib/gitlab/gitignore_spec.rb b/spec/lib/gitlab/gitignore_spec.rb new file mode 100644 index 0000000000..72baa516cc --- /dev/null +++ b/spec/lib/gitlab/gitignore_spec.rb @@ -0,0 +1,40 @@ +require 'spec_helper' + +describe Gitlab::Gitignore do + subject { Gitlab::Gitignore } + + describe '.all' do + it 'strips the gitignore suffix' do + expect(subject.all.first.name).not_to end_with('.gitignore') + end + + it 'combines the globals and rest' do + all = subject.all.map(&:name) + + expect(all).to include('Vim') + expect(all).to include('Ruby') + end + end + + describe '.find' do + it 'returns nil if the file does not exist' do + expect(subject.find('mepmep-yadida')).to be nil + end + + it 'returns the Gitignore object of a valid file' do + ruby = subject.find('Ruby') + + expect(ruby).to be_a Gitlab::Gitignore + expect(ruby.name).to eq('Ruby') + end + end + + describe '#content' do + it 'loads the full file' do + gitignore = subject.new(Rails.root.join('vendor/gitignore/Ruby.gitignore')) + + expect(gitignore.name).to eq 'Ruby' + expect(gitignore.content).to start_with('*.gem') + end + end +end diff --git a/spec/lib/gitlab/import_url_spec.rb b/spec/lib/gitlab/import_url_spec.rb deleted file mode 100644 index f758cb8693..0000000000 --- a/spec/lib/gitlab/import_url_spec.rb +++ /dev/null @@ -1,21 +0,0 @@ -require 'spec_helper' - -describe Gitlab::ImportUrl do - - let(:credentials) { { user: 'blah', password: 'password' } } - let(:import_url) do - Gitlab::ImportUrl.new("https://github.com/me/project.git", credentials: credentials) - end - - describe :full_url do - it { expect(import_url.full_url).to eq("https://blah:password@github.com/me/project.git") } - end - - describe :sanitized_url do - it { expect(import_url.sanitized_url).to eq("https://github.com/me/project.git") } - end - - describe :credentials do - it { expect(import_url.credentials).to eq(credentials) } - end -end diff --git a/spec/lib/gitlab/lazy_spec.rb b/spec/lib/gitlab/lazy_spec.rb new file mode 100644 index 0000000000..b5ca89dd24 --- /dev/null +++ b/spec/lib/gitlab/lazy_spec.rb @@ -0,0 +1,37 @@ +require 'spec_helper' + +describe Gitlab::Lazy, lib: true do + let(:dummy) { double(:dummy) } + + context 'when not calling any methods' do + it 'does not call the supplied block' do + expect(dummy).not_to receive(:foo) + + described_class.new { dummy.foo } + end + end + + context 'when calling a method on the object' do + it 'lazy loads the value returned by the block' do + expect(dummy).to receive(:foo).and_return('foo') + + lazy = described_class.new { dummy.foo } + + expect(lazy.to_s).to eq('foo') + end + end + + describe '#respond_to?' do + it 'returns true for a method defined on the wrapped object' do + lazy = described_class.new { 'foo' } + + expect(lazy).to respond_to(:downcase) + end + + it 'returns false for a method not defined on the wrapped object' do + lazy = described_class.new { 'foo' } + + expect(lazy).not_to respond_to(:quack) + end + end +end diff --git a/spec/lib/gitlab/lfs/lfs_router_spec.rb b/spec/lib/gitlab/lfs/lfs_router_spec.rb index 5852b31ab3..88814bc474 100644 --- a/spec/lib/gitlab/lfs/lfs_router_spec.rb +++ b/spec/lib/gitlab/lfs/lfs_router_spec.rb @@ -26,8 +26,8 @@ describe Gitlab::Lfs::Router, lib: true do let(:sample_oid) { "b68143e6463773b1b6c6fd009a76c32aeec041faff32ba2ed42fd7f708a17f80" } let(:sample_size) { 499013 } - let(:respond_with_deprecated) {[ 501, { "Content-Type"=>"application/json; charset=utf-8" }, ["{\"message\":\"Server supports batch API only, please update your Git LFS client to version 1.0.1 and up.\",\"documentation_url\":\"#{Gitlab.config.gitlab.url}/help\"}"]]} - let(:respond_with_disabled) {[ 501, { "Content-Type"=>"application/json; charset=utf-8" }, ["{\"message\":\"Git LFS is not enabled on this GitLab server, contact your admin.\",\"documentation_url\":\"#{Gitlab.config.gitlab.url}/help\"}"]]} + let(:respond_with_deprecated) {[ 501, { "Content-Type" => "application/json; charset=utf-8" }, ["{\"message\":\"Server supports batch API only, please update your Git LFS client to version 1.0.1 and up.\",\"documentation_url\":\"#{Gitlab.config.gitlab.url}/help\"}"]]} + let(:respond_with_disabled) {[ 501, { "Content-Type" => "application/json; charset=utf-8" }, ["{\"message\":\"Git LFS is not enabled on this GitLab server, contact your admin.\",\"documentation_url\":\"#{Gitlab.config.gitlab.url}/help\"}"]]} describe 'when lfs is disabled' do before do @@ -368,7 +368,7 @@ describe Gitlab::Lfs::Router, lib: true do expect(response['objects']).to be_kind_of(Array) expect(response['objects'].first['oid']).to eq(sample_oid) expect(response['objects'].first['size']).to eq(sample_size) - expect(lfs_object.projects.pluck(:id)).to_not include(project.id) + expect(lfs_object.projects.pluck(:id)).not_to include(project.id) expect(lfs_object.projects.pluck(:id)).to include(public_project.id) expect(response['objects'].first['actions']['upload']['href']).to eq("#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}/#{sample_size}") expect(response['objects'].first['actions']['upload']['header']).to eq('Authorization' => @auth) @@ -430,7 +430,7 @@ describe Gitlab::Lfs::Router, lib: true do expect(response_body['objects'].last['oid']).to eq(sample_oid) expect(response_body['objects'].last['size']).to eq(sample_size) - expect(response_body['objects'].last).to_not have_key('actions') + expect(response_body['objects'].last).not_to have_key('actions') end end end diff --git a/spec/lib/gitlab/metrics/instrumentation_spec.rb b/spec/lib/gitlab/metrics/instrumentation_spec.rb index 5c885a7a98..220e86924a 100644 --- a/spec/lib/gitlab/metrics/instrumentation_spec.rb +++ b/spec/lib/gitlab/metrics/instrumentation_spec.rb @@ -56,9 +56,6 @@ describe Gitlab::Metrics::Instrumentation do allow(described_class).to receive(:transaction). and_return(transaction) - expect(transaction).to receive(:increment). - with(:method_duration, a_kind_of(Numeric)) - expect(transaction).to receive(:add_metric). with(described_class::SERIES, an_instance_of(Hash), method: 'Dummy.foo') @@ -70,7 +67,7 @@ describe Gitlab::Metrics::Instrumentation do allow(Gitlab::Metrics).to receive(:method_call_threshold). and_return(100) - expect(transaction).to_not receive(:add_metric) + expect(transaction).not_to receive(:add_metric) @dummy.foo end @@ -139,9 +136,6 @@ describe Gitlab::Metrics::Instrumentation do allow(described_class).to receive(:transaction). and_return(transaction) - expect(transaction).to receive(:increment). - with(:method_duration, a_kind_of(Numeric)) - expect(transaction).to receive(:add_metric). with(described_class::SERIES, an_instance_of(Hash), method: 'Dummy#bar') @@ -153,7 +147,7 @@ describe Gitlab::Metrics::Instrumentation do allow(Gitlab::Metrics).to receive(:method_call_threshold). and_return(100) - expect(transaction).to_not receive(:add_metric) + expect(transaction).not_to receive(:add_metric) @dummy.new.bar end @@ -226,7 +220,7 @@ describe Gitlab::Metrics::Instrumentation do described_class.instrument_methods(@dummy) - expect(@dummy).to_not respond_to(:_original_kittens) + expect(@dummy).not_to respond_to(:_original_kittens) end it 'can take a block to determine if a method should be instrumented' do @@ -234,7 +228,7 @@ describe Gitlab::Metrics::Instrumentation do false end - expect(@dummy).to_not respond_to(:_original_foo) + expect(@dummy).not_to respond_to(:_original_foo) end end diff --git a/spec/lib/gitlab/metrics/sampler_spec.rb b/spec/lib/gitlab/metrics/sampler_spec.rb index 38da77adc9..59db127674 100644 --- a/spec/lib/gitlab/metrics/sampler_spec.rb +++ b/spec/lib/gitlab/metrics/sampler_spec.rb @@ -130,7 +130,7 @@ describe Gitlab::Metrics::Sampler do 100.times do interval = sampler.sleep_interval - expect(interval).to_not eq(last) + expect(interval).not_to eq(last) last = interval end diff --git a/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb b/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb index e3293a0120..49699ffe28 100644 --- a/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb +++ b/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb @@ -13,7 +13,7 @@ describe Gitlab::Metrics::Subscribers::ActiveRecord do describe 'without a current transaction' do it 'simply returns' do expect_any_instance_of(Gitlab::Metrics::Transaction). - to_not receive(:increment) + not_to receive(:increment) subscriber.sql(event) end diff --git a/spec/lib/gitlab/metrics/subscribers/rails_cache_spec.rb b/spec/lib/gitlab/metrics/subscribers/rails_cache_spec.rb index e01b0b4bd2..d824dc5443 100644 --- a/spec/lib/gitlab/metrics/subscribers/rails_cache_spec.rb +++ b/spec/lib/gitlab/metrics/subscribers/rails_cache_spec.rb @@ -9,7 +9,7 @@ describe Gitlab::Metrics::Subscribers::RailsCache do describe '#cache_read' do it 'increments the cache_read duration' do expect(subscriber).to receive(:increment). - with(:cache_read_duration, event.duration) + with(:cache_read, event.duration) subscriber.cache_read(event) end @@ -18,7 +18,7 @@ describe Gitlab::Metrics::Subscribers::RailsCache do describe '#cache_write' do it 'increments the cache_write duration' do expect(subscriber).to receive(:increment). - with(:cache_write_duration, event.duration) + with(:cache_write, event.duration) subscriber.cache_write(event) end @@ -27,7 +27,7 @@ describe Gitlab::Metrics::Subscribers::RailsCache do describe '#cache_delete' do it 'increments the cache_delete duration' do expect(subscriber).to receive(:increment). - with(:cache_delete_duration, event.duration) + with(:cache_delete, event.duration) subscriber.cache_delete(event) end @@ -36,7 +36,7 @@ describe Gitlab::Metrics::Subscribers::RailsCache do describe '#cache_exist?' do it 'increments the cache_exists duration' do expect(subscriber).to receive(:increment). - with(:cache_exists_duration, event.duration) + with(:cache_exists, event.duration) subscriber.cache_exist?(event) end @@ -61,10 +61,16 @@ describe Gitlab::Metrics::Subscribers::RailsCache do expect(transaction).to receive(:increment). with(:cache_duration, event.duration) + expect(transaction).to receive(:increment). + with(:cache_count, 1) + expect(transaction).to receive(:increment). with(:cache_delete_duration, event.duration) - subscriber.increment(:cache_delete_duration, event.duration) + expect(transaction).to receive(:increment). + with(:cache_delete_count, 1) + + subscriber.increment(:cache_delete, event.duration) end end end diff --git a/spec/lib/gitlab/middleware/rails_queue_duration_spec.rb b/spec/lib/gitlab/middleware/rails_queue_duration_spec.rb new file mode 100644 index 0000000000..fd6f684db0 --- /dev/null +++ b/spec/lib/gitlab/middleware/rails_queue_duration_spec.rb @@ -0,0 +1,31 @@ +require 'spec_helper' + +describe Gitlab::Middleware::RailsQueueDuration do + let(:app) { double(:app) } + let(:middleware) { described_class.new(app) } + let(:env) { {} } + let(:transaction) { double(:transaction) } + + before { expect(app).to receive(:call).with(env).and_return('yay') } + + describe '#call' do + it 'calls the app when metrics are disabled' do + expect(Gitlab::Metrics).to receive(:current_transaction).and_return(nil) + expect(middleware.call(env)).to eq('yay') + end + + context 'when metrics are enabled' do + before { allow(Gitlab::Metrics).to receive(:current_transaction).and_return(transaction) } + + it 'calls the app when metrics are enabled but no timing header is found' do + expect(middleware.call(env)).to eq('yay') + end + + it 'sets proxy_flight_time and calls the app when the header is present' do + env['HTTP_GITLAB_WORHORSE_PROXY_START'] = '123' + expect(transaction).to receive(:set).with(:rails_queue_duration, an_instance_of(Float)) + expect(middleware.call(env)).to eq('yay') + end + end + end +end diff --git a/spec/lib/gitlab/note_data_builder_spec.rb b/spec/lib/gitlab/note_data_builder_spec.rb index f093d0a0d8..e848d88182 100644 --- a/spec/lib/gitlab/note_data_builder_spec.rb +++ b/spec/lib/gitlab/note_data_builder_spec.rb @@ -9,7 +9,8 @@ describe 'Gitlab::NoteDataBuilder', lib: true do before(:each) do expect(data).to have_key(:object_attributes) expect(data[:object_attributes]).to have_key(:url) - expect(data[:object_attributes][:url]).to eq(Gitlab::UrlBuilder.build(note)) + expect(data[:object_attributes][:url]) + .to eq(Gitlab::UrlBuilder.build(note)) expect(data[:object_kind]).to eq('note') expect(data[:user]).to eq(user.hook_attrs) end @@ -37,13 +38,21 @@ describe 'Gitlab::NoteDataBuilder', lib: true do end describe 'When asking for a note on issue' do - let(:issue) { create(:issue, created_at: fixed_time, updated_at: fixed_time) } - let(:note) { create(:note_on_issue, noteable_id: issue.id, project: project) } + let(:issue) do + create(:issue, created_at: fixed_time, updated_at: fixed_time, + project: project) + end + + let(:note) do + create(:note_on_issue, noteable: issue, project: project) + end it 'returns the note and issue-specific data' do expect(data).to have_key(:issue) - expect(data[:issue].except('updated_at')).to eq(issue.hook_attrs.except('updated_at')) - expect(data[:issue]['updated_at']).to be > issue.hook_attrs['updated_at'] + expect(data[:issue].except('updated_at')) + .to eq(issue.reload.hook_attrs.except('updated_at')) + expect(data[:issue]['updated_at']) + .to be > issue.hook_attrs['updated_at'] end include_examples 'project hook data' @@ -51,13 +60,23 @@ describe 'Gitlab::NoteDataBuilder', lib: true do end describe 'When asking for a note on merge request' do - let(:merge_request) { create(:merge_request, created_at: fixed_time, updated_at: fixed_time) } - let(:note) { create(:note_on_merge_request, noteable_id: merge_request.id, project: project) } + let(:merge_request) do + create(:merge_request, created_at: fixed_time, + updated_at: fixed_time, + source_project: project) + end + + let(:note) do + create(:note_on_merge_request, noteable: merge_request, + project: project) + end it 'returns the note and merge request data' do expect(data).to have_key(:merge_request) - expect(data[:merge_request].except('updated_at')).to eq(merge_request.hook_attrs.except('updated_at')) - expect(data[:merge_request]['updated_at']).to be > merge_request.hook_attrs['updated_at'] + expect(data[:merge_request].except('updated_at')) + .to eq(merge_request.reload.hook_attrs.except('updated_at')) + expect(data[:merge_request]['updated_at']) + .to be > merge_request.hook_attrs['updated_at'] end include_examples 'project hook data' @@ -65,13 +84,22 @@ describe 'Gitlab::NoteDataBuilder', lib: true do end describe 'When asking for a note on merge request diff' do - let(:merge_request) { create(:merge_request, created_at: fixed_time, updated_at: fixed_time) } - let(:note) { create(:note_on_merge_request_diff, noteable_id: merge_request.id, project: project) } + let(:merge_request) do + create(:merge_request, created_at: fixed_time, updated_at: fixed_time, + source_project: project) + end + + let(:note) do + create(:note_on_merge_request_diff, noteable: merge_request, + project: project) + end it 'returns the note and merge request diff data' do expect(data).to have_key(:merge_request) - expect(data[:merge_request].except('updated_at')).to eq(merge_request.hook_attrs.except('updated_at')) - expect(data[:merge_request]['updated_at']).to be > merge_request.hook_attrs['updated_at'] + expect(data[:merge_request].except('updated_at')) + .to eq(merge_request.reload.hook_attrs.except('updated_at')) + expect(data[:merge_request]['updated_at']) + .to be > merge_request.hook_attrs['updated_at'] end include_examples 'project hook data' @@ -79,13 +107,22 @@ describe 'Gitlab::NoteDataBuilder', lib: true do end describe 'When asking for a note on project snippet' do - let!(:snippet) { create(:project_snippet, created_at: fixed_time, updated_at: fixed_time) } - let!(:note) { create(:note_on_project_snippet, noteable_id: snippet.id, project: project) } + let!(:snippet) do + create(:project_snippet, created_at: fixed_time, updated_at: fixed_time, + project: project) + end + + let!(:note) do + create(:note_on_project_snippet, noteable: snippet, + project: project) + end it 'returns the note and project snippet data' do expect(data).to have_key(:snippet) - expect(data[:snippet].except('updated_at')).to eq(snippet.hook_attrs.except('updated_at')) - expect(data[:snippet]['updated_at']).to be > snippet.hook_attrs['updated_at'] + expect(data[:snippet].except('updated_at')) + .to eq(snippet.reload.hook_attrs.except('updated_at')) + expect(data[:snippet]['updated_at']) + .to be > snippet.hook_attrs['updated_at'] end include_examples 'project hook data' diff --git a/spec/lib/gitlab/sherlock/collection_spec.rb b/spec/lib/gitlab/sherlock/collection_spec.rb index de6bb86c5d..2ae79b50e7 100644 --- a/spec/lib/gitlab/sherlock/collection_spec.rb +++ b/spec/lib/gitlab/sherlock/collection_spec.rb @@ -11,13 +11,13 @@ describe Gitlab::Sherlock::Collection, lib: true do it 'adds a new transaction' do collection.add(transaction) - expect(collection).to_not be_empty + expect(collection).not_to be_empty end it 'is aliased as <<' do collection << transaction - expect(collection).to_not be_empty + expect(collection).not_to be_empty end end @@ -47,7 +47,7 @@ describe Gitlab::Sherlock::Collection, lib: true do it 'returns false for a collection with a transaction' do collection.add(transaction) - expect(collection).to_not be_empty + expect(collection).not_to be_empty end end diff --git a/spec/lib/gitlab/sherlock/query_spec.rb b/spec/lib/gitlab/sherlock/query_spec.rb index 05da915ccf..0a62042813 100644 --- a/spec/lib/gitlab/sherlock/query_spec.rb +++ b/spec/lib/gitlab/sherlock/query_spec.rb @@ -85,7 +85,7 @@ FROM users; frames = query.application_backtrace expect(frames).to be_an_instance_of(Array) - expect(frames).to_not be_empty + expect(frames).not_to be_empty frames.each do |frame| expect(frame.path).to start_with(Rails.root.to_s) diff --git a/spec/lib/gitlab/sherlock/transaction_spec.rb b/spec/lib/gitlab/sherlock/transaction_spec.rb index 7553f2a045..9fe18f253f 100644 --- a/spec/lib/gitlab/sherlock/transaction_spec.rb +++ b/spec/lib/gitlab/sherlock/transaction_spec.rb @@ -203,7 +203,7 @@ describe Gitlab::Sherlock::Transaction, lib: true do end it 'only tracks queries triggered from the transaction thread' do - expect(transaction).to_not receive(:track_query) + expect(transaction).not_to receive(:track_query) Thread.new { subscription.publish('test', time, time, nil, query_data) }. join @@ -226,7 +226,7 @@ describe Gitlab::Sherlock::Transaction, lib: true do end it 'only tracks views rendered from the transaction thread' do - expect(transaction).to_not receive(:track_view) + expect(transaction).not_to receive(:track_view) Thread.new { subscription.publish('test', time, time, nil, view_data) }. join diff --git a/spec/lib/gitlab/url_sanitizer_spec.rb b/spec/lib/gitlab/url_sanitizer_spec.rb new file mode 100644 index 0000000000..de55334118 --- /dev/null +++ b/spec/lib/gitlab/url_sanitizer_spec.rb @@ -0,0 +1,68 @@ +require 'spec_helper' + +describe Gitlab::UrlSanitizer, lib: true do + let(:credentials) { { user: 'blah', password: 'password' } } + let(:url_sanitizer) do + described_class.new("https://github.com/me/project.git", credentials: credentials) + end + + describe '.sanitize' do + def sanitize_url(url) + # We want to try with multi-line content because is how error messages are formatted + described_class.sanitize(%Q{ + remote: Not Found + fatal: repository '#{url}' not found + }) + end + + it 'mask the credentials from HTTP URLs' do + filtered_content = sanitize_url('http://user:pass@test.com/root/repoC.git/') + + expect(filtered_content).to include("http://*****:*****@test.com/root/repoC.git/") + end + + it 'mask the credentials from HTTPS URLs' do + filtered_content = sanitize_url('https://user:pass@test.com/root/repoA.git/') + + expect(filtered_content).to include("https://*****:*****@test.com/root/repoA.git/") + end + + it 'mask credentials from SSH URLs' do + filtered_content = sanitize_url('ssh://user@host.test/path/to/repo.git') + + expect(filtered_content).to include("ssh://*****@host.test/path/to/repo.git") + end + + it 'does not modify Git URLs' do + # git protocol does not support authentication + filtered_content = sanitize_url('git://host.test/path/to/repo.git') + + expect(filtered_content).to include("git://host.test/path/to/repo.git") + end + + it 'does not modify scp-like URLs' do + filtered_content = sanitize_url('user@server:project.git') + + expect(filtered_content).to include("user@server:project.git") + end + end + + describe '#sanitized_url' do + it { expect(url_sanitizer.sanitized_url).to eq("https://github.com/me/project.git") } + end + + describe '#credentials' do + it { expect(url_sanitizer.credentials).to eq(credentials) } + end + + describe '#full_url' do + it { expect(url_sanitizer.full_url).to eq("https://blah:password@github.com/me/project.git") } + + it 'supports scp-like URLs' do + sanitizer = described_class.new('user@server:project.git') + + expect(sanitizer.full_url).to eq('user@server:project.git') + end + end + +end diff --git a/spec/lib/json_web_token/rsa_token_spec.rb b/spec/lib/json_web_token/rsa_token_spec.rb new file mode 100644 index 0000000000..1872675451 --- /dev/null +++ b/spec/lib/json_web_token/rsa_token_spec.rb @@ -0,0 +1,43 @@ +describe JSONWebToken::RSAToken do + let(:rsa_key) do + OpenSSL::PKey::RSA.new <<-eos.strip_heredoc + -----BEGIN RSA PRIVATE KEY----- + MIIBOgIBAAJBAMA5sXIBE0HwgIB40iNidN4PGWzOyLQK0bsdOBNgpEXkDlZBvnak + OUgAPF+rME4PB0Yl415DabUI40T5UNmlwxcCAwEAAQJAZtY2pSwIFm3JAXIh0cZZ + iXcAfiJ+YzuqinUOS+eW2sBCAEzjcARlU/o6sFQgtsOi4FOMczAd1Yx8UDMXMmrw + 2QIhAPBgVhJiTF09pdmeFWutCvTJDlFFAQNbrbo2X2x/9WF9AiEAzLgqMKeStSRu + H9N16TuDrUoO8R+DPqriCwkKrSHaWyMCIFzMhE4inuKcSywBaLmiG4m3GQzs++Al + A6PRG/PSTpQtAiBxtBg6zdf+JC3GH3zt/dA0/10tL4OF2wORfYQghRzyYQIhAL2l + 0ZQW+yLIZAGrdBFWYEAa52GZosncmzBNlsoTgwE4 + -----END RSA PRIVATE KEY----- + eos + end + let(:rsa_token) { described_class.new(nil) } + let(:rsa_encoded) { rsa_token.encoded } + + before { allow_any_instance_of(described_class).to receive(:key).and_return(rsa_key) } + + context 'token' do + context 'for valid key to be validated' do + before { rsa_token['key'] = 'value' } + + subject { JWT.decode(rsa_encoded, rsa_key) } + + it { expect{subject}.not_to raise_error } + it { expect(subject.first).to include('key' => 'value') } + it do + expect(subject.second).to eq( + "typ" => "JWT", + "alg" => "RS256", + "kid" => "OGXY:4TR7:FAVO:WEM2:XXEW:E4FP:TKL7:7ACK:TZAF:D54P:SUIA:P3B2") + end + end + + context 'for invalid key to raise an exception' do + let(:new_key) { OpenSSL::PKey::RSA.generate(512) } + subject { JWT.decode(rsa_encoded, new_key) } + + it { expect{subject}.to raise_error(JWT::DecodeError) } + end + end +end diff --git a/spec/lib/json_web_token/token_spec.rb b/spec/lib/json_web_token/token_spec.rb new file mode 100644 index 0000000000..3d955e4d77 --- /dev/null +++ b/spec/lib/json_web_token/token_spec.rb @@ -0,0 +1,18 @@ +describe JSONWebToken::Token do + let(:token) { described_class.new } + + context 'custom parameters' do + let(:value) { 'value' } + before { token[:key] = value } + + it { expect(token[:key]).to eq(value) } + it { expect(token.payload).to include(key: value) } + end + + context 'embeds default payload' do + subject { token.payload } + let(:default) { token.send(:default_payload) } + + it { is_expected.to include(default) } + end +end diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index 495c5cbac0..818825b147 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -51,7 +51,7 @@ describe Notify do context 'when enabled email_author_in_body' do before do - allow(current_application_settings).to receive(:email_author_in_body).and_return(true) + allow_any_instance_of(ApplicationSetting).to receive(:email_author_in_body).and_return(true) end it 'contains a link to note author' do @@ -230,7 +230,7 @@ describe Notify do context 'when enabled email_author_in_body' do before do - allow(current_application_settings).to receive(:email_author_in_body).and_return(true) + allow_any_instance_of(ApplicationSetting).to receive(:email_author_in_body).and_return(true) end it 'contains a link to note author' do @@ -454,7 +454,7 @@ describe Notify do context 'when enabled email_author_in_body' do before do - allow(current_application_settings).to receive(:email_author_in_body).and_return(true) + allow_any_instance_of(ApplicationSetting).to receive(:email_author_in_body).and_return(true) end it 'contains a link to note author' do @@ -593,7 +593,7 @@ describe Notify do let(:user) { create(:user) } let(:tree_path) { namespace_project_tree_path(project.namespace, project, "master") } - subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :create) } + subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/heads/master', action: :create) } it_behaves_like 'it should not have Gmail Actions links' it_behaves_like "a user cannot unsubscribe through footer link" @@ -606,10 +606,6 @@ describe Notify do expect(sender.address).to eq(gitlab_sender) end - it 'is sent to recipient' do - is_expected.to deliver_to 'devs@company.name' - end - it 'has the correct subject' do is_expected.to have_subject /Pushed new branch master/ end @@ -624,7 +620,7 @@ describe Notify do let(:user) { create(:user) } let(:tree_path) { namespace_project_tree_path(project.namespace, project, "v1.0") } - subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/tags/v1.0', action: :create) } + subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/tags/v1.0', action: :create) } it_behaves_like 'it should not have Gmail Actions links' it_behaves_like "a user cannot unsubscribe through footer link" @@ -637,10 +633,6 @@ describe Notify do expect(sender.address).to eq(gitlab_sender) end - it 'is sent to recipient' do - is_expected.to deliver_to 'devs@company.name' - end - it 'has the correct subject' do is_expected.to have_subject /Pushed new tag v1\.0/ end @@ -654,7 +646,7 @@ describe Notify do let(:example_site_path) { root_path } let(:user) { create(:user) } - subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :delete) } + subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/heads/master', action: :delete) } it_behaves_like 'it should not have Gmail Actions links' it_behaves_like "a user cannot unsubscribe through footer link" @@ -667,10 +659,6 @@ describe Notify do expect(sender.address).to eq(gitlab_sender) end - it 'is sent to recipient' do - is_expected.to deliver_to 'devs@company.name' - end - it 'has the correct subject' do is_expected.to have_subject /Deleted branch master/ end @@ -680,7 +668,7 @@ describe Notify do let(:example_site_path) { root_path } let(:user) { create(:user) } - subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/tags/v1.0', action: :delete) } + subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/tags/v1.0', action: :delete) } it_behaves_like 'it should not have Gmail Actions links' it_behaves_like "a user cannot unsubscribe through footer link" @@ -693,10 +681,6 @@ describe Notify do expect(sender.address).to eq(gitlab_sender) end - it 'is sent to recipient' do - is_expected.to deliver_to 'devs@company.name' - end - it 'has the correct subject' do is_expected.to have_subject /Deleted tag v1\.0/ end @@ -709,8 +693,9 @@ describe Notify do let(:commits) { Commit.decorate(compare.commits, nil) } let(:diff_path) { namespace_project_compare_path(project.namespace, project, from: Commit.new(compare.base, project), to: Commit.new(compare.head, project)) } let(:send_from_committer_email) { false } + let(:diff_refs) { [project.merge_base_commit(sample_image_commit.id, sample_commit.id), project.commit(sample_commit.id)] } - subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :push, compare: compare, reverse_compare: false, send_from_committer_email: send_from_committer_email) } + subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/heads/master', action: :push, compare: compare, reverse_compare: false, diff_refs: diff_refs, send_from_committer_email: send_from_committer_email) } it_behaves_like 'it should not have Gmail Actions links' it_behaves_like "a user cannot unsubscribe through footer link" @@ -723,10 +708,6 @@ describe Notify do expect(sender.address).to eq(gitlab_sender) end - it 'is sent to recipient' do - is_expected.to deliver_to 'devs@company.name' - end - it 'has the correct subject' do is_expected.to have_subject /\[#{project.path_with_namespace}\]\[master\] #{commits.length} commits:/ end @@ -735,15 +716,15 @@ describe Notify do is_expected.to have_body_text /Change some files/ end - it 'includes diffs' do - is_expected.to have_body_text /def archive_formats_regex/ + it 'includes diffs with character-level highlighting' do + is_expected.to have_body_text /def<\/span> archive_formats_regex/ end it 'contains a link to the diff' do is_expected.to have_body_text /#{diff_path}/ end - it 'doesn not contain the misleading footer' do + it 'does not contain the misleading footer' do is_expected.not_to have_body_text /you are a member of/ end @@ -817,8 +798,9 @@ describe Notify do let(:compare) { Gitlab::Git::Compare.new(project.repository.raw_repository, sample_commit.parent_id, sample_commit.id) } let(:commits) { Commit.decorate(compare.commits, nil) } let(:diff_path) { namespace_project_commit_path(project.namespace, project, commits.first) } + let(:diff_refs) { [project.merge_base_commit(sample_commit.parent_id, sample_commit.id), project.commit(sample_commit.id)] } - subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :push, compare: compare) } + subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/heads/master', action: :push, compare: compare, diff_refs: diff_refs) } it_behaves_like 'it should show Gmail Actions View Commit link' it_behaves_like "a user cannot unsubscribe through footer link" @@ -831,10 +813,6 @@ describe Notify do expect(sender.address).to eq(gitlab_sender) end - it 'is sent to recipient' do - is_expected.to deliver_to 'devs@company.name' - end - it 'has the correct subject' do is_expected.to have_subject /#{commits.first.title}/ end @@ -843,8 +821,8 @@ describe Notify do is_expected.to have_body_text /Change some files/ end - it 'includes diffs' do - is_expected.to have_body_text /def archive_formats_regex/ + it 'includes diffs with character-level highlighting' do + is_expected.to have_body_text /def<\/span> archive_formats_regex/ end it 'contains a link to the diff' do diff --git a/spec/mailers/previews/devise_mailer_preview.rb b/spec/mailers/previews/devise_mailer_preview.rb new file mode 100644 index 0000000000..dc3062a433 --- /dev/null +++ b/spec/mailers/previews/devise_mailer_preview.rb @@ -0,0 +1,11 @@ +class DeviseMailerPreview < ActionMailer::Preview + def confirmation_instructions_for_signup + user = User.new(name: 'Jane Doe', email: 'signup@example.com') + DeviseMailer.confirmation_instructions(user, 'faketoken', {}) + end + + def confirmation_instructions_for_new_email + user = User.last + DeviseMailer.confirmation_instructions(user, 'faketoken', {}) + end +end diff --git a/spec/mailers/shared/notify.rb b/spec/mailers/shared/notify.rb index 5a85cb501d..93de5850ba 100644 --- a/spec/mailers/shared/notify.rb +++ b/spec/mailers/shared/notify.rb @@ -146,8 +146,8 @@ shared_examples 'it should have Gmail Actions links' do end shared_examples 'it should not have Gmail Actions links' do - it { is_expected.to_not have_body_text '

    ;~W88}#(x1WH~0kNnVRRVoxx6Q<4N;j2e5P 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 Z^w2{OJ@n8+4?T9p_#ZMZ503y?2LR=%8W{ip From 6c082edef83c021b933724c33fb979efdc697904 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 18 May 2016 18:17:16 +0200 Subject: [PATCH 186/730] fixed issue exporting builds --- lib/gitlab/import_export/relation_factory.rb | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb index 68319441a6..d4e49ae17f 100644 --- a/lib/gitlab/import_export/relation_factory.rb +++ b/lib/gitlab/import_export/relation_factory.rb @@ -22,7 +22,7 @@ module Gitlab update_user_references(relation_hash, members_mapper.map) update_project_references(relation_hash, klass) - imported_object(klass, relation_hash) + generate_imported_object(klass, relation_hash, relation_sym) end private @@ -58,6 +58,18 @@ module Gitlab "\n\n *By #{author_name} on #{timestamp} (imported from GitLab project)*" end + def generate_imported_object(klass, relation_hash, relation_sym) + if relation_sym == 'commit_status' # call #trace= method after assigning the other attributes + trace = relation_hash.delete('trace') + imported_object(klass, relation_hash) do |imported_object| + imported_object.trace = trace + imported_object.commit_id = nil + end + else + imported_object(klass, relation_hash) + end + end + def update_project_references(relation_hash, klass) project_id = relation_hash.delete('project_id') @@ -86,6 +98,7 @@ module Gitlab def imported_object(klass, relation_hash) imported_object = klass.new(relation_hash) + yield(imported_object) if block_given? imported_object.importing = true if imported_object.respond_to?(:importing) imported_object end From 30f4dcd4c906a71db98833075c76eb59922f5b98 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 19 May 2016 13:02:57 +0200 Subject: [PATCH 187/730] uploads export --- .../projects/import_export/export_service.rb | 6 +++- lib/gitlab/import_export/uploads_saver.rb | 35 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 lib/gitlab/import_export/uploads_saver.rb diff --git a/app/services/projects/import_export/export_service.rb b/app/services/projects/import_export/export_service.rb index 0691ca9d46..1a23a4ede9 100644 --- a/app/services/projects/import_export/export_service.rb +++ b/app/services/projects/import_export/export_service.rb @@ -4,7 +4,7 @@ module Projects def execute(options = {}) @shared = Gitlab::ImportExport::Shared.new(relative_path: File.join(project.path_with_namespace, 'work')) - save_all if [save_version, save_project_tree, bundle_repo, bundle_wiki_repo].all? + save_all if [save_version, save_project_tree, save_uploads, bundle_repo, bundle_wiki_repo].all? cleanup_and_notify_worker if @shared.errors.any? end @@ -18,6 +18,10 @@ module Projects Gitlab::ImportExport::ProjectTreeSaver.new(project: project, shared: @shared).save end + def save_uploads + Gitlab::ImportExport::UploadsSaver.save(project: project, shared: @shared) + end + def bundle_repo Gitlab::ImportExport::RepoBundler.new(project: project, shared: @shared).bundle end diff --git a/lib/gitlab/import_export/uploads_saver.rb b/lib/gitlab/import_export/uploads_saver.rb new file mode 100644 index 0000000000..3420d2ea4c --- /dev/null +++ b/lib/gitlab/import_export/uploads_saver.rb @@ -0,0 +1,35 @@ +module Gitlab + module ImportExport + class UploadsSaver + + def self.save(*args) + new(*args).save + end + + def initialize(project:, shared:) + @project = project + @shared = shared + end + + def save + return true unless File.directory?(uploads_path) + + FileUtils.copy_entry(uploads_path, uploads_export_path) + true + rescue => e + @shared.error(e.message) + false + end + + private + + def uploads_export_path + File.join(@shared.export_path, 'uploads') + end + + def uploads_path + File.join(Rails.root.join('public/uploads'), project.path_with_namespace) + end + end + end +end From bac27df16c35abb2f8115d9c94edcc4ecbace1a7 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 19 May 2016 13:10:41 +0200 Subject: [PATCH 188/730] Squashed commit of the following: commit 92de6309e1c918a4ae023641dc42b196b3fb25ea Merge: 6c082ed 30f4dcd Author: James Lopez Date: Thu May 19 13:06:34 2016 +0200 Merge branches 'feature/project-export' and 'feature/project-import' of gitlab.com:gitlab-org/gitlab-ce into feature/project-import commit 30f4dcd4c906a71db98833075c76eb59922f5b98 Author: James Lopez Date: Thu May 19 13:02:57 2016 +0200 uploads export --- .../projects/import_export/export_service.rb | 6 +++- lib/gitlab/import_export/uploads_saver.rb | 35 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 lib/gitlab/import_export/uploads_saver.rb diff --git a/app/services/projects/import_export/export_service.rb b/app/services/projects/import_export/export_service.rb index 0691ca9d46..1a23a4ede9 100644 --- a/app/services/projects/import_export/export_service.rb +++ b/app/services/projects/import_export/export_service.rb @@ -4,7 +4,7 @@ module Projects def execute(options = {}) @shared = Gitlab::ImportExport::Shared.new(relative_path: File.join(project.path_with_namespace, 'work')) - save_all if [save_version, save_project_tree, bundle_repo, bundle_wiki_repo].all? + save_all if [save_version, save_project_tree, save_uploads, bundle_repo, bundle_wiki_repo].all? cleanup_and_notify_worker if @shared.errors.any? end @@ -18,6 +18,10 @@ module Projects Gitlab::ImportExport::ProjectTreeSaver.new(project: project, shared: @shared).save end + def save_uploads + Gitlab::ImportExport::UploadsSaver.save(project: project, shared: @shared) + end + def bundle_repo Gitlab::ImportExport::RepoBundler.new(project: project, shared: @shared).bundle end diff --git a/lib/gitlab/import_export/uploads_saver.rb b/lib/gitlab/import_export/uploads_saver.rb new file mode 100644 index 0000000000..3420d2ea4c --- /dev/null +++ b/lib/gitlab/import_export/uploads_saver.rb @@ -0,0 +1,35 @@ +module Gitlab + module ImportExport + class UploadsSaver + + def self.save(*args) + new(*args).save + end + + def initialize(project:, shared:) + @project = project + @shared = shared + end + + def save + return true unless File.directory?(uploads_path) + + FileUtils.copy_entry(uploads_path, uploads_export_path) + true + rescue => e + @shared.error(e.message) + false + end + + private + + def uploads_export_path + File.join(@shared.export_path, 'uploads') + end + + def uploads_path + File.join(Rails.root.join('public/uploads'), project.path_with_namespace) + end + end + end +end From 816dfcb1c54277ce5e3e3da1a0c1028b4c2cdb3c Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 19 May 2016 13:21:56 +0200 Subject: [PATCH 189/730] fix path --- lib/gitlab/import_export/uploads_saver.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gitlab/import_export/uploads_saver.rb b/lib/gitlab/import_export/uploads_saver.rb index 3420d2ea4c..7bce4ddd4e 100644 --- a/lib/gitlab/import_export/uploads_saver.rb +++ b/lib/gitlab/import_export/uploads_saver.rb @@ -28,7 +28,7 @@ module Gitlab end def uploads_path - File.join(Rails.root.join('public/uploads'), project.path_with_namespace) + File.join(Rails.root.join('public/uploads'), @project.path_with_namespace) end end end From 1466997755f704b1f8af49ced136e91827a0892c Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 19 May 2016 15:36:20 +0200 Subject: [PATCH 190/730] import uploads. Fixed a few things to do with members, triggers, etc... --- app/models/member.rb | 9 +++++---- lib/gitlab/import_export.rb | 4 ++++ lib/gitlab/import_export/import_service.rb | 6 +++++- lib/gitlab/import_export/members_mapper.rb | 4 ++-- lib/gitlab/import_export/relation_factory.rb | 10 +++++++++- lib/gitlab/import_export/uploads_restorer.rb | 19 +++++++++++++++++++ lib/gitlab/import_export/uploads_saver.rb | 13 +++++++++---- 7 files changed, 53 insertions(+), 12 deletions(-) create mode 100644 lib/gitlab/import_export/uploads_restorer.rb diff --git a/app/models/member.rb b/app/models/member.rb index cca82da89f..bef0b545c7 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -22,6 +22,7 @@ class Member < ActiveRecord::Base include Gitlab::Access attr_accessor :raw_invite_token + attr_accessor :importing belongs_to :created_by, class_name: "User" belongs_to :user @@ -54,10 +55,10 @@ class Member < ActiveRecord::Base scope :owners, -> { where(access_level: OWNER) } before_validation :generate_invite_token, on: :create, if: -> (member) { member.invite_email.present? } - after_create :send_invite, if: :invite? - after_create :create_notification_setting, unless: :invite? - after_create :post_create_hook, unless: :invite? - after_update :post_update_hook, unless: :invite? + after_create :send_invite, if: :invite?, unless: :importing + after_create :create_notification_setting, unless: [:invite?, :importing] + after_create :post_create_hook, unless: [:invite?, :importing] + after_update :post_update_hook, unless: [:invite?, :importing] after_destroy :post_destroy_hook, unless: :invite? delegate :name, :username, :email, to: :user, prefix: true diff --git a/lib/gitlab/import_export.rb b/lib/gitlab/import_export.rb index 65a8fcfadd..9c04a3d699 100644 --- a/lib/gitlab/import_export.rb +++ b/lib/gitlab/import_export.rb @@ -27,5 +27,9 @@ module Gitlab def version VERSION end + + def reset_tokens? + true + end end end diff --git a/lib/gitlab/import_export/import_service.rb b/lib/gitlab/import_export/import_service.rb index b025bff29b..acd734f089 100644 --- a/lib/gitlab/import_export/import_service.rb +++ b/lib/gitlab/import_export/import_service.rb @@ -16,7 +16,7 @@ module Gitlab def execute Gitlab::ImportExport::Importer.import(archive_file: @archive_file, shared: @shared) - if [restore_version, restore_project_tree, restore_repo, restore_wiki_repo].all? + if [restore_version, restore_project_tree, restore_repo, restore_wiki_repo, restore_uploads].all? project_tree.project else project_tree.project.destroy if project_tree.project @@ -52,6 +52,10 @@ module Gitlab project: ProjectWiki.new(project_tree.project)).restore end + def restore_uploads + Gitlab::ImportExport::UploadsRestorer.restore(project: project_tree.project, shared: @shared) + end + def path_with_namespace(project_path) File.join(@namespace.path, project_path) end diff --git a/lib/gitlab/import_export/members_mapper.rb b/lib/gitlab/import_export/members_mapper.rb index 4401fab3d2..28e5786715 100644 --- a/lib/gitlab/import_export/members_mapper.rb +++ b/lib/gitlab/import_export/members_mapper.rb @@ -50,11 +50,11 @@ module Gitlab end def member_hash(member) - member.except('id').merge(source_id: @project.id) + member.except('id').merge(source_id: @project.id, importing: true) end def default_project_member_hash - { user: @user, access_level: ProjectMember::MASTER, source_id: @project.id } + { user: @user, access_level: ProjectMember::MASTER, source_id: @project.id, importing: true } end def find_project_user_query(member) diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb index d4e49ae17f..566777e8fc 100644 --- a/lib/gitlab/import_export/relation_factory.rb +++ b/lib/gitlab/import_export/relation_factory.rb @@ -12,7 +12,7 @@ module Gitlab builds: 'Ci::Build', hooks: 'ProjectHook' }.freeze - USER_REFERENCES = %w(author_id assignee_id updated_by_id).freeze + USER_REFERENCES = %w(author_id assignee_id updated_by_id user_id).freeze def create(relation_sym:, relation_hash:, members_mapper:, user_admin:) relation_sym = parse_relation_sym(relation_sym) @@ -21,6 +21,7 @@ module Gitlab update_missing_author(relation_hash, members_mapper, user_admin) if relation_sym == :notes update_user_references(relation_hash, members_mapper.map) update_project_references(relation_hash, klass) + reset_tokens(relation_hash) if relation_sym == 'Ci::Trigger' generate_imported_object(klass, relation_hash, relation_sym) end @@ -88,6 +89,13 @@ module Gitlab relation_hash['gl_project_id'] = project_id if relation_hash ['gl_project_id'] end + def reset_tokens(relation_hash) + return unless Gitlab::ImportExport.reset_tokens? + + # If we import/export a project to the same instance, tokens will have to be reseated. + relation_hash['token'] = nil + end + def relation_class(relation_sym) relation_sym.to_s.classify.constantize end diff --git a/lib/gitlab/import_export/uploads_restorer.rb b/lib/gitlab/import_export/uploads_restorer.rb new file mode 100644 index 0000000000..fdcbc48eb1 --- /dev/null +++ b/lib/gitlab/import_export/uploads_restorer.rb @@ -0,0 +1,19 @@ +module Gitlab + module ImportExport + class UploadsRestorer < UploadsSaver + + class << self + alias_method :restore, :save + end + + def save + return true unless File.directory?(uploads_export_path) + + copy_files(uploads_export_path, uploads_path) + rescue => e + @shared.error(e) + false + end + end + end +end diff --git a/lib/gitlab/import_export/uploads_saver.rb b/lib/gitlab/import_export/uploads_saver.rb index 3420d2ea4c..93bc626b36 100644 --- a/lib/gitlab/import_export/uploads_saver.rb +++ b/lib/gitlab/import_export/uploads_saver.rb @@ -14,21 +14,26 @@ module Gitlab def save return true unless File.directory?(uploads_path) - FileUtils.copy_entry(uploads_path, uploads_export_path) - true + copy_files(uploads_path, uploads_export_path) rescue => e - @shared.error(e.message) + @shared.error(e) false end private + def copy_files(source, destination) + FileUtils.mkdir_p(destination) + FileUtils.copy_entry(source, destination) + true + end + def uploads_export_path File.join(@shared.export_path, 'uploads') end def uploads_path - File.join(Rails.root.join('public/uploads'), project.path_with_namespace) + File.join(Rails.root.join('public/uploads'), @project.path_with_namespace) end end end From 7df495fb7702f3635d6746cb9b0d79d00eafed80 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 19 May 2016 15:37:21 +0200 Subject: [PATCH 191/730] updated uploads saver --- lib/gitlab/import_export/uploads_saver.rb | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/gitlab/import_export/uploads_saver.rb b/lib/gitlab/import_export/uploads_saver.rb index 7bce4ddd4e..93bc626b36 100644 --- a/lib/gitlab/import_export/uploads_saver.rb +++ b/lib/gitlab/import_export/uploads_saver.rb @@ -14,15 +14,20 @@ module Gitlab def save return true unless File.directory?(uploads_path) - FileUtils.copy_entry(uploads_path, uploads_export_path) - true + copy_files(uploads_path, uploads_export_path) rescue => e - @shared.error(e.message) + @shared.error(e) false end private + def copy_files(source, destination) + FileUtils.mkdir_p(destination) + FileUtils.copy_entry(source, destination) + true + end + def uploads_export_path File.join(@shared.export_path, 'uploads') end From becd9bfdc6142779e3874ba0558af29d9ef96588 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 19 May 2016 16:42:41 +0200 Subject: [PATCH 192/730] updated spec file --- .../import_export/test_project_export.tar.gz | Bin 340523 -> 672360 bytes 1 file changed, 0 insertions(+), 0 deletions(-) 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 7eed8a6306a1e3fb2c06b2eb148e765da05de12c..b85055070d821808e0ca0e52254bee72520637db 100644 GIT binary patch delta 185822 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 z

    7g8I(}Y#lKt*9#?#@J6{iJE91IC@UCdqoQIM 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�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 a2L}fS2L}fS2M34$1O5VaR0RhB2nPT)(dtP6 delta 76663 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%0A6Whh9o8R7GQTtRFcu7wXsDNtpP zG>MTA=4=_d&_r#`6zZ|&QDJqj*K;Rd`=<&HVk;2>V~KP#EnJ|oWl)HQz?IOV*=1f z{V9}ygs}sd*D${wmC1&fEPli9x16xZ_}-_nLST`;GQ*;JgIgY-Mr~kJzkC`~0*3*K zs`M=^WH~l87-U^^xyd)Ht-#Yw0y!}sKxFu02rW^YCbf%+Th)(drhbSpc~_L*i+atY zB;1jt3e4TG6onV5MdGk!)N6kb_)9VXd5$kjh{_3MakW$jOOiOAbp{6j2kr+v0KIupU@-n{Tn4BfPW44G*5LxRm{(!(k zK`}*5M2+vOAk~>0CNK!e6f8!~Ax&@vE%3QA!Gi&qX1NJHwJtk1C-CwRHXss$ zgdimX3w*L$QGUPg7%Y76LrJEOwUrqx)EnG#`B1RNd=eju=$L;(MzS4C6C~S^d6CyM zX~lA6Q_?k6ajdjrOBqdSnhzyOp1iQ%O6^0b^-_JS3x~8aDtq)qg|#1?9N5ytOh(;` z$=TEXAp={KF;>Pn2s4f4K@5y5a<&mUr|B6@pgJPtLV_mESROzBUJ_<@2@ey{pU%W~ z_~E)Cz6d@GQmTJ}EMj7jgNRrLgG5>=7P)H%dAqogA*84&`Q`+16-03{ATxv;(V;!7 z{rsR2-$q7ALo{yOT~DlS>TAGP;mJLt;R2-`TwEh=3-p3T=lUUTL?hfcV3Ayf;6MV_ zo(<(NW9L2brKI?;LLi7AZ9y&!5uX}?U~Y&RLkAi?a*BUSRX90@Vgx#q%UEMf2JTU7 zJIst8e9tdh8Kg&d=+{DzT@-hMnwh{(a<__ni#Qr6Llc0?WNk;HMli>>7((P5X0pfy z7wf_!p~zDZp|=>G_8}DG0*r!`!t`ZiWqgnmxJArLEPV;n8Mom?-v<@eUx_&xqi`0- z45MPAfboAx0hMCcGYN)d%mQXcKE1=a!T`p&l^~^T&IvqW ze6O${xLQJ5tAe~)6=iQJ(%=MSxCE_|OF`{6!cBn=ucPc>M&0p^da)XGlpEUV2G=Wr z@X>!^Xz76HXF|6zl|UEoL6#*z%OuE>M+MImNVx%kJF}sMdLrtWMQR0fJpgPvDHj^|C>1-blMk-~;j3F5VZG=4 zVrUN1E7i35SZ5#tuFG7|+A~*M-3ow77tBjBxS&VYF7RENKQpgT9@bD5ib)_N= zuoT1E5=c`wsp$0xIAMauW#Dxld~-K!FHH$-Z6dfbN&z37gs2uFRX=PA5+n$ryUxK? zc|Kwl2XyWr5ozNTY(pW+2C;m2lL%uT1>T+njZeZ?nnG5#z^Y`_#VODgyP(KK43mGs z7Ky@ciAI^ogiXI8&PoNv7;HH#xM>dFDh3+~gpE-lU336#^pqmS2I}M-e4ivZ7htS! zg`A{@ln&62eyuKaj~W#ZzuVd-8*wsy`Qsl(P`#+yS&=N zGfP*umtC2^%(qYWcJaSCdpv)3=B?r1ptw_D5~p%Zk8zqp=Gs-C>Z@NUab1y|%Kc`? z2idU9Kdd)|ZJ8D`Rm?FqF)%PT3_Nk-yzkZ1zKI=gdM#ux9({2jdCHtC^Y*7al-YSe zn_+)EkE3P99Bofsy+DogXU?%O2uUzcRalj7H8nlPrExRkHTPY!HL56Hy?Zv$F*^!I i!6+C7qhJ(_f>AIEM!_f;1*2dTAOHZwlBK@@;06Gb%tLAb From 1eb802cde331fa8b3e18b45d0d3f81061661a22f Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 13 May 2016 16:25:27 +0200 Subject: [PATCH 157/730] fixed leaving comments on notes about missing authors --- lib/gitlab/import_export/import_service.rb | 7 ++++++- lib/gitlab/import_export/members_mapper.rb | 13 +++++++------ lib/gitlab/import_export/project_tree_restorer.rb | 2 +- lib/gitlab/import_export/relation_factory.rb | 9 +++++---- .../lib/gitlab/import_export/members_mapper_spec.rb | 2 +- 5 files changed, 20 insertions(+), 13 deletions(-) diff --git a/lib/gitlab/import_export/import_service.rb b/lib/gitlab/import_export/import_service.rb index 670f1ebece..0c483884fe 100644 --- a/lib/gitlab/import_export/import_service.rb +++ b/lib/gitlab/import_export/import_service.rb @@ -16,7 +16,12 @@ module Gitlab def execute Gitlab::ImportExport::Importer.import(archive_file: @archive_file, shared: @shared) - project_tree.project if [restore_project_tree, restore_repo, restore_wiki_repo].all? + if [restore_project_tree, restore_repo, restore_wiki_repo].all? + project_tree.project + else + project_tree.project.destroy if project_tree.project + nil + end end private diff --git a/lib/gitlab/import_export/members_mapper.rb b/lib/gitlab/import_export/members_mapper.rb index da8aa47565..5332529a90 100644 --- a/lib/gitlab/import_export/members_mapper.rb +++ b/lib/gitlab/import_export/members_mapper.rb @@ -4,10 +4,10 @@ module Gitlab attr_reader :map, :note_member_list - def initialize(exported_members:, user:, project_id:) + def initialize(exported_members:, user:, project:) @exported_members = exported_members @user = user - @project_id = project_id + @project = project @note_member_list = [] @project_member_map = Hash.new do |_, key| @@ -36,20 +36,21 @@ module Gitlab end def member_hash(member) - member.except('id').merge(source_id: @project_id) + member.except('id').merge(source_id: @project.id) end - #TODO: If default, then we need to leave a comment 'Comment by ' on comments def default_project_member @default_project_member ||= begin + return @project.project_members.first.user.id unless @project.project_members.empty? default_member = ProjectMember.new(default_project_member_hash) - default_member.user.id if default_member.save + default_member.save! + default_member.user.id end end def default_project_member_hash - { user: @user, access_level: ProjectMember::MASTER, source_id: @project_id } + { user: @user, access_level: ProjectMember::MASTER, source_id: @project.id } end def find_project_user_query(member) diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index a840c9f947..bd343d0b69 100644 --- a/lib/gitlab/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -29,7 +29,7 @@ module Gitlab def members_mapper @members_mapper ||= Gitlab::ImportExport::MembersMapper.new(exported_members: @project_members, user: @user, - project_id: project.id) + project: project) end def create_relations(relation_list = default_relation_list, tree_hash = @tree_hash) diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb index 0adcd0d5e6..cdd4987f98 100644 --- a/lib/gitlab/import_export/relation_factory.rb +++ b/lib/gitlab/import_export/relation_factory.rb @@ -30,16 +30,17 @@ module Gitlab def update_missing_author(relation_hash, members_map) old_author_id = relation_hash['author_id'] relation_hash['author_id'] = members_map.map[old_author_id] + author = relation_hash.delete('author') + return unless members_map.note_member_list.include?(old_author_id) relation_hash['note'] = ('*Blank note*') if relation_hash['note'].blank? - relation_hash['note'] += (missing_author_note(relation_hash['updated_at'], - relation_hash['author']['name'])) - relation_hash.delete('author') + relation_hash['note'] += (missing_author_note(relation_hash['updated_at'], author['name'])) end def missing_author_note(updated_at, author_name) - "\n\n *By #{author_name} on #{updated_at} (imported from GitLab project)*" + timestamp = updated_at.split('.').first + "\n\n *By #{author_name} on #{timestamp} (imported from GitLab project)*" end def update_project_references(relation_hash, klass) diff --git a/spec/lib/gitlab/import_export/members_mapper_spec.rb b/spec/lib/gitlab/import_export/members_mapper_spec.rb index 78706f64fb..adaadbff6f 100644 --- a/spec/lib/gitlab/import_export/members_mapper_spec.rb +++ b/spec/lib/gitlab/import_export/members_mapper_spec.rb @@ -32,7 +32,7 @@ describe Gitlab::ImportExport::MembersMapper, services: true do let(:members_mapper) do described_class.new( - exported_members: exported_members, user: user, project_id: project.id) + exported_members: exported_members, user: user, project: project) end it 'maps a project member' do From 8c508037a63ba2b82d56757bce011ac53a073ae6 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 13 May 2016 17:03:03 +0200 Subject: [PATCH 158/730] updated controllers with permissions check --- .../import/gitlab_project_controller.rb | 45 ------------------- .../import/gitlab_projects_controller.rb | 43 ++++++++---------- app/controllers/projects_controller.rb | 2 +- 3 files changed, 20 insertions(+), 70 deletions(-) delete mode 100644 app/controllers/import/gitlab_project_controller.rb diff --git a/app/controllers/import/gitlab_project_controller.rb b/app/controllers/import/gitlab_project_controller.rb deleted file mode 100644 index ab0da196ac..0000000000 --- a/app/controllers/import/gitlab_project_controller.rb +++ /dev/null @@ -1,45 +0,0 @@ -class Import::GitlabProjectController < Import::BaseController - before_action :verify_gitlab_project_import_enabled - before_action :gitlab_project_auth, except: :callback - - rescue_from OAuth::Error, with: :gitlab_project_unauthorized - - #TODO permissions stuff - - def callback - - redirect_to status_import_gitlab_project_url - end - - def status - @repos = client.projects - @incompatible_repos = client.incompatible_projects - - @already_added_projects = current_user.created_projects.where(import_type: "gitlab_project") - already_added_projects_names = @already_added_projects.pluck(:import_source) - - @repos.to_a.reject!{ |repo| already_added_projects_names.include? "#{repo["owner"]}/#{repo["slug"]}" } - end - - def jobs - jobs = current_user.created_projects.where(import_type: "gitlab_project").to_json(only: [:id, :import_status]) - render json: jobs - end - - def create - @file = params[:file] - - repo_owner = current_user.username - @target_namespace = params[:new_namespace].presence || repo_owner - - # namespace = get_or_create_namespace || (render and return) - - @project = Gitlab::ImportExport::ImportService.execute(archive_file: file, owner: repo_owner) - end - - private - - def verify_gitlab_project_import_enabled - render_404 unless gitlab_project_import_enabled? - end -end diff --git a/app/controllers/import/gitlab_projects_controller.rb b/app/controllers/import/gitlab_projects_controller.rb index f8d4bcff55..41b72c33ff 100644 --- a/app/controllers/import/gitlab_projects_controller.rb +++ b/app/controllers/import/gitlab_projects_controller.rb @@ -1,44 +1,39 @@ class Import::GitlabProjectsController < Import::BaseController before_action :verify_gitlab_project_import_enabled - #before_action :gitlab_project_auth, except: :callback + before_action :verify_project_and_namespace_access rescue_from OAuth::Error, with: :gitlab_project_unauthorized - #TODO permissions stuff - def new @namespace_id = project_params[:namespace_id] @path = project_params[:path] end - def status - - end - - def jobs - jobs = current_user.created_projects.where(import_type: "gitlab_project").to_json(only: [:id, :import_status]) - render json: jobs - end - def create - # TODO verify access to namespace and path - file = params[:file] - namespace_id = project_params[:namespace_id] - path = project_params[:path] - - repo_owner = current_user.username - @target_namespace = params[:new_namespace].presence || repo_owner - @project = Project.create_from_import_job(current_user_id: current_user.id, - tmp_file: File.expand_path(file.path), - namespace_id: namespace_id, - project_path: path) + tmp_file: File.expand_path(params[:file].path), + namespace_id: project_params[:namespace_id], + project_path: project_params[:path]) - redirect_to status_import_gitlab_project_path + redirect_to dashboard_projects_path end private + def verify_project_and_namespace_access + unless namespace_access? && project_access? + render_403 + end + end + + def project_access? + can?(current_user, :admin_project, @project) + end + + def namespace_access? + current_user.can?(:create_projects, Namespace.find(project_params[:namespace_id])) + end + def verify_gitlab_project_import_enabled render_404 unless gitlab_project_import_enabled? end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index f15f20dcf5..980cae65f8 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -7,7 +7,7 @@ class ProjectsController < Projects::ApplicationController before_action :assign_ref_vars, :tree, only: [:show], if: :repo_exists? # Authorize - before_action :authorize_admin_project!, only: [:edit, :update, :housekeeping] + before_action :authorize_admin_project!, only: [:edit, :update, :housekeeping, :download_export, :export] before_action :event_filter, only: [:show, :activity] layout :determine_layout From 89fb5df534c5b7c1ffc147e9274aee9db4f4cbc4 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 13 May 2016 17:08:19 +0200 Subject: [PATCH 159/730] updated routes file --- config/routes.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index 871997d01a..08598e36fe 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -160,9 +160,7 @@ Rails.application.routes.draw do end resource :gitlab_project, only: [:create, :new], controller: :gitlab_projects do - get :status post :create - get :jobs end end From 1ee19f04fd51322606d641ba82e6434d8d5c186f Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 13 May 2016 17:16:24 +0200 Subject: [PATCH 160/730] fixed permissions --- app/controllers/import/gitlab_projects_controller.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/controllers/import/gitlab_projects_controller.rb b/app/controllers/import/gitlab_projects_controller.rb index 41b72c33ff..a4ac55cd2a 100644 --- a/app/controllers/import/gitlab_projects_controller.rb +++ b/app/controllers/import/gitlab_projects_controller.rb @@ -21,15 +21,11 @@ class Import::GitlabProjectsController < Import::BaseController private def verify_project_and_namespace_access - unless namespace_access? && project_access? + unless namespace_access? render_403 end end - def project_access? - can?(current_user, :admin_project, @project) - end - def namespace_access? current_user.can?(:create_projects, Namespace.find(project_params[:namespace_id])) end From 2e1decd061d679b3b8acd0a3e2178b61b59af65d Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 13 May 2016 17:17:46 +0200 Subject: [PATCH 161/730] restricted actual member mapping to admins --- lib/gitlab/import_export/members_mapper.rb | 20 +++++++++---------- .../import_export/project_tree_restorer.rb | 6 ++++-- lib/gitlab/import_export/relation_factory.rb | 17 +++++++++++----- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/lib/gitlab/import_export/members_mapper.rb b/lib/gitlab/import_export/members_mapper.rb index 5332529a90..a5fdac6d93 100644 --- a/lib/gitlab/import_export/members_mapper.rb +++ b/lib/gitlab/import_export/members_mapper.rb @@ -18,6 +18,16 @@ module Gitlab @map = generate_map end + def default_project_member + @default_project_member ||= + begin + return @project.project_members.first.user.id unless @project.project_members.empty? + default_member = ProjectMember.new(default_project_member_hash) + default_member.save! + default_member.user.id + end + end + private def generate_map @@ -39,16 +49,6 @@ module Gitlab member.except('id').merge(source_id: @project.id) end - def default_project_member - @default_project_member ||= - begin - return @project.project_members.first.user.id unless @project.project_members.empty? - default_member = ProjectMember.new(default_project_member_hash) - default_member.save! - default_member.user.id - end - end - def default_project_member_hash { user: @user, access_level: ProjectMember::MASTER, source_id: @project.id } end diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index bd343d0b69..911ba06e74 100644 --- a/lib/gitlab/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -94,8 +94,10 @@ module Gitlab end def relation_from_factory(relation, relation_hash) - Gitlab::ImportExport::RelationFactory.create( - relation_sym: relation.to_sym, relation_hash: relation_hash.merge('project_id' => project.id), members_mapper: members_mapper) + Gitlab::ImportExport::RelationFactory.create(relation_sym: relation.to_sym, + relation_hash: relation_hash.merge('project_id' => project.id), + members_mapper: members_mapper, + user_admin: @user.is_admin?) end end end diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb index cdd4987f98..3b27f133ec 100644 --- a/lib/gitlab/import_export/relation_factory.rb +++ b/lib/gitlab/import_export/relation_factory.rb @@ -6,11 +6,11 @@ module Gitlab OVERRIDES = { snippets: :project_snippets, ci_commits: 'Ci::Commit', statuses: 'commit_status' }.freeze USER_REFERENCES = %w(author_id assignee_id updated_by_id).freeze - def create(relation_sym:, relation_hash:, members_mapper:) + def create(relation_sym:, relation_hash:, members_mapper:, user_admin:) relation_sym = parse_relation_sym(relation_sym) klass = parse_relation(relation_hash, relation_sym) - update_missing_author(relation_hash, members_mapper) if relation_sym == :notes + update_missing_author(relation_hash, members_mapper, user_admin) if relation_sym == :notes update_user_references(relation_hash, members_mapper.map) update_project_references(relation_hash, klass) @@ -27,12 +27,19 @@ module Gitlab end end - def update_missing_author(relation_hash, members_map) + def update_missing_author(relation_hash, members_map, user_admin) old_author_id = relation_hash['author_id'] - relation_hash['author_id'] = members_map.map[old_author_id] + + # Users with admin access have access to mapping of users + if user_admin + relation_hash['author_id'] = members_map.default_project_member + else + relation_hash['author_id'] = members_map.map[old_author_id] + end + author = relation_hash.delete('author') - return unless members_map.note_member_list.include?(old_author_id) + return unless user_admin && members_map.note_member_list.include?(old_author_id) relation_hash['note'] = ('*Blank note*') if relation_hash['note'].blank? relation_hash['note'] += (missing_author_note(relation_hash['updated_at'], author['name'])) From 2dff04f24a8446216e12d43fab6841f28f3dd406 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 13 May 2016 17:39:03 +0200 Subject: [PATCH 162/730] fixed TODOs left --- lib/gitlab/import_export.rb | 8 ++++++++ lib/gitlab/import_export/project_tree_saver.rb | 7 +------ lib/gitlab/import_export/repo_bundler.rb | 7 +------ 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/lib/gitlab/import_export.rb b/lib/gitlab/import_export.rb index 6835411ba7..bf80ac7f09 100644 --- a/lib/gitlab/import_export.rb +++ b/lib/gitlab/import_export.rb @@ -9,5 +9,13 @@ module Gitlab def storage_path File.join(Settings.shared['path'], 'tmp/project_exports') end + + def project_filename + "project.json" + end + + def project_bundle_filename + "project.bundle" + end end end diff --git a/lib/gitlab/import_export/project_tree_saver.rb b/lib/gitlab/import_export/project_tree_saver.rb index 2287524c8a..c894295b0f 100644 --- a/lib/gitlab/import_export/project_tree_saver.rb +++ b/lib/gitlab/import_export/project_tree_saver.rb @@ -6,7 +6,7 @@ module Gitlab def initialize(project:, shared:) @project = project @shared = shared - @full_path = File.join(@shared.export_path, project_filename) + @full_path = File.join(@shared.export_path, ImportExport.project_filename) end def save @@ -20,11 +20,6 @@ module Gitlab private - # TODO remove magic keyword and move it to a shared config - def project_filename - "project.json" - end - def project_json_tree @project.to_json(Gitlab::ImportExport::ImportExportReader.new(shared: @shared).project_tree) end diff --git a/lib/gitlab/import_export/repo_bundler.rb b/lib/gitlab/import_export/repo_bundler.rb index bcf976fb62..aff6e92be7 100644 --- a/lib/gitlab/import_export/repo_bundler.rb +++ b/lib/gitlab/import_export/repo_bundler.rb @@ -12,7 +12,7 @@ module Gitlab def bundle return false if @project.empty_repo? - @full_path = File.join(@shared.export_path, project_filename) + @full_path = File.join(@shared.export_path, ImportExport.project_bundle_filename) bundle_to_disk end @@ -26,11 +26,6 @@ module Gitlab false end - # TODO remove magic keyword and move it to a shared config - def project_filename - "project.bundle" - end - def path_to_repo @project.repository.path_to_repo end From bf81c588fd7f34e475c0f317f7e49dc70e36366d Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 13 May 2016 19:51:07 +0200 Subject: [PATCH 163/730] fix issue with mapping members --- lib/gitlab/import_export/command_line_util.rb | 6 ------ lib/gitlab/import_export/members_mapper.rb | 4 ++++ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/gitlab/import_export/command_line_util.rb b/lib/gitlab/import_export/command_line_util.rb index f53f8fba96..c99b0d83b4 100644 --- a/lib/gitlab/import_export/command_line_util.rb +++ b/lib/gitlab/import_export/command_line_util.rb @@ -19,12 +19,6 @@ module Gitlab private - def git_unbundle(git_bin_path: Gitlab.config.git.bin_path, repo_path:, bundle_path:) - cmd = %W(#{git_bin_path} clone --bare #{bundle_path} #{repo_path}) - _output, status = Gitlab::Popen.popen(cmd) - status.zero? - end - def tar_with_options(archive:, dir:, options:) execute(%W(tar -#{options} #{archive} -C #{dir} .)) end diff --git a/lib/gitlab/import_export/members_mapper.rb b/lib/gitlab/import_export/members_mapper.rb index a5fdac6d93..4401fab3d2 100644 --- a/lib/gitlab/import_export/members_mapper.rb +++ b/lib/gitlab/import_export/members_mapper.rb @@ -10,6 +10,10 @@ module Gitlab @project = project @note_member_list = [] + # This needs to run first, as second call would be from generate_map + # which means project members already exist. + default_project_member + @project_member_map = Hash.new do |_, key| @note_member_list << key default_project_member From 220e55a9806c4de9fc6839b1c676ba022b83f720 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 13 May 2016 20:58:27 +0200 Subject: [PATCH 164/730] fix spec --- .../gitlab/import_export/project_tree_restorer_spec.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) 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 6464b0141f..bc7993b9d7 100644 --- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb @@ -5,9 +5,13 @@ describe Gitlab::ImportExport::ProjectTreeRestorer, services: true do let(:user) { create(:user) } let(:namespace) { create(:namespace, owner: user) } - let(:shared) { Gitlab::ImportExport::Shared.new(relative_path: "../../../spec/lib/gitlab/import_export/", project_path: 'path') } + let(:shared) { Gitlab::ImportExport::Shared.new(relative_path: "", project_path: 'path') } let(:project_tree_restorer) { described_class.new(user: user, shared: shared, namespace_id: namespace.id) } - let!(:restored_project_json) { project_tree_restorer.restore } + let(:restored_project_json) { project_tree_restorer.restore } + + before do + allow(shared).to receive(:export_path).and_return('spec/lib/gitlab/import_export/') + end context 'JSON' do it 'restores models based on JSON' do From f386d7a7b7f67ba8e77ee40ef6a3383d5206d0c1 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 16 May 2016 10:13:00 +0200 Subject: [PATCH 165/730] some changes based on MR feedback --- lib/gitlab/import_export/command_line_util.rb | 8 ++++++-- lib/gitlab/import_export/import_export_reader.rb | 1 + lib/gitlab/import_export/repo_bundler.rb | 2 +- lib/gitlab/import_export/wiki_repo_bundler.rb | 11 +++++------ .../gitlab/import_export/import_export_reader_spec.rb | 6 +++--- 5 files changed, 16 insertions(+), 12 deletions(-) diff --git a/lib/gitlab/import_export/command_line_util.rb b/lib/gitlab/import_export/command_line_util.rb index c99b0d83b4..78664f076e 100644 --- a/lib/gitlab/import_export/command_line_util.rb +++ b/lib/gitlab/import_export/command_line_util.rb @@ -9,11 +9,11 @@ module Gitlab untar_with_options(archive: archive, dir: dir, options: 'zxf') end - def git_bundle(git_bin_path: Gitlab.config.git.bin_path, repo_path:, bundle_path:) + def git_bundle(repo_path:, bundle_path:) execute(%W(#{git_bin_path} --git-dir=#{repo_path} bundle create #{bundle_path} --all)) end - def git_unbundle(git_bin_path: Gitlab.config.git.bin_path, repo_path:, bundle_path:) + def git_unbundle(repo_path:, bundle_path:) execute(%W(#{git_bin_path} clone --bare #{bundle_path} #{repo_path})) end @@ -31,6 +31,10 @@ module Gitlab _output, status = Gitlab::Popen.popen(cmd) status.zero? end + + def git_bin_path + Gitlab.config.git.bin_path + end end end end diff --git a/lib/gitlab/import_export/import_export_reader.rb b/lib/gitlab/import_export/import_export_reader.rb index 9aac0eae79..25e13074e9 100644 --- a/lib/gitlab/import_export/import_export_reader.rb +++ b/lib/gitlab/import_export/import_export_reader.rb @@ -14,6 +14,7 @@ module Gitlab @attributes_parser.find_included(:project).merge(include: build_hash(@tree)) rescue => e @shared.error(e.message) + false end private diff --git a/lib/gitlab/import_export/repo_bundler.rb b/lib/gitlab/import_export/repo_bundler.rb index aff6e92be7..f41d5af4e5 100644 --- a/lib/gitlab/import_export/repo_bundler.rb +++ b/lib/gitlab/import_export/repo_bundler.rb @@ -5,7 +5,7 @@ module Gitlab attr_reader :full_path - def initialize(project: , shared: ) + def initialize(project:, shared:) @project = project @shared = shared end diff --git a/lib/gitlab/import_export/wiki_repo_bundler.rb b/lib/gitlab/import_export/wiki_repo_bundler.rb index a0000176bb..016c640ae1 100644 --- a/lib/gitlab/import_export/wiki_repo_bundler.rb +++ b/lib/gitlab/import_export/wiki_repo_bundler.rb @@ -3,14 +3,13 @@ module Gitlab class WikiRepoBundler < RepoBundler def bundle @wiki = ProjectWiki.new(@project) - return true if !wiki? # it's okay to have no Wiki - @full_path = File.join(@shared.export_path, project_filename) - bundle_to_disk + return true unless wiki_repository_exists? # it's okay to have no Wiki + bundle_to_disk(File.join(@shared.export_path, project_filename)) end - def bundle_to_disk + def bundle_to_disk(full_path) FileUtils.mkdir_p(@shared.export_path) - git_bundle(repo_path: path_to_repo, bundle_path: @full_path) + git_bundle(repo_path: path_to_repo, bundle_path: full_path) rescue => e @shared.error(e.message) false @@ -26,7 +25,7 @@ module Gitlab @wiki.repository.path_to_repo end - def wiki? + def wiki_repository_exists? File.exists?(@wiki.repository.path_to_repo) && !@wiki.repository.empty? end end diff --git a/spec/lib/gitlab/import_export/import_export_reader_spec.rb b/spec/lib/gitlab/import_export/import_export_reader_spec.rb index 2fc9a39c68..c4d03fecd5 100644 --- a/spec/lib/gitlab/import_export/import_export_reader_spec.rb +++ b/spec/lib/gitlab/import_export/import_export_reader_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Gitlab::ImportExport::ImportExportReader do +describe Gitlab::ImportExport::ImportExportReader, lib: true do let(:shared) { Gitlab::ImportExport::Shared.new(relative_path:'') } let(:test_config) { 'spec/support/import_export/import_export.yml' } let(:project_tree_hash) do @@ -16,7 +16,7 @@ describe Gitlab::ImportExport::ImportExportReader do } end - it 'should generate hash from project tree config' do - expect(described_class.new(config: test_config, shared: shared).project_tree) =~ (project_tree_hash) + it 'generates hash from project tree config' do + expect(described_class.new(config: test_config, shared: shared).project_tree).to match(project_tree_hash) end end From 30aa37c8127dfe10df44f7945a4722b95581ff24 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 16 May 2016 11:24:20 +0200 Subject: [PATCH 166/730] remove spec change --- spec/spec_helper.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 5b90a4b534..576d16e7ea 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -52,7 +52,3 @@ FactoryGirl::SyntaxRunner.class_eval do end ActiveRecord::Migration.maintain_test_schema! - -Capybara.register_driver :poltergeist do |app| - Capybara::Poltergeist::Driver.new(app, timeout: 1.minute) -end From 5777ad9a1f016f170585949059b08a4eeb7d19a9 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 16 May 2016 12:04:31 +0200 Subject: [PATCH 167/730] adding versioning to export --- .../projects/import_export/export_service.rb | 11 +++++-- lib/gitlab/import_export.rb | 6 ++++ lib/gitlab/import_export/version_saver.rb | 29 +++++++++++++++++++ 3 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 lib/gitlab/import_export/version_saver.rb diff --git a/app/services/projects/import_export/export_service.rb b/app/services/projects/import_export/export_service.rb index e6eb6f915b..0691ca9d46 100644 --- a/app/services/projects/import_export/export_service.rb +++ b/app/services/projects/import_export/export_service.rb @@ -4,12 +4,16 @@ module Projects def execute(options = {}) @shared = Gitlab::ImportExport::Shared.new(relative_path: File.join(project.path_with_namespace, 'work')) - save_all if [save_project_tree, bundle_repo, bundle_wiki_repo].all? - notify_worker if @shared.errors.any? + save_all if [save_version, save_project_tree, bundle_repo, bundle_wiki_repo].all? + cleanup_and_notify_worker if @shared.errors.any? end private + def save_version + Gitlab::ImportExport::VersionSaver.save(shared: @shared) + end + def save_project_tree Gitlab::ImportExport::ProjectTreeSaver.new(project: project, shared: @shared).save end @@ -26,7 +30,8 @@ module Projects Gitlab::ImportExport::Saver.save(shared: @shared) end - def notify_worker + def cleanup_and_notify_worker + FileUtils.rm_rf(@shared.export_path) raise Gitlab::ImportExport::Error.new(@shared.errors.join(', ')) end end diff --git a/lib/gitlab/import_export.rb b/lib/gitlab/import_export.rb index bf80ac7f09..9c7c72e2b4 100644 --- a/lib/gitlab/import_export.rb +++ b/lib/gitlab/import_export.rb @@ -2,6 +2,8 @@ module Gitlab module ImportExport extend self + VERSION = '0.1.0' + def export_path(relative_path:) File.join(storage_path, relative_path) end @@ -17,5 +19,9 @@ module Gitlab def project_bundle_filename "project.bundle" end + + def version_filename + 'VERSION' + end end end diff --git a/lib/gitlab/import_export/version_saver.rb b/lib/gitlab/import_export/version_saver.rb new file mode 100644 index 0000000000..e8be52b990 --- /dev/null +++ b/lib/gitlab/import_export/version_saver.rb @@ -0,0 +1,29 @@ +module Gitlab + module ImportExport + class VersionSaver + + def self.save(*args) + new(*args).save + end + + def initialize(shared:) + @shared = shared + end + + def save + File.open(version_file, 'w') do |file| + file.write(Gitlab::ImportExport.VERSION) + end + rescue => e + @shared.error(e.message) + false + end + + private + + def version_file + File.join(@shared.export_path, Gitlab::ImportExport.version_filename) + end + end + end +end From 51487575bca1f4cdce4919bb4cb2bbb1ee686368 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 16 May 2016 12:39:42 +0200 Subject: [PATCH 168/730] added version check on import --- lib/gitlab/import_export/import_service.rb | 6 +++- lib/gitlab/import_export/version_restorer.rb | 36 ++++++++++++++++++++ lib/gitlab/import_export/version_saver.rb | 2 +- 3 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 lib/gitlab/import_export/version_restorer.rb diff --git a/lib/gitlab/import_export/import_service.rb b/lib/gitlab/import_export/import_service.rb index 0c483884fe..b025bff29b 100644 --- a/lib/gitlab/import_export/import_service.rb +++ b/lib/gitlab/import_export/import_service.rb @@ -16,7 +16,7 @@ module Gitlab def execute Gitlab::ImportExport::Importer.import(archive_file: @archive_file, shared: @shared) - if [restore_project_tree, restore_repo, restore_wiki_repo].all? + if [restore_version, restore_project_tree, restore_repo, restore_wiki_repo].all? project_tree.project else project_tree.project.destroy if project_tree.project @@ -26,6 +26,10 @@ module Gitlab private + def restore_version + Gitlab::ImportExport::VersionRestorer.restore(shared: @shared) + end + def restore_project_tree project_tree.restore end diff --git a/lib/gitlab/import_export/version_restorer.rb b/lib/gitlab/import_export/version_restorer.rb new file mode 100644 index 0000000000..797696511d --- /dev/null +++ b/lib/gitlab/import_export/version_restorer.rb @@ -0,0 +1,36 @@ +module Gitlab + module ImportExport + class VersionRestorer + + def self.restore(*args) + new(*args).restore + end + + def initialize(shared:) + @shared = shared + end + + def restore + version = File.open(version_file, &:readline) + verify_version!(version) + rescue => e + @shared.error(e) + false + end + + private + + def version_file + File.join(@shared.export_path, Gitlab::ImportExport.version_filename) + end + + def verify_version!(version) + if Gem::Version.new(version) > Gem::Version.new(Gitlab::ImportExport.VERSION) + raise Gitlab::ImportExport::Error("Import version mismatch: Required <= #{Gitlab::ImportExport.VERSION} but was #{version}") + else + true + end + end + end + end +end diff --git a/lib/gitlab/import_export/version_saver.rb b/lib/gitlab/import_export/version_saver.rb index e8be52b990..197271f355 100644 --- a/lib/gitlab/import_export/version_saver.rb +++ b/lib/gitlab/import_export/version_saver.rb @@ -15,7 +15,7 @@ module Gitlab file.write(Gitlab::ImportExport.VERSION) end rescue => e - @shared.error(e.message) + @shared.error(e) false end From c374700390ad0e3ab8a7ad954ee1b6e311a48129 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 16 May 2016 12:40:01 +0200 Subject: [PATCH 169/730] missing new line --- lib/gitlab/import_export/version_restorer.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/gitlab/import_export/version_restorer.rb b/lib/gitlab/import_export/version_restorer.rb index 797696511d..bab2fecec4 100644 --- a/lib/gitlab/import_export/version_restorer.rb +++ b/lib/gitlab/import_export/version_restorer.rb @@ -34,3 +34,4 @@ module Gitlab end end end + From 360689bb5834cfe5b57c121d71a5123f27081fb0 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 16 May 2016 13:11:49 +0200 Subject: [PATCH 170/730] fix version --- lib/gitlab/import_export/version_restorer.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/import_export/version_restorer.rb b/lib/gitlab/import_export/version_restorer.rb index bab2fecec4..2c83bf0899 100644 --- a/lib/gitlab/import_export/version_restorer.rb +++ b/lib/gitlab/import_export/version_restorer.rb @@ -25,8 +25,8 @@ module Gitlab end def verify_version!(version) - if Gem::Version.new(version) > Gem::Version.new(Gitlab::ImportExport.VERSION) - raise Gitlab::ImportExport::Error("Import version mismatch: Required <= #{Gitlab::ImportExport.VERSION} but was #{version}") + if Gem::Version.new(version) > Gem::Version.new(Gitlab::ImportExport.version) + raise Gitlab::ImportExport::Error("Import version mismatch: Required <= #{Gitlab::ImportExport.version} but was #{version}") else true end From 504c186f7139df71dbea596b422d833f32348f46 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 16 May 2016 13:28:11 +0200 Subject: [PATCH 171/730] fix version issue --- lib/gitlab/import_export.rb | 4 ++++ lib/gitlab/import_export/project_tree_saver.rb | 1 - lib/gitlab/import_export/version_saver.rb | 4 +++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/import_export.rb b/lib/gitlab/import_export.rb index 9c7c72e2b4..65a8fcfadd 100644 --- a/lib/gitlab/import_export.rb +++ b/lib/gitlab/import_export.rb @@ -23,5 +23,9 @@ module Gitlab def version_filename 'VERSION' end + + def version + VERSION + end end end diff --git a/lib/gitlab/import_export/project_tree_saver.rb b/lib/gitlab/import_export/project_tree_saver.rb index c894295b0f..631746a47f 100644 --- a/lib/gitlab/import_export/project_tree_saver.rb +++ b/lib/gitlab/import_export/project_tree_saver.rb @@ -10,7 +10,6 @@ module Gitlab end def save - FileUtils.mkdir_p(@shared.export_path) File.write(full_path, project_json_tree) true rescue => e diff --git a/lib/gitlab/import_export/version_saver.rb b/lib/gitlab/import_export/version_saver.rb index e8be52b990..904645f273 100644 --- a/lib/gitlab/import_export/version_saver.rb +++ b/lib/gitlab/import_export/version_saver.rb @@ -11,8 +11,10 @@ module Gitlab end def save + FileUtils.mkdir_p(@shared.export_path) + File.open(version_file, 'w') do |file| - file.write(Gitlab::ImportExport.VERSION) + file.write(Gitlab::ImportExport.version) end rescue => e @shared.error(e.message) From 7ea68d006e93f4bfe59d0513696e46c1ad5ee6a1 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 16 May 2016 15:17:44 +0200 Subject: [PATCH 172/730] updated file import spec --- .../import_export/test_project_export.tar.gz | Bin 339384 -> 339482 bytes 1 file changed, 0 insertions(+), 0 deletions(-) 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 aef4af6998ee729c2eea80c9d2423fc787083950..4f2ec49e9b51682a2813d3d310ea899a2ff361f3 100644 GIT binary patch delta 74261 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 z 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