diff options
30 files changed, 135 insertions, 102 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3c357c489f8..c7528029c89 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -229,7 +229,6 @@ rake ee_compat_check: <<: *exec only: - branches@gitlab-org/gitlab-ce - - branches@gitlab/gitlabhq except: - master - tags diff --git a/Gemfile.lock b/Gemfile.lock index 1db0e466164..5a14ed6fede 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -614,8 +614,7 @@ GEM rubyntlm (0.5.2) rubypants (0.2.0) rubyzip (1.2.0) - rufus-scheduler (3.3.0) - tzinfo + rufus-scheduler (3.1.10) rugged (0.24.0) safe_yaml (1.0.4) sanitize (2.1.0) diff --git a/changelogs/unreleased/api-branch-status.yml b/changelogs/unreleased/api-branch-status.yml new file mode 100644 index 00000000000..c5763345a22 --- /dev/null +++ b/changelogs/unreleased/api-branch-status.yml @@ -0,0 +1,4 @@ +--- +title: 'API: Expose merge status for branch API' +merge_request: +author: Robert Schilling diff --git a/db/migrate/20130319214458_create_forked_project_links.rb b/db/migrate/20130319214458_create_forked_project_links.rb index 41b0b700a6f..065a5e08243 100644 --- a/db/migrate/20130319214458_create_forked_project_links.rb +++ b/db/migrate/20130319214458_create_forked_project_links.rb @@ -1,5 +1,7 @@ # rubocop:disable all class CreateForkedProjectLinks < ActiveRecord::Migration + DOWNTIME = false + def change create_table :forked_project_links do |t| t.integer :forked_to_project_id, null: false diff --git a/db/migrate/20130506090604_create_deploy_keys_projects.rb b/db/migrate/20130506090604_create_deploy_keys_projects.rb index f2e416d3b6f..8b9662a27c3 100644 --- a/db/migrate/20130506090604_create_deploy_keys_projects.rb +++ b/db/migrate/20130506090604_create_deploy_keys_projects.rb @@ -1,5 +1,7 @@ # rubocop:disable all class CreateDeployKeysProjects < ActiveRecord::Migration + DOWNTIME = false + def change create_table :deploy_keys_projects do |t| t.integer :deploy_key_id, null: false diff --git a/db/migrate/20130617095603_create_users_groups.rb b/db/migrate/20130617095603_create_users_groups.rb index cb098aa9bf9..4ba7d0c9461 100644 --- a/db/migrate/20130617095603_create_users_groups.rb +++ b/db/migrate/20130617095603_create_users_groups.rb @@ -1,5 +1,7 @@ # rubocop:disable all class CreateUsersGroups < ActiveRecord::Migration + DOWNTIME = false + def change create_table :users_groups do |t| t.integer :group_access, null: false diff --git a/db/migrate/20130711063759_create_project_group_links.rb b/db/migrate/20130711063759_create_project_group_links.rb index 8da7ff6f4cd..efccb2aa938 100644 --- a/db/migrate/20130711063759_create_project_group_links.rb +++ b/db/migrate/20130711063759_create_project_group_links.rb @@ -1,5 +1,7 @@ # rubocop:disable all class CreateProjectGroupLinks < ActiveRecord::Migration + DOWNTIME = false + def change create_table :project_group_links do |t| t.integer :project_id, null: false diff --git a/db/migrate/20131112114325_create_broadcast_messages.rb b/db/migrate/20131112114325_create_broadcast_messages.rb index 4ada40f1b66..ad2549e53af 100644 --- a/db/migrate/20131112114325_create_broadcast_messages.rb +++ b/db/migrate/20131112114325_create_broadcast_messages.rb @@ -1,5 +1,7 @@ # rubocop:disable all class CreateBroadcastMessages < ActiveRecord::Migration + DOWNTIME = false + def change create_table :broadcast_messages do |t| t.text :message, null: false diff --git a/db/migrate/20140122112253_create_merge_request_diffs.rb b/db/migrate/20140122112253_create_merge_request_diffs.rb index 68448c91529..6c7a92b6950 100644 --- a/db/migrate/20140122112253_create_merge_request_diffs.rb +++ b/db/migrate/20140122112253_create_merge_request_diffs.rb @@ -1,5 +1,7 @@ # rubocop:disable all class CreateMergeRequestDiffs < ActiveRecord::Migration + DOWNTIME = false + def up create_table :merge_request_diffs do |t| t.string :state, null: false, default: 'collected' diff --git a/db/migrate/20140209025651_create_emails.rb b/db/migrate/20140209025651_create_emails.rb index 48d14682628..51886f8fc89 100644 --- a/db/migrate/20140209025651_create_emails.rb +++ b/db/migrate/20140209025651_create_emails.rb @@ -1,10 +1,12 @@ # rubocop:disable all class CreateEmails < ActiveRecord::Migration + DOWNTIME = false + def change create_table :emails do |t| t.integer :user_id, null: false t.string :email, null: false - + t.timestamps null: true end diff --git a/db/migrate/20140625115202_create_users_star_projects.rb b/db/migrate/20140625115202_create_users_star_projects.rb index c50bc4bd614..d4f3fe5ac62 100644 --- a/db/migrate/20140625115202_create_users_star_projects.rb +++ b/db/migrate/20140625115202_create_users_star_projects.rb @@ -1,5 +1,7 @@ # rubocop:disable all class CreateUsersStarProjects < ActiveRecord::Migration + DOWNTIME = false + def change create_table :users_star_projects do |t| t.integer :project_id, null: false diff --git a/db/migrate/20140729134820_create_labels.rb b/db/migrate/20140729134820_create_labels.rb index 589aced0d76..66d20e741a6 100644 --- a/db/migrate/20140729134820_create_labels.rb +++ b/db/migrate/20140729134820_create_labels.rb @@ -1,5 +1,7 @@ # rubocop:disable all class CreateLabels < ActiveRecord::Migration + DOWNTIME = false + def change create_table :labels do |t| t.string :title diff --git a/db/migrate/20140729140420_create_label_links.rb b/db/migrate/20140729140420_create_label_links.rb index abdbaa1bd1a..dacd9f2e4b6 100644 --- a/db/migrate/20140729140420_create_label_links.rb +++ b/db/migrate/20140729140420_create_label_links.rb @@ -1,5 +1,7 @@ # rubocop:disable all class CreateLabelLinks < ActiveRecord::Migration + DOWNTIME = false + def change create_table :label_links do |t| t.integer :label_id diff --git a/db/migrate/20140914113604_add_members_table.rb b/db/migrate/20140914113604_add_members_table.rb index fb0876dd520..0f76bb0ef79 100644 --- a/db/migrate/20140914113604_add_members_table.rb +++ b/db/migrate/20140914113604_add_members_table.rb @@ -1,5 +1,7 @@ # rubocop:disable all class AddMembersTable < ActiveRecord::Migration + DOWNTIME = false + def change create_table :members do |t| t.integer :access_level, null: false diff --git a/db/migrate/20140914173417_remove_old_member_tables.rb b/db/migrate/20140914173417_remove_old_member_tables.rb index 067dc21ccf1..d2ab326ef1f 100644 --- a/db/migrate/20140914173417_remove_old_member_tables.rb +++ b/db/migrate/20140914173417_remove_old_member_tables.rb @@ -1,5 +1,7 @@ # rubocop:disable all class RemoveOldMemberTables < ActiveRecord::Migration + DOWNTIME = false + def up drop_table :users_groups drop_table :users_projects diff --git a/db/migrate/20141118150935_add_audit_event.rb b/db/migrate/20141118150935_add_audit_event.rb index f0452f46459..52d70b4a0ac 100644 --- a/db/migrate/20141118150935_add_audit_event.rb +++ b/db/migrate/20141118150935_add_audit_event.rb @@ -1,5 +1,7 @@ # rubocop:disable all class AddAuditEvent < ActiveRecord::Migration + DOWNTIME = false + def change create_table :audit_events do |t| t.integer :author_id, null: false diff --git a/db/migrate/20141216155758_create_doorkeeper_tables.rb b/db/migrate/20141216155758_create_doorkeeper_tables.rb index 1c4d32e133c..17e45a77291 100644 --- a/db/migrate/20141216155758_create_doorkeeper_tables.rb +++ b/db/migrate/20141216155758_create_doorkeeper_tables.rb @@ -1,5 +1,7 @@ # rubocop:disable all class CreateDoorkeeperTables < ActiveRecord::Migration + DOWNTIME = false + def change create_table :oauth_applications do |t| t.string :name, null: false diff --git a/db/migrate/20150108073740_create_application_settings.rb b/db/migrate/20150108073740_create_application_settings.rb index c26a7c39574..0e4c66ca8c0 100644 --- a/db/migrate/20150108073740_create_application_settings.rb +++ b/db/migrate/20150108073740_create_application_settings.rb @@ -1,5 +1,7 @@ # rubocop:disable all class CreateApplicationSettings < ActiveRecord::Migration + DOWNTIME = false + def change create_table :application_settings do |t| t.integer :default_projects_limit diff --git a/db/migrate/20150313012111_create_subscriptions_table.rb b/db/migrate/20150313012111_create_subscriptions_table.rb index 0977c9adfec..a9a8435330d 100644 --- a/db/migrate/20150313012111_create_subscriptions_table.rb +++ b/db/migrate/20150313012111_create_subscriptions_table.rb @@ -1,15 +1,17 @@ # rubocop:disable all class CreateSubscriptionsTable < ActiveRecord::Migration + DOWNTIME = false + def change create_table :subscriptions do |t| t.integer :user_id t.references :subscribable, polymorphic: true t.boolean :subscribed - + t.timestamps null: true end - add_index :subscriptions, + add_index :subscriptions, [:subscribable_id, :subscribable_type, :user_id], unique: true, name: 'subscriptions_user_id_and_ref_fields' diff --git a/db/migrate/20150806104937_create_abuse_reports.rb b/db/migrate/20150806104937_create_abuse_reports.rb index 9f1512db862..52aed9e1d1d 100644 --- a/db/migrate/20150806104937_create_abuse_reports.rb +++ b/db/migrate/20150806104937_create_abuse_reports.rb @@ -1,5 +1,7 @@ # rubocop:disable all class CreateAbuseReports < ActiveRecord::Migration + DOWNTIME = false + def change create_table :abuse_reports do |t| t.integer :reporter_id diff --git a/db/migrate/20151103134857_create_lfs_objects.rb b/db/migrate/20151103134857_create_lfs_objects.rb index fadaf637cec..db6fa27199b 100644 --- a/db/migrate/20151103134857_create_lfs_objects.rb +++ b/db/migrate/20151103134857_create_lfs_objects.rb @@ -1,5 +1,7 @@ # rubocop:disable all class CreateLfsObjects < ActiveRecord::Migration + DOWNTIME = false + def change create_table :lfs_objects do |t| t.string :oid, null: false, unique: true diff --git a/db/migrate/20151103134958_create_lfs_objects_projects.rb b/db/migrate/20151103134958_create_lfs_objects_projects.rb index e830cbe4656..5af1c39fd9c 100644 --- a/db/migrate/20151103134958_create_lfs_objects_projects.rb +++ b/db/migrate/20151103134958_create_lfs_objects_projects.rb @@ -1,5 +1,7 @@ # rubocop:disable all class CreateLfsObjectsProjects < ActiveRecord::Migration + DOWNTIME = false + def change create_table :lfs_objects_projects do |t| t.integer :lfs_object_id, null: false diff --git a/db/migrate/20151105094515_create_releases.rb b/db/migrate/20151105094515_create_releases.rb index 87f692c64d0..34dd7a10942 100644 --- a/db/migrate/20151105094515_create_releases.rb +++ b/db/migrate/20151105094515_create_releases.rb @@ -1,5 +1,7 @@ # rubocop:disable all class CreateReleases < ActiveRecord::Migration + DOWNTIME = false + def change create_table :releases do |t| t.string :tag diff --git a/db/migrate/20160212123307_create_tasks.rb b/db/migrate/20160212123307_create_tasks.rb index 8b5b1dd694d..cd3ad0e4cd8 100644 --- a/db/migrate/20160212123307_create_tasks.rb +++ b/db/migrate/20160212123307_create_tasks.rb @@ -1,5 +1,7 @@ # rubocop:disable all class CreateTasks < ActiveRecord::Migration + DOWNTIME = false + def change create_table :tasks do |t| t.references :user, null: false, index: true diff --git a/db/migrate/20160416180807_add_award_emoji.rb b/db/migrate/20160416180807_add_award_emoji.rb index c0957f028a8..0d252e5044e 100644 --- a/db/migrate/20160416180807_add_award_emoji.rb +++ b/db/migrate/20160416180807_add_award_emoji.rb @@ -1,5 +1,7 @@ # rubocop:disable all class AddAwardEmoji < ActiveRecord::Migration + DOWNTIME = false + def change create_table :award_emoji do |t| t.string :name diff --git a/doc/api/branches.md b/doc/api/branches.md index 07dfa5d4d7f..ffcfea41453 100644 --- a/doc/api/branches.md +++ b/doc/api/branches.md @@ -22,6 +22,7 @@ Example response: [ { "name": "master", + "merged": false, "protected": true, "developers_can_push": false, "developers_can_merge": false, @@ -65,6 +66,7 @@ Example response: ```json { "name": "master", + "merged": false, "protected": true, "developers_can_push": false, "developers_can_merge": false, @@ -123,6 +125,7 @@ Example response: ] }, "name": "master", + "merged": false, "protected": true, "developers_can_push": true, "developers_can_merge": true @@ -166,6 +169,7 @@ Example response: ] }, "name": "master", + "merged": false, "protected": false, "developers_can_push": false, "developers_can_merge": false @@ -206,6 +210,7 @@ Example response: ] }, "name": "newbranch", + "merged": false, "protected": false, "developers_can_push": false, "developers_can_merge": false diff --git a/doc/api/repository_files.md b/doc/api/repository_files.md index 1bc6a24e914..b8c9eb2c9a8 100644 --- a/doc/api/repository_files.md +++ b/doc/api/repository_files.md @@ -60,7 +60,7 @@ Parameters: - `file_path` (required) - Full path to new file. Ex. lib/class.rb - `branch_name` (required) - The name of branch -- `encoding` (optional) - 'text' or 'base64'. Text is default. +- `encoding` (optional) - Change encoding to 'base64'. Default is text. - `author_email` (optional) - Specify the commit author's email address - `author_name` (optional) - Specify the commit author's name - `content` (required) - File content @@ -89,7 +89,7 @@ Parameters: - `file_path` (required) - Full path to file. Ex. lib/class.rb - `branch_name` (required) - The name of branch -- `encoding` (optional) - 'text' or 'base64'. Text is default. +- `encoding` (optional) - Change encoding to 'base64'. Default is text. - `author_email` (optional) - Specify the commit author's email address - `author_name` (optional) - Specify the commit author's name - `content` (required) - New file content diff --git a/lib/api/entities.rb b/lib/api/entities.rb index fdb19558c1c..d5dfb8d00be 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -141,8 +141,12 @@ module API options[:project].repository.commit(repo_branch.dereferenced_target) end + expose :merged do |repo_branch, options| + options[:project].repository.merged_to_root_ref?(repo_branch.name) + end + expose :protected do |repo_branch, options| - options[:project].protected_branch? repo_branch.name + options[:project].protected_branch?(repo_branch.name) end expose :developers_can_push do |repo_branch, options| diff --git a/lib/api/files.rb b/lib/api/files.rb index 96510e651a3..28f306e45f3 100644 --- a/lib/api/files.rb +++ b/lib/api/files.rb @@ -23,140 +23,107 @@ module API branch_name: attrs[:branch_name] } end + + params :simple_file_params do + requires :file_path, type: String, desc: 'The path to new file. Ex. lib/class.rb' + requires :branch_name, type: String, desc: 'The name of branch' + requires :commit_message, type: String, desc: 'Commit Message' + optional :author_email, type: String, desc: 'The email of the author' + optional :author_name, type: String, desc: 'The name of the author' + end + + params :extended_file_params do + use :simple_file_params + requires :content, type: String, desc: 'File content' + optional :encoding, type: String, values: %w[base64], desc: 'File encoding' + end end + params do + requires :id, type: String, desc: 'The project ID' + end resource :projects do - # Get file from repository - # File content is Base64 encoded - # - # Parameters: - # file_path (required) - The path to the file. Ex. lib/class.rb - # ref (required) - The name of branch, tag or commit - # - # Example Request: - # GET /projects/:id/repository/files - # - # Example response: - # { - # "file_name": "key.rb", - # "file_path": "app/models/key.rb", - # "size": 1476, - # "encoding": "base64", - # "content": "IyA9PSBTY2hlbWEgSW5mb3...", - # "ref": "master", - # "blob_id": "79f7bbd25901e8334750839545a9bd021f0e4c83", - # "commit_id": "d5a3ff139356ce33e37e73add446f16869741b50", - # "last_commit_id": "570e7b2abdd848b95f2f578043fc23bd6f6fd24d", - # } - # + desc 'Get a file from repository' + params do + requires :file_path, type: String, desc: 'The path to the file. Ex. lib/class.rb' + requires :ref, type: String, desc: 'The name of branch, tag, or commit' + end get ":id/repository/files" do authorize! :download_code, user_project - required_attributes! [:file_path, :ref] - attrs = attributes_for_keys [:file_path, :ref] - ref = attrs.delete(:ref) - file_path = attrs.delete(:file_path) - - commit = user_project.commit(ref) - not_found! 'Commit' unless commit + commit = user_project.commit(params[:ref]) + not_found!('Commit') unless commit repo = user_project.repository - blob = repo.blob_at(commit.sha, file_path) + blob = repo.blob_at(commit.sha, params[:file_path]) + not_found!('File') unless blob - if blob - blob.load_all_data!(repo) - status(200) + blob.load_all_data!(repo) + status(200) - { - file_name: blob.name, - file_path: blob.path, - size: blob.size, - encoding: "base64", - content: Base64.strict_encode64(blob.data), - ref: ref, - blob_id: blob.id, - commit_id: commit.id, - last_commit_id: repo.last_commit_for_path(commit.sha, file_path).id - } - else - not_found! 'File' - end + { + file_name: blob.name, + file_path: blob.path, + size: blob.size, + encoding: "base64", + content: Base64.strict_encode64(blob.data), + ref: params[:ref], + blob_id: blob.id, + commit_id: commit.id, + last_commit_id: repo.last_commit_for_path(commit.sha, params[:file_path]).id + } end - # Create new file in repository - # - # Parameters: - # file_path (required) - The path to new file. Ex. lib/class.rb - # branch_name (required) - The name of branch - # content (required) - File content - # commit_message (required) - Commit message - # - # Example Request: - # POST /projects/:id/repository/files - # + desc 'Create new file in repository' + params do + use :extended_file_params + end post ":id/repository/files" do authorize! :push_code, user_project - required_attributes! [:file_path, :branch_name, :content, :commit_message] - attrs = attributes_for_keys [:file_path, :branch_name, :content, :commit_message, :encoding, :author_email, :author_name] - result = ::Files::CreateService.new(user_project, current_user, commit_params(attrs)).execute + file_params = declared_params(include_missing: false) + result = ::Files::CreateService.new(user_project, current_user, commit_params(file_params)).execute if result[:status] == :success status(201) - commit_response(attrs) + commit_response(file_params) else render_api_error!(result[:message], 400) end end - # Update existing file in repository - # - # Parameters: - # file_path (optional) - The path to file. Ex. lib/class.rb - # branch_name (required) - The name of branch - # content (required) - File content - # commit_message (required) - Commit message - # - # Example Request: - # PUT /projects/:id/repository/files - # + desc 'Update existing file in repository' + params do + use :extended_file_params + end put ":id/repository/files" do authorize! :push_code, user_project - required_attributes! [:file_path, :branch_name, :content, :commit_message] - attrs = attributes_for_keys [:file_path, :branch_name, :content, :commit_message, :encoding, :author_email, :author_name] - result = ::Files::UpdateService.new(user_project, current_user, commit_params(attrs)).execute + file_params = declared_params(include_missing: false) + result = ::Files::UpdateService.new(user_project, current_user, commit_params(file_params)).execute if result[:status] == :success status(200) - commit_response(attrs) + commit_response(file_params) else http_status = result[:http_status] || 400 render_api_error!(result[:message], http_status) end end - # Delete existing file in repository - # - # Parameters: - # file_path (optional) - The path to file. Ex. lib/class.rb - # branch_name (required) - The name of branch - # content (required) - File content - # commit_message (required) - Commit message - # - # Example Request: - # DELETE /projects/:id/repository/files - # + desc 'Delete an existing file in repository' + params do + use :simple_file_params + end delete ":id/repository/files" do authorize! :push_code, user_project - required_attributes! [:file_path, :branch_name, :commit_message] - attrs = attributes_for_keys [:file_path, :branch_name, :commit_message, :author_email, :author_name] - result = ::Files::DeleteService.new(user_project, current_user, commit_params(attrs)).execute + file_params = declared_params(include_missing: false) + result = ::Files::DeleteService.new(user_project, current_user, commit_params(file_params)).execute if result[:status] == :success status(200) - commit_response(attrs) + commit_response(file_params) else render_api_error!(result[:message], 400) end diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb index fe6b875b997..28fbae18de1 100644 --- a/spec/requests/api/branches_spec.rb +++ b/spec/requests/api/branches_spec.rb @@ -31,11 +31,22 @@ describe API::API, api: true do expect(json_response['name']).to eq(branch_name) expect(json_response['commit']['id']).to eq(branch_sha) + expect(json_response['merged']).to eq(false) expect(json_response['protected']).to eq(false) expect(json_response['developers_can_push']).to eq(false) expect(json_response['developers_can_merge']).to eq(false) end + context 'on a merged branch' do + it "returns the branch information for a single branch" do + get api("/projects/#{project.id}/repository/branches/merge-test", user) + + expect(response).to have_http_status(200) + expect(json_response['name']).to eq('merge-test') + expect(json_response['merged']).to eq(true) + end + end + it "returns a 403 error if guest" do get api("/projects/#{project.id}/repository/branches", user2) expect(response).to have_http_status(403) |