Commit 6a9aed1e878bc8651243d645d0a9d2f7da33f248
Exists in
master
and in
4 other branches
Merge branch 'master' into 6-0-dev
Conflicts: CHANGELOG VERSION app/views/admin/teams/projects/new.html.haml app/views/projects/teams/available.html.haml doc/install/installation.md
Showing
10 changed files
with
181 additions
and
23 deletions
Show diff stats
CHANGELOG
| ... | ... | @@ -17,6 +17,16 @@ v 6.0.0 |
| 17 | 17 | - You an use arrows to navigate at tree view |
| 18 | 18 | - Apply user project limit only for personal projects |
| 19 | 19 | |
| 20 | +v 5.4.0 | |
| 21 | + - Ability to edit own comments | |
| 22 | + - Documentation improvements | |
| 23 | + - Improve dashboard projects page | |
| 24 | + - Fixed nav for empty repos | |
| 25 | + - GitLab Markdown help page | |
| 26 | + - Misspelling fixes | |
| 27 | + - Added suppoort of unicorn and fog gems | |
| 28 | + - Added client list to API doc | |
| 29 | + | |
| 20 | 30 | v 5.3.0 |
| 21 | 31 | - Refactored services |
| 22 | 32 | - Campfire service added | ... | ... |
app/assets/stylesheets/gitlab_bootstrap/nav.scss
doc/api/README.md
| ... | ... | @@ -69,18 +69,18 @@ When listing resources you can pass the following parameters: |
| 69 | 69 | |
| 70 | 70 | ## Contents |
| 71 | 71 | |
| 72 | -+ [Users](users.md) | |
| 73 | -+ [Session](session.md) | |
| 74 | -+ [Projects](projects.md) | |
| 75 | -+ [Project Snippets](project_snippets.md) | |
| 76 | -+ [Repositories](repositories.md) | |
| 77 | -+ [Issues](issues.md) | |
| 78 | -+ [Milestones](milestones.md) | |
| 79 | -+ [Notes](notes.md) | |
| 80 | -+ [Deploy Keys](deploy_keys.md) | |
| 81 | -+ [System Hooks](system_hooks.md) | |
| 82 | -+ [Groups](groups.md) | |
| 83 | -+ [User Teams](user_teams.md) | |
| 72 | ++ [Users](api/users.md) | |
| 73 | ++ [Session](api/session.md) | |
| 74 | ++ [Projects](api/projects.md) | |
| 75 | ++ [Project Snippets](api/project_snippets.md) | |
| 76 | ++ [Repositories](api/repositories.md) | |
| 77 | ++ [Issues](api/issues.md) | |
| 78 | ++ [Milestones](api/milestones.md) | |
| 79 | ++ [Notes](api/notes.md) | |
| 80 | ++ [Deploy Keys](api/deploy_keys.md) | |
| 81 | ++ [System Hooks](api/system_hooks.md) | |
| 82 | ++ [Groups](api/groups.md) | |
| 83 | ++ [User Teams](api/user_teams.md) | |
| 84 | 84 | |
| 85 | 85 | ## Clients |
| 86 | 86 | ... | ... |
doc/api/projects.md
| ... | ... | @@ -453,3 +453,28 @@ Parameters: |
| 453 | 453 | + `id` (required) - The ID of the project. |
| 454 | 454 | + `branch` (required) - The name of the branch. |
| 455 | 455 | |
| 456 | + | |
| 457 | +## Admin fork relation | |
| 458 | + | |
| 459 | +Allows modification of the forked relationship between existing projects. . Available only for admins. | |
| 460 | + | |
| 461 | +### Create a forked from/to relation between existing projects. | |
| 462 | + | |
| 463 | +``` | |
| 464 | +POST /projects/:id/fork/:forked_from_id | |
| 465 | +``` | |
| 466 | + | |
| 467 | +Parameters: | |
| 468 | + | |
| 469 | ++ `id` (required) - The ID of the project | |
| 470 | ++ `forked_from_id:` (required) - The ID of the project that was forked from | |
| 471 | + | |
| 472 | +### Delete an existing forked from relationship | |
| 473 | + | |
| 474 | +``` | |
| 475 | +DELETE /projects/:id/fork | |
| 476 | +``` | |
| 477 | + | |
| 478 | +Parameter: | |
| 479 | + | |
| 480 | ++ `id` (required) - The ID of the project | |
| 456 | 481 | \ No newline at end of file | ... | ... |
doc/install/installation.md
| ... | ... | @@ -42,11 +42,13 @@ up-to-date and install it. |
| 42 | 42 | apt-get install sudo -y |
| 43 | 43 | |
| 44 | 44 | **Note:** |
| 45 | -Vim is an editor that is used here whenever there are files that need to be | |
| 46 | -edited by hand. But, you can use any editor you like instead. | |
| 45 | +During this installation some files will need to be edited manually. | |
| 46 | +If you are familiar with vim set it as default editor with the commands below. | |
| 47 | +If you are not familiar with vim please skip this and keep using the default editor. | |
| 47 | 48 | |
| 48 | - # Install vim | |
| 49 | + # Install vim and set as default editor | |
| 49 | 50 | sudo apt-get install -y vim |
| 51 | + sudo update-alternatives --set editor /usr/bin/vim.basic | |
| 50 | 52 | |
| 51 | 53 | Install the required packages: |
| 52 | 54 | |
| ... | ... | @@ -123,7 +125,7 @@ GitLab Shell is a ssh access and repository management software developed specia |
| 123 | 125 | |
| 124 | 126 | # Edit config and replace gitlab_url |
| 125 | 127 | # with something like 'http://domain.com/' |
| 126 | - sudo -u git -H vim config.yml | |
| 128 | + sudo -u git -H editor config.yml | |
| 127 | 129 | |
| 128 | 130 | # Do setup |
| 129 | 131 | sudo -u git -H ./bin/install |
| ... | ... | @@ -162,7 +164,7 @@ You can change `5-3-stable` to `master` if you want the *bleeding edge* version, |
| 162 | 164 | |
| 163 | 165 | # Make sure to change "localhost" to the fully-qualified domain name of your |
| 164 | 166 | # host serving GitLab where necessary |
| 165 | - sudo -u git -H vim config/gitlab.yml | |
| 167 | + sudo -u git -H editor config/gitlab.yml | |
| 166 | 168 | |
| 167 | 169 | # Make sure GitLab can write to the log/ and tmp/ directories |
| 168 | 170 | sudo chown -R git log/ |
| ... | ... | @@ -214,7 +216,7 @@ Make sure to edit both `gitlab.yml` and `unicorn.rb` to match your setup. |
| 214 | 216 | # Change 'root' to 'gitlab' |
| 215 | 217 | # Change 'secure password' with the value you have given to $password |
| 216 | 218 | # You can keep the double quotes around the password |
| 217 | - sudo -u git -H vim config/database.yml | |
| 219 | + sudo -u git -H editor config/database.yml | |
| 218 | 220 | |
| 219 | 221 | # Make config/database.yml readable to git only |
| 220 | 222 | sudo -u git -H chmod o-rwx config/database.yml |
| ... | ... | @@ -295,7 +297,7 @@ Make sure to edit the config file to match your setup: |
| 295 | 297 | |
| 296 | 298 | # Change YOUR_SERVER_FQDN to the fully-qualified |
| 297 | 299 | # domain name of your host serving GitLab. |
| 298 | - sudo vim /etc/nginx/sites-available/gitlab | |
| 300 | + sudo editor /etc/nginx/sites-available/gitlab | |
| 299 | 301 | |
| 300 | 302 | ## Restart |
| 301 | 303 | ... | ... |
lib/api/entities.rb
| ... | ... | @@ -25,6 +25,12 @@ module API |
| 25 | 25 | expose :id, :url, :created_at |
| 26 | 26 | end |
| 27 | 27 | |
| 28 | + class ForkedFromProject < Grape::Entity | |
| 29 | + expose :id | |
| 30 | + expose :name, :name_with_namespace | |
| 31 | + expose :path, :path_with_namespace | |
| 32 | + end | |
| 33 | + | |
| 28 | 34 | class Project < Grape::Entity |
| 29 | 35 | expose :id, :description, :default_branch, :public, :ssh_url_to_repo, :http_url_to_repo, :web_url |
| 30 | 36 | expose :owner, using: Entities::UserBasic |
| ... | ... | @@ -32,6 +38,7 @@ module API |
| 32 | 38 | expose :path, :path_with_namespace |
| 33 | 39 | expose :issues_enabled, :merge_requests_enabled, :wall_enabled, :wiki_enabled, :created_at, :last_activity_at |
| 34 | 40 | expose :namespace |
| 41 | + expose :forked_from_project, using: Entities::ForkedFromProject, :if => lambda{ | project, options | project.forked? } | |
| 35 | 42 | end |
| 36 | 43 | |
| 37 | 44 | class ProjectMember < UserBasic | ... | ... |
lib/api/helpers.rb
| ... | ... | @@ -5,12 +5,12 @@ module API |
| 5 | 5 | end |
| 6 | 6 | |
| 7 | 7 | def user_project |
| 8 | - @project ||= find_project | |
| 8 | + @project ||= find_project(params[:id]) | |
| 9 | 9 | @project || not_found! |
| 10 | 10 | end |
| 11 | 11 | |
| 12 | - def find_project | |
| 13 | - project = Project.find_by_id(params[:id]) || Project.find_with_namespace(params[:id]) | |
| 12 | + def find_project(id) | |
| 13 | + project = Project.find_by_id(id) || Project.find_with_namespace(id) | |
| 14 | 14 | |
| 15 | 15 | if project && can?(current_user, :read_project, project) |
| 16 | 16 | project | ... | ... |
lib/api/projects.rb
| ... | ... | @@ -121,6 +121,42 @@ module API |
| 121 | 121 | end |
| 122 | 122 | |
| 123 | 123 | |
| 124 | + # Mark this project as forked from another | |
| 125 | + # | |
| 126 | + # Parameters: | |
| 127 | + # id: (required) - The ID of the project being marked as a fork | |
| 128 | + # forked_from_id: (required) - The ID of the project it was forked from | |
| 129 | + # Example Request: | |
| 130 | + # POST /projects/:id/fork/:forked_from_id | |
| 131 | + post ":id/fork/:forked_from_id" do | |
| 132 | + authenticated_as_admin! | |
| 133 | + forked_from_project = find_project(params[:forked_from_id]) | |
| 134 | + unless forked_from_project.nil? | |
| 135 | + if user_project.forked_from_project.nil? | |
| 136 | + user_project.create_forked_project_link(forked_to_project_id: user_project.id, forked_from_project_id: forked_from_project.id) | |
| 137 | + else | |
| 138 | + render_api_error!("Project already forked", 409) | |
| 139 | + end | |
| 140 | + else | |
| 141 | + not_found! | |
| 142 | + end | |
| 143 | + | |
| 144 | + end | |
| 145 | + | |
| 146 | + # Remove a forked_from relationship | |
| 147 | + # | |
| 148 | + # Parameters: | |
| 149 | + # id: (required) - The ID of the project being marked as a fork | |
| 150 | + # Example Request: | |
| 151 | + # DELETE /projects/:id/fork | |
| 152 | + delete ":id/fork" do | |
| 153 | + authenticated_as_admin! | |
| 154 | + unless user_project.forked_project_link.nil? | |
| 155 | + user_project.forked_project_link.destroy | |
| 156 | + end | |
| 157 | + end | |
| 158 | + | |
| 159 | + | |
| 124 | 160 | # Get a project team members |
| 125 | 161 | # |
| 126 | 162 | # Parameters: | ... | ... |
lib/redcarpet/render/gitlab_html.rb
| ... | ... | @@ -12,7 +12,7 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML |
| 12 | 12 | def block_code(code, language) |
| 13 | 13 | options = { options: {encoding: 'utf-8'} } |
| 14 | 14 | lexer = Pygments::Lexer.find(language) # language can be an alias |
| 15 | - options.merge!(lexer: lexer.name.downcase) if lexer # downcase is required | |
| 15 | + options.merge!(lexer: lexer.aliases[0].downcase) if lexer # downcase is required | |
| 16 | 16 | |
| 17 | 17 | # New lines are placed to fix an rendering issue |
| 18 | 18 | # with code wrapped inside <h1> tag for next case: | ... | ... |
spec/requests/api/projects_spec.rb
| ... | ... | @@ -595,4 +595,71 @@ describe API::API do |
| 595 | 595 | end |
| 596 | 596 | end |
| 597 | 597 | end |
| 598 | + | |
| 599 | + describe :fork_admin do | |
| 600 | + let(:project_fork_target) { create(:project) } | |
| 601 | + let(:project_fork_source) { create(:project, public: true) } | |
| 602 | + | |
| 603 | + describe "POST /projects/:id/fork/:forked_from_id" do | |
| 604 | + let(:new_project_fork_source) { create(:project, public: true) } | |
| 605 | + | |
| 606 | + it "shouldn't available for non admin users" do | |
| 607 | + post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", user) | |
| 608 | + response.status.should == 403 | |
| 609 | + end | |
| 610 | + | |
| 611 | + it "should allow project to be forked from an existing project" do | |
| 612 | + project_fork_target.forked?.should_not be_true | |
| 613 | + post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin) | |
| 614 | + response.status.should == 201 | |
| 615 | + project_fork_target.reload | |
| 616 | + project_fork_target.forked_from_project.id.should == project_fork_source.id | |
| 617 | + project_fork_target.forked_project_link.should_not be_nil | |
| 618 | + project_fork_target.forked?.should be_true | |
| 619 | + end | |
| 620 | + | |
| 621 | + it "should fail if forked_from project which does not exist" do | |
| 622 | + post api("/projects/#{project_fork_target.id}/fork/9999", admin) | |
| 623 | + response.status.should == 404 | |
| 624 | + end | |
| 625 | + | |
| 626 | + it "should fail with 409 if already forked" do | |
| 627 | + post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin) | |
| 628 | + project_fork_target.reload | |
| 629 | + project_fork_target.forked_from_project.id.should == project_fork_source.id | |
| 630 | + post api("/projects/#{project_fork_target.id}/fork/#{new_project_fork_source.id}", admin) | |
| 631 | + response.status.should == 409 | |
| 632 | + project_fork_target.reload | |
| 633 | + project_fork_target.forked_from_project.id.should == project_fork_source.id | |
| 634 | + project_fork_target.forked?.should be_true | |
| 635 | + end | |
| 636 | + end | |
| 637 | + | |
| 638 | + describe "DELETE /projects/:id/fork" do | |
| 639 | + | |
| 640 | + it "shouldn't available for non admin users" do | |
| 641 | + delete api("/projects/#{project_fork_target.id}/fork", user) | |
| 642 | + response.status.should == 403 | |
| 643 | + end | |
| 644 | + | |
| 645 | + it "should make forked project unforked" do | |
| 646 | + post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin) | |
| 647 | + project_fork_target.reload | |
| 648 | + project_fork_target.forked_from_project.should_not be_nil | |
| 649 | + project_fork_target.forked?.should be_true | |
| 650 | + delete api("/projects/#{project_fork_target.id}/fork", admin) | |
| 651 | + response.status.should == 200 | |
| 652 | + project_fork_target.reload | |
| 653 | + project_fork_target.forked_from_project.should be_nil | |
| 654 | + project_fork_target.forked?.should_not be_true | |
| 655 | + end | |
| 656 | + | |
| 657 | + it "should be idempotent if not forked" do | |
| 658 | + project_fork_target.forked_from_project.should be_nil | |
| 659 | + delete api("/projects/#{project_fork_target.id}/fork", admin) | |
| 660 | + response.status.should == 200 | |
| 661 | + project_fork_target.reload.forked_from_project.should be_nil | |
| 662 | + end | |
| 663 | + end | |
| 664 | + end | |
| 598 | 665 | end | ... | ... |