Commit e16eb912990770c9e5bddece966d2988ed7fa575

Authored by Marin Jankovski
2 parents e130e2f6 80b11370

Merge branch 'master' into relative

.travis.yml
... ... @@ -9,7 +9,6 @@ env:
9 9 - TASK=jasmine:ci
10 10 before_install:
11 11 - sudo apt-get install libicu-dev -y
12   - - gem install charlock_holmes -v="0.6.9"
13 12 branches:
14 13 only:
15 14 - 'master'
... ...
CONTRIBUTING.md
... ... @@ -9,6 +9,10 @@ This guide details how to use issues and pull requests to improve GitLab.
9 9  
10 10 If you want to know how the GitLab team handles contributions have a look at [the GitLab contributing process](PROCESS.md).
11 11  
  12 +## Contributor license agreement
  13 +
  14 +By submitting code as an individual you agree to the [individual contributor license agreement](doc/legal/individual_contributor_license_agreement.md). By submitting code as an entity you agree to the [corporate contributor license agreement](doc/legal/corporate_contributor_license_agreement.md).
  15 +
12 16 ## Closing policy for issues and pull requests
13 17  
14 18 GitLab is a popular open source project and the capacity to deal with issues and pull requests is limited. Out of respect for our volunteers, issues and pull requests not in line with the guidelines listed in this document may be closed without notice.
... ...
README.md
... ... @@ -64,9 +64,10 @@ If you want to contribute, please first read our [Contributing Guidelines](https
64 64  
65 65 * [Installation guides](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Unofficial-Installation-Guides) public wiki with unofficial guides to install GitLab on different operating systems.
66 66  
67   -* [BitNami one-click installers](http://bitnami.com/stack/gitlab)
68 67  
69   -* [TurnKey Linux virtual appliance](http://www.turnkeylinux.org/gitlab)
  68 +* [Digital Ocean 1-Click Application Install](https://www.digitalocean.com/) Have a new server up in 55 seconds. Digital Ocean uses SSD disks which is great for an IO intensive app as GitLab. Look for GitLab under 'Select Image' => 'Applications' when creating a droplet.
  69 +
  70 +* [BitNami one-click installers](http://bitnami.com/stack/gitlab) Get an image with GitLab and GitLab CI preinstalled for Amazon Web Services, Azure, VMware or your local server.
70 71  
71 72  
72 73 ### New versions and upgrading
... ...
app/assets/javascripts/notes.js
... ... @@ -233,10 +233,12 @@ var NoteList = {
233 233 form.show();
234 234  
235 235 var textarea = form.find("textarea");
236   - var p = $("<p></p>").text(textarea.val());
237   - var hidden_div = $('<div class="note-original-content"></div>').append(p);
238   - form.append(hidden_div);
239   - hidden_div.hide();
  236 + if (form.find(".note-original-content").length === 0) {
  237 + var p = $("<p></p>").text(textarea.val());
  238 + var hidden_div = $('<div class="note-original-content"></div>').append(p);
  239 + form.append(hidden_div);
  240 + hidden_div.hide();
  241 + }
240 242 textarea.focus();
241 243 },
242 244  
... ... @@ -532,6 +534,8 @@ var NoteList = {
532 534 note_text.html(response.note).show();
533 535  
534 536 var note_form = note_li.find(".note-edit-form");
  537 + var original_content = note_form.find(".note-original-content");
  538 + original_content.remove();
535 539 note_form.hide();
536 540 note_form.find(".btn-save").enableButton();
537 541  
... ...
app/assets/javascripts/project.js.coffee
... ... @@ -40,3 +40,8 @@ $ -&gt;
40 40 # Ref switcher
41 41 $('.project-refs-select').on 'change', ->
42 42 $(@).parents('form').submit()
  43 +
  44 + $('.hide-no-ssh-message').on 'click', (e) ->
  45 + $.cookie('hide_no_ssh_message', 'false')
  46 + $(@).parents('.no-ssh-key-message').hide()
  47 + e.preventDefault()
... ...
app/assets/stylesheets/common.scss
... ... @@ -220,7 +220,6 @@ li.note {
220 220 .error-message {
221 221 padding: 10px;
222 222 background: #C67;
223   - padding-left: 20px;
224 223 margin: 0;
225 224 color: #FFF;
226 225  
... ... @@ -228,8 +227,18 @@ li.note {
228 227 color: #fff;
229 228 text-decoration: underline;
230 229 }
231   - &.centered {
232   - text-align: center;
  230 +}
  231 +
  232 +.no-ssh-key-message {
  233 + padding: 10px 0;
  234 + background: #C67;
  235 + margin: 0;
  236 + color: #FFF;
  237 + text-align: center;
  238 +
  239 + a {
  240 + color: #fff;
  241 + text-decoration: underline;
233 242 }
234 243 }
235 244  
... ...
app/contexts/files/create_context.rb
... ... @@ -33,11 +33,10 @@ module Files
33 33 return error("Your changes could not be commited, because file with such name exists")
34 34 end
35 35  
36   - new_file_action = Gitlab::Satellite::NewFileAction.new(current_user, project, ref, path)
  36 + new_file_action = Gitlab::Satellite::NewFileAction.new(current_user, project, ref, file_path)
37 37 created_successfully = new_file_action.commit!(
38 38 params[:content],
39   - params[:commit_message],
40   - file_name,
  39 + params[:commit_message]
41 40 )
42 41  
43 42 if created_successfully
... ...
app/contexts/files/update_context.rb
... ... @@ -24,8 +24,7 @@ module Files
24 24 new_file_action = Gitlab::Satellite::EditFileAction.new(current_user, project, ref, path)
25 25 created_successfully = new_file_action.commit!(
26 26 params[:content],
27   - params[:commit_message],
28   - params[:last_commit]
  27 + params[:commit_message]
29 28 )
30 29  
31 30 if created_successfully
... ...
app/mailers/emails/groups.rb
... ... @@ -5,7 +5,7 @@ module Emails
5 5 @group = @membership.group
6 6  
7 7 mail(to: @membership.user.email,
8   - subject: subject("access to group was granted"))
  8 + subject: subject("Access to group was granted"))
9 9 end
10 10 end
11 11 end
... ...
app/mailers/emails/issues.rb
... ... @@ -3,14 +3,14 @@ module Emails
3 3 def new_issue_email(recipient_id, issue_id)
4 4 @issue = Issue.find(issue_id)
5 5 @project = @issue.project
6   - mail(to: recipient(recipient_id), subject: subject("new issue ##{@issue.iid}", @issue.title))
  6 + mail(to: recipient(recipient_id), subject: subject("New issue ##{@issue.iid}", @issue.title))
7 7 end
8 8  
9 9 def reassigned_issue_email(recipient_id, issue_id, previous_assignee_id)
10 10 @issue = Issue.find(issue_id)
11 11 @previous_assignee = User.find_by_id(previous_assignee_id) if previous_assignee_id
12 12 @project = @issue.project
13   - mail(to: recipient(recipient_id), subject: subject("changed issue ##{@issue.iid}", @issue.title))
  13 + mail(to: recipient(recipient_id), subject: subject("Changed issue ##{@issue.iid}", @issue.title))
14 14 end
15 15  
16 16 def closed_issue_email(recipient_id, issue_id, updated_by_user_id)
... ... @@ -27,7 +27,7 @@ module Emails
27 27 @project = @issue.project
28 28 @updated_by = User.find updated_by_user_id
29 29 mail(to: recipient(recipient_id),
30   - subject: subject("changed issue ##{@issue.iid}", @issue.title))
  30 + subject: subject("Changed issue ##{@issue.iid}", @issue.title))
31 31 end
32 32 end
33 33 end
... ...
app/mailers/emails/merge_requests.rb
... ... @@ -2,24 +2,24 @@ module Emails
2 2 module MergeRequests
3 3 def new_merge_request_email(recipient_id, merge_request_id)
4 4 @merge_request = MergeRequest.find(merge_request_id)
5   - mail(to: recipient(recipient_id), subject: subject("new merge request !#{@merge_request.iid}", @merge_request.title))
  5 + mail(to: recipient(recipient_id), subject: subject("New merge request ##{@merge_request.iid}", @merge_request.title))
6 6 end
7 7  
8 8 def reassigned_merge_request_email(recipient_id, merge_request_id, previous_assignee_id)
9 9 @merge_request = MergeRequest.find(merge_request_id)
10 10 @previous_assignee = User.find_by_id(previous_assignee_id) if previous_assignee_id
11   - mail(to: recipient(recipient_id), subject: subject("changed merge request !#{@merge_request.iid}", @merge_request.title))
  11 + mail(to: recipient(recipient_id), subject: subject("Changed merge request ##{@merge_request.iid}", @merge_request.title))
12 12 end
13 13  
14 14 def closed_merge_request_email(recipient_id, merge_request_id, updated_by_user_id)
15 15 @merge_request = MergeRequest.find(merge_request_id)
16 16 @updated_by = User.find updated_by_user_id
17   - mail(to: recipient(recipient_id), subject: subject("Closed merge request !#{@merge_request.iid}", @merge_request.title))
  17 + mail(to: recipient(recipient_id), subject: subject("Closed merge request ##{@merge_request.iid}", @merge_request.title))
18 18 end
19 19  
20 20 def merged_merge_request_email(recipient_id, merge_request_id)
21 21 @merge_request = MergeRequest.find(merge_request_id)
22   - mail(to: recipient(recipient_id), subject: subject("Accepted merge request !#{@merge_request.iid}", @merge_request.title))
  22 + mail(to: recipient(recipient_id), subject: subject("Accepted merge request ##{@merge_request.iid}", @merge_request.title))
23 23 end
24 24 end
25 25  
... ...
app/mailers/emails/notes.rb
... ... @@ -4,27 +4,27 @@ module Emails
4 4 @note = Note.find(note_id)
5 5 @commit = @note.noteable
6 6 @project = @note.project
7   - mail(to: recipient(recipient_id), subject: subject("note for commit #{@commit.short_id}", @commit.title))
  7 + mail(to: recipient(recipient_id), subject: subject("Note for commit #{@commit.short_id}", @commit.title))
8 8 end
9 9  
10 10 def note_issue_email(recipient_id, note_id)
11 11 @note = Note.find(note_id)
12 12 @issue = @note.noteable
13 13 @project = @note.project
14   - mail(to: recipient(recipient_id), subject: subject("note for issue ##{@issue.iid}"))
  14 + mail(to: recipient(recipient_id), subject: subject("Note for issue ##{@issue.iid}"))
15 15 end
16 16  
17 17 def note_merge_request_email(recipient_id, note_id)
18 18 @note = Note.find(note_id)
19 19 @merge_request = @note.noteable
20 20 @project = @note.project
21   - mail(to: recipient(recipient_id), subject: subject("note for merge request ##{@merge_request.iid}"))
  21 + mail(to: recipient(recipient_id), subject: subject("Note for merge request ##{@merge_request.iid}"))
22 22 end
23 23  
24 24 def note_wall_email(recipient_id, note_id)
25 25 @note = Note.find(note_id)
26 26 @project = @note.project
27   - mail(to: recipient(recipient_id), subject: subject("note on wall"))
  27 + mail(to: recipient(recipient_id), subject: subject("Note on wall"))
28 28 end
29 29 end
30 30 end
... ...
app/mailers/emails/projects.rb
... ... @@ -4,14 +4,14 @@ module Emails
4 4 @users_project = UsersProject.find user_project_id
5 5 @project = @users_project.project
6 6 mail(to: @users_project.user.email,
7   - subject: subject("access to project was granted"))
  7 + subject: subject("Access to project was granted"))
8 8 end
9 9  
10 10 def project_was_moved_email(project_id, user_id)
11 11 @user = User.find user_id
12 12 @project = Project.find project_id
13 13 mail(to: @user.email,
14   - subject: subject("project was moved"))
  14 + subject: subject("Project was moved"))
15 15 end
16 16 end
17 17 end
... ...
app/models/issue.rb
... ... @@ -21,6 +21,8 @@ class Issue &lt; ActiveRecord::Base
21 21 include Issuable
22 22 include InternalId
23 23  
  24 + ActsAsTaggableOn.strict_case_match = true
  25 +
24 26 belongs_to :project
25 27 validates :project, presence: true
26 28  
... ...
app/models/project.rb
... ... @@ -27,6 +27,8 @@
27 27 class Project < ActiveRecord::Base
28 28 include Gitlab::ShellAdapter
29 29 extend Enumerize
  30 +
  31 + ActsAsTaggableOn.strict_case_match = true
30 32  
31 33 attr_accessible :name, :path, :description, :issues_tracker, :label_list,
32 34 :issues_enabled, :wall_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id,
... ...
app/views/notify/_note_message.html.haml
1 1 %p
2 2 %strong #{@note.author_name}
3   - left next message:
  3 + wrote:
4 4  
5 5 %cite{style: 'color: #666'}
6 6 = markdown(@note.note)
... ...
app/views/notify/new_merge_request_email.html.haml
1 1 %p
2   - = "New Merge Request !#{@merge_request.iid}"
  2 + = "New Merge Request ##{@merge_request.iid}"
3 3 %p
4 4 = link_to_gfm truncate(@merge_request.title, length: 40), project_merge_request_url(@merge_request.target_project, @merge_request)
5 5 %p
... ...
app/views/notify/new_merge_request_email.text.erb
1   -New Merge Request <%= @merge_request.iid %>
  1 +New Merge Request #<%= @merge_request.iid %>
2 2  
3 3 <%= url_for(project_merge_request_url(@merge_request.target_project, @merge_request)) %>
4 4  
... ...
app/views/notify/reassigned_merge_request_email.html.haml
1 1 %p
2   - = "Reassigned Merge Request !#{@merge_request.iid}"
  2 + = "Reassigned Merge Request ##{@merge_request.iid}"
3 3 = link_to_gfm truncate(@merge_request.title, length: 30), project_merge_request_url(@merge_request.target_project, @merge_request)
4 4 %p
5 5 Assignee changed
... ...
app/views/notify/reassigned_merge_request_email.text.erb
1   -Reassigned Merge Request <%= @merge_request.iid %>
  1 +Reassigned Merge Request #<%= @merge_request.iid %>
2 2  
3 3 <%= url_for(project_merge_request_url(@merge_request.target_project, @merge_request)) %>
4 4  
... ...
app/views/shared/_no_ssh.html.haml
1   -- if current_user.require_ssh_key? && alert.blank? && notice.blank?
2   - %p.error-message.centered
3   - You won't be able to pull or push project code via SSH until you #{link_to 'add an SSH key', new_profile_key_path} to your profile
  1 +- if cookies[:hide_no_ssh_message].blank? && current_user.require_ssh_key?
  2 + .no-ssh-key-message
  3 + .container
  4 + You won't be able to pull or push project code via SSH until you #{link_to 'add an SSH key', new_profile_key_path} to your profile
  5 + = link_to '#', class: 'pull-right hide-no-ssh-message' do
  6 + %i.icon-remove
... ...
config/application.rb
... ... @@ -78,7 +78,6 @@ module Gitlab
78 78 #
79 79 # config.relative_url_root = "/gitlab"
80 80  
81   - # Uncomment to enable rack attack middleware
82   - # config.middleware.use Rack::Attack
  81 + config.middleware.use Rack::Attack
83 82 end
84 83 end
... ...
config/gitlab.yml.example
... ... @@ -59,7 +59,7 @@ production: &amp;base
59 59 # If a commit message matches this regular expression, all issues referenced from the matched text will be closed.
60 60 # This happends when the commit is pushed or merged into the default branch of a project.
61 61 # When not specified the default issue_closing_pattern as specified below will be used.
62   - # issue_closing_pattern: ([Cc]loses|[Ff]ixes) +#\d+
  62 + # issue_closing_pattern: ([Cc]lose[sd]|[Ff]ixe[sd]) +#\d+
63 63  
64 64 ## Default project features settings
65 65 default_projects_features:
... ...
config/initializers/rack_attack.rb.example
1   -# To enable rack-attack for your GitLab instance do the following:
2   -# 1. In config/application.rb find and uncomment the following line:
3   -# config.middleware.use Rack::Attack
4   -# 2. Rename this file to rack_attack.rb
5   -# 3. Review the paths_to_be_protected and add any other path you need protecting
6   -# 4. Restart GitLab instance
  1 +# 1. Rename this file to rack_attack.rb
  2 +# 2. Review the paths_to_be_protected and add any other path you need protecting
7 3 #
8 4  
9 5 paths_to_be_protected = [
... ...
doc/api/repositories.md
... ... @@ -368,4 +368,32 @@ GET /projects/:id/repository/archive
368 368  
369 369 Parameters:
370 370 + `id` (required) - The ID of a project
371   -+ `sha` (optional) - The commit sha to download defaults to the tip of the default branch
372 371 \ No newline at end of file
  372 ++ `sha` (optional) - The commit sha to download defaults to the tip of the default branch
  373 +
  374 +
  375 +## Create new file in repository
  376 +
  377 +```
  378 +POST /projects/:id/repository/files
  379 +```
  380 +
  381 +Parameters:
  382 +
  383 ++ `file_name` (required) - The name of new file. Ex. class.rb
  384 ++ `file_path` (optional) - The path to new file. Ex. lib/
  385 ++ `branch_name` (required) - The name of branch
  386 ++ `content` (required) - File content
  387 ++ `commit_message` (required) - Commit message
  388 +
  389 +## Update existing file in repository
  390 +
  391 +```
  392 +PUT /projects/:id/repository/files
  393 +```
  394 +
  395 +Parameters:
  396 +
  397 ++ `file_path` (required) - Full path to file. Ex. lib/class.rb
  398 ++ `branch_name` (required) - The name of branch
  399 ++ `content` (required) - New file content
  400 ++ `commit_message` (required) - Commit message
... ...
doc/install/installation.md
... ... @@ -227,10 +227,6 @@ You can change `6-2-stable` to `master` if you want the *bleeding edge* version,
227 227 # Copy the example Rack attack config
228 228 sudo -u git -H cp config/initializers/rack_attack.rb.example config/initializers/rack_attack.rb
229 229  
230   - # Enable rack attack middleware
231   - # Find and uncomment the line 'config.middleware.use Rack::Attack'
232   - sudo -u git -H editor config/application.rb
233   -
234 230 # Configure Git global settings for git user, useful when editing via web
235 231 # Edit user.email according to what is set in gitlab.yml
236 232 sudo -u git -H git config --global user.name "GitLab"
... ... @@ -265,8 +261,6 @@ Make sure to edit both `gitlab.yml` and `unicorn.rb` to match your setup.
265 261  
266 262 cd /home/git/gitlab
267 263  
268   - sudo gem install charlock_holmes --version '0.6.9.4'
269   -
270 264 # For MySQL (note, the option says "without ... postgres")
271 265 sudo -u git -H bundle install --deployment --without development test postgres aws
272 266  
... ...
doc/legal/corporate_contributor_license_agreement.md 0 → 100644
... ... @@ -0,0 +1,25 @@
  1 +You accept and agree to the following terms and conditions for Your present and future Contributions submitted to GitLab.com. Except for the license granted herein to GitLab.com and recipients of software distributed by GitLab.com, You reserve all right, title, and interest in and to Your Contributions.
  2 +
  3 +1. Definitions.
  4 +
  5 + "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with GitLab.com. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
  6 +
  7 + "Contribution" shall mean the code, documentation or other original works of authorship expressly identified in Schedule B, as well as any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to GitLab.com for inclusion in, or documentation of, any of the products owned or managed by GitLab.com (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to GitLab.com or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, GitLab.com for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution."
  8 +
  9 +2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to GitLab.com and to recipients of software distributed by GitLab.com a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works.
  10 +
  11 +3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to GitLab.com and to recipients of software distributed by GitLab.com a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed.
  12 +
  13 +4. You represent that You are legally entitled to grant the above license. You represent further that each employee of the Corporation designated on Schedule A below (or in a subsequent written modification to that Schedule) is authorized to submit Contributions on behalf of the Corporation.
  14 +
  15 +5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others).
  16 +
  17 +6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.
  18 +
  19 +7. Should You wish to submit work that is not Your original creation, You may submit it to GitLab.com separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]".
  20 +
  21 +8. It is your responsibility to notify GitLab.com when any change is required to the list of designated employees authorized to submit Contributions on behalf of the Corporation, or to the Corporation's Point of Contact with GitLab.com.
  22 +
  23 +---------------------------------------
  24 +
  25 +This text is licensed under the [Creative Commons Attribution 3.0 License](http://creativecommons.org/licenses/by/3.0/) and the original source is the Google Open Source Programs Office.
... ...
doc/legal/individual_contributor_license_agreement.md 0 → 100644
... ... @@ -0,0 +1,25 @@
  1 +You accept and agree to the following terms and conditions for Your present and future Contributions submitted to GitLab.com. Except for the license granted herein to GitLab.com and recipients of software distributed by GitLab.com, You reserve all right, title, and interest in and to Your Contributions.
  2 +
  3 +1. Definitions.
  4 +
  5 + "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with GitLab.com. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
  6 +
  7 + "Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to GitLab.com for inclusion in, or documentation of, any of the products owned or managed by GitLab.com (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to GitLab.com or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, GitLab.com for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution."
  8 +
  9 +2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to GitLab.com and to recipients of software distributed by GitLab.com a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works.
  10 +
  11 +3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to GitLab.com and to recipients of software distributed by GitLab.com a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed.
  12 +
  13 +4. You represent that you are legally entitled to grant the above license. If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to GitLab.com, or that your employer has executed a separate Corporate CLA with GitLab.com.
  14 +
  15 +5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions.
  16 +
  17 +6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON- INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.
  18 +
  19 +7. Should You wish to submit work that is not Your original creation, You may submit it to GitLab.com separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [[]named here]".
  20 +
  21 +8. You agree to notify GitLab.com of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect.
  22 +
  23 +---------------------------------------
  24 +
  25 +This text is licensed under the [Creative Commons Attribution 3.0 License](http://creativecommons.org/licenses/by/3.0/) and the original source is the Google Open Source Programs Office.
... ...
lib/api/api.rb
... ... @@ -39,5 +39,6 @@ module API
39 39 mount DeployKeys
40 40 mount ProjectHooks
41 41 mount Services
  42 + mount Files
42 43 end
43 44 end
... ...
lib/api/files.rb 0 → 100644
... ... @@ -0,0 +1,73 @@
  1 +module API
  2 + # Projects API
  3 + class Files < Grape::API
  4 + before { authenticate! }
  5 + before { authorize! :push_code, user_project }
  6 +
  7 + resource :projects do
  8 + # Create new file in repository
  9 + #
  10 + # Parameters:
  11 + # file_name (required) - The name of new file. Ex. class.rb
  12 + # file_path (optional) - The path to new file. Ex. lib/
  13 + # branch_name (required) - The name of branch
  14 + # content (required) - File content
  15 + # commit_message (required) - Commit message
  16 + #
  17 + # Example Request:
  18 + # POST /projects/:id/repository/files
  19 + #
  20 + post ":id/repository/files" do
  21 + required_attributes! [:file_name, :branch_name, :content, :commit_message]
  22 + attrs = attributes_for_keys [:file_name, :file_path, :branch_name, :content, :commit_message]
  23 + branch_name = attrs.delete(:branch_name)
  24 + file_path = attrs.delete(:file_path)
  25 + result = ::Files::CreateContext.new(user_project, current_user, attrs, branch_name, file_path).execute
  26 +
  27 + if result[:status] == :success
  28 + status(201)
  29 +
  30 + {
  31 + file_name: attrs[:file_name],
  32 + file_path: file_path,
  33 + branch_name: branch_name
  34 + }
  35 + else
  36 + render_api_error!(result[:error], 400)
  37 + end
  38 + end
  39 +
  40 + # Update existing file in repository
  41 + #
  42 + # Parameters:
  43 + # file_name (required) - The name of new file. Ex. class.rb
  44 + # file_path (optional) - The path to new file. Ex. lib/
  45 + # branch_name (required) - The name of branch
  46 + # content (required) - File content
  47 + # commit_message (required) - Commit message
  48 + #
  49 + # Example Request:
  50 + # PUT /projects/:id/repository/files
  51 + #
  52 + put ":id/repository/files" do
  53 + required_attributes! [:file_path, :branch_name, :content, :commit_message]
  54 + attrs = attributes_for_keys [:file_path, :branch_name, :content, :commit_message]
  55 + branch_name = attrs.delete(:branch_name)
  56 + file_path = attrs.delete(:file_path)
  57 + result = ::Files::UpdateContext.new(user_project, current_user, attrs, branch_name, file_path).execute
  58 +
  59 + if result[:status] == :success
  60 + status(200)
  61 +
  62 + {
  63 + file_path: file_path,
  64 + branch_name: branch_name
  65 + }
  66 + else
  67 + render_api_error!(result[:error], 400)
  68 + end
  69 + end
  70 + end
  71 + end
  72 +end
  73 +
... ...
lib/api/helpers.rb
... ... @@ -6,19 +6,23 @@ module API
6 6 SUDO_PARAM = :sudo
7 7  
8 8 def current_user
9   - @current_user ||= User.find_by_authentication_token(params[PRIVATE_TOKEN_PARAM] || env[PRIVATE_TOKEN_HEADER])
  9 + private_token = (params[PRIVATE_TOKEN_PARAM] || env[PRIVATE_TOKEN_HEADER]).to_s
  10 + @current_user ||= User.find_by_authentication_token(private_token)
10 11 identifier = sudo_identifier()
  12 +
11 13 # If the sudo is the current user do nothing
12 14 if (identifier && !(@current_user.id == identifier || @current_user.username == identifier))
13 15 render_api_error!('403 Forbidden: Must be admin to use sudo', 403) unless @current_user.is_admin?
14 16 @current_user = User.by_username_or_id(identifier)
15 17 not_found!("No user id or username for: #{identifier}") if @current_user.nil?
16 18 end
  19 +
17 20 @current_user
18 21 end
19 22  
20 23 def sudo_identifier()
21 24 identifier ||= params[SUDO_PARAM] ||= env[SUDO_HEADER]
  25 +
22 26 # Regex for integers
23 27 if (!!(identifier =~ /^[0-9]+$/))
24 28 identifier.to_i
... ... @@ -29,6 +33,7 @@ module API
29 33  
30 34 def set_current_user_for_thread
31 35 Thread.current[:current_user] = current_user
  36 +
32 37 begin
33 38 yield
34 39 ensure
... ...
lib/gitlab/satellite/files/edit_file_action.rb
... ... @@ -10,9 +10,7 @@ module Gitlab
10 10 # Returns false if committing the change fails
11 11 # Returns false if pushing from the satellite to Gitolite failed or was rejected
12 12 # Returns true otherwise
13   - def commit!(content, commit_message, last_commit)
14   - return false unless can_edit?(last_commit)
15   -
  13 + def commit!(content, commit_message)
16 14 in_locked_and_timed_satellite do |repo|
17 15 prepare_satellite!(repo)
18 16  
... ...
lib/gitlab/satellite/files/file_action.rb
... ... @@ -8,13 +8,6 @@ module Gitlab
8 8 @file_path = file_path
9 9 @ref = ref
10 10 end
11   -
12   - protected
13   -
14   - def can_edit?(last_commit)
15   - current_last_commit = Gitlab::Git::Commit.last_for_path(@project.repository, ref, file_path).sha
16   - last_commit == current_last_commit
17   - end
18 11 end
19 12 end
20 13 end
... ...
lib/gitlab/satellite/files/new_file_action.rb
... ... @@ -9,7 +9,7 @@ module Gitlab
9 9 # Returns false if committing the change fails
10 10 # Returns false if pushing from the satellite to Gitolite failed or was rejected
11 11 # Returns true otherwise
12   - def commit!(content, commit_message, file_name)
  12 + def commit!(content, commit_message)
13 13 in_locked_and_timed_satellite do |repo|
14 14 prepare_satellite!(repo)
15 15  
... ... @@ -17,7 +17,7 @@ module Gitlab
17 17 repo.git.checkout({raise: true, timeout: true, b: true}, ref, "origin/#{ref}")
18 18  
19 19 # update the file in the satellite's working dir
20   - file_path_in_satellite = File.join(repo.working_dir, file_path, file_name)
  20 + file_path_in_satellite = File.join(repo.working_dir, file_path)
21 21 File.open(file_path_in_satellite, 'w') { |f| f.write(content) }
22 22  
23 23 # add new file
... ...
spec/mailers/notify_spec.rb
... ... @@ -110,7 +110,7 @@ describe Notify do
110 110 it_behaves_like 'an assignee email'
111 111  
112 112 it 'has the correct subject' do
113   - should have_subject /#{project.name} \| new issue ##{issue.iid} \| #{issue.title}/
  113 + should have_subject /#{project.name} \| New issue ##{issue.iid} \| #{issue.title}/
114 114 end
115 115  
116 116 it 'contains a link to the new issue' do
... ... @@ -126,7 +126,7 @@ describe Notify do
126 126 it_behaves_like 'a multiple recipients email'
127 127  
128 128 it 'has the correct subject' do
129   - should have_subject /changed issue ##{issue.iid} \| #{issue.title}/
  129 + should have_subject /Changed issue ##{issue.iid} \| #{issue.title}/
130 130 end
131 131  
132 132 it 'contains the name of the previous assignee' do
... ... @@ -148,7 +148,7 @@ describe Notify do
148 148 subject { Notify.issue_status_changed_email(recipient.id, issue.id, status, current_user) }
149 149  
150 150 it 'has the correct subject' do
151   - should have_subject /changed issue ##{issue.iid} \| #{issue.title}/i
  151 + should have_subject /Changed issue ##{issue.iid} \| #{issue.title}/i
152 152 end
153 153  
154 154 it 'contains the new status' do
... ... @@ -175,7 +175,7 @@ describe Notify do
175 175 it_behaves_like 'an assignee email'
176 176  
177 177 it 'has the correct subject' do
178   - should have_subject /new merge request !#{merge_request.iid}/
  178 + should have_subject /New merge request ##{merge_request.iid}/
179 179 end
180 180  
181 181 it 'contains a link to the new merge request' do
... ... @@ -199,7 +199,7 @@ describe Notify do
199 199 it_behaves_like 'a multiple recipients email'
200 200  
201 201 it 'has the correct subject' do
202   - should have_subject /changed merge request !#{merge_request.iid}/
  202 + should have_subject /Changed merge request ##{merge_request.iid}/
203 203 end
204 204  
205 205 it 'contains the name of the previous assignee' do
... ... @@ -224,7 +224,7 @@ describe Notify do
224 224 subject { Notify.project_was_moved_email(project.id, user.id) }
225 225  
226 226 it 'has the correct subject' do
227   - should have_subject /project was moved/
  227 + should have_subject /Project was moved/
228 228 end
229 229  
230 230 it 'contains name of project' do
... ... @@ -244,7 +244,7 @@ describe Notify do
244 244 user: user) }
245 245 subject { Notify.project_access_granted_email(users_project.id) }
246 246 it 'has the correct subject' do
247   - should have_subject /access to project was granted/
  247 + should have_subject /Access to project was granted/
248 248 end
249 249 it 'contains name of project' do
250 250 should have_body_text /#{project.name}/
... ... @@ -302,7 +302,7 @@ describe Notify do
302 302 it_behaves_like 'a note email'
303 303  
304 304 it 'has the correct subject' do
305   - should have_subject /note for commit #{commit.short_id}/
  305 + should have_subject /Note for commit #{commit.short_id}/
306 306 end
307 307  
308 308 it 'contains a link to the commit' do
... ... @@ -320,7 +320,7 @@ describe Notify do
320 320 it_behaves_like 'a note email'
321 321  
322 322 it 'has the correct subject' do
323   - should have_subject /note for merge request ##{merge_request.iid}/
  323 + should have_subject /Note for merge request ##{merge_request.iid}/
324 324 end
325 325  
326 326 it 'contains a link to the merge request note' do
... ... @@ -338,7 +338,7 @@ describe Notify do
338 338 it_behaves_like 'a note email'
339 339  
340 340 it 'has the correct subject' do
341   - should have_subject /note for issue ##{issue.iid}/
  341 + should have_subject /Note for issue ##{issue.iid}/
342 342 end
343 343  
344 344 it 'contains a link to the issue note' do
... ... @@ -356,7 +356,7 @@ describe Notify do
356 356 subject { Notify.group_access_granted_email(membership.id) }
357 357  
358 358 it 'has the correct subject' do
359   - should have_subject /access to group was granted/
  359 + should have_subject /Access to group was granted/
360 360 end
361 361  
362 362 it 'contains name of project' do
... ... @@ -367,4 +367,28 @@ describe Notify do
367 367 should have_body_text /#{membership.human_access}/
368 368 end
369 369 end
  370 +
  371 + describe 'confirmation if email changed' do
  372 + let(:example_site_path) { root_path }
  373 + let(:user) { create(:user, email: 'old-email@mail.com') }
  374 +
  375 + before do
  376 + user.email = "new-email@mail.com"
  377 + user.save
  378 + end
  379 +
  380 + subject { ActionMailer::Base.deliveries.last }
  381 +
  382 + it 'is sent to the new user' do
  383 + should deliver_to 'new-email@mail.com'
  384 + end
  385 +
  386 + it 'has the correct subject' do
  387 + should have_subject "Confirmation instructions"
  388 + end
  389 +
  390 + it 'includes a link to the site' do
  391 + should have_body_text /#{example_site_path}/
  392 + end
  393 + end
370 394 end
... ...
spec/requests/api/files_spec.rb 0 → 100644
... ... @@ -0,0 +1,81 @@
  1 +require 'spec_helper'
  2 +
  3 +describe API::API do
  4 + include ApiHelpers
  5 + before(:each) { ActiveRecord::Base.observers.enable(:user_observer) }
  6 + after(:each) { ActiveRecord::Base.observers.disable(:user_observer) }
  7 +
  8 + let(:user) { create(:user) }
  9 + let!(:project) { create(:project_with_code, namespace: user.namespace ) }
  10 + before { project.team << [user, :developer] }
  11 +
  12 + describe "POST /projects/:id/repository/files" do
  13 + let(:valid_params) {
  14 + {
  15 + file_name: 'newfile.rb',
  16 + branch_name: 'master',
  17 + content: 'puts 8',
  18 + commit_message: 'Added newfile'
  19 + }
  20 + }
  21 +
  22 + it "should create a new file in project repo" do
  23 + Gitlab::Satellite::NewFileAction.any_instance.stub(
  24 + commit!: true,
  25 + )
  26 +
  27 + post api("/projects/#{project.id}/repository/files", user), valid_params
  28 + response.status.should == 201
  29 + json_response['file_name'].should == 'newfile.rb'
  30 + end
  31 +
  32 + it "should return a 400 bad request if no params given" do
  33 + post api("/projects/#{project.id}/repository/files", user)
  34 + response.status.should == 400
  35 + end
  36 +
  37 + it "should return a 400 if satellite fails to create file" do
  38 + Gitlab::Satellite::NewFileAction.any_instance.stub(
  39 + commit!: false,
  40 + )
  41 +
  42 + post api("/projects/#{project.id}/repository/files", user), valid_params
  43 + response.status.should == 400
  44 + end
  45 + end
  46 +
  47 + describe "PUT /projects/:id/repository/files" do
  48 + let(:valid_params) {
  49 + {
  50 + file_path: 'spec/spec_helper.rb',
  51 + branch_name: 'master',
  52 + content: 'puts 8',
  53 + commit_message: 'Changed file'
  54 + }
  55 + }
  56 +
  57 + it "should update existing file in project repo" do
  58 + Gitlab::Satellite::EditFileAction.any_instance.stub(
  59 + commit!: true,
  60 + )
  61 +
  62 + put api("/projects/#{project.id}/repository/files", user), valid_params
  63 + response.status.should == 200
  64 + json_response['file_path'].should == 'spec/spec_helper.rb'
  65 + end
  66 +
  67 + it "should return a 400 bad request if no params given" do
  68 + put api("/projects/#{project.id}/repository/files", user)
  69 + response.status.should == 400
  70 + end
  71 +
  72 + it "should return a 400 if satellite fails to create file" do
  73 + Gitlab::Satellite::EditFileAction.any_instance.stub(
  74 + commit!: false,
  75 + )
  76 +
  77 + put api("/projects/#{project.id}/repository/files", user), valid_params
  78 + response.status.should == 400
  79 + end
  80 + end
  81 +end
... ...
spec/support/test_env.rb
... ... @@ -45,6 +45,7 @@ module TestEnv
45 45 def disable_mailer
46 46 NotificationService.any_instance.stub(mailer: double.as_null_object)
47 47 end
  48 +
48 49 def enable_mailer
49 50 NotificationService.any_instance.unstub(:mailer)
50 51 end
... ...