diff --git a/CHANGELOG b/CHANGELOG index 2afa50a4ba0a0f448af837c2955d5a23bd6fdcbf..57f37d36a47605fd72045b1129bb3c040027b3a6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -17,6 +17,16 @@ v 6.0.0 - You an use arrows to navigate at tree view - Apply user project limit only for personal projects +v 5.4.0 + - Ability to edit own comments + - Documentation improvements + - Improve dashboard projects page + - Fixed nav for empty repos + - GitLab Markdown help page + - Misspelling fixes + - Added suppoort of unicorn and fog gems + - Added client list to API doc + v 5.3.0 - Refactored services - Campfire service added diff --git a/app/assets/stylesheets/gitlab_bootstrap/nav.scss b/app/assets/stylesheets/gitlab_bootstrap/nav.scss index 561029090355bfaa1d93a8d20f7482e7c06b7bf4..de07730361751ad872aa5d4eff04a414a26175d0 100644 --- a/app/assets/stylesheets/gitlab_bootstrap/nav.scss +++ b/app/assets/stylesheets/gitlab_bootstrap/nav.scss @@ -71,3 +71,14 @@ &.nav-small-tabs > li > a { padding: 6px 9px; } } + + + +/** + * fix to keep tooltips position in top navigation bar + * + */ +.navbar .nav > li { + position: relative; + white-space: nowrap; +} diff --git a/doc/api/README.md b/doc/api/README.md index 4bcd89949dfcf657800cbafdc73ea9b42345a51c..9d6e229e4cb574c1f20bf88534bcd71d01112e7a 100644 --- a/doc/api/README.md +++ b/doc/api/README.md @@ -69,18 +69,18 @@ When listing resources you can pass the following parameters: ## Contents -+ [Users](users.md) -+ [Session](session.md) -+ [Projects](projects.md) -+ [Project Snippets](project_snippets.md) -+ [Repositories](repositories.md) -+ [Issues](issues.md) -+ [Milestones](milestones.md) -+ [Notes](notes.md) -+ [Deploy Keys](deploy_keys.md) -+ [System Hooks](system_hooks.md) -+ [Groups](groups.md) -+ [User Teams](user_teams.md) ++ [Users](api/users.md) ++ [Session](api/session.md) ++ [Projects](api/projects.md) ++ [Project Snippets](api/project_snippets.md) ++ [Repositories](api/repositories.md) ++ [Issues](api/issues.md) ++ [Milestones](api/milestones.md) ++ [Notes](api/notes.md) ++ [Deploy Keys](api/deploy_keys.md) ++ [System Hooks](api/system_hooks.md) ++ [Groups](api/groups.md) ++ [User Teams](api/user_teams.md) ## Clients diff --git a/doc/api/projects.md b/doc/api/projects.md index 323c0be63a48d597f54b976c93dce49318763342..41b6b6add394e1c8e9af7756995b29a9e968be52 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -453,3 +453,28 @@ Parameters: + `id` (required) - The ID of the project. + `branch` (required) - The name of the branch. + +## Admin fork relation + +Allows modification of the forked relationship between existing projects. . Available only for admins. + +### Create a forked from/to relation between existing projects. + +``` +POST /projects/:id/fork/:forked_from_id +``` + +Parameters: + ++ `id` (required) - The ID of the project ++ `forked_from_id:` (required) - The ID of the project that was forked from + +### Delete an existing forked from relationship + +``` +DELETE /projects/:id/fork +``` + +Parameter: + ++ `id` (required) - The ID of the project \ No newline at end of file diff --git a/doc/install/installation.md b/doc/install/installation.md index 9200d59725927b52629eb7c6ae3c37b60604d755..65865e1635bfc258dd9d9bdbe86fc9929f399982 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -42,11 +42,13 @@ up-to-date and install it. apt-get install sudo -y **Note:** -Vim is an editor that is used here whenever there are files that need to be -edited by hand. But, you can use any editor you like instead. +During this installation some files will need to be edited manually. +If you are familiar with vim set it as default editor with the commands below. +If you are not familiar with vim please skip this and keep using the default editor. - # Install vim + # Install vim and set as default editor sudo apt-get install -y vim + sudo update-alternatives --set editor /usr/bin/vim.basic Install the required packages: @@ -123,7 +125,7 @@ GitLab Shell is a ssh access and repository management software developed specia # Edit config and replace gitlab_url # with something like 'http://domain.com/' - sudo -u git -H vim config.yml + sudo -u git -H editor config.yml # Do setup 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, # Make sure to change "localhost" to the fully-qualified domain name of your # host serving GitLab where necessary - sudo -u git -H vim config/gitlab.yml + sudo -u git -H editor config/gitlab.yml # Make sure GitLab can write to the log/ and tmp/ directories sudo chown -R git log/ @@ -214,7 +216,7 @@ Make sure to edit both `gitlab.yml` and `unicorn.rb` to match your setup. # Change 'root' to 'gitlab' # Change 'secure password' with the value you have given to $password # You can keep the double quotes around the password - sudo -u git -H vim config/database.yml + sudo -u git -H editor config/database.yml # Make config/database.yml readable to git only 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: # Change YOUR_SERVER_FQDN to the fully-qualified # domain name of your host serving GitLab. - sudo vim /etc/nginx/sites-available/gitlab + sudo editor /etc/nginx/sites-available/gitlab ## Restart diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 14d6c0f9353835406e2101dd835cf31d2269b605..7fcc7eba9d2bd75ce22cd6312fdb61ee21cd1510 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -25,6 +25,12 @@ module API expose :id, :url, :created_at end + class ForkedFromProject < Grape::Entity + expose :id + expose :name, :name_with_namespace + expose :path, :path_with_namespace + end + class Project < Grape::Entity expose :id, :description, :default_branch, :public, :ssh_url_to_repo, :http_url_to_repo, :web_url expose :owner, using: Entities::UserBasic @@ -32,6 +38,7 @@ module API expose :path, :path_with_namespace expose :issues_enabled, :merge_requests_enabled, :wall_enabled, :wiki_enabled, :created_at, :last_activity_at expose :namespace + expose :forked_from_project, using: Entities::ForkedFromProject, :if => lambda{ | project, options | project.forked? } end class ProjectMember < UserBasic diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 94cf4f2e69f75b739495933fd6476000ef07a11d..f857d4133b21fde3f1392a2d9282c844b2c13a2a 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -5,12 +5,12 @@ module API end def user_project - @project ||= find_project + @project ||= find_project(params[:id]) @project || not_found! end - def find_project - project = Project.find_by_id(params[:id]) || Project.find_with_namespace(params[:id]) + def find_project(id) + project = Project.find_by_id(id) || Project.find_with_namespace(id) if project && can?(current_user, :read_project, project) project diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 6dc051e4ba27a3530d22abd338da7dca3bd7f16a..d5709f5cb594001b0d428194ca547aa529792ec4 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -121,6 +121,42 @@ module API end + # Mark this project as forked from another + # + # Parameters: + # id: (required) - The ID of the project being marked as a fork + # forked_from_id: (required) - The ID of the project it was forked from + # Example Request: + # POST /projects/:id/fork/:forked_from_id + post ":id/fork/:forked_from_id" do + authenticated_as_admin! + forked_from_project = find_project(params[:forked_from_id]) + unless forked_from_project.nil? + if user_project.forked_from_project.nil? + user_project.create_forked_project_link(forked_to_project_id: user_project.id, forked_from_project_id: forked_from_project.id) + else + render_api_error!("Project already forked", 409) + end + else + not_found! + end + + end + + # Remove a forked_from relationship + # + # Parameters: + # id: (required) - The ID of the project being marked as a fork + # Example Request: + # DELETE /projects/:id/fork + delete ":id/fork" do + authenticated_as_admin! + unless user_project.forked_project_link.nil? + user_project.forked_project_link.destroy + end + end + + # Get a project team members # # Parameters: diff --git a/lib/redcarpet/render/gitlab_html.rb b/lib/redcarpet/render/gitlab_html.rb index 318adbf1894280d934533ce38b095de4a2909e52..d9c2d3b626d70b192873d2c5866c63fd56f0723a 100644 --- a/lib/redcarpet/render/gitlab_html.rb +++ b/lib/redcarpet/render/gitlab_html.rb @@ -12,7 +12,7 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML def block_code(code, language) options = { options: {encoding: 'utf-8'} } lexer = Pygments::Lexer.find(language) # language can be an alias - options.merge!(lexer: lexer.name.downcase) if lexer # downcase is required + options.merge!(lexer: lexer.aliases[0].downcase) if lexer # downcase is required # New lines are placed to fix an rendering issue # with code wrapped inside <h1> tag for next case: diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 437722c774cd9e7bec9841ea2c19556c424b61af..300bff288712290d2a9651fc8c181201bae400cb 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -595,4 +595,71 @@ describe API::API do end end end + + describe :fork_admin do + let(:project_fork_target) { create(:project) } + let(:project_fork_source) { create(:project, public: true) } + + describe "POST /projects/:id/fork/:forked_from_id" do + let(:new_project_fork_source) { create(:project, public: true) } + + it "shouldn't available for non admin users" do + post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", user) + response.status.should == 403 + end + + it "should allow project to be forked from an existing project" do + project_fork_target.forked?.should_not be_true + post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin) + response.status.should == 201 + project_fork_target.reload + project_fork_target.forked_from_project.id.should == project_fork_source.id + project_fork_target.forked_project_link.should_not be_nil + project_fork_target.forked?.should be_true + end + + it "should fail if forked_from project which does not exist" do + post api("/projects/#{project_fork_target.id}/fork/9999", admin) + response.status.should == 404 + end + + it "should fail with 409 if already forked" do + post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin) + project_fork_target.reload + project_fork_target.forked_from_project.id.should == project_fork_source.id + post api("/projects/#{project_fork_target.id}/fork/#{new_project_fork_source.id}", admin) + response.status.should == 409 + project_fork_target.reload + project_fork_target.forked_from_project.id.should == project_fork_source.id + project_fork_target.forked?.should be_true + end + end + + describe "DELETE /projects/:id/fork" do + + it "shouldn't available for non admin users" do + delete api("/projects/#{project_fork_target.id}/fork", user) + response.status.should == 403 + end + + it "should make forked project unforked" do + post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin) + project_fork_target.reload + project_fork_target.forked_from_project.should_not be_nil + project_fork_target.forked?.should be_true + delete api("/projects/#{project_fork_target.id}/fork", admin) + response.status.should == 200 + project_fork_target.reload + project_fork_target.forked_from_project.should be_nil + project_fork_target.forked?.should_not be_true + end + + it "should be idempotent if not forked" do + project_fork_target.forked_from_project.should be_nil + delete api("/projects/#{project_fork_target.id}/fork", admin) + response.status.should == 200 + project_fork_target.reload.forked_from_project.should be_nil + end + end + end end