From f4e7a8893d71bcbc92a5ecd16c95593f17d1ddf5 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Thu, 24 Dec 2015 19:05:57 +0100 Subject: Add builds API (listing, showing trace) --- lib/api/api.rb | 2 ++ lib/api/builds.rb | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/api/entities.rb | 13 +++++++++ 3 files changed, 95 insertions(+) create mode 100644 lib/api/builds.rb (limited to 'lib') diff --git a/lib/api/api.rb b/lib/api/api.rb index 7834262d612..266b5f48f8f 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -54,5 +54,7 @@ module API mount Keys mount Tags mount Triggers + + mount Builds end end diff --git a/lib/api/builds.rb b/lib/api/builds.rb new file mode 100644 index 00000000000..ce4892b5eeb --- /dev/null +++ b/lib/api/builds.rb @@ -0,0 +1,80 @@ +module API + # Projects builds API + class Builds < Grape::API + before { authenticate! } + + resource :projects do + # Get a project repository commits + # + # Parameters: + # id (required) - The ID of a project + # scope (optional) - The scope of builds to show (one of: all, finished, running) + # page (optional) - The page number for pagination (default: 1) + # per_page (ooptional) - The value of items per page to show (default 30) + # Example Request: + # GET /projects/:id/builds/all + get ':id/builds' do + all_builds = user_project.builds + builds = all_builds.order('created_at DESC') + builds = + case params[:scope] + when 'all' + builds + when 'finished' + builds.finished + when 'running' + builds.running + when 'pending' + builds.pending + when 'success' + builds.success + when 'failed' + builds.failed + else + builds.running_or_pending.reverse_order + end + + page = (params[:page] || 1).to_i + per_page = (params[:per_page] || 30).to_i + + present builds.page(page).per(per_page), with: Entities::Build + end + + # Get a specific build of a project + # + # Parameters: + # id (required) - The ID of a project + # build_id (required) - The ID of a build + # Example Request: + # GET /projects/:id/builds/:build_id + get ':id/builds/:build_id' do + present get_build(params[:build_id]), with: Entities::Build + end + + # Get a trace of a specific build of a project + # + # Parameters: + # id (required) - The ID of a project + # build_id (required) - The ID of a build + # Example Request: + # GET /projects/:id/build/:build_id/trace + get ':id/builds/:build_id/trace' do + trace = get_build(params[:build_id]).trace + trace = + unless trace.nil? + trace.split("\n") + else + [] + end + + present trace + end + end + + helpers do + def get_build(id) + user_project.builds.where(id: id).first + end + end + end +end diff --git a/lib/api/entities.rb b/lib/api/entities.rb index f8511ac5f5c..0bf50490eac 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -366,5 +366,18 @@ module API class TriggerRequest < Grape::Entity expose :id, :variables end + + class Build < Grape::Entity + expose :id + expose :status + expose :stage + expose :name + expose :ref + expose :commit + expose :runner + expose :created_at + expose :started_at + expose :finished_at + end end end -- cgit v1.2.1 From b5fef34f1e3beb60e7184cfb3420976bfa367137 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Thu, 24 Dec 2015 19:18:01 +0100 Subject: Fix example request url --- lib/api/builds.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/api/builds.rb b/lib/api/builds.rb index ce4892b5eeb..0ddb9e98de6 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -12,7 +12,7 @@ module API # page (optional) - The page number for pagination (default: 1) # per_page (ooptional) - The value of items per page to show (default 30) # Example Request: - # GET /projects/:id/builds/all + # GET /projects/:id/builds get ':id/builds' do all_builds = user_project.builds builds = all_builds.order('created_at DESC') -- cgit v1.2.1 From f39959d00a1358ba7d73ebeaccb827738c8151ba Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Mon, 28 Dec 2015 13:09:51 +0100 Subject: Add some fixes to builds API --- lib/api/builds.rb | 27 +++++++++------------------ lib/api/entities.rb | 20 ++++++++++++++++++-- 2 files changed, 27 insertions(+), 20 deletions(-) (limited to 'lib') diff --git a/lib/api/builds.rb b/lib/api/builds.rb index 0ddb9e98de6..863be0d5e40 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -15,23 +15,15 @@ module API # GET /projects/:id/builds get ':id/builds' do all_builds = user_project.builds - builds = all_builds.order('created_at DESC') + builds = all_builds.order('id DESC') builds = case params[:scope] - when 'all' - builds when 'finished' builds.finished when 'running' builds.running - when 'pending' - builds.pending - when 'success' - builds.success - when 'failed' - builds.failed else - builds.running_or_pending.reverse_order + builds end page = (params[:page] || 1).to_i @@ -59,15 +51,14 @@ module API # Example Request: # GET /projects/:id/build/:build_id/trace get ':id/builds/:build_id/trace' do - trace = get_build(params[:build_id]).trace - trace = - unless trace.nil? - trace.split("\n") - else - [] - end + build = get_build(params[:build_id]) + + header 'Content-Disposition', "infile; filename=\"#{build.id}.log\"" + content_type 'text/plain' + env['api.format'] = :binary - present trace + trace = build.trace + body trace end end diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 0bf50490eac..76b5d14f202 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -367,14 +367,30 @@ module API expose :id, :variables end + class CiCommit < Grape::Entity + expose :id + expose :ref + expose :sha + expose :committed_at + end + + class CiRunner < Grape::Entity + expose :id + expose :token + expose :description + expose :active + expose :is_shared + expose :name + end + class Build < Grape::Entity expose :id expose :status expose :stage expose :name expose :ref - expose :commit - expose :runner + expose :commit, with: CiCommit + expose :runner, with: CiRunner expose :created_at expose :started_at expose :finished_at -- cgit v1.2.1 From f4cff4dcd0b11d4597efe454731838fbf5803516 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Mon, 28 Dec 2015 13:33:03 +0100 Subject: Modify build pagination to use 'paginate' helper --- lib/api/builds.rb | 5 +---- lib/api/helpers.rb | 6 ++++-- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/api/builds.rb b/lib/api/builds.rb index 863be0d5e40..f219b0f5241 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -26,10 +26,7 @@ module API builds end - page = (params[:page] || 1).to_i - per_page = (params[:per_page] || 30).to_i - - present builds.page(page).per(per_page), with: Entities::Build + present paginate(builds), with: Entities::Build end # Get a specific build of a project diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index a4df810e755..8fb5cd6ab63 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -97,8 +97,10 @@ module API end def paginate(relation) - per_page = params[:per_page].to_i - paginated = relation.page(params[:page]).per(per_page) + page = (params[:page] || 1).to_i + per_page = (params[:per_page] || 30).to_i + + paginated = relation.page(page).per(per_page) add_pagination_headers(paginated, per_page) paginated -- cgit v1.2.1 From d398e78ea09c1f88800cd4c99f92dd8e5d1d0d39 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Mon, 28 Dec 2015 15:49:13 +0100 Subject: Add endpoint for getting builds for a specific commit --- lib/api/builds.rb | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/api/builds.rb b/lib/api/builds.rb index f219b0f5241..7488863cdcf 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -4,7 +4,7 @@ module API before { authenticate! } resource :projects do - # Get a project repository commits + # Get a project builds # # Parameters: # id (required) - The ID of a project @@ -14,18 +14,21 @@ module API # Example Request: # GET /projects/:id/builds get ':id/builds' do - all_builds = user_project.builds - builds = all_builds.order('id DESC') - builds = - case params[:scope] - when 'finished' - builds.finished - when 'running' - builds.running - else - builds - end + builds = user_project.builds.order('id DESC') + builds = filter_builds(builds, params[:scope]) + present paginate(builds), with: Entities::Build + end + # GET builds for a specific commit of a project + # + # Parameters: + # id (required) - The ID of a project + # sha (required) - The SHA id of a commit + # Example Request: + # GET /projects/:id/builds/commit/:sha + get ':id/builds/commit/:sha' do + builds = user_project.ci_commits.find_by_sha(params[:sha]).builds.order('id DESC') + builds = filter_builds(builds, params[:scope]) present paginate(builds), with: Entities::Build end @@ -63,6 +66,17 @@ module API def get_build(id) user_project.builds.where(id: id).first end + + def filter_builds(builds, scope) + case scope + when 'finished' + builds.finished + when 'running' + builds.running + else + builds + end + end end end end -- cgit v1.2.1 From e7d0746d9319119c459581615ae4205139bee444 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Mon, 28 Dec 2015 16:38:02 +0100 Subject: Add 'not_found' notifications in build/trace details --- lib/api/builds.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/api/builds.rb b/lib/api/builds.rb index 7488863cdcf..5ac24d0367a 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -19,7 +19,7 @@ module API present paginate(builds), with: Entities::Build end - # GET builds for a specific commit of a project + # Get builds for a specific commit of a project # # Parameters: # id (required) - The ID of a project @@ -40,7 +40,10 @@ module API # Example Request: # GET /projects/:id/builds/:build_id get ':id/builds/:build_id' do - present get_build(params[:build_id]), with: Entities::Build + build = get_build(params[:build_id]) + return not_found!(build) unless build + + present build, with: Entities::Build end # Get a trace of a specific build of a project @@ -52,6 +55,7 @@ module API # GET /projects/:id/build/:build_id/trace get ':id/builds/:build_id/trace' do build = get_build(params[:build_id]) + return not_found!(build) unless build header 'Content-Disposition', "infile; filename=\"#{build.id}.log\"" content_type 'text/plain' -- cgit v1.2.1 From 8d4555037a844d21dbf56c2995cff30782af920b Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Mon, 28 Dec 2015 16:38:29 +0100 Subject: Add cancel/retry endpoints to build API --- lib/api/builds.rb | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'lib') diff --git a/lib/api/builds.rb b/lib/api/builds.rb index 5ac24d0367a..16e4549d280 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -64,6 +64,42 @@ module API trace = build.trace body trace end + + # cancel a specific build of a project + # + # parameters: + # id (required) - the id of a project + # build_id (required) - the id of a build + # example request: + # post /projects/:id/build/:build_id/cancel + post ':id/builds/:build_id/cancel' do + authorize_manage_builds! + + build = get_build(params[:build_id]) + return not_found!(build) unless build + + build.cancel + + present build, with: Entities::Build + end + + # cancel a specific build of a project + # + # parameters: + # id (required) - the id of a project + # build_id (required) - the id of a build + # example request: + # post /projects/:id/build/:build_id/retry + post ':id/builds/:build_id/retry' do + authorize_manage_builds! + + build = get_build(params[:build_id]) + return not_found!(build) unless build && build.retryable? + + build = Ci::Build.retry(build) + + present build, with: Entities::Build + end end helpers do @@ -81,6 +117,10 @@ module API builds end end + + def authorize_manage_builds! + authorize! :manage_builds, user_project + end end end end -- cgit v1.2.1 From b2fbeb377d8ba17352d40817b0b444196cb97636 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Mon, 28 Dec 2015 17:01:02 +0100 Subject: Remove changes in 'paginate' helper --- lib/api/helpers.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 8fb5cd6ab63..a4df810e755 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -97,10 +97,8 @@ module API end def paginate(relation) - page = (params[:page] || 1).to_i - per_page = (params[:per_page] || 30).to_i - - paginated = relation.page(page).per(per_page) + per_page = params[:per_page].to_i + paginated = relation.page(params[:page]).per(per_page) add_pagination_headers(paginated, per_page) paginated -- cgit v1.2.1 From d2601211a0c7a44666501dea82a8488b08f8faa7 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Tue, 29 Dec 2015 23:12:36 +0100 Subject: Add specs for build listings in API --- lib/api/builds.rb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/api/builds.rb b/lib/api/builds.rb index 16e4549d280..a519224d2b8 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -27,7 +27,10 @@ module API # Example Request: # GET /projects/:id/builds/commit/:sha get ':id/builds/commit/:sha' do - builds = user_project.ci_commits.find_by_sha(params[:sha]).builds.order('id DESC') + commit = user_project.ci_commits.find_by_sha(params[:sha]) + return not_found! unless commit + + builds = commit.builds.order('id DESC') builds = filter_builds(builds, params[:scope]) present paginate(builds), with: Entities::Build end @@ -65,7 +68,7 @@ module API body trace end - # cancel a specific build of a project + # Cancel a specific build of a project # # parameters: # id (required) - the id of a project @@ -83,7 +86,7 @@ module API present build, with: Entities::Build end - # cancel a specific build of a project + # Retry a specific build of a project # # parameters: # id (required) - the id of a project -- cgit v1.2.1 From 628297fe5692fc241c93ff34cece71132bfb9aed Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Thu, 31 Dec 2015 23:01:28 +0100 Subject: Remove incorrect 'default' values from method description --- lib/api/builds.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/api/builds.rb b/lib/api/builds.rb index a519224d2b8..92bf849824c 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -9,8 +9,8 @@ module API # Parameters: # id (required) - The ID of a project # scope (optional) - The scope of builds to show (one of: all, finished, running) - # page (optional) - The page number for pagination (default: 1) - # per_page (ooptional) - The value of items per page to show (default 30) + # page (optional) - The page number for pagination + # per_page (ooptional) - The value of items per page to show # Example Request: # GET /projects/:id/builds get ':id/builds' do -- cgit v1.2.1 From a862ade55bf68f56734538b40e02e56036f8a1bd Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Tue, 5 Jan 2016 16:36:14 +0100 Subject: Update ./doc/api/ --- lib/api/builds.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/api/builds.rb b/lib/api/builds.rb index 92bf849824c..6b0edcff820 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -8,7 +8,7 @@ module API # # Parameters: # id (required) - The ID of a project - # scope (optional) - The scope of builds to show (one of: all, finished, running) + # scope (optional) - The scope of builds to show (one of: all, finished, running; default: all) # page (optional) - The page number for pagination # per_page (ooptional) - The value of items per page to show # Example Request: @@ -24,6 +24,7 @@ module API # Parameters: # id (required) - The ID of a project # sha (required) - The SHA id of a commit + # scope (optional) - The scope of builds to show (one of: all, finished, running; default: all) # Example Request: # GET /projects/:id/builds/commit/:sha get ':id/builds/commit/:sha' do -- cgit v1.2.1 From 549a2fa7873366b52e9ba3caa849073b7b958b73 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Fri, 8 Jan 2016 14:01:31 +0100 Subject: Modify builds scope filtering in builds API --- lib/api/builds.rb | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/api/builds.rb b/lib/api/builds.rb index 6b0edcff820..6aae1856953 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -8,9 +8,8 @@ module API # # Parameters: # id (required) - The ID of a project - # scope (optional) - The scope of builds to show (one of: all, finished, running; default: all) - # page (optional) - The page number for pagination - # per_page (ooptional) - The value of items per page to show + # scope (optional) - The scope of builds to show (one or array of: pending, running, failed, success, canceled; + # if none provided showing all builds) # Example Request: # GET /projects/:id/builds get ':id/builds' do @@ -24,7 +23,8 @@ module API # Parameters: # id (required) - The ID of a project # sha (required) - The SHA id of a commit - # scope (optional) - The scope of builds to show (one of: all, finished, running; default: all) + # scope (optional) - The scope of builds to show (one or array of: pending, running, failed, success, canceled; + # if none provided showing all builds) # Example Request: # GET /projects/:id/builds/commit/:sha get ':id/builds/commit/:sha' do @@ -112,14 +112,21 @@ module API end def filter_builds(builds, scope) - case scope - when 'finished' - builds.finished - when 'running' - builds.running - else - builds - end + available_scopes = Ci::Build.available_statuses + scope = + if scope.is_a?(String) || scope.is_a?(Symbol) + available_scopes & [scope.to_s] + elsif scope.is_a?(Array) + available_scopes & scope + elsif scope.respond_to?(:to_h) + available_scopes & scope.to_h.values + else + [] + end + + return builds if scope.empty? + + builds.where(status: scope) end def authorize_manage_builds! -- cgit v1.2.1 From 1eb7b5ee8d5afeeea74ccbd5627e5a235dffe9fd Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Fri, 8 Jan 2016 22:57:42 +0100 Subject: Modify entities for builds API --- lib/api/builds.rb | 16 +++++++++++----- lib/api/entities.rb | 37 ++++++++++++++++++------------------- 2 files changed, 29 insertions(+), 24 deletions(-) (limited to 'lib') diff --git a/lib/api/builds.rb b/lib/api/builds.rb index 6aae1856953..33e6ed24101 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -15,7 +15,9 @@ module API get ':id/builds' do builds = user_project.builds.order('id DESC') builds = filter_builds(builds, params[:scope]) - present paginate(builds), with: Entities::Build + + present paginate(builds), with: Entities::Build, + user_can_download_artifacts: can?(current_user, :download_build_artifacts, user_project) end # Get builds for a specific commit of a project @@ -33,7 +35,8 @@ module API builds = commit.builds.order('id DESC') builds = filter_builds(builds, params[:scope]) - present paginate(builds), with: Entities::Build + present paginate(builds), with: Entities::Build, + user_can_download_artifacts: can?(current_user, :download_build_artifacts, user_project) end # Get a specific build of a project @@ -47,7 +50,8 @@ module API build = get_build(params[:build_id]) return not_found!(build) unless build - present build, with: Entities::Build + present build, with: Entities::Build, + user_can_download_artifacts: can?(current_user, :download_build_artifacts, user_project) end # Get a trace of a specific build of a project @@ -84,7 +88,8 @@ module API build.cancel - present build, with: Entities::Build + present build, with: Entities::Build, + user_can_download_artifacts: can?(current_user, :download_build_artifacts, user_project) end # Retry a specific build of a project @@ -102,7 +107,8 @@ module API build = Ci::Build.retry(build) - present build, with: Entities::Build + present build, with: Entities::Build, + user_can_download_artifacts: can?(current_user, :download_build_artifacts, user_project) end end diff --git a/lib/api/entities.rb b/lib/api/entities.rb index f21da54b8fc..cb00b392db9 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -366,16 +366,8 @@ module API expose :id, :variables end - class CiCommit < Grape::Entity + class Runner < Grape::Entity expose :id - expose :ref - expose :sha - expose :committed_at - end - - class CiRunner < Grape::Entity - expose :id - expose :token expose :description expose :active expose :is_shared @@ -383,16 +375,23 @@ module API end class Build < Grape::Entity - expose :id - expose :status - expose :stage - expose :name - expose :ref - expose :commit, with: CiCommit - expose :runner, with: CiRunner - expose :created_at - expose :started_at - expose :finished_at + expose :id, :status, :stage, :name, :ref, :tag, :coverage, :user + expose :created_at, :started_at, :finished_at + expose :download_url do |repo_obj, options| + if options[:user_can_download_artifacts] + repo_obj.download_url + else + nil + end + end + expose :commit, with: RepoCommit do |repo_obj, _options| + if repo_obj.respond_to?(:commit) + repo_obj.commit.commit_data + else + nil + end + end + expose :runner, with: Runner end end end -- cgit v1.2.1 From 4eb27d7c72d57015c7551a00e34a54cefc2d3db9 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Fri, 8 Jan 2016 23:33:45 +0100 Subject: Add some modifications to builds API and specs --- lib/api/builds.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/api/builds.rb b/lib/api/builds.rb index 33e6ed24101..05d1b8d92ea 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -103,7 +103,7 @@ module API authorize_manage_builds! build = get_build(params[:build_id]) - return not_found!(build) unless build && build.retryable? + return forbidden!('Build is not retryable') unless build && build.retryable? build = Ci::Build.retry(build) -- cgit v1.2.1 From 96bbc145f31ad029e080ad8903445d81d6c31968 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Mon, 11 Jan 2016 10:20:45 +0100 Subject: Change commit builds URL in builds API --- lib/api/builds.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/api/builds.rb b/lib/api/builds.rb index 05d1b8d92ea..8c21754596b 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -28,8 +28,8 @@ module API # scope (optional) - The scope of builds to show (one or array of: pending, running, failed, success, canceled; # if none provided showing all builds) # Example Request: - # GET /projects/:id/builds/commit/:sha - get ':id/builds/commit/:sha' do + # GET /projects/:id/repository/commits/:sha/builds + get ':id/repository/commits/:sha/builds' do commit = user_project.ci_commits.find_by_sha(params[:sha]) return not_found! unless commit -- cgit v1.2.1 From 4e70f2519bba83d5f9d6fd0bed80e9837e8b5fc5 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Mon, 11 Jan 2016 11:15:04 +0100 Subject: Update ./doc/api/builds.md --- lib/api/entities.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/api/entities.rb b/lib/api/entities.rb index cb00b392db9..a1a886d6fea 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -375,8 +375,9 @@ module API end class Build < Grape::Entity - expose :id, :status, :stage, :name, :ref, :tag, :coverage, :user + expose :id, :status, :stage, :name, :ref, :tag, :coverage expose :created_at, :started_at, :finished_at + expose :user, with: UserFull expose :download_url do |repo_obj, options| if options[:user_can_download_artifacts] repo_obj.download_url -- cgit v1.2.1 From 5dcfd7d06754fecb245475cc005c112677693801 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Mon, 11 Jan 2016 15:49:25 +0100 Subject: Add TODO notice to build trace feature in CI API --- lib/api/builds.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib') diff --git a/lib/api/builds.rb b/lib/api/builds.rb index 8c21754596b..d3f4e33ebbf 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -61,6 +61,10 @@ module API # build_id (required) - The ID of a build # Example Request: # GET /projects/:id/build/:build_id/trace + # + # TODO: We should use `present_file!` and leave this implementation for backward compatibility (when build trace + # is saved in the DB instead of file). But before that, we need to consider how to replace the value of + # `runners_token` with some mask (like `xxxxxx`) when sending trace file directly by workhorse. get ':id/builds/:build_id/trace' do build = get_build(params[:build_id]) return not_found!(build) unless build -- cgit v1.2.1 From ab2c6cc01ff26e07db15110e037e72159c48dc53 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Tue, 12 Jan 2016 18:32:18 +0100 Subject: Add some fixes --- lib/api/api.rb | 1 - lib/api/entities.rb | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/api/api.rb b/lib/api/api.rb index 266b5f48f8f..1a1340c428c 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -54,7 +54,6 @@ module API mount Keys mount Tags mount Triggers - mount Builds end end diff --git a/lib/api/entities.rb b/lib/api/entities.rb index a1a886d6fea..e19f9f8d75a 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -377,7 +377,7 @@ module API class Build < Grape::Entity expose :id, :status, :stage, :name, :ref, :tag, :coverage expose :created_at, :started_at, :finished_at - expose :user, with: UserFull + expose :user, with: User expose :download_url do |repo_obj, options| if options[:user_can_download_artifacts] repo_obj.download_url -- cgit v1.2.1 From 97338496188add9ec8d192c7e78f6a6040befffa Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Wed, 13 Jan 2016 15:17:59 +0100 Subject: Add some fixes after review --- lib/api/builds.rb | 24 +++++++++++++----------- lib/api/entities.rb | 6 ++---- 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'lib') diff --git a/lib/api/builds.rb b/lib/api/builds.rb index d3f4e33ebbf..1337e1bb452 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -35,6 +35,7 @@ module API builds = commit.builds.order('id DESC') builds = filter_builds(builds, params[:scope]) + present paginate(builds), with: Entities::Build, user_can_download_artifacts: can?(current_user, :download_build_artifacts, user_project) end @@ -118,25 +119,26 @@ module API helpers do def get_build(id) - user_project.builds.where(id: id).first + user_project.builds.find_by(id: id.to_i) end def filter_builds(builds, scope) - available_scopes = Ci::Build.available_statuses + return builds if scope.nil? || scope.empty? + + available_statuses = Ci::Build.available_statuses scope = - if scope.is_a?(String) || scope.is_a?(Symbol) - available_scopes & [scope.to_s] - elsif scope.is_a?(Array) - available_scopes & scope - elsif scope.respond_to?(:to_h) - available_scopes & scope.to_h.values + if scope.is_a?(String) + [scope] + elsif scope.is_a?(Hashie::Mash) + scope.values else - [] + ['unknown'] end - return builds if scope.empty? + unknown = scope - available_statuses + render_api_error!('Scope contains invalid value(s)', 400) unless unknown.empty? - builds.where(status: scope) + builds.where(status: available_statuses && scope) end def authorize_manage_builds! diff --git a/lib/api/entities.rb b/lib/api/entities.rb index e19f9f8d75a..f0816a46529 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -378,18 +378,16 @@ module API expose :id, :status, :stage, :name, :ref, :tag, :coverage expose :created_at, :started_at, :finished_at expose :user, with: User + # TODO: download_url in Ci:Build model is an GitLab Web Interface URL, not API URL. We should think on some API + # for downloading of artifacts (see: https://gitlab.com/gitlab-org/gitlab-ce/issues/4255) expose :download_url do |repo_obj, options| if options[:user_can_download_artifacts] repo_obj.download_url - else - nil end end expose :commit, with: RepoCommit do |repo_obj, _options| if repo_obj.respond_to?(:commit) repo_obj.commit.commit_data - else - nil end end expose :runner, with: Runner -- cgit v1.2.1 From 2a20c0e590be2f673188f1a0d27409a714800c89 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 7 Jan 2016 15:46:12 +0100 Subject: Prevent circular reference error in Banzai --- lib/banzai/cross_project_reference.rb | 2 -- lib/banzai/filter.rb | 1 - lib/banzai/filter/abstract_reference_filter.rb | 2 -- lib/banzai/filter/autolink_filter.rb | 1 - lib/banzai/filter/commit_range_reference_filter.rb | 2 -- lib/banzai/filter/commit_reference_filter.rb | 2 -- lib/banzai/filter/emoji_filter.rb | 1 - lib/banzai/filter/external_issue_reference_filter.rb | 2 -- lib/banzai/filter/external_link_filter.rb | 1 - lib/banzai/filter/issue_reference_filter.rb | 2 -- lib/banzai/filter/label_reference_filter.rb | 2 -- lib/banzai/filter/markdown_filter.rb | 1 - lib/banzai/filter/merge_request_reference_filter.rb | 2 -- lib/banzai/filter/redactor_filter.rb | 1 - lib/banzai/filter/reference_filter.rb | 1 - lib/banzai/filter/reference_gatherer_filter.rb | 1 - lib/banzai/filter/relative_link_filter.rb | 1 - lib/banzai/filter/sanitization_filter.rb | 1 - lib/banzai/filter/snippet_reference_filter.rb | 2 -- lib/banzai/filter/syntax_highlight_filter.rb | 1 - lib/banzai/filter/table_of_contents_filter.rb | 1 - lib/banzai/filter/task_list_filter.rb | 1 - lib/banzai/filter/upload_link_filter.rb | 1 - lib/banzai/filter/user_reference_filter.rb | 2 -- lib/banzai/lazy_reference.rb | 2 -- lib/banzai/pipeline.rb | 2 -- lib/banzai/pipeline/asciidoc_pipeline.rb | 2 -- lib/banzai/pipeline/atom_pipeline.rb | 2 -- lib/banzai/pipeline/base_pipeline.rb | 1 - lib/banzai/pipeline/combined_pipeline.rb | 2 -- lib/banzai/pipeline/description_pipeline.rb | 2 -- lib/banzai/pipeline/email_pipeline.rb | 2 -- lib/banzai/pipeline/full_pipeline.rb | 2 -- lib/banzai/pipeline/gfm_pipeline.rb | 2 -- lib/banzai/pipeline/note_pipeline.rb | 2 -- lib/banzai/pipeline/plain_markdown_pipeline.rb | 2 -- lib/banzai/pipeline/post_process_pipeline.rb | 2 -- lib/banzai/pipeline/reference_extraction_pipeline.rb | 2 -- lib/banzai/pipeline/single_line_pipeline.rb | 2 -- lib/banzai/reference_extractor.rb | 2 -- lib/gitlab/markdown/pipeline.rb | 2 -- lib/gitlab/reference_extractor.rb | 2 -- 42 files changed, 69 deletions(-) (limited to 'lib') diff --git a/lib/banzai/cross_project_reference.rb b/lib/banzai/cross_project_reference.rb index ba2866e1efa..0257848b6bc 100644 --- a/lib/banzai/cross_project_reference.rb +++ b/lib/banzai/cross_project_reference.rb @@ -1,5 +1,3 @@ -require 'banzai' - module Banzai # Common methods for ReferenceFilters that support an optional cross-project # reference. diff --git a/lib/banzai/filter.rb b/lib/banzai/filter.rb index fd4fe024252..905c4c0144e 100644 --- a/lib/banzai/filter.rb +++ b/lib/banzai/filter.rb @@ -1,5 +1,4 @@ require 'active_support/core_ext/string/output_safety' -require 'banzai' module Banzai module Filter diff --git a/lib/banzai/filter/abstract_reference_filter.rb b/lib/banzai/filter/abstract_reference_filter.rb index b2db10e6864..cdbaecf8d90 100644 --- a/lib/banzai/filter/abstract_reference_filter.rb +++ b/lib/banzai/filter/abstract_reference_filter.rb @@ -1,5 +1,3 @@ -require 'banzai' - module Banzai module Filter # Issues, Merge Requests, Snippets, Commits and Commit Ranges share diff --git a/lib/banzai/filter/autolink_filter.rb b/lib/banzai/filter/autolink_filter.rb index da4ee80c1b5..856f56fb175 100644 --- a/lib/banzai/filter/autolink_filter.rb +++ b/lib/banzai/filter/autolink_filter.rb @@ -1,4 +1,3 @@ -require 'banzai' require 'html/pipeline/filter' require 'uri' diff --git a/lib/banzai/filter/commit_range_reference_filter.rb b/lib/banzai/filter/commit_range_reference_filter.rb index e67cd45ab9b..470727ee312 100644 --- a/lib/banzai/filter/commit_range_reference_filter.rb +++ b/lib/banzai/filter/commit_range_reference_filter.rb @@ -1,5 +1,3 @@ -require 'banzai' - module Banzai module Filter # HTML filter that replaces commit range references with links. diff --git a/lib/banzai/filter/commit_reference_filter.rb b/lib/banzai/filter/commit_reference_filter.rb index 9e57608b483..713a56ba949 100644 --- a/lib/banzai/filter/commit_reference_filter.rb +++ b/lib/banzai/filter/commit_reference_filter.rb @@ -1,5 +1,3 @@ -require 'banzai' - module Banzai module Filter # HTML filter that replaces commit references with links. diff --git a/lib/banzai/filter/emoji_filter.rb b/lib/banzai/filter/emoji_filter.rb index 86838e1483c..5952a031626 100644 --- a/lib/banzai/filter/emoji_filter.rb +++ b/lib/banzai/filter/emoji_filter.rb @@ -1,5 +1,4 @@ require 'action_controller' -require 'banzai' require 'gitlab_emoji' require 'html/pipeline/filter' diff --git a/lib/banzai/filter/external_issue_reference_filter.rb b/lib/banzai/filter/external_issue_reference_filter.rb index 6136e73c096..edc26386903 100644 --- a/lib/banzai/filter/external_issue_reference_filter.rb +++ b/lib/banzai/filter/external_issue_reference_filter.rb @@ -1,5 +1,3 @@ -require 'banzai' - module Banzai module Filter # HTML filter that replaces external issue tracker references with links. diff --git a/lib/banzai/filter/external_link_filter.rb b/lib/banzai/filter/external_link_filter.rb index ac87b9820af..8d368f3b9e7 100644 --- a/lib/banzai/filter/external_link_filter.rb +++ b/lib/banzai/filter/external_link_filter.rb @@ -1,4 +1,3 @@ -require 'banzai' require 'html/pipeline/filter' module Banzai diff --git a/lib/banzai/filter/issue_reference_filter.rb b/lib/banzai/filter/issue_reference_filter.rb index 51180cb901a..9f08aa36e8b 100644 --- a/lib/banzai/filter/issue_reference_filter.rb +++ b/lib/banzai/filter/issue_reference_filter.rb @@ -1,5 +1,3 @@ -require 'banzai' - module Banzai module Filter # HTML filter that replaces issue references with links. References to diff --git a/lib/banzai/filter/label_reference_filter.rb b/lib/banzai/filter/label_reference_filter.rb index a3a7a23c1e6..95e7d209119 100644 --- a/lib/banzai/filter/label_reference_filter.rb +++ b/lib/banzai/filter/label_reference_filter.rb @@ -1,5 +1,3 @@ -require 'banzai' - module Banzai module Filter # HTML filter that replaces label references with links. diff --git a/lib/banzai/filter/markdown_filter.rb b/lib/banzai/filter/markdown_filter.rb index d09cf41df39..0659fed1419 100644 --- a/lib/banzai/filter/markdown_filter.rb +++ b/lib/banzai/filter/markdown_filter.rb @@ -1,4 +1,3 @@ -require 'banzai' require 'html/pipeline/filter' module Banzai diff --git a/lib/banzai/filter/merge_request_reference_filter.rb b/lib/banzai/filter/merge_request_reference_filter.rb index 755b946a34b..57c71708992 100644 --- a/lib/banzai/filter/merge_request_reference_filter.rb +++ b/lib/banzai/filter/merge_request_reference_filter.rb @@ -1,5 +1,3 @@ -require 'banzai' - module Banzai module Filter # HTML filter that replaces merge request references with links. References diff --git a/lib/banzai/filter/redactor_filter.rb b/lib/banzai/filter/redactor_filter.rb index 66f77902319..7141ed7c9bd 100644 --- a/lib/banzai/filter/redactor_filter.rb +++ b/lib/banzai/filter/redactor_filter.rb @@ -1,4 +1,3 @@ -require 'banzai' require 'html/pipeline/filter' module Banzai diff --git a/lib/banzai/filter/reference_filter.rb b/lib/banzai/filter/reference_filter.rb index 5dd6d2fe3c7..20bd4f7ee6e 100644 --- a/lib/banzai/filter/reference_filter.rb +++ b/lib/banzai/filter/reference_filter.rb @@ -1,5 +1,4 @@ require 'active_support/core_ext/string/output_safety' -require 'banzai' require 'html/pipeline/filter' module Banzai diff --git a/lib/banzai/filter/reference_gatherer_filter.rb b/lib/banzai/filter/reference_gatherer_filter.rb index bef04112919..86d484feb90 100644 --- a/lib/banzai/filter/reference_gatherer_filter.rb +++ b/lib/banzai/filter/reference_gatherer_filter.rb @@ -1,4 +1,3 @@ -require 'banzai' require 'html/pipeline/filter' module Banzai diff --git a/lib/banzai/filter/relative_link_filter.rb b/lib/banzai/filter/relative_link_filter.rb index 66f166939e4..41380627d39 100644 --- a/lib/banzai/filter/relative_link_filter.rb +++ b/lib/banzai/filter/relative_link_filter.rb @@ -1,4 +1,3 @@ -require 'banzai' require 'html/pipeline/filter' require 'uri' diff --git a/lib/banzai/filter/sanitization_filter.rb b/lib/banzai/filter/sanitization_filter.rb index d03e3ae4b3c..3f49d492f2f 100644 --- a/lib/banzai/filter/sanitization_filter.rb +++ b/lib/banzai/filter/sanitization_filter.rb @@ -1,4 +1,3 @@ -require 'banzai' require 'html/pipeline/filter' require 'html/pipeline/sanitization_filter' diff --git a/lib/banzai/filter/snippet_reference_filter.rb b/lib/banzai/filter/snippet_reference_filter.rb index 1ad5df96f85..c870a42f741 100644 --- a/lib/banzai/filter/snippet_reference_filter.rb +++ b/lib/banzai/filter/snippet_reference_filter.rb @@ -1,5 +1,3 @@ -require 'banzai' - module Banzai module Filter # HTML filter that replaces snippet references with links. References to diff --git a/lib/banzai/filter/syntax_highlight_filter.rb b/lib/banzai/filter/syntax_highlight_filter.rb index c889cc1e97c..8c5855e5ffc 100644 --- a/lib/banzai/filter/syntax_highlight_filter.rb +++ b/lib/banzai/filter/syntax_highlight_filter.rb @@ -1,4 +1,3 @@ -require 'banzai' require 'html/pipeline/filter' require 'rouge/plugins/redcarpet' diff --git a/lib/banzai/filter/table_of_contents_filter.rb b/lib/banzai/filter/table_of_contents_filter.rb index 9b3e67206d5..4056dcd6d64 100644 --- a/lib/banzai/filter/table_of_contents_filter.rb +++ b/lib/banzai/filter/table_of_contents_filter.rb @@ -1,4 +1,3 @@ -require 'banzai' require 'html/pipeline/filter' module Banzai diff --git a/lib/banzai/filter/task_list_filter.rb b/lib/banzai/filter/task_list_filter.rb index d0ce13003a5..66608c9859c 100644 --- a/lib/banzai/filter/task_list_filter.rb +++ b/lib/banzai/filter/task_list_filter.rb @@ -1,4 +1,3 @@ -require 'banzai' require 'task_list/filter' module Banzai diff --git a/lib/banzai/filter/upload_link_filter.rb b/lib/banzai/filter/upload_link_filter.rb index 1a1d0aad8ca..f642aee0967 100644 --- a/lib/banzai/filter/upload_link_filter.rb +++ b/lib/banzai/filter/upload_link_filter.rb @@ -1,4 +1,3 @@ -require 'banzai' require 'html/pipeline/filter' require 'uri' diff --git a/lib/banzai/filter/user_reference_filter.rb b/lib/banzai/filter/user_reference_filter.rb index 964ab60f614..24f16f8b547 100644 --- a/lib/banzai/filter/user_reference_filter.rb +++ b/lib/banzai/filter/user_reference_filter.rb @@ -1,5 +1,3 @@ -require 'banzai' - module Banzai module Filter # HTML filter that replaces user or group references with links. diff --git a/lib/banzai/lazy_reference.rb b/lib/banzai/lazy_reference.rb index 073ec5d9801..1095b4debc7 100644 --- a/lib/banzai/lazy_reference.rb +++ b/lib/banzai/lazy_reference.rb @@ -1,5 +1,3 @@ -require 'banzai' - module Banzai class LazyReference def self.load(refs) diff --git a/lib/banzai/pipeline.rb b/lib/banzai/pipeline.rb index 4e017809d9d..142a9962eb1 100644 --- a/lib/banzai/pipeline.rb +++ b/lib/banzai/pipeline.rb @@ -1,5 +1,3 @@ -require 'banzai' - module Banzai module Pipeline def self.[](name) diff --git a/lib/banzai/pipeline/asciidoc_pipeline.rb b/lib/banzai/pipeline/asciidoc_pipeline.rb index 5e76a817be5..f1331c0ebf9 100644 --- a/lib/banzai/pipeline/asciidoc_pipeline.rb +++ b/lib/banzai/pipeline/asciidoc_pipeline.rb @@ -1,5 +1,3 @@ -require 'banzai' - module Banzai module Pipeline class AsciidocPipeline < BasePipeline diff --git a/lib/banzai/pipeline/atom_pipeline.rb b/lib/banzai/pipeline/atom_pipeline.rb index 957f352aec5..9694e4bc23f 100644 --- a/lib/banzai/pipeline/atom_pipeline.rb +++ b/lib/banzai/pipeline/atom_pipeline.rb @@ -1,5 +1,3 @@ -require 'banzai' - module Banzai module Pipeline class AtomPipeline < FullPipeline diff --git a/lib/banzai/pipeline/base_pipeline.rb b/lib/banzai/pipeline/base_pipeline.rb index cd30009e5c0..db5177db7b3 100644 --- a/lib/banzai/pipeline/base_pipeline.rb +++ b/lib/banzai/pipeline/base_pipeline.rb @@ -1,4 +1,3 @@ -require 'banzai' require 'html/pipeline' module Banzai diff --git a/lib/banzai/pipeline/combined_pipeline.rb b/lib/banzai/pipeline/combined_pipeline.rb index f3bf1809d18..9485199132e 100644 --- a/lib/banzai/pipeline/combined_pipeline.rb +++ b/lib/banzai/pipeline/combined_pipeline.rb @@ -1,5 +1,3 @@ -require 'banzai' - module Banzai module Pipeline module CombinedPipeline diff --git a/lib/banzai/pipeline/description_pipeline.rb b/lib/banzai/pipeline/description_pipeline.rb index 94c2cb165a5..20e24ace352 100644 --- a/lib/banzai/pipeline/description_pipeline.rb +++ b/lib/banzai/pipeline/description_pipeline.rb @@ -1,5 +1,3 @@ -require 'banzai' - module Banzai module Pipeline class DescriptionPipeline < FullPipeline diff --git a/lib/banzai/pipeline/email_pipeline.rb b/lib/banzai/pipeline/email_pipeline.rb index 14356145a35..e47c384afc1 100644 --- a/lib/banzai/pipeline/email_pipeline.rb +++ b/lib/banzai/pipeline/email_pipeline.rb @@ -1,5 +1,3 @@ -require 'banzai' - module Banzai module Pipeline class EmailPipeline < FullPipeline diff --git a/lib/banzai/pipeline/full_pipeline.rb b/lib/banzai/pipeline/full_pipeline.rb index 72395a5d50e..d47ddfda4be 100644 --- a/lib/banzai/pipeline/full_pipeline.rb +++ b/lib/banzai/pipeline/full_pipeline.rb @@ -1,5 +1,3 @@ -require 'banzai' - module Banzai module Pipeline class FullPipeline < CombinedPipeline.new(PlainMarkdownPipeline, GfmPipeline) diff --git a/lib/banzai/pipeline/gfm_pipeline.rb b/lib/banzai/pipeline/gfm_pipeline.rb index 838155e8831..b7a38ea8427 100644 --- a/lib/banzai/pipeline/gfm_pipeline.rb +++ b/lib/banzai/pipeline/gfm_pipeline.rb @@ -1,5 +1,3 @@ -require 'banzai' - module Banzai module Pipeline class GfmPipeline < BasePipeline diff --git a/lib/banzai/pipeline/note_pipeline.rb b/lib/banzai/pipeline/note_pipeline.rb index 89335143852..7890f20f716 100644 --- a/lib/banzai/pipeline/note_pipeline.rb +++ b/lib/banzai/pipeline/note_pipeline.rb @@ -1,5 +1,3 @@ -require 'banzai' - module Banzai module Pipeline class NotePipeline < FullPipeline diff --git a/lib/banzai/pipeline/plain_markdown_pipeline.rb b/lib/banzai/pipeline/plain_markdown_pipeline.rb index 998fd75daa2..3fbc681457b 100644 --- a/lib/banzai/pipeline/plain_markdown_pipeline.rb +++ b/lib/banzai/pipeline/plain_markdown_pipeline.rb @@ -1,5 +1,3 @@ -require 'banzai' - module Banzai module Pipeline class PlainMarkdownPipeline < BasePipeline diff --git a/lib/banzai/pipeline/post_process_pipeline.rb b/lib/banzai/pipeline/post_process_pipeline.rb index 148f24b6ce1..bd338c045f3 100644 --- a/lib/banzai/pipeline/post_process_pipeline.rb +++ b/lib/banzai/pipeline/post_process_pipeline.rb @@ -1,5 +1,3 @@ -require 'banzai' - module Banzai module Pipeline class PostProcessPipeline < BasePipeline diff --git a/lib/banzai/pipeline/reference_extraction_pipeline.rb b/lib/banzai/pipeline/reference_extraction_pipeline.rb index 4f9bc9fcccc..eaddccd30a5 100644 --- a/lib/banzai/pipeline/reference_extraction_pipeline.rb +++ b/lib/banzai/pipeline/reference_extraction_pipeline.rb @@ -1,5 +1,3 @@ -require 'banzai' - module Banzai module Pipeline class ReferenceExtractionPipeline < BasePipeline diff --git a/lib/banzai/pipeline/single_line_pipeline.rb b/lib/banzai/pipeline/single_line_pipeline.rb index a3c9d4f43aa..8b84ab401df 100644 --- a/lib/banzai/pipeline/single_line_pipeline.rb +++ b/lib/banzai/pipeline/single_line_pipeline.rb @@ -1,5 +1,3 @@ -require 'banzai' - module Banzai module Pipeline class SingleLinePipeline < GfmPipeline diff --git a/lib/banzai/reference_extractor.rb b/lib/banzai/reference_extractor.rb index 2c197d31898..f4079538ec5 100644 --- a/lib/banzai/reference_extractor.rb +++ b/lib/banzai/reference_extractor.rb @@ -1,5 +1,3 @@ -require 'banzai' - module Banzai # Extract possible GFM references from an arbitrary String for further processing. class ReferenceExtractor diff --git a/lib/gitlab/markdown/pipeline.rb b/lib/gitlab/markdown/pipeline.rb index 8f3f43c0e91..699d8b9fc07 100644 --- a/lib/gitlab/markdown/pipeline.rb +++ b/lib/gitlab/markdown/pipeline.rb @@ -1,5 +1,3 @@ -require 'banzai' - module Gitlab module Markdown class Pipeline diff --git a/lib/gitlab/reference_extractor.rb b/lib/gitlab/reference_extractor.rb index 4164e998dd1..4d830aa45e1 100644 --- a/lib/gitlab/reference_extractor.rb +++ b/lib/gitlab/reference_extractor.rb @@ -1,5 +1,3 @@ -require 'banzai' - module Gitlab # Extract possible GFM references from an arbitrary String for further processing. class ReferenceExtractor < Banzai::ReferenceExtractor -- cgit v1.2.1 From 3183092ca94b14d6e61f5e8ba51069554646baf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Thu, 14 Jan 2016 12:08:44 +0100 Subject: Add pagination headers to already paginated API resources --- lib/api/helpers.rb | 30 +++++++++++++++++++----------- lib/api/notes.rb | 12 +++--------- 2 files changed, 22 insertions(+), 20 deletions(-) (limited to 'lib') diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index a4df810e755..312ef90915f 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -97,11 +97,9 @@ module API end def paginate(relation) - per_page = params[:per_page].to_i - paginated = relation.page(params[:page]).per(per_page) - add_pagination_headers(paginated, per_page) - - paginated + relation.page(params[:page]).per(params[:per_page].to_i).tap do |data| + add_pagination_headers(data) + end end def authenticate! @@ -327,16 +325,26 @@ module API private - def add_pagination_headers(paginated, per_page) + 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 links = [] - links << %(<#{request_url}?page=#{paginated.current_page - 1}&per_page=#{per_page}>; rel="prev") unless paginated.first_page? - links << %(<#{request_url}?page=#{paginated.current_page + 1}&per_page=#{per_page}>; rel="next") unless paginated.last_page? - links << %(<#{request_url}?page=1&per_page=#{per_page}>; rel="first") - links << %(<#{request_url}?page=#{paginated.total_pages}&per_page=#{per_page}>; rel="last") + links << %(<#{request_url}?page=#{paginated_data.current_page - 1}&per_page=#{paginated_data.limit_value}>; rel="prev") unless paginated_data.first_page? + links << %(<#{request_url}?page=#{paginated_data.current_page + 1}&per_page=#{paginated_data.limit_value}>; rel="next") unless paginated_data.last_page? + links << %(<#{request_url}?page=1&per_page=#{paginated_data.limit_value}>; rel="first") + links << %(<#{request_url}?page=#{paginated_data.total_pages}&per_page=#{paginated_data.limit_value}>; rel="last") - header 'Link', links.join(', ') + links.join(', ') end def abilities diff --git a/lib/api/notes.rb b/lib/api/notes.rb index 174473f5371..ebd9e97148c 100644 --- a/lib/api/notes.rb +++ b/lib/api/notes.rb @@ -22,17 +22,11 @@ module API @noteable = user_project.send(:"#{noteables_str}").find(params[:"#{noteable_id_str}"]) # 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. + # by the current user. 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). + @noteable.notes. reject { |n| n.cross_reference_not_visible_for?(current_user) } - present notes, with: Entities::Note + present paginate(Kaminari.paginate_array(notes)), with: Entities::Note end # Get a single +noteable+ note -- cgit v1.2.1 From f5d530865875440d69217cf249715bffaa3d11b8 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 18 Dec 2015 11:59:10 +0100 Subject: Add implementation of StringPath class `StringPath` class is something similar to Ruby's `Pathname` class, but does not involve any IO operations. `StringPath` objects require passing string representation of path, and array of paths that represents universe to constructor to be intantiated. --- lib/gitlab/string_path.rb | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 lib/gitlab/string_path.rb (limited to 'lib') diff --git a/lib/gitlab/string_path.rb b/lib/gitlab/string_path.rb new file mode 100644 index 00000000000..be65b41dff5 --- /dev/null +++ b/lib/gitlab/string_path.rb @@ -0,0 +1,35 @@ +module Gitlab + ## + # Class that represents a path to a file or directory + # + # This is IO-operations safe class, that does similar job to + # Ruby's Pathname but without the risk of accessing filesystem. + # + # + class StringPath + def initialize(path, universe) + @path = path + @universe = universe + end + + def absolute? + @path.start_with?('/') + end + + def relative? + !absolute? + end + + def directory? + @path.end_with?('/') + end + + def file? + !directory? + end + + def to_s + @path + end + end +end -- cgit v1.2.1 From 73d2c7a553ca239cdce04af793992fd579ad3e4b Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 18 Dec 2015 12:32:21 +0100 Subject: Add new methods to StringPath --- lib/gitlab/string_path.rb | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/string_path.rb b/lib/gitlab/string_path.rb index be65b41dff5..9ccf54bd62f 100644 --- a/lib/gitlab/string_path.rb +++ b/lib/gitlab/string_path.rb @@ -7,11 +7,17 @@ module Gitlab # # class StringPath + attr_reader :path, :universe + def initialize(path, universe) @path = path @universe = universe end + def to_s + @path + end + def absolute? @path.start_with?('/') end @@ -28,8 +34,17 @@ module Gitlab !directory? end - def to_s - @path + def files + raise NotImplementedError + end + + def basename + name = @path.split(::File::SEPARATOR).last + directory? ? name + ::File::SEPARATOR : name + end + + def ==(other) + @path == other.path && @universe == other.universe end end end -- cgit v1.2.1 From 80a71576ba27d84b3406a8b929328359e2edc9da Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 18 Dec 2015 12:55:50 +0100 Subject: Use `Gitlab::StringPath` in CI build artifacts controller --- lib/gitlab/string_path.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'lib') diff --git a/lib/gitlab/string_path.rb b/lib/gitlab/string_path.rb index 9ccf54bd62f..3aa6200b572 100644 --- a/lib/gitlab/string_path.rb +++ b/lib/gitlab/string_path.rb @@ -34,6 +34,18 @@ module Gitlab !directory? end + def has_parent? + raise NotImplementedError + end + + def parent + raise NotImplementedError + end + + def directories + raise NotImplementedError + end + def files raise NotImplementedError end -- cgit v1.2.1 From 518b206287318006f9b57382a747b1474b6795a4 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Sat, 19 Dec 2015 09:31:52 +0100 Subject: Add `parent` iteration implementation to `StringPath` --- lib/gitlab/string_path.rb | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/string_path.rb b/lib/gitlab/string_path.rb index 3aa6200b572..3add56d2213 100644 --- a/lib/gitlab/string_path.rb +++ b/lib/gitlab/string_path.rb @@ -35,11 +35,12 @@ module Gitlab end def has_parent? - raise NotImplementedError + @universe.include?(@path.sub(basename, '')) end def parent - raise NotImplementedError + return nil unless has_parent? + new(@path.sub(basename, '')) end def directories @@ -58,5 +59,11 @@ module Gitlab def ==(other) @path == other.path && @universe == other.universe end + + private + + def new(path) + self.class.new(path, @universe) + end end end -- cgit v1.2.1 From d382335dcd9285c9355ed04dc12c5314bca3c024 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Mon, 21 Dec 2015 10:11:15 +0100 Subject: Add implementation of remaining methods in `StringPath` --- lib/gitlab/string_path.rb | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/string_path.rb b/lib/gitlab/string_path.rb index 3add56d2213..a2dc63db2f2 100644 --- a/lib/gitlab/string_path.rb +++ b/lib/gitlab/string_path.rb @@ -43,12 +43,24 @@ module Gitlab new(@path.sub(basename, '')) end + def descendants + return [] unless directory? + children = @universe.select { |entry| entry =~ /^#{@path}.+/ } + children.map { |path| new(path) } + end + + def children + descendants.select { |descendant| descendant.parent == self } + end + def directories - raise NotImplementedError + return [] unless directory? + children.select { |child| child.directory? } end def files - raise NotImplementedError + return [] unless directory? + children.select { |child| child.file? } end def basename -- cgit v1.2.1 From 37b2c5dd5521f25a7195e82538a0ffc528c3ec6d Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Mon, 21 Dec 2015 12:08:04 +0100 Subject: Add support for root path for `StringPath` --- lib/gitlab/string_path.rb | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/string_path.rb b/lib/gitlab/string_path.rb index a2dc63db2f2..d165829132a 100644 --- a/lib/gitlab/string_path.rb +++ b/lib/gitlab/string_path.rb @@ -1,6 +1,6 @@ module Gitlab ## - # Class that represents a path to a file or directory + # Class that represents a simplified path to a file or directory # # This is IO-operations safe class, that does similar job to # Ruby's Pathname but without the risk of accessing filesystem. @@ -10,8 +10,9 @@ module Gitlab attr_reader :path, :universe def initialize(path, universe) - @path = path - @universe = universe + @path = prepare(path) + @universe = universe.map { |entry| prepare(entry) } + @universe.unshift('./') unless @universe.include?('./') end def to_s @@ -43,6 +44,15 @@ module Gitlab new(@path.sub(basename, '')) end + def basename + name = @path.split(::File::SEPARATOR).last + directory? ? name + ::File::SEPARATOR : name + end + + def has_descendants? + descendants.any? + end + def descendants return [] unless directory? children = @universe.select { |entry| entry =~ /^#{@path}.+/ } @@ -63,11 +73,6 @@ module Gitlab children.select { |child| child.file? } end - def basename - name = @path.split(::File::SEPARATOR).last - directory? ? name + ::File::SEPARATOR : name - end - def ==(other) @path == other.path && @universe == other.universe end @@ -77,5 +82,10 @@ module Gitlab def new(path) self.class.new(path, @universe) end + + def prepare(path) + return path if path =~ %r{^(/|\.|\.\.)} + path.dup.prepend('./') + end end end -- cgit v1.2.1 From b19e958d86f5363057f006c8dbf9a8e8762618b9 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 22 Dec 2015 11:05:22 +0100 Subject: Add support for parent directories in `StringPath` This support is not completed though, as parent directory that is first in collection returned by `directories!` is not iterable yet. --- lib/gitlab/string_path.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/string_path.rb b/lib/gitlab/string_path.rb index d165829132a..493fceb256d 100644 --- a/lib/gitlab/string_path.rb +++ b/lib/gitlab/string_path.rb @@ -5,6 +5,7 @@ module Gitlab # This is IO-operations safe class, that does similar job to # Ruby's Pathname but without the risk of accessing filesystem. # + # TODO: better support for './' and '../' # class StringPath attr_reader :path, :universe @@ -45,10 +46,13 @@ module Gitlab end def basename - name = @path.split(::File::SEPARATOR).last directory? ? name + ::File::SEPARATOR : name end + def name + @path.split(::File::SEPARATOR).last + end + def has_descendants? descendants.any? end @@ -68,6 +72,10 @@ module Gitlab children.select { |child| child.directory? } end + def directories! + has_parent? ? directories.prepend(new(@path + '../')) : directories + end + def files return [] unless directory? children.select { |child| child.file? } -- cgit v1.2.1 From 1cc26e0f0e2ef62fecb688e45bc51c66c8fdf0a7 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 22 Dec 2015 13:02:00 +0100 Subject: Improve performance of `StringPath` --- lib/gitlab/string_path.rb | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/string_path.rb b/lib/gitlab/string_path.rb index 493fceb256d..1eb8162f805 100644 --- a/lib/gitlab/string_path.rb +++ b/lib/gitlab/string_path.rb @@ -5,15 +5,15 @@ module Gitlab # This is IO-operations safe class, that does similar job to # Ruby's Pathname but without the risk of accessing filesystem. # - # TODO: better support for './' and '../' + # TODO: better support for '../' and './' # class StringPath attr_reader :path, :universe def initialize(path, universe) @path = prepare(path) - @universe = universe.map { |entry| prepare(entry) } - @universe.unshift('./') unless @universe.include?('./') + @universe = Set.new(universe.map { |entry| prepare(entry) }) + @universe.add('./') end def to_s @@ -64,7 +64,10 @@ module Gitlab end def children - descendants.select { |descendant| descendant.parent == self } + return [] unless directory? + return @children if @children + children = @universe.select { |entry| entry =~ %r{^#{@path}[^/]+/?$} } + @children = children.map { |path| new(path) } end def directories @@ -85,6 +88,10 @@ module Gitlab @path == other.path && @universe == other.universe end + def inspect + "#{self.class.name}: #{@path}" + end + private def new(path) -- cgit v1.2.1 From c177784d5af6b47ae613f922e075a38fc56ad711 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 29 Dec 2015 11:40:57 +0100 Subject: Use short method call in StringPath instead block --- lib/gitlab/string_path.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/string_path.rb b/lib/gitlab/string_path.rb index 1eb8162f805..af80a502bf6 100644 --- a/lib/gitlab/string_path.rb +++ b/lib/gitlab/string_path.rb @@ -72,7 +72,7 @@ module Gitlab def directories return [] unless directory? - children.select { |child| child.directory? } + children.select(&:directory?) end def directories! @@ -81,7 +81,7 @@ module Gitlab def files return [] unless directory? - children.select { |child| child.file? } + children.select(&:file?) end def ==(other) -- cgit v1.2.1 From 447f56036e837fc9a9c2bcaf382d38dc513a9733 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 31 Dec 2015 09:25:59 +0100 Subject: Use metadata stored in artifacats metadata file --- lib/gitlab/string_path.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/string_path.rb b/lib/gitlab/string_path.rb index af80a502bf6..bfeb0f852f0 100644 --- a/lib/gitlab/string_path.rb +++ b/lib/gitlab/string_path.rb @@ -5,7 +5,7 @@ module Gitlab # This is IO-operations safe class, that does similar job to # Ruby's Pathname but without the risk of accessing filesystem. # - # TODO: better support for '../' and './' + # TODO, better support for '../' and './' # class StringPath attr_reader :path, :universe -- cgit v1.2.1 From 3de8a4620a70c886c815576dc0a30a745cbb8ccb Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 31 Dec 2015 12:21:56 +0100 Subject: Parse artifacts metadata stored in JSON format --- lib/gitlab/string_path.rb | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/string_path.rb b/lib/gitlab/string_path.rb index bfeb0f852f0..ad68a8ff2d6 100644 --- a/lib/gitlab/string_path.rb +++ b/lib/gitlab/string_path.rb @@ -10,10 +10,11 @@ module Gitlab class StringPath attr_reader :path, :universe - def initialize(path, universe) + def initialize(path, universe, metadata = []) @path = prepare(path) - @universe = Set.new(universe.map { |entry| prepare(entry) }) - @universe.add('./') + @universe = universe.map { |entry| prepare(entry) } + @universe << './' unless @universe.include?('./') + @metadata = metadata end def to_s @@ -84,6 +85,11 @@ module Gitlab children.select(&:file?) end + def metadata + index = @universe.index(@path) + @metadata[index] + end + def ==(other) @path == other.path && @universe == other.universe end -- cgit v1.2.1 From a3191463b60c8ded25a2898d5e5520ae4aff1114 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Sat, 2 Jan 2016 09:43:10 +0100 Subject: Add path sanitization to `StringPath` [ci skip] --- lib/gitlab/string_path.rb | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/string_path.rb b/lib/gitlab/string_path.rb index ad68a8ff2d6..8310564646e 100644 --- a/lib/gitlab/string_path.rb +++ b/lib/gitlab/string_path.rb @@ -5,15 +5,12 @@ module Gitlab # This is IO-operations safe class, that does similar job to # Ruby's Pathname but without the risk of accessing filesystem. # - # TODO, better support for '../' and './' - # class StringPath attr_reader :path, :universe def initialize(path, universe, metadata = []) - @path = prepare(path) - @universe = universe.map { |entry| prepare(entry) } - @universe << './' unless @universe.include?('./') + @path = sanitize(path) + @universe = universe.map { |entry| sanitize(entry) } @metadata = metadata end @@ -60,15 +57,16 @@ module Gitlab def descendants return [] unless directory? - children = @universe.select { |entry| entry =~ /^#{@path}.+/ } - children.map { |path| new(path) } + select { |entry| entry =~ /^#{@path}.+/ } end def children return [] unless directory? return @children if @children - children = @universe.select { |entry| entry =~ %r{^#{@path}[^/]+/?$} } - @children = children.map { |path| new(path) } + + @children = select do |entry| + self.class.child?(@path, entry) + end end def directories @@ -104,9 +102,26 @@ module Gitlab self.class.new(path, @universe) end - def prepare(path) - return path if path =~ %r{^(/|\.|\.\.)} - path.dup.prepend('./') + def select + selected = @universe.select { |entry| yield entry } + selected.map { |path| new(path) } + end + + def sanitize(path) + self.class.sanitize(path) + end + + def self.sanitize(path) + # It looks like Pathname#new doesn't touch a file system, + # neither Pathname#cleanpath does, so it is, hopefully, filesystem safe + + clean = Pathname.new(path).cleanpath.to_s + raise ArgumentError, 'Invalid path' if clean.start_with?('../') + clean + (path.end_with?('/') ? '/' : '') + end + + def self.child?(path, entry) + entry =~ %r{^#{path}[^/\s]+/?$} end end end -- cgit v1.2.1 From df41148662142ce20a77b092665f48dd4dfa7bfb Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Sat, 2 Jan 2016 20:09:21 +0100 Subject: Improve path sanitization in `StringPath` --- lib/gitlab/string_path.rb | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/string_path.rb b/lib/gitlab/string_path.rb index 8310564646e..e7d99a35869 100644 --- a/lib/gitlab/string_path.rb +++ b/lib/gitlab/string_path.rb @@ -57,7 +57,7 @@ module Gitlab def descendants return [] unless directory? - select { |entry| entry =~ /^#{@path}.+/ } + select { |entry| entry =~ /^#{Regexp.escape(@path)}.+/ } end def children @@ -65,7 +65,7 @@ module Gitlab return @children if @children @children = select do |entry| - self.class.child?(@path, entry) + entry =~ %r{^#{Regexp.escape(@path)}[^/\s]+/?$} end end @@ -75,7 +75,7 @@ module Gitlab end def directories! - has_parent? ? directories.prepend(new(@path + '../')) : directories + has_parent? ? directories.prepend(parent) : directories end def files @@ -115,13 +115,12 @@ module Gitlab # It looks like Pathname#new doesn't touch a file system, # neither Pathname#cleanpath does, so it is, hopefully, filesystem safe - clean = Pathname.new(path).cleanpath.to_s - raise ArgumentError, 'Invalid path' if clean.start_with?('../') - clean + (path.end_with?('/') ? '/' : '') - end + clean_path = Pathname.new(path).cleanpath.to_s + raise ArgumentError, 'Invalid path' if clean_path.start_with?('../') - def self.child?(path, entry) - entry =~ %r{^#{path}[^/\s]+/?$} + prefix = './' unless clean_path =~ %r{^[\.|/]} + suffix = '/' if path.end_with?('/') || clean_path =~ /^[\.|\.\.]$/ + prefix.to_s + clean_path + suffix.to_s end end end -- cgit v1.2.1 From a7f99b67a0bf1160f41ebf4dc92c618eb13a7a10 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Mon, 4 Jan 2016 13:08:49 +0100 Subject: Extract artifacts metadata implementation to separate class --- lib/gitlab/ci/build/artifacts/metadata.rb | 57 +++++++++++++++++++++++++++++++ lib/gitlab/string_path.rb | 4 +-- 2 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 lib/gitlab/ci/build/artifacts/metadata.rb (limited to 'lib') diff --git a/lib/gitlab/ci/build/artifacts/metadata.rb b/lib/gitlab/ci/build/artifacts/metadata.rb new file mode 100644 index 00000000000..5313182d55f --- /dev/null +++ b/lib/gitlab/ci/build/artifacts/metadata.rb @@ -0,0 +1,57 @@ +require 'zlib' +require 'json' + +module Gitlab + module Ci + module Build + module Artifacts + class Metadata + def initialize(file, path) + @file = file + + @path = path.sub(/^\.\//, '') + @path << '/' unless path.end_with?('/') + end + + def exists? + File.exists?(@file) + end + + def match! + raise StandardError, 'Metadata file not found !' unless exists? + paths, metadata = [], [] + + each do |line| + next unless line =~ %r{^#{Regexp.escape(@path)}[^/\s]+/?\s} + + path, meta = line.split(' ') + paths.push(path) + metadata.push(meta) + end + + [paths, metadata.map { |meta| JSON.parse(meta) }] + end + + def to_string_path + universe, metadata = match! + ::Gitlab::StringPath.new(@path, universe, metadata) + end + + private + + def each + open do |file| + gzip = Zlib::GzipReader.new(file) + gzip.each_line { |line| yield line } + gzip.close + end + end + + def open + File.open(@file) { |file| yield file } + end + end + end + end + end +end diff --git a/lib/gitlab/string_path.rb b/lib/gitlab/string_path.rb index e7d99a35869..9948502e8ea 100644 --- a/lib/gitlab/string_path.rb +++ b/lib/gitlab/string_path.rb @@ -75,7 +75,7 @@ module Gitlab end def directories! - has_parent? ? directories.prepend(parent) : directories + @path =~ %r{^\./[^/]/} ? directories.prepend(parent) : directories end def files @@ -119,7 +119,7 @@ module Gitlab raise ArgumentError, 'Invalid path' if clean_path.start_with?('../') prefix = './' unless clean_path =~ %r{^[\.|/]} - suffix = '/' if path.end_with?('/') || clean_path =~ /^[\.|\.\.]$/ + suffix = '/' if path.end_with?('/') || ['.', '..'].include?(clean_path) prefix.to_s + clean_path + suffix.to_s end end -- cgit v1.2.1 From f948c00757ca9529817c7368610b0c0d6734d48f Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Mon, 4 Jan 2016 13:40:42 +0100 Subject: Do not depend on universe when checking parent in `StringPath` --- lib/gitlab/string_path.rb | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/string_path.rb b/lib/gitlab/string_path.rb index 9948502e8ea..4d024b3ff73 100644 --- a/lib/gitlab/string_path.rb +++ b/lib/gitlab/string_path.rb @@ -7,6 +7,7 @@ module Gitlab # class StringPath attr_reader :path, :universe + attr_accessor :name def initialize(path, universe, metadata = []) @path = sanitize(path) @@ -35,7 +36,7 @@ module Gitlab end def has_parent? - @universe.include?(@path.sub(basename, '')) + nodes > 1 end def parent @@ -48,7 +49,7 @@ module Gitlab end def name - @path.split(::File::SEPARATOR).last + @name || @path.split(::File::SEPARATOR).last end def has_descendants? @@ -75,7 +76,11 @@ module Gitlab end def directories! - @path =~ %r{^\./[^/]/} ? directories.prepend(parent) : directories + return directories unless has_parent? && directory? + + dotted_parent = parent + dotted_parent.name = '..' + directories.prepend(dotted_parent) end def files @@ -88,6 +93,10 @@ module Gitlab @metadata[index] end + def nodes + @path.count('/') + (file? ? 1 : 0) + end + def ==(other) @path == other.path && @universe == other.universe end -- cgit v1.2.1 From a5e1905d28e490fb4734bff0e02a1ecff4c7c029 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Mon, 4 Jan 2016 14:00:49 +0100 Subject: Render 404 when artifacts path is invalid --- lib/gitlab/ci/build/artifacts/metadata.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/ci/build/artifacts/metadata.rb b/lib/gitlab/ci/build/artifacts/metadata.rb index 5313182d55f..d5c3cd10e48 100644 --- a/lib/gitlab/ci/build/artifacts/metadata.rb +++ b/lib/gitlab/ci/build/artifacts/metadata.rb @@ -22,7 +22,7 @@ module Gitlab paths, metadata = [], [] each do |line| - next unless line =~ %r{^#{Regexp.escape(@path)}[^/\s]+/?\s} + next unless line =~ %r{^#{Regexp.escape(@path)}[^/\s]*/?\s} path, meta = line.split(' ') paths.push(path) -- cgit v1.2.1 From cd3b8bbd2f8e7ad75a453441f83c46aeb1d37353 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Mon, 4 Jan 2016 14:18:06 +0100 Subject: Add method that checks if path exists in `StringPath` --- lib/gitlab/string_path.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib') diff --git a/lib/gitlab/string_path.rb b/lib/gitlab/string_path.rb index 4d024b3ff73..a6234d34e7d 100644 --- a/lib/gitlab/string_path.rb +++ b/lib/gitlab/string_path.rb @@ -19,6 +19,10 @@ module Gitlab @path end + def exists? + @path == './' || @universe.include?(@path) + end + def absolute? @path.start_with?('/') end -- cgit v1.2.1 From 1b1793c2530d7003d8baa5aa1912a4ab258d4a1c Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Mon, 4 Jan 2016 15:07:49 +0100 Subject: Show file size in artifacts browser using metadata --- lib/gitlab/ci/build/artifacts/metadata.rb | 5 ++--- lib/gitlab/string_path.rb | 12 ++++++------ 2 files changed, 8 insertions(+), 9 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/ci/build/artifacts/metadata.rb b/lib/gitlab/ci/build/artifacts/metadata.rb index d5c3cd10e48..1f3000e7c8a 100644 --- a/lib/gitlab/ci/build/artifacts/metadata.rb +++ b/lib/gitlab/ci/build/artifacts/metadata.rb @@ -23,13 +23,12 @@ module Gitlab each do |line| next unless line =~ %r{^#{Regexp.escape(@path)}[^/\s]*/?\s} - path, meta = line.split(' ') paths.push(path) metadata.push(meta) - end + end - [paths, metadata.map { |meta| JSON.parse(meta) }] + [paths, metadata.map { |meta| JSON.parse(meta, symbolize_names: true) }] end def to_string_path diff --git a/lib/gitlab/string_path.rb b/lib/gitlab/string_path.rb index a6234d34e7d..774d4244a2a 100644 --- a/lib/gitlab/string_path.rb +++ b/lib/gitlab/string_path.rb @@ -19,10 +19,6 @@ module Gitlab @path end - def exists? - @path == './' || @universe.include?(@path) - end - def absolute? @path.start_with?('/') end @@ -94,13 +90,17 @@ module Gitlab def metadata index = @universe.index(@path) - @metadata[index] + @metadata[index] || {} end def nodes @path.count('/') + (file? ? 1 : 0) end + def exists? + @path == './' || @universe.include?(@path) + end + def ==(other) @path == other.path && @universe == other.universe end @@ -112,7 +112,7 @@ module Gitlab private def new(path) - self.class.new(path, @universe) + self.class.new(path, @universe, @metadata) end def select -- cgit v1.2.1 From 387b27813d1d496c015f4f174812b4761c32648d Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 8 Jan 2016 12:35:49 +0100 Subject: Change format of artifacts metadata from text to binary 0.0.1 This changes the format of metadata to handle paths, that may contain whitespace characters, new line characters and non-UTF-8 characters. Now those paths along with metadata in JSON format are stored as length-prefixed strings (uint32 prefix). Metadata file has a custom format: 1. First string field is metadata version field (string) 2. Second string field is metadata errors field (JSON strong) 3. All subsequent fields is pair of path (string) and path metadata in JSON format. Path's metadata contains all fields that where possible to extract from ZIP archive like date of modification, CRC, compressed size, uncompressed size and comment. --- lib/gitlab/ci/build/artifacts/metadata.rb | 68 ++++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/ci/build/artifacts/metadata.rb b/lib/gitlab/ci/build/artifacts/metadata.rb index 1f3000e7c8a..d90a64fdbb8 100644 --- a/lib/gitlab/ci/build/artifacts/metadata.rb +++ b/lib/gitlab/ci/build/artifacts/metadata.rb @@ -17,18 +17,33 @@ module Gitlab File.exists?(@file) end + def full_version + gzip do|gz| + read_string(gz) do |size| + raise StandardError, 'Artifacts metadata file empty!' unless size + end + end + end + + def version + full_version.match(/\w+ (\d+\.\d+\.\d+)/).captures.first + end + + def errors + gzip do|gz| + read_string(gz) # version + JSON.parse(read_string(gz)) + end + end + def match! raise StandardError, 'Metadata file not found !' unless exists? - paths, metadata = [], [] - each do |line| - next unless line =~ %r{^#{Regexp.escape(@path)}[^/\s]*/?\s} - path, meta = line.split(' ') - paths.push(path) - metadata.push(meta) + gzip do |gz| + read_string(gz) # version field + read_string(gz) # errors field + iterate_entries(gz) end - - [paths, metadata.map { |meta| JSON.parse(meta, symbolize_names: true) }] end def to_string_path @@ -38,11 +53,44 @@ module Gitlab private - def each + def iterate_entries(gz) + paths, metadata = [], [] + + until gz.eof? do + begin + path = read_string(gz) + meta = read_string(gz) + + next unless path =~ %r{^#{Regexp.escape(@path)}[^/\s]*/?$} + + paths.push(path) + metadata.push(JSON.parse(meta, symbolize_names: true)) + rescue JSON::ParserError + next + end + end + + [paths, metadata] + end + + def read_string_size(gz) + binary = gz.read(4) + binary.unpack('L>')[0] if binary + end + + def read_string(gz) + string_size = read_string_size(gz) + yield string_size if block_given? + return false unless string_size + gz.read(string_size).chomp + end + + def gzip open do |file| gzip = Zlib::GzipReader.new(file) - gzip.each_line { |line| yield line } + result = yield gzip gzip.close + result end end -- cgit v1.2.1 From 61fb47a43202332fe9ac57847996da929ba42d3f Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Sat, 9 Jan 2016 14:41:43 +0100 Subject: Simplify implementation of build artifacts browser (refactoring) --- lib/gitlab/ci/build/artifacts/metadata.rb | 74 ++++++------- lib/gitlab/ci/build/artifacts/metadata/path.rb | 114 ++++++++++++++++++++ lib/gitlab/string_path.rb | 139 ------------------------- 3 files changed, 153 insertions(+), 174 deletions(-) create mode 100644 lib/gitlab/ci/build/artifacts/metadata/path.rb delete mode 100644 lib/gitlab/string_path.rb (limited to 'lib') diff --git a/lib/gitlab/ci/build/artifacts/metadata.rb b/lib/gitlab/ci/build/artifacts/metadata.rb index d90a64fdbb8..996b5d91ff2 100644 --- a/lib/gitlab/ci/build/artifacts/metadata.rb +++ b/lib/gitlab/ci/build/artifacts/metadata.rb @@ -6,65 +6,54 @@ module Gitlab module Build module Artifacts class Metadata - def initialize(file, path) - @file = file - - @path = path.sub(/^\.\//, '') - @path << '/' unless path.end_with?('/') - end + VERSION_PATTERN = '[\w\s]+(\d+\.\d+\.\d+)' + attr_reader :file, :path, :full_version - def exists? - File.exists?(@file) - end - - def full_version - gzip do|gz| - read_string(gz) do |size| - raise StandardError, 'Artifacts metadata file empty!' unless size - end - end + def initialize(file, path) + @file, @path = file, path + @full_version = read_version + @path << '/' unless path.end_with?('/') || path.empty? end def version - full_version.match(/\w+ (\d+\.\d+\.\d+)/).captures.first + @full_version.match(/#{VERSION_PATTERN}/).captures.first end def errors gzip do|gz| read_string(gz) # version - JSON.parse(read_string(gz)) + errors = read_string(gz) + raise StandardError, 'Errors field not found!' unless errors + JSON.parse(errors) end end def match! - raise StandardError, 'Metadata file not found !' unless exists? - gzip do |gz| - read_string(gz) # version field - read_string(gz) # errors field - iterate_entries(gz) + 2.times { read_string(gz) } # version and errors fields + match_entries(gz) end end - def to_string_path - universe, metadata = match! - ::Gitlab::StringPath.new(@path, universe, metadata) + def to_path + Path.new(@path, *match!) end private - def iterate_entries(gz) + def match_entries(gz) paths, metadata = [], [] - + child_pattern = %r{^#{Regexp.escape(@path)}[^/\s]*/?$} + until gz.eof? do begin path = read_string(gz) meta = read_string(gz) - next unless path =~ %r{^#{Regexp.escape(@path)}[^/\s]*/?$} - + next unless path =~ child_pattern + paths.push(path) - metadata.push(JSON.parse(meta, symbolize_names: true)) + metadata.push(JSON.parse(meta.chomp, symbolize_names: true)) rescue JSON::ParserError next end @@ -73,16 +62,31 @@ module Gitlab [paths, metadata] end - def read_string_size(gz) + def read_version + gzip do|gz| + version_string = read_string(gz) + + unless version_string + raise StandardError, 'Artifacts metadata file empty!' + end + + unless version_string =~ /^#{VERSION_PATTERN}/ + raise StandardError, 'Invalid version!' + end + + version_string.chomp + end + end + + def read_uint32(gz) binary = gz.read(4) binary.unpack('L>')[0] if binary end def read_string(gz) - string_size = read_string_size(gz) - yield string_size if block_given? + string_size = read_uint32(gz) return false unless string_size - gz.read(string_size).chomp + gz.read(string_size) end def gzip diff --git a/lib/gitlab/ci/build/artifacts/metadata/path.rb b/lib/gitlab/ci/build/artifacts/metadata/path.rb new file mode 100644 index 00000000000..222903b348e --- /dev/null +++ b/lib/gitlab/ci/build/artifacts/metadata/path.rb @@ -0,0 +1,114 @@ +module Gitlab + module Ci::Build::Artifacts + class Metadata + ## + # Class that represents a simplified path to a file or + # directory in GitLab CI Build Artifacts binary file / archive + # + # This is IO-operations safe class, that does similar job to + # Ruby's Pathname but without the risk of accessing filesystem. + # + class Path + attr_reader :path, :universe + attr_accessor :name + + def initialize(path, universe, metadata = []) + @path = path + @universe = universe + @metadata = metadata + + if path.include?("\0") + raise ArgumentError, 'Path contains zero byte character!' + end + end + + def directory? + @path.end_with?('/') || @path.blank? + end + + def file? + !directory? + end + + def has_parent? + nodes > 0 + end + + def parent + return nil unless has_parent? + new(@path.chomp(basename)) + end + + def basename + directory? ? name + ::File::SEPARATOR : name + end + + def name + @name || @path.split(::File::SEPARATOR).last + end + + def children + return [] unless directory? + return @children if @children + + child_pattern = %r{^#{Regexp.escape(@path)}[^/\s]+/?$} + @children = select { |entry| entry =~ child_pattern } + end + + def directories + return [] unless directory? + children.select(&:directory?) + end + + def directories! + return directories unless has_parent? + + dotted_parent = parent + dotted_parent.name = '..' + directories.prepend(dotted_parent) + end + + def files + return [] unless directory? + children.select(&:file?) + end + + def metadata + @index ||= @universe.index(@path) + @metadata[@index] || {} + end + + def nodes + @path.count('/') + (file? ? 1 : 0) + end + + def exists? + @path.blank? || @universe.include?(@path) + end + + def to_s + @path + end + + def ==(other) + @path == other.path && @universe == other.universe + end + + def inspect + "#{self.class.name}: #{@path}" + end + + private + + def new(path) + self.class.new(path, @universe, @metadata) + end + + def select + selected = @universe.select { |entry| yield entry } + selected.map { |path| new(path) } + end + end + end + end +end diff --git a/lib/gitlab/string_path.rb b/lib/gitlab/string_path.rb deleted file mode 100644 index 774d4244a2a..00000000000 --- a/lib/gitlab/string_path.rb +++ /dev/null @@ -1,139 +0,0 @@ -module Gitlab - ## - # Class that represents a simplified path to a file or directory - # - # This is IO-operations safe class, that does similar job to - # Ruby's Pathname but without the risk of accessing filesystem. - # - class StringPath - attr_reader :path, :universe - attr_accessor :name - - def initialize(path, universe, metadata = []) - @path = sanitize(path) - @universe = universe.map { |entry| sanitize(entry) } - @metadata = metadata - end - - def to_s - @path - end - - def absolute? - @path.start_with?('/') - end - - def relative? - !absolute? - end - - def directory? - @path.end_with?('/') - end - - def file? - !directory? - end - - def has_parent? - nodes > 1 - end - - def parent - return nil unless has_parent? - new(@path.sub(basename, '')) - end - - def basename - directory? ? name + ::File::SEPARATOR : name - end - - def name - @name || @path.split(::File::SEPARATOR).last - end - - def has_descendants? - descendants.any? - end - - def descendants - return [] unless directory? - select { |entry| entry =~ /^#{Regexp.escape(@path)}.+/ } - end - - def children - return [] unless directory? - return @children if @children - - @children = select do |entry| - entry =~ %r{^#{Regexp.escape(@path)}[^/\s]+/?$} - end - end - - def directories - return [] unless directory? - children.select(&:directory?) - end - - def directories! - return directories unless has_parent? && directory? - - dotted_parent = parent - dotted_parent.name = '..' - directories.prepend(dotted_parent) - end - - def files - return [] unless directory? - children.select(&:file?) - end - - def metadata - index = @universe.index(@path) - @metadata[index] || {} - end - - def nodes - @path.count('/') + (file? ? 1 : 0) - end - - def exists? - @path == './' || @universe.include?(@path) - end - - def ==(other) - @path == other.path && @universe == other.universe - end - - def inspect - "#{self.class.name}: #{@path}" - end - - private - - def new(path) - self.class.new(path, @universe, @metadata) - end - - def select - selected = @universe.select { |entry| yield entry } - selected.map { |path| new(path) } - end - - def sanitize(path) - self.class.sanitize(path) - end - - def self.sanitize(path) - # It looks like Pathname#new doesn't touch a file system, - # neither Pathname#cleanpath does, so it is, hopefully, filesystem safe - - clean_path = Pathname.new(path).cleanpath.to_s - raise ArgumentError, 'Invalid path' if clean_path.start_with?('../') - - prefix = './' unless clean_path =~ %r{^[\.|/]} - suffix = '/' if path.end_with?('/') || ['.', '..'].include?(clean_path) - prefix.to_s + clean_path + suffix.to_s - end - end -end -- cgit v1.2.1 From 09a4a5aff8c53dd5930044ddbb285a95ef177d8a Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Mon, 11 Jan 2016 09:57:03 +0100 Subject: Render only valid paths in artifacts metadata In this version we will support only relative paths in artifacts metadata. Support for absolute paths will be introduced later. --- lib/gitlab/ci/build/artifacts/metadata.rb | 10 +++++++--- lib/gitlab/ci/build/artifacts/metadata/path.rb | 12 ++++++++---- 2 files changed, 15 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/ci/build/artifacts/metadata.rb b/lib/gitlab/ci/build/artifacts/metadata.rb index 996b5d91ff2..91017f633a0 100644 --- a/lib/gitlab/ci/build/artifacts/metadata.rb +++ b/lib/gitlab/ci/build/artifacts/metadata.rb @@ -12,7 +12,6 @@ module Gitlab def initialize(file, path) @file, @path = file, path @full_version = read_version - @path << '/' unless path.end_with?('/') || path.empty? end def version @@ -43,14 +42,15 @@ module Gitlab def match_entries(gz) paths, metadata = [], [] - child_pattern = %r{^#{Regexp.escape(@path)}[^/\s]*/?$} + match_pattern = %r{^#{Regexp.escape(@path)}[^/\s]*/?$} until gz.eof? do begin path = read_string(gz) meta = read_string(gz) - next unless path =~ child_pattern + next unless path =~ match_pattern + next unless path_valid?(path) paths.push(path) metadata.push(JSON.parse(meta.chomp, symbolize_names: true)) @@ -62,6 +62,10 @@ module Gitlab [paths, metadata] end + def path_valid?(path) + !(path.start_with?('/') || path =~ %r{\.?\./}) + end + def read_version gzip do|gz| version_string = read_string(gz) diff --git a/lib/gitlab/ci/build/artifacts/metadata/path.rb b/lib/gitlab/ci/build/artifacts/metadata/path.rb index 222903b348e..80ead335d57 100644 --- a/lib/gitlab/ci/build/artifacts/metadata/path.rb +++ b/lib/gitlab/ci/build/artifacts/metadata/path.rb @@ -23,7 +23,7 @@ module Gitlab end def directory? - @path.end_with?('/') || @path.blank? + blank_node? || @path.end_with?('/') end def file? @@ -40,11 +40,11 @@ module Gitlab end def basename - directory? ? name + ::File::SEPARATOR : name + (directory? && !blank_node?) ? name + ::File::SEPARATOR : name end def name - @name || @path.split(::File::SEPARATOR).last + @name || @path.split(::File::SEPARATOR).last.to_s end def children @@ -83,7 +83,11 @@ module Gitlab end def exists? - @path.blank? || @universe.include?(@path) + blank_node? || @universe.include?(@path) + end + + def blank_node? + @path.empty? # "" is considered to be './' end def to_s -- cgit v1.2.1 From ffee05c242c87e004054b48747287c3160d1c19a Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Mon, 11 Jan 2016 12:50:21 +0100 Subject: Improve invalid build artifacts metadata path matcher --- lib/gitlab/ci/build/artifacts/metadata.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/ci/build/artifacts/metadata.rb b/lib/gitlab/ci/build/artifacts/metadata.rb index 91017f633a0..2b17712cdbe 100644 --- a/lib/gitlab/ci/build/artifacts/metadata.rb +++ b/lib/gitlab/ci/build/artifacts/metadata.rb @@ -43,6 +43,7 @@ module Gitlab def match_entries(gz) paths, metadata = [], [] match_pattern = %r{^#{Regexp.escape(@path)}[^/\s]*/?$} + invalid_pattern = %r{(^\.?\.?/)|(/\.?\.?/)} until gz.eof? do begin @@ -50,7 +51,7 @@ module Gitlab meta = read_string(gz) next unless path =~ match_pattern - next unless path_valid?(path) + next if path =~ invalid_pattern paths.push(path) metadata.push(JSON.parse(meta.chomp, symbolize_names: true)) @@ -62,10 +63,6 @@ module Gitlab [paths, metadata] end - def path_valid?(path) - !(path.start_with?('/') || path =~ %r{\.?\./}) - end - def read_version gzip do|gz| version_string = read_string(gz) -- cgit v1.2.1 From 2be76355caa579d444c8e3c0d25563eb9778bfb2 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 12 Jan 2016 10:04:26 +0100 Subject: Support only valid UTF-8 paths in build artifacts browser --- lib/gitlab/ci/build/artifacts/metadata.rb | 8 +++++--- lib/gitlab/ci/build/artifacts/metadata/path.rb | 10 ++++++++-- 2 files changed, 13 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/ci/build/artifacts/metadata.rb b/lib/gitlab/ci/build/artifacts/metadata.rb index 2b17712cdbe..d9c051be9f3 100644 --- a/lib/gitlab/ci/build/artifacts/metadata.rb +++ b/lib/gitlab/ci/build/artifacts/metadata.rb @@ -10,7 +10,8 @@ module Gitlab attr_reader :file, :path, :full_version def initialize(file, path) - @file, @path = file, path + @file = file + @path = path.force_encoding('ASCII-8BIT') @full_version = read_version end @@ -42,7 +43,7 @@ module Gitlab def match_entries(gz) paths, metadata = [], [] - match_pattern = %r{^#{Regexp.escape(@path)}[^/\s]*/?$} + match_pattern = %r{^#{Regexp.escape(@path)}[^/]*/?$} invalid_pattern = %r{(^\.?\.?/)|(/\.?\.?/)} until gz.eof? do @@ -51,11 +52,12 @@ module Gitlab meta = read_string(gz) next unless path =~ match_pattern + next unless path.force_encoding('UTF-8').valid_encoding? next if path =~ invalid_pattern paths.push(path) metadata.push(JSON.parse(meta.chomp, symbolize_names: true)) - rescue JSON::ParserError + rescue JSON::ParserError, Encoding::CompatibilityError next end end diff --git a/lib/gitlab/ci/build/artifacts/metadata/path.rb b/lib/gitlab/ci/build/artifacts/metadata/path.rb index 80ead335d57..6896aa936d5 100644 --- a/lib/gitlab/ci/build/artifacts/metadata/path.rb +++ b/lib/gitlab/ci/build/artifacts/metadata/path.rb @@ -8,18 +8,24 @@ module Gitlab # This is IO-operations safe class, that does similar job to # Ruby's Pathname but without the risk of accessing filesystem. # + # This class is working only with UTF-8 encoded paths. + # class Path attr_reader :path, :universe attr_accessor :name def initialize(path, universe, metadata = []) - @path = path + @path = path.force_encoding('UTF-8') @universe = universe @metadata = metadata if path.include?("\0") raise ArgumentError, 'Path contains zero byte character!' end + + unless path.valid_encoding? + raise ArgumentError, 'Path contains non-UTF-8 byte sequence!' + end end def directory? @@ -51,7 +57,7 @@ module Gitlab return [] unless directory? return @children if @children - child_pattern = %r{^#{Regexp.escape(@path)}[^/\s]+/?$} + child_pattern = %r{^#{Regexp.escape(@path)}[^/]+/?$} @children = select { |entry| entry =~ child_pattern } end -- cgit v1.2.1 From 487b0a026f9efe2d8214c19a7b95b391708ba3f4 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 12 Jan 2016 11:02:15 +0100 Subject: Improvements, readability for artifacts browser --- lib/gitlab/ci/build/artifacts/metadata.rb | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/ci/build/artifacts/metadata.rb b/lib/gitlab/ci/build/artifacts/metadata.rb index d9c051be9f3..47efc51a76e 100644 --- a/lib/gitlab/ci/build/artifacts/metadata.rb +++ b/lib/gitlab/ci/build/artifacts/metadata.rb @@ -56,7 +56,7 @@ module Gitlab next if path =~ invalid_pattern paths.push(path) - metadata.push(JSON.parse(meta.chomp, symbolize_names: true)) + metadata.push(JSON.parse(meta, symbolize_names: true)) rescue JSON::ParserError, Encoding::CompatibilityError next end @@ -66,7 +66,7 @@ module Gitlab end def read_version - gzip do|gz| + gzip do |gz| version_string = read_string(gz) unless version_string @@ -95,9 +95,11 @@ module Gitlab def gzip open do |file| gzip = Zlib::GzipReader.new(file) - result = yield gzip - gzip.close - result + begin + yield gzip + ensure + gzip.close + end end end -- cgit v1.2.1 From e8995f9fd5c12882eafcf3766627f64a3d6f623d Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 12 Jan 2016 14:39:15 +0100 Subject: Modify artifacts upload API endpoint, add artifacts metadata --- lib/ci/api/builds.rb | 20 ++++++++++++++++---- lib/ci/api/entities.rb | 1 + 2 files changed, 17 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/ci/api/builds.rb b/lib/ci/api/builds.rb index 15faa6edd84..2aaa06a022c 100644 --- a/lib/ci/api/builds.rb +++ b/lib/ci/api/builds.rb @@ -78,11 +78,15 @@ module Ci # Parameters: # id (required) - The ID of a build # token (required) - The build authorization token - # file (required) - The uploaded file + # file (required) - Artifacts file + # metadata (optional) - Artifacts metadata file # Parameters (accelerated by GitLab Workhorse): # file.path - path to locally stored body (generated by Workhorse) # file.name - real filename as send in Content-Disposition # file.type - real content type as send in Content-Type + # metadata.path - path to locally stored body (generated by Workhorse) + # metadata.name - real filename as send in Content-Disposition + # metadata.type - real content type as send in Content-Type # Headers: # BUILD-TOKEN (required) - The build authorization token, the same as token # Body: @@ -98,10 +102,17 @@ module Ci authenticate_build_token!(build) forbidden!('build is not running') unless build.running? - file = uploaded_file!(:file, ArtifactUploader.artifacts_upload_path) - file_to_large! unless file.size < max_artifacts_size + artifacts_upload_path = ArtifactUploader.artifacts_upload_path + artifacts = uploaded_file!(:file, artifacts_upload_path) + file_to_large! unless artifacts.size < max_artifacts_size + artifacts_attributes = { artifacts_file: artifacts } - if build.update_attributes(artifacts_file: file) + if params[:metadata] || params['metadata.path'.to_sym] + metadata = uploaded_file!(:metadata, artifacts_upload_path) + artifacts_attributes.store(:artifacts_metadata, metadata) + end + + if build.update_attributes(artifacts_attributes) present build, with: Entities::Build else render_validation_error!(build) @@ -148,6 +159,7 @@ module Ci not_found! unless build authenticate_build_token!(build) build.remove_artifacts_file! + build.remove_artifacts_metadata! end end end diff --git a/lib/ci/api/entities.rb b/lib/ci/api/entities.rb index e4ac0545ea2..dd34c661e25 100644 --- a/lib/ci/api/entities.rb +++ b/lib/ci/api/entities.rb @@ -31,6 +31,7 @@ module Ci expose :variables expose :artifacts_file, using: ArtifactFile + expose :artifacts_metadata, using: ArtifactFile end class Runner < Grape::Entity -- cgit v1.2.1 From 0b946029a1fb429db39fbec0cddccf40f7e2aa08 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 13 Jan 2016 09:56:05 +0100 Subject: Update build artifacts API We do not want to allow runners to upload a metadata file. This needs to be generated by Workhorse only. --- lib/ci/api/builds.rb | 17 ++++++++--------- lib/ci/api/entities.rb | 1 - 2 files changed, 8 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/ci/api/builds.rb b/lib/ci/api/builds.rb index 2aaa06a022c..be2790571cb 100644 --- a/lib/ci/api/builds.rb +++ b/lib/ci/api/builds.rb @@ -79,14 +79,13 @@ module Ci # id (required) - The ID of a build # token (required) - The build authorization token # file (required) - Artifacts file - # metadata (optional) - Artifacts metadata file # Parameters (accelerated by GitLab Workhorse): # file.path - path to locally stored body (generated by Workhorse) # file.name - real filename as send in Content-Disposition # file.type - real content type as send in Content-Type # metadata.path - path to locally stored body (generated by Workhorse) - # metadata.name - real filename as send in Content-Disposition - # metadata.type - real content type as send in Content-Type + # metadata.name - filename (generated by Workhorse) + # metadata.type - content type (returned by Workhorse) # Headers: # BUILD-TOKEN (required) - The build authorization token, the same as token # Body: @@ -101,19 +100,19 @@ module Ci not_found! unless build authenticate_build_token!(build) forbidden!('build is not running') unless build.running? + forbidden!('metadata reserved for workhorse') if params[:metadata] artifacts_upload_path = ArtifactUploader.artifacts_upload_path artifacts = uploaded_file!(:file, artifacts_upload_path) file_to_large! unless artifacts.size < max_artifacts_size - artifacts_attributes = { artifacts_file: artifacts } + build.artifacts_file = artifacts - if params[:metadata] || params['metadata.path'.to_sym] - metadata = uploaded_file!(:metadata, artifacts_upload_path) - artifacts_attributes.store(:artifacts_metadata, metadata) + if params[:'metadata.path'] && params[:'metadata.name'] + build.artifacts_metadata = uploaded_file!(:metadata, artifacts_upload_path) end - if build.update_attributes(artifacts_attributes) - present build, with: Entities::Build + if build.save + present(build, with: Entities::Build) else render_validation_error!(build) end diff --git a/lib/ci/api/entities.rb b/lib/ci/api/entities.rb index dd34c661e25..e4ac0545ea2 100644 --- a/lib/ci/api/entities.rb +++ b/lib/ci/api/entities.rb @@ -31,7 +31,6 @@ module Ci expose :variables expose :artifacts_file, using: ArtifactFile - expose :artifacts_metadata, using: ArtifactFile end class Runner < Grape::Entity -- cgit v1.2.1 From a9783c439bd6e3322b6fc72371c9fe3837a63be5 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 13 Jan 2016 10:13:39 +0100 Subject: Make encoding of paths returned by metadata consistent (UTF-8) --- lib/gitlab/ci/build/artifacts/metadata.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/ci/build/artifacts/metadata.rb b/lib/gitlab/ci/build/artifacts/metadata.rb index 47efc51a76e..0c252c0bf30 100644 --- a/lib/gitlab/ci/build/artifacts/metadata.rb +++ b/lib/gitlab/ci/build/artifacts/metadata.rb @@ -20,7 +20,7 @@ module Gitlab end def errors - gzip do|gz| + gzip do |gz| read_string(gz) # version errors = read_string(gz) raise StandardError, 'Errors field not found!' unless errors @@ -36,7 +36,7 @@ module Gitlab end def to_path - Path.new(@path, *match!) + Path.new(@path.dup.force_encoding('UTF-8'), *match!) end private @@ -88,7 +88,7 @@ module Gitlab def read_string(gz) string_size = read_uint32(gz) - return false unless string_size + return nil unless string_size gz.read(string_size) end -- cgit v1.2.1 From 3f0c18f80e36561581ef6fa6dbfcec169e1a6e08 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 13 Jan 2016 13:45:28 +0100 Subject: Simplify encoding related implementation in artifacts metadata --- lib/gitlab/ci/build/artifacts/metadata.rb | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/ci/build/artifacts/metadata.rb b/lib/gitlab/ci/build/artifacts/metadata.rb index 0c252c0bf30..e9ec8f1302c 100644 --- a/lib/gitlab/ci/build/artifacts/metadata.rb +++ b/lib/gitlab/ci/build/artifacts/metadata.rb @@ -10,8 +10,7 @@ module Gitlab attr_reader :file, :path, :full_version def initialize(file, path) - @file = file - @path = path.force_encoding('ASCII-8BIT') + @file, @path = file, path @full_version = read_version end @@ -36,7 +35,7 @@ module Gitlab end def to_path - Path.new(@path.dup.force_encoding('UTF-8'), *match!) + Path.new(@path, *match!) end private @@ -48,11 +47,11 @@ module Gitlab until gz.eof? do begin - path = read_string(gz) - meta = read_string(gz) + path = read_string(gz).force_encoding('UTF-8') + meta = read_string(gz).force_encoding('UTF-8') + next unless path.valid_encoding? && meta.valid_encoding? next unless path =~ match_pattern - next unless path.force_encoding('UTF-8').valid_encoding? next if path =~ invalid_pattern paths.push(path) -- cgit v1.2.1 From 154b8ceba4ac2d92a2387ad50d7f2b4ed5b2dd8a Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 13 Jan 2016 14:02:36 +0100 Subject: Refactor build artifacts upload API endpoint --- lib/api/helpers.rb | 4 +++- lib/ci/api/builds.rb | 15 +++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) (limited to 'lib') diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index a4df810e755..d46b5c42967 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -289,12 +289,14 @@ module API # file helpers - def uploaded_file!(field, uploads_path) + 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) diff --git a/lib/ci/api/builds.rb b/lib/ci/api/builds.rb index be2790571cb..fb87637b94f 100644 --- a/lib/ci/api/builds.rb +++ b/lib/ci/api/builds.rb @@ -85,7 +85,6 @@ module Ci # file.type - real content type as send in Content-Type # metadata.path - path to locally stored body (generated by Workhorse) # metadata.name - filename (generated by Workhorse) - # metadata.type - content type (returned by Workhorse) # Headers: # BUILD-TOKEN (required) - The build authorization token, the same as token # Body: @@ -99,17 +98,17 @@ module Ci build = Ci::Build.find_by_id(params[:id]) not_found! unless build authenticate_build_token!(build) - forbidden!('build is not running') unless build.running? - forbidden!('metadata reserved for workhorse') if params[:metadata] + forbidden!('Build is not running!') unless build.running? artifacts_upload_path = ArtifactUploader.artifacts_upload_path - artifacts = uploaded_file!(:file, artifacts_upload_path) + artifacts = uploaded_file(:file, artifacts_upload_path) + metadata = uploaded_file(:metadata, artifacts_upload_path) + + bad_request!('Missing artifacts file!') unless artifacts file_to_large! unless artifacts.size < max_artifacts_size - build.artifacts_file = artifacts - if params[:'metadata.path'] && params[:'metadata.name'] - build.artifacts_metadata = uploaded_file!(:metadata, artifacts_upload_path) - end + build.artifacts_file = artifacts + build.artifacts_metadata = metadata if build.save present(build, with: Entities::Build) -- cgit v1.2.1 From 6b0a43aff36f0bbb9050b3c04155a3ccd9c1a75b Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 13 Jan 2016 21:17:28 +0100 Subject: Improve readability of artifacts browser `Entry` related code --- lib/gitlab/ci/build/artifacts/metadata.rb | 5 +- lib/gitlab/ci/build/artifacts/metadata/entry.rb | 125 ++++++++++++++++++++++++ lib/gitlab/ci/build/artifacts/metadata/path.rb | 124 ----------------------- 3 files changed, 128 insertions(+), 126 deletions(-) create mode 100644 lib/gitlab/ci/build/artifacts/metadata/entry.rb delete mode 100644 lib/gitlab/ci/build/artifacts/metadata/path.rb (limited to 'lib') diff --git a/lib/gitlab/ci/build/artifacts/metadata.rb b/lib/gitlab/ci/build/artifacts/metadata.rb index e9ec8f1302c..bfdfc9a1d7d 100644 --- a/lib/gitlab/ci/build/artifacts/metadata.rb +++ b/lib/gitlab/ci/build/artifacts/metadata.rb @@ -34,8 +34,9 @@ module Gitlab end end - def to_path - Path.new(@path, *match!) + def to_entry + entires, metadata = match! + Entry.new(@path, entires, metadata) end private diff --git a/lib/gitlab/ci/build/artifacts/metadata/entry.rb b/lib/gitlab/ci/build/artifacts/metadata/entry.rb new file mode 100644 index 00000000000..2fb6c327729 --- /dev/null +++ b/lib/gitlab/ci/build/artifacts/metadata/entry.rb @@ -0,0 +1,125 @@ +module Gitlab + module Ci::Build::Artifacts + class Metadata + ## + # Class that represents an entry (path and metadata) to a file or + # directory in GitLab CI Build Artifacts binary file / archive + # + # This is IO-operations safe class, that does similar job to + # Ruby's Pathname but without the risk of accessing filesystem. + # + # This class is working only with UTF-8 encoded paths. + # + class Entry + attr_reader :path, :entires + attr_accessor :name + + def initialize(path, entires, metadata = []) + @path = path.force_encoding('UTF-8') + @entires = entires + @metadata = metadata + + if path.include?("\0") + raise ArgumentError, 'Path contains zero byte character!' + end + + unless path.valid_encoding? + raise ArgumentError, 'Path contains non-UTF-8 byte sequence!' + end + end + + def directory? + blank_node? || @path.end_with?('/') + end + + def file? + !directory? + end + + def has_parent? + nodes > 0 + end + + def parent + return nil unless has_parent? + new(@path.chomp(basename)) + end + + def basename + (directory? && !blank_node?) ? name + '/' : name + end + + def name + @name || @path.split('/').last.to_s + end + + def children + return [] unless directory? + return @children if @children + + child_pattern = %r{^#{Regexp.escape(@path)}[^/]+/?$} + @children = select_entires { |entry| entry =~ child_pattern } + end + + def directories(opts = {}) + return [] unless directory? + dirs = children.select(&:directory?) + return dirs unless has_parent? && opts[:parent] + + dotted_parent = parent + dotted_parent.name = '..' + dirs.prepend(dotted_parent) + end + + def files + return [] unless directory? + children.select(&:file?) + end + + def metadata + @index ||= @entires.index(@path) + @metadata[@index] || {} + end + + def nodes + @path.count('/') + (file? ? 1 : 0) + end + + def blank_node? + @path.empty? # "" is considered to be './' + end + + def exists? + blank_node? || @entires.include?(@path) + end + + def empty? + children.empty? + end + + def to_s + @path + end + + def ==(other) + @path == other.path && @entires == other.entires + end + + def inspect + "#{self.class.name}: #{@path}" + end + + private + + def new(path) + self.class.new(path, @entires, @metadata) + end + + def select_entires + selected = @entires.select { |entry| yield entry } + selected.map { |path| new(path) } + end + end + end + end +end diff --git a/lib/gitlab/ci/build/artifacts/metadata/path.rb b/lib/gitlab/ci/build/artifacts/metadata/path.rb deleted file mode 100644 index 6896aa936d5..00000000000 --- a/lib/gitlab/ci/build/artifacts/metadata/path.rb +++ /dev/null @@ -1,124 +0,0 @@ -module Gitlab - module Ci::Build::Artifacts - class Metadata - ## - # Class that represents a simplified path to a file or - # directory in GitLab CI Build Artifacts binary file / archive - # - # This is IO-operations safe class, that does similar job to - # Ruby's Pathname but without the risk of accessing filesystem. - # - # This class is working only with UTF-8 encoded paths. - # - class Path - attr_reader :path, :universe - attr_accessor :name - - def initialize(path, universe, metadata = []) - @path = path.force_encoding('UTF-8') - @universe = universe - @metadata = metadata - - if path.include?("\0") - raise ArgumentError, 'Path contains zero byte character!' - end - - unless path.valid_encoding? - raise ArgumentError, 'Path contains non-UTF-8 byte sequence!' - end - end - - def directory? - blank_node? || @path.end_with?('/') - end - - def file? - !directory? - end - - def has_parent? - nodes > 0 - end - - def parent - return nil unless has_parent? - new(@path.chomp(basename)) - end - - def basename - (directory? && !blank_node?) ? name + ::File::SEPARATOR : name - end - - def name - @name || @path.split(::File::SEPARATOR).last.to_s - end - - def children - return [] unless directory? - return @children if @children - - child_pattern = %r{^#{Regexp.escape(@path)}[^/]+/?$} - @children = select { |entry| entry =~ child_pattern } - end - - def directories - return [] unless directory? - children.select(&:directory?) - end - - def directories! - return directories unless has_parent? - - dotted_parent = parent - dotted_parent.name = '..' - directories.prepend(dotted_parent) - end - - def files - return [] unless directory? - children.select(&:file?) - end - - def metadata - @index ||= @universe.index(@path) - @metadata[@index] || {} - end - - def nodes - @path.count('/') + (file? ? 1 : 0) - end - - def exists? - blank_node? || @universe.include?(@path) - end - - def blank_node? - @path.empty? # "" is considered to be './' - end - - def to_s - @path - end - - def ==(other) - @path == other.path && @universe == other.universe - end - - def inspect - "#{self.class.name}: #{@path}" - end - - private - - def new(path) - self.class.new(path, @universe, @metadata) - end - - def select - selected = @universe.select { |entry| yield entry } - selected.map { |path| new(path) } - end - end - end - end -end -- cgit v1.2.1 From ad2b0358e0facd5c65c4141ce54c2e55bab165e6 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 13 Jan 2016 22:31:27 +0100 Subject: Improve readability of artifacts `Metadata` related code --- lib/gitlab/ci/build/artifacts/metadata.rb | 32 +++++++++---------------- lib/gitlab/ci/build/artifacts/metadata/entry.rb | 26 ++++++++++---------- 2 files changed, 24 insertions(+), 34 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/ci/build/artifacts/metadata.rb b/lib/gitlab/ci/build/artifacts/metadata.rb index bfdfc9a1d7d..94821c0eae0 100644 --- a/lib/gitlab/ci/build/artifacts/metadata.rb +++ b/lib/gitlab/ci/build/artifacts/metadata.rb @@ -6,7 +6,9 @@ module Gitlab module Build module Artifacts class Metadata - VERSION_PATTERN = '[\w\s]+(\d+\.\d+\.\d+)' + VERSION_PATTERN = /^[\w\s]+(\d+\.\d+\.\d+)/ + INVALID_PATH_PATTERN = %r{(^\.?\.?/)|(/\.?\.?/)} + attr_reader :file, :path, :full_version def initialize(file, path) @@ -15,7 +17,7 @@ module Gitlab end def version - @full_version.match(/#{VERSION_PATTERN}/).captures.first + @full_version.match(VERSION_PATTERN)[1] end def errors @@ -27,7 +29,7 @@ module Gitlab end end - def match! + def find_entries! gzip do |gz| 2.times { read_string(gz) } # version and errors fields match_entries(gz) @@ -35,8 +37,8 @@ module Gitlab end def to_entry - entires, metadata = match! - Entry.new(@path, entires, metadata) + entries, metadata = find_entries! + Entry.new(@path, entries, metadata) end private @@ -44,7 +46,6 @@ module Gitlab def match_entries(gz) paths, metadata = [], [] match_pattern = %r{^#{Regexp.escape(@path)}[^/]*/?$} - invalid_pattern = %r{(^\.?\.?/)|(/\.?\.?/)} until gz.eof? do begin @@ -53,7 +54,7 @@ module Gitlab next unless path.valid_encoding? && meta.valid_encoding? next unless path =~ match_pattern - next if path =~ invalid_pattern + next if path =~ INVALID_PATH_PATTERN paths.push(path) metadata.push(JSON.parse(meta, symbolize_names: true)) @@ -73,7 +74,7 @@ module Gitlab raise StandardError, 'Artifacts metadata file empty!' end - unless version_string =~ /^#{VERSION_PATTERN}/ + unless version_string =~ VERSION_PATTERN raise StandardError, 'Invalid version!' end @@ -92,19 +93,8 @@ module Gitlab gz.read(string_size) end - def gzip - open do |file| - gzip = Zlib::GzipReader.new(file) - begin - yield gzip - ensure - gzip.close - end - end - end - - def open - File.open(@file) { |file| yield file } + def gzip(&block) + Zlib::GzipReader.open(@file, &block) end end end diff --git a/lib/gitlab/ci/build/artifacts/metadata/entry.rb b/lib/gitlab/ci/build/artifacts/metadata/entry.rb index 2fb6c327729..12bb1bf0346 100644 --- a/lib/gitlab/ci/build/artifacts/metadata/entry.rb +++ b/lib/gitlab/ci/build/artifacts/metadata/entry.rb @@ -11,12 +11,12 @@ module Gitlab # This class is working only with UTF-8 encoded paths. # class Entry - attr_reader :path, :entires + attr_reader :path, :entries attr_accessor :name - def initialize(path, entires, metadata = []) + def initialize(path, entries, metadata = []) @path = path.force_encoding('UTF-8') - @entires = entires + @entries = entries @metadata = metadata if path.include?("\0") @@ -42,7 +42,7 @@ module Gitlab def parent return nil unless has_parent? - new(@path.chomp(basename)) + new_entry(@path.chomp(basename)) end def basename @@ -58,7 +58,7 @@ module Gitlab return @children if @children child_pattern = %r{^#{Regexp.escape(@path)}[^/]+/?$} - @children = select_entires { |entry| entry =~ child_pattern } + @children = select_entries { |entry| entry =~ child_pattern } end def directories(opts = {}) @@ -77,7 +77,7 @@ module Gitlab end def metadata - @index ||= @entires.index(@path) + @index ||= @entries.index(@path) @metadata[@index] || {} end @@ -90,7 +90,7 @@ module Gitlab end def exists? - blank_node? || @entires.include?(@path) + blank_node? || @entries.include?(@path) end def empty? @@ -102,7 +102,7 @@ module Gitlab end def ==(other) - @path == other.path && @entires == other.entires + @path == other.path && @entries == other.entries end def inspect @@ -111,13 +111,13 @@ module Gitlab private - def new(path) - self.class.new(path, @entires, @metadata) + def new_entry(path) + self.class.new(path, @entries, @metadata) end - def select_entires - selected = @entires.select { |entry| yield entry } - selected.map { |path| new(path) } + def select_entries + selected = @entries.select { |entry| yield entry } + selected.map { |path| new_entry(path) } end end end -- cgit v1.2.1 From 0d6e7b9d3d38e60e5a706956a853e7dc940e4574 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 13 Jan 2016 23:24:28 +0100 Subject: Use Hash to store paths and entries metadata in artifacts browser --- lib/gitlab/ci/build/artifacts/metadata.rb | 11 +++++------ lib/gitlab/ci/build/artifacts/metadata/entry.rb | 18 ++++++------------ 2 files changed, 11 insertions(+), 18 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/ci/build/artifacts/metadata.rb b/lib/gitlab/ci/build/artifacts/metadata.rb index 94821c0eae0..25ecf27d4e6 100644 --- a/lib/gitlab/ci/build/artifacts/metadata.rb +++ b/lib/gitlab/ci/build/artifacts/metadata.rb @@ -37,14 +37,14 @@ module Gitlab end def to_entry - entries, metadata = find_entries! - Entry.new(@path, entries, metadata) + entries = find_entries! + Entry.new(@path, entries) end private def match_entries(gz) - paths, metadata = [], [] + entries = {} match_pattern = %r{^#{Regexp.escape(@path)}[^/]*/?$} until gz.eof? do @@ -56,14 +56,13 @@ module Gitlab next unless path =~ match_pattern next if path =~ INVALID_PATH_PATTERN - paths.push(path) - metadata.push(JSON.parse(meta, symbolize_names: true)) + entries.store(path, JSON.parse(meta, symbolize_names: true)) rescue JSON::ParserError, Encoding::CompatibilityError next end end - [paths, metadata] + entries end def read_version diff --git a/lib/gitlab/ci/build/artifacts/metadata/entry.rb b/lib/gitlab/ci/build/artifacts/metadata/entry.rb index 12bb1bf0346..4dae02ce4f7 100644 --- a/lib/gitlab/ci/build/artifacts/metadata/entry.rb +++ b/lib/gitlab/ci/build/artifacts/metadata/entry.rb @@ -14,10 +14,9 @@ module Gitlab attr_reader :path, :entries attr_accessor :name - def initialize(path, entries, metadata = []) - @path = path.force_encoding('UTF-8') + def initialize(path, entries) + @path = path.dup.force_encoding('UTF-8') @entries = entries - @metadata = metadata if path.include?("\0") raise ArgumentError, 'Path contains zero byte character!' @@ -42,7 +41,7 @@ module Gitlab def parent return nil unless has_parent? - new_entry(@path.chomp(basename)) + self.class.new(@path.chomp(basename), @entries) end def basename @@ -77,8 +76,7 @@ module Gitlab end def metadata - @index ||= @entries.index(@path) - @metadata[@index] || {} + @entries[@path] || {} end def nodes @@ -111,13 +109,9 @@ module Gitlab private - def new_entry(path) - self.class.new(path, @entries, @metadata) - end - def select_entries - selected = @entries.select { |entry| yield entry } - selected.map { |path| new_entry(path) } + selected = @entries.select { |entry, _metadata| yield entry } + selected.map { |path, _metadata| self.class.new(path, @entries) } end end end -- cgit v1.2.1 From be764a3a20c7cecce2a047ddd46aff954c33b306 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 14 Jan 2016 12:12:05 +0100 Subject: Minor improvements in build arfifacts browser Added also a `Gitlab::Ci::Build::Artifacts::Metadata::ParserError` exception class. --- lib/gitlab/ci/build/artifacts/metadata.rb | 17 ++++++++++++----- lib/gitlab/ci/build/artifacts/metadata/entry.rb | 4 ++-- 2 files changed, 14 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/ci/build/artifacts/metadata.rb b/lib/gitlab/ci/build/artifacts/metadata.rb index 25ecf27d4e6..1344f5d120b 100644 --- a/lib/gitlab/ci/build/artifacts/metadata.rb +++ b/lib/gitlab/ci/build/artifacts/metadata.rb @@ -6,6 +6,8 @@ module Gitlab module Build module Artifacts class Metadata + class ParserError < StandardError; end + VERSION_PATTERN = /^[\w\s]+(\d+\.\d+\.\d+)/ INVALID_PATH_PATTERN = %r{(^\.?\.?/)|(/\.?\.?/)} @@ -24,8 +26,13 @@ module Gitlab gzip do |gz| read_string(gz) # version errors = read_string(gz) - raise StandardError, 'Errors field not found!' unless errors - JSON.parse(errors) + raise ParserError, 'Errors field not found!' unless errors + + begin + JSON.parse(errors) + rescue JSON::ParserError + raise ParserError, 'Invalid errors field!' + end end end @@ -56,7 +63,7 @@ module Gitlab next unless path =~ match_pattern next if path =~ INVALID_PATH_PATTERN - entries.store(path, JSON.parse(meta, symbolize_names: true)) + entries[path] = JSON.parse(meta, symbolize_names: true) rescue JSON::ParserError, Encoding::CompatibilityError next end @@ -70,11 +77,11 @@ module Gitlab version_string = read_string(gz) unless version_string - raise StandardError, 'Artifacts metadata file empty!' + raise ParserError, 'Artifacts metadata file empty!' end unless version_string =~ VERSION_PATTERN - raise StandardError, 'Invalid version!' + raise ParserError, 'Invalid version!' end version_string.chomp diff --git a/lib/gitlab/ci/build/artifacts/metadata/entry.rb b/lib/gitlab/ci/build/artifacts/metadata/entry.rb index 4dae02ce4f7..25b71fc3275 100644 --- a/lib/gitlab/ci/build/artifacts/metadata/entry.rb +++ b/lib/gitlab/ci/build/artifacts/metadata/entry.rb @@ -57,7 +57,7 @@ module Gitlab return @children if @children child_pattern = %r{^#{Regexp.escape(@path)}[^/]+/?$} - @children = select_entries { |entry| entry =~ child_pattern } + @children = select_entries { |path| path =~ child_pattern } end def directories(opts = {}) @@ -110,7 +110,7 @@ module Gitlab private def select_entries - selected = @entries.select { |entry, _metadata| yield entry } + selected = @entries.select { |path, _metadata| yield path } selected.map { |path, _metadata| self.class.new(path, @entries) } end end -- cgit v1.2.1 From 05187f0fc671e1ddcbe6d7b0f76971d792acaada Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 14 Jan 2016 13:09:36 +0100 Subject: Properly generate diff of orphan commits, like the first commit in a repository --- lib/gitlab/diff/parser.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/diff/parser.rb b/lib/gitlab/diff/parser.rb index 7015fe36c3d..516e59b87a3 100644 --- a/lib/gitlab/diff/parser.rb +++ b/lib/gitlab/diff/parser.rb @@ -56,8 +56,9 @@ module Gitlab private def filename?(line) - line.start_with?('--- /dev/null', '+++ /dev/null', '--- a', '+++ b', - '--- /tmp/diffy', '+++ /tmp/diffy') + line.start_with?( '--- /dev/null', '+++ /dev/null', '--- a', '+++ b', + '+++ a', # The line will start with `+++ a` in the reverse diff of an orphan commit + '--- /tmp/diffy', '+++ /tmp/diffy') end def identification_type(line) -- cgit v1.2.1 From c31d777c8f24029d7e11dd1e78eddf0c0b6e6f01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Thu, 14 Jan 2016 14:20:21 +0100 Subject: Revert changes to how the notes are paginated in the API --- lib/api/notes.rb | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/api/notes.rb b/lib/api/notes.rb index ebd9e97148c..174473f5371 100644 --- a/lib/api/notes.rb +++ b/lib/api/notes.rb @@ -22,11 +22,17 @@ module API @noteable = user_project.send(:"#{noteables_str}").find(params[:"#{noteable_id_str}"]) # We exclude notes that are cross-references and that cannot be viewed - # by the current user. + # 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 = - @noteable.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 paginate(Kaminari.paginate_array(notes)), with: Entities::Note + present notes, with: Entities::Note end # Get a single +noteable+ note -- cgit v1.2.1 From 2c7d9cfa7dbd4e7716793bdb1ee9e081f13c33b2 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Thu, 14 Jan 2016 14:59:04 +0100 Subject: Move Ci::Build#available_statuses to AVAILABLE_STATUSES constant in CommitStatus --- lib/api/builds.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/api/builds.rb b/lib/api/builds.rb index 1337e1bb452..d293f988165 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -125,7 +125,7 @@ module API def filter_builds(builds, scope) return builds if scope.nil? || scope.empty? - available_statuses = Ci::Build.available_statuses + available_statuses = ::CommitStatus::AVAILABLE_STATUSES scope = if scope.is_a?(String) [scope] -- cgit v1.2.1 From 78f5eb94fb15f7e4cc4208a4871b9533243bec40 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 6 Jan 2016 21:15:37 -0200 Subject: Import GitHub wiki into GitLab --- lib/gitlab/github_import/importer.rb | 13 +++++++++++++ lib/gitlab/github_import/project_creator.rb | 3 ++- lib/gitlab/github_import/wiki_formatter.rb | 19 +++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 lib/gitlab/github_import/wiki_formatter.rb (limited to 'lib') diff --git a/lib/gitlab/github_import/importer.rb b/lib/gitlab/github_import/importer.rb index 2b0afbc7b39..f75227b4734 100644 --- a/lib/gitlab/github_import/importer.rb +++ b/lib/gitlab/github_import/importer.rb @@ -1,6 +1,8 @@ module Gitlab module GithubImport class Importer + include Gitlab::ShellAdapter + attr_reader :project, :client def initialize(project) @@ -14,8 +16,11 @@ module Gitlab def execute import_issues import_pull_requests + import_wiki true + rescue Gitlab::Shell::Error + false end private @@ -66,6 +71,14 @@ module Gitlab noteable.notes.create!(comment.attributes) end end + + def import_wiki + unless project.wiki_enabled? + wiki = WikiFormatter.new(project) + gitlab_shell.import_repository(wiki.path_with_namespace, wiki.import_url) + project.update_attribute(:wiki_enabled, true) + end + end end end end diff --git a/lib/gitlab/github_import/project_creator.rb b/lib/gitlab/github_import/project_creator.rb index 8c27ebd1ce8..474927069a5 100644 --- a/lib/gitlab/github_import/project_creator.rb +++ b/lib/gitlab/github_import/project_creator.rb @@ -20,7 +20,8 @@ module Gitlab visibility_level: repo.private ? Gitlab::VisibilityLevel::PRIVATE : Gitlab::VisibilityLevel::PUBLIC, import_type: "github", import_source: repo.full_name, - import_url: repo.clone_url.sub("https://", "https://#{@session_data[:github_access_token]}@") + import_url: repo.clone_url.sub("https://", "https://#{@session_data[:github_access_token]}@"), + wiki_enabled: !repo.has_wiki? # If repo has wiki we'll import it later ).execute project.create_import_data(data: { "github_session" => session_data } ) diff --git a/lib/gitlab/github_import/wiki_formatter.rb b/lib/gitlab/github_import/wiki_formatter.rb new file mode 100644 index 00000000000..6dd2b917c4a --- /dev/null +++ b/lib/gitlab/github_import/wiki_formatter.rb @@ -0,0 +1,19 @@ +module Gitlab + module GithubImport + class WikiFormatter + attr_reader :project + + def initialize(project) + @project = project + end + + def path_with_namespace + "#{project.path_with_namespace}.wiki" + end + + def import_url + project.import_url.sub(".git", ".wiki.git") + end + end + end +end -- cgit v1.2.1 From a6a5990ee5f504107944c3bba5c18dbdea9f5207 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 12 Jan 2016 02:05:18 -0200 Subject: Add Banzai::Filter::GollumTagsFilter for parsing Gollum's tags in HTML --- lib/banzai/filter/gollum_tags_filter.rb | 106 ++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 lib/banzai/filter/gollum_tags_filter.rb (limited to 'lib') diff --git a/lib/banzai/filter/gollum_tags_filter.rb b/lib/banzai/filter/gollum_tags_filter.rb new file mode 100644 index 00000000000..f78b30bd4e9 --- /dev/null +++ b/lib/banzai/filter/gollum_tags_filter.rb @@ -0,0 +1,106 @@ +require 'banzai' +require 'html/pipeline/filter' + +module Banzai + module Filter + # HTML Filter for parsing Gollum's tags in HTML. + # + # Based on Gollum::Filter::Tags + # + # Context options: + # :project_wiki (required) - Current project wiki. + # + class GollumTagsFilter < HTML::Pipeline::Filter + include ActionView::Helpers::TagHelper + + # Pattern to match tag contents. + TAGS_PATTERN = %r{(.?)\[\[(.+?)\]\]([^\[]?)} + + def call + search_text_nodes(doc).each do |node| + content = node.content + + next unless content.match(TAGS_PATTERN) + + html = process_tag($2) + + node.replace(html) if html != node.content + end + + doc + end + + private + + # Process a single tag into its final HTML form. + # + # tag - The String tag contents (the stuff inside the double brackets). + # + # Returns the String HTML version of the tag. + def process_tag(tag) + if html = process_image_tag(tag) + html + else + process_page_link_tag(tag) + end + end + + # Attempt to process the tag as an image tag. + # + # tag - The String tag contents (the stuff inside the double brackets). + # + # Returns the String HTML if the tag is a valid image tag or nil + # if it is not. + def process_image_tag(tag) + parts = tag.split('|') + return if parts.size.zero? + + name = parts[0].strip + + if file = project_wiki.find_file(name) + path = ::File.join project_wiki_base_path, file.path + elsif name =~ /^https?:\/\/.+(jpg|png|gif|svg|bmp)$/i + path = name + end + + if path + content_tag(:img, nil, src: path) + end + end + + # Attempt to process the tag as a page link tag. + # + # tag - The String tag contents (the stuff inside the double brackets). + # + # Returns the String HTML if the tag is a valid page link tag or nil + # if it is not. + def process_page_link_tag(tag) + parts = tag.split('|') + return if parts.size.zero? + + if parts.size == 1 + url = parts[0].strip + else + name, url = *parts.compact.map(&:strip) + end + + content_tag(:a, name || url, href: url) + end + + def project_wiki + context[:project_wiki] + end + + def project_wiki_base_path + project_wiki && project_wiki.wiki_base_path + end + + # Ensure that a :project_wiki key exists in context + # + # Note that while the key might exist, its value could be nil! + def validate + needs :project_wiki + end + end + end +end -- cgit v1.2.1 From 4872b319c8152837bd36e7fc0a5ad912d1c3ef90 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 12 Jan 2016 02:10:08 -0200 Subject: Use the WikiPipeline when rendering the wiki markdown content --- lib/banzai/pipeline/gollum_tags_pipeline.rb | 13 +++++++++++++ lib/banzai/pipeline/wiki_pipeline.rb | 9 +++++++++ 2 files changed, 22 insertions(+) create mode 100644 lib/banzai/pipeline/gollum_tags_pipeline.rb create mode 100644 lib/banzai/pipeline/wiki_pipeline.rb (limited to 'lib') diff --git a/lib/banzai/pipeline/gollum_tags_pipeline.rb b/lib/banzai/pipeline/gollum_tags_pipeline.rb new file mode 100644 index 00000000000..1f98d3a183a --- /dev/null +++ b/lib/banzai/pipeline/gollum_tags_pipeline.rb @@ -0,0 +1,13 @@ +require 'banzai' + +module Banzai + module Pipeline + class GollumTagsPipeline < BasePipeline + def self.filters + [ + Filter::GollumTagsFilter + ] + end + end + end +end diff --git a/lib/banzai/pipeline/wiki_pipeline.rb b/lib/banzai/pipeline/wiki_pipeline.rb new file mode 100644 index 00000000000..4635a8d6471 --- /dev/null +++ b/lib/banzai/pipeline/wiki_pipeline.rb @@ -0,0 +1,9 @@ +require 'banzai' + +module Banzai + module Pipeline + class WikiPipeline < CombinedPipeline.new(PlainMarkdownPipeline, GollumTagsPipeline, GfmPipeline) + + end + end +end -- cgit v1.2.1 From 60f8434a9d7def80e43ca2e1c8e4e3e502856913 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 12 Jan 2016 12:41:22 -0200 Subject: Refactoring Gitlab::GithubImport::Importer --- lib/gitlab/github_import/importer.rb | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/github_import/importer.rb b/lib/gitlab/github_import/importer.rb index f75227b4734..18929b9113b 100644 --- a/lib/gitlab/github_import/importer.rb +++ b/lib/gitlab/github_import/importer.rb @@ -14,13 +14,7 @@ module Gitlab end def execute - import_issues - import_pull_requests - import_wiki - - true - rescue Gitlab::Shell::Error - false + import_issues && import_pull_requests && import_wiki end private @@ -39,6 +33,10 @@ module Gitlab end end end + + true + rescue ActiveRecord::RecordInvalid + false end def import_pull_requests @@ -53,6 +51,10 @@ module Gitlab import_comments_on_diff(pull_request.number, merge_request) end end + + true + rescue ActiveRecord::RecordInvalid + false end def import_comments(issue_number, noteable) @@ -78,6 +80,10 @@ module Gitlab gitlab_shell.import_repository(wiki.path_with_namespace, wiki.import_url) project.update_attribute(:wiki_enabled, true) end + + true + rescue Gitlab::Shell::Error + false end end end -- cgit v1.2.1 From ca87bb652a1a8390cdc686059f670b89b274dce2 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 12 Jan 2016 14:16:32 -0200 Subject: Remove GollumTagsPipeline --- lib/banzai/pipeline/gollum_tags_pipeline.rb | 13 ------------- lib/banzai/pipeline/wiki_pipeline.rb | 6 ++++-- 2 files changed, 4 insertions(+), 15 deletions(-) delete mode 100644 lib/banzai/pipeline/gollum_tags_pipeline.rb (limited to 'lib') diff --git a/lib/banzai/pipeline/gollum_tags_pipeline.rb b/lib/banzai/pipeline/gollum_tags_pipeline.rb deleted file mode 100644 index 1f98d3a183a..00000000000 --- a/lib/banzai/pipeline/gollum_tags_pipeline.rb +++ /dev/null @@ -1,13 +0,0 @@ -require 'banzai' - -module Banzai - module Pipeline - class GollumTagsPipeline < BasePipeline - def self.filters - [ - Filter::GollumTagsFilter - ] - end - end - end -end diff --git a/lib/banzai/pipeline/wiki_pipeline.rb b/lib/banzai/pipeline/wiki_pipeline.rb index 4635a8d6471..50b5450e70b 100644 --- a/lib/banzai/pipeline/wiki_pipeline.rb +++ b/lib/banzai/pipeline/wiki_pipeline.rb @@ -2,8 +2,10 @@ require 'banzai' module Banzai module Pipeline - class WikiPipeline < CombinedPipeline.new(PlainMarkdownPipeline, GollumTagsPipeline, GfmPipeline) - + class WikiPipeline < FullPipeline + def self.filters + super.insert(1, Filter::GollumTagsFilter) + end end end end -- cgit v1.2.1 From 89e8b82b638e440bc487c4135cdfa4402fdffde5 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 12 Jan 2016 14:50:25 -0200 Subject: Make sure the .git is at the end on Gitlab::GithubImport::WikiFormatter --- lib/gitlab/github_import/wiki_formatter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/github_import/wiki_formatter.rb b/lib/gitlab/github_import/wiki_formatter.rb index 6dd2b917c4a..6c592ff469c 100644 --- a/lib/gitlab/github_import/wiki_formatter.rb +++ b/lib/gitlab/github_import/wiki_formatter.rb @@ -12,7 +12,7 @@ module Gitlab end def import_url - project.import_url.sub(".git", ".wiki.git") + project.import_url.sub(/\.git\z/, ".wiki.git") end end end -- cgit v1.2.1 From 765a2c73271cf311311c391e7e64f83e141c79ae Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 12 Jan 2016 18:59:49 -0200 Subject: Refactoring Banzai::Filter::GollumTagsFilter --- lib/banzai/filter/gollum_tags_filter.rb | 47 ++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 19 deletions(-) (limited to 'lib') diff --git a/lib/banzai/filter/gollum_tags_filter.rb b/lib/banzai/filter/gollum_tags_filter.rb index f78b30bd4e9..e4a73030597 100644 --- a/lib/banzai/filter/gollum_tags_filter.rb +++ b/lib/banzai/filter/gollum_tags_filter.rb @@ -14,7 +14,10 @@ module Banzai include ActionView::Helpers::TagHelper # Pattern to match tag contents. - TAGS_PATTERN = %r{(.?)\[\[(.+?)\]\]([^\[]?)} + TAGS_PATTERN = %r{\[\[(.+?)\]\]} + + # Pattern to match allowed image extensions + ALLOWED_IMAGE_EXTENSIONS = %r{.+(jpg|png|gif|svg|bmp)\z}i def call search_text_nodes(doc).each do |node| @@ -22,9 +25,11 @@ module Banzai next unless content.match(TAGS_PATTERN) - html = process_tag($2) + html = process_tag($1) - node.replace(html) if html != node.content + if html && html != node.content + node.replace(html) + end end doc @@ -38,11 +43,11 @@ module Banzai # # Returns the String HTML version of the tag. def process_tag(tag) - if html = process_image_tag(tag) - html - else - process_page_link_tag(tag) - end + parts = tag.split('|') + + return if parts.size.zero? + + process_image_tag(parts) || process_page_link_tag(parts) end # Attempt to process the tag as an image tag. @@ -51,16 +56,15 @@ module Banzai # # Returns the String HTML if the tag is a valid image tag or nil # if it is not. - def process_image_tag(tag) - parts = tag.split('|') - return if parts.size.zero? + def process_image_tag(parts) + content = parts[0].strip - name = parts[0].strip + return unless image?(content) - if file = project_wiki.find_file(name) + if url?(content) + path = content + elsif file = project_wiki.find_file(content) path = ::File.join project_wiki_base_path, file.path - elsif name =~ /^https?:\/\/.+(jpg|png|gif|svg|bmp)$/i - path = name end if path @@ -68,16 +72,21 @@ module Banzai end end + def image?(path) + path =~ ALLOWED_IMAGE_EXTENSIONS + end + + def url?(path) + path.start_with?(*%w(http https)) + end + # Attempt to process the tag as a page link tag. # # tag - The String tag contents (the stuff inside the double brackets). # # Returns the String HTML if the tag is a valid page link tag or nil # if it is not. - def process_page_link_tag(tag) - parts = tag.split('|') - return if parts.size.zero? - + def process_page_link_tag(parts) if parts.size == 1 url = parts[0].strip else -- cgit v1.2.1 From ac2c86055eb189690bf67cf97cc6eb5ec9c2be7b Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 12 Jan 2016 20:24:17 -0200 Subject: Update documentation on Banzai::Filter::GollumTagsFilter --- lib/banzai/filter/gollum_tags_filter.rb | 40 +++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/banzai/filter/gollum_tags_filter.rb b/lib/banzai/filter/gollum_tags_filter.rb index e4a73030597..fe01dae4850 100644 --- a/lib/banzai/filter/gollum_tags_filter.rb +++ b/lib/banzai/filter/gollum_tags_filter.rb @@ -3,7 +3,28 @@ require 'html/pipeline/filter' module Banzai module Filter - # HTML Filter for parsing Gollum's tags in HTML. + # HTML Filter for parsing Gollum's tags in HTML. It's only parses the + # following tags: + # + # - Link to internal pages: + # + # * [[Bug Reports]] + # * [[How to Contribute|Contributing]] + # + # - Link to external resources: + # + # * [[http://en.wikipedia.org/wiki/Git_(software)]] + # * [[Git|http://en.wikipedia.org/wiki/Git_(software)]] + # + # - Link internal images, the special attributes will be ignored: + # + # * [[images/logo.png]] + # * [[images/logo.png|alt=Logo]] + # + # - Link external images, the special attributes will be ignored: + # + # * [[http://example.com/images/logo.png]] + # * [[http://example.com/images/logo.png|alt=Logo]] # # Based on Gollum::Filter::Tags # @@ -13,7 +34,22 @@ module Banzai class GollumTagsFilter < HTML::Pipeline::Filter include ActionView::Helpers::TagHelper - # Pattern to match tag contents. + # Pattern to match tags content that should be parsed in HTML. + # + # Gollum's tags have been made to resemble the tags of other markups, + # especially MediaWiki. The basic syntax is: + # + # [[tag]] + # + # Some tags will accept attributes which are separated by pipe + # symbols.Some attributes must precede the tag and some must follow it: + # + # [[prefix-attribute|tag]] + # [[tag|suffix-attribute]] + # + # See https://github.com/gollum/gollum/wiki + # + # Rubular: http://rubular.com/r/7dQnE5CUCH TAGS_PATTERN = %r{\[\[(.+?)\]\]} # Pattern to match allowed image extensions -- cgit v1.2.1