From e9ef274bb24218f49d6a7e12210df223150434f7 Mon Sep 17 00:00:00 2001 From: Antonio Huete Jimenez Date: Fri, 19 Jun 2015 09:01:35 +0200 Subject: [PATCH 001/174] Use whoami instead of $USER - Use whoami instead of relying on the existence of $USER enviroment variable which is not always present --- lib/support/init.d/gitlab | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab index 946902e2f6d..a3455728a94 100755 --- a/lib/support/init.d/gitlab +++ b/lib/support/init.d/gitlab @@ -41,7 +41,7 @@ shell_path="/bin/bash" test -f /etc/default/gitlab && . /etc/default/gitlab # Switch to the app_user if it is not he/she who is running the script. -if [ "$USER" != "$app_user" ]; then +if [ `whoami` != "$app_user" ]; then eval su - "$app_user" -s $shell_path -c $(echo \")$0 "$@"$(echo \"); exit; fi From bb50b7fcd0161a7b9f0f87cb395e355a87a9dd17 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Mon, 6 Jul 2015 18:43:17 +0200 Subject: [PATCH 002/174] Allow custom backup archive permissions This change helps system administrators who want to replicate GitLab backup files without needing root permissions. --- CHANGELOG | 1 + config/gitlab.yml.example | 1 + config/initializers/1_settings.rb | 1 + doc/raketasks/backup_restore.md | 17 +++++++++++++++++ lib/backup/manager.rb | 6 +++--- 5 files changed, 23 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index d538bb42992..1c2155c0f9c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -37,6 +37,7 @@ v 7.13.0 (unreleased) - Correctly show anonymous authorized applications under Profile > Applications. - Query Optimization in MySQL. - Allow users to be blocked and unblocked via the API + - Allow custom backup archive permissions v 7.12.2 - Correctly show anonymous authorized applications under Profile > Applications. diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index c32ac2042d0..542106e86dd 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -247,6 +247,7 @@ production: &base ## Backup settings backup: path: "tmp/backups" # Relative paths are relative to Rails.root (default: tmp/backups/) + # archive_permissions: 0640 # Permissions for the resulting backup.tar file (default: 0600) # keep_time: 604800 # default: 0 (forever) (in seconds) # upload: # # Fog storage connection settings, see http://fog.io/storage/ . diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index 7b5d488f59e..bd76c918485 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -170,6 +170,7 @@ Settings.gitlab_shell['ssh_path_prefix'] ||= Settings.send(:build_gitlab_shell_s Settings['backup'] ||= Settingslogic.new({}) Settings.backup['keep_time'] ||= 0 Settings.backup['path'] = File.expand_path(Settings.backup['path'] || "tmp/backups/", Rails.root) +Settings.backup['archive_permissions'] ||= 0600 Settings.backup['upload'] ||= Settingslogic.new({ 'remote_directory' => nil, 'connection' => nil }) # Convert upload connection settings to use symbol keys, to make Fog happy if Settings.backup['upload']['connection'] diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md index 39a13b14fba..4a2e2df357a 100644 --- a/doc/raketasks/backup_restore.md +++ b/doc/raketasks/backup_restore.md @@ -141,6 +141,23 @@ with the name of your bucket: } ``` +## Backup archive permissions + +The backup archives created by GitLab (123456_gitlab_backup.tar) will have owner/group git:git and 0600 permissions by default. +This is meant to avoid other system users reading GitLab's data. +If you need the backup archives to have different permissions you can use the 'archive_permissions' setting. + +``` +# In /etc/gitlab/gitlab.rb, for omnibus packages +gitlab_rails['backup_archive_permissions'] = 0644 # Makes the backup archives world-readable +``` + +``` +# In gitlab.yml, for installations from source: + backup: + archive_permissions: 0644 # Makes the backup archives world-readable +``` + ## Storing configuration files Please be informed that a backup does not store your configuration files. diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb index 6fa2079d1a8..5103b265ed4 100644 --- a/lib/backup/manager.rb +++ b/lib/backup/manager.rb @@ -20,14 +20,14 @@ module Backup # create archive $progress.print "Creating backup archive: #{tar_file} ... " - orig_umask = File.umask(0077) - if Kernel.system('tar', '-cf', tar_file, *backup_contents) + # Set file permissions on open to prevent chmod races. + tar_system_options = {out: [tar_file, 'w', Gitlab.config.backup.archive_permissions]} + if Kernel.system('tar', '-cf', '-', *backup_contents, tar_system_options) $progress.puts "done".green else puts "creating archive #{tar_file} failed".red abort 'Backup failed' end - File.umask(orig_umask) upload(tar_file) end From 0194dd4182778b6bbf6b02f5d57e995ecbb43066 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 7 Jul 2015 19:03:29 +0200 Subject: [PATCH 003/174] Add tests for custom backup archive file permissions --- spec/tasks/gitlab/backup_rake_spec.rb | 31 +++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb index cdcfeba8d1f..e1f4a887dcc 100644 --- a/spec/tasks/gitlab/backup_rake_spec.rb +++ b/spec/tasks/gitlab/backup_rake_spec.rb @@ -60,7 +60,7 @@ describe 'gitlab:app namespace rake task' do Dir.glob(File.join(Gitlab.config.backup.path, '*_gitlab_backup.tar')) end - before :all do + def create_backup # Record the existing backup tars so we don't touch them existing_tars = tars_glob @@ -73,13 +73,36 @@ describe 'gitlab:app namespace rake task' do @backup_tar = (tars_glob - existing_tars).first end + before :all do + create_backup + end + after :all do FileUtils.rm(@backup_tar) end - it 'should set correct permissions on the tar file' do - expect(File.exist?(@backup_tar)).to be_truthy - expect(File::Stat.new(@backup_tar).mode.to_s(8)).to eq('100600') + context 'archive file permissions' do + it 'should set correct permissions on the tar file' do + expect(File.exist?(@backup_tar)).to be_truthy + expect(File::Stat.new(@backup_tar).mode.to_s(8)).to eq('100600') + end + + context 'with custom archive_permissions' do + before do + allow(Gitlab.config.backup).to receive(:archive_permissions).and_return(0651) + # We created a backup in a before(:all) so it got the default permissions. + # We now need to do some work to create a _new_ backup file using our stub. + FileUtils.rm(@backup_tar) + Rake::Task["gitlab:backup:db:create"].reenable + Rake::Task["gitlab:backup:repo:create"].reenable + Rake::Task["gitlab:backup:uploads:create"].reenable + create_backup + end + + it 'uses the custom permissions' do + expect(File::Stat.new(@backup_tar).mode.to_s(8)).to eq('100651') + end + end end it 'should set correct permissions on the tar contents' do From 64f60340918d3f4aa3c1d33b89d8dc90bcd96de7 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Wed, 8 Jul 2015 20:07:56 +0200 Subject: [PATCH 004/174] More hacks to get the specs working again --- spec/tasks/gitlab/backup_rake_spec.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb index e1f4a887dcc..7f0396795b8 100644 --- a/spec/tasks/gitlab/backup_rake_spec.rb +++ b/spec/tasks/gitlab/backup_rake_spec.rb @@ -97,6 +97,9 @@ describe 'gitlab:app namespace rake task' do Rake::Task["gitlab:backup:repo:create"].reenable Rake::Task["gitlab:backup:uploads:create"].reenable create_backup + Rake::Task["gitlab:backup:db:create"].reenable + Rake::Task["gitlab:backup:repo:create"].reenable + Rake::Task["gitlab:backup:uploads:create"].reenable end it 'uses the custom permissions' do From 4612599e5eb94e09f539a3fbbc3a1eaeaa96a3c7 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 9 Jul 2015 12:11:35 +0200 Subject: [PATCH 005/174] Remove rake task re-enabling into a method --- spec/tasks/gitlab/backup_rake_spec.rb | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb index 7f0396795b8..ec06670ba19 100644 --- a/spec/tasks/gitlab/backup_rake_spec.rb +++ b/spec/tasks/gitlab/backup_rake_spec.rb @@ -73,6 +73,12 @@ describe 'gitlab:app namespace rake task' do @backup_tar = (tars_glob - existing_tars).first end + def reenable_backup_sub_tasks + Rake::Task["gitlab:backup:db:create"].reenable + Rake::Task["gitlab:backup:repo:create"].reenable + Rake::Task["gitlab:backup:uploads:create"].reenable + end + before :all do create_backup end @@ -93,13 +99,9 @@ describe 'gitlab:app namespace rake task' do # We created a backup in a before(:all) so it got the default permissions. # We now need to do some work to create a _new_ backup file using our stub. FileUtils.rm(@backup_tar) - Rake::Task["gitlab:backup:db:create"].reenable - Rake::Task["gitlab:backup:repo:create"].reenable - Rake::Task["gitlab:backup:uploads:create"].reenable + reenable_backup_sub_tasks create_backup - Rake::Task["gitlab:backup:db:create"].reenable - Rake::Task["gitlab:backup:repo:create"].reenable - Rake::Task["gitlab:backup:uploads:create"].reenable + reenable_backup_sub_tasks end it 'uses the custom permissions' do From ec72aaeae7c478c671c11bd678c3bd22d79e1549 Mon Sep 17 00:00:00 2001 From: karen Carias Date: Thu, 9 Jul 2015 15:33:42 -0700 Subject: [PATCH 006/174] added new doc about creating a new branch --- doc/gitlab-basics/README.md | 2 ++ doc/gitlab-basics/basic-git-commands.md | 29 ++++++++++------- doc/gitlab-basics/command-line-commands.md | 30 ++++++++++-------- doc/gitlab-basics/create-branch.md | 37 ++++++++++++++++++++++ doc/gitlab-basics/create-project.md | 8 ++--- doc/gitlab-basics/create-your-ssh-keys.md | 20 ++++++------ doc/gitlab-basics/start-using-git.md | 36 +++++++++------------ 7 files changed, 100 insertions(+), 62 deletions(-) create mode 100644 doc/gitlab-basics/create-branch.md diff --git a/doc/gitlab-basics/README.md b/doc/gitlab-basics/README.md index 3e4400b544b..63fa7a90a26 100644 --- a/doc/gitlab-basics/README.md +++ b/doc/gitlab-basics/README.md @@ -13,3 +13,5 @@ Step-by-step guides on the basics of working with Git and GitLab. * [Create a project](create-project.md) * [Create a group](create-group.md) + +* [Create a branch](create-branch.md) diff --git a/doc/gitlab-basics/basic-git-commands.md b/doc/gitlab-basics/basic-git-commands.md index ed210ba5420..52465c24319 100644 --- a/doc/gitlab-basics/basic-git-commands.md +++ b/doc/gitlab-basics/basic-git-commands.md @@ -1,58 +1,63 @@ # Basic Git commands -* Go to the master branch to pull the latest changes from there +### Go to the master branch to pull the latest changes from there ``` git checkout master ``` -* Download the latest changes in the project, so that you work on an up-to-date copy (this is important to do every time you work on a project), while you setup tracking branches +### Download the latest changes in the project +This is for you to work on an up-to-date copy (it is important to do every time you work on a project), while you setup tracking branches. ``` git pull REMOTE NAME-OF-BRANCH -u ``` (REMOTE: origin) (NAME-OF-BRANCH: could be "master" or an existing branch) -* Create a branch (remember that spaces won't be recognized, you need to use a hyphen or underscore) +### Create a branch +Spaces won't be recognized, so you need to use a hyphen or underscore. ``` git checkout -b NAME-OF-BRANCH ``` -* Work on a branch that has already been created +### Work on a branch that has already been created ``` git checkout NAME-OF-BRANCH ``` -* To see the changes you've made (it's important to be aware of what's happening and what's the status of your changes) +### View the changes you've made +It's important to be aware of what's happening and what's the status of your changes. ``` git status ``` -* Add changes to commit (you'll be able to see your changes in red when you type "git status") +### Add changes to commit +You'll see your changes in red when you type "git status". ``` git add CHANGES IN RED git commit -m "DESCRIBE THE INTENTION OF THE COMMIT" ``` -* Send changes to gitlab.com +### Send changes to gitlab.com ``` -git push origin NAME-OF-BRANCH +git push REMOTE NAME-OF-BRANCH ``` -* Throw away all changes in the Git repository, but leave unstaged things +### Delete all changes in the Git repository, but leave unstaged things ``` git checkout . ``` -* Delete all changes in the Git repository, including untracked files +### Delete all changes in the Git repository, including untracked files ``` git clean -f ``` -* Remove all the changes that you don't want to send to gitlab.com +### Remove all the changes that you don't want to send to gitlab.com ``` git add NAME-OF-FILE -all ``` -* Merge created branch with master branch. You need to be in the created branch +### Merge created branch with master branch +You need to be in the created branch. ``` git checkout NAME-OF-BRANCH git merge master diff --git a/doc/gitlab-basics/command-line-commands.md b/doc/gitlab-basics/command-line-commands.md index a596bf20c74..a8223a9b161 100644 --- a/doc/gitlab-basics/command-line-commands.md +++ b/doc/gitlab-basics/command-line-commands.md @@ -2,46 +2,47 @@ ## Start working on your project -* In Git, when you copy a project you say you "clone" it. To work on a git project locally (from your own computer), you will need to clone it. To do this, sign in to [GitLab.com](https://gitlab.com) +In Git, when you copy a project you say you "clone" it. To work on a git project locally (from your own computer), you will need to clone it. To do this, sign in to [GitLab.com](https://gitlab.com). -* When you are on your Dashboard, click on the project that you'd like to clone, which you'll find at the right side of your screen +When you are on your Dashboard, click on the project that you'd like to clone, which you'll find at the right side of your screen. ![Select a project](basicsimages/select_project.png) -* To work in the project, you can copy a link to the Git repository through a SSH or a HTTPS protocol. SSH is easier to use after it's been [setup](create-your-ssh-keys.md). When you're in the project, click on the HTTPS or SSH button at the right side of your screen. Then copy the link (you'll have to paste it on your shell in the next step) +To work in the project, you can copy a link to the Git repository through a SSH or a HTTPS protocol. SSH is easier to use after it's been [setup](create-your-ssh-keys.md). When you're in the project, click on the HTTPS or SSH button at the right side of your screen. Then copy the link (you'll have to paste it on your shell in the next step). ![Copy the HTTPS or SSH](basicsimages/https.png) ## On the command line -* To clone your project, go to your computer's shell and type the following command +### Clone your project +Go to your computer's shell and type the following command: ``` git clone PASTE HTTPS OR SSH HERE ``` -* A clone of the project will be created in your computer +A clone of the project will be created in your computer. -* Go into a project, directory or file to work in it +### Go into a project, directory or file to work in it ``` cd NAME-OF-PROJECT-OR-FILE ``` -* Go back one directory or file +### Go back one directory or file ``` cd ../ ``` -* To see what’s in the directory that you are in +### View what’s in the directory that you are in ``` ls ``` -* Create a directory +### Create a directory ``` mkdir NAME-OF-YOUR-DIRECTORY ``` -* Create a README.md or file in directory +### Create a README.md or file in directory ``` touch README.md nano README.md @@ -51,22 +52,23 @@ nano README.md #### Press: enter ``` -* Remove a file +### Remove a file ``` rm NAME-OF-FILE ``` -* Remove a directory and all of its contents +### Remove a directory and all of its contents ``` rm -rf NAME-OF-DIRECTORY ``` -* View history in the command line +### View history in the command line ``` history ``` -* Carry out commands for which the account you are using lacks authority. (You will be asked for an administrator’s password) +### Carry out commands for which the account you are using lacks authority +You will be asked for an administrator’s password. ``` sudo ``` diff --git a/doc/gitlab-basics/create-branch.md b/doc/gitlab-basics/create-branch.md new file mode 100644 index 00000000000..ea37bc377ed --- /dev/null +++ b/doc/gitlab-basics/create-branch.md @@ -0,0 +1,37 @@ +# How to create a branch + +To add changes to your project in GitLab, you should create a branch. + +To create a new branch, sign in to [gitlab.com](https://gitlab.com). + +Select a project on the right side of your screen: + +![Select a project](basicsimages/select_project.png) + +Click on "commits" on the menu on the left side of your screen: + +![Commits](basicsimages/commits.png) + +Click on the "branches" tab: + +![Branches](basicsimages/branches.png) + +Click on the "new branch" button on the right side of the screen: + +![New branch](basicsimages/newbranch.png) + +Fill out the information required: + +1. Add a name for your new branch (you can't add spaces, so you can use hyphens or underscores) + +1. On the "create from" space, add the word: master or the name of the master branch + +1. Click on the button "create branch" + +![Branch info](basicsimages/branch_info.png) + +After you created a new branch, click on the files on which you'll be working. + +You will be able to find and select the name of your branch in the white box next to the project's name: + +![Branch name](basicsimages/branch_name.png) diff --git a/doc/gitlab-basics/create-project.md b/doc/gitlab-basics/create-project.md index e3963f66010..90d40cb6c51 100644 --- a/doc/gitlab-basics/create-project.md +++ b/doc/gitlab-basics/create-project.md @@ -1,14 +1,12 @@ # How to create a project in GitLab -## Create a project +To create a new project, sign in to [GitLab.com](https://gitlab.com). -* Sign in to [GitLab.com](https://gitlab.com) - -* Go to your Dashboard and click on "new project" on the right side of your screen +Go to your Dashboard and click on "new project" on the right side of your screen. ![Create a project](basicsimages/new_project.png) -* Fill out the required information +Fill out the required information: 1. Project path or the name of your project (you can't add spaces, so you can use hyphens or underscores) diff --git a/doc/gitlab-basics/create-your-ssh-keys.md b/doc/gitlab-basics/create-your-ssh-keys.md index cb699588cac..dcd3e6ffb31 100644 --- a/doc/gitlab-basics/create-your-ssh-keys.md +++ b/doc/gitlab-basics/create-your-ssh-keys.md @@ -4,34 +4,34 @@ You need to connect your computer to your GitLab account through SSH Keys. They ## Generate your SSH Key -* Create an account on GitLab. Sign up and check your email for your confirmation link +Create an account on GitLab. Sign up and check your email for your confirmation link. -* After you confirm, go to [GitLab.com](https://about.gitlab.com/) and sign in to your account +After you confirm, go to [GitLab.com](https://about.gitlab.com/) and sign in to your account. ## Add your SSH Key -* At the top right corner, click on "profile settings" +At the top right corner, click on "profile settings": ![profile settings](basicsimages/profile_settings.png) -* On the left side menu click on "SSH Keys" +On the left side menu click on "SSH Keys": ![SSH Keys](basicsimages/shh_keys.png) -* Then click on the green button "Add SSH Key" +Then click on the green button "Add SSH Key": ![Add SSH Key](basicsimages/add_sshkey.png) -* There, you should paste the SSH Key that your commandline will generate for you. Below you'll find the steps to generate it +There, you should paste the SSH Key that your command line will generate for you. Below you'll find the steps to generate it: ![Paste SSH Key](basicsimages/paste_sshkey.png) -## To generate an SSH Key on your commandline +## To generate an SSH Key on your command line -* Go to your [commandline](start-using-git.md) and follow the [instructions](../ssh/README.md) to generate it +Go to your [command line](start-using-git.md) and follow the [instructions](../ssh/README.md) to generate it. -* Copy the SSH Key that your commandline created and paste it on the "Key" box on the GitLab page. The title will be added automatically +Copy the SSH Key that your command line created and paste it on the "Key" box on the GitLab page. The title will be added automatically. ![Paste SSH Key](basicsimages/key.png) -* Now, you'll be able to use Git over SSH, instead of Git over HTTP. +Now, you'll be able to use Git over SSH, instead of Git over HTTP. diff --git a/doc/gitlab-basics/start-using-git.md b/doc/gitlab-basics/start-using-git.md index 21d93ed2e4d..5b1c6c1cd46 100644 --- a/doc/gitlab-basics/start-using-git.md +++ b/doc/gitlab-basics/start-using-git.md @@ -1,10 +1,10 @@ -# Start using Git on the commandline +# Start using Git on the command line -If you want to start using a Git and GitLab, make sure that you have created an account on [GitLab.com](https://about.gitlab.com/) +If you want to start using a Git and GitLab, make sure that you have created an account on [GitLab.com](https://about.gitlab.com/). ## Open a shell -* Depending on your operating system, find the shell of your preference. Here are some suggestions +Depending on your operating system, find the shell of your preference. Here are some suggestions. - [Terminal](http://blog.teamtreehouse.com/introduction-to-the-mac-os-x-command-line) on Mac OSX @@ -14,54 +14,48 @@ If you want to start using a Git and GitLab, make sure that you have created an ## Check if Git has already been installed -* Git is usually preinstalled on Mac and Linux - -* Type the following command and then press enter +Git is usually preinstalled on Mac and Linux. +Type the following command and then press enter: ``` git --version ``` -* You should receive a message that will tell you which Git version you have in your computer. If you don’t receive a "Git version" message, it means that you need to [download Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) +You should receive a message that will tell you which Git version you have in your computer. If you don’t receive a "Git version" message, it means that you need to [download Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git). -* If Git doesn't automatically download, there's an option on the website to [download manually](https://git-scm.com/downloads). Then follow the steps on the installation window +If Git doesn't automatically download, there's an option on the website to [download manually](https://git-scm.com/downloads). Then follow the steps on the installation window. -* After you finished installing, open a new shell and type "git --version" again to verify that it was correctly installed +After you finished installing, open a new shell and type "git --version" again to verify that it was correctly installed. ## Add your Git username and set your email -* It is important because every Git commit that you create will use this information - -* On your shell, type the following command to add your username +It is important because every Git commit that you create will use this information. +On your shell, type the following command to add your username: ``` git config --global user.name ADD YOUR USERNAME ``` -* Then verify that you have the correct username - +Then verify that you have the correct username: ``` git config --global user.name ``` -* To set your email address, type the following command - +To set your email address, type the following command: ``` git config --global user.email ADD YOUR EMAIL ``` -* To verify that you entered your email correctly, type - +To verify that you entered your email correctly, type: ``` git config --global user.email ``` -* You'll need to do this only once because you are using the "--global" option. It tells Git to always use this information for anything you do on that system. If you want to override this with a different username or email address for specific projects, you can run the command without the "--global" option when you’re in that project +You'll need to do this only once because you are using the "--global" option. It tells Git to always use this information for anything you do on that system. If you want to override this with a different username or email address for specific projects, you can run the command without the "--global" option when you’re in that project. ## Check your information -* To view the information that you entered, type - +To view the information that you entered, type: ``` git config --global --list ``` From 810ffab4b135024a76b2b68f0edbbbf76036d027 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 10 Jul 2015 14:44:07 +0200 Subject: [PATCH 007/174] Use a loop when enabling subtasks --- spec/tasks/gitlab/backup_rake_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb index ec06670ba19..476e22b8802 100644 --- a/spec/tasks/gitlab/backup_rake_spec.rb +++ b/spec/tasks/gitlab/backup_rake_spec.rb @@ -74,9 +74,9 @@ describe 'gitlab:app namespace rake task' do end def reenable_backup_sub_tasks - Rake::Task["gitlab:backup:db:create"].reenable - Rake::Task["gitlab:backup:repo:create"].reenable - Rake::Task["gitlab:backup:uploads:create"].reenable + %w{db repo uploads}.each do |subtask| + Rake::Task["gitlab:backup:#{subtask}:create"].reenable + end end before :all do From 414cacd7f47c8c89a6a270928bbf9c8d8dcbd3ab Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 9 Jul 2015 13:21:37 -0400 Subject: [PATCH 008/174] api: expose work_in_progress flag --- doc/api/merge_requests.md | 7 +++++-- lib/api/entities.rb | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md index 7b0873a9111..24c0b461308 100644 --- a/doc/api/merge_requests.md +++ b/doc/api/merge_requests.md @@ -49,7 +49,8 @@ Parameters: "state": "active", "created_at": "2012-04-29T08:46:00Z" }, - "description":"fixed login page css paddings" + "description":"fixed login page css paddings", + "work_in_progress": false } ] ``` @@ -94,7 +95,8 @@ Parameters: "state": "active", "created_at": "2012-04-29T08:46:00Z" }, - "description":"fixed login page css paddings" + "description":"fixed login page css paddings", + "work_in_progress": false } ``` @@ -118,6 +120,7 @@ Parameters: "project_id": 4, "title": "Blanditiis beatae suscipit hic assumenda et molestias nisi asperiores repellat et.", "description": "Qui voluptatibus placeat ipsa alias quasi. Deleniti rem ut sint. Optio velit qui distinctio.", + "work_in_progress": false, "state": "reopened", "created_at": "2015-02-02T19:49:39.159Z", "updated_at": "2015-02-02T20:08:49.959Z", diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 31202fa8c1f..ecf1412dee5 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -171,6 +171,7 @@ module API expose :source_project_id, :target_project_id expose :label_names, as: :labels expose :description + expose :work_in_progress?, as: :work_in_progress expose :milestone, using: Entities::Milestone end From 10e8fd46b1b6b91adb253c08dba4eb53fb2a6f6d Mon Sep 17 00:00:00 2001 From: karen Carias Date: Fri, 10 Jul 2015 16:09:52 -0700 Subject: [PATCH 009/174] fixed info in doc --- doc/gitlab-basics/create-branch.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/gitlab-basics/create-branch.md b/doc/gitlab-basics/create-branch.md index ea37bc377ed..b0a26176b31 100644 --- a/doc/gitlab-basics/create-branch.md +++ b/doc/gitlab-basics/create-branch.md @@ -1,10 +1,11 @@ # How to create a branch -To add changes to your project in GitLab, you should create a branch. +A branch is an independent line of development. +New commits are recorded in the history for the current branch, which results in taking the source from someone’s repository (the place where the history of your work is stored) at certain point in time, and apply your own changes to it in the history of the project. -To create a new branch, sign in to [gitlab.com](https://gitlab.com). +To add changes to your GitLab project, you should create a branch. You can do it in your shell or in [GitLab.com](https://gitlab.com). -Select a project on the right side of your screen: +To create a new branch in [GitLab.com](https://gitlab.com), sign in and then select a project on the right side of your screen: ![Select a project](basicsimages/select_project.png) @@ -24,7 +25,7 @@ Fill out the information required: 1. Add a name for your new branch (you can't add spaces, so you can use hyphens or underscores) -1. On the "create from" space, add the word: master or the name of the master branch +1. On the "create from" space, add the the name of the branch you want to branch off from 1. Click on the button "create branch" From bbd3d2c39d2068411f8d8067655d6b139a8a4201 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 13 Jul 2015 11:27:25 +0200 Subject: [PATCH 010/174] Avoid copy of strings in memory for parsing git grep result Signed-off-by: Dmitriy Zaporozhets --- app/models/repository.rb | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/app/models/repository.rb b/app/models/repository.rb index 6262b5c4c92..c0bc1829e82 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -442,8 +442,7 @@ class Repository filename = nil startline = 0 - lines = result.lines - lines.each_with_index do |line, index| + result.each_line.each_with_index do |line, index| if line =~ /^.*:.*:\d+:/ ref, filename, startline = line.split(':') startline = startline.to_i - index @@ -451,11 +450,11 @@ class Repository end end - data = lines.map do |line| - line.sub(ref, '').sub(filename, '').sub(/^:-\d+-/, '').sub(/^::\d+:/, '') - end + data = "" - data = data.join("") + result.each_line do |line| + data << line.sub(ref, '').sub(filename, '').sub(/^:-\d+-/, '').sub(/^::\d+:/, '') + end OpenStruct.new( filename: filename, From 6f581841d5c01b39fcc9f5c013541136d861ebcc Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Mon, 13 Jul 2015 18:54:15 +0200 Subject: [PATCH 011/174] Remove author information from "post" in merge_requests API. From both experimenting with the API and reading the source code, this appears to not be used at all. My guess is this was copypasta from somewhere else. --- doc/api/merge_requests.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md index 7b0873a9111..7624fd3a3ef 100644 --- a/doc/api/merge_requests.md +++ b/doc/api/merge_requests.md @@ -336,14 +336,6 @@ Parameters: ```json { - "author": { - "id": 1, - "username": "admin", - "email": "admin@example.com", - "name": "Administrator", - "blocked": false, - "created_at": "2012-04-29T08:46:00Z" - }, "note": "text1" } ``` From 3020fa9945c9c15878ce043c961e764e02fa2511 Mon Sep 17 00:00:00 2001 From: karen Carias Date: Mon, 13 Jul 2015 12:44:50 -0700 Subject: [PATCH 012/174] added link to doc --- doc/gitlab-basics/basic-git-commands.md | 5 ----- doc/gitlab-basics/create-branch.md | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/doc/gitlab-basics/basic-git-commands.md b/doc/gitlab-basics/basic-git-commands.md index 52465c24319..2b5767dd2d3 100644 --- a/doc/gitlab-basics/basic-git-commands.md +++ b/doc/gitlab-basics/basic-git-commands.md @@ -51,11 +51,6 @@ git checkout . git clean -f ``` -### Remove all the changes that you don't want to send to gitlab.com -``` -git add NAME-OF-FILE -all -``` - ### Merge created branch with master branch You need to be in the created branch. ``` diff --git a/doc/gitlab-basics/create-branch.md b/doc/gitlab-basics/create-branch.md index b0a26176b31..3521de6bea3 100644 --- a/doc/gitlab-basics/create-branch.md +++ b/doc/gitlab-basics/create-branch.md @@ -3,9 +3,9 @@ A branch is an independent line of development. New commits are recorded in the history for the current branch, which results in taking the source from someone’s repository (the place where the history of your work is stored) at certain point in time, and apply your own changes to it in the history of the project. -To add changes to your GitLab project, you should create a branch. You can do it in your shell or in [GitLab.com](https://gitlab.com). +To add changes to your GitLab project, you should create a branch. You can do it in your [shell](basic-git-commands.md) or in [GitLab](https://gitlab.com). -To create a new branch in [GitLab.com](https://gitlab.com), sign in and then select a project on the right side of your screen: +To create a new branch in GitLab, sign in and then select a project on the right side of your screen: ![Select a project](basicsimages/select_project.png) From 753f34c8fa91e0caa9a305d49c28ef6dd9447be2 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 14 Jul 2015 19:46:51 +0200 Subject: [PATCH 013/174] Fix docker image --- docker/Dockerfile | 4 +++- docker/assets/wrapper | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 86f6c896a6d..05521af6963 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -30,7 +30,9 @@ RUN ( \ echo "" && \ echo "# Docker options" && \ echo "# Prevent Postgres from trying to allocate 25% of total memory" && \ - echo "postgresql['shared_buffers'] = '1MB'" ) >> /etc/gitlab/gitlab.rb + echo "postgresql['shared_buffers'] = '1MB'" ) >> /etc/gitlab/gitlab.rb && \ + mkdir -p /assets/ && \ + cp /etc/gitlab/gitlab.rb /assets/gitlab.rb # Expose web & ssh EXPOSE 443 80 22 diff --git a/docker/assets/wrapper b/docker/assets/wrapper index 966b2cab4a1..8bc8370fbc9 100755 --- a/docker/assets/wrapper +++ b/docker/assets/wrapper @@ -13,4 +13,9 @@ function entrypoint() { gitlab-ctl tail # tail all logs } +if [[ ! -e /etc/gitlab/gitlab.rb ]]; then + cp /assets/gitlab.rb /etc/gitlab/gitlab.rb + chmod 0600 /etc/gitlab/gitlab.rb +fi + entrypoint From 82bb5c5e03858db094654a5ecced67a193be7931 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Wed, 15 Jul 2015 13:53:40 +0200 Subject: [PATCH 014/174] Expire Rails cache entries after two weeks This should help prevent endless Redis growth. --- CHANGELOG | 3 +++ config/application.rb | 1 + 2 files changed, 4 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 12564b3bb56..3dcf76e23d0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,8 @@ Please view this file on the master branch, on stable branches it's out of date. +v 7.14.0 (unreleased) + - Expire Rails cache entries after two weeks to prevent endless Redis growth + v 7.13.0 (unreleased) - Only enable HSTS header for HTTPS and port 443 (Stan Hu) - Fix user autocomplete for unauthenticated users accessing public projects (Stan Hu) diff --git a/config/application.rb b/config/application.rb index 7e899cc3b5b..a96e22211e6 100644 --- a/config/application.rb +++ b/config/application.rb @@ -96,6 +96,7 @@ module Gitlab end redis_config_hash[:namespace] = 'cache:gitlab' + redis_config_hash[:expires_in] = 2.weeks # Cache should not grow forever config.cache_store = :redis_store, redis_config_hash # This is needed for gitlab-shell From d2479a25c761f2517f94048e6da888186317142b Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Wed, 15 Jul 2015 16:59:31 +0300 Subject: [PATCH 015/174] Time ago fix for compare page --- app/views/projects/merge_requests/branch_from.js.haml | 1 + app/views/projects/merge_requests/branch_to.js.haml | 1 + 2 files changed, 2 insertions(+) diff --git a/app/views/projects/merge_requests/branch_from.js.haml b/app/views/projects/merge_requests/branch_from.js.haml index 8372afa61b5..9210798f39c 100644 --- a/app/views/projects/merge_requests/branch_from.js.haml +++ b/app/views/projects/merge_requests/branch_from.js.haml @@ -1,2 +1,3 @@ :plain $(".mr_source_commit").html("#{commit_to_html(@commit, @source_project, false)}"); + $('.js-timeago').timeago() diff --git a/app/views/projects/merge_requests/branch_to.js.haml b/app/views/projects/merge_requests/branch_to.js.haml index f7ede0ded53..32fe2d535f3 100644 --- a/app/views/projects/merge_requests/branch_to.js.haml +++ b/app/views/projects/merge_requests/branch_to.js.haml @@ -1,2 +1,3 @@ :plain $(".mr_target_commit").html("#{commit_to_html(@commit, @target_project, false)}"); + $('.js-timeago').timeago() From 6096c0296d37287ca2612a7c88c120edc0e5dbb3 Mon Sep 17 00:00:00 2001 From: karen Carias Date: Wed, 15 Jul 2015 11:13:40 -0700 Subject: [PATCH 016/174] added note about chef --- docker/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docker/README.md b/docker/README.md index 293ca79f915..d684f75dda0 100644 --- a/docker/README.md +++ b/docker/README.md @@ -165,3 +165,4 @@ sudo docker push gitlab/gitlab-ce:latest Please see the [troubleshooting](troubleshooting.md) file in this directory. Note: We use `fig.yml` to have compatibility with fig and because docker-compose also supports it. +Our docker image runs chef at every start to generate GitLab configuration. From 4944df86fad5adc69451be519cf3a26407c718eb Mon Sep 17 00:00:00 2001 From: karen Carias Date: Wed, 15 Jul 2015 16:40:20 -0700 Subject: [PATCH 017/174] added additional space --- docker/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docker/README.md b/docker/README.md index d684f75dda0..dbd30682d37 100644 --- a/docker/README.md +++ b/docker/README.md @@ -165,4 +165,5 @@ sudo docker push gitlab/gitlab-ce:latest Please see the [troubleshooting](troubleshooting.md) file in this directory. Note: We use `fig.yml` to have compatibility with fig and because docker-compose also supports it. + Our docker image runs chef at every start to generate GitLab configuration. From c8758357b16c9b8d648c6be1bed9e002c73cd0de Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 16 Jul 2015 12:13:09 +0000 Subject: [PATCH 018/174] Document should start from h1 title. Also put badges on top for easier tracking --- README.md | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index f8ce5f22ec2..8b14d6a6b16 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,14 @@ +# GitLab + +[![build status](https://ci.gitlab.com/projects/1/status.png?ref=master)](https://ci.gitlab.com/projects/1?ref=master) +[![Build Status](https://semaphoreapp.com/api/v1/projects/2f1a5809-418b-4cc2-a1f4-819607579fe7/243338/badge.png)](https://semaphoreapp.com/gitlabhq/gitlabhq) +[![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.svg)](https://codeclimate.com/github/gitlabhq/gitlabhq) +[![Coverage Status](https://coveralls.io/repos/gitlabhq/gitlabhq/badge.png?branch=master)](https://coveralls.io/r/gitlabhq/gitlabhq?branch=master) + ## Canonical source The source of GitLab Community Edition is [hosted on GitLab.com](https://gitlab.com/gitlab-org/gitlab-ce/) and there are mirrors to make [contributing](CONTRIBUTING.md) as easy as possible. -# ![logo](https://about.gitlab.com/images/gitlab_logo.png) GitLab - ## Open source software to collaborate on code To see how GitLab looks please see the [features page on our website](https://about.gitlab.com/features/). @@ -23,16 +28,6 @@ There are two editions of GitLab. *GitLab Enterprise Edition (EE)* includes [extra features](https://about.gitlab.com/features/#compare) that are most useful for organizations with more than 100 users. To use EE and get official support please [become a subscriber](https://about.gitlab.com/pricing/). -## Code status - -- [![build status](https://ci.gitlab.com/projects/1/status.png?ref=master)](https://ci.gitlab.com/projects/1?ref=master) on ci.gitlab.com (master branch) - -- [![Build Status](https://semaphoreapp.com/api/v1/projects/2f1a5809-418b-4cc2-a1f4-819607579fe7/243338/badge.png)](https://semaphoreapp.com/gitlabhq/gitlabhq) - -- [![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.svg)](https://codeclimate.com/github/gitlabhq/gitlabhq) - -- [![Coverage Status](https://coveralls.io/repos/gitlabhq/gitlabhq/badge.png?branch=master)](https://coveralls.io/r/gitlabhq/gitlabhq?branch=master) - ## Website On [about.gitlab.com](https://about.gitlab.com/) you can find more information about: From 53d40b8ab1275fa39e1ae4b82a228ccf731045f9 Mon Sep 17 00:00:00 2001 From: karen Carias Date: Thu, 16 Jul 2015 11:18:10 -0700 Subject: [PATCH 019/174] changed some text --- doc/gitlab-basics/create-branch.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/gitlab-basics/create-branch.md b/doc/gitlab-basics/create-branch.md index 3521de6bea3..a8afbfe53d7 100644 --- a/doc/gitlab-basics/create-branch.md +++ b/doc/gitlab-basics/create-branch.md @@ -3,7 +3,7 @@ A branch is an independent line of development. New commits are recorded in the history for the current branch, which results in taking the source from someone’s repository (the place where the history of your work is stored) at certain point in time, and apply your own changes to it in the history of the project. -To add changes to your GitLab project, you should create a branch. You can do it in your [shell](basic-git-commands.md) or in [GitLab](https://gitlab.com). +To add changes to your GitLab project, you should create a branch. You can do it in your [shell](basic-git-commands.md) or in GitLab. To create a new branch in GitLab, sign in and then select a project on the right side of your screen: @@ -31,8 +31,8 @@ Fill out the information required: ![Branch info](basicsimages/branch_info.png) -After you created a new branch, click on the files on which you'll be working. - -You will be able to find and select the name of your branch in the white box next to the project's name: +### Note: + +You will be able to find and select the name of your branch in the white box next to a project's name: ![Branch name](basicsimages/branch_name.png) From 6c9f527b3f3f0c47438e0722792ca247a44e4964 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Thu, 16 Jul 2015 22:33:58 -0700 Subject: [PATCH 020/174] Return comments in created order in merge request API Closes #1832 --- CHANGELOG | 1 + lib/api/merge_requests.rb | 2 +- spec/requests/api/merge_requests_spec.rb | 6 ++++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 12564b3bb56..dbd3975095e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.13.0 (unreleased) + - Return comments in created order in merge request API (Stan Hu) - Only enable HSTS header for HTTPS and port 443 (Stan Hu) - Fix user autocomplete for unauthenticated users accessing public projects (Stan Hu) - Fix redirection to home page URL for unauthorized users (Daniel Gerhardt) diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb index aa43e1dffd9..ce21c699e8f 100644 --- a/lib/api/merge_requests.rb +++ b/lib/api/merge_requests.rb @@ -229,7 +229,7 @@ module API authorize! :read_merge_request, merge_request - present paginate(merge_request.notes), with: Entities::MRNote + present paginate(merge_request.notes.fresh), with: Entities::MRNote end # Post comment to merge request diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index 7030c105b58..29db035b2de 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -8,6 +8,7 @@ describe API::API, api: true do let!(:merge_request_closed) { create(:merge_request, state: "closed", author: user, assignee: user, source_project: project, target_project: project, title: "Closed test") } let!(:merge_request_merged) { create(:merge_request, state: "merged", author: user, assignee: user, source_project: project, target_project: project, title: "Merged test") } let!(:note) { create(:note_on_merge_request, author: user, project: project, noteable: merge_request, note: "a comment on a MR") } + let!(:note2) { create(:note_on_merge_request, author: user, project: project, noteable: merge_request, note: "another comment on a MR") } before do project.team << [user, :reporters] @@ -397,13 +398,14 @@ describe API::API, api: true do end describe "GET :id/merge_request/:merge_request_id/comments" do - it "should return merge_request comments" do + it "should return merge_request comments ordered by created_at" do get api("/projects/#{project.id}/merge_request/#{merge_request.id}/comments", user) expect(response.status).to eq(200) expect(json_response).to be_an Array - expect(json_response.length).to eq(1) + expect(json_response.length).to eq(2) expect(json_response.first['note']).to eq("a comment on a MR") expect(json_response.first['author']['id']).to eq(user.id) + expect(json_response.last['note']).to eq("another comment on a MR") end it "should return a 404 error if merge_request_id not found" do From 2590b16cb4c383221a7cef04a43802d43330ff1b Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Fri, 17 Jul 2015 09:50:37 +0000 Subject: [PATCH 021/174] Improve the layout of the readme. --- README.md | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 8b14d6a6b16..5034a5e0b48 100644 --- a/README.md +++ b/README.md @@ -41,14 +41,6 @@ On [about.gitlab.com](https://about.gitlab.com/) you can find more information a ## Requirements -GitLab requires the following software: - -- Ubuntu/Debian/CentOS/RHEL -- Ruby (MRI) 2.0 or 2.1 -- Git 1.7.10+ -- Redis 2.0+ -- MySQL or PostgreSQL - Please see the [requirements documentation](doc/install/requirements.md) for system requirements and more information about the supported operating systems. ## Installation @@ -59,6 +51,28 @@ There are various other options to install GitLab, please refer to the [installa You can access a new installation with the login **`root`** and password **`5iveL!fe`**, after login you are required to set a unique password. +## Install a development environment + +To work on GitLab itself, we recommend setting up your development environment with [the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit). +If you do not use the GitLab Development Kit you need to install and setup all the dependencies yourself, this is a lot of work and error prone. +One small thing you also have to do when installing it yourself is to copy the example development unicorn configuration file: + + cp config/unicorn.rb.example.development config/unicorn.rb + +Instructions on how to start GitLab and how to run the tests can be found in the [development section of the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit#development). + +## Software stack + +GitLab is a Ruby on Rails application that runs on the following software: + +- Ubuntu/Debian/CentOS/RHEL +- Ruby (MRI) 2.0 or 2.1 +- Git 1.7.10+ +- Redis 2.0+ +- MySQL or PostgreSQL + +For more information please see the [architecture documentation](http://doc.gitlab.com/ce/development/architecture.html). + ## Third-party applications There are a lot of [third-party applications integrating with GitLab](https://about.gitlab.com/applications/). These include GUI Git clients, mobile applications and API wrappers for various languages. @@ -71,16 +85,6 @@ Since 2011 a minor or major version of GitLab is released on the 22nd of every m For upgrading information please see our [update page](https://about.gitlab.com/update/). -## Install a development environment - -To work on GitLab itself, we recommend setting up your development environment with [the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit). -If you do not use the GitLab Development Kit you need to install and setup all the dependencies yourself, this is a lot of work and error prone. -One small thing you also have to do when installing it yourself is to copy the example development unicorn configuration file: - - cp config/unicorn.rb.example.development config/unicorn.rb - -Instructions on how to start GitLab and how to run the tests can be found in the [development section of the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit#development). - ## Documentation All documentation can be found on [doc.gitlab.com/ce/](http://doc.gitlab.com/ce/). From 5d168588c07b230f4698142e568b56b1938c56c5 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Fri, 17 Jul 2015 09:52:41 +0000 Subject: [PATCH 022/174] Update installation instructions. --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5034a5e0b48..74520786165 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,9 @@ Please see the [requirements documentation](doc/install/requirements.md) for sys ## Installation -The recommended way to install GitLab is using the provided [Omnibus packages](https://about.gitlab.com/downloads/). Compared to an installation from source, this is faster and less error prone. Just select your operating system, download the respective package (Debian or RPM) and install it using the system's package manager. +The recommended way to install GitLab is with the [Omnibus packages](https://about.gitlab.com/downloads/) on our package server. +Compared to an installation from source, this is faster and less error prone. +Just select your operating system, download the respective package (Debian or RPM) and install it using the system's package manager. There are various other options to install GitLab, please refer to the [installation page on the GitLab website](https://about.gitlab.com/installation/) for more information. From 95400db9c8008a7abb3dd5f876710d855a7082a7 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Fri, 17 Jul 2015 09:56:34 +0000 Subject: [PATCH 023/174] Clean up editions paragraph --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 74520786165..bd663b30f3e 100644 --- a/README.md +++ b/README.md @@ -22,11 +22,12 @@ To see how GitLab looks please see the [features page on our website](https://ab ## Editions -There are two editions of GitLab. -*GitLab [Community Edition](https://about.gitlab.com/features/) (CE)* is available without any costs under an MIT license. +There are two editions of GitLab: -*GitLab Enterprise Edition (EE)* includes [extra features](https://about.gitlab.com/features/#compare) that are most useful for organizations with more than 100 users. -To use EE and get official support please [become a subscriber](https://about.gitlab.com/pricing/). +- GitLab Community Edition (CE) is available freely under the MIT Expat license. +- GitLab Enterprise Edition (EE) includes [extra features](https://about.gitlab.com/features/#compare) that are more useful for organizations with more than 100 users. To use EE and get official support please [become a subscriber](https://about.gitlab.com/pricing/). + +Included with the GitLab Omnibus Packages is [GitLab CI](https://about.gitlab.com/gitlab-ci/) that can easily build, test and deploy code. ## Website From 881fbe5070331f934fff3441dbc0e65377b030bf Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 17 Jul 2015 13:59:40 +0200 Subject: [PATCH 024/174] Add more seed projects. Control amount with SIZE env variable Signed-off-by: Dmitriy Zaporozhets --- db/fixtures/development/04_project.rb | 35 ++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/db/fixtures/development/04_project.rb b/db/fixtures/development/04_project.rb index 87839770924..8f71198e47f 100644 --- a/db/fixtures/development/04_project.rb +++ b/db/fixtures/development/04_project.rb @@ -11,9 +11,42 @@ Sidekiq::Testing.inline! do 'https://github.com/twitter/flight.git', 'https://github.com/twitter/typeahead.js.git', 'https://github.com/h5bp/html5-boilerplate.git', + 'https://github.com/google/material-design-lite.git', + 'https://github.com/jlevy/the-art-of-command-line.git', + 'https://github.com/FreeCodeCamp/freecodecamp.git', + 'https://github.com/google/deepdream.git', + 'https://github.com/jtleek/datasharing.git', + 'https://github.com/WebAssembly/design.git', + 'https://github.com/airbnb/javascript.git', + 'https://github.com/tessalt/echo-chamber-js.git', + 'https://github.com/atom/atom.git', + 'https://github.com/ipselon/react-ui-builder.git', + 'https://github.com/mattermost/platform.git', + 'https://github.com/purifycss/purifycss.git', + 'https://github.com/facebook/nuclide.git', + 'https://github.com/wbkd/awesome-d3.git', + 'https://github.com/kilimchoi/engineering-blogs.git', + 'https://github.com/gilbarbara/logos.git', + 'https://github.com/gaearon/redux.git', + 'https://github.com/awslabs/s2n.git', + 'https://github.com/arkency/reactjs_koans.git', + 'https://github.com/twbs/bootstrap.git', + 'https://github.com/chjj/ttystudio.git', + 'https://github.com/DrBoolean/mostly-adequate-guide.git', + 'https://github.com/octocat/Spoon-Knife.git', + 'https://github.com/opencontainers/runc.git', + 'https://github.com/googlesamples/android-topeka.git' ] - project_urls.each_with_index do |url, i| + # You can specify how many projects you need during seed execution + size = if ENV['SIZE'].present? + ENV['SIZE'].to_i + else + 8 + end + + + project_urls.first(size).each_with_index do |url, i| group_path, project_path = url.split('/')[-2..-1] group = Group.find_by(path: group_path) From 67ca5a53f6df0c3d0f2598c777491c0548d76e50 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 17 Jul 2015 14:50:03 +0200 Subject: [PATCH 025/174] Build missing cache items in background job after each push Signed-off-by: Dmitriy Zaporozhets --- app/models/repository.rb | 23 +++++++++++++++++++++-- app/services/git_push_service.rb | 1 + app/services/git_tag_push_service.rb | 6 +++--- app/workers/project_cache_worker.rb | 9 +++++++++ lib/repository_cache.rb | 4 ++++ 5 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 app/workers/project_cache_worker.rb diff --git a/app/models/repository.rb b/app/models/repository.rb index 6262b5c4c92..bca14aa1a33 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -130,13 +130,32 @@ class Repository cache.fetch(:size) { raw_repository.size } end - def expire_cache + def cache_keys %i(size branch_names tag_names commit_count graph_log - readme version contribution_guide changelog license).each do |key| + readme version contribution_guide changelog license) + end + + def build_cache + cache_keys.each do |key| + unless cache.exist?(key) + send(key) + end + end + end + + def expire_cache + cache_keys.each do |key| cache.expire(key) end end + def rebuild_cache + cache_keys.each do |key| + cache.expire(key) + send(key) + end + end + def graph_log cache.fetch(:graph_log) do commits = raw_repository.log(limit: 6000, skip_merges: true, diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index 6135ae65007..c36113329ea 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -61,6 +61,7 @@ class GitPushService EventCreateService.new.push(project, user, @push_data) project.execute_hooks(@push_data.dup, :push_hooks) project.execute_services(@push_data.dup, :push_hooks) + ProjectCacheWorker.perform_async(project.id) end protected diff --git a/app/services/git_tag_push_service.rb b/app/services/git_tag_push_service.rb index 075a6118da2..1cc42b0b0ad 100644 --- a/app/services/git_tag_push_service.rb +++ b/app/services/git_tag_push_service.rb @@ -2,15 +2,15 @@ class GitTagPushService attr_accessor :project, :user, :push_data def execute(project, user, oldrev, newrev, ref) - @project, @user = project, user + project.repository.expire_cache + @project, @user = project, user @push_data = build_push_data(oldrev, newrev, ref) EventCreateService.new.push(project, user, @push_data) project.execute_hooks(@push_data.dup, :tag_push_hooks) project.execute_services(@push_data.dup, :tag_push_hooks) - - project.repository.expire_cache + ProjectCacheWorker.perform_async(project.id) true end diff --git a/app/workers/project_cache_worker.rb b/app/workers/project_cache_worker.rb new file mode 100644 index 00000000000..4c14565dce5 --- /dev/null +++ b/app/workers/project_cache_worker.rb @@ -0,0 +1,9 @@ +class ProjectCacheWorker + include Sidekiq::Worker + + sidekiq_options queue: :default + + def perform(project_id) + Project.find(project_id).repository.build_cache + end +end diff --git a/lib/repository_cache.rb b/lib/repository_cache.rb index fa016a170cd..639687067ec 100644 --- a/lib/repository_cache.rb +++ b/lib/repository_cache.rb @@ -18,4 +18,8 @@ class RepositoryCache def fetch(key, &block) backend.fetch(cache_key(key), &block) end + + def exist?(key) + backend.exist?(key) + end end From f0116f13354fa1e57e3ba8013ea67d3b0e193375 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 17 Jul 2015 15:22:56 +0200 Subject: [PATCH 026/174] Store commit count in project table Signed-off-by: Dmitriy Zaporozhets --- app/helpers/projects_helper.rb | 14 ++++++++++++++ app/models/project.rb | 4 ++++ app/models/repository.rb | 12 ------------ app/services/git_push_service.rb | 1 - app/views/explore/projects/_project.html.haml | 2 +- app/views/projects/show.html.haml | 2 +- app/workers/project_cache_worker.rb | 5 ++++- app/workers/repository_import_worker.rb | 2 +- .../20150717130904_add_commits_count_to_project.rb | 5 +++++ db/schema.rb | 3 ++- lib/repository_cache.rb | 6 +++++- 11 files changed, 37 insertions(+), 19 deletions(-) create mode 100644 db/migrate/20150717130904_add_commits_count_to_project.rb diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 78f24dbd7ef..f61baf00525 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -276,4 +276,18 @@ module ProjectsHelper def readme_cache_key [@project.id, @project.commit.sha, "readme"].join('-') end + + def round_commit_count(project) + count = project.commit_count + + if count > 10000 + '10000+' + elsif count > 5000 + '5000+' + elsif count > 1000 + '1000+' + else + count + end + end end diff --git a/app/models/project.rb b/app/models/project.rb index b161cbe86b9..ff372ea9aa5 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -683,6 +683,10 @@ class Project < ActiveRecord::Base update_attribute(:repository_size, repository.size) end + def update_commit_count + update_attribute(:commit_count, repository.commit_count) + end + def forks_count ForkedProjectLink.where(forked_from_project_id: self.id).count end diff --git a/app/models/repository.rb b/app/models/repository.rb index bca14aa1a33..2985619fd2e 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -94,18 +94,6 @@ class Repository gitlab_shell.rm_tag(path_with_namespace, tag_name) end - def round_commit_count - if commit_count > 10000 - '10000+' - elsif commit_count > 5000 - '5000+' - elsif commit_count > 1000 - '1000+' - else - commit_count - end - end - def branch_names cache.fetch(:branch_names) { raw_repository.branch_names } end diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index c36113329ea..3511392d1d8 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -21,7 +21,6 @@ class GitPushService project.ensure_satellite_exists project.repository.expire_cache - project.update_repository_size if push_remove_branch?(ref, newrev) @push_commits = [] diff --git a/app/views/explore/projects/_project.html.haml b/app/views/explore/projects/_project.html.haml index d65fb529373..d769c91545d 100644 --- a/app/views/explore/projects/_project.html.haml +++ b/app/views/explore/projects/_project.html.haml @@ -14,7 +14,7 @@ .repo-info - unless project.empty_repo? - = link_to pluralize(project.repository.round_commit_count, 'commit'), namespace_project_commits_path(project.namespace, project, project.default_branch) + = link_to pluralize(round_commit_count(project), 'commit'), namespace_project_commits_path(project.namespace, project, project.default_branch) · = link_to pluralize(project.repository.branch_names.count, 'branch'), namespace_project_branches_path(project.namespace, project) · diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index 98d9053eb1d..b90cadfb1e2 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -13,7 +13,7 @@ %ul.nav.nav-pills %li = link_to namespace_project_commits_path(@project.namespace, @project, @ref || @repository.root_ref) do - = pluralize(number_with_delimiter(@repository.commit_count), 'commit') + = pluralize(number_with_delimiter(@project.commit_count), 'commit') %li = link_to namespace_project_branches_path(@project.namespace, @project) do = pluralize(number_with_delimiter(@repository.branch_names.count), 'branch') diff --git a/app/workers/project_cache_worker.rb b/app/workers/project_cache_worker.rb index 4c14565dce5..61416d634bd 100644 --- a/app/workers/project_cache_worker.rb +++ b/app/workers/project_cache_worker.rb @@ -4,6 +4,9 @@ class ProjectCacheWorker sidekiq_options queue: :default def perform(project_id) - Project.find(project_id).repository.build_cache + project = Project.find(project_id) + project.update_repository_size + project.update_commit_count + project.repository.build_cache end end diff --git a/app/workers/repository_import_worker.rb b/app/workers/repository_import_worker.rb index e6a50afedb1..94832872d13 100644 --- a/app/workers/repository_import_worker.rb +++ b/app/workers/repository_import_worker.rb @@ -28,7 +28,7 @@ class RepositoryImportWorker project.import_finish project.save project.satellite.create unless project.satellite.exists? - project.update_repository_size + ProjectCacheWorker.perform_async(project.id) Gitlab::BitbucketImport::KeyDeleter.new(project).execute if project.import_type == 'bitbucket' end end diff --git a/db/migrate/20150717130904_add_commits_count_to_project.rb b/db/migrate/20150717130904_add_commits_count_to_project.rb new file mode 100644 index 00000000000..9b46daa5933 --- /dev/null +++ b/db/migrate/20150717130904_add_commits_count_to_project.rb @@ -0,0 +1,5 @@ +class AddCommitsCountToProject < ActiveRecord::Migration + def change + add_column :projects, :commit_count, :integer, default: 0 + end +end diff --git a/db/schema.rb b/db/schema.rb index d6c34a77ee6..a63c2d05821 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20150713160110) do +ActiveRecord::Schema.define(version: 20150717130904) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -374,6 +374,7 @@ ActiveRecord::Schema.define(version: 20150713160110) do t.integer "star_count", default: 0, null: false t.string "import_type" t.string "import_source" + t.integer "commit_count", default: 0 end add_index "projects", ["created_at", "id"], name: "index_projects_on_created_at_and_id", using: :btree diff --git a/lib/repository_cache.rb b/lib/repository_cache.rb index 639687067ec..8ddc3511293 100644 --- a/lib/repository_cache.rb +++ b/lib/repository_cache.rb @@ -20,6 +20,10 @@ class RepositoryCache end def exist?(key) - backend.exist?(key) + backend.exist?(cache_key(key)) + end + + def read(key) + backend.read(cache_key(key)) end end From c3e35917fbfbe64a068e387207aa510d76852e61 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Fri, 17 Jul 2015 15:26:09 +0200 Subject: [PATCH 027/174] Validate format of project_url and token for GitLab CI service. --- app/models/project_services/gitlab_ci_service.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/models/project_services/gitlab_ci_service.rb b/app/models/project_services/gitlab_ci_service.rb index c284e19fe50..5aaa4e85cbc 100644 --- a/app/models/project_services/gitlab_ci_service.rb +++ b/app/models/project_services/gitlab_ci_service.rb @@ -22,8 +22,12 @@ class GitlabCiService < CiService API_PREFIX = "api/v1" prop_accessor :project_url, :token - validates :project_url, presence: true, if: :activated? - validates :token, presence: true, if: :activated? + validates :project_url, + presence: true, + format: { with: /\A#{URI.regexp(%w(http https))}\z/, message: "should be a valid url" }, if: :activated? + validates :token, + presence: true, + format: { with: /\A([A-Za-z0-9]+)\z/ }, if: :activated? after_save :compose_service_hook, if: :activated? From df2bb60f90315a77718b9122e9d06f5655750640 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Tue, 14 Jul 2015 15:20:38 -0700 Subject: [PATCH 028/174] Add support for destroying project milestones Closes https://github.com/gitlabhq/gitlabhq/issues/1504 --- CHANGELOG | 3 ++ .../projects/milestones_controller.rb | 7 ++++- .../projects/milestones/_milestone.html.haml | 4 +++ app/views/projects/milestones/show.html.haml | 3 ++ config/routes.rb | 2 +- features/project/issues/milestones.feature | 4 +++ features/steps/project/issues/milestones.rb | 8 ++++++ .../projects/milestones_controller_spec.rb | 28 +++++++++++++++++++ 8 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 spec/controllers/projects/milestones_controller_spec.rb diff --git a/CHANGELOG b/CHANGELOG index 12564b3bb56..e3b4ad130ba 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,8 @@ Please view this file on the master branch, on stable branches it's out of date. +v 7.14.0 (unreleased) + - Add support for destroying project milestones (Stan Hu) + v 7.13.0 (unreleased) - Only enable HSTS header for HTTPS and port 443 (Stan Hu) - Fix user autocomplete for unauthenticated users accessing public projects (Stan Hu) diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb index 61689488d13..9efe9704d1e 100644 --- a/app/controllers/projects/milestones_controller.rb +++ b/app/controllers/projects/milestones_controller.rb @@ -64,7 +64,12 @@ class Projects::MilestonesController < Projects::ApplicationController end def destroy - return access_denied! unless can?(current_user, :admin_milestone, @milestone) + return access_denied! unless can?(current_user, :admin_milestone, @project) + + update_params = { milestone: nil } + @milestone.issues.each do |issue| + Issues::UpdateService.new(@project, current_user, update_params).execute(issue) + end @milestone.destroy diff --git a/app/views/projects/milestones/_milestone.html.haml b/app/views/projects/milestones/_milestone.html.haml index 14a0580f966..2ce5358fa74 100644 --- a/app/views/projects/milestones/_milestone.html.haml +++ b/app/views/projects/milestones/_milestone.html.haml @@ -5,6 +5,10 @@ %i.fa.fa-pencil-square-o Edit = link_to 'Close Milestone', namespace_project_milestone_path(@project.namespace, @project, milestone, milestone: {state_event: :close }), method: :put, remote: true, class: "btn btn-sm btn-close" + = link_to namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone), data: { confirm: 'Are you sure?' }, method: :delete, class: "btn btn-sm btn-remove" do + %i.fa.fa-trash-o + Remove + %h4 = link_to_gfm truncate(milestone.title, length: 100), namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone) - if milestone.expired? and not milestone.closed? diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml index 5947498e379..7b1681df336 100644 --- a/app/views/projects/milestones/show.html.haml +++ b/app/views/projects/milestones/show.html.haml @@ -19,6 +19,9 @@ = link_to 'Close Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :close }), method: :put, class: "btn btn-close btn-grouped" - else = link_to 'Reopen Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :activate }), method: :put, class: "btn btn-reopen btn-grouped" + = link_to namespace_project_milestone_path(@project.namespace, @project, @milestone), data: { confirm: 'Are you sure?' }, method: :delete, class: "btn btn-grouped btn-remove" do + %i.fa.fa-trash-o + Remove %hr - if @milestone.issues.any? && @milestone.can_be_closed? diff --git a/config/routes.rb b/config/routes.rb index 055d59a0c93..2e16c3ecb39 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -481,7 +481,7 @@ Gitlab::Application.routes.draw do end end - resources :milestones, except: [:destroy], constraints: { id: /\d+/ } do + resources :milestones, constraints: { id: /\d+/ } do member do put :sort_issues put :sort_merge_requests diff --git a/features/project/issues/milestones.feature b/features/project/issues/milestones.feature index 9ac65b1257c..bfbaaec5a35 100644 --- a/features/project/issues/milestones.feature +++ b/features/project/issues/milestones.feature @@ -17,6 +17,10 @@ Feature: Project Issues Milestones And I submit new milestone "v2.3" Then I should see milestone "v2.3" + Scenario: I delete new milestone + Given I click link to remove milestone "v2.2" + And I should see no milestones + @javascript Scenario: Listing closed issues Given the milestone has open and closed issues diff --git a/features/steps/project/issues/milestones.rb b/features/steps/project/issues/milestones.rb index 708c5243947..61e62c2adbd 100644 --- a/features/steps/project/issues/milestones.rb +++ b/features/steps/project/issues/milestones.rb @@ -56,4 +56,12 @@ class Spinach::Features::ProjectIssuesMilestones < Spinach::FeatureSteps step 'I should see 3 issues' do expect(page).to have_selector('#tab-issues li.issue-row', count: 4) end + + step 'I click link to remove milestone "v2.2"' do + click_link 'Remove' + end + + step 'I should see no milestones' do + expect(page).to have_content('No milestones to show') + end end diff --git a/spec/controllers/projects/milestones_controller_spec.rb b/spec/controllers/projects/milestones_controller_spec.rb new file mode 100644 index 00000000000..d3868c13202 --- /dev/null +++ b/spec/controllers/projects/milestones_controller_spec.rb @@ -0,0 +1,28 @@ +require 'spec_helper' + +describe Projects::MilestonesController do + let(:project) { create(:project) } + let(:user) { create(:user) } + let(:milestone) { create(:milestone, project: project) } + let(:issue) { create(:issue, project: project, milestone: milestone) } + + before do + sign_in(user) + project.team << [user, :master] + controller.instance_variable_set(:@project, project) + end + + describe "#destroy" do + it "should remove milestone" do + expect(issue.milestone_id).to eq(milestone.id) + delete :destroy, namespace_id: project.namespace.id, project_id: project.id, id: milestone.id, format: :js + expect(response).to be_success + expect { Milestone.find(milestone.id) }.to raise_exception(ActiveRecord::RecordNotFound) + issue.reload + expect(issue.milestone_id).to eq(nil) + # Check system note left for milestone removal + last_note = project.issues.find(issue.id).notes[-1].note + expect(last_note).to eq('Milestone removed') + end + end +end From 302c52551a0155f3955144690f1b67ac4ef98282 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Fri, 17 Jul 2015 15:58:26 +0200 Subject: [PATCH 029/174] Fix failing specs after adding format verification for token and project url in gitlab ci service. --- spec/requests/api/projects_spec.rb | 2 +- spec/requests/api/services_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 4178bb2e836..5bd8206b890 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -89,7 +89,7 @@ describe API::API, api: true do it 'returns projects in the correct order when ci_enabled_first parameter is passed' do [project, project2, project3].each{ |project| project.build_missing_services } - project2.gitlab_ci_service.update(active: true, token: "token", project_url: "url") + project2.gitlab_ci_service.update(active: true, token: "token", project_url: "http://ci.example.com/projects/1") get api('/projects', user), { ci_enabled_first: 'true' } expect(response.status).to eq(200) expect(json_response).to be_an Array diff --git a/spec/requests/api/services_spec.rb b/spec/requests/api/services_spec.rb index 51c543578df..cedb5f15ead 100644 --- a/spec/requests/api/services_spec.rb +++ b/spec/requests/api/services_spec.rb @@ -7,7 +7,7 @@ describe API::API, api: true do describe "POST /projects/:id/services/gitlab-ci" do it "should update gitlab-ci settings" do - put api("/projects/#{project.id}/services/gitlab-ci", user), token: 'secret-token', project_url: "http://ci.example.com/projects/1" + put api("/projects/#{project.id}/services/gitlab-ci", user), token: 'secrettoken', project_url: "http://ci.example.com/projects/1" expect(response.status).to eq(200) end From 67654a44d13632e2bc8c5637baef4459a58d65b1 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 17 Jul 2015 16:03:38 +0200 Subject: [PATCH 030/174] Avoid cache building for super-weird case when repository root_ref is nil Signed-off-by: Dmitriy Zaporozhets --- app/workers/project_cache_worker.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/workers/project_cache_worker.rb b/app/workers/project_cache_worker.rb index 61416d634bd..55cb6af232e 100644 --- a/app/workers/project_cache_worker.rb +++ b/app/workers/project_cache_worker.rb @@ -7,6 +7,9 @@ class ProjectCacheWorker project = Project.find(project_id) project.update_repository_size project.update_commit_count - project.repository.build_cache + + if project.repository.root_ref + project.repository.build_cache + end end end From 559c363b1e0063550cf97de4f737daed9e0f3005 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 17 Jul 2015 16:32:06 +0200 Subject: [PATCH 031/174] The release manager owns the stable branches I think this helps the release manager because it means they don't have to worry about others pushing commits at the last minute. --- doc/release/monthly.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/release/monthly.md b/doc/release/monthly.md index 3bc92187218..ca9696e957e 100644 --- a/doc/release/monthly.md +++ b/doc/release/monthly.md @@ -6,6 +6,7 @@ It starts 7 working days before the release. The release manager doesn't have to perform all the work but must ensure someone is assigned. The current release manager must schedule the appointment of the next release manager. The new release manager should create overall issue to track the progress. +The release manager should be the only person pushing/merging commits to the x-y-stable branches. ## Release Manager From 5bac64552d7852691edb3fed80723bc74ee62e33 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Fri, 17 Jul 2015 07:32:17 -0700 Subject: [PATCH 032/174] Fix bug where clicking on the link icon on a file would result in "L#undefined" in the URL Closes #2002 --- app/assets/javascripts/line_highlighter.js.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/line_highlighter.js.coffee b/app/assets/javascripts/line_highlighter.js.coffee index a8b3c1fa33e..e604e6025c2 100644 --- a/app/assets/javascripts/line_highlighter.js.coffee +++ b/app/assets/javascripts/line_highlighter.js.coffee @@ -70,7 +70,7 @@ class @LineHighlighter @clearHighlight() - lineNumber = $(event.target).data('line-number') + lineNumber = $(event.target).closest('a').data('line-number') current = @hashToRange(@_hash) unless current[0] && event.shiftKey From c7daa5f17fdb45cb7acc058a3a418be19c42712a Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Fri, 17 Jul 2015 17:03:15 +0200 Subject: [PATCH 033/174] Add specs for gitlab ci service validity. --- .../gitlab_ci_service_spec.rb | 27 +++++++++++++++++++ spec/requests/api/services_spec.rb | 12 +++++++++ 2 files changed, 39 insertions(+) diff --git a/spec/models/project_services/gitlab_ci_service_spec.rb b/spec/models/project_services/gitlab_ci_service_spec.rb index fedc37c9b94..4f8a1986995 100644 --- a/spec/models/project_services/gitlab_ci_service_spec.rb +++ b/spec/models/project_services/gitlab_ci_service_spec.rb @@ -26,6 +26,33 @@ describe GitlabCiService do it { is_expected.to have_one(:service_hook) } end + describe 'validations' do + context 'active' do + before { allow(subject).to receive(:activated?).and_return(true) } + + it { is_expected.to validate_presence_of(:token) } + it { is_expected.to validate_presence_of(:project_url) } + it { is_expected.to allow_value('ewf9843kdnfdfs89234n').for(:token) } + it { is_expected.to allow_value('http://ci.example.com/project/1').for(:project_url) } + it { is_expected.not_to allow_value('token with spaces').for(:token) } + it { is_expected.not_to allow_value('token/with%spaces').for(:token) } + it { is_expected.not_to allow_value('this is not url').for(:project_url) } + it { is_expected.not_to allow_value('http//noturl').for(:project_url) } + it { is_expected.not_to allow_value('ftp://ci.example.com/projects/3').for(:project_url) } + end + + context 'inactive' do + before { allow(subject).to receive(:activated?).and_return(false) } + + it { is_expected.not_to validate_presence_of(:token) } + it { is_expected.not_to validate_presence_of(:project_url) } + it { is_expected.to allow_value('ewf9843kdnfdfs89234n').for(:token) } + it { is_expected.to allow_value('http://ci.example.com/project/1').for(:project_url) } + it { is_expected.to allow_value('token with spaces').for(:token) } + it { is_expected.to allow_value('ftp://ci.example.com/projects/3').for(:project_url) } + end + end + describe 'commits methods' do before do @service = GitlabCiService.new diff --git a/spec/requests/api/services_spec.rb b/spec/requests/api/services_spec.rb index cedb5f15ead..6d29a28580a 100644 --- a/spec/requests/api/services_spec.rb +++ b/spec/requests/api/services_spec.rb @@ -17,6 +17,18 @@ describe API::API, api: true do expect(response.status).to eq(400) end + + it "should return if the format of token is invalid" do + put api("/projects/#{project.id}/services/gitlab-ci", user), token: 'token-with dashes and spaces%', project_url: "http://ci.example.com/projects/1", active: true + + expect(response.status).to eq(404) + end + + it "should return if the format of token is invalid" do + put api("/projects/#{project.id}/services/gitlab-ci", user), token: 'token-with dashes and spaces%', project_url: "ftp://ci.example/projects/1", active: true + + expect(response.status).to eq(404) + end end describe "DELETE /projects/:id/services/gitlab-ci" do From 77f325a49fd955f73197a6270c82d28053e2c19e Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Fri, 17 Jul 2015 17:17:33 +0200 Subject: [PATCH 034/174] Do not disappoint rubocop. --- spec/models/project_services/gitlab_ci_service_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/models/project_services/gitlab_ci_service_spec.rb b/spec/models/project_services/gitlab_ci_service_spec.rb index 4f8a1986995..a14384c87b4 100644 --- a/spec/models/project_services/gitlab_ci_service_spec.rb +++ b/spec/models/project_services/gitlab_ci_service_spec.rb @@ -26,7 +26,7 @@ describe GitlabCiService do it { is_expected.to have_one(:service_hook) } end - describe 'validations' do + describe 'validations' do context 'active' do before { allow(subject).to receive(:activated?).and_return(true) } From 53d9f78043b9743e45cf170baca21d56d92af052 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 17 Jul 2015 18:21:47 +0200 Subject: [PATCH 035/174] Update changelog Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 3dcf76e23d0..1ae1f57b7a1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -49,6 +49,8 @@ v 7.13.0 (unreleased) - Faster code search in repository and wiki. Fixes search page timeout for big repositories - Allow administrators to disable 2FA for a specific user - Add error message for SSH key linebreaks + - Store commits count in database (will populate with valid values only after first push) + - Rebuild cache after push to repository in background job v 7.12.2 - Correctly show anonymous authorized applications under Profile > Applications. From 782500158608eba36e27f53e1d8822d25710fe80 Mon Sep 17 00:00:00 2001 From: Daniel Gerhardt Date: Fri, 10 Jul 2015 16:41:43 +0200 Subject: [PATCH 036/174] Fix file upload dialog for comment editing This fixes the file upload dialog which currently works for new comments but not for comment editing. The cause for this is a missing DOM class which causes traversal to the dropzone to fail. This is fixed by adding the expected `gfm-form` class to the edit form. It has to be added dynamically since adding it to the form template would break the form's layout and comment saving. --- CHANGELOG | 1 + app/assets/javascripts/notes.js.coffee | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 001d5350bad..c4877042fed 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.14.0 (unreleased) + - Fix file upload dialog for comment editing (Daniel Gerhardt) - Expire Rails cache entries after two weeks to prevent endless Redis growth - Add support for destroying project milestones (Stan Hu) diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee index 1c05a2b9fe8..bcff7bcc49e 100644 --- a/app/assets/javascripts/notes.js.coffee +++ b/app/assets/javascripts/notes.js.coffee @@ -298,7 +298,7 @@ class @Notes note.find(".note-header").hide() base_form = note.find(".note-edit-form") form = base_form.clone().insertAfter(base_form) - form.addClass('current-note-edit-form') + form.addClass('current-note-edit-form gfm-form') form.find('.div-dropzone').remove() # Show the attachment delete link From 5f4dcbf8be36e7c87afdc28afd7f2d663a9abf28 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Fri, 17 Jul 2015 16:17:04 -0700 Subject: [PATCH 037/174] Set OmniAuth full_host parameter to ensure redirect URIs are correct Closes #1967 --- CHANGELOG | 1 + config/initializers/7_omniauth.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 001d5350bad..38c56e91e1a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.14.0 (unreleased) + - Set OmniAuth full_host parameter to ensure redirect URIs are correct (Stan Hu) - Expire Rails cache entries after two weeks to prevent endless Redis growth - Add support for destroying project milestones (Stan Hu) diff --git a/config/initializers/7_omniauth.rb b/config/initializers/7_omniauth.rb index df73ec1304a..7f73546ac89 100644 --- a/config/initializers/7_omniauth.rb +++ b/config/initializers/7_omniauth.rb @@ -11,6 +11,7 @@ if Gitlab::LDAP::Config.enabled? end end +OmniAuth.config.full_host = Settings.gitlab['url'] OmniAuth.config.allowed_request_methods = [:post] #In case of auto sign-in, the GET method is used (users don't get to click on a button) OmniAuth.config.allowed_request_methods << :get if Gitlab.config.omniauth.auto_sign_in_with_provider.present? From dd6daf465624d0a4ec2bc232f647c0d484a82351 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Fri, 17 Jul 2015 20:40:56 -0400 Subject: [PATCH 038/174] Add test case for clicking line number anchor icon --- spec/javascripts/fixtures/line_highlighter.html.haml | 4 +++- spec/javascripts/line_highlighter_spec.js.coffee | 8 ++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/spec/javascripts/fixtures/line_highlighter.html.haml b/spec/javascripts/fixtures/line_highlighter.html.haml index 15ad1d8968f..da1ebcdb23c 100644 --- a/spec/javascripts/fixtures/line_highlighter.html.haml +++ b/spec/javascripts/fixtures/line_highlighter.html.haml @@ -2,7 +2,9 @@ .file-content .line-numbers - 1.upto(25) do |i| - %a{href: "#L#{i}", id: "L#{i}", 'data-line-number' => i}= i + %a{href: "#L#{i}", id: "L#{i}", 'data-line-number' => i} + %i.fa.fa-link + = i %pre.code.highlight %code - 1.upto(25) do |i| diff --git a/spec/javascripts/line_highlighter_spec.js.coffee b/spec/javascripts/line_highlighter_spec.js.coffee index 14fa487ff7f..57453c716a5 100644 --- a/spec/javascripts/line_highlighter_spec.js.coffee +++ b/spec/javascripts/line_highlighter_spec.js.coffee @@ -48,6 +48,14 @@ describe 'LineHighlighter', -> clickLine(13) expect(spy).toHaveBeenPrevented() + it 'handles clicking on a child icon element', -> + spy = spyOn(@class, 'setHash').and.callThrough() + + $('#L13 i').mousedown().click() + + expect(spy).toHaveBeenCalledWith(13) + expect($('#LC13')).toHaveClass(@css) + describe 'without shiftKey', -> it 'highlights one line when clicked', -> clickLine(13) From 58b94be9a7e97112755041e30559ebc2ca0a8b1d Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Sun, 12 Jul 2015 22:46:51 +0200 Subject: [PATCH 039/174] Only load byebug on MRI This Gem relies on MRI specific debugging APIs. This at least allows installation on Rubinius/JRuby. --- Gemfile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Gemfile b/Gemfile index 9b7fd18ab19..ba32feba3e7 100644 --- a/Gemfile +++ b/Gemfile @@ -46,7 +46,7 @@ gem "gitlab_git", '~> 7.2.5' gem 'gitlab-grack', '~> 2.0.2', require: 'grack' # LDAP Auth -# GitLab fork with several improvements to original library. For full list of changes +# GitLab fork with several improvements to original library. For full list of changes # see https://github.com/intridea/omniauth-ldap/compare/master...gitlabhq:master gem 'gitlab_omniauth-ldap', '1.2.1', require: "omniauth-ldap" @@ -54,9 +54,9 @@ gem 'gitlab_omniauth-ldap', '1.2.1', require: "omniauth-ldap" gem 'gollum-lib', '~> 4.0.2' # Language detection -# GitLab fork of linguist does not require pygments/python dependency. -# New version of original gem also dropped pygments support but it has strict -# dependency to unstable rugged version. We have internal issue for replacing +# GitLab fork of linguist does not require pygments/python dependency. +# New version of original gem also dropped pygments support but it has strict +# dependency to unstable rugged version. We have internal issue for replacing # fork with original gem when we meet on same rugged version - https://dev.gitlab.org/gitlab/gitlabhq/issues/2052. gem "gitlab-linguist", "~> 3.0.1", require: "linguist" @@ -227,7 +227,7 @@ end group :development, :test do gem 'awesome_print' - gem 'byebug' + gem 'byebug', platform: :mri gem 'fuubar', '~> 2.0.0' gem 'pry-rails' From 875d8e7f31db88443c3c573473b496945d7673a0 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 18 Jul 2015 07:32:18 -0700 Subject: [PATCH 040/174] Fix bug where notes were being rendered with wrong color preferences due to caching Closes #2008 --- app/views/projects/notes/_note.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/notes/_note.html.haml b/app/views/projects/notes/_note.html.haml index 5478a887f91..c8d705687da 100644 --- a/app/views/projects/notes/_note.html.haml +++ b/app/views/projects/notes/_note.html.haml @@ -56,7 +56,7 @@ .note-body{class: note_editable?(note) ? 'js-task-list-container' : ''} - = cache [note, 'markdown'] do + = cache [note, 'markdown', user_color_scheme_class] do .note-text = preserve do = markdown(note.note, {no_header_anchors: true}) From 682c0deffe4e1849a2dd5bd61d90aa08e4209681 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 18 Jul 2015 08:02:38 -0700 Subject: [PATCH 041/174] Remove redundant last push event if activity feed is set to main page Closes #2009 --- app/views/projects/show.html.haml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index b90cadfb1e2..769dd68f089 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -6,7 +6,9 @@ = render 'shared/no_ssh' = render 'shared/no_password' -= render 'projects/last_push' +- if prefer_readme? + = render 'projects/last_push' + = render "home_panel" .project-stats From a364d4260d357c10d45108da8f8ab55426c64fa2 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sat, 18 Jul 2015 17:54:56 -0400 Subject: [PATCH 042/174] Make username parameter for Users#show case-insensitive Closes #2012 --- app/controllers/users_controller.rb | 2 +- spec/controllers/users_controller_spec.rb | 35 ++++++++++++++++------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 2bb5c338cf6..a67325ae659 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -50,7 +50,7 @@ class UsersController < ApplicationController private def set_user - @user = User.find_by_username!(params[:username]) + @user = User.find_by!('lower(username) = ?', params[:username].downcase) unless current_user || @user.public_profile? return authenticate_user! diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index d47a37914df..9f89101d7f7 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -1,25 +1,38 @@ require 'spec_helper' describe UsersController do - let(:user) { create(:user, username: 'user1', name: 'User 1', email: 'user1@gitlab.com') } - - before do - sign_in(user) - end + let(:user) { create(:user) } describe 'GET #show' do - render_views + it 'is case-insensitive' do + user = create(:user, username: 'CamelCaseUser') + sign_in(user) - it 'renders the show template' do - get :show, username: user.username - expect(response.status).to eq(200) - expect(response).to render_template('show') + get :show, username: user.username.downcase + + expect(response).to be_success + end + + context 'with rendered views' do + render_views + + it 'renders the show template' do + sign_in(user) + + get :show, username: user.username + + expect(response).to be_success + expect(response).to render_template('show') + end end end describe 'GET #calendar' do it 'renders calendar' do + sign_in(user) + get :calendar, username: user.username + expect(response).to render_template('calendar') end end @@ -30,6 +43,8 @@ describe UsersController do before do allow_any_instance_of(User).to receive(:contributed_projects_ids).and_return([project.id]) + + sign_in(user) project.team << [user, :developer] end From f92bbd2f284530b0c05bc179a60ceb9751556026 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sat, 18 Jul 2015 18:05:07 -0400 Subject: [PATCH 043/174] Show the first tab automatically on MergeRequests#new Closes #2013 --- app/assets/javascripts/merge_request.js.coffee | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/merge_request.js.coffee b/app/assets/javascripts/merge_request.js.coffee index 7462975bd3d..b21cb7904b5 100644 --- a/app/assets/javascripts/merge_request.js.coffee +++ b/app/assets/javascripts/merge_request.js.coffee @@ -15,9 +15,7 @@ class @MergeRequest this.$('.show-all-commits').on 'click', => this.showAllCommits() - # `MergeRequests#new` has no tab-persisting or lazy-loading behavior - unless @opts.action == 'new' - new MergeRequestTabs(@opts) + @initTabs() # Prevent duplicate event bindings @disableTaskList() @@ -29,6 +27,14 @@ class @MergeRequest $: (selector) -> this.$el.find(selector) + initTabs: -> + if @opts.action != 'new' + # `MergeRequests#new` has no tab-persisting or lazy-loading behavior + new MergeRequestTabs(@opts) + else + # Show the first tab (Commits) + $('.merge-request-tabs a[data-toggle="tab"]:first').tab('show') + showAllCommits: -> this.$('.first-commits').remove() this.$('.all-commits').removeClass 'hide' From 19163f84fbec0e1798300c62745d1f747259eb61 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 18 Jul 2015 15:57:11 -0700 Subject: [PATCH 044/174] Fix OAuth provider bug where GitLab would not go return to the redirect_uri after sign-in Closes #1612 --- CHANGELOG | 1 + config/initializers/doorkeeper.rb | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index c4877042fed..9fe1e8c90c7 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.14.0 (unreleased) + - Fix OAuth provider bug where GitLab would not go return to the redirect_uri after sign-in (Stan Hu) - Fix file upload dialog for comment editing (Daniel Gerhardt) - Expire Rails cache entries after two weeks to prevent endless Redis growth - Add support for destroying project milestones (Stan Hu) diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb index d422acb31d6..6139ddbe6cd 100644 --- a/config/initializers/doorkeeper.rb +++ b/config/initializers/doorkeeper.rb @@ -6,7 +6,8 @@ Doorkeeper.configure do # This block will be called to check whether the resource owner is authenticated or not. resource_owner_authenticator do # Put your resource owner authentication logic here. - # Example implementation: + # Ensure user is redirected to redirect_uri after login + session[:user_return_to] = request.fullpath current_user || redirect_to(new_user_session_url) end From 69417d36b2fa4dfbe2205c4df1428eb17ebd061e Mon Sep 17 00:00:00 2001 From: Daniel Gerhardt Date: Sun, 19 Jul 2015 20:58:59 +0200 Subject: [PATCH 045/174] Fix label read access for unauthenticated users The label page was added to navigation for unauthorized users because the previously used milestone read permission was still checked. This has been fixed and read access to labels is now granted (again) for public projects. This regression has been introduced in 07efb17e10fe26a01b60d8441868f9fbda0768f2 (7.12). See also 9bcd36396b9b71467f66dd4ed79ab709bb5d027a. Refs !836, !842. --- CHANGELOG | 1 + app/helpers/projects_helper.rb | 6 +++++- app/models/ability.rb | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 9fe1e8c90c7..b1d079ef207 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.14.0 (unreleased) + - Fix label read access for unauthenticated users (Daniel Gerhardt) - Fix OAuth provider bug where GitLab would not go return to the redirect_uri after sign-in (Stan Hu) - Fix file upload dialog for comment editing (Daniel Gerhardt) - Expire Rails cache entries after two weeks to prevent endless Redis growth diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index f61baf00525..3cd52b381bd 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -131,8 +131,12 @@ module ProjectsHelper nav_tabs << :snippets end + if can?(current_user, :read_label, project) + nav_tabs << :labels + end + if can?(current_user, :read_milestone, project) - nav_tabs << [:milestones, :labels] + nav_tabs << :milestones end nav_tabs.flatten diff --git a/app/models/ability.rb b/app/models/ability.rb index d3631d49ec6..7dab50d47d4 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -35,6 +35,7 @@ class Ability :read_project, :read_wiki, :read_issue, + :read_label, :read_milestone, :read_project_snippet, :read_project_member, From e65b08106282015955fce52e818b7431d5cb2e83 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sun, 19 Jul 2015 16:48:33 -0400 Subject: [PATCH 046/174] Dynamically check `:admin_*` ability in issuable context Closes #2001 --- app/views/shared/issuable/_context.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/shared/issuable/_context.html.haml b/app/views/shared/issuable/_context.html.haml index 46990895d33..d1bd5ef968d 100644 --- a/app/views/shared/issuable/_context.html.haml +++ b/app/views/shared/issuable/_context.html.haml @@ -8,7 +8,7 @@ - else none .issuable-context-selectbox - - if can?(current_user, :admin_issue, @project) + - if can?(current_user, :"admin_#{issuable.class.to_s.underscore}", @project) = users_select_tag("#{issuable.class.table_name.singularize}[assignee_id]", placeholder: 'Select assignee', class: 'custom-form-control js-select2 js-assignee', selected: issuable.assignee_id, project: @target_project, null_user: true) %div.prepend-top-20.clearfix @@ -24,7 +24,7 @@ - else none .issuable-context-selectbox - - if can?(current_user, :admin_issue, @project) + - if can?(current_user, :"admin_#{issuable.class.to_s.underscore}", @project) = f.select(:milestone_id, milestone_options(issuable), { include_blank: 'Select milestone' }, {class: 'select2 select2-compact js-select2 js-milestone'}) = hidden_field_tag :issuable_context = f.submit class: 'btn hide' From 5eeab9f0a62f4843dcef2a7fb2f7f67610bef22d Mon Sep 17 00:00:00 2001 From: Sven Strickroth Date: Mon, 20 Jul 2015 00:53:43 +0200 Subject: [PATCH 047/174] GoogleCode importer: Do not care about casing of image file extensions Signed-off-by: Sven Strickroth --- lib/gitlab/google_code_import/importer.rb | 2 +- spec/fixtures/GoogleCodeProjectHosting.json | 5 +++++ spec/lib/gitlab/google_code_import/importer_spec.rb | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/gitlab/google_code_import/importer.rb b/lib/gitlab/google_code_import/importer.rb index 70bfe059776..03c410726a5 100644 --- a/lib/gitlab/google_code_import/importer.rb +++ b/lib/gitlab/google_code_import/importer.rb @@ -327,7 +327,7 @@ module Gitlab link = "https://storage.googleapis.com/google-code-attachments/#{@repo.name}/issue-#{issue_id}/comment-#{comment_id}/#{filename}" text = "[#{filename}](#{link})" - text = "!#{text}" if filename =~ /\.(png|jpg|jpeg|gif|bmp|tiff)\z/ + text = "!#{text}" if filename =~ /\.(png|jpg|jpeg|gif|bmp|tiff)\z/i text end.compact end diff --git a/spec/fixtures/GoogleCodeProjectHosting.json b/spec/fixtures/GoogleCodeProjectHosting.json index d05e77271ae..67bb3bae5b7 100644 --- a/spec/fixtures/GoogleCodeProjectHosting.json +++ b/spec/fixtures/GoogleCodeProjectHosting.json @@ -382,6 +382,11 @@ "fileName" : "screenshot.png", "fileSize" : 0, "mimetype" : "image/png" + }, { + "attachmentId" : "001", + "fileName" : "screenshot1.PNG", + "fileSize" : 0, + "mimetype" : "image/x-png" } ] }, { "id" : 1, diff --git a/spec/lib/gitlab/google_code_import/importer_spec.rb b/spec/lib/gitlab/google_code_import/importer_spec.rb index c53ddeb87b5..f49cbb7f532 100644 --- a/spec/lib/gitlab/google_code_import/importer_spec.rb +++ b/spec/lib/gitlab/google_code_import/importer_spec.rb @@ -65,6 +65,7 @@ describe Gitlab::GoogleCodeImport::Importer do expect(issue.description).to include('all the best!') expect(issue.description).to include('[tint2_task_scrolling.diff](https://storage.googleapis.com/google-code-attachments/tint2/issue-169/comment-0/tint2_task_scrolling.diff)') expect(issue.description).to include('![screenshot.png](https://storage.googleapis.com/google-code-attachments/tint2/issue-169/comment-0/screenshot.png)') + expect(issue.description).to include('![screenshot1.PNG](https://storage.googleapis.com/google-code-attachments/tint2/issue-169/comment-0/screenshot1.PNG)') end it "imports issue comments" do From e1811316d73ea0b240d7f47e1de557b712ed4cee Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sun, 19 Jul 2015 22:53:14 -0700 Subject: [PATCH 048/174] Remove repository graph log to fix slow cache updates after push event Recalculating graph_log took minutes on a large repository since each of the 6000 commits would need to calculate the diff. Since graph_log does not appear to be used, remove it from the list of things to update. For the Linux kernel repository, this reduced the ProjectCacheWorker time from 8+ minutes to 16 seconds. Closes #2016 --- CHANGELOG | 1 + app/models/repository.rb | 20 +------------------- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index b1d079ef207..ed23ee4a90c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.14.0 (unreleased) + - Remove repository graph log to fix slow cache updates after push event (Stan Hu) - Fix label read access for unauthenticated users (Daniel Gerhardt) - Fix OAuth provider bug where GitLab would not go return to the redirect_uri after sign-in (Stan Hu) - Fix file upload dialog for comment editing (Daniel Gerhardt) diff --git a/app/models/repository.rb b/app/models/repository.rb index 1d208aa71c4..807b33b2a3e 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -119,7 +119,7 @@ class Repository end def cache_keys - %i(size branch_names tag_names commit_count graph_log + %i(size branch_names tag_names commit_count readme version contribution_guide changelog license) end @@ -144,24 +144,6 @@ class Repository end end - def graph_log - cache.fetch(:graph_log) do - commits = raw_repository.log(limit: 6000, skip_merges: true, - ref: root_ref) - - commits.map do |rugged_commit| - commit = Gitlab::Git::Commit.new(rugged_commit) - - { - author_name: commit.author_name, - author_email: commit.author_email, - additions: commit.stats.additions, - deletions: commit.stats.deletions, - } - end - end - end - def lookup_cache @lookup_cache ||= {} end From 4a0e4c857f799d2e3cc5d5dc37de6da784661965 Mon Sep 17 00:00:00 2001 From: Daniel Gerhardt Date: Sun, 19 Jul 2015 23:21:33 +0200 Subject: [PATCH 049/174] Fix access to disabled features for unauthenticated users Unauthenticated users had access to disabled features of public projects. The code has been slightly refactored so that feature checks are done in a separate method and can also be applied for public access. --- CHANGELOG | 1 + app/models/ability.rb | 54 +++++++++++++++++++++++++------------------ 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 9fe1e8c90c7..cc39373fd44 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.14.0 (unreleased) + - Fix access to disabled features for unauthenticated users (Daniel Gerhardt) - Fix OAuth provider bug where GitLab would not go return to the redirect_uri after sign-in (Stan Hu) - Fix file upload dialog for comment editing (Daniel Gerhardt) - Expire Rails cache entries after two weeks to prevent endless Redis growth diff --git a/app/models/ability.rb b/app/models/ability.rb index d3631d49ec6..6cffc46cec3 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -31,7 +31,7 @@ class Ability end if project && project.public? - [ + rules = [ :read_project, :read_wiki, :read_issue, @@ -42,6 +42,8 @@ class Ability :read_note, :download_code ] + + rules - project_disabled_features_rules(project) else group = if subject.kind_of?(Group) subject @@ -102,28 +104,7 @@ class Ability rules -= project_archived_rules end - unless project.issues_enabled - rules -= named_abilities('issue') - end - - unless project.merge_requests_enabled - rules -= named_abilities('merge_request') - end - - unless project.issues_enabled or project.merge_requests_enabled - rules -= named_abilities('label') - rules -= named_abilities('milestone') - end - - unless project.snippets_enabled - rules -= named_abilities('project_snippet') - end - - unless project.wiki_enabled - rules -= named_abilities('wiki') - end - - rules + rules - project_disabled_features_rules(project) end end @@ -205,6 +186,33 @@ class Ability ] end + def project_disabled_features_rules(project) + rules = [] + + unless project.issues_enabled + rules += named_abilities('issue') + end + + unless project.merge_requests_enabled + rules += named_abilities('merge_request') + end + + unless project.issues_enabled or project.merge_requests_enabled + rules += named_abilities('label') + rules += named_abilities('milestone') + end + + unless project.snippets_enabled + rules += named_abilities('project_snippet') + end + + unless project.wiki_enabled + rules += named_abilities('wiki') + end + + rules + end + def group_abilities(user, group) rules = [] From c61e7dd4ac76b23a1089041ba4a41fd7b56166e0 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Mon, 20 Jul 2015 13:54:56 +0300 Subject: [PATCH 050/174] Public project activity page asks for sign-in --- app/controllers/projects_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index b191819a117..586359f3080 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -1,6 +1,6 @@ class ProjectsController < ApplicationController prepend_before_filter :render_go_import, only: [:show] - skip_before_action :authenticate_user!, only: [:show] + skip_before_action :authenticate_user!, only: [:show, :activity] before_action :project, except: [:new, :create] before_action :repository, except: [:new, :create] From 374b95c38e2b178d0a0b006c41ed12cd272bdb9f Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 19 Mar 2015 09:36:07 -0400 Subject: [PATCH 051/174] merge_requests: add fetch command to the MR page --- CHANGELOG | 1 + app/views/projects/merge_requests/_show.html.haml | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 0db3dfc04a5..881b2705274 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -7,6 +7,7 @@ v 7.14.0 (unreleased) - Set OmniAuth full_host parameter to ensure redirect URIs are correct (Stan Hu) - Expire Rails cache entries after two weeks to prevent endless Redis growth - Add support for destroying project milestones (Stan Hu) + - Add fetch command to the MR page. v 7.13.0 (unreleased) - Only enable HSTS header for HTTPS and port 443 (Stan Hu) diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index b6d9b135c70..faaa85896cf 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -31,6 +31,16 @@ %li= link_to "Email Patches", merge_request_path(@merge_request, format: :patch) %li= link_to "Plain Diff", merge_request_path(@merge_request, format: :diff) + - if @merge_request.open? and @merge_request.source_branch_exists? + .append-bottom-20 + .slead + %span + Fetch the branch with + %strong.label-branch< + git fetch + \ #{@merge_request.source_project.http_url_to_repo} + \ #{@merge_request.source_branch} + = render "projects/merge_requests/show/how_to_merge" = render "projects/merge_requests/widget/show.html.haml" From e252410058a5aab0cb0427aeb0768b19b0fce4de Mon Sep 17 00:00:00 2001 From: Daniel Gerhardt Date: Mon, 20 Jul 2015 18:56:49 +0200 Subject: [PATCH 052/174] Fix change log for 7.11 and move entry to 7.12 The change log for 7.11 was accidentally split in 3865a1d92585cb31864b5d0f1b325c3585b5c681. Additionally, the change added with this commit did not make it into 7.11 according to `git branch --contains` and it has not been cherry picked to 7-11-stable so the entry is moved to 7.12. Refs GH-5625, GH-9318. [ci skip] --- CHANGELOG | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index d249a014802..052f4865d69 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -134,6 +134,7 @@ v 7.12.0 - Improve group removing logic - Trigger create-hooks on backup restore task - Add option to automatically link omniauth and LDAP identities + - Allow special character in users bio. I.e.: I <3 GitLab v 7.11.4 - Fix missing bullets when creating lists @@ -152,9 +153,6 @@ v 7.11.1 v 7.11.0 - Fall back to Plaintext when Syntaxhighlighting doesn't work. Fixes some buggy lexers (Hannes Rosenögger) - Get editing comments to work in Chrome 43 again. - - Allow special character in users bio. I.e.: I <3 GitLab - -v 7.11.0 - Fix broken view when viewing history of a file that includes a path that used to be another file (Stan Hu) - Don't show duplicate deploy keys - Fix commit time being displayed in the wrong timezone in some cases (Hannes Rosenögger) From 346b07497989c824b201e501dfa24b8af630da8a Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 21 Jul 2015 10:37:27 +0200 Subject: [PATCH 053/174] Don't stop if database.sql.gz already exists The existing behavior of the backups is to overwrite whatever data was still there in the scratch directories. This broke when we added a 'gzip' step because 'gzip database.sql' will fail if 'database.sql.gz' already exists. Doing 'rm -f database.sql.gz' before the 'gzip' avoids this failure. --- lib/backup/database.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/backup/database.rb b/lib/backup/database.rb index b8aa6b9ff2f..c5a5396cbbf 100644 --- a/lib/backup/database.rb +++ b/lib/backup/database.rb @@ -25,6 +25,7 @@ module Backup abort 'Backup failed' unless success $progress.print 'Compressing database ... ' + FileUtils.rm_f db_file_name_gz success = system('gzip', db_file_name) report_success(success) abort 'Backup failed: compress error' unless success From 280576a2d5a4d1167504ee48e1d4d00a8339a5be Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Tue, 21 Jul 2015 10:40:05 +0000 Subject: [PATCH 054/174] Update changelog --- CHANGELOG | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 052f4865d69..6920adeaf16 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,6 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.14.0 (unreleased) - - Remove repository graph log to fix slow cache updates after push event (Stan Hu) - Fix label read access for unauthenticated users (Daniel Gerhardt) - Fix access to disabled features for unauthenticated users (Daniel Gerhardt) - Fix OAuth provider bug where GitLab would not go return to the redirect_uri after sign-in (Stan Hu) @@ -12,6 +11,7 @@ v 7.14.0 (unreleased) - Add fetch command to the MR page. v 7.13.0 (unreleased) + - Remove repository graph log to fix slow cache updates after push event (Stan Hu) - Only enable HSTS header for HTTPS and port 443 (Stan Hu) - Fix user autocomplete for unauthenticated users accessing public projects (Stan Hu) - Fix redirection to home page URL for unauthorized users (Daniel Gerhardt) @@ -1587,4 +1587,4 @@ v 0.8.0 - stability - security fixes - increased test coverage - - email notification + - email notification \ No newline at end of file From bf3b318ec561a3d8146c6bff56fe21335cab0aec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Rosen=C3=B6gger?= <123haynes@gmail.com> Date: Tue, 21 Jul 2015 13:59:14 +0200 Subject: [PATCH 055/174] revert caching of note text --- app/views/projects/notes/_note.html.haml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/views/projects/notes/_note.html.haml b/app/views/projects/notes/_note.html.haml index c8d705687da..4a1009686c6 100644 --- a/app/views/projects/notes/_note.html.haml +++ b/app/views/projects/notes/_note.html.haml @@ -56,10 +56,9 @@ .note-body{class: note_editable?(note) ? 'js-task-list-container' : ''} - = cache [note, 'markdown', user_color_scheme_class] do - .note-text - = preserve do - = markdown(note.note, {no_header_anchors: true}) + .note-text + = preserve do + = markdown(note.note, {no_header_anchors: true}) = render 'projects/notes/edit_form', note: note - if note.attachment.url From 96819d2fb42b65066f4adcc5e48daf65a58449ec Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 21 Jul 2015 14:35:58 +0200 Subject: [PATCH 056/174] You need to store your DB encryption key --- doc/profile/two_factor_authentication.md | 5 ++++ doc/raketasks/backup_restore.md | 35 ++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/doc/profile/two_factor_authentication.md b/doc/profile/two_factor_authentication.md index fb215c8b269..f60ce35d3e2 100644 --- a/doc/profile/two_factor_authentication.md +++ b/doc/profile/two_factor_authentication.md @@ -63,5 +63,10 @@ your phone's application or a recovery code to log in. 1. Go to **Account**. 1. Click **Disable Two-factor Authentication**. +## Note to GitLab administrators + +You need to take special care to that 2FA keeps working after +[restoring a GitLab backup](../raketasks/backup_restore.md). + [Google Authenticator]: https://support.google.com/accounts/answer/1066447?hl=en [FreeOTP]: https://fedorahosted.org/freeotp/ diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md index 39a13b14fba..36ab2b91959 100644 --- a/doc/raketasks/backup_restore.md +++ b/doc/raketasks/backup_restore.md @@ -9,6 +9,13 @@ This archive will be saved in backup_path (see `config/gitlab.yml`). The filename will be `[TIMESTAMP]_gitlab_backup.tar`. This timestamp can be used to restore an specific backup. You can only restore a backup to exactly the same version of GitLab that you created it on, for example 7.2.1. +You need to keep a separate copy of `/etc/gitlab/gitlab-secrets.json` +(for omnibus packages) or `/home/git/gitlab/.secret` (for installations +from source). This file contains the database encryption key used +for two-factor authentication. If you restore a GitLab backup without +restoring the database encryption key, users who have two-factor +authentication enabled will loose access to your GitLab server. + If you are interested in GitLab CI backup please follow to the [CI backup documentation](https://gitlab.com/gitlab-org/gitlab-ci/blob/master/doc/raketasks/backup_restore.md)* ``` @@ -143,15 +150,39 @@ with the name of your bucket: ## Storing configuration files -Please be informed that a backup does not store your configuration files. +Please be informed that a backup does not store your configuration +files. One reason for this is that your database contains encrypted +information for two-factor authentication. Storing encrypted +information along with its key in the same place defeats the purpose +of using encryption in the first place! + If you use an Omnibus package please see the [instructions in the readme to backup your configuration](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md#backup-and-restore-omnibus-gitlab-configuration). If you have a cookbook installation there should be a copy of your configuration in Chef. -If you have an installation from source, please consider backing up your `gitlab.yml` file, any SSL keys and certificates, and your [SSH host keys](https://superuser.com/questions/532040/copy-ssh-keys-from-one-server-to-another-server/532079#532079). +If you have an installation from source, please consider backing up your `.secret` file, `gitlab.yml` file, any SSL keys and certificates, and your [SSH host keys](https://superuser.com/questions/532040/copy-ssh-keys-from-one-server-to-another-server/532079#532079). + +At the very **minimum** you should backup `/etc/gitlab/gitlab-secrets.json` +(Omnibus) or `/home/git/gitlab/.secret` (source) to preserve your +database encryption key. ## Restore a previously created backup You can only restore a backup to exactly the same version of GitLab that you created it on, for example 7.2.1. +### Prerequisites + +You need to have a working GitLab installation before you can perform +a restore. This is mainly because the system user performing the +restore actions ('git') is usually not allowed to create or delete +the SQL database it needs to import data into ('gitlabhq_production'). +All existing data will be either erased (SQL) or moved to a separate +directory (repositories, uploads). + +If some or all of your GitLab users are using two-factor authentication +(2FA) then you must also make sure to restore +`/etc/gitlab/gitlab-secrets.json` (Omnibus) or `/home/git/gitlab/.secret` +(installations from source). Note that you need to run `gitlab-ctl +reconfigure` after changing `gitlab-secrets.json`. + ### Installation from source ``` From 65bd871be7112c32065ddd01b166d309c6efe06c Mon Sep 17 00:00:00 2001 From: Daniel Gerhardt Date: Tue, 21 Jul 2015 19:15:52 +0200 Subject: [PATCH 057/174] Fix full screen mode for snippet comments ZenMode is now initialized for snippet pages. Fixes #2036. --- CHANGELOG | 1 + app/assets/javascripts/dispatcher.js.coffee | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 6920adeaf16..dab74b654b0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.14.0 (unreleased) + - Fix full screen mode for snippet comments (Daniel Gerhardt) - Fix label read access for unauthenticated users (Daniel Gerhardt) - Fix access to disabled features for unauthenticated users (Daniel Gerhardt) - Fix OAuth provider bug where GitLab would not go return to the redirect_uri after sign-in (Stan Hu) diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee index 2ab148bc296..81e73799271 100644 --- a/app/assets/javascripts/dispatcher.js.coffee +++ b/app/assets/javascripts/dispatcher.js.coffee @@ -128,7 +128,10 @@ class Dispatcher shortcut_handler = new ShortcutsNavigation() new ZenMode() new DropzoneInput($('.wiki-form')) - when 'snippets', 'labels', 'graphs' + when 'snippets' + shortcut_handler = new ShortcutsNavigation() + new ZenMode() if path[2] == 'show' + when 'labels', 'graphs' shortcut_handler = new ShortcutsNavigation() when 'project_members', 'deploy_keys', 'hooks', 'services', 'protected_branches' shortcut_handler = new ShortcutsNavigation() From 643557dabccbb3a503b0867ae44ec5701759d2a8 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Mon, 20 Jul 2015 16:55:45 -0700 Subject: [PATCH 058/174] Fix 404 error in files view after deleting the last file in a repository Closes #1362 --- CHANGELOG | 1 + app/controllers/projects/tree_controller.rb | 4 ++- .../{ => projects}/tree_controller_spec.rb | 29 +++++++++++++++++-- spec/requests/api/branches_spec.rb | 9 +++++- spec/support/test_env.rb | 11 +++++-- 5 files changed, 46 insertions(+), 8 deletions(-) rename spec/controllers/{ => projects}/tree_controller_spec.rb (69%) diff --git a/CHANGELOG b/CHANGELOG index 052f4865d69..038a4d95d7e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.14.0 (unreleased) + - Fix 404 error in files view after deleting the last file in a repository (Stan Hu) - Remove repository graph log to fix slow cache updates after push event (Stan Hu) - Fix label read access for unauthenticated users (Daniel Gerhardt) - Fix access to disabled features for unauthenticated users (Daniel Gerhardt) diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb index b659e15f242..92e4bc16d9d 100644 --- a/app/controllers/projects/tree_controller.rb +++ b/app/controllers/projects/tree_controller.rb @@ -7,13 +7,15 @@ class Projects::TreeController < Projects::ApplicationController before_action :authorize_download_code! def show + return not_found! unless @repository.commit(@ref) + if tree.entries.empty? if @repository.blob_at(@commit.id, @path) redirect_to( namespace_project_blob_path(@project.namespace, @project, File.join(@ref, @path)) ) and return - else + elsif @path.present? return not_found! end end diff --git a/spec/controllers/tree_controller_spec.rb b/spec/controllers/projects/tree_controller_spec.rb similarity index 69% rename from spec/controllers/tree_controller_spec.rb rename to spec/controllers/projects/tree_controller_spec.rb index e09caf5df13..53915856357 100644 --- a/spec/controllers/tree_controller_spec.rb +++ b/spec/controllers/projects/tree_controller_spec.rb @@ -8,9 +8,6 @@ describe Projects::TreeController do sign_in(user) project.team << [user, :master] - - allow(project).to receive(:branches).and_return(['master', 'foo/bar/baz']) - allow(project).to receive(:tags).and_return(['v1.0.0', 'v2.0.0']) controller.instance_variable_set(:@project, project) end @@ -44,6 +41,32 @@ describe Projects::TreeController do let(:id) { 'invalid-branch/encoding/' } it { is_expected.to respond_with(:not_found) } end + + context "valid empty branch, invalid path" do + let(:id) { 'empty-branch/invalid-path/' } + it { is_expected.to respond_with(:not_found) } + end + + context "valid empty branch" do + let(:id) { 'empty-branch' } + it { is_expected.to respond_with(:success) } + end + + context "invalid SHA commit ID" do + let(:id) { 'ff39438/.gitignore' } + it { is_expected.to respond_with(:not_found) } + end + + context "valid SHA commit ID" do + let(:id) { '6d39438' } + it { is_expected.to respond_with(:success) } + end + + context "valid SHA commit ID with path" do + let(:id) { '6d39438/.gitignore' } + it { expect(response.status).to eq(302) } + end + end describe 'GET show with blob path' do diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb index cb6e5e89625..bb3862c9eb2 100644 --- a/spec/requests/api/branches_spec.rb +++ b/spec/requests/api/branches_spec.rb @@ -13,11 +13,18 @@ describe API::API, api: true do let!(:branch_sha) { '0b4bc9a49b562e85de7cc9e834518ea6828729b9' } describe "GET /projects/:id/repository/branches" do + before do + # Ensure that repository.branch_names is cleared from the cache at start to ensure + # the list matches reality + Rails.cache.clear + end + it "should return an array of project branches" do get api("/projects/#{project.id}/repository/branches", user) expect(response.status).to eq(200) expect(json_response).to be_an Array - expect(json_response.first['name']).to eq(project.repository.branch_names.first) + branch_names = json_response.map { |x| x['name'] } + expect(branch_names).to match_array(project.repository.branch_names) end end diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index 8bdd6b43cdd..dcf2a9e2ce5 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -5,6 +5,7 @@ module TestEnv # When developing the seed repository, comment out the branch you will modify. BRANCH_SHA = { + 'empty-branch' => '7efb185', 'flatten-dir' => 'e56497b', 'feature' => '0b4bc9a', 'feature_conflict' => 'bb5206f', @@ -14,9 +15,13 @@ module TestEnv 'master' => '5937ac0' } - FORKED_BRANCH_SHA = BRANCH_SHA.merge({ - 'add-submodule-version-bump' => '3f547c08' - }) + # gitlab-test-fork is a fork of gitlab-fork, but we don't necessarily + # need to keep all the branches in sync. + # We currently only need a subset of the branches + FORKED_BRANCH_SHA = { + 'add-submodule-version-bump' => '3f547c08', + 'master' => '5937ac0' + } # Test environment # From 42130a97e992f608bf5deaf2afbe203f21d2e2b3 Mon Sep 17 00:00:00 2001 From: karen Carias Date: Tue, 21 Jul 2015 15:45:12 -0700 Subject: [PATCH 059/174] added Fork Project document --- doc/gitlab-basics/README.md | 2 ++ doc/gitlab-basics/create-branch.md | 3 ++- doc/gitlab-basics/fork-project.md | 19 +++++++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 doc/gitlab-basics/fork-project.md diff --git a/doc/gitlab-basics/README.md b/doc/gitlab-basics/README.md index 63fa7a90a26..d6272cd5912 100644 --- a/doc/gitlab-basics/README.md +++ b/doc/gitlab-basics/README.md @@ -15,3 +15,5 @@ Step-by-step guides on the basics of working with Git and GitLab. * [Create a group](create-group.md) * [Create a branch](create-branch.md) + +* [Fork a project](fork-project.md) diff --git a/doc/gitlab-basics/create-branch.md b/doc/gitlab-basics/create-branch.md index a8afbfe53d7..7556b0f663e 100644 --- a/doc/gitlab-basics/create-branch.md +++ b/doc/gitlab-basics/create-branch.md @@ -1,6 +1,7 @@ # How to create a branch A branch is an independent line of development. + New commits are recorded in the history for the current branch, which results in taking the source from someone’s repository (the place where the history of your work is stored) at certain point in time, and apply your own changes to it in the history of the project. To add changes to your GitLab project, you should create a branch. You can do it in your [shell](basic-git-commands.md) or in GitLab. @@ -32,7 +33,7 @@ Fill out the information required: ![Branch info](basicsimages/branch_info.png) ### Note: - + You will be able to find and select the name of your branch in the white box next to a project's name: ![Branch name](basicsimages/branch_name.png) diff --git a/doc/gitlab-basics/fork-project.md b/doc/gitlab-basics/fork-project.md new file mode 100644 index 00000000000..e97ec0959a4 --- /dev/null +++ b/doc/gitlab-basics/fork-project.md @@ -0,0 +1,19 @@ +# How to fork a project + +A fork is a copy of an original repository that you can put somewhere else +or where you can experiment and apply changes that you can later decide if +publishing or not, without affecting your original project. + +It takes just a few steps to fork a project in GitLab. + +Sign in to [gitlab.com](https://gitlab.com). + +Select a project on the right side of your screen: + +![Select a project](basicsimages/select_project.png) + +Click on the "fork" button on the right side of your screen: + +![Fork](simple_guide_images/fork.png) + +Click on the user or group to where you'd like to add the forked project. From afc8e922238e9d6146926b88fa94f18700bb64e1 Mon Sep 17 00:00:00 2001 From: karen Carias Date: Tue, 21 Jul 2015 15:47:17 -0700 Subject: [PATCH 060/174] fixed image --- doc/gitlab-basics/fork-project.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/gitlab-basics/fork-project.md b/doc/gitlab-basics/fork-project.md index e97ec0959a4..5173aae2c0f 100644 --- a/doc/gitlab-basics/fork-project.md +++ b/doc/gitlab-basics/fork-project.md @@ -14,6 +14,6 @@ Select a project on the right side of your screen: Click on the "fork" button on the right side of your screen: -![Fork](simple_guide_images/fork.png) +![Fork](basicsimages/fork.png) Click on the user or group to where you'd like to add the forked project. From 913e1b217ec2d4c3cdb22e4b336ea11c0213cb97 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Tue, 21 Jul 2015 18:09:06 -0700 Subject: [PATCH 061/174] Remove 7.14 entry that was pushed to 7.13 --- CHANGELOG | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index d26ac5bbfab..2765923124f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,7 +3,6 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.14.0 (unreleased) - Fix full screen mode for snippet comments (Daniel Gerhardt) - Fix 404 error in files view after deleting the last file in a repository (Stan Hu) - - Remove repository graph log to fix slow cache updates after push event (Stan Hu) - Fix label read access for unauthenticated users (Daniel Gerhardt) - Fix access to disabled features for unauthenticated users (Daniel Gerhardt) - Fix OAuth provider bug where GitLab would not go return to the redirect_uri after sign-in (Stan Hu) @@ -1590,4 +1589,4 @@ v 0.8.0 - stability - security fixes - increased test coverage - - email notification \ No newline at end of file + - email notification From 5aff5223d4ba675beae2673fe5ed204531f5b42c Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Tue, 21 Jul 2015 18:52:56 -0700 Subject: [PATCH 062/174] Clearing the entire Redis cache may be too expensive; just use the repository expire_cache method --- spec/requests/api/branches_spec.rb | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb index bb3862c9eb2..5c1b58535cc 100644 --- a/spec/requests/api/branches_spec.rb +++ b/spec/requests/api/branches_spec.rb @@ -13,13 +13,9 @@ describe API::API, api: true do let!(:branch_sha) { '0b4bc9a49b562e85de7cc9e834518ea6828729b9' } describe "GET /projects/:id/repository/branches" do - before do - # Ensure that repository.branch_names is cleared from the cache at start to ensure - # the list matches reality - Rails.cache.clear - end - it "should return an array of project branches" do + project.repository.expire_cache + get api("/projects/#{project.id}/repository/branches", user) expect(response.status).to eq(200) expect(json_response).to be_an Array From 1fee24a36143e8057d495e8a7e0f2d4b93d83f2a Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 16 Jul 2015 14:17:43 -0400 Subject: [PATCH 063/174] Remove unused `be_valid_commit` matcher --- spec/support/matchers.rb | 9 --------- 1 file changed, 9 deletions(-) diff --git a/spec/support/matchers.rb b/spec/support/matchers.rb index a2f853e3e70..87a034cca3b 100644 --- a/spec/support/matchers.rb +++ b/spec/support/matchers.rb @@ -1,12 +1,3 @@ -RSpec::Matchers.define :be_valid_commit do - match do |actual| - actual && - actual.id == ValidCommit::ID && - actual.message == ValidCommit::MESSAGE && - actual.author_name == ValidCommit::AUTHOR_FULL_NAME - end -end - def emulate_user(user) user = case user when :user then create(:user) From a2ecfdc5859c1703dbbad6dde888f7a0eb5817c8 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 21 Jul 2015 22:09:02 -0400 Subject: [PATCH 064/174] Move access-related matchers to their own module --- .../security/dashboard_access_spec.rb | 2 + .../security/group/group_access_spec.rb | 2 + .../group/internal_group_access_spec.rb | 2 + .../security/group/mixed_group_access_spec.rb | 2 + .../group/public_group_access_spec.rb | 2 + spec/features/security/profile_access_spec.rb | 2 + .../security/project/internal_access_spec.rb | 2 + .../security/project/private_access_spec.rb | 2 + .../security/project/public_access_spec.rb | 3 +- spec/support/matchers.rb | 34 ------------ spec/support/matchers/access_matchers.rb | 54 +++++++++++++++++++ 11 files changed, 72 insertions(+), 35 deletions(-) create mode 100644 spec/support/matchers/access_matchers.rb diff --git a/spec/features/security/dashboard_access_spec.rb b/spec/features/security/dashboard_access_spec.rb index 67238e3ab76..c38cddbb904 100644 --- a/spec/features/security/dashboard_access_spec.rb +++ b/spec/features/security/dashboard_access_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe "Dashboard access", feature: true do + include AccessMatchers + describe "GET /dashboard" do subject { dashboard_path } diff --git a/spec/features/security/group/group_access_spec.rb b/spec/features/security/group/group_access_spec.rb index 63793149459..e42b7b8d8a0 100644 --- a/spec/features/security/group/group_access_spec.rb +++ b/spec/features/security/group/group_access_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe "Group access", feature: true do + include AccessMatchers + describe "GET /projects/new" do it { expect(new_group_path).to be_allowed_for :admin } it { expect(new_group_path).to be_allowed_for :user } diff --git a/spec/features/security/group/internal_group_access_spec.rb b/spec/features/security/group/internal_group_access_spec.rb index d17a7412e43..28673a3ab2f 100644 --- a/spec/features/security/group/internal_group_access_spec.rb +++ b/spec/features/security/group/internal_group_access_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe "Group with internal project access", feature: true do + include AccessMatchers + describe "Group" do let(:group) { create(:group) } diff --git a/spec/features/security/group/mixed_group_access_spec.rb b/spec/features/security/group/mixed_group_access_spec.rb index b3db7b5dea4..f7f0213737e 100644 --- a/spec/features/security/group/mixed_group_access_spec.rb +++ b/spec/features/security/group/mixed_group_access_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe "Group access", feature: true do + include AccessMatchers + describe "Group" do let(:group) { create(:group) } diff --git a/spec/features/security/group/public_group_access_spec.rb b/spec/features/security/group/public_group_access_spec.rb index c16f0c0d1e1..03cafad8d7e 100644 --- a/spec/features/security/group/public_group_access_spec.rb +++ b/spec/features/security/group/public_group_access_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe "Group with public project access", feature: true do + include AccessMatchers + describe "Group" do let(:group) { create(:group) } diff --git a/spec/features/security/profile_access_spec.rb b/spec/features/security/profile_access_spec.rb index bcabc2d53ac..847566d0de9 100644 --- a/spec/features/security/profile_access_spec.rb +++ b/spec/features/security/profile_access_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe "Profile access", feature: true do + include AccessMatchers + before do @u1 = create(:user) end diff --git a/spec/features/security/project/internal_access_spec.rb b/spec/features/security/project/internal_access_spec.rb index 4649e58cb1a..57563add74c 100644 --- a/spec/features/security/project/internal_access_spec.rb +++ b/spec/features/security/project/internal_access_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe "Internal Project Access", feature: true do + include AccessMatchers + let(:project) { create(:project, :internal) } let(:master) { create(:user) } diff --git a/spec/features/security/project/private_access_spec.rb b/spec/features/security/project/private_access_spec.rb index 2866bf0355b..a1e111c6cab 100644 --- a/spec/features/security/project/private_access_spec.rb +++ b/spec/features/security/project/private_access_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe "Private Project Access", feature: true do + include AccessMatchers + let(:project) { create(:project) } let(:master) { create(:user) } diff --git a/spec/features/security/project/public_access_spec.rb b/spec/features/security/project/public_access_spec.rb index 554c96bcdc5..655d2c8b7d9 100644 --- a/spec/features/security/project/public_access_spec.rb +++ b/spec/features/security/project/public_access_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe "Public Project Access", feature: true do + include AccessMatchers + let(:project) { create(:project) } let(:master) { create(:user) } @@ -17,7 +19,6 @@ describe "Public Project Access", feature: true do # readonly project.team << [reporter, :reporter] - end describe "Project should be public" do diff --git a/spec/support/matchers.rb b/spec/support/matchers.rb index 87a034cca3b..d9b27ab08d8 100644 --- a/spec/support/matchers.rb +++ b/spec/support/matchers.rb @@ -1,37 +1,3 @@ -def emulate_user(user) - user = case user - when :user then create(:user) - when :visitor then nil - when :admin then create(:admin) - else user - end - login_with(user) if user -end - -RSpec::Matchers.define :be_allowed_for do |user| - match do |url| - emulate_user(user) - visit url - status_code != 404 && current_path != new_user_session_path - end -end - -RSpec::Matchers.define :be_denied_for do |user| - match do |url| - emulate_user(user) - visit url - status_code == 404 || current_path == new_user_session_path - end -end - -RSpec::Matchers.define :be_not_found_for do |user| - match do |url| - emulate_user(user) - visit url - status_code == 404 - end -end - RSpec::Matchers.define :include_module do |expected| match do described_class.included_modules.include?(expected) diff --git a/spec/support/matchers/access_matchers.rb b/spec/support/matchers/access_matchers.rb new file mode 100644 index 00000000000..558e8b1612f --- /dev/null +++ b/spec/support/matchers/access_matchers.rb @@ -0,0 +1,54 @@ +# AccessMatchers +# +# The custom matchers contained in this module are used to test a user's access +# to a URL by emulating a specific user or type of user account, visiting the +# URL, and then checking the response status code and resulting path. +module AccessMatchers + extend RSpec::Matchers::DSL + include Warden::Test::Helpers + + def emulate_user(user) + case user + when :user + login_as(create(:user)) + when :visitor + logout + when :admin + login_as(create(:admin)) + when User + login_as(user) + else + raise ArgumentError, "cannot emulate user #{user}" + end + end + + def description_for(user, type) + if user.kind_of?(User) + # User#inspect displays too much information for RSpec's description + # messages + "be #{type} for supplied User" + else + "be #{type} for #{user}" + end + end + + matcher :be_allowed_for do |user| + match do |url| + emulate_user(user) + visit url + status_code != 404 && current_path != new_user_session_path + end + + description { description_for(user, 'allowed') } + end + + matcher :be_denied_for do |user| + match do |url| + emulate_user(user) + visit url + status_code == 404 || current_path == new_user_session_path + end + + description { description_for(user, 'denied') } + end +end From 421b06508d6ddc76c90ed8e54271dfb18e5c5833 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 16 Jul 2015 15:01:20 -0400 Subject: [PATCH 065/174] Remove be_not_found_for matcher It was only used in one test, and the test was kind of redundant. --- spec/features/security/profile_access_spec.rb | 5 ----- 1 file changed, 5 deletions(-) diff --git a/spec/features/security/profile_access_spec.rb b/spec/features/security/profile_access_spec.rb index 847566d0de9..eee2588408a 100644 --- a/spec/features/security/profile_access_spec.rb +++ b/spec/features/security/profile_access_spec.rb @@ -6,11 +6,6 @@ describe "Profile access", feature: true do before do @u1 = create(:user) end - - describe "GET /login" do - it { expect(new_user_session_path).not_to be_not_found_for :visitor } - end - describe "GET /profile/keys" do subject { profile_keys_path } From ff8811c40b33a3a98203478925810035fffe7094 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 16 Jul 2015 15:02:06 -0400 Subject: [PATCH 066/174] Remove redundant Profile access test cases The user being created was no different than what `be_allowed_for` was doing behind the scenes so we were essentially testing all user-level accesses twice. --- spec/features/security/profile_access_spec.rb | 9 --------- 1 file changed, 9 deletions(-) diff --git a/spec/features/security/profile_access_spec.rb b/spec/features/security/profile_access_spec.rb index eee2588408a..c19678ab381 100644 --- a/spec/features/security/profile_access_spec.rb +++ b/spec/features/security/profile_access_spec.rb @@ -3,13 +3,9 @@ require 'spec_helper' describe "Profile access", feature: true do include AccessMatchers - before do - @u1 = create(:user) - end describe "GET /profile/keys" do subject { profile_keys_path } - it { is_expected.to be_allowed_for @u1 } it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :user } it { is_expected.to be_denied_for :visitor } @@ -18,7 +14,6 @@ describe "Profile access", feature: true do describe "GET /profile" do subject { profile_path } - it { is_expected.to be_allowed_for @u1 } it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :user } it { is_expected.to be_denied_for :visitor } @@ -27,7 +22,6 @@ describe "Profile access", feature: true do describe "GET /profile/account" do subject { profile_account_path } - it { is_expected.to be_allowed_for @u1 } it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :user } it { is_expected.to be_denied_for :visitor } @@ -36,7 +30,6 @@ describe "Profile access", feature: true do describe "GET /profile/preferences" do subject { profile_preferences_path } - it { is_expected.to be_allowed_for @u1 } it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :user } it { is_expected.to be_denied_for :visitor } @@ -45,7 +38,6 @@ describe "Profile access", feature: true do describe "GET /profile/audit_log" do subject { audit_log_profile_path } - it { is_expected.to be_allowed_for @u1 } it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :user } it { is_expected.to be_denied_for :visitor } @@ -54,7 +46,6 @@ describe "Profile access", feature: true do describe "GET /profile/notifications" do subject { profile_notifications_path } - it { is_expected.to be_allowed_for @u1 } it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :user } it { is_expected.to be_denied_for :visitor } From 0d5cf111f3070994c0e80ef764d1bd4b9e4936b1 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 21 Jul 2015 22:09:58 -0400 Subject: [PATCH 067/174] Move custom matchers to their own files under spec/support/matchers --- .../{matchers.rb => matchers/include_module.rb} | 10 ---------- spec/support/matchers/is_within.rb | 9 +++++++++ 2 files changed, 9 insertions(+), 10 deletions(-) rename spec/support/{matchers.rb => matchers/include_module.rb} (54%) create mode 100644 spec/support/matchers/is_within.rb diff --git a/spec/support/matchers.rb b/spec/support/matchers/include_module.rb similarity index 54% rename from spec/support/matchers.rb rename to spec/support/matchers/include_module.rb index d9b27ab08d8..0a78af1e90e 100644 --- a/spec/support/matchers.rb +++ b/spec/support/matchers/include_module.rb @@ -11,13 +11,3 @@ RSpec::Matchers.define :include_module do |expected| "expected #{described_class} to include the #{expected} module" end end - -# Extend shoulda-matchers -module Shoulda::Matchers::ActiveModel - class ValidateLengthOfMatcher - # Shortcut for is_at_least and is_at_most - def is_within(range) - is_at_least(range.min) && is_at_most(range.max) - end - end -end diff --git a/spec/support/matchers/is_within.rb b/spec/support/matchers/is_within.rb new file mode 100644 index 00000000000..0c35fc7e899 --- /dev/null +++ b/spec/support/matchers/is_within.rb @@ -0,0 +1,9 @@ +# Extend shoulda-matchers +module Shoulda::Matchers::ActiveModel + class ValidateLengthOfMatcher + # Shortcut for is_at_least and is_at_most + def is_within(range) + is_at_least(range.min) && is_at_most(range.max) + end + end +end From b24d5f13a5dde7ab85dce93900fa309b3485adb9 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 16 Jul 2015 17:05:14 -0400 Subject: [PATCH 068/174] Consolidate group access specs into one file --- .../security/group/group_access_spec.rb | 100 ------ .../group/internal_group_access_spec.rb | 84 ------ .../security/group/mixed_group_access_spec.rb | 85 ------ .../group/public_group_access_spec.rb | 84 ------ spec/features/security/group_access_spec.rb | 284 ++++++++++++++++++ 5 files changed, 284 insertions(+), 353 deletions(-) delete mode 100644 spec/features/security/group/group_access_spec.rb delete mode 100644 spec/features/security/group/internal_group_access_spec.rb delete mode 100644 spec/features/security/group/mixed_group_access_spec.rb delete mode 100644 spec/features/security/group/public_group_access_spec.rb create mode 100644 spec/features/security/group_access_spec.rb diff --git a/spec/features/security/group/group_access_spec.rb b/spec/features/security/group/group_access_spec.rb deleted file mode 100644 index e42b7b8d8a0..00000000000 --- a/spec/features/security/group/group_access_spec.rb +++ /dev/null @@ -1,100 +0,0 @@ -require 'spec_helper' - -describe "Group access", feature: true do - include AccessMatchers - - describe "GET /projects/new" do - it { expect(new_group_path).to be_allowed_for :admin } - it { expect(new_group_path).to be_allowed_for :user } - it { expect(new_group_path).to be_denied_for :visitor } - end - - describe "Group" do - let(:group) { create(:group) } - - let(:owner) { create(:owner) } - let(:master) { create(:user) } - let(:reporter) { create(:user) } - let(:guest) { create(:user) } - let(:nonmember) { create(:user) } - - before do - group.add_user(owner, Gitlab::Access::OWNER) - group.add_user(master, Gitlab::Access::MASTER) - group.add_user(reporter, Gitlab::Access::REPORTER) - group.add_user(guest, Gitlab::Access::GUEST) - end - - describe "GET /groups/:path" do - subject { group_path(group) } - - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :visitor } - end - - describe "GET /groups/:path/issues" do - subject { issues_group_path(group) } - - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :visitor } - end - - describe "GET /groups/:path/merge_requests" do - subject { merge_requests_group_path(group) } - - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :visitor } - end - - describe "GET /groups/:path/group_members" do - subject { group_group_members_path(group) } - - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :visitor } - end - - describe "GET /groups/:path/edit" do - subject { edit_group_path(group) } - - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_denied_for master } - it { is_expected.to be_denied_for reporter } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :visitor } - end - - describe "GET /groups/:path/projects" do - subject { projects_group_path(group) } - - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_denied_for master } - it { is_expected.to be_denied_for reporter } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :visitor } - end - end -end diff --git a/spec/features/security/group/internal_group_access_spec.rb b/spec/features/security/group/internal_group_access_spec.rb deleted file mode 100644 index 28673a3ab2f..00000000000 --- a/spec/features/security/group/internal_group_access_spec.rb +++ /dev/null @@ -1,84 +0,0 @@ -require 'spec_helper' - -describe "Group with internal project access", feature: true do - include AccessMatchers - - describe "Group" do - let(:group) { create(:group) } - - let(:owner) { create(:owner) } - let(:master) { create(:user) } - let(:reporter) { create(:user) } - let(:guest) { create(:user) } - let(:nonmember) { create(:user) } - - before do - group.add_user(owner, Gitlab::Access::OWNER) - group.add_user(master, Gitlab::Access::MASTER) - group.add_user(reporter, Gitlab::Access::REPORTER) - group.add_user(guest, Gitlab::Access::GUEST) - - create(:project, :internal, group: group) - end - - describe "GET /groups/:path" do - subject { group_path(group) } - - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_denied_for :visitor } - end - - describe "GET /groups/:path/issues" do - subject { issues_group_path(group) } - - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_denied_for :visitor } - end - - describe "GET /groups/:path/merge_requests" do - subject { merge_requests_group_path(group) } - - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_denied_for :visitor } - end - - describe "GET /groups/:path/group_members" do - subject { group_group_members_path(group) } - - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_denied_for :visitor } - end - - describe "GET /groups/:path/edit" do - subject { edit_group_path(group) } - - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_denied_for master } - it { is_expected.to be_denied_for reporter } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :visitor } - end - end -end diff --git a/spec/features/security/group/mixed_group_access_spec.rb b/spec/features/security/group/mixed_group_access_spec.rb deleted file mode 100644 index f7f0213737e..00000000000 --- a/spec/features/security/group/mixed_group_access_spec.rb +++ /dev/null @@ -1,85 +0,0 @@ -require 'spec_helper' - -describe "Group access", feature: true do - include AccessMatchers - - describe "Group" do - let(:group) { create(:group) } - - let(:owner) { create(:owner) } - let(:master) { create(:user) } - let(:reporter) { create(:user) } - let(:guest) { create(:user) } - let(:nonmember) { create(:user) } - - before do - group.add_user(owner, Gitlab::Access::OWNER) - group.add_user(master, Gitlab::Access::MASTER) - group.add_user(reporter, Gitlab::Access::REPORTER) - group.add_user(guest, Gitlab::Access::GUEST) - - create(:project, :internal, path: "internal_project", group: group) - create(:project, :public, path: "public_project", group: group) - end - - describe "GET /groups/:path" do - subject { group_path(group) } - - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_allowed_for :visitor } - end - - describe "GET /groups/:path/issues" do - subject { issues_group_path(group) } - - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_allowed_for :visitor } - end - - describe "GET /groups/:path/merge_requests" do - subject { merge_requests_group_path(group) } - - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_allowed_for :visitor } - end - - describe "GET /groups/:path/group_members" do - subject { group_group_members_path(group) } - - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_allowed_for :visitor } - end - - describe "GET /groups/:path/edit" do - subject { edit_group_path(group) } - - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_denied_for master } - it { is_expected.to be_denied_for reporter } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :visitor } - end - end -end diff --git a/spec/features/security/group/public_group_access_spec.rb b/spec/features/security/group/public_group_access_spec.rb deleted file mode 100644 index 03cafad8d7e..00000000000 --- a/spec/features/security/group/public_group_access_spec.rb +++ /dev/null @@ -1,84 +0,0 @@ -require 'spec_helper' - -describe "Group with public project access", feature: true do - include AccessMatchers - - describe "Group" do - let(:group) { create(:group) } - - let(:owner) { create(:owner) } - let(:master) { create(:user) } - let(:reporter) { create(:user) } - let(:guest) { create(:user) } - let(:nonmember) { create(:user) } - - before do - group.add_user(owner, Gitlab::Access::OWNER) - group.add_user(master, Gitlab::Access::MASTER) - group.add_user(reporter, Gitlab::Access::REPORTER) - group.add_user(guest, Gitlab::Access::GUEST) - - create(:project, :public, group: group) - end - - describe "GET /groups/:path" do - subject { group_path(group) } - - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_allowed_for :visitor } - end - - describe "GET /groups/:path/issues" do - subject { issues_group_path(group) } - - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_allowed_for :visitor } - end - - describe "GET /groups/:path/merge_requests" do - subject { merge_requests_group_path(group) } - - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_allowed_for :visitor } - end - - describe "GET /groups/:path/group_members" do - subject { group_group_members_path(group) } - - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_allowed_for :visitor } - end - - describe "GET /groups/:path/edit" do - subject { edit_group_path(group) } - - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_denied_for master } - it { is_expected.to be_denied_for reporter } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :visitor } - end - end -end diff --git a/spec/features/security/group_access_spec.rb b/spec/features/security/group_access_spec.rb new file mode 100644 index 00000000000..0f36e474989 --- /dev/null +++ b/spec/features/security/group_access_spec.rb @@ -0,0 +1,284 @@ +require 'rails_helper' + +describe 'Group access', feature: true do + include AccessMatchers + + def group + @group ||= create(:group) + end + + def create_project(access_level) + if access_level == :mixed + create(:empty_project, :public, group: group) + create(:empty_project, :internal, group: group) + else + create(:empty_project, access_level, group: group) + end + end + + def group_member(access_level, group = group) + level = Object.const_get("Gitlab::Access::#{access_level.upcase}") + + create(:user).tap do |user| + group.add_user(user, level) + end + end + + describe 'GET /groups/new' do + subject { new_group_path } + + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } + end + + describe 'GET /groups/:path' do + subject { group_path(group) } + + context 'with public projects' do + before(:all) { create_project(:public) } + + it { is_expected.to be_allowed_for group_member(:owner) } + it { is_expected.to be_allowed_for group_member(:master) } + it { is_expected.to be_allowed_for group_member(:reporter) } + it { is_expected.to be_allowed_for group_member(:guest) } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } + end + + context 'with mixed projects' do + before(:all) { create_project(:mixed) } + + it { is_expected.to be_allowed_for group_member(:owner) } + it { is_expected.to be_allowed_for group_member(:master) } + it { is_expected.to be_allowed_for group_member(:reporter) } + it { is_expected.to be_allowed_for group_member(:guest) } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } + end + + context 'with internal projects' do + before(:all) { create_project(:internal) } + + it { is_expected.to be_allowed_for group_member(:owner) } + it { is_expected.to be_allowed_for group_member(:master) } + it { is_expected.to be_allowed_for group_member(:reporter) } + it { is_expected.to be_allowed_for group_member(:guest) } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } + end + + context 'with no projects' do + it { is_expected.to be_allowed_for group_member(:owner) } + it { is_expected.to be_allowed_for group_member(:master) } + it { is_expected.to be_allowed_for group_member(:reporter) } + it { is_expected.to be_allowed_for group_member(:guest) } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } + end + end + + describe 'GET /groups/:path/issues' do + subject { issues_group_path(group) } + + context 'with public projects' do + before(:all) { create_project(:public) } + + it { is_expected.to be_allowed_for group_member(:owner) } + it { is_expected.to be_allowed_for group_member(:master) } + it { is_expected.to be_allowed_for group_member(:reporter) } + it { is_expected.to be_allowed_for group_member(:guest) } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } + end + + context 'with mixed projects' do + before(:all) { create_project(:mixed) } + + it { is_expected.to be_allowed_for group_member(:owner) } + it { is_expected.to be_allowed_for group_member(:master) } + it { is_expected.to be_allowed_for group_member(:reporter) } + it { is_expected.to be_allowed_for group_member(:guest) } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } + end + + context 'with internal projects' do + before(:all) { create_project(:internal) } + + it { is_expected.to be_allowed_for group_member(:owner) } + it { is_expected.to be_allowed_for group_member(:master) } + it { is_expected.to be_allowed_for group_member(:reporter) } + it { is_expected.to be_allowed_for group_member(:guest) } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } + end + + context 'with no projects' do + it { is_expected.to be_allowed_for group_member(:owner) } + it { is_expected.to be_allowed_for group_member(:master) } + it { is_expected.to be_allowed_for group_member(:reporter) } + it { is_expected.to be_allowed_for group_member(:guest) } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } + end + end + + describe 'GET /groups/:path/merge_requests' do + subject { merge_requests_group_path(group) } + + context 'with public projects' do + before(:all) { create_project(:public) } + + it { is_expected.to be_allowed_for group_member(:owner) } + it { is_expected.to be_allowed_for group_member(:master) } + it { is_expected.to be_allowed_for group_member(:reporter) } + it { is_expected.to be_allowed_for group_member(:guest) } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } + end + + context 'with mixed projects' do + before(:all) { create_project(:mixed) } + + it { is_expected.to be_allowed_for group_member(:owner) } + it { is_expected.to be_allowed_for group_member(:master) } + it { is_expected.to be_allowed_for group_member(:reporter) } + it { is_expected.to be_allowed_for group_member(:guest) } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } + end + + context 'with internal projects' do + before(:all) { create_project(:internal) } + + it { is_expected.to be_allowed_for group_member(:owner) } + it { is_expected.to be_allowed_for group_member(:master) } + it { is_expected.to be_allowed_for group_member(:reporter) } + it { is_expected.to be_allowed_for group_member(:guest) } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } + end + + context 'with no projects' do + it { is_expected.to be_allowed_for group_member(:owner) } + it { is_expected.to be_allowed_for group_member(:master) } + it { is_expected.to be_allowed_for group_member(:reporter) } + it { is_expected.to be_allowed_for group_member(:guest) } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } + end + end + + describe 'GET /groups/:path/group_members' do + subject { group_group_members_path(group) } + + context 'with public projects' do + before(:all) { create_project(:public) } + + it { is_expected.to be_allowed_for group_member(:owner) } + it { is_expected.to be_allowed_for group_member(:master) } + it { is_expected.to be_allowed_for group_member(:reporter) } + it { is_expected.to be_allowed_for group_member(:guest) } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } + end + + context 'with mixed projects' do + before(:all) { create_project(:mixed) } + + it { is_expected.to be_allowed_for group_member(:owner) } + it { is_expected.to be_allowed_for group_member(:master) } + it { is_expected.to be_allowed_for group_member(:reporter) } + it { is_expected.to be_allowed_for group_member(:guest) } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } + end + + context 'with internal projects' do + before(:all) { create_project(:internal) } + + it { is_expected.to be_allowed_for group_member(:owner) } + it { is_expected.to be_allowed_for group_member(:master) } + it { is_expected.to be_allowed_for group_member(:reporter) } + it { is_expected.to be_allowed_for group_member(:guest) } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } + end + + context 'with no projects' do + it { is_expected.to be_allowed_for group_member(:owner) } + it { is_expected.to be_allowed_for group_member(:master) } + it { is_expected.to be_allowed_for group_member(:reporter) } + it { is_expected.to be_allowed_for group_member(:guest) } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } + end + end + + describe 'GET /groups/:path/edit' do + subject { edit_group_path(group) } + + context 'with public projects' do + before(:all) { create_project(:public) } + + it { is_expected.to be_allowed_for group_member(:owner) } + it { is_expected.to be_denied_for group_member(:master) } + it { is_expected.to be_denied_for group_member(:reporter) } + it { is_expected.to be_denied_for group_member(:guest) } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } + end + + context 'with mixed projects' do + before(:all) { create_project(:mixed) } + + it { is_expected.to be_allowed_for group_member(:owner) } + it { is_expected.to be_denied_for group_member(:master) } + it { is_expected.to be_denied_for group_member(:reporter) } + it { is_expected.to be_denied_for group_member(:guest) } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } + end + + context 'with internal projects' do + before(:all) { create_project(:internal) } + + it { is_expected.to be_allowed_for group_member(:owner) } + it { is_expected.to be_denied_for group_member(:master) } + it { is_expected.to be_denied_for group_member(:reporter) } + it { is_expected.to be_denied_for group_member(:guest) } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } + end + + context 'with no projects' do + it { is_expected.to be_allowed_for group_member(:owner) } + it { is_expected.to be_denied_for group_member(:master) } + it { is_expected.to be_denied_for group_member(:reporter) } + it { is_expected.to be_denied_for group_member(:guest) } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } + end + end +end From b42422a7a97d376fb5f78e8dfa614857d6b8d1fa Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 22 Jul 2015 00:39:18 -0400 Subject: [PATCH 069/174] Move spec/features/admin/security_spec to spec/features/security --- .../{admin/security_spec.rb => security/admin_access_spec.rb} | 2 ++ 1 file changed, 2 insertions(+) rename spec/features/{admin/security_spec.rb => security/admin_access_spec.rb} (96%) diff --git a/spec/features/admin/security_spec.rb b/spec/features/security/admin_access_spec.rb similarity index 96% rename from spec/features/admin/security_spec.rb rename to spec/features/security/admin_access_spec.rb index 175fa9d4647..fe8cd7b7602 100644 --- a/spec/features/admin/security_spec.rb +++ b/spec/features/security/admin_access_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe "Admin::Projects", feature: true do + include AccessMatchers + describe "GET /admin/projects" do subject { admin_namespaces_projects_path } From aee579eac2389fdf9ec8e3e60f2c8cabeac10f3d Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Wed, 22 Jul 2015 11:31:15 +0200 Subject: [PATCH 070/174] Use mdash to prevent breaking html emails. --- app/views/layouts/notify.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/layouts/notify.html.haml b/app/views/layouts/notify.html.haml index ee1b57278b6..c8662a15adb 100644 --- a/app/views/layouts/notify.html.haml +++ b/app/views/layouts/notify.html.haml @@ -33,7 +33,7 @@ = yield %div.footer{style: "margin-top: 10px;"} %p - \— + — %br - if @target_url #{link_to "View it on GitLab", @target_url} From ca451365abc26ede22f9b13482e3120fd61833de Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Wed, 22 Jul 2015 11:46:08 +0200 Subject: [PATCH 071/174] Remove docs and rake task for gmail actions to prevent problems with registration. --- doc/integration/gitlab_actions.png | Bin 17321 -> 0 bytes doc/integration/gitlab_buttons_in_gmail.md | 28 ------- .../mail_google_schema_whitelisting.rake | 73 ------------------ 3 files changed, 101 deletions(-) delete mode 100644 doc/integration/gitlab_actions.png delete mode 100644 doc/integration/gitlab_buttons_in_gmail.md delete mode 100644 lib/tasks/gitlab/mail_google_schema_whitelisting.rake diff --git a/doc/integration/gitlab_actions.png b/doc/integration/gitlab_actions.png deleted file mode 100644 index b08f54d137bd9ab1bde8471211f95016a9ee6aa0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17321 zcmb{4bzED`qA&bDErn9tDee?69=sHa6N;Ch#hnIsTHGma0a`3L#T`ls?gZBo+>1+) zH+}X#=k9awe$VIL`@Z=jnYCsXGi1#Q%$FZ4;vG;P=Q+jmM~@!iC@RQmJbLul8dbh| z_89e?(aIU{=#k7vMOkSr&-sHaLp28d`=d*{9pP2VSIf?;IJ%aN8kM-ZLBh9YZ&-85 zuGD_O!mMdy{d^-cYGEvS5`-B*ub&I1y^xh}(nJEYFUuYVrK+9JfP#M=2O4YD9FRxnuY+oy*Y{ z-J}vf1y&^a<89&HH%QvbJABrwend3-ll6e(Gq=jaCZ=TUr$OI(_yh#_B&o&P@C~wu0`$_ev#ZR#y*F~XQf+g37~Q**erm!oY<@^f%_m#TZlujlPB;39etPAD*i+)evFM z63meqjmVD;uhR)r@5$sA^oAFW-S^r_!RC@JMffg82p=q$yRQ$1k3BA;Ap_KHo}woe z!URB1&C&bRaOKZ#N|6A@{=d)!vfixo!sZ4-hNeI?zCZ-$8PAB$ha3=JZKH9KP_Ud} z9nlo7V{2OfjUxlF7*2e(;(vFZL)dYDy7Ex9>$`V-TH_K?b9zg1w>LL;t?lR5GQ~%n7T30e1Z42rQth&naXGjsMvEW(u z)G@}xy+=Q}SoTSWZ3ni zAK$Hif0}(stNF7l_>%Y_waOKr(SfpQiebTh0Wr03BH(7fepW8w9|Sl8Esa{2P8mZNZ0gqGi%L^;BQ3GM zb0bd*e04QSmUzwqec6*XY%4j2i-K$%i!H?i$w`BND0s2mUboYY3O*)y4DO?_N^jhU6+1%8)k6iW5)9RhA!; zQBbEMqW7(oc5vzgejr<0}#Lu}|V&*wmb%WMJ#!MA$-|czE3jnj&iLm24I1h6k zh7l&Q)5|56Lb)IA7Bjk&{Bh%blivZ12umWmzuyCiv{Ri42O|JtOfRBY`5`d?pN106 zCB105pXRwb6TWvU;%7>zS$y)VjZ|aAPpB23)|I>3Ph7coNH%iC+JLi=?HF|T`LgrV zJ^A_AY0oWFI{Bmq#9gKF5yEvQ?_*0Q2i!kEoa2nxN{p8F1qD5<{WqvdwIjpgU_mPX zjVN)(elp=mFElhXw8s+n>SX8aWg;~VMa;glL)*}u2ETlvP?J4hPhq%x591PLn?#IS z4I83rNA><^aw~bi*kuoO1{p_4Ou=~3iuiAzEAQ_L{Fl7_^wOZ}S{7&qBn3lO-b2JuScqS6gH>f1*1qn88~dEVjni%M zZEZ%32yQ~GlWks}L+|nAx8roS(wSZaVwA+{6``8N^N=C1)@h8WmYg=(yc3(@8M*{l z{D?MXj5B?k5*HEB)gX$We5pUVaxHruK!RrP7S{Qpo$R zCa2^j{38ZJpJ_YYJR{&HL`Ln(_w!GYOLaaMuf2#*$- z+f3ha9cDo>8m#$m_uLAzY-{Z7h~}S4LMZvFy_iGxj<2>ZcK0s><4z^x=z&>ME%`U= zQ}(r1t1i1i+`i`yR@dJ5uRVq+0o5WNssV>OJvRm$?PqEUQu;#BEY{RfbP|s@kW2F4 zWv91qFO*d-2FAX8aQ@QwmiT<=9r!sfgH&d}G~>PJ(%Y1)r52mzw`!` z{uOd^u$+sEM!t6|`A6QZqRwt@qKcICO2Pu!Nv07=kOj$%CBq%8b5sgZoAfd#VCkUsu&*cq&0CW z&Q>3h4GKr`kP43=1X6_`fp^>bZE9>quCzQe;?`TRF z_p`s z>`W_n+eBZ8GM_(%o{OCAynv!e8Fe@M{zalPy{F-q z?X%yvLBP!Ae#J`eGl+O1gQmYCtCSiYamE=r@g{Ri()Vv>oWmRh(ACAuqowT9fCRh< zz})2w5aOuOjt`YY7k>p6)a!hYqfs%I%irSqMf0{A0qun*k_tYXbZ6vu^C-_l2yD15 zfTt3{UZ$@|w!UzuOo7BGh{|Ih#K9$^0yYt6leq?7 zVG~)t$ZVW!#0x)i1ycj(>HgL@OD`TSi_zI7agQE`NYgj(O)KN9beH(V#VACpVDUxq z@i`tmGfBH_hrBnL08YhZU0kcVYk6l_6D&LPsPKa!#Eul|6%D7au8oo;0OKaM$NFC7hNc$C1Ff09dvk9QA-?`Ezezso|x%8C+7pGu5 znD+hs_J(3Dfk#Tb8}I-g`r>&^zllt$^hs75>h`m-)OP>7d44rJeCQGxZaADiZSfp$ zu1pIY*4z$%134@3Fgt`IG{DZ5c%{mww=EWJ0Nt|g7pvK+fMGi-!*ESR^A873&^hde zUP2$-!(XpHpBGW1sY6_6EjSa(&R#}j1xsUaV+9H#YRQka!=#cgE~nU+ly|w`NEG6# zr-o%$0+xmh+M3wfXC4=rh@L9yQxGWIZS67wr!j=CVw+zZS?pB4rTcb>4;V* z9OZ3x(w)W_-UbT_RD+}a31U%P+W?HpB_x`1dgB*v<~AF-S}w4@uB zi(l_V`yk}W4E8V8SD85Oo!%PO#U?ojM6mSY!YpGBwl-#G*0R#{C0`0U&8m0JJEIa+zK+#Otovr~oO6-(pR?GO!ikDOhG8GUN`&Q__b;$4 z7E3m3R-Sz3d?GQsWEfHY@myaYOu;y!p8<6f;VOaxcxtuEf6?{LFafJwZsY_gaOI*I zeGAMdKa`D_XHk!D4+o2iY^P;W5ermQS|6lktpgz*Grg|zy71F>u~-lgw>bw;y!3?f zMW>~SMsZW6&W;h$z>ZeNZ3j~;%$UR_xkOOTe!oOj)%R4_KFKUPF|r0E>Ds2T#=%!$ zz>>(J?U|jL>Y5-eV+IkqrXL*HbmOg`Su{-bFvb+zZAQC#p_y zALGTZG-PkhD>vxE=J*F(!v%+dZl@cVi1o>WB&7tn5-Tni)y~dZCYihXS9M5(*Hq@3 zpF{dLiaJ{^V0~g0LKHvy{ATs}=$G+KrbuBH7RN z9okFE8QOZw=4l@rUR7mGyw%OE_iENSc+$-_QIIaZL`ZNNa$}o}dON5?TF5v@GVjOG zIR!V$tX$t>6R=XY;UIC9Z6zcv6bpD7xz(hY*C3&@t`VFcKU@r`;}&{_T}<)W-F!LM zjPPvITf{Y?teSZGeNlT?`dEBej77wGF$LgBxZfDeX)q%3G z9U2GTjj`Hgh(+_ISWBvr{_?}SrIuK!v}(z${nw=xLcHwhxF2JCZZhgCx#Y)|oD zoTNSPrA#^SSYb~Iy!rHoGDMhhBy*_w1LOOn4;ww|kbPLrVQcR7HC+u&H<4(5@g%dM z(ez4Ikxzkcoj_tAfn{I?*Tkm0(urPx;t?#^pA}6?*XMon`NHdNJ!NFf_`Tw2!;pz8 zpKf0@HUm(1(a0M4I9i4I)VGCe!??GuI}K!@km?XU^s(@_`uxTnojz&*j^4!?n+y|& za~0BIr()rew5@F$*R-1O91i{!ZKV!m{s>&sKh?6Ed$*tPPW-@si|%x8XD`-cH>T@H7ITF!%RCX3N>5*WQsZzb^zm~iSqa1L6 zrDyKp)2S@>$`ucJwzII;r&KMLN%1+O#Ng!zgS&XgAUov%-hH~N8G#OY!!)1Tk>2Ge z;hNR`-Gz6ffjADEZ);56ABWF1-W|G|8LOD(fS5zm#rz`Ri|-yBTTn{y;%_k;!F9Ft_t2C6cIfKOvsoMW6PTG3@V znPdu0MozvG3s?~nbXnGS{_d%Ad|Y-=2D*8z1DD{>_b|1wQun~A(c!*3rwy2j zi=#M{C|PVNb-}UI>O+4vL2Z-+Oe35WZzw=&ysCn=_#71p9t@m$uh0Wo_RFjo*BA?N zPW$|~8yq1X`dgMN&^TauQhDgBJ!8v5D>hLPYYUgRm1FVgs$DEcZI)9#W!=|j9q2cM zk9HgF;*EDXQw!$OaHLy%0hH-mdMsP1{X1N&NCl~9?1n|-Yg>bpwDRz~v($~w!$pdO z+XJEdW_rn8x(`sX9PMWKUbfRIylyw7(3Vy5$+TGZ zLYwEfjaxy;Yt(JWu$Go)!oMYcQKPCw(>Ed@P&mdx3RVn{{IO-hJrL-*@UU|p<*P@R zY<}AM>PpqPPOnY_KJVMqa!qUO)Uj@Lk0t5;OC%ibx86x(1&+O?F)B2s|8^HQ;~#$d zboD#cQv{j`YMl)yxa0^5b3MFszxfA%1q0}TkHGit9kH{qVG5@2;z{QpJP*Q9d;d^f zheWHHU$mBa2SOT|Q+S8Jg%zmje`~i+j6nOvt5JtX@F{b z>CTEt_f_qeT>5(6V>?uL{{o@^S^V$#^&cqv-|_3;DEq(gYbzD_4?REni1Rnho-qQ^ zmi}z_{8M33#s2`=e<{ZOY4UIO|I6P0t0tXySNC^51seSu&K-aKwxpx=JgH)(^*{SV z%6|Gp187cqIUiX+0i*-I@GRvc8yg$((WI&HSK9p&AMzjQ+h2~|H;nn8d}gKfIay_W zKpVqDLGsyWDo0WMQxR7fp3Rf_xC{OI&%XPp6L5$64y0-OFiW9F<~c4}!51A_7lSzg zXHWighH_u`>Y&}%!l_*ch+q}B^UHrlV+}8@8r0wrRI+| z0kC3cpJV1jT1u}O3u|k0Ur~2&`bP2ehiX0v3A6sQvw^qz+*6V<^81l&A<#m+$qD?e zAAPW(zo@@KVuZzF48&EQqt!jmdh=e=3i>I4Ii(mRJnJTRm*SzR)-m%2Iezb7`4sG4 zpcfn6Rs-uu_W=9*xZGw*FhWfmlK$zmp8yzx=Oyez+dcja=_)ia_|a0VJNKb-dl-20l;o{tce)> zYxD7aHf>fvMEKXg{#4h7EEZvbd#V{=BJV&-edNy$8oZOa4meVVq#<~*07V{`vt|A= z!rA+V;wOalPtML)L--{HkF@U*=^YfV#1l{M`^3u3u5)k-gYMTl&MLh(HPooyO6277w3R#DrnEpFFPqK=` zg}J2~6$!y&-L-W-I3rnu#Eq`sLsqkV7&81IfbfHO=EY3h!)3s@FyepTV3iD{UHMtO zIoK_naI~KV?upW9LpIiJUy(;2ZdG7miqgG^JTw*)&C?#Xm+ji$ws_T=#x9_BnnWt| z?IR$+P2rvpo4L#q-EBbeL_?vi-W6oc%etrzmLm+=d&4&rn-a=^Sz$}RI~iN?p02Sm zk<_41&HEYs1j19Xh=tVcl0;9nb%=L_fyl*MYR|&cO#td;Eq(HZ1-NqZfGrxh^A{s9 zZXVspkGF%GN+{e#@*GAmYj&D2KbnuRO}SclN5uUawu4?Zbl_N_g1kE}8`Fdw`1+b# z2je4u+HDBk*{0MvJ$!k-^Uk_jR|!CyLxFl^iu@Xc!t+$zJ*@?*2kXxHE|rI=(&yK! z`^hsIXkNs*I-OkzNDdc<_ZA9YFXXU}O!xy#q-)J-D@hWf{-R_MgSZ-TkX3uTLC30< zwhz;kdt4Yupwy-N_6sdN?G8KE6*HF%nPFdl^L6*5#WU$6c?Vk=_MaAMNi2AIJ<}@k zAQ&=gX&&-uYAunf2Na+ys%EONZ8EW0sPTZOd7_psNO-tFl{|V$QB}QYMj|aUOA_lM zla={V1}EqK9A&4eZ*?0s+nL+A*^5Rs*}F2kck+yTH)C&_1z^`j|NrPI5fliBw+@Ec zcY5~t|I#=$cvT(Grd_)6##Ea~?X2-;4cM0tH?R%c=DKAw zl%dKhuwo;Q>;dBE>1#!#nsQn#D+Odb<0j($+Le{c_Wi#?f7u3Wm(#}&knr`#Y)6qo zf3S%7Dc=s`hxo{Z==_rjHl1k_60Qgp3O{g%Zl3|%j^H)?XTN$JF z?M+SD9FDUyzF;k?L4zb!RmqY$J+vg@0$JtLI z6vE;;&88K()E|yA?h;mg$(B-PX71`!eFEMI7>v-n_#ZVAA@)}?Awrq;dq2Njg-Dl? z84jG++c?H&2vJi`*|@rP7gnxAr=0nr73jh*z_Bdpt+sapZ?w}o1S4HIdwBbe9F|mq z`-R}(X{a&wsdDw=hpei!k_$=2Us_HT8Sc#1%s+3EI0cQRYHWuG)fLcYzxS7wG~nwv zbxs!TnH6-#uf<}4l~$`AAL%$hM1=#mm^1GBV4{2JhsT>nU)xo;Ebhuhk{4 z5=7s|g2N7quU%EPln%}-a$+l*g-ctoxD-HxUjXlCkQmDyc-v9lX06}uG{P;9sW@{w z+P&s8e+b6l2@$8g(o(PmWSA8k9%BSaCISk2cy;6B`aIh5BTn;uzF!(HzM2c{|8;va zJssvXz0?WugL!qC9C!D*E&?I;UM-^ZKtF6x6Ci4NUPX~_@a?UY`wkuS%A#8>PK}kz z7Qg5~&T{tGhrX0H{>j>a~EI%Q9ocJ7TLnf_}!mN929QY$cT|j zy`wW1A}$_yOqm2wh4MR)7Kk5|F!bX0PZVlm@3_9fVU|JWVu2}W-!$Ox2qBn0tXfsl z2bbj7fxFkkn!R2pg=CJXcZhV ziULTu&{}`lS3bV22jvA^o6L=d0?zS3qeq%SJIW4PGY?gcgwTMUBJST-7(QFN_Eh3j ziz5T0uR1QXV*oLu9}a6Ms(HSTcJd;$DtxupuMu<0TV$D8`2mVu0E(u*RS%;5D)KV$b`y?ISag|ib(fXb{IwD>e$tR1{j06fc)5;_elE|J~+wJc^X@@8JWNGSZw^h=^U9J`MKZ!Q9$;)I5a?3mAQ@+(M zGLiU<*QDX`Shcth4XzQKA6NTWk1OLttk0$rC|GN}N8C^fW3L|?J<&JBNg-ZEQjztg zIX{%FiEAmyVqKsLHhx*;-#%nJftr05%|)(c%~6{;^o?4R@(iOJU9Re6Px-vuG@A6j zq{N%n%(?RSM1-Gy_F6D}_%f_S;!(6G#syO}_7>jsXXhqiwYvD;%+%ANKON=L4T2CH zHic_03+cGY<^M9BGlQ0eyBs&}(vAFn-Th*j=k8-PfS)o_B&c3tt&AJ?f>&;dhZRw~ zcJewZ_wnA&C5=l51?w=j>LdT{` zK^> z*5H6eJ87|t6RnTdh#an5hQ5kg9&dj}-YkY|Mi|%iB_NN7x^3(@p<3leF`+!nBFyoW z@!G;K!5I}6MBq@q%dAX$Bz|@SV9E8pta4&X)(4Z8{%0zwC2dV2#us89b=h-_nf+qf zv&+p*7%b!E4oO3@5Z(%%d8`bk#>LiRu5(u45kaNe6uVi9Go>dNKI>^r9d2_yFwDkK z5<}2%=T#4zGB8ws*YE>Bv^&sTleMP@b$vwW$&^e}sSTpm9ApQUK|GhH(wQ$b%>k`D zEQnglwOalHdc?kn&U0`i8I);UbR(zgT~E2KBvJyuk8dn!X(@U3xo$@t36vMnTHpmr zg$H^^p1x6@dX5|D8;e-45W9=i%OqbOcQ03E>ChnDZwwIK&Y~#8J=?M>95_<%D7eofnn+8WLOrfJqn#0Xcj<;}v5tf6t3)-34JHCNJjqD)f! zSyiSag&^M_eMh#WLNbhHYeo&%G^a~cx0o%p81;E_a?P)FT4rTi8@<{I((Mz+_fkqV z*qYiB=?Z7bY-O%0zIk0I{5BS_v=~AaKC`ELZ7-B4X^0&#c~?V;x!?UyTixr^(tQzgDl%89au1M4hFia zcoZPLOUJG4Fh!O};~OtaZ}b{-DWYw)my{t*z!e0sv#X5_?E7x;2<3Cm!XqO?*p8)& z!Y-`Nix$+XXnFcwJrD>nf5%=^s8}f`QbhS1HfcfK?grc`jI;C$eNk#o*dPDlTOW+@ zh|W_7!sO?h$R7+Dv@(B;TS>-hCrO*`Hd(G@NG~%_X0R1gHG_!^pWQF$r5z;j(Bi{N zq**Ehm2S~>dkwiF_5YzEFa?|-kx~G4q#?FX(I+f z-fxiJUh#M#toBru(E}?3?-CGWp|RT&Ml+Ig%ghapskKTVr<7 zaF1M<($eQ}-W-3CNM0K{yJ+h3eeM#>kh3V;$(BRE@dVZ(Nd~ku{6=)Mb%!+9E)eRv;6tfaC!KxVDbco5 z4tL5qk8tvj#vBgbbnn11G@8o4vVklZflbhggOGiSZ8eTdE6FI{S@j`Hn3@;vNrF2g+Max2rA8(AGZ8Ev#;Tbc~Mdq&Mz$no79^pCh50 zb9>baE=%Q^L$JQ&sa!X(ujOVUlbJ>=Hjr%jf95?gWUTv8ZS~R{(&8>5(kD<_?}Nny zf&|=OvtFOx7~7$uh^`j3T$d~05C62SoadZK=eofB`5VPlA{XS7gRoLctH|OI#%i~w;m;HjC zt@jeK`gw^#EYr1?Ek3x-K8WonIdq8I8Z19CPLAlqdl}u(t<5<;nuq!2j8SotB0YnN zgP|?V@*Jx2r)jGnEMbaqdP-TS-K>bT#EDU{N}!MHsVyxBP%t?;9z7! z`7K|>`sGRhPYS!Ss>Py#$2$vq!g1f#%K!`K{E(27bKTVQfIGh#sa3pTo^mHg8fTJo zPc9|h;#ULlYQ;vx_ve)>E=>ljxrIF9jr1CSDAh)J8bzmo5+ zc>Xt`x>6A`8WR?Ni}`C#{k_^RqSQf)iM`YLt0iNGfB^S{860$7qqEbF%PkCquQY&D z{xhIc4IhehI@|}R#*}Bhc^&p_#E| zDaT83;Zr43mag+ioU)?)VGP z{ayUPs7*lPL+^@vs_E(K$6$PY(1L_G*HpFxvh+bTnXbc4|Ne$OJK*7ucH=`%){GgU zD7KVD_$u_Ckr%i6i#gWP{;A{t4+-CjQk#;@f8tCe(I|4sixTg=JNG{!Sky4LTn?#_ zsw>~_tUEGMWBG%oGNhyNv1@xXl~1C@X&5uSa8U+ntcUFH&Gx~?hnr78UBNVh?4!+teRpT}0)PAE7_Nlvn8W27~FJ z1p?^W{g5mViVrfr>aB$riT^l=#YsT&0Cm<(9`&sj)(GYVDbP%W3NQPgYz|1X{zpx5 zD>N1661!_;jNI^ek>ief>t4MAOR6biE16jToqT>o!;G3ftjkADoOs1sR$0jEzyDt1 zVzO8VL;oD@R43|bM?WI1h~PyVbD9jfVARG!{i-TfVEqao8$CB-Vi3G}?k_-WGRsqE zKlr>r<(u>a=uZavAXK>G=(m@r_TQ#G_MfJGFdzeAZy+;9+*ieW7>0(*^+3&_WPyW; z*E}3>IDd+YTBSj)gBs@%P;rJbCIX+8apXu$?gi z+O|vVQndQhLfpI2gGYXTo~zMn!#>F!o|~129GS>u`k6wmbg^b{rd0_eB(2OW{#Km3 zPK=PedwRaD(4j7FoKt<49ln~yQ`~FeZrTP1#)i#zi3^Zvi~^_kklfi_`jHmkW#Z!Q z8Tn%-O&4PC(V?B`xf;3h%@ng?59X#$6obbpmoj%DnZ>}%ZlItJV>?k(k1YSv87-DN zMTDlRw|A#zsX;7wdQ{5V6krB3!X75mf zbu%+mz+O*{9hWjgY1g>vcc~7McbdmrZUE^~)(puh#yx?H(4{1z)j?VR{WH@ARXue! zAG@MA_y#k_3W%g6f@mr-v>E^-GF`(vh*}(*=a4v942!zJ{b#du&o2aU{@r(o0S7|QD1|Tm)POyo>l801JHA!FU(4#{~G6AIgUV__ri?F##IEM>#p)L+!k0 zBOnJ4Md2mWIHu_fO9tr|$ThuhP{6|VRo~b%`iqd60SES{W^>E;s|;G1GVu7F_8!3L zaq+ir->TA|wEK!m448+7$uYJV=<~RAOb*2tt8!;X$5hAC`~$-)qP+iM;mjl484OzB zd3^B-zP4jSvz2;Rf!O?3W z7p-e)Hy)(&oIO^GV#^YvO!r&hU|!ear(T?r=&|Kf!b(YBE0C4-lLXRU>DWBrgeQXO z`==|c9336|IuCPx8huils!6tUj}zWAM05G=?Up{e)sOozRrfrT+g8Hy8}xnl9v#rx z#@TRZx0`TfGOKiIuFR11)VXSqndL*K?KnY)X-7u8Pp=RdXVTajHwP^%rnNNqj9!!#~|S-K^aFqs%Ky z*{RaE1soV_FT@-U?Ub+`sjNz7rrwBlhFev6v%WP?cg;{f7^}vNRdz`UO7_^mPMucb zF6=kv-w-qF3OtrAdB;w5BwGj2AKbeDci;x~D$OZ~C-+-SC@uxH!EclVj%K5sBE_{8KODpXT*V0WMAP2FG2&$`3 zR#{s-)yAgPx}l-ii9xd5xkXl?k(%KIPV*|b6vw@)C&bsy3Z;9Rkp0D#_+;~Xqpglt zpVua((<3!?CutR(4V*0oissX=*gPn5#s@0ab3|>BgLu3$R@32y_Y$q0OT6jrjU`zC zR#!YKc%Y4;L1BmmD%iy|q5uTi)!T<*Jmm&rSB|kPwr|sQyM&NV*rmu|yG!`0O-Gc%)M( z_go8TEs@=pJ60~$S(d6iGW04VSGJi2 z0k#t3em((Fp%VD^cBDx_6Ef08pnqL^4@yw-^R`?aV#XV*cwxI|$)HkyEs%@$74^?K z&fxp)mtd-_gp%{tDAdd&jKfj0xp3okb11vIdB1bT*h}4(gN>=Um(*OcJ>}XZ@F?{e znmxs$i;hF@2OX|!p|S5HWpatse)V(1ccPJS^3!o4rj5yxlu1Jr7-7WR75wzDV19;k z&_|2VkI+oCXY)NYmp?v|^+dwpMt2qYOG8 zjFuNC>b(5RQZ$|l`h08B;Bz@uQ}dUHqK27*<*4j~R+E$%HiS8U|ME2+Z9{_;T3XM` z#Na3&8ZN@D)aS$e(=@o7EeHckSidINR`n$7caM-lh3|uZLWKFj=8dRSfGp%mp8r1x z{G+jd2x-<_K@bFyN+Km8nYE6=F#=xW%y&09H#f*8SFxkX*yPeLU2*}A7D2`7jC*2B8LWqsSOUq*bYb`|t(c79r2t{KmgAj-;p zFPJR9gk7FDXOuQ0&cRQ#Sivm!Hi2b?ywWH&2B4_{(?fps9K*(%|5=-Sn^n zZ(E72+bhJRns;?keFxI5(fcE>+ty1USG9*MH>Wv5<=!Ak9;_%?pE36?Ose0n__NK~ zEZFxH2qfre4~L`cU}m>XsAlO2yjbJ_4KeLLFU&1)k)YMM&J{2&MA109YLL%$MUiE( ze)USQgUsP1ziw0UP|4PnDQn8lv9}P7lKLi+S26nNfrAS99rYL5rhwwdDXN>Tdh}& zz;*N6`qAB=t^{Z1y*q@gwE;FB^%VfPpjF}t z0971*orRSJW4QICL5MB z2dwuN$k&oy`aS1$v4e-z2%u#p)g%>$Ybx1Pix};JN3IhO1u}_a22ybGf_gOCQ3>W8 zZiNHE(t5F;{v56a!x=IVk2)K0HaX)et@+kcWlAZ&mJm##QRh3b<=e3P&RT8tyw-9w zoX8B)wz`wz8IQb@rM#zFgRv4q`J@#74k+tFNX0OAH0rcWzC}lE&5WW;*c#Ynm5@vo zSC#CdGXgcc>=}W&mwP9>BLr5~jBB~eI)VQ1)%BPBX$iNp@7#aK975fbIK&!SHB;^= ze5s2;r}>0Y3PtXw2dO_&e#j~htlf)$S9HK(5&Mx5Jqyhx}9oLgJ}NFTDyc;E8^!;T`hrJwXQ1O-@%wZLmD z&LnUq^lIcVI?IouuCttVhztMJXDTs7!Q6(z|iP=#=b|LhyOLSgD zXn8QbOMvKzg5UpAP@`RG{T}rggKNZt-xxc}V0-=RH$yMLMRIte`GqT7o>FYynYh@B z)LCpOm%y;il?F$VV)>j4=&%^OPJ7-3K?RjRR6SaY@1C2vlT?66q1_b4Xx38LH1D6L zaYuZ>t;Pbv7DF8ug3Y$BhjMSb>4-;LUBSy|PXhRyVukrt4PVH>=7y{jgM4ekY$YOB z#c5VVq0!_CV4zH6JxtK)icyBHF{vJBE*eo*aF@XlH>siOz-#T1LPSJlw`#&)b2u*c zzNK;%v*0~{*M2e6Xo7#Ba)BH0CNi*i^Wz8eAXrBIF;8^nKdex z{#KV0c7tN1B|bC97@E`2m6R!m&zwoOufY@*%wrobW%%9XrQ5~9N{1?&Fra*qrH;%d z4!*3z-e1m=x(vvQ$e9AP8Zh<2B63l=jlgP}q44>X4s_~ejl(m$QuZ4H=zR4%UsQN` z76;!us-_a@mj+NoYsoXT;Z?W&qKwHLo1Q~#G1K-k_W;+AZ_gG+#h=5L<_G{{Ymj+g zystdjg(+$gyy^)E3uQnDCx{fB(kwYAU0;9gZI!Fxki2`J_h67w;zI&Y*UU74>qG2s z<;6+U3|Hne@c3rZ-ZKUj6m;piV>`P$_}MvRs~%Q>1(zVphYrD(GTy_31gv6%#Vu4J ziwD7B=`_CEo4k}|id)ZL47`R^G`5XhJS9(8+PrqxALxj+i{kCwVJB*~H#3(b8Fety zrx00}>Pva+?42UvS7I;r?B){=etzNfg6W-W;?kqf568LPY@i6ZxP!njFp9)k9hqxi zJ9#u}CO?-bjr@B^aEI+q%EH}Xm+O!fw5?Ik*E~EmmYzfnruz4DeJ{A{!s~Zx+ zrQg(q+5ec_TP?~2${L+j!p=BGq#kY)Z?7A^>(UZWV_Uojr?fy(E^XA(B&=+6akePB zX7S)XY+|ZWkmos647w{(GMn(Ie2Fob%$(CDgqgGcW_U3L+FM3z@zRsW+@s~*b@%`- z)SGc~`cQ*)SGwT?OZg07&NQ%}f8d-QvosRG3MGk4i&;2w6uu~M?0CY-2>fOY&Y;{~ zakwO0KP6?&!Y#Qt8oxUO8+3Gey5=!u+8KhvoJ**_CEXfSex|D9de4r(Pa^ zbY=7?Kbk)(an7Cm-XH7sUR!~0%|C$?m7sM;VDCNA^SIn&8u7~mRBDzEq!RkQdr7RJ z4tH!F$B815$l9$cpu<8EtdYKP@1jv6BILQ5nc9c#EK1L$O>(5qY6@g!7JgWRX(VUs zD~9m!*@E5}6p*jO2l(XvK<^`sde}~RJ)d+Z0O=@fKo^z7{mo8B| zn)40nJo+V@>@YP72xoE^j2ZT{3tEhEk!+WC^gh>IU#!KK@uK>j&g#az#tr-ZP|4pQ z9+G~l7jLSxY$RW!UpBhd=&)^?N0KZbB8HU|IV?1bbl8@KGW3p}QlU~ETTmvChw#JN-a+c^P(Wud zZY#?=_tfIIg@{Or5rm`z;5}Qj4J!)B+UclL@=#_cE(UJi2}dS(%B)XT){goA$!Gjg z;9rWGb?#X$)Ohi*uMAwZw8fym_l|d8iI1wU0Xy0cS8I4RVgb+9*r0!swe<=ArOhW4Mh;4|dUk(l zNNXLxs(lhp^yzbx=1mCC_GvPEVr$cPmVciT{(rfN#J}8H0wt3uLjCUo&Hsed|Gb~X zk3j - - - - GitLab - - - - - -
-
-

I like it :+1:

-
-
- -
- - " - end - - def send_now - if ENV['SEND'] == "true" - true - else - false - end - end -end From 276ca427ea8c30b20881f466bb9137596174cdb4 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 22 Jul 2015 14:07:41 +0200 Subject: [PATCH 072/174] Fix Remove source-branch for MRs from same project --- CHANGELOG | 1 + app/models/merge_request.rb | 4 ++++ app/services/files/base_service.rb | 2 +- app/services/merge_requests/auto_merge_service.rb | 6 +++++- lib/gitlab/satellite/merge_action.rb | 2 +- 5 files changed, 12 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 2765923124f..136cfe5f74f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -11,6 +11,7 @@ v 7.14.0 (unreleased) - Expire Rails cache entries after two weeks to prevent endless Redis growth - Add support for destroying project milestones (Stan Hu) - Add fetch command to the MR page. + - Fix bug causing "Remove source-branch" option not to work for merge requests from the same project. v 7.13.0 (unreleased) - Remove repository graph log to fix slow cache updates after push event (Stan Hu) diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 53b3fc10ccb..1ef76d16700 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -235,6 +235,10 @@ class MergeRequest < ActiveRecord::Base execute(self, commit_message) end + def remove_source_branch? + self.should_remove_source_branch && !self.source_project.root_ref?(self.source_branch) && !self.for_fork? + end + def open? opened? || reopened? end diff --git a/app/services/files/base_service.rb b/app/services/files/base_service.rb index f587ee266da..646784f2d9d 100644 --- a/app/services/files/base_service.rb +++ b/app/services/files/base_service.rb @@ -39,7 +39,7 @@ module Files def after_commit(sha, branch) commit = repository.commit(sha) - full_ref = 'refs/heads/' + branch + full_ref = "#{Gitlab::Git::BRANCH_REF_PREFIX}#{branch}" old_sha = commit.parent_id || Gitlab::Git::BLANK_SHA GitPushService.new.execute(project, current_user, old_sha, sha, full_ref) end diff --git a/app/services/merge_requests/auto_merge_service.rb b/app/services/merge_requests/auto_merge_service.rb index df793fc997d..a5ee16e529c 100644 --- a/app/services/merge_requests/auto_merge_service.rb +++ b/app/services/merge_requests/auto_merge_service.rb @@ -37,6 +37,10 @@ module MergeRequests # Merge local branches using rugged instead of satellites if sha = commit after_commit(sha, merge_request.target_branch) + + if merge_request.remove_source_branch? + DeleteBranchService.new(merge_request.source_project, current_user).execute(merge_request.source_branch) + end end end end @@ -55,7 +59,7 @@ module MergeRequests def after_commit(sha, branch) commit = repository.commit(sha) - full_ref = 'refs/heads/' + branch + full_ref = "#{Gitlab::Git::BRANCH_REF_PREFIX}#{branch}" old_sha = commit.parent_id || Gitlab::Git::BLANK_SHA GitPushService.new.execute(project, current_user, old_sha, sha, full_ref) end diff --git a/lib/gitlab/satellite/merge_action.rb b/lib/gitlab/satellite/merge_action.rb index 1f2e5f82dd5..f9bf286697e 100644 --- a/lib/gitlab/satellite/merge_action.rb +++ b/lib/gitlab/satellite/merge_action.rb @@ -33,7 +33,7 @@ module Gitlab merge_repo.git.push(default_options, :origin, merge_request.target_branch) # remove source branch - if merge_request.should_remove_source_branch && !project.root_ref?(merge_request.source_branch) && !merge_request.for_fork? + if merge_request.remove_source_branch? # will raise CommandFailed when push fails merge_repo.git.push(default_options, :origin, ":#{merge_request.source_branch}") end From dbff6bc106c679edbd135a69ba74532fabe1e996 Mon Sep 17 00:00:00 2001 From: ngentile Date: Wed, 22 Jul 2015 09:58:17 -0400 Subject: [PATCH 073/174] Gitlab Issue 707: Indent unfolded code 1 character --- app/assets/javascripts/diff.js.coffee | 4 ++++ app/views/projects/blob/diff.html.haml | 2 +- lib/unfold_form.rb | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/diff.js.coffee b/app/assets/javascripts/diff.js.coffee index 069f91c30e1..6d9b364cb8d 100644 --- a/app/assets/javascripts/diff.js.coffee +++ b/app/assets/javascripts/diff.js.coffee @@ -31,6 +31,10 @@ class @Diff bottom: unfoldBottom offset: offset unfold: unfold + # indent is used to compensate for single space indent to fit + # '+' and '-' prepended to diff lines, + # see https://gitlab.com/gitlab-org/gitlab-ce/issues/707 + indent: 1 $.get(link, params, (response) => target.parent().replaceWith(response) diff --git a/app/views/projects/blob/diff.html.haml b/app/views/projects/blob/diff.html.haml index 84742608986..f3b01ff3288 100644 --- a/app/views/projects/blob/diff.html.haml +++ b/app/views/projects/blob/diff.html.haml @@ -11,7 +11,7 @@ %td.old_line.diff-line-num{data: {linenumber: line_old}} = link_to raw(line_old), "#" %td.new_line= link_to raw(line_new) , "#" - %td.line_content.noteable_line= line + %td.line_content.noteable_line= ' ' * @form.indent + line - if @form.unfold? && @form.bottom? && @form.to < @blob.loc %tr.line_holder{ id: @form.to } diff --git a/lib/unfold_form.rb b/lib/unfold_form.rb index 46b12beeaaf..fcd01503d1b 100644 --- a/lib/unfold_form.rb +++ b/lib/unfold_form.rb @@ -8,4 +8,5 @@ class UnfoldForm attribute :bottom, Boolean attribute :unfold, Boolean, default: true attribute :offset, Integer + attribute :indent, Integer, default: 0 end From bde2173b636782aee14c5c3c09ca2cc1775931e1 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Wed, 22 Jul 2015 16:59:06 +0300 Subject: [PATCH 074/174] Fix link to 2fa help page. Closes #2055 --- app/views/profiles/two_factor_auths/new.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/profiles/two_factor_auths/new.html.haml b/app/views/profiles/two_factor_auths/new.html.haml index 74268c9bde2..92dc58c10d7 100644 --- a/app/views/profiles/two_factor_auths/new.html.haml +++ b/app/views/profiles/two_factor_auths/new.html.haml @@ -5,7 +5,7 @@ Download the Google Authenticator application from App Store for iOS or Google Play for Android and scan this code. - More information is available in the #{link_to('documentation', help_page_path('workflow', 'two_factor_authentication'))}. + More information is available in the #{link_to('documentation', help_page_path('profile', 'two_factor_authentication'))}. %hr From 6454bcbfa4bee56b53ff4e17f9e18ecc00ecbbd5 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Wed, 22 Jul 2015 17:53:18 +0300 Subject: [PATCH 075/174] revert cache issue --- CHANGELOG | 3 + app/views/projects/issues/_issue.html.haml | 73 +++++++++++----------- 2 files changed, 39 insertions(+), 37 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 2765923124f..1ba9d9f308c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -12,6 +12,9 @@ v 7.14.0 (unreleased) - Add support for destroying project milestones (Stan Hu) - Add fetch command to the MR page. +v 7.13.1 + - Revert issue caching + v 7.13.0 (unreleased) - Remove repository graph log to fix slow cache updates after push event (Stan Hu) - Only enable HSTS header for HTTPS and port 443 (Stan Hu) diff --git a/app/views/projects/issues/_issue.html.haml b/app/views/projects/issues/_issue.html.haml index 1b45bb1af0c..b6910c8f796 100644 --- a/app/views/projects/issues/_issue.html.haml +++ b/app/views/projects/issues/_issue.html.haml @@ -3,43 +3,42 @@ .issue-check = check_box_tag dom_id(issue,"selected"), nil, false, 'data-id' => issue.id, class: "selected_issue" - = cache issue do - .issue-title - %span.issue-title-text - = link_to_gfm issue.title, issue_path(issue), class: "row_title" - .issue-labels - - issue.labels.each do |label| - = link_to_label(label, project: issue.project) - .pull-right.light - - if issue.closed? - %span - CLOSED - - if issue.assignee - = link_to_member(@project, issue.assignee, name: false) - - note_count = issue.notes.user.count - - if note_count > 0 -   - %span - %i.fa.fa-comments - = note_count - - else -   - %span.issue-no-comments - %i.fa.fa-comments - = 0 - - .issue-info - = "#{issue.to_reference} opened #{time_ago_with_tooltip(issue.created_at, placement: 'bottom')} by #{link_to_member(@project, issue.author, avatar: false)}".html_safe - - if issue.votes_count > 0 - = render 'votes/votes_inline', votable: issue - - if issue.milestone + .issue-title + %span.issue-title-text + = link_to_gfm issue.title, issue_path(issue), class: "row_title" + .issue-labels + - issue.labels.each do |label| + = link_to_label(label, project: issue.project) + .pull-right.light + - if issue.closed? + %span + CLOSED + - if issue.assignee + = link_to_member(@project, issue.assignee, name: false) + - note_count = issue.notes.user.count + - if note_count > 0   %span - %i.fa.fa-clock-o - = issue.milestone.title - - if issue.tasks? - %span.task-status - = issue.task_status + %i.fa.fa-comments + = note_count + - else +   + %span.issue-no-comments + %i.fa.fa-comments + = 0 - .pull-right.issue-updated-at - %small updated #{time_ago_with_tooltip(issue.updated_at, placement: 'bottom', html_class: 'issue_update_ago')} + .issue-info + = "#{issue.to_reference} opened #{time_ago_with_tooltip(issue.created_at, placement: 'bottom')} by #{link_to_member(@project, issue.author, avatar: false)}".html_safe + - if issue.votes_count > 0 + = render 'votes/votes_inline', votable: issue + - if issue.milestone +   + %span + %i.fa.fa-clock-o + = issue.milestone.title + - if issue.tasks? + %span.task-status + = issue.task_status + + .pull-right.issue-updated-at + %small updated #{time_ago_with_tooltip(issue.updated_at, placement: 'bottom', html_class: 'issue_update_ago')} From 6e08e7aac490c5758589bd50db331d42dd24219b Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Wed, 22 Jul 2015 17:04:49 +0200 Subject: [PATCH 076/174] Check if session_expire_delay column exists before adding the column. --- ...121_add_session_expire_delay_for_application_settings.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/db/migrate/20150609141121_add_session_expire_delay_for_application_settings.rb b/db/migrate/20150609141121_add_session_expire_delay_for_application_settings.rb index ffa22e6d5ef..61ff0af41f4 100644 --- a/db/migrate/20150609141121_add_session_expire_delay_for_application_settings.rb +++ b/db/migrate/20150609141121_add_session_expire_delay_for_application_settings.rb @@ -1,5 +1,7 @@ class AddSessionExpireDelayForApplicationSettings < ActiveRecord::Migration def change - add_column :application_settings, :session_expire_delay, :integer, default: 10080, null: false + unless column_exists?(:application_settings, :session_expire_delay) + add_column :application_settings, :session_expire_delay, :integer, default: 10080, null: false + end end -end \ No newline at end of file +end From 4466f25dd52e7eb9230b7d16d8d4103ebd900cc6 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Wed, 22 Jul 2015 17:03:57 +0300 Subject: [PATCH 077/174] revert cache for events --- CHANGELOG | 1 + app/views/events/_event.html.haml | 15 +++++++-------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 1ba9d9f308c..7ddddac014f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -14,6 +14,7 @@ v 7.14.0 (unreleased) v 7.13.1 - Revert issue caching + - Reverted cache for events v 7.13.0 (unreleased) - Remove repository graph log to fix slow cache updates after push event (Stan Hu) diff --git a/app/views/events/_event.html.haml b/app/views/events/_event.html.haml index b8409f64665..5ab5ffc238c 100644 --- a/app/views/events/_event.html.haml +++ b/app/views/events/_event.html.haml @@ -8,11 +8,10 @@ = image_tag avatar_icon(event.author_email, 24), class: "avatar s24", alt:'' = render "events/event/created_project", event: event - else - = cache event do - = image_tag avatar_icon(event.author_email, 24), class: "avatar s24", alt:'' - - if event.push? - = render "events/event/push", event: event - - elsif event.commented? - = render "events/event/note", event: event - - else - = render "events/event/common", event: event + = image_tag avatar_icon(event.author_email, 24), class: "avatar s24", alt:'' + - if event.push? + = render "events/event/push", event: event + - elsif event.commented? + = render "events/event/note", event: event + - else + = render "events/event/common", event: event From 0484ae7e6a7f0e6301089cdf7ce3e8a17e9079b8 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 23 Jul 2015 13:10:32 +0200 Subject: [PATCH 078/174] Return true/false from AutoMergeService#merge! --- app/services/merge_requests/auto_merge_service.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/services/merge_requests/auto_merge_service.rb b/app/services/merge_requests/auto_merge_service.rb index a5ee16e529c..db824d452d0 100644 --- a/app/services/merge_requests/auto_merge_service.rb +++ b/app/services/merge_requests/auto_merge_service.rb @@ -41,6 +41,10 @@ module MergeRequests if merge_request.remove_source_branch? DeleteBranchService.new(merge_request.source_project, current_user).execute(merge_request.source_branch) end + + true + else + false end end end From 70a3c165a9f3882a82cf8946a783ace091635797 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 2 Jul 2015 16:33:38 +0200 Subject: [PATCH 079/174] Allow custom label to be set for authentication providers. --- CHANGELOG | 1 + .../bitbucket_64.png | Bin app/assets/images/auth_buttons/github_64.png | Bin 0 -> 2625 bytes app/assets/images/auth_buttons/gitlab_64.png | Bin 0 -> 2849 bytes .../google_64.png | Bin .../twitter_64.png | Bin app/assets/images/authbuttons/github_64.png | Bin 4196 -> 0 bytes app/assets/images/authbuttons/gitlab_64.png | Bin 6559 -> 0 bytes app/controllers/application_controller.rb | 6 +-- .../omniauth_callbacks_controller.rb | 5 +- app/controllers/sessions_controller.rb | 2 +- app/helpers/auth_helper.rb | 50 ++++++++++++++++++ app/helpers/oauth_helper.rb | 34 ------------ app/helpers/profile_helper.rb | 13 ----- app/views/admin/identities/_form.html.haml | 3 +- .../admin/identities/_identity.html.haml | 2 +- app/views/devise/sessions/_new_ldap.html.haml | 2 +- .../devise/shared/_omniauth_box.html.haml | 8 ++- app/views/devise/shared/_signin_box.html.haml | 2 +- app/views/profiles/accounts/show.html.haml | 14 ++--- config/gitlab.yml.example | 25 ++++++--- doc/integration/omniauth.md | 2 +- features/steps/admin/users.rb | 9 +++- lib/gitlab/o_auth/provider.rb | 30 +++++++---- spec/helpers/auth_helper_spec.rb | 20 +++++++ spec/helpers/oauth_helper_spec.rb | 20 ------- 26 files changed, 140 insertions(+), 108 deletions(-) rename app/assets/images/{authbuttons => auth_buttons}/bitbucket_64.png (100%) create mode 100644 app/assets/images/auth_buttons/github_64.png create mode 100644 app/assets/images/auth_buttons/gitlab_64.png rename app/assets/images/{authbuttons => auth_buttons}/google_64.png (100%) rename app/assets/images/{authbuttons => auth_buttons}/twitter_64.png (100%) delete mode 100644 app/assets/images/authbuttons/github_64.png delete mode 100644 app/assets/images/authbuttons/gitlab_64.png create mode 100644 app/helpers/auth_helper.rb delete mode 100644 app/helpers/oauth_helper.rb delete mode 100644 app/helpers/profile_helper.rb create mode 100644 spec/helpers/auth_helper_spec.rb delete mode 100644 spec/helpers/oauth_helper_spec.rb diff --git a/CHANGELOG b/CHANGELOG index c6c5bc0aac4..b31ef352549 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -72,6 +72,7 @@ v 7.12.2 - Faster automerge check and merge itself when source and target branches are in same repository - Audit log for user authentication - Fix transferring of project to another group using the API. + - Allow custom label to be set for authentication providers. v 7.12.1 - Fix error when deleting a user who has projects (Stan Hu) diff --git a/app/assets/images/authbuttons/bitbucket_64.png b/app/assets/images/auth_buttons/bitbucket_64.png similarity index 100% rename from app/assets/images/authbuttons/bitbucket_64.png rename to app/assets/images/auth_buttons/bitbucket_64.png diff --git a/app/assets/images/auth_buttons/github_64.png b/app/assets/images/auth_buttons/github_64.png new file mode 100644 index 0000000000000000000000000000000000000000..182a1a3f734fc1b7d712c68b04c29bad9460d6cd GIT binary patch literal 2625 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 literal 0 HcmV?d00001 diff --git a/app/assets/images/authbuttons/google_64.png b/app/assets/images/auth_buttons/google_64.png similarity index 100% rename from app/assets/images/authbuttons/google_64.png rename to app/assets/images/auth_buttons/google_64.png diff --git a/app/assets/images/authbuttons/twitter_64.png b/app/assets/images/auth_buttons/twitter_64.png similarity index 100% rename from app/assets/images/authbuttons/twitter_64.png rename to app/assets/images/auth_buttons/twitter_64.png diff --git a/app/assets/images/authbuttons/github_64.png b/app/assets/images/authbuttons/github_64.png deleted file mode 100644 index dc7c03d10052a596f062207ae0fd8e9cf384b2aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4196 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

X%~0la9wB4oXwju zWm>O7AtSrGx?Jpb0$5Bs!C)}RhQ=msdiu(q=H`|-Hj8EEayWgJMl2SaauZ8PfCdN- z3hY|Dc8wt+F`kVmKsGx;r_q2Rc9+n-y}g+%HaiLc*mvns`qA+i=z4o=3i7ir3>lg@ z#7!(2j3^4#)KoWY-?sVip~FXWfwI)}eUP0LA3f`*gZnZK2E7I$gjA}owv#80>}_jn zDZUREa6gEv`R=<-1pv@6bLNao8jZTG&oh+OYVBUNGW`Mo+*-c;?HYox_xz{*uwJKC zWSu&eQC(G0fDocclBCK@Z&baqXu&D~2psVAHZdVO?eyu)EUVS3LkJ;RXGg<_2MfR2$CczlA@|^R^EK&g;CC-RfRM{oowAO0Q*v^0h`ZRshsWm&SuB>l zurRMmBJrg2`2z97_WKASV6#}7g!rMYQ>RUj=5l%7aQixrBU&*`EEeOju|rgYV}=Ob z-Nh2@5qf9<0IS8)ed%IO9*fCljTo6chQVO4+S^;}zWnm@1KYOmJ_rEP2N@@L!^i7B zF_}z?+vjq2OG!!b#a%mo*wNjs>U@;*K8hkO1VN|}MOht>Qg@2IXMU+0wIJf7K`$1 z*2$yCj~%+8)Abr3!3osEk^v7hEY~a)alWF zegWYCKx=7flz;Z=KM$6c*PL*GtcRAckJtZgN4H98cDh@oQZ|3E`n~VYW}P}nlBBjT z+`3;P>{2S4Uw?gZ<*=lr?$M)1Ym$?b)yc`p>X9QyX-1D4)v|5tmLi+YrhU*=cLa;Q zrKPEC#XEofy13})EGG-4QYlUA|MB5=00?^|_VMMHr`_hp1H8xV+_5#wXfQa#p6uw5 zRxf&K-j|mP^DiNU?0tKL`|MHOkt2tSA|k>o9YiYOcq!(lr4=+cHPsBn>-e!F=k0d8#i>AB zYwNAI-dvLT^OeFngpmCqct1^bbye%MY15hjphqlr@A>e<52|~6b)64r{GDku8jXC- z2k)IbnR)z*qlrT{o6U0c=%KR-af4^wgYomR@zU;xaLQD+ik?ztkbn?*Q`9%-P7Iq7>>{#&LRza_w2g-#b=*f z?d|RDb)FsEtSrx;oHBM90Qfwq!&hHEm+@?I(a)I_McHp7E|YcV_N|vb|JR27dc96| zpOB^yqDYFO2#TTzM~^|>D_BU9H0GQ?m%rxymB-|Ane(i{UQ~4DB$tgp`>4j_kLUos z%}&V=?8`7DB*ck=fK-Mt3}Itsb0Zqb7IU!BZ6ewrjndsS8Ct(ED^KlgAK4jHJq`ELpa0DkkHO?~Im z#he<1C_*liUrC)kX~X4$ON9@5p~7jsR;!gQ{>zL1K7Q;JLeZZO^gW34^?|qvE}H-rQYNQ`K@mCpe8a8V&l5UwnG*?3t4n zEEbb;Z^n+?sHl)M01!AQd3NUDKlUXh8o=n)E8p2Im9}Z6()QZVKilwQds|!m{c63% zV(HnlXJ=N<`Ll(sEzOFxAFSMmW03r~^u!;>pq>H%gB7HguM|}@HP&i}3>g|fC_F-R z{rc64fPg@Ti;IhUzw0HOCR~O{vUM1{yjKkr$ezM{3yMEZZ>stg+>Fo|+F#j)c zfbo}`INJJKO(o@}MRFf6ZwZ&faaVT9Y6Aj-M07esvdH(%M0@Ja@7ijqIcWY zANFToDA?urh00?w{;@gWH$PNz_?bP^#4{$C2?zw}e~{{cDhNt3<1 Rz)t`G002ovPDHLkV1k8$(}Ms2 diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 362b03e0d5e..3ce8dbc9407 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -299,14 +299,14 @@ class ApplicationController < ActionController::Base end def github_import_enabled? - OauthHelper.enabled_oauth_providers.include?(:github) + Gitlab::OAuth::Provider.enabled?(:github) end def gitlab_import_enabled? - OauthHelper.enabled_oauth_providers.include?(:gitlab) + Gitlab::OAuth::Provider.enabled?(:gitlab) end def bitbucket_import_enabled? - OauthHelper.enabled_oauth_providers.include?(:bitbucket) && Gitlab::BitbucketImport.public_key.present? + Gitlab::OAuth::Provider.enabled?(:bitbucket) && Gitlab::BitbucketImport.public_key.present? end end diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb index fd51b380da2..523264b8ea9 100644 --- a/app/controllers/omniauth_callbacks_controller.rb +++ b/app/controllers/omniauth_callbacks_controller.rb @@ -72,10 +72,11 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController end end rescue Gitlab::OAuth::SignupDisabledError => e - message = "Signing in using your #{oauth['provider']} account without a pre-existing GitLab account is not allowed." + label = Gitlab::OAuth::Provider.label_for(oauth['provider']) + message = "Signing in using your #{label} account without a pre-existing GitLab account is not allowed." if current_application_settings.signup_enabled? - message << " Create a GitLab account first, and then connect it to your #{oauth['provider']} account." + message << " Create a GitLab account first, and then connect it to your #{label} account." end flash[:notice] = message diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 89629bc0581..796cbe4c58c 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -90,7 +90,7 @@ class SessionsController < Devise::SessionsController # Prevent alert from popping up on the first page shown after authentication. flash[:alert] = nil - redirect_to omniauth_authorize_path(:user, provider.to_sym) + redirect_to user_omniauth_authorize_path(provider.to_sym) end def valid_otp_attempt?(user) diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb new file mode 100644 index 00000000000..0e7a37b4cc6 --- /dev/null +++ b/app/helpers/auth_helper.rb @@ -0,0 +1,50 @@ +module AuthHelper + PROVIDERS_WITH_ICONS = %w(twitter github gitlab bitbucket google_oauth2).freeze + FORM_BASED_PROVIDERS = [/\Aldap/, 'kerberos'].freeze + + def ldap_enabled? + Gitlab.config.ldap.enabled + end + + def provider_has_icon?(name) + PROVIDERS_WITH_ICONS.include?(name.to_s) + end + + def auth_providers + Gitlab::OAuth::Provider.providers + end + + def label_for_provider(name) + Gitlab::OAuth::Provider.label_for(name) + end + + def form_based_provider?(name) + FORM_BASED_PROVIDERS.any? { |pattern| pattern === name.to_s } + end + + def form_based_providers + auth_providers.select { |provider| form_based_provider?(provider) } + end + + def button_based_providers + auth_providers.reject { |provider| form_based_provider?(provider) } + end + + def provider_image_tag(provider, size = 64) + label = label_for_provider(provider) + + if provider_has_icon?(provider) + file_name = "#{provider.to_s.split('_').first}_#{size}.png" + + image_tag(image_path("auth_buttons/#{file_name}"), alt: label, title: "Sign in with #{label}") + else + label + end + end + + def auth_active?(provider) + current_user.identities.exists?(provider: provider.to_s) + end + + extend self +end diff --git a/app/helpers/oauth_helper.rb b/app/helpers/oauth_helper.rb deleted file mode 100644 index 2fdca13ed40..00000000000 --- a/app/helpers/oauth_helper.rb +++ /dev/null @@ -1,34 +0,0 @@ -module OauthHelper - def ldap_enabled? - Gitlab.config.ldap.enabled - end - - def default_providers - [:twitter, :github, :gitlab, :bitbucket, :google_oauth2, :ldap] - end - - def enabled_oauth_providers - Devise.omniauth_providers - end - - def enabled_social_providers - enabled_oauth_providers.select do |name| - [:saml, :twitter, :gitlab, :github, :bitbucket, :google_oauth2].include?(name.to_sym) - end - end - - def additional_providers - enabled_oauth_providers.reject{|provider| provider.to_s.starts_with?('ldap')} - end - - def oauth_image_tag(provider, size = 64) - file_name = "#{provider.to_s.split('_').first}_#{size}.png" - image_tag(image_path("authbuttons/#{file_name}"), alt: "Sign in with #{provider.to_s.titleize}") - end - - def oauth_active?(provider) - current_user.identities.exists?(provider: provider.to_s) - end - - extend self -end diff --git a/app/helpers/profile_helper.rb b/app/helpers/profile_helper.rb deleted file mode 100644 index 780c7cd5133..00000000000 --- a/app/helpers/profile_helper.rb +++ /dev/null @@ -1,13 +0,0 @@ -module ProfileHelper - def show_profile_username_tab? - current_user.can_change_username? - end - - def show_profile_social_tab? - enabled_social_providers.any? - end - - def show_profile_remove_tab? - signup_enabled? - end -end diff --git a/app/views/admin/identities/_form.html.haml b/app/views/admin/identities/_form.html.haml index 0525552ebf8..3a788558226 100644 --- a/app/views/admin/identities/_form.html.haml +++ b/app/views/admin/identities/_form.html.haml @@ -8,7 +8,8 @@ .form-group = f.label :provider, class: 'control-label' .col-sm-10 - = f.select :provider, Gitlab::OAuth::Provider.names, { allow_blank: false }, class: 'form-control' + - values = Gitlab::OAuth::Provider.providers.map { |name| ["#{Gitlab::OAuth::Provider.label_for(name)} (#{name})", name] } + = f.select :provider, values, { allow_blank: false }, class: 'form-control' .form-group = f.label :extern_uid, "Identifier", class: 'control-label' .col-sm-10 diff --git a/app/views/admin/identities/_identity.html.haml b/app/views/admin/identities/_identity.html.haml index 671c4fbc677..7362d904b94 100644 --- a/app/views/admin/identities/_identity.html.haml +++ b/app/views/admin/identities/_identity.html.haml @@ -1,6 +1,6 @@ %tr %td - = identity.provider + = "#{Gitlab::OAuth::Provider.label_for(identity.provider)} (#{identity.provider})" %td = identity.extern_uid %td diff --git a/app/views/devise/sessions/_new_ldap.html.haml b/app/views/devise/sessions/_new_ldap.html.haml index 6ec741e4882..689cd6ed665 100644 --- a/app/views/devise/sessions/_new_ldap.html.haml +++ b/app/views/devise/sessions/_new_ldap.html.haml @@ -6,4 +6,4 @@ %label{for: "remember_me"} = check_box_tag :remember_me, '1', false, id: 'remember_me' %span Remember me - = button_tag "#{server['label']} Sign in", class: "btn-save btn" + = button_tag "Sign in", class: "btn-save btn" diff --git a/app/views/devise/shared/_omniauth_box.html.haml b/app/views/devise/shared/_omniauth_box.html.haml index f8ba9d80ae8..ecf680e7b23 100644 --- a/app/views/devise/shared/_omniauth_box.html.haml +++ b/app/views/devise/shared/_omniauth_box.html.haml @@ -1,10 +1,8 @@ %p %span.light Sign in with   - - providers = additional_providers + - providers = button_based_providers - providers.each do |provider| %span.light - - if default_providers.include?(provider) - = link_to oauth_image_tag(provider), omniauth_authorize_path(resource_name, provider), method: :post, class: 'oauth-image-link' - - else - = link_to provider.to_s.titleize, omniauth_authorize_path(resource_name, provider), method: :post, class: "btn", "data-no-turbolink" => "true" + - has_icon = provider_has_icon?(provider) + = link_to provider_image_tag(provider), user_omniauth_authorize_path(provider), method: :post, class: (has_icon ? 'oauth-image-link' : 'btn'), "data-no-turbolink" => "true" diff --git a/app/views/devise/shared/_signin_box.html.haml b/app/views/devise/shared/_signin_box.html.haml index c76574db457..bb5e479697d 100644 --- a/app/views/devise/shared/_signin_box.html.haml +++ b/app/views/devise/shared/_signin_box.html.haml @@ -6,7 +6,7 @@ .login-heading %h3 Sign in .login-body - - if ldap_enabled? + - if form_based_providers.any? %ul.nav.nav-tabs - @ldap_servers.each_with_index do |server, i| %li{class: (:active if i.zero?)} diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml index 378dfa2dce0..767fe2e0e9a 100644 --- a/app/views/profiles/accounts/show.html.haml +++ b/app/views/profiles/accounts/show.html.haml @@ -59,22 +59,22 @@ %div = link_to 'Enable Two-factor Authentication', new_profile_two_factor_auth_path, class: 'btn btn-success' - - if show_profile_social_tab? + - if button_based_providers.any? .panel.panel-default .panel-heading Connected Accounts .panel-body .oauth-buttons.append-bottom-10 %p Click on icon to activate signin with one of the following services - - enabled_social_providers.each do |provider| + - button_based_providers.each do |provider| .btn-group - = link_to oauth_image_tag(provider), omniauth_authorize_path(User, provider), - method: :post, class: "btn btn-lg #{'active' if oauth_active?(provider)}" - - if oauth_active?(provider) + = link_to provider_image_tag(provider), user_omniauth_authorize_path(provider), method: :post, class: "btn btn-lg #{'active' if auth_active?(provider)}", "data-no-turbolink" => "true" + + - if auth_active?(provider) = link_to unlink_profile_account_path(provider: provider), method: :delete, class: 'btn btn-lg' do = icon('close') - - if show_profile_username_tab? + - if current_user.can_change_username? .panel.panel-warning.update-username .panel-heading Change Username @@ -94,7 +94,7 @@ %div = f.submit 'Save username', class: "btn btn-warning" - - if show_profile_remove_tab? + - if signup_enabled? .panel.panel-danger.remove-account .panel-heading Remove account diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index c32ac2042d0..41a01e7703c 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -209,20 +209,29 @@ production: &base # arguments, followed by optional 'args' which can be either a hash or an array. # Documentation for this is available at http://doc.gitlab.com/ce/integration/omniauth.html providers: - # - { name: 'google_oauth2', app_id: 'YOUR_APP_ID', + # - { name: 'google_oauth2', + # label: 'Google', + # app_id: 'YOUR_APP_ID', # app_secret: 'YOUR_APP_SECRET', # args: { access_type: 'offline', approval_prompt: '' } } - # - { name: 'twitter', app_id: 'YOUR_APP_ID', - # app_secret: 'YOUR_APP_SECRET'} - # - { name: 'github', app_id: 'YOUR_APP_ID', + # - { name: 'twitter', + # app_id: 'YOUR_APP_ID', + # app_secret: 'YOUR_APP_SECRET' } + # - { name: 'github', + # label: 'GitHub', + # app_id: 'YOUR_APP_ID', # app_secret: 'YOUR_APP_SECRET', # args: { scope: 'user:email' } } - # - { name: 'gitlab', app_id: 'YOUR_APP_ID', + # - { name: 'gitlab', + # label: 'GitLab.com', + # app_id: 'YOUR_APP_ID', # app_secret: 'YOUR_APP_SECRET', # args: { scope: 'api' } } - # - { name: 'bitbucket', app_id: 'YOUR_APP_ID', - # app_secret: 'YOUR_APP_SECRET'} - # - { name: 'saml', + # - { name: 'bitbucket', + # app_id: 'YOUR_APP_ID', + # app_secret: 'YOUR_APP_SECRET' } + # - { name: 'saml', + # label: 'Our SAML Provider', # args: { # assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback', # idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8', diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md index 8e2a602ec35..2010cb9b8a1 100644 --- a/doc/integration/omniauth.md +++ b/doc/integration/omniauth.md @@ -84,7 +84,7 @@ Existing users can enable OmniAuth for specific providers after the account is c 1. Sign in normally - whether standard sign in, LDAP, or another OmniAuth provider. 1. Go to profile settings (the silhouette icon in the top right corner). 1. Select the "Account" tab. -1. Under "Social Accounts" select the desired OmniAuth provider, such as Twitter. +1. Under "Connected Accounts" select the desired OmniAuth provider, such as Twitter. 1. The user will be redirected to the provider. Once the user authorized GitLab they will be redirected back to GitLab. The chosen OmniAuth provider is now active and can be used to sign in to GitLab from then on. diff --git a/features/steps/admin/users.rb b/features/steps/admin/users.rb index 6c4b91586d6..49e64eeff71 100644 --- a/features/steps/admin/users.rb +++ b/features/steps/admin/users.rb @@ -3,6 +3,14 @@ class Spinach::Features::AdminUsers < Spinach::FeatureSteps include SharedPaths include SharedAdmin + before do + allow(Devise).to receive(:omniauth_providers).and_return([:twitter, :twitter_updated]) + end + + after do + allow(Devise).to receive(:omniauth_providers).and_call_original + end + step 'I should see all users' do User.all.each do |user| expect(page).to have_content user.name @@ -121,7 +129,6 @@ class Spinach::Features::AdminUsers < Spinach::FeatureSteps end step 'I visit "Pete" identities page in admin' do - allow(Gitlab::OAuth::Provider).to receive(:names).and_return(%w(twitter twitter_updated)) visit admin_user_identities_path(@user) end diff --git a/lib/gitlab/o_auth/provider.rb b/lib/gitlab/o_auth/provider.rb index f986499a27c..90c3fe8da33 100644 --- a/lib/gitlab/o_auth/provider.rb +++ b/lib/gitlab/o_auth/provider.rb @@ -1,18 +1,30 @@ module Gitlab module OAuth class Provider - def self.names - providers = [] + def self.providers + Devise.omniauth_providers + end - Gitlab.config.ldap.servers.values.each do |server| - providers << server['provider_name'] + def self.enabled?(name) + providers.include?(name.to_sym) + end + + def self.ldap_provider?(name) + name.to_s.start_with?('ldap') + end + + def self.config_for(name) + name = name.to_s + if ldap_provider?(name) + Gitlab::LDAP::Config.new(name).options + else + Gitlab.config.omniauth.providers.find { |provider| provider.name == name } end + end - Gitlab.config.omniauth.providers.each do |provider| - providers << provider['name'] - end - - providers + def self.label_for(name) + config = config_for(name) + (config && config['label']) || name.to_s.titleize end end end diff --git a/spec/helpers/auth_helper_spec.rb b/spec/helpers/auth_helper_spec.rb new file mode 100644 index 00000000000..e47a54fdac5 --- /dev/null +++ b/spec/helpers/auth_helper_spec.rb @@ -0,0 +1,20 @@ +require "spec_helper" + +describe AuthHelper do + describe "button_based_providers" do + it 'returns all enabled providers' do + allow(helper).to receive(:auth_providers) { [:twitter, :github] } + expect(helper.button_based_providers).to include(*[:twitter, :github]) + end + + it 'does not return ldap provider' do + allow(helper).to receive(:auth_providers) { [:twitter, :ldapmain] } + expect(helper.button_based_providers).to include(:twitter) + end + + it 'returns empty array' do + allow(helper).to receive(:auth_providers) { [] } + expect(helper.button_based_providers).to eq([]) + end + end +end diff --git a/spec/helpers/oauth_helper_spec.rb b/spec/helpers/oauth_helper_spec.rb deleted file mode 100644 index 3ef35f35102..00000000000 --- a/spec/helpers/oauth_helper_spec.rb +++ /dev/null @@ -1,20 +0,0 @@ -require "spec_helper" - -describe OauthHelper do - describe "additional_providers" do - it 'returns all enabled providers' do - allow(helper).to receive(:enabled_oauth_providers) { [:twitter, :github] } - expect(helper.additional_providers).to include(*[:twitter, :github]) - end - - it 'does not return ldap provider' do - allow(helper).to receive(:enabled_oauth_providers) { [:twitter, :ldapmain] } - expect(helper.additional_providers).to include(:twitter) - end - - it 'returns empty array' do - allow(helper).to receive(:enabled_oauth_providers) { [] } - expect(helper.additional_providers).to eq([]) - end - end -end From f6ba8c41e23e449da52c019b7faf3e07a33bd9d7 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Thu, 23 Jul 2015 14:47:15 +0000 Subject: [PATCH 080/174] Clarify some things in monthly.md --- doc/release/monthly.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/release/monthly.md b/doc/release/monthly.md index ca9696e957e..552b24195b1 100644 --- a/doc/release/monthly.md +++ b/doc/release/monthly.md @@ -68,7 +68,7 @@ Xth: (2 working days before the 22nd) Xth: (1 working day before the 22nd) - [ ] Merge CE stable into EE stable -- [ ] Create (hopefully final) CE, EE, CI release candidates (#LINK) +- [ ] Create CE, EE, CI release candidates (#LINK) (hopefully final ones with the same commit as the release tomorrow) - [ ] Create Omnibus tags and build packages for the latest release candidates - [ ] Update GitLab.com with the latest RC (#LINK) - [ ] Update ci.gitLab.com with the latest RC (#LINK) @@ -81,10 +81,10 @@ workday to quickly fix any issues. - [ ] Merge CE stable into EE stable (#LINK) - [ ] Create the 'x.y.0' tag with the [release tools](https://dev.gitlab.org/gitlab/release-tools) (#LINK) -- [ ] BEFORE 11AM CET Create and push omnibus tags for x.y.0 (will auto-release the packages) (#LINK) -- [ ] BEFORE 12AM CET Publish the release blog post (#LINK) +- [ ] Try to do before 11AM CET: Create and push omnibus tags for x.y.0 (will auto-release the packages) (#LINK) +- [ ] Try to do before 12AM CET: Publish the release blog post (#LINK) - [ ] Tweet about the release (blog post) (#LINK) -- [ ] Schedule a second tweet of the release announcement at 6PM CET / 9AM PST +- [ ] Schedule a second tweet of the release announcement with the same text at 6PM CET / 9AM PST ``` @@ -220,4 +220,4 @@ Consider creating a post on Hacker News. ## Create a WIP blogpost for the next release -Create a WIP blogpost using [release blog template](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/doc/release_blog_template.md). +Create a WIP blogpost using [release blog template](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/doc/release_blog_template.md). \ No newline at end of file From 01d29ae66127845df42b3dcb915162b3def71f61 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Thu, 23 Jul 2015 15:12:44 +0000 Subject: [PATCH 081/174] update changelog1 --- CHANGELOG | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index c6c5bc0aac4..10c755403e9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -14,8 +14,14 @@ v 7.14.0 (unreleased) - Fix bug causing "Remove source-branch" option not to work for merge requests from the same project. v 7.13.1 - - Revert issue caching - - Reverted cache for events + - Fix: Label modifications are not reflected in existing notes and in the issue list + - Fix: Label not shown in the Issue list, although it's set through web interface + - Fix: Group/project references are linked incorrectly + - Improve documentation + - Fix of migration: Check if session_expire_delay column exists before adding the column + - Fix: ActionView::Template::Error + - Fix: "Create Merge Request" isn't always shown in event for newly pushed branch + - Fix bug causing "Remove source-branch" option not to work for merge requests from the same project. v 7.13.0 (unreleased) - Remove repository graph log to fix slow cache updates after push event (Stan Hu) @@ -1594,4 +1600,4 @@ v 0.8.0 - stability - security fixes - increased test coverage - - email notification + - email notification \ No newline at end of file From 2e5be9c9942fc6f8e20bb76a6daa73a6acf48d51 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Thu, 23 Jul 2015 15:13:47 +0000 Subject: [PATCH 082/174] update changelog --- CHANGELOG | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 10c755403e9..9371877dcb4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -10,8 +10,7 @@ v 7.14.0 (unreleased) - Set OmniAuth full_host parameter to ensure redirect URIs are correct (Stan Hu) - Expire Rails cache entries after two weeks to prevent endless Redis growth - Add support for destroying project milestones (Stan Hu) - - Add fetch command to the MR page. - - Fix bug causing "Remove source-branch" option not to work for merge requests from the same project. + - Add fetch command to the MR page v 7.13.1 - Fix: Label modifications are not reflected in existing notes and in the issue list @@ -23,7 +22,7 @@ v 7.13.1 - Fix: "Create Merge Request" isn't always shown in event for newly pushed branch - Fix bug causing "Remove source-branch" option not to work for merge requests from the same project. -v 7.13.0 (unreleased) +v 7.13.0 - Remove repository graph log to fix slow cache updates after push event (Stan Hu) - Only enable HSTS header for HTTPS and port 443 (Stan Hu) - Fix user autocomplete for unauthenticated users accessing public projects (Stan Hu) From 9a7645c8a4336ac592fb159ea5d39e6397ad56d9 Mon Sep 17 00:00:00 2001 From: karen Carias Date: Thu, 23 Jul 2015 12:30:05 -0700 Subject: [PATCH 083/174] added note about labels in MR --- doc/workflow/labels.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/workflow/labels.md b/doc/workflow/labels.md index 085b7baf5ce..6e4840ca5ae 100644 --- a/doc/workflow/labels.md +++ b/doc/workflow/labels.md @@ -1,6 +1,6 @@ # Labels -In GitLab, you can easily tag issues and merge requests. If you have permission level `Developer` or higher, you can manage labels. To create, edit or delete a label, go to a project and then to `Issues` and then `Labels`. +In GitLab, you can easily tag issues and Merge Requests. If you have permission level `Developer` or higher, you can manage labels. To create, edit or delete a label, go to a project and then to `Issues` and then `Labels`. Here you can create a new label. @@ -14,3 +14,5 @@ If you want to change an existing label, press edit next to the listed label. You will be presented with the same form as when creating a new label. ![edit label](labels/label3.png) + +You can add labels to Merge Requests when you create or edit them. From ae3f869fd1f4326e26805606197dea4ea15c67bb Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Tue, 21 Jul 2015 17:37:33 -0700 Subject: [PATCH 084/174] Fix the "Reload with full diff" URL button On the first load, the merge request tabs would be requested in JSON format to render the HTML. This would cause the "Reload with full diff" button to create a link to diff.json. Closes #2041 --- CHANGELOG | 1 + app/assets/javascripts/merge_request_tabs.js.coffee | 10 ++-------- app/views/projects/diffs/_warning.html.haml | 2 +- app/views/projects/merge_requests/_show.html.haml | 6 ++---- spec/javascripts/merge_request_tabs_spec.js.coffee | 6 ++++++ 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index c6c5bc0aac4..9610a350442 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.14.0 (unreleased) - Fix full screen mode for snippet comments (Daniel Gerhardt) - Fix 404 error in files view after deleting the last file in a repository (Stan Hu) + - Fix the "Reload with full diff" URL button (Stan Hu) - Fix label read access for unauthenticated users (Daniel Gerhardt) - Fix access to disabled features for unauthenticated users (Daniel Gerhardt) - Fix OAuth provider bug where GitLab would not go return to the redirect_uri after sign-in (Stan Hu) diff --git a/app/assets/javascripts/merge_request_tabs.js.coffee b/app/assets/javascripts/merge_request_tabs.js.coffee index a132a0a9dcc..19a07b6a033 100644 --- a/app/assets/javascripts/merge_request_tabs.js.coffee +++ b/app/assets/javascripts/merge_request_tabs.js.coffee @@ -49,12 +49,6 @@ class @MergeRequestTabs # Store the `location` object, allowing for easier stubbing in tests @_location = location - switch @opts.action - when 'commits' - @commitsLoaded = true - when 'diffs' - @diffsLoaded = true - @bindEvents() @activateTab(@opts.action) @@ -102,7 +96,7 @@ class @MergeRequestTabs action = 'notes' if action == 'show' # Remove a trailing '/commits' or '/diffs' - new_state = @_location.pathname.replace(/\/(commits|diffs)\/?$/, '') + new_state = @_location.pathname.replace(/\/(commits|diffs)(\.html)?\/?$/, '') # Append the new action if we're on a tab other than 'notes' unless action == 'notes' @@ -133,7 +127,7 @@ class @MergeRequestTabs return if @diffsLoaded @_get - url: "#{source}.json" + url: "#{source}.json" + @_location.search success: (data) => document.getElementById('diffs').innerHTML = data.html @diffsLoaded = true diff --git a/app/views/projects/diffs/_warning.html.haml b/app/views/projects/diffs/_warning.html.haml index da3d4be84ba..caed0e69dc8 100644 --- a/app/views/projects/diffs/_warning.html.haml +++ b/app/views/projects/diffs/_warning.html.haml @@ -3,7 +3,7 @@ Too many changes to show. .pull-right - unless diff_hard_limit_enabled? - = link_to "Reload with full diff", url_for(params.merge(force_show_diff: true)), class: "btn btn-sm btn-warning" + = link_to "Reload with full diff", url_for(params.merge(force_show_diff: true, format: :html)), class: "btn btn-sm btn-warning" - if current_controller?(:commit) or current_controller?(:merge_requests) - if current_controller?(:commit) diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index faaa85896cf..c57eee14143 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -66,11 +66,9 @@ #notes.notes.tab-pane.voting_notes = render "projects/merge_requests/discussion" #commits.commits.tab-pane - - if current_page?(action: 'commits') - = render "projects/merge_requests/show/commits" + - # This tab is always loaded via AJAX #diffs.diffs.tab-pane - - if current_page?(action: 'diffs') - = render "projects/merge_requests/show/diffs" + - # This tab is always loaded via AJAX .mr-loading-status = spinner diff --git a/spec/javascripts/merge_request_tabs_spec.js.coffee b/spec/javascripts/merge_request_tabs_spec.js.coffee index 6cc96fb68a0..a0cfba455ea 100644 --- a/spec/javascripts/merge_request_tabs_spec.js.coffee +++ b/spec/javascripts/merge_request_tabs_spec.js.coffee @@ -51,6 +51,12 @@ describe 'MergeRequestTabs', -> expect(@subject('notes')).toBe('/foo/bar/merge_requests/1') expect(@subject('commits')).toBe('/foo/bar/merge_requests/1/commits') + it 'changes from diffs.html', -> + @class._location = stubLocation(pathname: '/foo/bar/merge_requests/1/diffs.html') + + expect(@subject('notes')).toBe('/foo/bar/merge_requests/1') + expect(@subject('commits')).toBe('/foo/bar/merge_requests/1/commits') + it 'changes from notes', -> @class._location = stubLocation(pathname: '/foo/bar/merge_requests/1') From cad0e848b099ab1993d1088e317fb6e5307862ad Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 23 Jul 2015 15:55:49 -0400 Subject: [PATCH 085/174] Fix and style the "Changes suppressed" link. --- app/assets/javascripts/application.js.coffee | 7 ++++--- app/assets/stylesheets/generic/common.scss | 2 +- app/assets/stylesheets/pages/diff.scss | 11 +++++++++++ app/views/projects/diffs/_text_file.html.haml | 3 ++- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee index 8b041c490d8..bb0a0c51fd4 100644 --- a/app/assets/javascripts/application.js.coffee +++ b/app/assets/javascripts/application.js.coffee @@ -164,9 +164,10 @@ $ -> $('.account-box').hover -> $(@).toggleClass('hover') # Commit show suppressed diff - $(".diff-content").on "click", ".supp_diff_link", -> - $(@).next('table').show() - $(@).remove() + $(document).on 'click', '.diff-content .js-show-suppressed-diff', -> + $container = $(@).parent() + $container.next('table').show() + $container.remove() $('.navbar-toggle').on 'click', -> $('.header-content .title').toggle() diff --git a/app/assets/stylesheets/generic/common.scss b/app/assets/stylesheets/generic/common.scss index 961ac793de2..d36530169a9 100644 --- a/app/assets/stylesheets/generic/common.scss +++ b/app/assets/stylesheets/generic/common.scss @@ -184,7 +184,7 @@ li.note { } } -.supp_diff_link, +.show-suppressed-diff, .show-all-commits { cursor: pointer; } diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss index af6ea58382f..1557c243db5 100644 --- a/app/assets/stylesheets/pages/diff.scss +++ b/app/assets/stylesheets/pages/diff.scss @@ -65,6 +65,17 @@ color: #777; } + .suppressed-container { + padding: ($padding-base-vertical + 5px) $padding-base-horizontal; + text-align: center; + + // "Changes suppressed. Click to show." link + .show-suppressed-diff { + font-size: 110%; + font-weight: bold; + } + } + table { width: 100%; font-family: $monospace_font; diff --git a/app/views/projects/diffs/_text_file.html.haml b/app/views/projects/diffs/_text_file.html.haml index ed4c601bcdb..977ca423f75 100644 --- a/app/views/projects/diffs/_text_file.html.haml +++ b/app/views/projects/diffs/_text_file.html.haml @@ -1,6 +1,7 @@ - too_big = diff_file.diff_lines.count > Commit::DIFF_SAFE_LINES - if too_big - %a.supp_diff_link Changes suppressed. Click to show + .suppressed-container + %a.show-suppressed-diff.js-show-suppressed-diff Changes suppressed. Click to show. %table.text-file{class: "#{'hide' if too_big}"} - last_line = 0 From 5ce6d18681ee7b74ba0c443672224dd580bd34b0 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 23 Jul 2015 17:16:39 -0400 Subject: [PATCH 086/174] Add User.find_by_username! --- app/controllers/users_controller.rb | 2 +- app/models/user.rb | 4 ++++ spec/models/user_spec.rb | 12 ++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index a67325ae659..2bb5c338cf6 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -50,7 +50,7 @@ class UsersController < ApplicationController private def set_user - @user = User.find_by!('lower(username) = ?', params[:username].downcase) + @user = User.find_by_username!(params[:username]) unless current_user || @user.public_profile? return authenticate_user! diff --git a/app/models/user.rb b/app/models/user.rb index fb330ff7185..4a10520b209 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -274,6 +274,10 @@ class User < ActiveRecord::Base value: login.to_s.downcase).first end + def find_by_username!(username) + find_by!('lower(username) = ?', username.downcase) + end + def by_username_or_id(name_or_id) where('users.username = ? OR users.id = ?', name_or_id.to_s, name_or_id.to_i).first end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 16902317f10..76f16323e2f 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -442,6 +442,18 @@ describe User do end end + describe '.find_by_username!' do + it 'raises RecordNotFound' do + expect { described_class.find_by_username!('JohnDoe') }. + to raise_error(ActiveRecord::RecordNotFound) + end + + it 'is case-insensitive' do + user = create(:user, username: 'JohnDoe') + expect(described_class.find_by_username!('JOHNDOE')).to eq user + end + end + describe 'all_ssh_keys' do it { is_expected.to have_many(:keys).dependent(:destroy) } From a1ca9b5220f5b47bc834378d632b3e7f90dde236 Mon Sep 17 00:00:00 2001 From: karen Carias Date: Thu, 23 Jul 2015 16:38:22 -0700 Subject: [PATCH 087/174] added info about repo size --- doc/workflow/importing/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/workflow/importing/README.md b/doc/workflow/importing/README.md index 19395657719..c6cd4d34cce 100644 --- a/doc/workflow/importing/README.md +++ b/doc/workflow/importing/README.md @@ -6,4 +6,6 @@ 4. [SVN](migrating_from_svn.md) ### Note -* If you'd like to migrate from a self-hosted GitLab instance to GitLab.com, you can copy your repos by changing the remote and pushing to the new server; but issues and merge requests can't be imported. \ No newline at end of file +* If you'd like to migrate from a self-hosted GitLab instance to GitLab.com, you can copy your repos by changing the remote and pushing to the new server; but issues and merge requests can't be imported. + +* When you migrate repositories to GitLab, there is no restriction on maximum size. They are imported via HTTP, but if the repository is too large, it can timeout. From 50b36c0ae73085faee73e2fb53224d116884fa6c Mon Sep 17 00:00:00 2001 From: karen Carias Date: Thu, 23 Jul 2015 17:11:17 -0700 Subject: [PATCH 088/174] added new document about adding new files --- doc/gitlab-basics/README.md | 4 +++- doc/gitlab-basics/add-file.md | 31 +++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 doc/gitlab-basics/add-file.md diff --git a/doc/gitlab-basics/README.md b/doc/gitlab-basics/README.md index d6272cd5912..538894f5848 100644 --- a/doc/gitlab-basics/README.md +++ b/doc/gitlab-basics/README.md @@ -2,7 +2,7 @@ Step-by-step guides on the basics of working with Git and GitLab. -* [Start using Git on the commandline](start-using-git.md) +* [Start using Git on the command line](start-using-git.md) * [Create and add your SSH Keys](create-your-ssh-keys.md) @@ -17,3 +17,5 @@ Step-by-step guides on the basics of working with Git and GitLab. * [Create a branch](create-branch.md) * [Fork a project](fork-project.md) + +* [Add a file](add-file.md) diff --git a/doc/gitlab-basics/add-file.md b/doc/gitlab-basics/add-file.md new file mode 100644 index 00000000000..ac0d98085a4 --- /dev/null +++ b/doc/gitlab-basics/add-file.md @@ -0,0 +1,31 @@ +# How to add a file + +You can create a file in your [shell](command-line-commands.md) or in GitLab. + +To create a file in GitLab, sign in to [GitLab.com](https://gitlab.com). + +Select a project on the right side of your screen: + +![Select a project](basicsimages/select_project.png) + +[Create a branch](create-branch.md). + +Go to the directory where you'd like to add the file and click on the "+" sign next to the name of the project and directory: + +![Create a file](basicsimages/create_file.png) + +Add a name to your file, use .md or .html at the end, depending on which markup language you'd like to use (you can't add spaces, so you can use hyphens or underscores): + +![File name](basicsimages/file_name.png) + +Add all the information that you'd like to include in your file: + +![Add information](basicsimages/white_space.png) + +Add a commit message based on what you just added and then click on "commit changes": + +![Commit changes](basicsimages/commit_changes.png) + +### Note +Besides its regular files, every directory needs a README.md or README.html file which works like an index, telling +what the directory is about. It's the first document you'll find when you open a directory. From d3cae9278fe36e8c7731aa6e7aaaf33014c8df7d Mon Sep 17 00:00:00 2001 From: Daniel Gerhardt Date: Fri, 24 Jul 2015 16:09:19 +0200 Subject: [PATCH 089/174] Add rake task 'gitlab:update_commit_count' Starting with migration `20150717130904` commit count is stored in the database. For existing projects it defaults to `0` and is updated to the correct value when commits are pushed. The newly introduced rake task updates the commit count for all projects which have not been updated yet. Refs !986, !989, #2040. --- CHANGELOG | 1 + lib/tasks/gitlab/update_commit_count.rake | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 lib/tasks/gitlab/update_commit_count.rake diff --git a/CHANGELOG b/CHANGELOG index 9ffbf64fe1d..e8c27a52d71 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.14.0 (unreleased) + - Add rake task 'gitlab:update_commit_count' (Daniel Gerhardt) - Fix full screen mode for snippet comments (Daniel Gerhardt) - Fix 404 error in files view after deleting the last file in a repository (Stan Hu) - Fix label read access for unauthenticated users (Daniel Gerhardt) diff --git a/lib/tasks/gitlab/update_commit_count.rake b/lib/tasks/gitlab/update_commit_count.rake new file mode 100644 index 00000000000..9b636f12d9f --- /dev/null +++ b/lib/tasks/gitlab/update_commit_count.rake @@ -0,0 +1,20 @@ +namespace :gitlab do + desc "GitLab | Update commit count for projects" + task update_commit_count: :environment do + projects = Project.where(commit_count: 0) + puts "#{projects.size} projects need to be updated. This might take a while." + ask_to_continue unless ENV['force'] == 'yes' + + projects.find_each(batch_size: 100) do |project| + print "#{project.name_with_namespace.yellow} ... " + + unless project.repo_exists? + puts "skipping, because the repo is empty".magenta + next + end + + project.update_commit_count + puts project.commit_count.to_s.green + end + end +end From db0fce322a19e20e755abca772ceb2918d815ea0 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 24 Jul 2015 18:34:00 +0200 Subject: [PATCH 090/174] Create more backups during backup tests I hope this makes the backup tests more reliable. --- spec/tasks/gitlab/backup_rake_spec.rb | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb index 476e22b8802..48d08031d29 100644 --- a/spec/tasks/gitlab/backup_rake_spec.rb +++ b/spec/tasks/gitlab/backup_rake_spec.rb @@ -15,6 +15,12 @@ describe 'gitlab:app namespace rake task' do Rake.application.invoke_task task_name end + def reenable_backup_sub_tasks + %w{db repo uploads}.each do |subtask| + Rake::Task["gitlab:backup:#{subtask}:create"].reenable + end + end + describe 'backup_restore' do before do # avoid writing task output to spec progress @@ -67,23 +73,19 @@ describe 'gitlab:app namespace rake task' do # Redirect STDOUT and run the rake task orig_stdout = $stdout $stdout = StringIO.new + reenable_backup_sub_tasks run_rake_task('gitlab:backup:create') + reenable_backup_sub_tasks $stdout = orig_stdout @backup_tar = (tars_glob - existing_tars).first end - def reenable_backup_sub_tasks - %w{db repo uploads}.each do |subtask| - Rake::Task["gitlab:backup:#{subtask}:create"].reenable - end - end - - before :all do + before do create_backup end - after :all do + after do FileUtils.rm(@backup_tar) end @@ -99,9 +101,7 @@ describe 'gitlab:app namespace rake task' do # We created a backup in a before(:all) so it got the default permissions. # We now need to do some work to create a _new_ backup file using our stub. FileUtils.rm(@backup_tar) - reenable_backup_sub_tasks create_backup - reenable_backup_sub_tasks end it 'uses the custom permissions' do @@ -138,9 +138,7 @@ describe 'gitlab:app namespace rake task' do before :all do @origin_cd = Dir.pwd - Rake::Task["gitlab:backup:db:create"].reenable - Rake::Task["gitlab:backup:repo:create"].reenable - Rake::Task["gitlab:backup:uploads:create"].reenable + reenable_backup_sub_tasks # Record the existing backup tars so we don't touch them existing_tars = tars_glob From 39a7e210a3484fb84683d53c2cf5e0f7ef0c3a80 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 24 Jul 2015 18:54:06 +0200 Subject: [PATCH 091/174] Use a separate backup test directory and nuke its contents --- config/gitlab.yml.example | 2 ++ spec/support/test_env.rb | 5 +++++ spec/tasks/gitlab/backup_rake_spec.rb | 10 ++++------ 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index 542106e86dd..456fb3d636e 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -339,6 +339,8 @@ test: # user: YOUR_USERNAME satellites: path: tmp/tests/gitlab-satellites/ + backup: + path: tmp/tests/backups gitlab_shell: path: tmp/tests/gitlab-shell/ repos_path: tmp/tests/repositories/ diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index 8bdd6b43cdd..2bdb64ff314 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -29,6 +29,7 @@ module TestEnv clean_test_path FileUtils.mkdir_p(repos_path) + FileUtils.mkdir_p(backup_path) # Setup GitLab shell for test instance setup_gitlab_shell @@ -121,6 +122,10 @@ module TestEnv Gitlab.config.gitlab_shell.repos_path end + def backup_path + Gitlab.config.backup.path + end + def copy_forked_repo_with_submodules(project) base_repo_path = File.expand_path(forked_repo_path_bare) target_repo_path = File.expand_path(repos_path + "/#{project.namespace.path}/#{project.path}.git") diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb index 48d08031d29..23f322e0a62 100644 --- a/spec/tasks/gitlab/backup_rake_spec.rb +++ b/spec/tasks/gitlab/backup_rake_spec.rb @@ -67,8 +67,7 @@ describe 'gitlab:app namespace rake task' do end def create_backup - # Record the existing backup tars so we don't touch them - existing_tars = tars_glob + FileUtils.rm tars_glob # Redirect STDOUT and run the rake task orig_stdout = $stdout @@ -78,7 +77,7 @@ describe 'gitlab:app namespace rake task' do reenable_backup_sub_tasks $stdout = orig_stdout - @backup_tar = (tars_glob - existing_tars).first + @backup_tar = tars_glob.first end before do @@ -140,8 +139,7 @@ describe 'gitlab:app namespace rake task' do reenable_backup_sub_tasks - # Record the existing backup tars so we don't touch them - existing_tars = tars_glob + FileUtils.rm tars_glob # Redirect STDOUT and run the rake task orig_stdout = $stdout @@ -150,7 +148,7 @@ describe 'gitlab:app namespace rake task' do run_rake_task('gitlab:backup:create') $stdout = orig_stdout - @backup_tar = (tars_glob - existing_tars).first + @backup_tar = tars_glob.first end after :all do From d371331a65070ce5b3ab9c210eac697062170c91 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 24 Jul 2015 18:55:50 +0200 Subject: [PATCH 092/174] Remove weird trailing characters --- config/gitlab.yml.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index 456fb3d636e..6dc0d170826 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -339,7 +339,7 @@ test: # user: YOUR_USERNAME satellites: path: tmp/tests/gitlab-satellites/ - backup: + backup: path: tmp/tests/backups gitlab_shell: path: tmp/tests/gitlab-shell/ From a5e8ea54eceeb02fe34f0265d8cfe6af8b599098 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Thu, 23 Jul 2015 23:52:21 -0700 Subject: [PATCH 093/174] Fix Error 500 when browsing projects with no HEAD Steps to reproduce: 1. Create a project with a README 2. In the actual remote, type: `git symbolic-ref HEAD refs/heads/nowhere` 3. Check that HEAD is gone via `git ls-remote .` 4. Go to the projects page and see the Error 500 Closes https://github.com/gitlabhq/gitlabhq/issues/9484 --- CHANGELOG | 1 + app/helpers/projects_helper.rb | 3 ++- spec/helpers/projects_helper_spec.rb | 20 +++++++++++++++++++- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index c6c5bc0aac4..580f20558f3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.14.0 (unreleased) + - Fix Error 500 when browsing projects with no HEAD (Stan Hu) - Fix full screen mode for snippet comments (Daniel Gerhardt) - Fix 404 error in files view after deleting the last file in a repository (Stan Hu) - Fix label read access for unauthenticated users (Daniel Gerhardt) diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 3cd52b381bd..a675a292432 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -278,7 +278,8 @@ module ProjectsHelper end def readme_cache_key - [@project.id, @project.commit.sha, "readme"].join('-') + sha = @project.commit.try(:sha) || 'nil' + [@project.id, sha, "readme"].join('-') end def round_commit_count(project) diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb index beb9b4e438e..99abb95d906 100644 --- a/spec/helpers/projects_helper_spec.rb +++ b/spec/helpers/projects_helper_spec.rb @@ -22,7 +22,7 @@ describe ProjectsHelper do let(:user) { create(:user) } - it "returns false if there are no approipriate permissions" do + it "returns false if there are no appropriate permissions" do allow(helper).to receive(:can?) { false } expect(helper.can_change_visibility_level?(project, user)).to be_falsey @@ -52,4 +52,22 @@ describe ProjectsHelper do end end end + + describe "readme_cache_key" do + let(:project) { create(:project) } + + before do + helper.instance_variable_set(:@project, project) + end + + it "returns a valid cach key" do + expect(helper.send(:readme_cache_key)).to eq("#{project.id}-#{project.commit.id}-readme") + end + + it "returns a valid cache key if HEAD does not exist" do + allow(project).to receive(:commit) { nil } + + expect(helper.send(:readme_cache_key)).to eq("#{project.id}-nil-readme") + end + end end From 31dc5e7034b8cace96477f23d06182c22d09b570 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 23 Jul 2015 14:48:55 -0400 Subject: [PATCH 094/174] Add admin_merge_request ability to Developer level and up This was necessary because this permission is checked dynamically by `app/views/shared/issuable/_context` when on a Merge Request. Closes #2058 --- app/models/ability.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/models/ability.rb b/app/models/ability.rb index 9258d981ac9..6a8f683bc89 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -140,12 +140,13 @@ class Ability :create_project_snippet, :update_issue, :admin_issue, - :admin_label, + :admin_label ] end def project_dev_rules project_report_rules + [ + :admin_merge_request, :create_merge_request, :create_wiki, :push_code From b5e6ffa6165e9bbb999dd6b69e6161da80f66e7f Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Fri, 24 Jul 2015 14:59:02 -0400 Subject: [PATCH 095/174] Add "Manage merge requests" permission to docs --- doc/permissions/permissions.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/permissions/permissions.md b/doc/permissions/permissions.md index 70b7e17795d..e81432c600f 100644 --- a/doc/permissions/permissions.md +++ b/doc/permissions/permissions.md @@ -17,6 +17,7 @@ If a user is a GitLab administrator they receive all permissions. | Create code snippets | | ✓ | ✓ | ✓ | ✓ | | Manage issue tracker | | ✓ | ✓ | ✓ | ✓ | | Manage labels | | ✓ | ✓ | ✓ | ✓ | +| Manage merge requests | | | ✓ | ✓ | ✓ | | Create new merge request | | | ✓ | ✓ | ✓ | | Create new branches | | | ✓ | ✓ | ✓ | | Push to non-protected branches | | | ✓ | ✓ | ✓ | From 37bc7bac19599092b25f5aa30705fb1bf89e4f42 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Fri, 24 Jul 2015 15:31:15 -0400 Subject: [PATCH 096/174] Add Issuable#to_ability_name --- app/models/concerns/issuable.rb | 10 ++++++++++ app/views/shared/issuable/_context.html.haml | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index 97846b06d72..c21e7fd0e3b 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -159,6 +159,16 @@ module Issuable end end + # Convert this Issuable class name to a format usable by Ability definitions + # + # Examples: + # + # issuable.class # => MergeRequest + # issuable.to_ability_name # => "merge_request" + def to_ability_name + self.class.to_s.underscore + end + private def filter_superceded_votes(votes, notes) diff --git a/app/views/shared/issuable/_context.html.haml b/app/views/shared/issuable/_context.html.haml index d1bd5ef968d..19e8c31975b 100644 --- a/app/views/shared/issuable/_context.html.haml +++ b/app/views/shared/issuable/_context.html.haml @@ -8,7 +8,7 @@ - else none .issuable-context-selectbox - - if can?(current_user, :"admin_#{issuable.class.to_s.underscore}", @project) + - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project) = users_select_tag("#{issuable.class.table_name.singularize}[assignee_id]", placeholder: 'Select assignee', class: 'custom-form-control js-select2 js-assignee', selected: issuable.assignee_id, project: @target_project, null_user: true) %div.prepend-top-20.clearfix @@ -24,7 +24,7 @@ - else none .issuable-context-selectbox - - if can?(current_user, :"admin_#{issuable.class.to_s.underscore}", @project) + - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project) = f.select(:milestone_id, milestone_options(issuable), { include_blank: 'Select milestone' }, {class: 'select2 select2-compact js-select2 js-milestone'}) = hidden_field_tag :issuable_context = f.submit class: 'btn hide' From e496c35fedeb44648dec363acac1e6e30722d1b7 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Fri, 24 Jul 2015 15:31:21 -0400 Subject: [PATCH 097/174] Dynamically check `:admin_*` ability on issuable form Closes #2092 --- app/views/shared/issuable/_form.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml index e434e1b6b98..8cc0b517cd2 100644 --- a/app/views/shared/issuable/_form.html.haml +++ b/app/views/shared/issuable/_form.html.haml @@ -38,7 +38,7 @@ .clearfix .error-alert %hr -- if can?(current_user, :admin_issue, @project) +- if can?(current_user, :"admin_#{issuable.to_ability_name}", @project) .form-group .issue-assignee = f.label :assignee_id, class: 'control-label' do From b9b2d08638131be9861cb8d7e4f645a9013dd03f Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Fri, 24 Jul 2015 15:46:40 -0400 Subject: [PATCH 098/174] Dynamically check `:admin_*` ability in IssuableBaseService Closes #2092 --- app/services/issuable_base_service.rb | 6 ++++-- app/services/issues/base_service.rb | 4 ++++ app/services/merge_requests/base_service.rb | 6 ++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb index f1ef5ca84fe..15b3825f96a 100644 --- a/app/services/issuable_base_service.rb +++ b/app/services/issuable_base_service.rb @@ -27,8 +27,10 @@ class IssuableBaseService < BaseService old_branch, new_branch) end - def filter_params - unless can?(current_user, :admin_issue, project) + def filter_params(issuable_ability_name = :issue) + ability = :"admin_#{issuable_ability_name}" + + unless can?(current_user, ability, project) params.delete(:milestone_id) params.delete(:label_ids) params.delete(:assignee_id) diff --git a/app/services/issues/base_service.rb b/app/services/issues/base_service.rb index c3ca04a4343..770f32de944 100644 --- a/app/services/issues/base_service.rb +++ b/app/services/issues/base_service.rb @@ -10,6 +10,10 @@ module Issues private + def filter_params + super(:issue) + end + def execute_hooks(issue, action = 'open') issue_data = hook_data(issue, action) issue.project.execute_hooks(issue_data, :issue_hooks) diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb index e455fe95791..7b306a8a531 100644 --- a/app/services/merge_requests/base_service.rb +++ b/app/services/merge_requests/base_service.rb @@ -20,5 +20,11 @@ module MergeRequests merge_request.project.execute_services(merge_data, :merge_request_hooks) end end + + private + + def filter_params + super(:merge_request) + end end end From f8471cd1872aec5141cab4e1dce715741f9eb9d3 Mon Sep 17 00:00:00 2001 From: karen Carias Date: Fri, 24 Jul 2015 18:05:52 -0700 Subject: [PATCH 099/174] added note about unique SSH keys --- doc/ssh/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/ssh/README.md b/doc/ssh/README.md index 5f44f9351dd..7cdcd11c04c 100644 --- a/doc/ssh/README.md +++ b/doc/ssh/README.md @@ -105,3 +105,6 @@ IdentityFile ~/my-ssh-key-directory/company-com-private-key-filename Note in the gitlab.com example above a username was specified to override the default chosen by OpenSSH (your local username). This is only required if your local and remote usernames differ. Due to the wide variety of SSH clients and their very large number of configuration options, further explanation of these topics is beyond the scope of this document. + +Public SSH keys need to be unique, as they will bind to your account. Your SSH key is the only identifier you'll +have when pushing code via SSH. That's why it needs to uniquely map to a single user. From 779318398c1b74ebde29cd72d656882e21e121dd Mon Sep 17 00:00:00 2001 From: Arno Fleming Date: Sat, 25 Jul 2015 18:43:58 +0200 Subject: [PATCH 100/174] Minor styling fixes. - Link to rendered html instead of markdown source. - Removed typos --- doc/workflow/gitlab_flow.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/workflow/gitlab_flow.md b/doc/workflow/gitlab_flow.md index 0e87dc74217..f608674faf6 100644 --- a/doc/workflow/gitlab_flow.md +++ b/doc/workflow/gitlab_flow.md @@ -31,7 +31,7 @@ We think there is still room for improvement and will detail a set of practices ## Git flow and its problems -[![Git Flow timeline by Vincent Driessen, used with permission](gitdashflow.png) +![Git Flow timeline by Vincent Driessen, used with permission](gitdashflow.png) Git flow was one of the first proposals to use git branches and it has gotten a lot of attention. It advocates a master branch and a separate develop branch as well as supporting branches for features, releases and hotfixes. @@ -54,7 +54,7 @@ And doing releases doesn't automatically mean also doing hotfixes. ![Master branch with feature branches merged in](github_flow.png) - In reaction to git flow a simpler alternative was detailed, [GitHub flow](https://guides.github.com/introduction/flow/index.html). +In reaction to git flow a simpler alternative was detailed, [GitHub flow](https://guides.github.com/introduction/flow/index.html). This flow has only feature branches and a master branch. This is very simple and clean, many organizations have adopted it with great success. Atlassian recommends [a similar strategy](http://blogs.atlassian.com/2014/01/simple-git-workflow-simple/) although they rebase feature branches. @@ -131,7 +131,7 @@ When you feel comfortable with it to be merged you assign it to the person that There is room for more feedback and after the assigned person feels comfortable with the result the branch is merged. If the assigned person does not feel comfortable they can close the merge request without merging. -In GitLab it is common to protect the long-lived branches (e.g. the master branch) so that normal developers [can't modify these protected branches](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/permissions/permissions.md). +In GitLab it is common to protect the long-lived branches (e.g. the master branch) so that normal developers [can't modify these protected branches](http://doc.gitlab.com/ce/permissions/permissions.html). So if you want to merge it into a protected branch you assign it to someone with master authorizations. ## Issues with GitLab flow @@ -216,7 +216,7 @@ This prevents creating a merge commit when merging master into your feature bran However, just like with squashing you should never rebase commits you have pushed to a remote server. This makes it impossible to rebase work in progress that you already shared with your team which is something we recommend. When using rebase to keep your feature branch updated you [need to resolve similar conflicts again and again](http://blogs.atlassian.com/2013/10/git-team-workflows-merge-or-rebase/). -You can reuse recorded resolutions (rerere) sometimes, but with without rebasing you only have to solve the conflicts one time and you’re set. +You can reuse recorded resolutions (rerere) sometimes, but without rebasing you only have to solve the conflicts one time and you’re set. There has to be a better way to avoid many merge commits. The way to prevent creating many merge commits is to not frequently merge master into the feature branch. From d92668a05bf35995b4b93069269084ee5db93484 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sat, 25 Jul 2015 16:42:28 -0400 Subject: [PATCH 101/174] Only create :admin user in the one test where it's used --- spec/services/projects/create_service_spec.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb index 97b206c9854..3e3d85db858 100644 --- a/spec/services/projects/create_service_spec.rb +++ b/spec/services/projects/create_service_spec.rb @@ -4,7 +4,6 @@ describe Projects::CreateService do describe :create_by_user do before do @user = create :user - @admin = create :user, admin: true @opts = { name: "GitLab", namespace: @user.namespace @@ -75,7 +74,9 @@ describe Projects::CreateService do end it 'should allow a restricted visibility level for admins' do - project = create_project(@admin, @opts) + admin = create(:admin) + project = create_project(admin, @opts) + expect(project.errors.any?).to be(false) expect(project.saved?).to be(true) end From 88aed4096274db4b2cf61c0afaa7c1df5c5f5b33 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sat, 25 Jul 2015 16:43:18 -0400 Subject: [PATCH 102/174] Create project services on Project creation --- app/services/projects/create_service.rb | 2 ++ spec/services/projects/create_service_spec.rb | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index 011f6f6145e..b35aed005da 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -85,6 +85,8 @@ module Projects @project.create_wiki if @project.wiki_enabled? + @project.build_missing_services + event_service.create_project(@project, current_user) system_hook_service.execute_hooks_for(@project, :create) diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb index 3e3d85db858..66cdfd5d758 100644 --- a/spec/services/projects/create_service_spec.rb +++ b/spec/services/projects/create_service_spec.rb @@ -10,6 +10,13 @@ describe Projects::CreateService do } end + it 'creates services on Project creation' do + project = create_project(@user, @opts) + project.reload + + expect(project.services).not_to be_empty + end + context 'user namespace' do before do @project = create_project(@user, @opts) From 562242cb9dc11f0a5957a58eb9f91a484a909b40 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sun, 26 Jul 2015 02:17:34 -0700 Subject: [PATCH 103/174] Fix commit data retrieval when branch name has single quotes Closes #1724 --- CHANGELOG | 1 + app/controllers/projects/refs_controller.rb | 6 ++++++ app/views/projects/refs/logs_tree.js.haml | 8 +++++--- app/views/projects/tree/_tree.html.haml | 2 +- features/project/source/browse_files.feature | 7 +++++++ features/steps/project/source/browse_files.rb | 17 +++++++++++++++++ spec/support/test_env.rb | 3 ++- 7 files changed, 39 insertions(+), 5 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 1ca4c7a8480..024be16708e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.14.0 (unreleased) + - Fix commit data retrieval when branch name has single quotes (Stan Hu) - Fix Error 500 when browsing projects with no HEAD (Stan Hu) - Fix full screen mode for snippet comments (Daniel Gerhardt) - Fix 404 error in files view after deleting the last file in a repository (Stan Hu) diff --git a/app/controllers/projects/refs_controller.rb b/app/controllers/projects/refs_controller.rb index d83561cf32a..6080c849c8d 100644 --- a/app/controllers/projects/refs_controller.rb +++ b/app/controllers/projects/refs_controller.rb @@ -1,5 +1,6 @@ class Projects::RefsController < Projects::ApplicationController include ExtractsPath + include TreeHelper before_action :require_non_empty_project before_action :assign_ref_vars @@ -60,6 +61,11 @@ class Projects::RefsController < Projects::ApplicationController } end + if @logs.present? + @log_url = namespace_project_tree_url(@project.namespace, @project, tree_join(@ref, @path || '/')) + @more_log_url = logs_file_namespace_project_ref_path(@project.namespace, @project, @ref, @path || '', offset: (@offset + @limit)) + end + respond_to do |format| format.html { render_404 } format.js diff --git a/app/views/projects/refs/logs_tree.js.haml b/app/views/projects/refs/logs_tree.js.haml index 35c15cf3a9e..db7f244d002 100644 --- a/app/views/projects/refs/logs_tree.js.haml +++ b/app/views/projects/refs/logs_tree.js.haml @@ -11,9 +11,11 @@ - if @logs.present? :plain var current_url = location.href.replace(/\/?$/, '/'); - var log_url = '#{namespace_project_tree_url(@project.namespace, @project, tree_join(@ref, @path || '/'))}'.replace(/\/?$/, '/'); + var log_url = "#{escape_javascript(@log_url)}".replace(/\/?$/, '/'); + if(current_url == log_url) { - // Load 10 more commit log for each file in tree + // Load more commit logs for each file in tree // if we still on the same page - ajaxGet('#{logs_file_namespace_project_ref_path(@project.namespace, @project, @ref, @path || '', offset: (@offset + @limit))}'); + var url = "#{escape_javascript(@more_log_url)}"; + ajaxGet(url); } diff --git a/app/views/projects/tree/_tree.html.haml b/app/views/projects/tree/_tree.html.haml index d304690d162..5048154cb2f 100644 --- a/app/views/projects/tree/_tree.html.haml +++ b/app/views/projects/tree/_tree.html.haml @@ -49,5 +49,5 @@ :javascript // Load last commit log for each file in tree $('#tree-slider').waitForImages(function() { - ajaxGet('#{@logs_path}'); + ajaxGet("#{escape_javascript(@logs_path)}"); }); diff --git a/features/project/source/browse_files.feature b/features/project/source/browse_files.feature index af68cb96ed9..d3a77466a35 100644 --- a/features/project/source/browse_files.feature +++ b/features/project/source/browse_files.feature @@ -158,3 +158,10 @@ Feature: Project Source Browse Files Given I visit project source page for "6d394385cf567f80a8fd85055db1ab4c5295806f" And I click on ".gitignore" file in repo Then I don't see the permalink link + + @javascript + Scenario: I browse code with single quotes in the ref + Given I switch ref to 'test' + And I see the ref 'test' has been selected + And I visit the 'test' tree + Then I see the commit data diff --git a/features/steps/project/source/browse_files.rb b/features/steps/project/source/browse_files.rb index 95879b9544d..5cb085db207 100644 --- a/features/steps/project/source/browse_files.rb +++ b/features/steps/project/source/browse_files.rb @@ -193,6 +193,23 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps FileUtils.rm_f(File.join(@project.repository.path, 'hooks', 'pre-receive')) end + step "I switch ref to 'test'" do + select "'test'", from: 'ref' + end + + step "I see the ref 'test' has been selected" do + expect(page).to have_selector '.select2-chosen', text: "'test'" + end + + step "I visit the 'test' tree" do + visit namespace_project_tree_path(@project.namespace, @project, "'test'") + end + + step 'I see the commit data' do + expect(page).to have_css('.tree-commit-link', visible: true) + expect(page).not_to have_content('Loading commit data...') + end + private def set_new_content diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index dcf2a9e2ce5..dab4535e2c7 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -12,7 +12,8 @@ module TestEnv 'fix' => '12d65c8', 'improve/awesome' => '5937ac0', 'markdown' => '0ed8c6c', - 'master' => '5937ac0' + 'master' => '5937ac0', + "'test'" => 'e56497b', } # gitlab-test-fork is a fork of gitlab-fork, but we don't necessarily From dfe7807653304f2a42369141925733f3c6515488 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sun, 26 Jul 2015 09:52:49 -0700 Subject: [PATCH 104/174] Fix live notes refresh in relative URL deployments --- CHANGELOG | 1 + app/assets/javascripts/notes.js.coffee | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 1ca4c7a8480..e198b48e86e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.14.0 (unreleased) + - Fix URL used for refreshing notes if relative_url is present (Bartłomiej Święcki) - Fix Error 500 when browsing projects with no HEAD (Stan Hu) - Fix full screen mode for snippet comments (Daniel Gerhardt) - Fix 404 error in files view after deleting the last file in a repository (Stan Hu) diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee index bcff7bcc49e..0021d17d85e 100644 --- a/app/assets/javascripts/notes.js.coffee +++ b/app/assets/javascripts/notes.js.coffee @@ -10,7 +10,6 @@ class @Notes constructor: (notes_url, note_ids, last_fetched_at, view) -> @notes_url = notes_url - @notes_url = gon.relative_url_root + @notes_url if gon.relative_url_root? @note_ids = note_ids @last_fetched_at = last_fetched_at @view = view From 7679a7ea55851265e9d0015a51126bec489fbc6d Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sun, 26 Jul 2015 16:55:43 -0400 Subject: [PATCH 105/174] Render Note field hints consistently for "new" and "edit" forms - The "Edit" form didn't have Markdown hints. - The "New" form had a paperclip icon for attachments, the "edit" form didn't. Closes #2010 Closes internal https://dev.gitlab.org/gitlab/gitlabhq/issues/2525 --- app/views/projects/notes/_edit_form.html.haml | 5 +---- app/views/projects/notes/_form.html.haml | 14 ++------------ app/views/projects/notes/_hints.html.haml | 9 +++++++++ 3 files changed, 12 insertions(+), 16 deletions(-) create mode 100644 app/views/projects/notes/_hints.html.haml diff --git a/app/views/projects/notes/_edit_form.html.haml b/app/views/projects/notes/_edit_form.html.haml index 7472b33bb53..8f7d2e84c70 100644 --- a/app/views/projects/notes/_edit_form.html.haml +++ b/app/views/projects/notes/_edit_form.html.haml @@ -3,10 +3,7 @@ = note_target_fields(note) = render layout: 'projects/md_preview', locals: { preview_class: 'note-text' } do = render 'projects/zen', f: f, attr: :note, classes: 'note_text js-note-text js-task-list-field' - - .comment-hints.clearfix - .pull-left #{link_to 'Markdown ', help_page_path('markdown', 'markdown'),{ target: '_blank', tabindex: -1 }} - .pull-right #{link_to 'Attach a file', '#', class: 'markdown-selector', tabindex: -1 } + = render 'projects/notes/hints' .note-form-actions .buttons diff --git a/app/views/projects/notes/_form.html.haml b/app/views/projects/notes/_form.html.haml index 64f98741d45..3be8f44b282 100644 --- a/app/views/projects/notes/_form.html.haml +++ b/app/views/projects/notes/_form.html.haml @@ -8,18 +8,8 @@ = f.hidden_field :noteable_type = render layout: 'projects/md_preview', locals: { preview_class: "note-text", referenced_users: true } do - = render 'projects/zen', f: f, attr: :note, - classes: 'note_text js-note-text' - - .comment-hints.clearfix - .pull-left - = link_to "Markdown ", help_page_path("markdown", "markdown"),{ target: '_blank', tabindex: -1 } - tip: - = random_markdown_tip - .pull-right - = link_to '#', class: 'markdown-selector', tabindex: -1 do - Attach a file - = icon('paperclip') + = render 'projects/zen', f: f, attr: :note, classes: 'note_text js-note-text' + = render 'projects/notes/hints' .error-alert .note-form-actions diff --git a/app/views/projects/notes/_hints.html.haml b/app/views/projects/notes/_hints.html.haml new file mode 100644 index 00000000000..6e7929bdab0 --- /dev/null +++ b/app/views/projects/notes/_hints.html.haml @@ -0,0 +1,9 @@ +.comment-hints.clearfix + .pull-left + = link_to 'Markdown', help_page_path('markdown', 'markdown'), target: '_blank', tabindex: -1 + tip: + = random_markdown_tip + .pull-right + = link_to '#', class: 'markdown-selector', tabindex: -1 do + = icon('paperclip') + Attach a file From 1cd28600652e23c8605b9344e269c34e83edccd1 Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Mon, 27 Jul 2015 15:29:10 +0900 Subject: [PATCH 106/174] Fix the image file that contains non-ascii character is not displayed --- CHANGELOG | 1 + lib/gitlab/markdown/relative_link_filter.rb | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index e198b48e86e..808f66b9483 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.14.0 (unreleased) + - Fix the image file that contains non-ascii character is not displayed(Hiroyuki Sato) - Fix URL used for refreshing notes if relative_url is present (Bartłomiej Święcki) - Fix Error 500 when browsing projects with no HEAD (Stan Hu) - Fix full screen mode for snippet comments (Daniel Gerhardt) diff --git a/lib/gitlab/markdown/relative_link_filter.rb b/lib/gitlab/markdown/relative_link_filter.rb index 9de2b24a9da..3eaceba5323 100644 --- a/lib/gitlab/markdown/relative_link_filter.rb +++ b/lib/gitlab/markdown/relative_link_filter.rb @@ -98,9 +98,10 @@ module Gitlab # # Returns a String def path_type(path) - if repository.tree(current_sha, path).entries.any? + unescaped_path = Addressable::URI.unescape(path) + if repository.tree(current_sha, unescaped_path).entries.any? 'tree' - elsif repository.blob_at(current_sha, path).try(:image?) + elsif repository.blob_at(current_sha, unescaped_path).try(:image?) 'raw' else 'blob' From 12a913a93c339a3dc325cbf53ae07eff902d937c Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Mon, 27 Jul 2015 17:32:56 -0400 Subject: [PATCH 107/174] Make `hr`s more visible in note bodies Closes #2107 --- app/assets/stylesheets/pages/notes.scss | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss index 4da65b28743..85c828ec1ad 100644 --- a/app/assets/stylesheets/pages/notes.scss +++ b/app/assets/stylesheets/pages/notes.scss @@ -37,7 +37,7 @@ ul.notes { font-size: 13px; a { - @extend .cgray; + @extend .cgray; &:hover { text-decoration: underline; @@ -105,6 +105,8 @@ ul.notes { } hr { + // Darken 'whitesmoke' a bit to make it more visible in note bodies + border-color: darken(#F5F5F5, 8%); margin: 10px 0; } } From 30b2a95b4d7d51f7c14c07c9f57fa84c1148725f Mon Sep 17 00:00:00 2001 From: Darby Date: Mon, 27 Jul 2015 17:41:31 -0400 Subject: [PATCH 108/174] Added a timestamp to the wikis page just below the title --- app/views/projects/wikis/show.html.haml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/views/projects/wikis/show.html.haml b/app/views/projects/wikis/show.html.haml index 83cd4c66672..5c4dd7f91ae 100644 --- a/app/views/projects/wikis/show.html.haml +++ b/app/views/projects/wikis/show.html.haml @@ -3,6 +3,10 @@ %h3.page-title = @page.title = render 'main_links' + +.wiki-last-edit-by + Last edited by #{@page.commit.author.name} #{time_ago_with_tooltip(@page.commit.authored_date)} + - if @page.historical? .warning_message This is an old version of this page. @@ -16,6 +20,6 @@ = render_wiki_content(@page) %hr - .wiki-last-edit-by Last edited by #{@page.commit.author.name} #{time_ago_with_tooltip(@page.commit.authored_date)} + From d61433542e3bbcfac6b706a5e907240ca02c6de9 Mon Sep 17 00:00:00 2001 From: karen Carias Date: Mon, 27 Jul 2015 16:46:30 -0700 Subject: [PATCH 109/174] fixed details in document --- doc/gitlab-basics/add-file.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/gitlab-basics/add-file.md b/doc/gitlab-basics/add-file.md index ac0d98085a4..e7c441e7698 100644 --- a/doc/gitlab-basics/add-file.md +++ b/doc/gitlab-basics/add-file.md @@ -8,13 +8,13 @@ Select a project on the right side of your screen: ![Select a project](basicsimages/select_project.png) -[Create a branch](create-branch.md). +It's a good idea to [create a branch](create-branch.md), but it's not necessary. Go to the directory where you'd like to add the file and click on the "+" sign next to the name of the project and directory: ![Create a file](basicsimages/create_file.png) -Add a name to your file, use .md or .html at the end, depending on which markup language you'd like to use (you can't add spaces, so you can use hyphens or underscores): +Name your file (you can't add spaces, so you can use hyphens or underscores). Don't forget to include the markup language you'd like to use : ![File name](basicsimages/file_name.png) From 6b243dd138115470a3d49b90ee3d2a199776c790 Mon Sep 17 00:00:00 2001 From: karen Carias Date: Mon, 27 Jul 2015 21:53:55 -0700 Subject: [PATCH 110/174] fixed text --- doc/workflow/importing/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/workflow/importing/README.md b/doc/workflow/importing/README.md index c6cd4d34cce..cd98d1b9852 100644 --- a/doc/workflow/importing/README.md +++ b/doc/workflow/importing/README.md @@ -8,4 +8,5 @@ ### Note * If you'd like to migrate from a self-hosted GitLab instance to GitLab.com, you can copy your repos by changing the remote and pushing to the new server; but issues and merge requests can't be imported. -* When you migrate repositories to GitLab, there is no restriction on maximum size. They are imported via HTTP, but if the repository is too large, it can timeout. +* Repositories are imported to GitLab via HTTP. +If the repository is too large, it can timeout. We have a soft limit of 10GB. From d3305df7aac4e632707492118a0ce91e67ed74ce Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 28 Jul 2015 14:33:19 +0200 Subject: [PATCH 111/174] Experimental support for gitlab-git-http-server https://gitlab.com/gitlab-org/gitlab-git-http-server This change introduces the GITLAB_GRACK_AUTH_ONLY environment variable. When set, Grack requests to GitLab will only respond with the user's GL_ID (if the request is OK) or an error. This allows gitlab-git-http-server to use the main GitLab application as an authentication and authorization backend. If we like how this works we should drop the GITLAB_GRACK_AUTH_ONLY variable at some point in the future. --- lib/gitlab/backend/grack_auth.rb | 7 ++++++- lib/gitlab/backend/shell_env.rb | 6 +++++- lib/support/nginx/gitlab | 25 +++++++++++++++++++++++++ lib/support/nginx/gitlab-ssl | 25 +++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/backend/grack_auth.rb b/lib/gitlab/backend/grack_auth.rb index 03cef30c97d..f7fc97651f2 100644 --- a/lib/gitlab/backend/grack_auth.rb +++ b/lib/gitlab/backend/grack_auth.rb @@ -26,7 +26,12 @@ module Grack auth! if project && authorized_request? - @app.call(env) + if ENV['GITLAB_GRACK_AUTH_ONLY'] == '1' + # Tell gitlab-git-http-server the request is OK, and what the GL_ID is + [200, { "Content-Type" => "text/plain" }, [Gitlab::ShellEnv.gl_id(@user)]] + else + @app.call(env) + end elsif @user.nil? && !@gitlab_ci unauthorized else diff --git a/lib/gitlab/backend/shell_env.rb b/lib/gitlab/backend/shell_env.rb index 17ec029eed4..009a3ec1a4b 100644 --- a/lib/gitlab/backend/shell_env.rb +++ b/lib/gitlab/backend/shell_env.rb @@ -7,7 +7,7 @@ module Gitlab def set_env(user) # Set GL_ID env variable if user - ENV['GL_ID'] = "user-#{user.id}" + ENV['GL_ID'] = gl_id(user) end end @@ -15,5 +15,9 @@ module Gitlab # Reset GL_ID env variable ENV['GL_ID'] = nil end + + def gl_id(user) + "user-#{user.id}" + end end end diff --git a/lib/support/nginx/gitlab b/lib/support/nginx/gitlab index edb987875df..efa0898900f 100644 --- a/lib/support/nginx/gitlab +++ b/lib/support/nginx/gitlab @@ -38,6 +38,11 @@ upstream gitlab { server unix:/home/git/gitlab/tmp/sockets/gitlab.socket fail_timeout=0; } +## Experimental: gitlab-git-http-server +# upstream gitlab-git-http-server { +# server localhost:8181; +# } + ## Normal HTTP host server { ## Either remove "default_server" from the listen line below, @@ -109,6 +114,26 @@ server { proxy_pass http://gitlab; } + ## Experimental: send Git HTTP traffic to gitlab-git-http-server instead of Unicorn + # location ~ [-\/\w\.]+\.git\/ { + # ## If you use HTTPS make sure you disable gzip compression + # ## to be safe against BREACH attack. + # # gzip off; + + # ## https://github.com/gitlabhq/gitlabhq/issues/694 + # ## Some requests take more than 30 seconds. + # proxy_read_timeout 300; + # proxy_connect_timeout 300; + # proxy_redirect off; + + # proxy_set_header Host $http_host; + # proxy_set_header X-Real-IP $remote_addr; + # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # proxy_set_header X-Forwarded-Proto $scheme; + + # proxy_pass http://gitlab-git-http-server; + # } + ## Enable gzip compression as per rails guide: ## http://guides.rubyonrails.org/asset_pipeline.html#gzip-compression ## WARNING: If you are using relative urls remove the block below diff --git a/lib/support/nginx/gitlab-ssl b/lib/support/nginx/gitlab-ssl index 766559b49f6..314525518f1 100644 --- a/lib/support/nginx/gitlab-ssl +++ b/lib/support/nginx/gitlab-ssl @@ -42,6 +42,11 @@ upstream gitlab { server unix:/home/git/gitlab/tmp/sockets/gitlab.socket fail_timeout=0; } +## Experimental: gitlab-git-http-server +# upstream gitlab-git-http-server { +# server localhost:8181; +# } + ## Redirects all HTTP traffic to the HTTPS host server { ## Either remove "default_server" from the listen line below, @@ -156,6 +161,26 @@ server { proxy_pass http://gitlab; } + ## Experimental: send Git HTTP traffic to gitlab-git-http-server instead of Unicorn + # location ~ [-\/\w\.]+\.git\/ { + # ## If you use HTTPS make sure you disable gzip compression + # ## to be safe against BREACH attack. + # gzip off; + + # ## https://github.com/gitlabhq/gitlabhq/issues/694 + # ## Some requests take more than 30 seconds. + # proxy_read_timeout 300; + # proxy_connect_timeout 300; + # proxy_redirect off; + + # proxy_set_header Host $http_host; + # proxy_set_header X-Real-IP $remote_addr; + # proxy_set_header X-Forwarded-Ssl on; + # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # proxy_set_header X-Forwarded-Proto $scheme; + # proxy_pass http://gitlab-git-http-server; + # } + ## Enable gzip compression as per rails guide: ## http://guides.rubyonrails.org/asset_pipeline.html#gzip-compression ## WARNING: If you are using relative urls remove the block below From ae9e5eea3c6955d278182005808fbdfccd4d447b Mon Sep 17 00:00:00 2001 From: GitLab Date: Tue, 28 Jul 2015 15:17:06 +0200 Subject: [PATCH 112/174] Handle missing @user during Git HTTP requests --- lib/gitlab/backend/grack_auth.rb | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/gitlab/backend/grack_auth.rb b/lib/gitlab/backend/grack_auth.rb index f7fc97651f2..5966d394b62 100644 --- a/lib/gitlab/backend/grack_auth.rb +++ b/lib/gitlab/backend/grack_auth.rb @@ -28,7 +28,7 @@ module Grack if project && authorized_request? if ENV['GITLAB_GRACK_AUTH_ONLY'] == '1' # Tell gitlab-git-http-server the request is OK, and what the GL_ID is - [200, { "Content-Type" => "text/plain" }, [Gitlab::ShellEnv.gl_id(@user)]] + render_grack_auth_ok else @app.call(env) end @@ -179,6 +179,15 @@ module Grack end end + def render_grack_auth_ok + if @user.present? + body = Gitlab::ShellEnv.gl_id(@user) + else + body = '' + end + [200, { "Content-Type" => "text/plain" }, [body]] + end + def render_not_found [404, { "Content-Type" => "text/plain" }, ["Not Found"]] end From 42ebd902de707c8ddc35b97983ec0eee16458e56 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 28 Jul 2015 15:33:16 +0200 Subject: [PATCH 113/174] Fix bug causing Bitbucket importer to crash when OAuth application had been removed. --- CHANGELOG | 1 + .../import/bitbucket_controller.rb | 1 + lib/gitlab/bitbucket_import/client.rb | 21 +++++++++++++------ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index cf0fa36bd47..331f7d7a3a0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -16,6 +16,7 @@ v 7.14.0 (unreleased) - Expire Rails cache entries after two weeks to prevent endless Redis growth - Add support for destroying project milestones (Stan Hu) - Add fetch command to the MR page + - Fix bug causing Bitbucket importer to crash when OAuth application had been removed. v 7.13.1 - Fix: Label modifications are not reflected in existing notes and in the issue list diff --git a/app/controllers/import/bitbucket_controller.rb b/app/controllers/import/bitbucket_controller.rb index ca78a4aaa8e..af0b841f0b7 100644 --- a/app/controllers/import/bitbucket_controller.rb +++ b/app/controllers/import/bitbucket_controller.rb @@ -3,6 +3,7 @@ class Import::BitbucketController < Import::BaseController before_action :bitbucket_auth, except: :callback rescue_from OAuth::Error, with: :bitbucket_unauthorized + rescue_from Gitlab::BitbucketImport::Client::Unauthorized, with: :bitbucket_unauthorized def callback request_token = session.delete(:oauth_request_token) diff --git a/lib/gitlab/bitbucket_import/client.rb b/lib/gitlab/bitbucket_import/client.rb index 5b1952b9675..778b76f6890 100644 --- a/lib/gitlab/bitbucket_import/client.rb +++ b/lib/gitlab/bitbucket_import/client.rb @@ -1,6 +1,8 @@ module Gitlab module BitbucketImport class Client + class Unauthorized < StandardError; end + attr_reader :consumer, :api def initialize(access_token = nil, access_token_secret = nil) @@ -46,23 +48,23 @@ module Gitlab end def user - JSON.parse(api.get("/api/1.0/user").body) + JSON.parse(get("/api/1.0/user").body) end def issues(project_identifier) - JSON.parse(api.get("/api/1.0/repositories/#{project_identifier}/issues").body) + JSON.parse(get("/api/1.0/repositories/#{project_identifier}/issues").body) end def issue_comments(project_identifier, issue_id) - JSON.parse(api.get("/api/1.0/repositories/#{project_identifier}/issues/#{issue_id}/comments").body) + JSON.parse(get("/api/1.0/repositories/#{project_identifier}/issues/#{issue_id}/comments").body) end def project(project_identifier) - JSON.parse(api.get("/api/1.0/repositories/#{project_identifier}").body) + JSON.parse(get("/api/1.0/repositories/#{project_identifier}").body) end def find_deploy_key(project_identifier, key) - JSON.parse(api.get("/api/1.0/repositories/#{project_identifier}/deploy-keys").body).find do |deploy_key| + JSON.parse(get("/api/1.0/repositories/#{project_identifier}/deploy-keys").body).find do |deploy_key| deploy_key["key"].chomp == key.chomp end end @@ -82,11 +84,18 @@ module Gitlab end def projects - JSON.parse(api.get("/api/1.0/user/repositories").body).select { |repo| repo["scm"] == "git" } + JSON.parse(get("/api/1.0/user/repositories").body).select { |repo| repo["scm"] == "git" } end private + def get(url) + response = api.get(url) + raise Unauthorized if (400..499).include?(response.code.to_i) + + response + end + def config Gitlab.config.omniauth.providers.find { |provider| provider.name == "bitbucket"} end From a784b996b3071cfe1807b1108316143dbc64492f Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 28 Jul 2015 15:49:44 +0200 Subject: [PATCH 114/174] Add project star and fork count, group avatar URL and user/group web URL attributes to API --- CHANGELOG | 1 + app/models/group.rb | 11 +++++++++++ app/models/user.rb | 4 ++++ lib/api/entities.rb | 4 +++- 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index cf0fa36bd47..eef3c3e7c01 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -16,6 +16,7 @@ v 7.14.0 (unreleased) - Expire Rails cache entries after two weeks to prevent endless Redis growth - Add support for destroying project milestones (Stan Hu) - Add fetch command to the MR page + - Add project star and fork count, group avatar URL and user/group web URL attributes to API v 7.13.1 - Fix: Label modifications are not reflected in existing notes and in the issue list diff --git a/app/models/group.rb b/app/models/group.rb index 051c672cb33..adcbbec465e 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -17,6 +17,7 @@ require 'carrierwave/orm/activerecord' require 'file_size_validator' class Group < Namespace + include Gitlab::ConfigHelper include Referable has_many :group_members, dependent: :destroy, as: :source, class_name: 'GroupMember' @@ -56,6 +57,16 @@ class Group < Namespace name end + def avatar_url(size = nil) + if avatar.present? + [gitlab_config.url, avatar.url].join + end + end + + def web_url + [gitlab_config.url, "groups", self.path].join('/') + end + def owners @owners ||= group_members.owners.map(&:user) end diff --git a/app/models/user.rb b/app/models/user.rb index 4a10520b209..00a37cd9135 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -637,6 +637,10 @@ class User < ActiveRecord::Base end end + def web_url + [gitlab_config.url, "u", self.username].join('/') + end + def all_emails [self.email, *self.emails.map(&:email)] end diff --git a/lib/api/entities.rb b/lib/api/entities.rb index ecf1412dee5..c1b0cece344 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -5,7 +5,7 @@ module API end class UserBasic < UserSafe - expose :id, :state, :avatar_url + expose :id, :state, :avatar_url, :web_url end class User < UserBasic @@ -59,6 +59,7 @@ module API expose :namespace expose :forked_from_project, using: Entities::ForkedFromProject, if: lambda{ | project, options | project.forked? } expose :avatar_url + expose :star_count, :forks_count end class ProjectMember < UserBasic @@ -69,6 +70,7 @@ module API class Group < Grape::Entity expose :id, :name, :path, :description + expose :avatar_url, :web_url end class GroupDetail < Group From 6912f21e5c9dd812286fce156534ebc094466e17 Mon Sep 17 00:00:00 2001 From: GitLab Date: Tue, 28 Jul 2015 15:55:53 +0200 Subject: [PATCH 115/174] Send GL_ID to gitlab-git-http-server as JSON --- lib/gitlab/backend/grack_auth.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/gitlab/backend/grack_auth.rb b/lib/gitlab/backend/grack_auth.rb index 5966d394b62..e8cb0c77fb4 100644 --- a/lib/gitlab/backend/grack_auth.rb +++ b/lib/gitlab/backend/grack_auth.rb @@ -181,11 +181,12 @@ module Grack def render_grack_auth_ok if @user.present? - body = Gitlab::ShellEnv.gl_id(@user) + gl_id = Gitlab::ShellEnv.gl_id(@user) else - body = '' + gl_id = '' end - [200, { "Content-Type" => "text/plain" }, [body]] + + [200, { "Content-Type" => "application/json" }, [JSON.dump({'GL_ID' => gl_id})]] end def render_not_found From f9bcb9632c1f7f5c5c72d50a90289baa2af762f5 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 28 Jul 2015 16:32:15 +0200 Subject: [PATCH 116/174] Add specific ability for managing group members --- app/controllers/groups/group_members_controller.rb | 7 +++++++ app/models/ability.rb | 5 +++-- app/views/dashboard/groups/index.html.haml | 7 ++++--- app/views/groups/group_members/_group_member.html.haml | 2 +- app/views/groups/group_members/index.html.haml | 2 +- 5 files changed, 16 insertions(+), 7 deletions(-) diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb index 040255f08e6..b9c428a964f 100644 --- a/app/controllers/groups/group_members_controller.rb +++ b/app/controllers/groups/group_members_controller.rb @@ -21,6 +21,8 @@ class Groups::GroupMembersController < Groups::ApplicationController end def create + return render_403 unless can?(current_user, :admin_group_member, @group) + @group.add_users(params[:user_ids].split(','), params[:access_level], current_user) redirect_to group_group_members_path(@group), notice: 'Users were successfully added.' @@ -28,6 +30,9 @@ class Groups::GroupMembersController < Groups::ApplicationController def update @member = @group.group_members.find(params[:id]) + + return render_403 unless can?(current_user, :update_group_member, @member) + @member.update_attributes(member_params) end @@ -46,6 +51,8 @@ class Groups::GroupMembersController < Groups::ApplicationController end def resend_invite + return render_403 unless can?(current_user, :admin_group_member, @group) + redirect_path = group_group_members_path(@group) @group_member = @group.group_members.find(params[:id]) diff --git a/app/models/ability.rb b/app/models/ability.rb index 6a8f683bc89..f8e5afa9b01 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -233,7 +233,8 @@ class Ability if group.has_owner?(user) || user.admin? rules.push(*[ :admin_group, - :admin_namespace + :admin_namespace, + :admin_group_member ]) end @@ -295,7 +296,7 @@ class Ability rules = [] target_user = subject.user group = subject.group - can_manage = group_abilities(user, group).include?(:admin_group) + can_manage = group_abilities(user, group).include?(:admin_group_member) if can_manage && (user != target_user) rules << :update_group_member diff --git a/app/views/dashboard/groups/index.html.haml b/app/views/dashboard/groups/index.html.haml index 0a354373b9b..b75c11795bd 100644 --- a/app/views/dashboard/groups/index.html.haml +++ b/app/views/dashboard/groups/index.html.haml @@ -23,9 +23,10 @@ %i.fa.fa-cogs Settings - = link_to leave_group_group_members_path(group), data: { confirm: leave_group_message(group.name) }, method: :delete, class: "btn-sm btn btn-grouped", title: 'Leave this group' do - %i.fa.fa-sign-out - Leave + - if can?(current_user, :destroy_group_member, group_member) + = link_to leave_group_group_members_path(group), data: { confirm: leave_group_message(group.name) }, method: :delete, class: "btn-sm btn btn-grouped", title: 'Leave this group' do + %i.fa.fa-sign-out + Leave = image_tag group_icon(group), class: "avatar s40 avatar-tile hidden-xs" = link_to group, class: 'group-name' do diff --git a/app/views/groups/group_members/_group_member.html.haml b/app/views/groups/group_members/_group_member.html.haml index b460e0ff59e..acc7f8b28c2 100644 --- a/app/views/groups/group_members/_group_member.html.haml +++ b/app/views/groups/group_members/_group_member.html.haml @@ -24,7 +24,7 @@ = link_to member.created_by.name, user_path(member.created_by) = time_ago_with_tooltip(member.created_at) - - if show_controls && can?(current_user, :admin_group, @group) + - if show_controls && can?(current_user, :admin_group_member, member) = link_to resend_invite_group_group_member_path(@group, member), method: :post, class: "btn-xs btn", title: 'Resend invite' do Resend invite diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml index a70d1ff0697..dba395cc8fa 100644 --- a/app/views/groups/group_members/index.html.haml +++ b/app/views/groups/group_members/index.html.haml @@ -17,7 +17,7 @@ = search_field_tag :search, params[:search], { placeholder: 'Find existing member by name', class: 'form-control search-text-input' } = button_tag 'Search', class: 'btn' - - if current_user && current_user.can?(:admin_group, @group) + - if current_user && current_user.can?(:admin_group_member, @group) .pull-right = button_tag class: 'btn btn-new js-toggle-button', type: 'button' do Add members From 45acfdd32ace09b8ff4c8905cbeefb3d8001ccc3 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 28 Jul 2015 16:36:48 +0200 Subject: [PATCH 117/174] Disable adding members from admin area when appropriate --- app/views/admin/groups/show.html.haml | 34 ++++++++++++++------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml index 187314872de..296497a4cd4 100644 --- a/app/views/admin/groups/show.html.haml +++ b/app/views/admin/groups/show.html.haml @@ -51,21 +51,22 @@ = paginate @projects, param_name: 'projects_page', theme: 'gitlab' .col-md-6 - .panel.panel-default - .panel-heading - Add user(s) to the group: - .panel-body.form-holder - %p.light - Read more about project permissions - %strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink" + - if can?(current_user, :admin_group_member, @group) + .panel.panel-default + .panel-heading + Add user(s) to the group: + .panel-body.form-holder + %p.light + Read more about project permissions + %strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink" - = form_tag members_update_admin_group_path(@group), id: "new_project_member", class: "bulk_import", method: :put do - %div - = users_select_tag(:user_ids, multiple: true, email_user: true, scope: :all) - %div.prepend-top-10 - = select_tag :access_level, options_for_select(GroupMember.access_level_roles), class: "project-access-select select2" - %hr - = button_tag 'Add users to group', class: "btn btn-create" + = form_tag members_update_admin_group_path(@group), id: "new_project_member", class: "bulk_import", method: :put do + %div + = users_select_tag(:user_ids, multiple: true, email_user: true, scope: :all) + %div.prepend-top-10 + = select_tag :access_level, options_for_select(GroupMember.access_level_roles), class: "project-access-select select2" + %hr + = button_tag 'Add users to group', class: "btn btn-create" .panel.panel-default .panel-heading %h3.panel-title @@ -86,7 +87,8 @@ (invited) %span.pull-right.light = member.human_access - = link_to group_group_member_path(@group, member), data: { confirm: remove_user_from_group_message(@group, member) }, method: :delete, remote: true, class: "btn-xs btn btn-remove", title: 'Remove user from group' do - %i.fa.fa-minus.fa-inverse + - if can?(current_user, :destroy_group_member, member) + = link_to group_group_member_path(@group, member), data: { confirm: remove_user_from_group_message(@group, member) }, method: :delete, remote: true, class: "btn-xs btn btn-remove", title: 'Remove user from group' do + %i.fa.fa-minus.fa-inverse .panel-footer = paginate @members, param_name: 'members_page', theme: 'gitlab' From b230335090ee8fa22ab79453e24c1c3c468569df Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 28 Jul 2015 17:52:38 +0200 Subject: [PATCH 118/174] Show Leave button when you're the last owner, so that the error explains the reason --- app/views/dashboard/groups/index.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/dashboard/groups/index.html.haml b/app/views/dashboard/groups/index.html.haml index b75c11795bd..6ef4d752ac3 100644 --- a/app/views/dashboard/groups/index.html.haml +++ b/app/views/dashboard/groups/index.html.haml @@ -23,7 +23,7 @@ %i.fa.fa-cogs Settings - - if can?(current_user, :destroy_group_member, group_member) + - if can?(current_user, :admin_group_member, group) = link_to leave_group_group_members_path(group), data: { confirm: leave_group_message(group.name) }, method: :delete, class: "btn-sm btn btn-grouped", title: 'Leave this group' do %i.fa.fa-sign-out Leave From 16dcf356b5afe351a78ac976db30e4999600b13b Mon Sep 17 00:00:00 2001 From: GitLab Date: Tue, 28 Jul 2015 18:04:57 +0200 Subject: [PATCH 119/174] Fix style points To make Rubocop and Douwe happy --- lib/gitlab/backend/grack_auth.rb | 8 +------- lib/gitlab/backend/shell_env.rb | 7 ++++++- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/lib/gitlab/backend/grack_auth.rb b/lib/gitlab/backend/grack_auth.rb index e8cb0c77fb4..12292f614e9 100644 --- a/lib/gitlab/backend/grack_auth.rb +++ b/lib/gitlab/backend/grack_auth.rb @@ -180,13 +180,7 @@ module Grack end def render_grack_auth_ok - if @user.present? - gl_id = Gitlab::ShellEnv.gl_id(@user) - else - gl_id = '' - end - - [200, { "Content-Type" => "application/json" }, [JSON.dump({'GL_ID' => gl_id})]] + [200, { "Content-Type" => "application/json" }, [JSON.dump({ 'GL_ID' => Gitlab::ShellEnv.gl_id(@user) })]] end def render_not_found diff --git a/lib/gitlab/backend/shell_env.rb b/lib/gitlab/backend/shell_env.rb index 009a3ec1a4b..9f5adee594a 100644 --- a/lib/gitlab/backend/shell_env.rb +++ b/lib/gitlab/backend/shell_env.rb @@ -17,7 +17,12 @@ module Gitlab end def gl_id(user) - "user-#{user.id}" + if user.present? + "user-#{user.id}" + else + # This empty string is used in the render_grack_auth_ok method + "" + end end end end From c22b4061c2136c57a30b96a886688d49ecd88193 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Tue, 28 Jul 2015 08:07:25 -0700 Subject: [PATCH 120/174] Upgrade gitlab_git to version 7.2.6 to fix Error 500 when creating network graphs Closes #745 --- CHANGELOG | 1 + Gemfile | 2 +- Gemfile.lock | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index cf0fa36bd47..12ad9b7e790 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.14.0 (unreleased) + - Upgrade gitlab_git to version 7.2.6 to fix Error 500 when creating network graphs (Stan Hu) - Fix URL used for refreshing notes if relative_url is present (Bartłomiej Święcki) - Fix commit data retrieval when branch name has single quotes (Stan Hu) - Fix Error 500 when browsing projects with no HEAD (Stan Hu) diff --git a/Gemfile b/Gemfile index ba32feba3e7..8552e731bbd 100644 --- a/Gemfile +++ b/Gemfile @@ -38,7 +38,7 @@ gem "browser", '~> 0.8.0' # Extracting information from a git repository # Provide access to Gitlab::Git library -gem "gitlab_git", '~> 7.2.5' +gem "gitlab_git", '~> 7.2.6' # Ruby/Rack Git Smart-HTTP Server Handler # GitLab fork with a lot of changes (improved thread-safety, better memory usage etc) diff --git a/Gemfile.lock b/Gemfile.lock index 6e571072a4c..bef67884c37 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -271,7 +271,7 @@ GEM mime-types (~> 1.19) gitlab_emoji (0.1.0) gemojione (~> 2.0) - gitlab_git (7.2.5) + gitlab_git (7.2.6) activesupport (~> 4.0) charlock_holmes (~> 0.6) gitlab-linguist (~> 3.0) @@ -784,7 +784,7 @@ DEPENDENCIES gitlab-grack (~> 2.0.2) gitlab-linguist (~> 3.0.1) gitlab_emoji (~> 0.1) - gitlab_git (~> 7.2.5) + gitlab_git (~> 7.2.6) gitlab_meta (= 7.0) gitlab_omniauth-ldap (= 1.2.1) gollum-lib (~> 4.0.2) From 5bdcef7b0b6fd9cfdc3498a40d2b2b2a9ddc682c Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Tue, 28 Jul 2015 17:37:14 +0000 Subject: [PATCH 121/174] Change before(:all) -> let! to avoid leaking data across tests Closes https://github.com/gitlabhq/gitlabhq/issues/9495 --- spec/features/security/group_access_spec.rb | 30 ++++++++++----------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/spec/features/security/group_access_spec.rb b/spec/features/security/group_access_spec.rb index 0f36e474989..8ce15388605 100644 --- a/spec/features/security/group_access_spec.rb +++ b/spec/features/security/group_access_spec.rb @@ -36,7 +36,7 @@ describe 'Group access', feature: true do subject { group_path(group) } context 'with public projects' do - before(:all) { create_project(:public) } + let!(:project) { create_project(:public) } it { is_expected.to be_allowed_for group_member(:owner) } it { is_expected.to be_allowed_for group_member(:master) } @@ -48,7 +48,7 @@ describe 'Group access', feature: true do end context 'with mixed projects' do - before(:all) { create_project(:mixed) } + let!(:project) { create_project(:mixed) } it { is_expected.to be_allowed_for group_member(:owner) } it { is_expected.to be_allowed_for group_member(:master) } @@ -60,7 +60,7 @@ describe 'Group access', feature: true do end context 'with internal projects' do - before(:all) { create_project(:internal) } + let!(:project) { create_project(:internal) } it { is_expected.to be_allowed_for group_member(:owner) } it { is_expected.to be_allowed_for group_member(:master) } @@ -86,7 +86,7 @@ describe 'Group access', feature: true do subject { issues_group_path(group) } context 'with public projects' do - before(:all) { create_project(:public) } + let!(:project) { create_project(:public) } it { is_expected.to be_allowed_for group_member(:owner) } it { is_expected.to be_allowed_for group_member(:master) } @@ -98,7 +98,7 @@ describe 'Group access', feature: true do end context 'with mixed projects' do - before(:all) { create_project(:mixed) } + let!(:project) { create_project(:mixed) } it { is_expected.to be_allowed_for group_member(:owner) } it { is_expected.to be_allowed_for group_member(:master) } @@ -110,7 +110,7 @@ describe 'Group access', feature: true do end context 'with internal projects' do - before(:all) { create_project(:internal) } + let!(:project) { create_project(:internal) } it { is_expected.to be_allowed_for group_member(:owner) } it { is_expected.to be_allowed_for group_member(:master) } @@ -136,7 +136,7 @@ describe 'Group access', feature: true do subject { merge_requests_group_path(group) } context 'with public projects' do - before(:all) { create_project(:public) } + let!(:project) { create_project(:public) } it { is_expected.to be_allowed_for group_member(:owner) } it { is_expected.to be_allowed_for group_member(:master) } @@ -148,7 +148,7 @@ describe 'Group access', feature: true do end context 'with mixed projects' do - before(:all) { create_project(:mixed) } + let!(:project) { create_project(:mixed) } it { is_expected.to be_allowed_for group_member(:owner) } it { is_expected.to be_allowed_for group_member(:master) } @@ -160,7 +160,7 @@ describe 'Group access', feature: true do end context 'with internal projects' do - before(:all) { create_project(:internal) } + let!(:project) { create_project(:internal) } it { is_expected.to be_allowed_for group_member(:owner) } it { is_expected.to be_allowed_for group_member(:master) } @@ -186,7 +186,7 @@ describe 'Group access', feature: true do subject { group_group_members_path(group) } context 'with public projects' do - before(:all) { create_project(:public) } + let!(:project) { create_project(:public) } it { is_expected.to be_allowed_for group_member(:owner) } it { is_expected.to be_allowed_for group_member(:master) } @@ -198,7 +198,7 @@ describe 'Group access', feature: true do end context 'with mixed projects' do - before(:all) { create_project(:mixed) } + let!(:project) { create_project(:mixed) } it { is_expected.to be_allowed_for group_member(:owner) } it { is_expected.to be_allowed_for group_member(:master) } @@ -210,7 +210,7 @@ describe 'Group access', feature: true do end context 'with internal projects' do - before(:all) { create_project(:internal) } + let!(:project) { create_project(:internal) } it { is_expected.to be_allowed_for group_member(:owner) } it { is_expected.to be_allowed_for group_member(:master) } @@ -236,7 +236,7 @@ describe 'Group access', feature: true do subject { edit_group_path(group) } context 'with public projects' do - before(:all) { create_project(:public) } + let!(:project) { create_project(:public) } it { is_expected.to be_allowed_for group_member(:owner) } it { is_expected.to be_denied_for group_member(:master) } @@ -248,7 +248,7 @@ describe 'Group access', feature: true do end context 'with mixed projects' do - before(:all) { create_project(:mixed) } + let!(:project) { create_project(:mixed) } it { is_expected.to be_allowed_for group_member(:owner) } it { is_expected.to be_denied_for group_member(:master) } @@ -260,7 +260,7 @@ describe 'Group access', feature: true do end context 'with internal projects' do - before(:all) { create_project(:internal) } + let!(:project) { create_project(:internal) } it { is_expected.to be_allowed_for group_member(:owner) } it { is_expected.to be_denied_for group_member(:master) } From f8bfd065aa010955e9435347cb92b92006f0d5bf Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Tue, 28 Jul 2015 14:31:02 -0700 Subject: [PATCH 122/174] Fix extraneous version --- CHANGELOG | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 12ad9b7e790..b2169b5de12 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -30,7 +30,6 @@ v 7.13.1 v 7.13.0 - Remove repository graph log to fix slow cache updates after push event (Stan Hu) -v 7.13.0 (unreleased) - Return comments in created order in merge request API (Stan Hu) - Only enable HSTS header for HTTPS and port 443 (Stan Hu) - Fix user autocomplete for unauthenticated users accessing public projects (Stan Hu) From b07ecbb5e37530e7754dc267da4ded1d7d2d736d Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sun, 19 Jul 2015 19:41:54 -0400 Subject: [PATCH 123/174] Simplify AutolinkFilter specs --- spec/features/markdown_spec.rb | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/spec/features/markdown_spec.rb b/spec/features/markdown_spec.rb index b8199aa5e61..b8a846c7015 100644 --- a/spec/features/markdown_spec.rb +++ b/spec/features/markdown_spec.rb @@ -195,45 +195,41 @@ describe 'GitLab Markdown', feature: true do end describe 'AutolinkFilter' do - let(:list) { get_section('autolinkfilter').next_element } + def body + get_section('autolinkfilter').next_element + end - def item(index) - list.at_css("li:nth-child(#{index})") + # Override Capybara's `have_link` matcher to simplify our use case + def have_link(link) + super(link, href: link) end it 'autolinks http://' do - expect(item(1).children.first.name).to eq 'a' - expect(item(1).children.first['href']).to eq 'http://about.gitlab.com/' + expect(body).to have_link('http://about.gitlab.com/') end it 'autolinks https://' do - expect(item(2).children.first.name).to eq 'a' - expect(item(2).children.first['href']).to eq 'https://google.com/' + expect(body).to have_link('https://google.com/') end it 'autolinks ftp://' do - expect(item(3).children.first.name).to eq 'a' - expect(item(3).children.first['href']).to eq 'ftp://ftp.us.debian.org/debian/' + expect(body).to have_link('ftp://ftp.us.debian.org/debian/') end it 'autolinks smb://' do - expect(item(4).children.first.name).to eq 'a' - expect(item(4).children.first['href']).to eq 'smb://foo/bar/baz' + expect(body).to have_link('smb://foo/bar/baz') end it 'autolinks irc://' do - expect(item(5).children.first.name).to eq 'a' - expect(item(5).children.first['href']).to eq 'irc://irc.freenode.net/git' + expect(body).to have_link('irc://irc.freenode.net/git') end it 'autolinks short, invalid URLs' do - expect(item(6).children.first.name).to eq 'a' - expect(item(6).children.first['href']).to eq 'http://localhost:3000' + expect(body).to have_link('http://localhost:3000') end %w(code a kbd).each do |elem| it "ignores links inside '#{elem}' element" do - body = get_section('autolinkfilter') expect(body).not_to have_selector("#{elem} a") end end From 06478ef3ecba80625e5cff70cb3697f442e24cba Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Mon, 20 Jul 2015 22:22:17 -0400 Subject: [PATCH 124/174] Minor Markdown feature spec reorganization --- spec/features/markdown_spec.rb | 93 +++++++++++++++++----------------- 1 file changed, 47 insertions(+), 46 deletions(-) diff --git a/spec/features/markdown_spec.rb b/spec/features/markdown_spec.rb index b8a846c7015..f1be4e49c8a 100644 --- a/spec/features/markdown_spec.rb +++ b/spec/features/markdown_spec.rb @@ -33,39 +33,31 @@ require 'erb' # See the MarkdownFeature class for setup details. describe 'GitLab Markdown', feature: true do - include ActionView::Helpers::TagHelper - include ActionView::Helpers::UrlHelper include Capybara::Node::Matchers include GitlabMarkdownHelper - # `markdown` calls these two methods - def current_user - @feat.user - end - - def user_color_scheme_class - :white - end - # Let's only parse this thing once before(:all) do @feat = MarkdownFeature.new - # `markdown` expects a `@project` variable + # `gfm_with_options` depends on a `@project` variable @project = @feat.project - @md = markdown(@feat.raw_markdown) - @doc = Nokogiri::HTML::DocumentFragment.parse(@md) + @html = markdown(@feat.raw_markdown) end after(:all) do @feat.teardown end + def doc + @doc ||= Nokogiri::HTML::DocumentFragment.parse(@html) + end + # Given a header ID, goes to that element's parent (the header itself), then # its next sibling element (the body). def get_section(id) - @doc.at_css("##{id}").parent.next_element + doc.at_css("##{id}").parent.next_element end # Sometimes it can be useful to see the parsed output of the Markdown document @@ -74,11 +66,11 @@ describe 'GitLab Markdown', feature: true do # # it 'writes to a file' do # File.open(Rails.root.join('tmp/capybara/markdown_spec.html'), 'w') do |file| - # file.puts @md + # file.puts @html # end # end - describe 'Markdown' do + describe 'Redcarpet extensions' do describe 'No Intra Emphasis' do it 'does not parse emphasis inside of words' do body = get_section('no-intra-emphasis') @@ -95,21 +87,21 @@ describe 'GitLab Markdown', feature: true do end it 'allows Markdown in tables' do - expect(@doc.at_css('td:contains("Baz")').children.to_html). + expect(doc.at_css('td:contains("Baz")').children.to_html). to eq 'Baz' end end describe 'Fenced Code Blocks' do it 'parses fenced code blocks' do - expect(@doc).to have_selector('pre.code.highlight.white.c') - expect(@doc).to have_selector('pre.code.highlight.white.python') + expect(doc).to have_selector('pre.code.highlight.white.c') + expect(doc).to have_selector('pre.code.highlight.white.python') end end describe 'Strikethrough' do it 'parses strikethroughs' do - expect(@doc).to have_selector(%{del:contains("and this text doesn't")}) + expect(doc).to have_selector(%{del:contains("and this text doesn't")}) end end @@ -125,28 +117,28 @@ describe 'GitLab Markdown', feature: true do describe 'HTML::Pipeline' do describe 'SanitizationFilter' do it 'uses a permissive whitelist' do - expect(@doc).to have_selector('b:contains("b tag")') - expect(@doc).to have_selector('em:contains("em tag")') - expect(@doc).to have_selector('code:contains("code tag")') - expect(@doc).to have_selector('kbd:contains("s")') - expect(@doc).to have_selector('strike:contains(Emoji)') - expect(@doc).to have_selector('img[src*="smile.png"]') - expect(@doc).to have_selector('br') - expect(@doc).to have_selector('hr') + expect(doc).to have_selector('b:contains("b tag")') + expect(doc).to have_selector('em:contains("em tag")') + expect(doc).to have_selector('code:contains("code tag")') + expect(doc).to have_selector('kbd:contains("s")') + expect(doc).to have_selector('strike:contains(Emoji)') + expect(doc).to have_selector('img[src*="smile.png"]') + expect(doc).to have_selector('br') + expect(doc).to have_selector('hr') end it 'permits span elements' do - expect(@doc).to have_selector('span:contains("span tag")') + expect(doc).to have_selector('span:contains("span tag")') end it 'permits table alignment' do - expect(@doc.at_css('th:contains("Header")')['style']).to eq 'text-align: center' - expect(@doc.at_css('th:contains("Row")')['style']).to eq 'text-align: right' - expect(@doc.at_css('th:contains("Example")')['style']).to eq 'text-align: left' + expect(doc.at_css('th:contains("Header")')['style']).to eq 'text-align: center' + expect(doc.at_css('th:contains("Row")')['style']).to eq 'text-align: right' + expect(doc.at_css('th:contains("Example")')['style']).to eq 'text-align: left' - expect(@doc.at_css('td:contains("Foo")')['style']).to eq 'text-align: center' - expect(@doc.at_css('td:contains("Bar")')['style']).to eq 'text-align: right' - expect(@doc.at_css('td:contains("Baz")')['style']).to eq 'text-align: left' + expect(doc.at_css('td:contains("Foo")')['style']).to eq 'text-align: center' + expect(doc.at_css('td:contains("Bar")')['style']).to eq 'text-align: right' + expect(doc.at_css('td:contains("Baz")')['style']).to eq 'text-align: left' end it 'removes `rel` attribute from links' do @@ -155,12 +147,12 @@ describe 'GitLab Markdown', feature: true do end it "removes `href` from `a` elements if it's fishy" do - expect(@doc).not_to have_selector('a[href*="javascript"]') + expect(doc).not_to have_selector('a[href*="javascript"]') end end describe 'Escaping' do - let(:table) { @doc.css('table').last.at_css('tbody') } + let(:table) { doc.css('table').last.at_css('tbody') } it 'escapes non-tag angle brackets' do expect(table.at_xpath('.//tr[1]/td[3]').inner_html).to eq '1 < 3 & 5' @@ -169,28 +161,28 @@ describe 'GitLab Markdown', feature: true do describe 'Edge Cases' do it 'allows markup inside link elements' do - expect(@doc.at_css('a[href="#link-emphasis"]').to_html). + expect(doc.at_css('a[href="#link-emphasis"]').to_html). to eq %{text} - expect(@doc.at_css('a[href="#link-strong"]').to_html). + expect(doc.at_css('a[href="#link-strong"]').to_html). to eq %{text} - expect(@doc.at_css('a[href="#link-code"]').to_html). + expect(doc.at_css('a[href="#link-code"]').to_html). to eq %{text} end end describe 'EmojiFilter' do it 'parses Emoji' do - expect(@doc).to have_selector('img.emoji', count: 10) + expect(doc).to have_selector('img.emoji', count: 10) end end describe 'TableOfContentsFilter' do it 'creates anchors inside header elements' do - expect(@doc).to have_selector('h1 a#gitlab-markdown') - expect(@doc).to have_selector('h2 a#markdown') - expect(@doc).to have_selector('h3 a#autolinkfilter') + expect(doc).to have_selector('h1 a#gitlab-markdown') + expect(doc).to have_selector('h2 a#markdown') + expect(doc).to have_selector('h3 a#autolinkfilter') end end @@ -249,7 +241,7 @@ describe 'GitLab Markdown', feature: true do describe 'ReferenceFilter' do it 'handles references in headers' do - header = @doc.at_css('#reference-filters-eg-1').parent + header = doc.at_css('#reference-filters-eg-1').parent expect(header.css('a').size).to eq 2 end @@ -304,6 +296,15 @@ describe 'GitLab Markdown', feature: true do end end end + + # `markdown` calls these two methods + def current_user + @feat.user + end + + def user_color_scheme_class + :white + end end # This is a helper class used by the GitLab Markdown feature spec From 3cafa74387d707dac37d0e81bf2bb194e94957e4 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Mon, 20 Jul 2015 22:31:05 -0400 Subject: [PATCH 125/174] Use aggregate_failures where appropriate --- spec/features/markdown_spec.rb | 85 +++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 33 deletions(-) diff --git a/spec/features/markdown_spec.rb b/spec/features/markdown_spec.rb index f1be4e49c8a..dadb1c3589f 100644 --- a/spec/features/markdown_spec.rb +++ b/spec/features/markdown_spec.rb @@ -81,9 +81,12 @@ describe 'GitLab Markdown', feature: true do describe 'Tables' do it 'parses table Markdown' do body = get_section('tables') - expect(body).to have_selector('th:contains("Header")') - expect(body).to have_selector('th:contains("Row")') - expect(body).to have_selector('th:contains("Example")') + + aggregate_failures do + expect(body).to have_selector('th:contains("Header")') + expect(body).to have_selector('th:contains("Row")') + expect(body).to have_selector('th:contains("Example")') + end end it 'allows Markdown in tables' do @@ -94,8 +97,10 @@ describe 'GitLab Markdown', feature: true do describe 'Fenced Code Blocks' do it 'parses fenced code blocks' do - expect(doc).to have_selector('pre.code.highlight.white.c') - expect(doc).to have_selector('pre.code.highlight.white.python') + aggregate_failures do + expect(doc).to have_selector('pre.code.highlight.white.c') + expect(doc).to have_selector('pre.code.highlight.white.python') + end end end @@ -108,8 +113,11 @@ describe 'GitLab Markdown', feature: true do describe 'Superscript' do it 'parses superscript' do body = get_section('superscript') - expect(body.to_html).to match('1st') - expect(body.to_html).to match('2nd') + + aggregate_failures do + expect(body.to_html).to match('1st') + expect(body.to_html).to match('2nd') + end end end end @@ -117,14 +125,16 @@ describe 'GitLab Markdown', feature: true do describe 'HTML::Pipeline' do describe 'SanitizationFilter' do it 'uses a permissive whitelist' do - expect(doc).to have_selector('b:contains("b tag")') - expect(doc).to have_selector('em:contains("em tag")') - expect(doc).to have_selector('code:contains("code tag")') - expect(doc).to have_selector('kbd:contains("s")') - expect(doc).to have_selector('strike:contains(Emoji)') - expect(doc).to have_selector('img[src*="smile.png"]') - expect(doc).to have_selector('br') - expect(doc).to have_selector('hr') + aggregate_failures do + expect(doc).to have_selector('b:contains("b tag")') + expect(doc).to have_selector('em:contains("em tag")') + expect(doc).to have_selector('code:contains("code tag")') + expect(doc).to have_selector('kbd:contains("s")') + expect(doc).to have_selector('strike:contains(Emoji)') + expect(doc).to have_selector('img[src*="smile.png"]') + expect(doc).to have_selector('br') + expect(doc).to have_selector('hr') + end end it 'permits span elements' do @@ -132,13 +142,15 @@ describe 'GitLab Markdown', feature: true do end it 'permits table alignment' do - expect(doc.at_css('th:contains("Header")')['style']).to eq 'text-align: center' - expect(doc.at_css('th:contains("Row")')['style']).to eq 'text-align: right' - expect(doc.at_css('th:contains("Example")')['style']).to eq 'text-align: left' + aggregate_failures do + expect(doc.at_css('th:contains("Header")')['style']).to eq 'text-align: center' + expect(doc.at_css('th:contains("Row")')['style']).to eq 'text-align: right' + expect(doc.at_css('th:contains("Example")')['style']).to eq 'text-align: left' - expect(doc.at_css('td:contains("Foo")')['style']).to eq 'text-align: center' - expect(doc.at_css('td:contains("Bar")')['style']).to eq 'text-align: right' - expect(doc.at_css('td:contains("Baz")')['style']).to eq 'text-align: left' + expect(doc.at_css('td:contains("Foo")')['style']).to eq 'text-align: center' + expect(doc.at_css('td:contains("Bar")')['style']).to eq 'text-align: right' + expect(doc.at_css('td:contains("Baz")')['style']).to eq 'text-align: left' + end end it 'removes `rel` attribute from links' do @@ -161,14 +173,16 @@ describe 'GitLab Markdown', feature: true do describe 'Edge Cases' do it 'allows markup inside link elements' do - expect(doc.at_css('a[href="#link-emphasis"]').to_html). - to eq %{text} + aggregate_failures do + expect(doc.at_css('a[href="#link-emphasis"]').to_html). + to eq %{text} - expect(doc.at_css('a[href="#link-strong"]').to_html). - to eq %{text} + expect(doc.at_css('a[href="#link-strong"]').to_html). + to eq %{text} - expect(doc.at_css('a[href="#link-code"]').to_html). - to eq %{text} + expect(doc.at_css('a[href="#link-code"]').to_html). + to eq %{text} + end end end @@ -180,9 +194,11 @@ describe 'GitLab Markdown', feature: true do describe 'TableOfContentsFilter' do it 'creates anchors inside header elements' do - expect(doc).to have_selector('h1 a#gitlab-markdown') - expect(doc).to have_selector('h2 a#markdown') - expect(doc).to have_selector('h3 a#autolinkfilter') + aggregate_failures do + expect(doc).to have_selector('h1 a#gitlab-markdown') + expect(doc).to have_selector('h2 a#markdown') + expect(doc).to have_selector('h3 a#autolinkfilter') + end end end @@ -290,9 +306,12 @@ describe 'GitLab Markdown', feature: true do describe 'Task Lists' do it 'generates task lists' do body = get_section('task-lists') - expect(body).to have_selector('ul.task-list', count: 2) - expect(body).to have_selector('li.task-list-item', count: 7) - expect(body).to have_selector('input[checked]', count: 3) + + aggregate_failures do + expect(body).to have_selector('ul.task-list', count: 2) + expect(body).to have_selector('li.task-list-item', count: 7) + expect(body).to have_selector('input[checked]', count: 3) + end end end end From 97cedc5d1b023af56c035cccc5914d11bf6299de Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Mon, 20 Jul 2015 23:57:26 -0400 Subject: [PATCH 126/174] Break up SanitizationFilter feature specs --- spec/features/markdown_spec.rb | 53 ++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/spec/features/markdown_spec.rb b/spec/features/markdown_spec.rb index dadb1c3589f..5adf19980dd 100644 --- a/spec/features/markdown_spec.rb +++ b/spec/features/markdown_spec.rb @@ -124,29 +124,52 @@ describe 'GitLab Markdown', feature: true do describe 'HTML::Pipeline' do describe 'SanitizationFilter' do - it 'uses a permissive whitelist' do - aggregate_failures do - expect(doc).to have_selector('b:contains("b tag")') - expect(doc).to have_selector('em:contains("em tag")') - expect(doc).to have_selector('code:contains("code tag")') - expect(doc).to have_selector('kbd:contains("s")') - expect(doc).to have_selector('strike:contains(Emoji)') - expect(doc).to have_selector('img[src*="smile.png"]') - expect(doc).to have_selector('br') - expect(doc).to have_selector('hr') - end + it 'permits b elements' do + expect(doc).to have_selector('b:contains("b tag")') + end + + it 'permits em elements' do + expect(doc).to have_selector('em:contains("em tag")') + end + + it 'permits code elements' do + expect(doc).to have_selector('code:contains("code tag")') + end + + it 'permits kbd elements' do + expect(doc).to have_selector('kbd:contains("s")') + end + + it 'permits strike elements' do + expect(doc).to have_selector('strike:contains(Emoji)') + end + + it 'permits img elements' do + expect(doc).to have_selector('img[src*="smile.png"]') + end + + it 'permits br elements' do + expect(doc).to have_selector('br') + end + + it 'permits hr elements' do + expect(doc).to have_selector('hr') end it 'permits span elements' do expect(doc).to have_selector('span:contains("span tag")') end - it 'permits table alignment' do + it 'permits style attribute in th elements' do aggregate_failures do expect(doc.at_css('th:contains("Header")')['style']).to eq 'text-align: center' expect(doc.at_css('th:contains("Row")')['style']).to eq 'text-align: right' expect(doc.at_css('th:contains("Example")')['style']).to eq 'text-align: left' + end + end + it 'permits style attribute in td elements' do + aggregate_failures do expect(doc.at_css('td:contains("Foo")')['style']).to eq 'text-align: center' expect(doc.at_css('td:contains("Bar")')['style']).to eq 'text-align: right' expect(doc.at_css('td:contains("Baz")')['style']).to eq 'text-align: left' @@ -154,8 +177,7 @@ describe 'GitLab Markdown', feature: true do end it 'removes `rel` attribute from links' do - body = get_section('sanitizationfilter') - expect(body).not_to have_selector('a[rel="bookmark"]') + expect(doc).not_to have_selector('a[rel="bookmark"]') end it "removes `href` from `a` elements if it's fishy" do @@ -164,9 +186,8 @@ describe 'GitLab Markdown', feature: true do end describe 'Escaping' do - let(:table) { doc.css('table').last.at_css('tbody') } - it 'escapes non-tag angle brackets' do + table = doc.css('table').last.at_css('tbody') expect(table.at_xpath('.//tr[1]/td[3]').inner_html).to eq '1 < 3 & 5' end end From b07df8b1b05117352bc77fd4be0227dc588255fe Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 21 Jul 2015 00:21:51 -0400 Subject: [PATCH 127/174] Make links inside ignored elements unique This is to prevent false matches since the Autolink section uses about.gitlab.com as well. --- spec/fixtures/markdown.md.erb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/fixtures/markdown.md.erb b/spec/fixtures/markdown.md.erb index 02ab46c905a..75f6528ccdf 100644 --- a/spec/fixtures/markdown.md.erb +++ b/spec/fixtures/markdown.md.erb @@ -123,9 +123,9 @@ These are all plain text that should get turned into links: But it shouldn't autolink text inside certain tags: -- http://about.gitlab.com/ -- http://about.gitlab.com/ -- http://about.gitlab.com/ +- http://code.gitlab.com/ +- http://a.gitlab.com/ +- http://kbd.gitlab.com/ ### ExternalLinkFilter From 590fca0f06c4a21dbac90480bc6622f4da97dc86 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 21 Jul 2015 00:23:27 -0400 Subject: [PATCH 128/174] Move MarkdownFeature to its own support file This file's about to get much bigger and this removes some of the extra noise. --- spec/features/markdown_spec.rb | 115 ------------------------------- spec/support/markdown_feature.rb | 114 ++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+), 115 deletions(-) create mode 100644 spec/support/markdown_feature.rb diff --git a/spec/features/markdown_spec.rb b/spec/features/markdown_spec.rb index 5adf19980dd..46814fdfb8e 100644 --- a/spec/features/markdown_spec.rb +++ b/spec/features/markdown_spec.rb @@ -346,118 +346,3 @@ describe 'GitLab Markdown', feature: true do :white end end - -# This is a helper class used by the GitLab Markdown feature spec -# -# Because the feature spec only cares about the output of the Markdown, and the -# test setup and teardown and parsing is fairly expensive, we only want to do it -# once. Unfortunately RSpec will not let you access `let`s in a `before(:all)` -# block, so we fake it by encapsulating all the shared setup in this class. -# -# The class renders `spec/fixtures/markdown.md.erb` using ERB, allowing for -# reference to the factory-created objects. -class MarkdownFeature - include FactoryGirl::Syntax::Methods - - def initialize - DatabaseCleaner.start - end - - def teardown - DatabaseCleaner.clean - end - - def user - @user ||= create(:user) - end - - def group - unless @group - @group = create(:group) - @group.add_user(user, Gitlab::Access::DEVELOPER) - end - - @group - end - - # Direct references ---------------------------------------------------------- - - def project - @project ||= create(:project) - end - - def issue - @issue ||= create(:issue, project: project) - end - - def merge_request - @merge_request ||= create(:merge_request, :simple, source_project: project) - end - - def snippet - @snippet ||= create(:project_snippet, project: project) - end - - def commit - @commit ||= project.commit - end - - def commit_range - unless @commit_range - commit2 = project.commit('HEAD~3') - @commit_range = CommitRange.new("#{commit.id}...#{commit2.id}", project) - end - - @commit_range - end - - def simple_label - @simple_label ||= create(:label, name: 'gfm', project: project) - end - - def label - @label ||= create(:label, name: 'awaiting feedback', project: project) - end - - # Cross-references ----------------------------------------------------------- - - def xproject - unless @xproject - namespace = create(:namespace, name: 'cross-reference') - @xproject = create(:project, namespace: namespace) - @xproject.team << [user, :developer] - end - - @xproject - end - - def xissue - @xissue ||= create(:issue, project: xproject) - end - - def xmerge_request - @xmerge_request ||= create(:merge_request, :simple, source_project: xproject) - end - - def xsnippet - @xsnippet ||= create(:project_snippet, project: xproject) - end - - def xcommit - @xcommit ||= xproject.commit - end - - def xcommit_range - unless @xcommit_range - xcommit2 = xproject.commit('HEAD~2') - @xcommit_range = CommitRange.new("#{xcommit.id}...#{xcommit2.id}", xproject) - end - - @xcommit_range - end - - def raw_markdown - fixture = Rails.root.join('spec/fixtures/markdown.md.erb') - ERB.new(File.read(fixture)).result(binding) - end -end diff --git a/spec/support/markdown_feature.rb b/spec/support/markdown_feature.rb new file mode 100644 index 00000000000..5e18ffa4143 --- /dev/null +++ b/spec/support/markdown_feature.rb @@ -0,0 +1,114 @@ +# This is a helper class used by the GitLab Markdown feature spec +# +# Because the feature spec only cares about the output of the Markdown, and the +# test setup and teardown and parsing is fairly expensive, we only want to do it +# once. Unfortunately RSpec will not let you access `let`s in a `before(:all)` +# block, so we fake it by encapsulating all the shared setup in this class. +# +# The class renders `spec/fixtures/markdown.md.erb` using ERB, allowing for +# reference to the factory-created objects. +class MarkdownFeature + include FactoryGirl::Syntax::Methods + + def initialize + DatabaseCleaner.start + end + + def teardown + DatabaseCleaner.clean + end + + def user + @user ||= create(:user) + end + + def group + unless @group + @group = create(:group) + @group.add_user(user, Gitlab::Access::DEVELOPER) + end + + @group + end + + # Direct references ---------------------------------------------------------- + + def project + @project ||= create(:project) + end + + def issue + @issue ||= create(:issue, project: project) + end + + def merge_request + @merge_request ||= create(:merge_request, :simple, source_project: project) + end + + def snippet + @snippet ||= create(:project_snippet, project: project) + end + + def commit + @commit ||= project.commit + end + + def commit_range + unless @commit_range + commit2 = project.commit('HEAD~3') + @commit_range = CommitRange.new("#{commit.id}...#{commit2.id}", project) + end + + @commit_range + end + + def simple_label + @simple_label ||= create(:label, name: 'gfm', project: project) + end + + def label + @label ||= create(:label, name: 'awaiting feedback', project: project) + end + + # Cross-references ----------------------------------------------------------- + + def xproject + unless @xproject + namespace = create(:namespace, name: 'cross-reference') + @xproject = create(:project, namespace: namespace) + @xproject.team << [user, :developer] + end + + @xproject + end + + def xissue + @xissue ||= create(:issue, project: xproject) + end + + def xmerge_request + @xmerge_request ||= create(:merge_request, :simple, source_project: xproject) + end + + def xsnippet + @xsnippet ||= create(:project_snippet, project: xproject) + end + + def xcommit + @xcommit ||= xproject.commit + end + + def xcommit_range + unless @xcommit_range + xcommit2 = xproject.commit('HEAD~2') + @xcommit_range = CommitRange.new("#{xcommit.id}...#{xcommit2.id}", xproject) + end + + @xcommit_range + end + + def raw_markdown + fixture = Rails.root.join('spec/fixtures/markdown.md.erb') + ERB.new(File.read(fixture)).result(binding) + end +end From 0673ca36812ac3f709032938b77e5ab6e1d63885 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 22 Jul 2015 21:22:16 -0400 Subject: [PATCH 129/174] Add RelativeLinkFilter section to Markdown fixture --- spec/fixtures/markdown.md.erb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/spec/fixtures/markdown.md.erb b/spec/fixtures/markdown.md.erb index 75f6528ccdf..41d12afa9ce 100644 --- a/spec/fixtures/markdown.md.erb +++ b/spec/fixtures/markdown.md.erb @@ -100,6 +100,13 @@ Markdown should be usable inside a link. Let's try! - [**text**](#link-strong) - [`text`](#link-code) +### RelativeLinkFilter + +Linking to a file relative to this project's repository should work. + +[Relative Link](doc/README.md) +![Relative Image](app/assets/images/touch-icon-ipad.png) + ### EmojiFilter Because life would be :zzz: without Emoji, right? :rocket: From 05f9a6a9c44c094d281d3dc8d80eb30c4e7dff27 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 22 Jul 2015 21:22:57 -0400 Subject: [PATCH 130/174] Update Markdown feature to allow for multiple pipelines --- spec/features/markdown_spec.rb | 238 ++++++--------------- spec/support/matchers/markdown_matchers.rb | 156 ++++++++++++++ 2 files changed, 220 insertions(+), 174 deletions(-) create mode 100644 spec/support/matchers/markdown_matchers.rb diff --git a/spec/features/markdown_spec.rb b/spec/features/markdown_spec.rb index 46814fdfb8e..ddef2317e1c 100644 --- a/spec/features/markdown_spec.rb +++ b/spec/features/markdown_spec.rb @@ -17,16 +17,8 @@ require 'erb' # -> Post-process HTML # -> `gfm_with_options` helper # -> HTML::Pipeline -# -> Sanitize -# -> RelativeLink -# -> Emoji -# -> Table of Contents -# -> Autolinks -# -> Rinku (http, https, ftp) -# -> Other schemes -# -> ExternalLink -# -> References -# -> TaskList +# -> SanitizationFilter +# -> Other filters, depending on pipeline # -> `html_safe` # -> Template # @@ -35,6 +27,7 @@ require 'erb' describe 'GitLab Markdown', feature: true do include Capybara::Node::Matchers include GitlabMarkdownHelper + include MarkdownMatchers # Let's only parse this thing once before(:all) do @@ -42,50 +35,37 @@ describe 'GitLab Markdown', feature: true do # `gfm_with_options` depends on a `@project` variable @project = @feat.project - - @html = markdown(@feat.raw_markdown) end after(:all) do @feat.teardown end - def doc - @doc ||= Nokogiri::HTML::DocumentFragment.parse(@html) - end - - # Given a header ID, goes to that element's parent (the header itself), then - # its next sibling element (the body). - def get_section(id) - doc.at_css("##{id}").parent.next_element + def doc(html = @html) + Nokogiri::HTML::DocumentFragment.parse(html) end # Sometimes it can be useful to see the parsed output of the Markdown document - # for debugging. Uncomment this block to write the output to - # tmp/capybara/markdown_spec.html. - # - # it 'writes to a file' do - # File.open(Rails.root.join('tmp/capybara/markdown_spec.html'), 'w') do |file| - # file.puts @html - # end - # end - - describe 'Redcarpet extensions' do - describe 'No Intra Emphasis' do - it 'does not parse emphasis inside of words' do - body = get_section('no-intra-emphasis') - expect(body.to_html).not_to match('foobarbaz') - end + # for debugging. Call this method to write the output to + # `tmp/capybara/.html`. + def write_markdown(filename = 'markdown_spec') + File.open(Rails.root.join("tmp/capybara/#{filename}.html"), 'w') do |file| + file.puts @html end + end + + # Shared behavior that all pipelines should exhibit + shared_examples 'all pipelines' do + describe 'Redcarpet extensions' do + it 'does not parse emphasis inside of words' do + expect(doc.to_html).not_to match('foobarbaz') + end - describe 'Tables' do it 'parses table Markdown' do - body = get_section('tables') - aggregate_failures do - expect(body).to have_selector('th:contains("Header")') - expect(body).to have_selector('th:contains("Row")') - expect(body).to have_selector('th:contains("Example")') + expect(doc).to have_selector('th:contains("Header")') + expect(doc).to have_selector('th:contains("Row")') + expect(doc).to have_selector('th:contains("Example")') end end @@ -93,36 +73,23 @@ describe 'GitLab Markdown', feature: true do expect(doc.at_css('td:contains("Baz")').children.to_html). to eq 'Baz' end - end - describe 'Fenced Code Blocks' do it 'parses fenced code blocks' do aggregate_failures do expect(doc).to have_selector('pre.code.highlight.white.c') expect(doc).to have_selector('pre.code.highlight.white.python') end end - end - describe 'Strikethrough' do it 'parses strikethroughs' do expect(doc).to have_selector(%{del:contains("and this text doesn't")}) end - end - describe 'Superscript' do it 'parses superscript' do - body = get_section('superscript') - - aggregate_failures do - expect(body.to_html).to match('1st') - expect(body.to_html).to match('2nd') - end + expect(doc).to have_selector('sup', count: 2) end end - end - describe 'HTML::Pipeline' do describe 'SanitizationFilter' do it 'permits b elements' do expect(doc).to have_selector('b:contains("b tag")') @@ -207,133 +174,56 @@ describe 'GitLab Markdown', feature: true do end end - describe 'EmojiFilter' do - it 'parses Emoji' do - expect(doc).to have_selector('img.emoji', count: 10) - end - end - - describe 'TableOfContentsFilter' do - it 'creates anchors inside header elements' do - aggregate_failures do - expect(doc).to have_selector('h1 a#gitlab-markdown') - expect(doc).to have_selector('h2 a#markdown') - expect(doc).to have_selector('h3 a#autolinkfilter') - end - end - end - - describe 'AutolinkFilter' do - def body - get_section('autolinkfilter').next_element - end - - # Override Capybara's `have_link` matcher to simplify our use case - def have_link(link) - super(link, href: link) - end - - it 'autolinks http://' do - expect(body).to have_link('http://about.gitlab.com/') - end - - it 'autolinks https://' do - expect(body).to have_link('https://google.com/') - end - - it 'autolinks ftp://' do - expect(body).to have_link('ftp://ftp.us.debian.org/debian/') - end - - it 'autolinks smb://' do - expect(body).to have_link('smb://foo/bar/baz') - end - - it 'autolinks irc://' do - expect(body).to have_link('irc://irc.freenode.net/git') - end - - it 'autolinks short, invalid URLs' do - expect(body).to have_link('http://localhost:3000') - end - - %w(code a kbd).each do |elem| - it "ignores links inside '#{elem}' element" do - expect(body).not_to have_selector("#{elem} a") - end - end - end - describe 'ExternalLinkFilter' do - let(:links) { get_section('externallinkfilter').next_element } - it 'adds nofollow to external link' do - expect(links.css('a').first.to_html).to match 'nofollow' + link = doc.at_css('a:contains("Google")') + expect(link.attr('rel')).to match 'nofollow' end it 'ignores internal link' do - expect(links.css('a').last.to_html).not_to match 'nofollow' + link = doc.at_css('a:contains("GitLab Root")') + expect(link.attr('rel')).not_to match 'nofollow' + end + end + end + + context 'default pipeline' do + before(:all) do + @html = markdown(@feat.raw_markdown) + end + + it_behaves_like 'all pipelines' + + it 'includes RelativeLinkFilter' do + expect(doc).to parse_relative_links + end + + it 'includes EmojiFilter' do + expect(doc).to parse_emoji + end + + it 'includes TableOfContentsFilter' do + expect(doc).to create_header_links + end + + it 'includes AutolinkFilter' do + expect(doc).to create_autolinks + end + + it 'includes all reference filters' do + aggregate_failures do + expect(doc).to reference_users + expect(doc).to reference_issues + expect(doc).to reference_merge_requests + expect(doc).to reference_snippets + expect(doc).to reference_commit_ranges + expect(doc).to reference_commits + expect(doc).to reference_labels end end - describe 'ReferenceFilter' do - it 'handles references in headers' do - header = doc.at_css('#reference-filters-eg-1').parent - - expect(header.css('a').size).to eq 2 - end - - it "handles references in Markdown" do - body = get_section('reference-filters-eg-1') - expect(body).to have_selector('em a.gfm-merge_request', count: 1) - end - - it 'parses user references' do - body = get_section('userreferencefilter') - expect(body).to have_selector('a.gfm.gfm-project_member', count: 3) - end - - it 'parses issue references' do - body = get_section('issuereferencefilter') - expect(body).to have_selector('a.gfm.gfm-issue', count: 2) - end - - it 'parses merge request references' do - body = get_section('mergerequestreferencefilter') - expect(body).to have_selector('a.gfm.gfm-merge_request', count: 2) - end - - it 'parses snippet references' do - body = get_section('snippetreferencefilter') - expect(body).to have_selector('a.gfm.gfm-snippet', count: 2) - end - - it 'parses commit range references' do - body = get_section('commitrangereferencefilter') - expect(body).to have_selector('a.gfm.gfm-commit_range', count: 2) - end - - it 'parses commit references' do - body = get_section('commitreferencefilter') - expect(body).to have_selector('a.gfm.gfm-commit', count: 2) - end - - it 'parses label references' do - body = get_section('labelreferencefilter') - expect(body).to have_selector('a.gfm.gfm-label', count: 3) - end - end - - describe 'Task Lists' do - it 'generates task lists' do - body = get_section('task-lists') - - aggregate_failures do - expect(body).to have_selector('ul.task-list', count: 2) - expect(body).to have_selector('li.task-list-item', count: 7) - expect(body).to have_selector('input[checked]', count: 3) - end - end + it 'includes TaskListFilter' do + expect(doc).to parse_task_lists end end diff --git a/spec/support/matchers/markdown_matchers.rb b/spec/support/matchers/markdown_matchers.rb new file mode 100644 index 00000000000..9df226c3af8 --- /dev/null +++ b/spec/support/matchers/markdown_matchers.rb @@ -0,0 +1,156 @@ +# MarkdownMatchers +# +# Custom matchers for our custom HTML::Pipeline filters. These are used to test +# that specific filters are or are not used by our defined pipelines. +# +# Must be included manually. +module MarkdownMatchers + extend RSpec::Matchers::DSL + include Capybara::Node::Matchers + + # RelativeLinkFilter + matcher :parse_relative_links do + set_default_markdown_messages + + match do |actual| + link = actual.at_css('a:contains("Relative Link")') + image = actual.at_css('img[alt="Relative Image"]') + + expect(link['href']).to end_with('master/doc/README.md') + expect(image['src']).to end_with('master/app/assets/images/touch-icon-ipad.png') + end + end + + # EmojiFilter + matcher :parse_emoji do + set_default_markdown_messages + + match do |actual| + expect(actual).to have_selector('img.emoji', count: 10) + end + end + + # TableOfContentsFilter + matcher :create_header_links do + set_default_markdown_messages + + match do |actual| + expect(actual).to have_selector('h1 a#gitlab-markdown') + expect(actual).to have_selector('h2 a#markdown') + expect(actual).to have_selector('h3 a#autolinkfilter') + end + end + + # AutolinkFilter + matcher :create_autolinks do + def have_autolink(link) + have_link(link, href: link) + end + + set_default_markdown_messages + + match do |actual| + expect(actual).to have_autolink('http://about.gitlab.com/') + expect(actual).to have_autolink('https://google.com/') + expect(actual).to have_autolink('ftp://ftp.us.debian.org/debian/') + expect(actual).to have_autolink('smb://foo/bar/baz') + expect(actual).to have_autolink('irc://irc.freenode.net/git') + expect(actual).to have_autolink('http://localhost:3000') + + %w(code a kbd).each do |elem| + expect(body).not_to have_selector("#{elem} a") + end + end + end + + # UserReferenceFilter + matcher :reference_users do + set_default_markdown_messages + + match do |actual| + expect(actual).to have_selector('a.gfm.gfm-project_member', count: 3) + end + end + + # IssueReferenceFilter + matcher :reference_issues do + set_default_markdown_messages + + match do |actual| + expect(actual).to have_selector('a.gfm.gfm-issue', count: 3) + end + end + + # MergeRequestReferenceFilter + matcher :reference_merge_requests do + set_default_markdown_messages + + match do |actual| + expect(actual).to have_selector('a.gfm.gfm-merge_request', count: 3) + expect(actual).to have_selector('em a.gfm-merge_request') + end + end + + # SnippetReferenceFilter + matcher :reference_snippets do + set_default_markdown_messages + + match do |actual| + expect(actual).to have_selector('a.gfm.gfm-snippet', count: 2) + end + end + + # CommitRangeReferenceFilter + matcher :reference_commit_ranges do + set_default_markdown_messages + + match do |actual| + expect(actual).to have_selector('a.gfm.gfm-commit_range', count: 2) + end + end + + # CommitReferenceFilter + matcher :reference_commits do + set_default_markdown_messages + + match do |actual| + expect(actual).to have_selector('a.gfm.gfm-commit', count: 2) + end + end + + # LabelReferenceFilter + matcher :reference_labels do + set_default_markdown_messages + + match do |actual| + expect(actual).to have_selector('a.gfm.gfm-label', count: 3) + end + end + + # TaskListFilter + matcher :parse_task_lists do + set_default_markdown_messages + + match do |actual| + expect(actual).to have_selector('ul.task-list', count: 2) + expect(actual).to have_selector('li.task-list-item', count: 7) + expect(actual).to have_selector('input[checked]', count: 3) + end + end +end + +# Monkeypatch the matcher DSL so that we can reduce some noisy duplication for +# setting the failure messages for these matchers +module RSpec::Matchers::DSL::Macros + def set_default_markdown_messages + failure_message do + # expected to parse emoji, but didn't + "expected to #{description}, but didn't" + end + + failure_message_when_negated do + # expected not to parse task lists, but did + "expected not to #{description}, but did" + end + end +end From 8c957b54f5a70d07a0c70f15c84cdf9fc7eb0f23 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 28 Jul 2015 23:27:08 -0400 Subject: [PATCH 131/174] Fix setup/teardown for Markdown feature spec Prior, CI seemed to be freezing after running these specs. --- spec/features/markdown_spec.rb | 25 +++++++++---------------- spec/support/markdown_feature.rb | 8 -------- 2 files changed, 9 insertions(+), 24 deletions(-) diff --git a/spec/features/markdown_spec.rb b/spec/features/markdown_spec.rb index ddef2317e1c..859a62f740f 100644 --- a/spec/features/markdown_spec.rb +++ b/spec/features/markdown_spec.rb @@ -29,22 +29,6 @@ describe 'GitLab Markdown', feature: true do include GitlabMarkdownHelper include MarkdownMatchers - # Let's only parse this thing once - before(:all) do - @feat = MarkdownFeature.new - - # `gfm_with_options` depends on a `@project` variable - @project = @feat.project - end - - after(:all) do - @feat.teardown - end - - def doc(html = @html) - Nokogiri::HTML::DocumentFragment.parse(html) - end - # Sometimes it can be useful to see the parsed output of the Markdown document # for debugging. Call this method to write the output to # `tmp/capybara/.html`. @@ -54,6 +38,10 @@ describe 'GitLab Markdown', feature: true do end end + def doc(html = @html) + Nokogiri::HTML::DocumentFragment.parse(html) + end + # Shared behavior that all pipelines should exhibit shared_examples 'all pipelines' do describe 'Redcarpet extensions' do @@ -189,6 +177,11 @@ describe 'GitLab Markdown', feature: true do context 'default pipeline' do before(:all) do + @feat = MarkdownFeature.new + + # `gfm_with_options` depends on a `@project` variable + @project = @feat.project + @html = markdown(@feat.raw_markdown) end diff --git a/spec/support/markdown_feature.rb b/spec/support/markdown_feature.rb index 5e18ffa4143..2a868aed73b 100644 --- a/spec/support/markdown_feature.rb +++ b/spec/support/markdown_feature.rb @@ -10,14 +10,6 @@ class MarkdownFeature include FactoryGirl::Syntax::Methods - def initialize - DatabaseCleaner.start - end - - def teardown - DatabaseCleaner.clean - end - def user @user ||= create(:user) end From f736721c5bb8f1f6031d36cc726cbd11cc499a72 Mon Sep 17 00:00:00 2001 From: Stefan Tatschner Date: Sun, 28 Jun 2015 20:45:40 +0200 Subject: [PATCH 132/174] Replace Rugments with Rouge I have mainly created the rugments fork for the purpose of improving gitlab's highlighting. Nowadays IMO it works way better than the old highlight.js solution. But the development is stuck on my side because of a couple of personal reasons: * I have finished my studies; last months I was writing my master thesis. So there was a huge time problem. I am sorry for that. * I had to move to Munich due to getting a (paid) job. Searching a flat here is horrible... :) * Last but not least, maintaining the same code base in two seperate projects is a mess. I have decided to switch back to rouge due to several reasons: * In the beginning I was quite motivated, but since I start working on my new job next week, the best solution IMO is switching back to upstream rouge. * Rouge is continously improving: https://github.com/jneen/rouge/blob/master/CHANGELOG.md http://rouge.jneen.net/ * There should be absolutely no regressions with this change. Most likely this pull request will almost fix some minor bugs. * One less gem in gitlab is a good thing. since Gitlab is quite a huge bundle of gems. Reducing complexity should be a major milestone. Thanks a lot to @stanhu and @jneen for the review! --- Gemfile | 1 - Gemfile.lock | 2 -- app/helpers/blob_helper.rb | 8 ++++---- app/helpers/emails_helper.rb | 4 ++-- lib/redcarpet/render/gitlab_html.rb | 8 ++++---- 5 files changed, 10 insertions(+), 13 deletions(-) diff --git a/Gemfile b/Gemfile index 8552e731bbd..1c49a603798 100644 --- a/Gemfile +++ b/Gemfile @@ -272,4 +272,3 @@ end gem "newrelic_rpm" gem 'octokit', '3.7.0' -gem "rugments", "~> 1.0.0.beta8" diff --git a/Gemfile.lock b/Gemfile.lock index bef67884c37..f5c547f024a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -579,7 +579,6 @@ GEM rubyntlm (0.5.0) rubypants (0.2.0) rugged (0.22.2) - rugments (1.0.0.beta8) safe_yaml (1.0.4) sanitize (2.1.0) nokogiri (>= 1.4.4) @@ -836,7 +835,6 @@ DEPENDENCIES rqrcode-rails3 rspec-rails (~> 3.3.0) rubocop (= 0.28.0) - rugments (~> 1.0.0.beta8) sanitize (~> 2.0) sass-rails (~> 4.0.5) sdoc diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index 50df3801703..f6263818055 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -1,6 +1,6 @@ module BlobHelper def highlight(blob_name, blob_content, nowrap: false, continue: false) - @formatter ||= Rugments::Formatters::HTML.new( + @formatter ||= Rouge::Formatters::HTMLGitlab.new( nowrap: nowrap, cssclass: 'code highlight', lineanchors: true, @@ -8,11 +8,11 @@ module BlobHelper ) begin - @lexer ||= Rugments::Lexer.guess(filename: blob_name, source: blob_content).new + @lexer ||= Rouge::Lexer.guess(filename: blob_name, source: blob_content) result = @formatter.format(@lexer.lex(blob_content, continue: continue)).html_safe rescue - lexer = Rugments::Lexers::PlainText - result = @formatter.format(lexer.lex(blob_content)).html_safe + @lexer = Rouge::Lexers::PlainText + result = @formatter.format(@lexer.lex(blob_content)).html_safe end result diff --git a/app/helpers/emails_helper.rb b/app/helpers/emails_helper.rb index 128de18bc47..45788ba95ac 100644 --- a/app/helpers/emails_helper.rb +++ b/app/helpers/emails_helper.rb @@ -31,8 +31,8 @@ module EmailsHelper end def color_email_diff(diffcontent) - formatter = Rugments::Formatters::HTML.new(cssclass: "highlight", inline_theme: :github) - lexer = Rugments::Lexers::Diff.new + formatter = Rouge::Formatters::HTML.new(css_class: 'highlight', inline_theme: 'github') + lexer = Rouge::Lexers::Diff raw formatter.format(lexer.lex(diffcontent)) end diff --git a/lib/redcarpet/render/gitlab_html.rb b/lib/redcarpet/render/gitlab_html.rb index 2f7aff03c2a..04440e4f68d 100644 --- a/lib/redcarpet/render/gitlab_html.rb +++ b/lib/redcarpet/render/gitlab_html.rb @@ -22,10 +22,10 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML ERB::Util.html_escape_once(text) end - # Stolen from Rugments::Plugins::Redcarpet as this module is not required - # from Rugments's gem root. + # Stolen from Rouge::Plugins::Redcarpet as this module is not required + # from Rouge's gem root. def block_code(code, language) - lexer = Rugments::Lexer.find_fancy(language, code) || Rugments::Lexers::PlainText + lexer = Rouge::Lexer.find_fancy(language, code) || Rouge::Lexers::PlainText # XXX HACK: Redcarpet strips hard tabs out of code blocks, # so we assume you're not using leading spaces that aren't tabs, @@ -34,7 +34,7 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML code.gsub!(/^ /, "\t") end - formatter = Rugments::Formatters::HTML.new( + formatter = Rouge::Formatters::HTMLGitlab.new( cssclass: "code highlight #{@color_scheme} #{lexer.tag}" ) formatter.format(lexer.lex(code)) From 00ff84d3c02e551cb7c4be3f71e1836e9f5abce2 Mon Sep 17 00:00:00 2001 From: Stefan Tatschner Date: Sun, 28 Jun 2015 20:42:41 +0200 Subject: [PATCH 133/174] Add HTMLGitlab formatter This custom formatter for rouge is needed to generate HTML output specifically for gitlab. Since its usecase is mostly suitable for gitlab it had been rejected upstream: https://github.com/jneen/rouge/pull/268 Thanks a lot to @stanhu, @jneen and @tsigo for review! --- app/helpers/blob_helper.rb | 2 +- lib/rouge/formatters/html_gitlab.rb | 168 ++++++++++++++++++++++++++++ 2 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 lib/rouge/formatters/html_gitlab.rb diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index f6263818055..77d99140c43 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -8,7 +8,7 @@ module BlobHelper ) begin - @lexer ||= Rouge::Lexer.guess(filename: blob_name, source: blob_content) + @lexer ||= Rouge::Lexer.guess(filename: blob_name, source: blob_content).new result = @formatter.format(@lexer.lex(blob_content, continue: continue)).html_safe rescue @lexer = Rouge::Lexers::PlainText diff --git a/lib/rouge/formatters/html_gitlab.rb b/lib/rouge/formatters/html_gitlab.rb new file mode 100644 index 00000000000..485af6832d7 --- /dev/null +++ b/lib/rouge/formatters/html_gitlab.rb @@ -0,0 +1,168 @@ +require 'cgi' + +module Rouge + module Formatters + class HTMLGitlab < Rouge::Formatter + tag 'html_gitlab' + + # Creates a new Rouge::Formatter::HTMLGitlab instance. + # + # [+nowrap+] If set to True, don't wrap the output at all, not + # even inside a

 tag (default: false).
+      # [+cssclass+]        CSS class for the wrapping 
tag + # (default: 'highlight'). + # [+linenos+] If set to 'table', output line numbers as a table + # with two cells, one containing the line numbers, + # the other the whole code. This is copy paste friendly, + # but may cause alignment problems with some browsers + # or fonts. If set to 'inline', the line numbers will + # be integrated in the
 tag that contains
+      #                     the code (default: nil).
+      # [+linenostart+]     The line number for the first line (default: 1).
+      # [+lineanchors+]     If set to true the formatter will wrap each output
+      #                     line in an anchor tag with a name of L-linenumber.
+      #                     This allows easy linking to certain lines
+      #                     (default: false).
+      # [+lineanchorsid+]   If lineanchors is true the name of the anchors can
+      #                     be changed with lineanchorsid to e.g. foo-linenumber
+      #                     (default: 'L').
+      # [+anchorlinenos+]   If set to true, will wrap line numbers in 
+      #                     tags. Used in combination with linenos and lineanchors
+      #                     (default: false).
+      # [+inline_theme+]    Inline CSS styles for the 
 tag (default: false).
+      def initialize(
+          nowrap: false,
+          cssclass: 'highlight',
+          linenos: nil,
+          linenostart: 1,
+          lineanchors: false,
+          lineanchorsid: 'L',
+          anchorlinenos: false,
+          inline_theme: nil
+        )
+        @nowrap = nowrap
+        @cssclass = cssclass
+        @linenos = linenos
+        @linenostart = linenostart
+        @lineanchors = lineanchors
+        @lineanchorsid = lineanchorsid
+        @anchorlinenos = anchorlinenos
+        @inline_theme = Theme.find(@inline_theme).new if @inline_theme.is_a?(String)
+      end
+
+      def render(tokens)
+        case @linenos
+        when 'table'
+          render_tableized(tokens)
+        when 'inline'
+          render_untableized(tokens)
+        else
+          render_untableized(tokens)
+        end
+      end
+
+      alias_method :format, :render
+
+      private
+
+      def render_untableized(tokens)
+        data = process_tokens(tokens)
+
+        html = ''
+        html << "
" unless @nowrap
+        html << wrap_lines(data[:code])
+        html << "
\n" unless @nowrap + html + end + + def render_tableized(tokens) + data = process_tokens(tokens) + + html = '' + html << "
" unless @nowrap + html << '' + html << "' + html << "' + html << '
"
+        html << wrap_linenos(data[:numbers])
+        html << '
"
+        html << wrap_lines(data[:code])
+        html << '
' + html << '
' unless @nowrap + html + end + + def process_tokens(tokens) + num_lines = 0 + last_val = '' + rendered = '' + + tokens.each do |tok, val| + last_val = val + num_lines += val.scan(/\n/).size + rendered << span(tok, val) + end + + numbers = (@linenostart..num_lines + @linenostart - 1).to_a + + { numbers: numbers, code: rendered } + end + + def wrap_linenos(numbers) + if @anchorlinenos + numbers.map! do |number| + "
#{number}" + end + end + numbers.join("\n") + end + + def wrap_lines(rendered) + if @lineanchors + lines = rendered.split("\n") + lines = lines.each_with_index.map do |line, index| + number = index + @linenostart + + if @linenos == 'inline' + "" \ + "#{number}" \ + "#{line}" \ + '' + else + "#{line}" \ + '' + end + end + lines.join("\n") + else + if @linenos == 'inline' + lines = rendered.split("\n") + lines = lines.each_with_index.map do |line, index| + number = index + @linenostart + "#{number}#{line}" + end + lines.join("\n") + else + rendered + end + end + end + + def span(tok, val) + # http://stackoverflow.com/a/1600584/2587286 + val = CGI.escapeHTML(val) + + if tok.shortname.empty? + val + else + if @inline_theme + rules = @inline_theme.style_for(tok).rendered_rules + "#{val}" + else + "#{val}" + end + end + end + end + end +end From f2d4672b3803d52c7a0e58a80cd6a7e83f808ef6 Mon Sep 17 00:00:00 2001 From: Stefan Tatschner Date: Tue, 14 Jul 2015 19:10:16 +0200 Subject: [PATCH 134/174] Manually update rouge to 1.9.1 Since gollum-lib blocks rouge from updating, let's bump the version manually. The fix has already been accepted upstream: https://github.com/gollum/gollum-lib/commit/9c042ea0914a7714abbda9d89e234c8a79fba893 --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index f5c547f024a..44365017edc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -288,7 +288,7 @@ GEM github-markup (~> 1.3.1) gollum-grit_adapter (~> 0.1, >= 0.1.1) nokogiri (~> 1.6.4) - rouge (~> 1.7.4) + rouge (~> 1.9) sanitize (~> 2.1.0) stringex (~> 2.5.1) gon (5.0.1) @@ -536,7 +536,7 @@ GEM netrc (~> 0.7) rinku (1.7.3) rotp (1.6.1) - rouge (1.7.7) + rouge (1.9.1) rqrcode (0.4.2) rqrcode-rails3 (0.1.7) rqrcode (>= 0.4.2) From e72a9685f3298536568e885afb1d5dabd9b315c5 Mon Sep 17 00:00:00 2001 From: Daryl Chan Date: Sat, 25 Jul 2015 17:51:22 +0800 Subject: [PATCH 135/174] Added tags to disable autocapitalize and autocorrect on login field - Updated CHANGELOG --- CHANGELOG | 1 + app/views/devise/sessions/_new_base.html.haml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index b0811db1f7f..ec61759cd0c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -18,6 +18,7 @@ v 7.14.0 (unreleased) - Add support for destroying project milestones (Stan Hu) - Add fetch command to the MR page - Fix bug causing Bitbucket importer to crash when OAuth application had been removed. + - Disabled autocapitalize and autocorrect on login field (Daryl Chan) v 7.13.1 - Fix: Label modifications are not reflected in existing notes and in the issue list diff --git a/app/views/devise/sessions/_new_base.html.haml b/app/views/devise/sessions/_new_base.html.haml index 54a39726771..9f5520603cd 100644 --- a/app/views/devise/sessions/_new_base.html.haml +++ b/app/views/devise/sessions/_new_base.html.haml @@ -1,5 +1,5 @@ = form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| - = f.text_field :login, class: "form-control top", placeholder: "Username or Email", autofocus: "autofocus" + = f.text_field :login, class: "form-control top", placeholder: "Username or Email", autofocus: "autofocus", autocapitalize: "off", autocorrect: "off" = f.password_field :password, class: "form-control bottom", placeholder: "Password" - if devise_mapping.rememberable? .remember-me.checkbox From c5aae3077335ab0eaafb73f51548d4c85413a1d1 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Wed, 29 Jul 2015 11:18:55 +0200 Subject: [PATCH 136/174] Set internal backup directory modes on create This sidesteps problems with running 'chmod' on some CIFS mounts. --- lib/backup/database.rb | 2 +- lib/backup/manager.rb | 2 -- lib/backup/repository.rb | 2 +- lib/backup/uploads.rb | 2 +- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/backup/database.rb b/lib/backup/database.rb index c5a5396cbbf..8450019980f 100644 --- a/lib/backup/database.rb +++ b/lib/backup/database.rb @@ -7,7 +7,7 @@ module Backup def initialize @config = YAML.load_file(File.join(Rails.root,'config','database.yml'))[Rails.env] @db_dir = File.join(Gitlab.config.backup.path, 'db') - FileUtils.mkdir_p(@db_dir) unless Dir.exists?(@db_dir) + FileUtils.mkdir_p(@db_dir, mode: 0700)unless Dir.exists?(@db_dir) end def dump diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb index 6fa2079d1a8..9ae4b346436 100644 --- a/lib/backup/manager.rb +++ b/lib/backup/manager.rb @@ -16,8 +16,6 @@ module Backup file << s.to_yaml.gsub(/^---\n/,'') end - FileUtils.chmod(0700, folders_to_backup) - # create archive $progress.print "Creating backup archive: #{tar_file} ... " orig_umask = File.umask(0077) diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb index dfb2da9f84e..36d43d62982 100644 --- a/lib/backup/repository.rb +++ b/lib/backup/repository.rb @@ -130,7 +130,7 @@ module Backup def prepare FileUtils.rm_rf(backup_repos_path) - FileUtils.mkdir_p(backup_repos_path) + FileUtils.mkdir_p(backup_repos_path, mode: 0700) end def silent diff --git a/lib/backup/uploads.rb b/lib/backup/uploads.rb index bf43610acf6..ed445f79084 100644 --- a/lib/backup/uploads.rb +++ b/lib/backup/uploads.rb @@ -10,7 +10,7 @@ module Backup # Copy uploads from public/uploads to backup/uploads def dump - FileUtils.mkdir_p(backup_uploads_dir) + FileUtils.mkdir_p(backup_uploads_dir, mode: 0700) FileUtils.cp_r(app_uploads_dir, backup_dir) end From 545f389910f738e021e2fbc9b5a1e0bcca45b580 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Wed, 29 Jul 2015 12:10:10 +0300 Subject: [PATCH 137/174] update changelog --- CHANGELOG | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index b0811db1f7f..7ca450d423c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,8 +4,6 @@ v 7.14.0 (unreleased) - Upgrade gitlab_git to version 7.2.6 to fix Error 500 when creating network graphs (Stan Hu) - Fix URL used for refreshing notes if relative_url is present (Bartłomiej Święcki) - Fix commit data retrieval when branch name has single quotes (Stan Hu) - - Fix Error 500 when browsing projects with no HEAD (Stan Hu) - - Add rake task 'gitlab:update_commit_count' (Daniel Gerhardt) - Fix full screen mode for snippet comments (Daniel Gerhardt) - Fix 404 error in files view after deleting the last file in a repository (Stan Hu) - Fix the "Reload with full diff" URL button (Stan Hu) @@ -18,6 +16,17 @@ v 7.14.0 (unreleased) - Add support for destroying project milestones (Stan Hu) - Add fetch command to the MR page - Fix bug causing Bitbucket importer to crash when OAuth application had been removed. + - Add fetch command to the MR page. + +v 7.13.2 + - Fix randomly failed spec + - Create project services on Project creation + - Add admin_merge_request ability to Developer level and up + - Fix Error 500 when browsing projects with no HEAD (Stan Hu) + - Fix labels / assignee / milestone for the merge requests when issues are disabled + - Show the first tab automatically on MergeRequests#new + - Add rake task 'gitlab:update_commit_count' (Daniel Gerhardt) + - Fix Gmail Actions v 7.13.1 - Fix: Label modifications are not reflected in existing notes and in the issue list @@ -28,6 +37,7 @@ v 7.13.1 - Fix: ActionView::Template::Error - Fix: "Create Merge Request" isn't always shown in event for newly pushed branch - Fix bug causing "Remove source-branch" option not to work for merge requests from the same project. + - Render Note field hints consistently for "new" and "edit" forms v 7.13.0 - Remove repository graph log to fix slow cache updates after push event (Stan Hu) From 05cca9342b3cff4e9f2785a062822cd3af9fcdd4 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 29 Jul 2015 12:03:53 +0200 Subject: [PATCH 138/174] Use URL helpers --- app/models/group.rb | 4 ++-- app/models/project.rb | 2 +- app/models/user.rb | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/models/group.rb b/app/models/group.rb index adcbbec465e..885d3b1e5ab 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -17,7 +17,7 @@ require 'carrierwave/orm/activerecord' require 'file_size_validator' class Group < Namespace - include Gitlab::ConfigHelper + include Rails.application.routes.url_helpers include Referable has_many :group_members, dependent: :destroy, as: :source, class_name: 'GroupMember' @@ -64,7 +64,7 @@ class Group < Namespace end def web_url - [gitlab_config.url, "groups", self.path].join('/') + group_url(self) end def owners diff --git a/app/models/project.rb b/app/models/project.rb index ff372ea9aa5..0608133b2cb 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -316,7 +316,7 @@ class Project < ActiveRecord::Base end def web_url - [gitlab_config.url, path_with_namespace].join('/') + namespace_project_url(self.namespace, self) end def web_url_without_protocol diff --git a/app/models/user.rb b/app/models/user.rb index 00a37cd9135..6dd2271abe2 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -67,6 +67,7 @@ class User < ActiveRecord::Base include Gitlab::ConfigHelper include Gitlab::CurrentSettings + include Rails.application.routes.url_helpers include Referable include Sortable include TokenAuthenticatable @@ -638,7 +639,7 @@ class User < ActiveRecord::Base end def web_url - [gitlab_config.url, "u", self.username].join('/') + user_url(self) end def all_emails From d953f6927cfa605d0bc336b09a25bde2a483b3ba Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 29 Jul 2015 12:15:21 +0200 Subject: [PATCH 139/174] Restore Leave button on dashboard groups page --- app/views/dashboard/groups/index.html.haml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/views/dashboard/groups/index.html.haml b/app/views/dashboard/groups/index.html.haml index 6ef4d752ac3..0a354373b9b 100644 --- a/app/views/dashboard/groups/index.html.haml +++ b/app/views/dashboard/groups/index.html.haml @@ -23,10 +23,9 @@ %i.fa.fa-cogs Settings - - if can?(current_user, :admin_group_member, group) - = link_to leave_group_group_members_path(group), data: { confirm: leave_group_message(group.name) }, method: :delete, class: "btn-sm btn btn-grouped", title: 'Leave this group' do - %i.fa.fa-sign-out - Leave + = link_to leave_group_group_members_path(group), data: { confirm: leave_group_message(group.name) }, method: :delete, class: "btn-sm btn btn-grouped", title: 'Leave this group' do + %i.fa.fa-sign-out + Leave = image_tag group_icon(group), class: "avatar s40 avatar-tile hidden-xs" = link_to group, class: 'group-name' do From 72c552c2d4ea985a9ab1470ba2e44fc7e52673d9 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 29 Jul 2015 13:23:28 +0200 Subject: [PATCH 140/174] Fix specs --- app/models/project.rb | 2 +- spec/models/project_spec.rb | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/app/models/project.rb b/app/models/project.rb index 0608133b2cb..2d029962557 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -571,7 +571,7 @@ class Project < ActiveRecord::Base end def http_url_to_repo - [gitlab_config.url, '/', path_with_namespace, '.git'].join('') + "#{web_url}.git" end # Check if current branch name is marked as protected in the system diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 63091e913ff..1ffd92b9bd9 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -111,14 +111,20 @@ describe Project do expect(project.url_to_repo).to eq(Gitlab.config.gitlab_shell.ssh_path_prefix + 'somewhere.git') end - it 'returns the full web URL for this repo' do - project = Project.new(path: 'somewhere') - expect(project.web_url).to eq("#{Gitlab.config.gitlab.url}/somewhere") + describe "#web_url" do + let(:project) { create(:empty_project, path: "somewhere") } + + it 'returns the full web URL for this repo' do + expect(project.web_url).to eq("#{Gitlab.config.gitlab.url}/#{project.namespace.path}/somewhere") + end end - it 'returns the web URL without the protocol for this repo' do - project = Project.new(path: 'somewhere') - expect(project.web_url_without_protocol).to eq("#{Gitlab.config.gitlab.url.split('://')[1]}/somewhere") + describe "#web_url_without_protocol" do + let(:project) { create(:empty_project, path: "somewhere") } + + it 'returns the web URL without the protocol for this repo' do + expect(project.web_url_without_protocol).to eq("#{Gitlab.config.gitlab.url.split('://')[1]}/#{project.namespace.path}/somewhere") + end end describe 'last_activity methods' do From 4fb6ddfe06164c211f22e69fdec0b248bc61f6b4 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 29 Jul 2015 15:40:08 +0200 Subject: [PATCH 141/174] Add ability to manage user email addresses via the API. --- CHANGELOG | 1 + doc/api/users.md | 132 ++++++++++++++++++++++++ lib/api/entities.rb | 4 + lib/api/users.rb | 111 +++++++++++++++++++++ spec/requests/api/users_spec.rb | 171 ++++++++++++++++++++++++++++++++ 5 files changed, 419 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 7ca450d423c..ab46ef3b169 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -17,6 +17,7 @@ v 7.14.0 (unreleased) - Add fetch command to the MR page - Fix bug causing Bitbucket importer to crash when OAuth application had been removed. - Add fetch command to the MR page. + - Add ability to manage user email addresses via the API. v 7.13.2 - Fix randomly failed spec diff --git a/doc/api/users.md b/doc/api/users.md index 5dca77b5c7b..9ac55d3f09e 100644 --- a/doc/api/users.md +++ b/doc/api/users.md @@ -397,6 +397,138 @@ Parameters: Will return `200 OK` on success, or `404 Not found` if either user or key cannot be found. +## List emails + +Get a list of currently authenticated user's emails. + +``` +GET /user/emails +``` + +```json +[ + { + "id": 1, + "email": "email@example.com" + }, + { + "id": 3, + "email": "email2@example.com" + } +] +``` + +Parameters: + +- **none** + +## List emails for user + +Get a list of a specified user's emails. Available only for admin + +``` +GET /users/:uid/emails +``` + +Parameters: + +- `uid` (required) - id of specified user + +## Single SSH key + +Get a single key. + +``` +GET /user/emails/:id +``` + +Parameters: + +- `id` (required) - The ID of an SSH key + +```json +{ + "id": 1, + "email": "email@example.com" +} +``` + +## Add email + +Creates a new email owned by the currently authenticated user. + +``` +POST /user/emails +``` + +Parameters: + +- `email` (required) - email address + +```json +{ + "id": 4, + "email": "email@example.com" +} +``` + +Will return created key with status `201 Created` on success. If an +error occurs a `400 Bad Request` is returned with a message explaining the error: + +```json +{ + "message": { + "email": [ + "has already been taken" + ] + } +} +``` + +## Add email for user + +Create new email owned by specified user. Available only for admin + +``` +POST /users/:id/emails +``` + +Parameters: + +- `id` (required) - id of specified user +- `email` (required) - email address + +Will return created key with status `201 Created` on success, or `404 Not found` on fail. + +## Delete email for current user + +Deletes email owned by currently authenticated user. +This is an idempotent function and calling it on a email that is already deleted +or not available results in `200 OK`. + +``` +DELETE /user/emails/:id +``` + +Parameters: + +- `id` (required) - email ID + +## Delete email for given user + +Deletes email owned by a specified user. Available only for admin. + +``` +DELETE /users/:uid/emails/:id +``` + +Parameters: + +- `uid` (required) - id of specified user +- `id` (required) - email ID + +Will return `200 OK` on success, or `404 Not found` if either user or key cannot be found. + ## Block user Blocks the specified user. Available only for admin. diff --git a/lib/api/entities.rb b/lib/api/entities.rb index ecf1412dee5..ce3d09a32cd 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -31,6 +31,10 @@ module API expose :private_token end + class Email < Grape::Entity + expose :id, :email + end + class Hook < Grape::Entity expose :id, :url, :created_at end diff --git a/lib/api/users.rb b/lib/api/users.rb index c468371d3d4..bd8cc9f16a8 100644 --- a/lib/api/users.rb +++ b/lib/api/users.rb @@ -185,6 +185,65 @@ module API end end + # Add email to a specified user. Only available to admin users. + # + # Parameters: + # id (required) - The ID of a user + # email (required) - Email address + # Example Request: + # POST /users/:id/emails + post ":id/emails" do + authenticated_as_admin! + required_attributes! [:email] + + user = User.find(params[:id]) + attrs = attributes_for_keys [:email] + email = user.emails.new attrs + if email.save + NotificationService.new.new_email(email) + present email, with: Entities::Email + else + render_validation_error!(email) + end + end + + # Get emails of a specified user. Only available to admin users. + # + # Parameters: + # uid (required) - The ID of a user + # Example Request: + # GET /users/:uid/emails + get ':uid/emails' do + authenticated_as_admin! + user = User.find_by(id: params[:uid]) + not_found!('User') unless user + + present user.emails, with: Entities::Email + end + + # Delete existing email of a specified user. Only available to admin + # users. + # + # Parameters: + # uid (required) - The ID of a user + # id (required) - Email ID + # Example Request: + # DELETE /users/:uid/emails/:id + delete ':uid/emails/:id' do + authenticated_as_admin! + user = User.find_by(id: params[:uid]) + not_found!('User') unless user + + begin + email = user.emails.find params[:id] + email.destroy + + user.update_secondary_emails! + rescue ActiveRecord::RecordNotFound + not_found!('Email') + end + end + # Delete user. Available only for admin # # Example Request: @@ -289,6 +348,58 @@ module API rescue end end + + # Get currently authenticated user's emails + # + # Example Request: + # GET /user/emails + get "emails" do + present current_user.emails, with: Entities::Email + end + + # Get single email owned by currently authenticated user + # + # Example Request: + # GET /user/emails/:id + get "emails/:id" do + email = current_user.emails.find params[:id] + present email, with: Entities::Email + end + + # Add new email to currently authenticated user + # + # Parameters: + # email (required) - Email address + # Example Request: + # POST /user/emails + post "emails" do + required_attributes! [:email] + + attrs = attributes_for_keys [:email] + email = current_user.emails.new attrs + if email.save + NotificationService.new.new_email(email) + present email, with: Entities::Email + else + render_validation_error!(email) + end + end + + # Delete existing email of currently authenticated user + # + # Parameters: + # id (required) - EMail ID + # Example Request: + # DELETE /user/emails/:id + delete "emails/:id" do + begin + email = current_user.emails.find params[:id] + email.destroy + + current_user.update_secondary_emails! + rescue + end + end end end end diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index c4dd1f76cf2..7fa6aebca0b 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -6,6 +6,7 @@ describe API::API, api: true do let(:user) { create(:user) } let(:admin) { create(:admin) } let(:key) { create(:key, user: user) } + let(:email) { create(:email, user: user) } describe "GET /users" do context "when unauthenticated" do @@ -384,6 +385,87 @@ describe API::API, api: true do end end + describe "POST /users/:id/emails" do + before { admin } + + it "should not create invalid email" do + post api("/users/#{user.id}/emails", admin), { } + expect(response.status).to eq(400) + expect(json_response['message']).to eq('400 (Bad request) "email" not given') + end + + it "should create email" do + email_attrs = attributes_for :email + expect do + post api("/users/#{user.id}/emails", admin), email_attrs + end.to change{ user.emails.count }.by(1) + end + end + + describe 'GET /user/:uid/emails' do + before { admin } + + context 'when unauthenticated' do + it 'should return authentication error' do + get api("/users/#{user.id}/emails") + expect(response.status).to eq(401) + end + end + + context 'when authenticated' do + it 'should return 404 for non-existing user' do + get api('/users/999999/emails', admin) + expect(response.status).to eq(404) + expect(json_response['message']).to eq('404 User Not Found') + end + + it 'should return array of emails' do + user.emails << email + user.save + get api("/users/#{user.id}/emails", admin) + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.first['email']).to eq(email.email) + end + end + end + + describe 'DELETE /user/:uid/emails/:id' do + before { admin } + + context 'when unauthenticated' do + it 'should return authentication error' do + delete api("/users/#{user.id}/emails/42") + expect(response.status).to eq(401) + end + end + + context 'when authenticated' do + it 'should delete existing email' do + user.emails << email + user.save + expect do + delete api("/users/#{user.id}/emails/#{email.id}", admin) + end.to change { user.emails.count }.by(-1) + expect(response.status).to eq(200) + end + + it 'should return 404 error if user not found' do + user.emails << email + user.save + delete api("/users/999999/emails/#{email.id}", admin) + expect(response.status).to eq(404) + expect(json_response['message']).to eq('404 User Not Found') + end + + it 'should return 404 error if email not foud' do + delete api("/users/#{user.id}/emails/42", admin) + expect(response.status).to eq(404) + expect(json_response['message']).to eq('404 Email Not Found') + end + end + end + describe "DELETE /users/:id" do before { admin } @@ -528,6 +610,95 @@ describe API::API, api: true do end end + describe "GET /user/emails" do + context "when unauthenticated" do + it "should return authentication error" do + get api("/user/emails") + expect(response.status).to eq(401) + end + end + + context "when authenticated" do + it "should return array of emails" do + user.emails << email + user.save + get api("/user/emails", user) + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.first["email"]).to eq(email.email) + end + end + end + + describe "GET /user/emails/:id" do + it "should return single email" do + user.emails << email + user.save + get api("/user/emails/#{email.id}", user) + expect(response.status).to eq(200) + expect(json_response["email"]).to eq(email.email) + end + + it "should return 404 Not Found within invalid ID" do + get api("/user/emails/42", user) + expect(response.status).to eq(404) + expect(json_response['message']).to eq('404 Not found') + end + + it "should return 404 error if admin accesses user's email" do + user.emails << email + user.save + admin + get api("/user/emails/#{email.id}", admin) + expect(response.status).to eq(404) + expect(json_response['message']).to eq('404 Not found') + end + end + + describe "POST /user/emails" do + it "should create email" do + email_attrs = attributes_for :email + expect do + post api("/user/emails", user), email_attrs + end.to change{ user.emails.count }.by(1) + expect(response.status).to eq(201) + end + + it "should return a 401 error if unauthorized" do + post api("/user/emails"), email: 'some email' + expect(response.status).to eq(401) + end + + it "should not create email with invalid email" do + post api("/user/emails", user), {} + expect(response.status).to eq(400) + expect(json_response['message']).to eq('400 (Bad request) "email" not given') + end + end + + describe "DELETE /user/emails/:id" do + it "should delete existed email" do + user.emails << email + user.save + expect do + delete api("/user/emails/#{email.id}", user) + end.to change{user.emails.count}.by(-1) + expect(response.status).to eq(200) + end + + it "should return success if email ID not found" do + delete api("/user/emails/42", user) + expect(response.status).to eq(200) + end + + it "should return 401 error if unauthorized" do + user.emails << email + user.save + delete api("/user/emails/#{email.id}") + expect(response.status).to eq(401) + end + end + describe 'PUT /user/:id/block' do before { admin } it 'should block existing user' do From 097a8952d0991b42752a84aedd472aa8291717cf Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Wed, 29 Jul 2015 15:42:18 +0200 Subject: [PATCH 142/174] Move CHANGELOG entry to 7.14 --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index d0f7f775916..3570bb6df51 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -11,6 +11,7 @@ v 7.14.0 (unreleased) - Expire Rails cache entries after two weeks to prevent endless Redis growth - Add support for destroying project milestones (Stan Hu) - Add fetch command to the MR page. + - Allow custom backup archive permissions v 7.13.0 (unreleased) - Remove repository graph log to fix slow cache updates after push event (Stan Hu) @@ -52,7 +53,6 @@ v 7.13.0 (unreleased) - Correctly show anonymous authorized applications under Profile > Applications. - Query Optimization in MySQL. - Allow users to be blocked and unblocked via the API - - Allow custom backup archive permissions - Use native Postgres database cleaning during backup restore - Redesign project page. Show README as default instead of activity. Move project activity to separate page - Make left menu more hierarchical and less contextual by adding back item at top From e361dc3a1d78d77b40f865280e125926a901a200 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Wed, 29 Jul 2015 15:46:28 +0200 Subject: [PATCH 143/174] Manually fix automatic CHANGELOG merge --- CHANGELOG | 4 ---- 1 file changed, 4 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 6e3a7e8669b..3cd18479bd8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -19,10 +19,6 @@ v 7.14.0 (unreleased) - Add fetch command to the MR page. - Allow custom backup archive permissions -v 7.13.0 (unreleased) - - Add fetch command to the MR page - - Fix bug causing Bitbucket importer to crash when OAuth application had been removed. - v 7.13.1 - Fix: Label modifications are not reflected in existing notes and in the issue list - Fix: Label not shown in the Issue list, although it's set through web interface From 3e9b612306e026e7a91bd1bc5e52cc6f0c9c48de Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Thu, 23 Jul 2015 23:52:21 -0700 Subject: [PATCH 144/174] Check that project was actually created rather than just validated in import:repos task Add gitlab-shell to error message to give user a clue that something may be wrong there. Ran into this in #2082. User was told that repositories were created when they were not due to hooks symlink being wrong. --- CHANGELOG | 1 + app/models/project.rb | 4 ++-- lib/tasks/gitlab/import.rake | 4 ++-- spec/services/projects/fork_service_spec.rb | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 01c59299ece..1aa3f13f168 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,6 +4,7 @@ v 7.14.0 (unreleased) - Upgrade gitlab_git to version 7.2.6 to fix Error 500 when creating network graphs (Stan Hu) - Fix URL used for refreshing notes if relative_url is present (Bartłomiej Święcki) - Fix commit data retrieval when branch name has single quotes (Stan Hu) + - Check that project was actually created rather than just validated in import:repos task (Stan Hu) - Fix full screen mode for snippet comments (Daniel Gerhardt) - Fix 404 error in files view after deleting the last file in a repository (Stan Hu) - Fix the "Reload with full diff" URL button (Stan Hu) diff --git a/app/models/project.rb b/app/models/project.rb index ff372ea9aa5..1800c3a7e01 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -705,14 +705,14 @@ class Project < ActiveRecord::Base ensure_satellite_exists true else - errors.add(:base, 'Failed to fork repository') + errors.add(:base, 'Failed to fork repository via gitlab-shell') false end else if gitlab_shell.add_repository(path_with_namespace) true else - errors.add(:base, 'Failed to create repository') + errors.add(:base, 'Failed to create repository via gitlab-shell') false end end diff --git a/lib/tasks/gitlab/import.rake b/lib/tasks/gitlab/import.rake index 5f83e5e8e7f..c1ee271ae2b 100644 --- a/lib/tasks/gitlab/import.rake +++ b/lib/tasks/gitlab/import.rake @@ -62,11 +62,11 @@ namespace :gitlab do project = Projects::CreateService.new(user, project_params).execute - if project.valid? + if project.persisted? puts " * Created #{project.name} (#{repo_path})".green else puts " * Failed trying to create #{project.name} (#{repo_path})".red - puts " Validation Errors: #{project.errors.messages}".red + puts " Errors: #{project.errors.messages}".red end end end diff --git a/spec/services/projects/fork_service_spec.rb b/spec/services/projects/fork_service_spec.rb index 439a492cea9..c04e842c67e 100644 --- a/spec/services/projects/fork_service_spec.rb +++ b/spec/services/projects/fork_service_spec.rb @@ -29,7 +29,7 @@ describe Projects::ForkService do it "fails due to transaction failure" do @to_project = fork_project(@from_project, @to_user, false) expect(@to_project.errors).not_to be_empty - expect(@to_project.errors[:base]).to include("Failed to fork repository") + expect(@to_project.errors[:base]).to include("Failed to fork repository via gitlab-shell") end end From 34c2867ca29e60af763bb420a308090994e68e73 Mon Sep 17 00:00:00 2001 From: Darby Date: Wed, 29 Jul 2015 12:59:50 -0700 Subject: [PATCH 145/174] Switched the otder of the SSH key form --- app/views/profiles/keys/_form.html.haml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/views/profiles/keys/_form.html.haml b/app/views/profiles/keys/_form.html.haml index f905417f0e2..b76a5b636ac 100644 --- a/app/views/profiles/keys/_form.html.haml +++ b/app/views/profiles/keys/_form.html.haml @@ -6,14 +6,13 @@ - @key.errors.full_messages.each do |msg| %li= msg - .form-group - = f.label :title, class: 'control-label' - .col-sm-10= f.text_field :title, class: "form-control" .form-group = f.label :key, class: 'control-label' .col-sm-10 = f.text_area :key, class: "form-control", rows: 8 - + .form-group + = f.label :title, class: 'control-label' + .col-sm-10= f.text_field :title, class: "form-control" .form-actions = f.submit 'Add key', class: "btn btn-create" From 0fac66f84d85eb072f2d96a54820ac805799c5f3 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Thu, 30 Jul 2015 01:06:16 +0300 Subject: [PATCH 146/174] Mention group and project name in flash messages upon create, update and delete. --- CHANGELOG | 1 + app/controllers/groups_controller.rb | 6 +++--- app/controllers/projects_controller.rb | 8 ++++---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 01c59299ece..0cebe2519e3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -17,6 +17,7 @@ v 7.14.0 (unreleased) - Add fetch command to the MR page - Fix bug causing Bitbucket importer to crash when OAuth application had been removed. - Add fetch command to the MR page. + - Mention group and project name in creation, update and deletion notices (Achilleas Pipinellis) v 7.13.2 - Fix randomly failed spec diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 901c1cdddcb..784cb0f8f7e 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -24,7 +24,7 @@ class GroupsController < Groups::ApplicationController if @group.save @group.add_owner(current_user) - redirect_to @group, notice: 'Group was successfully created.' + redirect_to @group, notice: "Group '#{@group.name}' was successfully created." else render action: "new" end @@ -75,7 +75,7 @@ class GroupsController < Groups::ApplicationController def update if @group.update_attributes(group_params) - redirect_to edit_group_path(@group), notice: 'Group was successfully updated.' + redirect_to edit_group_path(@group), notice: "Group '#{@group.name}' was successfully updated." else render action: "edit" end @@ -84,7 +84,7 @@ class GroupsController < Groups::ApplicationController def destroy DestroyGroupService.new(@group, current_user).execute - redirect_to root_path, notice: 'Group was removed.' + redirect_to root_path, notice: "Group '#{@group.name} was deleted." end protected diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 586359f3080..dafc11d0707 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -24,7 +24,7 @@ class ProjectsController < ApplicationController if @project.saved? redirect_to( project_path(@project), - notice: 'Project was successfully created.' + notice: "Project '#{@project.name}' was successfully created." ) else render 'new' @@ -36,11 +36,11 @@ class ProjectsController < ApplicationController respond_to do |format| if status - flash[:notice] = 'Project was successfully updated.' + flash[:notice] = "Project '#{@project.name}' was successfully updated." format.html do redirect_to( edit_project_path(@project), - notice: 'Project was successfully updated.' + notice: "Project '#{@project.name}' was successfully updated." ) end format.js @@ -100,7 +100,7 @@ class ProjectsController < ApplicationController return access_denied! unless can?(current_user, :remove_project, @project) ::Projects::DestroyService.new(@project, current_user, {}).execute - flash[:alert] = 'Project deleted.' + flash[:alert] = "Project '#{@project.name}' was deleted." if request.referer.include?('/admin') redirect_to admin_namespaces_projects_path From 725a891dda4beae9a365058f58bb44aebf1fc9cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Doursenaud?= Date: Wed, 29 Jul 2015 23:27:04 +0000 Subject: [PATCH 147/174] Updated Twitter OmniAuth documentation --- doc/integration/twitter.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/doc/integration/twitter.md b/doc/integration/twitter.md index fe9091ad9a8..1350c8f693c 100644 --- a/doc/integration/twitter.md +++ b/doc/integration/twitter.md @@ -2,9 +2,7 @@ To enable the Twitter OmniAuth provider you must register your application with Twitter. Twitter will generate a client ID and secret key for you to use. -1. Sign in to [Twitter Developers](https://dev.twitter.com/) area. - -1. Hover over the avatar in the top right corner and select "My applications." +1. Sign in to [Twitter Application Management](https://apps.twitter.com/). 1. Select "Create new app" @@ -14,18 +12,18 @@ To enable the Twitter OmniAuth provider you must register your application with - Description: Create a description. - Website: The URL to your GitLab installation. 'https://gitlab.example.com' - Callback URL: 'https://gitlab.example.com/users/auth/twitter/callback' - - Agree to the "Rules of the Road." + - Agree to the "Developer Agreement". ![Twitter App Details](twitter_app_details.png) 1. Select "Create your Twitter application." 1. Select the "Settings" tab. -1. Underneath the Callback URL check the box next to "Allow this application to be used to Sign in the Twitter." +1. Underneath the Callback URL check the box next to "Allow this application to be used to Sign in with Twitter." 1. Select "Update settings" at the bottom to save changes. -1. Select the "API Keys" tab. +1. Select the "Keys and Access Tokens" tab. 1. You should now see an API key and API secret (see screenshot). Keep this page open as you continue configuration. @@ -78,4 +76,4 @@ To enable the Twitter OmniAuth provider you must register your application with 1. Restart GitLab for the changes to take effect. -On the sign in page there should now be a Twitter icon below the regular sign in form. Click the icon to begin the authentication process. Twitter will ask the user to sign in and authorize the GitLab application. If everything goes well the user will be returned to GitLab and will be signed in. +On the sign in page there should now be a Twitter icon below the regular sign in form. Click the icon to begin the authentication process. Twitter will ask the user to sign in and authorize the GitLab application. If everything goes well the user will be returned to GitLab and will be signed in. \ No newline at end of file From 369275d63074e5d526c0d1cf404b4a3742bb1e6a Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Tue, 28 Jul 2015 18:15:23 -0700 Subject: [PATCH 148/174] Fix network graph when branch name has single quotes Closes https://github.com/gitlabhq/gitlabhq/issues/9500 --- CHANGELOG | 1 + app/controllers/projects/network_controller.rb | 4 ++++ app/views/projects/network/show.html.haml | 6 +++--- features/project/network_graph.feature | 5 +++++ features/steps/project/network_graph.rb | 14 ++++++++++++-- 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 01c59299ece..9c36822caf0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.14.0 (unreleased) + - Fix network graph when branch name has single quotes (Stan Hu) - Upgrade gitlab_git to version 7.2.6 to fix Error 500 when creating network graphs (Stan Hu) - Fix URL used for refreshing notes if relative_url is present (Bartłomiej Święcki) - Fix commit data retrieval when branch name has single quotes (Stan Hu) diff --git a/app/controllers/projects/network_controller.rb b/app/controllers/projects/network_controller.rb index 06aef91cadd..b181c47baec 100644 --- a/app/controllers/projects/network_controller.rb +++ b/app/controllers/projects/network_controller.rb @@ -7,6 +7,10 @@ class Projects::NetworkController < Projects::ApplicationController before_action :authorize_download_code! def show + + @url = namespace_project_network_path(@project.namespace, @project, @ref, @options.merge(format: :json)) + @commit_url = namespace_project_commit_path(@project.namespace, @project, 'ae45ca32').gsub("ae45ca32", "%s") + respond_to do |format| format.html diff --git a/app/views/projects/network/show.html.haml b/app/views/projects/network/show.html.haml index a88cf167511..52b5b8b877e 100644 --- a/app/views/projects/network/show.html.haml +++ b/app/views/projects/network/show.html.haml @@ -17,9 +17,9 @@ :javascript network_graph = new Network({ - url: '#{namespace_project_network_path(@project.namespace, @project, @ref, @options.merge(format: :json))}', - commit_url: '#{namespace_project_commit_path(@project.namespace, @project, 'ae45ca32').gsub("ae45ca32", "%s")}', - ref: '#{@ref}', + url: "#{escape_javascript(@url)}", + commit_url: "#{escape_javascript(@commit_url)}", + ref: "#{escape_javascript(@ref)}", commit_id: '#{@commit.id}' }) new ShortcutsNetwork(network_graph.branch_graph) diff --git a/features/project/network_graph.feature b/features/project/network_graph.feature index 8beb6043aff..6cc89a15a78 100644 --- a/features/project/network_graph.feature +++ b/features/project/network_graph.feature @@ -10,6 +10,11 @@ Feature: Project Network Graph And page should select "master" in select box And page should have "master" on graph + @javascript + Scenario: I should see project network with 'test' branch + When I visit project network page on branch 'test' + Then page should have 'test' on graph + @javascript Scenario: I should switch "branch" and "tag" When I switch ref to "feature" diff --git a/features/steps/project/network_graph.rb b/features/steps/project/network_graph.rb index 992cf2734fd..7a83d32a240 100644 --- a/features/steps/project/network_graph.rb +++ b/features/steps/project/network_graph.rb @@ -11,8 +11,12 @@ class Spinach::Features::ProjectNetworkGraph < Spinach::FeatureSteps # Stub Graph max_size to speed up test (10 commits vs. 650) Network::Graph.stub(max_count: 10) - project = Project.find_by(name: "Shop") - visit namespace_project_network_path(project.namespace, project, "master") + @project = Project.find_by(name: "Shop") + visit namespace_project_network_path(@project.namespace, @project, "master") + end + + step "I visit project network page on branch 'test'" do + visit namespace_project_network_path(@project.namespace, @project, "'test'") end step 'page should select "master" in select box' do @@ -29,6 +33,12 @@ class Spinach::Features::ProjectNetworkGraph < Spinach::FeatureSteps end end + step "page should have 'test' on graph" do + page.within '.network-graph' do + expect(page).to have_content "'test'" + end + end + When 'I switch ref to "feature"' do select 'feature', from: 'ref' sleep 2 From baa157926d432f404a41c31ad6514ff8d5366269 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 30 Jul 2015 10:17:34 +0200 Subject: [PATCH 149/174] Stricter mkdir's in 'rake gitlab:backup:create' --- lib/backup/database.rb | 7 +++++-- lib/backup/repository.rb | 5 ++++- lib/backup/uploads.rb | 6 +++++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/backup/database.rb b/lib/backup/database.rb index 8450019980f..bbb230a10f0 100644 --- a/lib/backup/database.rb +++ b/lib/backup/database.rb @@ -7,7 +7,11 @@ module Backup def initialize @config = YAML.load_file(File.join(Rails.root,'config','database.yml'))[Rails.env] @db_dir = File.join(Gitlab.config.backup.path, 'db') - FileUtils.mkdir_p(@db_dir, mode: 0700)unless Dir.exists?(@db_dir) + FileUtils.rm_rf(@db_dir) + # Ensure the parent dir of @db_dir exists + FileUtils.mkdir_p(Gitlab.config.backup.path) + # Fail if somebody raced to create @db_dir before us + FileUtils.mkdir(@db_dir, mode: 0700) end def dump @@ -25,7 +29,6 @@ module Backup abort 'Backup failed' unless success $progress.print 'Compressing database ... ' - FileUtils.rm_f db_file_name_gz success = system('gzip', db_file_name) report_success(success) abort 'Backup failed: compress error' unless success diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb index 36d43d62982..4d70f7883dd 100644 --- a/lib/backup/repository.rb +++ b/lib/backup/repository.rb @@ -130,7 +130,10 @@ module Backup def prepare FileUtils.rm_rf(backup_repos_path) - FileUtils.mkdir_p(backup_repos_path, mode: 0700) + # Ensure the parent dir of backup_repos_path exists + FileUtils.mkdir_p(Gitlab.config.backup.path) + # Fail if somebody raced to create backup_repos_path before us + FileUtils.mkdir(backup_repos_path, mode: 0700) end def silent diff --git a/lib/backup/uploads.rb b/lib/backup/uploads.rb index ed445f79084..1f9626644e6 100644 --- a/lib/backup/uploads.rb +++ b/lib/backup/uploads.rb @@ -10,7 +10,11 @@ module Backup # Copy uploads from public/uploads to backup/uploads def dump - FileUtils.mkdir_p(backup_uploads_dir, mode: 0700) + FileUtils.rm_rf(backup_uploads_dir) + # Ensure the parent dir of backup_uploads_dir exists + FileUtils.mkdir_p(Gitlab.config.backup.path) + # Fail if somebody raced to create backup_uploads_dir before us + FileUtils.mkdir(backup_uploads_dir, mode: 0700) FileUtils.cp_r(app_uploads_dir, backup_dir) end From 1c7a8b8c27398250983bf4329007f6971df65f34 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 30 Jul 2015 11:41:59 +0200 Subject: [PATCH 150/174] Fix docs --- doc/api/users.md | 12 ++++++------ spec/requests/api/users_spec.rb | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/api/users.md b/doc/api/users.md index 9ac55d3f09e..7ba2db248ff 100644 --- a/doc/api/users.md +++ b/doc/api/users.md @@ -434,9 +434,9 @@ Parameters: - `uid` (required) - id of specified user -## Single SSH key +## Single email -Get a single key. +Get a single email. ``` GET /user/emails/:id @@ -444,7 +444,7 @@ GET /user/emails/:id Parameters: -- `id` (required) - The ID of an SSH key +- `id` (required) - email ID ```json { @@ -472,7 +472,7 @@ Parameters: } ``` -Will return created key with status `201 Created` on success. If an +Will return created email with status `201 Created` on success. If an error occurs a `400 Bad Request` is returned with a message explaining the error: ```json @@ -498,7 +498,7 @@ Parameters: - `id` (required) - id of specified user - `email` (required) - email address -Will return created key with status `201 Created` on success, or `404 Not found` on fail. +Will return created email with status `201 Created` on success, or `404 Not found` on fail. ## Delete email for current user @@ -527,7 +527,7 @@ Parameters: - `uid` (required) - id of specified user - `id` (required) - email ID -Will return `200 OK` on success, or `404 Not found` if either user or key cannot be found. +Will return `200 OK` on success, or `404 Not found` if either user or email cannot be found. ## Block user diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index 7fa6aebca0b..f2aa369985e 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -389,7 +389,7 @@ describe API::API, api: true do before { admin } it "should not create invalid email" do - post api("/users/#{user.id}/emails", admin), { } + post api("/users/#{user.id}/emails", admin), {} expect(response.status).to eq(400) expect(json_response['message']).to eq('400 (Bad request) "email" not given') end From b8066e2cd0c8ae8384b68c81ea3a6c071cd44c51 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 30 Jul 2015 11:56:15 +0200 Subject: [PATCH 151/174] No more web url --- app/models/group.rb | 5 ----- app/models/project.rb | 3 +-- app/models/user.rb | 5 ----- lib/api/entities.rb | 12 ++++++++++-- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/app/models/group.rb b/app/models/group.rb index 885d3b1e5ab..cfb8faa1491 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -17,7 +17,6 @@ require 'carrierwave/orm/activerecord' require 'file_size_validator' class Group < Namespace - include Rails.application.routes.url_helpers include Referable has_many :group_members, dependent: :destroy, as: :source, class_name: 'GroupMember' @@ -63,10 +62,6 @@ class Group < Namespace end end - def web_url - group_url(self) - end - def owners @owners ||= group_members.owners.map(&:user) end diff --git a/app/models/project.rb b/app/models/project.rb index 2d029962557..99be170731b 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -36,7 +36,6 @@ class Project < ActiveRecord::Base include Gitlab::ConfigHelper include Gitlab::ShellAdapter include Gitlab::VisibilityLevel - include Rails.application.routes.url_helpers include Referable include Sortable @@ -316,7 +315,7 @@ class Project < ActiveRecord::Base end def web_url - namespace_project_url(self.namespace, self) + Rails.application.routes.url_helpers.namespace_project_url(self.namespace, self) end def web_url_without_protocol diff --git a/app/models/user.rb b/app/models/user.rb index 6dd2271abe2..4a10520b209 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -67,7 +67,6 @@ class User < ActiveRecord::Base include Gitlab::ConfigHelper include Gitlab::CurrentSettings - include Rails.application.routes.url_helpers include Referable include Sortable include TokenAuthenticatable @@ -638,10 +637,6 @@ class User < ActiveRecord::Base end end - def web_url - user_url(self) - end - def all_emails [self.email, *self.emails.map(&:email)] end diff --git a/lib/api/entities.rb b/lib/api/entities.rb index c1b0cece344..dcfd7a8e1a7 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -5,7 +5,11 @@ module API end class UserBasic < UserSafe - expose :id, :state, :avatar_url, :web_url + expose :id, :state, :avatar_url + + expose :web_url do |user, options| + Rails.application.routes.url_helpers.user_url(user) + end end class User < UserBasic @@ -70,7 +74,11 @@ module API class Group < Grape::Entity expose :id, :name, :path, :description - expose :avatar_url, :web_url + expose :avatar_url + + expose :web_url do |group, options| + Rails.application.routes.url_helpers.group_url(group) + end end class GroupDetail < Group From 2a60b8006b1374aec998370f9cfe5b574255712f Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 30 Jul 2015 12:35:09 +0200 Subject: [PATCH 152/174] Fix Project --- app/models/project.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/project.rb b/app/models/project.rb index 99be170731b..cc2b936ba2a 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -432,7 +432,7 @@ class Project < ActiveRecord::Base if avatar.present? [gitlab_config.url, avatar.url].join elsif avatar_in_git - [gitlab_config.url, namespace_project_avatar_path(namespace, self)].join + Rails.application.routes.url_helpers.namespace_project_avatar_url(namespace, self) end end From feb2865fba15524c7dd1ae03274c63ae02edd152 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Thu, 30 Jul 2015 14:11:26 +0300 Subject: [PATCH 153/174] Raise alert when group is deleted. This change was made to match the project deletion. --- app/controllers/groups_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 784cb0f8f7e..279c6ef0f4d 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -84,7 +84,7 @@ class GroupsController < Groups::ApplicationController def destroy DestroyGroupService.new(@group, current_user).execute - redirect_to root_path, notice: "Group '#{@group.name} was deleted." + redirect_to root_path, alert: "Group '#{@group.name} was deleted." end protected From 0b5acdd88fb745821cd49f539e7e6cd4874a58ab Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 30 Jul 2015 15:12:57 +0200 Subject: [PATCH 154/174] Show buttons to add license, changelog and contribution guide if they're missing. --- CHANGELOG | 1 + app/assets/stylesheets/pages/projects.scss | 9 +++++ app/helpers/projects_helper.rb | 44 ++++++++++++++++++++-- app/views/projects/show.html.haml | 21 +++++++++-- 4 files changed, 68 insertions(+), 7 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index c03e5053d17..3b1d8dc7b61 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -19,6 +19,7 @@ v 7.14.0 (unreleased) - Add fetch command to the MR page - Fix bug causing Bitbucket importer to crash when OAuth application had been removed. - Add fetch command to the MR page. + - Show buttons to add license, changelog and contribution guide if they're missing. v 7.13.2 - Fix randomly failed spec diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 5f415f2d78f..21d958db80c 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -297,6 +297,15 @@ table.table.protected-branches-list tr.no-border { ul.nav-pills { display:inline-block; } li { display:inline; } a { float:left; } + + li.missing a { + color: #bbb; + border: 1px dashed #ccc; + + &:hover { + background-color: #FAFAFA; + } + } } pre.light-well { diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index a675a292432..f5b78533896 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -184,7 +184,43 @@ module ProjectsHelper end end - def contribution_guide_url(project) + def add_contribution_guide_path(project) + if project && !project.repository.contribution_guide + namespace_project_new_blob_path( + project.namespace, + project, + project.default_branch, + file_name: "CONTRIBUTING.md", + commit_message: "Add contribution guide" + ) + end + end + + def add_changelog_path(project) + if project && !project.repository.changelog + namespace_project_new_blob_path( + project.namespace, + project, + project.default_branch, + file_name: "CHANGELOG", + commit_message: "Add changelog" + ) + end + end + + def add_license_path(project) + if project && !project.repository.license + namespace_project_new_blob_path( + project.namespace, + project, + project.default_branch, + file_name: "LICENSE", + commit_message: "Add license" + ) + end + end + + def contribution_guide_path(project) if project && contribution_guide = project.repository.contribution_guide namespace_project_blob_path( project.namespace, @@ -195,7 +231,7 @@ module ProjectsHelper end end - def changelog_url(project) + def changelog_path(project) if project && changelog = project.repository.changelog namespace_project_blob_path( project.namespace, @@ -206,7 +242,7 @@ module ProjectsHelper end end - def license_url(project) + def license_path(project) if project && license = project.repository.license namespace_project_blob_path( project.namespace, @@ -217,7 +253,7 @@ module ProjectsHelper end end - def version_url(project) + def version_path(project) if project && version = project.repository.version namespace_project_blob_path( project.namespace, diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index 769dd68f089..4577b84ab89 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -22,19 +22,34 @@ %li = link_to namespace_project_tags_path(@project.namespace, @project) do = pluralize(number_with_delimiter(@repository.tag_names.count), 'tag') + - if @repository.changelog %li - = link_to changelog_url(@project) do + = link_to changelog_path(@project) do Changelog - if @repository.license %li - = link_to license_url(@project) do + = link_to license_path(@project) do License - if @repository.contribution_guide %li - = link_to contribution_guide_url(@project) do + = link_to contribution_guide_path(@project) do Contribution guide + - if current_user && can_push_branch?(@project, @project.default_branch) + - unless @repository.changelog + %li.missing + = link_to add_changelog_path(@project) do + Add Changelog + - unless @repository.license + %li.missing + = link_to add_license_path(@project) do + Add License + - unless @repository.contribution_guide + %li.missing + = link_to add_contribution_guide_path(@project) do + Add Contribution guide + - if @project.archived? .text-warning.center.prepend-top-20 %p From 66cc712fa516d758ab09f22ffe78b85cb4415740 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 30 Jul 2015 15:31:34 +0200 Subject: [PATCH 155/174] Fix method name. --- app/views/shared/issuable/_form.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml index 8cc0b517cd2..ac8c1936c9e 100644 --- a/app/views/shared/issuable/_form.html.haml +++ b/app/views/shared/issuable/_form.html.haml @@ -100,7 +100,7 @@ = link_to 'Change branches', mr_change_branches_path(@merge_request) .form-actions - - if !issuable.project.empty_repo? && (guide_url = contribution_guide_url(issuable.project)) && !issuable.persisted? + - if !issuable.project.empty_repo? && (guide_url = contribution_guide_path(issuable.project)) && !issuable.persisted? %p Please review the %strong #{link_to 'guidelines for contribution', guide_url} From ee1710284883d4cf61fc89d5197beef63646a220 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Wed, 29 Jul 2015 09:03:15 -0700 Subject: [PATCH 156/174] Check that hooks directory exists before attempting to call realpath Closes #2121 --- lib/tasks/gitlab/check.rake | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index aed84226a2f..badb47c6779 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -485,7 +485,8 @@ namespace :gitlab do if project.empty_repo? puts "repository is empty".magenta - elsif File.realpath(project_hook_directory) == File.realpath(gitlab_shell_hooks_path) + elsif File.directory?(project_hook_directory) && File.directory?(gitlab_shell_hooks_path) && + (File.realpath(project_hook_directory) == File.realpath(gitlab_shell_hooks_path)) puts 'ok'.green else puts "wrong or missing hooks".red @@ -754,7 +755,7 @@ namespace :gitlab do print "Ruby version >= #{required_version} ? ... " if current_version.valid? && required_version <= current_version - puts "yes (#{current_version})".green + puts "yes (#{current_version})".green else puts "no".red try_fixing_it( @@ -772,7 +773,7 @@ namespace :gitlab do print "Git version >= #{required_version} ? ... " if current_version.valid? && required_version <= current_version - puts "yes (#{current_version})".green + puts "yes (#{current_version})".green else puts "no".red try_fixing_it( @@ -806,4 +807,3 @@ namespace :gitlab do end end end - From 168f10febaab7ec1590ed8a1ba2771b534ae9c22 Mon Sep 17 00:00:00 2001 From: karen Carias Date: Thu, 30 Jul 2015 13:20:10 -0700 Subject: [PATCH 157/174] added new doc about adding users and members --- doc/permissions/permissions.md | 3 +++ doc/workflow/README.md | 1 + doc/workflow/add-user/add-user.md | 25 ++++++++++++++++++ doc/workflow/add-user/images/add-members.png | Bin 0 -> 2361 bytes doc/workflow/add-user/images/members.png | Bin 0 -> 8295 bytes doc/workflow/add-user/images/new-member.png | Bin 0 -> 12038 bytes .../add-user/images/select-project.png | Bin 0 -> 4042 bytes 7 files changed, 29 insertions(+) create mode 100644 doc/workflow/add-user/add-user.md create mode 100644 doc/workflow/add-user/images/add-members.png create mode 100644 doc/workflow/add-user/images/members.png create mode 100644 doc/workflow/add-user/images/new-member.png create mode 100644 doc/workflow/add-user/images/select-project.png diff --git a/doc/permissions/permissions.md b/doc/permissions/permissions.md index e81432c600f..e6185472dab 100644 --- a/doc/permissions/permissions.md +++ b/doc/permissions/permissions.md @@ -6,6 +6,9 @@ If a user is both in a project group and in the project itself, the highest perm If a user is a GitLab administrator they receive all permissions. +To add or import a user or member, you can follow the [Project users and members +documentation](workflow/add-user/add-user.md). + ## Project | Action | Guest | Reporter | Developer | Master | Owner | diff --git a/doc/workflow/README.md b/doc/workflow/README.md index 1f39d02bdf3..139f4db7d57 100644 --- a/doc/workflow/README.md +++ b/doc/workflow/README.md @@ -10,6 +10,7 @@ - [Notification emails](notifications.md) - [Project Features](project_features.md) - [Project forking workflow](forking_workflow.md) +- [Project users and members](add-user/add-user.md) - [Protected branches](protected_branches.md) - [Web Editor](web_editor.md) - ["Work In Progress" Merge Requests](wip_merge_requests.md) diff --git a/doc/workflow/add-user/add-user.md b/doc/workflow/add-user/add-user.md new file mode 100644 index 00000000000..1693dd6e527 --- /dev/null +++ b/doc/workflow/add-user/add-user.md @@ -0,0 +1,25 @@ +# Project Users and Members + +You can add or import members to your projects. You can also give them different access +levels. + +You should have 'master' or 'owner' permissions to add or import a new member to your +project. + +To add or import a new member, go to your project and click on "Members" on the left side +of your screen: + +![Members](images/members.png) + +Select "Add members" or "Import members" on the right side of your screen: + +![Add or Import](images/add-members.png) + +If you are adding a member, select the user and the [permission level](doc/permissions/permissions.md) that you'd like to +give the member: + +![Add or Import](images/new-member.png) + +If you are importing a member, follow the steps to select the project where you'd like to import the user from. + +![Add or Import](images/select-project.png) diff --git a/doc/workflow/add-user/images/add-members.png b/doc/workflow/add-user/images/add-members.png new file mode 100644 index 0000000000000000000000000000000000000000..2805c5764a577f4ea1cbf20047ebb3007c72e5f3 GIT binary patch literal 2361 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 literal 0 HcmV?d00001 diff --git a/doc/workflow/add-user/images/new-member.png b/doc/workflow/add-user/images/new-member.png new file mode 100644 index 0000000000000000000000000000000000000000..d500daea56e89f0a753d997469dbf593335f1457 GIT binary patch literal 12038 zcmajFbx>TVuHL)X>fYb#ud4Un5h}{Em}n$u0000}UQS9406>HQ0B}Yq2yYfj5qV_* z0RCC!lZN!`>+ALPH2~^GR z`T7b=O?iENGo0UT*Pgz-I=!u8U6PWLyIA7rWomLYou1RV-kp>3u+#Z^Grmybv;F+K zcK14b`D$X~V{L5mdb8TGe*OA#u+^1Y8(<88hNr2pDfcWGeE6WAFk<3X3MeRJ?lT6YfQ~3 zsV+=6vI$8q_l()Nto`jrO|7nw?G7PkDcG!@+z85$?Rm2OnSK9+uEKR ztV}6gy3ME_@=k0}U}c@zziwE+JvlzkYMxFnsC&Ma?5yL@qM5!;am%g)x}OxnIr zXDhkggbv=bxiWK zEA}z$-PrSJ*p8T4om(C~SRBprkDaV2&54g7Dhg(Wx>p?C+Kg|FZ7lRpO-aTK0;<|W zg0f>`e!_ma7leOLa@VG&77(DO&R^V`>n{7^T~Pnib~49WM_*S)@k;;)<0lPwcSD)( z(+g9#EC4i)P0L?EK!Dz+Jh!jxXeiIPt!-#L*H@jBCC!hurc%Hqq%}#15&&T7mX`u+ zcq|^zfPV&Y5QT1tp#@h_EsqR2;3sBw=QbsGE`B1TO-$WesLVgO<$Eij|L3SDQPZm9 z={`&^A6Y6tAgdhk@s0`+v2!-_#@K|Ik|g44ePD3WZdY3CU0VE8^uWVtk(saVIK?Ad z-vtsC$ajetG*B}$plsQ13BWu>mQ(pTF7o~e^uycnlbCATHDRh-fd@YvDH%0bP@+m3 zS#>$m^dZQiJ<_JZ#S$kisz8z`#wCVV4sr(pie!UHq{?{YAUxsz6HtaXr7!_#6$^Z> zw!h_6O>zWuv}evTc2w=1Qjkv!wAt;gLm@qp>zo3fI^tAhe`iZWja-to2oMycv`Olq zT<986D*Nf-i6li!zYwpg83~e7^Hptjzn~rX80f9-H3RKCWHQLrt5yxlnF@6bh331yQwHjEiZp^gZg4uN-N8ZiYiGPc?>UT+?w# z271?djDXgjMP|uGMq3$?j8(@Kz64pr;!qkzM6H|^=nPb`Hd9B|J>^{82YygbP>{fU z5+)fKeThzSsd%J0q<5a#(Cb1>^RUI^G!bJ&fFje*8b+Yygzq7QE;)p*ZoPaHpbeX#~k z$Npmwocts1`%r99Z32MInl=#u3xdXiVwI@HpNPPdJh`YPACHMq~|B_2UfKVq=HnsMh-%E_=C?7YbD$#J*J*O z@XQaD;PRC?-a0Uq3o!uE@HoU)Ol66b#Adj*gsf9E)wzbobI$t8M6le`Jl-(sJqBJU z3os)t-x_}5S1A%qlKA^XUIN#AY_DqsDX9X&Otdq!lnuWpLk}~=Glw-KgT%6p1aXrz z=P4OXT)UfXY6^X-{p8}(B{;x6#|>`Iwh4k_iwbP~0&j-7{TweJ*D5+OkM@{gp_#sG zC4>6LleiCV{JLZr{=)riEoyYU(ipjz`HGMg$D{9n^SgsraJkYkK0454&H8G9=TUOz zp=II5Y{mtXq<-`p=7QJ@#WuhDDWuv++J)%5Y6W8~EUsR#Pztf2C={j@tI14`ibhic zsuz!wRM^{&`->J*-}IS~c?K8VFn^FM&O@$)h9;LKMXpupPU^q ziseavN^iY~X^geMQ`4;gX=Wu~L5rC}i!cZI#% zEvhcEdGTNmfV3CT$Gh3;6OaQAFZwjB@;*U)UcU89-jJyu6Wlc-7!V%I0OXw*Y65<* zjT$$fKRcw%Mm-ncO_kZVsHRnDA^18m)Os2h94W)(yT!jqg$+w0wVx!I+jc-$N%oE% z?Q2U<|LLHlE19sV~MAGLz9 z8i8dpxC-{8jfd$%iq0IkvCoH>(RCN$N}_=!z!s)q8_X^Ce#!PY;plge8Tpbw(rSSc z0yB9k4AaS}|4_YW#tid8V}sIZzhGCh~0_ zGE4}Q`R3yK+F%5;*u)k3X=OLUOXUM6?+wd%B3Y0c2c#I4leZyY+6t#RsHw_U2QZ@y zDc0UdIolZSld6w8i5jz$jf`bC@MHJMCip|Yb2*zDMx)|HU0nul*~=r$DW zU3VUSQ6d)jt@C>fffoN39^)zE%aHX^28Yd1JdISIsJsVc$zpuJRFM`OBj=lL<{gq3u?r4Err-0umHN@kXzneOPBT z{?QpgDxu#PTm?qRn9VkIx)FR+bSZN%$5WCMl6tJ)D&C6)eP45XR}V-Kk4VaB+Zdo0 z2P+sRncW}9Ou&GaDc%-&t8zZb93&ME&02zixO+^$s)2NS*qyikkJze33Ljpo4{tD zLi4hRQbgaTc+Le7Sw+`Hm97?qOfc|%P*}L&T>>YhzV^$e4u*3&VuaKdil?0lKFbO% zai2#^tmqyG`&@@va!B<^eTE{b-K6&*y;#~$!t&Ow%vp)#>>SlbfV287!!!-cXcc385bX4k1y}HSv zJixW$x8J)AV_uyXt_>IE;|5YmbcqIxD-mgoU~(NK_~S^BoB+XfK{)F2LTTR_C>sdn zG^`!#HOA1SQnrAae^2!#CQpExEpN$&>0xkf=tff9`TpQlGiaKE`jMd|aQ4gs8a03a zk!Rwy19~irTWQt0;2O3`C(Us>xy7h`U&07n24&N;1`}dzCVY$X>6XS)DO8Qbg8;fo zl5RnobZ+qX0;OV2=F1@A_99&eTh<#+Elum!uhO#Stz##GQHX*jkTn$phs8O)!G1Ct_12ZO!fwc`{gm3G(#G?_+)=lE?AN)9$caZSj@1^@ zG21TR$Bn9^qpF*p<-MsJ`Sj*mJdGBi7uBRLz{(2=>~~G1l>3*jB}XxR75vtCe|Pk* zJ4c!0VBalfeA(agl(pSk+@ssUmFBc|dh|_sSAg4TU{;)k8C7757p^i@yD3E!KHo(^VKU=~_mMmD z*a)2)--!Lh$yKy^W|EF^P@Llv0I>dBL;&Z%dVqiawuqYlU*nzIArvT11O%-2qha^s z@KgQfTn^u}ffka!nh6BN>axOox4BvfZl=ygP3k_pD*w8YOFO!e) z!6+5h4K?<0ZTB}`Aqkh`qdaLJx8ot2#5ANbmO~l5wRW^AH3(EN>2zQllD0#Yj>D^E zYl|^lve2BR@K4Ft`7-vW4j8Z8L+ff`jEg{CZPY|*43|s;+Yn>f9iZ(qvR+eXoPT&E5^rgV5ja)d#3(#x&jtLpmpN|hJ@+T!2lym1+?pfuw z+$lptxbIpeZmGqUfqP1D(!e71$Z}63+m7#e_nV5iJ3xgoUfep{Hm)aI(o%9AuW3Y0 zL5=BzNP|(%5l0m_c-dTKoDLL@g%z}Zn6pof^#b?jjE8fRAicGfa@)J9Yz?tKB^tZvj z_>ODKzNB#7@;ij&D(#>tdnd{``8Ezh>R3rdZ`NGp5T ztnckr|3 z%8Waq%9!?Z6^0ebTBN?TLV?69`UcEf3)y^gePUZJ=OFQqulys0^L(_vMAc;3|7$20${SP|Ip6uv#`kLJ?wkCSR={rUcssxozDKz(bFfFBCewrcCcb z=6)RD-|U{A?m^A##-qteJALJFUPwco&H0elbbT2`h+6|}f+A4GUQ3<&TQ9E-!SRv) ztNxS?^$6RVDeZEpV_@PhoR}2*N=pV_oF^n73&-M>egRB-upT4$s z-z^%Gyc`a+1YKO(U({cpLmy6jYB>lMV=JoTDV4+tkET9q`B2O75m>1Pd3 z4*B~px$ZkT)1PUti~Guj+Fd3waV9_1M8rDb=Kx_w=Lh zsjM|AJ0mQy)#|#IorV>4ET}GVkCfM;RqA_J8NJ7ZU`zWb6zAt5k%u^QR`0GFpZnQr z-i`cpyigiV=aZR_e=`2+H_^iwj-D>H7bY=&mir7vr{L~#oqS4a@{=jG+D5P&Es5B> zLVLF|g>Em5EgkduZ=>|QuFj~?qolo3G7E}_TPf)9-M?Ej{!dURq)tJt$FI_>Nk6nCAwVD3IkW=g$( zEV?(yeq9S&o``q8jO|~zl5^W&B_TQDOBsHg;SDdH>)<}84Aze5Yx{H5y zK~xo)t_eqrM&6KRzO*D-Ov0YWQre4Ui%da!iCbp+CP(ro@8P7V9bWJruh{t7h(~@vMTt>P3 zr^;%LJV;=+rERZXAqArOh_*05K@eCK6MipS2oX)~;7j}ASgq>(Fc7U&|A-%a)3?mp zi25n~yq;xA;`r9)pdn+1;10F@WDh*5juw?taQlJ$O7==+t4y~!!@_vfqd=J{xQta# zied?}xp4Rl*f(ZF7@$COuRP=z`cFcDPU-JzY4jy=`K>D>4w2i0|WOX4QQlcG*v&^Khuy;3*tdrA{& zR#;=FN9?`YKZ2TeDfR~*2jTjnnuH%EoR`!nC(-O4p^_RTSW=~#BHqetuO7%1x`LDx z!BtGEQ_AEOrqpU)vBb373D-x0mapIY9dfnuj27#;vFk+oF?g@^DF|+U+uvRi@h{>r zPX)I&_amAUsoD~~#jf<_tQXE_=?0_+8jws^as7K7NLrd?tl=&%F*>lwkD!$wA%CPq zxpgtx2Db%1Rfv_G_E13>b$-1Xkf-2@Zt_!W9N7bDUu!NwfL)L;MA)71?xwraIE%!M zO8fRL@JXer=Q&`#Cb<=tD*}v|6Iv47#e*A=K6h+aYPsdmbj?a0;n4jALuz{sXE3$zz&!5&ZGlPPhz0v2%(kjd<`JuPP@sJ%@%mFRY26c%r*A z3|~T@_M=yfZ?M;y<84!IXf^UtcYM@EZ?;+at^2rkGVDgfnsi8iGCTL7;5ZDXsMx_P z7874)ey|emHzQxg6|t!B??B%Z*+gsMrOlrQq}y&#Y0>pT02D)G3;i{5!j{rflonv+ zIOL6C{N+-YJ>Tu1Ki?;OUv|N^q~7)qLmin&*#@fGeZ#XVIabEkyh#-#{@x=OWvauI z6JMTlB}A?tQfmK*Ubn~4Y0_NdYbu>n!7GOKk#Jji6rwSC?x0NngmKzjdvc7I;LUJ+ zqteeR1YNR1;!uN0rb%B!~*__^(i=DkPV2;yg5R zoXZbaAP}vhYqoG*Z#S_SzQWLjgaYxMmg%lJfK25LCi2ANk!kg*Y=pp_748d+{uiBw zx_J1n?zFTu%Nct|0T_gTiH|m{i8jnI<4-mc#Tm<-ykb*C<3$gj+GN8%?aAFN`odN^ z##rvXu0VttUMl{s^H>I6`V2A5vl9fjU$%qj)4dZQ>Dlby6)i~%n7&J^gt)`^yPhbm6J*#W zeW4n8757ee);Y~WN;G)b#be+F(5O1r1L2pOv=KZF>Ts`F{`TXEm^-1y%@455bml6B zz~2ueBtg_?Ih&N^m&;31fCT96khFs7l_3G%JG#Oyka!>*Kl&Qz6to`Zdx`DH`E%<| zi*|zbY-z;CAk7m?u&a4HZg#qHBD*3>E0HN<%TE7Zb5QbLi8_88TRM2>iDbbu{@uOi z&o2t7f;Iw6N=`|P_rha*gs0Qfi3g7lrdfOUqHCFZ_eV32m(QY)1@~veIYsxGg%s2SXkw^aO0TVkT0)=Gaw6cP7 zsr{el=i~TRrx2o?c>n9}04(Y%qR#zvQhV*gcKVeBAw0~kg(7iC^vLtLW5&;g=@9a# zb)FiG?puxoE`|X5=D3v1B4FK5`jF^1Q8}nBYD*Sz)#v&E%-KN?muFJy z@SdSG_&e`ih{&3MAW7eUSelb_OB!53D&WQ0Cg zTHi1WiIu#X6;_Cqnh?*XTvl)+vFO=nP9>&u?YYUFO_TVu9h7aj^?(WR-9&f~?k5MVFD7So6ak=|s* z5ZFDoQ*t%66V}^X{=;LLppdCdm<1u6h%b7wxvA7CHsi5&(PqXeR+S2wPESuSQnp4m z<{d>UJsB;|HlD%J!NI*Dwpvy0Y%dwx-Mn`DY$U6dZ14epyY{KnI2Wv~gfQ2GTM!53 z4tF|#iRl)0L^vLG8N>dGe9efno~E%PUqkmZi=xgBC^s%0Y+joFwxKtfQ*c!^(jEmF z&Fe(bJRv@c)4_9vxELusLm+6@Vz z%#{pAMyLy`b0=vyl_e1CPn5BvkVFsKPD!Z~jupKN%&us-OmkzrsR8YlsI&FY={x@| z4Dy4e-V*YEsc-n{g8GTu>i3+#mZsB6(yc^J+y(+fl}zmv*h8-Y5-db5qzJk{IiI_y z|IFvb*N673Pvz?=>f}?bDO?*M3BAkp>gT&Daci(?|1DbNFuG=IRh?o!iqM*>`6oXR zKe33iFrA6XyT8oD-Vn5(611518lCWb^Bd_8wVZ0#c%dnCoU+A%mDkqGY4P;e1~7hc z`M&)Ndwy<`3g;EOf*8GT3j#F&712L`o%|}JO-Mk32r-8vJqjPx5=dVw>UAywM_?{E z3nCu#ay59VfatG&ke_#N77=@$;dZd6NbauS+V}GJ@!aZc^E7&Y>h8{g442AZ_czTE=ntUN*MXQid#Rub^RuuMDTZ`_YT zSm7|3Dj{SdCiTl=FiK6-U?n9Bl?3BM*nU{G9Wyh#Ldzv{^P$MzW4;c{IW@_>DEg}J zUhA3nA4JMgLB@*UehFaLug1nkPD$#Y#IsSxFZ5UVq9z=%fiK=jR(e#EI9(i7y@eY_ zpcRR2s!(GS^oKSw3baW&#HS5xf0ILQeZ+1KjIRGJPw0~}Z12fJ3&~cjNuAn%OUk{h zG`D-FeLbAoxQ+5{fg=iyaQwEY8V8uT+sxpY_B(|S53Oq8_4QPzO{Dy@=APN_vzR1(1D^IZGW2ZR7iT^vVV|Ac628G zL|q+e7av2;t4?0^J%6Jn{1TtHslgHFDwf zsGJ%lw;<#lj9Ly+=~ws%tlyOze&qE1)Amj}$1S)nIt6CQ6#b{9*G5%@Fbxx5Qa*D! z>O`9c@7)RO5ANQCR#AMV*Xe9US|(wN(|pj%WId84k6ZB zjR`HPsocjIh8!)c+h3F~A$Q{XZZ}SHvRLGj@f}`OLhFtaauzk&Hf>9u%gHpPGz+-i zH7iw`Em|HT@0+sjomC`Q*j6c_i7r}lqGNS7v$qYsX|vX>(;kK)ydBYio{91KdAXLK zQo8=)ke|$Q|;En{n37#>{z^JsS>RM@($Glzdb-C+>8C5 zzJM#`pV=sHH-usG@eDHAJPp5yosckrwU2fZ5g;`^we@c84Q!;^nq)enn{5BhyMgGX zMCw^~2U=^a)PE4jG3u3h2iRn|D2h_dPiIRRgsEX_dGygK)}Z8a!)F7OvEdcCfVaJA(Qt8fBpQ4emoq zI@64*c$Wz!Y(}%uTAZRVPN8Sp2wB=oWi0T$lXm8w(~u3od6qO+z;YA`if>p=A=M@@ zG~!S(NnTrBLcGrM9>Z;1h_qFIC7ppxgQ{NKnvb#p?hTp_E2mIl;gz8tC2IujW7v3f zW=K<`pDnu=J%&?k>pM2@8Y~fdPQIy)wU&y}G$wamI+nTY>LEN>GoYMf&txdl&L;0M zYpD)v0~#86FbUp<$zdNBHH?!5KWd%!a_LHRQ>Pq~9)lR_qgGFpXCbBT2BnzH_o5@< zzG4Hyp4UxTWP==Us8=\S>b(f5c!f5C2!DhW4-1iz#7e?++a3(9j;d_LVl@pj!m zKRzoj(wsrIlcvMsza-N285JQ+h>@Z=3+DWTYbyvsUI}NVhq`g?F5r&+BG`qRBw!W8 zjeGZJdZ8acfx1HRc}izv@kO4`SWY^W=E+X*Cd`W1Iil?0`-^m!j0KfB%4{Wq`%Nx5 zt;gz`u1Ipoe^Uppa10UOfFjfDJ;pKC5Qb4y!9{V*gGhE8^>CQ~hvS)I%Jf4hzUsr&`5%Np=>RIAJK;&h4=0Ms#{ zxbIvcc(4mcZ4Y^ND>n6af^*9 zNQM}{2?DKypajTpaL90ZE&}__YtFJ~zL@*vf5CI_6==R(s#G#I9y zV~U8Yaz0RDMiV_tyXA-oBxkAsDJGrP*zm*QX8}Z zFyZGr#(_%vcIv}Tu6m3GJt|KPrw}Up;+M_VJ~#V(=-fE4sM8=h}3z9W%uH<;PD1+;)+% zx+}a$^!S~E*6gQ%Fzw~nFHk>F^K;UpH%+GJg*ruE-waE_<1do`EKIZj9eP-~uwWo~ z0pA~!{$iz{e$}9|i}lmn-qZCPxW9;MP>whv;wR(8=)a$3LuP zO>Epv|1k5mIsK(?V5gEW_#Bg7Je)L4T1~3Vcony~gW#8cN^C9gz?i{br`GV>@mgWH z>&@Mqo-bTa4a#MXfEDRen-9)Qbl7r7Y8Ik93V)7I^D1hp2TOZS2aX)cLq05kM9S-X z3L}7Ur5sgY^_lSU){gH(XEz@#hSp%Owm4d_rI_I4?XSBZTU{p-F((!Owt|1@B^m#+ z;P9PhB~H-+Q@HCHMvh!HE@rAN4Q=US7)1nPI$10CuRT3)x{f}~3xSr(CXQAm7tu8# z)s$O!{NblxuTKTDmzzN|P&0Yna6?&jKOg1RY?5wS&C5U=97_KEnZhnX=j*%Db^V?^ z6UM%APyiB;Pi~cA*505MZ^E(X{fljmjkzH{yR3`kY9$+vj%}TEMIYwsr$pEST-_aF z&f~-r$B_u-#Ct=&b*;jSUg!X(LT^v}XIFUMP$1j~j!Lj%C{4Bxd34Awy>;${k2T{` zZEfv?hAa2MkqYInVF$?j-Y`j@F9_>j^Z6Oy9f|EbdV={x*@2aCB=J8z#tB%S`aaX} zpco4V~#*bz#Ca0Aj7>;3J?qajYTlX5Mcr+L;@&pUk^DP maAG$>>v{kAfBk=sjx08Ml^e2R3qIffT$GnqmMWJp3i@AyRyTA2 literal 0 HcmV?d00001 diff --git a/doc/workflow/add-user/images/select-project.png b/doc/workflow/add-user/images/select-project.png new file mode 100644 index 0000000000000000000000000000000000000000..dd3844edff8d6c6a379b5a9e565c81a7c5b3a8a2 GIT binary patch literal 4042 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 literal 0 HcmV?d00001 From e70901abe76b07d7d08c6687ec746ac0491ddf26 Mon Sep 17 00:00:00 2001 From: karen Carias Date: Thu, 30 Jul 2015 13:26:10 -0700 Subject: [PATCH 158/174] typo --- doc/permissions/permissions.md | 4 ++-- doc/workflow/add-user/add-user.md | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/permissions/permissions.md b/doc/permissions/permissions.md index e6185472dab..029d446640d 100644 --- a/doc/permissions/permissions.md +++ b/doc/permissions/permissions.md @@ -6,8 +6,8 @@ If a user is both in a project group and in the project itself, the highest perm If a user is a GitLab administrator they receive all permissions. -To add or import a user or member, you can follow the [Project users and members -documentation](workflow/add-user/add-user.md). +To add or import a user or member, you can follow the [project users and members +documentation](doc/workflow/add-user/add-user.md). ## Project diff --git a/doc/workflow/add-user/add-user.md b/doc/workflow/add-user/add-user.md index 1693dd6e527..58f7bd0a5ce 100644 --- a/doc/workflow/add-user/add-user.md +++ b/doc/workflow/add-user/add-user.md @@ -1,12 +1,12 @@ -# Project Users and Members +# Project users and members -You can add or import members to your projects. You can also give them different access +You can add or import users to your projects. You can also give them different access levels. -You should have 'master' or 'owner' permissions to add or import a new member to your +You should have 'master' or 'owner' permissions to add or import a new user to your project. -To add or import a new member, go to your project and click on "Members" on the left side +To add or import a user, go to your project and click on "Members" on the left side of your screen: ![Members](images/members.png) @@ -15,11 +15,11 @@ Select "Add members" or "Import members" on the right side of your screen: ![Add or Import](images/add-members.png) -If you are adding a member, select the user and the [permission level](doc/permissions/permissions.md) that you'd like to -give the member: +If you are adding a user, select the user and the [permission level](doc/permissions/permissions.md) that you'd like to +give the user: ![Add or Import](images/new-member.png) -If you are importing a member, follow the steps to select the project where you'd like to import the user from. +If you are importing a user, follow the steps to select the project where you'd like to import the user from: ![Add or Import](images/select-project.png) From bd72b5bd32c64606a498066cadf9f765be059b9d Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Thu, 30 Jul 2015 13:40:30 -0700 Subject: [PATCH 159/174] Fix version for CHANGELOG entry --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index c03e5053d17..a3b1b82e0eb 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -19,6 +19,7 @@ v 7.14.0 (unreleased) - Add fetch command to the MR page - Fix bug causing Bitbucket importer to crash when OAuth application had been removed. - Add fetch command to the MR page. + - Disabled autocapitalize and autocorrect on login field (Daryl Chan) v 7.13.2 - Fix randomly failed spec @@ -29,7 +30,6 @@ v 7.13.2 - Show the first tab automatically on MergeRequests#new - Add rake task 'gitlab:update_commit_count' (Daniel Gerhardt) - Fix Gmail Actions - - Disabled autocapitalize and autocorrect on login field (Daryl Chan) v 7.13.1 - Fix: Label modifications are not reflected in existing notes and in the issue list From 2911b71e821daf90642d2a60b62b14c4380832ad Mon Sep 17 00:00:00 2001 From: karen Carias Date: Thu, 30 Jul 2015 13:50:15 -0700 Subject: [PATCH 160/174] added new doc about creating MR --- doc/gitlab-basics/README.md | 2 ++ doc/gitlab-basics/add-merge-request.md | 41 ++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 doc/gitlab-basics/add-merge-request.md diff --git a/doc/gitlab-basics/README.md b/doc/gitlab-basics/README.md index 538894f5848..9491f8c91fe 100644 --- a/doc/gitlab-basics/README.md +++ b/doc/gitlab-basics/README.md @@ -19,3 +19,5 @@ Step-by-step guides on the basics of working with Git and GitLab. * [Fork a project](fork-project.md) * [Add a file](add-file.md) + +* [Create a Merge Request](add-merge-request.md) diff --git a/doc/gitlab-basics/add-merge-request.md b/doc/gitlab-basics/add-merge-request.md new file mode 100644 index 00000000000..a02b3f05205 --- /dev/null +++ b/doc/gitlab-basics/add-merge-request.md @@ -0,0 +1,41 @@ +# How to create a merge request + +Merge Requests are useful to integrate separate changes that you've made to a project, on different branches. + +To create a new Merge Request, sign in to [GitLab.com](https://gitlab.com). + +Select a project on the right side of your screen: + +![Select a project](basicsimages/select_project.png) + +Click on "Merge Requests" on the left side of your screen: + +![Merge requests](basicsimages/merge_requests.png) + +Click on "+ new Merge Request" on the right side of the screen: + +![New Merge Request](basicsimages/new_merge_request.png) + +Select a source branch or branch: + +![Select a branch](basicsimages/select_branch.png) + +Click on the "compare branches" button: + +![Compare branches](basicsimages/compare_branches.png) + +Add a title and a description to your Merge Request: + +![Add a title and description](basicsimages/title_description_mr.png) + +Select a user to review your Merge Request and to accept or close it. You may also select milestones and labels (they are optional). Then click on the "submit new Merge Request" button: + +![Add a new merge request](basicsimages/add_new_merge_request.png) + +Your Merge Request will be ready to be approved and published. + +### Note + +After you created a new branch, you'll be able to find a "create a Merge Request" button at the top of your screen. +You may automatically create a Merge Request from your recently created branch when clicking on this button: + From 89fc87122fead708671180c88652d3a9bd032613 Mon Sep 17 00:00:00 2001 From: karen Carias Date: Thu, 30 Jul 2015 13:54:37 -0700 Subject: [PATCH 161/174] added image --- doc/gitlab-basics/add-merge-request.md | 5 +++-- .../basicsimages/button-create-mr.png | Bin 0 -> 6154 bytes 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 doc/gitlab-basics/basicsimages/button-create-mr.png diff --git a/doc/gitlab-basics/add-merge-request.md b/doc/gitlab-basics/add-merge-request.md index a02b3f05205..d829faf097f 100644 --- a/doc/gitlab-basics/add-merge-request.md +++ b/doc/gitlab-basics/add-merge-request.md @@ -36,6 +36,7 @@ Your Merge Request will be ready to be approved and published. ### Note -After you created a new branch, you'll be able to find a "create a Merge Request" button at the top of your screen. +After you created a new branch, you'll immediately find a "create a Merge Request" button at the top of your screen. You may automatically create a Merge Request from your recently created branch when clicking on this button: - + +![Automatic MR button](basicsimages/button-create-mr.png) diff --git a/doc/gitlab-basics/basicsimages/button-create-mr.png b/doc/gitlab-basics/basicsimages/button-create-mr.png new file mode 100644 index 0000000000000000000000000000000000000000..457af459bb9f89a53abea4c550cba1d98dca1aa5 GIT binary patch literal 6154 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 literal 0 HcmV?d00001 From 4e22dcb6a34f43e5b3b2700ec72b32354315adc0 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 30 Jul 2015 17:25:07 -0400 Subject: [PATCH 162/174] Add spec to RelativeLinkFilter for Unicode filenames --- lib/gitlab/markdown/relative_link_filter.rb | 13 +++++++++++-- .../gitlab/markdown/relative_link_filter_spec.rb | 16 ++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/markdown/relative_link_filter.rb b/lib/gitlab/markdown/relative_link_filter.rb index 3eaceba5323..30f50b82996 100644 --- a/lib/gitlab/markdown/relative_link_filter.rb +++ b/lib/gitlab/markdown/relative_link_filter.rb @@ -99,15 +99,24 @@ module Gitlab # Returns a String def path_type(path) unescaped_path = Addressable::URI.unescape(path) - if repository.tree(current_sha, unescaped_path).entries.any? + + if tree?(unescaped_path) 'tree' - elsif repository.blob_at(current_sha, unescaped_path).try(:image?) + elsif image?(unescaped_path) 'raw' else 'blob' end end + def tree?(path) + repository.tree(current_sha, path).entries.any? + end + + def image?(path) + repository.blob_at(current_sha, path).try(:image?) + end + def current_sha context[:commit].try(:id) || ref ? repository.commit(ref).try(:sha) : repository.head_commit.sha diff --git a/spec/lib/gitlab/markdown/relative_link_filter_spec.rb b/spec/lib/gitlab/markdown/relative_link_filter_spec.rb index 5ee5310825d..7f4d67e403f 100644 --- a/spec/lib/gitlab/markdown/relative_link_filter_spec.rb +++ b/spec/lib/gitlab/markdown/relative_link_filter_spec.rb @@ -1,3 +1,5 @@ +# encoding: UTF-8 + require 'spec_helper' module Gitlab::Markdown @@ -101,6 +103,20 @@ module Gitlab::Markdown expect(doc.at_css('a')['href']).to eq 'http://example.com' end + it 'supports Unicode filenames' do + path = 'files/images/한글.png' + escaped = Addressable::URI.escape(path) + + # Stub these methods so the file doesn't actually need to be in the repo + allow_any_instance_of(described_class).to receive(:file_exists?). + and_return(true) + allow_any_instance_of(described_class). + to receive(:image?).with(path).and_return(true) + + doc = filter(image(escaped)) + expect(doc.at_css('img')['src']).to match '/raw/' + end + context 'when requested path is a file in the repo' do let(:requested_path) { 'doc/api/README.md' } include_examples :relative_to_requested From 7ca7770e984d802f9f35579d6b5c08ad63a3052a Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 30 Jul 2015 17:27:25 -0400 Subject: [PATCH 163/174] Fix CHANGELOG entry --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 86927eae79f..c1f7da82f5e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,7 +3,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.14.0 (unreleased) - Fix network graph when branch name has single quotes (Stan Hu) - Upgrade gitlab_git to version 7.2.6 to fix Error 500 when creating network graphs (Stan Hu) - - Fix the image file that contains non-ascii character is not displayed(Hiroyuki Sato) + - Add support for Unicode filenames in relative links (Hiroyuki Sato) - Fix URL used for refreshing notes if relative_url is present (Bartłomiej Święcki) - Fix commit data retrieval when branch name has single quotes (Stan Hu) - Check that project was actually created rather than just validated in import:repos task (Stan Hu) From 0abe98f0497b667ef85ad4e078ea5c10b5b26ede Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Thu, 30 Jul 2015 22:31:53 -0700 Subject: [PATCH 164/174] Fix multi-line syntax highlighting HTML span elements only apply to a single line, and in the case of multi-line comments, the highlighting was dropped as a result. Ensure that each line has the proper styling to fix this. Closes #1577 --- CHANGELOG | 1 + lib/rouge/formatters/html_gitlab.rb | 12 ++++++++++-- spec/helpers/blob_helper_spec.rb | 18 ++++++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index bfff6a56777..27cf89b5938 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.14.0 (unreleased) + - Fix multi-line syntax highlighting (Stan Hu) - Fix network graph when branch name has single quotes (Stan Hu) - Upgrade gitlab_git to version 7.2.6 to fix Error 500 when creating network graphs (Stan Hu) - Add support for Unicode filenames in relative links (Hiroyuki Sato) diff --git a/lib/rouge/formatters/html_gitlab.rb b/lib/rouge/formatters/html_gitlab.rb index 485af6832d7..092a920a0c4 100644 --- a/lib/rouge/formatters/html_gitlab.rb +++ b/lib/rouge/formatters/html_gitlab.rb @@ -148,6 +148,12 @@ module Rouge end end + def wrap_values(val, element) + lines = val.split("\n") + lines = lines.map{ |x| "#{x}" } + lines.join("\n") + end + def span(tok, val) # http://stackoverflow.com/a/1600584/2587286 val = CGI.escapeHTML(val) @@ -155,11 +161,13 @@ module Rouge if tok.shortname.empty? val else + # In the case of multi-line values (e.g. comments), we need to apply + # styling to each line since span elements are inline. if @inline_theme rules = @inline_theme.style_for(tok).rendered_rules - "#{val}" + wrap_values(val, "style=\"#{rules.to_a.join(';')}\"") else - "#{val}" + wrap_values(val, "class=\"#{tok.shortname}\"") end end end diff --git a/spec/helpers/blob_helper_spec.rb b/spec/helpers/blob_helper_spec.rb index e49e4e6d5d8..76009c36099 100644 --- a/spec/helpers/blob_helper_spec.rb +++ b/spec/helpers/blob_helper_spec.rb @@ -6,6 +6,14 @@ describe BlobHelper do let(:no_context_content) { ":type \"assem\"))" } let(:blob_content) { "(make-pathname :defaults name\n#{no_context_content}" } let(:split_content) { blob_content.split("\n") } + let(:multiline_content) do + %q( + def test(input): + """This is line 1 of a multi-line comment. + This is line 2. + """ + ) + end it 'should return plaintext for unknown lexer context' do result = highlight(blob_name, no_context_content, nowrap: true, continue: false) @@ -29,5 +37,15 @@ describe BlobHelper do result = split_content.map{ |content| highlight(blob_name, content, nowrap: true, continue: true) } expect(result).to eq(expected) end + + it 'should highlight multi-line comments' do + result = highlight(blob_name, multiline_content, nowrap: true, continue: false) + html = Nokogiri::HTML(result) + lines = html.search('.s') + expect(lines.count).to eq(3) + expect(lines[0].text).to eq('"""This is line 1 of a multi-line comment.') + expect(lines[1].text).to eq(' This is line 2.') + expect(lines[2].text).to eq(' """') + end end end From 0736f348a6953e6417d3857b78ea5c7eb5954e51 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 31 Jul 2015 14:15:49 +0200 Subject: [PATCH 165/174] Use before_actions --- app/controllers/groups/application_controller.rb | 6 ++++++ app/controllers/groups/group_members_controller.rb | 5 +---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/controllers/groups/application_controller.rb b/app/controllers/groups/application_controller.rb index 4df9d1b7533..6878d4bc07e 100644 --- a/app/controllers/groups/application_controller.rb +++ b/app/controllers/groups/application_controller.rb @@ -18,4 +18,10 @@ class Groups::ApplicationController < ApplicationController return render_404 end end + + def authorize_admin_group_member! + unless can?(current_user, :admin_group_member, group) + return render_403 + end + end end diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb index b9c428a964f..91518c44a98 100644 --- a/app/controllers/groups/group_members_controller.rb +++ b/app/controllers/groups/group_members_controller.rb @@ -5,6 +5,7 @@ class Groups::GroupMembersController < Groups::ApplicationController # Authorize before_action :authorize_read_group! before_action :authorize_admin_group!, except: [:index, :leave] + before_action :authorize_admin_group_member!, only: [:create, :resend_invite] def index @project = @group.projects.find(params[:project_id]) if params[:project_id] @@ -21,8 +22,6 @@ class Groups::GroupMembersController < Groups::ApplicationController end def create - return render_403 unless can?(current_user, :admin_group_member, @group) - @group.add_users(params[:user_ids].split(','), params[:access_level], current_user) redirect_to group_group_members_path(@group), notice: 'Users were successfully added.' @@ -51,8 +50,6 @@ class Groups::GroupMembersController < Groups::ApplicationController end def resend_invite - return render_403 unless can?(current_user, :admin_group_member, @group) - redirect_path = group_group_members_path(@group) @group_member = @group.group_members.find(params[:id]) From 87df06171ebfdcab01f377e4e040f72b4ba3b013 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 31 Jul 2015 15:48:23 +0200 Subject: [PATCH 166/174] Bump redis-store to 1.1.6 and remove redid-store-fix-expiry --- CHANGELOG | 1 + Gemfile.lock | 4 +- config/initializers/redis-store-fix-expiry.rb | 44 ------------------- 3 files changed, 3 insertions(+), 46 deletions(-) delete mode 100644 config/initializers/redis-store-fix-expiry.rb diff --git a/CHANGELOG b/CHANGELOG index 8dc23cf175f..5716afa227c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -24,6 +24,7 @@ v 7.14.0 (unreleased) - Add fetch command to the MR page. - Disabled autocapitalize and autocorrect on login field (Daryl Chan) - Mention group and project name in creation, update and deletion notices (Achilleas Pipinellis) + - Remove redis-store TTL monkey patch v 7.13.2 - Fix randomly failed spec diff --git a/Gemfile.lock b/Gemfile.lock index 44365017edc..58622f2ac10 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -508,7 +508,7 @@ GEM rdoc (3.12.2) json (~> 1.4) redcarpet (3.3.2) - redis (3.1.0) + redis (3.2.1) redis-actionpack (4.0.0) actionpack (~> 4) redis-rack (~> 1.5.0) @@ -525,7 +525,7 @@ GEM redis-actionpack (~> 4) redis-activesupport (~> 4) redis-store (~> 1.1.0) - redis-store (1.1.4) + redis-store (1.1.6) redis (>= 2.2) request_store (1.0.5) rerun (0.10.0) diff --git a/config/initializers/redis-store-fix-expiry.rb b/config/initializers/redis-store-fix-expiry.rb deleted file mode 100644 index fce0a135330..00000000000 --- a/config/initializers/redis-store-fix-expiry.rb +++ /dev/null @@ -1,44 +0,0 @@ -# Monkey-patch Redis::Store to make 'setex' and 'expire' work with namespacing - -module Gitlab - class Redis - class Store - module Namespace - # Redis::Store#setex in redis-store 1.1.4 does not respect namespaces; - # this new method does. - def setex(key, expires_in, value, options=nil) - namespace(key) { |key| super(key, expires_in, value) } - end - - # Redis::Store#expire in redis-store 1.1.4 does not respect namespaces; - # this new method does. - def expire(key, expires_in) - namespace(key) { |key| super(key, expires_in) } - end - - private - - # Our new definitions of #setex and #expire above assume that the - # #namespace method exists. Because we cannot be sure of that, we - # re-implement the #namespace method from Redis::Store::Namespace so - # that it is available for all Redis::Store instances, whether they use - # namespacing or not. - # - # Based on lib/redis/store/namespace.rb L49-51 (redis-store 1.1.4) - def namespace(key) - if @namespace - yield interpolate(key) - else - # This Redis::Store instance does not use a namespace so we should - # just pass through the key. - yield key - end - end - end - end - end -end - -Redis::Store.class_eval do - include Gitlab::Redis::Store::Namespace -end From e72e721f0453abdd383aacebf0aebc8f5f7f4b3c Mon Sep 17 00:00:00 2001 From: karen Carias Date: Fri, 31 Jul 2015 08:21:53 -0700 Subject: [PATCH 167/174] small changes --- doc/gitlab-basics/add-file.md | 2 +- doc/gitlab-basics/add-merge-request.md | 4 ++-- doc/gitlab-basics/command-line-commands.md | 2 +- doc/gitlab-basics/create-group.md | 2 +- doc/gitlab-basics/create-project.md | 2 +- doc/gitlab-basics/create-your-ssh-keys.md | 2 +- doc/gitlab-basics/fork-project.md | 2 +- doc/gitlab-basics/start-using-git.md | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/gitlab-basics/add-file.md b/doc/gitlab-basics/add-file.md index e7c441e7698..57136ac5c39 100644 --- a/doc/gitlab-basics/add-file.md +++ b/doc/gitlab-basics/add-file.md @@ -2,7 +2,7 @@ You can create a file in your [shell](command-line-commands.md) or in GitLab. -To create a file in GitLab, sign in to [GitLab.com](https://gitlab.com). +To create a file in GitLab, sign in to GitLab. Select a project on the right side of your screen: diff --git a/doc/gitlab-basics/add-merge-request.md b/doc/gitlab-basics/add-merge-request.md index d829faf097f..236b4248ea2 100644 --- a/doc/gitlab-basics/add-merge-request.md +++ b/doc/gitlab-basics/add-merge-request.md @@ -2,9 +2,9 @@ Merge Requests are useful to integrate separate changes that you've made to a project, on different branches. -To create a new Merge Request, sign in to [GitLab.com](https://gitlab.com). +To create a new Merge Request, sign in to GitLab. -Select a project on the right side of your screen: +Go to the project where you'd like to merge your changes: ![Select a project](basicsimages/select_project.png) diff --git a/doc/gitlab-basics/command-line-commands.md b/doc/gitlab-basics/command-line-commands.md index a8223a9b161..b03cca4029c 100644 --- a/doc/gitlab-basics/command-line-commands.md +++ b/doc/gitlab-basics/command-line-commands.md @@ -2,7 +2,7 @@ ## Start working on your project -In Git, when you copy a project you say you "clone" it. To work on a git project locally (from your own computer), you will need to clone it. To do this, sign in to [GitLab.com](https://gitlab.com). +In Git, when you copy a project you say you "clone" it. To work on a git project locally (from your own computer), you will need to clone it. To do this, sign in to GitLab. When you are on your Dashboard, click on the project that you'd like to clone, which you'll find at the right side of your screen. diff --git a/doc/gitlab-basics/create-group.md b/doc/gitlab-basics/create-group.md index 8e168395ff7..f80ae62e442 100644 --- a/doc/gitlab-basics/create-group.md +++ b/doc/gitlab-basics/create-group.md @@ -2,7 +2,7 @@ ## Create a group -Your projects in [GitLab.com](https://gitlab.com) can be organized in 2 different ways: +Your projects in GitLab can be organized in 2 different ways: under your own namespace for single projects, such as ´your-name/project-1'; or under groups. If you organize your projects under a group, it works like a folder. You can manage your group members' permissions and access to the projects. diff --git a/doc/gitlab-basics/create-project.md b/doc/gitlab-basics/create-project.md index 90d40cb6c51..b545d62549d 100644 --- a/doc/gitlab-basics/create-project.md +++ b/doc/gitlab-basics/create-project.md @@ -1,6 +1,6 @@ # How to create a project in GitLab -To create a new project, sign in to [GitLab.com](https://gitlab.com). +To create a new project, sign in to GitLab. Go to your Dashboard and click on "new project" on the right side of your screen. diff --git a/doc/gitlab-basics/create-your-ssh-keys.md b/doc/gitlab-basics/create-your-ssh-keys.md index dcd3e6ffb31..c8a73feb028 100644 --- a/doc/gitlab-basics/create-your-ssh-keys.md +++ b/doc/gitlab-basics/create-your-ssh-keys.md @@ -6,7 +6,7 @@ You need to connect your computer to your GitLab account through SSH Keys. They Create an account on GitLab. Sign up and check your email for your confirmation link. -After you confirm, go to [GitLab.com](https://about.gitlab.com/) and sign in to your account. +After you confirm, go to GitLab and sign in to your account. ## Add your SSH Key diff --git a/doc/gitlab-basics/fork-project.md b/doc/gitlab-basics/fork-project.md index 5173aae2c0f..5f8b81ea919 100644 --- a/doc/gitlab-basics/fork-project.md +++ b/doc/gitlab-basics/fork-project.md @@ -6,7 +6,7 @@ publishing or not, without affecting your original project. It takes just a few steps to fork a project in GitLab. -Sign in to [gitlab.com](https://gitlab.com). +Sign in to GitLab. Select a project on the right side of your screen: diff --git a/doc/gitlab-basics/start-using-git.md b/doc/gitlab-basics/start-using-git.md index 5b1c6c1cd46..b2ceda025c0 100644 --- a/doc/gitlab-basics/start-using-git.md +++ b/doc/gitlab-basics/start-using-git.md @@ -1,6 +1,6 @@ # Start using Git on the command line -If you want to start using a Git and GitLab, make sure that you have created an account on [GitLab.com](https://about.gitlab.com/). +If you want to start using a Git and GitLab, make sure that you have created an account on GitLab. ## Open a shell From 8802846565f382f4bf21ff7e08a4e9c459bb10d6 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 31 Jul 2015 14:35:32 +0200 Subject: [PATCH 168/174] Fix indentation --- lib/api/users.rb | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/api/users.rb b/lib/api/users.rb index bd8cc9f16a8..ee29f952246 100644 --- a/lib/api/users.rb +++ b/lib/api/users.rb @@ -131,11 +131,11 @@ module API # Add ssh key to a specified user. Only available to admin users. # # Parameters: - # id (required) - The ID of a user - # key (required) - New SSH Key - # title (required) - New SSH Key's title + # id (required) - The ID of a user + # key (required) - New SSH Key + # title (required) - New SSH Key's title # Example Request: - # POST /users/:id/keys + # POST /users/:id/keys post ":id/keys" do authenticated_as_admin! required_attributes! [:title, :key] @@ -153,9 +153,9 @@ module API # Get ssh keys of a specified user. Only available to admin users. # # Parameters: - # uid (required) - The ID of a user + # uid (required) - The ID of a user # Example Request: - # GET /users/:uid/keys + # GET /users/:uid/keys get ':uid/keys' do authenticated_as_admin! user = User.find_by(id: params[:uid]) @@ -188,10 +188,10 @@ module API # Add email to a specified user. Only available to admin users. # # Parameters: - # id (required) - The ID of a user - # email (required) - Email address + # id (required) - The ID of a user + # email (required) - Email address # Example Request: - # POST /users/:id/emails + # POST /users/:id/emails post ":id/emails" do authenticated_as_admin! required_attributes! [:email] @@ -210,9 +210,9 @@ module API # Get emails of a specified user. Only available to admin users. # # Parameters: - # uid (required) - The ID of a user + # uid (required) - The ID of a user # Example Request: - # GET /users/:uid/emails + # GET /users/:uid/emails get ':uid/emails' do authenticated_as_admin! user = User.find_by(id: params[:uid]) From 1aa1f392482ac721e2fabf17e4b4a0cbc6493b0e Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Fri, 31 Jul 2015 17:44:16 -0400 Subject: [PATCH 169/174] Make `code` elements in links display as such Also adds some minor padding to inline `code` elements. --- app/assets/stylesheets/base/mixins.scss | 2 +- app/assets/stylesheets/generic/typography.scss | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/base/mixins.scss b/app/assets/stylesheets/base/mixins.scss index d64e79170b9..7beef1845ef 100644 --- a/app/assets/stylesheets/base/mixins.scss +++ b/app/assets/stylesheets/base/mixins.scss @@ -70,7 +70,7 @@ font-family: $monospace_font; white-space: pre; word-wrap: normal; - padding: 0; + padding: 1px 2px; } kbd { diff --git a/app/assets/stylesheets/generic/typography.scss b/app/assets/stylesheets/generic/typography.scss index 2db4213159a..34b4ee3e17e 100644 --- a/app/assets/stylesheets/generic/typography.scss +++ b/app/assets/stylesheets/generic/typography.scss @@ -38,6 +38,10 @@ code { } } +a > code { + color: $link-color; +} + /** * Wiki typography * From f33898ecfb7c5c15c8a3355dabe07cdff296fc75 Mon Sep 17 00:00:00 2001 From: Atsushi Ishida Date: Mon, 3 Aug 2015 01:52:54 +0900 Subject: [PATCH 170/174] Re-annotate models --- app/models/application_setting.rb | 5 +++-- app/models/audit_event.rb | 14 ++++++++++++++ app/models/project.rb | 3 ++- app/models/security_event.rb | 14 ++++++++++++++ app/models/user.rb | 1 + spec/factories/projects.rb | 3 ++- spec/models/application_setting_spec.rb | 5 ++++- spec/models/project_spec.rb | 3 ++- spec/models/user_spec.rb | 1 + 9 files changed, 43 insertions(+), 6 deletions(-) diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index fee52694099..6d1ad82a262 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -14,13 +14,14 @@ # default_branch_protection :integer default(2) # twitter_sharing_enabled :boolean default(TRUE) # restricted_visibility_levels :text +# version_check_enabled :boolean default(TRUE) # max_attachment_size :integer default(10), not null -# session_expire_delay :integer default(10080), not null # default_project_visibility :integer # default_snippet_visibility :integer # restricted_signup_domains :text -# user_oauth_applications :bool default(TRUE) +# user_oauth_applications :boolean default(TRUE) # after_sign_out_path :string(255) +# session_expire_delay :integer default(10080), not null # class ApplicationSetting < ActiveRecord::Base diff --git a/app/models/audit_event.rb b/app/models/audit_event.rb index 967ffd46db0..0ed0dd98a59 100644 --- a/app/models/audit_event.rb +++ b/app/models/audit_event.rb @@ -1,3 +1,17 @@ +# == Schema Information +# +# Table name: audit_events +# +# id :integer not null, primary key +# author_id :integer not null +# type :string(255) not null +# entity_id :integer not null +# entity_type :string(255) not null +# details :text +# created_at :datetime +# updated_at :datetime +# + class AuditEvent < ActiveRecord::Base serialize :details, Hash diff --git a/app/models/project.rb b/app/models/project.rb index 0921fdfe9b4..3dc1729e812 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -21,12 +21,13 @@ # import_url :string(255) # visibility_level :integer default(0), not null # archived :boolean default(FALSE), not null +# avatar :string(255) # import_status :string(255) # repository_size :float default(0.0) # star_count :integer default(0), not null # import_type :string(255) # import_source :string(255) -# avatar :string(255) +# commit_count :integer default(0) # require 'carrierwave/orm/activerecord' diff --git a/app/models/security_event.rb b/app/models/security_event.rb index d131c11cb6c..68c00adad59 100644 --- a/app/models/security_event.rb +++ b/app/models/security_event.rb @@ -1,2 +1,16 @@ +# == Schema Information +# +# Table name: audit_events +# +# id :integer not null, primary key +# author_id :integer not null +# type :string(255) not null +# entity_id :integer not null +# entity_type :string(255) not null +# details :text +# created_at :datetime +# updated_at :datetime +# + class SecurityEvent < AuditEvent end diff --git a/app/models/user.rb b/app/models/user.rb index 4a10520b209..2beefb1d614 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -57,6 +57,7 @@ # otp_backup_codes :text # public_email :string(255) default(""), not null # dashboard :integer default(0) +# project_view :integer default(0) # require 'carrierwave/orm/activerecord' diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index 102678a1d74..1d500a11ad7 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -21,12 +21,13 @@ # import_url :string(255) # visibility_level :integer default(0), not null # archived :boolean default(FALSE), not null +# avatar :string(255) # import_status :string(255) # repository_size :float default(0.0) # star_count :integer default(0), not null # import_type :string(255) # import_source :string(255) -# avatar :string(255) +# commit_count :integer default(0) # FactoryGirl.define do diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index d648f4078be..bc14ff98fd8 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -14,11 +14,14 @@ # default_branch_protection :integer default(2) # twitter_sharing_enabled :boolean default(TRUE) # restricted_visibility_levels :text +# version_check_enabled :boolean default(TRUE) # max_attachment_size :integer default(10), not null -# session_expire_delay :integer default(10080), not null # default_project_visibility :integer # default_snippet_visibility :integer # restricted_signup_domains :text +# user_oauth_applications :boolean default(TRUE) +# after_sign_out_path :string(255) +# session_expire_delay :integer default(10080), not null # require 'spec_helper' diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 1ffd92b9bd9..5d40754d59d 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -21,12 +21,13 @@ # import_url :string(255) # visibility_level :integer default(0), not null # archived :boolean default(FALSE), not null +# avatar :string(255) # import_status :string(255) # repository_size :float default(0.0) # star_count :integer default(0), not null # import_type :string(255) # import_source :string(255) -# avatar :string(255) +# commit_count :integer default(0) # require 'spec_helper' diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 76f16323e2f..922e9ebf844 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -57,6 +57,7 @@ # otp_backup_codes :text # public_email :string(255) default(""), not null # dashboard :integer default(0) +# project_view :integer default(0) # require 'spec_helper' From 8ec7025a5d49548c1876440c1bd9b767828a5f56 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Mon, 3 Aug 2015 11:33:48 +0000 Subject: [PATCH 171/174] Link to admin raketask --- doc/raketasks/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/raketasks/README.md b/doc/raketasks/README.md index 770b7a70fe0..a8dc5c24df2 100644 --- a/doc/raketasks/README.md +++ b/doc/raketasks/README.md @@ -7,3 +7,4 @@ - [User management](user_management.md) - [Web hooks](web_hooks.md) - [Import](import.md) of git repositories in bulk +- [Rebuild authorized_keys file](http://doc.gitlab.com/ce/raketasks/maintenance.html#rebuild-authorized_keys-file) task for administrators \ No newline at end of file From 8221236df1acd1d38f36e79f248bc4fff3474839 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sun, 2 Aug 2015 22:36:34 -0700 Subject: [PATCH 172/174] Update merge request text to reflect editability of source/target branch Closes #2134 --- .../merge_requests/widget/open/_missing_branch.html.haml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/views/projects/merge_requests/widget/open/_missing_branch.html.haml b/app/views/projects/merge_requests/widget/open/_missing_branch.html.haml index 423fcd48e25..1c565bae80a 100644 --- a/app/views/projects/merge_requests/widget/open/_missing_branch.html.haml +++ b/app/views/projects/merge_requests/widget/open/_missing_branch.html.haml @@ -6,9 +6,11 @@ %span.label.label-inverse= @merge_request.source_branch does not exist in %span.label.label-info= @merge_request.source_project_path + %br + %strong Please close this merge request and open a new merge request to change source branches. - else %span.label.label-inverse= @merge_request.target_branch does not exist in %span.label.label-info= @merge_request.target_project_path - %br - %strong Please close this merge request or change branches with existing one + %br + %strong Please close this merge request or change to another target branch. From 28cc6d9b9860fb38fc68d05c40d552d3a46e7ac8 Mon Sep 17 00:00:00 2001 From: karen Carias Date: Mon, 3 Aug 2015 15:51:09 -0700 Subject: [PATCH 173/174] text fixed --- doc/permissions/permissions.md | 2 +- doc/workflow/add-user/add-user.md | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/permissions/permissions.md b/doc/permissions/permissions.md index 029d446640d..7a6a1958445 100644 --- a/doc/permissions/permissions.md +++ b/doc/permissions/permissions.md @@ -6,7 +6,7 @@ If a user is both in a project group and in the project itself, the highest perm If a user is a GitLab administrator they receive all permissions. -To add or import a user or member, you can follow the [project users and members +To add or import a user, you can follow the [project users and members documentation](doc/workflow/add-user/add-user.md). ## Project diff --git a/doc/workflow/add-user/add-user.md b/doc/workflow/add-user/add-user.md index 58f7bd0a5ce..8c9b4f72631 100644 --- a/doc/workflow/add-user/add-user.md +++ b/doc/workflow/add-user/add-user.md @@ -1,13 +1,13 @@ -# Project users and members +# Project users -You can add or import users to your projects. You can also give them different access -levels. +You can manage the groups and users and their access levels in all of your projects. You can also personalize the access level you give each user, per project. -You should have 'master' or 'owner' permissions to add or import a new user to your -project. +Here's how to add or import users to your projects. -To add or import a user, go to your project and click on "Members" on the left side -of your screen: +You should have 'master' or 'owner' permissions to add or import a new user +to your project. + +To add or import a user, go to your project and click on "Members" on the left side of your screen: ![Members](images/members.png) From c5a6c16dba66318ea7f36b368217a275f1dd24e8 Mon Sep 17 00:00:00 2001 From: karen Carias Date: Mon, 3 Aug 2015 15:55:02 -0700 Subject: [PATCH 174/174] typo --- doc/workflow/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/workflow/README.md b/doc/workflow/README.md index 139f4db7d57..3915198ad2a 100644 --- a/doc/workflow/README.md +++ b/doc/workflow/README.md @@ -10,7 +10,7 @@ - [Notification emails](notifications.md) - [Project Features](project_features.md) - [Project forking workflow](forking_workflow.md) -- [Project users and members](add-user/add-user.md) +- [Project users](add-user/add-user.md) - [Protected branches](protected_branches.md) - [Web Editor](web_editor.md) - ["Work In Progress" Merge Requests](wip_merge_requests.md)